diff --git a/DEPS b/DEPS index 1c9c9a0..3820d96 100644 --- a/DEPS +++ b/DEPS
@@ -245,15 +245,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': 'bdc0bad2e216eab790842912ad184191c2426ac1', + 'skia_revision': '112f9f1273ef9505673c4a5154a2f9d8cc929d23', # 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': '74de5fddb9c4b85ec495c5ae587578d845737942', + 'v8_revision': '0eca9b90ee3689f6cbf93e01b5e0fc480175ce42', # 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': 'a7e0d520f4ca8947444467424869f6a467f3acbc', + 'angle_revision': '993f388967f8725d1ef8ce138ce8be4c0ae852ed', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -276,7 +276,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling googletest # and whatever else without interference from each other. - 'googletest_revision': '9a32aee22d771387c494be2d8519fbdf46a713b2', + 'googletest_revision': '71d4e2f7423274d178b446e94b88082559f2fa7a', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling lighttpd # and whatever else without interference from each other. @@ -320,7 +320,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': 'dc48499246acb27c90ce034619b335726ea2834c', + 'devtools_frontend_revision': 'eba1a96f6793a1360b99f86597632af9e565b953', # 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. @@ -360,7 +360,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': '3324caee9c7c34ac1bffef87a6ca378eb23b5150', + 'dawn_revision': '007f0d57a8fa7f2c79ded05036e98ba3bfbfe42d', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -805,7 +805,7 @@ 'packages': [ { 'package': 'chromium/third_party/androidx', - 'version': 'vmWZ1WUPgUEe8dpm2UVl-azbGg4DDN1As69u4IhVXpgC', + 'version': 'ZFybfM9WA_ZDTzPoqqNyWkYnKhc-eKP-qu_wHennQ34C', }, ], 'condition': 'checkout_android', @@ -1648,7 +1648,7 @@ Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'c843f8d63c8c17acfbb7d48e09059a581ba779b9', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '2be1808023189ba27973a1f0fc437125fbf5da77', + Var('webrtc_git') + '/src.git' + '@' + 'ce702dbbe4e86d5248a6ad4b13475cc166dd02a8', 'src/third_party/libgifcodec': Var('skia_git') + '/libgifcodec' + '@'+ Var('libgifcodec_revision'), @@ -1730,7 +1730,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@662e18c549447c9b9ea21f88058ed54842cc993a', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@0b962ed90d3d4a7a9b8561dd52e0910ed8a7ed2b', 'condition': 'checkout_src_internal', }, @@ -1782,7 +1782,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/projector_app/app', - 'version': 'vhsSk8Bb4-9wo4PaV0WUu6vpB-dYlDklx5wajGObTEMC', + 'version': 'ouEsQyUuqIb66n6x2iR0-Wx33CxqYHAWVD-EZf8po88C', }, ], 'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/PRESUBMIT.py b/PRESUBMIT.py index 430de79..ff2447d 100644 --- a/PRESUBMIT.py +++ b/PRESUBMIT.py
@@ -3720,8 +3720,6 @@ input_api.DEFAULT_FILES_TO_SKIP + (r"^chrome/common/extensions/docs", r"^chrome/docs", - r"^components/dom_distiller/core/css/distilledpage_ios.css", - r"^components/neterror/resources/neterror.css", r"^native_client_sdk")) file_filter = lambda f: input_api.FilterSourceFile( f, files_to_check=file_inclusion_pattern, files_to_skip=files_to_skip)
diff --git a/ash/app_list/views/productivity_launcher_search_view.cc b/ash/app_list/views/productivity_launcher_search_view.cc index ed45fa3..c8486cc 100644 --- a/ash/app_list/views/productivity_launcher_search_view.cc +++ b/ash/app_list/views/productivity_launcher_search_view.cc
@@ -23,6 +23,7 @@ #include "base/notreached.h" #include "base/strings/string_number_conversions.h" #include "third_party/abseil-cpp/absl/types/optional.h" +#include "ui/accessibility/platform/ax_unique_id.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/metadata/metadata_impl_macros.h" #include "ui/gfx/geometry/rect.h" @@ -251,22 +252,20 @@ if (ignore_result_changes_for_a11y_) return; - // Ignore result selection change if the focus moved away from the search box - // textfield, for example to the close button. - if (!search_box_view_->search_box()->HasFocus()) + if (!result_selection_controller_->selected_result()) { + search_box_view_->SetA11yActiveDescendant(absl::nullopt); return; - - if (!result_selection_controller_->selected_result()) - return; + } views::View* selected_view = result_selection_controller_->selected_result()->GetSelectedView(); - if (!selected_view) + if (!selected_view) { + search_box_view_->SetA11yActiveDescendant(absl::nullopt); return; + } - selected_view->NotifyAccessibilityEvent(ax::mojom::Event::kSelection, true); - NotifyAccessibilityEvent(ax::mojom::Event::kSelectedChildrenChanged, true); - search_box_view_->set_a11y_selection_on_search_result(true); + search_box_view_->SetA11yActiveDescendant( + selected_view->GetViewAccessibility().GetUniqueId().Get()); } bool ProductivityLauncherSearchView::CanSelectSearchResults() {
diff --git a/ash/app_list/views/productivity_launcher_search_view_unittest.cc b/ash/app_list/views/productivity_launcher_search_view_unittest.cc index 892541ee..1a06a09 100644 --- a/ash/app_list/views/productivity_launcher_search_view_unittest.cc +++ b/ash/app_list/views/productivity_launcher_search_view_unittest.cc
@@ -518,22 +518,22 @@ // Pressing down should not generate a selection accessibility event because // A11Y announcements are delayed since the results list just changed. PressAndReleaseKey(ui::VKEY_DOWN); - EXPECT_EQ(0, ax_counter.GetCount(ax::mojom::Event::kSelection)); + EXPECT_EQ(0, ax_counter.GetCount(ax::mojom::Event::kActiveDescendantChanged)); // Advance time to fire the timer to stop ignoring A11Y announcements. task_environment()->FastForwardBy(base::Milliseconds(5000)); // A selection event is generated when the timer fires. - EXPECT_EQ(1, ax_counter.GetCount(ax::mojom::Event::kSelection)); + EXPECT_EQ(1, ax_counter.GetCount(ax::mojom::Event::kActiveDescendantChanged)); // Successive up/down key presses should generate additional selection events. PressAndReleaseKey(ui::VKEY_DOWN); - EXPECT_EQ(2, ax_counter.GetCount(ax::mojom::Event::kSelection)); + EXPECT_EQ(2, ax_counter.GetCount(ax::mojom::Event::kActiveDescendantChanged)); PressAndReleaseKey(ui::VKEY_UP); - EXPECT_EQ(3, ax_counter.GetCount(ax::mojom::Event::kSelection)); + EXPECT_EQ(3, ax_counter.GetCount(ax::mojom::Event::kActiveDescendantChanged)); PressAndReleaseKey(ui::VKEY_DOWN); - EXPECT_EQ(4, ax_counter.GetCount(ax::mojom::Event::kSelection)); + EXPECT_EQ(4, ax_counter.GetCount(ax::mojom::Event::kActiveDescendantChanged)); PressAndReleaseKey(ui::VKEY_DOWN); - EXPECT_EQ(5, ax_counter.GetCount(ax::mojom::Event::kSelection)); + EXPECT_EQ(5, ax_counter.GetCount(ax::mojom::Event::kActiveDescendantChanged)); } TEST_P(ProductivityLauncherSearchViewTest, SearchPageA11y) {
diff --git a/ash/app_list/views/search_box_view.cc b/ash/app_list/views/search_box_view.cc index c3ad1a6..d2cb81b 100644 --- a/ash/app_list/views/search_box_view.cc +++ b/ash/app_list/views/search_box_view.cc
@@ -144,6 +144,14 @@ } } +void SearchBoxView::UpdateSearchTextfieldAccessibleNodeData( + ui::AXNodeData* node_data) { + if (a11y_active_descendant_) { + node_data->AddIntAttribute(ax::mojom::IntAttribute::kActivedescendantId, + *a11y_active_descendant_); + } +} + void SearchBoxView::ClearSearch() { SearchBoxViewBase::ClearSearch(); current_query_.clear(); @@ -597,10 +605,8 @@ } void SearchBoxView::OnBeforeUserAction(views::Textfield* sender) { - if (a11y_selection_on_search_result_) { - a11y_selection_on_search_result_ = false; - search_box()->NotifyAccessibilityEvent(ax::mojom::Event::kSelection, true); - } + if (a11y_active_descendant_) + SetA11yActiveDescendant(absl::nullopt); } void SearchBoxView::ContentsChanged(views::Textfield* sender, @@ -673,11 +679,18 @@ if (!is_search_box_active()) return; - a11y_selection_on_search_result_ = false; + SetA11yActiveDescendant(absl::nullopt); ClearSearch(); SetSearchBoxActive(false, ui::ET_UNKNOWN); } +void SearchBoxView::SetA11yActiveDescendant( + const absl::optional<int32_t>& active_descendant) { + a11y_active_descendant_ = active_descendant; + search_box()->NotifyAccessibilityEvent( + ax::mojom::Event::kActiveDescendantChanged, true); +} + bool SearchBoxView::HandleKeyEvent(views::Textfield* sender, const ui::KeyEvent& key_event) { DCHECK(result_selection_controller_); @@ -799,9 +812,7 @@ DCHECK(close_button()->GetVisible()); close_button()->RequestFocus(); - close_button()->NotifyAccessibilityEvent(ax::mojom::Event::kSelection, - true); - a11y_selection_on_search_result_ = false; + SetA11yActiveDescendant(absl::nullopt); break; case ResultSelectionController::MoveResult::kResultChanged: UpdateSearchBoxTextForSelectedResult(
diff --git a/ash/app_list/views/search_box_view.h b/ash/app_list/views/search_box_view.h index 7b74bc4c..1bd8602 100644 --- a/ash/app_list/views/search_box_view.h +++ b/ash/app_list/views/search_box_view.h
@@ -5,6 +5,8 @@ #ifndef ASH_APP_LIST_VIEWS_SEARCH_BOX_VIEW_H_ #define ASH_APP_LIST_VIEWS_SEARCH_BOX_VIEW_H_ +#include <stdint.h> + #include <vector> #include "ash/app_list/app_list_model_provider.h" @@ -15,6 +17,7 @@ #include "ash/public/cpp/app_list/app_list_types.h" #include "ash/search_box/search_box_view_base.h" #include "base/scoped_observation.h" +#include "third_party/abseil-cpp/absl/types/optional.h" namespace views { class Textfield; @@ -62,6 +65,8 @@ // Overridden from SearchBoxViewBase: void Init(const InitParams& params) override; + void UpdateSearchTextfieldAccessibleNodeData( + ui::AXNodeData* node_data) override; void ClearSearch() override; void HandleSearchBoxEvent(ui::LocatedEvent* located_event) override; void UpdateKeyboardVisibility() override; @@ -115,15 +120,18 @@ // Clears the search query and de-activate the search box. void ClearSearchAndDeactivateSearchBox(); + // Sets the view accessibility ID of the search box's active descendant. + // The active descendant should be the currently selected result view in the + // search results list. + // `nullopt` indicates no active descendant, i.e. that no result is selected. + void SetA11yActiveDescendant( + const absl::optional<int32_t>& active_descendant); + void set_contents_view(ContentsView* contents_view) { contents_view_ = contents_view; } ContentsView* contents_view() { return contents_view_; } - void set_a11y_selection_on_search_result(bool value) { - a11y_selection_on_search_result_ = value; - } - ResultSelectionController* result_selection_controller_for_test() { return result_selection_controller_; } @@ -210,8 +218,9 @@ bool is_tablet_mode_; // Set by SearchResultPageView when the accessibility selection moves to a - // search result view. - bool a11y_selection_on_search_result_ = false; + // search result view - the value is the ID of the currently selected result + // view. + absl::optional<int32_t> a11y_active_descendant_; // Owned by SearchResultPageView (for fullscreen launcher) or // ProductivityLauncherSearchPage (for bubble launcher).
diff --git a/ash/app_list/views/search_result_page_view.cc b/ash/app_list/views/search_result_page_view.cc index 0461d43..d7dd14e 100644 --- a/ash/app_list/views/search_result_page_view.cc +++ b/ash/app_list/views/search_result_page_view.cc
@@ -30,6 +30,7 @@ #include "base/memory/ptr_util.h" #include "base/strings/string_number_conversions.h" #include "third_party/abseil-cpp/absl/types/optional.h" +#include "ui/accessibility/platform/ax_unique_id.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/metadata/metadata_header_macros.h" #include "ui/base/metadata/metadata_impl_macros.h" @@ -431,26 +432,25 @@ void SearchResultPageView::NotifySelectedResultChanged() { // Result selection should be handled by |productivity_launcher_search_page_|. DCHECK(!features::IsProductivityLauncherEnabled()); - if (ignore_result_changes_for_a11y_ || - !result_selection_controller_->selected_location_details() || + if (ignore_result_changes_for_a11y_) + return; + + SearchBoxView* search_box = AppListPage::contents_view()->GetSearchBoxView(); + if (!result_selection_controller_->selected_location_details() || !result_selection_controller_->selected_result()) { + search_box->SetA11yActiveDescendant(absl::nullopt); return; } - SearchBoxView* search_box = AppListPage::contents_view()->GetSearchBoxView(); - // Ignore result selection change if the focus moved away from the search boc - // textfield, for example to the close button. - if (!search_box->search_box()->HasFocus()) - return; - views::View* selected_view = result_selection_controller_->selected_result()->GetSelectedView(); - if (!selected_view) + if (!selected_view) { + search_box->SetA11yActiveDescendant(absl::nullopt); return; + } - selected_view->NotifyAccessibilityEvent(ax::mojom::Event::kSelection, true); - NotifyAccessibilityEvent(ax::mojom::Event::kSelectedChildrenChanged, true); - search_box->set_a11y_selection_on_search_result(true); + search_box->SetA11yActiveDescendant( + selected_view->GetViewAccessibility().GetUniqueId().Get()); } void SearchResultPageView::OnActiveAppListModelsChanged(
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 c23a6d4..a371045 100644 --- a/ash/app_list/views/search_result_tile_item_view.cc +++ b/ash/app_list/views/search_result_tile_item_view.cc
@@ -257,7 +257,6 @@ // The tile is a list item in the search result page's result list. node_data->role = ax::mojom::Role::kListBoxOption; - node_data->AddBoolAttribute(ax::mojom::BoolAttribute::kSelected, selected()); node_data->SetDefaultActionVerb(ax::mojom::DefaultActionVerb::kClick); // Specify |ax::mojom::StringAttribute::kDescription| with an empty string, so
diff --git a/ash/app_list/views/search_result_view.cc b/ash/app_list/views/search_result_view.cc index e9f866b..30bd19b 100644 --- a/ash/app_list/views/search_result_view.cc +++ b/ash/app_list/views/search_result_view.cc
@@ -564,7 +564,6 @@ // button are child button of SearchResultView), which is not supported by // ChromeVox. see details in crbug.com/924776. node_data->role = ax::mojom::Role::kListBoxOption; - node_data->AddBoolAttribute(ax::mojom::BoolAttribute::kSelected, selected()); node_data->SetDefaultActionVerb(ax::mojom::DefaultActionVerb::kClick); node_data->SetName(GetAccessibleName()); }
diff --git a/ash/components/arc/BUILD.gn b/ash/components/arc/BUILD.gn index 8822e91..2ee8c6a 100644 --- a/ash/components/arc/BUILD.gn +++ b/ash/components/arc/BUILD.gn
@@ -133,6 +133,7 @@ "//components/device_event_log", "//components/exo", "//components/guest_os", + "//components/metrics", "//components/prefs", "//components/session_manager/core",
diff --git a/ash/components/arc/arc_features.cc b/ash/components/arc/arc_features.cc index 546f7b5..65f9f8e5 100644 --- a/ash/components/arc/arc_features.cc +++ b/ash/components/arc/arc_features.cc
@@ -163,6 +163,14 @@ const base::Feature kVideoDecoder{"ArcVideoDecoder", base::FEATURE_ENABLED_BY_DEFAULT}; +// Feature to continuously log PSI memory pressure data to Chrome. +const base::Feature kVmMemoryPSIReports{"ArcVmMemoryPSIReports", + base::FEATURE_ENABLED_BY_DEFAULT}; + +// Controls how frequently memory pressure data is logged +const base::FeatureParam<int> kVmMemoryPSIReportsPeriod{&kVmMemoryPSIReports, + "period", 10}; + // Controls whether a custom memory size is used when creating ARCVM. When // enabled, ARCVM is sized with the following formula: // min(max_mib, RAM + shift_mib)
diff --git a/ash/components/arc/arc_features.h b/ash/components/arc/arc_features.h index b1e86e5..f44976c 100644 --- a/ash/components/arc/arc_features.h +++ b/ash/components/arc/arc_features.h
@@ -41,6 +41,8 @@ extern const base::Feature kUseDalvikMemoryProfile; extern const base::Feature kUseDefaultBlockSize; extern const base::Feature kVideoDecoder; +extern const base::Feature kVmMemoryPSIReports; +extern const base::FeatureParam<int> kVmMemoryPSIReportsPeriod; extern const base::Feature kVmMemorySize; extern const base::FeatureParam<int> kVmMemorySizeShiftMiB; extern const base::FeatureParam<int> kVmMemorySizeMaxMiB;
diff --git a/ash/components/arc/compat_mode/touch_mode_mouse_rewriter.cc b/ash/components/arc/compat_mode/touch_mode_mouse_rewriter.cc index 4af69f9..dc585b11 100644 --- a/ash/components/arc/compat_mode/touch_mode_mouse_rewriter.cc +++ b/ash/components/arc/compat_mode/touch_mode_mouse_rewriter.cc
@@ -96,86 +96,29 @@ // caption bar. if (!target || target->GetType() != aura::client::WINDOW_TYPE_CONTROL) return SendEvent(continuation, &event); - bool found = false; - // TODO(b/202679170): Verify that it does not affect performance before - // flipping the flag, and fix it if necessary. - while (target != nullptr) { - if (enabled_windows_.count(target)) { - found = true; - break; - } - target = target->parent(); - } - if (!found) - return SendEvent(continuation, &event); - if (base::FeatureList::IsEnabled(arc::kMouseWheelSmoothScroll) && - event.IsMouseWheelEvent()) { - const ui::MouseWheelEvent& wheel_event = *event.AsMouseWheelEvent(); - const bool started = !scroll_timeout_.is_zero(); - scroll_y_offset_ += kWheelToSmoothScrollScale * wheel_event.y_offset(); - scroll_timeout_ = kSmoothScrollTimeout; - if (started) { - ui::ScrollEvent fling_cancel_event( - ui::ET_SCROLL_FLING_CANCEL, wheel_event.location_f(), - wheel_event.root_location_f(), wheel_event.time_stamp(), 0, 0, 0, 0, - 0, 0); - base::SequencedTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(&TouchModeMouseRewriter::SendScrollEvent, - weak_ptr_factory_.GetWeakPtr(), wheel_event, - continuation)); - return SendEvent(continuation, &fling_cancel_event); - } - return DiscardEvent(continuation); - } + const bool in_resize_locked = IsInResizeLockedWindow(target); + if (event.IsMouseWheelEvent()) { + if (!base::FeatureList::IsEnabled(arc::kMouseWheelSmoothScroll)) + return SendEvent(continuation, &event); - if (!base::FeatureList::IsEnabled(arc::kRightClickLongPress)) - return SendEvent(continuation, &event); + if (!in_resize_locked) + return SendEvent(continuation, &event); + + return RewriteMouseWheelEvent(*event.AsMouseWheelEvent(), continuation); + } const ui::MouseEvent& mouse_event = *event.AsMouseEvent(); - if (mouse_event.IsRightMouseButton()) { - // 1. If there is already an ongoing simulated long press, discard the - // subsequent right click. - // 2. If the left button is currently pressed, discard the right click. - // 3. Discard events that is not a right press. - if (release_event_scheduled_ || left_pressed_ || - mouse_event.type() != ui::ET_MOUSE_PRESSED) { - return DiscardEvent(continuation); - } - // Schedule the release event after |kLongPressInterval|. - release_event_scheduled_ = true; - base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, - base::BindOnce(&TouchModeMouseRewriter::SendReleaseEvent, - weak_ptr_factory_.GetWeakPtr(), mouse_event, - continuation), - kLongPressInterval); - // Send the press event now. - ui::MouseEvent press_event( - ui::ET_MOUSE_PRESSED, mouse_event.location(), - mouse_event.root_location(), mouse_event.time_stamp(), - ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); - return SendEvent(continuation, &press_event); - } else if (mouse_event.IsLeftMouseButton()) { - if (mouse_event.type() == ui::ET_MOUSE_PRESSED) - left_pressed_ = true; - else if (mouse_event.type() == ui::ET_MOUSE_RELEASED) - left_pressed_ = false; - // Discard a release event that corresponds to a previously discarded press - // event. - if (discard_next_left_release_ && - mouse_event.type() == ui::ET_MOUSE_RELEASED) { - discard_next_left_release_ = false; - return DiscardEvent(continuation); - } - // Discard the left click if there is an ongoing simulated long press. - if (release_event_scheduled_) { - if (mouse_event.type() == ui::ET_MOUSE_PRESSED) - discard_next_left_release_ = true; - return DiscardEvent(continuation); - } - return SendEvent(continuation, &event); + if (mouse_event.IsRightMouseButton() || mouse_event.IsLeftMouseButton()) { + if (!base::FeatureList::IsEnabled(arc::kRightClickLongPress)) + return SendEvent(continuation, &event); + + if (!in_resize_locked) + return SendEvent(continuation, &event); + + return RewriteMouseClickEvent(mouse_event, continuation); } + return SendEvent(continuation, &event); } @@ -219,4 +162,82 @@ } } +ui::EventDispatchDetails TouchModeMouseRewriter::RewriteMouseWheelEvent( + const ui::MouseWheelEvent& event, + const Continuation continuation) { + const bool started = !scroll_timeout_.is_zero(); + scroll_y_offset_ += kWheelToSmoothScrollScale * event.y_offset(); + scroll_timeout_ = kSmoothScrollTimeout; + if (started) { + ui::ScrollEvent fling_cancel_event( + ui::ET_SCROLL_FLING_CANCEL, event.location_f(), event.root_location_f(), + event.time_stamp(), 0, 0, 0, 0, 0, 0); + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce(&TouchModeMouseRewriter::SendScrollEvent, + weak_ptr_factory_.GetWeakPtr(), event, continuation)); + return SendEvent(continuation, &fling_cancel_event); + } + return DiscardEvent(continuation); +} + +ui::EventDispatchDetails TouchModeMouseRewriter::RewriteMouseClickEvent( + const ui::MouseEvent& event, + const Continuation continuation) { + if (event.IsRightMouseButton()) { + // 1. If there is already an ongoing simulated long press, discard the + // subsequent right click. + // 2. If the left button is currently pressed, discard the right click. + // 3. Discard events that is not a right press. + if (release_event_scheduled_ || left_pressed_ || + event.type() != ui::ET_MOUSE_PRESSED) { + return DiscardEvent(continuation); + } + // Schedule the release event after |kLongPressInterval|. + release_event_scheduled_ = true; + base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::BindOnce(&TouchModeMouseRewriter::SendReleaseEvent, + weak_ptr_factory_.GetWeakPtr(), event, continuation), + kLongPressInterval); + // Send the press event now. + ui::MouseEvent press_event( + ui::ET_MOUSE_PRESSED, event.location(), event.root_location(), + event.time_stamp(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); + return SendEvent(continuation, &press_event); + } else if (event.IsLeftMouseButton()) { + if (event.type() == ui::ET_MOUSE_PRESSED) + left_pressed_ = true; + else if (event.type() == ui::ET_MOUSE_RELEASED) + left_pressed_ = false; + // Discard a release event that corresponds to a previously discarded press + // event. + if (discard_next_left_release_ && event.type() == ui::ET_MOUSE_RELEASED) { + discard_next_left_release_ = false; + return DiscardEvent(continuation); + } + // Discard the left click if there is an ongoing simulated long press. + if (release_event_scheduled_) { + if (event.type() == ui::ET_MOUSE_PRESSED) + discard_next_left_release_ = true; + return DiscardEvent(continuation); + } + return SendEvent(continuation, &event); + } + + return SendEvent(continuation, &event); +} + +bool TouchModeMouseRewriter::IsInResizeLockedWindow( + const aura::Window* window) const { + // TODO(b/202679170): Verify that it does not affect performance before + // flipping the flag, and fix it if necessary. + while (window != nullptr) { + if (enabled_windows_.count(window)) + return true; + window = window->parent(); + } + return false; +} + } // namespace arc
diff --git a/ash/components/arc/compat_mode/touch_mode_mouse_rewriter.h b/ash/components/arc/compat_mode/touch_mode_mouse_rewriter.h index 2cf5f1c..5422f78 100644 --- a/ash/components/arc/compat_mode/touch_mode_mouse_rewriter.h +++ b/ash/components/arc/compat_mode/touch_mode_mouse_rewriter.h
@@ -55,6 +55,14 @@ void SendScrollEvent(const ui::MouseWheelEvent& original_event, const Continuation continuation); + ui::EventDispatchDetails RewriteMouseWheelEvent( + const ui::MouseWheelEvent& event, + const Continuation continuation); + ui::EventDispatchDetails RewriteMouseClickEvent( + const ui::MouseEvent& event, + const Continuation continuation); + bool IsInResizeLockedWindow(const aura::Window* window) const; + // Used for right click long press. bool release_event_scheduled_ = false; bool left_pressed_ = false; @@ -65,7 +73,7 @@ base::TimeDelta scroll_timeout_; std::multiset<aura::WindowTreeHost*> hosts_; - std::set<aura::Window*> enabled_windows_; + std::set<const aura::Window*> enabled_windows_; base::ScopedMultiSourceObservation<aura::Window, aura::WindowObserver> window_observations_{this};
diff --git a/ash/components/arc/ime/arc_ime_bridge_impl.cc b/ash/components/arc/ime/arc_ime_bridge_impl.cc index 76d8f1f3..1e9e29d 100644 --- a/ash/components/arc/ime/arc_ime_bridge_impl.cc +++ b/ash/components/arc/ime/arc_ime_bridge_impl.cc
@@ -173,10 +173,6 @@ is_screen_coordinates); } -void ArcImeBridgeImpl::RequestHideImeDeprecated() { - DVLOG(1) << "RequestHideIme is deprecated."; -} - void ArcImeBridgeImpl::SendKeyEvent(std::unique_ptr<ui::KeyEvent> key_event, SendKeyEventCallback callback) { delegate_->SendKeyEvent(std::move(key_event), std::move(callback));
diff --git a/ash/components/arc/ime/arc_ime_bridge_impl.h b/ash/components/arc/ime/arc_ime_bridge_impl.h index f108ef2..0e3463f 100644 --- a/ash/components/arc/ime/arc_ime_bridge_impl.h +++ b/ash/components/arc/ime/arc_ime_bridge_impl.h
@@ -55,7 +55,6 @@ const std::string& text_in_range, const gfx::Range& selection_range, bool screen_coordinates) override; - void RequestHideImeDeprecated() override; void SendKeyEvent(std::unique_ptr<ui::KeyEvent> key_event, SendKeyEventCallback callback) override;
diff --git a/ash/components/arc/metrics/DEPS b/ash/components/arc/metrics/DEPS index 5cfe334..cea4cfa2 100644 --- a/ash/components/arc/metrics/DEPS +++ b/ash/components/arc/metrics/DEPS
@@ -1,5 +1,6 @@ include_rules = [ + "+components/metrics", "+ui/aura", "+ui/events/ozone/gamepad", "+ui/wm/public", -] \ No newline at end of file +]
diff --git a/ash/components/arc/metrics/arc_metrics_service.cc b/ash/components/arc/metrics/arc_metrics_service.cc index e95d750..6ca24b5 100644 --- a/ash/components/arc/metrics/arc_metrics_service.cc +++ b/ash/components/arc/metrics/arc_metrics_service.cc
@@ -7,6 +7,7 @@ #include <string> #include <utility> +#include "ash/components/arc/arc_features.h" #include "ash/components/arc/arc_prefs.h" #include "ash/components/arc/arc_util.h" #include "ash/components/arc/metrics/stability_metrics_manager.h" @@ -22,6 +23,7 @@ #include "chromeos/dbus/power_manager/idle.pb.h" #include "chromeos/dbus/session_manager/session_manager_client.h" #include "components/exo/wm_helper.h" +#include "components/metrics/psi_memory_parser.h" #include "components/prefs/pref_service.h" #include "components/user_prefs/user_prefs.h" #include "content/public/browser/browser_context.h" @@ -58,6 +60,10 @@ constexpr char kAppTypeSystem[] = "SystemApp"; constexpr char kAppTypeOther[] = "Other"; +// Memory pressure histograms. +const char kPSIMemoryPressureSomeARC[] = "ChromeOS.CWP.PSIMemPressure.ArcSome"; +const char kPSIMemoryPressureFullARC[] = "ChromeOS.CWP.PSIMemPressure.ArcFull"; + // Logs UMA enum values to facilitate finding feedback reports in Xamine. template <typename T> void LogStabilityUmaEnum(const std::string& name, T sample) { @@ -175,6 +181,11 @@ StabilityMetricsManager::Get()->SetArcNativeBridgeType( NativeBridgeType::UNKNOWN); + + if (base::FeatureList::IsEnabled(kVmMemoryPSIReports)) { + psi_parser_ = std::make_unique<metrics::PSIMemoryParser>( + kVmMemoryPSIReportsPeriod.Get()); + } } ArcMetricsService::~ArcMetricsService() { @@ -529,6 +540,32 @@ base::Milliseconds(duration_ms)); } +void ArcMetricsService::ReportMemoryPressure( + const std::vector<uint8_t>& psi_file_contents) { + if (!psi_parser_) { + LOG(WARNING) << "Unexpected PSI reporting call detected"; + return; + } + + int metric_some; + int metric_full; + + auto stat = psi_parser_->ParseMetrics(psi_file_contents.data(), + psi_file_contents.size(), &metric_some, + &metric_full); + psi_parser_->LogParseStatus( + stat); // Log success and failure, for histograms. + if (stat != metrics::ParsePSIMemStatus::kSuccess) + return; + + base::UmaHistogramCustomCounts( + kPSIMemoryPressureSomeARC, metric_some, metrics::kMemPressureMin, + metrics::kMemPressureExclusiveMax, metrics::kMemPressureHistogramBuckets); + base::UmaHistogramCustomCounts( + kPSIMemoryPressureFullARC, metric_full, metrics::kMemPressureMin, + metrics::kMemPressureExclusiveMax, metrics::kMemPressureHistogramBuckets); +} + void ArcMetricsService::OnWindowActivated( wm::ActivationChangeObserver::ActivationReason reason, aura::Window* gained_active,
diff --git a/ash/components/arc/metrics/arc_metrics_service.h b/ash/components/arc/metrics/arc_metrics_service.h index ee78a8b..a3f0d01 100644 --- a/ash/components/arc/metrics/arc_metrics_service.h +++ b/ash/components/arc/metrics/arc_metrics_service.h
@@ -32,6 +32,10 @@ class BrowserContextKeyedServiceFactory; +namespace metrics { +class PSIMemoryParser; +} // namespace metrics + namespace aura { class Window; } // namespace aura @@ -137,6 +141,7 @@ void ReportAppPrimaryAbi(mojom::AppPrimaryAbi abi) override; void ReportDataRestore(mojom::DataRestoreStatus status, int64_t duration_ms) override; + void ReportMemoryPressure(const std::vector<uint8_t>& psiFile) override; // wm::ActivationChangeObserver overrides. // Records to UMA when a user has interacted with an ARC app window. @@ -282,6 +287,7 @@ ArcBridgeServiceObserver arc_bridge_service_observer_; IntentHelperObserver intent_helper_observer_; AppLauncherObserver app_launcher_observer_; + std::unique_ptr<metrics::PSIMemoryParser> psi_parser_; bool was_arc_window_active_ = false; std::vector<int32_t> task_ids_;
diff --git a/ash/components/arc/mojom/accessibility_helper.mojom b/ash/components/arc/mojom/accessibility_helper.mojom index 6f4aacf..6940f18 100644 --- a/ash/components/arc/mojom/accessibility_helper.mojom +++ b/ash/components/arc/mojom/accessibility_helper.mojom
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Next MinVersion: 23 +// Next MinVersion: 24 module arc.mojom; @@ -493,9 +493,18 @@ [MinVersion=18] OnToggleNativeChromeVoxArcSupport@3(bool enabled); }; +// Response code for SetNativeChromeVoxArcSupportForFocusedWindow. +[Extensible] +enum SetNativeChromeVoxResponse { + SUCCESS, + WINDOW_NOT_FOUND, + TALKBACK_NOT_INSTALLED, + FAILURE, +}; + // Interface for communicating to Android. // Deprecated method IDs: 0, 1, 3, 5 -// Next method ID: 12 +// Next method ID: 13 interface AccessibilityHelperInstance { // Establishes full-duplex communication with the host. [MinVersion=9] Init@7( @@ -510,7 +519,7 @@ // Sets the focused window's package to use ChromeVox (true) or TalkBack // (false). - [MinVersion=8] SetNativeChromeVoxArcSupportForFocusedWindow@6( + [MinVersion=8] SetNativeChromeVoxArcSupportForFocusedWindowDeprecated@6( bool enabled) => (bool processed); // Requests the service to enable or disable Explore By Touch. @@ -527,4 +536,9 @@ // Requests the whole accessibility tree with the specified window. [MinVersion=17] RequestSendAccessibilityTree@11( AccessibilityWindowKey window); + + // Sets the focused window's package to use ChromeVox (true) or TalkBack + // (false). + [MinVersion=24] SetNativeChromeVoxArcSupportForFocusedWindow@12( + bool enabled) => (SetNativeChromeVoxResponse response); };
diff --git a/ash/components/arc/mojom/app.mojom b/ash/components/arc/mojom/app.mojom index aa1531b..1085dd3 100644 --- a/ash/components/arc/mojom/app.mojom +++ b/ash/components/arc/mojom/app.mojom
@@ -357,9 +357,6 @@ // Next method ID: 40 // Deprecated method IDs: 0, 1, 2, 3, 4, 9, 12, 13, 15, 17, 22 interface AppInstance { - // DEPRECATED: Please use Init@21 instead. - InitDeprecated@0(pending_remote<AppHost> host_remote); - // Establishes full-duplex communication with the host. [MinVersion=26] Init@21(pending_remote<AppHost> host_remote) => ();
diff --git a/ash/components/arc/mojom/audio.mojom b/ash/components/arc/mojom/audio.mojom index eb9a344c7..c17b9eb 100644 --- a/ash/components/arc/mojom/audio.mojom +++ b/ash/components/arc/mojom/audio.mojom
@@ -24,11 +24,9 @@ [MinVersion=3] OnSystemVolumeUpdateRequest@1(int32 percent); }; +// Deprecated method IDs: 1 // Next method ID: 4 interface AudioInstance { - // DEPRECATED: Please use Init@3 instead. - [MinVersion=1] InitDeprecated@1(pending_remote<AudioHost> host_remote); - // Establishes full-duplex communication with the host. [MinVersion=4] Init@3(pending_remote<AudioHost> host_remote) => ();
diff --git a/ash/components/arc/mojom/bluetooth.mojom b/ash/components/arc/mojom/bluetooth.mojom index a2c5ac8..b748225 100644 --- a/ash/components/arc/mojom/bluetooth.mojom +++ b/ash/components/arc/mojom/bluetooth.mojom
@@ -423,11 +423,6 @@ [MinVersion=1] ReadRemoteRssi@28(BluetoothAddress remote_addr) => (int32 rssi); - // DEPRECATED: Use BluetoothSocketListen@47 or BluetoothSocketConnect@48 - // instead. - [MinVersion=2] OpenBluetoothSocketDeprecated@29() - => (handle sock); - // Bluetooth Gatt Server functions // Copied from Android API // https://source.android.com/devices/halref/bt__gatt__server_8h.html @@ -474,24 +469,6 @@ [MinVersion=8] DisableAdvertisement@43(int32 adv_handle) => (BluetoothGattStatus status); - // RFCOMM functions - // Opens a bluetooth socket with socket option |optval|, and then bind() and - // listen() with the requested RFCOMM |channel| number. When |channel| = 0, - // we will select a channel number automatically. If this process succeeds, - // returns SUCCESS in |status|, the actual listening channel in |channel|, - // and a new mojo connection which represents the listening socket. - [MinVersion=15] RfcommListenDeprecated@45(int32 channel, int32 optval) - => (BluetoothStatus status, int32 channel, - RfcommListeningSocketClient&? client); - // Opens a bluetooth socket with socket option |optval|, and then connect() - // to (|remote_addr|, |channel|). If this process succeeds, returns SUCCESS - // in |status| and a new mojo connection which holds the connecting socket. - // Unlike in RfcommListen(), |channel| here could not be 0, since this is the - // peer channel number. - [MinVersion=15] RfcommConnectDeprecated@46(BluetoothAddress remote_addr, - int32 channel, int32 optval) - => (BluetoothStatus status, RfcommConnectingSocketClient&? client); - // Bluetooth socket (RFCOMM and L2CAP LE) functions // Opens a |sock_type| socket with security options in |sock_flags|, and // listens on |port| (RFCOMM channel or L2CAP PSM). When |port| = 0, we will @@ -512,11 +489,8 @@ }; // Next Method ID: 24 -// Deprecated Method ID: 2, 6, 11, 12 +// Deprecated Method ID: 0, 2, 6, 11, 12 interface BluetoothInstance { - // DEPRECATED: Please use Init@18 instead. - InitDeprecated@0(pending_remote<BluetoothHost> host_remote); - // Establishes full-duplex communication with the host. [MinVersion=7] Init@18(pending_remote<BluetoothHost> host_remote) => ();
diff --git a/ash/components/arc/mojom/boot_phase_monitor.mojom b/ash/components/arc/mojom/boot_phase_monitor.mojom index 703df7f..5a38abc 100644 --- a/ash/components/arc/mojom/boot_phase_monitor.mojom +++ b/ash/components/arc/mojom/boot_phase_monitor.mojom
@@ -12,11 +12,9 @@ OnBootCompleted@0(); }; +// Deprecated method ID: 0 // Next method ID: 2 interface BootPhaseMonitorInstance { - // DEPRECATED: Please use Init@1 instead. - InitDeprecated@0(pending_remote<BootPhaseMonitorHost> host_remote); - // Establishes full-duplex communication with the host. [MinVersion=1] Init@1(pending_remote<BootPhaseMonitorHost> host_remote) => (); };
diff --git a/ash/components/arc/mojom/cert_store.mojom b/ash/components/arc/mojom/cert_store.mojom index 984ffdd..94ddb79 100644 --- a/ash/components/arc/mojom/cert_store.mojom +++ b/ash/components/arc/mojom/cert_store.mojom
@@ -108,11 +108,9 @@ Abort@5(uint64 operation_handle) => (KeymasterError error); }; +// Deprecated method IDs: 0 // Next method ID: 4 interface CertStoreInstance { - // DEPRECATED: Please use Init@3 instead. - InitDeprecated@0(pending_remote<CertStoreHost> host_remote); - // Establishes full-duplex communication with the host. [MinVersion=1] Init@3(pending_remote<CertStoreHost> host_remote) => ();
diff --git a/ash/components/arc/mojom/clipboard.mojom b/ash/components/arc/mojom/clipboard.mojom index 452599c..ce6d395 100644 --- a/ash/components/arc/mojom/clipboard.mojom +++ b/ash/components/arc/mojom/clipboard.mojom
@@ -50,11 +50,8 @@ }; // Next method ID: 4 -// Deprecated method IDs: 1 +// Deprecated method IDs: 0, 1 interface ClipboardInstance { - // DEPRECATED: Please use Init@3 instead. - InitDeprecated@0(pending_remote<ClipboardHost> host_remote); - // Establishes full-duplex communication with the host. [MinVersion=2] Init@3(pending_remote<ClipboardHost> host_remote) => ();
diff --git a/ash/components/arc/mojom/crash_collector.mojom b/ash/components/arc/mojom/crash_collector.mojom index 4faafb0..dc7dac59 100644 --- a/ash/components/arc/mojom/crash_collector.mojom +++ b/ash/components/arc/mojom/crash_collector.mojom
@@ -36,11 +36,9 @@ [MinVersion=5] DumpKernelCrash@3(handle ramoops_handle); }; +// Deprecated method IDs: 0 // Next Method ID: 2 interface CrashCollectorInstance { - // DEPRECATED: Please use Init@1 instead. - InitDeprecated@0(pending_remote<CrashCollectorHost> host_remote); - // Establishes full-duplex communication with the host. [MinVersion=2] Init@1(pending_remote<CrashCollectorHost> host_remote) => (); };
diff --git a/ash/components/arc/mojom/enterprise_reporting.mojom b/ash/components/arc/mojom/enterprise_reporting.mojom index a302a5d..ac93f2d8 100644 --- a/ash/components/arc/mojom/enterprise_reporting.mojom +++ b/ash/components/arc/mojom/enterprise_reporting.mojom
@@ -25,11 +25,9 @@ ReportManagementState@0(ManagementState state); }; +// Deprecated method IDs: 0 // Next method ID: 3 interface EnterpriseReportingInstance { - // DEPRECATED: Please use Init@2 instead. - InitDeprecated@0(pending_remote<EnterpriseReportingHost> host_remote); - // Establishes full-duplex communication with the host. [MinVersion=2] Init@2( pending_remote<EnterpriseReportingHost> host_remote) => ();
diff --git a/ash/components/arc/mojom/file_system.mojom b/ash/components/arc/mojom/file_system.mojom index d7e099c..e4a67617 100644 --- a/ash/components/arc/mojom/file_system.mojom +++ b/ash/components/arc/mojom/file_system.mojom
@@ -323,6 +323,7 @@ (FileSelectorElements elements); }; +// Deprecated method IDs: 5 // Next method ID: 24 interface FileSystemInstance { // Notes about Android Documents Provider: @@ -432,9 +433,6 @@ string target_parent_document_id) => (Document? document); - // DEPRECATED: Please use Init@10 instead. - [MinVersion=3] InitDeprecated@5(pending_remote<FileSystemHost> host_remote); - // Establishes full-duplex communication with the host. [MinVersion=7] Init@10(pending_remote<FileSystemHost> host_remote) => ();
diff --git a/ash/components/arc/mojom/ime.mojom b/ash/components/arc/mojom/ime.mojom index 17bf41de..4624789 100644 --- a/ash/components/arc/mojom/ime.mojom +++ b/ash/components/arc/mojom/ime.mojom
@@ -70,7 +70,7 @@ [MinVersion=16] uint32 scan_code; }; -// Next method ID: 8 +// Next method ID: 5, 8 interface ImeHost { // Notifies Chrome that the text input focus is changed. // Each bit of the bitmask |flags| corresponds to TEXT_INPUT_FLAG_*. @@ -116,10 +116,6 @@ // are in screen coordinates. ); - // Requests Chrome to hide the virtual keyboard. - // However, hiding can be canceled if a text field gets focus. - [MinVersion=9] RequestHideImeDeprecated@5(); - // Sends a key event to Chrome to pass it to the Chrome OS IME. [MinVersion=14] SendKeyEvent@7(KeyEventData key_event_data) => (bool is_consumed); @@ -127,11 +123,8 @@ // Represents a text input field that is hosted inside ARC++, allowing Chrome OS // browser process to manipulate text within Android apps. -// Next method ID: 9 +// Next method ID: 0, 9 interface ImeInstance { - // DEPRECATED: Please use Init@6 instead. - InitDeprecated@0(pending_remote<ImeHost> host_remote); - // Establishes full-duplex communication with the host. [MinVersion=6] Init@6(pending_remote<ImeHost> host_remote) => ();
diff --git a/ash/components/arc/mojom/kiosk.mojom b/ash/components/arc/mojom/kiosk.mojom index 852991b1..4ace32f 100644 --- a/ash/components/arc/mojom/kiosk.mojom +++ b/ash/components/arc/mojom/kiosk.mojom
@@ -20,11 +20,9 @@ OnMaintenanceSessionFinished@1(int32 session_id, bool succeeded); }; +// Deprecated method IDs: 0 // Next method ID: 2 interface KioskInstance { - // DEPRECATED: Please use Init@1 instead. - InitDeprecated@0(pending_remote<KioskHost> host_remote); - // Establishes full-duplex communication with the host. [MinVersion=1] Init@1(pending_remote<KioskHost> host_remote) => (); };
diff --git a/ash/components/arc/mojom/metrics.mojom b/ash/components/arc/mojom/metrics.mojom index b8af41b..794bdb1 100644 --- a/ash/components/arc/mojom/metrics.mojom +++ b/ash/components/arc/mojom/metrics.mojom
@@ -1,7 +1,7 @@ // Copyright 2016 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Next MinVersion: 20 +// Next MinVersion: 22 module arc.mojom; @@ -326,7 +326,7 @@ // tools/metrics/histograms/enums.xml. }; -// Next method ID: 23 +// Next method ID: 24 interface MetricsHost { // Reports boot progress events from ARC instance. ReportBootProgress@0(array<BootProgressEvent> events, @@ -419,13 +419,15 @@ // for ARC++ P container. [MinVersion=20] ReportDataRestore@22(DataRestoreStatus status, int64 duration_ms); + + // Reports raw memory pressure data, as the contents of /proc/pressure/memory. + // This is invoked solely by ARCVM. + [MinVersion=21] ReportMemoryPressure@23(array<uint8> psi_file_contents); }; +// Deprecated method IDs: 0 // Next method ID: 3 interface MetricsInstance { - // DEPRECATED: Please use Init@1 instead. - InitDeprecated@0(pending_remote<MetricsHost> host_remote); - // Establishes full-duplex communication with the host. [MinVersion=2] Init@1(pending_remote<MetricsHost> host_remote) => ();
diff --git a/ash/components/arc/mojom/midis.mojom b/ash/components/arc/mojom/midis.mojom index 18d9e403..52e12ebaf 100644 --- a/ash/components/arc/mojom/midis.mojom +++ b/ash/components/arc/mojom/midis.mojom
@@ -41,6 +41,7 @@ // This interface is used by the client to send messages / requests to the // daemon. This should be implemented by midis. +// Deprecated method IDs: 0 // Next Method ID: 4 interface MidisServer { // Used to list out the MIDI devices that are currently connected to the @@ -50,8 +51,6 @@ // This function returns a handle(a Unix FD wrapped in a Mojo Handle) // for a subdevice specified by |request|. // In the event of an error, returns an empty handle. - // DEPRECATED: Please use RequestPort@3 instead. - RequestPortDeprecated@1(MidisRequest request) => (handle port_handle); [MinVersion=2] RequestPort@3(MidisRequest request) => (handle? port_handle); @@ -72,11 +71,9 @@ // MidisInstance is implemented in the ARC MIDI JNI code that // runs in Android and handles the Android side of the ArcBridge connection. +// Deprecated method IDs: 0 // Next Method ID: 2 interface MidisInstance { - // DEPRECATED: Please use Init@1 instead. - InitDeprecated@0(pending_remote<MidisHost> host_remote); - // Establishes full-duplex communication with the host. [MinVersion=1] Init@1(pending_remote<MidisHost> host_remote) => (); };
diff --git a/ash/components/arc/mojom/net.mojom b/ash/components/arc/mojom/net.mojom index f7aaba1..f7d32d1 100644 --- a/ash/components/arc/mojom/net.mojom +++ b/ash/components/arc/mojom/net.mojom
@@ -603,11 +603,8 @@ }; // Next Method ID: 11 -// ID 2 is missing as it belonged to deprecated method. +// IDs 0 and 2 are missing as they belonged to deprecated method. interface NetInstance { - // DEPRECATED: Please use Init@6 instead. - InitDeprecated@0(pending_remote<NetHost> host_remote); - // Establishes full-duplex communication with the host. [MinVersion=8] Init@6(pending_remote<NetHost> host_remote) => ();
diff --git a/ash/components/arc/mojom/notifications.mojom b/ash/components/arc/mojom/notifications.mojom index b6cfe279..5a544a6 100644 --- a/ash/components/arc/mojom/notifications.mojom +++ b/ash/components/arc/mojom/notifications.mojom
@@ -248,12 +248,10 @@ OnLockScreenSettingUpdated@10(ArcLockScreenNotificationSetting setting); }; +// Deprecated method IDs: 0 // Next Method ID: 14 // TODO(lhchavez): Migrate all request/response messages to Mojo. interface NotificationsInstance { - // DEPRECATED: Please use Init@5 instead. - InitDeprecated@0(pending_remote<NotificationsHost> host_remote); - // Establishes full-duplex communication with the host. [MinVersion=14] Init@5(pending_remote<NotificationsHost> host_remote) => ();
diff --git a/ash/components/arc/mojom/obb_mounter.mojom b/ash/components/arc/mojom/obb_mounter.mojom index 403522c..a33c3b8 100644 --- a/ash/components/arc/mojom/obb_mounter.mojom +++ b/ash/components/arc/mojom/obb_mounter.mojom
@@ -18,11 +18,9 @@ UnmountObb@1(string target_path) => (bool success); }; +// Deprecated method IDs: 0 // Next Method ID: 2 interface ObbMounterInstance { - // DEPRECATED: Please use Init@1 instead. - InitDeprecated@0(pending_remote<ObbMounterHost> host_remote); - // Establishes full-duplex communication with the host. [MinVersion=1] Init@1(pending_remote<ObbMounterHost> host_remote) => (); };
diff --git a/ash/components/arc/mojom/oemcrypto.mojom b/ash/components/arc/mojom/oemcrypto.mojom index 98ed0fb..710182a 100644 --- a/ash/components/arc/mojom/oemcrypto.mojom +++ b/ash/components/arc/mojom/oemcrypto.mojom
@@ -487,11 +487,9 @@ // OemCryptoInstance is implemented in the liboemcrypto.so library that runs in // Android and handles the Android side of the ArcBridge connection. +// Deprecated method IDs: 0 // Next Method ID: 2 interface OemCryptoInstance { - // DEPRECATED: Please use Init@1 instead. - InitDeprecated@0(pending_remote<OemCryptoHost> host_remote); - // Establishes full-duplex communication with the host. [MinVersion=1] Init@1(pending_remote<OemCryptoHost> host_remote) => (); };
diff --git a/ash/components/arc/mojom/policy.mojom b/ash/components/arc/mojom/policy.mojom index 820e8a4..d479731 100644 --- a/ash/components/arc/mojom/policy.mojom +++ b/ash/components/arc/mojom/policy.mojom
@@ -95,11 +95,9 @@ array<string> package_names); }; +// Deprecated method IDs: 0 // Next Method ID: 4 interface PolicyInstance { - // DEPRECATED: Please use Init@2 instead. - InitDeprecated@0(pending_remote<PolicyHost> host_remote); - // Establishes full-duplex communication with the host. [MinVersion=2] Init@2(pending_remote<PolicyHost> host_remote) => ();
diff --git a/ash/components/arc/mojom/power.mojom b/ash/components/arc/mojom/power.mojom index 42dcaf8..c926178 100644 --- a/ash/components/arc/mojom/power.mojom +++ b/ash/components/arc/mojom/power.mojom
@@ -83,11 +83,9 @@ [MinVersion=8] OnAnrRecoveryFailed@7(AnrType type); }; +// Deprecated method IDs: 0 // Next method ID: 9 interface PowerInstance { - // DEPRECATED: Please use Init@5 instead. - InitDeprecated@0(pending_remote<PowerHost> host_remote); - // Establishes full-duplex communication with the host. [MinVersion=4] Init@5(pending_remote<PowerHost> host_remote) => ();
diff --git a/ash/components/arc/mojom/print_spooler.mojom b/ash/components/arc/mojom/print_spooler.mojom index 6039dd1..c28e1fe 100644 --- a/ash/components/arc/mojom/print_spooler.mojom +++ b/ash/components/arc/mojom/print_spooler.mojom
@@ -36,15 +36,6 @@ // Deprecated method ID: 0 // Next method ID: 2 interface PrintSpoolerHost { - // DEPRECATED: Please use StartPrintInCustomTab@1 instead. - [MinVersion=1] StartPrintInCustomTabDeprecated@0( - handle scoped_handle, - int32 task_id, - int32 surface_id, - int32 top_margin, - pending_remote<PrintSessionInstance> instance) - => (pending_remote<PrintSessionHost>? host); - // Opens the file owned by |scoped_handle| in Chrome print preview in an ARC // Custom Tab. // The |task_id| specifies the Android task on which the ARC Custom Tab should
diff --git a/ash/components/arc/mojom/process.mojom b/ash/components/arc/mojom/process.mojom index 14c68ab..0733f6c 100644 --- a/ash/components/arc/mojom/process.mojom +++ b/ash/components/arc/mojom/process.mojom
@@ -153,6 +153,7 @@ uint32 private_footprint_kb = 0; }; +// Deprecated method IDs: 6, 7 // Next Method ID: 11 interface ProcessInstance { // Requests ARC instance to kill a process. @@ -163,16 +164,6 @@ RequestProcessList@5() => (array<RunningAppProcessInfo> processes); // Requests memory usage dumps for all ARC application processes. - [MinVersion=7] - RequestApplicationProcessMemoryInfoDeprecated@6() - => (memory_instrumentation.mojom.GlobalMemoryDump dump); - - // Requests memory usage dumps for all ARC system processes. - [MinVersion=7] - RequestSystemProcessMemoryInfoDeprecated@7(array<uint32> nspids) - => (memory_instrumentation.mojom.GlobalMemoryDump dump); - - // Requests memory usage dumps for all ARC application processes. [MinVersion=8] RequestApplicationProcessMemoryInfo@8() => (array<ArcMemoryDump> process_dumps);
diff --git a/ash/components/arc/mojom/tts.mojom b/ash/components/arc/mojom/tts.mojom index 27a8643..01667b7 100644 --- a/ash/components/arc/mojom/tts.mojom +++ b/ash/components/arc/mojom/tts.mojom
@@ -31,14 +31,9 @@ bool is_network_connection_required; }; +// Deprecated method IDs: 0 // Next Method ID: 3 interface TtsHost { - // Notifies Chrome of Android tts events. - OnTtsEventDeprecated@0(uint32 utteranceId, - TtsEventType event_type, - uint32 char_index, - string error_msg); - // Notifies Chrome of Android tts voices. [MinVersion=2] OnVoicesChanged@1(array<TtsVoice> voices); @@ -50,11 +45,9 @@ string error_msg); }; +// Deprecated method IDs: 0 // Next Method ID: 4 interface TtsInstance { - // DEPRECATED: Please use Init@3 instead. - InitDeprecated@0(pending_remote<TtsHost> host_remote); - // Establishes full-duplex communication with the host. [MinVersion=1] Init@3(pending_remote<TtsHost> host_remote) => ();
diff --git a/ash/components/arc/mojom/usb_host.mojom b/ash/components/arc/mojom/usb_host.mojom index e31181ba..0edc5ec 100644 --- a/ash/components/arc/mojom/usb_host.mojom +++ b/ash/components/arc/mojom/usb_host.mojom
@@ -8,6 +8,7 @@ // re-use device.mojom.UsbDeviceInfo import "services/device/public/mojom/usb_device.mojom"; +// Deprecated method IDs: 0 // Next method ID: 4 interface UsbHostHost { // Tries to open the USB device node for the device named 'guid' for caller @@ -16,16 +17,6 @@ // call will fail. Note the 'pkg_name' is informational purposes only, there // is no effective way that host can restrict access to only a specific // package at the security boundary formed by this Mojo interface. - // Deprecated. - OpenDeviceDeprecated@0(string guid, - [MinVersion=1] string? pkg_name) => (handle usb_fd); - - // Tries to open the USB device node for the device named 'guid' for caller - // 'pkg_name' and returns an open file descriptor to this node. 'pkg_name' - // needs to have previously called RequestPermission for this 'guid' else this - // call will fail. Note the 'pkg_name' is informational purposes only, there - // is no effective way that host can restrict access to only a specific - // package at the security boundary formed by this Mojo interface. // When app tries to open a device without requesting permission, or // permission_broker rejects the open request, empty handle will be returned. [MinVersion=3] OpenDevice@3(string guid, string? pkg_name) =>
diff --git a/ash/components/arc/mojom/video.mojom b/ash/components/arc/mojom/video.mojom index a9bca34..d45c414 100644 --- a/ash/components/arc/mojom/video.mojom +++ b/ash/components/arc/mojom/video.mojom
@@ -24,11 +24,9 @@ string token); }; +// Deprecated method IDs: 0 // Next method ID: 2 interface VideoInstance { - // DEPRECATED: Please use Init@1 instead. - InitDeprecated@0(pending_remote<VideoHost> host_remote); - // Establishes full-duplex communication with the host. [MinVersion=5] Init@1(pending_remote<VideoHost> host_remote) => (); };
diff --git a/ash/components/arc/mojom/video_encode_accelerator.mojom b/ash/components/arc/mojom/video_encode_accelerator.mojom index 857e97d..0e09919 100644 --- a/ash/components/arc/mojom/video_encode_accelerator.mojom +++ b/ash/components/arc/mojom/video_encode_accelerator.mojom
@@ -116,20 +116,6 @@ Initialize@9(VideoEncodeAcceleratorConfig config, pending_remote<VideoEncodeClient> client) => (Result result); - // Initializes the video encoder with specific configuration. Called once per - // encoder construction. - // Parameters: - // |config| is the parameter set for encoder initialization. - // |client| is the client of this video encoder. The client must be valid - // during the lifetime of this accelerator. - // Callback: - // Called with true iff initialization is successful. The client should not - // invoke any other methods before the callback. - [MinVersion=1] - InitializeDeprecated@7(VideoEncodeAcceleratorConfig config, - pending_remote<VideoEncodeClient> client) => - (bool success); - // Encodes the given frame. // Parameters: // |format| is the pixel format of video frame. This could be different from
diff --git a/ash/components/arc/mojom/wallpaper.mojom b/ash/components/arc/mojom/wallpaper.mojom index cab9703..d3497089d 100644 --- a/ash/components/arc/mojom/wallpaper.mojom +++ b/ash/components/arc/mojom/wallpaper.mojom
@@ -21,11 +21,9 @@ }; // Connects with container side to publish wallpaper related intents. +// Deprecated method IDs: 0 // Next method ID: 4 interface WallpaperInstance { - // DEPRECATED: Please use Init@3 instead. - InitDeprecated@0(pending_remote<WallpaperHost> host_remote); - // Establishes full-duplex communication with the host. [MinVersion=3] Init@3(pending_remote<WallpaperHost> host_remote) => ();
diff --git a/ash/components/arc/session/arc_vm_client_adapter.cc b/ash/components/arc/session/arc_vm_client_adapter.cc index 6f04f3b..ed702a61 100644 --- a/ash/components/arc/session/arc_vm_client_adapter.cc +++ b/ash/components/arc/session/arc_vm_client_adapter.cc
@@ -300,6 +300,13 @@ } } + if (base::FeatureList::IsEnabled(kVmMemoryPSIReports)) { + auto period = kVmMemoryPSIReportsPeriod.Get(); + // Since Android performs parameter validation, not doing it here. + result.push_back(base::StringPrintf( + "androidboot.arcvm_metrics_mem_psi_period=%d", period)); + } + if (base::FeatureList::IsEnabled(arc::kUseDalvikMemoryProfile)) { switch (start_params.dalvik_memory_profile) { case StartParams::DalvikMemoryProfile::DEFAULT:
diff --git a/ash/components/arc/session/arc_vm_client_adapter_unittest.cc b/ash/components/arc/session/arc_vm_client_adapter_unittest.cc index bb630d9..ce6d923 100644 --- a/ash/components/arc/session/arc_vm_client_adapter_unittest.cc +++ b/ash/components/arc/session/arc_vm_client_adapter_unittest.cc
@@ -2289,6 +2289,38 @@ base::Contains(request.params(), "androidboot.arcvm.logd.size=1M")); } +// Test that StartArcVmRequest has no matching command line flag +// when kVmMemoryPSIReports is enabled. +TEST_F(ArcVmClientAdapterTest, ArcVmMemoryPSIReportsDisabled) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndDisableFeature(kVmMemoryPSIReports); + StartParams start_params(GetPopulatedStartParams()); + SetValidUserInfo(); + StartMiniArcWithParams(true, std::move(start_params)); + EXPECT_GE(GetTestConciergeClient()->start_arc_vm_call_count(), 1); + EXPECT_FALSE(is_system_shutdown().has_value()); + const auto& request = GetTestConciergeClient()->start_arc_vm_request(); + EXPECT_FALSE(HasParameterWithPrefix( + request, "androidboot.arcvm_metrics_mem_psi_period=")); +} + +// Test that StartArcVmRequest has correct command line flag +// when kVmMemoryPSIReports is enabled. +TEST_F(ArcVmClientAdapterTest, ArcVmMemoryPSIReportsEnabled) { + base::test::ScopedFeatureList feature_list; + base::FieldTrialParams params; + params["period"] = "300"; + feature_list.InitAndEnableFeatureWithParameters(kVmMemoryPSIReports, params); + StartParams start_params(GetPopulatedStartParams()); + SetValidUserInfo(); + StartMiniArcWithParams(true, std::move(start_params)); + EXPECT_GE(GetTestConciergeClient()->start_arc_vm_call_count(), 1); + EXPECT_FALSE(is_system_shutdown().has_value()); + const auto& request = GetTestConciergeClient()->start_arc_vm_request(); + EXPECT_TRUE(base::Contains(request.params(), + "androidboot.arcvm_metrics_mem_psi_period=300")); +} + struct DalvikMemoryProfileTestParam { // Requested profile. StartParams::DalvikMemoryProfile profile;
diff --git a/ash/components/arc/test/fake_accessibility_helper_instance.cc b/ash/components/arc/test/fake_accessibility_helper_instance.cc index 1f58f84..859787e 100644 --- a/ash/components/arc/test/fake_accessibility_helper_instance.cc +++ b/ash/components/arc/test/fake_accessibility_helper_instance.cc
@@ -33,10 +33,18 @@ } void FakeAccessibilityHelperInstance:: + SetNativeChromeVoxArcSupportForFocusedWindowDeprecated( + bool enabled, + SetNativeChromeVoxArcSupportForFocusedWindowDeprecatedCallback + callback) { + std::move(callback).Run(true); +} + +void FakeAccessibilityHelperInstance:: SetNativeChromeVoxArcSupportForFocusedWindow( bool enabled, SetNativeChromeVoxArcSupportForFocusedWindowCallback callback) { - std::move(callback).Run(true); + std::move(callback).Run(arc::mojom::SetNativeChromeVoxResponse::SUCCESS); } void FakeAccessibilityHelperInstance::SetExploreByTouchEnabled(bool enabled) {
diff --git a/ash/components/arc/test/fake_accessibility_helper_instance.h b/ash/components/arc/test/fake_accessibility_helper_instance.h index 8cea85f..aaf0eac 100644 --- a/ash/components/arc/test/fake_accessibility_helper_instance.h +++ b/ash/components/arc/test/fake_accessibility_helper_instance.h
@@ -27,6 +27,10 @@ void SetFilter(mojom::AccessibilityFilterType filter_type) override; void PerformAction(mojom::AccessibilityActionDataPtr action_data_ptr, PerformActionCallback callback) override; + void SetNativeChromeVoxArcSupportForFocusedWindowDeprecated( + bool enabled, + SetNativeChromeVoxArcSupportForFocusedWindowDeprecatedCallback callback) + override; void SetNativeChromeVoxArcSupportForFocusedWindow( bool enabled, SetNativeChromeVoxArcSupportForFocusedWindowCallback callback) override;
diff --git a/ash/components/arc/test/fake_app_instance.cc b/ash/components/arc/test/fake_app_instance.cc index 021e68b..d5cad83 100644 --- a/ash/components/arc/test/fake_app_instance.cc +++ b/ash/components/arc/test/fake_app_instance.cc
@@ -62,11 +62,6 @@ : app_host_(app_host) {} FakeAppInstance::~FakeAppInstance() {} -void FakeAppInstance::InitDeprecated( - mojo::PendingRemote<mojom::AppHost> host_remote) { - Init(std::move(host_remote), base::DoNothing()); -} - void FakeAppInstance::Init(mojo::PendingRemote<mojom::AppHost> host_remote, InitCallback callback) { // For every change in a connection bind latest remote.
diff --git a/ash/components/arc/test/fake_app_instance.h b/ash/components/arc/test/fake_app_instance.h index f835aa07..231cd10 100644 --- a/ash/components/arc/test/fake_app_instance.h +++ b/ash/components/arc/test/fake_app_instance.h
@@ -98,7 +98,6 @@ ~FakeAppInstance() override; // mojom::AppInstance overrides: - void InitDeprecated(mojo::PendingRemote<mojom::AppHost> host_remote) override; void Init(mojo::PendingRemote<mojom::AppHost> host_remote, InitCallback callback) override; void LaunchAppDeprecated(const std::string& package_name,
diff --git a/ash/components/arc/test/fake_bluetooth_instance.cc b/ash/components/arc/test/fake_bluetooth_instance.cc index 24d425f..17cad4e 100644 --- a/ash/components/arc/test/fake_bluetooth_instance.cc +++ b/ash/components/arc/test/fake_bluetooth_instance.cc
@@ -47,11 +47,6 @@ FakeBluetoothInstance::LEConnectionStateChangeData:: ~LEConnectionStateChangeData() = default; -void FakeBluetoothInstance::InitDeprecated( - mojo::PendingRemote<mojom::BluetoothHost> host_remote) { - Init(std::move(host_remote), base::DoNothing()); -} - void FakeBluetoothInstance::Init( mojo::PendingRemote<mojom::BluetoothHost> host_remote, InitCallback callback) {
diff --git a/ash/components/arc/test/fake_bluetooth_instance.h b/ash/components/arc/test/fake_bluetooth_instance.h index ed5ac59..f8f240965 100644 --- a/ash/components/arc/test/fake_bluetooth_instance.h +++ b/ash/components/arc/test/fake_bluetooth_instance.h
@@ -115,8 +115,6 @@ ~FakeBluetoothInstance() override; // mojom::BluetoothInstance overrides: - void InitDeprecated( - mojo::PendingRemote<mojom::BluetoothHost> host_remote) override; void Init(mojo::PendingRemote<mojom::BluetoothHost> host_remote, InitCallback callback) override; void OnAdapterProperties(
diff --git a/ash/components/arc/test/fake_clipboard_instance.cc b/ash/components/arc/test/fake_clipboard_instance.cc index 23d71979..6f470e8 100644 --- a/ash/components/arc/test/fake_clipboard_instance.cc +++ b/ash/components/arc/test/fake_clipboard_instance.cc
@@ -17,11 +17,6 @@ std::move(callback).Run(); } -void FakeClipboardInstance::InitDeprecated( - mojo::PendingRemote<mojom::ClipboardHost> host_remote) { - Init(std::move(host_remote), base::DoNothing()); -} - void FakeClipboardInstance::OnHostClipboardUpdated() { num_host_clipboard_updated_++; }
diff --git a/ash/components/arc/test/fake_clipboard_instance.h b/ash/components/arc/test/fake_clipboard_instance.h index 2f52b8b..dd1bfaea 100644 --- a/ash/components/arc/test/fake_clipboard_instance.h +++ b/ash/components/arc/test/fake_clipboard_instance.h
@@ -24,8 +24,6 @@ // mojom::ClipboardInstance overrides: void Init(mojo::PendingRemote<mojom::ClipboardHost> host_remote, InitCallback callback) override; - void InitDeprecated( - mojo::PendingRemote<mojom::ClipboardHost> host_remote) override; void OnHostClipboardUpdated() override; private:
diff --git a/ash/components/arc/test/fake_file_system_instance.cc b/ash/components/arc/test/fake_file_system_instance.cc index bc526c9..5c89d58 100644 --- a/ash/components/arc/test/fake_file_system_instance.cc +++ b/ash/components/arc/test/fake_file_system_instance.cc
@@ -630,11 +630,6 @@ base::BindOnce(std::move(callback), MakeDocument(iter->second))); } -void FakeFileSystemInstance::InitDeprecated( - mojo::PendingRemote<mojom::FileSystemHost> host_remote) { - Init(std::move(host_remote), base::DoNothing()); -} - void FakeFileSystemInstance::Init( mojo::PendingRemote<mojom::FileSystemHost> host_remote, InitCallback callback) {
diff --git a/ash/components/arc/test/fake_file_system_instance.h b/ash/components/arc/test/fake_file_system_instance.h index e49ba99..e39b1ec 100644 --- a/ash/components/arc/test/fake_file_system_instance.h +++ b/ash/components/arc/test/fake_file_system_instance.h
@@ -339,7 +339,6 @@ const std::string& source_parent_document_id, const std::string& target_parent_document_id, MoveDocumentCallback callback) override; - void InitDeprecated(mojo::PendingRemote<mojom::FileSystemHost> host) override; void Init(mojo::PendingRemote<mojom::FileSystemHost> host, InitCallback callback) override; void OpenFileToRead(const std::string& url,
diff --git a/ash/components/arc/test/fake_net_instance.cc b/ash/components/arc/test/fake_net_instance.cc index c9f8eab..4eb132f 100644 --- a/ash/components/arc/test/fake_net_instance.cc +++ b/ash/components/arc/test/fake_net_instance.cc
@@ -10,9 +10,6 @@ FakeNetInstance::~FakeNetInstance() = default; -void FakeNetInstance::InitDeprecated( - mojo::PendingRemote<mojom::NetHost> host_remote) {} - void FakeNetInstance::Init(::mojo::PendingRemote<mojom::NetHost> host_remote, InitCallback callback) {}
diff --git a/ash/components/arc/test/fake_net_instance.h b/ash/components/arc/test/fake_net_instance.h index 499db3e8..7dfd17a 100644 --- a/ash/components/arc/test/fake_net_instance.h +++ b/ash/components/arc/test/fake_net_instance.h
@@ -17,8 +17,6 @@ FakeNetInstance(const FakeNetInstance&) = delete; FakeNetInstance& operator=(const FakeNetInstance&) = delete; - void InitDeprecated(mojo::PendingRemote<mojom::NetHost> host_remote) override; - void Init(::mojo::PendingRemote<mojom::NetHost> host_remote, InitCallback callback) override;
diff --git a/ash/components/arc/test/fake_notifications_instance.cc b/ash/components/arc/test/fake_notifications_instance.cc index 16d5a56..832a9a66 100644 --- a/ash/components/arc/test/fake_notifications_instance.cc +++ b/ash/components/arc/test/fake_notifications_instance.cc
@@ -37,11 +37,6 @@ void FakeNotificationsInstance::CancelPress(const std::string& key) {} -void FakeNotificationsInstance::InitDeprecated( - mojo::PendingRemote<mojom::NotificationsHost> host_remote) { - Init(std::move(host_remote), base::DoNothing()); -} - void FakeNotificationsInstance::Init( mojo::PendingRemote<mojom::NotificationsHost> host_remote, InitCallback callback) {
diff --git a/ash/components/arc/test/fake_notifications_instance.h b/ash/components/arc/test/fake_notifications_instance.h index 2b816ec..48db740 100644 --- a/ash/components/arc/test/fake_notifications_instance.h +++ b/ash/components/arc/test/fake_notifications_instance.h
@@ -25,8 +25,6 @@ ~FakeNotificationsInstance() override; // mojom::NotificationsInstance overrides: - void InitDeprecated( - mojo::PendingRemote<mojom::NotificationsHost> host_remote) override; void Init(mojo::PendingRemote<mojom::NotificationsHost> host_remote, InitCallback callback) override;
diff --git a/ash/components/arc/test/fake_policy_instance.cc b/ash/components/arc/test/fake_policy_instance.cc index 6ccfce3..c9b1f21c3 100644 --- a/ash/components/arc/test/fake_policy_instance.cc +++ b/ash/components/arc/test/fake_policy_instance.cc
@@ -17,11 +17,6 @@ FakePolicyInstance::~FakePolicyInstance() = default; -void FakePolicyInstance::InitDeprecated( - mojo::PendingRemote<mojom::PolicyHost> host_remote) { - Init(std::move(host_remote), base::DoNothing()); -} - void FakePolicyInstance::Init( mojo::PendingRemote<mojom::PolicyHost> host_remote, InitCallback callback) {
diff --git a/ash/components/arc/test/fake_policy_instance.h b/ash/components/arc/test/fake_policy_instance.h index ac683b5..8c1816d 100644 --- a/ash/components/arc/test/fake_policy_instance.h +++ b/ash/components/arc/test/fake_policy_instance.h
@@ -23,8 +23,6 @@ ~FakePolicyInstance() override; // mojom::PolicyInstance - void InitDeprecated( - mojo::PendingRemote<mojom::PolicyHost> host_remote) override; void Init(mojo::PendingRemote<mojom::PolicyHost> host_remote, InitCallback callback) override; void OnPolicyUpdated() override;
diff --git a/ash/components/arc/test/fake_power_instance.cc b/ash/components/arc/test/fake_power_instance.cc index 2b409f1..8ece156 100644 --- a/ash/components/arc/test/fake_power_instance.cc +++ b/ash/components/arc/test/fake_power_instance.cc
@@ -19,11 +19,6 @@ return std::move(suspend_callback_); } -void FakePowerInstance::InitDeprecated( - mojo::PendingRemote<mojom::PowerHost> host_remote) { - Init(std::move(host_remote), base::DoNothing()); -} - void FakePowerInstance::Init(mojo::PendingRemote<mojom::PowerHost> host_remote, InitCallback callback) { host_remote_.reset();
diff --git a/ash/components/arc/test/fake_power_instance.h b/ash/components/arc/test/fake_power_instance.h index 586ff92..a64b8c1 100644 --- a/ash/components/arc/test/fake_power_instance.h +++ b/ash/components/arc/test/fake_power_instance.h
@@ -35,8 +35,6 @@ SuspendCallback GetSuspendCallback(); // mojom::PowerInstance overrides: - void InitDeprecated( - mojo::PendingRemote<mojom::PowerHost> host_remote) override; void Init(mojo::PendingRemote<mojom::PowerHost> host_remote, InitCallback callback) override; void SetInteractive(bool enabled) override;
diff --git a/ash/components/arc/test/fake_process_instance.cc b/ash/components/arc/test/fake_process_instance.cc index fd8f7e4..e624f9c 100644 --- a/ash/components/arc/test/fake_process_instance.cc +++ b/ash/components/arc/test/fake_process_instance.cc
@@ -24,17 +24,6 @@ DCHECK(false); } -void FakeProcessInstance::RequestApplicationProcessMemoryInfoDeprecated( - RequestApplicationProcessMemoryInfoDeprecatedCallback callback) { - DCHECK(false); -} - -void FakeProcessInstance::RequestSystemProcessMemoryInfoDeprecated( - const std::vector<uint32_t>& nspids, - RequestSystemProcessMemoryInfoDeprecatedCallback callback) { - DCHECK(false); -} - void FakeProcessInstance::RequestApplicationProcessMemoryInfo( RequestApplicationProcessMemoryInfoCallback callback) { DCHECK(false);
diff --git a/ash/components/arc/test/fake_process_instance.h b/ash/components/arc/test/fake_process_instance.h index dfa52f50..b2e6359 100644 --- a/ash/components/arc/test/fake_process_instance.h +++ b/ash/components/arc/test/fake_process_instance.h
@@ -21,11 +21,6 @@ void KillProcess(uint32_t pid, const std::string& reason) override; void RequestProcessList(RequestProcessListCallback callback) override; - void RequestApplicationProcessMemoryInfoDeprecated( - RequestApplicationProcessMemoryInfoDeprecatedCallback callback) override; - void RequestSystemProcessMemoryInfoDeprecated( - const std::vector<uint32_t>& nspids, - RequestSystemProcessMemoryInfoDeprecatedCallback callback) override; void RequestApplicationProcessMemoryInfo( RequestApplicationProcessMemoryInfoCallback callback) override; void RequestSystemProcessMemoryInfo(
diff --git a/ash/components/arc/test/fake_wallpaper_instance.cc b/ash/components/arc/test/fake_wallpaper_instance.cc index 82150aef..9ca531d6 100644 --- a/ash/components/arc/test/fake_wallpaper_instance.cc +++ b/ash/components/arc/test/fake_wallpaper_instance.cc
@@ -15,11 +15,6 @@ FakeWallpaperInstance::~FakeWallpaperInstance() = default; -void FakeWallpaperInstance::InitDeprecated( - mojo::PendingRemote<mojom::WallpaperHost> host_remote) { - Init(std::move(host_remote), base::DoNothing()); -} - void FakeWallpaperInstance::Init( mojo::PendingRemote<mojom::WallpaperHost> host_remote, InitCallback callback) {
diff --git a/ash/components/arc/test/fake_wallpaper_instance.h b/ash/components/arc/test/fake_wallpaper_instance.h index 5b4fe284..31cc480 100644 --- a/ash/components/arc/test/fake_wallpaper_instance.h +++ b/ash/components/arc/test/fake_wallpaper_instance.h
@@ -26,8 +26,6 @@ const std::vector<int32_t>& changed_ids() const { return changed_ids_; } // Overridden from mojom::WallpaperInstance - void InitDeprecated( - mojo::PendingRemote<mojom::WallpaperHost> host_remote) override; void Init(mojo::PendingRemote<mojom::WallpaperHost> host_remote, InitCallback callback) override; void OnWallpaperChanged(int32_t walpaper_id) override;
diff --git a/ash/components/arc/usb/usb_host_bridge.cc b/ash/components/arc/usb/usb_host_bridge.cc index 3bb72cd..1399040 100644 --- a/ash/components/arc/usb/usb_host_bridge.cc +++ b/ash/components/arc/usb/usb_host_bridge.cc
@@ -200,14 +200,6 @@ base::BindOnce(&OnDeviceOpenError, std::move(split_callback.second))); } -void ArcUsbHostBridge::OpenDeviceDeprecated( - const std::string& guid, - const absl::optional<std::string>& package, - OpenDeviceCallback callback) { - LOG(ERROR) << "ArcUsbHostBridge::OpenDeviceDeprecated is deprecated"; - OpenDevice(guid, package, std::move(callback)); -} - void ArcUsbHostBridge::GetDeviceInfo(const std::string& guid, GetDeviceInfoCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_);
diff --git a/ash/components/arc/usb/usb_host_bridge.h b/ash/components/arc/usb/usb_host_bridge.h index c4f5eaa..f2c56ef 100644 --- a/ash/components/arc/usb/usb_host_bridge.h +++ b/ash/components/arc/usb/usb_host_bridge.h
@@ -72,9 +72,6 @@ const std::string& package, bool interactive, RequestPermissionCallback callback) override; - void OpenDeviceDeprecated(const std::string& guid, - const absl::optional<std::string>& package, - OpenDeviceCallback callback) override; void OpenDevice(const std::string& guid, const absl::optional<std::string>& package, OpenDeviceCallback callback) override;
diff --git a/ash/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.cc b/ash/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.cc index fedac047..2fd5857 100644 --- a/ash/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.cc +++ b/ash/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.cc
@@ -103,15 +103,6 @@ std::move(callback).Run(result); } -void GpuArcVideoEncodeAccelerator::InitializeDeprecated( - const media::VideoEncodeAccelerator::Config& config, - mojo::PendingRemote<mojom::VideoEncodeClient> client, - InitializeDeprecatedCallback callback) { - auto result = InitializeTask(config, std::move(client)); - std::move(callback).Run(result == - mojom::VideoEncodeAccelerator::Result::kSuccess); -} - mojom::VideoEncodeAccelerator::Result GpuArcVideoEncodeAccelerator::InitializeTask( const media::VideoEncodeAccelerator::Config& config,
diff --git a/ash/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.h b/ash/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.h index 520e122..545868c 100644 --- a/ash/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.h +++ b/ash/components/arc/video_accelerator/gpu_arc_video_encode_accelerator.h
@@ -57,10 +57,6 @@ void Initialize(const media::VideoEncodeAccelerator::Config& config, mojo::PendingRemote<mojom::VideoEncodeClient> client, InitializeCallback callback) override; - void InitializeDeprecated( - const media::VideoEncodeAccelerator::Config& config, - mojo::PendingRemote<mojom::VideoEncodeClient> client, - InitializeDeprecatedCallback callback) override; mojom::VideoEncodeAccelerator::Result InitializeTask( const media::VideoEncodeAccelerator::Config& config, mojo::PendingRemote<mojom::VideoEncodeClient> client);
diff --git a/ash/components/fwupd/BUILD.gn b/ash/components/fwupd/BUILD.gn index d6c6f1c..396d1440 100644 --- a/ash/components/fwupd/BUILD.gn +++ b/ash/components/fwupd/BUILD.gn
@@ -10,7 +10,6 @@ defines = [ "IS_ASH_FIRMWARE_UPDATE_MANAGER_IMPL" ] deps = [ - "//ash/public/cpp", "//ash/public/mojom", "//ash/webui/firmware_update_ui/mojom", "//base:base", @@ -30,21 +29,14 @@ deps = [ ":fwupd", "//ash/constants", - "//ash/public/cpp", "//ash/public/mojom", "//ash/webui/firmware_update_ui/mojom", "//base/test:test_support", "//chromeos/dbus/fwupd", "//dbus:test_support", - "//services/network:test_support", - "//services/network/public/cpp", "//testing/gmock", "//testing/gtest", ] - sources = [ - "fake_fwupd_download_client.cc", - "fake_fwupd_download_client.h", - "firmware_update_manager_unittest.cc", - ] + sources = [ "firmware_update_manager_unittest.cc" ] }
diff --git a/ash/components/fwupd/fake_fwupd_download_client.cc b/ash/components/fwupd/fake_fwupd_download_client.cc deleted file mode 100644 index e293265..0000000 --- a/ash/components/fwupd/fake_fwupd_download_client.cc +++ /dev/null
@@ -1,81 +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 "ash/components/fwupd/fake_fwupd_download_client.h" - -#include <memory> -#include <utility> - -#include "mojo/public/cpp/bindings/pending_receiver.h" -#include "mojo/public/cpp/bindings/pending_remote.h" -#include "net/traffic_annotation/network_traffic_annotation.h" -#include "services/network/public/cpp/shared_url_loader_factory.h" -#include "services/network/test/test_url_loader_factory.h" - -namespace { - -class FakeSharedURLLoaderFactory : public network::SharedURLLoaderFactory { - public: - FakeSharedURLLoaderFactory() = default; - FakeSharedURLLoaderFactory(const FakeSharedURLLoaderFactory&) = delete; - FakeSharedURLLoaderFactory& operator=(const FakeSharedURLLoaderFactory&) = - delete; - - // network::mojom::URLLoaderFactory implementation: - void Clone(mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver) - override { - test_url_loader_factory_.Clone(std::move(receiver)); - } - - void CreateLoaderAndStart( - mojo::PendingReceiver<network::mojom::URLLoader> loader, - int32_t request_id, - uint32_t options, - const network::ResourceRequest& request, - mojo::PendingRemote<network::mojom::URLLoaderClient> client, - const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) - override { - test_url_loader_factory_.CreateLoaderAndStart( - std::move(loader), request_id, options, request, std::move(client), - traffic_annotation); - } - - // network::SharedURLLoaderFactory implementation: - std::unique_ptr<network::PendingSharedURLLoaderFactory> Clone() override { - NOTREACHED(); - return nullptr; - } - - network::TestURLLoaderFactory& test_url_loader_factory() { - return test_url_loader_factory_; - } - - private: - friend class base::RefCounted<FakeSharedURLLoaderFactory>; - - ~FakeSharedURLLoaderFactory() override = default; - - network::TestURLLoaderFactory test_url_loader_factory_; -}; - -} // namespace - -namespace ash { - -FakeFwupdDownloadClient::FakeFwupdDownloadClient() - : url_loader_factory_(base::MakeRefCounted<FakeSharedURLLoaderFactory>()) {} -FakeFwupdDownloadClient::~FakeFwupdDownloadClient() = default; - -scoped_refptr<network::SharedURLLoaderFactory> -FakeFwupdDownloadClient::GetURLLoaderFactory() { - return url_loader_factory_; -} - -network::TestURLLoaderFactory& -FakeFwupdDownloadClient::test_url_loader_factory() { - return static_cast<FakeSharedURLLoaderFactory*>(url_loader_factory_.get()) - ->test_url_loader_factory(); -} - -} // namespace ash
diff --git a/ash/components/fwupd/fake_fwupd_download_client.h b/ash/components/fwupd/fake_fwupd_download_client.h deleted file mode 100644 index 3f47de2..0000000 --- a/ash/components/fwupd/fake_fwupd_download_client.h +++ /dev/null
@@ -1,38 +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 ASH_COMPONENTS_FWUPD_FAKE_FWUPD_DOWNLOAD_CLIENT_H_ -#define ASH_COMPONENTS_FWUPD_FAKE_FWUPD_DOWNLOAD_CLIENT_H_ - -#include "ash/public/cpp/fwupd_download_client.h" -#include "base/component_export.h" -#include "services/network/test/test_url_loader_factory.h" - -namespace network { -class SharedURLLoaderFactory; -} // namespace network - -namespace ash { - -// A fake implementation of FwupdDownloadClient used for testing. -class COMPONENT_EXPORT(ASH_FIRMWARE_UPDATE_MANAGER) FakeFwupdDownloadClient - : public ash::FwupdDownloadClient { - public: - FakeFwupdDownloadClient(); - FakeFwupdDownloadClient(const FwupdDownloadClient&) = delete; - FakeFwupdDownloadClient& operator=(const FwupdDownloadClient&) = delete; - ~FakeFwupdDownloadClient() override; - - // ash::FwupdDownloadClient: - scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() override; - - network::TestURLLoaderFactory& test_url_loader_factory(); - - private: - scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_; -}; - -} // namespace ash - -#endif // ASH_COMPONENTS_FWUPD_FAKE_FWUPD_DOWNLOAD_CLIENT_H_
diff --git a/ash/components/fwupd/firmware_update_manager.cc b/ash/components/fwupd/firmware_update_manager.cc index b56e3b9..290e99f 100644 --- a/ash/components/fwupd/firmware_update_manager.cc +++ b/ash/components/fwupd/firmware_update_manager.cc
@@ -6,7 +6,6 @@ #include <utility> -#include "ash/public/cpp/fwupd_download_client.h" #include "ash/webui/firmware_update_ui/mojom/firmware_update.mojom.h" #include "base/base_paths.h" #include "base/check_op.h" @@ -25,13 +24,6 @@ #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/receiver.h" #include "mojo/public/cpp/bindings/remote_set.h" -#include "net/traffic_annotation/network_traffic_annotation.h" -#include "services/network/public/cpp/resource_request.h" -#include "services/network/public/cpp/shared_url_loader_factory.h" -#include "services/network/public/cpp/simple_url_loader.h" -#include "services/network/public/mojom/fetch_api.mojom.h" -#include "services/network/public/mojom/url_response_head.mojom.h" -#include "url/gurl.h" namespace ash { @@ -40,12 +32,6 @@ const char kBaseRootPath[] = "firmware-updates"; const char kCachePath[] = "cache"; const char kCabFileExtension[] = ".cab"; -const char kFirmwareMirrorPrefix[] = - "https://storage.googleapis.com/chromeos-localmirror/lvfs/"; - -const char kSampleFirmwareUpgrade[] = - "c15a0df7386812781d1f376fe54729e64f69b2a8a6c4b580914d4f6740e4fcc3-HP-USBC_" - "DOCK_G5-V1.0.13.0.cab"; FirmwareUpdateManager* g_instance = nullptr; @@ -84,39 +70,6 @@ return update; } -constexpr net::NetworkTrafficAnnotationTag kFwupdFirmwareUpdateNetworkTag = - net::DefineNetworkTrafficAnnotation("fwupd_firmware_update", R"( - semantics { - sender: "FWUPD firmware update" - description: - "Get the firmware update patch file from url and store it in the " - "the device cache. This is used to update a specific peripheral's " - "firmware." - - trigger: - "Triggered by the user when they explicitly use the Firmware Update" - " UI to update their peripheral." - data: "None." - destination: GOOGLE_OWNED_SERVICE - })"); - -std::unique_ptr<network::SimpleURLLoader> CreateSimpleURLLoader(GURL url) { - auto resource_request = std::make_unique<network::ResourceRequest>(); - resource_request->url = url; - resource_request->method = "GET"; - resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit; - - return network::SimpleURLLoader::Create(std::move(resource_request), - kFwupdFirmwareUpdateNetworkTag); -} - -int GetResponseCode(network::SimpleURLLoader* simple_loader) { - if (simple_loader->ResponseInfo() && simple_loader->ResponseInfo()->headers) - return simple_loader->ResponseInfo()->headers->response_code(); - else - return -1; -} - } // namespace FirmwareUpdateManager::FirmwareUpdateManager() @@ -188,7 +141,7 @@ .Append(FILE_PATH_LITERAL(kCachePath)); base::OnceClosure dir_created_callback = - base::BindOnce(&FirmwareUpdateManager::CreateLocalPatchFile, + base::BindOnce(&FirmwareUpdateManager::OnCacheDirectoryCreated, weak_ptr_factory_.GetWeakPtr(), cache_path, device_id, release, std::move(callback)); @@ -198,14 +151,14 @@ [](const base::FilePath& path) { if (!CreateDirIfNotExists(path)) { LOG(ERROR) << "Cannot create firmware update directory, " - << "may be created already."; + << " may be created already."; } }, cache_path), std::move(dir_created_callback)); } -void FirmwareUpdateManager::CreateLocalPatchFile( +void FirmwareUpdateManager::OnCacheDirectoryCreated( const base::FilePath& cache_path, const std::string& device_id, int release, @@ -213,59 +166,6 @@ const base::FilePath patch_path = cache_path.Append(GetFilenameFromDevice(device_id, release)); - // Create the patch file. - task_runner_->PostTaskAndReply( - FROM_HERE, - base::BindOnce( - [](const base::FilePath& patch_path) { - base::WriteFile(patch_path, /*data=*/"", /*size=*/1); - }, - patch_path), - base::BindOnce(&FirmwareUpdateManager::DownloadFileToInternal, - weak_ptr_factory_.GetWeakPtr(), patch_path, device_id, - std::move(callback))); -} - -void FirmwareUpdateManager::DownloadFileToInternal( - const base::FilePath& patch_path, - const std::string& device_id, - base::OnceCallback<void()> callback) { - std::string prefix_url(kFirmwareMirrorPrefix); - GURL download_url(fake_url_for_testing_.empty() - ? prefix_url + std::string(kSampleFirmwareUpgrade) - : fake_url_for_testing_); - - std::unique_ptr<network::SimpleURLLoader> simple_loader = - CreateSimpleURLLoader(download_url); - DCHECK(FwupdDownloadClient::Get()); - - scoped_refptr<network::SharedURLLoaderFactory> loader_factory = - FwupdDownloadClient::Get()->GetURLLoaderFactory(); - // Save the pointer before moving `simple_loader` in the following call to - // `DownloadToFile()`. - auto* loader_ptr = simple_loader.get(); - - loader_ptr->DownloadToFile( - loader_factory.get(), - base::BindOnce(&FirmwareUpdateManager::OnUrlDownloadedToFile, - weak_ptr_factory_.GetWeakPtr(), device_id, - std::move(simple_loader), std::move(callback)), - patch_path); -} - -void FirmwareUpdateManager::OnUrlDownloadedToFile( - const std::string& device_id, - std::unique_ptr<network::SimpleURLLoader> simple_loader, - base::OnceCallback<void()> callback, - base::FilePath download_path) { - if (simple_loader->NetError() != net::OK) { - LOG(ERROR) << "Downloading to file failed with error code: " - << GetResponseCode(simple_loader.get()) << " with network error " - << simple_loader->NetError(); - std::move(callback).Run(); - return; - } - // TODO(jimmyxgong): Determine if this options map can be static or will need // to remain dynamic. // Fwupd Install Dbus flags, flag documentation can be found in @@ -276,7 +176,7 @@ {"allow-reinstall", true}}; task_runner_->PostTaskAndReplyWithResult( - FROM_HERE, base::BindOnce(&OpenFileAndGetFileDescriptor, download_path), + FROM_HERE, base::BindOnce(&OpenFileAndGetFileDescriptor, patch_path), base::BindOnce(&FirmwareUpdateManager::InstallUpdate, weak_ptr_factory_.GetWeakPtr(), device_id, std::move(options), std::move(callback)));
diff --git a/ash/components/fwupd/firmware_update_manager.h b/ash/components/fwupd/firmware_update_manager.h index 5ecd0ab..55165a1 100644 --- a/ash/components/fwupd/firmware_update_manager.h +++ b/ash/components/fwupd/firmware_update_manager.h
@@ -23,12 +23,6 @@ #include "mojo/public/cpp/bindings/receiver.h" #include "mojo/public/cpp/bindings/remote_set.h" -namespace network { - -class SimpleURLLoader; - -} // namespace network - namespace ash { // FirmwareUpdateManager contains all logic that runs the firmware update SWA. class COMPONENT_EXPORT(ASH_FIRMWARE_UPDATE_MANAGER) FirmwareUpdateManager @@ -98,20 +92,10 @@ base::OnceCallback<void()> callback, base::ScopedFD file_descriptor); - void CreateLocalPatchFile(const base::FilePath& cache_path, - const std::string& device_id, - int release, - base::OnceCallback<void()> callback); - - void DownloadFileToInternal(const base::FilePath& patch_path, - const std::string& device_id, - base::OnceCallback<void()> callback); - - void OnUrlDownloadedToFile( - const std::string& device_id, - std::unique_ptr<network::SimpleURLLoader> simple_loader, - base::OnceCallback<void()> callback, - base::FilePath download_path); + void OnCacheDirectoryCreated(const base::FilePath& root_path, + const std::string& device_id, + int release, + base::OnceCallback<void()> callback); // Notifies observers registered with ObservePeripheralUpdates() the current // list of devices with pending updates (if any). @@ -119,10 +103,6 @@ bool HasPendingUpdates(); - void SetFakeUrlForTesting(const std::string& fake_url) { - fake_url_for_testing_ = fake_url; - } - // Map of a device ID to `FwupdDevice` which is waiting for the list // of updates. base::flat_map<std::string, chromeos::FwupdDevice> devices_pending_update_; @@ -131,9 +111,6 @@ // empty then this list is not yet complete. std::vector<firmware_update::mojom::FirmwareUpdatePtr> updates_; - // Only used for testing if StartInstall() queries to a fake URL. - std::string fake_url_for_testing_; - // Remotes for tracking observers that will be notified of changes to the // list of firmware updates. mojo::RemoteSet<firmware_update::mojom::UpdateObserver>
diff --git a/ash/components/fwupd/firmware_update_manager_unittest.cc b/ash/components/fwupd/firmware_update_manager_unittest.cc index bad84e5..f4b4a15 100644 --- a/ash/components/fwupd/firmware_update_manager_unittest.cc +++ b/ash/components/fwupd/firmware_update_manager_unittest.cc
@@ -9,7 +9,6 @@ #include <memory> #include <string> -#include "ash/components/fwupd/fake_fwupd_download_client.h" #include "ash/constants/ash_features.h" #include "base/files/file.h" #include "base/files/file_path.h" @@ -24,8 +23,6 @@ #include "dbus/mock_object_proxy.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/receiver.h" -#include "services/network/public/cpp/shared_url_loader_factory.h" -#include "services/network/test/test_url_loader_factory.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -108,7 +105,6 @@ dbus_client_ = FwupdClient::Create(); dbus_client_->InitForTesting(bus_.get()); - fake_fwupd_download_client_ = std::make_unique<FakeFwupdDownloadClient>(); firmware_update_manager_ = std::make_unique<FirmwareUpdateManager>(); } FirmwareUpdateManagerTest(const FirmwareUpdateManagerTest&) = delete; @@ -137,10 +133,6 @@ loop.Run(); } - void SetFakeUrlForTesting(const std::string& fake_url) { - firmware_update_manager_->SetFakeUrlForTesting(fake_url); - } - std::unique_ptr<dbus::Response> CreateEmptyDeviceResponse() { auto response = dbus::Response::CreateEmpty(); @@ -305,13 +297,8 @@ base::RunLoop().RunUntilIdle(); } - network::TestURLLoaderFactory& GetTestUrlLoaderFactory() { - return fake_fwupd_download_client_->test_url_loader_factory(); - } - // `FwupdClient` must be be before `FirmwareUpdateManager`. std::unique_ptr<FwupdClient> dbus_client_; - std::unique_ptr<FakeFwupdDownloadClient> fake_fwupd_download_client_; std::unique_ptr<FirmwareUpdateManager> firmware_update_manager_; // Mock bus for simulating calls. @@ -420,26 +407,24 @@ dbus_responses_.push_back(dbus::Response::CreateEmpty()); - std::string fake_url = "https://faketesturl/"; - std::unique_ptr<FirmwareUpdateManager> firmware_update_manager_; - SetFakeUrlForTesting(fake_url); - GetTestUrlLoaderFactory().AddResponse(fake_url, ""); - - EXPECT_EQ(0, GetOnInstallResponseCallbackCallCountForTesting()); - StartInstall(std::string(kFakeDeviceIdForTesting), /*release=*/0); - - base::RunLoop().RunUntilIdle(); - base::FilePath root_dir; CHECK(base::PathService::Get(base::DIR_TEMP, &root_dir)); const base::FilePath root_path = root_dir.Append(FILE_PATH_LITERAL(kDownloadDir)) .Append(FILE_PATH_LITERAL(kCacheDir)); + const std::string test_filename = std::string(kFakeDeviceIdForTesting) + std::string(kCabExtension); base::FilePath full_path = root_path.Append(test_filename); - // Check that that expected patch file was created. + // Create a temporary file to simulate a .cab available for install. + base::WriteFile(full_path, "", 0); EXPECT_TRUE(base::PathExists(full_path)); + base::RunLoop().RunUntilIdle(); + + EXPECT_EQ(0, GetOnInstallResponseCallbackCallCountForTesting()); + StartInstall(std::string(kFakeDeviceIdForTesting), /*release=*/0); + + base::RunLoop().RunUntilIdle(); EXPECT_EQ(1, GetOnInstallResponseCallbackCallCountForTesting()); }
diff --git a/ash/components/timezone/timezone_request.cc b/ash/components/timezone/timezone_request.cc index 036aa63..00da029 100644 --- a/ash/components/timezone/timezone_request.cc +++ b/ash/components/timezone/timezone_request.cc
@@ -93,6 +93,54 @@ TIMEZONE_REQUEST_RESULT_COUNT = 4 }; +constexpr net::NetworkTrafficAnnotationTag kTimezoneRequestNetworkTag = + net::DefineNetworkTrafficAnnotation("timezone_lookup", R"( + semantics { + sender: "Timezone Resolver" + description: + "Determine the user's timezone based on their geolocation." + trigger: + "Triggered during the device setup wizard, on boot, on user " + "session start, and in regular intervals." + data: + "The user's geolocation. By default, the geolocation is determined " + "from the ip address of the user, but depending on policies and " + "preferences, the user's Wi-Fi and mobile networks can also be " + "taken into account." + destination: GOOGLE_OWNED_SERVICE + } + policy { + cookies_allowed: NO + setting: + "You can enable or disable automatic timezone detection in Chrome " + "OS settings under 'Advanced' -> 'Date and time' -> 'Timezone' by " + "specifying a fixed timezone under 'Choose from list'. When you do " + "not specify a fixed timezone, you can select whether just the ip " + "address or also Wi-Fi and mobile networks are used to determine " + "your geolocation." + policy_exception_justification: + "Controlled by SystemTimeZone and SystemTimezonAutomaticDetection. " + "chrome_device_policy not supported by auditor yet." + # TODO(b/210911671): Add the following policies once they are + # supported: + # chrome_policy { + # SystemTimezone { + # # cmfcmf: HasSystemTimezonePolicy + # timezone: 'not empty, e.g. Europe/Berlin' + # } + # } + # chrome_policy { + # SystemTimezone { + # AutomaticTimezoneDetectionType: DISABLED + # } + # } + # chrome_policy { + # SystemTimezone { + # AutomaticTimezoneDetectionType: IP_ONLY + # } + # } + })"); + // Too many requests (more than 1) mean there is a problem in implementation. void RecordUmaEvent(TimeZoneRequestEvent event) { UMA_HISTOGRAM_ENUMERATION( @@ -354,7 +402,7 @@ request->load_flags = net::LOAD_BYPASS_CACHE | net::LOAD_DISABLE_CACHE; request->credentials_mode = network::mojom::CredentialsMode::kOmit; url_loader_ = network::SimpleURLLoader::Create(std::move(request), - NO_TRAFFIC_ANNOTATION_YET); + kTimezoneRequestNetworkTag); url_loader_->DownloadToStringOfUnboundedSizeUntilCrashAndDie( shared_url_loader_factory_.get(),
diff --git a/ash/search_box/search_box_view_base.cc b/ash/search_box/search_box_view_base.cc index a37676fa..135b02a 100644 --- a/ash/search_box/search_box_view_base.cc +++ b/ash/search_box/search_box_view_base.cc
@@ -251,6 +251,11 @@ } } + void GetAccessibleNodeData(ui::AXNodeData* node_data) override { + views::Textfield::GetAccessibleNodeData(node_data); + search_box_view_->UpdateSearchTextfieldAccessibleNodeData(node_data); + } + private: SearchBoxViewBase* const search_box_view_; }; @@ -521,6 +526,9 @@ return trimmed_query.empty(); } +void SearchBoxViewBase::UpdateSearchTextfieldAccessibleNodeData( + ui::AXNodeData* node_data) {} + void SearchBoxViewBase::ClearSearch() { // Avoid setting |search_box_| text to empty if it is already empty. if (search_box_->GetText() == std::u16string())
diff --git a/ash/search_box/search_box_view_base.h b/ash/search_box/search_box_view_base.h index 87becba..f6a1922 100644 --- a/ash/search_box/search_box_view_base.h +++ b/ash/search_box/search_box_view_base.h
@@ -114,6 +114,9 @@ // Whether the trimmed query in the search box is empty. bool IsSearchBoxTrimmedQueryEmpty() const; + virtual void UpdateSearchTextfieldAccessibleNodeData( + ui::AXNodeData* node_data); + virtual void ClearSearch(); // Called when the search box active state changes.
diff --git a/ash/services/recording/recording_encoder_muxer.cc b/ash/services/recording/recording_encoder_muxer.cc index b8dbd20..b528f70 100644 --- a/ash/services/recording/recording_encoder_muxer.cc +++ b/ash/services/recording/recording_encoder_muxer.cc
@@ -153,7 +153,7 @@ // Holds on to the old encoder until it flushes its buffers, then // destroys it. [](std::unique_ptr<media::VpxVideoEncoder> old_encoder, - media::Status status) {}, + media::EncoderStatus status) {}, std::move(video_encoder_))); } @@ -215,7 +215,7 @@ base::BindOnce(&RecordingEncoderMuxer::OnAudioEncoderFlushed, weak_ptr_factory_.GetWeakPtr(), std::move(on_done))); } else { - OnAudioEncoderFlushed(std::move(on_done), media::OkStatus()); + OnAudioEncoderFlushed(std::move(on_done), media::EncoderStatus::Codes::kOk); } } @@ -260,7 +260,8 @@ weak_ptr_factory_.GetWeakPtr())); } -void RecordingEncoderMuxer::OnAudioEncoderInitialized(media::Status status) { +void RecordingEncoderMuxer::OnAudioEncoderInitialized( + media::EncoderStatus status) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!status.is_ok()) { @@ -278,7 +279,7 @@ void RecordingEncoderMuxer::OnVideoEncoderInitialized( media::VpxVideoEncoder* encoder, - media::Status status) { + media::EncoderStatus status) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // Ignore initialization of encoders that were removed as part of @@ -362,7 +363,7 @@ } void RecordingEncoderMuxer::OnAudioEncoderFlushed(base::OnceClosure on_done, - media::Status status) { + media::EncoderStatus status) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!status.is_ok()) @@ -375,7 +376,7 @@ } void RecordingEncoderMuxer::OnVideoEncoderFlushed(base::OnceClosure on_done, - media::Status status) { + media::EncoderStatus status) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!status.is_ok()) { @@ -388,7 +389,7 @@ } void RecordingEncoderMuxer::OnEncoderStatus(bool for_video, - media::Status status) { + media::EncoderStatus status) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (status.is_ok())
diff --git a/ash/services/recording/recording_encoder_muxer.h b/ash/services/recording/recording_encoder_muxer.h index fcfc5c3..e504cc0 100644 --- a/ash/services/recording/recording_encoder_muxer.h +++ b/ash/services/recording/recording_encoder_muxer.h
@@ -135,13 +135,13 @@ // Called when the audio encoder is initialized to provide the |status| of // the initialization. - void OnAudioEncoderInitialized(media::Status status); + void OnAudioEncoderInitialized(media::EncoderStatus status); // Called when the video |encoder| is initialized to provide the |status| of // the initialization. If initialization failed, |on_failure_callback_| will // be triggered. void OnVideoEncoderInitialized(media::VpxVideoEncoder* encoder, - media::Status status); + media::EncoderStatus status); // Performs the actual encoding of the given audio |frame|. It should never be // called before the audio encoder is initialized. Audio frames received @@ -169,16 +169,18 @@ // Called when the audio encoder flushes all its buffered frames, at which // point we can flush the video encoder. |on_done| will be passed to // OnVideoEncoderFlushed() - void OnAudioEncoderFlushed(base::OnceClosure on_done, media::Status status); + void OnAudioEncoderFlushed(base::OnceClosure on_done, + media::EncoderStatus status); // Called when the video encoder flushes all its buffered frames, at which // point we can flush the muxer. |on_done| will be called to signal that // flushing is complete. - void OnVideoEncoderFlushed(base::OnceClosure on_done, media::Status status); + void OnVideoEncoderFlushed(base::OnceClosure on_done, + media::EncoderStatus status); // Called by both the audio and video encoders to provide the |status| of // encoding tasks. - void OnEncoderStatus(bool for_video, media::Status status); + void OnEncoderStatus(bool for_video, media::EncoderStatus status); // Notifies the owner of this object (via |on_failure_callback_|) that a // failure noted by |status| has occurred during audio or video encoding, or
diff --git a/ash/session/fullscreen_controller.cc b/ash/session/fullscreen_controller.cc index 45c9017a..a012772 100644 --- a/ash/session/fullscreen_controller.cc +++ b/ash/session/fullscreen_controller.cc
@@ -146,9 +146,4 @@ MaybeShowNotification(); } -void FullscreenController::OnLockStateChanged(bool locked) { - if (!locked) - MaybeShowNotification(); -} - } // namespace ash
diff --git a/ash/session/fullscreen_controller.h b/ash/session/fullscreen_controller.h index 190e0fa..9938b50 100644 --- a/ash/session/fullscreen_controller.h +++ b/ash/session/fullscreen_controller.h
@@ -29,11 +29,6 @@ static void RegisterProfilePrefs(PrefRegistrySimple* registry); - void OnLockStateChanged(bool locked); - - // Returns the bubble for testing purposes. - FullscreenNotificationBubble* bubble_for_test() { return bubble_.get(); } - private: // chromeos::PowerManagerClient::Observer: void SuspendImminent(power_manager::SuspendImminent::Reason reason) override;
diff --git a/ash/session/session_controller_impl.cc b/ash/session/session_controller_impl.cc index a6a6a2d..3b05ebd 100644 --- a/ash/session/session_controller_impl.cc +++ b/ash/session/session_controller_impl.cc
@@ -490,14 +490,6 @@ observer.OnLockStateChanged(locked); session_activation_observer_holder_.NotifyLockStateChanged(locked); - - // We cannot use SessionObserver or SessionManagerObserver because they get - // notified before the lock screen widget is destroyed which would mean that - // the active window would always be a full screen window and the - // FullscreenController would therefore always show the - // FullscreenNotificationBubble. We cannot use SessionActivationObserver - // because they are always tied to an account. - fullscreen_controller_->OnLockStateChanged(locked); } EnsureSigninScreenPrefService();
diff --git a/ash/session/session_controller_impl.h b/ash/session/session_controller_impl.h index 7b9e5e8..17b6f6f 100644 --- a/ash/session/session_controller_impl.h +++ b/ash/session/session_controller_impl.h
@@ -219,10 +219,6 @@ // Test helpers. void ClearUserSessionsForTest(); - FullscreenController* fullscreen_controller_for_test() { - return fullscreen_controller_.get(); - } - private: friend class TestSessionControllerClient;
diff --git a/ash/session/session_controller_impl_unittest.cc b/ash/session/session_controller_impl_unittest.cc index d562520..85a9b917 100644 --- a/ash/session/session_controller_impl_unittest.cc +++ b/ash/session/session_controller_impl_unittest.cc
@@ -9,28 +9,21 @@ #include <utility> #include <vector> -#include "ash/constants/ash_features.h" -#include "ash/constants/ash_pref_names.h" #include "ash/login_status.h" #include "ash/public/cpp/ash_prefs.h" #include "ash/public/cpp/session/session_observer.h" -#include "ash/session/fullscreen_controller.h" -#include "ash/session/fullscreen_notification_bubble.h" #include "ash/session/test_session_controller_client.h" #include "ash/shell.h" #include "ash/system/tray/system_tray_notifier.h" #include "ash/test/ash_test_base.h" -#include "ash/wm/window_state.h" #include "ash/wm/window_util.h" #include "base/bind.h" #include "base/callback.h" #include "base/run_loop.h" -#include "base/test/scoped_feature_list.h" #include "base/threading/thread_task_runner_handle.h" #include "components/prefs/testing_pref_service.h" #include "components/user_manager/user_type.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/aura/client/aura_constants.h" #include "ui/aura/window.h" #include "ui/views/widget/widget.h" #include "ui/views/window/dialog_delegate.h" @@ -805,97 +798,5 @@ EXPECT_TRUE(widget->IsActive()); } -class SessionControllerImplLockStateChangedTest : public AshTestBase { - public: - SessionControllerImplLockStateChangedTest() {} - - SessionControllerImplLockStateChangedTest( - const SessionControllerImplLockStateChangedTest&) = delete; - SessionControllerImplLockStateChangedTest& operator=( - const SessionControllerImplLockStateChangedTest&) = delete; - - ~SessionControllerImplLockStateChangedTest() override {} - - // AshTestBase: - void SetUp() override { - // Enable the FullscreenAlertBubble feature for testing. - feature_list_.InitAndEnableFeature(features::kFullscreenAlertBubble); - - AshTestBase::SetUp(); - - // Set the FullscreenAlertEnabled pref value to true for testing. - Shell::Get()->session_controller()->GetPrimaryUserPrefService()->SetBoolean( - prefs::kFullscreenAlertEnabled, true); - - fullscreen_controller_ = - Shell::Get()->session_controller()->fullscreen_controller_for_test(); - } - - void TearDown() override { - window_.reset(); - AshTestBase::TearDown(); - } - - void CreateFullscreenWindow() { - window_ = CreateTestWindow(); - window_->SetProperty(aura::client::kShowStateKey, - ui::SHOW_STATE_FULLSCREEN); - window_state_ = WindowState::Get(window_.get()); - } - - void ExpectFullscreenNotificationShowing(bool expect_notification) { - if (expect_notification) { - views::Widget* fullscreen_notification_widget = - fullscreen_controller_->bubble_for_test()->widget_for_test(); - EXPECT_TRUE(fullscreen_notification_widget->IsVisible()); - return; - } - EXPECT_TRUE(!fullscreen_controller_->bubble_for_test() || - !fullscreen_controller_->bubble_for_test()->widget_for_test() || - !fullscreen_controller_->bubble_for_test() - ->widget_for_test() - ->IsVisible()); - } - - protected: - std::unique_ptr<aura::Window> window_; - - WindowState* window_state_ = nullptr; - FullscreenController* fullscreen_controller_ = nullptr; - - base::test::ScopedFeatureList feature_list_; -}; - -TEST_F(SessionControllerImplLockStateChangedTest, ExitFullscreenBeforeLock) { - CreateFullscreenWindow(); - EXPECT_TRUE(window_state_->IsFullscreen()); - - base::RunLoop run_loop; - Shell::Get()->session_controller()->PrepareForLock(run_loop.QuitClosure()); - EXPECT_FALSE(window_state_->IsFullscreen()); -} - -// Test that no full screen notification is shown on session lock or unlock when -// there is no window in full screen mode. -TEST_F(SessionControllerImplLockStateChangedTest, WithoutFullscreenWindow) { - GetSessionControllerClient()->LockScreen(); - ExpectFullscreenNotificationShowing(false); - - GetSessionControllerClient()->UnlockScreen(); - ExpectFullscreenNotificationShowing(false); -} - -// Test that the full screen notification is shown on session unlock when there -// is a window in full screen mode. -TEST_F(SessionControllerImplLockStateChangedTest, WithFullscreenWindow) { - CreateFullscreenWindow(); - - GetSessionControllerClient()->LockScreen(); - ExpectFullscreenNotificationShowing(false); - - GetSessionControllerClient()->UnlockScreen(); - ExpectFullscreenNotificationShowing(true); -} - } // namespace } // namespace ash
diff --git a/ash/webui/camera_app_ui/resources/js/face.js b/ash/webui/camera_app_ui/resources/js/face.js deleted file mode 100644 index 6f79601..0000000 --- a/ash/webui/camera_app_ui/resources/js/face.js +++ /dev/null
@@ -1,133 +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. - -import {assertInstanceof, assertNotReached} from './assert.js'; -import * as dom from './dom.js'; - -// eslint-disable-next-line no-unused-vars -import {Resolution} from './type.js'; - -// G-yellow-600 with alpha = 0.8 -const RECT_COLOR = 'rgba(249, 171, 0, 0.8)'; - -/** - * Rotates the given coordinates in [0, 1] square space by the given - * orientation. - * @param {number} x - * @param {number} y - * @param {number} orientation - * @return {!Array<number>} The rotated [x, y]. - */ -function rotate(x, y, orientation) { - switch (orientation) { - case 0: - return [x, y]; - case 90: - return [y, 1.0 - x]; - case 180: - return [1.0 - x, 1.0 - y]; - case 270: - return [1.0 - y, x]; - } - assertNotReached('Unexpected orientation'); -} - -/** - * An overlay to show face rectangles over preview. - */ -export class FaceOverlay { - /** - * @param {!Resolution} activeArraySize - * @param {number} orientation Counter-clockwise angles to apply rotation to - * the face rectangles. - */ - constructor(activeArraySize, orientation) { - /** - * @const {!Resolution} - * @private - */ - this.activeArraySize_ = activeArraySize; - - /** - * @const {number} - * @private - */ - this.orientation_ = orientation; - - /** - * @const {!HTMLCanvasElement} - * @private - */ - this.canvas_ = dom.get('#preview-face-overlay', HTMLCanvasElement); - - /** - * @const {!CanvasRenderingContext2D} - * @private - */ - this.ctx_ = assertInstanceof( - this.canvas_.getContext('2d'), CanvasRenderingContext2D); - } - - /** - * Shows the given rectangles on overlay. The old rectangles would be - * cleared, if any. - * @param {!Array<number>} rects An array of [x1, y1, x2, y2] to represent - * rectangles in the coordinate system of active array in sensor. - */ - show(rects) { - this.ctx_.clearRect(0, 0, this.canvas_.width, this.canvas_.height); - - // TODO(b/178344897): Handle zoomed preview. - // TODO(b/178344897): Handle screen orientation dynamically. - - this.ctx_.strokeStyle = RECT_COLOR; - for (let i = 0; i < rects.length; i += 4) { - let [x1, y1, x2, y2] = rects.slice(i, i + 4); - x1 /= this.activeArraySize_.width; - y1 /= this.activeArraySize_.height; - x2 /= this.activeArraySize_.width; - y2 /= this.activeArraySize_.height; - [x1, y1] = rotate(x1, y1, this.orientation_); - [x2, y2] = rotate(x2, y2, this.orientation_); - const canvasAspectRatio = this.canvas_.width / this.canvas_.height; - const sensorAspectRatio = - this.activeArraySize_.width / this.activeArraySize_.height; - if (canvasAspectRatio > sensorAspectRatio) { - // Canvas has wider aspect than the sensor, e.g. when we're showing a - // 16:9 stream captured from a 4:3 sensor. Based on our hardware - // requirement, we assume the stream is cropped into letterbox from the - // active array. - const normalizedCanvasHeight = sensorAspectRatio / canvasAspectRatio; - const clipped = (1 - normalizedCanvasHeight) / 2; - x1 *= this.canvas_.width; - y1 = (Math.max(y1 - clipped, 0) / normalizedCanvasHeight) * - this.canvas_.height; - x2 *= this.canvas_.width; - y2 = (Math.max(y2 - clipped, 0) / normalizedCanvasHeight) * - this.canvas_.height; - } else if (canvasAspectRatio < sensorAspectRatio) { - // Canvas has taller aspect than the sensor, e.g. when we're showing a - // 4:3 stream captured from a 16:9 sensor. Based on our hardware - // requirement, we assume the stream is cropped into pillarbox from the - // active array. - const normalizedCanvasWidth = canvasAspectRatio / sensorAspectRatio; - const clipped = (1 - normalizedCanvasWidth) / 2; - x1 = (Math.max(x1 - clipped, 0) * normalizedCanvasWidth) * - this.canvas_.width; - y1 *= this.canvas_.height; - x2 = (Math.max(x2 - clipped, 0) * normalizedCanvasWidth) * - this.canvas_.width; - y2 *= this.canvas_.height; - } - this.ctx_.strokeRect(x1, y1, x2 - x1, y2 - y1); - } - } - - /** - * Clears all rectangles. - */ - clear() { - this.ctx_.clearRect(0, 0, this.canvas_.width, this.canvas_.height); - } -}
diff --git a/ash/webui/camera_app_ui/resources/js/face.ts b/ash/webui/camera_app_ui/resources/js/face.ts new file mode 100644 index 0000000..bda76c4 --- /dev/null +++ b/ash/webui/camera_app_ui/resources/js/face.ts
@@ -0,0 +1,111 @@ +// 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 {assertInstanceof, assertNotReached} from './assert.js'; +import * as dom from './dom.js'; +import {Resolution} from './type.js'; + +// G-yellow-600 with alpha = 0.8 +const RECT_COLOR = 'rgba(249, 171, 0, 0.8)'; + +/** + * Rotates the given coordinates in [0, 1] square space by the given + * orientation. + * @return The rotated [x, y]. + */ +function rotate(x: number, y: number, orientation: number): number[] { + switch (orientation) { + case 0: + return [x, y]; + case 90: + return [y, 1.0 - x]; + case 180: + return [1.0 - x, 1.0 - y]; + case 270: + return [1.0 - y, x]; + } + assertNotReached('Unexpected orientation'); +} + +/** + * An overlay to show face rectangles over preview. + */ +export class FaceOverlay { + private readonly canvas = dom.get('#preview-face-overlay', HTMLCanvasElement); + private readonly ctx: CanvasRenderingContext2D; + + /** + * @param orientation Counter-clockwise angles to apply rotation to + * the face rectangles. + */ + constructor( + private readonly activeArraySize: Resolution, + private readonly orientation: number) { + this.ctx = assertInstanceof( + this.canvas.getContext('2d'), CanvasRenderingContext2D); + } + + /** + * Shows the given rectangles on overlay. The old rectangles would be + * cleared, if any. + * @param rects An array of [x1, y1, x2, y2] to represent rectangles in the + * coordinate system of active array in sensor. + */ + show(rects: number[]): void { + this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); + + // TODO(b/178344897): Handle zoomed preview. + // TODO(b/178344897): Handle screen orientation dynamically. + + this.ctx.strokeStyle = RECT_COLOR; + for (let i = 0; i < rects.length; i += 4) { + let [x1, y1, x2, y2] = rects.slice(i, i + 4); + x1 /= this.activeArraySize.width; + y1 /= this.activeArraySize.height; + x2 /= this.activeArraySize.width; + y2 /= this.activeArraySize.height; + [x1, y1] = rotate(x1, y1, this.orientation); + [x2, y2] = rotate(x2, y2, this.orientation); + + const canvasAspectRatio = this.canvas.width / this.canvas.height; + const sensorAspectRatio = + this.activeArraySize.width / this.activeArraySize.height; + if (canvasAspectRatio > sensorAspectRatio) { + // Canvas has wider aspect than the sensor, e.g. when we're showing a + // 16:9 stream captured from a 4:3 sensor. Based on our hardware + // requirement, we assume the stream is cropped into letterbox from the + // active array. + const normalizedCanvasHeight = sensorAspectRatio / canvasAspectRatio; + const clipped = (1 - normalizedCanvasHeight) / 2; + x1 *= this.canvas.width; + y1 = (Math.max(y1 - clipped, 0) / normalizedCanvasHeight) * + this.canvas.height; + x2 *= this.canvas.width; + y2 = (Math.max(y2 - clipped, 0) / normalizedCanvasHeight) * + this.canvas.height; + } else if (canvasAspectRatio < sensorAspectRatio) { + // Canvas has taller aspect than the sensor, e.g. when we're showing a + // 4:3 stream captured from a 16:9 sensor. Based on our hardware + // requirement, we assume the stream is cropped into pillarbox from the + // active array. + const normalizedCanvasWidth = canvasAspectRatio / sensorAspectRatio; + const clipped = (1 - normalizedCanvasWidth) / 2; + x1 = (Math.max(x1 - clipped, 0) * normalizedCanvasWidth) * + this.canvas.width; + y1 *= this.canvas.height; + x2 = (Math.max(x2 - clipped, 0) * normalizedCanvasWidth) * + this.canvas.width; + y2 *= this.canvas.height; + } + this.ctx.strokeRect(x1, y1, x2 - x1, y2 - y1); + } + } + + /** + * Clears all rectangles. + */ + clear(): void { + this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); + } +}
diff --git a/ash/webui/camera_app_ui/resources/js/focus_ring.js b/ash/webui/camera_app_ui/resources/js/focus_ring.ts similarity index 85% rename from ash/webui/camera_app_ui/resources/js/focus_ring.js rename to ash/webui/camera_app_ui/resources/js/focus_ring.ts index cbf37bf..02fd6e847 100644 --- a/ash/webui/camera_app_ui/resources/js/focus_ring.js +++ b/ash/webui/camera_app_ui/resources/js/focus_ring.ts
@@ -12,46 +12,37 @@ /** * Focus ring element. - * @type {?HTMLElement} */ -let ring = null; +let ring: HTMLElement|null = null; -/** - * @type {?CSSStyleDeclaration} - */ -let ringCSSStyle = null; +let ringCSSStyle: CSSStyleDeclaration|null = null; /** * All valid values of '--focus-ring-style'. - * @const {!Set<string>} */ const ringStyleValues = new Set(['circle', 'mode-item-input', 'none', 'pill']); /** * The reference bounding rectangle of focused UI. - * @type {!DOMRectReadOnly} */ let uiRect = new DOMRectReadOnly(); /** * Name of event triggered for calculating bounding rectangle of focused UI. - * @const {string} */ export const FOCUS_RING_UI_RECT_EVENT_NAME = 'focusringuirect'; /** * Sets reference bounding rectangle of focused UI. - * @param {!DOMRectReadOnly} rect */ -export function setUIRect(rect) { +export function setUIRect(rect: DOMRectReadOnly): void { uiRect = rect; } /** * Shows focus ring on |el|. - * @param {!HTMLElement} el */ -function showFocus(el) { +function showFocus(el: HTMLElement) { const style = el.computedStyleMap(); const size = getStyleValueInPx(style, '--focus-ring-size'); const ringStyleValue = `${style.get('--focus-ring-style')}`; @@ -70,17 +61,11 @@ ringCSSStyle.setProperty('left', `${(uiRect.left + uiRect.right) / 2}px`); } -/** - * @public - */ -export function initialize() { +export function initialize(): void { ring = dom.get('#focus-ring', HTMLElement); ringCSSStyle = cssStyle('#focus-ring'); - /** - * @param {!HTMLElement} el - */ - const setup = (el) => { + const setup = (el: HTMLElement) => { el.addEventListener('focus', () => showFocus(el)); if (el === document.activeElement) { showFocus(el);
diff --git a/ash/webui/camera_app_ui/resources/js/js.gni b/ash/webui/camera_app_ui/resources/js/js.gni index 305ffd6..f049b5d 100644 --- a/ash/webui/camera_app_ui/resources/js/js.gni +++ b/ash/webui/camera_app_ui/resources/js/js.gni
@@ -17,9 +17,9 @@ "dom.ts", "error.ts", "expert.ts", - "face.js", + "face.ts", "flag.ts", - "focus_ring.js", + "focus_ring.ts", "gallerybutton.js", "geometry.ts", "h264.js",
diff --git a/ash/webui/shimless_rma/resources/icons.html b/ash/webui/shimless_rma/resources/icons.html index e6d1b43..afeb2bd 100644 --- a/ash/webui/shimless_rma/resources/icons.html +++ b/ash/webui/shimless_rma/resources/icons.html
@@ -7,6 +7,9 @@ <g id="info"> <path fill-rule="evenodd" clip-rule="evenodd" d="M9 14H11V10H9V14ZM10 2C5.584 2 2 5.584 2 10C2 14.416 5.584 18 10 18C14.416 18 18 14.416 18 10C18 5.584 14.416 2 10 2ZM10 16C6.6925 16 4 13.3075 4 10C4 6.6925 6.6925 4 10 4C13.3075 4 16 6.6925 16 10C16 13.3075 13.3075 16 10 16ZM9 8H11V6H9V8Z"></path> </g> + <g id="info-grey" width="20" height="20" viewBox="0 0 20 20"> + <path fill-rule="evenodd" clip-rule="evenodd" d="M9 14H11V10H9V14ZM10 2C5.584 2 2 5.584 2 10C2 14.416 5.584 18 10 18C14.416 18 18 14.416 18 10C18 5.584 14.416 2 10 2ZM10 16C6.6925 16 4 13.3075 4 10C4 6.6925 6.6925 4 10 4C13.3075 4 16 6.6925 16 10C16 13.3075 13.3075 16 10 16ZM9 8H11V6H9V8Z" fill="#202124"></path> + </g> <g id="warning"> <path d="M9 12H11V8H9V12Z" fill="#202124"></path> <path d="M11 15H9V13H11V15Z" fill="#202124"></path>
diff --git a/ash/webui/shimless_rma/resources/wrapup_repair_complete_page.html b/ash/webui/shimless_rma/resources/wrapup_repair_complete_page.html index b1c755a..53c683d 100644 --- a/ash/webui/shimless_rma/resources/wrapup_repair_complete_page.html +++ b/ash/webui/shimless_rma/resources/wrapup_repair_complete_page.html
@@ -12,6 +12,10 @@ width: 350px; } + :host([plugged-in_]) #batteryCutButton { + opacity: 0.5; + } + .button-text { flex-basis: 250px; } @@ -87,24 +91,30 @@ </div> </div> </cr-button> - <!-- TODO(gavindodd): Add UI cues that button is disabled. --> - <cr-button id="batteryCutButton" class="button-card" - on-click="onBatteryCutButtonClick_" disabled$="[[pluggedIn_]]"> - <iron-icon icon="shimless-icon:battery-cutoff" class="button-icon" - hidden="[[!checked]]"> - </iron-icon> - <div class="button-text"> - <div class="button-label"> - <span>[[i18n('repairCompletedShutoffButtonText')]]</span> + <div id="batteryCutoffTooltipWrapper"> + <cr-button id="batteryCutButton" class="button-card" + on-click="onBatteryCutButtonClick_" disabled$="[[pluggedIn_]]"> + <iron-icon id="battery-cutoff-icon" icon="shimless-icon:battery-cutoff" class="button-icon" + hidden="[[!checked]]"> + </iron-icon> + <div class="button-text"> + <div class="button-label"> + <span>[[i18n('repairCompletedShutoffButtonText')]]</span> + <iron-icon id="battery-cutoff-info-icon" icon="shimless-icon:info-grey" hidden="[[!pluggedIn_]]"> + </iron-icon> + </div> + <div class="button-description"> + [[i18n('repairCompletedShutoffDescriptionText')]] + </div> + <div class="button-description" hidden="[[!pluggedIn_]]"> + [[i18n('repairCompletedShutoffInstructionsText')]] + </div> </div> - <div class="button-description"> - [[i18n('repairCompletedShutoffDescriptionText')]] - </div> - <div class="button-description" hidden="[[!pluggedIn_]]"> - [[i18n('repairCompletedShutoffInstructionsText')]] - </div> - </div> - </cr-button> + </cr-button> + </div> + <paper-tooltip for="batteryCutoffTooltipWrapper" hidden="[[!pluggedIn_]]"> + [[i18n('batteryShutoffTooltipText')]] + </paper-tooltip> </div> </base-page> @@ -124,25 +134,3 @@ </cr-button> </div> </cr-dialog> - -<!-- TODO(gavindodd): Confirm we need this. The cutoff button is guarded by - a check for power cable state so it could immediately shut down. --> -<cr-dialog id="batteryCutDialog" close-text="close"> - <div slot="title"> - [[i18n('batteryShutoffTitleText')]] - </div> - <div slot="body"> - <div> - [[batteryCutInstructions_(pluggedIn_)]] - </div> - </div> - <div slot="footer"> - <cr-button id="closeBatteryDialogButton" on-click="onCancelClick_"> - [[i18n('batteryShutoffCancelButtonText')]] - </cr-button> - <cr-button id="shutdownButton" on-click="onShutdownClick_" - disabled$="[[pluggedIn_]]"> - [[i18n('batteryShutoffShutdownButtonText')]] - </cr-button> - </div> -</cr-dialog>
diff --git a/ash/webui/shimless_rma/resources/wrapup_repair_complete_page.js b/ash/webui/shimless_rma/resources/wrapup_repair_complete_page.js index 74baa6b..aa1dc9a 100644 --- a/ash/webui/shimless_rma/resources/wrapup_repair_complete_page.js +++ b/ash/webui/shimless_rma/resources/wrapup_repair_complete_page.js
@@ -4,6 +4,7 @@ import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js'; import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; +import 'chrome://resources/polymer/v3_0/paper-tooltip/paper-tooltip.js'; import './base_page.js'; import './shimless_rma_shared_css.js'; @@ -50,6 +51,7 @@ * Assume plugged in is true until first observation. */ pluggedIn_: { + reflectToAttribute: true, type: Boolean, value: true, } @@ -115,19 +117,7 @@ } /** @protected */ - onBatteryCutButtonClick_() { - const dialog = /** @type {!CrDialogElement} */ ( - this.shadowRoot.querySelector('#batteryCutDialog')); - if (!dialog.open) { - dialog.showModal(); - } - } - - /** @protected */ - batteryCutInstructions_() { - return this.pluggedIn_ ? this.i18n('batteryShutoffUnplugMessageText') : - this.i18n('batteryShutoffShutdownMessageText'); - } + onBatteryCutButtonClick_() {} /** @protected */ onCancelClick_() {
diff --git a/ash/webui/shimless_rma/shimless_rma.cc b/ash/webui/shimless_rma/shimless_rma.cc index 7a19f41..0d47855 100644 --- a/ash/webui/shimless_rma/shimless_rma.cc +++ b/ash/webui/shimless_rma/shimless_rma.cc
@@ -213,15 +213,8 @@ {"rmaLogsTitleText", IDS_SHIMLESS_RMA_LOGS_TITLE}, {"rmaLogsCancelButtonText", IDS_SHIMLESS_RMA_LOGS_CANCEL_BUTTON}, {"rmaLogsSaveToUsbButtonText", IDS_SHIMLESS_RMA_LOGS_SAVE_BUTTON}, - {"batteryShutoffTitleText", IDS_SHIMLESS_BATTERY_CUTOFF_TITLE}, - {"batteryShutoffUnplugMessageText", - IDS_SHIMLESS_BATTERY_SHUTOFF_UNPLUG_MESSAGE}, - {"batteryShutoffShutdownMessageText", - IDS_SHIMLESS_BATTERY_SHUTOFF_SHUTDOWN_MESSAGE}, - {"batteryShutoffCancelButtonText", - IDS_SHIMLESS_BATTERY_SHUTOFF_CANCEL_BUTTON}, - {"batteryShutoffShutdownButtonText", - IDS_SHIMLESS_BATTERY_SHUTOFF_SHUTDOWN_BUTTON}, + {"batteryShutoffTooltipText", IDS_SHIMLESS_BATTERY_SHUTOFF_TOOLTIP_TEXT}, + // Manual disable wp page {"manuallyDisableWpTitleText", IDS_SHIMLESS_RMA_MANUALLY_DISABLE_WP_TITLE},
diff --git a/base/trace_event/trace_log.cc b/base/trace_event/trace_log.cc index 5724372..8bc58b1 100644 --- a/base/trace_event/trace_log.cc +++ b/base/trace_event/trace_log.cc
@@ -1654,7 +1654,7 @@ void TraceLog::UseNextTraceBuffer() { logged_events_.reset(CreateTraceBuffer()); - subtle::NoBarrier_AtomicIncrement(&generation_, 1); + generation_.fetch_add(1, std::memory_order_relaxed); thread_shared_chunk_.reset(); thread_shared_chunk_index_ = 0; }
diff --git a/base/trace_event/trace_log.h b/base/trace_event/trace_log.h index 0f53e26..f232e0f 100644 --- a/base/trace_event/trace_log.h +++ b/base/trace_event/trace_log.h
@@ -552,7 +552,7 @@ void OnFlushTimeout(int generation, bool discard_events); int generation() const { - return static_cast<int>(subtle::NoBarrier_Load(&generation_)); + return generation_.load(std::memory_order_relaxed); } bool CheckGeneration(int generation) const { return generation == this->generation(); @@ -646,7 +646,7 @@ ArgumentFilterPredicate argument_filter_predicate_; MetadataFilterPredicate metadata_filter_predicate_; bool record_host_app_package_name_{false}; - subtle::AtomicWord generation_; + std::atomic<int> generation_; bool use_worker_thread_; std::atomic<AddTraceEventOverrideFunction> add_trace_event_override_{nullptr}; std::atomic<OnFlushFunction> on_flush_override_{nullptr};
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index 1220bba0..7fa20e5 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -7.20211221.3.1 +7.20211222.1.1
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index 1220bba0..7fa20e5 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -7.20211221.3.1 +7.20211222.1.1
diff --git a/chrome/VERSION b/chrome/VERSION index 0daadaa1..88bf9e5 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=99 MINOR=0 -BUILD=4781 +BUILD=4782 PATCH=0
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni index 1c03058..073059a1 100644 --- a/chrome/android/chrome_java_sources.gni +++ b/chrome/android/chrome_java_sources.gni
@@ -834,8 +834,6 @@ "java/src/org/chromium/chrome/browser/ntp/SnapScrollHelperImpl.java", "java/src/org/chromium/chrome/browser/ntp/TitleUtil.java", "java/src/org/chromium/chrome/browser/ntp/cards/SignInPromo.java", - "java/src/org/chromium/chrome/browser/ntp/cards/promo/enhanced_protection/EnhancedProtectionPromoController.java", - "java/src/org/chromium/chrome/browser/ntp/cards/promo/enhanced_protection/EnhancedProtectionPromoUtils.java", "java/src/org/chromium/chrome/browser/ntp/search/SearchBoxContainerView.java", "java/src/org/chromium/chrome/browser/ntp/search/SearchBoxCoordinator.java", "java/src/org/chromium/chrome/browser/ntp/search/SearchBoxMediator.java",
diff --git a/chrome/android/chrome_test_java_sources.gni b/chrome/android/chrome_test_java_sources.gni index e7c446f3..760eb2a 100644 --- a/chrome/android/chrome_test_java_sources.gni +++ b/chrome/android/chrome_test_java_sources.gni
@@ -311,7 +311,6 @@ "javatests/src/org/chromium/chrome/browser/ntp/RecentTabsPageTest.java", "javatests/src/org/chromium/chrome/browser/ntp/RevampedIncognitoDescriptionViewRenderTest.java", "javatests/src/org/chromium/chrome/browser/ntp/TitleUtilTest.java", - "javatests/src/org/chromium/chrome/browser/ntp/cards/promo/enhanced_protection/EnhancedProtectionPromoTest.java", "javatests/src/org/chromium/chrome/browser/offlinepages/MHTMLPageTest.java", "javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageArchivePublisherBridgeTest.java", "javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageAutoFetchTest.java",
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java index 1c95533..f3989f0 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java
@@ -44,7 +44,6 @@ import org.chromium.chrome.browser.feedback.HelpAndFeedbackLauncher; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.ntp.NewTabPageLaunchOrigin; -import org.chromium.chrome.browser.ntp.cards.promo.enhanced_protection.EnhancedProtectionPromoController; import org.chromium.chrome.browser.privacy.settings.PrivacyPreferencesManagerImpl; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.settings.SettingsLauncherImpl; @@ -112,11 +111,6 @@ private boolean mIsActive; private int mHeaderCount; - // Enhanced Protection promo view will be not-null once we have it created, until it is - // destroyed. - private @Nullable View mEnhancedProtectionPromoView; - private @Nullable EnhancedProtectionPromoController mEnhancedProtectionPromoController; - // Used when Feed is enabled. private @Nullable Profile mProfile; private @Nullable FeedSurfaceLifecycleManager mFeedSurfaceLifecycleManager; @@ -311,11 +305,6 @@ mHandler = new Handler(Looper.getMainLooper()); - if (isEnhancedProtectionPromoEnabled()) { - mEnhancedProtectionPromoController = - new EnhancedProtectionPromoController(mActivity, mProfile); - } - // MVC setup for feed header. if (ChromeFeatureList.isEnabled(ChromeFeatureList.WEB_FEED)) { mSectionHeaderView = (SectionHeaderView) LayoutInflater.from(mActivity).inflate( @@ -372,9 +361,6 @@ stopBubbleTriggering(); if (mFeedSurfaceLifecycleManager != null) mFeedSurfaceLifecycleManager.destroy(); mFeedSurfaceLifecycleManager = null; - if (mEnhancedProtectionPromoController != null) { - mEnhancedProtectionPromoController.destroy(); - } stopScrollTracking(); if (mSectionHeaderModelChangeProcessor != null) { mSectionHeaderModelChangeProcessor.destroy(); @@ -655,9 +641,6 @@ if (mNtpHeader != null) UiUtils.removeViewFromParent(mNtpHeader); UiUtils.removeViewFromParent(mSectionHeaderView); if (mSigninPromoView != null) UiUtils.removeViewFromParent(mSigninPromoView); - if (mEnhancedProtectionPromoView != null) { - UiUtils.removeViewFromParent(mEnhancedProtectionPromoView); - } // Directly add header views to content manager. List<View> headerList = new ArrayList<>(); @@ -741,12 +724,6 @@ mFeedSurfaceLifecycleManager = null; mStream = null; mSigninPromoView = null; - - mEnhancedProtectionPromoView = null; - if (mEnhancedProtectionPromoController != null) { - mEnhancedProtectionPromoController.destroy(); - mEnhancedProtectionPromoController = null; - } } mScrollViewForPolicy = new PolicyScrollView(mActivity); @@ -793,8 +770,7 @@ /** * Update header views in the Feed. */ - void updateHeaderViews( - boolean isSignInPromoVisible, @Nullable View enhancedProtectionPromoView) { + void updateHeaderViews(boolean isSignInPromoVisible) { if (mStream == null) return; List<View> headers = new ArrayList<>(); @@ -803,11 +779,6 @@ headers.add(mNtpHeader); } - if (enhancedProtectionPromoView != null) { - mEnhancedProtectionPromoView = enhancedProtectionPromoView; - headers.add(enhancedProtectionPromoView); - } - headers.add(mSectionHeaderView); if (isSignInPromoVisible) { @@ -816,14 +787,6 @@ setHeaders(headers); } - EnhancedProtectionPromoController getEnhancedProtectionPromoController() { - return mEnhancedProtectionPromoController; - } - - private boolean isEnhancedProtectionPromoEnabled() { - return ChromeFeatureList.isEnabled(ChromeFeatureList.ENHANCED_PROTECTION_PROMO_CARD); - } - @VisibleForTesting public FeedSurfaceMediator getMediatorForTesting() { return mMediator;
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 ba9546d..48e3eaac 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
@@ -37,7 +37,6 @@ import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.ntp.NewTabPageLaunchOrigin; import org.chromium.chrome.browser.ntp.cards.SignInPromo; -import org.chromium.chrome.browser.ntp.cards.promo.enhanced_protection.EnhancedProtectionPromoController.EnhancedProtectionPromoStateListener; import org.chromium.chrome.browser.preferences.Pref; import org.chromium.chrome.browser.preferences.PrefChangeRegistrar; import org.chromium.chrome.browser.profiles.Profile; @@ -77,8 +76,7 @@ @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE) public class FeedSurfaceMediator implements FeedSurfaceScrollDelegate, TouchEnabledDelegate, TemplateUrlServiceObserver, - ListMenu.Delegate, EnhancedProtectionPromoStateListener, - IdentityManager.Observer { + ListMenu.Delegate, IdentityManager.Observer { private static final String TAG = "FeedSurfaceMediator"; private static final int INTEREST_FEED_HEADER_POSITION = 0; @@ -144,7 +142,7 @@ if (isVisible() == visible) return; super.setVisibilityInternal(visible); - mCoordinator.updateHeaderViews(visible, null); + mCoordinator.updateHeaderViews(visible); maybeUpdateSignInPromo(); } @@ -169,7 +167,7 @@ @Override public void onDismissPromo() { super.onDismissPromo(); - mCoordinator.updateHeaderViews(false, null); + mCoordinator.updateHeaderViews(false); } } @@ -197,7 +195,6 @@ private @Nullable SignInPromo mSignInPromo; private RecyclerViewAnimationFinishDetector mRecyclerViewAnimationFinishDetector = new RecyclerViewAnimationFinishDetector(); - private @Nullable View mEnhancedProtectionPromo; private boolean mFeedEnabled; private boolean mTouchEnabled = true; @@ -601,12 +598,7 @@ private void initStreamHeaderViews() { boolean signInPromoVisible = createSignInPromoIfNeeded(); - mEnhancedProtectionPromo = null; - if (!signInPromoVisible) { - mEnhancedProtectionPromo = createEnhancedProtectionPromoIfNeeded(); - } - // We are not going to show two promos at the same time. - mCoordinator.updateHeaderViews(signInPromoVisible, mEnhancedProtectionPromo); + mCoordinator.updateHeaderViews(signInPromoVisible); } /** @@ -627,19 +619,6 @@ return mSignInPromo.isVisible(); } - private View createEnhancedProtectionPromoIfNeeded() { - if (mCoordinator.getEnhancedProtectionPromoController() == null) return null; - - View enhancedProtectionPromoView = - mCoordinator.getEnhancedProtectionPromoController().getPromoView(); - if (enhancedProtectionPromoView != null) { - mCoordinator.getEnhancedProtectionPromoController() - .setEnhancedProtectionPromoStateListener(this); - updatePromoCardPadding(enhancedProtectionPromoView); - } - return enhancedProtectionPromoView; - } - private void updatePromoCardPadding(View promoCard) { MarginLayoutParams layoutParams = promoCard.getLayoutParams() == null ? new MarginLayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT) @@ -765,9 +744,6 @@ if (mSignInPromo != null) { mSignInPromo.setCanShowPersonalizedSuggestions(suggestionsVisible); } - if (mEnhancedProtectionPromo != null) { - updatePromoCardPadding(mEnhancedProtectionPromo); - } if (suggestionsVisible) mCoordinator.getSurfaceLifecycleManager().show(); mStreamContentChanged = true; @@ -1065,12 +1041,6 @@ } } - @Override - public void onEnhancedProtectionPromoStateChange() { - // If the enhanced protection promo has been dismissed, delete it. - mCoordinator.updateHeaderViews(false, null); - } - // IdentityManager.Observer interface. @Override
diff --git a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/FeedV2NewTabPageTest.java b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/FeedV2NewTabPageTest.java index 8abc3a4..b791bf9 100644 --- a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/FeedV2NewTabPageTest.java +++ b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/FeedV2NewTabPageTest.java
@@ -111,8 +111,6 @@ @CommandLineFlags. Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, "disable-features=IPH_FeedHeaderMenu"}) @Features.EnableFeatures(ChromeFeatureList.INTEREST_FEED_V2) -@Features. -DisableFeatures({ChromeFeatureList.QUERY_TILES, ChromeFeatureList.ENHANCED_PROTECTION_PROMO_CARD}) public class FeedV2NewTabPageTest { private static final int ARTICLE_SECTION_HEADER_POSITION = 1; private static final int SIGNIN_PROMO_POSITION = 2;
diff --git a/chrome/android/java/res/values/ids.xml b/chrome/android/java/res/values/ids.xml index 48fafb5..65fe425f0e 100644 --- a/chrome/android/java/res/values/ids.xml +++ b/chrome/android/java/res/values/ids.xml
@@ -108,9 +108,6 @@ <item type="id" name="ntp_feed_header_menu_item_learn" /> <item type="id" name="ntp_feed_header_menu_item_toggle_switch" /> - <!-- Enhanced Protection Promo --> - <item type="id" name="enhanced_protection_promo" /> - <!-- Custom Tabs --> <item type="id" name="view_id_tag_key" /> </resources>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/promo/enhanced_protection/DIR_METADATA b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/promo/enhanced_protection/DIR_METADATA deleted file mode 100644 index d4a02b62..0000000 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/promo/enhanced_protection/DIR_METADATA +++ /dev/null
@@ -1,4 +0,0 @@ -monorail { - component: "Services>Safebrowsing" -} -team_email: "safebrowsing@chromium.org"
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/promo/enhanced_protection/EnhancedProtectionPromoController.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/promo/enhanced_protection/EnhancedProtectionPromoController.java deleted file mode 100644 index 7667d48..0000000 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/promo/enhanced_protection/EnhancedProtectionPromoController.java +++ /dev/null
@@ -1,186 +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.ntp.cards.promo.enhanced_protection; - -import android.content.Context; -import android.content.res.ColorStateList; -import android.content.res.Resources; -import android.graphics.drawable.Drawable; -import android.view.View; - -import androidx.annotation.Nullable; -import androidx.appcompat.content.res.AppCompatResources; - -import org.chromium.chrome.R; -import org.chromium.chrome.browser.ntp.cards.promo.enhanced_protection.EnhancedProtectionPromoUtils.EnhancedProtectionPromoAction; -import org.chromium.chrome.browser.profiles.Profile; -import org.chromium.chrome.browser.safe_browsing.metrics.SettingsAccessPoint; -import org.chromium.chrome.browser.safe_browsing.settings.SafeBrowsingSettingsFragment; -import org.chromium.chrome.browser.settings.SettingsLauncherImpl; -import org.chromium.components.browser_ui.settings.SettingsLauncher; -import org.chromium.components.browser_ui.widget.promo.PromoCardCoordinator; -import org.chromium.components.browser_ui.widget.promo.PromoCardProperties; -import org.chromium.ui.modelutil.PropertyModel; - -/** - * Controller for the Enhanced Protection promo component. - * The logic for creating and managing the promo is relatively simple, so this class merges the duty - * of mediator and coordinator. - */ -public class EnhancedProtectionPromoController { - /** - * Interface that represents the holder of a Enhanced Protection Promo. When the promo has state - * changes due to enhanced protection changes / being dismissed, {@link - * #onEnhancedProtectionPromoDataChange()} will be called. - */ - public interface EnhancedProtectionPromoStateListener { - /** - * Called when promo has state changes due to enhanced protection pref changes / being - * dismissed. - */ - void onEnhancedProtectionPromoStateChange(); - } - - private final Context mContext; - private final @Nullable Profile mProfile; - - // Created only when creation criteria is met. - private EnhancedProtectionPromoStateListener mStateListener; - private PromoCardCoordinator mPromoCoordinator; - private PropertyModel mModel; - private boolean mIsPromoShowing; - - /** - * Build the EnhancedProtectionPromoController that handles the set up / tear down for the - * enhanced protection promo. - * @param context Context from the activity. - * @param profile Current user profile. - */ - public EnhancedProtectionPromoController(Context context, @Nullable Profile profile) { - mContext = context; - mProfile = profile; - } - - /** - * @param listener Listener to be notified when the promo should be removed from the parent - * view. - */ - public void setEnhancedProtectionPromoStateListener( - EnhancedProtectionPromoStateListener listener) { - mStateListener = listener; - } - - /** - * Retrieve the view representing EnhancedProtectionPromo. - * - * Internally, this function will check the creation criteria from SharedPreference. If the - * creation criteria is not met, this function will return null; otherwise, promo controller - * will create the view lazily if not yet created, and return. - * - * Note that the same View will be returned until the promo is dismissed by internal or external - * signal. - * - * @return View represent EnhancedProtectionPromo if creation criteria is meet; null If the - * criteria is not meet. - */ - public @Nullable View getPromoView() { - if (mIsPromoShowing || EnhancedProtectionPromoUtils.shouldCreatePromo(mProfile)) { - mIsPromoShowing = true; - return getPromoCoordinator().getView(); - } else { - return null; - } - } - - /** - * Destroy the EnhancedProtectionPromo and release its dependencies. - */ - public void destroy() { - mStateListener = null; - - // Early return if promo coordinator is not initialized. - if (mPromoCoordinator == null) return; - - mPromoCoordinator.destroy(); - - // Update the listener if the promo is shown and not yet dismissed. - if (mIsPromoShowing) dismissPromoInternal(); - } - - /** - * @return The PromoCardCoordinator for enhanced protection promo. If the coordinator is not - * created, create it lazily. - */ - private PromoCardCoordinator getPromoCoordinator() { - if (mPromoCoordinator != null) return mPromoCoordinator; - - mModel = buildModel(); - - mPromoCoordinator = new PromoCardCoordinator(mContext, mModel, - EnhancedProtectionPromoUtils.ENHANCED_PROTECTION_PROMO_CARD_FEATURE); - - mPromoCoordinator.getView().setId(R.id.enhanced_protection_promo); - - EnhancedProtectionPromoUtils.recordEnhancedProtectionPromoEvent( - EnhancedProtectionPromoAction.CREATED); - - return mPromoCoordinator; - } - - private PropertyModel buildModel() { - Resources r = mContext.getResources(); - Drawable securityIcon = - AppCompatResources.getDrawable(mContext, R.drawable.ic_security_grey); - ColorStateList tint = AppCompatResources.getColorStateList( - mContext, R.color.default_icon_color_accent1_tint_list); - - PropertyModel.Builder builder = new PropertyModel.Builder(PromoCardProperties.ALL_KEYS); - builder.with(PromoCardProperties.PRIMARY_BUTTON_CALLBACK, (v) -> onPrimaryButtonClicked()) - .with(PromoCardProperties.IMPRESSION_SEEN_CALLBACK, this::onPromoSeen) - .with(PromoCardProperties.IS_IMPRESSION_ON_PRIMARY_BUTTON, true) - .with(PromoCardProperties.IMAGE, securityIcon) - .with(PromoCardProperties.ICON_TINT, tint) - .with(PromoCardProperties.TITLE, - r.getString(R.string.enhanced_protection_promo_title)) - .with(PromoCardProperties.DESCRIPTION, - r.getString(R.string.enhanced_protection_promo_description)) - .with(PromoCardProperties.PRIMARY_BUTTON_TEXT, - r.getString(R.string.continue_button)) - .with(PromoCardProperties.HAS_SECONDARY_BUTTON, true) - .with(PromoCardProperties.SECONDARY_BUTTON_TEXT, r.getString(R.string.no_thanks)) - .with(PromoCardProperties.SECONDARY_BUTTON_CALLBACK, (v) -> dismissPromo()) - .build(); - return builder.build(); - } - - /** - * Dismissed the promo and record the user action. - */ - private void dismissPromo() { - EnhancedProtectionPromoUtils.setPromoDismissedInSharedPreference(true); - EnhancedProtectionPromoUtils.recordEnhancedProtectionPromoEvent( - EnhancedProtectionPromoAction.DISMISSED); - dismissPromoInternal(); - } - - private void dismissPromoInternal() { - mIsPromoShowing = false; - if (mStateListener != null) mStateListener.onEnhancedProtectionPromoStateChange(); - } - - private void onPrimaryButtonClicked() { - EnhancedProtectionPromoUtils.recordEnhancedProtectionPromoEvent( - EnhancedProtectionPromoAction.ACCEPTED); - SettingsLauncher launcher = new SettingsLauncherImpl(); - launcher.launchSettingsActivity(mContext, SafeBrowsingSettingsFragment.class, - SafeBrowsingSettingsFragment.createArguments( - SettingsAccessPoint.SURFACE_EXPLORER_PROMO_SLINGER)); - } - - private void onPromoSeen() { - EnhancedProtectionPromoUtils.recordEnhancedProtectionPromoEvent( - EnhancedProtectionPromoAction.SEEN); - } -}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/promo/enhanced_protection/EnhancedProtectionPromoUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/promo/enhanced_protection/EnhancedProtectionPromoUtils.java deleted file mode 100644 index 347b0ab1..0000000 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/promo/enhanced_protection/EnhancedProtectionPromoUtils.java +++ /dev/null
@@ -1,114 +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.ntp.cards.promo.enhanced_protection; - -import androidx.annotation.IntDef; -import androidx.annotation.Nullable; - -import org.chromium.base.metrics.RecordHistogram; -import org.chromium.base.metrics.RecordUserAction; -import org.chromium.chrome.browser.flags.ChromeFeatureList; -import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; -import org.chromium.chrome.browser.preferences.Pref; -import org.chromium.chrome.browser.preferences.SharedPreferencesManager; -import org.chromium.chrome.browser.profiles.Profile; -import org.chromium.chrome.browser.safe_browsing.SafeBrowsingBridge; -import org.chromium.components.user_prefs.UserPrefs; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * Enhanced Protection promo related utils class. - */ -final class EnhancedProtectionPromoUtils { - /** - * Possible user actions associated with homepage promo. Used for Histogram - * "NewTabPage.Promo.EnhancedProtectionPromo" recorded in {@link - * #recordEnhancedProtectionPromoEvent(int)}. - * - * These values are corresponded with enum "AndroidEnhancedProtectionPromoAction" and persisted - * to logs, therefore should be treated as append only. - */ - @IntDef({EnhancedProtectionPromoAction.CREATED, EnhancedProtectionPromoAction.SEEN, - EnhancedProtectionPromoAction.DISMISSED, EnhancedProtectionPromoAction.ACCEPTED}) - @Retention(RetentionPolicy.SOURCE) - public @interface EnhancedProtectionPromoAction { - int CREATED = 0; - int SEEN = 1; - int DISMISSED = 2; - int ACCEPTED = 3; - int TOTAL = 4; - } - - // Suffix for PROMO_IS_DISMISSED and PROMO_TIMES_SEEN Chrome preference keys. - public static final String ENHANCED_PROTECTION_PROMO_CARD_FEATURE = - "EnhancedProtectionPromoCard"; - private static final int DEFAULT_MAX_IMPRESSION_SEEN = 22; - - // Do not instantiate. - private EnhancedProtectionPromoUtils() {} - - /** - * @return True if EnhancedProtectionPromo has not yet been dismissed and if the user has not - * selected Enhanced Protection and if the user has not seen the promos too many times - * and if Safe Browsing is not managed. - */ - static boolean shouldCreatePromo(@Nullable Profile profile) { - String timesSeenKey = getTimesSeenKey(); - int timesSeen = SharedPreferencesManager.getInstance().readInt(timesSeenKey, 0); - int maxImpressions = ChromeFeatureList.getFieldTrialParamByFeatureAsInt( - ChromeFeatureList.ENHANCED_PROTECTION_PROMO_CARD, - "MaxEnhancedProtectionPromoImpressions", DEFAULT_MAX_IMPRESSION_SEEN); - // TODO(bdea): If the user has pressed "Continue" and not selected Enhanced Protection, - // should we still show the promo. - return (profile != null) && !UserPrefs.get(profile).getBoolean(Pref.SAFE_BROWSING_ENHANCED) - && !isPromoDismissedInSharedPreference() && (timesSeen <= maxImpressions) - && !SafeBrowsingBridge.isSafeBrowsingManaged(); - } - - static boolean isPromoDismissedInSharedPreference() { - return SharedPreferencesManager.getInstance().readBoolean(getDismissedKey(), false); - } - - static void setPromoDismissedInSharedPreference(boolean isDismissed) { - SharedPreferencesManager.getInstance().writeBoolean(getDismissedKey(), isDismissed); - } - - static String getDismissedKey() { - return ChromePreferenceKeys.PROMO_IS_DISMISSED.createKey( - ENHANCED_PROTECTION_PROMO_CARD_FEATURE); - } - - static String getTimesSeenKey() { - return ChromePreferenceKeys.PROMO_TIMES_SEEN.createKey( - ENHANCED_PROTECTION_PROMO_CARD_FEATURE); - } - - static void recordEnhancedProtectionPromoEvent(@EnhancedProtectionPromoAction int action) { - RecordHistogram.recordEnumeratedHistogram("NewTabPage.Promo.EnhancedProtectionPromo", - action, EnhancedProtectionPromoAction.TOTAL); - - if (action == EnhancedProtectionPromoAction.CREATED) return; - int maxImpressions = ChromeFeatureList.getFieldTrialParamByFeatureAsInt( - ChromeFeatureList.ENHANCED_PROTECTION_PROMO_CARD, - "MaxEnhancedProtectionPromoImpressions", DEFAULT_MAX_IMPRESSION_SEEN); - String timesSeenKey = getTimesSeenKey(); - int timesSeen = SharedPreferencesManager.getInstance().readInt(timesSeenKey, 0); - if (action == EnhancedProtectionPromoAction.SEEN) { - SharedPreferencesManager.getInstance().writeInt(timesSeenKey, timesSeen + 1); - } else if (action == EnhancedProtectionPromoAction.ACCEPTED) { - RecordUserAction.record("NewTabPage.Promo.EnhancedProtectionPromo.Accepted"); - RecordHistogram.recordLinearCountHistogram( - "NewTabPage.Promo.EnhancedProtectionPromo.ImpressionUntilAction", timesSeen, 1, - maxImpressions, maxImpressions + 1); - } else if (action == EnhancedProtectionPromoAction.DISMISSED) { - RecordUserAction.record("NewTabPage.Promo.EnhancedProtectionPromo.Dismissed"); - RecordHistogram.recordLinearCountHistogram( - "NewTabPage.Promo.EnhancedProtectionPromo.ImpressionUntilDismissal", timesSeen, - 1, maxImpressions, maxImpressions + 1); - } - } -}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/promo/enhanced_protection/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/promo/enhanced_protection/OWNERS deleted file mode 100644 index eac9d323..0000000 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/promo/enhanced_protection/OWNERS +++ /dev/null
@@ -1,2 +0,0 @@ -bdea@chromium.org -xinghuilu@chromium.org
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/PowerBookmarkTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/PowerBookmarkTest.java index 7f4953d..4be9638e 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/PowerBookmarkTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/PowerBookmarkTest.java
@@ -31,6 +31,7 @@ import org.chromium.base.test.params.ParameterAnnotations; import org.chromium.base.test.params.ParameterSet; import org.chromium.base.test.params.ParameterizedRunner; +import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; import org.chromium.chrome.R; import org.chromium.chrome.browser.flags.ChromeFeatureList; @@ -180,6 +181,7 @@ @Test @MediumTest @Feature({"RenderTest"}) + @DisabledTest(message = "crbug.com/1282173") public void testShoppingRebindUI() throws IOException { TestThreadUtils.runOnUiThreadBlocking(() -> { mPowerBookmarkShoppingItemRow.initPriceTrackingUI("http://foo.com/img", false,
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/fullscreen/FullscreenManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/fullscreen/FullscreenManagerTest.java index 00acf05b..aa6d6052 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/fullscreen/FullscreenManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/fullscreen/FullscreenManagerTest.java
@@ -184,6 +184,7 @@ @Test @MediumTest @Feature({"Fullscreen"}) + @DisabledTest(message = "crbug.com/1282137") public void testDelayedPersistentFullscreen() { mActivityTestRule.startMainActivityWithURL(LONG_HTML_TEST_PAGE); @@ -215,6 +216,7 @@ @Test @LargeTest @Feature({"Fullscreen"}) + @DisabledTest(message = "crbug.com/1282137") public void testPersistentFullscreenChangingUiFlags() throws InterruptedException { // Exiting fullscreen via UI Flags is not supported in versions prior to MR2. if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) return; @@ -540,6 +542,7 @@ @Test @LargeTest @Feature({"Fullscreen"}) + @DisabledTest(message = "crbug.com/1282137") public void testEnterPendingPersistentFullscreen() { FullscreenManagerTestUtils.disableBrowserOverrides(); mActivityTestRule.startMainActivityWithURL(LONG_FULLSCREEN_API_HTML_TEST_PAGE);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageColorWithFeedV2Test.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageColorWithFeedV2Test.java index 6d506fe6..44c4eaf 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageColorWithFeedV2Test.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageColorWithFeedV2Test.java
@@ -86,8 +86,6 @@ @MediumTest @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE) @Feature({"NewTabPage", "FeedNewTabPage"}) - @Features.DisableFeatures({ - ChromeFeatureList.ENHANCED_PROTECTION_PROMO_CARD}) public void testTextBoxBackgroundColor() throws Exception { // clang-format on RecyclerView recycleView = (RecyclerView) mNtp.getCoordinatorForTesting().getRecyclerView();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/cards/promo/enhanced_protection/EnhancedProtectionPromoTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/cards/promo/enhanced_protection/EnhancedProtectionPromoTest.java deleted file mode 100644 index 29539586..0000000 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/cards/promo/enhanced_protection/EnhancedProtectionPromoTest.java +++ /dev/null
@@ -1,228 +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.ntp.cards.promo.enhanced_protection; - -import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.action.ViewActions.click; -import static androidx.test.espresso.intent.Intents.intended; -import static androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent; -import static androidx.test.espresso.intent.matcher.IntentMatchers.hasExtra; -import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; -import static androidx.test.espresso.matcher.ViewMatchers.withId; - -import static org.hamcrest.Matchers.allOf; - -import static org.chromium.ui.test.util.ViewUtils.waitForView; - -import android.content.Intent; -import android.os.Build; -import android.view.View; -import android.view.ViewGroup; - -import androidx.test.espresso.contrib.RecyclerViewActions; -import androidx.test.espresso.intent.Intents; -import androidx.test.filters.MediumTest; -import androidx.test.filters.SmallTest; - -import org.hamcrest.Matcher; -import org.hamcrest.Matchers; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.MockitoAnnotations; - -import org.chromium.base.metrics.RecordHistogram; -import org.chromium.base.test.util.CommandLineFlags; -import org.chromium.base.test.util.Criteria; -import org.chromium.base.test.util.CriteriaHelper; -import org.chromium.base.test.util.DisableIf; -import org.chromium.base.test.util.UserActionTester; -import org.chromium.chrome.R; -import org.chromium.chrome.browser.flags.ChromeFeatureList; -import org.chromium.chrome.browser.flags.ChromeSwitches; -import org.chromium.chrome.browser.ntp.cards.SignInPromo; -import org.chromium.chrome.browser.ntp.cards.promo.enhanced_protection.EnhancedProtectionPromoUtils.EnhancedProtectionPromoAction; -import org.chromium.chrome.browser.preferences.Pref; -import org.chromium.chrome.browser.preferences.SharedPreferencesManager; -import org.chromium.chrome.browser.profiles.Profile; -import org.chromium.chrome.browser.safe_browsing.settings.SafeBrowsingSettingsFragment; -import org.chromium.chrome.browser.settings.SettingsActivity; -import org.chromium.chrome.browser.tab.Tab; -import org.chromium.chrome.test.ChromeJUnit4ClassRunner; -import org.chromium.chrome.test.ChromeTabbedActivityTestRule; -import org.chromium.chrome.test.util.NewTabPageTestUtils; -import org.chromium.chrome.test.util.browser.Features; -import org.chromium.chrome.test.util.browser.Features.EnableFeatures; -import org.chromium.components.embedder_support.util.UrlConstants; -import org.chromium.components.user_prefs.UserPrefs; -import org.chromium.content_public.browser.test.util.TestThreadUtils; - -/** - * Unit test for {@link EnhancedProtectionPromoController} - */ -@RunWith(ChromeJUnit4ClassRunner.class) -@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) -@EnableFeatures({ChromeFeatureList.ENHANCED_PROTECTION_PROMO_CARD}) -@Features.DisableFeatures({ChromeFeatureList.QUERY_TILES}) -public class EnhancedProtectionPromoTest { - private static final String METRICS_ENHANCED_PROTECTION_PROMO = - "NewTabPage.Promo.EnhancedProtectionPromo"; - private static final String METRICS_ENHANCED_PROTECTION_PROMO_IMPRESSION_ACTION = - "NewTabPage.Promo.EnhancedProtectionPromo.ImpressionUntilAction"; - private static final String METRICS_ENHANCED_PROTECTION_PROMO_IMPRESSION_DISMISSAL = - "NewTabPage.Promo.EnhancedProtectionPromo.ImpressionUntilDismissal"; - private static final int NTP_HEADER_POSITION = 0; - - private boolean mHasEnhancedProtectionPromoDismissed; // Test value before the test. - private UserActionTester mActionTester; - - @Rule - public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - mActivityTestRule.startMainActivityOnBlankPage(); - - // Set promo not dismissed. - mHasEnhancedProtectionPromoDismissed = - EnhancedProtectionPromoUtils.isPromoDismissedInSharedPreference(); - EnhancedProtectionPromoUtils.setPromoDismissedInSharedPreference(false); - - SignInPromo.setDisablePromoForTests(true); - } - - @After - public void tearDown() { - EnhancedProtectionPromoUtils.setPromoDismissedInSharedPreference( - mHasEnhancedProtectionPromoDismissed); - if (mActionTester != null) mActionTester.tearDown(); - SignInPromo.setDisablePromoForTests(false); - } - - /** - * Test that the enhanced protection promo should show for users not signed up for enhanced - * protection - */ - @Test - @SmallTest - @DisableIf.Build(message = "Flaky on Android Lollipop, see crbug.com/1199125", - sdk_is_less_than = Build.VERSION_CODES.M) - public void - testSetUp_Basic() { - mActivityTestRule.loadUrl(UrlConstants.NTP_URL); - - View enhancedProtectionPromo = - mActivityTestRule.getActivity().findViewById(R.id.enhanced_protection_promo); - Assert.assertNotNull( - "Enhanced Protection promo should be added to NTP.", enhancedProtectionPromo); - Assert.assertEquals("Enhanced Protection promo should be visible.", View.VISIBLE, - enhancedProtectionPromo.getVisibility()); - - Assert.assertEquals("Promo created should be recorded once. ", 1, - RecordHistogram.getHistogramValueCountForTesting( - METRICS_ENHANCED_PROTECTION_PROMO, EnhancedProtectionPromoAction.CREATED)); - } - - @Test - @MediumTest - public void testSetUp_NoShow() { - TestThreadUtils.runOnUiThreadBlocking(() -> { - UserPrefs.get(Profile.getLastUsedRegularProfile()) - .setBoolean(Pref.SAFE_BROWSING_ENHANCED, true); - }); - mActivityTestRule.loadUrl(UrlConstants.NTP_URL); - - View enhancedProtectionPromo = - mActivityTestRule.getActivity().findViewById(R.id.enhanced_protection_promo); - Assert.assertNull( - "Enhanced Protection promo should not be added to NTP.", enhancedProtectionPromo); - } - - @Test - @MediumTest - public void testAcceptImpl() { - mActivityTestRule.loadUrl(UrlConstants.NTP_URL); - Intents.init(); - - scrollToEnhancedProtectionPromo(); - - onView(withId(R.id.promo_primary_button)).perform(click()); - - Matcher<Intent> isCorrectComponent = hasComponent(SettingsActivity.class.getName()); - Matcher<Intent> isCorrectFragment = - hasExtra("show_fragment", SafeBrowsingSettingsFragment.class.getName()); - intended(allOf(isCorrectComponent, isCorrectFragment)); - - Assert.assertEquals("Promo accepted should be recorded once. ", 1, - RecordHistogram.getHistogramValueCountForTesting( - METRICS_ENHANCED_PROTECTION_PROMO, EnhancedProtectionPromoAction.ACCEPTED)); - Assert.assertEquals("Promo impression until action should be recorded once.", 1, - RecordHistogram.getHistogramTotalCountForTesting( - METRICS_ENHANCED_PROTECTION_PROMO_IMPRESSION_ACTION)); - Intents.release(); - } - - @Test - @MediumTest - public void testDismissImpl() { - mActionTester = new UserActionTester(); - mActivityTestRule.loadUrl(UrlConstants.NTP_URL); - - scrollToEnhancedProtectionPromo(); - - onView(withId(R.id.promo_secondary_button)).perform(click()); - Assert.assertNull("Enhanced Protection promo should be removed after dismissed.", - mActivityTestRule.getActivity().findViewById(R.id.enhanced_protection_promo)); - Assert.assertEquals("Promo dismissed should be recorded once. ", 1, - RecordHistogram.getHistogramValueCountForTesting(METRICS_ENHANCED_PROTECTION_PROMO, - EnhancedProtectionPromoAction.DISMISSED)); - Assert.assertEquals("Promo impression until dismissed should be recorded once.", 1, - RecordHistogram.getHistogramTotalCountForTesting( - METRICS_ENHANCED_PROTECTION_PROMO_IMPRESSION_DISMISSAL)); - boolean action_tracked = false; - for (String action : mActionTester.getActions()) { - if (action.startsWith("NewTabPage.Promo.EnhancedProtectionPromo.Dismissed")) { - action_tracked = true; - } - } - Assert.assertTrue(action_tracked); - - // Load to NTP one more time. The promo should not show. - mActivityTestRule.loadUrlInNewTab("about:blank"); - launchNewTabPage(); - Assert.assertNull("Enhanced Protection promo should not be added to NTP.", - mActivityTestRule.getActivity().findViewById(R.id.enhanced_protection_promo)); - } - - private void scrollToEnhancedProtectionPromo() { - onView(withId(R.id.feed_stream_recycler_view)) - .perform(RecyclerViewActions.scrollToPosition(NTP_HEADER_POSITION + 1)); - waitForView((ViewGroup) mActivityTestRule.getActivity().findViewById( - R.id.enhanced_protection_promo), - allOf(withId(R.id.promo_primary_button), isDisplayed())); - - CriteriaHelper.pollUiThread(() -> { - // Verify impression tracking metrics is working. - Criteria.checkThat("Promo created should be seen.", - RecordHistogram.getHistogramValueCountForTesting( - METRICS_ENHANCED_PROTECTION_PROMO, EnhancedProtectionPromoAction.SEEN), - Matchers.is(1)); - Criteria.checkThat("Impression should be tracked in shared preference.", - SharedPreferencesManager.getInstance().readInt( - EnhancedProtectionPromoUtils.getTimesSeenKey()), - Matchers.is(1)); - }); - } - - private void launchNewTabPage() { - mActivityTestRule.loadUrl(UrlConstants.NTP_URL); - Tab tab = mActivityTestRule.getActivity().getActivityTab(); - NewTabPageTestUtils.waitForNtpLoaded(tab); - } -}
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinatorTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinatorTest.java index b2a1b1f..dbc6d33 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinatorTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinatorTest.java
@@ -75,12 +75,10 @@ /** * Tests for {@link FeedSurfaceCoordinator}. * - * EnhancedProtectionPromoCard does not need to be disabled. Its value just need to be set. */ @RunWith(BaseRobolectricTestRunner.class) @Config(manifest = Config.NONE) -@Features.DisableFeatures({ChromeFeatureList.ENHANCED_PROTECTION_PROMO_CARD, - ChromeFeatureList.WEB_FEED, ChromeFeatureList.INTEREST_FEED_V2_AUTOPLAY, +@Features.DisableFeatures({ChromeFeatureList.WEB_FEED, ChromeFeatureList.INTEREST_FEED_V2_AUTOPLAY, ChromeFeatureList.FEED_INTERACTIVE_REFRESH, ChromeFeatureList.FEED_BACK_TO_TOP}) @Features.EnableFeatures({ChromeFeatureList.FEED_RELIABILITY_LOGGING}) public class FeedSurfaceCoordinatorTest {
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp index 5c796b05..fa944b9 100644 --- a/chrome/app/settings_strings.grdp +++ b/chrome/app/settings_strings.grdp
@@ -2064,6 +2064,9 @@ <message name="IDS_SETTINGS_SITE_SETTINGS_ALL_SITES_SORT_METHOD_NAME" desc="A selection menu option to sort the All Sites list by the name of the site, which is derived from its URL." meaning="Name of an inanimate object"> Name </message> + <message name="IDS_SETTINGS_SITE_SETTINGS_SITE_ENTRY_PARTITIONED_LABEL" desc="The label which is applied to site entries which are partitioned. These entries represent data whose access scope is limited to the site the labeled entry appears under"> + Partitioned + </message> <message name="IDS_SETTINGS_SITE_SETTINGS_SITE_REPRESENTATION_SEPARATOR" desc="The separator used to split up the display of a URL into host and scheme/protocol, when the scheme is not HTTPS. For example, it will be used in a string that looks like 'google.co.uk — http'."> — </message> @@ -3060,6 +3063,9 @@ <message name="IDS_SETTINGS_SITE_SETTINGS_REMOVE_SITE_ORIGIN_APP_DIALOG_TITLE" desc="Title of the confirmation dialog when a user selects to remove a specific origin, and that origin also has an installed web app"> Clear site data and permissions for <ph name="SITE_NAME">$1<ex>www.example.com</ex></ph> and its installed app? </message> + <message name="IDS_SETTINGS_SITE_SETTINGS_REMOVE_SITE_ORIGIN_PARTITIONED_DIALOG_TITLE" desc="Title of the confirmation dialog when a user selects to remove a specific origins partitioned data. That data will be partitioned on a specific eTLD +1."> + Clear site data for <ph name="SITE_NAME">$1<ex>www.ad-tech.com</ex></ph> partitioned on <ph name="PARTITION_SITE_NAME">$2<ex>www.publisher.com</ex></ph>? + </message> <message name="IDS_SETTINGS_SITE_SETTINGS_REMOVE_SITE_GROUP_DIALOG_TITLE" desc="Title of the confirmation dialog when a user selects to remove a group of sites"> Clear site data and permissions for <ph name="SITE_NAME">$1<ex>www.example.com</ex></ph> and all sites under it? </message>
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_REMOVE_SITE_ORIGIN_PARTITIONED_DIALOG_TITLE.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_REMOVE_SITE_ORIGIN_PARTITIONED_DIALOG_TITLE.png.sha1 new file mode 100644 index 0000000..2bd5abbb --- /dev/null +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_REMOVE_SITE_ORIGIN_PARTITIONED_DIALOG_TITLE.png.sha1
@@ -0,0 +1 @@ +adb7988a3fbbe3c83bae573f61b96430bbc2189a \ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_SITE_ENTRY_PARTITIONED_LABEL.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_SITE_ENTRY_PARTITIONED_LABEL.png.sha1 new file mode 100644 index 0000000..c703650 --- /dev/null +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_SITE_ENTRY_PARTITIONED_LABEL.png.sha1
@@ -0,0 +1 @@ +2bcabfbd00b7c37b0ad4b256ef4ffaa1c386fdc6 \ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index e0b9da01..37fd6b5 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -4595,6 +4595,8 @@ "apps/app_service/metrics/app_platform_metrics_service.h", "apps/app_service/metrics/app_platform_metrics_utils.cc", "apps/app_service/metrics/app_platform_metrics_utils.h", + "apps/app_service/metrics/browser_to_tab_list.cc", + "apps/app_service/metrics/browser_to_tab_list.h", "apps/app_service/publishers/arc_apps.cc", "apps/app_service/publishers/arc_apps.h", "apps/app_service/publishers/arc_apps_factory.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index ed4ab2c..ccdf7bee 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -1931,24 +1931,6 @@ {"60 minutes", kConditionalTabStripAndroid_60Minutes, base::size(kConditionalTabStripAndroid_60Minutes), nullptr}, }; - -const FeatureEntry::FeatureParam - kEnhancedProtectionPromoCard_SigninPromoImpressions_Count1[] = { - {"MaxSigninPromoImpressions", "1"}}; -const FeatureEntry::FeatureParam - kEnhancedProtectionPromoCard_SigninPromoImpressions_Count5[] = { - {"MaxSigninPromoImpressions", "5"}}; -const FeatureEntry::FeatureVariation kEnhancedProtectionPromoCardVariations[] = - { - {"Max Impressions 1", - kEnhancedProtectionPromoCard_SigninPromoImpressions_Count1, - base::size(kEnhancedProtectionPromoCard_SigninPromoImpressions_Count1), - nullptr}, - {"Max Impressions 5", - kEnhancedProtectionPromoCard_SigninPromoImpressions_Count5, - base::size(kEnhancedProtectionPromoCard_SigninPromoImpressions_Count5), - nullptr}, -}; #endif // OS_ANDROID #if defined(OS_ANDROID) @@ -5594,6 +5576,10 @@ flag_descriptions::kArcGhostWindowDescription, kOsCrOS, FEATURE_VALUE_TYPE(full_restore::features::kArcGhostWindow)}, + {"arc-window-predictor", flag_descriptions::kArcWindowPredictorName, + flag_descriptions::kArcWindowPredictorDescription, kOsCrOS, + FEATURE_VALUE_TYPE(full_restore::features::kArcWindowPredictor)}, + {"arc-input-overlay", flag_descriptions::kArcInputOverlayName, flag_descriptions::kArcInputOverlayDescription, kOsCrOS, FEATURE_VALUE_TYPE(ash::features::kArcInputOverlay)}, @@ -5907,14 +5893,6 @@ FEATURE_VALUE_TYPE(features::kSearchHistoryLink)}, #if defined(OS_ANDROID) - {"safe-browsing-enhanced-protection-promo-android", - flag_descriptions::kEnhancedProtectionPromoAndroidName, - flag_descriptions::kEnhancedProtectionPromoAndroidDescription, kOsAndroid, - FEATURE_WITH_PARAMS_VALUE_TYPE( - chrome::android::kEnhancedProtectionPromoCard, - kEnhancedProtectionPromoCardVariations, - "EnhancedProtectionPromoCard")}, - {"safe-browsing-password-protection-for-signed-in-users", flag_descriptions::kPasswordProtectionForSignedInUsersName, flag_descriptions::kPasswordProtectionForSignedInUsersDescription,
diff --git a/chrome/browser/accessibility/accessibility_extension_api_chromeos.cc b/chrome/browser/accessibility/accessibility_extension_api_chromeos.cc index 86560da..b4d7a75 100644 --- a/chrome/browser/accessibility/accessibility_extension_api_chromeos.cc +++ b/chrome/browser/accessibility/accessibility_extension_api_chromeos.cc
@@ -253,9 +253,30 @@ EXTENSION_FUNCTION_VALIDATE(args().size() >= 1); EXTENSION_FUNCTION_VALIDATE(args()[0].is_bool()); bool enabled = args()[0].GetBool(); - bridge->SetNativeChromeVoxArcSupport(enabled); + bridge->SetNativeChromeVoxArcSupport( + enabled, + base::BindOnce( + &AccessibilityPrivateSetNativeChromeVoxArcSupportForCurrentAppFunction:: + OnResponse, + this)); + return did_respond() ? AlreadyResponded() : RespondLater(); } - return RespondNow(NoArguments()); + return RespondNow(ArgumentList( + extensions::api::accessibility_private:: + SetNativeChromeVoxArcSupportForCurrentApp::Results::Create( + extensions::api::accessibility_private:: + SetNativeChromeVoxResponse:: + SET_NATIVE_CHROME_VOX_RESPONSE_FAILURE))); +} + +void AccessibilityPrivateSetNativeChromeVoxArcSupportForCurrentAppFunction:: + OnResponse( + extensions::api::accessibility_private::SetNativeChromeVoxResponse + response) { + Respond(ArgumentList( + extensions::api::accessibility_private:: + SetNativeChromeVoxArcSupportForCurrentApp::Results::Create( + response))); } ExtensionFunction::ResponseAction
diff --git a/chrome/browser/accessibility/accessibility_extension_api_chromeos.h b/chrome/browser/accessibility/accessibility_extension_api_chromeos.h index 2182f3d..9cc9adc 100644 --- a/chrome/browser/accessibility/accessibility_extension_api_chromeos.h +++ b/chrome/browser/accessibility/accessibility_extension_api_chromeos.h
@@ -6,6 +6,7 @@ #define CHROME_BROWSER_ACCESSIBILITY_ACCESSIBILITY_EXTENSION_API_CHROMEOS_H_ #include "build/chromeos_buildflags.h" +#include "chrome/common/extensions/api/accessibility_private.h" #include "extensions/browser/extension_function.h" // API function that enables or disables web content accessibility support. @@ -66,6 +67,9 @@ ~AccessibilityPrivateSetNativeChromeVoxArcSupportForCurrentAppFunction() override {} ResponseAction Run() override; + void OnResponse( + extensions::api::accessibility_private::SetNativeChromeVoxResponse + response); DECLARE_EXTENSION_FUNCTION( "accessibilityPrivate.setNativeChromeVoxArcSupportForCurrentApp", ACCESSIBILITY_PRIVATE_SETNATIVECHROMEVOXARCSUPPORTFORCURRENTAPP)
diff --git a/chrome/browser/android/webapps/launchpad/java/src/org/chromium/chrome/browser/webapps/launchpad/LaunchpadCoordinatorTest.java b/chrome/browser/android/webapps/launchpad/java/src/org/chromium/chrome/browser/webapps/launchpad/LaunchpadCoordinatorTest.java index d56d704..8c2b22f 100644 --- a/chrome/browser/android/webapps/launchpad/java/src/org/chromium/chrome/browser/webapps/launchpad/LaunchpadCoordinatorTest.java +++ b/chrome/browser/android/webapps/launchpad/java/src/org/chromium/chrome/browser/webapps/launchpad/LaunchpadCoordinatorTest.java
@@ -34,7 +34,6 @@ /** * Tests for {@link LaunchpadCoordinator}. * - * EnhancedProtectionPromoCard does not need to be disabled. Its value just need to be set. */ @RunWith(BaseRobolectricTestRunner.class) @Config(manifest = Config.NONE)
diff --git a/chrome/browser/apps/app_service/metrics/DEPS b/chrome/browser/apps/app_service/metrics/DEPS index 64e2821..df77277 100644 --- a/chrome/browser/apps/app_service/metrics/DEPS +++ b/chrome/browser/apps/app_service/metrics/DEPS
@@ -2,4 +2,8 @@ "app_platform_input_metrics\.cc": [ "+ash/shell.h", ], + "app_platform_metrics_service_unittest\.cc": [ + "+ash/test/ash_test_base.h", + "+ash/test/ash_test_helper.h", + ], }
diff --git a/chrome/browser/apps/app_service/metrics/app_platform_metrics.cc b/chrome/browser/apps/app_service/metrics/app_platform_metrics.cc index 6978f57..95933d3 100644 --- a/chrome/browser/apps/app_service/metrics/app_platform_metrics.cc +++ b/chrome/browser/apps/app_service/metrics/app_platform_metrics.cc
@@ -355,11 +355,6 @@ } } -AppPlatformMetrics::BrowserToTab::BrowserToTab( - const aura::Window* browser_window, - const base::UnguessableToken& tab_id) - : browser_window(browser_window), tab_id(tab_id) {} - AppPlatformMetrics::AppPlatformMetrics( Profile* profile, apps::AppRegistryCache& app_registry_cache, @@ -700,7 +695,7 @@ // For the browser window, if a tab of the browser is activated, we don't // need to calculate the browser window running time. if (app_id == extension_misc::kChromeAppId && - HasActivatedTab(update.Window())) { + browser_to_tab_list_.HasActivatedTab(update.Window())) { SetWindowInActivated(app_id, update.InstanceId(), kInActivated); return; } @@ -708,9 +703,9 @@ // For web apps open in tabs, set the top browser window as inactive to stop // calculating the browser window running time. if (IsAppOpenedInTab(app_type_name, app_id)) { - RemoveActivatedTab(update.InstanceId()); - AddActivatedTab(update.Window()->GetToplevelWindow(), - update.InstanceId()); + browser_to_tab_list_.RemoveActivatedTab(update.InstanceId()); + browser_to_tab_list_.AddActivatedTab(update.Window()->GetToplevelWindow(), + update.InstanceId()); InstanceState state; base::UnguessableToken browser_id; GetBrowserIdAndState(update, browser_id, state); @@ -768,17 +763,17 @@ void AppPlatformMetrics::UpdateBrowserWindowStatus( const InstanceUpdate& update) { const base::UnguessableToken& tab_id = update.InstanceId(); - const auto* browser_window = GetBrowserWindow(tab_id); + const auto* browser_window = browser_to_tab_list_.GetBrowserWindow(tab_id); if (!browser_window) { return; } // Remove the tab id from `active_browser_to_tabs_`. - RemoveActivatedTab(tab_id); + browser_to_tab_list_.RemoveActivatedTab(tab_id); // If there are other activated web app tab, we don't need to set the browser // window as activated. - if (HasActivatedTab(browser_window)) { + if (browser_to_tab_list_.HasActivatedTab(browser_window)) { return; } @@ -798,46 +793,6 @@ } } -bool AppPlatformMetrics::HasActivatedTab(const aura::Window* browser_window) { - for (const auto& it : active_browsers_to_tabs_) { - if (it.browser_window == browser_window) { - return true; - } - } - return false; -} - -const aura::Window* AppPlatformMetrics::GetBrowserWindow( - const base::UnguessableToken& tab_id) const { - for (const auto& it : active_browsers_to_tabs_) { - if (it.tab_id == tab_id) { - return it.browser_window; - } - } - return nullptr; -} - -void AppPlatformMetrics::AddActivatedTab(const aura::Window* browser_window, - const base::UnguessableToken& tab_id) { - bool found = false; - for (const auto& it : active_browsers_to_tabs_) { - if (it.browser_window == browser_window && it.tab_id == tab_id) { - found = true; - break; - } - } - - if (!found) { - active_browsers_to_tabs_.push_back(BrowserToTab(browser_window, tab_id)); - } -} - -void AppPlatformMetrics::RemoveActivatedTab( - const base::UnguessableToken& tab_id) { - active_browsers_to_tabs_.remove_if( - [&](const BrowserToTab& item) { return item.tab_id == tab_id; }); -} - void AppPlatformMetrics::SetWindowActivated( apps::mojom::AppType app_type, AppTypeName app_type_name,
diff --git a/chrome/browser/apps/app_service/metrics/app_platform_metrics.h b/chrome/browser/apps/app_service/metrics/app_platform_metrics.h index c757bf0..4b90f0e 100644 --- a/chrome/browser/apps/app_service/metrics/app_platform_metrics.h +++ b/chrome/browser/apps/app_service/metrics/app_platform_metrics.h
@@ -5,13 +5,13 @@ #ifndef CHROME_BROWSER_APPS_APP_SERVICE_METRICS_APP_PLATFORM_METRICS_H_ #define CHROME_BROWSER_APPS_APP_SERVICE_METRICS_APP_PLATFORM_METRICS_H_ -#include <list> #include <map> #include <set> #include <string> #include "base/time/time.h" #include "chrome/browser/apps/app_service/metrics/app_platform_metrics_utils.h" +#include "chrome/browser/apps/app_service/metrics/browser_to_tab_list.h" #include "components/services/app_service/public/cpp/app_registry_cache.h" #include "components/services/app_service/public/cpp/instance_registry.h" #include "components/services/app_service/public/mojom/types.mojom.h" @@ -19,10 +19,6 @@ class Profile; -namespace aura { -class Window; -} - namespace apps { class AppUpdate; @@ -157,15 +153,6 @@ bool window_is_closed = false; }; - struct BrowserToTab { - BrowserToTab(const aura::Window* browser_window, - const base::UnguessableToken& tab_id); - const aura::Window* browser_window; - base::UnguessableToken tab_id; - }; - - using BrowserToTabs = std::list<BrowserToTab>; - // AppRegistryCache::Observer: void OnAppTypeInitialized(apps::mojom::AppType app_type) override; void OnAppRegistryCacheWillBeDestroyed( @@ -189,22 +176,6 @@ // inactivated. void UpdateBrowserWindowStatus(const InstanceUpdate& update); - // Returns true if the browser with `browser_window` has activated tabs. - // Otherwise, returns false. - bool HasActivatedTab(const aura::Window* browser_window); - - // Returns the browser window for `tab_id`. - const aura::Window* GetBrowserWindow( - const base::UnguessableToken& tab_id) const; - - // Adds an activated `browser_window` and `tab_id` to - // `active_browser_to_tabs_`. - void AddActivatedTab(const aura::Window* browser_window, - const base::UnguessableToken& tab_id); - - // Removes `tab_id` from `active_browser_to_tabs_`. - void RemoveActivatedTab(const base::UnguessableToken& tab_id); - void SetWindowActivated(apps::mojom::AppType app_type, AppTypeName app_type_name, AppTypeNameV2 app_type_name_v2, @@ -246,8 +217,7 @@ int user_type_by_device_type_; - // Records the map from browsers to activated web apps tabs. - BrowserToTabs active_browsers_to_tabs_; + BrowserToTabList browser_to_tab_list_; // |running_start_time_| and |running_duration_| are used for accumulating app // running duration per each day interval.
diff --git a/chrome/browser/apps/app_service/metrics/app_platform_metrics_service.h b/chrome/browser/apps/app_service/metrics/app_platform_metrics_service.h index 0a8de9c8..72ca4cb7 100644 --- a/chrome/browser/apps/app_service/metrics/app_platform_metrics_service.h +++ b/chrome/browser/apps/app_service/metrics/app_platform_metrics_service.h
@@ -45,6 +45,8 @@ } private: + friend class AppPlatformInputMetricsTest; + // Helper function to check if a new day has arrived. void CheckForNewDay();
diff --git a/chrome/browser/apps/app_service/metrics/app_platform_metrics_service_unittest.cc b/chrome/browser/apps/app_service/metrics/app_platform_metrics_service_unittest.cc index 05a8d3d..39353e2 100644 --- a/chrome/browser/apps/app_service/metrics/app_platform_metrics_service_unittest.cc +++ b/chrome/browser/apps/app_service/metrics/app_platform_metrics_service_unittest.cc
@@ -7,6 +7,8 @@ #include <memory> #include <utility> +#include "ash/test/ash_test_base.h" +#include "ash/test/ash_test_helper.h" #include "base/json/values_util.h" #include "base/metrics/histogram_base.h" #include "base/test/metrics/histogram_tester.h" @@ -704,6 +706,10 @@ return std::move(app_platform_metrics_service_); } + AppPlatformMetricsService* app_platform_metrics_service() { + return app_platform_metrics_service_.get(); + } + TestingProfile* profile() { return testing_profile_.get(); } syncer::TestSyncService* sync_service() { return sync_service_; } @@ -1572,4 +1578,200 @@ apps::mojom::UninstallSource::kAppList); } +// Tests for app platform input metrics. +class AppPlatformInputMetricsTest : public AppPlatformMetricsServiceTest { + public: + void SetUp() override { + AppPlatformMetricsServiceTest::SetUp(); + + ash_test_helper_ = std::make_unique<ash::AshTestHelper>(); + ash_test_helper_->SetUp(); + + widget_ = ash::AshTestBase::CreateTestWidget(); + } + + void TearDown() override { + widget_.reset(); + ash_test_helper_->TearDown(); + AppPlatformMetricsServiceTest::TearDown(); + } + + AppPlatformInputMetrics* app_platform_input_metrics() { + return app_platform_metrics_service()->app_platform_input_metrics_.get(); + } + + aura::Window* window() { return widget_->GetNativeWindow(); } + + void CreateInputEvent(InputEventSource event_source) { + switch (event_source) { + case InputEventSource::kUnknown: + break; + case InputEventSource::kMouse: { + ui::MouseEvent mouse_event(ui::ET_MOUSE_RELEASED, gfx::Point(), + gfx::Point(), base::TimeTicks(), 0, 0); + ui::Event::DispatcherApi(&mouse_event).set_target(window()); + app_platform_input_metrics()->OnMouseEvent(&mouse_event); + break; + } + case InputEventSource::kStylus: { + ui::TouchEvent touch_event( + ui::ET_TOUCH_RELEASED, gfx::Point(), base::TimeTicks(), + ui::PointerDetails(ui::EventPointerType::kPen, 0)); + ui::Event::DispatcherApi(&touch_event).set_target(window()); + app_platform_input_metrics()->OnTouchEvent(&touch_event); + break; + } + case InputEventSource::kTouch: { + ui::TouchEvent touch_event( + ui::ET_TOUCH_RELEASED, gfx::Point(), base::TimeTicks(), + ui::PointerDetails(ui::EventPointerType::kTouch, 0)); + ui::Event::DispatcherApi(&touch_event).set_target(window()); + app_platform_input_metrics()->OnTouchEvent(&touch_event); + break; + } + case InputEventSource::kKeyboard: { + ui::KeyEvent key_event(ui::ET_KEY_RELEASED, ui::VKEY_MENU, + ui::EF_ALT_DOWN); + ui::Event::DispatcherApi(&key_event).set_target(window()); + app_platform_input_metrics()->OnKeyEvent(&key_event); + break; + } + } + } + + void VerifyUkm(const std::string& app_info, + AppTypeName app_type_name, + int event_count, + InputEventSource event_source) { + const auto entries = + test_ukm_recorder()->GetEntriesByName("ChromeOSApp.InputEvent"); + ASSERT_EQ(1U, entries.size()); + const auto* entry = entries[0]; + test_ukm_recorder()->ExpectEntrySourceHasUrl(entry, GURL(app_info)); + test_ukm_recorder()->ExpectEntryMetric(entry, "AppType", + (int)app_type_name); + test_ukm_recorder()->ExpectEntryMetric(entry, "AppInputEventCount", + event_count); + test_ukm_recorder()->ExpectEntryMetric(entry, "AppInputEventSource", + (int)event_source); + } + + private: + std::unique_ptr<ash::AshTestHelper> ash_test_helper_; + + // Where down events are dispatched to. + std::unique_ptr<views::Widget> widget_; +}; + +// Verify the input event is recorded when the window is inactivated, and no +// more input event is recorded when the window is destroyed. +TEST_F(AppPlatformInputMetricsTest, WindowStateChanged) { + ModifyInstance(/*app_id=*/"a", window(), kInactiveInstanceState); + CreateInputEvent(InputEventSource::kMouse); + app_platform_input_metrics()->OnFiveMinutes(); + VerifyUkm("app://com.google.A", AppTypeName::kArc, /*event_count=*/1, + InputEventSource::kMouse); + + ModifyInstance(/*app_id=*/"a", window(), apps::InstanceState::kDestroyed); + CreateInputEvent(InputEventSource::kMouse); + app_platform_input_metrics()->OnFiveMinutes(); + // Verify no more input event is recorded. + VerifyUkm("app://com.google.A", AppTypeName::kArc, /*event_count=*/1, + InputEventSource::kMouse); +} + +TEST_F(AppPlatformInputMetricsTest, MouseEvent) { + ModifyInstance(/*app_id=*/"a", window(), apps::InstanceState::kActive); + CreateInputEvent(InputEventSource::kMouse); + app_platform_input_metrics()->OnFiveMinutes(); + VerifyUkm("app://com.google.A", AppTypeName::kArc, /*event_count=*/1, + InputEventSource::kMouse); +} + +TEST_F(AppPlatformInputMetricsTest, StylusEvent) { + ModifyInstance(/*app_id=*/"w", window(), apps::InstanceState::kActive); + CreateInputEvent(InputEventSource::kStylus); + app_platform_input_metrics()->OnFiveMinutes(); + VerifyUkm("https://foo.com", AppTypeName::kWeb, /*event_count=*/1, + InputEventSource::kStylus); +} + +TEST_F(AppPlatformInputMetricsTest, TouchEvents) { + ModifyInstance(/*app_id=*/"a", window(), apps::InstanceState::kActive); + CreateInputEvent(InputEventSource::kTouch); + CreateInputEvent(InputEventSource::kTouch); + app_platform_input_metrics()->OnFiveMinutes(); + VerifyUkm("app://com.google.A", AppTypeName::kArc, /*event_count=*/2, + InputEventSource::kTouch); +} + +TEST_F(AppPlatformInputMetricsTest, KeyEvents) { + ModifyInstance(/*app_id=*/"a", window(), apps::InstanceState::kActive); + CreateInputEvent(InputEventSource::kKeyboard); + app_platform_input_metrics()->OnFiveMinutes(); + VerifyUkm("app://com.google.A", AppTypeName::kArc, /*event_count=*/1, + InputEventSource::kKeyboard); + + CreateInputEvent(InputEventSource::kKeyboard); + CreateInputEvent(InputEventSource::kKeyboard); + app_platform_input_metrics()->OnFiveMinutes(); + + // Verify 2 input metrics events are recorded. + const auto entries = + test_ukm_recorder()->GetEntriesByName("ChromeOSApp.InputEvent"); + ASSERT_EQ(2U, entries.size()); + std::set<int> counts; + for (const auto* entry : entries) { + test_ukm_recorder()->ExpectEntrySourceHasUrl(entry, + GURL("app://com.google.A")); + test_ukm_recorder()->ExpectEntryMetric(entry, "AppType", + (int)AppTypeName::kArc); + test_ukm_recorder()->ExpectEntryMetric(entry, "AppInputEventSource", + (int)InputEventSource::kKeyboard); + counts.insert( + *(test_ukm_recorder()->GetEntryMetric(entry, "AppInputEventCount"))); + } + EXPECT_TRUE(base::Contains(counts, 1)); + EXPECT_TRUE(base::Contains(counts, 2)); +} + +TEST_F(AppPlatformInputMetricsTest, MultipleEvents) { + ModifyInstance(/*app_id=*/"a", window(), apps::InstanceState::kActive); + CreateInputEvent(InputEventSource::kMouse); + CreateInputEvent(InputEventSource::kMouse); + CreateInputEvent(InputEventSource::kKeyboard); + CreateInputEvent(InputEventSource::kStylus); + app_platform_input_metrics()->OnFiveMinutes(); + + // Verify 3 input metrics events are recorded. + const auto entries = + test_ukm_recorder()->GetEntriesByName("ChromeOSApp.InputEvent"); + ASSERT_EQ(3U, entries.size()); + int event_source; + int mouse_event_count = 0; + int keyboard_event_count = 0; + int stylus_event_count = 0; + for (const auto* entry : entries) { + test_ukm_recorder()->ExpectEntrySourceHasUrl(entry, + GURL("app://com.google.A")); + test_ukm_recorder()->ExpectEntryMetric(entry, "AppType", + (int)AppTypeName::kArc); + event_source = + *(test_ukm_recorder()->GetEntryMetric(entry, "AppInputEventSource")); + if (event_source == (int)InputEventSource::kMouse) { + mouse_event_count = + *(test_ukm_recorder()->GetEntryMetric(entry, "AppInputEventCount")); + } else if (event_source == (int)InputEventSource::kKeyboard) { + keyboard_event_count = + *(test_ukm_recorder()->GetEntryMetric(entry, "AppInputEventCount")); + } else if (event_source == (int)InputEventSource::kStylus) { + stylus_event_count = + *(test_ukm_recorder()->GetEntryMetric(entry, "AppInputEventCount")); + } + } + EXPECT_EQ(2, mouse_event_count); + EXPECT_EQ(1, keyboard_event_count); + EXPECT_EQ(1, stylus_event_count); +} + } // namespace apps
diff --git a/chrome/browser/apps/app_service/metrics/browser_to_tab_list.cc b/chrome/browser/apps/app_service/metrics/browser_to_tab_list.cc new file mode 100644 index 0000000..3522bdf --- /dev/null +++ b/chrome/browser/apps/app_service/metrics/browser_to_tab_list.cc
@@ -0,0 +1,60 @@ +// Copyright (c) 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. + +#include "chrome/browser/apps/app_service/metrics/browser_to_tab_list.h" + +#include "ui/aura/window.h" + +namespace apps { + +BrowserToTabList::BrowserToTabList() = default; + +BrowserToTabList::~BrowserToTabList() = default; + +BrowserToTabList::BrowserToTab::BrowserToTab( + const aura::Window* browser_window, + const base::UnguessableToken& tab_id) + : browser_window(browser_window), tab_id(tab_id) {} + +bool BrowserToTabList::HasActivatedTab(const aura::Window* browser_window) { + for (const auto& it : active_browsers_to_tabs_) { + if (it.browser_window == browser_window) { + return true; + } + } + return false; +} + +const aura::Window* BrowserToTabList::GetBrowserWindow( + const base::UnguessableToken& tab_id) const { + for (const auto& it : active_browsers_to_tabs_) { + if (it.tab_id == tab_id) { + return it.browser_window; + } + } + return nullptr; +} + +void BrowserToTabList::AddActivatedTab(const aura::Window* browser_window, + const base::UnguessableToken& tab_id) { + bool found = false; + for (const auto& it : active_browsers_to_tabs_) { + if (it.browser_window == browser_window && it.tab_id == tab_id) { + found = true; + break; + } + } + + if (!found) { + active_browsers_to_tabs_.push_back(BrowserToTab(browser_window, tab_id)); + } +} + +void BrowserToTabList::RemoveActivatedTab( + const base::UnguessableToken& tab_id) { + active_browsers_to_tabs_.remove_if( + [&](const BrowserToTab& item) { return item.tab_id == tab_id; }); +} + +} // namespace apps
diff --git a/chrome/browser/apps/app_service/metrics/browser_to_tab_list.h b/chrome/browser/apps/app_service/metrics/browser_to_tab_list.h new file mode 100644 index 0000000..3b16f3c --- /dev/null +++ b/chrome/browser/apps/app_service/metrics/browser_to_tab_list.h
@@ -0,0 +1,57 @@ +// Copyright (c) 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_APPS_APP_SERVICE_METRICS_BROWSER_TO_TAB_LIST_H_ +#define CHROME_BROWSER_APPS_APP_SERVICE_METRICS_BROWSER_TO_TAB_LIST_H_ + +#include <list> + +#include "base/unguessable_token.h" +#include "ui/aura/window.h" + +namespace aura { +class Window; +} + +namespace apps { + +// BrowserToTabList saves the map from browser windows to tab instance ids. +class BrowserToTabList { + public: + BrowserToTabList(); + ~BrowserToTabList(); + + BrowserToTabList(const BrowserToTabList&) = delete; + BrowserToTabList& operator=(const BrowserToTabList&) = delete; + + // Returns true if the browser with `browser_window` has activated tabs. + // Otherwise, returns false. + bool HasActivatedTab(const aura::Window* browser_window); + + // Returns the browser window for `tab_id`. + const aura::Window* GetBrowserWindow( + const base::UnguessableToken& tab_id) const; + + // Adds `browser_window` and `tab_id` to`active_browser_to_tabs_`. + void AddActivatedTab(const aura::Window* browser_window, + const base::UnguessableToken& tab_id); + + // Removes `tab_id` from `active_browser_to_tabs_`. + void RemoveActivatedTab(const base::UnguessableToken& tab_id); + + private: + struct BrowserToTab { + BrowserToTab(const aura::Window* browser_window, + const base::UnguessableToken& tab_id); + const aura::Window* browser_window; + base::UnguessableToken tab_id; + }; + + // Stores the list of browser-tab instance id pairs. + std::list<BrowserToTab> active_browsers_to_tabs_; +}; + +} // namespace apps + +#endif // CHROME_BROWSER_APPS_APP_SERVICE_METRICS_BROWSER_TO_TAB_LIST_H_
diff --git a/chrome/browser/ash/accessibility/spoken_feedback_app_list_browsertest.cc b/chrome/browser/ash/accessibility/spoken_feedback_app_list_browsertest.cc index 5a57dc6..cfff5ff3 100644 --- a/chrome/browser/ash/accessibility/spoken_feedback_app_list_browsertest.cc +++ b/chrome/browser/ash/accessibility/spoken_feedback_app_list_browsertest.cc
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "ash/app_list/app_list_controller_impl.h" #include "ash/app_list/app_list_model_provider.h" #include "ash/app_list/model/app_list_item.h" #include "ash/constants/ash_features.h" @@ -16,6 +17,9 @@ #include "chrome/browser/ui/app_list/app_list_client_impl.h" #include "chrome/browser/ui/app_list/chrome_app_list_model_updater.h" #include "chrome/browser/ui/app_list/search/chrome_search_result.h" +#include "chrome/browser/ui/app_list/search/search_controller_impl.h" +#include "chrome/browser/ui/app_list/search/search_controller_impl_new.h" +#include "chrome/browser/ui/app_list/search/search_provider.h" #include "chrome/browser/ui/app_list/test/chrome_app_list_test_support.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_window.h" @@ -40,6 +44,105 @@ nullptr, key, true, true, false, false))); } +class TestSearchResult : public ChromeSearchResult { + public: + TestSearchResult(const std::string& id, double relevance) { + set_id(id); + SetTitle(base::UTF8ToUTF16(id)); + set_relevance(relevance); + } + + TestSearchResult(const TestSearchResult&) = delete; + TestSearchResult& operator=(const TestSearchResult&) = delete; + + ~TestSearchResult() override {} + + // ChromeSearchResult overrides: + void Open(int event_flags) override {} +}; + +class TestSearchProvider : public app_list::SearchProvider { + public: + TestSearchProvider(const std::string& prefix, + ChromeSearchResult::DisplayType display_type, + ChromeSearchResult::Category category, + ChromeSearchResult::ResultType result_type) + : prefix_(prefix), + display_type_(display_type), + category_(category), + result_type_(result_type) {} + + TestSearchProvider(const TestSearchProvider&) = delete; + TestSearchProvider& operator=(const TestSearchProvider&) = delete; + + ~TestSearchProvider() override {} + + // SearchProvider overrides: + void Start(const std::u16string& query) override { + auto create_result = + [this](int index) -> std::unique_ptr<ChromeSearchResult> { + const std::string id = + base::StringPrintf("%s %d", prefix_.c_str(), index); + double relevance = 1.0f - index / 100.0; + auto result = std::make_unique<TestSearchResult>(id, relevance); + + result->SetDisplayType(display_type_); + result->SetCategory(category_); + result->SetResultType(result_type_); + + return result; + }; + + std::vector<std::unique_ptr<ChromeSearchResult>> results; + for (size_t i = 0; i < count_ + best_match_count_; ++i) { + std::unique_ptr<ChromeSearchResult> result = create_result(i); + result->SetBestMatch(i < best_match_count_); + results.push_back(std::move(result)); + } + + SwapResults(&results); + } + + ChromeSearchResult::ResultType ResultType() override { return result_type_; } + + void set_count(size_t count) { count_ = count; } + void set_best_match_count(size_t count) { best_match_count_ = count; } + + private: + std::string prefix_; + size_t count_ = 0; + size_t best_match_count_ = 0; + ChromeSearchResult::DisplayType display_type_; + ChromeSearchResult::Category category_; + ChromeSearchResult::ResultType result_type_; +}; + +// Adds two test providers to `search_controller` - one for app results, and +// another one for omnibox results. Returns pointers to created providers +// through `apps_provder_ptr` and `web_provider_ptr`. +void InitializeTestSearchProviders( + app_list::SearchController* search_controller, + TestSearchProvider** apps_provider_ptr, + TestSearchProvider** web_provider_ptr) { + std::unique_ptr<TestSearchProvider> apps_provider = + std::make_unique<TestSearchProvider>( + "app", ChromeSearchResult::DisplayType::kTile, + ChromeSearchResult::Category::kApps, + ChromeSearchResult::ResultType::kInstalledApp); + *apps_provider_ptr = apps_provider.get(); + size_t apps_group_id = search_controller->AddGroup(10); + search_controller->AddProvider(apps_group_id, std::move(apps_provider)); + + std::unique_ptr<TestSearchProvider> web_provider = + std::make_unique<TestSearchProvider>( + "item", ChromeSearchResult::DisplayType::kList, + ChromeSearchResult::Category::kWeb, + ChromeSearchResult::ResultType::kOmnibox); + *web_provider_ptr = web_provider.get(); + size_t omnibox_group_id = search_controller->AddGroup(10); + search_controller->AddProvider(omnibox_group_id, std::move(web_provider)); +} + } // namespace enum SpokenFeedbackAppListTestVariant { kTestAsNormalUser, kTestAsGuestUser }; @@ -129,6 +232,43 @@ ::testing::Values(kTestAsNormalUser, kTestAsGuestUser)); +class SpokenFeedbackAppListSearchTest : public SpokenFeedbackAppListTest { + public: + // SpokenFeedbackAppListTest: + void SetUpOnMainThread() override { + SpokenFeedbackAppListTest::SetUpOnMainThread(); + + Shell::Get()->app_list_controller()->MarkSuggestedContentInfoDismissed(); + + // Reset default search controller, so the test has better control over the + // set of results shown in the search result UI. + AppListClientImpl* app_list_client = AppListClientImpl::GetInstance(); + std::unique_ptr<app_list::SearchController> search_controller = + std::make_unique<app_list::SearchControllerImpl>( + app_list_client->GetModelUpdaterForTest(), app_list_client, nullptr, + browser()->profile()); + InitializeTestSearchProviders(search_controller.get(), &apps_provider_, + &web_provider_); + ASSERT_TRUE(apps_provider_); + ASSERT_TRUE(web_provider_); + app_list_client->SetSearchControllerForTest(std::move(search_controller)); + } + + void TearDownOnMainThread() override { + AppListClientImpl::GetInstance()->SetSearchControllerForTest(nullptr); + SpokenFeedbackAppListTest::TearDownOnMainThread(); + } + + protected: + TestSearchProvider* apps_provider_ = nullptr; + TestSearchProvider* web_provider_ = nullptr; +}; + +INSTANTIATE_TEST_SUITE_P(TestAsNormalAndGuestUser, + SpokenFeedbackAppListSearchTest, + ::testing::Values(kTestAsNormalUser, + kTestAsGuestUser)); + class TabletModeSpokenFeedbackAppListTest : public SpokenFeedbackAppListTest { protected: TabletModeSpokenFeedbackAppListTest() = default; @@ -180,6 +320,43 @@ ::testing::Values(kTestAsNormalUser, kTestAsGuestUser)); +class SpokenFeedbackAppListSearchProductivityLauncherTest + : public SpokenFeedbackAppListProductivityLauncherTest { + public: + // SpokenFeedbackAppListProductivityLauncherTest: + void SetUpOnMainThread() override { + SpokenFeedbackAppListProductivityLauncherTest::SetUpOnMainThread(); + + AppListClientImpl* app_list_client = AppListClientImpl::GetInstance(); + + // Reset default search controller, so the test has better control over the + // set of results shown in the search result UI. + std::unique_ptr<app_list::SearchController> search_controller = + std::make_unique<app_list::SearchControllerImplNew>( + app_list_client->GetModelUpdaterForTest(), app_list_client, nullptr, + browser()->profile()); + InitializeTestSearchProviders(search_controller.get(), &apps_provider_, + &web_provider_); + ASSERT_TRUE(apps_provider_); + ASSERT_TRUE(web_provider_); + app_list_client->SetSearchControllerForTest(std::move(search_controller)); + } + + void TearDownOnMainThread() override { + AppListClientImpl::GetInstance()->SetSearchControllerForTest(nullptr); + SpokenFeedbackAppListProductivityLauncherTest::TearDownOnMainThread(); + } + + protected: + TestSearchProvider* apps_provider_ = nullptr; + TestSearchProvider* web_provider_ = nullptr; +}; + +INSTANTIATE_TEST_SUITE_P(TestAsNormalAndGuestUser, + SpokenFeedbackAppListSearchProductivityLauncherTest, + ::testing::Values(kTestAsNormalUser, + kTestAsGuestUser)); + // Checks that when an app list item with a notification badge is focused, an // announcement is made that the item requests your attention. IN_PROC_BROWSER_TEST_P(NotificationSpokenFeedbackAppListTest, @@ -769,6 +946,117 @@ sm_.Replay(); } +IN_PROC_BROWSER_TEST_P(SpokenFeedbackAppListSearchTest, + LauncherSearchInClamshell) { + EnableChromeVox(); + + // Focus the shelf. This selects the launcher button. + sm_.Call([this]() { + EXPECT_TRUE(PerformAcceleratorAction(AcceleratorAction::FOCUS_SHELF)); + }); + sm_.ExpectSpeechPattern("Launcher"); + sm_.ExpectSpeech("Button"); + sm_.ExpectSpeech("Shelf"); + sm_.ExpectSpeech("Tool bar"); + + // Activate the launcher button. This opens bubble launcher. + sm_.Call([this]() { SendKeyPressWithSearch(ui::VKEY_SPACE); }); + sm_.ExpectSpeechPattern("Search your device,*"); + sm_.ExpectSpeech("Edit text"); + + sm_.Call([this]() { + apps_provider_->set_count(3); + web_provider_->set_count(4); + SendKeyPress(ui::VKEY_G); + }); + + sm_.ExpectSpeech("G"); + sm_.ExpectSpeech("app 0"); + sm_.ExpectSpeech("List item 1 of 7"); + + // Traverse app results, which are horizontally traversable + for (int i = 1; i < 5; ++i) { + sm_.Call([this]() { SendKeyPress(ui::VKEY_RIGHT); }); + sm_.ExpectSpeech(base::StringPrintf("app %d", i % 3)); + sm_.ExpectSpeech(base::StringPrintf("List item %d of 7", (i % 3) + 1)); + } + + // Traverse omnibox results. + for (int i = 0; i < 4; ++i) { + sm_.Call([this]() { SendKeyPress(ui::VKEY_DOWN); }); + sm_.ExpectSpeech(base::StringPrintf("item %d", i)); + sm_.ExpectSpeech(base::StringPrintf("List item %d of 7", i + 4)); + } + + // Cycle focus to the close button. + sm_.Call([this]() { SendKeyPress(ui::VKEY_DOWN); }); + sm_.ExpectSpeech("Clear searchbox text"); + sm_.ExpectSpeech("Press Search plus Space to activate"); + + // Go back to the last result. + sm_.Call([this]() { SendKeyPress(ui::VKEY_UP); }); + sm_.ExpectSpeech("item 3"); + + // Update the query, to initiate new search. + sm_.Call([this]() { + apps_provider_->set_count(3); + web_provider_->set_count(2); + SendKeyPress(ui::VKEY_A); + }); + + sm_.ExpectSpeech("A"); + sm_.ExpectSpeech("app 0"); + + // Make sure key traversal still works. + for (int i = 0; i < 2; ++i) { + sm_.Call([this]() { SendKeyPress(ui::VKEY_DOWN); }); + sm_.ExpectSpeech(base::StringPrintf("item %d", i)); + sm_.ExpectSpeech(base::StringPrintf("List item %d of 5", i + 4)); + } + + sm_.Replay(); +} + +IN_PROC_BROWSER_TEST_P(SpokenFeedbackAppListSearchTest, + VocalizeResultCountInClamshell) { + EnableChromeVox(); + + // Focus the shelf. This selects the launcher button. + sm_.Call([this]() { + EXPECT_TRUE(PerformAcceleratorAction(AcceleratorAction::FOCUS_SHELF)); + }); + sm_.ExpectSpeechPattern("Launcher"); + sm_.ExpectSpeech("Button"); + sm_.ExpectSpeech("Shelf"); + sm_.ExpectSpeech("Tool bar"); + + // Activate the launcher button. This opens bubble launcher. + sm_.Call([this]() { SendKeyPressWithSearch(ui::VKEY_SPACE); }); + sm_.ExpectSpeechPattern("Search your device,*"); + sm_.ExpectSpeech("Edit text"); + + sm_.Call([this]() { + apps_provider_->set_count(3); + web_provider_->set_count(4); + SendKeyPress(ui::VKEY_G); + }); + + sm_.ExpectSpeech("G"); + sm_.ExpectSpeech("Displaying 7 results for g"); + + // Update the query, to initiate new search. + sm_.Call([this]() { + apps_provider_->set_count(3); + web_provider_->set_count(2); + SendKeyPress(ui::VKEY_A); + }); + + sm_.ExpectSpeech("A"); + sm_.ExpectSpeech("Displaying 5 results for ga"); + + sm_.Replay(); +} + IN_PROC_BROWSER_TEST_P(SpokenFeedbackAppListProductivityLauncherTest, ClamshellLauncher) { std::vector<std::string> suggestion_chips = GetPublishedSuggestionChips(); @@ -825,4 +1113,243 @@ sm_.Replay(); } +IN_PROC_BROWSER_TEST_P(SpokenFeedbackAppListSearchProductivityLauncherTest, + LauncherSearchInClamshell) { + EnableChromeVox(); + + // Focus the shelf. This selects the launcher button. + sm_.Call([this]() { + EXPECT_TRUE(PerformAcceleratorAction(AcceleratorAction::FOCUS_SHELF)); + }); + sm_.ExpectSpeechPattern("Launcher"); + sm_.ExpectSpeech("Button"); + sm_.ExpectSpeech("Shelf"); + sm_.ExpectSpeech("Tool bar"); + + // Activate the launcher button. This opens bubble launcher. + sm_.Call([this]() { SendKeyPressWithSearch(ui::VKEY_SPACE); }); + sm_.ExpectSpeechPattern("Search your device,*"); + sm_.ExpectSpeech("Edit text"); + + sm_.Call([this]() { + apps_provider_->set_best_match_count(2); + apps_provider_->set_count(3); + web_provider_->set_count(4); + SendKeyPress(ui::VKEY_G); + }); + + sm_.ExpectSpeech("G"); + sm_.ExpectSpeech("app 0"); + sm_.ExpectSpeech("List item 1 of 8"); + + // Traverse best match results; + for (int i = 1; i < 2; ++i) { + sm_.Call([this]() { SendKeyPress(ui::VKEY_DOWN); }); + sm_.ExpectSpeech(base::StringPrintf("app %d", i)); + sm_.ExpectSpeech(base::StringPrintf("List item %d of 8", i + 1)); + } + + // Traverse non-best-match app results. + for (int i = 2; i < 5; ++i) { + sm_.Call([this]() { SendKeyPress(ui::VKEY_DOWN); }); + sm_.ExpectSpeech(base::StringPrintf("app %d", i)); + sm_.ExpectSpeech(base::StringPrintf("List item %d of 8", i + 1)); + } + + // Traverse omnibox results. + for (int i = 0; i < 3; ++i) { + sm_.Call([this]() { SendKeyPress(ui::VKEY_DOWN); }); + sm_.ExpectSpeech(base::StringPrintf("item %d", i)); + sm_.ExpectSpeech(base::StringPrintf("List item %d of 8", i + 6)); + } + + // Cycle focus to the close button. + sm_.Call([this]() { SendKeyPress(ui::VKEY_DOWN); }); + sm_.ExpectSpeech("Clear searchbox text"); + + // Go back to the last result. + sm_.Call([this]() { SendKeyPress(ui::VKEY_UP); }); + sm_.ExpectSpeech("item 2"); + + // Update the query, to initiate new search. + sm_.Call([this]() { + apps_provider_->set_best_match_count(0); + apps_provider_->set_count(3); + web_provider_->set_count(2); + SendKeyPress(ui::VKEY_A); + }); + + sm_.ExpectSpeech("A"); + sm_.ExpectSpeech("app 0"); + + // Verify traversal works after result change. + for (int i = 1; i < 3; ++i) { + sm_.Call([this]() { SendKeyPress(ui::VKEY_DOWN); }); + sm_.ExpectSpeech(base::StringPrintf("app %d", i)); + sm_.ExpectSpeech(base::StringPrintf("List item %d of 5", i + 1)); + } + + for (int i = 0; i < 2; ++i) { + sm_.Call([this]() { SendKeyPress(ui::VKEY_DOWN); }); + sm_.ExpectSpeech(base::StringPrintf("item %d", i)); + sm_.ExpectSpeech(base::StringPrintf("List item %d of 5", i + 4)); + } + + sm_.Replay(); +} + +IN_PROC_BROWSER_TEST_P(SpokenFeedbackAppListSearchProductivityLauncherTest, + VocalizeResultCountInClamshell) { + EnableChromeVox(); + + // Focus the shelf. This selects the launcher button. + sm_.Call([this]() { + EXPECT_TRUE(PerformAcceleratorAction(AcceleratorAction::FOCUS_SHELF)); + }); + sm_.ExpectSpeechPattern("Launcher"); + sm_.ExpectSpeech("Button"); + sm_.ExpectSpeech("Shelf"); + sm_.ExpectSpeech("Tool bar"); + + // Activate the launcher button. This opens bubble launcher. + sm_.Call([this]() { SendKeyPressWithSearch(ui::VKEY_SPACE); }); + sm_.ExpectSpeechPattern("Search your device,*"); + sm_.ExpectSpeech("Edit text"); + + sm_.Call([this]() { + apps_provider_->set_best_match_count(2); + apps_provider_->set_count(3); + web_provider_->set_count(4); + SendKeyPress(ui::VKEY_G); + }); + + sm_.ExpectSpeech("G"); + sm_.ExpectSpeech("Displaying 8 results for g"); + + // Update the query, to initiate new search. + sm_.Call([this]() { + apps_provider_->set_best_match_count(0); + apps_provider_->set_count(3); + web_provider_->set_count(2); + SendKeyPress(ui::VKEY_A); + }); + + sm_.ExpectSpeech("A"); + sm_.ExpectSpeech("Displaying 5 results for ga"); + + sm_.Replay(); +} + +IN_PROC_BROWSER_TEST_P(SpokenFeedbackAppListSearchProductivityLauncherTest, + LauncherSearchInTablet) { + ShellTestApi().SetTabletModeEnabledForTest(true); + EnableChromeVox(); + + // Minimize the test window to transition to tablet mode home screen. + sm_.Call([this]() { browser()->window()->Minimize(); }); + + sm_.ExpectSpeechPattern("Search your device,*"); + sm_.ExpectSpeech("Edit text"); + + sm_.Call([this]() { + apps_provider_->set_best_match_count(2); + apps_provider_->set_count(3); + web_provider_->set_count(4); + SendKeyPress(ui::VKEY_G); + }); + + sm_.ExpectSpeech("G"); + sm_.ExpectSpeech("app 0"); + + // Traverse best match results; + for (int i = 1; i < 2; ++i) { + sm_.Call([this]() { SendKeyPress(ui::VKEY_DOWN); }); + sm_.ExpectSpeech(base::StringPrintf("app %d", i)); + sm_.ExpectSpeech(base::StringPrintf("List item %d of 8", i + 1)); + } + + // Traverse non-best-match app results. + for (int i = 2; i < 5; ++i) { + sm_.Call([this]() { SendKeyPress(ui::VKEY_DOWN); }); + sm_.ExpectSpeech(base::StringPrintf("app %d", i)); + sm_.ExpectSpeech(base::StringPrintf("List item %d of 8", i + 1)); + } + + // Traverse omnibox results. + for (int i = 0; i < 3; ++i) { + sm_.Call([this]() { SendKeyPress(ui::VKEY_DOWN); }); + sm_.ExpectSpeech(base::StringPrintf("item %d", i)); + sm_.ExpectSpeech(base::StringPrintf("List item %d of 8", i + 6)); + } + + // Cycle focus to the close button. + sm_.Call([this]() { SendKeyPress(ui::VKEY_DOWN); }); + sm_.ExpectSpeech("Clear searchbox text"); + + // Go back to the last result. + sm_.Call([this]() { SendKeyPress(ui::VKEY_UP); }); + sm_.ExpectSpeech("item 2"); + + // Update the query, to initiate new search. + sm_.Call([this]() { + apps_provider_->set_best_match_count(0); + apps_provider_->set_count(3); + web_provider_->set_count(2); + SendKeyPress(ui::VKEY_A); + }); + + sm_.ExpectSpeech("A"); + sm_.ExpectSpeech("app 0"); + + // Verify traversal works after result change. + for (int i = 1; i < 3; ++i) { + sm_.Call([this]() { SendKeyPress(ui::VKEY_DOWN); }); + sm_.ExpectSpeech(base::StringPrintf("app %d", i)); + sm_.ExpectSpeech(base::StringPrintf("List item %d of 5", i + 1)); + } + + for (int i = 0; i < 2; ++i) { + sm_.Call([this]() { SendKeyPress(ui::VKEY_DOWN); }); + sm_.ExpectSpeech(base::StringPrintf("item %d", i)); + sm_.ExpectSpeech(base::StringPrintf("List item %d of 5", i + 4)); + } + + sm_.Replay(); +} + +IN_PROC_BROWSER_TEST_P(SpokenFeedbackAppListSearchProductivityLauncherTest, + VocalizeResultCountInTablet) { + ShellTestApi().SetTabletModeEnabledForTest(true); + EnableChromeVox(); + + // Minimize the test window to transition to tablet mode home screen. + sm_.Call([this]() { browser()->window()->Minimize(); }); + + sm_.ExpectSpeechPattern("Search your device,*"); + sm_.ExpectSpeech("Edit text"); + + sm_.Call([this]() { + apps_provider_->set_best_match_count(2); + apps_provider_->set_count(3); + web_provider_->set_count(4); + SendKeyPress(ui::VKEY_G); + }); + + sm_.ExpectSpeech("G"); + sm_.ExpectSpeech("Displaying 8 results for g"); + + // Update the query, to initiate new search. + sm_.Call([this]() { + apps_provider_->set_best_match_count(0); + apps_provider_->set_count(3); + web_provider_->set_count(2); + SendKeyPress(ui::VKEY_A); + }); + + sm_.ExpectSpeech("A"); + sm_.ExpectSpeech("Displaying 5 results for ga"); + + sm_.Replay(); +} + } // namespace ash
diff --git a/chrome/browser/ash/arc/accessibility/arc_accessibility_helper_bridge.cc b/chrome/browser/ash/arc/accessibility/arc_accessibility_helper_bridge.cc index a955e56..31c3d2b 100644 --- a/chrome/browser/ash/arc/accessibility/arc_accessibility_helper_bridge.cc +++ b/chrome/browser/ash/arc/accessibility/arc_accessibility_helper_bridge.cc
@@ -244,8 +244,10 @@ ArcAccessibilityHelperBridge::~ArcAccessibilityHelperBridge() = default; -void ArcAccessibilityHelperBridge::SetNativeChromeVoxArcSupport(bool enabled) { - tree_tracker_.SetNativeChromeVoxArcSupport(enabled); +void ArcAccessibilityHelperBridge::SetNativeChromeVoxArcSupport( + bool enabled, + SetNativeChromeVoxCallback callback) { + tree_tracker_.SetNativeChromeVoxArcSupport(enabled, std::move(callback)); } bool ArcAccessibilityHelperBridge::EnableTree(const ui::AXTreeID& tree_id) {
diff --git a/chrome/browser/ash/arc/accessibility/arc_accessibility_helper_bridge.h b/chrome/browser/ash/arc/accessibility/arc_accessibility_helper_bridge.h index 669863f..ac36233 100644 --- a/chrome/browser/ash/arc/accessibility/arc_accessibility_helper_bridge.h +++ b/chrome/browser/ash/arc/accessibility/arc_accessibility_helper_bridge.h
@@ -72,7 +72,8 @@ ~ArcAccessibilityHelperBridge() override; // Sets ChromeVox or TalkBack active for the current task. - void SetNativeChromeVoxArcSupport(bool enabled); + void SetNativeChromeVoxArcSupport(bool enabled, + SetNativeChromeVoxCallback callback); // Request Android to send the entire tree with the tree id. Returns true if // the specified tree is an ARC tree and a request was sent.
diff --git a/chrome/browser/ash/arc/accessibility/arc_accessibility_helper_bridge_browsertest.cc b/chrome/browser/ash/arc/accessibility/arc_accessibility_helper_bridge_browsertest.cc index 502fb12..2cbb3d0 100644 --- a/chrome/browser/ash/arc/accessibility/arc_accessibility_helper_bridge_browsertest.cc +++ b/chrome/browser/ash/arc/accessibility/arc_accessibility_helper_bridge_browsertest.cc
@@ -193,7 +193,11 @@ // Enable TalkBack. Touch exploration pass through of test_window_1 // (current active window) would become true. - bridge->SetNativeChromeVoxArcSupport(false); + bridge->SetNativeChromeVoxArcSupport( + false, + base::BindOnce( + [](extensions::api::accessibility_private::SetNativeChromeVoxResponse + response) {})); EXPECT_TRUE( test_window_1.shell_surface->GetWidget()->GetNativeWindow()->GetProperty(
diff --git a/chrome/browser/ash/arc/accessibility/arc_accessibility_tree_tracker.cc b/chrome/browser/ash/arc/accessibility/arc_accessibility_tree_tracker.cc index ab720077..1614685 100644 --- a/chrome/browser/ash/arc/accessibility/arc_accessibility_tree_tracker.cc +++ b/chrome/browser/ash/arc/accessibility/arc_accessibility_tree_tracker.cc
@@ -95,6 +95,27 @@ } } +extensions::api::accessibility_private::SetNativeChromeVoxResponse +FromMojomResponseToAutomationResponse( + arc::mojom::SetNativeChromeVoxResponse response) { + switch (response) { + case arc::mojom::SetNativeChromeVoxResponse::SUCCESS: + return extensions::api::accessibility_private:: + SetNativeChromeVoxResponse::SET_NATIVE_CHROME_VOX_RESPONSE_SUCCESS; + case arc::mojom::SetNativeChromeVoxResponse::TALKBACK_NOT_INSTALLED: + return extensions::api::accessibility_private:: + SetNativeChromeVoxResponse:: + SET_NATIVE_CHROME_VOX_RESPONSE_TALKBACKNOTINSTALLED; + case arc::mojom::SetNativeChromeVoxResponse::WINDOW_NOT_FOUND: + return extensions::api::accessibility_private:: + SetNativeChromeVoxResponse:: + SET_NATIVE_CHROME_VOX_RESPONSE_WINDOWNOTFOUND; + case arc::mojom::SetNativeChromeVoxResponse::FAILURE: + return extensions::api::accessibility_private:: + SetNativeChromeVoxResponse::SET_NATIVE_CHROME_VOX_RESPONSE_FAILURE; + } +} + } // namespace class ArcAccessibilityTreeTracker::FocusChangeObserver @@ -473,13 +494,23 @@ // OnSetNativeChromeVoxArcSupportProcessed()? } -void ArcAccessibilityTreeTracker::SetNativeChromeVoxArcSupport(bool enabled) { +void ArcAccessibilityTreeTracker::SetNativeChromeVoxArcSupport( + bool enabled, + SetNativeChromeVoxCallback callback) { aura::Window* window = GetFocusedArcWindow(); - if (!window) + if (!window) { + std::move(callback).Run( + extensions::api::accessibility_private::SetNativeChromeVoxResponse:: + SET_NATIVE_CHROME_VOX_RESPONSE_FAILURE); return; + } - if (!arc::GetWindowTaskId(window).has_value()) + if (!arc::GetWindowTaskId(window).has_value()) { + std::move(callback).Run( + extensions::api::accessibility_private::SetNativeChromeVoxResponse:: + SET_NATIVE_CHROME_VOX_RESPONSE_FAILURE); return; + } std::unique_ptr<aura::WindowTracker> window_tracker = std::make_unique<aura::WindowTracker>(); @@ -489,15 +520,21 @@ enabled, base::BindOnce( &ArcAccessibilityTreeTracker::OnSetNativeChromeVoxArcSupportProcessed, - base::Unretained(this), std::move(window_tracker), enabled)); + base::Unretained(this), std::move(window_tracker), enabled, + std::move(callback))); } void ArcAccessibilityTreeTracker::OnSetNativeChromeVoxArcSupportProcessed( std::unique_ptr<aura::WindowTracker> window_tracker, bool enabled, - bool processed) { - if (!processed || window_tracker->windows().size() != 1) + SetNativeChromeVoxCallback callback, + arc::mojom::SetNativeChromeVoxResponse response) { + std::move(callback).Run(FromMojomResponseToAutomationResponse(response)); + + if (response != arc::mojom::SetNativeChromeVoxResponse::SUCCESS || + window_tracker->windows().size() != 1) { return; + } aura::Window* window = window_tracker->Pop(); auto task_id = arc::GetWindowTaskId(window);
diff --git a/chrome/browser/ash/arc/accessibility/arc_accessibility_tree_tracker.h b/chrome/browser/ash/arc/accessibility/arc_accessibility_tree_tracker.h index 54311e5..60110eae 100644 --- a/chrome/browser/ash/arc/accessibility/arc_accessibility_tree_tracker.h +++ b/chrome/browser/ash/arc/accessibility/arc_accessibility_tree_tracker.h
@@ -15,6 +15,7 @@ #include "chrome/browser/ash/arc/accessibility/accessibility_helper_instance_remote_proxy.h" #include "chrome/browser/ash/arc/accessibility/ax_tree_source_arc.h" #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h" +#include "chrome/common/extensions/api/accessibility_private.h" #include "ui/aura/client/focus_change_observer.h" #include "ui/aura/env.h" #include "ui/aura/env_observer.h" @@ -31,6 +32,9 @@ namespace arc { +using SetNativeChromeVoxCallback = base::OnceCallback<void( + extensions::api::accessibility_private::SetNativeChromeVoxResponse)>; + // ArcAccessibilityTreeTracker is responsible for mapping accessibility tree // from android to exo window / surfaces. class ArcAccessibilityTreeTracker : public aura::EnvObserver { @@ -90,13 +94,15 @@ void OnToggleNativeChromeVoxArcSupport(bool enabled); // To be called from chrome automation private API. - void SetNativeChromeVoxArcSupport(bool enabled); + void SetNativeChromeVoxArcSupport(bool enabled, + SetNativeChromeVoxCallback callback); // Receives the result of setting native ChromeVox ARC support. void OnSetNativeChromeVoxArcSupportProcessed( std::unique_ptr<aura::WindowTracker> window_tracker, bool enabled, - bool processed); + SetNativeChromeVoxCallback callback, + arc::mojom::SetNativeChromeVoxResponse response); // Returns a tree source for the specified AXTreeID. AXTreeSourceArc* GetFromTreeId(const ui::AXTreeID& tree_id) const;
diff --git a/chrome/browser/ash/arc/bluetooth/arc_bluetooth_bridge.cc b/chrome/browser/ash/arc/bluetooth/arc_bluetooth_bridge.cc index b245265..ef54437 100644 --- a/chrome/browser/ash/arc/bluetooth/arc_bluetooth_bridge.cc +++ b/chrome/browser/ash/arc/bluetooth/arc_bluetooth_bridge.cc
@@ -1944,26 +1944,6 @@ } } -void ArcBluetoothBridge::OpenBluetoothSocketDeprecated( - OpenBluetoothSocketDeprecatedCallback callback) { - base::ScopedFD sock(socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)); - if (!sock.is_valid()) { - LOG(ERROR) << "Failed to open socket."; - std::move(callback).Run(mojo::ScopedHandle()); - return; - } - - mojo::ScopedHandle handle = - mojo::WrapPlatformHandle(mojo::PlatformHandle(std::move(sock))); - if (!handle.is_valid()) { - LOG(ERROR) << "Failed to wrap socket handle. Closing"; - std::move(callback).Run(mojo::ScopedHandle()); - return; - } - - std::move(callback).Run(std::move(handle)); -} - bool ArcBluetoothBridge::IsGattServerAttributeHandleAvailable(int need) { return gatt_server_attribute_next_handle_ + need <= kMaxGattAttributeHandle; } @@ -3062,40 +3042,6 @@ } // namespace -void ArcBluetoothBridge::RfcommListenDeprecated( - int32_t channel, - int32_t optval, - RfcommListenDeprecatedCallback callback) { - if (channel != kAutoSockPort && - !IsValidPort(mojom::BluetoothSocketType::TYPE_RFCOMM, channel)) { - LOG(ERROR) << "Invalid channel number"; - std::move(callback).Run( - mojom::BluetoothStatus::FAIL, /*channel=*/0, - mojo::PendingReceiver<mojom::RfcommListeningSocketClient>()); - return; - } - - uint16_t listen_channel = static_cast<uint16_t>(channel); - auto sock_wrapper = CreateBluetoothListenSocket( - mojom::BluetoothSocketType::TYPE_RFCOMM, optval, &listen_channel); - if (!sock_wrapper) { - std::move(callback).Run( - mojom::BluetoothStatus::FAIL, /*channel=*/0, - mojo::PendingReceiver<mojom::RfcommListeningSocketClient>()); - return; - } - - sock_wrapper->created_by_deprecated_method = true; - std::move(callback).Run( - mojom::BluetoothStatus::SUCCESS, listen_channel, - sock_wrapper->deprecated_remote.BindNewPipeAndPassReceiver()); - - sock_wrapper->deprecated_remote.set_disconnect_handler( - base::BindOnce(&ArcBluetoothBridge::CloseBluetoothListeningSocket, - weak_factory_.GetWeakPtr(), sock_wrapper.get())); - listening_sockets_.insert(std::move(sock_wrapper)); -} - void ArcBluetoothBridge::BluetoothSocketListen( mojom::BluetoothSocketType sock_type, mojom::BluetoothSocketFlagsPtr sock_flags, @@ -3142,37 +3088,6 @@ listening_sockets_.erase(itr); } -void ArcBluetoothBridge::RfcommConnectDeprecated( - mojom::BluetoothAddressPtr remote_addr, - int32_t channel, - int32_t optval, - RfcommConnectDeprecatedCallback callback) { - if (!IsValidPort(mojom::BluetoothSocketType::TYPE_RFCOMM, channel)) { - LOG(ERROR) << "Invalid channel number " << channel; - std::move(callback).Run(mojom::BluetoothStatus::FAIL, - mojom::RfcommConnectingSocketClientRequest()); - return; - } - - auto sock_wrapper = CreateBluetoothConnectSocket( - mojom::BluetoothSocketType::TYPE_RFCOMM, optval, std::move(remote_addr), - static_cast<uint16_t>(channel)); - if (!sock_wrapper) { - std::move(callback).Run(mojom::BluetoothStatus::FAIL, - mojom::RfcommConnectingSocketClientRequest()); - return; - } - - sock_wrapper->created_by_deprecated_method = true; - std::move(callback).Run( - mojom::BluetoothStatus::SUCCESS, - sock_wrapper->deprecated_remote.BindNewPipeAndPassReceiver()); - sock_wrapper->deprecated_remote.set_disconnect_handler( - base::BindOnce(&ArcBluetoothBridge::CloseBluetoothConnectingSocket, - weak_factory_.GetWeakPtr(), sock_wrapper.get())); - connecting_sockets_.insert(std::move(sock_wrapper)); -} - void ArcBluetoothBridge::BluetoothSocketConnect( mojom::BluetoothSocketType sock_type, mojom::BluetoothSocketFlagsPtr sock_flags,
diff --git a/chrome/browser/ash/arc/bluetooth/arc_bluetooth_bridge.h b/chrome/browser/ash/arc/bluetooth/arc_bluetooth_bridge.h index ece137df..5e629a7 100644 --- a/chrome/browser/ash/arc/bluetooth/arc_bluetooth_bridge.h +++ b/chrome/browser/ash/arc/bluetooth/arc_bluetooth_bridge.h
@@ -270,9 +270,6 @@ void ReadRemoteRssi(mojom::BluetoothAddressPtr remote_addr, ReadRemoteRssiCallback callback) override; - void OpenBluetoothSocketDeprecated( - OpenBluetoothSocketDeprecatedCallback callback) override; - // Bluetooth Mojo host interface - Bluetooth Gatt Server functions // Android counterpart link: // https://source.android.com/devices/halref/bt__gatt__server_8h.html @@ -319,16 +316,6 @@ void RemoveSdpRecord(uint32_t service_handle, RemoveSdpRecordCallback callback) override; - // Bluetooth Mojo host interface - Bluetooth RFCOMM functions - void RfcommListenDeprecated(int32_t channel, - int32_t optval, - RfcommListenDeprecatedCallback callback) override; - void RfcommConnectDeprecated( - mojom::BluetoothAddressPtr remote_addr, - int32_t channel, - int32_t optval, - RfcommConnectDeprecatedCallback callback) override; - // Bluetooth Mojo host interface - Bluetooth socket functions void BluetoothSocketListen(mojom::BluetoothSocketType sock_type, mojom::BluetoothSocketFlagsPtr sock_flags,
diff --git a/chrome/browser/ash/arc/input_method_manager/arc_input_method_manager_service_unittest.cc b/chrome/browser/ash/arc/input_method_manager/arc_input_method_manager_service_unittest.cc index 5cc008f..cd8dbc2 100644 --- a/chrome/browser/ash/arc/input_method_manager/arc_input_method_manager_service_unittest.cc +++ b/chrome/browser/ash/arc/input_method_manager/arc_input_method_manager_service_unittest.cc
@@ -304,7 +304,6 @@ tablet_mode_controller_.reset(); profile_.reset(); im::InputMethodManager::Shutdown(); - ui::IMEBridge::Shutdown(); } private:
diff --git a/chrome/browser/ash/arc/input_method_manager/input_connection_impl_unittest.cc b/chrome/browser/ash/arc/input_method_manager/input_connection_impl_unittest.cc index 0667f20..9010231 100644 --- a/chrome/browser/ash/arc/input_method_manager/input_connection_impl_unittest.cc +++ b/chrome/browser/ash/arc/input_method_manager/input_connection_impl_unittest.cc
@@ -216,7 +216,6 @@ engine_.reset(); bridge_.reset(); ash::input_method::InputMethodManager::Shutdown(); - ui::IMEBridge::Shutdown(); } private:
diff --git a/chrome/browser/ash/arc/print_spooler/arc_print_spooler_bridge.cc b/chrome/browser/ash/arc/print_spooler/arc_print_spooler_bridge.cc index 9b93819..13be0d7 100644 --- a/chrome/browser/ash/arc/print_spooler/arc_print_spooler_bridge.cc +++ b/chrome/browser/ash/arc/print_spooler/arc_print_spooler_bridge.cc
@@ -68,17 +68,6 @@ arc_bridge_service_->print_spooler()->SetHost(nullptr); } -void ArcPrintSpoolerBridge::StartPrintInCustomTabDeprecated( - mojo::ScopedHandle scoped_handle, - int32_t task_id, - int32_t surface_id, - int32_t top_margin, - mojo::PendingRemote<mojom::PrintSessionInstance> instance, - StartPrintInCustomTabCallback callback) { - StartPrintInCustomTab(std::move(scoped_handle), task_id, std::move(instance), - std::move(callback)); -} - void ArcPrintSpoolerBridge::StartPrintInCustomTab( mojo::ScopedHandle scoped_handle, int32_t task_id,
diff --git a/chrome/browser/ash/arc/print_spooler/arc_print_spooler_bridge.h b/chrome/browser/ash/arc/print_spooler/arc_print_spooler_bridge.h index c41529a9a..f83f5a3 100644 --- a/chrome/browser/ash/arc/print_spooler/arc_print_spooler_bridge.h +++ b/chrome/browser/ash/arc/print_spooler/arc_print_spooler_bridge.h
@@ -41,13 +41,6 @@ ~ArcPrintSpoolerBridge() override; // mojom::PrintSpoolerHost: - void StartPrintInCustomTabDeprecated( - mojo::ScopedHandle scoped_handle, - int32_t task_id, - int32_t surface_id, - int32_t top_margin, - mojo::PendingRemote<mojom::PrintSessionInstance> instance, - StartPrintInCustomTabCallback callback) override; void StartPrintInCustomTab( mojo::ScopedHandle scoped_handle, int32_t task_id,
diff --git a/chrome/browser/ash/arc/tts/arc_tts_service.cc b/chrome/browser/ash/arc/tts/arc_tts_service.cc index 3ac94e8..070ad142 100644 --- a/chrome/browser/ash/arc/tts/arc_tts_service.cc +++ b/chrome/browser/ash/arc/tts/arc_tts_service.cc
@@ -80,13 +80,6 @@ arc_bridge_service_->tts()->SetHost(nullptr); } -void ArcTtsService::OnTtsEventDeprecated(uint32_t id, - mojom::TtsEventType event_type, - uint32_t char_index, - const std::string& error_msg) { - OnTtsEvent(id, event_type, char_index, -1 /* length */, error_msg); -} - void ArcTtsService::OnTtsEvent(uint32_t id, mojom::TtsEventType event_type, uint32_t char_index,
diff --git a/chrome/browser/ash/arc/tts/arc_tts_service.h b/chrome/browser/ash/arc/tts/arc_tts_service.h index bbec1e1..72bdec5 100644 --- a/chrome/browser/ash/arc/tts/arc_tts_service.h +++ b/chrome/browser/ash/arc/tts/arc_tts_service.h
@@ -39,10 +39,6 @@ ~ArcTtsService() override; // mojom::TtsHost overrides: - void OnTtsEventDeprecated(uint32_t id, - mojom::TtsEventType event_type, - uint32_t char_index, - const std::string& error_msg) override; void OnTtsEvent(uint32_t id, mojom::TtsEventType event_type, uint32_t char_index,
diff --git a/chrome/browser/ash/chrome_browser_main_parts_ash.cc b/chrome/browser/ash/chrome_browser_main_parts_ash.cc index bad96f0..4ea240e 100644 --- a/chrome/browser/ash/chrome_browser_main_parts_ash.cc +++ b/chrome/browser/ash/chrome_browser_main_parts_ash.cc
@@ -172,7 +172,6 @@ #include "chrome/browser/task_manager/task_manager_interface.h" #include "chrome/browser/ui/ash/assistant/assistant_browser_delegate_impl.h" #include "chrome/browser/ui/ash/assistant/assistant_state_client.h" -#include "chrome/browser/ui/ash/fwupd_download_client_impl.h" #include "chrome/browser/ui/ash/image_downloader_impl.h" #include "chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.h" #include "chrome/browser/ui/ash/quick_answers/quick_answers_controller_impl.h" @@ -1247,7 +1246,6 @@ if (features::IsFirmwareUpdaterAppEnabled()) { firmware_update_manager_ = std::make_unique<FirmwareUpdateManager>(); - fwupd_download_client_ = std::make_unique<FwupdDownloadClientImpl>(); } if (features::IsPciguardUiEnabled()) {
diff --git a/chrome/browser/ash/chrome_browser_main_parts_ash.h b/chrome/browser/ash/chrome_browser_main_parts_ash.h index 643b240..7c0d28f 100644 --- a/chrome/browser/ash/chrome_browser_main_parts_ash.h +++ b/chrome/browser/ash/chrome_browser_main_parts_ash.h
@@ -73,7 +73,6 @@ class DemoModeResourcesRemover; class EventRewriterDelegateImpl; class FirmwareUpdateManager; -class FwupdDownloadClientImpl; class GnubbyNotification; class IdleActionWarningObserver; class LoginScreenExtensionsLifetimeManager; @@ -230,8 +229,6 @@ std::unique_ptr<BulkPrintersCalculatorFactory> bulk_printers_calculator_factory_; - std::unique_ptr<FwupdDownloadClientImpl> fwupd_download_client_; - std::unique_ptr<SessionTerminationManager> session_termination_manager_; // Set when PreProfileInit() is called. If PreMainMessageLoopRun() exits
diff --git a/chrome/browser/ash/input_method/assistive_window_controller_unittest.cc b/chrome/browser/ash/input_method/assistive_window_controller_unittest.cc index 58586a6..02c92cb 100644 --- a/chrome/browser/ash/input_method/assistive_window_controller_unittest.cc +++ b/chrome/browser/ash/input_method/assistive_window_controller_unittest.cc
@@ -53,7 +53,7 @@ class AssistiveWindowControllerTest : public ChromeAshTestBase { protected: AssistiveWindowControllerTest() = default; - ~AssistiveWindowControllerTest() override { ui::IMEBridge::Shutdown(); } + ~AssistiveWindowControllerTest() override = default; void SetUp() override { ChromeAshTestBase::SetUp();
diff --git a/chrome/browser/ash/input_method/input_method_configuration.cc b/chrome/browser/ash/input_method/input_method_configuration.cc index 3c7e111..660b12d 100644 --- a/chrome/browser/ash/input_method/input_method_configuration.cc +++ b/chrome/browser/ash/input_method/input_method_configuration.cc
@@ -6,14 +6,11 @@ #include <memory> -#include "base/bind.h" -#include "base/logging.h" #include "chrome/browser/ash/input_method/accessibility.h" #include "chrome/browser/ash/input_method/component_extension_ime_manager_delegate_impl.h" #include "chrome/browser/ash/input_method/input_method_delegate_impl.h" #include "chrome/browser/ash/input_method/input_method_manager_impl.h" #include "chrome/browser/ash/input_method/input_method_persistence.h" -#include "ui/base/ime/ash/ime_bridge.h" namespace ash { namespace input_method { @@ -21,63 +18,28 @@ namespace { bool g_disable_extension_loading = false; - -class InputMethodConfiguration { - public: - InputMethodConfiguration() = default; - virtual ~InputMethodConfiguration() = default; - - void Initialize() { - auto* impl = new InputMethodManagerImpl( - std::make_unique<InputMethodDelegateImpl>(), - std::make_unique<ComponentExtensionIMEManagerDelegateImpl>(), - !g_disable_extension_loading); - InputMethodManager::Initialize(impl); - - DCHECK(InputMethodManager::Get()); - - accessibility_ = std::make_unique<Accessibility>(impl); - input_method_persistence_ = std::make_unique<InputMethodPersistence>(impl); - - DVLOG(1) << "InputMethodManager initialized"; - } - - void InitializeForTesting(InputMethodManager* mock_manager) { - InputMethodManager::Initialize(mock_manager); - DVLOG(1) << "InputMethodManager for testing initialized"; - } - - void Shutdown() { - accessibility_.reset(); - - input_method_persistence_.reset(); - - InputMethodManager::Shutdown(); - - ui::IMEBridge::Shutdown(); - - DVLOG(1) << "InputMethodManager shutdown"; - } - - private: - std::unique_ptr<Accessibility> accessibility_; - std::unique_ptr<InputMethodPersistence> input_method_persistence_; -}; - -InputMethodConfiguration* g_input_method_configuration = NULL; +Accessibility* g_accessibility = nullptr; +InputMethodPersistence* g_input_method_persistence = nullptr; } // namespace void Initialize() { - if (!g_input_method_configuration) - g_input_method_configuration = new InputMethodConfiguration(); - g_input_method_configuration->Initialize(); + auto* impl = new InputMethodManagerImpl( + std::make_unique<InputMethodDelegateImpl>(), + std::make_unique<ComponentExtensionIMEManagerDelegateImpl>(), + !g_disable_extension_loading); + InputMethodManager::Initialize(impl); + DCHECK(InputMethodManager::Get()); + + delete g_accessibility; + g_accessibility = new Accessibility(impl); + + delete g_input_method_persistence; + g_input_method_persistence = new InputMethodPersistence(impl); } void InitializeForTesting(InputMethodManager* mock_manager) { - if (!g_input_method_configuration) - g_input_method_configuration = new InputMethodConfiguration(); - g_input_method_configuration->InitializeForTesting(mock_manager); + InputMethodManager::Initialize(mock_manager); } void DisableExtensionLoading() { @@ -85,12 +47,13 @@ } void Shutdown() { - if (!g_input_method_configuration) - return; + delete g_accessibility; + g_accessibility = nullptr; - g_input_method_configuration->Shutdown(); - delete g_input_method_configuration; - g_input_method_configuration = NULL; + delete g_input_method_persistence; + g_input_method_persistence = nullptr; + + InputMethodManager::Shutdown(); } } // namespace input_method
diff --git a/chrome/browser/ash/input_method/input_method_configuration.h b/chrome/browser/ash/input_method/input_method_configuration.h index a078ae0..d8dcae1 100644 --- a/chrome/browser/ash/input_method/input_method_configuration.h +++ b/chrome/browser/ash/input_method/input_method_configuration.h
@@ -12,22 +12,17 @@ namespace ash { namespace input_method { -// Initializes the InputMethodManager. Must be called before any calls to -// GetInstance(). We explicitly initialize and shut down the global instance, -// rather than making it a Singleton, to ensure clean startup and shutdown. void Initialize(); -// Similar to Initialize(), but can inject an alternative -// InputMethodManager such as MockInputMethodManager for testing. -// The injected object will be owned by the internal pointer and deleted -// by Shutdown(). +// Similar to Initialize(), but can inject an alternative InputMethodManager +// such as MockInputMethodManager for testing. The injected object will be +// owned by the internal pointer and deleted by Shutdown(). // TODO(nona): Remove this and use InputMethodManager::Initialize instead. void InitializeForTesting(InputMethodManager* mock_manager); // Disables the IME extension loading (e.g. for browser tests). void DisableExtensionLoading(); -// Destroys the global InputMethodManager instance. void Shutdown(); } // namespace input_method
diff --git a/chrome/browser/ash/input_method/input_method_manager_impl_unittest.cc b/chrome/browser/ash/input_method/input_method_manager_impl_unittest.cc index 447ddbd8..86e1025 100644 --- a/chrome/browser/ash/input_method/input_method_manager_impl_unittest.cc +++ b/chrome/browser/ash/input_method/input_method_manager_impl_unittest.cc
@@ -212,7 +212,6 @@ chrome_keyboard_controller_client_test_helper_.reset(); BrowserWithTestWindowTest::TearDown(); - ui::ShutdownInputMethodForTesting(); candidate_window_controller_ = nullptr; keyboard_ = nullptr;
diff --git a/chrome/browser/ash/policy/core/user_cloud_policy_manager_ash.cc b/chrome/browser/ash/policy/core/user_cloud_policy_manager_ash.cc index d43b0aa2..fe30e2b7 100644 --- a/chrome/browser/ash/policy/core/user_cloud_policy_manager_ash.cc +++ b/chrome/browser/ash/policy/core/user_cloud_policy_manager_ash.cc
@@ -276,7 +276,7 @@ app_install_event_log_uploader_ = std::make_unique<ArcAppInstallEventLogUploader>(client(), profile_); extension_install_event_log_uploader_ = - std::make_unique<ExtensionInstallEventLogUploader>(profile_); + ExtensionInstallEventLogUploader::Create(profile_); } void UserCloudPolicyManagerAsh::OnAccessTokenAvailable(
diff --git a/chrome/browser/ash/policy/reporting/extension_install_event_log_manager_unittest.cc b/chrome/browser/ash/policy/reporting/extension_install_event_log_manager_unittest.cc index 48705db6..7f5f80a 100644 --- a/chrome/browser/ash/policy/reporting/extension_install_event_log_manager_unittest.cc +++ b/chrome/browser/ash/policy/reporting/extension_install_event_log_manager_unittest.cc
@@ -6,6 +6,7 @@ #include <iterator> #include <map> +#include <memory> #include <vector> #include "ash/components/arc/arc_prefs.h" @@ -18,10 +19,12 @@ #include "base/test/scoped_mock_time_message_loop_task_runner.h" #include "base/test/test_mock_time_task_runner.h" #include "base/test/test_simple_task_runner.h" +#include "base/threading/sequenced_task_runner_handle.h" #include "base/time/tick_clock.h" #include "base/time/time.h" #include "base/values.h" #include "chrome/browser/ash/policy/reporting/extension_install_event_log.h" +#include "chrome/browser/ash/policy/reporting/extension_install_event_log_uploader.h" #include "chrome/browser/ash/policy/reporting/install_event_log_util.h" #include "chrome/browser/profiles/reporting_util.h" #include "chrome/test/base/testing_profile.h" @@ -154,8 +157,7 @@ class ExtensionInstallEventLogManagerTest : public testing::Test { protected: ExtensionInstallEventLogManagerTest() - : uploader_(/*profile=*/nullptr), - log_task_runner_(log_task_runner_wrapper_.test_task_runner()), + : log_task_runner_(log_task_runner_wrapper_.test_task_runner()), log_file_path_(profile_.GetPath().Append(kLogFileName)), extension_ids_{std::begin(kExtensionIds), std::end(kExtensionIds)}, events_value_(base::Value::Type::DICTIONARY), @@ -165,9 +167,13 @@ // testing::Test: void SetUp() override { - auto mock_report_queue = std::make_unique<reporting::MockReportQueue>(); + auto mock_report_queue = std::unique_ptr<::reporting::MockReportQueue, + base::OnTaskRunnerDeleter>( + new ::reporting::MockReportQueue(), + base::OnTaskRunnerDeleter(base::SequencedTaskRunnerHandle::Get())); mock_report_queue_ = mock_report_queue.get(); - uploader_.SetReportQueue(std::move(mock_report_queue)); + uploader_ = ExtensionInstallEventLogUploader::CreateForTest( + /*profile=*/nullptr, std::move(mock_report_queue)); event_.set_timestamp(0); event_.set_event_type(em::ExtensionInstallReportLogEvent::SUCCESS); @@ -188,7 +194,7 @@ void CreateManager() { manager_ = std::make_unique<ExtensionInstallEventLogManager>( - &log_task_runner_wrapper_, &uploader_, &profile_); + &log_task_runner_wrapper_, uploader_.get(), &profile_); FlushNonDelayedTasks(); } @@ -308,7 +314,7 @@ disable_purge_for_testing_; TestingProfile profile_; reporting::MockReportQueue* mock_report_queue_; - ExtensionInstallEventLogUploader uploader_; + std::unique_ptr<ExtensionInstallEventLogUploader> uploader_; std::unique_ptr<base::ScopedMockTimeMessageLoopTaskRunner> scoped_main_task_runner_;
diff --git a/chrome/browser/ash/policy/reporting/extension_install_event_log_uploader.cc b/chrome/browser/ash/policy/reporting/extension_install_event_log_uploader.cc index d315591..6b96eeea 100644 --- a/chrome/browser/ash/policy/reporting/extension_install_event_log_uploader.cc +++ b/chrome/browser/ash/policy/reporting/extension_install_event_log_uploader.cc
@@ -4,107 +4,47 @@ #include "chrome/browser/ash/policy/reporting/extension_install_event_log_uploader.h" -#include <atomic> +#include <memory> +#include <utility> #include "ash/constants/ash_switches.h" #include "base/bind.h" #include "base/command_line.h" -#include "base/task/thread_pool.h" -#include "base/threading/thread_task_runner_handle.h" -#include "base/time/time.h" +#include "base/memory/ptr_util.h" +#include "base/task/sequenced_task_runner.h" #include "base/values.h" #include "chrome/browser/ash/policy/reporting/install_event_log_util.h" -#include "chrome/browser/policy/dm_token_utils.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/reporting_util.h" #include "components/policy/core/common/cloud/realtime_reporting_job_configuration.h" #include "components/policy/proto/device_management_backend.pb.h" -#include "components/reporting/client/report_queue.h" -#include "components/reporting/client/report_queue_provider.h" -#include "content/public/browser/browser_task_traits.h" -#include "content/public/browser/browser_thread.h" +#include "components/reporting/client/report_queue_configuration.h" +#include "components/reporting/client/report_queue_factory.h" namespace em = enterprise_management; namespace policy { -namespace { - -ExtensionInstallEventLogUploader::GetReportQueueConfigCallback -CreateReportQueueConfigGetter(Profile* profile) { - return base::BindRepeating( - [](Profile* profile, - ExtensionInstallEventLogUploader::ReportQueueConfigResultCallback - complete_cb) { - auto task = base::BindOnce( - [](Profile* profile, - base::OnceCallback<void( - ::reporting::StatusOr<std::unique_ptr< - ::reporting::ReportQueueConfiguration>>)> complete_cb) { - auto dm_token = GetDMToken(profile); - if (!dm_token.is_valid()) { - std::move(complete_cb) - .Run(::reporting::Status( - ::reporting::error::INVALID_ARGUMENT, - "DMToken must be valid")); - return; - } - std::move(complete_cb) - .Run(::reporting::ReportQueueConfiguration::Create( - dm_token.value(), ::reporting::Destination::UPLOAD_EVENTS, - base::BindRepeating( - []() { return ::reporting::Status::StatusOK(); }))); - }, - profile, std::move(complete_cb)); - - content::GetUIThreadTaskRunner({})->PostTask(FROM_HERE, - std::move(task)); - }, - profile); -} - -} // namespace - -class ExtensionInstallEventLogUploader::ReportQueueBuilderLeaderTracker - : public base::RefCountedThreadSafe<ReportQueueBuilderLeaderTracker> { - public: - static scoped_refptr<ReportQueueBuilderLeaderTracker> Create() { - return base::WrapRefCounted(new ReportQueueBuilderLeaderTracker()); - } - - ::reporting::StatusOr<base::OnceCallback<void()>> RequestLeaderPromotion() { - bool expected = false; - if (!has_promoted_leader_.compare_exchange_strong(expected, true)) { - return ::reporting::Status(::reporting::error::RESOURCE_EXHAUSTED, - "Only one leader is allowed at a time."); - } - return base::BindOnce(&ReportQueueBuilderLeaderTracker::ReleaseLeader, - this); - } - - private: - friend class base::RefCountedThreadSafe<ReportQueueBuilderLeaderTracker>; - - ReportQueueBuilderLeaderTracker(); - virtual ~ReportQueueBuilderLeaderTracker(); - - void ReleaseLeader() { - bool expected = true; - DCHECK(has_promoted_leader_.compare_exchange_strong(expected, false)) - << "Leader wasn't set"; - } - - std::atomic<bool> has_promoted_leader_{false}; -}; ExtensionInstallEventLogUploader::Delegate::~Delegate() {} -ExtensionInstallEventLogUploader::ExtensionInstallEventLogUploader( - Profile* profile) - : InstallEventLogUploaderBase(profile), - leader_tracker_(ReportQueueBuilderLeaderTracker::Create()), - report_queue_builder_task_runner_( - base::ThreadPool::CreateSequencedTaskRunner({})), - get_report_queue_config_cb_(CreateReportQueueConfigGetter(profile)) {} +// static +std::unique_ptr<ExtensionInstallEventLogUploader> +ExtensionInstallEventLogUploader::Create(Profile* profile) { + return base::WrapUnique(new ExtensionInstallEventLogUploader( + profile, ::reporting::ReportQueueFactory::CreateSpeculativeReportQueue( + ::reporting::EventType::kUser, + ::reporting::Destination::UPLOAD_EVENTS))); +} + +// static +std::unique_ptr<ExtensionInstallEventLogUploader> +ExtensionInstallEventLogUploader::CreateForTest( + Profile* profile, + std::unique_ptr<::reporting::ReportQueue, base::OnTaskRunnerDeleter> + report_queue) { + return base::WrapUnique( + new ExtensionInstallEventLogUploader(profile, std::move(report_queue))); +} ExtensionInstallEventLogUploader::~ExtensionInstallEventLogUploader() = default; @@ -114,118 +54,12 @@ delegate_ = delegate; } -void ExtensionInstallEventLogUploader::SetReportQueue( - std::unique_ptr<::reporting::ReportQueue> report_queue) { - if (report_queue_ == nullptr) { - report_queue_ = std::move(report_queue); - } -} - -void ExtensionInstallEventLogUploader::SetBuildReportQueueConfigurationForTests( - const std::string& dm_token) { - get_report_queue_config_cb_ = base::BindRepeating( - [](const std::string& dm_token, - ReportQueueConfigResultCallback complete_cb) { - std::move(complete_cb) - .Run(::reporting::ReportQueueConfiguration::Create( - dm_token, ::reporting::Destination::UPLOAD_EVENTS, - base::BindRepeating( - []() { return ::reporting::Status::StatusOK(); }))); - }, - dm_token); -} - -ExtensionInstallEventLogUploader::ReportQueueBuilderLeaderTracker:: - ReportQueueBuilderLeaderTracker() = default; -ExtensionInstallEventLogUploader::ReportQueueBuilderLeaderTracker:: - ~ReportQueueBuilderLeaderTracker() = default; - -ExtensionInstallEventLogUploader::ReportQueueBuilder::ReportQueueBuilder( - base::OnceCallback<void(std::unique_ptr<::reporting::ReportQueue>, - base::OnceCallback<void()>)> set_report_queue_cb, - GetReportQueueConfigCallback get_report_queue_config_cb, - scoped_refptr<ReportQueueBuilderLeaderTracker> leader_tracker, - base::OnceCallback<void(bool)> completion_cb, - scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner) - : ::reporting::TaskRunnerContext<bool>(std::move(completion_cb), - sequenced_task_runner), - set_report_queue_cb_(std::move(set_report_queue_cb)), - get_report_queue_config_cb_(std::move(get_report_queue_config_cb)), - leader_tracker_(leader_tracker) {} - -ExtensionInstallEventLogUploader::ReportQueueBuilder::~ReportQueueBuilder() = - default; - -void ExtensionInstallEventLogUploader::ReportQueueBuilder::OnStart() { - auto promo_result = leader_tracker_->RequestLeaderPromotion(); - if (!promo_result.ok()) { - // There is already a ReportQueueBuilder building a ReportQueue - go - // ahead and exit. - Complete(); - return; - } - - release_leader_cb_ = std::move(promo_result.ValueOrDie()); - BuildReportQueueConfig(); -} - -void ExtensionInstallEventLogUploader::ReportQueueBuilder:: - BuildReportQueueConfig() { - std::move(get_report_queue_config_cb_) - .Run(base::BindOnce(&ReportQueueBuilder::OnReportQueueConfigResult, - base::Unretained(this))); -} - -void ExtensionInstallEventLogUploader::ReportQueueBuilder:: - OnReportQueueConfigResult( - ReportQueueConfigResult report_queue_config_result) { - if (!report_queue_config_result.ok()) { - Complete(); - return; - } - Schedule(&ReportQueueBuilder::BuildReportQueue, base::Unretained(this), - std::move(report_queue_config_result.ValueOrDie())); -} - -void ExtensionInstallEventLogUploader::ReportQueueBuilder::BuildReportQueue( - std::unique_ptr<::reporting::ReportQueueConfiguration> - report_queue_config) { - ::reporting::ReportQueueProvider::CreateQueue( - std::move(report_queue_config), - base::BindOnce(&ReportQueueBuilder::OnReportQueueResult, - base::Unretained(this))); -} - -void ExtensionInstallEventLogUploader::ReportQueueBuilder::OnReportQueueResult( - ::reporting::StatusOr<std::unique_ptr<::reporting::ReportQueue>> - report_queue_result) { - if (!report_queue_result.ok()) { - Complete(); - return; - } - Schedule(&ReportQueueBuilder::SetReportQueue, base::Unretained(this), - std::move(report_queue_result.ValueOrDie())); -} - -void ExtensionInstallEventLogUploader::ReportQueueBuilder::SetReportQueue( - std::unique_ptr<::reporting::ReportQueue> report_queue) { - DCHECK(report_queue); - std::move(set_report_queue_cb_) - .Run(std::move(report_queue), - base::BindOnce(&ReportQueueBuilder::Complete, - base::Unretained(this))); -} - -void ExtensionInstallEventLogUploader::ReportQueueBuilder::Complete() { - Schedule(&ReportQueueBuilder::ReleaseLeader, base::Unretained(this)); -} - -void ExtensionInstallEventLogUploader::ReportQueueBuilder::ReleaseLeader() { - if (release_leader_cb_) { - std::move(release_leader_cb_).Run(); - } - Response(true); -} +ExtensionInstallEventLogUploader::ExtensionInstallEventLogUploader( + Profile* profile, + std::unique_ptr<::reporting::ReportQueue, base::OnTaskRunnerDeleter> + report_queue) + : InstallEventLogUploaderBase(profile), + report_queue_(std::move(report_queue)) {} void ExtensionInstallEventLogUploader::CancelClientUpload() { weak_factory_.InvalidateWeakPtrs(); @@ -233,7 +67,7 @@ void ExtensionInstallEventLogUploader::StartSerialization() { delegate_->SerializeExtensionLogForUpload( - base::BindOnce(&ExtensionInstallEventLogUploader::OnSerialized, + base::BindOnce(&ExtensionInstallEventLogUploader::EnqueueReport, weak_factory_.GetWeakPtr())); } @@ -253,56 +87,10 @@ base::Milliseconds(retry_backoff_ms_)); } -void ExtensionInstallEventLogUploader::OnSerialized( - const em::ExtensionInstallReportRequest* report) { - // If report_queue_ hasn't been set, start a ReportQueueBuilder and call - // OnUploadDone(false). The upload will be attempted again in the future. - // If another ReportQueueBuilder starts while the previous one is running, it - // will exit early because the first ReportQueueBuilder will acquire leader - // role from ReportQueueBuilderLeaderTracker. - // If the ReportQueueBuilder fails to build, it will release the leader and - // the next ReportQueueBuilder will acquire the leader role. If a - // ReportQueueBuilder sets the report_queue_ after it has been checked here, - // a new ReportQueueBuilder will spawn, but will be unable to set the - // report_queue_. - if (report_queue_ == nullptr) { - auto set_report_queue_cb = base::BindOnce( - [](base::WeakPtr<ExtensionInstallEventLogUploader> uploader, - scoped_refptr<base::SingleThreadTaskRunner> task_runner, - std::unique_ptr<::reporting::ReportQueue> report_queue, - base::OnceCallback<void()> on_set_cb) { - auto call_uploader_with_report_queue_cb = base::BindOnce( - [](base::WeakPtr<ExtensionInstallEventLogUploader> uploader, - std::unique_ptr<::reporting::ReportQueue> report_queue, - base::OnceCallback<void()> on_set_cb) { - uploader->SetReportQueue(std::move(report_queue)); - }, - std::move(uploader), std::move(report_queue), - std::move(on_set_cb)); - task_runner->PostTask(FROM_HERE, - std::move(call_uploader_with_report_queue_cb)); - }, - weak_factory_.GetWeakPtr(), base::ThreadTaskRunnerHandle::Get()); - - auto completion_cb = base::BindOnce([](bool success) { - LOG_IF(WARNING, !success) << "ReportQueueBuilder was unsuccessful"; - }); - - ::reporting::Start<ReportQueueBuilder>( - std::move(set_report_queue_cb), get_report_queue_config_cb_, - leader_tracker_, std::move(completion_cb), - report_queue_builder_task_runner_); - - OnUploadDone(false); - return; - } - EnqueueReport(*report); -} - void ExtensionInstallEventLogUploader::EnqueueReport( - const em::ExtensionInstallReportRequest& report) { + const em::ExtensionInstallReportRequest* report) { base::Value context = ::reporting::GetContext(profile_); - base::Value event_list = ConvertExtensionProtoToValue(&report, context); + base::Value event_list = ConvertExtensionProtoToValue(report, context); base::Value value_report = RealtimeReportingJobConfiguration::BuildReport( std::move(event_list), std::move(context)); @@ -312,7 +100,7 @@ if (base::CommandLine::ForCurrentProcess()->HasSwitch( ash::switches::kExtensionInstallEventChromeLogForTests)) { for (const em::ExtensionInstallReport& extension_install_report : - report.extension_install_reports()) { + report->extension_install_reports()) { for (const em::ExtensionInstallReportLogEvent& extension_install_report_log_event : extension_install_report.logs()) {
diff --git a/chrome/browser/ash/policy/reporting/extension_install_event_log_uploader.h b/chrome/browser/ash/policy/reporting/extension_install_event_log_uploader.h index 140a523..e654ac5 100644 --- a/chrome/browser/ash/policy/reporting/extension_install_event_log_uploader.h +++ b/chrome/browser/ash/policy/reporting/extension_install_event_log_uploader.h
@@ -9,6 +9,7 @@ #include "base/callback.h" #include "base/memory/weak_ptr.h" +#include "base/task/sequenced_task_runner.h" #include "chrome/browser/ash/policy/reporting/install_event_log_uploader_base.h" #include "components/reporting/client/report_queue.h" #include "components/reporting/client/report_queue_provider.h" @@ -28,18 +29,6 @@ // logs and the policy system which uploads them to the management server. class ExtensionInstallEventLogUploader : public InstallEventLogUploaderBase { public: - // Result of trying to build a |ReportQueueConfiguration|. - using ReportQueueConfigResult = ::reporting::StatusOr< - std::unique_ptr<::reporting::ReportQueueConfiguration>>; - - // Callback for handling a |ReportQueueConfigResult|. - using ReportQueueConfigResultCallback = - base::OnceCallback<void(ReportQueueConfigResult)>; - - // Callback for getting a |ReportQueueConfiguration|. - using GetReportQueueConfigCallback = - base::RepeatingCallback<void(ReportQueueConfigResultCallback)>; - // The delegate that event logs will be retrieved from. class Delegate { public: @@ -62,7 +51,18 @@ virtual ~Delegate(); }; - explicit ExtensionInstallEventLogUploader(Profile* profile); + // Helper for creating a new |ExtensionInstallEventLogUploader| using the + // specified profile. + static std::unique_ptr<ExtensionInstallEventLogUploader> Create( + Profile* profile); + + // Test helper for creating a new |ExtensionInstallEventLogUploader| using the + // specified profile and mock report queue. + static std::unique_ptr<ExtensionInstallEventLogUploader> CreateForTest( + Profile* profile, + std::unique_ptr<::reporting::ReportQueue, base::OnTaskRunnerDeleter> + report_queue); + ~ExtensionInstallEventLogUploader() override; // Sets the delegate. The delegate must either outlive |this| or be explicitly @@ -70,86 +70,11 @@ // delegate cancels the pending log upload, if any. void SetDelegate(Delegate* delegate); - // Sets the report queue if it is not already set. - void SetReportQueue(std::unique_ptr<reporting::ReportQueue> report_queue); - - // Meant to be used in tests for creating the ReportQueueConfiguration. - void SetBuildReportQueueConfigurationForTests(const std::string& dm_token); - private: - // Ensures that only one ReportQueueBuilder is working at one time. - class ReportQueueBuilderLeaderTracker; - - // ReportQueueBuilder instantiates a ReportQueue and uses - // |set_report_queue_cb| to set it in the ExtensionInstallEventLogUploader. - // ReportQueueBuilder ensures that only one ReportQueue instance is - // built for ExtensionInstallLogUploader. - // TODO: For testing there ideally there would be a way to capture the - // ReportQueueConfiguration prior to passing it to the ReportQueue. - class ReportQueueBuilder : public reporting::TaskRunnerContext<bool> { - public: - using SetReportQueueCallback = - base::OnceCallback<void(std::unique_ptr<reporting::ReportQueue>, - base::OnceCallback<void()>)>; - - ReportQueueBuilder( - SetReportQueueCallback set_report_queue_cb, - GetReportQueueConfigCallback get_report_queue_config_cb, - scoped_refptr<ReportQueueBuilderLeaderTracker> leader_tracker, - base::OnceCallback<void(bool)> completion_cb, - scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner); - - private: - ~ReportQueueBuilder() override; - - // |OnStart| requests leadership promotion from the provided - // |leader_tracker|. If there is already a leader, |OnStart| will exit. - // Otherwise it will call |BuildReportQueue|. - void OnStart() override; - - // Posts the task for building the ReportQueueConfiguration used to - // instantiate the ReportQueue. - void BuildReportQueueConfig(); - - // Handles the result of the task posted in |BuildReportQueueConfig|. - void OnReportQueueConfigResult(ReportQueueConfigResult report_queue_result); - - // |BuildReportQueue| uses the |report_queue_config| to build a ReportQueue - // with ReportQueueProvider::CreateQueue. Sets |OnReportQueueResult| as - // the completion callback for |ReportQueueProvider::CreateQueue|. - void BuildReportQueue(std::unique_ptr<::reporting::ReportQueueConfiguration> - report_queue_config); - - // |OnReportQueueResult| will evaluate |report_queue_result|. If it is not - // an OK status, it exits the builder with a |Complete| call. On an OK - // status it |Schedule|s SetReportQueue. - void OnReportQueueResult( - reporting::StatusOr<std::unique_ptr<reporting::ReportQueue>> - report_queue_result); - - // SetReportQueue will call |set_report_queue_cb_| with the provided - // |report_queue|. - void SetReportQueue(std::unique_ptr<reporting::ReportQueue> report_queue); - - // |Schedules| |ReleaseLeader|. - void Complete(); - - // Releases the leader lock if it is held, and then calls |Response|. - void ReleaseLeader(); - - // Callback for setting the ReportQueue in the calling - // |ExtensionInstallEventLogUploader|. - SetReportQueueCallback set_report_queue_cb_; - - // Callback for creating the |ReportQueueConfiguration|. - GetReportQueueConfigCallback get_report_queue_config_cb_; - - // |leader_tracker_| is used to ensure that only one ReportQueueBuilder is - // active at a time. - scoped_refptr<ReportQueueBuilderLeaderTracker> leader_tracker_; - - base::OnceCallback<void()> release_leader_cb_; - }; + explicit ExtensionInstallEventLogUploader( + Profile* profile, + std::unique_ptr<::reporting::ReportQueue, base::OnTaskRunnerDeleter> + report_queue); // InstallEventLogUploaderBase: void CheckDelegateSet() override; @@ -158,14 +83,10 @@ void OnUploadSuccess() override; void StartSerialization() override; - // Callback invoked by the delegate with the extension logs to be uploaded in - // |report|. Forwards the logs to the client for upload. - void OnSerialized( - const enterprise_management::ExtensionInstallReportRequest* report); - - // Enqueues the report for upload. + // Enqueues the report for upload, and is invoked by the delegate with the + // extension logs to be uploaded in |report|. void EnqueueReport( - const enterprise_management::ExtensionInstallReportRequest& report); + const enterprise_management::ExtensionInstallReportRequest* report); // Handles the status of the report enqueue. void OnEnqueueDone(reporting::Status status); @@ -173,18 +94,9 @@ // The delegate that provides serialized logs to be uploaded. Delegate* delegate_ = nullptr; - // ReportQueueBuilderLeaderTracker for building the ReportQueue, - // passed to each ReportQueueBuilder in order to track which is the leader. - scoped_refptr<ReportQueueBuilderLeaderTracker> leader_tracker_; - - // SequencedTaskRunenr for building the ReportQueue. - scoped_refptr<base::SequencedTaskRunner> report_queue_builder_task_runner_; - - // Callback to generate a ReportQueueConfiguration. - GetReportQueueConfigCallback get_report_queue_config_cb_; - - // ReportQueue for uploading events. - std::unique_ptr<reporting::ReportQueue> report_queue_; + // Speculative report queue for uploading events. + const std::unique_ptr<::reporting::ReportQueue, base::OnTaskRunnerDeleter> + report_queue_; // Weak pointer factory for invalidating callbacks passed to the delegate and // scheduled retries when the upload request is canceled or |this| is
diff --git a/chrome/browser/ash/policy/reporting/extension_install_event_log_uploader_unittest.cc b/chrome/browser/ash/policy/reporting/extension_install_event_log_uploader_unittest.cc index d1d7805..5ce2bf5 100644 --- a/chrome/browser/ash/policy/reporting/extension_install_event_log_uploader_unittest.cc +++ b/chrome/browser/ash/policy/reporting/extension_install_event_log_uploader_unittest.cc
@@ -11,9 +11,11 @@ #include "base/json/json_string_value_serializer.h" #include "base/memory/ref_counted.h" +#include "base/task/sequenced_task_runner.h" #include "base/test/gmock_move_support.h" #include "base/test/task_environment.h" #include "base/test/test_mock_time_task_runner.h" +#include "base/threading/sequenced_task_runner_handle.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "base/values.h" @@ -96,13 +98,16 @@ } void CreateUploader() { - uploader_ = std::make_unique<ExtensionInstallEventLogUploader>( - /*profile=*/nullptr); - uploader_->SetDelegate(&delegate_); - - auto mock_report_queue = std::make_unique<reporting::MockReportQueue>(); + ASSERT_TRUE(base::SequencedTaskRunnerHandle::IsSet()); + auto mock_report_queue = std::unique_ptr<::reporting::MockReportQueue, + base::OnTaskRunnerDeleter>( + new ::reporting::MockReportQueue(), + base::OnTaskRunnerDeleter(base::SequencedTaskRunnerHandle::Get())); mock_report_queue_ = mock_report_queue.get(); - uploader_->SetReportQueue(std::move(mock_report_queue)); + + uploader_ = ExtensionInstallEventLogUploader::CreateForTest( + /*profile=*/nullptr, std::move(mock_report_queue)); + uploader_->SetDelegate(&delegate_); } void CompleteSerialize() {
diff --git a/chrome/browser/ash/psi_memory_metrics.cc b/chrome/browser/ash/psi_memory_metrics.cc index 4c9276f..95b4fac 100644 --- a/chrome/browser/ash/psi_memory_metrics.cc +++ b/chrome/browser/ash/psi_memory_metrics.cc
@@ -34,49 +34,19 @@ namespace { -// Default interval between externally-reported metrics being collected. -constexpr base::TimeDelta kMinCollectionInterval = base::Seconds(10); -constexpr base::TimeDelta kMidCollectionInterval = base::Seconds(60); -constexpr base::TimeDelta kMaxCollectionInterval = base::Seconds(300); - -constexpr base::TimeDelta kDefaultCollectionInterval = kMinCollectionInterval; - // Name of the histogram that represents the success and various failure modes // for parsing PSI memory data. -const char kParsePSIMemoryHistogramName[] = "ChromeOS.CWP.ParsePSIMemory"; const char kPSIMemoryPressureSomeName[] = "ChromeOS.CWP.PSIMemPressure.Some"; const char kPSIMemoryPressureFullName[] = "ChromeOS.CWP.PSIMemPressure.Full"; // File path that stores PSI Memory data. const char kPSIMemoryPath[] = "/proc/pressure/memory"; -constexpr base::StringPiece kContentPrefixSome = "some"; -constexpr base::StringPiece kContentPrefixFull = "full"; -constexpr base::StringPiece kContentTerminator = " total="; -constexpr base::StringPiece kMetricTerminator = " "; - -const char kMetricPrefixFormat[] = "avg%" PRId64 "="; - -// Values as logged in the histogram for memory pressure. -constexpr int kMemPressureMin = 1; // As 0 is for underflow. -constexpr int kMemPressureExclusiveMax = 10000; -constexpr int kMemPressureHistogramBuckets = 100; - } // namespace PSIMemoryMetrics::PSIMemoryMetrics(uint32_t period) - : memory_psi_file_(kPSIMemoryPath), - collection_interval_(kDefaultCollectionInterval) { - if (period == kMinCollectionInterval.InSeconds() || - period == kMidCollectionInterval.InSeconds() || - period == kMaxCollectionInterval.InSeconds()) { - collection_interval_ = base::Seconds(period); - } else { - LOG(WARNING) << "Ignoring invalid interval [" << period << "]"; - } - - metric_prefix_ = - base::StringPrintf(kMetricPrefixFormat, collection_interval_.InSeconds()); + : memory_psi_file_(kPSIMemoryPath), parser_(period) { + collection_interval_ = base::Seconds(parser_.GetPeriod()); runner_ = base::ThreadPool::CreateSequencedTaskRunner( {base::MayBlock(), base::TaskPriority::BEST_EFFORT, @@ -104,103 +74,28 @@ base::BindOnce(&PSIMemoryMetrics::CancelTimer, this)); } -int PSIMemoryMetrics::GetMetricValue(const std::string& content, - size_t start, - size_t end) { - size_t value_start; - size_t value_end; - if (!internal::FindMiddleString(content, start, metric_prefix_, - kMetricTerminator, &value_start, - &value_end)) { - return -1; - } - if (value_end > end) { - return -1; // Out of bounds of the search area. - } - - double n; - const base::StringPiece metric_value_text(content.c_str() + value_start, - value_end - value_start); - if (!base::StringToDouble(metric_value_text, &n)) { - return -1; // Unable to convert string to number - } - - // Want to multiply by 100, but to avoid integer truncation, - // do best-effort rounding. - const int preround = static_cast<int>(n * 1000); - return (preround + 5) / 10; -} - -PSIMemoryMetrics::ParsePSIMemStatus PSIMemoryMetrics::ParseMetrics( - const std::string& content, - int* metric_some, - int* metric_full) { - size_t str_some_start; - size_t str_some_end; - size_t str_full_start; - size_t str_full_end; - - DCHECK_NE(metric_some, nullptr); - DCHECK_NE(metric_full, nullptr); - - if (!internal::FindMiddleString(content, 0, kContentPrefixSome, - kContentTerminator, &str_some_start, - &str_some_end)) { - return ParsePSIMemStatus::kUnexpectedDataFormat; - } - - if (!internal::FindMiddleString(content, - str_some_end + kContentTerminator.length(), - kContentPrefixFull, kContentTerminator, - &str_full_start, &str_full_end)) { - return ParsePSIMemStatus::kUnexpectedDataFormat; - } - - int compute_some = GetMetricValue(content, str_some_start, str_some_end); - if (compute_some < 0) { - return ParsePSIMemStatus::kInvalidMetricFormat; - } - - int compute_full = GetMetricValue(content, str_full_start, str_full_end); - if (compute_full < 0) { - return ParsePSIMemStatus::kInvalidMetricFormat; - } - - *metric_some = compute_some; - *metric_full = compute_full; - - return ParsePSIMemStatus::kSuccess; -} - -PSIMemoryMetrics::ParsePSIMemStatus PSIMemoryMetrics::CollectEvents() { - // Example file content: - // some avg10=0.00 avg60=0.00 avg300=0.00 total=417963 - // full avg10=0.00 avg60=0.00 avg300=0.00 total=205933 - // we will pick one of the columns depending on the colleciton period set +void PSIMemoryMetrics::CollectEvents() { std::string content; int metric_some; int metric_full; - PSIMemoryMetrics::ParsePSIMemStatus stat; if (!base::ReadFileToString(base::FilePath(memory_psi_file_), &content)) { - return ParsePSIMemStatus::kReadFileFailed; + parser_.LogParseStatus(metrics::ParsePSIMemStatus::kReadFileFailed); + return; } - stat = ParseMetrics(content, &metric_some, &metric_full); - - if (stat != ParsePSIMemStatus::kSuccess) { - return stat; + auto stat = parser_.ParseMetrics(content, &metric_some, &metric_full); + parser_.LogParseStatus(stat); // Log success and failure, for histograms. + if (stat != metrics::ParsePSIMemStatus::kSuccess) { + return; } - base::UmaHistogramCustomCounts(kPSIMemoryPressureSomeName, metric_some, - kMemPressureMin, kMemPressureExclusiveMax, - kMemPressureHistogramBuckets); - - base::UmaHistogramCustomCounts(kPSIMemoryPressureFullName, metric_full, - kMemPressureMin, kMemPressureExclusiveMax, - kMemPressureHistogramBuckets); - - return ParsePSIMemStatus::kSuccess; + base::UmaHistogramCustomCounts( + kPSIMemoryPressureSomeName, metric_some, metrics::kMemPressureMin, + metrics::kMemPressureExclusiveMax, metrics::kMemPressureHistogramBuckets); + base::UmaHistogramCustomCounts( + kPSIMemoryPressureFullName, metric_full, metrics::kMemPressureMin, + metrics::kMemPressureExclusiveMax, metrics::kMemPressureHistogramBuckets); } void PSIMemoryMetrics::CollectEventsAndReschedule() { @@ -208,12 +103,7 @@ return; } - ParsePSIMemStatus stat = CollectEvents(); - constexpr int statCeiling = - static_cast<int>(ParsePSIMemStatus::kMaxValue) + 1; - base::UmaHistogramExactLinear(kParsePSIMemoryHistogramName, - static_cast<int>(stat), statCeiling); - + CollectEvents(); ScheduleCollector(); } @@ -228,34 +118,4 @@ collection_interval_); } -namespace internal { - -bool FindMiddleString(const base::StringPiece& content, - size_t search_start, - const base::StringPiece& prefix, - const base::StringPiece& suffix, - size_t* start, - size_t* end) { - DCHECK_NE(start, nullptr); - DCHECK_NE(end, nullptr); - - size_t compute_start = content.find(prefix, search_start); - if (compute_start == std::string::npos) { - return false; - } - compute_start += prefix.length(); - - size_t compute_end = content.find(suffix, compute_start); - if (compute_end == std::string::npos) { - return false; - } - - *start = compute_start; - *end = compute_end; - - return true; -} - -} // namespace internal - } // namespace ash
diff --git a/chrome/browser/ash/psi_memory_metrics.h b/chrome/browser/ash/psi_memory_metrics.h index 3e48f21..2c4509f1 100644 --- a/chrome/browser/ash/psi_memory_metrics.h +++ b/chrome/browser/ash/psi_memory_metrics.h
@@ -6,6 +6,7 @@ #define CHROME_BROWSER_ASH_PSI_MEMORY_METRICS_H_ #include <string> +#include <vector> #include "base/gtest_prod_util.h" #include "base/memory/ref_counted.h" @@ -13,6 +14,7 @@ #include "base/task/delayed_task_handle.h" #include "base/task/task_runner.h" #include "base/time/time.h" +#include "components/metrics/psi_memory_parser.h" namespace ash { @@ -44,29 +46,9 @@ // Friend it so it can see private members for testing friend class PSIMemoryMetricsTest; - FRIEND_TEST_ALL_PREFIXES(PSIMemoryMetricsTest, CustomInterval); - FRIEND_TEST_ALL_PREFIXES(PSIMemoryMetricsTest, InvalidInterval); FRIEND_TEST_ALL_PREFIXES(PSIMemoryMetricsTest, SunnyDay1); FRIEND_TEST_ALL_PREFIXES(PSIMemoryMetricsTest, SunnyDay2); FRIEND_TEST_ALL_PREFIXES(PSIMemoryMetricsTest, SunnyDay3); - FRIEND_TEST_ALL_PREFIXES(PSIMemoryMetricsTest, InternalsA); - FRIEND_TEST_ALL_PREFIXES(PSIMemoryMetricsTest, InternalsB); - FRIEND_TEST_ALL_PREFIXES(PSIMemoryMetricsTest, InternalsC); - FRIEND_TEST_ALL_PREFIXES(PSIMemoryMetricsTest, InternalsD); - FRIEND_TEST_ALL_PREFIXES(PSIMemoryMetricsTest, InternalsE); - - // Enumeration representing success and various failure modes for parsing PSI - // memory data. These values are persisted to logs. Entries should not be - // renumbered and numeric values should never be reused. - enum class ParsePSIMemStatus { - kSuccess, - kReadFileFailed, - kUnexpectedDataFormat, - kInvalidMetricFormat, - kParsePSIValueFailed, - // Magic constant used by the histogram macros. - kMaxValue = kParsePSIValueFailed, - }; static scoped_refptr<PSIMemoryMetrics> CreateForTesting( uint32_t period, @@ -80,26 +62,7 @@ // Friend it so it can call our private destructor. friend class base::RefCountedThreadSafe<PSIMemoryMetrics>; - // Retrieves one metric value from |content|, for the currently configured - // metrics category (10, 60 or 300 seconds). - // Only considers the substring between |start| (inclusive) and |end| - // (exclusive). - // Returns the floating-point string representation converted into an integer - // which has the value multiplied by 100 - (10.20 = 1020), for - // histogram usage. - int GetMetricValue(const std::string& content, size_t start, size_t end); - - // Parses PSI memory pressure from |content|, for the currently configured - // metrics category (10, 60 or 300 seconds). - // The some and full values are output to |metricSome| and |metricFull|, - // respectively. - // Returns status of the parse operation - ParsePSIMemStatus::kSuccess - // or error code otherwise. - ParsePSIMemStatus ParseMetrics(const std::string& content, - int* metric_some, - int* metric_full); - - ParsePSIMemStatus CollectEvents(); + void CollectEvents(); // Calls CollectEvents and reschedules a future collection. void CollectEventsAndReschedule(); @@ -112,8 +75,8 @@ // Interval between metrics collection. std::string memory_psi_file_; + metrics::PSIMemoryParser parser_; base::TimeDelta collection_interval_; - std::string metric_prefix_; // Task controllers/monitors. scoped_refptr<base::SequencedTaskRunner> runner_; @@ -121,25 +84,6 @@ base::DelayedTaskHandle last_timer_; }; -// Items in internal are - as the name implies - NOT for outside consumption. -// Defined here to allow access to unit test. -namespace internal { - -// Finds the bounds for a substring of |content| which is sandwiched between -// the given |prefix| and |suffix| indices. Search only considers -// the portion of the string starting from |search_start|. -// Returns false if the prefix and/or suffix are not found, true otherwise. -// |start| and |end| are output parameters populated with the indices -// for the middle string. -bool FindMiddleString(const base::StringPiece& content, - size_t search_start, - const base::StringPiece& prefix, - const base::StringPiece& suffix, - size_t* start, - size_t* end); - -} // namespace internal - } // namespace ash #endif // CHROME_BROWSER_ASH_PSI_MEMORY_METRICS_H_
diff --git a/chrome/browser/ash/psi_memory_metrics_unittest.cc b/chrome/browser/ash/psi_memory_metrics_unittest.cc index 116458e..fa3ae5a 100644 --- a/chrome/browser/ash/psi_memory_metrics_unittest.cc +++ b/chrome/browser/ash/psi_memory_metrics_unittest.cc
@@ -26,11 +26,6 @@ "some avg10=23.10 avg60=5.06 avg300=15.10 total=417963\n" "full avg10=9.00 avg60=19.20 avg300=3.23 total=205933\n"; -// Number of decimals not consistent, slightly malformed - but acceptable. -const char kFileContents2[] = - "some avg10=24 avg60=5.06 avg300=15.10 total=417963\n" - "full avg10=9.2 avg60=19.20 avg300=3.23 total=205933\n"; - } // namespace class PSIMemoryMetricsTest : public testing::Test { @@ -48,7 +43,6 @@ const base::FilePath& GetTestFileName() { return testfilename_; } base::HistogramTester& Histograms() { return histogram_tester_; } scoped_refptr<PSIMemoryMetrics> Cit() { return cit_; } - const std::string& GetMetricPrefix() { return cit_->metric_prefix_; } content::BrowserTaskEnvironment& task_environment() { return task_environment_; } @@ -64,18 +58,6 @@ base::HistogramTester histogram_tester_; }; -TEST_F(PSIMemoryMetricsTest, CustomInterval) { - Init(60); - - EXPECT_EQ(base::Seconds(60), GetCollection()); -} - -TEST_F(PSIMemoryMetricsTest, InvalidInterval) { - Init(15); - - EXPECT_EQ(base::Seconds(10), GetCollection()); -} - TEST_F(PSIMemoryMetricsTest, SunnyDay1) { Init(10); int bytes_written = base::WriteFile(GetTestFileName(), kFileContents1, @@ -192,91 +174,4 @@ 323 /*bucket*/, 1 /*count*/); } -TEST_F(PSIMemoryMetricsTest, InternalsA) { - Init(10); - - std::string testContent1 = "prefix" + GetMetricPrefix() + "9.37 suffix"; - EXPECT_EQ(base::Seconds(10), GetCollection()); - - size_t s = 0; - size_t e = 0; - - EXPECT_EQ(false, internal::FindMiddleString(testContent1, 0, "nothere", - "suffix", &s, &e)); - - EXPECT_EQ(false, internal::FindMiddleString(testContent1, 0, "prefix", - "notthere", &s, &e)); - - EXPECT_EQ(true, internal::FindMiddleString(testContent1, 0, "prefix", - "suffix", &s, &e)); - EXPECT_EQ(6, s); - EXPECT_EQ(17, e); - - EXPECT_EQ(937, Cit()->GetMetricValue(testContent1, s, e)); - - std::string testContent2 = "extra " + testContent1; - EXPECT_EQ(true, internal::FindMiddleString(testContent2, 0, "prefix", - "suffix", &s, &e)); - EXPECT_EQ(12, s); - EXPECT_EQ(23, e); - - EXPECT_EQ(937, Cit()->GetMetricValue(testContent2, s, e)); -} - -TEST_F(PSIMemoryMetricsTest, InternalsB) { - Init(300); - - int msome; - int mfull; - PSIMemoryMetrics::ParsePSIMemStatus stat; - - stat = Cit()->ParseMetrics(kFileContents1, &msome, &mfull); - - EXPECT_EQ(PSIMemoryMetrics::ParsePSIMemStatus::kSuccess, stat); - EXPECT_EQ(1510, msome); - EXPECT_EQ(323, mfull); -} - -TEST_F(PSIMemoryMetricsTest, InternalsC) { - Init(60); - - int msome; - int mfull; - PSIMemoryMetrics::ParsePSIMemStatus stat; - - stat = Cit()->ParseMetrics(kFileContents1, &msome, &mfull); - - EXPECT_EQ(PSIMemoryMetrics::ParsePSIMemStatus::kSuccess, stat); - EXPECT_EQ(506, msome); - EXPECT_EQ(1920, mfull); -} - -TEST_F(PSIMemoryMetricsTest, InternalsD) { - Init(10); - - int msome; - int mfull; - PSIMemoryMetrics::ParsePSIMemStatus stat; - - stat = Cit()->ParseMetrics(kFileContents1, &msome, &mfull); - - EXPECT_EQ(PSIMemoryMetrics::ParsePSIMemStatus::kSuccess, stat); - EXPECT_EQ(2310, msome); - EXPECT_EQ(900, mfull); -} - -TEST_F(PSIMemoryMetricsTest, InternalsE) { - Init(10); - - int msome; - int mfull; - PSIMemoryMetrics::ParsePSIMemStatus stat; - - stat = Cit()->ParseMetrics(kFileContents2, &msome, &mfull); - - EXPECT_EQ(PSIMemoryMetrics::ParsePSIMemStatus::kSuccess, stat); - EXPECT_EQ(2400, msome); - EXPECT_EQ(920, mfull); -} - } // namespace ash
diff --git a/chrome/browser/autofill/autofill_interactive_uitest.cc b/chrome/browser/autofill/autofill_interactive_uitest.cc index 3d02cc3..0b2e044a 100644 --- a/chrome/browser/autofill/autofill_interactive_uitest.cc +++ b/chrome/browser/autofill/autofill_interactive_uitest.cc
@@ -86,6 +86,16 @@ #include "ui/events/keycodes/keyboard_code_conversion.h" #include "ui/events/keycodes/keyboard_codes.h" +#if BUILDFLAG(IS_CHROMEOS_ASH) && BUILDFLAG(ENABLE_EXTENSIONS) +// Includes for ChromeVox accessibility tests. +#include "chrome/browser/ash/accessibility/accessibility_manager.h" +#include "chrome/browser/ash/accessibility/speech_monitor.h" +#include "chrome/browser/ui/aura/accessibility/automation_manager_aura.h" +#include "chrome/test/base/ui_test_utils.h" +#include "extensions/browser/browsertest_util.h" +#include "ui/base/test/ui_controls.h" +#endif // BUILDFLAG(IS_CHROMEOS_ASH) && BUILDFLAG(ENABLE_EXTENSIONS) + using base::ASCIIToUTF16; using content::URLLoaderInterceptor; @@ -3636,4 +3646,94 @@ AutofillDynamicFormReplacementInteractiveTest, testing::Bool()); +// ChromeVox is only available on ChromeOS. +#if BUILDFLAG(IS_CHROMEOS_ASH) && BUILDFLAG(ENABLE_EXTENSIONS) + +class AutofillChromeVoxTest : public AutofillInteractiveTestBase { + public: + AutofillChromeVoxTest() = default; + ~AutofillChromeVoxTest() override = default; + + void TearDownOnMainThread() override { + // Unload the ChromeVox extension so the browser doesn't try to respond to + // in-flight requests during test shutdown. https://crbug.com/923090 + ash::AccessibilityManager::Get()->EnableSpokenFeedback(false); + AutomationManagerAura::GetInstance()->Disable(); + } + + void EnableChromeVox() { + // Test setup. + // Enable ChromeVox, disable earcons and wait for key mappings to be + // fetched. + ASSERT_FALSE(ash::AccessibilityManager::Get()->IsSpokenFeedbackEnabled()); + // TODO(accessibility): fix console error/warnings and insantiate + // |console_observer_| here. + + // Load ChromeVox and block until it's fully loaded. + ash::AccessibilityManager::Get()->EnableSpokenFeedback(true); + sm_.ExpectSpeechPattern("*"); + sm_.Call([this]() { DisableEarcons(); }); + } + + void DisableEarcons() { + // Playing earcons from within a test is not only annoying if you're + // running the test locally, but seems to cause crashes + // (http://crbug.com/396507). Work around this by just telling + // ChromeVox to not ever play earcons (prerecorded sound effects). + extensions::browsertest_util::ExecuteScriptInBackgroundPageNoWait( + browser()->profile(), extension_misc::kChromeVoxExtensionId, + "ChromeVox.earcons.playEarcon = function() {};"); + } + + ash::test::SpeechMonitor sm_; +}; + +// Ensure that autofill suggestions are properly read out via ChromeVox. +// This is a regressions test for crbug.com/1208913. +IN_PROC_BROWSER_TEST_F(AutofillChromeVoxTest, + TestNotificationOfAutofillDropdown) { + CreateTestProfile(); + + // Load the test page. + SetTestUrlResponse(kTestShippingFormString); + ASSERT_NO_FATAL_FAILURE( + ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetTestUrl()))); + + EnableChromeVox(); + content::EnableAccessibilityForWebContents(web_contents()); + + // The following contains a sequence of calls to + // sm_.ExpectSpeechPattern() and test_delegate()->Wait(). It is essential + // to first flush the expected speech patterns, otherwise the two functions + // start incompatible RunLoops. + sm_.ExpectSpeechPattern("Web Content"); + sm_.Call([this]() { + content::WaitForAccessibilityTreeToContainNodeWithName(web_contents(), + "First name:"); + web_contents()->Focus(); + test_delegate()->SetExpectations({ObservedUiEvents::kSuggestionShown}); + FocusFieldByName("firstname"); + }); + sm_.ExpectSpeechPattern("First name:"); + sm_.ExpectSpeechPattern("Edit text"); + sm_.ExpectSpeechPattern("Region"); + // Wait for suggestions popup to show up. This needs to happen before we + // simulate the cursor down key press. + sm_.Call([this]() { test_delegate()->Wait(); }); + sm_.Call([this]() { + test_delegate()->SetExpectations({ObservedUiEvents::kPreviewFormData}); + ASSERT_TRUE( + ui_controls::SendKeyPress(browser()->window()->GetNativeWindow(), + ui::VKEY_DOWN, false, false, false, false)); + }); + sm_.ExpectSpeechPattern("Autofill menu opened"); + sm_.ExpectSpeechPattern("Milton 4120 Freidrich Lane"); + sm_.ExpectSpeechPattern("List item"); + sm_.ExpectSpeechPattern("1 of 2"); + sm_.Call([this]() { test_delegate()->Wait(); }); + sm_.Replay(); +} + +#endif // BUILDFLAG(IS_CHROMEOS_ASH) && BUILDFLAG(ENABLE_EXTENSIONS) + } // namespace autofill
diff --git a/chrome/browser/browser_keyevents_browsertest.cc b/chrome/browser/browser_keyevents_browsertest.cc index 3afc64c..7420f34 100644 --- a/chrome/browser/browser_keyevents_browsertest.cc +++ b/chrome/browser/browser_keyevents_browsertest.cc
@@ -20,8 +20,6 @@ #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/interactive_test_utils.h" #include "chrome/test/base/ui_test_utils.h" -#include "content/public/browser/notification_registrar.h" -#include "content/public/browser/notification_service.h" #include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test.h" @@ -94,14 +92,12 @@ } // A class to help wait for the finish of a key event test. -class TestFinishObserver : public content::NotificationObserver { +class TestFinishObserver : public content::WebContentsObserver { public: explicit TestFinishObserver(content::WebContents* web_contents) - : finished_(false), waiting_(false) { - registrar_.Add(this, - content::NOTIFICATION_DOM_OPERATION_RESPONSE, - content::Source<content::WebContents>(web_contents)); - } + : content::WebContentsObserver(web_contents), + finished_(false), + waiting_(false) {} TestFinishObserver(const TestFinishObserver&) = delete; TestFinishObserver& operator=(const TestFinishObserver&) = delete; @@ -115,14 +111,11 @@ return finished_; } - void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) override { - DCHECK(type == content::NOTIFICATION_DOM_OPERATION_RESPONSE); - content::Details<std::string> dom_op_result(details); + void DomOperationResponse(content::RenderFrameHost* render_frame_host, + const std::string& dom_op_result) override { // We might receive responses for other script execution, but we only // care about the test finished message. - if (*dom_op_result.ptr() == "\"FINISHED\"") { + if (dom_op_result == "\"FINISHED\"") { finished_ = true; if (waiting_) base::RunLoop::QuitCurrentWhenIdleDeprecated(); @@ -132,7 +125,6 @@ private: bool finished_; bool waiting_; - content::NotificationRegistrar registrar_; }; class BrowserKeyEventsTest : public InProcessBrowserTest {
diff --git a/chrome/browser/chrome_browser_interface_binders.cc b/chrome/browser/chrome_browser_interface_binders.cc index 6a21319..80e960e 100644 --- a/chrome/browser/chrome_browser_interface_binders.cc +++ b/chrome/browser/chrome_browser_interface_binders.cc
@@ -343,6 +343,10 @@ void BindCommerceHintObserver( content::RenderFrameHost* const frame_host, mojo::PendingReceiver<cart::mojom::CommerceHintObserver> receiver) { + DCHECK(!frame_host->GetParentOrOuterDocument()); + if (frame_host->GetParentOrOuterDocument()) + return; + // Cart is not available for non-signin single-profile users. Profile* profile = Profile::FromBrowserContext( frame_host->GetProcess()->GetBrowserContext()); @@ -548,6 +552,8 @@ base::BindRepeating(&BindImageAnnotator)); #if !defined(OS_ANDROID) + // We should not request this mojo interface's binding for the subframes in + // the renderer. if (base::FeatureList::IsEnabled(ntp_features::kNtpChromeCartModule) && !render_frame_host->GetParent()) { map->Add<cart::mojom::CommerceHintObserver>(
diff --git a/chrome/browser/enterprise/util/affiliation.cc b/chrome/browser/enterprise/util/affiliation.cc index 408fdb2..f84b266 100644 --- a/chrome/browser/enterprise/util/affiliation.cc +++ b/chrome/browser/enterprise/util/affiliation.cc
@@ -10,10 +10,20 @@ #include "chrome/browser/profiles/profile.h" #include "components/policy/core/common/cloud/affiliation.h" +#if BUILDFLAG(IS_CHROMEOS_LACROS) +#include "components/policy/core/common/policy_loader_lacros.h" +#endif // BUILDFLAG(IS_CHROMEOS_LACROS) + namespace chrome { namespace enterprise_util { bool IsProfileAffiliated(Profile* profile) { +#if BUILDFLAG(IS_CHROMEOS_LACROS) + if (profile->IsMainProfile()) { + return policy::PolicyLoaderLacros::IsMainUserAffiliated(); + } +#endif // BUILDFLAG(IS_CHROMEOS_LACROS) + return policy::IsAffiliated( profile->GetProfilePolicyConnector()->user_affiliation_ids(), g_browser_process->browser_policy_connector()->device_affiliation_ids());
diff --git a/chrome/browser/extensions/api/identity/web_auth_flow.cc b/chrome/browser/extensions/api/identity/web_auth_flow.cc index 85dda1ca..d8f84a8 100644 --- a/chrome/browser/extensions/api/identity/web_auth_flow.cc +++ b/chrome/browser/extensions/api/identity/web_auth_flow.cc
@@ -223,16 +223,14 @@ void WebAuthFlow::DidStartNavigation( content::NavigationHandle* navigation_handle) { - // TODO(https://crbug.com/1218946): With MPArch there may be multiple main - // frames. This caller was converted automatically to the primary main frame - // to preserve its semantics. Follow up to confirm correctness. if (navigation_handle->IsInPrimaryMainFrame()) BeforeUrlLoaded(navigation_handle->GetURL()); } void WebAuthFlow::DidRedirectNavigation( content::NavigationHandle* navigation_handle) { - BeforeUrlLoaded(navigation_handle->GetURL()); + if (navigation_handle->IsInPrimaryMainFrame()) + BeforeUrlLoaded(navigation_handle->GetURL()); } void WebAuthFlow::DidFinishNavigation( @@ -240,9 +238,6 @@ // Websites may create and remove <iframe> during the auth flow. In // particular, to integrate CAPTCHA tests. Chrome shouldn't abort the auth // flow if a navigation failed in a sub-frame. https://crbug.com/1049565. - // TODO(https://crbug.com/1218946): With MPArch there may be multiple main - // frames. This caller was converted automatically to the primary main frame - // to preserve its semantics. Follow up to confirm correctness. if (!navigation_handle->IsInPrimaryMainFrame()) return;
diff --git a/chrome/browser/extensions/api/identity/web_auth_flow_browsertest.cc b/chrome/browser/extensions/api/identity/web_auth_flow_browsertest.cc new file mode 100644 index 0000000..45058d6a --- /dev/null +++ b/chrome/browser/extensions/api/identity/web_auth_flow_browsertest.cc
@@ -0,0 +1,150 @@ +// 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/extensions/api/identity/web_auth_flow.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "content/public/test/browser_test.h" +#include "content/public/test/fenced_frame_test_util.h" +#include "content/public/test/test_navigation_observer.h" +#include "testing/gmock/include/gmock/gmock.h" + +class MockWebAuthFlowDelegate : public extensions::WebAuthFlow::Delegate { + public: + MOCK_METHOD(void, OnAuthFlowURLChange, (const GURL&), (override)); + MOCK_METHOD(void, OnAuthFlowTitleChange, (const std::string&), (override)); + MOCK_METHOD(void, + OnAuthFlowFailure, + (extensions::WebAuthFlow::Failure), + (override)); +}; + +class WebAuthFlowBrowserTest : public InProcessBrowserTest { + public: + void SetUpOnMainThread() override { + InProcessBrowserTest::SetUpOnMainThread(); + ASSERT_TRUE(embedded_test_server()->Start()); + } + + void TearDownOnMainThread() override { + // Delete the web auth flow (uses DeleteSoon). + web_auth_flow_.release()->DetachDelegateAndDelete(); + base::RunLoop().RunUntilIdle(); + InProcessBrowserTest::TearDownOnMainThread(); + } + + void StartWebAuthFlow(const GURL& url) { + web_auth_flow_ = std::make_unique<extensions::WebAuthFlow>( + &mock_web_auth_flow_delegate_, browser()->profile(), url, + extensions::WebAuthFlow::INTERACTIVE, + extensions::WebAuthFlow::LAUNCH_WEB_AUTH_FLOW); + web_auth_flow_->Start(); + } + + content::WebContents* web_contents() { + DCHECK(web_auth_flow_); + return web_auth_flow_->web_contents(); + } + + MockWebAuthFlowDelegate& mock() { return mock_web_auth_flow_delegate_; } + + private: + std::unique_ptr<extensions::WebAuthFlow> web_auth_flow_; + MockWebAuthFlowDelegate mock_web_auth_flow_delegate_; +}; + +IN_PROC_BROWSER_TEST_F(WebAuthFlowBrowserTest, OnAuthFlowURLChangeCalled) { + const GURL auth_url = embedded_test_server()->GetURL("/title1.html"); + + // Observer for waiting until a navigation to a url has finished. + content::TestNavigationObserver navigation_observer(auth_url); + navigation_observer.StartWatchingNewWebContents(); + + StartWebAuthFlow(auth_url); + // The delegate method OnAuthFlowURLChange should be called + // by DidStartNavigation. + EXPECT_CALL(mock(), OnAuthFlowURLChange(auth_url)); + + navigation_observer.WaitForNavigationFinished(); +} + +IN_PROC_BROWSER_TEST_F(WebAuthFlowBrowserTest, OnAuthFlowFailureChangeCalled) { + // Navigate to a url that doesn't exist. + const GURL error_url = embedded_test_server()->GetURL("/error"); + + content::TestNavigationObserver navigation_observer(error_url); + navigation_observer.StartWatchingNewWebContents(); + + StartWebAuthFlow(error_url); + // The delegate method OnAuthFlowFailure should be called + // by DidFinishNavigation. + EXPECT_CALL(mock(), OnAuthFlowFailure(extensions::WebAuthFlow::LOAD_FAILED)); + + navigation_observer.WaitForNavigationFinished(); +} + +class WebAuthFlowFencedFrameTest : public WebAuthFlowBrowserTest { + public: + content::test::FencedFrameTestHelper& fenced_frame_test_helper() { + return fenced_frame_helper_; + } + + private: + content::test::FencedFrameTestHelper fenced_frame_helper_; +}; + +IN_PROC_BROWSER_TEST_F(WebAuthFlowFencedFrameTest, + FencedFrameNavigationSuccess) { + const GURL auth_url = embedded_test_server()->GetURL("/title1.html"); + + // Observer for waiting until loading stops. A fenced frame will be created + // after load has finished. + content::TestNavigationObserver navigation_observer(auth_url); + navigation_observer.set_wait_event( + content::TestNavigationObserver::WaitEvent::kLoadStopped); + navigation_observer.StartWatchingNewWebContents(); + + StartWebAuthFlow(auth_url); + + EXPECT_CALL(mock(), OnAuthFlowURLChange(auth_url)); + navigation_observer.Wait(); + testing::Mock::VerifyAndClearExpectations(&mock()); + + // Navigation for fenced frames should not affect to call the delegate methods + // in the WebAuthFlow. + EXPECT_CALL(mock(), OnAuthFlowURLChange(auth_url)).Times(0); + + // Create a fenced frame into the inner WebContents of the WebAuthFlow. + ASSERT_TRUE(fenced_frame_test_helper().CreateFencedFrame( + web_contents()->GetMainFrame(), + embedded_test_server()->GetURL("/fenced_frames/title1.html"))); +} + +IN_PROC_BROWSER_TEST_F(WebAuthFlowFencedFrameTest, + FencedFrameNavigationFailure) { + const GURL auth_url = embedded_test_server()->GetURL("/title1.html"); + + // Observer for waiting until loading stops. A fenced frame will be created + // after load has finished. + content::TestNavigationObserver navigation_observer(auth_url); + navigation_observer.set_wait_event( + content::TestNavigationObserver::WaitEvent::kLoadStopped); + navigation_observer.StartWatchingNewWebContents(); + + StartWebAuthFlow(auth_url); + + EXPECT_CALL(mock(), OnAuthFlowURLChange(auth_url)); + navigation_observer.Wait(); + testing::Mock::VerifyAndClearExpectations(&mock()); + + // Navigation for fenced frames should not affect to call the delegate methods + // in the WebAuthFlow. + EXPECT_CALL(mock(), OnAuthFlowURLChange(auth_url)).Times(0); + EXPECT_CALL(mock(), OnAuthFlowFailure).Times(0); + + // Create a fenced frame into the inner WebContents of the WebAuthFlow. + ASSERT_TRUE(fenced_frame_test_helper().CreateFencedFrame( + web_contents()->GetMainFrame(), embedded_test_server()->GetURL("/error"), + net::Error::ERR_FAILED)); +}
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index c5f4c03..12550e9b 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -265,6 +265,11 @@ "expiry_milestone": 97 }, { + "name": "arc-window-predictor", + "owners": [ "sstan" ], + "expiry_milestone": 110 + }, + { "name": "ash-advanced-screen-capture-settings", "owners": [ "afakhry", "gzadina", "fanafan" ], "expiry_milestone": 100 @@ -4846,11 +4851,6 @@ "expiry_milestone": 99 }, { - "name": "safe-browsing-enhanced-protection-promo-android", - "owners": [ "bdea", "chrome-safebrowsing-core@google.com" ], - "expiry_milestone": 100 - }, - { "name": "safe-browsing-password-protection-for-signed-in-users", "owners": [ "xinghuilu",
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 77165478..f009c57 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -3456,12 +3456,6 @@ const char kSafeBrowsingClientSideDetectionAndroidDescription[] = "Enable DOM feature collection on Safe Browsing pings on Android"; -const char kEnhancedProtectionPromoAndroidName[] = - "Enable enhanced protection promo card on Android on the New Tab Page"; -const char kEnhancedProtectionPromoAndroidDescription[] = - "Enable enhanced protection promo card for users that have not signed up " - "for enhanced protection."; - const char kScrollCaptureName[] = "Scroll Capture"; const char kScrollCaptureDescription[] = "Enables scrolling screenshot capture for web contents."; @@ -5022,6 +5016,10 @@ "Enables the pre-load app window for " "ARC++ app during ARCVM booting stage on full restore process"; +extern const char kArcWindowPredictorName[] = "Enable ARC window predictor"; +extern const char kArcWindowPredictorDescription[] = + "Enables the window state and bounds predictor for ARC task windows"; + const char kArcInputOverlayName[] = "Enable ARC Input Overlay"; const char kArcInputOverlayDescription[] = "Enables the input overlay feature for some Android game apps, "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 0c480d7..8c0fa89 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -1988,9 +1988,6 @@ extern const char kSafeBrowsingClientSideDetectionAndroidName[]; extern const char kSafeBrowsingClientSideDetectionAndroidDescription[]; -extern const char kEnhancedProtectionPromoAndroidName[]; -extern const char kEnhancedProtectionPromoAndroidDescription[]; - extern const char kScrollCaptureName[]; extern const char kScrollCaptureDescription[]; @@ -2901,6 +2898,9 @@ extern const char kArcGhostWindowName[]; extern const char kArcGhostWindowDescription[]; +extern const char kArcWindowPredictorName[]; +extern const char kArcWindowPredictorDescription[]; + extern const char kArcInputOverlayName[]; extern const char kArcInputOverlayDescription[];
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc index d5d29c2..9897525 100644 --- a/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -223,7 +223,6 @@ &kDynamicColorAndroid, &kEnableDangerousDownloadDialog, &kEnableDuplicateDownloadDialog, - &kEnhancedProtectionPromoCard, &kExperimentsForAgsa, &kExploreSites, &kFixedUmaSessionResumeOrder, @@ -613,9 +612,6 @@ const base::Feature kEnableMixedContentDownloadDialog{ "EnableMixedContentDownloadDialog", base::FEATURE_DISABLED_BY_DEFAULT}; -const base::Feature kEnhancedProtectionPromoCard{ - "EnhancedProtectionPromoCard", base::FEATURE_DISABLED_BY_DEFAULT}; - const base::Feature kExperimentsForAgsa{"ExperimentsForAgsa", base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser/flags/android/chrome_feature_list.h index 895d26b..99d66cd 100644 --- a/chrome/browser/flags/android/chrome_feature_list.h +++ b/chrome/browser/flags/android/chrome_feature_list.h
@@ -91,7 +91,6 @@ extern const base::Feature kEnableDangerousDownloadDialog; extern const base::Feature kEnableDuplicateDownloadDialog; extern const base::Feature kEnableMixedContentDownloadDialog; -extern const base::Feature kEnhancedProtectionPromoCard; extern const base::Feature kExperimentsForAgsa; extern const base::Feature kExploreSites; extern const base::Feature kFixedUmaSessionResumeOrder;
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java index 90291c3..5bd2bf7 100644 --- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java +++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
@@ -325,7 +325,6 @@ public static final String ENABLE_AUTOMATIC_SNOOZE = "EnableAutomaticSnooze"; public static final String ENABLE_DANGEROUS_DOWNLOAD_DIALOG = "EnableDangerousDownloadDialog"; public static final String ENABLE_DUPLICATE_DOWNLOAD_DIALOG = "EnableDuplicateDownloadDialog"; - public static final String ENHANCED_PROTECTION_PROMO_CARD = "EnhancedProtectionPromoCard"; public static final String ELASTIC_OVERSCROLL = "ElasticOverscroll"; public static final String EXPERIMENTS_FOR_AGSA = "ExperimentsForAgsa"; public static final String EXPLICIT_LANGUAGE_ASK = "ExplicitLanguageAsk";
diff --git a/chrome/browser/geolocation/geolocation_browsertest.cc b/chrome/browser/geolocation/geolocation_browsertest.cc index 64235af..5085b34 100644 --- a/chrome/browser/geolocation/geolocation_browsertest.cc +++ b/chrome/browser/geolocation/geolocation_browsertest.cc
@@ -17,7 +17,6 @@ #include "base/test/simple_test_clock.h" #include "base/time/clock.h" #include "build/build_config.h" -#include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" @@ -31,8 +30,6 @@ #include "components/permissions/permission_request_manager.h" #include "components/permissions/test/permission_request_observer.h" #include "content/public/browser/navigation_controller.h" -#include "content/public/browser/notification_details.h" -#include "content/public/browser/notification_service.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test.h" @@ -65,7 +62,7 @@ // Note: NavigateToURLBlockUntilNavigationsComplete doesn't seem to work for // multiple embedded iframes, as notifications seem to be 'batched'. Instead, we // load and wait one single frame here by calling a javascript function. -class IFrameLoader : public content::NotificationObserver { +class IFrameLoader : public content::WebContentsObserver { public: IFrameLoader(Browser* browser, int iframe_id, const GURL& url); @@ -74,16 +71,14 @@ ~IFrameLoader() override; - // content::NotificationObserver: - void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) override; + // content::WebContentsObserver + void DidStopLoading() override; + void DomOperationResponse(content::RenderFrameHost* render_frame_host, + const std::string& json_string) override; const GURL& iframe_url() const { return iframe_url_; } private: - content::NotificationRegistrar registrar_; - // If true the navigation has completed. bool navigation_completed_; @@ -94,6 +89,8 @@ // The URL for the iframe we just loaded. GURL iframe_url_; + base::RunLoop run_loop; + base::OnceClosure quit_closure_; }; IFrameLoader::IFrameLoader(Browser* browser, int iframe_id, const GURL& url) @@ -101,20 +98,18 @@ javascript_completed_(false) { content::WebContents* web_contents = browser->tab_strip_model()->GetActiveWebContents(); - content::NavigationController* controller = &web_contents->GetController(); - registrar_.Add(this, content::NOTIFICATION_LOAD_STOP, - content::Source<content::NavigationController>(controller)); - registrar_.Add(this, content::NOTIFICATION_DOM_OPERATION_RESPONSE, - content::NotificationService::AllSources()); + content::WebContentsObserver::Observe(web_contents); std::string script(base::StringPrintf( "window.domAutomationController.send(addIFrame(%d, \"%s\"));", iframe_id, url.spec().c_str())); web_contents->GetMainFrame()->ExecuteJavaScriptForTests( base::UTF8ToUTF16(script), base::NullCallback()); - content::RunMessageLoop(); + + quit_closure_ = run_loop.QuitWhenIdleClosure(); + run_loop.Run(); EXPECT_EQ(base::StringPrintf("\"%d\"", iframe_id), javascript_response_); - registrar_.RemoveAll(); + content::WebContentsObserver::Observe(nullptr); // Now that we loaded the iframe, let's fetch its src. script = base::StringPrintf( "window.domAutomationController.send(getIFrameSrc(%d))", iframe_id); @@ -124,18 +119,19 @@ IFrameLoader::~IFrameLoader() { } -void IFrameLoader::Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) { - if (type == content::NOTIFICATION_LOAD_STOP) { - navigation_completed_ = true; - } else if (type == content::NOTIFICATION_DOM_OPERATION_RESPONSE) { - content::Details<std::string> dom_op_result(details); - javascript_response_ = *dom_op_result.ptr(); - javascript_completed_ = true; - } +void IFrameLoader::DidStopLoading() { + navigation_completed_ = true; if (javascript_completed_ && navigation_completed_) - base::RunLoop::QuitCurrentWhenIdleDeprecated(); + std::move(quit_closure_).Run(); +} + +void IFrameLoader::DomOperationResponse( + content::RenderFrameHost* render_frame_host, + const std::string& json_string) { + javascript_response_ = json_string; + javascript_completed_ = true; + if (javascript_completed_ && navigation_completed_) + std::move(quit_closure_).Run(); } } // namespace
diff --git a/chrome/browser/media/webrtc/webrtc_desktop_capture_browsertest.cc b/chrome/browser/media/webrtc/webrtc_desktop_capture_browsertest.cc index 73df2eb..4baf1f4 100644 --- a/chrome/browser/media/webrtc/webrtc_desktop_capture_browsertest.cc +++ b/chrome/browser/media/webrtc/webrtc_desktop_capture_browsertest.cc
@@ -2,18 +2,33 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/barrier_closure.h" +#include "base/bind.h" +#include "base/callback_forward.h" #include "base/command_line.h" #include "base/memory/raw_ptr.h" +#include "base/run_loop.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" +#include "chrome/browser/extensions/api/desktop_capture/desktop_capture_api.h" +#include "chrome/browser/media/webrtc/fake_desktop_media_picker_factory.h" #include "chrome/browser/media/webrtc/webrtc_browsertest_base.h" #include "chrome/browser/media/webrtc/webrtc_browsertest_common.h" +#include "chrome/browser/sessions/tab_restore_service_factory.h" +#include "chrome/browser/sessions/tab_restore_service_load_waiter.h" #include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/browser_tabstrip.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" +#include "components/infobars/content/content_infobar_manager.h" +#include "components/infobars/core/confirm_infobar_delegate.h" +#include "components/infobars/core/infobar.h" +#include "components/infobars/core/infobar_manager.h" +#include "content/public/browser/browser_task_traits.h" +#include "content/public/browser/web_contents.h" #include "content/public/common/content_switches.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" @@ -22,13 +37,182 @@ namespace { static const char kMainWebrtcTestHtmlPage[] = "/webrtc/webrtc_jsep01_test.html"; + +content::WebContents* GetWebContents(Browser* browser, int tab) { + return browser->tab_strip_model()->GetWebContentsAt(tab); +} + +content::DesktopMediaID GetDesktopMediaIDForScreen() { + return content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN, + content::DesktopMediaID::kNullId); +} + +content::DesktopMediaID GetDesktopMediaIDForTab(Browser* browser, int tab) { + content::RenderFrameHost* main_frame = + GetWebContents(browser, tab)->GetMainFrame(); + return content::DesktopMediaID( + content::DesktopMediaID::TYPE_WEB_CONTENTS, + content::DesktopMediaID::kNullId, + content::WebContentsMediaCaptureId(main_frame->GetProcess()->GetID(), + main_frame->GetRoutingID())); +} + +infobars::ContentInfoBarManager* GetInfoBarManager(Browser* browser, int tab) { + return infobars::ContentInfoBarManager::FromWebContents( + GetWebContents(browser, tab)); +} + +infobars::ContentInfoBarManager* GetInfoBarManager( + content::WebContents* contents) { + return infobars::ContentInfoBarManager::FromWebContents(contents); +} + +ConfirmInfoBarDelegate* GetDelegate(Browser* browser, int tab) { + return static_cast<ConfirmInfoBarDelegate*>( + GetInfoBarManager(browser, tab)->infobar_at(0)->delegate()); +} + +class InfobarUIChangeObserver : public TabStripModelObserver { + public: + explicit InfobarUIChangeObserver(Browser* browser) : browser_{browser} { + for (int tab = 0; tab < browser_->tab_strip_model()->count(); ++tab) { + auto* contents = browser_->tab_strip_model()->GetWebContentsAt(tab); + observers_[contents] = + std::make_unique<InfoBarChangeObserver>(base::BindOnce( + &InfobarUIChangeObserver::EraseObserver, base::Unretained(this))); + GetInfoBarManager(contents)->AddObserver(observers_[contents].get()); + } + browser_->tab_strip_model()->AddObserver(this); + } + + ~InfobarUIChangeObserver() override { + for (auto& observer_iter : observers_) { + auto* contents = observer_iter.first; + auto* observer = observer_iter.second.get(); + + GetInfoBarManager(contents)->RemoveObserver(observer); + } + browser_->tab_strip_model()->RemoveObserver(this); + observers_.clear(); + } + + void ExpectCalls(size_t expected_changes) { + run_loop_ = std::make_unique<base::RunLoop>(); + barrier_closure_ = + base::BarrierClosure(expected_changes, run_loop_->QuitClosure()); + for (auto& observer : observers_) { + observer.second->SetCallback(barrier_closure_); + } + } + + void Wait() { run_loop_->Run(); } + + // TabStripModelObserver + void OnTabStripModelChanged( + TabStripModel* tab_strip_model, + const TabStripModelChange& change, + const TabStripSelectionChange& selection) override { + if (change.type() == TabStripModelChange::kInserted) { + for (const auto& contents_with_index : change.GetInsert()->contents) { + auto* contents = contents_with_index.contents; + if (observers_.find(contents) == observers_.end()) { + observers_[contents] = std::make_unique<InfoBarChangeObserver>( + base::BindOnce(&InfobarUIChangeObserver::EraseObserver, + base::Unretained(this))); + GetInfoBarManager(contents)->AddObserver(observers_[contents].get()); + if (!barrier_closure_.is_null()) { + observers_[contents]->SetCallback(barrier_closure_); + } + } + } + } + } + void TabChangedAt(content::WebContents* contents, + int index, + TabChangeType change_type) override { + if (observers_.find(contents) == observers_.end()) { + observers_[contents] = + std::make_unique<InfoBarChangeObserver>(base::BindOnce( + &InfobarUIChangeObserver::EraseObserver, base::Unretained(this))); + GetInfoBarManager(contents)->AddObserver(observers_[contents].get()); + if (!barrier_closure_.is_null()) { + observers_[contents]->SetCallback(barrier_closure_); + } + } + } + + private: + class InfoBarChangeObserver; + + public: + void EraseObserver(InfoBarChangeObserver* observer) { + auto iter = std::find_if(observers_.begin(), observers_.end(), + [observer](const auto& observer_iter) { + return observer_iter.second.get() == observer; + }); + observers_.erase(iter); + } + + private: + class InfoBarChangeObserver : public infobars::InfoBarManager::Observer { + public: + using ShutdownCallback = base::OnceCallback<void(InfoBarChangeObserver*)>; + + explicit InfoBarChangeObserver(ShutdownCallback shutdown_callback) + : shutdown_callback_{std::move(shutdown_callback)} {} + + ~InfoBarChangeObserver() override = default; + + void SetCallback(base::RepeatingClosure change_closure) { + DCHECK(!change_closure.is_null()); + change_closure_ = change_closure; + } + + void OnInfoBarAdded(infobars::InfoBar* infobar) override { + DCHECK(!change_closure_.is_null()); + change_closure_.Run(); + } + + void OnInfoBarRemoved(infobars::InfoBar* infobar, bool animate) override { + DCHECK(!change_closure_.is_null()); + change_closure_.Run(); + } + + void OnInfoBarReplaced(infobars::InfoBar* old_infobar, + infobars::InfoBar* new_infobar) override { + NOTREACHED(); + } + + void OnManagerShuttingDown(infobars::InfoBarManager* manager) override { + manager->RemoveObserver(this); + DCHECK(!shutdown_callback_.is_null()); + std::move(shutdown_callback_).Run(this); + } + + private: + base::RepeatingClosure change_closure_; + ShutdownCallback shutdown_callback_; + }; + + std::unique_ptr<base::RunLoop> run_loop_; + std::map<content::WebContents*, std::unique_ptr<InfoBarChangeObserver>> + observers_; + Browser* browser_; + base::RepeatingClosure barrier_closure_; +}; + } // namespace // Top-level integration test for WebRTC. Uses an actual desktop capture -// extension to capture whole screen. +// extension to capture the whole screen or a tab. class WebRtcDesktopCaptureBrowserTest : public WebRtcTestBase { public: - WebRtcDesktopCaptureBrowserTest() : left_tab_(nullptr), right_tab_(nullptr) {} + using MediaIDCallback = base::OnceCallback<content::DesktopMediaID()>; + + WebRtcDesktopCaptureBrowserTest() { + extensions::DesktopCaptureChooseDesktopMediaFunction:: + SetPickerFactoryForTests(&picker_factory_); + } void SetUpInProcessBrowserTestFixture() override { DetectErrorsInJavaScript(); // Look for errors in our rather complex js. @@ -46,20 +230,69 @@ } protected: - void DetectVideoAndHangUp() { - StartDetectingVideo(left_tab_, "remote-view"); - StartDetectingVideo(right_tab_, "remote-view"); -#if !defined(OS_MAC) - // Video is choppy on Mac OS X. http://crbug.com/443542. - WaitForVideoToPlay(left_tab_); - WaitForVideoToPlay(right_tab_); -#endif - HangUp(left_tab_); - HangUp(right_tab_); + void InitializeTabSharingForFirstTab(MediaIDCallback media_id_callback, + InfobarUIChangeObserver* observer) { + ASSERT_TRUE(embedded_test_server()->Start()); + LoadDesktopCaptureExtension(); + auto* first_tab = OpenTestPageInNewTab(kMainWebrtcTestHtmlPage); + OpenTestPageInNewTab(kMainWebrtcTestHtmlPage); + + FakeDesktopMediaPickerFactory::TestFlags test_flags{ + .expect_screens = true, + .expect_windows = true, + .expect_tabs = true, + .selected_source = std::move(media_id_callback).Run(), + }; + picker_factory_.SetTestFlags(&test_flags, /*tests_count=*/1); + + std::string stream_id = GetDesktopMediaStream(first_tab); + EXPECT_NE(stream_id, ""); + + LOG(INFO) << "Opened desktop media stream, got id " << stream_id; + + const std::string constraints = + "{audio: false, video: {mandatory: {chromeMediaSource: 'desktop'," + "chromeMediaSourceId: '" + + stream_id + "'}}}"; + + // Should create 3 infobars if a tab (webcontents) is shared! + if (observer) + observer->ExpectCalls(3); + + EXPECT_TRUE(GetUserMediaWithSpecificConstraintsAndAcceptIfPrompted( + first_tab, constraints)); + + if (observer) + observer->Wait(); } - raw_ptr<content::WebContents> left_tab_; - raw_ptr<content::WebContents> right_tab_; + void DetectVideoAndHangUp(content::WebContents* first_tab, + content::WebContents* second_tab) { + StartDetectingVideo(first_tab, "remote-view"); + StartDetectingVideo(second_tab, "remote-view"); +#if !defined(OS_MAC) + // Video is choppy on Mac OS X. http://crbug.com/443542. + WaitForVideoToPlay(first_tab); + WaitForVideoToPlay(second_tab); +#endif + HangUp(first_tab); + HangUp(second_tab); + } + + void RunP2PScreenshareWhileSharing(MediaIDCallback media_id_callback) { + InitializeTabSharingForFirstTab(std::move(media_id_callback), nullptr); + auto* first_tab = browser()->tab_strip_model()->GetWebContentsAt(1); + auto* second_tab = browser()->tab_strip_model()->GetWebContentsAt(2); + GetUserMediaAndAccept(second_tab); + + SetupPeerconnectionWithLocalStream(first_tab); + SetupPeerconnectionWithLocalStream(second_tab); + NegotiateCall(first_tab, second_tab); + VerifyStatsGeneratedCallback(second_tab); + DetectVideoAndHangUp(first_tab, second_tab); + } + + FakeDesktopMediaPickerFactory picker_factory_; }; // TODO(crbug.com/796889): Enable on Mac when thread check crash is fixed. @@ -68,25 +301,55 @@ // of lacros-chrome is complete. // TODO(crbug.com/1225911): Test is flaky on Linux. IN_PROC_BROWSER_TEST_F(WebRtcDesktopCaptureBrowserTest, - DISABLED_RunsScreenshareFromOneTabToAnother) { - ASSERT_TRUE(embedded_test_server()->Start()); - LoadDesktopCaptureExtension(); - left_tab_ = OpenTestPageInNewTab(kMainWebrtcTestHtmlPage); - std::string stream_id = GetDesktopMediaStream(left_tab_); - EXPECT_NE(stream_id, ""); + DISABLED_RunP2PScreenshareWhileSharingScreen) { + RunP2PScreenshareWhileSharing(base::BindOnce(GetDesktopMediaIDForScreen)); +} - LOG(INFO) << "Opened desktop media stream, got id " << stream_id; +IN_PROC_BROWSER_TEST_F(WebRtcDesktopCaptureBrowserTest, + RunP2PScreenshareWhileSharingTab) { + RunP2PScreenshareWhileSharing( + base::BindOnce(GetDesktopMediaIDForTab, base::Unretained(browser()), 2)); +} - const std::string constraints = - "{audio: false, video: {mandatory: {chromeMediaSource: 'desktop'," - "chromeMediaSourceId: '" + - stream_id + "'}}}"; - EXPECT_TRUE(GetUserMediaWithSpecificConstraintsAndAcceptIfPrompted( - left_tab_, constraints)); - right_tab_ = OpenTestPageAndGetUserMediaInNewTab(kMainWebrtcTestHtmlPage); - SetupPeerconnectionWithLocalStream(left_tab_); - SetupPeerconnectionWithLocalStream(right_tab_); - NegotiateCall(left_tab_, right_tab_); - VerifyStatsGeneratedCallback(right_tab_); - DetectVideoAndHangUp(); +IN_PROC_BROWSER_TEST_F(WebRtcDesktopCaptureBrowserTest, + SwitchSharedTabBackAndForth) { + InfobarUIChangeObserver observer(browser()); + + InitializeTabSharingForFirstTab( + base::BindOnce(GetDesktopMediaIDForTab, base::Unretained(browser()), 2), + &observer); + + // Should delete 3 infobars and create 3 new! + observer.ExpectCalls(6); + // Switch shared tab from 2 to 0. + GetDelegate(browser(), 0)->Cancel(); + observer.Wait(); + + // Should delete 3 infobars and create 3 new! + observer.ExpectCalls(6); + // Switch shared tab from 0 to 2. + GetDelegate(browser(), 2)->Cancel(); + observer.Wait(); +} + +IN_PROC_BROWSER_TEST_F(WebRtcDesktopCaptureBrowserTest, + CloseAndReopenNonSharedTab) { + InfobarUIChangeObserver observer(browser()); + + InitializeTabSharingForFirstTab( + base::BindOnce(GetDesktopMediaIDForTab, base::Unretained(browser()), 2), + &observer); + + // Should delete 1 infobar. + observer.ExpectCalls(1); + // Close non-shared and non-sharing, i.e., unrelated tab + browser()->tab_strip_model()->CloseWebContentsAt( + 0, TabStripModel::CloseTypes::CLOSE_CREATE_HISTORICAL_TAB); + observer.Wait(); + + // Should create 1 infobar. + observer.ExpectCalls(1); + // Restore tab + chrome::RestoreTab(browser()); + observer.Wait(); }
diff --git a/chrome/browser/password_manager/password_manager_captured_sites_interactive_uitest.cc b/chrome/browser/password_manager/password_manager_captured_sites_interactive_uitest.cc index 7abf186..099ebd7 100644 --- a/chrome/browser/password_manager/password_manager_captured_sites_interactive_uitest.cc +++ b/chrome/browser/password_manager/password_manager_captured_sites_interactive_uitest.cc
@@ -222,6 +222,8 @@ kAutofillUseUnassociatedListedElements}, {}); command_line->AppendSwitch(autofill::switches::kShowAutofillSignatures); + captured_sites_test_utils::TestRecipeReplayer::SetUpHostResolverRules( + command_line); captured_sites_test_utils::TestRecipeReplayer::SetUpCommandLine( command_line); }
diff --git a/chrome/browser/policy/chrome_browser_policy_connector.cc b/chrome/browser/policy/chrome_browser_policy_connector.cc index 9814e5b..85abf709 100644 --- a/chrome/browser/policy/chrome_browser_policy_connector.cc +++ b/chrome/browser/policy/chrome_browser_policy_connector.cc
@@ -285,6 +285,7 @@ base::ThreadPool::CreateSequencedTaskRunner( {base::MayBlock(), base::TaskPriority::BEST_EFFORT}), PolicyPerProfileFilter::kFalse); + device_account_policy_loader_ = loader.get(); return std::make_unique<AsyncPolicyProvider>(GetSchemaRegistry(), std::move(loader)); #elif defined(OS_POSIX) && !defined(OS_ANDROID)
diff --git a/chrome/browser/policy/chrome_browser_policy_connector.h b/chrome/browser/policy/chrome_browser_policy_connector.h index 9bc7974c..d493b44 100644 --- a/chrome/browser/policy/chrome_browser_policy_connector.h +++ b/chrome/browser/policy/chrome_browser_policy_connector.h
@@ -25,6 +25,7 @@ #if BUILDFLAG(IS_CHROMEOS_LACROS) #include "chrome/browser/lacros/device_settings_lacros.h" +#include "components/policy/core/common/policy_loader_lacros.h" #endif // BUILDFLAG(IS_CHROMEOS_LACROS) class PrefService; @@ -117,6 +118,10 @@ // The device settings used in Lacros. crosapi::mojom::DeviceSettings* GetDeviceSettings() const; + + PolicyLoaderLacros* device_account_policy_loader() { + return device_account_policy_loader_; + } #endif protected: @@ -176,6 +181,8 @@ #if BUILDFLAG(IS_CHROMEOS_LACROS) std::unique_ptr<DeviceSettingsLacros> device_settings_ = nullptr; + // Owned by |platform_provider_|. + PolicyLoaderLacros* device_account_policy_loader_ = nullptr; #endif // Holds a callback to |ChromeBrowserCloudManagementController::Init| so that
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/command_handler.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/command_handler.js index b298716..9997f4e 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/command_handler.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/command_handler.js
@@ -283,11 +283,20 @@ return false; case 'enableChromeVoxArcSupportForCurrentApp': chrome.accessibilityPrivate.setNativeChromeVoxArcSupportForCurrentApp( - true); + true, (response) => {}); break; case 'disableChromeVoxArcSupportForCurrentApp': chrome.accessibilityPrivate.setNativeChromeVoxArcSupportForCurrentApp( - false); + false, (response) => { + if (response === + chrome.accessibilityPrivate.SetNativeChromeVoxResponse + .TALKBACK_NOT_INSTALLED) { + ChromeVox.braille.write(NavBraille.fromText( + Msgs.getMsg('announce_install_talkback'))); + ChromeVox.tts.speak( + Msgs.getMsg('announce_install_talkback'), QueueMode.FLUSH); + } + }); break; case 'showTtsSettings': chrome.accessibilityPrivate.openSettingsSubpage(
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/desktop_automation_handler.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/desktop_automation_handler.js index 8efdd63..70689d6 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/desktop_automation_handler.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/desktop_automation_handler.js
@@ -673,6 +673,18 @@ override = !!walker || override; } + // Autofill popup menu items are always announced on selection events, + // independent of focus. + // The AutofillPopupSeparatorView is intentionally omitted because it + // cannot be focused. + if (target.className === 'AutofillPopupSuggestionView' || + target.className === 'PasswordPopupSuggestionView' || + target.className === 'AutofillPopupFooterView' || + target.className === 'AutofillPopupWarningView' || + target.className === 'AutofillPopupBaseView') { + override = true; + } + // The popup view associated with a datalist element does not descend // from the input with which it is associated. if (focus.role === RoleType.TEXT_FIELD_WITH_COMBO_BOX &&
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/chromevox_strings.grdp b/chrome/browser/resources/chromeos/accessibility/strings/chromevox_strings.grdp index 3eb5f53..b4a2fc7 100644 --- a/chrome/browser/resources/chromeos/accessibility/strings/chromevox_strings.grdp +++ b/chrome/browser/resources/chromeos/accessibility/strings/chromevox_strings.grdp
@@ -3378,4 +3378,7 @@ <message desc="Spoken to describe a <abbr> tag. For example, <abbr title='uniform resource locator'>URL/<abbr> would be spoken as 'URL, uniform resource locator, Abbreviation'" name="IDS_CHROMEVOX_TAG_ABBR" is_accessibility_with_no_ui="true"> Abbreviation </message> + <message desc="Spoken message asking users to install the Accessibility Suite app from the Play Store when users tried to turn on Talkback without installing Accessibility Suite." name="IDS_CHROMEVOX_ANNOUNCE_INSTALL_TALKBACK" is_accessibility_with_no_ui="true"> + TalkBack is currently not installed. Please install Android AccessibilitySuite through Play Store and try again. + </message> </grit-part>
diff --git a/chrome/browser/resources/settings/site_settings/all_sites.html b/chrome/browser/resources/settings/site_settings/all_sites.html index 3389730..84b21dda 100644 --- a/chrome/browser/resources/settings/site_settings/all_sites.html +++ b/chrome/browser/resources/settings/site_settings/all_sites.html
@@ -83,7 +83,8 @@ <cr-lazy-render id="menu"> <template> <cr-action-menu role-description="$i18n{menu}"> - <button class="dropdown-item" role="menuitem" + <button hidden$="[[actionMenuModel_.isPartitioned]]" + class="dropdown-item" role="menuitem" on-click="onConfirmResetSettings_"> $i18n{siteSettingsSiteGroupReset} </button>
diff --git a/chrome/browser/resources/settings/site_settings/all_sites.ts b/chrome/browser/resources/settings/site_settings/all_sites.ts index 4930e99..fb06f49 100644 --- a/chrome/browser/resources/settings/site_settings/all_sites.ts +++ b/chrome/browser/resources/settings/site_settings/all_sites.ts
@@ -44,6 +44,7 @@ index: number, item: SiteGroup, origin: string, + isPartitioned: boolean, path: string, target: HTMLElement, }; @@ -459,7 +460,7 @@ } onConfirmRemoveSite_(e: Event) { - const {index, actionScope, origin} = this.actionMenuModel_!; + const {index, actionScope, origin, isPartitioned} = this.actionMenuModel_!; const siteGroupToUpdate = this.filteredList_[index]; const updatedSiteGroup: SiteGroup = { @@ -470,17 +471,29 @@ }; if (actionScope === 'origin') { - this.browserProxy.recordAction(AllSitesAction2.REMOVE_ORIGIN); - this.browserProxy.clearOriginDataAndCookies(this.toUrl(origin)!.href); - this.resetPermissionsForOrigin_(origin); + if (isPartitioned) { + this.browserProxy.recordAction( + AllSitesAction2.REMOVE_ORIGIN_PARTITIONED); + this.browserProxy.clearPartitionedOriginDataAndCookies( + this.toUrl(origin)!.href, siteGroupToUpdate.etldPlus1); - updatedSiteGroup.origins = - siteGroupToUpdate.origins.filter(o => o.origin !== origin); + } else { + this.browserProxy.recordAction(AllSitesAction2.REMOVE_ORIGIN); + this.browserProxy.clearUnpartitionedOriginDataAndCookies( + this.toUrl(origin)!.href); + this.resetPermissionsForOrigin_(origin); + } + updatedSiteGroup.origins = siteGroupToUpdate.origins.filter( + o => (o.isPartitioned !== isPartitioned || o.origin !== origin)); + + console.log(updatedSiteGroup.origins); updatedSiteGroup.hasInstalledPWA = updatedSiteGroup.origins.some(o => o.isInstalled); updatedSiteGroup.numCookies -= - siteGroupToUpdate.origins.find(o => o.origin === origin)!.numCookies; - + siteGroupToUpdate.origins + .find( + o => o.isPartitioned === isPartitioned && + o.origin === origin)!.numCookies; } else { this.browserProxy.recordAction(AllSitesAction2.REMOVE_SITE_GROUP); this.browserProxy.clearEtldPlus1DataAndCookies( @@ -624,6 +637,14 @@ const singleOriginSite = !originScoped && this.actionMenuModel_.item.origins.length === 1; + if (this.actionMenuModel_.isPartitioned) { + assert(originScoped); + return loadTimeData.substituteString(this.i18n( + 'siteSettingsRemoveSiteOriginPartitionedDialogTitle', + this.originRepresentation(this.actionMenuModel_.origin), + this.originRepresentation(this.actionMenuModel_.item.etldPlus1))); + } + const numInstalledApps = this.actionMenuModel_.item.origins .filter( @@ -790,6 +811,7 @@ numCookies: siteGroupToUpdate.numCookies, hasPermissionSettings: false, isInstalled: false, + isPartitioned: false, }; updatedSiteGroup.origins.push(originPlaceHolder); this.set('filteredList_.' + index, updatedSiteGroup); @@ -835,7 +857,8 @@ * @param origin The origin of the target origin that should be cleared. */ private clearDataForOrigin_(index: number, origin: string) { - this.browserProxy.clearOriginDataAndCookies(this.toUrl(origin)!.href); + this.browserProxy.clearUnpartitionedOriginDataAndCookies( + this.toUrl(origin)!.href); const siteGroupToUpdate = this.filteredList_[index]; const updatedSiteGroup: SiteGroup = {
diff --git a/chrome/browser/resources/settings/site_settings/constants.ts b/chrome/browser/resources/settings/site_settings/constants.ts index 7edb50c..6915d09 100644 --- a/chrome/browser/resources/settings/site_settings/constants.ts +++ b/chrome/browser/resources/settings/site_settings/constants.ts
@@ -139,6 +139,7 @@ ENTER_SITE_DETAILS = 6, REMOVE_SITE_GROUP = 7, REMOVE_ORIGIN = 8, + REMOVE_ORIGIN_PARTITIONED = 9, } /**
diff --git a/chrome/browser/resources/settings/site_settings/site_entry.html b/chrome/browser/resources/settings/site_settings/site_entry.html index 17b299c..43fea4e 100644 --- a/chrome/browser/resources/settings/site_settings/site_entry.html +++ b/chrome/browser/resources/settings/site_settings/site_entry.html
@@ -102,7 +102,8 @@ <template is="dom-repeat" items="[[siteGroup.origins]]"> <div class="list-item hr"> <div class="start row-aligned list-item origin-link" - on-click="onOriginTap_" actionable> + on-click="onOriginTap_" + actionable$="[[!item.isPartitioned]]"> <site-favicon url="[[item.origin]]"></site-favicon> <div class="site-representation middle text-elide"> <span id="originSiteRepresentation" @@ -133,8 +134,13 @@ · [[originCookiesItem_(cookiesNum_.*, index)]] </span> + <span class="secondary" hidden$="[[!item.isPartitioned]]"> + · + $i18n{siteSettingsSiteEntryPartitionedLabel} + </span> </div> <cr-icon-button class="subpage-arrow" + hidden$="[[item.isPartitioned]]" aria-labelledby$="originSiteRepresentation" aria-roledescription= "$i18n{subpageArrowRoleDescription}" @@ -160,6 +166,7 @@ id="removeOriginButton" title$="[[getRemoveOriginButtonTitle_(item.origin)]]" data-origin$="[[item.origin]]" data-context="origin" + data-partitioned$="[[item.isPartitioned]]" on-click="onRemove_" focus-row-control focus-type="remove"> </cr-icon-button>
diff --git a/chrome/browser/resources/settings/site_settings/site_entry.ts b/chrome/browser/resources/settings/site_settings/site_entry.ts index 939fb79..aa6261b 100644 --- a/chrome/browser/resources/settings/site_settings/site_entry.ts +++ b/chrome/browser/resources/settings/site_settings/site_entry.ts
@@ -179,7 +179,8 @@ return false; } if (siteGroup.origins.length > 1 || - siteGroup.numCookies > siteGroup.origins[0].numCookies) { + siteGroup.numCookies > siteGroup.origins[0].numCookies || + siteGroup.origins.some(o => o.isPartitioned)) { return true; } return false; @@ -360,6 +361,9 @@ * A handler for selecting a site (by clicking on the origin). */ private onOriginTap_(e: RepeaterEvent) { + if (this.siteGroup.origins[e.model.index].isPartitioned) { + return; + } this.navigateToSiteDetails_(this.siteGroup.origins[e.model.index].origin); this.browserProxy.recordAction(AllSitesAction2.ENTER_SITE_DETAILS); chrome.metricsPrivate.recordUserAction('AllSites_EnterSiteDetails'); @@ -407,6 +411,7 @@ index: this.listIndex, item: this.siteGroup, origin: (e.target as HTMLElement).dataset['origin'], + isPartitioned: (e.target as HTMLElement).dataset['partitioned'], actionScope: (e.target as HTMLElement).dataset['context'], }); } @@ -417,6 +422,8 @@ index: this.listIndex, item: this.siteGroup, origin: (e.target as HTMLElement).dataset['origin'], + isPartitioned: + (e.target as HTMLElement).dataset['partitioned'] !== undefined, actionScope: (e.target as HTMLElement).dataset['context'], }); } @@ -468,16 +475,22 @@ (o1: OriginInfo, o2: OriginInfo) => number { if (sortMethod === SortMethod.MOST_VISITED) { return (origin1, origin2) => { - return origin2.engagement - origin1.engagement; + return (origin1.isPartitioned ? 1 : 0) - + (origin2.isPartitioned ? 1 : 0) || + origin2.engagement - origin1.engagement; }; } else if (sortMethod === SortMethod.STORAGE) { return (origin1, origin2) => { - return origin2.usage - origin1.usage || + return (origin1.isPartitioned ? 1 : 0) - + (origin2.isPartitioned ? 1 : 0) || + origin2.usage - origin1.usage || origin2.numCookies - origin1.numCookies; }; } else if (sortMethod === SortMethod.NAME) { return (origin1, origin2) => { - return origin1.origin.localeCompare(origin2.origin); + return (origin1.isPartitioned ? 1 : 0) - + (origin2.isPartitioned ? 1 : 0) || + origin1.origin.localeCompare(origin2.origin); }; } assertNotReached();
diff --git a/chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.ts b/chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.ts index a9dc98ed..d135d6e 100644 --- a/chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.ts +++ b/chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.ts
@@ -51,6 +51,7 @@ numCookies: number, hasPermissionSettings: boolean, isInstalled: boolean, + isPartitioned: boolean }; /** @@ -424,10 +425,18 @@ clearEtldPlus1DataAndCookies(etldPlus1: string): void; /** - * Clears all the web storage data and cookies for a given origin. + * Clears all the unpartitioned web storage data and cookies for a given + * origin. * @param origin The origin to clear data from. */ - clearOriginDataAndCookies(origin: string): void; + clearUnpartitionedOriginDataAndCookies(origin: string): void; + + /** + * Clears all the storage for |origin| which is partitioned on |etldPlus1|. + * @param origin The origin to clear data from. + * @param etldPlus1 The etld+1 which the data is partitioned for. + */ + clearPartitionedOriginDataAndCookies(origin: string, etldPlus1: string): void; /** * Record All Sites Page action for metrics. @@ -577,8 +586,12 @@ chrome.send('clearEtldPlus1DataAndCookies', [etldPlus1]); } - clearOriginDataAndCookies(origin: string) { - chrome.send('clearUsage', [origin]); + clearUnpartitionedOriginDataAndCookies(origin: string) { + chrome.send('clearUnpartitionedUsage', [origin]); + } + + clearPartitionedOriginDataAndCookies(origin: string, etldPlus1: string) { + chrome.send('clearPartitionedUsage', [origin, etldPlus1]); } recordAction(action: number) {
diff --git a/chrome/browser/ssl/ssl_browsertest.cc b/chrome/browser/ssl/ssl_browsertest.cc index 1f02839..b117c4a 100644 --- a/chrome/browser/ssl/ssl_browsertest.cc +++ b/chrome/browser/ssl/ssl_browsertest.cc
@@ -3098,7 +3098,7 @@ } class SSLUITestWaitForDOMNotification : public SSLUITestIgnoreCertErrors, - public content::NotificationObserver { + public content::WebContentsObserver { public: SSLUITestWaitForDOMNotification() : SSLUITestIgnoreCertErrors(), run_loop_(nullptr) {} @@ -3107,13 +3107,10 @@ delete; SSLUITestWaitForDOMNotification& operator=( const SSLUITestWaitForDOMNotification&) = delete; - - ~SSLUITestWaitForDOMNotification() override { registrar_.RemoveAll(); } + ~SSLUITestWaitForDOMNotification() override = default; void SetUpOnMainThread() override { SSLUITestIgnoreCertErrors::SetUpOnMainThread(); - registrar_.Add(this, content::NOTIFICATION_DOM_OPERATION_RESPONSE, - content::NotificationService::AllSources()); } void set_expected_notification(const std::string& expected_notification) { @@ -3121,22 +3118,20 @@ } void set_run_loop(base::RunLoop* run_loop) { run_loop_ = run_loop; } + void observe(content::WebContents* web_contents) { + content::WebContentsObserver::Observe(web_contents); + } - // content::NotificationObserver - void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) override { + // content::WebContentsObserver + void DomOperationResponse(content::RenderFrameHost* render_frame_host, + const std::string& json_string) override { DCHECK(run_loop_); - if (type == content::NOTIFICATION_DOM_OPERATION_RESPONSE) { - content::Details<std::string> dom_op_result(details); - if (*dom_op_result.ptr() == expected_notification_) { - run_loop_->Quit(); - } + if (json_string == expected_notification_) { + run_loop_->Quit(); } } private: - content::NotificationRegistrar registrar_; std::string expected_notification_; raw_ptr<base::RunLoop> run_loop_; }; @@ -3180,6 +3175,7 @@ // chain passes through HTTP, the page should be marked as mixed // content. set_expected_notification("\"mixed-image-loaded\""); + observe(tab); set_run_loop(&run_loop); ASSERT_TRUE(content::ExecuteScript( tab,
diff --git a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/SigninPromoController.java b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/SigninPromoController.java index 7595fc4..19fda325 100644 --- a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/SigninPromoController.java +++ b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/SigninPromoController.java
@@ -160,8 +160,6 @@ if (resetAfterMs <= 0 || lastShownTime <= 0) return; if (currentTime - lastShownTime >= resetAfterMs) { - SharedPreferencesManager.getInstance().writeInt( - getPromoShowCountPreferenceName(SigninAccessPoint.NTP_CONTENT_SUGGESTIONS), 0); SharedPreferencesManager.getInstance().removeKey( ChromePreferenceKeys.SIGNIN_PROMO_NTP_FIRST_SHOWN_TIME); SharedPreferencesManager.getInstance().removeKey( @@ -192,13 +190,7 @@ } private static boolean canShowNTPPromo() { - int maxImpressions = ChromeFeatureList.getFieldTrialParamByFeatureAsInt( - ChromeFeatureList.ENHANCED_PROTECTION_PROMO_CARD, "MaxSigninPromoImpressions", - Integer.MAX_VALUE); - if (SharedPreferencesManager.getInstance().readInt( - getPromoShowCountPreferenceName(SigninAccessPoint.NTP_CONTENT_SUGGESTIONS)) - >= maxImpressions - || timeElapsedSinceFirstShownExceedsLimit()) { + if (timeElapsedSinceFirstShownExceedsLimit()) { return false; } @@ -249,8 +241,6 @@ case SigninAccessPoint.BOOKMARK_MANAGER: return ChromePreferenceKeys.SYNC_PROMO_SHOW_COUNT.createKey( AccessPointId.BOOKMARKS); - case SigninAccessPoint.NTP_CONTENT_SUGGESTIONS: - return ChromePreferenceKeys.SYNC_PROMO_SHOW_COUNT.createKey(AccessPointId.NTP); case SigninAccessPoint.SETTINGS: return ChromePreferenceKeys.SYNC_PROMO_SHOW_COUNT.createKey(AccessPointId.SETTINGS); default: @@ -467,7 +457,8 @@ /** Increases promo show count by one. */ public void increasePromoShowCount() { - if (mAccessPoint != SigninAccessPoint.RECENT_TABS) { + if (mAccessPoint != SigninAccessPoint.RECENT_TABS + && mAccessPoint != SigninAccessPoint.NTP_CONTENT_SUGGESTIONS) { SharedPreferencesManager.getInstance().incrementInt( getPromoShowCountPreferenceName(mAccessPoint)); }
diff --git a/chrome/browser/ui/android/signin/junit/src/org/chromium/chrome/browser/ui/signin/SigninPromoControllerTest.java b/chrome/browser/ui/android/signin/junit/src/org/chromium/chrome/browser/ui/signin/SigninPromoControllerTest.java index 38ffc33b..b932bac 100644 --- a/chrome/browser/ui/android/signin/junit/src/org/chromium/chrome/browser/ui/signin/SigninPromoControllerTest.java +++ b/chrome/browser/ui/android/signin/junit/src/org/chromium/chrome/browser/ui/signin/SigninPromoControllerTest.java
@@ -79,9 +79,6 @@ IdentityServicesProvider.setInstanceForTests(mock(IdentityServicesProvider.class)); when(IdentityServicesProvider.get().getIdentityManager(Profile.getLastUsedRegularProfile())) .thenReturn(mIdentityManagerMock); - mSharedPreferencesManager.writeInt(SigninPromoController.getPromoShowCountPreferenceName( - SigninAccessPoint.NTP_CONTENT_SUGGESTIONS), - 0); mSharedPreferencesManager.writeLong( ChromePreferenceKeys.SIGNIN_PROMO_NTP_FIRST_SHOWN_TIME, 0L); mSharedPreferencesManager.writeLong( @@ -134,40 +131,6 @@ } @Test - public void shouldShowNTPSyncPromoWhenCountLimitIsNotExceeded() { - FeatureList.TestValues testValues = new FeatureList.TestValues(); - testValues.addFieldTrialParamOverride(ChromeFeatureList.ENHANCED_PROTECTION_PROMO_CARD, - "MaxSigninPromoImpressions", Integer.toString(MAX_SIGN_IN_PROMO_IMPRESSIONS)); - testValues.addFeatureFlagOverride(ChromeFeatureList.ENHANCED_PROTECTION_PROMO_CARD, true); - testValues.addFeatureFlagOverride( - ChromeFeatureList.FORCE_DISABLE_EXTENDED_SYNC_PROMOS, false); - FeatureList.setTestValues(testValues); - mSharedPreferencesManager.writeInt(SigninPromoController.getPromoShowCountPreferenceName( - SigninAccessPoint.NTP_CONTENT_SUGGESTIONS), - MAX_SIGN_IN_PROMO_IMPRESSIONS - 1); - - Assert.assertTrue( - SigninPromoController.canShowSyncPromo(SigninAccessPoint.NTP_CONTENT_SUGGESTIONS)); - } - - @Test - public void shouldHideNTPSyncPromoWhenCountLimitIsExceeded() { - FeatureList.TestValues testValues = new FeatureList.TestValues(); - testValues.addFieldTrialParamOverride(ChromeFeatureList.ENHANCED_PROTECTION_PROMO_CARD, - "MaxSigninPromoImpressions", Integer.toString(MAX_SIGN_IN_PROMO_IMPRESSIONS)); - testValues.addFeatureFlagOverride(ChromeFeatureList.ENHANCED_PROTECTION_PROMO_CARD, true); - testValues.addFeatureFlagOverride( - ChromeFeatureList.FORCE_DISABLE_EXTENDED_SYNC_PROMOS, false); - FeatureList.setTestValues(testValues); - mSharedPreferencesManager.writeInt(SigninPromoController.getPromoShowCountPreferenceName( - SigninAccessPoint.NTP_CONTENT_SUGGESTIONS), - MAX_SIGN_IN_PROMO_IMPRESSIONS); - - Assert.assertFalse( - SigninPromoController.canShowSyncPromo(SigninAccessPoint.NTP_CONTENT_SUGGESTIONS)); - } - - @Test public void shouldShowNTPSyncPromoWithoutTimeSinceFirstShownLimit() { final long firstShownTime = System.currentTimeMillis() - TIME_SINCE_FIRST_SHOWN_LIMIT_MS - 1; @@ -225,10 +188,6 @@ Assert.assertEquals(lastShownTime, SharedPreferencesManager.getInstance().readLong( ChromePreferenceKeys.SIGNIN_PROMO_NTP_LAST_SHOWN_TIME)); - Assert.assertEquals(MAX_SIGN_IN_PROMO_IMPRESSIONS, - SharedPreferencesManager.getInstance().readInt( - SigninPromoController.getPromoShowCountPreferenceName( - SigninAccessPoint.NTP_CONTENT_SUGGESTIONS))); } @Test @@ -250,10 +209,6 @@ Assert.assertEquals(lastShownTime, SharedPreferencesManager.getInstance().readLong( ChromePreferenceKeys.SIGNIN_PROMO_NTP_LAST_SHOWN_TIME)); - Assert.assertEquals(MAX_SIGN_IN_PROMO_IMPRESSIONS, - SharedPreferencesManager.getInstance().readInt( - SigninPromoController.getPromoShowCountPreferenceName( - SigninAccessPoint.NTP_CONTENT_SUGGESTIONS))); } @Test @@ -275,10 +230,6 @@ Assert.assertEquals(0L, SharedPreferencesManager.getInstance().readLong( ChromePreferenceKeys.SIGNIN_PROMO_NTP_LAST_SHOWN_TIME)); - Assert.assertEquals(0, - SharedPreferencesManager.getInstance().readInt( - SigninPromoController.getPromoShowCountPreferenceName( - SigninAccessPoint.NTP_CONTENT_SUGGESTIONS))); } @Test @@ -302,9 +253,6 @@ private void setNTPSyncPromoLimitsAndValues( long firstShownTime, long lastShownTime, int signinPromoResetAfterHours) { FeatureList.TestValues testValues = new FeatureList.TestValues(); - testValues.addFieldTrialParamOverride(ChromeFeatureList.ENHANCED_PROTECTION_PROMO_CARD, - "MaxSigninPromoImpressions", Integer.toString(MAX_SIGN_IN_PROMO_IMPRESSIONS)); - testValues.addFeatureFlagOverride(ChromeFeatureList.ENHANCED_PROTECTION_PROMO_CARD, true); testValues.addFeatureFlagOverride( ChromeFeatureList.FORCE_DISABLE_EXTENDED_SYNC_PROMOS, false); FeatureList.setTestValues(testValues); @@ -314,10 +262,6 @@ StartSurfaceConfiguration.SIGNIN_PROMO_NTP_RESET_AFTER_HOURS.setForTesting( signinPromoResetAfterHours); - SharedPreferencesManager.getInstance().writeInt( - SigninPromoController.getPromoShowCountPreferenceName( - SigninAccessPoint.NTP_CONTENT_SUGGESTIONS), - MAX_SIGN_IN_PROMO_IMPRESSIONS); SharedPreferencesManager.getInstance().writeLong( ChromePreferenceKeys.SIGNIN_PROMO_NTP_FIRST_SHOWN_TIME, firstShownTime); SharedPreferencesManager.getInstance().writeLong(
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd index 65084496..05938324 100644 --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -770,14 +770,6 @@ Chrome’s homepage </message> - <!-- Enhanced Protection Promo card --> - <message name="IDS_ENHANCED_PROTECTION_PROMO_TITLE" desc="The title displayed on homepage promo card, which guides the user to the chrome settings page to select the enhanced protection option."> - Get Chrome’s strongest security - </message> - <message name="IDS_ENHANCED_PROTECTION_PROMO_DESCRIPTION" desc="The description displayed on enhanced protection promo card, which guides the user to the chrome settings page to select the enhanced protection option."> - Enhanced protection does more to block phishing and malware - </message> - <!-- Notifications preferences --> <message name="IDS_PREFS_NOTIFICATIONS" desc="Title for Notification preferences."> Notifications
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_ENHANCED_PROTECTION_PROMO_DESCRIPTION.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_ENHANCED_PROTECTION_PROMO_DESCRIPTION.png.sha1 deleted file mode 100644 index 24ba182..0000000 --- a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_ENHANCED_PROTECTION_PROMO_DESCRIPTION.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -888b56743b22b1d76b9a0cd33645b49cd58e6a1a \ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_ENHANCED_PROTECTION_PROMO_TITLE.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_ENHANCED_PROTECTION_PROMO_TITLE.png.sha1 deleted file mode 100644 index 24ba182..0000000 --- a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_ENHANCED_PROTECTION_PROMO_TITLE.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -888b56743b22b1d76b9a0cd33645b49cd58e6a1a \ No newline at end of file
diff --git a/chrome/browser/ui/app_list/app_list_client_impl.cc b/chrome/browser/ui/app_list/app_list_client_impl.cc index bad11aa..9a2ae50 100644 --- a/chrome/browser/ui/app_list/app_list_client_impl.cc +++ b/chrome/browser/ui/app_list/app_list_client_impl.cc
@@ -457,6 +457,11 @@ return search_controller_.get(); } +void AppListClientImpl::SetSearchControllerForTest( + std::unique_ptr<app_list::SearchController> test_controller) { + search_controller_ = std::move(test_controller); +} + AppListModelUpdater* AppListClientImpl::GetModelUpdaterForTest() { return current_model_updater_; }
diff --git a/chrome/browser/ui/app_list/app_list_client_impl.h b/chrome/browser/ui/app_list/app_list_client_impl.h index d4efa84..bab7d710 100644 --- a/chrome/browser/ui/app_list/app_list_client_impl.h +++ b/chrome/browser/ui/app_list/app_list_client_impl.h
@@ -151,6 +151,9 @@ app_list::SearchController* search_controller(); + void SetSearchControllerForTest( + std::unique_ptr<app_list::SearchController> test_controller); + AppListModelUpdater* GetModelUpdaterForTest(); // Initializes as if a new user logged in for testing.
diff --git a/chrome/browser/ui/app_list/app_list_sort_unittest.cc b/chrome/browser/ui/app_list/app_list_sort_unittest.cc index c5974ff2..d207216 100644 --- a/chrome/browser/ui/app_list/app_list_sort_unittest.cc +++ b/chrome/browser/ui/app_list/app_list_sort_unittest.cc
@@ -6,6 +6,7 @@ #include "ash/app_list/model/app_list_model.h" #include "ash/constants/ash_features.h" +#include "base/containers/cxx20_erase_vector.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/app_list/app_list_model_updater.h" #include "chrome/browser/ui/app_list/app_list_test_util.h" @@ -378,8 +379,7 @@ // Verifies that merging two items to form a folder resets the nominal app list // sort order (if the app list is sorted at the time). -// Disabled due to flakiness (https://crbug.com/1281828). -TEST_F(TemporaryAppListSortTest, DISABLED_MergingItemsResetsSortOrder) { +TEST_F(TemporaryAppListSortTest, MergingItemsResetsSortOrder) { RemoveAllExistingItems(); std::vector<scoped_refptr<extensions::Extension>> apps; @@ -405,26 +405,44 @@ // Merge two items into a folder. ChromeAppListModelUpdater* model_updater = GetChromeModelUpdater(); - model_updater->model_for_test()->MergeItems(apps[8]->id(), apps[9]->id()); + const std::string folder_id = + model_updater->model_for_test()->MergeItems(apps[8]->id(), apps[9]->id()); // Verify that the app list is no longer considered sorted - new items are // added to the first position within the app list. EXPECT_FALSE(IsUnderTemporarySort()); EXPECT_EQ(ash::AppListSortOrder::kCustom, GetSortOrderFromPrefs()); - EXPECT_EQ(GetOrderedNamesFromSyncableService(), + std::vector<std::string> ordered_names = GetOrderedNamesFromSyncableService(); + // Note that newly created folder will have the same position as the item it + // was created from, so order of the original item and the folder may not be + // deterministic (both [folder, item], and [item, folder] are acceptable + // orders). Remove the folder from the list, and later test that the folder + // position is the same as the original item. + EXPECT_EQ(1u, base::EraseIf(ordered_names, [](const std::string& item) { + return item == ""; + })); + EXPECT_EQ(ordered_names, std::vector<std::string>({"Item 0", "Item 1", "Item 2", "Item 3", "Item 4", "Item 5", "Item 6", "Item 7", - "Item 8", "", "Item 9"})); + "Item 8", "Item 9"})); + EXPECT_EQ(GetPositionFromSyncData(apps[8]->id()), + GetPositionFromSyncData(folder_id)); scoped_refptr<extensions::Extension> new_app = MakeApp( "Item 10", GenerateId("new_install"), extensions::Extension::NO_FLAGS); InstallExtension(new_app.get()); EXPECT_EQ(ash::AppListSortOrder::kCustom, GetSortOrderFromPrefs()); - EXPECT_EQ(GetOrderedNamesFromSyncableService(), + ordered_names = GetOrderedNamesFromSyncableService(); + EXPECT_EQ(1u, base::EraseIf(ordered_names, [](const std::string& item) { + return item == ""; + })); + EXPECT_EQ(ordered_names, std::vector<std::string>({"Item 10", "Item 0", "Item 1", "Item 2", "Item 3", "Item 4", "Item 5", "Item 6", - "Item 7", "Item 8", "", "Item 9"})); + "Item 7", "Item 8", "Item 9"})); + EXPECT_EQ(GetPositionFromSyncData(apps[8]->id()), + GetPositionFromSyncData(folder_id)); } // Verifies that moving an item from a folder to root apps grid resets the
diff --git a/chrome/browser/ui/ash/shelf/app_service/exo_app_type_resolver.cc b/chrome/browser/ui/ash/shelf/app_service/exo_app_type_resolver.cc index bb5282c..34b6ec79 100644 --- a/chrome/browser/ui/ash/shelf/app_service/exo_app_type_resolver.cc +++ b/chrome/browser/ui/ash/shelf/app_service/exo_app_type_resolver.cc
@@ -14,6 +14,7 @@ #include "components/app_restore/window_properties.h" #include "components/exo/permission.h" #include "components/exo/shell_surface_util.h" +#include "components/exo/window_properties.h" #include "ui/aura/client/aura_constants.h" #include "ui/base/class_property.h" @@ -40,6 +41,10 @@ out_properties_container.SetProperty( exo::kPermissionKey, new exo::Permission(exo::Permission::Capability::kActivate)); + // Only Lacros windows should allow restore/fullscreen to kick windows out + // of fullscreen. + out_properties_container.SetProperty(exo::kRestoreOrMaximizeExitsFullscreen, + true); } else if (borealis::BorealisWindowManager::IsBorealisWindowId( params.app_id.empty() ? params.startup_id : params.app_id)) { // TODO(b/165865831): Stop using CROSTINI_APP for borealis windows.
diff --git a/chrome/browser/ui/ash/thumbnail_loader.cc b/chrome/browser/ui/ash/thumbnail_loader.cc index 1c8e5c8..1c74be2 100644 --- a/chrome/browser/ui/ash/thumbnail_loader.cc +++ b/chrome/browser/ui/ash/thumbnail_loader.cc
@@ -15,9 +15,8 @@ #include "base/values.h" #include "chrome/browser/ash/file_manager/app_id.h" #include "chrome/browser/ash/file_manager/fileapi_util.h" -#include "chrome/browser/bitmap_fetcher/bitmap_fetcher.h" -#include "chrome/browser/bitmap_fetcher/bitmap_fetcher_delegate.h" #include "chrome/browser/extensions/api/messaging/native_message_port.h" +#include "chrome/browser/image_decoder/image_decoder.h" #include "chrome/browser/profiles/profile.h" #include "extensions/browser/api/messaging/channel_endpoint.h" #include "extensions/browser/api/messaging/message_service.h" @@ -26,6 +25,7 @@ #include "extensions/common/api/messaging/port_id.h" #include "extensions/common/api/messaging/serialization_format.h" #include "extensions/common/extension.h" +#include "net/base/data_url.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "services/data_decoder/public/cpp/data_decoder.h" #include "services/network/public/cpp/shared_url_loader_factory.h" @@ -136,22 +136,26 @@ } // namespace // Converts a data URL to bitmap. -class ThumbnailLoader::ThumbnailDecoder : public BitmapFetcherDelegate { +class ThumbnailLoader::ThumbnailDecoder : public ImageDecoder::ImageRequest { public: - explicit ThumbnailDecoder(Profile* profile) : profile_(profile) {} + ThumbnailDecoder() = default; ThumbnailDecoder(const ThumbnailDecoder&) = delete; ThumbnailDecoder& operator=(const ThumbnailDecoder&) = delete; ~ThumbnailDecoder() override = default; - // BitmapFetcherDelegate: - void OnFetchComplete(const GURL& url, const SkBitmap* bitmap) override { - std::move(callback_).Run(bitmap, base::File::FILE_OK); + // ImageDecoder::ImageRequest: + void OnImageDecoded(const SkBitmap& bitmap) override { + std::move(callback_).Run(&bitmap, base::File::FILE_OK); + } + + // ImageDecoder::ImageRequest: + void OnDecodeImageFailed() override { + std::move(callback_).Run(/*bitmap=*/nullptr, base::File::FILE_ERROR_FAILED); } void Start(const std::string& data, ThumbnailLoader::ImageCallback callback) { DCHECK(!callback_); - DCHECK(!bitmap_fetcher_); // The data sent from the image loader extension should be in form of a data // URL. @@ -162,24 +166,19 @@ return; } + std::string mime_type, charset, image_data; + if (!net::DataURL::Parse(data_url, &mime_type, &charset, &image_data)) { + std::move(callback).Run(/*bitmap=*/nullptr, + base::File::FILE_ERROR_FAILED); + return; + } + callback_ = std::move(callback); - - // Note that the image downloader will not use network traffic for data - // URLs. - bitmap_fetcher_ = std::make_unique<BitmapFetcher>( - data_url, this, MISSING_TRAFFIC_ANNOTATION); - - bitmap_fetcher_->Init( - /*referrer=*/std::string(), net::ReferrerPolicy::NEVER_CLEAR, - network::mojom::CredentialsMode::kOmit); - - bitmap_fetcher_->Start(profile_->GetURLLoaderFactory().get()); + ImageDecoder::Start(this, std::move(image_data)); } private: - Profile* const profile_; ThumbnailLoader::ImageCallback callback_; - std::unique_ptr<BitmapFetcher> bitmap_fetcher_; }; ThumbnailLoader::ThumbnailLoader(Profile* profile) : profile_(profile) {} @@ -312,7 +311,7 @@ return; } - auto thumbnail_decoder = std::make_unique<ThumbnailDecoder>(profile_); + auto thumbnail_decoder = std::make_unique<ThumbnailDecoder>(); ThumbnailDecoder* thumbnail_decoder_ptr = thumbnail_decoder.get(); thumbnail_decoders_.emplace(request_id, std::move(thumbnail_decoder)); thumbnail_decoder_ptr->Start(
diff --git a/chrome/browser/ui/views/autofill/autofill_popup_base_view.cc b/chrome/browser/ui/views/autofill/autofill_popup_base_view.cc index 6f47b02..0c80dda 100644 --- a/chrome/browser/ui/views/autofill/autofill_popup_base_view.cc +++ b/chrome/browser/ui/views/autofill/autofill_popup_base_view.cc
@@ -9,6 +9,7 @@ #include <utility> #include "base/bind.h" +#include "base/dcheck_is_on.h" #include "base/location.h" #include "base/task/single_thread_task_runner.h" #include "base/threading/thread_task_runner_handle.h" @@ -36,6 +37,11 @@ #include "ui/views/focus/focus_manager.h" #include "ui/views/layout/fill_layout.h" +#if DCHECK_IS_ON() +#include "base/containers/fixed_flat_set.h" +#include "base/strings/string_piece.h" +#endif + namespace autofill { int AutofillPopupBaseView::GetCornerRadius() { @@ -186,6 +192,19 @@ is_ax_menu_start_event_fired_ = true; } selected_view->GetViewAccessibility().SetPopupFocusOverride(); +#if DCHECK_IS_ON() + constexpr auto kDerivedClasses = base::MakeFixedFlatSet<base::StringPiece>( + {"AutofillPopupSuggestionView", "PasswordPopupSuggestionView", + "AutofillPopupFooterView", "AutofillPopupSeparatorView", + "AutofillPopupWarningView", "AutofillPopupBaseView"}); + DCHECK(kDerivedClasses.contains(selected_view->GetClassName())) + << "If you add a new derived class from AutofillPopupRowView, add it " + "here and to onSelection(evt) in " + "chrome/browser/resources/chromeos/accessibility/chromevox/background/" + "desktop_automation_handler.js to ensure that ChromeVox announces " + "the item when selected. Missing class: " + << selected_view->GetClassName(); +#endif selected_view->NotifyAccessibilityEvent(ax::mojom::Event::kSelection, true); }
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc index 7810803..57fe55c2 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc +++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
@@ -202,6 +202,8 @@ } void GetAccessibleNodeData(ui::AXNodeData* node_data) override { + if (GetAccessibleName().empty()) + node_data->SetNameExplicitlyEmpty(); views::LabelButton::GetAccessibleNodeData(node_data); node_data->AddStringAttribute( ax::mojom::StringAttribute::kRoleDescription,
diff --git a/chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_network_handler.cc b/chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_network_handler.cc index fe10869e..451bf39 100644 --- a/chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_network_handler.cc +++ b/chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_network_handler.cc
@@ -81,10 +81,14 @@ void NetworkConfigMessageHandler::Initialize(base::Value::ConstListView args) { AllowJavascript(); - // Notify the main dialog that the network dialog has been loaded. + // Check if the main dialog exists and notify that the network dialog has + // been loaded. auto* password_sync_manager = GetInSessionPasswordSyncManager(); - password_sync_manager->get_reauth_dialog_for_testing() - ->OnNetworkDialogReadyForTesting(); + LockScreenStartReauthDialog* start_reauth_dialog = + password_sync_manager->get_reauth_dialog_for_testing(); + if (!start_reauth_dialog) + return; + start_reauth_dialog->OnNetworkDialogReadyForTesting(); } void NetworkConfigMessageHandler::ShowNetworkDetails(
diff --git a/chrome/browser/ui/webui/policy/policy_ui_handler.cc b/chrome/browser/ui/webui/policy/policy_ui_handler.cc index cc62e60b..7ea8ee3de 100644 --- a/chrome/browser/ui/webui/policy/policy_ui_handler.cc +++ b/chrome/browser/ui/webui/policy/policy_ui_handler.cc
@@ -108,6 +108,7 @@ #if BUILDFLAG(IS_CHROMEOS_LACROS) #include "chromeos/crosapi/mojom/policy_service.mojom.h" #include "chromeos/lacros/lacros_service.h" +#include "components/policy/core/common/policy_loader_lacros.h" #endif #if defined(OS_MAC) @@ -151,11 +152,15 @@ if (!user) return; dict->SetBoolean("isAffiliated", user->IsAffiliated()); -#else // BUILDFLAG(IS_CHROMEOS_ASH) +#else // Don't show affiliation status if the browser isn't enrolled in CBCM. - if (!policy::BrowserDMTokenStorage::Get()->RetrieveDMToken().is_valid()) - return; - +#if BUILDFLAG(IS_CHROMEOS_LACROS) + if (!profile->IsMainProfile()) +#endif // BUILDFLAG(IS_CHROMEOS_LACROS) + { + if (!policy::BrowserDMTokenStorage::Get()->RetrieveDMToken().is_valid()) + return; + } dict->SetBoolean("isAffiliated", chrome::enterprise_util::IsProfileAffiliated(profile)); #endif // BUILDFLAG(IS_CHROMEOS_ASH) @@ -251,6 +256,29 @@ raw_ptr<Profile> profile_; }; +#if BUILDFLAG(IS_CHROMEOS_LACROS) +// A cloud policy status provider for device account. +class UserPolicyStatusProviderLacros : public policy::PolicyStatusProvider { + public: + UserPolicyStatusProviderLacros(policy::PolicyLoaderLacros* loader, + Profile* profile); + + UserPolicyStatusProviderLacros(const UserPolicyStatusProviderLacros&) = + delete; + UserPolicyStatusProviderLacros& operator=( + const UserPolicyStatusProviderLacros&) = delete; + + ~UserPolicyStatusProviderLacros() override; + + // CloudPolicyCoreStatusProvider implementation. + void GetStatus(base::DictionaryValue* dict) override; + + private: + raw_ptr<Profile> profile_; + raw_ptr<policy::PolicyLoaderLacros> loader_; +}; +#endif + #if BUILDFLAG(IS_CHROMEOS_ASH) // A cloud policy status provider for user policy on Chrome OS. class UserCloudPolicyStatusProviderChromeOS @@ -436,6 +464,40 @@ GetUserAffiliationStatus(dict, profile_); } +#if BUILDFLAG(IS_CHROMEOS_LACROS) +UserPolicyStatusProviderLacros::UserPolicyStatusProviderLacros( + policy::PolicyLoaderLacros* loader, + Profile* profile) + : profile_(profile), loader_(loader) {} + +UserPolicyStatusProviderLacros::~UserPolicyStatusProviderLacros() = default; + +void UserPolicyStatusProviderLacros::GetStatus(base::DictionaryValue* dict) { + em::PolicyData* policy = loader_->GetPolicyData(); + if (!policy) + return; + GetStatusFromPolicyData(policy, dict); + ExtractDomainFromUsername(dict); + GetUserAffiliationStatus(dict, profile_); + + // Get last fetched time from policy, since we have no refresh scheduler here. + base::Time last_refresh_time = + policy && policy->has_timestamp() + ? base::Time::FromJavaTime(policy->timestamp()) + : base::Time(); + dict->SetString("timeSinceLastRefresh", + GetTimeSinceLastRefreshString(last_refresh_time)); + + // TODO(https://crbug.com/1243869): Pass this information from Ash through + // Mojo. Assume no error for now. + dict->SetBoolean("error", false); + dict->SetString("status", + FormatStoreStatus( + policy::CloudPolicyStore::STATUS_OK, + policy::CloudPolicyValidatorBase::Status::VALIDATION_OK)); +} +#endif + #if BUILDFLAG(IS_CHROMEOS_ASH) UserCloudPolicyStatusProviderChromeOS::UserCloudPolicyStatusProviderChromeOS( policy::CloudPolicyCore* core, @@ -751,6 +813,15 @@ if (user_cloud_policy_manager) { user_status_provider_ = std::make_unique<UserCloudPolicyStatusProvider>( user_cloud_policy_manager->core(), profile); + } else { +#if BUILDFLAG(IS_CHROMEOS_LACROS) + if (profile->IsMainProfile()) { + user_status_provider_ = std::make_unique<UserPolicyStatusProviderLacros>( + g_browser_process->browser_policy_connector() + ->device_account_policy_loader(), + profile); + } +#endif } policy::MachineLevelUserCloudPolicyManager* manager =
diff --git a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc index 24c7eee..492b701 100644 --- a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
@@ -1979,6 +1979,8 @@ IDS_SETTINGS_SITE_SETTINGS_ALL_SITES_SORT_METHOD_STORAGE}, {"siteSettingsAllSitesSortMethodName", IDS_SETTINGS_SITE_SETTINGS_ALL_SITES_SORT_METHOD_NAME}, + {"siteSettingsSiteEntryPartitionedLabel", + IDS_SETTINGS_SITE_SETTINGS_SITE_ENTRY_PARTITIONED_LABEL}, {"siteSettingsSiteRepresentationSeparator", IDS_SETTINGS_SITE_SETTINGS_SITE_REPRESENTATION_SEPARATOR}, {"siteSettingsAppProtocolHandlers", @@ -2312,6 +2314,8 @@ IDS_SETTINGS_SITE_SETTINGS_REMOVE_SITE_ORIGIN_DIALOG_TITLE}, {"siteSettingsRemoveSiteOriginAppDialogTitle", IDS_SETTINGS_SITE_SETTINGS_REMOVE_SITE_ORIGIN_APP_DIALOG_TITLE}, + {"siteSettingsRemoveSiteOriginPartitionedDialogTitle", + IDS_SETTINGS_SITE_SETTINGS_REMOVE_SITE_ORIGIN_PARTITIONED_DIALOG_TITLE}, {"siteSettingsRemoveSiteGroupDialogTitle", IDS_SETTINGS_SITE_SETTINGS_REMOVE_SITE_GROUP_DIALOG_TITLE}, {"siteSettingsRemoveSiteGroupAppDialogTitle",
diff --git a/chrome/browser/ui/webui/settings/site_settings_handler.cc b/chrome/browser/ui/webui/settings/site_settings_handler.cc index e830ab2..52c1642 100644 --- a/chrome/browser/ui/webui/settings/site_settings_handler.cc +++ b/chrome/browser/ui/webui/settings/site_settings_handler.cc
@@ -112,7 +112,8 @@ kEnterSiteDetails = 6, kRemoveSiteGroup = 7, kRemoveOrigin = 8, - kMaxValue = kRemoveOrigin, + kRemoveOriginPartitioned = 9, + kMaxValue = kRemoveOriginPartitioned, }; // Return an appropriate API Permission ID for the given string name. @@ -185,35 +186,44 @@ } // Groups |url| into sets of eTLD+1s in |site_group_map|, assuming |url| is an -// origin. +// origin. The effective eTLD+1 is |partition_etld_plus1| is set, otherwise it +// is the eTLD+1 of |url|. // There are three cases: -// 1. The ETLD+1 of |url| is not yet in |site_group_map|. We add the ETLD+1 -// to |site_group_map|. If the |url| is an ETLD+1 cookie origin, put a -// placeholder origin for the ETLD+1. -// 2. The ETLD+1 of |url| is in |site_group_map|, and is equal to host of +// 1. The effective eLTD+1 is not yet in |site_group_map|. We add the ETLD+1 +// to |site_group_map|. If the |url| is an effective ETLD+1 cookie origin, +// put a placeholder origin for the ETLD+1. +// 2. The effective ETLD+1 is in |site_group_map|, and is equal to host of // |url|. This means case 1 has already happened and nothing more needs to // be done. -// 3. The ETLD+1 of |url| is in |site_group_map| and is different to host of -// |url|. For a cookies url, if a https origin with same host exists, -// nothing more needs to be done. +// 3. The effective ETLD+1 is in |site_group_map| and is different to host of +// |url|. For a cookies url, if a https origin with same host and partitioned +// status exists, nothing more needs to be done. // In case 3, we try to add |url| to the set of origins for the ETLD+1. If an // existing origin is a placeholder, delete it, because the placeholder is no // longer needed. void CreateOrAppendSiteGroupEntry( - std::map<std::string, std::set<std::string>>* site_group_map, + std::map<std::string, std::set<std::pair<std::string, bool>>>* + site_group_map, const GURL& url, - bool url_is_origin_with_cookies = false) { - std::string etld_plus1_string = - net::registry_controlled_domains::GetDomainAndRegistry( - url, net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES); - auto entry = site_group_map->find(etld_plus1_string); + bool url_is_origin_with_cookies = false, + absl::optional<std::string> partition_etld_plus1 = absl::nullopt) { + bool is_partitioned = partition_etld_plus1.has_value(); + std::string effective_etld_plus1_string = + is_partitioned + ? partition_etld_plus1.value() + : net::registry_controlled_domains::GetDomainAndRegistry( + url, + net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES); + auto entry = site_group_map->find(effective_etld_plus1_string); bool etld_plus1_cookie_url = - url_is_origin_with_cookies && url.host() == etld_plus1_string; + url_is_origin_with_cookies && url.host() == effective_etld_plus1_string; if (entry == site_group_map->end()) { // Case 1: std::string origin = etld_plus1_cookie_url ? kPlaceholder : url.spec(); - site_group_map->emplace(etld_plus1_string, std::set<std::string>({origin})); + site_group_map->emplace( + effective_etld_plus1_string, + std::set<std::pair<std::string, bool>>({{origin, is_partitioned}})); return; } // Case 2: @@ -226,11 +236,13 @@ // version into the map. std::string https_url = std::string(url::kHttpsScheme) + url::kStandardSchemeSeparator + url.host() + "/"; - if (entry->second.find(https_url) != entry->second.end()) + if (entry->second.find({https_url, is_partitioned}) != + entry->second.end()) { return; + } } - entry->second.insert(url.spec()); - auto placeholder = entry->second.find(kPlaceholder); + entry->second.insert({url.spec(), is_partitioned}); + auto placeholder = entry->second.find({kPlaceholder, is_partitioned}); if (placeholder != entry->second.end()) entry->second.erase(placeholder); } @@ -246,7 +258,8 @@ // Converts a given |site_group_map| to a list of base::DictionaryValues, adding // the site engagement score for each origin. void ConvertSiteGroupMapToListValue( - const std::map<std::string, std::set<std::string>>& site_group_map, + const std::map<std::string, std::set<std::pair<std::string, bool>>>& + site_group_map, const std::set<std::string>& origin_permission_set, base::Value* list_value, Profile* profile) { @@ -263,7 +276,9 @@ base::Value(entry.first)); bool has_installed_pwa = false; base::Value origin_list(base::Value::Type::LIST); - for (const std::string& origin : entry.second) { + for (const auto& origin_is_partitioned : entry.second) { + const auto& origin = origin_is_partitioned.first; + bool is_partitioned = origin_is_partitioned.second; base::Value origin_object(base::Value::Type::DICTIONARY); // If origin is placeholder, create a http ETLD+1 origin for it. if (origin == kPlaceholder) { @@ -274,6 +289,7 @@ } else { origin_object.SetKey("origin", base::Value(origin)); } + origin_object.SetKey("isPartitioned", base::Value(is_partitioned)); origin_object.SetKey( "engagement", base::Value(engagement_service->GetScore(GURL(origin)))); @@ -344,7 +360,8 @@ } void UpdateDataFromCookiesTree( - std::map<std::string, std::set<std::string>>* all_sites_map, + std::map<std::string, std::set<std::pair<std::string, bool>>>* + all_sites_map, std::map<std::string, int64_t>* origin_size_map, const GURL& origin, int64_t size) { @@ -403,6 +420,82 @@ NOTREACHED(); } +// Removes all nodes from |model| which match |origin| and |etld_plus1|. At +// least one of |origin| or |etld_plus1| must be set. If only |origin| is set, +// then unpartitioned storage for that origin is removed. If only |etld_plus1| +// is set, then any unpartitioned storage which matches that etld + 1, or +// partitioned storage where it is the partitioning site, is removed. If both +// |origin| and |etld_plus1| is set, then only storage for |origin| partitioned +// by |etld_plus1| is removed. +void RemoveMatchingNodes(CookiesTreeModel* model, + absl::optional<std::string> origin, + absl::optional<std::string> etld_plus1) { + DCHECK(origin || etld_plus1); + std::vector<CookieTreeNode*> nodes_to_delete; + + for (const auto& host_node : model->GetRoot()->children()) { + bool origin_matches = + origin && + *origin == host_node->GetDetailedInfo().origin.GetURL().spec(); + + if (origin && !origin_matches) { + // If the origin is set, host nodes which do not match that origin cannot + // contain storage targeted for removal. + continue; + } + + std::string host_node_etld_plus1 = + net::registry_controlled_domains::GetDomainAndRegistry( + base::UTF16ToUTF8(host_node->GetTitle()), + net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES); + + bool etld_plus1_matches = etld_plus1 && *etld_plus1 == host_node_etld_plus1; + + for (const auto& storage_type_node : host_node->children()) { + if (storage_type_node->GetDetailedInfo().node_type != + CookieTreeNode::DetailedInfo::TYPE_COOKIES) { + // Non cookie storage cannot (currently) be partitioned. + if (origin && etld_plus1) { + continue; + } + + if (origin_matches || etld_plus1_matches) { + nodes_to_delete.push_back(storage_type_node.get()); + continue; + } + } else { + // Every cookie must be inspected to confirm partition state. + // TODO(crbug.com/1271155): This is slow, and should be addressed when + // the CookiesTreeModel is deprecated. + for (const auto& cookie_node : storage_type_node->children()) { + const auto& cookie = cookie_node->GetDetailedInfo().cookie; + if (!cookie->IsPartitioned() && + (origin_matches || etld_plus1_matches) && + (!origin || !etld_plus1)) { + nodes_to_delete.push_back(cookie_node.get()); + continue; + } + if (cookie->IsPartitioned()) { + const auto& partition_site = + cookie->PartitionKey()->site().GetURL().host(); + + // If an origin has been set, it must match the origin of the + // current node, which means it can be ignored. + DCHECK(!origin || origin_matches); + + if (etld_plus1 && partition_site == *etld_plus1) { + nodes_to_delete.push_back(cookie_node.get()); + } + } + } + } + } + } + + for (auto* node : nodes_to_delete) + model->DeleteCookieNode(node); +} + } // namespace SiteSettingsHandler::SiteSettingsHandler(Profile* profile) @@ -419,8 +512,13 @@ base::BindRepeating(&SiteSettingsHandler::HandleFetchUsageTotal, base::Unretained(this))); web_ui()->RegisterDeprecatedMessageCallback( - "clearUsage", base::BindRepeating(&SiteSettingsHandler::HandleClearUsage, - base::Unretained(this))); + "clearUnpartitionedUsage", + base::BindRepeating(&SiteSettingsHandler::HandleClearUnpartitionedUsage, + base::Unretained(this))); + web_ui()->RegisterDeprecatedMessageCallback( + "clearPartitionedUsage", + base::BindRepeating(&SiteSettingsHandler::HandleClearPartitionedUsage, + base::Unretained(this))); web_ui()->RegisterDeprecatedMessageCallback( "setDefaultValueForContentType", base::BindRepeating( @@ -671,19 +769,16 @@ EnsureCookiesTreeModelCreated(); } -void SiteSettingsHandler::HandleClearUsage(const base::ListValue* args) { +void SiteSettingsHandler::HandleClearUnpartitionedUsage( + const base::ListValue* args) { CHECK_EQ(1U, args->GetList().size()); const std::string& origin = args->GetList()[0].GetString(); GURL url(origin); if (!url.is_valid()) return; AllowJavascript(); - for (const auto& node : cookies_tree_model_->GetRoot()->children()) { - if (origin == node->GetDetailedInfo().origin.GetURL().spec()) { - cookies_tree_model_->DeleteCookieNode(node.get()); - break; - } - } + + RemoveMatchingNodes(cookies_tree_model_.get(), origin, absl::nullopt); // TODO(crbug.com/1271155, crbug.com/1268626): This is a temporary hack while // the CookiesTreeModel is deprecated. Currently cookies will fail to be @@ -696,6 +791,15 @@ url, GURL(), ContentSettingsType::CLIENT_HINTS, nullptr); } +void SiteSettingsHandler::HandleClearPartitionedUsage( + const base::ListValue* args) { + CHECK_EQ(2U, args->GetList().size()); + const std::string& origin = args->GetList()[0].GetString(); + const std::string& etld_plus1 = args->GetList()[1].GetString(); + + RemoveMatchingNodes(cookies_tree_model_.get(), origin, etld_plus1); +} + void SiteSettingsHandler::HandleSetDefaultValueForContentType( const base::ListValue* args) { CHECK_EQ(2U, args->GetList().size()); @@ -891,7 +995,8 @@ base::Value SiteSettingsHandler::PopulateCookiesAndUsageData(Profile* profile) { std::map<std::string, int64_t> origin_size_map; - std::map<std::string, int> origin_cookie_map; + std::map<std::pair<std::string, absl::optional<std::string>>, int> + origin_cookie_map; base::Value list_value(base::Value::Type::LIST); GetOriginStorage(&all_sites_map_, &origin_size_map); @@ -905,7 +1010,8 @@ int cookie_num = 0; const std::string& etld_plus1 = site_group.FindKey(kEffectiveTopLevelDomainPlus1Name)->GetString(); - const auto& etld_plus1_cookie_num_it = origin_cookie_map.find(etld_plus1); + const auto& etld_plus1_cookie_num_it = + origin_cookie_map.find({etld_plus1, absl::nullopt}); // Add the number of eTLD+1 scoped cookies. if (etld_plus1_cookie_num_it != origin_cookie_map.end()) cookie_num = etld_plus1_cookie_num_it->second; @@ -913,13 +1019,19 @@ // numbers. for (base::Value& origin_info : origin_list->GetList()) { const std::string& origin = origin_info.FindKey("origin")->GetString(); - const auto& size_info_it = origin_size_map.find(origin); - if (size_info_it != origin_size_map.end()) - origin_info.SetKey( - "usage", base::Value(static_cast<double>(size_info_it->second))); + bool is_partitioned = origin_info.FindKey("isPartitioned")->GetBool(); + if (!is_partitioned) { + // Only unpartitioned storage has a size. + const auto& size_info_it = origin_size_map.find(origin); + if (size_info_it != origin_size_map.end()) + origin_info.SetKey( + "usage", base::Value(static_cast<double>(size_info_it->second))); + } GURL origin_url(origin); - const auto& origin_cookie_num_it = - origin_cookie_map.find(origin_url.host()); + const auto& origin_cookie_num_it = origin_cookie_map.find( + {origin_url.host(), + (is_partitioned ? absl::optional<std::string>(etld_plus1) + : absl::nullopt)}); if (origin_cookie_num_it != origin_cookie_map.end()) { origin_info.SetKey(kNumCookies, base::Value(origin_cookie_num_it->second)); @@ -1532,7 +1644,8 @@ } void SiteSettingsHandler::GetOriginStorage( - std::map<std::string, std::set<std::string>>* all_sites_map, + std::map<std::string, std::set<std::pair<std::string, bool>>>* + all_sites_map, std::map<std::string, int64_t>* origin_size_map) { CHECK(cookies_tree_model_.get()); @@ -1546,38 +1659,57 @@ } void SiteSettingsHandler::GetOriginCookies( - std::map<std::string, std::set<std::string>>* all_sites_map, - std::map<std::string, int>* origin_cookie_map) { + std::map<std::string, std::set<std::pair<std::string, bool>>>* + all_sites_map, + std::map<std::pair<std::string, absl::optional<std::string>>, int>* + origin_cookie_map) { CHECK(cookies_tree_model_.get()); // Get sites that don't have data but have cookies. for (const auto& site : cookies_tree_model_->GetRoot()->children()) { GURL url = site->GetDetailedInfo().origin.GetURL(); - (*origin_cookie_map)[url.host()] = site->NumberOfCookies(); - CreateOrAppendSiteGroupEntry(all_sites_map, url, - /*url_is_origin_with_cookies = */ true); + if (!site->NumberOfCookies()) + continue; + + // Each cookie will need to be inspected to see if it is partitioned, so it + // may be associated with the appropriate eTLD+1. + // TODO (crbug.com/1271155): This is slow, the replacement for the + // CookiesTreeModel should improve this significantly. + for (const auto& site_child : site->children()) { + if (site_child->GetDetailedInfo().node_type != + CookieTreeNode::DetailedInfo::TYPE_COOKIES) { + continue; + } + + for (const auto& cookie : site_child->children()) { + const auto& detailed_info = cookie->GetDetailedInfo(); + DCHECK(detailed_info.node_type == + CookieTreeNode::DetailedInfo::TYPE_COOKIE); + DCHECK(detailed_info.cookie); + + absl::optional<std::string> associated_etld_plus1 = + detailed_info.cookie->IsPartitioned() + ? absl::optional<std::string>( + detailed_info.cookie->PartitionKey() + ->site() + .GetURL() + .host()) + : absl::nullopt; + CreateOrAppendSiteGroupEntry(all_sites_map, url, + /*url_is_origin_with_cookies = */ true, + associated_etld_plus1); + (*origin_cookie_map)[{url.host(), associated_etld_plus1}]++; + } + } } } void SiteSettingsHandler::HandleClearEtldPlus1DataAndCookies( const base::ListValue* args) { CHECK_EQ(1U, args->GetList().size()); - const std::string& etld_plus1_string = args->GetList()[0].GetString(); + const std::string& etld_plus1 = args->GetList()[0].GetString(); AllowJavascript(); - CookieTreeNode* parent = cookies_tree_model_->GetRoot(); - - // Find all the nodes that contain the given etld+1. - std::vector<CookieTreeNode*> nodes_to_delete; - for (const auto& node : parent->children()) { - std::string cookie_node_etld_plus1 = - net::registry_controlled_domains::GetDomainAndRegistry( - base::UTF16ToUTF8(node->GetTitle()), - net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES); - if (etld_plus1_string == cookie_node_etld_plus1) - nodes_to_delete.push_back(node.get()); - } - for (auto* node : nodes_to_delete) - cookies_tree_model_->DeleteCookieNode(node); + RemoveMatchingNodes(cookies_tree_model_.get(), absl::nullopt, etld_plus1); } void SiteSettingsHandler::HandleRecordAction(const base::ListValue* args) {
diff --git a/chrome/browser/ui/webui/settings/site_settings_handler.h b/chrome/browser/ui/webui/settings/site_settings_handler.h index 8047556..8ecbd74 100644 --- a/chrome/browser/ui/webui/settings/site_settings_handler.h +++ b/chrome/browser/ui/webui/settings/site_settings_handler.h
@@ -127,7 +127,12 @@ FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, ZoomLevels); FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, HandleClearEtldPlus1DataAndCookies); - FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, HandleClearUsage); + FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, + HandleClearUnpartitionedUsage); + FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, + ClearUnpartitionedClearsHints); + FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, + HandleClearPartitionedUsage); FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, CookieSettingDescription); FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, HandleGetFormattedBytes); FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, @@ -147,21 +152,26 @@ // Calculates the data storage that has been used for each origin, and // stores the information in the |all_sites_map| and |origin_size_map|. void GetOriginStorage( - std::map<std::string, std::set<std::string>>* all_sites_map, + std::map<std::string, std::set<std::pair<std::string, bool>>>* + all_sites_map, std::map<std::string, int64_t>* origin_size_map); // Calculates the number of cookies for each etld+1 and each origin, and // stores the information in the |all_sites_map| and |origin_cookie_map|. void GetOriginCookies( - std::map<std::string, std::set<std::string>>* all_sites_map, - std::map<std::string, int>* origin_cookie_map); + std::map<std::string, std::set<std::pair<std::string, bool>>>* + all_sites_map, + std::map<std::pair<std::string, absl::optional<std::string>>, int>* + origin_cookie_map); // Asynchronously fetches the usage for a given origin. Replies back with // OnGetUsageInfo above. void HandleFetchUsageTotal(const base::ListValue* args); // Deletes the storage being used for a given host. - void HandleClearUsage(const base::ListValue* args); + void HandleClearUnpartitionedUsage(const base::ListValue* args); + + void HandleClearPartitionedUsage(const base::ListValue* args); // Gets and sets the default value for a particular content settings type. void HandleSetDefaultValueForContentType(const base::ListValue* args); @@ -303,7 +313,7 @@ bool send_sites_list_ = false; // Populated every time the user reloads the All Sites page. - std::map<std::string, std::set<std::string>> all_sites_map_; + std::map<std::string, std::set<std::pair<std::string, bool>>> all_sites_map_; // Store the origins that has permission settings. std::set<std::string> origin_permission_set_;
diff --git a/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc b/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc index d8f30b8..a8e1168 100644 --- a/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc +++ b/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc
@@ -478,7 +478,7 @@ mock_browsing_data_cookie_helper->AddCookieSamples( GURL("http://example.com"), "A=1"); mock_browsing_data_cookie_helper->AddCookieSamples( - GURL("http://www.example.com/"), "B=1"); + GURL("https://www.example.com/"), "B=1"); mock_browsing_data_cookie_helper->AddCookieSamples( GURL("http://abc.example.com"), "C=1"); mock_browsing_data_cookie_helper->AddCookieSamples( @@ -487,6 +487,22 @@ GURL("http://google.com"), "B=1"); mock_browsing_data_cookie_helper->AddCookieSamples( GURL("http://google.com.au"), "A=1"); + + mock_browsing_data_cookie_helper->AddCookieSamples( + GURL("https://www.example.com"), + "__Host-A=1; Path=/; Partitioned; Secure;", + net::CookiePartitionKey::FromURLForTesting( + GURL("https://google.com.au"))); + mock_browsing_data_cookie_helper->AddCookieSamples( + GURL("https://www.another-example.com"), + "__Host-A=1; Path=/; Partitioned; Secure;", + net::CookiePartitionKey::FromURLForTesting( + GURL("https://google.com.au"))); + mock_browsing_data_cookie_helper->AddCookieSamples( + GURL("https://www.example.com"), + "__Host-A=1; Path=/; Partitioned; Secure;", + net::CookiePartitionKey::FromURLForTesting(GURL("https://google.com"))); + mock_browsing_data_cookie_helper->Notify(); handler()->SetCookiesTreeModelForTesting( @@ -500,6 +516,17 @@ return data.arg2()->GetList(); } + std::vector<CookieTreeNode*> GetHostNodes(GURL url) { + std::vector<CookieTreeNode*> nodes; + for (const auto& host_node : + handler()->cookies_tree_model_->GetRoot()->children()) { + if (host_node->GetDetailedInfo().origin.GetURL() == url) { + nodes.push_back(host_node.get()); + } + } + return nodes; + } + // Content setting group name for the relevant ContentSettingsType. const std::string kNotifications; const std::string kCookies; @@ -900,21 +927,33 @@ ASSERT_TRUE(site_group.FindStringKey("etldPlus1")); ASSERT_EQ("google.com", *site_group.FindStringKey("etldPlus1")); - EXPECT_EQ(2, site_group.FindKey("numCookies")->GetDouble()); + EXPECT_EQ(3, site_group.FindKey("numCookies")->GetDouble()); const base::Value* origin_list = site_group.FindListKey("origins"); ASSERT_TRUE(origin_list && origin_list->is_list()); - EXPECT_EQ(1U, origin_list->GetList().size()); + EXPECT_EQ(2U, origin_list->GetList().size()); - const base::Value& origin_info = origin_list->GetList()[0]; - ASSERT_TRUE(origin_info.is_dict()); + const base::Value& partitioned_origin_info = origin_list->GetList()[0]; + ASSERT_TRUE(partitioned_origin_info.is_dict()); + + EXPECT_EQ("https://www.example.com/", + partitioned_origin_info.FindKey("origin")->GetString()); + EXPECT_EQ(0, partitioned_origin_info.FindKey("engagement")->GetDouble()); + EXPECT_EQ(0, partitioned_origin_info.FindKey("usage")->GetDouble()); + EXPECT_EQ(1, partitioned_origin_info.FindKey("numCookies")->GetDouble()); + EXPECT_TRUE(partitioned_origin_info.FindKey("isPartitioned")->GetBool()); + + const base::Value& unpartitioned_origin_info = origin_list->GetList()[1]; + ASSERT_TRUE(unpartitioned_origin_info.is_dict()); EXPECT_EQ("https://www.google.com/", - origin_info.FindKey("origin")->GetString()); - EXPECT_EQ(0, origin_info.FindKey("engagement")->GetDouble()); - EXPECT_EQ(50000000000, origin_info.FindKey("usage")->GetDouble()); - EXPECT_EQ(0, origin_info.FindKey("numCookies")->GetDouble()); + unpartitioned_origin_info.FindKey("origin")->GetString()); + EXPECT_EQ(0, unpartitioned_origin_info.FindKey("engagement")->GetDouble()); + EXPECT_EQ(50000000000, + unpartitioned_origin_info.FindKey("usage")->GetDouble()); + EXPECT_EQ(0, unpartitioned_origin_info.FindKey("numCookies")->GetDouble()); + EXPECT_FALSE(unpartitioned_origin_info.FindKey("isPartitioned")->GetBool()); } { @@ -924,21 +963,39 @@ ASSERT_TRUE(site_group.FindStringKey("etldPlus1")); ASSERT_EQ("google.com.au", *site_group.FindStringKey("etldPlus1")); - EXPECT_EQ(1, site_group.FindKey("numCookies")->GetDouble()); + EXPECT_EQ(3, site_group.FindKey("numCookies")->GetDouble()); const base::Value* origin_list = site_group.FindListKey("origins"); ASSERT_TRUE(origin_list && origin_list->is_list()); - EXPECT_EQ(1U, origin_list->GetList().size()); + // The unpartitioned cookie set for google.com.au should be associated with + // the eTLD+1, and thus won't have an origin entry as other origin entries + // exist for the unpartitioned storage. + EXPECT_EQ(2U, origin_list->GetList().size()); - const base::Value& origin_info = origin_list->GetList()[0]; - ASSERT_TRUE(origin_info.is_dict()); + const base::Value& partitioned_origin_one_info = origin_list->GetList()[0]; + ASSERT_TRUE(partitioned_origin_one_info.is_dict()); - EXPECT_EQ("http://google.com.au/", - origin_info.FindKey("origin")->GetString()); - EXPECT_EQ(0, origin_info.FindKey("engagement")->GetDouble()); - EXPECT_EQ(0, origin_info.FindKey("usage")->GetDouble()); - EXPECT_EQ(1, origin_info.FindKey("numCookies")->GetDouble()); + EXPECT_EQ("https://www.another-example.com/", + partitioned_origin_one_info.FindKey("origin")->GetString()); + EXPECT_EQ(0, + partitioned_origin_one_info.FindKey("engagement")->GetDouble()); + EXPECT_EQ(0, partitioned_origin_one_info.FindKey("usage")->GetDouble()); + EXPECT_EQ(1, + partitioned_origin_one_info.FindKey("numCookies")->GetDouble()); + EXPECT_TRUE( + partitioned_origin_one_info.FindKey("isPartitioned")->GetBool()); + + const base::Value& partitioned_origin_two_info = origin_list->GetList()[1]; + EXPECT_EQ("https://www.example.com/", + partitioned_origin_two_info.FindKey("origin")->GetString()); + EXPECT_EQ(0, + partitioned_origin_two_info.FindKey("engagement")->GetDouble()); + EXPECT_EQ(0, partitioned_origin_two_info.FindKey("usage")->GetDouble()); + EXPECT_EQ(1, + partitioned_origin_two_info.FindKey("numCookies")->GetDouble()); + EXPECT_TRUE( + partitioned_origin_two_info.FindKey("isPartitioned")->GetBool()); } } @@ -978,17 +1035,15 @@ ASSERT_TRUE(site_group.FindStringKey("etldPlus1")); ASSERT_EQ("google.com", *site_group.FindStringKey("etldPlus1")); + EXPECT_FALSE(site_group.FindKey("hasInstalledPWA")->GetBool()); const base::Value* origin_list = site_group.FindListKey("origins"); ASSERT_TRUE(origin_list); - const base::Value& origin_info = origin_list->GetList()[0]; - ASSERT_TRUE(origin_info.is_dict()); - - EXPECT_EQ("https://www.google.com/", - origin_info.FindKey("origin")->GetString()); - EXPECT_FALSE(site_group.FindKey("hasInstalledPWA")->GetBool()); - EXPECT_FALSE(origin_info.FindKey("isInstalled")->GetBool()); + for (const auto& origin_info : origin_list->GetList()) { + ASSERT_TRUE(origin_info.is_dict()); + EXPECT_FALSE(origin_info.FindKey("isInstalled")->GetBool()); + } } } @@ -2389,7 +2444,7 @@ TEST_F(SiteSettingsHandlerTest, HandleClearEtldPlus1DataAndCookies) { SetUpCookiesTreeModel(); - EXPECT_EQ(22, handler()->cookies_tree_model_->GetRoot()->GetTotalNodeCount()); + EXPECT_EQ(27, handler()->cookies_tree_model_->GetRoot()->GetTotalNodeCount()); auto verify_site_group = [](const base::Value& site_group, std::string expected_etld_plus1) { @@ -2408,7 +2463,29 @@ args.Append("example.com"); handler()->HandleClearEtldPlus1DataAndCookies( &base::Value::AsListValue(args)); - EXPECT_EQ(11, handler()->cookies_tree_model_->GetRoot()->GetTotalNodeCount()); + + // All host nodes for non-secure example.com, and abc.example.com, which do + // not have any unpartitioned storage, should have been removed. + ASSERT_EQ(0u, GetHostNodes(GURL("http://example.com")).size()); + ASSERT_EQ(0u, GetHostNodes(GURL("http://abc.example.com")).size()); + + // Confirm that partitioned cookies for www.example.com have not been deleted, + auto remaining_host_nodes = GetHostNodes(GURL("https://www.example.com")); + + // example.com storage partitioned on other sites should still remain. + ASSERT_EQ(1u, remaining_host_nodes.size()); + ASSERT_EQ(1u, remaining_host_nodes[0]->children().size()); + const auto& storage_node = remaining_host_nodes[0]->children()[0]; + ASSERT_EQ(CookieTreeNode::DetailedInfo::TYPE_COOKIES, + storage_node->GetDetailedInfo().node_type); + ASSERT_EQ(2u, storage_node->children().size()); + for (const auto& cookie_node : storage_node->children()) { + const auto& cookie = cookie_node->GetDetailedInfo().cookie; + EXPECT_EQ("www.example.com", cookie->Domain()); + EXPECT_TRUE(cookie->IsPartitioned()); + } + + EXPECT_EQ(18, handler()->cookies_tree_model_->GetRoot()->GetTotalNodeCount()); storage_and_cookie_list = GetOnStorageFetchedSentListView(); EXPECT_EQ(2U, storage_and_cookie_list.size()); @@ -2420,7 +2497,7 @@ handler()->HandleClearEtldPlus1DataAndCookies( &base::Value::AsListValue(args)); - EXPECT_EQ(4, handler()->cookies_tree_model_->GetRoot()->GetTotalNodeCount()); + EXPECT_EQ(10, handler()->cookies_tree_model_->GetRoot()->GetTotalNodeCount()); storage_and_cookie_list = GetOnStorageFetchedSentListView(); EXPECT_EQ(1U, storage_and_cookie_list.size()); @@ -2431,19 +2508,60 @@ handler()->HandleClearEtldPlus1DataAndCookies( &base::Value::AsListValue(args)); - - EXPECT_EQ(1, handler()->cookies_tree_model_->GetRoot()->GetTotalNodeCount()); + // No nodes representing storage partitioned on google.com.au should be + // present. + for (const auto& host_node : + handler()->cookies_tree_model_->GetRoot()->children()) { + for (const auto& storage_node : host_node->children()) { + if (storage_node->GetDetailedInfo().node_type != + CookieTreeNode::DetailedInfo::TYPE_COOKIES) { + continue; + } + for (const auto& cookie_node : storage_node->children()) { + const auto& cookie = cookie_node->GetDetailedInfo().cookie; + if (cookie->IsPartitioned()) { + EXPECT_NE("google.com.au", + cookie->PartitionKey()->site().GetURL().host()); + } + } + } + } storage_and_cookie_list = GetOnStorageFetchedSentListView(); EXPECT_EQ(0U, storage_and_cookie_list.size()); } -// TODO(crbug.com/1271155, crbug.com/1268626): Add Validation for cookies nodes -// deleted correctly. -TEST_F(SiteSettingsHandlerTest, HandleClearUsage) { +TEST_F(SiteSettingsHandlerTest, HandleClearUnpartitionedUsage) { SetUpCookiesTreeModel(); - EXPECT_EQ(22, handler()->cookies_tree_model_->GetRoot()->GetTotalNodeCount()); + EXPECT_EQ(27, handler()->cookies_tree_model_->GetRoot()->GetTotalNodeCount()); + + base::Value args(base::Value::Type::LIST); + args.Append("https://www.example.com/"); + handler()->HandleClearUnpartitionedUsage(&base::Value::AsListValue(args)); + + // Confirm that only the unpartitioned items for example.com have been + // cleared. + auto remaining_host_nodes = GetHostNodes(GURL("https://www.example.com")); + + // There should only be partitioned cookie entries remaining for the site. + ASSERT_EQ(1u, remaining_host_nodes.size()); + ASSERT_EQ(1u, remaining_host_nodes[0]->children().size()); + const auto& storage_node = remaining_host_nodes[0]->children()[0]; + ASSERT_EQ(CookieTreeNode::DetailedInfo::TYPE_COOKIES, + storage_node->GetDetailedInfo().node_type); + ASSERT_EQ(2u, storage_node->children().size()); + for (const auto& cookie_node : storage_node->children()) { + const auto& cookie = cookie_node->GetDetailedInfo().cookie; + EXPECT_EQ("www.example.com", cookie->Domain()); + EXPECT_TRUE(cookie->IsPartitioned()); + } +} + +TEST_F(SiteSettingsHandlerTest, ClearUnpartitionedClearsHints) { + // Confirm that when the user clears unpartitioned storage, client hints + // are also cleared. + SetUpCookiesTreeModel(); GURL hosts[] = {GURL("https://example.com/"), GURL("https://google.com/")}; @@ -2470,10 +2588,10 @@ base::Value::ToUniquePtrValue(client_hints_dictionary.Clone())); } - // Clear usage data. + // Clear unpartitioned usage data. base::Value args(base::Value::Type::LIST); args.Append("https://example.com/"); - handler()->HandleClearUsage(&base::Value::AsListValue(args)); + handler()->HandleClearUnpartitionedUsage(&base::Value::AsListValue(args)); // Validate the client hint has been cleared. host_content_settings_map->GetSettingsForOneType( @@ -2486,6 +2604,44 @@ EXPECT_EQ(client_hints_dictionary, client_hints_settings.at(0).setting_value); } +TEST_F(SiteSettingsHandlerTest, HandleClearPartitionedUsage) { + // Confirm that removing unpartitioned storage correctly removes the + // appropriate nodes. + SetUpCookiesTreeModel(); + EXPECT_EQ(27, handler()->cookies_tree_model_->GetRoot()->GetTotalNodeCount()); + + base::Value args(base::Value::Type::LIST); + args.Append("https://www.example.com/"); + args.Append("google.com"); + handler()->HandleClearPartitionedUsage(&base::Value::AsListValue(args)); + + // This should have only removed cookies for embedded.com partitioned on + // google.com, leaving other cookies and storage untouched. + auto remaining_host_nodes = GetHostNodes(GURL("https://www.example.com")); + ASSERT_EQ(1u, remaining_host_nodes.size()); + + // Both cookies and local storage type nodes should remain. + ASSERT_EQ(2u, remaining_host_nodes[0]->children().size()); + + for (const auto& storage_node : remaining_host_nodes[0]->children()) { + if (storage_node->GetDetailedInfo().node_type == + CookieTreeNode::DetailedInfo::TYPE_COOKIES) { + // Two cookies should remain, one unpartitioned and one partitioned on + // a different site. + ASSERT_EQ(2u, storage_node->children().size()); + for (const auto& cookie_node : storage_node->children()) { + const auto& cookie = cookie_node->GetDetailedInfo().cookie; + if (cookie->IsPartitioned()) + ASSERT_EQ("google.com.au", + cookie->PartitionKey()->site().GetURL().host()); + } + } else { + ASSERT_EQ(storage_node->GetDetailedInfo().node_type, + CookieTreeNode::DetailedInfo::TYPE_LOCAL_STORAGES); + } + } +} + TEST_F(SiteSettingsHandlerTest, CookieSettingDescription) { const auto kBlocked = [](int num) { return l10n_util::GetPluralStringFUTF8(
diff --git a/chrome/browser/web_applications/isolated_app_browsertest.cc b/chrome/browser/web_applications/isolated_app_browsertest.cc index c489c8c..ea279be 100644 --- a/chrome/browser/web_applications/isolated_app_browsertest.cc +++ b/chrome/browser/web_applications/isolated_app_browsertest.cc
@@ -2,20 +2,40 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/barrier_closure.h" +#include "base/run_loop.h" #include "base/test/scoped_feature_list.h" +#include "base/test/test_future.h" +#include "chrome/browser/gcm/gcm_profile_service_factory.h" +#include "chrome/browser/notifications/notification_display_service_tester.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/push_messaging/push_messaging_app_identifier.h" +#include "chrome/browser/push_messaging/push_messaging_constants.h" +#include "chrome/browser/push_messaging/push_messaging_features.h" +#include "chrome/browser/push_messaging/push_messaging_service_factory.h" +#include "chrome/browser/push_messaging/push_messaging_service_impl.h" #include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/web_applications/app_browser_controller.h" +#include "chrome/browser/ui/web_applications/test/web_app_browsertest_util.h" #include "chrome/browser/ui/web_applications/web_app_controller_browsertest.h" #include "chrome/browser/web_applications/test/service_worker_registration_waiter.h" #include "chrome/browser/web_applications/test/web_app_test_utils.h" #include "chrome/test/base/ui_test_utils.h" +#include "components/gcm_driver/common/gcm_message.h" +#include "components/gcm_driver/fake_gcm_profile_service.h" +#include "components/permissions/permission_request_manager.h" +#include "content/public/browser/push_messaging_service.h" +#include "content/public/browser/render_frame_host.h" #include "content/public/browser/service_worker_context.h" +#include "content/public/browser/service_worker_running_info.h" #include "content/public/browser/storage_partition.h" #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" #include "net/test/embedded_test_server/embedded_test_server.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/public/common/features.h" +#include "third_party/blink/public/mojom/service_worker/service_worker_database.mojom-forward.h" namespace web_app { @@ -25,6 +45,125 @@ const char kApp2Host[] = "app2.com"; const char kNonAppHost[] = "nonapp.com"; +const int32_t kApplicationServerKeyLength = 65; +// NIST P-256 public key made available to tests. Must be an uncompressed +// point in accordance with SEC1 2.3.3. +const uint8_t kApplicationServerKey[kApplicationServerKeyLength] = { + 0x04, 0x55, 0x52, 0x6A, 0xA5, 0x6E, 0x8E, 0xAA, 0x47, 0x97, 0x36, + 0x10, 0xC1, 0x66, 0x3C, 0x1E, 0x65, 0xBF, 0xA1, 0x7B, 0xEE, 0x48, + 0xC9, 0xC6, 0xBB, 0xBF, 0x02, 0x18, 0x53, 0x72, 0x1D, 0x0C, 0x7B, + 0xA9, 0xE3, 0x11, 0xB7, 0x03, 0x52, 0x21, 0xD3, 0x71, 0x90, 0x13, + 0xA8, 0xC1, 0xCF, 0xED, 0x20, 0xF7, 0x1F, 0xD1, 0x7F, 0xF2, 0x76, + 0xB6, 0x01, 0x20, 0xD8, 0x35, 0xA5, 0xD9, 0x3C, 0x43, 0xFD}; + +std::string GetTestApplicationServerKey() { + std::string application_server_key( + kApplicationServerKey, + kApplicationServerKey + base::size(kApplicationServerKey)); + + return application_server_key; +} + +class BaseServiceWorkerVersionWaiter + : public content::ServiceWorkerContextObserver { + public: + explicit BaseServiceWorkerVersionWaiter( + content::StoragePartition* storage_partition) { + DCHECK(storage_partition); + + service_worker_context_ = storage_partition->GetServiceWorkerContext(); + service_worker_context_->AddObserver(this); + } + + BaseServiceWorkerVersionWaiter(const BaseServiceWorkerVersionWaiter&) = + delete; + BaseServiceWorkerVersionWaiter& operator=( + const BaseServiceWorkerVersionWaiter&) = delete; + + ~BaseServiceWorkerVersionWaiter() override { + if (service_worker_context_) + service_worker_context_->RemoveObserver(this); + } + + protected: + raw_ptr<content::ServiceWorkerContext> service_worker_context_; + + private: + void OnDestruct(content::ServiceWorkerContext* context) override { + service_worker_context_->RemoveObserver(this); + service_worker_context_ = nullptr; + } +}; + +class ServiceWorkerVersionActivatedWaiter + : public BaseServiceWorkerVersionWaiter { + public: + ServiceWorkerVersionActivatedWaiter( + content::StoragePartition* storage_partition, + GURL& url) + : BaseServiceWorkerVersionWaiter(storage_partition), url_(url) {} + + int64_t AwaitVersionActivated() { return future.Get(); } + + private: + // content::ServiceWorkerContextObserver: + void OnVersionActivated(int64_t version_id, const GURL& scope) override { + if (content::ServiceWorkerContext::ScopeMatches(scope, url_)) { + future.SetValue(version_id); + } + } + + const GURL url_; + base::test::TestFuture<int64_t> future; +}; + +class ServiceWorkerVersionStartedRunningWaiter + : public BaseServiceWorkerVersionWaiter { + public: + ServiceWorkerVersionStartedRunningWaiter( + content::StoragePartition* storage_partition, + int64_t version_id) + : BaseServiceWorkerVersionWaiter(storage_partition), + version_id_(version_id) {} + + void AwaitVersionStartedRunning() { run_loop_.Run(); } + + private: + // content::ServiceWorkerContextObserver: + void OnVersionStartedRunning( + int64_t version_id, + const content::ServiceWorkerRunningInfo& running_info) override { + if (version_id == version_id_) { + run_loop_.Quit(); + } + } + + const int64_t version_id_ = blink::mojom::kInvalidServiceWorkerVersionId; + base::RunLoop run_loop_; +}; + +class ServiceWorkerVersionStoppedRunningWaiter + : public BaseServiceWorkerVersionWaiter { + public: + ServiceWorkerVersionStoppedRunningWaiter( + content::StoragePartition* storage_partition, + int64_t version_id) + : BaseServiceWorkerVersionWaiter(storage_partition), + version_id_(version_id) {} + + void AwaitVersionStoppedRunning() { run_loop_.Run(); } + + private: + // content::ServiceWorkerContextObserver: + void OnVersionStoppedRunning(int64_t version_id) override { + if (version_id == version_id_) { + run_loop_.Quit(); + } + } + + const int64_t version_id_ = blink::mojom::kInvalidServiceWorkerVersionId; + base::RunLoop run_loop_; +}; } // namespace class IsolatedAppBrowserTest : public WebAppControllerBrowserTest { @@ -187,31 +326,167 @@ class IsolatedAppBrowserServiceWorkerTest : public IsolatedAppBrowserTest { protected: - content::RenderFrameHost* InstallIsolatedAppAndWaitForServiceWorker( - const GURL& app_url) { + void SetUpOnMainThread() override { + IsolatedAppBrowserTest::SetUpOnMainThread(); + + app_url_ = https_server()->GetURL(kAppHost, + "/banners/isolated/service_worker.html"); + } + + int64_t InstallIsolatedAppAndWaitForServiceWorker() { InstallIsolatedApp(kAppHost); - auto* app_window = NavigateInNewWindowAndAwaitInstallabilityCheck(app_url); - auto* web_contents = app_window->tab_strip_model()->GetActiveWebContents(); - auto* app_frame = web_contents->GetMainFrame(); - EXPECT_NE(default_storage_partition(), app_frame->GetStoragePartition()); + app_window_ = NavigateInNewWindowAndAwaitInstallabilityCheck(app_url_); + app_web_contents_ = app_window_->tab_strip_model()->GetActiveWebContents(); + app_frame_ = app_web_contents_->GetMainFrame(); + storage_partition_ = app_frame_->GetStoragePartition(); + EXPECT_NE(default_storage_partition(), storage_partition_); - ServiceWorkerRegistrationWaiter waiter(app_frame->GetStoragePartition(), - app_url); - waiter.AwaitRegistration(); + ServiceWorkerVersionActivatedWaiter version_activated_waiter( + storage_partition_, app_url_); - return app_frame; + return version_activated_waiter.AwaitVersionActivated(); } + + Browser* app_window_; + content::WebContents* app_web_contents_; + content::RenderFrameHost* app_frame_; + content::StoragePartition* storage_partition_; + + GURL app_url_; }; IN_PROC_BROWSER_TEST_F(IsolatedAppBrowserServiceWorkerTest, ServiceWorkerPartitioned) { - const GURL app_url = - https_server()->GetURL(kAppHost, "/banners/isolated/service_worker.html"); - - auto* app_frame = InstallIsolatedAppAndWaitForServiceWorker(app_url); + InstallIsolatedAppAndWaitForServiceWorker(); test::CheckServiceWorkerStatus( - app_url, app_frame->GetStoragePartition(), + app_url_, storage_partition_, content::ServiceWorkerCapability::SERVICE_WORKER_WITH_FETCH_HANDLER); } + +class IsolatedAppBrowserServiceWorkerPushTest + : public IsolatedAppBrowserServiceWorkerTest { + public: + IsolatedAppBrowserServiceWorkerPushTest() + : scoped_testing_factory_installer_( + base::BindRepeating(&gcm::FakeGCMProfileService::Build)) {} + + protected: + void SetUpOnMainThread() override { + IsolatedAppBrowserServiceWorkerTest::SetUpOnMainThread(); + + notification_tester_ = std::make_unique<NotificationDisplayServiceTester>( + browser()->profile()); + } + + void SendMessageAndWaitUntilHandled( + content::BrowserContext* context, + const PushMessagingAppIdentifier& app_identifier, + const gcm::IncomingMessage& message) { + auto* push_service = PushMessagingServiceFactory::GetForProfile(context); + base::RunLoop run_loop; + base::RepeatingClosure quit_barrier = + base::BarrierClosure(2 /* num_closures */, run_loop.QuitClosure()); + push_service->SetMessageCallbackForTesting(quit_barrier); + notification_tester_->SetNotificationAddedClosure(quit_barrier); + push_service->OnMessage(app_identifier.app_id(), message); + run_loop.Run(); + } + + PushMessagingAppIdentifier GetAppIdentifierForServiceWorkerRegistration( + int64_t service_worker_registration_id) { + GURL origin = url::Origin::Create(app_url_).GetURL(); + + PushMessagingAppIdentifier app_identifier = + PushMessagingAppIdentifier::FindByServiceWorker( + browser()->profile(), origin, service_worker_registration_id); + return app_identifier; + } + + std::string RunScript(content::RenderFrameHost* app_frame, + const std::string& script) { + std::string script_result; + EXPECT_TRUE(content::ExecuteScriptAndExtractString(app_frame, script, + &script_result)); + return script_result; + } + + std::unique_ptr<NotificationDisplayServiceTester> notification_tester_; + + private: + gcm::GCMProfileServiceFactory::ScopedTestingFactoryInstaller + scoped_testing_factory_installer_; +}; + +IN_PROC_BROWSER_TEST_F( + IsolatedAppBrowserServiceWorkerPushTest, + ServiceWorkerPartitionedWhenWakingUpDuetoPushNotification) { + int64_t service_worker_version_id = + InstallIsolatedAppAndWaitForServiceWorker(); + + // Request and confirm permission to show notifications. + auto* permission_request_manager = + permissions::PermissionRequestManager::FromWebContents(app_web_contents_); + permission_request_manager->set_auto_response_for_test( + permissions::PermissionRequestManager::ACCEPT_ALL); + ASSERT_EQ("permission status - granted", + RunScript(app_frame_, "requestNotificationPermission()")); + + // Subscribe to push notifications and retrieve the app identifier. + std::string push_messaging_endpoint = + RunScript(app_frame_, "documentSubscribePush()"); + size_t last_slash = push_messaging_endpoint.rfind('/'); + ASSERT_EQ(kPushMessagingGcmEndpoint, + push_messaging_endpoint.substr(0, last_slash + 1)); + PushMessagingAppIdentifier app_identifier = + GetAppIdentifierForServiceWorkerRegistration(0LL); + EXPECT_FALSE(app_identifier.is_null()); + + // Close the browser and stop the ServiceWorker + ServiceWorkerVersionStoppedRunningWaiter version_stopped_waiter( + storage_partition_, service_worker_version_id); + CloseBrowserSynchronously(app_window_); + base::RunLoop run_loop; + storage_partition_->GetServiceWorkerContext()->StopAllServiceWorkers( + run_loop.QuitClosure()); + run_loop.Run(); + version_stopped_waiter.AwaitVersionStoppedRunning(); + + // Push a message to the ServiceWorker and make sure the service worker is + // started again. + ServiceWorkerVersionStartedRunningWaiter version_started_waiter( + storage_partition_, service_worker_version_id); + + gcm::IncomingMessage message; + message.sender_id = GetTestApplicationServerKey(); + message.raw_data = "test"; + message.decrypted = true; + SendMessageAndWaitUntilHandled(browser()->profile(), app_identifier, message); + + version_started_waiter.AwaitVersionStartedRunning(); + + // Verify that the ServiceWorker has received the push message and created + // a push notification, then click on it. + auto notifications = notification_tester_->GetDisplayedNotificationsForType( + NotificationHandler::Type::WEB_PERSISTENT); + EXPECT_EQ(notifications.size(), 1UL); + + web_app::BrowserWaiter browser_waiter(nullptr); + notification_tester_->SimulateClick(NotificationHandler::Type::WEB_PERSISTENT, + notifications[0].id(), absl::nullopt, + absl::nullopt); + + // Check that the click resulted in a new isolated web app window that runs in + // the same isolated non-default storage partition. + auto* new_app_window = browser_waiter.AwaitAdded(); + auto* new_app_frame = + new_app_window->tab_strip_model()->GetActiveWebContents()->GetMainFrame(); + auto* new_storage_partition = new_app_frame->GetStoragePartition(); + EXPECT_EQ(new_storage_partition, storage_partition_); + EXPECT_EQ(new_app_frame->GetWebExposedIsolationLevel(), + content::RenderFrameHost::WebExposedIsolationLevel:: + kMaybeIsolatedApplication); + EXPECT_TRUE(AppBrowserController::IsWebApp(new_app_window)); +} + } // namespace web_app
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt index 429b372..e072d18 100644 --- a/chrome/build/linux.pgo.txt +++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@ -chrome-linux-main-1640109555-7330b9704534b468b8f03f344850f8ac3a456ec1.profdata +chrome-linux-main-1640152356-7110f7b9e061caa182e80e91922d963a27259c43.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index 3c10d9b..d1cae67 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-main-1640109555-4f788d66531f70fd161dada09e32b5851b4fbaae.profdata +chrome-mac-main-1640152356-8f297e453cce0188cadd2b4256a99a8b72186a5a.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index 1a01874..4e81953 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1640120104-62f9b79b00a887290a876ff7e43bd61c1c1ee4e5.profdata +chrome-win32-main-1640162853-e127f09e7d28173b7f76e48ecb02c54042744ba6.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index d6bfcc6..72066b2 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-main-1640120104-5f892614cbc8389f8f2aaaa4f4b032ceaee1d505.profdata +chrome-win64-main-1640162853-3c4bf97ec3b654f6ce6b7df852105d11837a41cc.profdata
diff --git a/chrome/common/extensions/api/accessibility_private.json b/chrome/common/extensions/api/accessibility_private.json index 912f11a..e407365 100644 --- a/chrome/common/extensions/api/accessibility_private.json +++ b/chrome/common/extensions/api/accessibility_private.json
@@ -242,6 +242,12 @@ "type": "string", "enum": [ "previousParagraph", "previousSentence", "pause", "resume", "nextSentence", "nextParagraph", "exit", "changeSpeed" ], "description": "Actions that can be performed in the Select-to-speak panel." + }, + { + "id": "SetNativeChromeVoxResponse", + "type": "string", + "enum": [ "success", "talkbackNotInstalled", "windowNotFound", "failure" ], + "description": "Response code for onNativeChromeVoxArcSupportResult" } ], "properties": { @@ -423,7 +429,18 @@ "type": "boolean", "description": "True for ChromeVox (native), false for TalkBack." } - ] + ], + "returns_async": { + "name": "callback", + "desctiprion": "Callback function.", + "parameters": [ + { + "name": "response", + "$ref": "SetNativeChromeVoxResponse", + "description": "Return Success if successfully toggled. Return error description otherwise." + } + ] + } }, { "name": "sendSyntheticKeyEvent",
diff --git a/chrome/renderer/cart/commerce_hint_agent.cc b/chrome/renderer/cart/commerce_hint_agent.cc index 730538a..2535b07 100644 --- a/chrome/renderer/cart/commerce_hint_agent.cc +++ b/chrome/renderer/cart/commerce_hint_agent.cc
@@ -233,6 +233,10 @@ content::RenderFrame* render_frame) { // Connect to Mojo service on browser to notify commerce signals. mojo::Remote<mojom::CommerceHintObserver> observer; + + // Subframes including fenced frames shouldn't be reached here. + DCHECK(render_frame->IsMainFrame() && !render_frame->IsInFencedFrameTree()); + render_frame->GetBrowserInterfaceBroker()->GetInterface( observer.BindNewPipeAndPassReceiver()); return observer; @@ -630,6 +634,9 @@ : content::RenderFrameObserver(render_frame), content::RenderFrameObserverTracker<CommerceHintAgent>(render_frame) { DCHECK(render_frame); + + // Subframes including fenced frames shouldn't be reached here. + DCHECK(render_frame->IsMainFrame() && !render_frame->IsInFencedFrameTree()); } CommerceHintAgent::~CommerceHintAgent() = default;
diff --git a/chrome/renderer/cart/commerce_hint_agent_browsertest.cc b/chrome/renderer/cart/commerce_hint_agent_browsertest.cc index 9d8ce3d..f86a0087 100644 --- a/chrome/renderer/cart/commerce_hint_agent_browsertest.cc +++ b/chrome/renderer/cart/commerce_hint_agent_browsertest.cc
@@ -27,6 +27,7 @@ #include "components/signin/public/identity_manager/identity_test_utils.h" #include "components/ukm/test_ukm_recorder.h" #include "content/public/test/browser_test.h" +#include "content/public/test/fenced_frame_test_util.h" #include "content/public/test/test_navigation_observer.h" #include "net/dns/mock_host_resolver.h" #include "net/test/embedded_test_server/embedded_test_server.h" @@ -166,7 +167,7 @@ using FormSubmittedEntry = ukm::builders::Shopping_FormSubmitted; using XHREntry = ukm::builders::Shopping_WillSendRequest; - void SetUpInProcessBrowserTestFixture() override { + CommerceHintAgentTest() { scoped_feature_list_.InitWithFeaturesAndParameters( {{ntp_features::kNtpChromeCartModule, {{"product-skip-pattern", "(^|\\W)(?i)(skipped)(\\W|$)"}, @@ -1180,4 +1181,42 @@ WaitForUmaBucketCount("Commerce.Carts.ExtractionTimedOut", 0, 2); } + +class CommerceHintAgentFencedFrameTest : public CommerceHintAgentTest { + public: + CommerceHintAgentFencedFrameTest() = default; + ~CommerceHintAgentFencedFrameTest() override = default; + CommerceHintAgentFencedFrameTest(const CommerceHintAgentFencedFrameTest&) = + delete; + + CommerceHintAgentFencedFrameTest& operator=( + const CommerceHintAgentFencedFrameTest&) = delete; + + content::test::FencedFrameTestHelper& fenced_frame_test_helper() { + return fenced_frame_helper_; + } + + private: + content::test::FencedFrameTestHelper fenced_frame_helper_; +}; + +IN_PROC_BROWSER_TEST_F(CommerceHintAgentFencedFrameTest, + VisitCartInFencedFrame) { + // For add-to-cart by URL, normally a URL in that domain has already been + // committed. + NavigateToURL("https://www.guitarcenter.com/cart.html"); + WaitForUmaCount("Commerce.Carts.VisitCart", 1); + + // Create a fenced frame. + GURL fenced_frame_url = + https_server_.GetURL("www.guitarcenter.com", "/cart.html"); + content::RenderFrameHost* fenced_frame_host = + fenced_frame_test_helper().CreateFencedFrame( + web_contents()->GetMainFrame(), fenced_frame_url); + EXPECT_NE(nullptr, fenced_frame_host); + + // Do not affect counts. + WaitForUmaCount("Commerce.Carts.VisitCart", 1); +} + } // namespace
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc index 5f853f9..4c75b556 100644 --- a/chrome/renderer/chrome_content_renderer_client.cc +++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -700,8 +700,11 @@ new SearchBox(render_frame); } + // We should create CommerceHintAgent only for a primary main frame. A fenced + // frame is the main frame as well, so we should check if |render_frame| + // is the primary main frame. if (base::FeatureList::IsEnabled(ntp_features::kNtpChromeCartModule) && - render_frame->IsMainFrame()) { + render_frame->IsMainFrame() && !render_frame->IsInFencedFrameTree()) { new cart::CommerceHintAgent(render_frame); } #endif // !defined(OS_ANDROID)
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index ef5489c..bd62f0b 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -2574,6 +2574,7 @@ "../browser/extensions/api/i18n/i18n_apitest.cc", "../browser/extensions/api/identity/identity_apitest.cc", "../browser/extensions/api/identity/identity_private_apitest.cc", + "../browser/extensions/api/identity/web_auth_flow_browsertest.cc", "../browser/extensions/api/idle/idle_apitest.cc", "../browser/extensions/api/idltest/idltest_apitest.cc", "../browser/extensions/api/image_writer_private/extractor_browsertest.cc", @@ -8516,6 +8517,12 @@ "//third_party/mesa_headers", "//ui/resources:ui_test_pak_data", ] + if (is_chromeos_ash && enable_extensions) { + # For ChromeVox tests. + data_deps += [ "//chrome/browser/resources/chromeos/accessibility:build" ] + data += [ "$root_out_dir/resources/chromeos/" ] + } + if (is_linux || is_chromeos || is_win) { data_deps += [ "//chrome:packed_resources" ] }
diff --git a/chrome/test/data/banners/isolated/service_worker.html b/chrome/test/data/banners/isolated/service_worker.html index 173fbab..4a6c0a8f 100644 --- a/chrome/test/data/banners/isolated/service_worker.html +++ b/chrome/test/data/banners/isolated/service_worker.html
@@ -1,4 +1,16 @@ <head> <title>Web app banner isolated service worker test page</title> - <script>navigator.serviceWorker.register('/banners/service_worker.js');</script> + <!-- + TODO: The test hangs if we add this line. + <link rel="manifest" href="/banners/manifest_isolated.json"> + --> + <script src="../../result_queue.js"></script> + <script src="../../push_messaging/push_constants.js"></script> + <script src="../../push_messaging/push_test.js"></script> + <script> + navigator.serviceWorker.register('/banners/isolated/service_worker.js'); + </script> </head> +<body> + Isolated Service Worker Test Page. +</body>
diff --git a/chrome/test/data/banners/isolated/service_worker.js b/chrome/test/data/banners/isolated/service_worker.js new file mode 100644 index 0000000..ee83f00 --- /dev/null +++ b/chrome/test/data/banners/isolated/service_worker.js
@@ -0,0 +1,26 @@ +// 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. + +self.addEventListener('fetch', e => { + e.respondWith((async () => { + try { + return await fetch(e.request); + } catch (error) { + return new Response('Hello offline page'); + } + })()); +}); + +self.addEventListener('push', event => { + self.registration.showNotification('Hello world!', { + body: 'Test Notification', + }); +}); + +self.addEventListener('notificationclick', event => { + event.notification.close(); + event.waitUntil(self.clients.openWindow( + self.location.origin + '/banners/isolated/service_worker.html' + )); +});
diff --git a/chrome/test/data/banners/isolated/service_worker.js.mock-http-headers b/chrome/test/data/banners/isolated/service_worker.js.mock-http-headers new file mode 100644 index 0000000..5e92f2ea --- /dev/null +++ b/chrome/test/data/banners/isolated/service_worker.js.mock-http-headers
@@ -0,0 +1,4 @@ +HTTP/1.1 200 OK +Content-Type: text/javascript +Cross-Origin-Opener-Policy: same-origin +Cross-Origin-Embedder-Policy: require-corp
diff --git a/chrome/test/data/cart/cart.html.mock-http-headers b/chrome/test/data/cart/cart.html.mock-http-headers new file mode 100644 index 0000000..263e89c4 --- /dev/null +++ b/chrome/test/data/cart/cart.html.mock-http-headers
@@ -0,0 +1,2 @@ +HTTP/1.1 200 OK +Supports-Loading-Mode: fenced-frame \ No newline at end of file
diff --git a/chrome/test/data/extensions/desktop_capture/content.js b/chrome/test/data/extensions/desktop_capture/content.js index ce66aea..3b3ffaf 100644 --- a/chrome/test/data/extensions/desktop_capture/content.js +++ b/chrome/test/data/extensions/desktop_capture/content.js
@@ -10,7 +10,7 @@ window.postMessage(request, "*"); }); -window.addEventListener('message', function(message) { +window.addEventListener('message', function(event) { if (event.source != window || !event.data) { return; }
diff --git a/chrome/test/data/webrtc/getusermedia.js b/chrome/test/data/webrtc/getusermedia.js index dfcdad7f..d1860327 100644 --- a/chrome/test/data/webrtc/getusermedia.js +++ b/chrome/test/data/webrtc/getusermedia.js
@@ -196,5 +196,5 @@ } }); - window.postMessage({desktopSourceTypes: ['window', 'screen']}, '*'); + window.postMessage({desktopSourceTypes: ['window', 'screen', 'tab']}, '*'); }
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/wrapup_repair_complete_page_test.js b/chrome/test/data/webui/chromeos/shimless_rma/wrapup_repair_complete_page_test.js index 19934443..970425e 100644 --- a/chrome/test/data/webui/chromeos/shimless_rma/wrapup_repair_complete_page_test.js +++ b/chrome/test/data/webui/chromeos/shimless_rma/wrapup_repair_complete_page_test.js
@@ -80,11 +80,6 @@ const logsDialog = component.shadowRoot.querySelector('#logsDialog'); assertTrue(!!logsDialog); assertFalse(logsDialog.open); - - const batteryDialog = - component.shadowRoot.querySelector('#batteryCutDialog'); - assertTrue(!!batteryDialog); - assertFalse(batteryDialog.open); }); test('CanShutDown', async () => { @@ -128,7 +123,7 @@ assertTrue(logsDialog.open); }); - test('BatteryCutDialogDisabledByDefault', async () => { + test('BatteryCutButtonDisabledByDefault', async () => { await initializeRepairCompletePage(); const button = component.shadowRoot.querySelector('#batteryCutButton'); @@ -136,7 +131,7 @@ assertTrue(button.disabled); }); - test('PowerCableStateTrueDisablesBatteryCutDialog', async () => { + test('PowerCableStateTrueDisablesBatteryCutButton', async () => { await initializeRepairCompletePage(); service.triggerPowerCableObserver(true, 0); await flushTasks(); @@ -146,7 +141,7 @@ assertTrue(button.disabled); }); - test('PowerCableStateFalseEnablesBatteryCutDialog', async () => { + test('PowerCableStateFalseEnablesBatteryCutButton', async () => { await initializeRepairCompletePage(); service.triggerPowerCableObserver(false, 0); await flushTasks(); @@ -156,19 +151,6 @@ assertFalse(button.disabled); }); - test('OpensBatteryCutDialog', async () => { - await initializeRepairCompletePage(); - // Trigger observation to enable button. - service.triggerPowerCableObserver(false, 0); - await flushTasks(); - await clickButton('#batteryCutButton'); - - const batteryDialog = - component.shadowRoot.querySelector('#batteryCutDialog'); - assertTrue(!!batteryDialog); - assertTrue(batteryDialog.open); - }); - test('DialogCloses', async () => { await initializeRepairCompletePage(); await clickButton('#rmaLogButton'); @@ -179,11 +161,5 @@ assertFalse(logsDialog.open); await clickButton('#batteryCutButton'); - await clickButton('#closeBatteryDialogButton'); - - const batteryDialog = - component.shadowRoot.querySelector('#batteryCutDialog'); - assertTrue(!!batteryDialog); - assertFalse(batteryDialog.open); }); }
diff --git a/chrome/test/data/webui/cr_components/BUILD.gn b/chrome/test/data/webui/cr_components/BUILD.gn index 26da3a6..91b65b3 100644 --- a/chrome/test/data/webui/cr_components/BUILD.gn +++ b/chrome/test/data/webui/cr_components/BUILD.gn
@@ -46,9 +46,9 @@ rebase_path("$root_gen_dir/chrome/test/data/webui/tsc/*", target_gen_dir) ] in_files = [ - "most_visited_focus_test.js", - "most_visited_test.js", - "most_visited_test_support.js", + "most_visited_focus_test.ts", + "most_visited_test.ts", + "most_visited_test_support.ts", ] deps = [ "//ui/webui/resources/cr_components/most_visited:build_ts" ] extra_deps = [ "..:generate_definitions" ]
diff --git a/chrome/test/data/webui/cr_components/most_visited_focus_test.js b/chrome/test/data/webui/cr_components/most_visited_focus_test.ts similarity index 63% rename from chrome/test/data/webui/cr_components/most_visited_focus_test.js rename to chrome/test/data/webui/cr_components/most_visited_focus_test.ts index bdb6f86c..bb3d1a8 100644 --- a/chrome/test/data/webui/cr_components/most_visited_focus_test.js +++ b/chrome/test/data/webui/cr_components/most_visited_focus_test.ts
@@ -7,32 +7,24 @@ import {MostVisitedBrowserProxy} from 'chrome://resources/cr_components/most_visited/browser_proxy.js'; import {MostVisitedElement} from 'chrome://resources/cr_components/most_visited/most_visited.js'; import {MostVisitedPageCallbackRouter, MostVisitedPageHandlerRemote} from 'chrome://resources/cr_components/most_visited/most_visited.mojom-webui.js'; -import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; import {TextDirection} from 'chrome://resources/mojo/mojo/public/mojom/base/text_direction.mojom-webui.js'; import {TestBrowserProxy} from 'chrome://webui-test/test_browser_proxy.js'; import {eventToPromise} from 'chrome://webui-test/test_util.js'; -import {$$, assertFocus, keydown} from './most_visited_test_support.js'; +import {assertFocus, keydown} from './most_visited_test_support.js'; suite('CrComponentsMostVisitedFocusTest', () => { - /** @type {!MostVisitedElement} */ - let mostVisited; + let mostVisited: MostVisitedElement; + let callbackRouterRemote: MostVisitedPageCallbackRouter; - /** @extends {TestBrowserProxy} */ - let callbackRouterRemote; - - /** @return {!Array<!Element>} */ function queryTiles() { - return Array.from(mostVisited.shadowRoot.querySelectorAll('.tile')); + return Array.from( + mostVisited.shadowRoot!.querySelectorAll<HTMLElement>('.tile')); } - /** - * @param {number} n - * @return {!Promise<void>} - */ - async function addTiles(n) { - const tiles = Array(n).fill(0).map((x, i) => { + async function addTiles(n: number): Promise<void> { + const tiles = Array(n).fill(0).map((_x, i) => { const char = String.fromCharCode(i + /* 'a' */ 97); return { title: char, @@ -52,10 +44,11 @@ await tilesRendered; } - setup(/** @suppress {checkTypes} */ () => { - document.innerHTML = ''; + setup(() => { + document.body.innerHTML = ''; - const handler = TestBrowserProxy.fromClass(MostVisitedPageHandlerRemote); + const handler = TestBrowserProxy.fromClass(MostVisitedPageHandlerRemote) as + unknown as MostVisitedPageHandlerRemote; const callbackRouter = new MostVisitedPageCallbackRouter(); MostVisitedBrowserProxy.setInstance( new MostVisitedBrowserProxy(handler, callbackRouter)); @@ -67,70 +60,70 @@ test('right focuses on addShortcut', async () => { await addTiles(1); - const [tile] = queryTiles(); + const tile = queryTiles()[0]!; tile.focus(); keydown(tile, 'ArrowRight'); - assertFocus($$(mostVisited, '#addShortcut')); + assertFocus(mostVisited.$.addShortcut); }); test('right focuses on addShortcut when menu button focused', async () => { await addTiles(1); - const [tile] = queryTiles(); - tile.querySelector('cr-icon-button').focus(); + const tile = queryTiles()[0]!; + tile.querySelector('cr-icon-button')!.focus(); keydown(tile, 'ArrowRight'); - assertFocus($$(mostVisited, '#addShortcut')); + assertFocus(mostVisited.$.addShortcut); }); test('right focuses next tile', async () => { await addTiles(2); - const [first, second] = queryTiles(); - first.focus(); - keydown(first, 'ArrowRight'); - assertFocus(second); + const tiles = queryTiles(); + tiles[0]!.focus(); + keydown(tiles[0]!, 'ArrowRight'); + assertFocus(tiles[1]!); }); test('right focuses on next tile when menu button focused', async () => { await addTiles(2); - const [first, second] = queryTiles(); - first.querySelector('cr-icon-button').focus(); - keydown(first, 'ArrowRight'); - assertFocus(second); + const tiles = queryTiles(); + tiles[0]!.querySelector('cr-icon-button')!.focus(); + keydown(tiles[0]!, 'ArrowRight'); + assertFocus(tiles[1]!); }); test('down focuses on addShortcut', async () => { await addTiles(1); - const [tile] = queryTiles(); + const tile = queryTiles()[0]!; tile.focus(); keydown(tile, 'ArrowDown'); - assertFocus($$(mostVisited, '#addShortcut')); + assertFocus(mostVisited.$.addShortcut); }); test('down focuses next tile', async () => { await addTiles(2); - const [first, second] = queryTiles(); - first.focus(); - keydown(first, 'ArrowDown'); - assertFocus(second); + const tiles = queryTiles(); + tiles[0]!.focus(); + keydown(tiles[0]!, 'ArrowDown'); + assertFocus(tiles[1]!); }); test('up focuses on previous tile from addShortcut', async () => { await addTiles(1); - $$(mostVisited, '#addShortcut').focus(); - keydown($$(mostVisited, '#addShortcut'), 'ArrowUp'); - assertFocus(queryTiles()[0]); + mostVisited.$.addShortcut.focus(); + keydown(mostVisited.$.addShortcut, 'ArrowUp'); + assertFocus(queryTiles()[0]!); }); test('up focuses on previous tile', async () => { await addTiles(2); - const [first, second] = queryTiles(); - second.focus(); - keydown(second, 'ArrowUp'); - assertFocus(first); + const tiles = queryTiles(); + tiles[1]!.focus(); + keydown(tiles[1]!, 'ArrowUp'); + assertFocus(tiles[0]!); }); test('up/left does not change focus when on first tile', async () => { await addTiles(1); - const [tile] = queryTiles(); + const tile = queryTiles()[0]!; tile.focus(); keydown(tile, 'ArrowUp'); assertFocus(tile); @@ -139,10 +132,10 @@ test('up/left/right/down addShortcut and no tiles', async () => { await addTiles(0); - $$(mostVisited, '#addShortcut').focus(); + mostVisited.$.addShortcut.focus(); for (const key of ['ArrowUp', 'ArrowLeft', 'ArrowRight', 'ArrowDown']) { - keydown($$(mostVisited, '#addShortcut'), key); - assertFocus($$(mostVisited, '#addShortcut')); + keydown(mostVisited.$.addShortcut, key); + assertFocus(mostVisited.$.addShortcut); } }); });
diff --git a/chrome/test/data/webui/cr_components/most_visited_test.js b/chrome/test/data/webui/cr_components/most_visited_test.ts similarity index 77% rename from chrome/test/data/webui/cr_components/most_visited_test.js rename to chrome/test/data/webui/cr_components/most_visited_test.ts index f6b3e00e..4d7c5e0a 100644 --- a/chrome/test/data/webui/cr_components/most_visited_test.js +++ b/chrome/test/data/webui/cr_components/most_visited_test.ts
@@ -6,76 +6,52 @@ import {MostVisitedBrowserProxy} from 'chrome://resources/cr_components/most_visited/browser_proxy.js'; import {MostVisitedElement} from 'chrome://resources/cr_components/most_visited/most_visited.js'; -import {MostVisitedPageCallbackRouter, MostVisitedPageHandlerRemote} from 'chrome://resources/cr_components/most_visited/most_visited.mojom-webui.js'; +import {MostVisitedPageCallbackRouter, MostVisitedPageHandlerRemote, MostVisitedTile} from 'chrome://resources/cr_components/most_visited/most_visited.mojom-webui.js'; import {MostVisitedWindowProxy} from 'chrome://resources/cr_components/most_visited/window_proxy.js'; -import {CrActionMenuElement} from 'chrome://resources/cr_elements/cr_action_menu/cr_action_menu.js'; +import {CrButtonElement} from 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; +import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js'; +import {CrInputElement} from 'chrome://resources/cr_elements/cr_input/cr_input.m.js'; import {isMac} from 'chrome://resources/js/cr.m.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; import {TextDirection} from 'chrome://resources/mojo/mojo/public/mojom/base/text_direction.mojom-webui.js'; - import {assertDeepEquals, assertEquals, assertFalse, assertNotEquals, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {TestBrowserProxy} from 'chrome://webui-test/test_browser_proxy.js'; import {eventToPromise, flushTasks} from 'chrome://webui-test/test_util.js'; import {$$, assertNotStyle, assertStyle, keydown} from './most_visited_test_support.js'; -/** @type {!MostVisitedElement} */ -let mostVisited; +let mostVisited: MostVisitedElement; +let windowProxy: MostVisitedWindowProxy&TestBrowserProxy; +let handler: MostVisitedPageHandlerRemote&TestBrowserProxy; +let callbackRouterRemote: MostVisitedPageCallbackRouter; +let mediaListenerWideWidth: FakeMediaQueryList; +let mediaListenerMediumWidth: FakeMediaQueryList; +let mediaListener: Function; -/** @extends {TestBrowserProxy} */ -let windowProxy; - -/** @extends {TestBrowserProxy} */ -let handler; - -/** @extends {TestBrowserProxy} */ -let callbackRouterRemote; - -/** @type {!MediaQueryList} */ -let mediaListenerWideWidth; - -/** @type {!MediaQueryList} */ -let mediaListenerMediumWidth; - -/** @type {!Function} */ -let mediaListener; - -/** - * @param {string} q - * @return {!Array<!Element>} - */ -function queryAll(q) { - return Array.from(mostVisited.shadowRoot.querySelectorAll(q)); +function queryAll<E extends Element = Element>(q: string): E[] { + return Array.from(mostVisited.shadowRoot!.querySelectorAll<E>(q)); } -/** @return {!Array<!Element>} */ -function queryTiles() { - return queryAll('.tile'); +function queryTiles(): HTMLAnchorElement[] { + return queryAll<HTMLAnchorElement>('.tile'); } -/** @return {!Array<!Element>} */ -function queryHiddenTiles() { - return queryAll('.tile[hidden]'); +function queryHiddenTiles(): HTMLAnchorElement[] { + return queryAll<HTMLAnchorElement>('.tile[hidden]'); } -/** @param {number} length */ -function assertTileLength(length) { +function assertTileLength(length: number) { assertEquals(length, queryTiles().length); } -/** @param {number} length */ -function assertHiddenTileLength(length) { +function assertHiddenTileLength(length: number) { assertEquals(length, queryHiddenTiles().length); } -/** - * @param {number|!Array} n - * @param {boolean=} customLinksEnabled - * @param {boolean=} visible - * @return {!Promise<void>} - */ -async function addTiles(n, customLinksEnabled = true, visible = true) { - const tiles = Array.isArray(n) ? n : Array(n).fill(0).map((x, i) => { +async function addTiles( + n: number|MostVisitedTile[], customLinksEnabled: boolean = true, + visible: boolean = true) { + const tiles = Array.isArray(n) ? n : Array(n).fill(0).map((_x, i) => { const char = String.fromCharCode(i + /* 'a' */ 97); return { title: char, @@ -97,18 +73,17 @@ } function assertAddShortcutHidden() { - assertTrue($$(mostVisited, '#addShortcut').hidden); + assertTrue(mostVisited.$.addShortcut.hidden); } function assertAddShortcutShown() { - assertFalse($$(mostVisited, '#addShortcut').hidden); + assertFalse(mostVisited.$.addShortcut.hidden); } -/** - * @suppress {checkTypes} - */ function createBrowserProxy() { - handler = TestBrowserProxy.fromClass(MostVisitedPageHandlerRemote); + handler = TestBrowserProxy.fromClass(MostVisitedPageHandlerRemote) as + unknown as MostVisitedPageHandlerRemote & + TestBrowserProxy; const callbackRouter = new MostVisitedPageCallbackRouter(); MostVisitedBrowserProxy.setInstance( new MostVisitedBrowserProxy(handler, callbackRouter)); @@ -122,20 +97,29 @@ })); } -/** - * @suppress {checkTypes} - */ +class FakeMediaQueryList extends EventTarget implements MediaQueryList { + matches: boolean = false; + media: string; + + constructor(query: string) { + super(); + this.media = query; + } + + addListener(listener: () => void) { + mediaListener = listener; + } + + removeListener() {} + onchange() {} +} + function createWindowProxy() { - windowProxy = TestBrowserProxy.fromClass(MostVisitedWindowProxy); - windowProxy.setResultMapperFor('matchMedia', query => { - const mediaListenerList = /** @type {!MediaQueryList} */ ({ - matches: false, // Used to determine the screen width. - media: query, - addListener(listener) { - mediaListener = listener; - }, - removeListener() {}, - }); + windowProxy = TestBrowserProxy.fromClass(MostVisitedWindowProxy) as unknown as + MostVisitedWindowProxy & + TestBrowserProxy; + windowProxy.setResultMapperFor('matchMedia', (query: string) => { + const mediaListenerList = new FakeMediaQueryList(query); if (query === '(min-width: 672px)') { mediaListenerWideWidth = mediaListenerList; } else if (query === '(min-width: 560px)') { @@ -148,11 +132,7 @@ MostVisitedWindowProxy.setInstance(windowProxy); } -/** - * @param {boolean} isWide - * @param {boolean} isMedium - */ -function updateScreenWidth(isWide, isMedium) { +function updateScreenWidth(isWide: boolean, isMedium: boolean) { assertTrue(!!mediaListenerWideWidth); assertTrue(!!mediaListenerMediumWidth); mediaListenerWideWidth.matches = isWide; @@ -169,8 +149,8 @@ } suite('General', () => { - setup(/** @suppress {checkTypes} */ () => { - document.innerHTML = ''; + setup(() => { + document.body.innerHTML = ''; createBrowserProxy(); createWindowProxy(); @@ -190,35 +170,34 @@ }); test('clicking on add shortcut opens dialog', () => { - assertFalse($$(mostVisited, '#dialog').open); - $$(mostVisited, '#addShortcut').click(); - assertTrue($$(mostVisited, '#dialog').open); + assertFalse(mostVisited.$.dialog.open); + mostVisited.$.addShortcut.click(); + assertTrue(mostVisited.$.dialog.open); }); test('pressing enter when add shortcut has focus opens dialog', () => { - $$(mostVisited, '#addShortcut').focus(); - assertFalse($$(mostVisited, '#dialog').open); - keydown($$(mostVisited, '#addShortcut'), 'Enter'); - assertTrue($$(mostVisited, '#dialog').open); + mostVisited.$.addShortcut.focus(); + assertFalse(mostVisited.$.dialog.open); + keydown(mostVisited.$.addShortcut, 'Enter'); + assertTrue(mostVisited.$.dialog.open); }); test('pressing space when add shortcut has focus opens dialog', () => { - $$(mostVisited, '#addShortcut').focus(); - assertFalse($$(mostVisited, '#dialog').open); - $$(mostVisited, '#addShortcut').dispatchEvent(new KeyboardEvent('keydown', { - key: ' ' - })); - $$(mostVisited, '#addShortcut').dispatchEvent(new KeyboardEvent('keyup', { - key: ' ' - })); - assertTrue($$(mostVisited, '#dialog').open); + mostVisited.$.addShortcut.focus(); + assertFalse(mostVisited.$.dialog.open); + mostVisited.$.addShortcut.dispatchEvent( + new KeyboardEvent('keydown', {key: ' '})); + mostVisited.$.addShortcut.dispatchEvent( + new KeyboardEvent('keyup', {key: ' '})); + assertTrue(mostVisited.$.dialog.open); }); test('four tiles fit on one line with addShortcut', async () => { await addTiles(4); assertEquals(4, queryTiles().length); assertAddShortcutShown(); - const tops = queryAll('a, #addShortcut').map(({offsetTop}) => offsetTop); + const tops = queryAll<HTMLElement>('a, #addShortcut') + .map(({offsetTop}) => offsetTop); assertEquals(5, tops.length); tops.forEach(top => { assertEquals(tops[0], top); @@ -229,7 +208,8 @@ await addTiles(5); assertEquals(5, queryTiles().length); assertAddShortcutShown(); - const tops = queryAll('a, #addShortcut').map(({offsetTop}) => offsetTop); + const tops = queryAll<HTMLElement>('a, #addShortcut') + .map(({offsetTop}) => offsetTop); assertEquals(6, tops.length); const firstRowTop = tops[0]; const secondRowTop = tops[3]; @@ -246,7 +226,8 @@ await addTiles(9); assertEquals(9, queryTiles().length); assertAddShortcutShown(); - const tops = queryAll('a, #addShortcut').map(({offsetTop}) => offsetTop); + const tops = queryAll<HTMLElement>('a, #addShortcut') + .map(({offsetTop}) => offsetTop); assertEquals(10, tops.length); const firstRowTop = tops[0]; const secondRowTop = tops[5]; @@ -263,7 +244,7 @@ await addTiles(10); assertEquals(10, queryTiles().length); assertAddShortcutHidden(); - const tops = queryAll('a:not([hidden])').map(a => a.offsetTop); + const tops = queryAll<HTMLElement>('a:not([hidden])').map(a => a.offsetTop); assertEquals(10, tops.length); const firstRowTop = tops[0]; const secondRowTop = tops[5]; @@ -310,17 +291,17 @@ assertEquals(1, queryTiles().length); assertEquals(0, queryAll('.tile[hidden]').length); assertTrue(mostVisited.hasAttribute('visible_')); - assertFalse($$(mostVisited, '#container').hidden); + assertFalse(mostVisited.$.container.hidden); await addTiles(1, /* customLinksEnabled */ true, /* visible */ false); assertEquals(1, queryTiles().length); assertEquals(0, queryAll('.tile[hidden]').length); assertFalse(mostVisited.hasAttribute('visible_')); - assertTrue($$(mostVisited, '#container').hidden); + assertTrue(mostVisited.$.container.hidden); await addTiles(1, /* customLinksEnabled */ true, /* visible */ true); assertEquals(1, queryTiles().length); assertEquals(0, queryAll('.tile[hidden]').length); assertTrue(mostVisited.hasAttribute('visible_')); - assertFalse($$(mostVisited, '#container').hidden); + assertFalse(mostVisited.$.container.hidden); }); suite('test various widths', () => { @@ -435,7 +416,7 @@ await addTiles(1); // Act. - const tileLink = queryTiles()[0]; + const tileLink = queryTiles()[0]!; // Prevent triggering a navigation, which would break the test. tileLink.href = '#'; tileLink.click(); @@ -478,8 +459,8 @@ }); }); - setup(/** @suppress {checkTypes} */ () => { - document.innerHTML = ''; + setup(() => { + document.body.innerHTML = ''; createBrowserProxy(); createWindowProxy(); @@ -492,24 +473,20 @@ }); suite('add dialog', () => { - let dialog; - let inputName; - - /** @type {!CrInputElement} */ - let inputUrl; - - let saveButton; - let cancelButton; + let dialog: CrDialogElement; + let inputName: CrInputElement; + let inputUrl: CrInputElement; + let saveButton: CrButtonElement; + let cancelButton: CrButtonElement; setup(() => { - dialog = $$(mostVisited, '#dialog'); - inputName = $$(mostVisited, '#dialogInputName'); - inputUrl = - /** @type {!CrInputElement} */ ($$(mostVisited, '#dialogInputUrl')); - saveButton = dialog.querySelector('.action-button'); - cancelButton = dialog.querySelector('.cancel-button'); + dialog = mostVisited.$.dialog; + inputName = $$<CrInputElement>(mostVisited, '#dialogInputName')!; + inputUrl = $$<CrInputElement>(mostVisited, '#dialogInputUrl')!; + saveButton = dialog.querySelector('.action-button')!; + cancelButton = dialog.querySelector('.cancel-button')!; - $$(mostVisited, '#addShortcut').click(); + mostVisited.$.addShortcut.click(); assertTrue(dialog.open); }); @@ -542,7 +519,7 @@ inputName.value = 'name'; inputUrl.value = 'url'; cancelButton.click(); - $$(mostVisited, '#addShortcut').click(); + mostVisited.$.addShortcut.click(); assertEquals('', inputName.value); assertEquals('', inputUrl.value); }); @@ -551,17 +528,17 @@ inputUrl.value = 'url'; const addCalled = handler.whenCalled('addMostVisitedTile'); saveButton.click(); - const [url, title] = await addCalled; + const [_url, title] = await addCalled; assertEquals('url', title); }); test('toast shown on save', async () => { inputUrl.value = 'url'; - assertFalse($$(mostVisited, '#toast').open); + assertFalse(mostVisited.$.toast.open); const addCalled = handler.whenCalled('addMostVisitedTile'); saveButton.click(); await addCalled; - assertTrue($$(mostVisited, '#toast').open); + assertTrue(mostVisited.$.toast.open); }); test('toast has undo buttons when action successful', async () => { @@ -572,7 +549,7 @@ saveButton.click(); await handler.whenCalled('addMostVisitedTile'); await flushTasks(); - assertFalse($$(mostVisited, '#undo').hidden); + assertFalse($$<HTMLElement>(mostVisited, '#undo')!.hidden); }); test('toast has no undo buttons when action successful', async () => { @@ -607,7 +584,7 @@ inputUrl.value = 'url'; const addCalled = handler.whenCalled('addMostVisitedTile'); saveButton.click(); - const [{url}, title] = await addCalled; + const [{url}, _title] = await addCalled; assertEquals('https://url/', url); }); @@ -667,41 +644,36 @@ test('open edit dialog', async () => { await addTiles(2); - const actionMenu = $$(mostVisited, '#actionMenu'); - const dialog = $$(mostVisited, '#dialog'); + const actionMenu = mostVisited.$.actionMenu; + const dialog = mostVisited.$.dialog; assertFalse(actionMenu.open); - queryTiles()[0].querySelector('#actionMenuButton').click(); + queryTiles()[0]!.querySelector<HTMLElement>('#actionMenuButton')!.click(); assertTrue(actionMenu.open); assertFalse(dialog.open); - $$(mostVisited, '#actionMenuEdit').click(); + $$<HTMLElement>(mostVisited, '#actionMenuEdit')!.click(); assertFalse(actionMenu.open); assertTrue(dialog.open); }); suite('edit dialog', () => { - let actionMenu; - let actionMenuButton; - let dialog; - let inputName; - let inputUrl; - let saveButton; - let cancelButton; - let tile; + let actionMenuButton: HTMLElement; + let inputName: CrInputElement; + let inputUrl: CrInputElement; + let saveButton: HTMLElement; + let tile: HTMLAnchorElement; setup(async () => { - actionMenu = $$(mostVisited, '#actionMenu'); - dialog = $$(mostVisited, '#dialog'); - inputName = $$(mostVisited, '#dialogInputName'); - inputUrl = $$(mostVisited, '#dialogInputUrl'); - saveButton = dialog.querySelector('.action-button'); - cancelButton = dialog.querySelector('.cancel-button'); + inputName = $$<CrInputElement>(mostVisited, '#dialogInputName')!; + inputUrl = $$<CrInputElement>(mostVisited, '#dialogInputUrl')!; + + const dialog = mostVisited.$.dialog; + saveButton = dialog.querySelector('.action-button')!; await addTiles(2); - tile = queryTiles()[1]; - actionMenuButton = /** @type {!CrActionMenuElement} */ ( - tile.querySelector('#actionMenuButton')); + tile = queryTiles()[1]!; + actionMenuButton = tile.querySelector<HTMLElement>('#actionMenuButton')!; actionMenuButton.click(); - $$(mostVisited, '#actionMenuEdit').click(); + $$<HTMLElement>(mostVisited, '#actionMenuEdit')!.click(); }); test('edit a tile URL', async () => { @@ -709,23 +681,23 @@ const updateCalled = handler.whenCalled('updateMostVisitedTile'); inputUrl.value = 'updated-url'; saveButton.click(); - const [url, newUrl, newTitle] = await updateCalled; + const [_url, newUrl, _newTitle] = await updateCalled; assertEquals('https://updated-url/', newUrl.url); }); test('toast shown when tile editted', async () => { inputUrl.value = 'updated-url'; - assertFalse($$(mostVisited, '#toast').open); + assertFalse(mostVisited.$.toast.open); saveButton.click(); await handler.whenCalled('updateMostVisitedTile'); - assertTrue($$(mostVisited, '#toast').open); + assertTrue(mostVisited.$.toast.open); }); test('no toast when not editted', async () => { - assertFalse($$(mostVisited, '#toast').open); + assertFalse(mostVisited.$.toast.open); saveButton.click(); await flushTasks(); - assertFalse($$(mostVisited, '#toast').open); + assertFalse(mostVisited.$.toast.open); }); test('edit a tile title', async () => { @@ -733,7 +705,7 @@ const updateCalled = handler.whenCalled('updateMostVisitedTile'); inputName.value = 'updated name'; saveButton.click(); - const [url, newUrl, newTitle] = await updateCalled; + const [_url, _newUrl, newTitle] = await updateCalled; assertEquals('updated name', newTitle); }); @@ -744,10 +716,10 @@ saveButton.click(); // Reopen dialog and edit URL. actionMenuButton.click(); - $$(mostVisited, '#actionMenuEdit').click(); + $$<HTMLElement>(mostVisited, '#actionMenuEdit')!.click(); inputUrl.value = 'updated-url'; saveButton.click(); - const [url, newUrl, newTitle] = await updateCalled; + const [_url, newUrl, _newTitle] = await updateCalled; assertEquals('https://updated-url/', newUrl.url); }); @@ -767,28 +739,29 @@ }); test('remove with action menu', async () => { - const actionMenu = $$(mostVisited, '#actionMenu'); - const removeButton = $$(mostVisited, '#actionMenuRemove'); + const actionMenu = mostVisited.$.actionMenu; + const removeButton = $$<HTMLElement>(mostVisited, '#actionMenuRemove')!; await addTiles(2); - const secondTile = queryTiles()[1]; - const actionMenuButton = secondTile.querySelector('#actionMenuButton'); + const secondTile = queryTiles()[1]!; + const actionMenuButton = + secondTile.querySelector<HTMLElement>('#actionMenuButton')!; assertFalse(actionMenu.open); actionMenuButton.click(); assertTrue(actionMenu.open); const deleteCalled = handler.whenCalled('deleteMostVisitedTile'); - assertFalse($$(mostVisited, '#toast').open); + assertFalse(mostVisited.$.toast.open); removeButton.click(); assertFalse(actionMenu.open); assertEquals('https://b/', (await deleteCalled).url); - assertTrue($$(mostVisited, '#toast').open); + assertTrue(mostVisited.$.toast.open); // Toast buttons are visible. assertTrue(!!$$(mostVisited, '#undo')); assertTrue(!!$$(mostVisited, '#restore')); }); test('remove query with action menu', async () => { - const actionMenu = $$(mostVisited, '#actionMenu'); - const removeButton = $$(mostVisited, '#actionMenuRemove'); + const actionMenu = mostVisited.$.actionMenu; + const removeButton = $$<HTMLElement>(mostVisited, '#actionMenuRemove')!; await addTiles([{ title: 'title', titleDirection: TextDirection.LEFT_TO_RIGHT, @@ -797,15 +770,16 @@ titleSource: 0, isQueryTile: true, }]); - const actionMenuButton = queryTiles()[0].querySelector('#actionMenuButton'); + const actionMenuButton = + queryTiles()[0]!.querySelector<HTMLElement>('#actionMenuButton')!; assertFalse(actionMenu.open); actionMenuButton.click(); assertTrue(actionMenu.open); const deleteCalled = handler.whenCalled('deleteMostVisitedTile'); - assertFalse($$(mostVisited, '#toast').open); + assertFalse(mostVisited.$.toast.open); removeButton.click(); assertEquals('https://search-url/', (await deleteCalled).url); - assertTrue($$(mostVisited, '#toast').open); + assertTrue(mostVisited.$.toast.open); // Toast buttons are visible. assertTrue(!!$$(mostVisited, '#undo')); assertTrue(!!$$(mostVisited, '#restore')); @@ -813,12 +787,13 @@ test('remove with icon button (customLinksEnabled=false)', async () => { await addTiles(1, /* customLinksEnabled */ false); - const removeButton = queryTiles()[0].querySelector('#removeButton'); + const removeButton = + queryTiles()[0]!.querySelector<HTMLElement>('#removeButton')!; const deleteCalled = handler.whenCalled('deleteMostVisitedTile'); - assertFalse($$(mostVisited, '#toast').open); + assertFalse(mostVisited.$.toast.open); removeButton.click(); assertEquals('https://a/', (await deleteCalled).url); - assertTrue($$(mostVisited, '#toast').open); + assertTrue(mostVisited.$.toast.open); // Toast buttons are visible. assertTrue(!!$$(mostVisited, '#undo')); assertTrue(!!$$(mostVisited, '#restore')); @@ -835,12 +810,13 @@ isQueryTile: true, }], /* customLinksEnabled */ false); - const removeButton = queryTiles()[0].querySelector('#removeButton'); + const removeButton = + queryTiles()[0]!.querySelector<HTMLElement>('#removeButton')!; const deleteCalled = handler.whenCalled('deleteMostVisitedTile'); - assertFalse($$(mostVisited, '#toast').open); + assertFalse(mostVisited.$.toast.open); removeButton.click(); assertEquals('https://search-url/', (await deleteCalled).url); - assertTrue($$(mostVisited, '#toast').open); + assertTrue(mostVisited.$.toast.open); // Toast buttons are not visible. assertFalse(!!$$(mostVisited, '#undo')); assertFalse(!!$$(mostVisited, '#restore')); @@ -848,27 +824,27 @@ test('tile url is set to href of <a>', async () => { await addTiles(1); - const [tile] = queryTiles(); + const tile = queryTiles()[0]!; assertEquals('https://a/', tile.href); }); test('delete first tile', async () => { await addTiles(1); - const [tile] = queryTiles(); + const tile = queryTiles()[0]!; const deleteCalled = handler.whenCalled('deleteMostVisitedTile'); - assertFalse($$(mostVisited, '#toast').open); + assertFalse(mostVisited.$.toast.open); keydown(tile, 'Delete'); assertEquals('https://a/', (await deleteCalled).url); - assertTrue($$(mostVisited, '#toast').open); + assertTrue(mostVisited.$.toast.open); }); test('ctrl+z triggers undo and hides toast', async () => { - const toast = $$(mostVisited, '#toast'); + const toast = mostVisited.$.toast; assertFalse(toast.open); // Add a tile and remove it to show the toast. await addTiles(1); - const [tile] = queryTiles(); + const tile = queryTiles()[0]!; keydown(tile, 'Delete'); await handler.whenCalled('deleteMostVisitedTile'); assertTrue(toast.open); @@ -885,18 +861,18 @@ }); test('ctrl+z does nothing if toast buttons are not showing', async () => { - const toast = $$(mostVisited, '#toast'); + const toast = mostVisited.$.toast; assertFalse(toast.open); // A failed attempt at adding a shortcut to show the toast with no buttons. handler.setResultFor('addMostVisitedTile', Promise.resolve({ success: false, })); - $$(mostVisited, '#addShortcut').click(); - const dialog = $$(mostVisited, '#dialog'); - const inputUrl = $$(mostVisited, '#dialogInputUrl'); + mostVisited.$.addShortcut.click(); + const inputUrl = $$<CrInputElement>(mostVisited, '#dialogInputUrl')!; inputUrl.value = 'url'; - const saveButton = dialog.querySelector('.action-button'); + const saveButton = + mostVisited.$.dialog.querySelector<HTMLElement>('.action-button')!; saveButton.click(); await handler.whenCalled('addMostVisitedTile'); @@ -913,41 +889,43 @@ test('toast restore defaults button', async () => { const wait = handler.whenCalled('restoreMostVisitedDefaults'); - const toast = $$(mostVisited, '#toast'); + const toast = mostVisited.$.toast; assertFalse(toast.open); // Add a tile and remove it to show the toast. await addTiles(1); - const [tile] = queryTiles(); + const tile = queryTiles()[0]!; keydown(tile, 'Delete'); await handler.whenCalled('deleteMostVisitedTile'); assertTrue(toast.open); - toast.querySelector('#restore').click(); + toast.querySelector<HTMLElement>('#restore')!.click(); await wait; assertFalse(toast.open); }); test('toast undo button', async () => { const wait = handler.whenCalled('undoMostVisitedTileAction'); - const toast = $$(mostVisited, '#toast'); + const toast = mostVisited.$.toast; assertFalse(toast.open); // Add a tile and remove it to show the toast. await addTiles(1); - const [tile] = queryTiles(); + const tile = queryTiles()[0]!; keydown(tile, 'Delete'); await handler.whenCalled('deleteMostVisitedTile'); assertTrue(toast.open); - toast.querySelector('#undo').click(); + toast.querySelector<HTMLElement>('#undo')!.click(); await wait; assertFalse(toast.open); }); test('drag first tile to second position', async () => { await addTiles(2); - const [first, second] = queryTiles(); + const tiles = queryTiles(); + const first = tiles[0]!; + const second = tiles[1]!; assertEquals('https://a/', first.href); assertTrue(first.draggable); assertEquals('https://b/', second.href); @@ -968,13 +946,15 @@ assertEquals('https://a/', url.url); assertEquals(1, newPos); const [newFirst, newSecond] = queryTiles(); - assertEquals('https://b/', newFirst.href); - assertEquals('https://a/', newSecond.href); + assertEquals('https://b/', newFirst!.href); + assertEquals('https://a/', newSecond!.href); }); test('drag second tile to first position', async () => { await addTiles(2); - const [first, second] = queryTiles(); + const tiles = queryTiles(); + const first = tiles[0]!; + const second = tiles[1]!; assertEquals('https://a/', first.href); assertTrue(first.draggable); assertEquals('https://b/', second.href); @@ -995,13 +975,15 @@ assertEquals('https://b/', url.url); assertEquals(0, newPos); const [newFirst, newSecond] = queryTiles(); - assertEquals('https://b/', newFirst.href); - assertEquals('https://a/', newSecond.href); + assertEquals('https://b/', newFirst!.href); + assertEquals('https://a/', newSecond!.href); }); test('most visited tiles cannot be reordered', async () => { await addTiles(2, /* customLinksEnabled= */ false); - const [first, second] = queryTiles(); + const tiles = queryTiles(); + const first = tiles[0]!; + const second = tiles[1]!; assertEquals('https://a/', first.href); assertTrue(first.draggable); assertEquals('https://b/', second.href); @@ -1019,14 +1001,14 @@ await flushTasks(); assertEquals(0, handler.getCallCount('reorderMostVisitedTile')); const [newFirst, newSecond] = queryTiles(); - assertEquals('https://a/', newFirst.href); - assertEquals('https://b/', newSecond.href); + assertEquals('https://a/', newFirst!.href); + assertEquals('https://b/', newSecond!.href); }); }); suite('Theming', () => { - setup(/** @suppress {checkTypes} */ () => { - document.innerHTML = ''; + setup(() => { + document.body.innerHTML = ''; createBrowserProxy(); createWindowProxy(); @@ -1047,8 +1029,8 @@ titleSource: 0, isQueryTile: false, }]); - const [tile] = queryTiles(); - const titleElement = tile.querySelector('.tile-title'); + const tile = queryTiles()[0]!; + const titleElement = tile.querySelector('.tile-title')!; assertEquals('rtl', window.getComputedStyle(titleElement).direction); }); @@ -1061,17 +1043,16 @@ titleSource: 0, isQueryTile: false, }]); - const [tile] = queryTiles(); - const titleElement = tile.querySelector('.tile-title'); + const tile = queryTiles()[0]!; + const titleElement = tile.querySelector('.tile-title')!; assertEquals('ltr', window.getComputedStyle(titleElement).direction); }); test('setting color styles tile color', () => { // Act. - $$(mostVisited, '#container') - .style.setProperty('--most-visited-text-color', 'blue'); - $$(mostVisited, '#container') - .style.setProperty('--tile-background-color', 'red'); + mostVisited.$.container.style.setProperty( + '--most-visited-text-color', 'blue'); + mostVisited.$.container.style.setProperty('--tile-background-color', 'red'); // Assert. queryAll('.tile-title').forEach(tile => {
diff --git a/chrome/test/data/webui/cr_components/most_visited_test_support.js b/chrome/test/data/webui/cr_components/most_visited_test_support.js deleted file mode 100644 index a97976f..0000000 --- a/chrome/test/data/webui/cr_components/most_visited_test_support.js +++ /dev/null
@@ -1,57 +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. - -import 'chrome://new-tab-page/strings.m.js'; - -import {getDeepActiveElement} from 'chrome://resources/js/util.m.js'; -import {keyDownOn} from 'chrome://resources/polymer/v3_0/iron-test-helpers/mock-interactions.js'; - -import {assertEquals, assertNotEquals} from 'chrome://webui-test/chai_assert.js'; - -/** - * @param {!Element} element - * @param {string} query - * @return {!Element} - */ -export function $$(element, query) { - return element.shadowRoot.querySelector(query); -} - -/** - * @param {!Element} element - * @param {string} key - */ -export function keydown(element, key) { - keyDownOn(element, '', [], key); -} - -/** - * Asserts the computed style value for an element. - * @param {!Element} element The element. - * @param {string} name The name of the style to assert. - * @param {string} expected The expected style value. - */ -export function assertStyle(element, name, expected) { - const actual = window.getComputedStyle(element).getPropertyValue(name).trim(); - assertEquals(expected, actual); -} - -/** - * Asserts the computed style for an element is not value. - * @param {!Element} element The element. - * @param {string} name The name of the style to assert. - * @param {string} not The value the style should not be. - */ -export function assertNotStyle(element, name, not) { - const actual = window.getComputedStyle(element).getPropertyValue(name).trim(); - assertNotEquals(not, actual); -} - -/** - * Asserts that an element is focused. - * @param {!Element} element The element to test. - */ -export function assertFocus(element) { - assertEquals(element, getDeepActiveElement()); -}
diff --git a/chrome/test/data/webui/cr_components/most_visited_test_support.ts b/chrome/test/data/webui/cr_components/most_visited_test_support.ts new file mode 100644 index 0000000..bc5e4c8 --- /dev/null +++ b/chrome/test/data/webui/cr_components/most_visited_test_support.ts
@@ -0,0 +1,47 @@ +// 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 'chrome://new-tab-page/strings.m.js'; + +import {getDeepActiveElement} from 'chrome://resources/js/util.m.js'; +import {keyDownOn} from 'chrome://resources/polymer/v3_0/iron-test-helpers/mock-interactions.js'; + +import {assertEquals, assertNotEquals} from 'chrome://webui-test/chai_assert.js'; + +export function $$<E extends Element = Element>( + element: HTMLElement, query: string): E { + return element.shadowRoot!.querySelector<E>(query)!; +} + +export function keydown(element: Element, key: string) { + keyDownOn(element, 0, [], key); +} + +/** + * Asserts the computed style value for an element. + * @param name The name of the style to assert. + * @param expected The expected style value. + */ +export function assertStyle(element: Element, name: string, expected: string) { + const actual = window.getComputedStyle(element).getPropertyValue(name).trim(); + assertEquals(expected, actual); +} + +/** + * Asserts the computed style for an element is not value. + * @param name The name of the style to assert. + * @param not The value the style should not be. + */ +export function assertNotStyle(element: Element, name: string, not: string) { + const actual = window.getComputedStyle(element).getPropertyValue(name).trim(); + assertNotEquals(not, actual); +} + +/** + * Asserts that an element is focused. + * @param element The element to test. + */ +export function assertFocus(element: Element) { + assertEquals(element, getDeepActiveElement()); +}
diff --git a/chrome/test/data/webui/cr_components/tsconfig_base.json b/chrome/test/data/webui/cr_components/tsconfig_base.json index eeddfb3..371e43b 100644 --- a/chrome/test/data/webui/cr_components/tsconfig_base.json +++ b/chrome/test/data/webui/cr_components/tsconfig_base.json
@@ -1,7 +1,6 @@ { "extends": "../../../../../tools/typescript/tsconfig_base.json", "compilerOptions": { - "allowJs": true, "typeRoots": [ "./../../../../../third_party/node/node_modules/@types" ]
diff --git a/chrome/test/data/webui/settings/all_sites_tests.ts b/chrome/test/data/webui/settings/all_sites_tests.ts index a8b5ff67..3717f89 100644 --- a/chrome/test/data/webui/settings/all_sites_tests.ts +++ b/chrome/test/data/webui/settings/all_sites_tests.ts
@@ -959,8 +959,54 @@ assertEquals( siteGroup.origins[0].origin, - await browserProxy.whenCalled('clearOriginDataAndCookies')); - assertEquals(1, browserProxy.getCallCount('clearOriginDataAndCookies')); + await browserProxy.whenCalled( + 'clearUnpartitionedOriginDataAndCookies')); + + const [origin, types, setting] = + await browserProxy.whenCalled('setOriginPermissions'); + assertEquals(origin, siteGroup.origins[0].origin); + assertEquals(types, null); // Null affects all content types. + assertEquals(setting, ContentSetting.DEFAULT); + + assertEquals( + 1, browserProxy.getCallCount('clearUnpartitionedOriginDataAndCookies')); + assertEquals(1, browserProxy.getCallCount('setOriginPermissions')); + assertEquals(5, testElement.$.allSitesList.items![0].numCookies); + }); + + test('remove partitioned origin', async function() { + const siteGroup = JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP)); + siteGroup.origins[0].isPartitioned = true; + siteGroup.origins[0].numCookies = 1; + siteGroup.origins[1].numCookies = 2; + siteGroup.origins[2].numCookies = 3; + siteGroup.numCookies = 6; + + testElement.siteGroupMap.set( + siteGroup.etldPlus1, JSON.parse(JSON.stringify(siteGroup))); + testElement.forceListUpdateForTesting(); + flush(); + + // Remove the the partitioned entry, which will have been ordered to the + // bottom of the displayed origins. + const siteEntries = + testElement.$.listContainer.querySelectorAll('site-entry'); + const originList = siteEntries[0]!.$.originList.get(); + flush(); + const originEntries = originList.querySelectorAll('.hr'); + assertEquals(3, originEntries.length); + originEntries[2]!.querySelector<HTMLElement>( + '#removeOriginButton')!.click(); + confirmDialog(); + + const [origin, etldPlus1] = + await browserProxy.whenCalled('clearPartitionedOriginDataAndCookies'); + + assertEquals(siteGroup.origins[0].origin, origin); + assertEquals(siteGroup.etldPlus1, etldPlus1); + assertEquals( + 1, browserProxy.getCallCount('clearPartitionedOriginDataAndCookies')); + assertEquals(0, browserProxy.getCallCount('setOriginPermissions')); assertEquals(5, testElement.$.allSitesList.items![0].numCookies); }); @@ -993,7 +1039,8 @@ removeFirstOrigin(); cancelDialog(); - assertEquals(0, browserProxy.getCallCount('clearOriginDataAndCookies')); + assertEquals( + 0, browserProxy.getCallCount('clearUnpartitionedOriginDataAndCookies')); assertEquals(0, browserProxy.getCallCount('setOriginPermissions')); assertEquals(6, testElement.$.allSitesList.items![0].numCookies); });
diff --git a/chrome/test/data/webui/settings/site_entry_tests.ts b/chrome/test/data/webui/settings/site_entry_tests.ts index 7de992d..433f13e 100644 --- a/chrome/test/data/webui/settings/site_entry_tests.ts +++ b/chrome/test/data/webui/settings/site_entry_tests.ts
@@ -10,11 +10,11 @@ import {LocalDataBrowserProxyImpl, SiteEntryElement, SiteSettingsPrefsBrowserProxyImpl, SortMethod} from 'chrome://settings/lazy_load.js'; import {Router, routes} from 'chrome://settings/settings.js'; import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; -import {eventToPromise} from 'chrome://webui-test/test_util.js'; +import {eventToPromise, isChildVisible} from 'chrome://webui-test/test_util.js'; import {TestLocalDataBrowserProxy} from './test_local_data_browser_proxy.js'; import {TestSiteSettingsPrefsBrowserProxy} from './test_site_settings_prefs_browser_proxy.js'; -import {createSiteGroup} from './test_util.js'; +import { createOriginInfo,createSiteGroup} from './test_util.js'; // clang-format on @@ -456,6 +456,12 @@ 'https://www.example.com', 'https://login.example.com', ]); + /** + * An example eTLD+1 Object with a single origin in it. + */ + const TEST_SINGLE_SITE_GROUP = createSiteGroup('foo.com', [ + 'https://login.foo.com', + ]); /** * The mock proxy object to use during test. @@ -528,4 +534,82 @@ assertEquals(testElement.listIndex, index); assertEquals(undefined, origin); }); + + test('partitioned entry interaction', async function() { + // Clone this object to avoid propagating changes made in this test. + const testSiteGroup = JSON.parse(JSON.stringify(TEST_MULTIPLE_SITE_GROUP)); + + // Add a partitioned entry for an unrelated origin. + testSiteGroup.origins.push( + createOriginInfo('wwww.unrelated.com', {isPartitioned: true})); + + testElement.siteGroup = testSiteGroup; + flush(); + const collapseChild = testElement.$.originList.get(); + testElement.$.toggleButton.click(); + flush(); + + const originList = collapseChild.querySelectorAll('.hr'); + assertEquals(4, originList.length); + + // Partitioned entries should not be displaying a link arrow, while + // unpartitioned entries should. + assertTrue(isChildVisible( + originList[0]!, 'cr-icon-button', /*checkLightDom=*/ true)); + assertFalse(isChildVisible( + originList[3]!, 'cr-icon-button', /*checkLightDom=*/ true)); + + // Removing a partitioned entry should fire the appropriate event. + const siteRemoved = eventToPromise('remove-site', testElement); + originList[3]!.querySelector<HTMLElement>('#removeOriginButton')!.click(); + const siteRemovedEvent = await siteRemoved; + + const args = siteRemovedEvent.detail; + const {actionScope, index, origin, isPartitioned} = args; + assertEquals('origin', actionScope); + assertEquals(testElement.listIndex, index); + assertEquals(testElement.siteGroup.origins[3]!.origin, origin); + assertTrue(isPartitioned); + }); + + test('partitioned entry prevents collapse', function() { + // If a siteGroup has a partitioned entry, even if it is the only entry, + // it should keep the site entry as a top level + collapse list. + const testSingleSite = JSON.parse(JSON.stringify(TEST_SINGLE_SITE_GROUP)); + testSingleSite.origins[0].isPartitioned = true; + + testElement.siteGroup = testSingleSite; + flush(); + const collapseChild = testElement.$.originList.get(); + + // The toggle button should expand the collapse, rather than navigate. + const startingRoute = Router.getInstance().getCurrentRoute(); + testElement.$.toggleButton.click(); + flush(); + assertEquals(startingRoute, Router.getInstance().getCurrentRoute()); + + const originList = collapseChild.querySelectorAll('.hr'); + assertEquals(1, originList.length); + }); + + test('unpartitioned entry remains collapsed', async function() { + // Check that a single origin containing unpartitioned storage only is + // correctly collapsed. + testElement.siteGroup = JSON.parse(JSON.stringify(TEST_SINGLE_SITE_GROUP)); + flush(); + const collapseChild = testElement.$.originList.get(); + + const originList = collapseChild.querySelectorAll('.hr'); + testElement.$.toggleButton.click(); + flush(); + assertEquals(0, originList.length); + + // Clicking the toggleButton should navigate the page away, as there is + // only one entry. + testElement.$.toggleButton.click(); + flush(); + assertEquals( + routes.SITE_SETTINGS_SITE_DETAILS.path, + Router.getInstance().getCurrentRoute().path); + }); });
diff --git a/chrome/test/data/webui/settings/test_site_settings_prefs_browser_proxy.ts b/chrome/test/data/webui/settings/test_site_settings_prefs_browser_proxy.ts index b7c3ce9..7002b56 100644 --- a/chrome/test/data/webui/settings/test_site_settings_prefs_browser_proxy.ts +++ b/chrome/test/data/webui/settings/test_site_settings_prefs_browser_proxy.ts
@@ -61,7 +61,8 @@ 'setProtocolHandlerDefault', 'updateIncognitoStatus', 'clearEtldPlus1DataAndCookies', - 'clearOriginDataAndCookies', + 'clearUnpartitionedOriginDataAndCookies', + 'clearPartitionedOriginDataAndCookies', 'recordAction', 'getCookieSettingDescription', 'getRecentSitePermissions', @@ -580,8 +581,14 @@ } /** @override */ - clearOriginDataAndCookies(origin: string) { - this.methodCalled('clearOriginDataAndCookies', origin); + clearUnpartitionedOriginDataAndCookies(origin: string) { + this.methodCalled('clearUnpartitionedOriginDataAndCookies', origin); + } + + /** @override */ + clearPartitionedOriginDataAndCookies(origin: string, etldPlus1: string) { + this.methodCalled( + 'clearPartitionedOriginDataAndCookies', [origin, etldPlus1]); } /** @override */
diff --git a/chrome/test/data/webui/settings/test_util.ts b/chrome/test/data/webui/settings/test_util.ts index 0e0247a4..14d3c37 100644 --- a/chrome/test/data/webui/settings/test_util.ts +++ b/chrome/test/data/webui/settings/test_util.ts
@@ -190,6 +190,7 @@ numCookies: 0, hasPermissionSettings: false, isInstalled: false, + isPartitioned: false, }, override || {}); }
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index 820b5a9..57215768 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -14409.0.0 \ No newline at end of file +14411.0.0 \ No newline at end of file
diff --git a/chromeos/chromeos_strings.grd b/chromeos/chromeos_strings.grd index 22a5581..e0af001 100644 --- a/chromeos/chromeos_strings.grd +++ b/chromeos/chromeos_strings.grd
@@ -2310,20 +2310,8 @@ <message name="IDS_SHIMLESS_RMA_LOGS_SAVE_BUTTON" translateable="false" desc="Label for the logs dialog save to USB button. This triggers saving to the root of a USB drive with no option to select location or title of the logs. It is automatic as the file browser is not available to the shimless RMA app."> Save to USB </message> - <message name="IDS_SHIMLESS_BATTERY_CUTOFF_TITLE" translateable="false" desc="Title for the battery cutoff dialog for confirming or cancelling the cutoff action"> - Battery Cutoff - </message> - <message name="IDS_SHIMLESS_BATTERY_SHUTOFF_UNPLUG_MESSAGE" translateable="false" desc="Message informing user they need to disconnect the power cable to perform battery shutoff"> - Unplug your cord to cut off battery - </message> - <message name="IDS_SHIMLESS_BATTERY_SHUTOFF_SHUTDOWN_MESSAGE" translateable="false" desc="Message informing user the device is ready to be shut down and perform battery shutoff"> - Shut down your device to complete battery cut off - </message> - <message name="IDS_SHIMLESS_BATTERY_SHUTOFF_CANCEL_BUTTON" translateable="false" desc="Label for the battery shutoff dialog cancel button"> - Cancel - </message> - <message name="IDS_SHIMLESS_BATTERY_SHUTOFF_SHUTDOWN_BUTTON" translateable="false" desc="Label for the battery shutoff dialog shut down button."> - Shut down + <message name="IDS_SHIMLESS_BATTERY_SHUTOFF_TOOLTIP_TEXT" translateable="false" desc="Label for the battery shutoff tooltip."> + Unplug power to perform battery cutoff </message> <!-- Run calibration page --> <message name="IDS_SHIMLESS_RMA_RUN_CALIBRATION_PAGE_TITLE" translateable="false" desc="Title for the page shown when running component calibration steps.">
diff --git a/chromeos/profiles/atom.afdo.newest.txt b/chromeos/profiles/atom.afdo.newest.txt index d4fcc29..39ddb27 100644 --- a/chromeos/profiles/atom.afdo.newest.txt +++ b/chromeos/profiles/atom.afdo.newest.txt
@@ -1 +1 @@ -chromeos-chrome-amd64-atom-99-4744.1-1639392235-benchmark-99.0.4768.0-r1-redacted.afdo.xz +chromeos-chrome-amd64-atom-99-4758.0-1639999136-benchmark-99.0.4777.0-r1-redacted.afdo.xz
diff --git a/chromeos/profiles/bigcore.afdo.newest.txt b/chromeos/profiles/bigcore.afdo.newest.txt index 6b956df..ec84f43 100644 --- a/chromeos/profiles/bigcore.afdo.newest.txt +++ b/chromeos/profiles/bigcore.afdo.newest.txt
@@ -1 +1 @@ -chromeos-chrome-amd64-bigcore-99-4744.1-1639397500-benchmark-99.0.4768.0-r1-redacted.afdo.xz +chromeos-chrome-amd64-bigcore-99-4758.0-1639999469-benchmark-99.0.4777.0-r1-redacted.afdo.xz
diff --git a/chromeos/profiles/orderfile.newest.txt b/chromeos/profiles/orderfile.newest.txt index ef4ad5d..a0018a8 100644 --- a/chromeos/profiles/orderfile.newest.txt +++ b/chromeos/profiles/orderfile.newest.txt
@@ -1 +1 @@ -chromeos-chrome-orderfile-field-98-4744.1-1639393599-benchmark-98.0.4758.8-r1.orderfile.xz +chromeos-chrome-orderfile-field-98-4744.1-1639393599-benchmark-98.0.4758.17-r1.orderfile.xz
diff --git a/chromeos/tast_control.gni b/chromeos/tast_control.gni index c5ac07a..27454634 100644 --- a/chromeos/tast_control.gni +++ b/chromeos/tast_control.gni
@@ -104,11 +104,12 @@ # https://crbug.com/1279285: Flaky. "policy.AllowWakeLocks", - # https://crbug.com/1281255 - "nacl.Pnacl", - # https://crbug.com/1281802 "graphics.TraceReplay", + "graphics.TraceReplay.glxgears_stable", + + # https://crbug.com/1281645 + "quicksettings.LockScreen", ] # To disable a specific test in lacros_all_tast_tests, add it the following
diff --git a/components/app_restore/features.cc b/components/app_restore/features.cc index 9b114cc..494ef80 100644 --- a/components/app_restore/features.cc +++ b/components/app_restore/features.cc
@@ -10,6 +10,9 @@ const base::Feature kArcGhostWindow{"ArcGhostWindow", base::FEATURE_ENABLED_BY_DEFAULT}; +const base::Feature kArcWindowPredictor{"ArcWindowPredictor", + base::FEATURE_DISABLED_BY_DEFAULT}; + const base::Feature kFullRestore{"FullRestore", base::FEATURE_ENABLED_BY_DEFAULT}; @@ -18,6 +21,10 @@ base::FeatureList::IsEnabled(kArcGhostWindow); } +bool IsArcWindowPredictorEnabled() { + return base::FeatureList::IsEnabled(kArcWindowPredictor); +} + bool IsFullRestoreEnabled() { return base::FeatureList::IsEnabled(kFullRestore); }
diff --git a/components/app_restore/features.h b/components/app_restore/features.h index 7528a13..a5025be 100644 --- a/components/app_restore/features.h +++ b/components/app_restore/features.h
@@ -15,6 +15,10 @@ // full restore process. COMPONENT_EXPORT(APP_RESTORE) extern const base::Feature kArcGhostWindow; +// Enables the window state and bounds predictor and full ghost window for ARC++ +// apps. +COMPONENT_EXPORT(APP_RESTORE) extern const base::Feature kArcWindowPredictor; + // Enables the full restore feature. If this is enabled, we will restore apps // and app windows after a crash or reboot. COMPONENT_EXPORT(APP_RESTORE) extern const base::Feature kFullRestore;
diff --git a/components/browsing_data/content/canonical_cookie_hash.cc b/components/browsing_data/content/canonical_cookie_hash.cc index fcaa43a6..c7c4c35 100644 --- a/components/browsing_data/content/canonical_cookie_hash.cc +++ b/components/browsing_data/content/canonical_cookie_hash.cc
@@ -12,7 +12,11 @@ size_t FastHash(const net::CanonicalCookie& cookie) { return base::PersistentHash(cookie.Name()) + 3 * base::PersistentHash(cookie.Domain()) + - 7 * base::PersistentHash(cookie.Path()); + 7 * base::PersistentHash(cookie.Path()) + + (cookie.IsPartitioned() + ? 13 * base::PersistentHash( + cookie.PartitionKey()->site().GetURL().host()) + : 0); } bool CanonicalCookieComparer::operator()( @@ -20,7 +24,8 @@ const net::CanonicalCookie& cookie2) const { return cookie1.Name() == cookie2.Name() && cookie1.Domain() == cookie2.Domain() && - cookie1.Path() == cookie2.Path(); + cookie1.Path() == cookie2.Path() && + cookie1.PartitionKey() == cookie2.PartitionKey(); } } // namespace canonical_cookie
diff --git a/components/browsing_data/content/mock_cookie_helper.cc b/components/browsing_data/content/mock_cookie_helper.cc index 59657cc..cbf9789 100644 --- a/components/browsing_data/content/mock_cookie_helper.cc +++ b/components/browsing_data/content/mock_cookie_helper.cc
@@ -29,26 +29,23 @@ } void MockCookieHelper::DeleteCookie(const net::CanonicalCookie& cookie) { - std::string key = cookie.Name() + "=" + cookie.Value(); - ASSERT_TRUE(base::Contains(cookies_, key)); - cookies_[key] = false; + ASSERT_TRUE(base::Contains(cookies_, cookie)); + cookies_[cookie] = false; } -void MockCookieHelper::AddCookieSamples(const GURL& url, - const std::string& cookie_line) { +void MockCookieHelper::AddCookieSamples( + const GURL& url, + const std::string& cookie_line, + absl::optional<net::CookiePartitionKey> cookie_partition_key) { std::unique_ptr<net::CanonicalCookie> cc(net::CanonicalCookie::Create( url, cookie_line, base::Time::Now(), absl::nullopt /* server_time */, - absl::nullopt /* cookie_partition_key */)); + cookie_partition_key)); if (cc.get()) { - for (const auto& cookie : cookie_list_) { - if (cookie.Name() == cc->Name() && cookie.Domain() == cc->Domain() && - cookie.Path() == cc->Path()) { - return; - } - } + if (cookies_.count(*cc)) + return; cookie_list_.push_back(*cc); - cookies_[cookie_line] = true; + cookies_[*cc] = true; } }
diff --git a/components/browsing_data/content/mock_cookie_helper.h b/components/browsing_data/content/mock_cookie_helper.h index 6fcc9201..d334cfa 100644 --- a/components/browsing_data/content/mock_cookie_helper.h +++ b/components/browsing_data/content/mock_cookie_helper.h
@@ -5,9 +5,10 @@ #ifndef COMPONENTS_BROWSING_DATA_CONTENT_MOCK_COOKIE_HELPER_H_ #define COMPONENTS_BROWSING_DATA_CONTENT_MOCK_COOKIE_HELPER_H_ -#include <map> #include <string> +#include <unordered_map> +#include "components/browsing_data/content/canonical_cookie_hash.h" #include "components/browsing_data/content/cookie_helper.h" #include "net/cookies/canonical_cookie.h" @@ -30,7 +31,10 @@ void DeleteCookie(const net::CanonicalCookie& cookie) override; // Adds some cookie samples. - void AddCookieSamples(const GURL& url, const std::string& cookie_line); + void AddCookieSamples(const GURL& url, + const std::string& cookie_line, + absl::optional<net::CookiePartitionKey> + cookie_partition_key = absl::nullopt); // Notifies the callback. void Notify(); @@ -50,7 +54,11 @@ net::CookieList cookie_list_; // Stores which cookies exist. - std::map<const std::string, bool> cookies_; + std::unordered_map<net::CanonicalCookie, + bool, + canonical_cookie::CanonicalCookieHasher, + canonical_cookie::CanonicalCookieComparer> + cookies_; }; } // namespace browsing_data
diff --git a/components/exo/shell_surface.cc b/components/exo/shell_surface.cc index 32da0d8..703c1de 100644 --- a/components/exo/shell_surface.cc +++ b/components/exo/shell_surface.cc
@@ -13,10 +13,12 @@ #include "ash/wm/window_state.h" #include "base/bind.h" #include "base/logging.h" +#include "base/strings/string_piece.h" #include "base/strings/utf_string_conversions.h" #include "base/trace_event/trace_event.h" #include "chromeos/ui/base/window_state_type.h" #include "components/exo/shell_surface_util.h" +#include "components/exo/window_properties.h" #include "ui/aura/client/aura_constants.h" #include "ui/aura/client/cursor_client.h" #include "ui/aura/env.h" @@ -154,14 +156,19 @@ TRACE_EVENT0("exo", "ShellSurface::Maximize"); if (!widget_) { - initial_show_state_ = ui::SHOW_STATE_MAXIMIZED; + if (initial_show_state_ != ui::SHOW_STATE_FULLSCREEN || + ShouldExitFullscreenFromRestoreOrMaximized()) + initial_show_state_ = ui::SHOW_STATE_MAXIMIZED; return; } - // Note: This will ask client to configure its surface even if already - // maximized. - ScopedConfigure scoped_configure(this, true); - widget_->Maximize(); + if (!widget_->IsFullscreen() || + ShouldExitFullscreenFromRestoreOrMaximized()) { + // Note: This will ask client to configure its surface even if already + // maximized. + ScopedConfigure scoped_configure(this, true); + widget_->Maximize(); + } } void ShellSurface::Minimize() { @@ -182,21 +189,30 @@ TRACE_EVENT0("exo", "ShellSurface::Restore"); if (!widget_) { - initial_show_state_ = ui::SHOW_STATE_NORMAL; + if (initial_show_state_ != ui::SHOW_STATE_FULLSCREEN || + ShouldExitFullscreenFromRestoreOrMaximized()) + initial_show_state_ = ui::SHOW_STATE_NORMAL; return; } - // Note: This will ask client to configure its surface even if not already - // maximized or minimized. - ScopedConfigure scoped_configure(this, true); - widget_->Restore(); + if (!widget_->IsFullscreen() || + ShouldExitFullscreenFromRestoreOrMaximized()) { + // Note: This will ask client to configure its surface even if already + // maximized. + ScopedConfigure scoped_configure(this, true); + widget_->Restore(); + } } void ShellSurface::SetFullscreen(bool fullscreen) { TRACE_EVENT1("exo", "ShellSurface::SetFullscreen", "fullscreen", fullscreen); if (!widget_) { - initial_show_state_ = ui::SHOW_STATE_FULLSCREEN; + if (fullscreen) { + initial_show_state_ = ui::SHOW_STATE_FULLSCREEN; + } else if (initial_show_state_ == ui::SHOW_STATE_FULLSCREEN) { + initial_show_state_ = ui::SHOW_STATE_DEFAULT; + } return; }
diff --git a/components/exo/shell_surface_base.cc b/components/exo/shell_surface_base.cc index 6edecb06..d549478 100644 --- a/components/exo/shell_surface_base.cc +++ b/components/exo/shell_surface_base.cc
@@ -1537,6 +1537,14 @@ return frame_view; } +bool ShellSurfaceBase::ShouldExitFullscreenFromRestoreOrMaximized() { + if (widget_ && widget_->GetNativeWindow()) { + return widget_->GetNativeWindow()->GetProperty( + kRestoreOrMaximizeExitsFullscreen); + } + return false; +} + //////////////////////////////////////////////////////////////////////////////// // ShellSurfaceBase, private:
diff --git a/components/exo/shell_surface_base.h b/components/exo/shell_surface_base.h index 71db71c..e23e5d2 100644 --- a/components/exo/shell_surface_base.h +++ b/components/exo/shell_surface_base.h
@@ -337,6 +337,10 @@ // without actually updating it. bool CalculateCanResize() const; + // Returns true if this surface will exit fullscreen from a restore or + // maximize request. Currently only true for Lacros. + bool ShouldExitFullscreenFromRestoreOrMaximized(); + views::Widget* widget_ = nullptr; bool movement_disabled_ = false; gfx::Point origin_;
diff --git a/components/exo/shell_surface_unittest.cc b/components/exo/shell_surface_unittest.cc index 5e1ceee..6e68cc3 100644 --- a/components/exo/shell_surface_unittest.cc +++ b/components/exo/shell_surface_unittest.cc
@@ -31,6 +31,7 @@ #include "components/exo/test/exo_test_base.h" #include "components/exo/test/exo_test_helper.h" #include "components/exo/test/shell_surface_builder.h" +#include "components/exo/window_properties.h" #include "components/exo/wm_helper.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/aura/client/aura_constants.h" @@ -252,6 +253,44 @@ EXPECT_FALSE(shell_surface->CanMaximize()); } +TEST_F(ShellSurfaceTest, MaximizeFromFullscreen) { + std::unique_ptr<ShellSurface> shell_surface = + test::ShellSurfaceBuilder({256, 256}) + .SetMaximumSize(gfx::Size(10, 10)) + .BuildShellSurface(); + // Act: Maximize after fullscreen + shell_surface->root_surface()->Commit(); + shell_surface->SetFullscreen(true); + shell_surface->root_surface()->Commit(); + shell_surface->Maximize(); + shell_surface->root_surface()->Commit(); + + // Assert: Window should stay fullscreen. + EXPECT_TRUE(shell_surface->GetWidget()->IsFullscreen()); +} + +TEST_F(ShellSurfaceTest, MaximizeExitsFullscreen) { + std::unique_ptr<ShellSurface> shell_surface = + test::ShellSurfaceBuilder({256, 256}) + .SetMaximumSize(gfx::Size(10, 10)) + .BuildShellSurface(); + + // Act: Set window property kRestoreOrMaximizeExitsFullscreen + // then maximize after fullscreen + shell_surface->root_surface()->Commit(); + shell_surface->GetWidget()->GetNativeWindow()->SetProperty( + kRestoreOrMaximizeExitsFullscreen, true); + shell_surface->SetFullscreen(true); + shell_surface->root_surface()->Commit(); + shell_surface->Maximize(); + shell_surface->root_surface()->Commit(); + + // Assert: Window should exit fullscreen and be maximized. + EXPECT_TRUE(shell_surface->GetWidget()->GetNativeWindow()->GetProperty( + kRestoreOrMaximizeExitsFullscreen)); + EXPECT_TRUE(shell_surface->GetWidget()->IsMaximized()); +} + TEST_F(ShellSurfaceTest, Minimize) { gfx::Size buffer_size(256, 256); std::unique_ptr<Buffer> buffer( @@ -305,6 +344,44 @@ shell_surface->GetWidget()->GetWindowBoundsInScreen().size().ToString()); } +TEST_F(ShellSurfaceTest, RestoreFromFullscreen) { + std::unique_ptr<ShellSurface> shell_surface = + test::ShellSurfaceBuilder({256, 256}) + .SetMaximumSize(gfx::Size(10, 10)) + .BuildShellSurface(); + + // Act: Restore after fullscreen + shell_surface->SetFullscreen(true); + shell_surface->root_surface()->Commit(); + shell_surface->Restore(); + shell_surface->root_surface()->Commit(); + + // Assert: Window should stay fullscreen. + EXPECT_TRUE(shell_surface->GetWidget()->IsFullscreen()); +} + +TEST_F(ShellSurfaceTest, RestoreExitsFullscreen) { + std::unique_ptr<ShellSurface> shell_surface = + test::ShellSurfaceBuilder({256, 256}) + .SetMaximumSize(gfx::Size(10, 10)) + .BuildShellSurface(); + + // Act: Set window property kRestoreOrMaximizeExitsFullscreen + // then restore after fullscreen + shell_surface->root_surface()->Commit(); + shell_surface->GetWidget()->GetNativeWindow()->SetProperty( + kRestoreOrMaximizeExitsFullscreen, true); + shell_surface->SetFullscreen(true); + shell_surface->Restore(); + shell_surface->root_surface()->Commit(); + + // Assert: Window should exit fullscreen and be restored. + EXPECT_TRUE(shell_surface->GetWidget()->GetNativeWindow()->GetProperty( + kRestoreOrMaximizeExitsFullscreen)); + EXPECT_EQ(gfx::Size(256, 256), + shell_surface->GetWidget()->GetWindowBoundsInScreen().size()); +} + TEST_F(ShellSurfaceTest, HostWindowBoundsUpdatedAfterCommitWidget) { gfx::Size buffer_size(256, 256); std::unique_ptr<Buffer> buffer( @@ -345,6 +422,33 @@ shell_surface->GetWidget()->GetWindowBoundsInScreen().ToString()); } +TEST_F(ShellSurfaceTest, PreWidgetUnfullscreen) { + std::unique_ptr<ShellSurface> shell_surface = + test::ShellSurfaceBuilder({256, 256}) + .SetNoCommit() + .SetMaximumSize(gfx::Size(10, 10)) + .BuildShellSurface(); + shell_surface->Maximize(); + shell_surface->SetFullscreen(false); + EXPECT_EQ(shell_surface->GetWidget(), nullptr); + shell_surface->root_surface()->Commit(); + EXPECT_TRUE(shell_surface->GetWidget()->IsMaximized()); +} + +TEST_F(ShellSurfaceTest, PreWidgetMaximizeFromFullscreen) { + std::unique_ptr<ShellSurface> shell_surface = + test::ShellSurfaceBuilder({256, 256}) + .SetNoCommit() + .SetMaximumSize(gfx::Size(10, 10)) + .BuildShellSurface(); + // Fullscreen -> Maximize for non Lacros surfaces should stay fullscreen + shell_surface->SetFullscreen(true); + shell_surface->Maximize(); + EXPECT_EQ(shell_surface->GetWidget(), nullptr); + shell_surface->root_surface()->Commit(); + EXPECT_TRUE(shell_surface->GetWidget()->IsFullscreen()); +} + TEST_F(ShellSurfaceTest, SetTitle) { gfx::Size buffer_size(256, 256); std::unique_ptr<Buffer> buffer(
diff --git a/components/exo/window_properties.cc b/components/exo/window_properties.cc index a5f6395..0043acf 100644 --- a/components/exo/window_properties.cc +++ b/components/exo/window_properties.cc
@@ -8,4 +8,6 @@ DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(std::string, kApplicationIdKey, nullptr) +DEFINE_UI_CLASS_PROPERTY_KEY(bool, kRestoreOrMaximizeExitsFullscreen, false) + } // namespace exo
diff --git a/components/exo/window_properties.h b/components/exo/window_properties.h index 303066c..8119b68 100644 --- a/components/exo/window_properties.h +++ b/components/exo/window_properties.h
@@ -16,6 +16,10 @@ // "org.chromium.lacros.<window-id>" for Lacros browser shell surfaces. extern const ui::ClassProperty<std::string*>* const kApplicationIdKey; +// Whether Restore and Maximize should exit full screen for this window. +// Currently only set to true for Lacros windows. +extern const ui::ClassProperty<bool>* const kRestoreOrMaximizeExitsFullscreen; + } // namespace exo #endif // COMPONENTS_EXO_WINDOW_PROPERTIES_H_
diff --git a/components/metrics/BUILD.gn b/components/metrics/BUILD.gn index 8c36b62d..90c21ce4 100644 --- a/components/metrics/BUILD.gn +++ b/components/metrics/BUILD.gn
@@ -156,6 +156,8 @@ if (is_linux || is_chromeos) { sources += [ "drive_metrics_provider_linux.cc", + "psi_memory_parser.h", + "psi_memory_parser_linux.cc", "system_memory_stats_recorder_linux.cc", ] } @@ -513,7 +515,10 @@ } if (is_linux || is_chromeos) { - sources += [ "serialization/serialization_utils_unittest.cc" ] + sources += [ + "psi_memory_parser_linux_unittest.cc", + "serialization/serialization_utils_unittest.cc", + ] deps += [ ":serialization" ] }
diff --git a/components/metrics/psi_memory_parser.h b/components/metrics/psi_memory_parser.h new file mode 100644 index 0000000..c1384dd --- /dev/null +++ b/components/metrics/psi_memory_parser.h
@@ -0,0 +1,114 @@ +// 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_METRICS_PSI_MEMORY_PARSER_H_ +#define COMPONENTS_METRICS_PSI_MEMORY_PARSER_H_ + +#include <string> + +#include "base/gtest_prod_util.h" +#include "base/strings/string_piece.h" + +namespace metrics { + +// Items in internal are - as the name implies - NOT for outside consumption. +// Defined here to allow access to unit test. +namespace internal { + +// Finds the bounds for a substring of |content| which is sandwiched between +// the given |prefix| and |suffix| indices. Search only considers +// the portion of the string starting from |search_start|. +// Returns false if the prefix and/or suffix are not found, true otherwise. +// |start| and |end| are output parameters populated with the indices +// for the middle string. +bool FindMiddleString(const base::StringPiece& content, + size_t search_start, + const base::StringPiece& prefix, + const base::StringPiece& suffix, + size_t* start, + size_t* end); + +} // namespace internal + +// Values as logged in the histogram for memory pressure. +constexpr int kMemPressureMin = 1; // As 0 is for underflow. +constexpr int kMemPressureExclusiveMax = 10000; +constexpr int kMemPressureHistogramBuckets = 100; + +// Enumeration representing success and various failure modes for parsing PSI +// memory data. These values are persisted to logs. Entries should not be +// renumbered and numeric values should never be reused. +enum class ParsePSIMemStatus { + kSuccess, + kReadFileFailed, + kUnexpectedDataFormat, + kInvalidMetricFormat, + kParsePSIValueFailed, + // Magic constant used by the histogram macros. + kMaxValue = kParsePSIValueFailed, +}; + +// PSIMemoryParser has logic to parse results from /proc/memory/pressure +// in Linux, which can be used for memory pressure metrics. +class PSIMemoryParser { + public: + explicit PSIMemoryParser(uint32_t period); + ~PSIMemoryParser(); + + // Parses PSI memory pressure from |content|, for the currently configured + // metrics period (10, 60 or 300 seconds). + // The some and full values are output to |metricSome| and |metricFull|, + // respectively. + // Returns status of the parse operation - ParsePSIMemStatus::kSuccess + // or error code otherwise. + ParsePSIMemStatus ParseMetrics(const base::StringPiece& content, + int* metric_some, + int* metric_full); + + // Raw buffer overload + ParsePSIMemStatus ParseMetrics(const uint8_t* content, + uint32_t len, + int* metric_some, + int* metric_full); + + uint32_t GetPeriod() const; + void LogParseStatus(ParsePSIMemStatus stat); + + PSIMemoryParser(const PSIMemoryParser&) = delete; + PSIMemoryParser& operator=(const PSIMemoryParser&) = delete; + PSIMemoryParser() = delete; + + private: + // Friend it so it can see private members for testing + friend class PSIMemoryParserTest; + FRIEND_TEST_ALL_PREFIXES(PSIMemoryParserTest, CustomInterval); + FRIEND_TEST_ALL_PREFIXES(PSIMemoryParserTest, InvalidInterval); + FRIEND_TEST_ALL_PREFIXES(PSIMemoryParserTest, InternalsA); + FRIEND_TEST_ALL_PREFIXES(PSIMemoryParserTest, InternalsB); + FRIEND_TEST_ALL_PREFIXES(PSIMemoryParserTest, InternalsC); + FRIEND_TEST_ALL_PREFIXES(PSIMemoryParserTest, InternalsD); + FRIEND_TEST_ALL_PREFIXES(PSIMemoryParserTest, InternalsE); + + ParsePSIMemStatus ParseMetricsInternal(const std::string& content, + int* metric_some, + int* metric_full); + + // Retrieves one metric value from |content|, for the currently configured + // metrics category (10, 60 or 300 seconds). + // Only considers the substring between |start| (inclusive) and |end| + // (exclusive). + // Returns the floating-point string representation converted into an integer + // which has the value multiplied by 100 - (10.20 = 1020), for + // histogram usage. + int GetMetricValue(const base::StringPiece& content, + size_t start, + size_t end); + + std::string metric_prefix_; + uint32_t period_; +}; + +} // namespace metrics + +#endif // COMPONENTS_METRICS_PSI_MEMORY_PARSER_H_
diff --git a/components/metrics/psi_memory_parser_linux.cc b/components/metrics/psi_memory_parser_linux.cc new file mode 100644 index 0000000..f5fddb0 --- /dev/null +++ b/components/metrics/psi_memory_parser_linux.cc
@@ -0,0 +1,185 @@ +// 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/metrics/psi_memory_parser.h" + +#include <stddef.h> + +#include <cinttypes> +#include <map> +#include <memory> +#include <string> + +#include "base/metrics/histogram.h" +#include "base/metrics/histogram_functions.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/stringprintf.h" +#include "components/metrics/metrics_log_store.h" + +namespace metrics { + +namespace { + +// Periods supported by standard Linux PSI metricvs. +constexpr uint32_t kMinCollectionInterval = 10; +constexpr uint32_t kMidCollectionInterval = 60; +constexpr uint32_t kMaxCollectionInterval = 300; + +constexpr uint32_t kDefaultCollectionInterval = kMinCollectionInterval; + +// Name of the histogram that represents the success and various failure modes +// for parsing PSI memory data. +const char kParsePSIMemoryHistogramName[] = "ChromeOS.CWP.ParsePSIMemory"; + +constexpr base::StringPiece kContentPrefixSome = "some"; +constexpr base::StringPiece kContentPrefixFull = "full"; +constexpr base::StringPiece kContentTerminator = " total="; +constexpr base::StringPiece kMetricTerminator = " "; + +const char kMetricPrefixFormat[] = "avg%d="; + +} // namespace + +PSIMemoryParser::PSIMemoryParser(uint32_t period) + : period_(kDefaultCollectionInterval) { + if (period == kMinCollectionInterval || period == kMidCollectionInterval || + period == kMaxCollectionInterval) { + period_ = period; + } else { + LOG(WARNING) << "Ignoring invalid interval [" << period << "]"; + } + + metric_prefix_ = base::StringPrintf(kMetricPrefixFormat, period_); +} + +PSIMemoryParser::~PSIMemoryParser() = default; + +uint32_t PSIMemoryParser::GetPeriod() const { + return period_; +} + +int PSIMemoryParser::GetMetricValue(const base::StringPiece& content, + size_t start, + size_t end) { + size_t value_start; + size_t value_end; + if (!internal::FindMiddleString(content, start, metric_prefix_, + kMetricTerminator, &value_start, + &value_end)) { + return -1; + } + if (value_end > end) { + return -1; // Out of bounds of the search area. + } + + double n; + const base::StringPiece metric_value_text = + content.substr(value_start, value_end - value_start); + if (!base::StringToDouble(metric_value_text, &n)) { + return -1; // Unable to convert string to number + } + + // Want to multiply by 100, but to avoid integer truncation, + // do best-effort rounding. + const int preround = static_cast<int>(n * 1000); + return (preround + 5) / 10; +} + +void PSIMemoryParser::LogParseStatus(ParsePSIMemStatus stat) { + constexpr int statCeiling = + static_cast<int>(ParsePSIMemStatus::kMaxValue) + 1; + base::UmaHistogramExactLinear(kParsePSIMemoryHistogramName, + static_cast<int>(stat), statCeiling); +} + +ParsePSIMemStatus PSIMemoryParser::ParseMetrics( + const base::StringPiece& content, + int* metric_some, + int* metric_full) { + size_t str_some_start; + size_t str_some_end; + size_t str_full_start; + size_t str_full_end; + + // Example of content: + // some avg10=0.00 avg60=0.00 avg300=0.00 total=417963 + // full avg10=0.00 avg60=0.00 avg300=0.00 total=205933 + // we will pick one of the columns depending on the colleciton period set + + DCHECK_NE(metric_some, nullptr); + DCHECK_NE(metric_full, nullptr); + + if (!internal::FindMiddleString(content, 0, kContentPrefixSome, + kContentTerminator, &str_some_start, + &str_some_end)) { + return ParsePSIMemStatus::kUnexpectedDataFormat; + } + + if (!internal::FindMiddleString(content, + str_some_end + kContentTerminator.length(), + kContentPrefixFull, kContentTerminator, + &str_full_start, &str_full_end)) { + return ParsePSIMemStatus::kUnexpectedDataFormat; + } + + int compute_some = GetMetricValue(content, str_some_start, str_some_end); + if (compute_some < 0) { + return ParsePSIMemStatus::kInvalidMetricFormat; + } + + int compute_full = GetMetricValue(content, str_full_start, str_full_end); + if (compute_full < 0) { + return ParsePSIMemStatus::kInvalidMetricFormat; + } + + *metric_some = compute_some; + *metric_full = compute_full; + + return ParsePSIMemStatus::kSuccess; +} + +ParsePSIMemStatus PSIMemoryParser::ParseMetrics(const uint8_t* content, + uint32_t len, + int* metric_some, + int* metric_full) { + // The cast below is admittedly sneaky, but inherently safe because + // we are translating a const pointer into another const pointer, + // and the data sizes of the pointed object are the same. + const char* string_content = reinterpret_cast<const char*>(content); + + return ParseMetrics(base::StringPiece(string_content, len), metric_some, + metric_full); +} + +namespace internal { + +bool FindMiddleString(const base::StringPiece& content, + size_t search_start, + const base::StringPiece& prefix, + const base::StringPiece& suffix, + size_t* start, + size_t* end) { + DCHECK_NE(start, nullptr); + DCHECK_NE(end, nullptr); + + size_t compute_start = content.find(prefix, search_start); + if (compute_start == std::string::npos) { + return false; + } + compute_start += prefix.length(); + + size_t compute_end = content.find(suffix, compute_start); + if (compute_end == std::string::npos) { + return false; + } + + *start = compute_start; + *end = compute_end; + + return true; +} + +} // namespace internal + +} // namespace metrics
diff --git a/components/metrics/psi_memory_parser_linux_unittest.cc b/components/metrics/psi_memory_parser_linux_unittest.cc new file mode 100644 index 0000000..0536975f --- /dev/null +++ b/components/metrics/psi_memory_parser_linux_unittest.cc
@@ -0,0 +1,163 @@ +// 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/metrics/psi_memory_parser.h" + +#include <memory> + +#include "base/files/file_util.h" +#include "base/metrics/statistics_recorder.h" +#include "base/test/metrics/histogram_tester.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace metrics { + +namespace { + +// Just as the kernel outputs. +const char kFileContents1[] = + "some avg10=23.10 avg60=5.06 avg300=15.10 total=417963\n" + "full avg10=9.00 avg60=19.20 avg300=3.23 total=205933\n"; + +// Number of decimals not consistent, slightly malformed - but acceptable. +const char kFileContents2[] = + "some avg10=24 avg60=5.06 avg300=15.10 total=417963\n" + "full avg10=9.2 avg60=19.20 avg300=3.23 total=205933\n"; + +} // namespace + +class PSIMemoryParserTest : public testing::Test { + public: + PSIMemoryParserTest() = default; + ~PSIMemoryParserTest() override = default; + + void Init(uint32_t period) { + cit_ = std::make_unique<PSIMemoryParser>(period); + } + + uint32_t GetPeriod() { return cit_->GetPeriod(); } + base::HistogramTester& Histograms() { return histogram_tester_; } + std::unique_ptr<PSIMemoryParser>& Cit() { return cit_; } + const std::string& GetMetricPrefix() { return cit_->metric_prefix_; } + + void KillCit() { cit_.reset(); } + + private: + std::unique_ptr<PSIMemoryParser> cit_; + base::HistogramTester histogram_tester_; +}; + +TEST_F(PSIMemoryParserTest, CustomInterval) { + Init(60u); + + EXPECT_EQ(60u, GetPeriod()); +} + +TEST_F(PSIMemoryParserTest, InvalidInterval) { + Init(15u); + + EXPECT_EQ(10u, GetPeriod()); +} + +TEST_F(PSIMemoryParserTest, InternalsA) { + Init(10u); + + std::string testContent1 = "prefix" + GetMetricPrefix() + "9.37 suffix"; + EXPECT_EQ(10u, GetPeriod()); + + size_t s = 0; + size_t e = 0; + + EXPECT_EQ(false, internal::FindMiddleString(testContent1, 0, "nothere", + "suffix", &s, &e)); + + EXPECT_EQ(false, internal::FindMiddleString(testContent1, 0, "prefix", + "notthere", &s, &e)); + + EXPECT_EQ(true, internal::FindMiddleString(testContent1, 0, "prefix", + "suffix", &s, &e)); + EXPECT_EQ(6u, s); + EXPECT_EQ(17u, e); + + EXPECT_EQ(937, Cit()->GetMetricValue(testContent1, s, e)); + + std::string testContent2 = "extra " + testContent1; + EXPECT_EQ(true, internal::FindMiddleString(testContent2, 0, "prefix", + "suffix", &s, &e)); + EXPECT_EQ(12u, s); + EXPECT_EQ(23u, e); + + EXPECT_EQ(937, Cit()->GetMetricValue(testContent2, s, e)); +} + +TEST_F(PSIMemoryParserTest, InternalsB) { + Init(300); + + int msome; + int mfull; + ParsePSIMemStatus stat; + + stat = Cit()->ParseMetrics(kFileContents1, &msome, &mfull); + + EXPECT_EQ(ParsePSIMemStatus::kSuccess, stat); + EXPECT_EQ(1510, msome); + EXPECT_EQ(323, mfull); +} + +TEST_F(PSIMemoryParserTest, InternalsC) { + Init(60); + + int msome; + int mfull; + ParsePSIMemStatus stat; + + stat = Cit()->ParseMetrics(kFileContents1, &msome, &mfull); + + EXPECT_EQ(ParsePSIMemStatus::kSuccess, stat); + EXPECT_EQ(506, msome); + EXPECT_EQ(1920, mfull); +} + +TEST_F(PSIMemoryParserTest, InternalsD) { + Init(10); + + int msome; + int mfull; + ParsePSIMemStatus stat; + + stat = Cit()->ParseMetrics(kFileContents1, &msome, &mfull); + + EXPECT_EQ(ParsePSIMemStatus::kSuccess, stat); + EXPECT_EQ(2310, msome); + EXPECT_EQ(900, mfull); +} + +TEST_F(PSIMemoryParserTest, InternalsE) { + Init(10); + + int msome; + int mfull; + ParsePSIMemStatus stat; + + stat = Cit()->ParseMetrics(kFileContents2, &msome, &mfull); + + EXPECT_EQ(ParsePSIMemStatus::kSuccess, stat); + EXPECT_EQ(2400, msome); + EXPECT_EQ(920, mfull); +} + +TEST_F(PSIMemoryParserTest, ParseResultCounter) { + Init(10); + + Cit()->LogParseStatus(ParsePSIMemStatus::kSuccess); + Cit()->LogParseStatus(ParsePSIMemStatus::kInvalidMetricFormat); + Cit()->LogParseStatus(ParsePSIMemStatus::kInvalidMetricFormat); + + Histograms().ExpectBucketCount("ChromeOS.CWP.ParsePSIMemory", + ParsePSIMemStatus::kSuccess, 1); + Histograms().ExpectBucketCount("ChromeOS.CWP.ParsePSIMemory", + ParsePSIMemStatus::kInvalidMetricFormat, 2); +} + +} // namespace metrics
diff --git a/components/password_manager/core/browser/login_database.cc b/components/password_manager/core/browser/login_database.cc index 65e8a3d..aa0d4ee 100644 --- a/components/password_manager/core/browser/login_database.cc +++ b/components/password_manager/core/browser/login_database.cc
@@ -628,7 +628,7 @@ return result; } -#if defined(OS_MAC) +#if defined(OS_MAC) || defined(OS_LINUX) // Fills |form| with necessary data required to be removed from the database // and returns it. PasswordForm GetFormForRemoval(sql::Statement& statement) { @@ -1442,9 +1442,10 @@ } DatabaseCleanupResult LoginDatabase::DeleteUndecryptableLogins() { -#if defined(OS_MAC) +#if defined(OS_MAC) || defined(OS_LINUX) TRACE_EVENT0("passwords", "LoginDatabase::DeleteUndecryptableLogins"); - // If the Keychain is unavailable, don't delete any logins. + // If the Keychain in MacOS or the real secret key in Linux is unavailable, + // don't delete any logins. if (!OSCrypt::IsEncryptionAvailable()) { metrics_util::LogDeleteUndecryptableLoginsReturnValue( metrics_util::DeleteCorruptedPasswordsResult::kEncryptionUnavailable);
diff --git a/components/password_manager/core/browser/login_database_unittest.cc b/components/password_manager/core/browser/login_database_unittest.cc index d9c3408..5ffb296 100644 --- a/components/password_manager/core/browser/login_database_unittest.cc +++ b/components/password_manager/core/browser/login_database_unittest.cc
@@ -2078,8 +2078,9 @@ base::HistogramTester histogram_tester; ASSERT_TRUE(db.Init()); -#if defined(OS_MAC) +#if defined(OS_MAC) || (defined(OS_LINUX) && !BUILDFLAG(IS_CHROMECAST)) // Make sure that we can't get any logins when database is corrupted. + // Disabling the checks in chromecast because encryption is unavailable. std::vector<std::unique_ptr<PasswordForm>> result; EXPECT_FALSE(db.GetAutofillableLogins(&result)); EXPECT_TRUE(result.empty()); @@ -2095,12 +2096,15 @@ EXPECT_THAT(result, IsEmpty()); RunUntilIdle(); +#elif (defined(OS_LINUX) && BUILDFLAG(IS_CHROMECAST)) + EXPECT_EQ(DatabaseCleanupResult::kEncryptionUnavailable, + db.DeleteUndecryptableLogins()); #else EXPECT_EQ(DatabaseCleanupResult::kSuccess, db.DeleteUndecryptableLogins()); #endif // Check histograms. -#if defined(OS_MAC) +#if defined(OS_MAC) || (defined(OS_LINUX) && !BUILDFLAG(IS_CHROMECAST)) histogram_tester.ExpectUniqueSample("PasswordManager.CleanedUpPasswords", 2, 1); histogram_tester.ExpectUniqueSample(
diff --git a/components/password_manager/core/browser/sync/password_sync_bridge.cc b/components/password_manager/core/browser/sync/password_sync_bridge.cc index a1fba1e..3a3b928 100644 --- a/components/password_manager/core/browser/sync/password_sync_bridge.cc +++ b/components/password_manager/core/browser/sync/password_sync_bridge.cc
@@ -11,6 +11,7 @@ #include "base/callback.h" #include "base/check_op.h" #include "base/containers/flat_map.h" +#include "base/feature_list.h" #include "base/memory/raw_ptr.h" #include "base/metrics/histogram_functions.h" #include "base/notreached.h" @@ -180,6 +181,9 @@ // Delete the local undecryptable copy when this is MacOS only. #if defined(OS_MAC) return true; +#elif defined(OS_LINUX) + return base::FeatureList::IsEnabled( + features::kSyncUndecryptablePasswordsLinux); #else return false; #endif @@ -314,7 +318,6 @@ // 3. |F| exists in both the local and the remote models --> both versions // should be merged by accepting the most recently created one, and update // local and remote models accordingly. - base::AutoReset<bool> processing_changes(&is_processing_remote_sync_changes_, true);
diff --git a/components/password_manager/core/browser/sync/password_sync_bridge.h b/components/password_manager/core/browser/sync/password_sync_bridge.h index e6e88403..b549e95 100644 --- a/components/password_manager/core/browser/sync/password_sync_bridge.h +++ b/components/password_manager/core/browser/sync/password_sync_bridge.h
@@ -68,11 +68,11 @@ const sync_pb::PasswordSpecificsData& password_data); private: - // On MacOS it may happen that some passwords cannot be decrypted due to - // modification of encryption key in Keychain (https://crbug.com/730625). This - // method deletes those logins from the store. So during merge, the data in - // sync will be added to the password store. This should be called during - // MergeSyncData(). + // On MacOS or Linux it may happen that some passwords cannot be decrypted due + // to modification of encryption key in Keychain or Keyring + // (https://crbug.com/730625). This method deletes those logins from the + // store. So during merge, the data in sync will be added to the password + // store. This should be called during MergeSyncData(). absl::optional<syncer::ModelError> CleanupPasswordStore(); // Retrieves the storage keys of all unsynced passwords in the store.
diff --git a/components/password_manager/core/browser/sync/password_sync_bridge_unittest.cc b/components/password_manager/core/browser/sync/password_sync_bridge_unittest.cc index dc88bc1..4d00f22 100644 --- a/components/password_manager/core/browser/sync/password_sync_bridge_unittest.cc +++ b/components/password_manager/core/browser/sync/password_sync_bridge_unittest.cc
@@ -11,14 +11,17 @@ #include "base/bind.h" #include "base/callback_helpers.h" +#include "base/feature_list.h" #include "base/strings/utf_string_conversions.h" #include "base/test/bind.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/mock_callback.h" +#include "base/test/scoped_feature_list.h" #include "build/build_config.h" #include "components/password_manager/core/browser/insecure_credentials_table.h" #include "components/password_manager/core/browser/password_form.h" #include "components/password_manager/core/browser/password_store_sync.h" +#include "components/password_manager/core/common/password_manager_features.h" #include "components/sync/base/client_tag_hash.h" #include "components/sync/model/data_batch.h" #include "components/sync/model/entity_change.h" @@ -960,10 +963,15 @@ mock_password_store_sync(), base::DoNothing()); } -#if defined(OS_MAC) +#if defined(OS_MAC) || defined(OS_LINUX) // Tests that in case ReadAllLogins() during initial merge returns encryption // service failure, the bridge would try to do a DB clean up. TEST_F(PasswordSyncBridgeTest, ShouldDeleteUndecryptableLoginsDuringMerge) { +#if defined(OS_LINUX) + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature(features::kSyncUndecryptablePasswordsLinux); +#endif + ON_CALL(*mock_password_store_sync(), DeleteUndecryptableLogins()) .WillByDefault(Return(DatabaseCleanupResult::kSuccess));
diff --git a/components/password_manager/core/common/password_manager_features.cc b/components/password_manager/core/common/password_manager_features.cc index cd5b413a..a30673a5 100644 --- a/components/password_manager/core/common/password_manager_features.cc +++ b/components/password_manager/core/common/password_manager_features.cc
@@ -134,6 +134,13 @@ const base::Feature kSupportForAddPasswordsInSettings = { "SupportForAddPasswordsInSettings", base::FEATURE_DISABLED_BY_DEFAULT}; +#if defined(OS_LINUX) +// When enabled, all undecryptable passwords are deleted from the local database +// during initial sync flow. +const base::Feature kSyncUndecryptablePasswordsLinux = { + "SyncUndecryptablePasswordsLinux", base::FEATURE_DISABLED_BY_DEFAULT}; +#endif + // Treat heuritistics to find new password fields as reliable. This enables // password generation on more forms, but could lead to false positives. const base::Feature kTreatNewPasswordHeuristicsAsReliable = {
diff --git a/components/password_manager/core/common/password_manager_features.h b/components/password_manager/core/common/password_manager_features.h index 8d183d8e..74618e62 100644 --- a/components/password_manager/core/common/password_manager_features.h +++ b/components/password_manager/core/common/password_manager_features.h
@@ -41,6 +41,9 @@ extern const base::Feature kReparseServerPredictionsFollowingFormChange; extern const base::Feature kSecondaryServerFieldPredictions; extern const base::Feature kSupportForAddPasswordsInSettings; +#if defined(OS_LINUX) +extern const base::Feature kSyncUndecryptablePasswordsLinux; +#endif extern const base::Feature kTreatNewPasswordHeuristicsAsReliable; #if defined(OS_ANDROID) extern const base::Feature kUnifiedCredentialManagerDryRun;
diff --git a/components/policy/core/browser/webui/policy_status_provider.cc b/components/policy/core/browser/webui/policy_status_provider.cc index 30b795e..dec7a88 100644 --- a/components/policy/core/browser/webui/policy_status_provider.cc +++ b/components/policy/core/browser/webui/policy_status_provider.cc
@@ -63,6 +63,7 @@ callback_.Run(); } +// static void PolicyStatusProvider::GetStatusFromCore(const CloudPolicyCore* core, base::DictionaryValue* dict) { const CloudPolicyStore* store = core->store(); @@ -73,17 +74,7 @@ const std::u16string status = GetPolicyStatusFromStore(store, client); const em::PolicyData* policy = store->policy(); - std::string client_id = policy ? policy->device_id() : std::string(); - std::string username = policy ? policy->username() : std::string(); - - if (policy && policy->has_annotated_asset_id()) - dict->SetString("assetId", policy->annotated_asset_id()); - if (policy && policy->has_annotated_location()) - dict->SetString("location", policy->annotated_location()); - if (policy && policy->has_directory_api_id()) - dict->SetString("directoryApiId", policy->directory_api_id()); - if (policy && policy->has_gaia_id()) - dict->SetString("gaiaId", policy->gaia_id()); + GetStatusFromPolicyData(policy, dict); base::TimeDelta refresh_interval = base::Milliseconds( refresh_scheduler ? refresh_scheduler->GetActualRefreshDelay() @@ -104,8 +95,6 @@ "policiesPushAvailable", refresh_scheduler ? refresh_scheduler->invalidations_available() : false); dict->SetString("status", status); - dict->SetString("clientId", client_id); - dict->SetString("username", username); dict->SetString( "refreshInterval", ui::TimeFormat::Simple(ui::TimeFormat::FORMAT_DURATION, @@ -114,6 +103,26 @@ GetTimeSinceLastRefreshString(last_refresh_time)); } +// static +void PolicyStatusProvider::GetStatusFromPolicyData( + const em::PolicyData* policy, + base::DictionaryValue* dict) { + std::string client_id = policy ? policy->device_id() : std::string(); + std::string username = policy ? policy->username() : std::string(); + + if (policy && policy->has_annotated_asset_id()) + dict->SetString("assetId", policy->annotated_asset_id()); + if (policy && policy->has_annotated_location()) + dict->SetString("location", policy->annotated_location()); + if (policy && policy->has_directory_api_id()) + dict->SetString("directoryApiId", policy->directory_api_id()); + if (policy && policy->has_gaia_id()) + dict->SetString("gaiaId", policy->gaia_id()); + + dict->SetString("clientId", client_id); + dict->SetString("username", username); +} + // CloudPolicyStore errors take precedence to show in the status message. // Other errors (such as transient policy fetching problems) get displayed // only if CloudPolicyStore is in STATUS_OK.
diff --git a/components/policy/core/browser/webui/policy_status_provider.h b/components/policy/core/browser/webui/policy_status_provider.h index d0cb45592..0e6e97c 100644 --- a/components/policy/core/browser/webui/policy_status_provider.h +++ b/components/policy/core/browser/webui/policy_status_provider.h
@@ -13,6 +13,10 @@ class Time; } +namespace enterprise_management { +class PolicyData; +} + namespace policy { class CloudPolicyClient; class CloudPolicyCore; @@ -37,6 +41,9 @@ static void GetStatusFromCore(const CloudPolicyCore* core, base::DictionaryValue* dict); + static void GetStatusFromPolicyData( + const enterprise_management::PolicyData* policy, + base::DictionaryValue* dict); protected: void NotifyStatusChange();
diff --git a/components/policy/core/common/policy_loader_lacros.cc b/components/policy/core/common/policy_loader_lacros.cc index e76ee56..40f5cdf 100644 --- a/components/policy/core/common/policy_loader_lacros.cc +++ b/components/policy/core/common/policy_loader_lacros.cc
@@ -122,6 +122,7 @@ per_profile_ == PolicyPerProfileFilter::kFalse) { *MainUserPolicyDataStorage() = *validator.policy_data(); } + policy_data_ = std::move(validator.policy_data()); return bundle; } @@ -133,6 +134,13 @@ Reload(true); } +enterprise_management::PolicyData* PolicyLoaderLacros::GetPolicyData() { + if (!policy_fetch_response_ || !policy_data_) + return nullptr; + + return policy_data_.get(); +} + // static bool PolicyLoaderLacros::IsMainUserManaged() { return g_is_main_user_managed_;
diff --git a/components/policy/core/common/policy_loader_lacros.h b/components/policy/core/common/policy_loader_lacros.h index 5e64f3f..706baf5 100644 --- a/components/policy/core/common/policy_loader_lacros.h +++ b/components/policy/core/common/policy_loader_lacros.h
@@ -47,6 +47,10 @@ // that is returned. std::unique_ptr<PolicyBundle> Load() override; + // Return the policy data object as received from Ash. Returns nullptr if + // initial load was not done yet. + enterprise_management::PolicyData* GetPolicyData(); + // LacrosChromeServiceDelegateImpl::Observer implementation. // Update and reload the policy with new data. void OnPolicyUpdated( @@ -73,6 +77,9 @@ // Serialized blob of PolicyFetchResponse object received from the server. absl::optional<std::vector<uint8_t>> policy_fetch_response_; + // The parsed policy objects received from Ash. + std::unique_ptr<enterprise_management::PolicyData> policy_data_; + // Checks that the method is called on the right sequence. SEQUENCE_CHECKER(sequence_checker_); };
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json index 1ad38b5..6ab0d6c 100644 --- a/components/policy/resources/policy_templates.json +++ b/components/policy/resources/policy_templates.json
@@ -29615,7 +29615,7 @@ 'DevicePciPeripheralDataAccessEnabled': 'device_pci_peripheral_data_access_enabled_v2.enabled', 'DeviceRestrictedManagedGuestSessionEnabled': 'device_restricted_managed_guest_session_enabled.enabled', 'DeviceLoginScreenPromptOnMultipleMatchingCertificates': 'login_screen_prompt_on_multiple_matching_certificates.value', - 'KioskCRXManifestUpdateURLIgnored': 'kiosk_crx_manifest_update_url_ignored', + 'KioskCRXManifestUpdateURLIgnored': 'kiosk_crx_manifest_update_url_ignored.value', 'DeviceI18nShortcutsEnabled': 'device_i18n_shortcuts_enabled.enabled', 'ChromadToCloudMigrationEnabled': 'chromad_to_cloud_migration_enabled.value', 'DeviceLoginScreenWebUILazyLoading': 'login_web_ui_lazy_loading.enabled',
diff --git a/components/sync/protocol/proto_enum_conversions.cc b/components/sync/protocol/proto_enum_conversions.cc index 71f77ee..a702f3f8 100644 --- a/components/sync/protocol/proto_enum_conversions.cc +++ b/components/sync/protocol/proto_enum_conversions.cc
@@ -682,6 +682,19 @@ return ""; } +const char* ProtoEnumToString( + sync_pb::WebauthnCredentialSpecifics::PaymentsSupport payments_support) { + ASSERT_ENUM_BOUNDS(sync_pb::WebauthnCredentialSpecifics, PaymentsSupport, + NONE, FIRST_AND_THIRD_PARTY); + switch (payments_support) { + ENUM_CASE(sync_pb::WebauthnCredentialSpecifics, NONE); + ENUM_CASE(sync_pb::WebauthnCredentialSpecifics, FIRST_PARTY); + ENUM_CASE(sync_pb::WebauthnCredentialSpecifics, FIRST_AND_THIRD_PARTY); + } + NOTREACHED(); + return ""; +} + #undef ASSERT_ENUM_BOUNDS #undef ENUM_CASE
diff --git a/components/sync/protocol/proto_enum_conversions.h b/components/sync/protocol/proto_enum_conversions.h index 9ae07b1..ac1ef6d 100644 --- a/components/sync/protocol/proto_enum_conversions.h +++ b/components/sync/protocol/proto_enum_conversions.h
@@ -152,6 +152,10 @@ const char* ProtoEnumToString( sync_pb::UserConsentTypes::AssistantActivityControlConsent::SettingType setting_type); + +const char* ProtoEnumToString( + sync_pb::WebauthnCredentialSpecifics::PaymentsSupport payments_support); + } // namespace syncer #endif // COMPONENTS_SYNC_PROTOCOL_PROTO_ENUM_CONVERSIONS_H_
diff --git a/components/sync/protocol/proto_visitors.h b/components/sync/protocol/proto_visitors.h index c129c1e..b922537 100644 --- a/components/sync/protocol/proto_visitors.h +++ b/components/sync/protocol/proto_visitors.h
@@ -674,6 +674,7 @@ VISIT(creation_time); VISIT(user_name); VISIT(user_display_name); + VISIT_ENUM(payments_support); // |private_key| is deliberately omitted to avoid including sensitive // information in debugging output, which might be included in bug reports // etc.
diff --git a/components/sync/protocol/webauthn_credential_specifics.proto b/components/sync/protocol/webauthn_credential_specifics.proto index a258756..1838a3d3 100644 --- a/components/sync/protocol/webauthn_credential_specifics.proto +++ b/components/sync/protocol/webauthn_credential_specifics.proto
@@ -115,6 +115,21 @@ // different key and then stored in a future encrypted_private_key field. optional bytes private_key = 9; + // Credentials may optionally be used as part of Web Payments Secure Payment + // Confirmation[1]. This is opt-in at creation time. + // + // [1] https://www.w3.org/TR/secure-payment-confirmation/ + enum PaymentsSupport { + // Indicates that this credential cannot be used to authenticate a payment. + NONE = 0; + // Indicates that the credential may authenticate a payment, but only for + // the same RP ID (i.e. same site) that created it. + FIRST_PARTY = 1; + // Indicates that the credential may authenticate a payment on any site. + FIRST_AND_THIRD_PARTY = 2; + }; + optional PaymentsSupport payments_support = 10; + // Support for CTAP 2.1 may require the addition of fields such as cred_blob // and hmac_secret_key in the future, but they are not currently supported. }
diff --git a/content/browser/back_forward_cache_features_browsertest.cc b/content/browser/back_forward_cache_features_browsertest.cc index 62aea25..388e5071 100644 --- a/content/browser/back_forward_cache_features_browsertest.cc +++ b/content/browser/back_forward_cache_features_browsertest.cc
@@ -1238,9 +1238,8 @@ blink::scheduler::WebSchedulerTrackedFeature::kWebOTPService, FROM_HERE); } -// crbug.com/1090223 IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest, - DISABLED_DoesNotCachePaymentManager) { + DoesNotCachePaymentManager) { ASSERT_TRUE(CreateHttpsServer()->Start()); // 1) Navigate to a page which includes PaymentManager functionality. Note
diff --git a/content/browser/direct_sockets/direct_sockets_open_browsertest.cc b/content/browser/direct_sockets/direct_sockets_open_browsertest.cc index 89e22ed2..2984b59e 100644 --- a/content/browser/direct_sockets/direct_sockets_open_browsertest.cc +++ b/content/browser/direct_sockets/direct_sockets_open_browsertest.cc
@@ -476,8 +476,9 @@ EXPECT_EQ(expected_result, EvalJs(shell(), script)); } +// TODO(https://crbug.com/1282060): This test is flaky. IN_PROC_BROWSER_TEST_F(DirectSocketsOpenBrowserTest, - OpenTcp_TransientActivation) { + DISABLED_OpenTcp_TransientActivation) { EXPECT_TRUE(NavigateToURL(shell(), GetTestOpenPageURL())); MockNetworkContext mock_network_context(net::OK); @@ -674,8 +675,9 @@ EXPECT_EQ("openUdp succeeded", EvalJs(shell(), script)); } +// TODO(https://crbug.com/1282060): This test is flaky. IN_PROC_BROWSER_TEST_F(DirectSocketsOpenBrowserTest, - OpenUdp_TransientActivation) { + DISABLED_OpenUdp_TransientActivation) { EXPECT_TRUE(NavigateToURL(shell(), GetTestOpenPageURL())); const std::string script = base::StringPrintf(
diff --git a/content/browser/renderer_host/media/media_stream_manager.cc b/content/browser/renderer_host/media/media_stream_manager.cc index 17628b9..72a1b24 100644 --- a/content/browser/renderer_host/media/media_stream_manager.cc +++ b/content/browser/renderer_host/media/media_stream_manager.cc
@@ -1249,18 +1249,12 @@ if (request->state(type) == MEDIA_REQUEST_STATE_DONE) CloseDevice(type, session_id); - if (request->ui_proxy) { - const DesktopMediaID media_id = DesktopMediaID::Parse(device_it->id); - if (!media_id.is_null()) - request->ui_proxy->OnDeviceStopped(request_it->first, media_id); - } - device_it = devices->erase(device_it); } // If this request doesn't have any active devices after a device // has been stopped above, remove the request. Note that the request is - // only deleted if a device as been removed from |devices|. + // only deleted if a device has been removed from |devices|. if (devices->empty()) { std::string label = request_it->first; ++request_it; @@ -1295,6 +1289,11 @@ request->device_stopped_cb) { request->device_stopped_cb.Run(labeled_request.first, device); } + if (request->ui_proxy) { + const DesktopMediaID media_id = DesktopMediaID::Parse(device.id); + if (!media_id.is_null()) + request->ui_proxy->OnDeviceStopped(labeled_request.first, media_id); + } } } } @@ -2598,6 +2597,15 @@ if (!request) return; + if (request->ui_proxy) { + for (const MediaStreamDevice& device : request->devices) { + const DesktopMediaID old_media_id = DesktopMediaID::Parse(device.id); + if (!old_media_id.is_null()) { + request->ui_proxy->OnDeviceStopped(label, old_media_id); + } + } + } + SendLogMessage(base::StringPrintf( "ChangeMediaStreamSourceFromBrowser({label=%s})", label.c_str()));
diff --git a/content/browser/renderer_host/media/media_stream_manager.h b/content/browser/renderer_host/media/media_stream_manager.h index 4524061..87de9f3 100644 --- a/content/browser/renderer_host/media/media_stream_manager.h +++ b/content/browser/renderer_host/media/media_stream_manager.h
@@ -442,11 +442,11 @@ void HandleRequestDone(const std::string& label, DeviceRequest* request); // Stop the use of the device associated with |session_id| of type |type| in // all |requests_|. The device is removed from the request. If a request - /// doesn't use any devices as a consequence, the request is deleted. + // doesn't use any devices as a consequence, the request is deleted. void StopDevice(blink::mojom::MediaStreamType type, const base::UnguessableToken& session_id); - // Calls the correct capture manager and close the device with |session_id|. - // All requests that uses the device are updated. + // Calls the correct capture manager and closes the device with |session_id|. + // All requests that use the device are updated. void CloseDevice(blink::mojom::MediaStreamType type, const base::UnguessableToken& session_id); // Returns true if a request for devices has been completed and the devices
diff --git a/content/browser/renderer_host/navigation_request.cc b/content/browser/renderer_host/navigation_request.cc index 02440a91..7efec132 100644 --- a/content/browser/renderer_host/navigation_request.cc +++ b/content/browser/renderer_host/navigation_request.cc
@@ -2083,8 +2083,7 @@ // starting SiteInstance. starting_site_instance_ = frame_tree_node->current_frame_host()->GetSiteInstance(); - site_info_ = GetSiteInfoForCommonParamsURL( - starting_site_instance_->GetWebExposedIsolationInfo()); + site_info_ = GetSiteInfoForCommonParamsURL(); // Compute the redirect chain. // TODO(clamy): Try to simplify this and have the redirects be part of @@ -2623,8 +2622,7 @@ RenderProcessHost* expected_process = site_instance->HasProcess() ? site_instance->GetProcess() : nullptr; - WillRedirectRequest(common_params_->referrer->url, - ComputeWebExposedIsolationInfo(), expected_process); + WillRedirectRequest(common_params_->referrer->url, expected_process); } base::WeakPtr<NavigationRequest> NavigationRequest::GetWeakPtr() { @@ -4745,14 +4743,12 @@ } void NavigationRequest::UpdateSiteInfo( - const WebExposedIsolationInfo& web_exposed_isolation_info, RenderProcessHost* post_redirect_process) { int post_redirect_process_id = post_redirect_process ? post_redirect_process->GetID() : ChildProcessHost::kInvalidUniqueID; - SiteInfo new_site_info = - GetSiteInfoForCommonParamsURL(web_exposed_isolation_info); + SiteInfo new_site_info = GetSiteInfoForCommonParamsURL(); if (new_site_info == site_info_ && post_redirect_process_id == expected_render_process_host_id_) { return; @@ -5481,12 +5477,11 @@ void NavigationRequest::WillRedirectRequest( const GURL& new_referrer_url, - const WebExposedIsolationInfo& web_exposed_isolation_info, RenderProcessHost* post_redirect_process) { EnterChildTraceEvent("WillRedirectRequest", this, "url", common_params_->url.possibly_invalid_spec()); UpdateStateFollowingRedirect(new_referrer_url); - UpdateSiteInfo(web_exposed_isolation_info, post_redirect_process); + UpdateSiteInfo(post_redirect_process); if (IsSelfReferentialURL()) { SetState(CANCELING); @@ -5653,13 +5648,8 @@ } } -SiteInfo NavigationRequest::GetSiteInfoForCommonParamsURL( - const WebExposedIsolationInfo& web_exposed_isolation_info) { - // We typically call this function when we don't yet have response headers, so - // the computed WebExposedIsolationInfo is not relevant. We override it with - // the value passed in. +SiteInfo NavigationRequest::GetSiteInfoForCommonParamsURL() { UrlInfo url_info = GetUrlInfo(); - url_info.web_exposed_isolation_info = web_exposed_isolation_info; // TODO(alexmos): Using |starting_site_instance_|'s IsolationContext may not // be correct for cross-BrowsingInstance redirects. @@ -7255,7 +7245,8 @@ console_messages_.clear(); } -WebExposedIsolationInfo NavigationRequest::ComputeWebExposedIsolationInfo() { +absl::optional<WebExposedIsolationInfo> +NavigationRequest::ComputeWebExposedIsolationInfo() { // If we are in an iframe, we inherit the isolation state of the top level // frame. This can be inferred from the main frame SiteInstance. Note that // Iframes have to pass COEP tests in |OnResponseStarted| before being loaded @@ -7270,6 +7261,11 @@ ->GetWebExposedIsolationInfo(); } + // If we haven't yet received a definitive network response, it is too early + // to guess the isolation state. + if (state_ < WILL_PROCESS_RESPONSE) + return absl::nullopt; + // We consider navigations to be cross-origin isolated if the response // asserts proper COOP and COEP headers. if (coop_status().current_coop().value !=
diff --git a/content/browser/renderer_host/navigation_request.h b/content/browser/renderer_host/navigation_request.h index 89db156..042fb6d 100644 --- a/content/browser/renderer_host/navigation_request.h +++ b/content/browser/renderer_host/navigation_request.h
@@ -480,10 +480,7 @@ // redirects. |post_redirect_process| is the renderer process that should // handle the navigation following the redirect if it can be handled by an // existing RenderProcessHost. Otherwise, it should be null. - // |web_exposed_isolation_info| is the new isolation info extracted from the - // redirect response. - void UpdateSiteInfo(const WebExposedIsolationInfo& web_exposed_isolation_info, - RenderProcessHost* post_redirect_process); + void UpdateSiteInfo(RenderProcessHost* post_redirect_process); int nav_entry_id() const { return nav_entry_id_; } @@ -1252,12 +1249,8 @@ // no live process that can be used. In that case, a suitable renderer process // will be created at commit time. // - // |web_exposed_isolation_info| is the new isolation info extracted from the - // redirect response. - void WillRedirectRequest( - const GURL& new_referrer_url, - const WebExposedIsolationInfo& web_exposed_isolation_info, - RenderProcessHost* post_redirect_process); + void WillRedirectRequest(const GURL& new_referrer_url, + RenderProcessHost* post_redirect_process); // Called when the URLRequest will fail. void WillFailRequest(); @@ -1286,8 +1279,7 @@ // Helper function that computes the SiteInfo for |common_params_.url|. // Note: |site_info_| should only be updated with the result of this function. - SiteInfo GetSiteInfoForCommonParamsURL( - const WebExposedIsolationInfo& cross_origin_isolated_origin_status); + SiteInfo GetSiteInfoForCommonParamsURL(); // Updates the state of the navigation handle after encountering a server // redirect. @@ -1452,7 +1444,10 @@ // Computes the web-exposed isolation information based on `coop_status_` and // current `frame_tree_node_` info. - WebExposedIsolationInfo ComputeWebExposedIsolationInfo(); + // If the return result is nullopt, it means that the WebExposedIsolationInfo + // is not relevant or unknown. This can happen for example when we do not have + // a network response yet, or when going to an "about:blank" page. + absl::optional<WebExposedIsolationInfo> ComputeWebExposedIsolationInfo(); // Never null. The pointee node owns this navigation request instance. FrameTreeNode* const frame_tree_node_;
diff --git a/content/browser/renderer_host/navigation_request_unittest.cc b/content/browser/renderer_host/navigation_request_unittest.cc index d297d43..efb3437 100644 --- a/content/browser/renderer_host/navigation_request_unittest.cc +++ b/content/browser/renderer_host/navigation_request_unittest.cc
@@ -116,8 +116,7 @@ base::Unretained(this))); GetNavigationRequest()->WillRedirectRequest( - GURL(), WebExposedIsolationInfo::CreateNonIsolated(), - nullptr /* post_redirect_process */); + GURL(), nullptr /* post_redirect_process */); } // Helper function to call WillFailRequest on |handle|. If this function
diff --git a/content/browser/renderer_host/navigator_unittest.cc b/content/browser/renderer_host/navigator_unittest.cc index 779c258..c108fb1 100644 --- a/content/browser/renderer_host/navigator_unittest.cc +++ b/content/browser/renderer_host/navigator_unittest.cc
@@ -91,8 +91,7 @@ SiteInstance* candidate_instance) { return static_cast<SiteInstanceImpl*>( rfhm->ConvertToSiteInstance( - descriptor, static_cast<SiteInstanceImpl*>(candidate_instance), - false /* is_speculative */) + descriptor, static_cast<SiteInstanceImpl*>(candidate_instance)) .get()); }
diff --git a/content/browser/renderer_host/render_frame_host_delegate.h b/content/browser/renderer_host/render_frame_host_delegate.h index 760a2dd..f0cf415de 100644 --- a/content/browser/renderer_host/render_frame_host_delegate.h +++ b/content/browser/renderer_host/render_frame_host_delegate.h
@@ -602,7 +602,8 @@ // Called when the renderer sends a response via DomAutomationController. // For example, `window.domAutomationController.send(foo())` sends the result // of foo() here. - virtual void DomOperationResponse(const std::string& json_string) {} + virtual void DomOperationResponse(RenderFrameHost* render_frame_host, + const std::string& json_string) {} virtual void OnCookiesAccessed(RenderFrameHostImpl* render_frame_host, const CookieAccessDetails& details) {}
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc index 008c1b1..8d2e57caf 100644 --- a/content/browser/renderer_host/render_frame_host_impl.cc +++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -6575,7 +6575,7 @@ } void RenderFrameHostImpl::DomOperationResponse(const std::string& json_string) { - delegate_->DomOperationResponse(json_string); + delegate_->DomOperationResponse(this, json_string); } std::unique_ptr<blink::PendingURLLoaderFactoryBundle> @@ -10115,8 +10115,9 @@ } bool RenderFrameHostImpl::IsNavigationSameSite(const UrlInfo& dest_url_info) { - if (GetSiteInstance()->GetWebExposedIsolationInfo() != - dest_url_info.web_exposed_isolation_info) { + if (!WebExposedIsolationInfo::AreCompatible( + GetSiteInstance()->GetWebExposedIsolationInfo(), + dest_url_info.web_exposed_isolation_info)) { return false; } return GetSiteInstance()->IsNavigationSameSite(
diff --git a/content/browser/renderer_host/render_frame_host_manager.cc b/content/browser/renderer_host/render_frame_host_manager.cc index dabd059..e3eaa7a 100644 --- a/content/browser/renderer_host/render_frame_host_manager.cc +++ b/content/browser/renderer_host/render_frame_host_manager.cc
@@ -175,14 +175,7 @@ bool IsSiteInstanceCompatibleWithWebExposedIsolation( SiteInstance* site_instance, - bool is_main_frame, - const UrlInfo& url_info, - bool is_speculative) { - // We do not want cross-origin-isolated have any impact on SiteInstances until - // we get an actual COOP value in a redirect or a final response. - if (is_speculative) - return true; - + const UrlInfo& url_info) { // Note: The about blank case is to accommodate web tests that use COOP. They // expect an about:blank page to stay in process, and hang otherwise. In // general, it is safe to allow about:blank pages to stay in process, since @@ -194,16 +187,9 @@ SiteInstanceImpl* site_instance_impl = static_cast<SiteInstanceImpl*>(site_instance); - if (is_main_frame) { - return site_instance_impl->GetWebExposedIsolationInfo() == - url_info.web_exposed_isolation_info; - } - // Subframes cannot swap BrowsingInstances, as a result they should either not - // load, for instance blocked by COEP, or inherit a compatible cross-origin - // isolated state. - DCHECK_EQ(site_instance_impl->IsCrossOriginIsolated(), - url_info.web_exposed_isolation_info.is_isolated()); - return true; + return WebExposedIsolationInfo::AreCompatible( + site_instance_impl->GetWebExposedIsolationInfo(), + url_info.web_exposed_isolation_info); } // Helper for appending more information to the optional |reason| parameter @@ -1519,8 +1505,7 @@ bool is_same_document, bool cross_origin_opener_policy_mismatch, bool was_server_redirect, - bool should_replace_current_entry, - bool is_speculative) { + bool should_replace_current_entry) { const GURL& destination_url = destination_url_info.url; // A subframe must stay in the same BrowsingInstance as its parent. bool is_main_frame = frame_tree_node_->IsMainFrame(); @@ -1659,8 +1644,7 @@ if (current_instance->HasSite() && !render_frame_host_->IsNavigationSameSite(destination_url_info) && !CanUseSourceSiteInstance(destination_url_info, source_instance, - was_server_redirect, is_failure, - is_speculative) && + was_server_redirect, is_failure) && !is_for_isolated_error_page && IsBrowsingInstanceSwapAllowedForPageTransition(transition, destination_url) && @@ -1835,7 +1819,6 @@ bool was_server_redirect, bool cross_origin_opener_policy_mismatch, bool should_replace_current_entry, - bool is_speculative, std::string* reason) { // On renderer-initiated navigations, when the frame initiating the navigation // and the frame being navigated differ, |source_instance| is set to the @@ -1894,7 +1877,7 @@ current_instance_impl, dest_instance, dest_url_info, dest_is_view_source_mode, transition, is_failure, is_reload, is_same_document, cross_origin_opener_policy_mismatch, - was_server_redirect, should_replace_current_entry, is_speculative); + was_server_redirect, should_replace_current_entry); TraceShouldSwapBrowsingInstanceResult(frame_tree_node_->frame_tree_node_id(), should_swap_result); @@ -1918,15 +1901,14 @@ SiteInstanceDescriptor new_instance_descriptor = DetermineSiteInstanceForURL( dest_url_info, source_instance, current_instance, dest_instance, transition, is_failure, dest_is_restore, dest_is_view_source_mode, - should_swap, was_server_redirect, is_speculative, reason); + should_swap, was_server_redirect, reason); - scoped_refptr<SiteInstance> new_instance = ConvertToSiteInstance( - new_instance_descriptor, candidate_instance, is_speculative); + scoped_refptr<SiteInstance> new_instance = + ConvertToSiteInstance(new_instance_descriptor, candidate_instance); SiteInstanceImpl* new_instance_impl = static_cast<SiteInstanceImpl*>(new_instance.get()); - DCHECK(IsSiteInstanceCompatibleWithWebExposedIsolation( - new_instance_impl, frame_tree_node_->IsMainFrame(), dest_url_info, - is_speculative)); + DCHECK(IsSiteInstanceCompatibleWithWebExposedIsolation(new_instance_impl, + dest_url_info)); // If |should_swap| is true, we must use a different SiteInstance than the // current one. If we didn't, we would have two RenderFrameHosts in the same @@ -2090,7 +2072,6 @@ bool dest_is_view_source_mode, bool force_browsing_instance_swap, bool was_server_redirect, - bool is_speculative, std::string* reason) { // Note that this function should return SiteInstance with // SiteInstanceRelation::UNRELATED relation to `current_instance` iff @@ -2109,9 +2090,8 @@ // when error pages are involved. if (IsSiteInstanceCompatibleWithErrorIsolation( dest_instance, *frame_tree_node_, is_failure)) { - if (IsSiteInstanceCompatibleWithWebExposedIsolation( - dest_instance, frame_tree_node_->IsMainFrame(), dest_url_info, - is_speculative)) { + if (IsSiteInstanceCompatibleWithWebExposedIsolation(dest_instance, + dest_url_info)) { // TODO(nasko,creis): The check whether data: or about: URLs are allowed // to commit in the current process should be in IsSuitableForUrlInfo. // However, making this change has further implications and needs more @@ -2155,9 +2135,8 @@ // If a swap is required, we need to force the SiteInstance AND // BrowsingInstance to be different ones, using CreateForURL. - bool can_use_source_instance = - CanUseSourceSiteInstance(dest_url_info, source_instance, - was_server_redirect, is_failure, is_speculative); + bool can_use_source_instance = CanUseSourceSiteInstance( + dest_url_info, source_instance, was_server_redirect, is_failure); if (force_browsing_instance_swap) { // In rare cases, `source_instance` maybe be already in another // BrowsingInstance from `current_instance` (e.g. see how the @@ -2191,7 +2170,7 @@ if (GetContentClient()->browser()->ShouldStayInParentProcessForNTP( dest_url_info.url, parent_site_instance)) { // NTP is considered non-isolated. - DCHECK(!dest_url_info.web_exposed_isolation_info.is_isolated()); + DCHECK(!dest_url_info.IsIsolated()); AppendReason(reason, "DetermineSiteInstanceForURL => parent_site_instance"); return SiteInstanceDescriptor(parent_site_instance); @@ -2213,8 +2192,7 @@ // restored or it's a Web UI as described below. // TODO(ahemery): In theory we should be able to go for an unused SiteInstance // with the same web exposed isolation status. - if (!current_instance_impl->HasSite() && - !dest_url_info.web_exposed_isolation_info.is_isolated() && + if (!current_instance_impl->HasSite() && !dest_url_info.IsIsolated() && !current_instance_impl->IsCrossOriginIsolated()) { // If we've already created a SiteInstance for our destination, we don't // want to use this unused SiteInstance; use the existing one. (We don't @@ -2286,8 +2264,7 @@ // Use the current SiteInstance for same site navigations. if (render_frame_host_->IsNavigationSameSite(dest_url_info) && IsSiteInstanceCompatibleWithWebExposedIsolation( - render_frame_host_->GetSiteInstance(), - frame_tree_node_->IsMainFrame(), dest_url_info, is_speculative)) { + render_frame_host_->GetSiteInstance(), dest_url_info)) { AppendReason(reason, "DetermineSiteInstanceForURL / same-site-navigation"); return SiteInstanceDescriptor(render_frame_host_->GetSiteInstance()); } @@ -2369,8 +2346,7 @@ // BrowsingInstance, unless the destination URL's web-exposed isolated state // cannot be hosted by it. if (IsSiteInstanceCompatibleWithWebExposedIsolation( - render_frame_host_->GetSiteInstance(), - frame_tree_node_->IsMainFrame(), dest_url_info, is_speculative)) { + render_frame_host_->GetSiteInstance(), dest_url_info)) { AppendReason(reason, "DetermineSiteInstanceForURL / fallback / coop-compatible"); return SiteInstanceDescriptor(dest_url_info, SiteInstanceRelation::RELATED); @@ -2421,18 +2397,15 @@ scoped_refptr<SiteInstance> RenderFrameHostManager::ConvertToSiteInstance( const SiteInstanceDescriptor& descriptor, - SiteInstanceImpl* candidate_instance, - bool is_speculative) { + SiteInstanceImpl* candidate_instance) { SiteInstanceImpl* current_instance = render_frame_host_->GetSiteInstance(); // If we are asked to return a related SiteInstance but the BrowsingInstance // has a different cross_origin_isolated state, something went wrong. - // This can be wrong for speculative frames, as the COOP mismatch mechanic has - // not yet been invoked. - CHECK(is_speculative || - descriptor.relation != SiteInstanceRelation::RELATED || - current_instance->IsCrossOriginIsolated() == - descriptor.dest_url_info.web_exposed_isolation_info.is_isolated()); + CHECK(descriptor.relation != SiteInstanceRelation::RELATED || + WebExposedIsolationInfo::AreCompatible( + current_instance->GetWebExposedIsolationInfo(), + descriptor.dest_url_info.web_exposed_isolation_info)); // Note: If the `candidate_instance` matches the descriptor, it will already // be set to `descriptor.existing_site_instance`. @@ -2457,8 +2430,7 @@ // check if the candidate matches. if (candidate_instance && IsSiteInstanceCompatibleWithWebExposedIsolation( - candidate_instance, frame_tree_node_->IsMainFrame(), - descriptor.dest_url_info, is_speculative) && + candidate_instance, descriptor.dest_url_info) && !current_instance->IsRelatedSiteInstance(candidate_instance) && candidate_instance->DoesSiteInfoForURLMatch(descriptor.dest_url_info)) { return candidate_instance; @@ -2473,8 +2445,7 @@ const UrlInfo& dest_url_info, SiteInstance* source_instance, bool was_server_redirect, - bool is_failure, - bool is_speculative) { + bool is_failure) { if (!source_instance) return false; @@ -2506,9 +2477,8 @@ return false; } - if (!IsSiteInstanceCompatibleWithWebExposedIsolation( - source_instance, frame_tree_node_->IsMainFrame(), dest_url_info, - is_speculative)) { + if (!IsSiteInstanceCompatibleWithWebExposedIsolation(source_instance, + dest_url_info)) { return false; } @@ -3062,10 +3032,7 @@ request->GetRestoreType() == RestoreType::kRestored, request->commit_params().is_view_source, request->WasServerRedirect(), request->coop_status().require_browsing_instance_swap(), - request->common_params().should_replace_current_entry, - request->state() < NavigationRequest::NavigationState:: - WILL_REDIRECT_REQUEST /* is_speculative */, - reason); + request->common_params().should_replace_current_entry, reason); TRACE_EVENT_INSTANT( "navigation",
diff --git a/content/browser/renderer_host/render_frame_host_manager.h b/content/browser/renderer_host/render_frame_host_manager.h index d2a65ba..f2a7e846 100644 --- a/content/browser/renderer_host/render_frame_host_manager.h +++ b/content/browser/renderer_host/render_frame_host_manager.h
@@ -658,8 +658,7 @@ bool is_same_document, bool cross_origin_opener_policy_mismatch, bool was_server_redirect, - bool should_replace_current_entry, - bool is_speculative); + bool should_replace_current_entry); ShouldSwapBrowsingInstance ShouldProactivelySwapBrowsingInstance( const UrlInfo& destination_url_info, @@ -683,7 +682,6 @@ bool was_server_redirect, bool cross_origin_opener_policy_mismatch, bool should_replace_current_entry, - bool is_speculative, std::string* reason); // Returns a descriptor of the appropriate SiteInstance object for the given @@ -699,11 +697,6 @@ // A is trying to change the src attribute of B, this will cause a navigation // where the source SiteInstance is A and B is the current SiteInstance. // - // `is_speculative` indicates that the SiteInstance is being computed for a - // speculative RenderFrameHost, which may change once response is received and - // a final RenderFrameHost/SiteInstance is computed. It is true at request - // start time, but false for redirects and at OnResponseStarted time. - // // This is a helper function for GetSiteInstanceForNavigation. SiteInstanceDescriptor DetermineSiteInstanceForURL( const UrlInfo& dest_url_info, @@ -716,7 +709,6 @@ bool dest_is_view_source_mode, bool force_browsing_instance_swap, bool was_server_redirect, - bool is_speculative, std::string* reason); // Returns true if a navigation to |dest_url| that uses the specified @@ -744,18 +736,14 @@ bool CanUseSourceSiteInstance(const UrlInfo& dest_url_info, SiteInstance* source_instance, bool was_server_redirect, - bool is_failure, - bool is_speculative); + bool is_failure); // Converts a SiteInstanceDescriptor to the actual SiteInstance it describes. // If a |candidate_instance| is provided (is not nullptr) and it matches the // description, it is returned as is. - // |is_speculative| indicates whether we are computing a SiteInstance for a - // speculative RenderFrameHost or if have already received a response. scoped_refptr<SiteInstance> ConvertToSiteInstance( const SiteInstanceDescriptor& descriptor, - SiteInstanceImpl* candidate_instance, - bool is_speculative); + SiteInstanceImpl* candidate_instance); // Returns true if `candidate` is currently same site with `dest_url_info`. // This method is a special case for handling hosted apps in this object. Most
diff --git a/content/browser/site_info.cc b/content/browser/site_info.cc index 2cd4ab8..9a113137 100644 --- a/content/browser/site_info.cc +++ b/content/browser/site_info.cc
@@ -276,7 +276,7 @@ if (url_info.url.SchemeIs(kChromeErrorScheme)) { // Error pages should never be cross origin isolated. - DCHECK(!url_info.web_exposed_isolation_info.is_isolated()); + DCHECK(!url_info.IsIsolated()); return CreateForErrorPage(storage_partition_config.value()); } // We should only set |requires_origin_keyed_process| if we are actually @@ -321,20 +321,22 @@ return Create(isolation_context, UrlInfo::CreateForTesting(url)); } -SiteInfo::SiteInfo(const GURL& site_url, - const GURL& process_lock_url, - bool requires_origin_keyed_process, - const StoragePartitionConfig storage_partition_config, - const WebExposedIsolationInfo& web_exposed_isolation_info, - bool is_guest, - bool does_site_request_dedicated_process_for_coop, - bool is_jit_disabled, - bool is_pdf) +SiteInfo::SiteInfo( + const GURL& site_url, + const GURL& process_lock_url, + bool requires_origin_keyed_process, + const StoragePartitionConfig storage_partition_config, + const absl::optional<WebExposedIsolationInfo>& web_exposed_isolation_info, + bool is_guest, + bool does_site_request_dedicated_process_for_coop, + bool is_jit_disabled, + bool is_pdf) : site_url_(site_url), process_lock_url_(process_lock_url), requires_origin_keyed_process_(requires_origin_keyed_process), storage_partition_config_(storage_partition_config), - web_exposed_isolation_info_(web_exposed_isolation_info), + web_exposed_isolation_info_(web_exposed_isolation_info.value_or( + WebExposedIsolationInfo::CreateNonIsolated())), is_guest_(is_guest), does_site_request_dedicated_process_for_coop_( does_site_request_dedicated_process_for_coop),
diff --git a/content/browser/site_info.h b/content/browser/site_info.h index 02a2ae52..00ce015 100644 --- a/content/browser/site_info.h +++ b/content/browser/site_info.h
@@ -112,15 +112,16 @@ // SiteInfos, to help ensure all creation sites are updated accordingly when // new values are added. The private function MakeTie() should be updated // accordingly. - SiteInfo(const GURL& site_url, - const GURL& process_lock_url, - bool requires_origin_keyed_process, - const StoragePartitionConfig storage_partition_config, - const WebExposedIsolationInfo& web_exposed_isolation_info, - bool is_guest, - bool does_site_request_dedicated_process_for_coop, - bool is_jit_disabled, - bool is_pdf); + SiteInfo( + const GURL& site_url, + const GURL& process_lock_url, + bool requires_origin_keyed_process, + const StoragePartitionConfig storage_partition_config, + const absl::optional<WebExposedIsolationInfo>& web_exposed_isolation_info, + bool is_guest, + bool does_site_request_dedicated_process_for_coop, + bool is_jit_disabled, + bool is_pdf); SiteInfo() = delete; SiteInfo(const SiteInfo& rhs); ~SiteInfo();
diff --git a/content/browser/site_instance_impl.cc b/content/browser/site_instance_impl.cc index d65dd30d..bf46068 100644 --- a/content/browser/site_instance_impl.cc +++ b/content/browser/site_instance_impl.cc
@@ -142,7 +142,8 @@ DCHECK(browser_context); // This will create a new SiteInstance and BrowsingInstance. scoped_refptr<BrowsingInstance> instance(new BrowsingInstance( - browser_context, url_info.web_exposed_isolation_info)); + browser_context, url_info.web_exposed_isolation_info.value_or( + WebExposedIsolationInfo::CreateNonIsolated()))); // Note: The |allow_default_instance| value used here MUST match the value // used in DoesSiteForURLMatch(). @@ -166,7 +167,8 @@ } else { // This will create a new SiteInstance and BrowsingInstance. scoped_refptr<BrowsingInstance> instance(new BrowsingInstance( - browser_context, url_info.web_exposed_isolation_info)); + browser_context, url_info.web_exposed_isolation_info.value_or( + WebExposedIsolationInfo::CreateNonIsolated()))); // We do NOT want to allow the default site instance here because workers // need to be kept separate from other sites.
diff --git a/content/browser/url_info.cc b/content/browser/url_info.cc index 7cf7749..95e560f 100644 --- a/content/browser/url_info.cc +++ b/content/browser/url_info.cc
@@ -34,6 +34,12 @@ .WithStoragePartitionConfig(storage_partition_config)); } +bool UrlInfo::IsIsolated() const { + if (!web_exposed_isolation_info) + return false; + return web_exposed_isolation_info->is_isolated(); +} + UrlInfoInit::UrlInfoInit(UrlInfoInit&) = default; UrlInfoInit::UrlInfoInit(const GURL& url) @@ -70,7 +76,7 @@ } UrlInfoInit& UrlInfoInit::WithWebExposedIsolationInfo( - const WebExposedIsolationInfo& web_exposed_isolation_info) { + absl::optional<WebExposedIsolationInfo> web_exposed_isolation_info) { web_exposed_isolation_info_ = web_exposed_isolation_info; return *this; }
diff --git a/content/browser/url_info.h b/content/browser/url_info.h index 00ef477..31500c3 100644 --- a/content/browser/url_info.h +++ b/content/browser/url_info.h
@@ -96,6 +96,10 @@ return (origin_isolation_request & OriginIsolationRequest::kCOOP); } + // Returns whether this UrlInfo is for a page that should be cross-origin + // isolated. + bool IsIsolated() const; + GURL url; // This field indicates whether the URL is requesting additional process @@ -128,7 +132,10 @@ // safely expose otherwise. "Cross-origin isolation", for example, requires // assertion of a Cross-Origin-Opener-Policy and // Cross-Origin-Embedder-Policy, and unlocks SharedArrayBuffer. - WebExposedIsolationInfo web_exposed_isolation_info; + // When we haven't yet been to the network or inherited properties that are + // sufficient to know the future isolation state - we are in a speculative + // state - this member will be empty. + absl::optional<WebExposedIsolationInfo> web_exposed_isolation_info; // Indicates that the URL directs to PDF content, which should be isolated // from other types of content. @@ -153,7 +160,7 @@ UrlInfoInit& WithStoragePartitionConfig( absl::optional<StoragePartitionConfig> storage_partition_config); UrlInfoInit& WithWebExposedIsolationInfo( - const WebExposedIsolationInfo& web_exposed_isolation_info); + absl::optional<WebExposedIsolationInfo> web_exposed_isolation_info); UrlInfoInit& WithIsPdf(bool is_pdf); private: @@ -166,7 +173,7 @@ UrlInfo::OriginIsolationRequest::kNone; url::Origin origin_; absl::optional<StoragePartitionConfig> storage_partition_config_; - WebExposedIsolationInfo web_exposed_isolation_info_; + absl::optional<WebExposedIsolationInfo> web_exposed_isolation_info_; bool is_pdf_ = false; // Any new fields should be added to the UrlInfoInit(UrlInfo) constructor.
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index 9f26fb3c..e11e653 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -6150,9 +6150,11 @@ delegate_->UnregisterProtocolHandler(source, protocol, url, user_gesture); } -void WebContentsImpl::DomOperationResponse(const std::string& json_string) { - OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::DomOperationResponse", - "json_string", json_string); +void WebContentsImpl::DomOperationResponse(RenderFrameHost* render_frame_host, + const std::string& json_string) { + OPTIONAL_TRACE_EVENT2("content", "WebContentsImpl::DomOperationResponse", + "render_frame_host", render_frame_host, "json_string", + json_string); // TODO(lukasza): The notification below should probably indicate which // RenderFrameHostImpl the message is coming from. This can enable tests to @@ -6162,6 +6164,9 @@ NotificationService::current()->Notify( NOTIFICATION_DOM_OPERATION_RESPONSE, Source<WebContents>(this), Details<const std::string>(&json_string)); + + observers_.NotifyObservers(&WebContentsObserver::DomOperationResponse, + render_frame_host, json_string); } void WebContentsImpl::SavableResourceLinksResponse(
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h index 1c40c72..8845a16 100644 --- a/content/browser/web_contents/web_contents_impl.h +++ b/content/browser/web_contents/web_contents_impl.h
@@ -778,7 +778,8 @@ const std::string& mime_type, network::mojom::RequestDestination request_destination, bool include_credentials) override; - void DomOperationResponse(const std::string& json_string) override; + void DomOperationResponse(RenderFrameHost* render_frame_host, + const std::string& json_string) override; void SavableResourceLinksResponse( RenderFrameHostImpl* source, const std::vector<GURL>& resources_list,
diff --git a/content/browser/web_exposed_isolation_info.cc b/content/browser/web_exposed_isolation_info.cc index 5cecf227..5106251 100644 --- a/content/browser/web_exposed_isolation_info.cc +++ b/content/browser/web_exposed_isolation_info.cc
@@ -6,8 +6,18 @@ #include <ostream> +#include "base/notreached.h" + namespace content { +namespace { + +constexpr char kComparisonErrorMessage[] = + "You are comparing optional WebExposedIsolationInfo objects using " + "operator==, use WebExposedIsolationInfo::AreCompatible() instead."; + +} // namespace + // static WebExposedIsolationInfo WebExposedIsolationInfo::CreateNonIsolated() { return WebExposedIsolationInfo(absl::nullopt /* origin */, @@ -24,6 +34,33 @@ return WebExposedIsolationInfo(origin, true /* isolated_application */); } +bool WebExposedIsolationInfo::AreCompatible(const WebExposedIsolationInfo& a, + const WebExposedIsolationInfo& b) { + return a == b; +} + +bool WebExposedIsolationInfo::AreCompatible( + const absl::optional<WebExposedIsolationInfo>& a, + const WebExposedIsolationInfo& b) { + if (!a.has_value()) + return true; + return AreCompatible(a.value(), b); +} + +bool WebExposedIsolationInfo::AreCompatible( + const WebExposedIsolationInfo& a, + const absl::optional<WebExposedIsolationInfo>& b) { + return AreCompatible(b, a); +} + +bool WebExposedIsolationInfo::AreCompatible( + const absl::optional<WebExposedIsolationInfo>& a, + const absl::optional<WebExposedIsolationInfo>& b) { + if (!a.has_value() || !b.has_value()) + return true; + return AreCompatible(a.value(), b.value()); +} + WebExposedIsolationInfo::WebExposedIsolationInfo( const absl::optional<url::Origin>& origin, bool isolated_application) @@ -91,4 +128,23 @@ out << "}"; return out; } + +bool operator==(const absl::optional<WebExposedIsolationInfo>& a, + const absl::optional<WebExposedIsolationInfo>& b) { + NOTREACHED() << kComparisonErrorMessage; + return false; +} + +bool operator==(const WebExposedIsolationInfo& a, + const absl::optional<WebExposedIsolationInfo>& b) { + NOTREACHED() << kComparisonErrorMessage; + return false; +} + +bool operator==(const absl::optional<WebExposedIsolationInfo>& a, + const WebExposedIsolationInfo& b) { + NOTREACHED() << kComparisonErrorMessage; + return false; +} + } // namespace content
diff --git a/content/browser/web_exposed_isolation_info.h b/content/browser/web_exposed_isolation_info.h index 703517c4..463e976 100644 --- a/content/browser/web_exposed_isolation_info.h +++ b/content/browser/web_exposed_isolation_info.h
@@ -36,6 +36,25 @@ static WebExposedIsolationInfo CreateIsolatedApplication( const url::Origin& origin); + // These helpers make it easy to compare against an optional + // WebExposedIsolationInfo. This is useful because a navigation may return + // an empty WebExposedIsolationInfo to the process model, for example when + // we do not yet have a final network response. In that case it is considered + // compatible with any WebExposedIsolationInfo. + // + // In details, the underlying logic is as follow: + // - Two valid values are compared using the == operator. + // - Null and a valid value returns true. + // - Two null values returns true. + static bool AreCompatible(const WebExposedIsolationInfo& a, + const WebExposedIsolationInfo& b); + static bool AreCompatible(const WebExposedIsolationInfo& a, + const absl::optional<WebExposedIsolationInfo>& b); + static bool AreCompatible(const absl::optional<WebExposedIsolationInfo>& a, + const WebExposedIsolationInfo& b); + static bool AreCompatible(const absl::optional<WebExposedIsolationInfo>& a, + const absl::optional<WebExposedIsolationInfo>& b); + WebExposedIsolationInfo(const WebExposedIsolationInfo& other); ~WebExposedIsolationInfo(); @@ -94,6 +113,17 @@ CONTENT_EXPORT std::ostream& operator<<(std::ostream& out, const WebExposedIsolationInfo& info); + +// Disable these operators to avoid confusion with AreCompatible() functions. +CONTENT_EXPORT bool operator==( + const absl::optional<WebExposedIsolationInfo>& a, + const absl::optional<WebExposedIsolationInfo>& b); +CONTENT_EXPORT bool operator==( + const WebExposedIsolationInfo& a, + const absl::optional<WebExposedIsolationInfo>& b); +CONTENT_EXPORT bool operator==(const absl::optional<WebExposedIsolationInfo>& a, + const WebExposedIsolationInfo& b); + } // namespace content #endif // CONTENT_BROWSER_WEB_EXPOSED_ISOLATION_INFO_H_
diff --git a/content/browser/web_exposed_isolation_info_unittest.cc b/content/browser/web_exposed_isolation_info_unittest.cc index f70ad5da..3273b04 100644 --- a/content/browser/web_exposed_isolation_info_unittest.cc +++ b/content/browser/web_exposed_isolation_info_unittest.cc
@@ -89,4 +89,76 @@ EXPECT_FALSE(appB < appA); } +TEST_F(WebExposedIsolationInfoTest, AreCompatibleFunctions) { + url::Origin originA = + url::Origin::CreateFromNormalizedTuple("https", "aaa.example", 443); + url::Origin originB = + url::Origin::CreateFromNormalizedTuple("https", "bbb.example", 443); + WebExposedIsolationInfo nonIsolated = + WebExposedIsolationInfo::CreateNonIsolated(); + WebExposedIsolationInfo isolatedA = + WebExposedIsolationInfo::CreateIsolated(originA); + WebExposedIsolationInfo isolatedB = + WebExposedIsolationInfo::CreateIsolated(originB); + WebExposedIsolationInfo appA = + WebExposedIsolationInfo::CreateIsolatedApplication(originA); + WebExposedIsolationInfo appB = + WebExposedIsolationInfo::CreateIsolatedApplication(originB); + + absl::optional<WebExposedIsolationInfo> optionalEmpty = absl::nullopt; + EXPECT_TRUE( + WebExposedIsolationInfo::AreCompatible(optionalEmpty, nonIsolated)); + EXPECT_TRUE(WebExposedIsolationInfo::AreCompatible(optionalEmpty, isolatedA)); + EXPECT_TRUE(WebExposedIsolationInfo::AreCompatible(optionalEmpty, appA)); + EXPECT_TRUE( + WebExposedIsolationInfo::AreCompatible(nonIsolated, optionalEmpty)); + EXPECT_TRUE(WebExposedIsolationInfo::AreCompatible(isolatedA, optionalEmpty)); + EXPECT_TRUE(WebExposedIsolationInfo::AreCompatible(appA, optionalEmpty)); + + absl::optional<WebExposedIsolationInfo> optionalNonIsolated = + WebExposedIsolationInfo::CreateNonIsolated(); + EXPECT_TRUE( + WebExposedIsolationInfo::AreCompatible(optionalNonIsolated, nonIsolated)); + EXPECT_FALSE( + WebExposedIsolationInfo::AreCompatible(optionalNonIsolated, isolatedA)); + EXPECT_FALSE( + WebExposedIsolationInfo::AreCompatible(optionalNonIsolated, appA)); + EXPECT_TRUE( + WebExposedIsolationInfo::AreCompatible(nonIsolated, optionalNonIsolated)); + EXPECT_FALSE( + WebExposedIsolationInfo::AreCompatible(isolatedA, optionalNonIsolated)); + EXPECT_FALSE( + WebExposedIsolationInfo::AreCompatible(appA, optionalNonIsolated)); + + absl::optional<WebExposedIsolationInfo> optionalIsolatedA = + WebExposedIsolationInfo::CreateIsolated(originA); + EXPECT_FALSE( + WebExposedIsolationInfo::AreCompatible(optionalIsolatedA, nonIsolated)); + EXPECT_TRUE( + WebExposedIsolationInfo::AreCompatible(optionalIsolatedA, isolatedA)); + EXPECT_FALSE( + WebExposedIsolationInfo::AreCompatible(optionalIsolatedA, isolatedB)); + EXPECT_FALSE(WebExposedIsolationInfo::AreCompatible(optionalIsolatedA, appA)); + EXPECT_FALSE( + WebExposedIsolationInfo::AreCompatible(nonIsolated, optionalIsolatedA)); + EXPECT_TRUE( + WebExposedIsolationInfo::AreCompatible(isolatedA, optionalIsolatedA)); + EXPECT_FALSE( + WebExposedIsolationInfo::AreCompatible(isolatedB, optionalIsolatedA)); + EXPECT_FALSE(WebExposedIsolationInfo::AreCompatible(appA, optionalIsolatedA)); + + absl::optional<WebExposedIsolationInfo> optionalAppA = + WebExposedIsolationInfo::CreateIsolatedApplication(originA); + EXPECT_FALSE( + WebExposedIsolationInfo::AreCompatible(optionalAppA, nonIsolated)); + EXPECT_FALSE(WebExposedIsolationInfo::AreCompatible(optionalAppA, isolatedA)); + EXPECT_TRUE(WebExposedIsolationInfo::AreCompatible(optionalAppA, appA)); + EXPECT_FALSE(WebExposedIsolationInfo::AreCompatible(optionalAppA, appB)); + EXPECT_FALSE( + WebExposedIsolationInfo::AreCompatible(nonIsolated, optionalAppA)); + EXPECT_FALSE(WebExposedIsolationInfo::AreCompatible(isolatedA, optionalAppA)); + EXPECT_TRUE(WebExposedIsolationInfo::AreCompatible(appA, optionalAppA)); + EXPECT_FALSE(WebExposedIsolationInfo::AreCompatible(appB, optionalAppA)); +} + } // namespace content
diff --git a/content/public/android/java/src/org/chromium/content/browser/accessibility/AccessibilityActionAndEventTracker.java b/content/public/android/java/src/org/chromium/content/browser/accessibility/AccessibilityActionAndEventTracker.java index fdc11b6..f87f596 100644 --- a/content/public/android/java/src/org/chromium/content/browser/accessibility/AccessibilityActionAndEventTracker.java +++ b/content/public/android/java/src/org/chromium/content/browser/accessibility/AccessibilityActionAndEventTracker.java
@@ -23,17 +23,23 @@ } public void addEvent(AccessibilityEvent event) { - mEvents.add(eventToString(event)); + // In rare cases there may be a lingering event, so only add if the test is not complete. + if (!mTestComplete) { + mEvents.add(eventToString(event)); + } } public void addAction(int action, Bundle arguments) { - mEvents.add(actionToString(action, arguments)); + // In rare cases there may be a lingering action, so only add if the test is not complete. + if (!mTestComplete) { + mEvents.add(actionToString(action, arguments)); + } } public String results() { StringBuilder results = new StringBuilder(); - for (String event : mEvents) { + for (String event : new LinkedList<String>(mEvents)) { if (event != null && !event.isEmpty()) { results.append(event); results.append('\n');
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityEventsTest.java b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityEventsTest.java index 46b962e..b3596f01 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityEventsTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityEventsTest.java
@@ -19,7 +19,6 @@ import org.junit.runner.RunWith; import org.chromium.base.test.util.Batch; -import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.FlakyTest; import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.content_public.browser.test.ContentJUnit4ClassRunner; @@ -32,7 +31,6 @@ @TargetApi(Build.VERSION_CODES.LOLLIPOP) @SuppressLint("VisibleForTests") @Batch(Batch.UNIT_TESTS) -@DisabledTest(message = "https://crbug.com/1261677") public class WebContentsAccessibilityEventsTest { // File path that holds all the relevant tests. private static final String BASE_FILE_PATH = "content/test/data/accessibility/event/";
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTreeTest.java b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTreeTest.java index 73c6766d..a08c5d7 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTreeTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTreeTest.java
@@ -207,6 +207,7 @@ @Test @SmallTest + @DisabledTest(message = "https://crbug.com/1279785") public void test_ariaButton() { performAriaTest("aria-button.html"); } @@ -219,12 +220,14 @@ @Test @SmallTest + @DisabledTest(message = "https://crbug.com/1279785") public void test_ariaCheckbox() { performAriaTest("aria-checkbox.html"); } @Test @SmallTest + @DisabledTest(message = "https://crbug.com/1279785") public void test_ariaChecked() { performAriaTest("aria-checked.html"); } @@ -261,6 +264,7 @@ @Test @SmallTest + @DisabledTest(message = "https://crbug.com/1279785") public void test_ariaCombobox() { performAriaTest("aria-combobox.html"); } @@ -273,6 +277,7 @@ @Test @SmallTest + @DisabledTest(message = "https://crbug.com/1279785") public void test_ariaComboboxUneditable() { performAriaTest("aria-combobox-uneditable.html"); } @@ -297,6 +302,7 @@ @Test @SmallTest + @DisabledTest(message = "https://crbug.com/1279785") public void test_ariaCurrent() { performAriaTest("aria-current.html"); } @@ -405,6 +411,7 @@ @Test @SmallTest + @DisabledTest(message = "https://crbug.com/1279785") public void test_ariaGridcell() { performAriaTest("aria-gridcell.html"); } @@ -459,6 +466,7 @@ @Test @SmallTest + @DisabledTest(message = "https://crbug.com/1279785") public void test_ariaIllegalVal() { performAriaTest("aria-illegal-val.html"); } @@ -507,18 +515,21 @@ @Test @SmallTest + @DisabledTest(message = "https://crbug.com/1279785") public void test_ariaListboxAriaSelected() { performAriaTest("aria-listbox-aria-selected.html"); } @Test @SmallTest + @DisabledTest(message = "https://crbug.com/1279785") public void test_ariaListboxDisabled() { performAriaTest("aria-listbox-disabled.html"); } @Test @SmallTest + @DisabledTest(message = "https://crbug.com/1279785") public void test_ariaListbox() { performAriaTest("aria-listbox.html"); } @@ -585,6 +596,7 @@ @Test @SmallTest + @DisabledTest(message = "https://crbug.com/1279785") public void test_ariaMenuitemcheckbox() { performAriaTest("aria-menuitemcheckbox.html"); } @@ -603,6 +615,7 @@ @Test @SmallTest + @DisabledTest(message = "https://crbug.com/1279785") public void test_ariaMenuitemradio() { performAriaTest("aria-menuitemradio.html"); } @@ -627,6 +640,7 @@ @Test @SmallTest + @DisabledTest(message = "https://crbug.com/1279785") public void test_ariaMultiselectable() { performAriaTest("aria-multiselectable.html"); } @@ -651,12 +665,14 @@ @Test @SmallTest + @DisabledTest(message = "https://crbug.com/1279785") public void test_ariaOptionComplexChildren() { performAriaTest("aria-option-complex-children.html"); } @Test @SmallTest + @DisabledTest(message = "https://crbug.com/1279785") public void test_ariaOption() { performAriaTest("aria-option.html"); } @@ -705,6 +721,7 @@ @Test @SmallTest + @DisabledTest(message = "https://crbug.com/1279785") public void test_ariaPressed() { performAriaTest("aria-pressed.html"); } @@ -795,6 +812,7 @@ @Test @SmallTest + @DisabledTest(message = "https://crbug.com/1279785") public void test_ariaSelected() { performAriaTest("aria-selected.html"); } @@ -807,6 +825,7 @@ @Test @SmallTest + @DisabledTest(message = "https://crbug.com/1279785") public void test_ariaSetsize() { performAriaTest("aria-setsize.html"); } @@ -933,6 +952,7 @@ @Test @SmallTest + @DisabledTest(message = "https://crbug.com/1279785") public void test_ariaTogglebutton() { performAriaTest("aria-togglebutton.html"); } @@ -963,6 +983,7 @@ @Test @SmallTest + @DisabledTest(message = "https://crbug.com/1279785") public void test_ariaTree() { performAriaTest("aria-tree.html"); } @@ -1035,6 +1056,7 @@ @Test @SmallTest + @DisabledTest(message = "https://crbug.com/1279785") public void test_toggleButtonExpandCollapse() { performAriaTest("toggle-button-expand-collapse.html"); }
diff --git a/content/public/browser/media_stream_request.h b/content/public/browser/media_stream_request.h index e4fd1d5..977faa5 100644 --- a/content/public/browser/media_stream_request.h +++ b/content/public/browser/media_stream_request.h
@@ -100,7 +100,7 @@ const DesktopMediaID& media_id, blink::mojom::MediaStreamStateChange new_state)>; - virtual ~MediaStreamUI() {} + virtual ~MediaStreamUI() = default; // Called when MediaStream capturing is started. Chrome layer can call |stop| // to stop the stream, or |source| to change the source of the stream, or
diff --git a/content/public/browser/notification_types.h b/content/public/browser/notification_types.h index a666e09b..792b67d 100644 --- a/content/public/browser/notification_types.h +++ b/content/public/browser/notification_types.h
@@ -103,6 +103,7 @@ // Notification from WebContents that we have received a response from the // renderer in response to a dom automation controller action. The source is // the RenderViewHost, and the details is a string with the response. + // DEPRECATED: Use WebContentsObserver::DomOperationResponse() // TODO(https://crbug.com/1174774): Remove. NOTIFICATION_DOM_OPERATION_RESPONSE,
diff --git a/content/public/browser/web_contents_observer.h b/content/public/browser/web_contents_observer.h index 5df6466..66e8be1e 100644 --- a/content/public/browser/web_contents_observer.h +++ b/content/public/browser/web_contents_observer.h
@@ -384,6 +384,15 @@ virtual void DocumentOnLoadCompletedInMainFrame( RenderFrameHost* render_frame_host) {} + // This method is invoked when we have received a response from the + // renderer in response to a dom automation controller action. + // For example, `window.domAutomationController.send(foo())` sends the + // result of foo() here. + // |json_string| is a string with the response which came from a specific + // |render_frame_host|. + virtual void DomOperationResponse(RenderFrameHost* render_frame_host, + const std::string& json_string) {} + // This method is invoked when the document in the given frame finished // loading. At this point, scripts marked as defer were executed, and // content scripts marked "document_end" get injected into the frame.
diff --git a/content/public/test/javascript_test_observer.cc b/content/public/test/javascript_test_observer.cc index 6675962e..2d4af73 100644 --- a/content/public/test/javascript_test_observer.cc +++ b/content/public/test/javascript_test_observer.cc
@@ -5,7 +5,6 @@ #include "content/public/test/javascript_test_observer.h" #include "base/run_loop.h" -#include "content/public/browser/notification_types.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/web_contents.h" #include "content/public/test/test_utils.h" @@ -28,15 +27,13 @@ error_message_.clear(); } -JavascriptTestObserver::JavascriptTestObserver( - WebContents* web_contents, TestMessageHandler* handler) - : handler_(handler), +JavascriptTestObserver::JavascriptTestObserver(WebContents* web_contents, + TestMessageHandler* handler) + : WebContentsObserver(web_contents), + handler_(handler), running_(false), finished_(false) { Reset(); - registrar_.Add(this, - NOTIFICATION_DOM_OPERATION_RESPONSE, - Source<WebContents>(web_contents)); } JavascriptTestObserver::~JavascriptTestObserver() { @@ -60,16 +57,13 @@ handler_->Reset(); } -void JavascriptTestObserver::Observe( - int type, - const NotificationSource& source, - const NotificationDetails& details) { - CHECK(type == NOTIFICATION_DOM_OPERATION_RESPONSE); - Details<std::string> dom_op_result(details); +void JavascriptTestObserver::DomOperationResponse( + RenderFrameHost* render_frame_host, + const std::string& json_string) { // We might receive responses for other script execution, but we only // care about the test finished message. TestMessageHandler::MessageResponse response = - handler_->HandleMessage(*dom_op_result.ptr()); + handler_->HandleMessage(json_string); if (response == TestMessageHandler::DONE) { EndTest();
diff --git a/content/public/test/javascript_test_observer.h b/content/public/test/javascript_test_observer.h index 27d066b..3c3bb79 100644 --- a/content/public/test/javascript_test_observer.h +++ b/content/public/test/javascript_test_observer.h
@@ -8,11 +8,9 @@ #include <string> #include "base/memory/raw_ptr.h" -#include "content/public/browser/notification_observer.h" -#include "content/public/browser/notification_registrar.h" +#include "content/public/browser/web_contents_observer.h" namespace content { -class WebContents; // Base class for handling a stream of automation messages produced by a // JavascriptTestObserver. @@ -51,7 +49,7 @@ // This class captures a stream of automation messages coming from a Javascript // test and dispatches them to a message handler. -class JavascriptTestObserver : public NotificationObserver { +class JavascriptTestObserver : public WebContentsObserver { public: // The observer does not own any arguments passed to it. It is assumed that // the arguments will outlive all uses of the observer. @@ -72,9 +70,8 @@ // while Run() is pumping the message loop. void Reset(); - void Observe(int type, - const NotificationSource& source, - const NotificationDetails& details) override; + void DomOperationResponse(RenderFrameHost* render_frame_host, + const std::string& json_string) override; private: // This message did not signal the end of a test, keep going. @@ -86,7 +83,6 @@ raw_ptr<TestMessageHandler> handler_; bool running_; bool finished_; - NotificationRegistrar registrar_; }; } // namespace content
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index e5942512..2293ffc 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc
@@ -738,7 +738,8 @@ BindHostReceiver(compositing_mode_reporter_.BindNewPipeAndPassReceiver()); compositing_mode_reporter_->AddCompositingModeWatcher( - compositing_mode_watcher_receiver_.BindNewPipeAndPassRemote()); + compositing_mode_watcher_receiver_.BindNewPipeAndPassRemote( + main_thread_scheduler_->CompositorTaskRunner())); } variations_observer_ = std::make_unique<VariationsRenderThreadObserver>();
diff --git a/fuchsia/engine/browser/frame_impl_unittest.cc b/fuchsia/engine/browser/frame_impl_unittest.cc index 111993f..cfc059e 100644 --- a/fuchsia/engine/browser/frame_impl_unittest.cc +++ b/fuchsia/engine/browser/frame_impl_unittest.cc
@@ -4,6 +4,7 @@ #include "fuchsia/engine/browser/frame_impl.h" #include "base/strings/string_piece.h" +#include "base/test/gtest_util.h" #include "testing/gtest/include/gtest/gtest.h" using NavigationState = fuchsia::web::NavigationState; @@ -97,3 +98,27 @@ EXPECT_FALSE(difference.IsEmpty()); EXPECT_TRUE(difference.is_main_document_loaded()); } + +// Verifies that transitions from empty to non-empty states are handled. +TEST(FrameImplUnitTest, DiffNavigationEntriesFromInitial) { + fuchsia::web::NavigationState difference; + NavigationState state1; + NavigationState state2 = CreateNavigationState( + GURL(kUrl1), kTitle1, fuchsia::web::PageType::NORMAL, true, true, false); + + DiffNavigationEntries(state1, state2, &difference); + EXPECT_FALSE(difference.IsEmpty()); + + // Transitions from non-empty to empty (initial) state are DCHECK'd. + EXPECT_DCHECK_DEATH({ DiffNavigationEntries(state2, state1, &difference); }); +} + +// Verifies that differencing between two empty/initial states are handled. +TEST(FrameImplUnitTest, DiffNavigationEntriesBothInitial) { + fuchsia::web::NavigationState difference; + NavigationState state1; + NavigationState state2; + + DiffNavigationEntries(state1, state2, &difference); + EXPECT_TRUE(difference.IsEmpty()); +}
diff --git a/fuchsia/engine/browser/navigation_controller_impl.cc b/fuchsia/engine/browser/navigation_controller_impl.cc index c48438e..9277bd7 100644 --- a/fuchsia/engine/browser/navigation_controller_impl.cc +++ b/fuchsia/engine/browser/navigation_controller_impl.cc
@@ -141,6 +141,8 @@ NavigationControllerImpl::GetVisibleNavigationState() const { content::NavigationEntry* const entry = web_contents_->GetController().GetVisibleEntry(); + CHECK(entry); + if (entry->IsInitialEntry()) return fuchsia::web::NavigationState(); @@ -374,6 +376,13 @@ fuchsia::web::NavigationState* difference) { DCHECK(difference); + // |new_entry| should not be empty when the difference is between states + // pre- and post-navigation. It is possible for non-navigation events (e.g. + // Renderer-process teardown) to trigger notifications, in which case both + // states may be empty (i.e. both come from the "initial" NavigationEntry). + if (new_entry.IsEmpty() && old_entry.IsEmpty()) + return; + DCHECK(new_entry.has_title()); if (!old_entry.has_title() || (new_entry.title() != old_entry.title())) { difference->set_title(new_entry.title());
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd index a39b165..81cf752 100644 --- a/ios/chrome/app/strings/ios_strings.grd +++ b/ios/chrome/app/strings/ios_strings.grd
@@ -2833,6 +2833,12 @@ <message name="IDS_IOS_TOOLS_MENU_ENTERPRISE_LEARN_MORE" desc="Link displayed to allow the user to learn more why the browser is managed by Enterprise policies. Shown at the bottom of the overflow menu. [iOS only]"> Learn More </message> + <message name="IDS_IOS_TOOLS_MENU_FOLLOW" desc="The iOS menu item for following web content. [iOS only]"> + Follow + </message> + <message name="IDS_IOS_TOOLS_MENU_UNFOLLOW" desc="The iOS menu item for unfollowing web content. [iOS only]"> + Unfollow + </message> <message name="IDS_IOS_TOOLS_MENU_TRANSLATE" desc="The iOS menu item for translating the current page [iOS only]" meaning="Open the translate infobar [Length: unlimited]"> Translate </message>
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_TOOLS_MENU_FOLLOW.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_TOOLS_MENU_FOLLOW.png.sha1 new file mode 100644 index 0000000..be0a067 --- /dev/null +++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_TOOLS_MENU_FOLLOW.png.sha1
@@ -0,0 +1 @@ +8f864cc2cb1c57c73cc8d199dd6a0cb029089659 \ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_TOOLS_MENU_UNFOLLOW.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_TOOLS_MENU_UNFOLLOW.png.sha1 new file mode 100644 index 0000000..736b7772 --- /dev/null +++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_TOOLS_MENU_UNFOLLOW.png.sha1
@@ -0,0 +1 @@ +b03fdc858cbcc78b14f2f379acd34d2cd9013e6e \ No newline at end of file
diff --git a/ios/chrome/browser/ui/first_run/first_run_egtest.mm b/ios/chrome/browser/ui/first_run/first_run_egtest.mm index 4c64432d..064b3fbb 100644 --- a/ios/chrome/browser/ui/first_run/first_run_egtest.mm +++ b/ios/chrome/browser/ui/first_run/first_run_egtest.mm
@@ -529,7 +529,8 @@ // Tests that the forced sign-in screen is shown when the policy is enabled. // If the user says no during the FRE, then they should be re-prompted at the // end of the FRE. -- (void)testSignInScreenUIWhenForcedByPolicy { +// TODO(crbug.com/1282047): Re-enable when fixed. +- (void)DISABLED_testSignInScreenUIWhenForcedByPolicy { AppLaunchConfiguration config = self.appConfigurationForTestCase; // Configure the policy to force sign-in. @@ -813,7 +814,8 @@ // Checks that the user is signed in and that sync is turned on after the user // chooses to turn on sync. -- (void)testSignInAndTurnOnSync { +// TODO(crbug.com/1282047): Re-enable when fixed. +- (void)DISABLED_testSignInAndTurnOnSync { FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1]; [SigninEarlGrey addFakeIdentity:fakeIdentity];
diff --git a/ios/chrome/browser/ui/follow/follow_action_state.h b/ios/chrome/browser/ui/follow/follow_action_state.h index dcc45ddf..ab5091b 100644 --- a/ios/chrome/browser/ui/follow/follow_action_state.h +++ b/ios/chrome/browser/ui/follow/follow_action_state.h
@@ -15,7 +15,7 @@ // "Follow" action is shown but disabled. FollowActionStateDisabled, // "Follow" action is shown and enabled. - FollowActionStateEnabld, + FollowActionStateEnabled, }; #endif // IOS_CHROME_BROWSER_UI_FOLLOW_FOLLOW_ACTION_STATE_H_
diff --git a/ios/chrome/browser/ui/follow/follow_util.mm b/ios/chrome/browser/ui/follow/follow_util.mm index e362b41..783db52 100644 --- a/ios/chrome/browser/ui/follow/follow_util.mm +++ b/ios/chrome/browser/ui/follow/follow_util.mm
@@ -37,7 +37,7 @@ if (!browserState->IsOffTheRecord() && authenticationService->GetPrimaryIdentity( signin::ConsentLevel::kSignin)) { - return FollowActionStateEnabld; + return FollowActionStateEnabled; } return FollowActionStateDisabled; }
diff --git a/ios/chrome/browser/ui/popup_menu/BUILD.gn b/ios/chrome/browser/ui/popup_menu/BUILD.gn index eca4022..a1850d7 100644 --- a/ios/chrome/browser/ui/popup_menu/BUILD.gn +++ b/ios/chrome/browser/ui/popup_menu/BUILD.gn
@@ -78,7 +78,10 @@ "//ios/chrome/browser/ui/commands", "//ios/chrome/browser/ui/coordinators:chrome_coordinators", "//ios/chrome/browser/ui/default_promo:utils", + "//ios/chrome/browser/ui/follow:enums", + "//ios/chrome/browser/ui/follow:utils", "//ios/chrome/browser/ui/list_model", + "//ios/chrome/browser/ui/ntp:feature_flags", "//ios/chrome/browser/ui/ntp_tile_views:constants", "//ios/chrome/browser/ui/popup_menu/cells", "//ios/chrome/browser/ui/popup_menu/overflow_menu",
diff --git a/ios/chrome/browser/ui/popup_menu/overflow_menu/BUILD.gn b/ios/chrome/browser/ui/popup_menu/overflow_menu/BUILD.gn index 14ec91af..29cf02cf 100644 --- a/ios/chrome/browser/ui/popup_menu/overflow_menu/BUILD.gn +++ b/ios/chrome/browser/ui/popup_menu/overflow_menu/BUILD.gn
@@ -16,6 +16,7 @@ "resources:overflow_menu_action_bookmark", "resources:overflow_menu_action_edit_bookmark", "resources:overflow_menu_action_find_in_page", + "resources:overflow_menu_action_follow", "resources:overflow_menu_action_help", "resources:overflow_menu_action_incognito", "resources:overflow_menu_action_new_tab", @@ -58,6 +59,7 @@ "//ios/chrome/browser/ui/browser_container:ui", "//ios/chrome/browser/ui/commands", "//ios/chrome/browser/ui/default_promo:utils", + "//ios/chrome/browser/ui/follow:enums", "//ios/chrome/browser/ui/util", "//ios/chrome/browser/web", "//ios/chrome/browser/web/font_size",
diff --git a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator.h b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator.h index 1f553b6d..e869459 100644 --- a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator.h +++ b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator.h
@@ -8,10 +8,12 @@ #import <UIKit/UIKit.h> #import "ios/chrome/browser/ui/browser_container/browser_container_consumer.h" +#import "ios/chrome/browser/ui/follow/follow_action_state.h" namespace bookmarks { class BookmarkModel; } + @protocol ApplicationCommands; @protocol BrowserCommands; class BrowserPolicyConnectorIOS; @@ -64,6 +66,9 @@ // The current browser policy connector. @property(nonatomic, assign) BrowserPolicyConnectorIOS* browserPolicyConnector; +// The follow action state. e.g. If the property value is FollowActionStateHide, +// "Follow" action should be hidden in the overflow menu. +@property(nonatomic, assign) FollowActionState followActionState; @end #endif // IOS_CHROME_BROWSER_UI_POPUP_MENU_OVERFLOW_MENU_OVERFLOW_MENU_MEDIATOR_H_
diff --git a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator.mm b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator.mm index 061fee0..2ce40695f 100644 --- a/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator.mm +++ b/ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator.mm
@@ -155,6 +155,7 @@ @property(nonatomic, strong) OverflowMenuAction* addBookmarkAction; @property(nonatomic, strong) OverflowMenuAction* editBookmarkAction; +@property(nonatomic, strong) OverflowMenuAction* followAction; @property(nonatomic, strong) OverflowMenuAction* readLaterAction; @property(nonatomic, strong) OverflowMenuAction* translateAction; @property(nonatomic, strong) OverflowMenuAction* requestDesktopAction; @@ -378,6 +379,15 @@ actions:@[] footer:nil]; + if (self.followActionState != FollowActionStateHidden) { + // TODO(crbug.com/1264872): Show follow/unfollow according to website follow + // status. + self.followAction = CreateOverflowMenuAction( + IDS_IOS_TOOLS_MENU_FOLLOW, @"overflow_menu_action_follow", ^{ + [weakSelf updateFollowStatus:YES]; + }); + } + self.addBookmarkAction = CreateOverflowMenuAction( IDS_IOS_TOOLS_MENU_ADD_TO_BOOKMARKS, @"overflow_menu_action_bookmark", ^{ [weakSelf addOrEditBookmark]; @@ -519,6 +529,12 @@ self.findInPageAction, self.textZoomAction ]; + // Add the follow action to the page action group if it is exists. + if (self.followAction) { + self.pageActionsGroup.actions = [@[ self.followAction ] + arrayByAddingObjectsFromArray:self.pageActionsGroup.actions]; + } + // Set footer (on last section), if any. if (_browserPolicyConnector && _browserPolicyConnector->HasMachineLevelPolicies()) { @@ -538,7 +554,10 @@ // which is paused while overlays are displayed over the web content area. self.readLaterAction.enabled = !self.webContentAreaShowingOverlay && [self isCurrentURLWebURL]; - + if (self.followAction) { + self.followAction.enabled = + self.followActionState == FollowActionStateEnabled ? YES : NO; + } BOOL bookmarkEnabled = [self isCurrentURLWebURL] && [self isEditBookmarksEnabled]; self.addBookmarkAction.enabled = bookmarkEnabled; @@ -837,6 +856,12 @@ GURL(kChromeUINewTabURL))]; } +// Dismisses the menu and and updates the follow status of the website. +- (void)updateFollowStatus:(BOOL)newStatus { + [self.dispatcher dismissPopupMenuAnimated:YES]; + // TODO(crbug.com/1264872): implement. +} + // Dismisses the menu and adds the current page as a bookmark or opens the // bookmark edit screen if the current page is bookmarked. - (void)addOrEditBookmark {
diff --git a/ios/chrome/browser/ui/popup_menu/overflow_menu/resources/BUILD.gn b/ios/chrome/browser/ui/popup_menu/overflow_menu/resources/BUILD.gn index 80dadaad..0cfae2a04 100644 --- a/ios/chrome/browser/ui/popup_menu/overflow_menu/resources/BUILD.gn +++ b/ios/chrome/browser/ui/popup_menu/overflow_menu/resources/BUILD.gn
@@ -28,6 +28,14 @@ ] } +imageset("overflow_menu_action_follow") { + sources = [ + "overflow_menu_action_follow.imageset/Contents.json", + "overflow_menu_action_follow.imageset/overflow_menu_action_follow@2x.png", + "overflow_menu_action_follow.imageset/overflow_menu_action_follow@3x.png", + ] +} + imageset("overflow_menu_action_help") { sources = [ "overflow_menu_action_help.imageset/Contents.json", @@ -124,6 +132,14 @@ ] } +imageset("overflow_menu_action_unfollow") { + sources = [ + "overflow_menu_action_unfollow.imageset/Contents.json", + "overflow_menu_action_unfollow.imageset/overflow_menu_action_unfollow@2x.png", + "overflow_menu_action_unfollow.imageset/overflow_menu_action_unfollow@3x.png", + ] +} + imageset("overflow_menu_destination_bookmarks") { sources = [ "overflow_menu_destination_bookmarks.imageset/Contents.json",
diff --git a/ios/chrome/browser/ui/popup_menu/overflow_menu/resources/overflow_menu_action_follow.imageset/Contents.json b/ios/chrome/browser/ui/popup_menu/overflow_menu/resources/overflow_menu_action_follow.imageset/Contents.json new file mode 100644 index 0000000..dd3658aa --- /dev/null +++ b/ios/chrome/browser/ui/popup_menu/overflow_menu/resources/overflow_menu_action_follow.imageset/Contents.json
@@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "overflow_menu_action_follow@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "overflow_menu_action_follow@3x.png", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties": { + "template-rendering-intent": "template" + } +}
diff --git a/ios/chrome/browser/ui/popup_menu/overflow_menu/resources/overflow_menu_action_follow.imageset/overflow_menu_action_follow@2x.png b/ios/chrome/browser/ui/popup_menu/overflow_menu/resources/overflow_menu_action_follow.imageset/overflow_menu_action_follow@2x.png new file mode 100644 index 0000000..1d817e4 --- /dev/null +++ b/ios/chrome/browser/ui/popup_menu/overflow_menu/resources/overflow_menu_action_follow.imageset/overflow_menu_action_follow@2x.png Binary files differ
diff --git a/ios/chrome/browser/ui/popup_menu/overflow_menu/resources/overflow_menu_action_follow.imageset/overflow_menu_action_follow@3x.png b/ios/chrome/browser/ui/popup_menu/overflow_menu/resources/overflow_menu_action_follow.imageset/overflow_menu_action_follow@3x.png new file mode 100644 index 0000000..0c7b3d7 --- /dev/null +++ b/ios/chrome/browser/ui/popup_menu/overflow_menu/resources/overflow_menu_action_follow.imageset/overflow_menu_action_follow@3x.png Binary files differ
diff --git a/ios/chrome/browser/ui/popup_menu/overflow_menu/resources/overflow_menu_action_unfollow.imageset/Contents.json b/ios/chrome/browser/ui/popup_menu/overflow_menu/resources/overflow_menu_action_unfollow.imageset/Contents.json new file mode 100644 index 0000000..102574a --- /dev/null +++ b/ios/chrome/browser/ui/popup_menu/overflow_menu/resources/overflow_menu_action_unfollow.imageset/Contents.json
@@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "overflow_menu_action_unfollow@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "overflow_menu_action_unfollow@3x.png", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties": { + "template-rendering-intent": "template" + } +}
diff --git a/ios/chrome/browser/ui/popup_menu/overflow_menu/resources/overflow_menu_action_unfollow.imageset/overflow_menu_action_unfollow@2x.png b/ios/chrome/browser/ui/popup_menu/overflow_menu/resources/overflow_menu_action_unfollow.imageset/overflow_menu_action_unfollow@2x.png new file mode 100644 index 0000000..a9790d97 --- /dev/null +++ b/ios/chrome/browser/ui/popup_menu/overflow_menu/resources/overflow_menu_action_unfollow.imageset/overflow_menu_action_unfollow@2x.png Binary files differ
diff --git a/ios/chrome/browser/ui/popup_menu/overflow_menu/resources/overflow_menu_action_unfollow.imageset/overflow_menu_action_unfollow@3x.png b/ios/chrome/browser/ui/popup_menu/overflow_menu/resources/overflow_menu_action_unfollow.imageset/overflow_menu_action_unfollow@3x.png new file mode 100644 index 0000000..ab4acb6 --- /dev/null +++ b/ios/chrome/browser/ui/popup_menu/overflow_menu/resources/overflow_menu_action_unfollow.imageset/overflow_menu_action_unfollow@3x.png Binary files differ
diff --git a/ios/chrome/browser/ui/popup_menu/popup_menu_coordinator.mm b/ios/chrome/browser/ui/popup_menu/popup_menu_coordinator.mm index 1765292..098df92f 100644 --- a/ios/chrome/browser/ui/popup_menu/popup_menu_coordinator.mm +++ b/ios/chrome/browser/ui/popup_menu/popup_menu_coordinator.mm
@@ -23,6 +23,9 @@ #import "ios/chrome/browser/ui/commands/command_dispatcher.h" #import "ios/chrome/browser/ui/commands/find_in_page_commands.h" #import "ios/chrome/browser/ui/commands/popup_menu_commands.h" +#import "ios/chrome/browser/ui/follow/follow_action_state.h" +#import "ios/chrome/browser/ui/follow/follow_util.h" +#import "ios/chrome/browser/ui/ntp/new_tab_page_feature.h" #import "ios/chrome/browser/ui/popup_menu/overflow_menu/feature_flags.h" #import "ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_mediator.h" #import "ios/chrome/browser/ui/popup_menu/overflow_menu/overflow_menu_swift.h" @@ -37,6 +40,7 @@ #import "ios/chrome/browser/ui/util/uikit_ui_util.h" #import "ios/chrome/browser/url_loading/url_loading_browser_agent.h" #import "ios/chrome/browser/web/web_navigation_browser_agent.h" +#import "ios/chrome/browser/web_state_list/web_state_list.h" #import "ios/chrome/common/ui/colors/semantic_color_names.h" #if !defined(__has_feature) || !__has_feature(objc_arc) @@ -320,6 +324,12 @@ overlayPresenter; self.overflowMenuMediator.browserPolicyConnector = GetApplicationContext()->GetBrowserPolicyConnector(); + self.overflowMenuMediator.followActionState = + IsWebChannelsEnabled() + ? GetFollowActionState( + self.browser->GetWebStateList()->GetActiveWebState(), + self.browser->GetBrowserState()) + : FollowActionStateHidden; // Replace the content blocker's consumer with the overflow menu mediator. self.contentBlockerMediator.consumer = self.overflowMenuMediator;
diff --git a/ios/chrome/browser/ui/settings/content_settings/BUILD.gn b/ios/chrome/browser/ui/settings/content_settings/BUILD.gn index f330360..06f2b87 100644 --- a/ios/chrome/browser/ui/settings/content_settings/BUILD.gn +++ b/ios/chrome/browser/ui/settings/content_settings/BUILD.gn
@@ -9,8 +9,13 @@ "block_popups_table_view_controller.mm", "content_settings_table_view_controller.h", "content_settings_table_view_controller.mm", + "default_page_mode_coordinator.h", + "default_page_mode_coordinator.mm", + "default_page_mode_mediator.h", + "default_page_mode_mediator.mm", ] deps = [ + ":content_settings_ui", "//base", "//components/content_settings/core/browser", "//components/content_settings/core/common", @@ -20,8 +25,10 @@ "//ios/chrome/browser:pref_names", "//ios/chrome/browser/browser_state", "//ios/chrome/browser/content_settings", + "//ios/chrome/browser/main:public", "//ios/chrome/browser/net:crurl", "//ios/chrome/browser/ui:feature_flags", + "//ios/chrome/browser/ui/coordinators:chrome_coordinators", "//ios/chrome/browser/ui/ntp:feature_flags", "//ios/chrome/browser/ui/settings:constants", "//ios/chrome/browser/ui/settings:settings_root", @@ -37,6 +44,20 @@ ] } +source_set("content_settings_ui") { + configs += [ "//build/config/compiler:enable_arc" ] + sources = [ + "default_page_mode_consumer.h", + "default_page_mode_table_view_controller.h", + "default_page_mode_table_view_controller.mm", + ] + deps = [ + "//ios/chrome/browser/ui/settings:settings_root", + "//ios/chrome/browser/ui/table_view:utils", + "//ios/chrome/browser/ui/table_view/cells", + ] +} + source_set("unit_tests") { configs += [ "//build/config/compiler:enable_arc" ] testonly = true @@ -51,6 +72,7 @@ "//ios/chrome/app/strings", "//ios/chrome/browser/browser_state:test_support", "//ios/chrome/browser/content_settings", + "//ios/chrome/browser/main:test_support", "//ios/chrome/browser/ui/table_view:test_support", "//ios/chrome/browser/ui/table_view/cells", "//ios/web/public/test",
diff --git a/ios/chrome/browser/ui/settings/content_settings/content_settings_table_view_controller.h b/ios/chrome/browser/ui/settings/content_settings/content_settings_table_view_controller.h index f5ff342..53719f6 100644 --- a/ios/chrome/browser/ui/settings/content_settings/content_settings_table_view_controller.h +++ b/ios/chrome/browser/ui/settings/content_settings/content_settings_table_view_controller.h
@@ -8,16 +8,15 @@ #import "ios/chrome/browser/ui/settings/settings_controller_protocol.h" #import "ios/chrome/browser/ui/settings/settings_root_table_view_controller.h" -class ChromeBrowserState; +class Browser; // Controller for the UI that allows the user to change content settings like // blocking popups. @interface ContentSettingsTableViewController : SettingsRootTableViewController <SettingsControllerProtocol> -// The designated initializer. |browserState| must not be nil. -- (instancetype)initWithBrowserState:(ChromeBrowserState*)browserState - NS_DESIGNATED_INITIALIZER; +// The designated initializer. |browser| must not be null. +- (instancetype)initWithBrowser:(Browser*)browser NS_DESIGNATED_INITIALIZER; - (instancetype)initWithStyle:(UITableViewStyle)style NS_UNAVAILABLE; @end
diff --git a/ios/chrome/browser/ui/settings/content_settings/content_settings_table_view_controller.mm b/ios/chrome/browser/ui/settings/content_settings/content_settings_table_view_controller.mm index c1735252..574ae05 100644 --- a/ios/chrome/browser/ui/settings/content_settings/content_settings_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/content_settings/content_settings_table_view_controller.mm
@@ -15,11 +15,13 @@ #include "components/strings/grit/components_strings.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" #include "ios/chrome/browser/content_settings/host_content_settings_map_factory.h" +#import "ios/chrome/browser/main/browser.h" #include "ios/chrome/browser/pref_names.h" #import "ios/chrome/browser/ui/ntp/new_tab_page_feature.h" #import "ios/chrome/browser/ui/settings/cells/settings_switch_cell.h" #import "ios/chrome/browser/ui/settings/cells/settings_switch_item.h" #import "ios/chrome/browser/ui/settings/content_settings/block_popups_table_view_controller.h" +#import "ios/chrome/browser/ui/settings/content_settings/default_page_mode_coordinator.h" #import "ios/chrome/browser/ui/settings/settings_navigation_controller.h" #import "ios/chrome/browser/ui/settings/settings_table_view_controller_constants.h" #import "ios/chrome/browser/ui/settings/utils/content_setting_backed_boolean.h" @@ -55,6 +57,7 @@ ItemTypeSettingsBlockPopups = kItemTypeEnumZero, ItemTypeSettingsComposeEmail, ItemTypeSettingsShowLinkPreview, + ItemTypeSettingsDefaultSiteMode, }; } // namespace @@ -67,6 +70,7 @@ TableViewDetailIconItem* _blockPopupsDetailItem; TableViewDetailIconItem* _composeEmailDetailItem; TableViewMultiDetailTextItem* _openedInAnotherWindowItem; + TableViewDetailIconItem* _defaultSiteMode; } // PrefBackedBoolean for "Show Link Preview" setting state. @@ -75,6 +79,10 @@ // The item related to the switch for the "Show Link Preview" setting. @property(nonatomic, strong) SettingsSwitchItem* linkPreviewItem; +// The coordinator showing the view to choose the defaultMode. +@property(nonatomic, strong) + DefaultPageModeCoordinator* defaultModeViewController; + // Helpers to create collection view items. - (id)blockPopupsItem; - (id)composeEmailItem; @@ -82,17 +90,19 @@ @end @implementation ContentSettingsTableViewController { - ChromeBrowserState* _browserState; // weak + Browser* _browser; // weak } -- (instancetype)initWithBrowserState:(ChromeBrowserState*)browserState { - DCHECK(browserState); +- (instancetype)initWithBrowser:(Browser*)browser { + DCHECK(browser); self = [super initWithStyle:ChromeTableViewStyle()]; if (self) { - _browserState = browserState; + _browser = browser; self.title = l10n_util::GetNSString(IDS_IOS_CONTENT_SETTINGS_TITLE); + ChromeBrowserState* browserState = browser->GetBrowserState(); + HostContentSettingsMap* settingsMap = ios::HostContentSettingsMapFactory::GetForBrowserState(browserState); _disablePopupsSetting = [[ContentSettingBackedBoolean alloc] @@ -102,7 +112,7 @@ [_disablePopupsSetting setObserver:self]; _linkPreviewEnabled = [[PrefBackedBoolean alloc] - initWithPrefService:_browserState->GetPrefs() + initWithPrefService:browserState->GetPrefs() prefName:prefs::kLinkPreviewEnabled]; [_linkPreviewEnabled setObserver:self]; } @@ -167,6 +177,11 @@ [model addItem:[self linkPreviewItem] toSectionWithIdentifier:SectionIdentifierSettings]; } + + if (base::FeatureList::IsEnabled(kAddSettingForDefaultPageMode)) { + [model addItem:[self defaultSiteMode] + toSectionWithIdentifier:SectionIdentifierSettings]; + } } #pragma mark - SettingsControllerProtocol @@ -181,6 +196,16 @@ #pragma mark - ContentSettingsTableViewController +- (TableViewItem*)defaultSiteMode { + _defaultSiteMode = [[TableViewDetailIconItem alloc] + initWithType:ItemTypeSettingsDefaultSiteMode]; + NSString* subtitle = @"TEST - Mobile"; + _defaultSiteMode.text = @"TEST - Default Mode"; + _defaultSiteMode.detailText = subtitle; + _defaultSiteMode.accessoryType = UITableViewCellAccessoryDisclosureIndicator; + return _defaultSiteMode; +} + - (TableViewItem*)blockPopupsItem { _blockPopupsDetailItem = [[TableViewDetailIconItem alloc] initWithType:ItemTypeSettingsBlockPopups]; @@ -276,7 +301,7 @@ case ItemTypeSettingsBlockPopups: { BlockPopupsTableViewController* controller = [[BlockPopupsTableViewController alloc] - initWithBrowserState:_browserState]; + initWithBrowserState:_browser->GetBrowserState()]; controller.dispatcher = self.dispatcher; [self.navigationController pushViewController:controller animated:YES]; break; @@ -298,6 +323,12 @@ } break; } + case ItemTypeSettingsDefaultSiteMode: { + self.defaultModeViewController = [[DefaultPageModeCoordinator alloc] + initWithBaseNavigationController:self.navigationController + browser:_browser]; + [self.defaultModeViewController start]; + } } [tableView deselectRowAtIndexPath:indexPath animated:YES]; }
diff --git a/ios/chrome/browser/ui/settings/content_settings/content_settings_table_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/content_settings/content_settings_table_view_controller_unittest.mm index 3295a73..a26588db 100644 --- a/ios/chrome/browser/ui/settings/content_settings/content_settings_table_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/settings/content_settings/content_settings_table_view_controller_unittest.mm
@@ -5,6 +5,7 @@ #import "ios/chrome/browser/ui/settings/content_settings/content_settings_table_view_controller.h" #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" +#import "ios/chrome/browser/main/test_browser.h" #import "ios/chrome/browser/ui/table_view/chrome_table_view_controller_test.h" #include "ios/chrome/grit/ios_strings.h" #include "ios/web/public/test/web_task_environment.h" @@ -20,20 +21,17 @@ class ContentSettingsTableViewControllerTest : public ChromeTableViewControllerTest { protected: - void SetUp() override { - ChromeTableViewControllerTest::SetUp(); - TestChromeBrowserState::Builder test_cbs_builder; - chrome_browser_state_ = test_cbs_builder.Build(); - } + ContentSettingsTableViewControllerTest() + : browser_(std::make_unique<TestBrowser>()) {} ChromeTableViewController* InstantiateController() override { return [[ContentSettingsTableViewController alloc] - initWithBrowserState:chrome_browser_state_.get()]; + initWithBrowser:browser_.get()]; } private: web::WebTaskEnvironment task_environment_; - std::unique_ptr<TestChromeBrowserState> chrome_browser_state_; + std::unique_ptr<TestBrowser> browser_; }; // Tests that there are 2 items in Content Settings.
diff --git a/ios/chrome/browser/ui/settings/content_settings/default_page_mode_consumer.h b/ios/chrome/browser/ui/settings/content_settings/default_page_mode_consumer.h new file mode 100644 index 0000000..32861e0 --- /dev/null +++ b/ios/chrome/browser/ui/settings/content_settings/default_page_mode_consumer.h
@@ -0,0 +1,25 @@ +// 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 IOS_CHROME_BROWSER_UI_SETTINGS_CONTENT_SETTINGS_DEFAULT_PAGE_MODE_CONSUMER_H_ +#define IOS_CHROME_BROWSER_UI_SETTINGS_CONTENT_SETTINGS_DEFAULT_PAGE_MODE_CONSUMER_H_ + +#import <UIKit/UIKit.h> + +// The mode in which pages should be loaded. +typedef NS_ENUM(NSUInteger, DefaultPageMode) { + DefaultPageModeMobile, + DefaultPageModeDesktop, +}; + +// Consumer protocol for the screen allowing the user to choose the default mode +// (Desktop/Mobile) for loading pages. +@protocol DefaultPageModeConsumer + +// Sets the mode in which pages are loaded by default. +- (void)setDefaultPageMode:(DefaultPageMode)mode; + +@end + +#endif // IOS_CHROME_BROWSER_UI_SETTINGS_CONTENT_SETTINGS_DEFAULT_PAGE_MODE_CONSUMER_H_
diff --git a/ios/chrome/browser/ui/settings/content_settings/default_page_mode_coordinator.h b/ios/chrome/browser/ui/settings/content_settings/default_page_mode_coordinator.h new file mode 100644 index 0000000..200f452 --- /dev/null +++ b/ios/chrome/browser/ui/settings/content_settings/default_page_mode_coordinator.h
@@ -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. + +#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_CONTENT_SETTINGS_DEFAULT_PAGE_MODE_COORDINATOR_H_ +#define IOS_CHROME_BROWSER_UI_SETTINGS_CONTENT_SETTINGS_DEFAULT_PAGE_MODE_COORDINATOR_H_ + +#import "ios/chrome/browser/ui/coordinators/chrome_coordinator.h" + +// Coordinator to display the screen allowing the user to choose the default +// mode (Desktop/Mobile) for loading pages. +@interface DefaultPageModeCoordinator : ChromeCoordinator + +- (instancetype)initWithBaseNavigationController: + (UINavigationController*)navigationController + browser:(Browser*)browser + NS_DESIGNATED_INITIALIZER; + +- (instancetype)initWithBaseViewController:(UIViewController*)viewController + browser:(Browser*)browser NS_UNAVAILABLE; + +@end + +#endif // IOS_CHROME_BROWSER_UI_SETTINGS_CONTENT_SETTINGS_DEFAULT_PAGE_MODE_COORDINATOR_H_
diff --git a/ios/chrome/browser/ui/settings/content_settings/default_page_mode_coordinator.mm b/ios/chrome/browser/ui/settings/content_settings/default_page_mode_coordinator.mm new file mode 100644 index 0000000..d76ec8c --- /dev/null +++ b/ios/chrome/browser/ui/settings/content_settings/default_page_mode_coordinator.mm
@@ -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. + +#import "ios/chrome/browser/ui/settings/content_settings/default_page_mode_coordinator.h" + +#import "ios/chrome/browser/ui/settings/content_settings/default_page_mode_mediator.h" +#import "ios/chrome/browser/ui/settings/content_settings/default_page_mode_table_view_controller.h" +#import "ios/chrome/browser/ui/table_view/table_view_utils.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +@interface DefaultPageModeCoordinator () + +@property(nonatomic, strong) DefaultPageModeTableViewController* viewController; +@property(nonatomic, strong) DefaultPageModeMediator* mediator; + +@end + +@implementation DefaultPageModeCoordinator + +@synthesize baseNavigationController = _baseNavigationController; + +- (instancetype)initWithBaseNavigationController: + (UINavigationController*)navigationController + browser:(Browser*)browser { + self = [super initWithBaseViewController:navigationController + browser:browser]; + if (self) { + _baseNavigationController = navigationController; + } + return self; +} + +- (void)start { + self.viewController = [[DefaultPageModeTableViewController alloc] + initWithStyle:ChromeTableViewStyle()]; + self.mediator = + [[DefaultPageModeMediator alloc] initWithConsumer:self.viewController]; + [self.baseNavigationController pushViewController:self.viewController + animated:YES]; +} + +@end
diff --git a/ios/chrome/browser/ui/settings/content_settings/default_page_mode_mediator.h b/ios/chrome/browser/ui/settings/content_settings/default_page_mode_mediator.h new file mode 100644 index 0000000..a14653f --- /dev/null +++ b/ios/chrome/browser/ui/settings/content_settings/default_page_mode_mediator.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 IOS_CHROME_BROWSER_UI_SETTINGS_CONTENT_SETTINGS_DEFAULT_PAGE_MODE_MEDIATOR_H_ +#define IOS_CHROME_BROWSER_UI_SETTINGS_CONTENT_SETTINGS_DEFAULT_PAGE_MODE_MEDIATOR_H_ + +#import <Foundation/Foundation.h> + +@protocol DefaultPageModeConsumer; + +// Mediator for the screen allowing the user to choose the default mode +// (Desktop/Mobile) for loading pages. +@interface DefaultPageModeMediator : NSObject + +- (instancetype)initWithConsumer:(id<DefaultPageModeConsumer>)consumer + NS_DESIGNATED_INITIALIZER; + +- (instancetype)init NS_UNAVAILABLE; + +@end + +#endif // IOS_CHROME_BROWSER_UI_SETTINGS_CONTENT_SETTINGS_DEFAULT_PAGE_MODE_MEDIATOR_H_
diff --git a/ios/chrome/browser/ui/settings/content_settings/default_page_mode_mediator.mm b/ios/chrome/browser/ui/settings/content_settings/default_page_mode_mediator.mm new file mode 100644 index 0000000..8c7cc3c --- /dev/null +++ b/ios/chrome/browser/ui/settings/content_settings/default_page_mode_mediator.mm
@@ -0,0 +1,29 @@ +// 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 "ios/chrome/browser/ui/settings/content_settings/default_page_mode_mediator.h" + +#import "ios/chrome/browser/ui/settings/content_settings/default_page_mode_consumer.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +@interface DefaultPageModeMediator () + +@property(nonatomic, weak) id<DefaultPageModeConsumer> consumer; + +@end + +@implementation DefaultPageModeMediator + +- (instancetype)initWithConsumer:(id<DefaultPageModeConsumer>)consumer { + self = [super init]; + if (self) { + _consumer = consumer; + } + return self; +} + +@end
diff --git a/ios/chrome/browser/ui/settings/content_settings/default_page_mode_table_view_controller.h b/ios/chrome/browser/ui/settings/content_settings/default_page_mode_table_view_controller.h new file mode 100644 index 0000000..5670228 --- /dev/null +++ b/ios/chrome/browser/ui/settings/content_settings/default_page_mode_table_view_controller.h
@@ -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. + +#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_CONTENT_SETTINGS_DEFAULT_PAGE_MODE_TABLE_VIEW_CONTROLLER_H_ +#define IOS_CHROME_BROWSER_UI_SETTINGS_CONTENT_SETTINGS_DEFAULT_PAGE_MODE_TABLE_VIEW_CONTROLLER_H_ + +#import "ios/chrome/browser/ui/settings/content_settings/default_page_mode_consumer.h" +#import "ios/chrome/browser/ui/settings/settings_controller_protocol.h" +#import "ios/chrome/browser/ui/settings/settings_root_table_view_controller.h" + +// ViewController for the screen allowing the user to choose the default mode +// (Desktop/Mobile) for loading pages. +@interface DefaultPageModeTableViewController + : SettingsRootTableViewController <DefaultPageModeConsumer, + SettingsControllerProtocol> + +@end + +#endif // IOS_CHROME_BROWSER_UI_SETTINGS_CONTENT_SETTINGS_DEFAULT_PAGE_MODE_TABLE_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/settings/content_settings/default_page_mode_table_view_controller.mm b/ios/chrome/browser/ui/settings/content_settings/default_page_mode_table_view_controller.mm new file mode 100644 index 0000000..e0949fa --- /dev/null +++ b/ios/chrome/browser/ui/settings/content_settings/default_page_mode_table_view_controller.mm
@@ -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. + +#import "ios/chrome/browser/ui/settings/content_settings/default_page_mode_table_view_controller.h" + +#import "ios/chrome/browser/ui/table_view/cells/table_view_detail_icon_item.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +@implementation DefaultPageModeTableViewController + +#pragma mark - DefaultPageModeConsumer + +- (void)setDefaultPageMode:(DefaultPageMode)mode { + // TODO(crbug.com/1276922): change the selected cell based on the mode. +} + +#pragma mark - SettingsControllerProtocol + +- (void)reportDismissalUserAction { + // TODO(crbug.com/1276922): Add UserAction recording. +} + +- (void)reportBackUserAction { + // TODO(crbug.com/1276922): Add UserAction recording. +} + +@end
diff --git a/ios/chrome/browser/ui/settings/settings_table_view_controller.mm b/ios/chrome/browser/ui/settings/settings_table_view_controller.mm index be0024f..0a371003 100644 --- a/ios/chrome/browser/ui/settings/settings_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/settings_table_view_controller.mm
@@ -1257,8 +1257,8 @@ } case SettingsItemTypeContentSettings: base::RecordAction(base::UserMetricsAction("Settings.ContentSettings")); - controller = [[ContentSettingsTableViewController alloc] - initWithBrowserState:_browserState]; + controller = + [[ContentSettingsTableViewController alloc] initWithBrowser:_browser]; break; case SettingsItemTypeBandwidth: base::RecordAction(base::UserMetricsAction("Settings.Bandwidth"));
diff --git a/media/audio/audio_encoders_unittest.cc b/media/audio/audio_encoders_unittest.cc index 0be36ca..cf56840 100644 --- a/media/audio/audio_encoders_unittest.cc +++ b/media/audio/audio_encoders_unittest.cc
@@ -76,8 +76,8 @@ encoder_ = std::make_unique<AudioOpusEncoder>(); bool called_done = false; - AudioEncoder::StatusCB done_cb = - base::BindLambdaForTesting([&](Status error) { + AudioEncoder::EncoderStatusCB done_cb = + base::BindLambdaForTesting([&](EncoderStatus error) { if (!error.is_ok()) FAIL() << error.message(); called_done = true; @@ -100,7 +100,7 @@ audio_source_.OnMoreData(base::TimeDelta(), timestamp, 0, audio_bus.get()); bool called_done = false; - auto done_cb = base::BindLambdaForTesting([&](Status error) { + auto done_cb = base::BindLambdaForTesting([&](EncoderStatus error) { if (!error.is_ok()) FAIL() << error.message(); called_done = true; @@ -155,7 +155,7 @@ } bool flush_done = false; - auto done_cb = base::BindLambdaForTesting([&](Status error) { + auto done_cb = base::BindLambdaForTesting([&](EncoderStatus error) { if (!error.is_ok()) FAIL() << error.message(); flush_done = true; @@ -248,7 +248,7 @@ EXPECT_EQ(3u, timestamps.size()); EXPECT_EQ(ts2, timestamps[2]); - encoder()->Flush(base::BindOnce([](Status error) { + encoder()->Flush(base::BindOnce([](EncoderStatus error) { if (!error.is_ok()) FAIL() << error.message(); })); @@ -304,7 +304,7 @@ // them before we destroy the encoder. Flushing should trigger the encode // callback and we should be able to decode the resulting encoded frames. if (total_frames > frames_in_60_ms) { - encoder()->Flush(base::BindOnce([](Status error) { + encoder()->Flush(base::BindOnce([](EncoderStatus error) { if (!error.is_ok()) FAIL() << error.message(); }));
diff --git a/media/audio/audio_opus_encoder.cc b/media/audio/audio_opus_encoder.cc index 3b65eb4..e9a84c5 100644 --- a/media/audio/audio_opus_encoder.cc +++ b/media/audio/audio_opus_encoder.cc
@@ -12,8 +12,7 @@ #include "base/numerics/checked_math.h" #include "base/strings/stringprintf.h" #include "media/base/bind_to_current_loop.h" -#include "media/base/status.h" -#include "media/base/status_codes.h" +#include "media/base/encoder_status.h" #include "media/base/timestamp_constants.h" namespace media { @@ -109,26 +108,26 @@ void AudioOpusEncoder::Initialize(const Options& options, OutputCB output_callback, - StatusCB done_cb) { + EncoderStatusCB done_cb) { DCHECK(!output_callback.is_null()); DCHECK(!done_cb.is_null()); done_cb = BindToCurrentLoop(std::move(done_cb)); if (opus_encoder_) { - std::move(done_cb).Run(StatusCode::kEncoderInitializeTwice); + std::move(done_cb).Run(EncoderStatus::Codes::kEncoderInitializeTwice); return; } options_ = options; input_params_ = CreateInputParams(options); if (!input_params_.IsValid()) { - std::move(done_cb).Run(StatusCode::kEncoderInitializationError); + std::move(done_cb).Run(EncoderStatus::Codes::kEncoderInitializationError); return; } converted_params_ = CreateOpusCompatibleParams(input_params_); if (!input_params_.IsValid()) { - std::move(done_cb).Run(StatusCode::kEncoderInitializationError); + std::move(done_cb).Run(EncoderStatus::Codes::kEncoderInitializationError); return; } @@ -155,7 +154,7 @@ converted_params_.frames_per_buffer())); output_cb_ = BindToCurrentLoop(std::move(output_callback)); - std::move(done_cb).Run(OkStatus()); + std::move(done_cb).Run(EncoderStatus::Codes::kOk); } AudioOpusEncoder::~AudioOpusEncoder() = default; @@ -207,7 +206,7 @@ void AudioOpusEncoder::Encode(std::unique_ptr<AudioBus> audio_bus, base::TimeTicks capture_time, - StatusCB done_cb) { + EncoderStatusCB done_cb) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_EQ(audio_bus->channels(), input_params_.channels()); DCHECK(!done_cb.is_null()); @@ -216,7 +215,7 @@ current_done_cb_ = BindToCurrentLoop(std::move(done_cb)); if (!opus_encoder_) { std::move(current_done_cb_) - .Run(StatusCode::kEncoderInitializeNeverCompleted); + .Run(EncoderStatus::Codes::kEncoderInitializeNeverCompleted); return; } @@ -229,16 +228,17 @@ if (!current_done_cb_.is_null()) { // Is |current_done_cb_| is null, it means OnFifoOutput() has already // reported an error. - std::move(current_done_cb_).Run(OkStatus()); + std::move(current_done_cb_).Run(EncoderStatus::Codes::kOk); } } -void AudioOpusEncoder::Flush(StatusCB done_cb) { +void AudioOpusEncoder::Flush(EncoderStatusCB done_cb) { DCHECK(!done_cb.is_null()); done_cb = BindToCurrentLoop(std::move(done_cb)); if (!opus_encoder_) { - std::move(done_cb).Run(StatusCode::kEncoderInitializeNeverCompleted); + std::move(done_cb).Run( + EncoderStatus::Codes::kEncoderInitializeNeverCompleted); return; } @@ -248,7 +248,7 @@ if (!current_done_cb_.is_null()) { // Is |current_done_cb_| is null, it means OnFifoOutput() has already // reported an error. - std::move(current_done_cb_).Run(OkStatus()); + std::move(current_done_cb_).Run(EncoderStatus::Codes::kOk); } } @@ -267,7 +267,8 @@ if (result < 0 && !current_done_cb_.is_null()) { std::move(current_done_cb_) - .Run(Status(StatusCode::kEncoderFailedEncode, opus_strerror(result))); + .Run(EncoderStatus(EncoderStatus::Codes::kEncoderFailedEncode, + opus_strerror(result))); return; } @@ -296,7 +297,7 @@ // Creates and returns the libopus encoder instance. Returns nullptr if the // encoder creation fails. -StatusOr<OwnedOpusEncoder> AudioOpusEncoder::CreateOpusEncoder() { +EncoderStatus::Or<OwnedOpusEncoder> AudioOpusEncoder::CreateOpusEncoder() { int opus_result; OwnedOpusEncoder encoder( opus_encoder_create(converted_params_.sample_rate(), @@ -305,8 +306,8 @@ OpusEncoderDeleter); if (opus_result < 0) { - return Status( - StatusCode::kEncoderInitializationError, + return EncoderStatus( + EncoderStatus::Codes::kEncoderInitializationError, base::StringPrintf( "Couldn't init Opus encoder: %s, sample rate: %d, channels: %d", opus_strerror(opus_result), converted_params_.sample_rate(), @@ -317,8 +318,8 @@ options_.bitrate.has_value() ? options_.bitrate.value() : OPUS_AUTO; if (encoder && opus_encoder_ctl(encoder.get(), OPUS_SET_BITRATE(bitrate)) != OPUS_OK) { - return Status( - StatusCode::kEncoderInitializationError, + return EncoderStatus( + EncoderStatus::Codes::kEncoderInitializationError, base::StringPrintf("Failed to set Opus bitrate: %d", bitrate)); }
diff --git a/media/audio/audio_opus_encoder.h b/media/audio/audio_opus_encoder.h index c11c5c0..74fc000 100644 --- a/media/audio/audio_opus_encoder.h +++ b/media/audio/audio_opus_encoder.h
@@ -33,13 +33,13 @@ // AudioEncoder: void Initialize(const Options& options, OutputCB output_callback, - StatusCB done_cb) override; + EncoderStatusCB done_cb) override; void Encode(std::unique_ptr<AudioBus> audio_bus, base::TimeTicks capture_time, - StatusCB done_cb) override; + EncoderStatusCB done_cb) override; - void Flush(StatusCB done_cb) override; + void Flush(EncoderStatusCB done_cb) override; static constexpr int kMinBitrate = 6000; @@ -50,7 +50,7 @@ CodecDescription PrepareExtraData(); - StatusOr<OwnedOpusEncoder> CreateOpusEncoder(); + EncoderStatus::Or<OwnedOpusEncoder> CreateOpusEncoder(); AudioParameters input_params_; @@ -81,7 +81,7 @@ // Callback for reporting completion and status of the current Flush() or // Encoder() - StatusCB current_done_cb_; + EncoderStatusCB current_done_cb_; // True if the next output needs to have extra_data in it, only happens once. bool need_to_emit_extra_data_ = true;
diff --git a/media/base/BUILD.gn b/media/base/BUILD.gn index 86557c5a..2c5c2e06 100644 --- a/media/base/BUILD.gn +++ b/media/base/BUILD.gn
@@ -158,6 +158,7 @@ "djb2.cc", "djb2.h", "eme_constants.h", + "encoder_status.h", "encryption_pattern.cc", "encryption_pattern.h", "encryption_scheme.cc",
diff --git a/media/base/async_destroy_video_encoder.h b/media/base/async_destroy_video_encoder.h index ffe5f55..6debc10 100644 --- a/media/base/async_destroy_video_encoder.h +++ b/media/base/async_destroy_video_encoder.h
@@ -39,7 +39,7 @@ void Initialize(VideoCodecProfile profile, const Options& options, OutputCB output_cb, - StatusCB done_cb) override { + EncoderStatusCB done_cb) override { DCHECK(wrapped_encoder_); wrapped_encoder_->Initialize(profile, options, std::move(output_cb), std::move(done_cb)); @@ -47,20 +47,20 @@ void Encode(scoped_refptr<VideoFrame> frame, bool key_frame, - StatusCB done_cb) override { + EncoderStatusCB done_cb) override { DCHECK(wrapped_encoder_); wrapped_encoder_->Encode(std::move(frame), key_frame, std::move(done_cb)); } void ChangeOptions(const Options& options, OutputCB output_cb, - StatusCB done_cb) override { + EncoderStatusCB done_cb) override { DCHECK(wrapped_encoder_); wrapped_encoder_->ChangeOptions(options, std::move(output_cb), std::move(done_cb)); } - void Flush(StatusCB done_cb) override { + void Flush(EncoderStatusCB done_cb) override { DCHECK(wrapped_encoder_); wrapped_encoder_->Flush(std::move(done_cb)); }
diff --git a/media/base/audio_encoder.h b/media/base/audio_encoder.h index 3d49b56..c94c137 100644 --- a/media/base/audio_encoder.h +++ b/media/base/audio_encoder.h
@@ -14,8 +14,8 @@ #include "media/base/audio_bus.h" #include "media/base/audio_codecs.h" #include "media/base/audio_parameters.h" +#include "media/base/encoder_status.h" #include "media/base/media_export.h" -#include "media/base/status.h" #include "media/base/timestamp_constants.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -85,7 +85,7 @@ absl::optional<CodecDescription>)>; // Signature of the callback to report errors. - using StatusCB = base::OnceCallback<void(Status error)>; + using EncoderStatusCB = base::OnceCallback<void(EncoderStatus error)>; AudioEncoder(); AudioEncoder(const AudioEncoder&) = delete; @@ -99,7 +99,7 @@ // No AudioEncoder calls should be made before |done_cb| is executed. virtual void Initialize(const Options& options, OutputCB output_cb, - StatusCB done_cb) = 0; + EncoderStatusCB done_cb) = 0; // Requests contents of |audio_bus| to be encoded. // |capture_time| is a media time at the end of the audio piece in the @@ -115,12 +115,12 @@ // including before Encode() returns. virtual void Encode(std::unique_ptr<AudioBus> audio_bus, base::TimeTicks capture_time, - StatusCB done_cb) = 0; + EncoderStatusCB done_cb) = 0; // Some encoders may choose to buffer audio frames before they encode them. // Requests all outputs for already encoded frames to be // produced via |output_cb| and calls |done_cb| after that. - virtual void Flush(StatusCB done_cb) = 0; + virtual void Flush(EncoderStatusCB done_cb) = 0; protected: Options options_;
diff --git a/media/base/encoder_status.h b/media/base/encoder_status.h new file mode 100644 index 0000000..3ec701c --- /dev/null +++ b/media/base/encoder_status.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 MEDIA_BASE_ENCODER_STATUS_H_ +#define MEDIA_BASE_ENCODER_STATUS_H_ + +#include "media/base/status.h" + +namespace media { + +struct EncoderStatusTraits { + enum class Codes : StatusCodeType { + kOk = 0, + kEncoderInitializeNeverCompleted = 1, + kEncoderInitializeTwice = 2, + kEncoderFailedEncode = 3, + kEncoderUnsupportedProfile = 4, + kEncoderUnsupportedCodec = 5, + kEncoderUnsupportedConfig = 6, + kEncoderInitializationError = 7, + kEncoderFailedFlush = 8, + kEncoderMojoConnectionError = 9, + }; + static constexpr StatusGroupType Group() { return "EncoderStatusCodes"; } + static constexpr Codes DefaultEnumValue() { return Codes::kOk; } +}; + +using EncoderStatus = TypedStatus<EncoderStatusTraits>; + +} // namespace media + +#endif // MEDIA_BASE_ENCODER_STATUS_H_
diff --git a/media/base/media_log.cc b/media/base/media_log.cc index 6cb08ed6..93e712d8 100644 --- a/media/base/media_log.cc +++ b/media/base/media_log.cc
@@ -7,7 +7,6 @@ #include <utility> #include "base/atomic_sequence_num.h" -#include "base/json/json_writer.h" #include "base/memory/ptr_util.h" #include "base/strings/string_util.h" #include "base/values.h" @@ -63,13 +62,6 @@ AddLogRecord(std::move(record)); } -void MediaLog::NotifyError(Status status) { - DCHECK(!status.is_ok()); - std::string output_str; - base::JSONWriter::Write(MediaSerialize(status), &output_str); - AddMessage(MediaLogMessageLevel::kERROR, output_str); -} - void MediaLog::OnWebMediaPlayerDestroyedLocked() {} void MediaLog::OnWebMediaPlayerDestroyed() { AddEvent<MediaLogEvent::kWebMediaPlayerDestroyed>();
diff --git a/media/base/media_log.h b/media/base/media_log.h index b6cf2bf..01db50f7 100644 --- a/media/base/media_log.h +++ b/media/base/media_log.h
@@ -14,6 +14,7 @@ #include <utility> #include "base/gtest_prod_util.h" +#include "base/json/json_writer.h" #include "base/logging.h" #include "base/memory/raw_ptr.h" #include "base/memory/ref_counted.h" @@ -95,7 +96,13 @@ void NotifyError(PipelineStatus status); // Notify a non-ok Status. This method Should _not_ be given an OK status. - void NotifyError(Status status); + template <typename T> + void NotifyError(const TypedStatus<T>& status) { + DCHECK(!status.is_ok()); + std::string output_str; + base::JSONWriter::Write(MediaSerialize(status), &output_str); + AddMessage(MediaLogMessageLevel::kERROR, output_str); + } // Notify the media log that the player is destroyed. Some implementations // will want to change event handling based on this.
diff --git a/media/base/mock_filters.h b/media/base/mock_filters.h index 2a115e4d..4f2e98c 100644 --- a/media/base/mock_filters.h +++ b/media/base/mock_filters.h
@@ -294,17 +294,17 @@ Initialize, (const AudioEncoder::Options& options, AudioEncoder::OutputCB output_cb, - AudioEncoder::StatusCB done_cb), + AudioEncoder::EncoderStatusCB done_cb), (override)); MOCK_METHOD(void, Encode, (std::unique_ptr<AudioBus> audio_bus, base::TimeTicks capture_time, - AudioEncoder::StatusCB done_cb), + AudioEncoder::EncoderStatusCB done_cb), (override)); - MOCK_METHOD(void, Flush, (AudioEncoder::StatusCB done_cb), (override)); + MOCK_METHOD(void, Flush, (AudioEncoder::EncoderStatusCB done_cb), (override)); // A function for mocking destructor calls MOCK_METHOD(void, OnDestruct, ()); @@ -325,24 +325,24 @@ (VideoCodecProfile profile, const VideoEncoder::Options& options, VideoEncoder::OutputCB output_cb, - VideoEncoder::StatusCB done_cb), + VideoEncoder::EncoderStatusCB done_cb), (override)); MOCK_METHOD(void, Encode, (scoped_refptr<VideoFrame> frame, bool key_frame, - VideoEncoder::StatusCB done_cb), + VideoEncoder::EncoderStatusCB done_cb), (override)); MOCK_METHOD(void, ChangeOptions, (const VideoEncoder::Options& options, VideoEncoder::OutputCB output_cb, - VideoEncoder::StatusCB done_cb), + VideoEncoder::EncoderStatusCB done_cb), (override)); - MOCK_METHOD(void, Flush, (VideoEncoder::StatusCB done_cb), (override)); + MOCK_METHOD(void, Flush, (VideoEncoder::EncoderStatusCB done_cb), (override)); // A function for mocking destructor calls MOCK_METHOD(void, Dtor, ());
diff --git a/media/base/offloading_audio_encoder.cc b/media/base/offloading_audio_encoder.cc index 8dad7381..eafa2f0 100644 --- a/media/base/offloading_audio_encoder.cc +++ b/media/base/offloading_audio_encoder.cc
@@ -34,7 +34,7 @@ void OffloadingAudioEncoder::Initialize(const Options& options, OutputCB output_cb, - StatusCB done_cb) { + EncoderStatusCB done_cb) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); work_runner_->PostTask( FROM_HERE, base::BindOnce(&AudioEncoder::Initialize, @@ -45,7 +45,7 @@ void OffloadingAudioEncoder::Encode(std::unique_ptr<AudioBus> audio_bus, base::TimeTicks capture_time, - StatusCB done_cb) { + EncoderStatusCB done_cb) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); work_runner_->PostTask( FROM_HERE, base::BindOnce(&AudioEncoder::Encode, @@ -54,7 +54,7 @@ WrapCallback(std::move(done_cb)))); } -void OffloadingAudioEncoder::Flush(StatusCB done_cb) { +void OffloadingAudioEncoder::Flush(EncoderStatusCB done_cb) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); work_runner_->PostTask( FROM_HERE, base::BindOnce(&AudioEncoder::Flush, @@ -73,4 +73,4 @@ return base::BindPostTask(callback_runner_, std::move(cb)); } -} // namespace media \ No newline at end of file +} // namespace media
diff --git a/media/base/offloading_audio_encoder.h b/media/base/offloading_audio_encoder.h index 39f4218..63a2f70 100644 --- a/media/base/offloading_audio_encoder.h +++ b/media/base/offloading_audio_encoder.h
@@ -39,13 +39,13 @@ void Initialize(const Options& options, OutputCB output_cb, - StatusCB done_cb) override; + EncoderStatusCB done_cb) override; void Encode(std::unique_ptr<AudioBus> audio_bus, base::TimeTicks capture_time, - StatusCB done_cb) override; + EncoderStatusCB done_cb) override; - void Flush(StatusCB done_cb) override; + void Flush(EncoderStatusCB done_cb) override; private: template <class T>
diff --git a/media/base/offloading_audio_encoder_unittest.cc b/media/base/offloading_audio_encoder_unittest.cc index 76d7e362..467ce41 100644 --- a/media/base/offloading_audio_encoder_unittest.cc +++ b/media/base/offloading_audio_encoder_unittest.cc
@@ -60,19 +60,20 @@ EXPECT_TRUE(callback_runner_->RunsTasksInCurrentSequence()); called_output = true; }); - AudioEncoder::StatusCB done_cb = base::BindLambdaForTesting([&](Status s) { - EXPECT_TRUE(callback_runner_->RunsTasksInCurrentSequence()); - called_done = true; - }); + AudioEncoder::EncoderStatusCB done_cb = + base::BindLambdaForTesting([&](EncoderStatus s) { + EXPECT_TRUE(callback_runner_->RunsTasksInCurrentSequence()); + called_done = true; + }); EXPECT_CALL(*mock_audio_encoder_, Initialize(_, _, _)) .WillOnce(Invoke([this](const AudioEncoder::Options& options, AudioEncoder::OutputCB output_cb, - AudioEncoder::StatusCB done_cb) { + AudioEncoder::EncoderStatusCB done_cb) { EXPECT_TRUE(work_runner_->RunsTasksInCurrentSequence()); AudioParameters params; EncodedAudioBuffer buf(params, nullptr, 0, base::TimeTicks()); - std::move(done_cb).Run(Status()); + std::move(done_cb).Run(EncoderStatus::Codes::kOk); // Usually |output_cb| is not called by Initialize() but for this // test it doesn't matter. We only care about a task runner used @@ -89,17 +90,18 @@ TEST_F(OffloadingAudioEncoderTest, Encode) { bool called_done = false; - AudioEncoder::StatusCB done_cb = base::BindLambdaForTesting([&](Status s) { - EXPECT_TRUE(callback_runner_->RunsTasksInCurrentSequence()); - called_done = true; - }); + AudioEncoder::EncoderStatusCB done_cb = + base::BindLambdaForTesting([&](EncoderStatus s) { + EXPECT_TRUE(callback_runner_->RunsTasksInCurrentSequence()); + called_done = true; + }); EXPECT_CALL(*mock_audio_encoder_, Encode(_, _, _)) .WillOnce(Invoke([this](std::unique_ptr<AudioBus> audio_bus, base::TimeTicks capture_time, - AudioEncoder::StatusCB done_cb) { + AudioEncoder::EncoderStatusCB done_cb) { EXPECT_TRUE(work_runner_->RunsTasksInCurrentSequence()); - std::move(done_cb).Run(Status()); + std::move(done_cb).Run(EncoderStatus::Codes::kOk); })); base::TimeTicks ts; @@ -110,15 +112,16 @@ TEST_F(OffloadingAudioEncoderTest, Flush) { bool called_done = false; - AudioEncoder::StatusCB done_cb = base::BindLambdaForTesting([&](Status s) { - EXPECT_TRUE(callback_runner_->RunsTasksInCurrentSequence()); - called_done = true; - }); + AudioEncoder::EncoderStatusCB done_cb = + base::BindLambdaForTesting([&](EncoderStatus s) { + EXPECT_TRUE(callback_runner_->RunsTasksInCurrentSequence()); + called_done = true; + }); EXPECT_CALL(*mock_audio_encoder_, Flush(_)) - .WillOnce(Invoke([this](AudioEncoder::StatusCB done_cb) { + .WillOnce(Invoke([this](AudioEncoder::EncoderStatusCB done_cb) { EXPECT_TRUE(work_runner_->RunsTasksInCurrentSequence()); - std::move(done_cb).Run(Status()); + std::move(done_cb).Run(EncoderStatus::Codes::kOk); })); offloading_encoder_->Flush(std::move(done_cb));
diff --git a/media/base/offloading_video_encoder.cc b/media/base/offloading_video_encoder.cc index 935cf74..737927f 100644 --- a/media/base/offloading_video_encoder.cc +++ b/media/base/offloading_video_encoder.cc
@@ -37,7 +37,7 @@ void OffloadingVideoEncoder::Initialize(VideoCodecProfile profile, const Options& options, OutputCB output_cb, - StatusCB done_cb) { + EncoderStatusCB done_cb) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); work_runner_->PostTask( FROM_HERE, @@ -49,7 +49,7 @@ void OffloadingVideoEncoder::Encode(scoped_refptr<VideoFrame> frame, bool key_frame, - StatusCB done_cb) { + EncoderStatusCB done_cb) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); work_runner_->PostTask( FROM_HERE, @@ -60,7 +60,7 @@ void OffloadingVideoEncoder::ChangeOptions(const Options& options, OutputCB output_cb, - StatusCB done_cb) { + EncoderStatusCB done_cb) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); work_runner_->PostTask( FROM_HERE, base::BindOnce(&VideoEncoder::ChangeOptions, @@ -69,7 +69,7 @@ WrapCallback(std::move(done_cb)))); } -void OffloadingVideoEncoder::Flush(StatusCB done_cb) { +void OffloadingVideoEncoder::Flush(EncoderStatusCB done_cb) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); work_runner_->PostTask( FROM_HERE, base::BindOnce(&VideoEncoder::Flush,
diff --git a/media/base/offloading_video_encoder.h b/media/base/offloading_video_encoder.h index 6000c4c..8b296d61 100644 --- a/media/base/offloading_video_encoder.h +++ b/media/base/offloading_video_encoder.h
@@ -40,17 +40,17 @@ void Initialize(VideoCodecProfile profile, const Options& options, OutputCB output_cb, - StatusCB done_cb) override; + EncoderStatusCB done_cb) override; void Encode(scoped_refptr<VideoFrame> frame, bool key_frame, - StatusCB done_cb) override; + EncoderStatusCB done_cb) override; void ChangeOptions(const Options& options, OutputCB output_cb, - StatusCB done_cb) override; + EncoderStatusCB done_cb) override; - void Flush(StatusCB done_cb) override; + void Flush(EncoderStatusCB done_cb) override; private: template <class T>
diff --git a/media/base/offloading_video_encoder_unittest.cc b/media/base/offloading_video_encoder_unittest.cc index c6374ad6..c5afc02 100644 --- a/media/base/offloading_video_encoder_unittest.cc +++ b/media/base/offloading_video_encoder_unittest.cc
@@ -62,18 +62,19 @@ EXPECT_TRUE(callback_runner_->RunsTasksInCurrentSequence()); called_output = true; }); - VideoEncoder::StatusCB done_cb = base::BindLambdaForTesting([&](Status s) { - EXPECT_TRUE(callback_runner_->RunsTasksInCurrentSequence()); - called_done = true; - }); + VideoEncoder::EncoderStatusCB done_cb = + base::BindLambdaForTesting([&](EncoderStatus s) { + EXPECT_TRUE(callback_runner_->RunsTasksInCurrentSequence()); + called_done = true; + }); EXPECT_CALL(*mock_video_encoder_, Initialize(_, _, _, _)) .WillOnce(Invoke([this](VideoCodecProfile profile, const VideoEncoder::Options& options, VideoEncoder::OutputCB output_cb, - VideoEncoder::StatusCB done_cb) { + VideoEncoder::EncoderStatusCB done_cb) { EXPECT_TRUE(work_runner_->RunsTasksInCurrentSequence()); - std::move(done_cb).Run(Status()); + std::move(done_cb).Run(EncoderStatus::Codes::kOk); std::move(output_cb).Run(VideoEncoderOutput(), {}); })); @@ -86,16 +87,17 @@ TEST_F(OffloadingVideoEncoderTest, Encode) { bool called_done = false; - VideoEncoder::StatusCB done_cb = base::BindLambdaForTesting([&](Status s) { - EXPECT_TRUE(callback_runner_->RunsTasksInCurrentSequence()); - called_done = true; - }); + VideoEncoder::EncoderStatusCB done_cb = + base::BindLambdaForTesting([&](EncoderStatus s) { + EXPECT_TRUE(callback_runner_->RunsTasksInCurrentSequence()); + called_done = true; + }); EXPECT_CALL(*mock_video_encoder_, Encode(_, _, _)) .WillOnce(Invoke([this](scoped_refptr<VideoFrame> frame, bool key_frame, - VideoEncoder::StatusCB done_cb) { + VideoEncoder::EncoderStatusCB done_cb) { EXPECT_TRUE(work_runner_->RunsTasksInCurrentSequence()); - std::move(done_cb).Run(Status()); + std::move(done_cb).Run(EncoderStatus::Codes::kOk); })); offloading_encoder_->Encode(nullptr, false, std::move(done_cb)); @@ -106,10 +108,11 @@ TEST_F(OffloadingVideoEncoderTest, ChangeOptions) { bool called_done = false; VideoEncoder::Options options; - VideoEncoder::StatusCB done_cb = base::BindLambdaForTesting([&](Status s) { - EXPECT_TRUE(callback_runner_->RunsTasksInCurrentSequence()); - called_done = true; - }); + VideoEncoder::EncoderStatusCB done_cb = + base::BindLambdaForTesting([&](EncoderStatus s) { + EXPECT_TRUE(callback_runner_->RunsTasksInCurrentSequence()); + called_done = true; + }); VideoEncoder::OutputCB output_cb = base::BindRepeating( [](VideoEncoderOutput, absl::optional<VideoEncoder::CodecDescription>) { @@ -118,9 +121,9 @@ EXPECT_CALL(*mock_video_encoder_, ChangeOptions(_, _, _)) .WillOnce(Invoke([this](const VideoEncoder::Options& options, VideoEncoder::OutputCB output_cb, - VideoEncoder::StatusCB done_cb) { + VideoEncoder::EncoderStatusCB done_cb) { EXPECT_TRUE(work_runner_->RunsTasksInCurrentSequence()); - std::move(done_cb).Run(Status()); + std::move(done_cb).Run(EncoderStatus::Codes::kOk); })); offloading_encoder_->ChangeOptions(options, std::move(output_cb), @@ -131,15 +134,16 @@ TEST_F(OffloadingVideoEncoderTest, Flush) { bool called_done = false; - VideoEncoder::StatusCB done_cb = base::BindLambdaForTesting([&](Status s) { - EXPECT_TRUE(callback_runner_->RunsTasksInCurrentSequence()); - called_done = true; - }); + VideoEncoder::EncoderStatusCB done_cb = + base::BindLambdaForTesting([&](EncoderStatus s) { + EXPECT_TRUE(callback_runner_->RunsTasksInCurrentSequence()); + called_done = true; + }); EXPECT_CALL(*mock_video_encoder_, Flush(_)) - .WillOnce(Invoke([this](VideoEncoder::StatusCB done_cb) { + .WillOnce(Invoke([this](VideoEncoder::EncoderStatusCB done_cb) { EXPECT_TRUE(work_runner_->RunsTasksInCurrentSequence()); - std::move(done_cb).Run(Status()); + std::move(done_cb).Run(EncoderStatus::Codes::kOk); })); offloading_encoder_->Flush(std::move(done_cb));
diff --git a/media/base/status.h b/media/base/status.h index 5a5f414..3b6a1b5 100644 --- a/media/base/status.h +++ b/media/base/status.h
@@ -24,6 +24,15 @@ struct StructTraits; } // namespace mojo +#define POST_STATUS_AND_RETURN_ON_FAILURE(eval_to_status, cb, ret) \ + do { \ + const auto EVALUATED = (eval_to_status); \ + if (!EVALUATED.is_ok()) { \ + cb.Run(std::move(EVALUATED)); \ + return ret; \ + } \ + } while (0) + namespace media { // See media/base/status.md for details and instructions for @@ -359,6 +368,9 @@ private: std::unique_ptr<internal::StatusData> data_; + // Let the status sink talk about the internal data. + friend class StatusSink; + template <typename StatusEnum, typename DataView> friend struct mojo::StructTraits;
diff --git a/media/base/status_codes.h b/media/base/status_codes.h index 3ac087a..d48bd8e 100644 --- a/media/base/status_codes.h +++ b/media/base/status_codes.h
@@ -30,6 +30,7 @@ kAborted = 0x0001, kInvalidArgument = 0x0002, kKeyFrameRequired = 0x0003, + kWrappedError = 0x0004, // Decoder Errors: 0x01 kDecoderInitializeNeverCompleted = 0x0101, @@ -64,17 +65,6 @@ kMojoDecoderNoConnection = 0x0404, kMojoDecoderDeletedWithoutInitialization = 0x0405, - // Encoder Error: 0x06 - kEncoderInitializeNeverCompleted = 0x0601, - kEncoderInitializeTwice = 0x0602, - kEncoderFailedEncode = 0x0603, - kEncoderUnsupportedProfile = 0x0604, - kEncoderUnsupportedCodec = 0x0605, - kEncoderUnsupportedConfig = 0x0606, - kEncoderInitializationError = 0x0607, - kEncoderFailedFlush = 0x0608, - kEncoderMojoConnectionError = 0x0609, - // Format Errors: 0x08 kH264ParsingError = 0x0801, kH264BufferTooSmall = 0x0802,
diff --git a/media/base/video_encoder.h b/media/base/video_encoder.h index 40464d3..15f0d5b2 100644 --- a/media/base/video_encoder.h +++ b/media/base/video_encoder.h
@@ -8,8 +8,8 @@ #include "base/callback.h" #include "base/time/time.h" #include "media/base/bitrate.h" +#include "media/base/encoder_status.h" #include "media/base/media_export.h" -#include "media/base/status.h" #include "media/base/svc_scalability_mode.h" #include "media/base/video_codecs.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -77,13 +77,13 @@ absl::optional<CodecDescription>)>; // Callback to report success and errors in encoder calls. - using StatusCB = base::OnceCallback<void(Status error)>; + using EncoderStatusCB = base::OnceCallback<void(EncoderStatus error)>; struct PendingEncode { PendingEncode(); PendingEncode(PendingEncode&&); ~PendingEncode(); - StatusCB done_callback; + EncoderStatusCB done_callback; scoped_refptr<VideoFrame> frame; bool key_frame; }; @@ -103,7 +103,7 @@ virtual void Initialize(VideoCodecProfile profile, const Options& options, OutputCB output_cb, - StatusCB done_cb) = 0; + EncoderStatusCB done_cb) = 0; // Requests a |frame| to be encoded. The status of the encoder and the frame // are returned via the provided callback |done_cb|. @@ -119,7 +119,7 @@ // and harvest the outputs. virtual void Encode(scoped_refptr<VideoFrame> frame, bool key_frame, - StatusCB done_cb) = 0; + EncoderStatusCB done_cb) = 0; // Adjust encoder options and the output callback for future frames, executing // the |done_cb| upon completion. @@ -130,11 +130,11 @@ // for it to finish. virtual void ChangeOptions(const Options& options, OutputCB output_cb, - StatusCB done_cb) = 0; + EncoderStatusCB done_cb) = 0; // Requests all outputs for already encoded frames to be // produced via |output_cb| and calls |dene_cb| after that. - virtual void Flush(StatusCB done_cb) = 0; + virtual void Flush(EncoderStatusCB done_cb) = 0; }; } // namespace media
diff --git a/media/mojo/clients/mojo_audio_encoder.cc b/media/mojo/clients/mojo_audio_encoder.cc index 2909457..66fd091 100644 --- a/media/mojo/clients/mojo_audio_encoder.cc +++ b/media/mojo/clients/mojo_audio_encoder.cc
@@ -26,12 +26,13 @@ void MojoAudioEncoder::Initialize(const Options& options, OutputCB output_cb, - StatusCB done_cb) { + EncoderStatusCB done_cb) { DCHECK(output_cb); DCHECK(done_cb); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (remote_encoder_.is_bound() || client_receiver_.is_bound()) { - PostStatusCallback(std::move(done_cb), StatusCode::kEncoderInitializeTwice); + PostStatusCallback(std::move(done_cb), + EncoderStatus::Codes::kEncoderInitializeTwice); return; } @@ -39,7 +40,7 @@ if (!remote_encoder_.is_bound() || !remote_encoder_.is_connected()) { PostStatusCallback(std::move(done_cb), - StatusCode::kEncoderInitializationError); + EncoderStatus::Codes::kEncoderInitializationError); return; } @@ -52,13 +53,14 @@ void MojoAudioEncoder::Encode(std::unique_ptr<AudioBus> audio_bus, base::TimeTicks capture_time, - StatusCB done_cb) { + EncoderStatusCB done_cb) { DCHECK(audio_bus); DCHECK(done_cb); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!remote_encoder_.is_bound() || !remote_encoder_.is_connected()) { - PostStatusCallback(std::move(done_cb), StatusCode::kEncoderFailedEncode); + PostStatusCallback(std::move(done_cb), + EncoderStatus::Codes::kEncoderFailedEncode); return; } @@ -70,12 +72,13 @@ WrapCallbackAsPending(std::move(done_cb))); } -void MojoAudioEncoder::Flush(StatusCB done_cb) { +void MojoAudioEncoder::Flush(EncoderStatusCB done_cb) { DCHECK(done_cb); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!remote_encoder_.is_bound() || !remote_encoder_.is_connected()) { - PostStatusCallback(std::move(done_cb), StatusCode::kEncoderFailedFlush); + PostStatusCallback(std::move(done_cb), + EncoderStatus::Codes::kEncoderFailedFlush); return; } @@ -92,24 +95,24 @@ } void MojoAudioEncoder::CallAndReleaseCallback(PendingCallbackHandle handle, - const Status& status) { + const EncoderStatus& status) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!pending_callbacks_.empty()) { - StatusCB callback = std::move(*handle); + EncoderStatusCB callback = std::move(*handle); pending_callbacks_.erase(handle); std::move(callback).Run(status); } } -MojoAudioEncoder::WrappedStatusCB MojoAudioEncoder::WrapCallbackAsPending( - StatusCB callback) { +MojoAudioEncoder::WrappedEncoderStatusCB +MojoAudioEncoder::WrapCallbackAsPending(EncoderStatusCB callback) { PendingCallbackHandle handle = pending_callbacks_.insert(pending_callbacks_.end(), std::move(callback)); return base::BindOnce(&MojoAudioEncoder::CallAndReleaseCallback, weak_this_, handle); } -void MojoAudioEncoder::CallAndReleaseAllPendingCallbacks(Status status) { +void MojoAudioEncoder::CallAndReleaseAllPendingCallbacks(EncoderStatus status) { for (auto& callback : pending_callbacks_) PostStatusCallback(std::move(callback), status); pending_callbacks_.clear(); @@ -125,12 +128,14 @@ void MojoAudioEncoder::OnConnectionError() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(!remote_encoder_.is_connected()); - CallAndReleaseAllPendingCallbacks(StatusCode::kEncoderMojoConnectionError); + CallAndReleaseAllPendingCallbacks( + EncoderStatus::Codes::kEncoderMojoConnectionError); weak_factory_.InvalidateWeakPtrs(); remote_encoder_.reset(); } -void MojoAudioEncoder::PostStatusCallback(StatusCB callback, Status status) { +void MojoAudioEncoder::PostStatusCallback(EncoderStatusCB callback, + EncoderStatus status) { runner_->PostTask(FROM_HERE, base::BindOnce(std::move(callback), std::move(status))); }
diff --git a/media/mojo/clients/mojo_audio_encoder.h b/media/mojo/clients/mojo_audio_encoder.h index bba5974..d8f4633 100644 --- a/media/mojo/clients/mojo_audio_encoder.h +++ b/media/mojo/clients/mojo_audio_encoder.h
@@ -35,13 +35,13 @@ // media::AudioEncoder implementation. void Initialize(const Options& options, OutputCB output_cb, - StatusCB done_cb) final; + EncoderStatusCB done_cb) final; void Encode(std::unique_ptr<AudioBus> audio_bus, base::TimeTicks capture_time, - StatusCB done_cb) final; + EncoderStatusCB done_cb) final; - void Flush(StatusCB done_cb) final; + void Flush(EncoderStatusCB done_cb) final; // AudioEncoderClient implementation. void OnEncodedBufferReady(media::EncodedAudioBuffer buffer, @@ -51,23 +51,24 @@ // Using std::list here for stable iterators, so we can add and remove // pending callbacks without worry and nuke them all at once if need be // if Mojo connection error occurs. - using PendingCallbacksList = std::list<StatusCB>; + using PendingCallbacksList = std::list<EncoderStatusCB>; using PendingCallbackHandle = PendingCallbacksList::iterator; - // It is different from regular StatusCB because mojo only gives us + // It is different from regular EncoderStatusCB because mojo only gives us // `const Status&` instead of `Status`. - using WrappedStatusCB = base::OnceCallback<void(const Status& error)>; + using WrappedEncoderStatusCB = + base::OnceCallback<void(const EncoderStatus& error)>; void CallAndReleaseCallback(PendingCallbackHandle handle, - const Status& status); - void CallAndReleaseAllPendingCallbacks(Status status) + const EncoderStatus& status); + void CallAndReleaseAllPendingCallbacks(EncoderStatus status) VALID_CONTEXT_REQUIRED(sequence_checker_); - WrappedStatusCB WrapCallbackAsPending(StatusCB callback) + WrappedEncoderStatusCB WrapCallbackAsPending(EncoderStatusCB callback) VALID_CONTEXT_REQUIRED(sequence_checker_); void BindRemote(); void OnConnectionError(); - void PostStatusCallback(StatusCB callback, Status status); + void PostStatusCallback(EncoderStatusCB callback, EncoderStatus status); SEQUENCE_CHECKER(sequence_checker_); mojo::PendingRemote<mojom::AudioEncoder> pending_remote_encoder_
diff --git a/media/mojo/clients/mojo_audio_encoder_unittest.cc b/media/mojo/clients/mojo_audio_encoder_unittest.cc index e0302c6..c9ddb9f 100644 --- a/media/mojo/clients/mojo_audio_encoder_unittest.cc +++ b/media/mojo/clients/mojo_audio_encoder_unittest.cc
@@ -106,7 +106,8 @@ return (ticks - base::TimeTicks()).InMilliseconds(); } - AudioEncoder::StatusCB ValidatingStatusCB(base::Location loc = FROM_HERE) { + AudioEncoder::EncoderStatusCB ValidatingStatusCB( + base::Location loc = FROM_HERE) { struct CallEnforcer { bool called = false; std::string location; @@ -117,7 +118,7 @@ auto enforcer = std::make_unique<CallEnforcer>(); enforcer->location = loc.ToString(); return base::BindLambdaForTesting( - [this, enforcer{std::move(enforcer)}](Status s) { + [this, enforcer{std::move(enforcer)}](EncoderStatus s) { EXPECT_TRUE(callback_runner_->RunsTasksInCurrentSequence()); EXPECT_TRUE(s.is_ok()) << " Callback created: " << enforcer->location << " Error: " << s.message(); @@ -149,16 +150,16 @@ EXPECT_CALL(*mock_audio_encoder_, Initialize(_, _, _)) .WillOnce(Invoke([this](const AudioEncoder::Options& options, AudioEncoder::OutputCB output_cb, - AudioEncoder::StatusCB done_cb) { + AudioEncoder::EncoderStatusCB done_cb) { EXPECT_TRUE(service_task_runner_->RunsTasksInCurrentSequence()); - std::move(done_cb).Run(OkStatus()); + std::move(done_cb).Run(EncoderStatus::Codes::kOk); })); AudioEncoder::OutputCB output_cb = base::BindLambdaForTesting( [&](EncodedAudioBuffer output, absl::optional<AudioEncoder::CodecDescription>) { FAIL(); }); - auto done_cb = base::BindLambdaForTesting([&, this](Status s) { + auto done_cb = base::BindLambdaForTesting([&, this](EncoderStatus s) { EXPECT_TRUE(callback_runner_->RunsTasksInCurrentSequence()); EXPECT_TRUE(s.is_ok()); run_loop.QuitWhenIdle(); @@ -175,17 +176,18 @@ EXPECT_CALL(*mock_audio_encoder_, Initialize(_, _, _)) .WillOnce(Invoke([](const AudioEncoder::Options& options, AudioEncoder::OutputCB output_cb, - AudioEncoder::StatusCB done_cb) { - std::move(done_cb).Run(StatusCode::kEncoderInitializationError); + AudioEncoder::EncoderStatusCB done_cb) { + std::move(done_cb).Run( + EncoderStatus::Codes::kEncoderInitializationError); })); AudioEncoder::OutputCB output_cb = base::BindLambdaForTesting( [&](EncodedAudioBuffer output, absl::optional<AudioEncoder::CodecDescription>) { FAIL(); }); - auto done_cb = base::BindLambdaForTesting([&, this](Status s) { + auto done_cb = base::BindLambdaForTesting([&, this](EncoderStatus s) { EXPECT_TRUE(callback_runner_->RunsTasksInCurrentSequence()); - EXPECT_EQ(s.code(), StatusCode::kEncoderInitializationError); + EXPECT_EQ(s.code(), EncoderStatus::Codes::kEncoderInitializationError); run_loop.QuitWhenIdle(); }); @@ -201,17 +203,17 @@ EXPECT_CALL(*mock_audio_encoder_, Initialize(_, _, _)) .WillRepeatedly(Invoke([](const AudioEncoder::Options& options, AudioEncoder::OutputCB output_cb, - AudioEncoder::StatusCB done_cb) { - std::move(done_cb).Run(OkStatus()); + AudioEncoder::EncoderStatusCB done_cb) { + std::move(done_cb).Run(EncoderStatus::Codes::kOk); })); - auto expect_ok = base::BindLambdaForTesting([&](Status s) { + auto expect_ok = base::BindLambdaForTesting([&](EncoderStatus s) { EXPECT_TRUE(s.is_ok()); good_init_run_loop.QuitWhenIdle(); }); - auto expect_error = base::BindLambdaForTesting([&](Status s) { - EXPECT_EQ(s.code(), StatusCode::kEncoderInitializeTwice); + auto expect_error = base::BindLambdaForTesting([&](EncoderStatus s) { + EXPECT_EQ(s.code(), EncoderStatus::Codes::kEncoderInitializeTwice); failed_initi_run_loop.QuitWhenIdle(); }); @@ -233,18 +235,18 @@ EXPECT_CALL(*mock_audio_encoder_, Initialize(_, _, _)) .WillOnce(Invoke([&, this](const AudioEncoder::Options& options, AudioEncoder::OutputCB output_cb, - AudioEncoder::StatusCB done_cb) { + AudioEncoder::EncoderStatusCB done_cb) { EXPECT_TRUE(service_task_runner_->RunsTasksInCurrentSequence()); service_output_cb = std::move(output_cb); - std::move(done_cb).Run(OkStatus()); + std::move(done_cb).Run(EncoderStatus::Codes::kOk); })); EXPECT_CALL(*mock_audio_encoder_, Encode(_, _, _)) .WillRepeatedly(Invoke([&, this](std::unique_ptr<AudioBus> audio_bus, base::TimeTicks capture_time, - AudioEncoder::StatusCB done_cb) { + AudioEncoder::EncoderStatusCB done_cb) { EXPECT_TRUE(service_task_runner_->RunsTasksInCurrentSequence()); - std::move(done_cb).Run(OkStatus()); + std::move(done_cb).Run(EncoderStatus::Codes::kOk); int64_t input_number = ToMilliseconds(capture_time); EXPECT_LE(input_number, input_count); @@ -313,17 +315,17 @@ EXPECT_CALL(*mock_audio_encoder_, Initialize(_, _, _)) .WillOnce(Invoke([&](const AudioEncoder::Options& options, AudioEncoder::OutputCB output_cb, - AudioEncoder::StatusCB done_cb) { + AudioEncoder::EncoderStatusCB done_cb) { service_output_cb = std::move(output_cb); - std::move(done_cb).Run(OkStatus()); + std::move(done_cb).Run(EncoderStatus::Codes::kOk); })); EXPECT_CALL(*mock_audio_encoder_, Encode(_, _, _)) .WillRepeatedly(Invoke([&, this](std::unique_ptr<AudioBus> audio_bus, base::TimeTicks capture_time, - AudioEncoder::StatusCB done_cb) { + AudioEncoder::EncoderStatusCB done_cb) { EXPECT_TRUE(service_task_runner_->RunsTasksInCurrentSequence()); - std::move(done_cb).Run(OkStatus()); + std::move(done_cb).Run(EncoderStatus::Codes::kOk); AudioParameters params(AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_DISCRETE, 8000, 1); @@ -361,16 +363,16 @@ EXPECT_CALL(*mock_audio_encoder_, Initialize(_, _, _)) .WillOnce(Invoke([&](const AudioEncoder::Options& options, AudioEncoder::OutputCB output_cb, - AudioEncoder::StatusCB done_cb) { + AudioEncoder::EncoderStatusCB done_cb) { service_output_cb = std::move(output_cb); - std::move(done_cb).Run(OkStatus()); + std::move(done_cb).Run(EncoderStatus::Codes::kOk); })); EXPECT_CALL(*mock_audio_encoder_, Encode(_, _, _)) .WillRepeatedly(Invoke([&](std::unique_ptr<AudioBus> audio_bus, base::TimeTicks capture_time, - AudioEncoder::StatusCB done_cb) { - std::move(done_cb).Run(OkStatus()); + AudioEncoder::EncoderStatusCB done_cb) { + std::move(done_cb).Run(EncoderStatus::Codes::kOk); AudioParameters params(AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_DISCRETE, options.sample_rate, @@ -381,9 +383,9 @@ })); EXPECT_CALL(*mock_audio_encoder_, Flush(_)) - .WillRepeatedly(Invoke([&, this](AudioEncoder::StatusCB done_cb) { + .WillRepeatedly(Invoke([&, this](AudioEncoder::EncoderStatusCB done_cb) { EXPECT_TRUE(service_task_runner_->RunsTasksInCurrentSequence()); - std::move(done_cb).Run(OkStatus()); + std::move(done_cb).Run(EncoderStatus::Codes::kOk); })); AudioEncoder::OutputCB output_cb = base::BindLambdaForTesting( @@ -400,7 +402,7 @@ ValidatingStatusCB()); } - AudioEncoder::StatusCB flush_cb = base::BindLambdaForTesting([&](Status s) { + auto flush_cb = base::BindLambdaForTesting([&](EncoderStatus s) { EXPECT_TRUE(callback_runner_->RunsTasksInCurrentSequence()); EXPECT_TRUE(s.is_ok()); EXPECT_EQ(output_count, input_count); @@ -416,24 +418,24 @@ TEST_F(MojoAudioEncoderTest, MojoErrorCallsAllDoneCallbacks) { base::RunLoop run_loop; AudioEncoder::Options options = MakeOptions(); - std::vector<AudioEncoder::StatusCB> done_callbacks; + std::vector<AudioEncoder::EncoderStatusCB> done_callbacks; const int input_count = 5; int error_count = 0; EXPECT_CALL(*mock_audio_encoder_, Initialize(_, _, _)) .WillOnce(Invoke([&](const AudioEncoder::Options& options, AudioEncoder::OutputCB output_cb, - AudioEncoder::StatusCB done_cb) { - std::move(done_cb).Run(OkStatus()); + AudioEncoder::EncoderStatusCB done_cb) { + std::move(done_cb).Run(EncoderStatus::Codes::kOk); })); EXPECT_CALL(*mock_audio_encoder_, Encode(_, _, _)) .WillRepeatedly(Invoke([&](std::unique_ptr<AudioBus> audio_bus, base::TimeTicks capture_time, - AudioEncoder::StatusCB done_cb) { + AudioEncoder::EncoderStatusCB done_cb) { done_callbacks.push_back(std::move(done_cb)); })); EXPECT_CALL(*mock_audio_encoder_, Flush(_)) - .WillOnce(Invoke([&](AudioEncoder::StatusCB done_cb) { + .WillOnce(Invoke([&](AudioEncoder::EncoderStatusCB done_cb) { done_callbacks.push_back(std::move(done_cb)); service_task_runner_->DeleteSoon(FROM_HERE, std::move(receiver_)); })); @@ -443,16 +445,16 @@ for (int i = 0; i < input_count; i++) { auto ts = FromMilliseconds(i); - auto done_cb = base::BindLambdaForTesting([&](Status s) { - EXPECT_EQ(s.code(), StatusCode::kEncoderMojoConnectionError); + auto done_cb = base::BindLambdaForTesting([&](EncoderStatus s) { + EXPECT_EQ(s.code(), EncoderStatus::Codes::kEncoderMojoConnectionError); error_count++; }); mojo_audio_encoder_->Encode( MakeInput(i, options.channels, options.sample_rate), ts, std::move(done_cb)); } - AudioEncoder::StatusCB flush_cb = base::BindLambdaForTesting([&](Status s) { - EXPECT_EQ(s.code(), StatusCode::kEncoderMojoConnectionError); + auto flush_cb = base::BindLambdaForTesting([&](EncoderStatus s) { + EXPECT_EQ(s.code(), EncoderStatus::Codes::kEncoderMojoConnectionError); run_loop.QuitWhenIdle(); });
diff --git a/media/mojo/mojom/BUILD.gn b/media/mojo/mojom/BUILD.gn index fd5ec68..16e65798 100644 --- a/media/mojo/mojom/BUILD.gn +++ b/media/mojo/mojom/BUILD.gn
@@ -364,6 +364,10 @@ mojom = "media.mojom.Status" cpp = "::media::Status" }, + { + mojom = "media.mojom.EncoderStatus" + cpp = "::media::EncoderStatus" + }, ] traits_headers = [ "status_mojom_traits.h" ] traits_sources = [ "status_mojom_traits.cc" ]
diff --git a/media/mojo/mojom/audio_encoder.mojom b/media/mojo/mojom/audio_encoder.mojom index 6dd927b..1d131ea 100644 --- a/media/mojo/mojom/audio_encoder.mojom +++ b/media/mojo/mojom/audio_encoder.mojom
@@ -51,17 +51,17 @@ // This must be called only once before any other Encode() and Flush(). // Returns errors as |status|. Initialize(pending_associated_remote<AudioEncoderClient> client, - AudioEncoderConfig config) => (Status status); + AudioEncoderConfig config) => (EncoderStatus status); // Requests contents of audio |buffer| to be encoded, encoded results // produced via AudioEncoderClient.EncodedBufferReady(). // Returns errors as |status|. - Encode(AudioBuffer buffer) => (Status status); + Encode(AudioBuffer buffer) => (EncoderStatus status); // Requests all outputs for already encoded frames to be // produced via AudioEncoderClient.EncodedBufferReady(). // Returns errors as |status|. - Flush() => (Status status); + Flush() => (EncoderStatus status); }; // A complimentary interface for AudioEncoder, bound
diff --git a/media/mojo/mojom/media_types.mojom b/media/mojo/mojom/media_types.mojom index 6504313..4020d63 100644 --- a/media/mojo/mojom/media_types.mojom +++ b/media/mojo/mojom/media_types.mojom
@@ -502,6 +502,10 @@ StatusData? internal; }; +struct EncoderStatus { + StatusData? internal; +}; + // Types of media stream, categorised by the media stream's source. // The enum values are emitted to metrics. Do not reorder. enum MediaStreamType {
diff --git a/media/mojo/mojom/status_mojom_traits.h b/media/mojo/mojom/status_mojom_traits.h index 5a742d5..116cf34 100644 --- a/media/mojo/mojom/status_mojom_traits.h +++ b/media/mojo/mojom/status_mojom_traits.h
@@ -7,6 +7,7 @@ #include "base/containers/span.h" #include "base/values.h" +#include "media/base/encoder_status.h" #include "media/base/ipc/media_param_traits.h" #include "media/base/status.h" #include "media/mojo/mojom/media_types.mojom.h"
diff --git a/media/mojo/services/mojo_audio_encoder_service.cc b/media/mojo/services/mojo_audio_encoder_service.cc index c85b428..f110c86 100644 --- a/media/mojo/services/mojo_audio_encoder_service.cc +++ b/media/mojo/services/mojo_audio_encoder_service.cc
@@ -28,7 +28,7 @@ const AudioEncoderConfig& config, InitializeCallback callback) { if (client_.is_bound()) { - std::move(callback).Run(StatusCode::kEncoderInitializeTwice); + std::move(callback).Run(EncoderStatus::Codes::kEncoderInitializeTwice); return; } @@ -43,7 +43,8 @@ void MojoAudioEncoderService::Encode(mojom::AudioBufferPtr buffer, EncodeCallback callback) { if (!client_.is_bound() || !client_.is_connected()) { - std::move(callback).Run(StatusCode::kEncoderInitializeNeverCompleted); + std::move(callback).Run( + EncoderStatus::Codes::kEncoderInitializeNeverCompleted); return; } @@ -57,7 +58,8 @@ void MojoAudioEncoderService::Flush(FlushCallback callback) { if (!client_.is_bound() || !client_.is_connected()) { - std::move(callback).Run(StatusCode::kEncoderInitializeNeverCompleted); + std::move(callback).Run( + EncoderStatus::Codes::kEncoderInitializeNeverCompleted); return; } @@ -65,7 +67,8 @@ std::move(callback))); } -void MojoAudioEncoderService::OnDone(MojoDoneCallback callback, Status error) { +void MojoAudioEncoderService::OnDone(MojoDoneCallback callback, + EncoderStatus error) { std::move(callback).Run(error); }
diff --git a/media/mojo/services/mojo_audio_encoder_service.h b/media/mojo/services/mojo_audio_encoder_service.h index 31ab1243..b1d31b47 100644 --- a/media/mojo/services/mojo_audio_encoder_service.h +++ b/media/mojo/services/mojo_audio_encoder_service.h
@@ -42,8 +42,9 @@ void Flush(FlushCallback callback) final; private: - using MojoDoneCallback = base::OnceCallback<void(const media::Status&)>; - void OnDone(MojoDoneCallback callback, Status error); + using MojoDoneCallback = + base::OnceCallback<void(const media::EncoderStatus&)>; + void OnDone(MojoDoneCallback callback, EncoderStatus error); void OnOutput(EncodedAudioBuffer output, absl::optional<media::AudioEncoder::CodecDescription> desc);
diff --git a/media/video/av1_video_encoder.cc b/media/video/av1_video_encoder.cc index c1a669f..6e4c619 100644 --- a/media/video/av1_video_encoder.cc +++ b/media/video/av1_video_encoder.cc
@@ -54,14 +54,15 @@ return desired_threads; } -Status SetUpAomConfig(const VideoEncoder::Options& opts, - aom_codec_enc_cfg_t* config) { +EncoderStatus SetUpAomConfig(const VideoEncoder::Options& opts, + aom_codec_enc_cfg_t* config) { if (opts.frame_size.width() <= 0 || opts.frame_size.height() <= 0) - return Status(StatusCode::kEncoderUnsupportedConfig, - "Negative width or height values."); + return EncoderStatus(EncoderStatus::Codes::kEncoderUnsupportedConfig, + "Negative width or height values."); if (!opts.frame_size.GetCheckedArea().IsValid()) - return Status(StatusCode::kEncoderUnsupportedConfig, "Frame is too large."); + return EncoderStatus(EncoderStatus::Codes::kEncoderUnsupportedConfig, + "Frame is too large."); config->g_profile = 0; // main config->g_input_bit_depth = 8; @@ -114,10 +115,10 @@ config->g_h = opts.frame_size.height(); if (opts.scalability_mode.has_value()) { - return Status(StatusCode::kEncoderUnsupportedConfig, - "Unsupported number of temporal layers."); + return EncoderStatus(EncoderStatus::Codes::kEncoderUnsupportedConfig, + "Unsupported number of temporal layers."); } - return OkStatus(); + return EncoderStatus::Codes::kOk; } } // namespace @@ -127,17 +128,17 @@ void Av1VideoEncoder::Initialize(VideoCodecProfile profile, const Options& options, OutputCB output_cb, - StatusCB done_cb) { + EncoderStatusCB done_cb) { done_cb = BindToCurrentLoop(std::move(done_cb)); if (codec_) { - std::move(done_cb).Run(StatusCode::kEncoderInitializeTwice); + std::move(done_cb).Run(EncoderStatus::Codes::kEncoderInitializeTwice); return; } profile_ = profile; if (profile < AV1PROFILE_MIN || profile > AV1PROFILE_MAX) { - auto status = Status(StatusCode::kEncoderUnsupportedProfile) - .WithData("profile", profile); - std::move(done_cb).Run(status); + std::move(done_cb).Run( + EncoderStatus(EncoderStatus::Codes::kEncoderUnsupportedProfile) + .WithData("profile", profile)); return; } @@ -146,18 +147,15 @@ auto error = aom_codec_enc_config_default(aom_codec_av1_cx(), &config_, AOM_USAGE_REALTIME); if (error != AOM_CODEC_OK) { - auto status = Status(StatusCode::kEncoderInitializationError, - "Failed to get default AOM config.") - .WithData("error_code", error); - std::move(done_cb).Run(status); + std::move(done_cb).Run( + EncoderStatus(EncoderStatus::Codes::kEncoderInitializationError, + "Failed to get default AOM config.") + .WithData("error_code", error)); return; } - Status status = SetUpAomConfig(options, &config_); - if (!status.is_ok()) { - std::move(done_cb).Run(status); - return; - } + POST_STATUS_AND_RETURN_ON_FAILURE(SetUpAomConfig(options, &config_), + std::move(done_cb), ); // Initialize an encoder instance. aom_codec_unique_ptr codec(new aom_codec_ctx_t, FreeCodecCtx); @@ -165,26 +163,26 @@ aom_codec_flags_t flags = 0; error = aom_codec_enc_init(codec.get(), aom_codec_av1_cx(), &config_, flags); if (error != AOM_CODEC_OK) { - status = Status(StatusCode::kEncoderInitializationError, - "aom_codec_enc_init() failed.") - .WithData("error_code", error) - .WithData("error_message", aom_codec_err_to_string(error)); - std::move(done_cb).Run(status); + std::move(done_cb).Run( + EncoderStatus(EncoderStatus::Codes::kEncoderInitializationError, + "aom_codec_enc_init() failed.") + .WithData("error_code", error) + .WithData("error_message", aom_codec_err_to_string(error))); return; } DCHECK_NE(codec->name, nullptr); -#define CALL_AOM_CONTROL(key, value) \ - do { \ - error = aom_codec_control(codec.get(), (key), (value)); \ - if (error != AOM_CODEC_OK) { \ - status = Status(StatusCode::kEncoderInitializationError, \ - "Setting " #key " failed.") \ - .WithData("error_code", error) \ - .WithData("error_message", aom_codec_err_to_string(error)); \ - std::move(done_cb).Run(status); \ - return; \ - } \ +#define CALL_AOM_CONTROL(key, value) \ + do { \ + error = aom_codec_control(codec.get(), (key), (value)); \ + if (error != AOM_CODEC_OK) { \ + std::move(done_cb).Run( \ + EncoderStatus(EncoderStatus::Codes::kEncoderInitializationError, \ + "Setting " #key " failed.") \ + .WithData("error_code", error) \ + .WithData("error_message", aom_codec_err_to_string(error))); \ + return; \ + } \ } while (false) CALL_AOM_CONTROL(AV1E_SET_ROW_MT, 1); @@ -227,21 +225,23 @@ originally_configured_size_ = options.frame_size; output_cb_ = BindToCurrentLoop(std::move(output_cb)); codec_ = std::move(codec); - std::move(done_cb).Run(OkStatus()); + std::move(done_cb).Run(EncoderStatus::Codes::kOk); } void Av1VideoEncoder::Encode(scoped_refptr<VideoFrame> frame, bool key_frame, - StatusCB done_cb) { + EncoderStatusCB done_cb) { done_cb = BindToCurrentLoop(std::move(done_cb)); if (!codec_) { - std::move(done_cb).Run(StatusCode::kEncoderInitializeNeverCompleted); + std::move(done_cb).Run( + EncoderStatus::Codes::kEncoderInitializeNeverCompleted); return; } if (!frame) { - std::move(done_cb).Run(Status(StatusCode::kEncoderFailedEncode, - "No frame provided for encoding.")); + std::move(done_cb).Run( + EncoderStatus(EncoderStatus::Codes::kEncoderFailedEncode, + "No frame provided for encoding.")); return; } @@ -253,12 +253,12 @@ frame->format() == PIXEL_FORMAT_ARGB; if ((!frame->IsMappable() && !frame->HasGpuMemoryBuffer()) || !supported_format) { - Status status = - Status(StatusCode::kEncoderFailedEncode, "Unexpected frame format.") + std::move(done_cb).Run( + EncoderStatus(EncoderStatus::Codes::kEncoderFailedEncode, + "Unexpected frame format.") .WithData("IsMappable", frame->IsMappable()) .WithData("HasGpuMemoryBuffer", frame->HasGpuMemoryBuffer()) - .WithData("format", frame->format()); - std::move(done_cb).Run(std::move(status)); + .WithData("format", frame->format())); return; } @@ -266,8 +266,8 @@ frame = ConvertToMemoryMappedFrame(frame); if (!frame) { std::move(done_cb).Run( - Status(StatusCode::kEncoderFailedEncode, - "Convert GMB frame to MemoryMappedFrame failed.")); + EncoderStatus(EncoderStatus::Codes::kEncoderFailedEncode, + "Convert GMB frame to MemoryMappedFrame failed.")); return; } } @@ -278,16 +278,20 @@ is_yuv ? frame->format() : PIXEL_FORMAT_I420, options_.frame_size, gfx::Rect(options_.frame_size), options_.frame_size, frame->timestamp()); - Status status; + if (resized_frame) { - status = ConvertAndScaleFrame(*frame, *resized_frame, resize_buf_); + Status conv_status = + ConvertAndScaleFrame(*frame, *resized_frame, resize_buf_); + if (!conv_status.is_ok()) { + std::move(done_cb).Run( + EncoderStatus(EncoderStatus::Codes::kEncoderFailedEncode) + .AddCause(std::move(conv_status))); + return; + } } else { - status = Status(StatusCode::kEncoderFailedEncode, - "Can't allocate a resized frame."); - } - if (!status.is_ok()) { - std::move(done_cb).Run(std::move(status)); - return; + std::move(done_cb).Run( + EncoderStatus(EncoderStatus::Codes::kEncoderFailedEncode, + "Can't allocate a resized frame.")); } frame = std::move(resized_frame); } @@ -324,24 +328,26 @@ base::StringPrintf("AOM encoding error: %s (%d)", aom_codec_error_detail(codec_.get()), codec_->err); DLOG(ERROR) << msg; - std::move(done_cb).Run(Status(StatusCode::kEncoderFailedEncode, msg)); + std::move(done_cb).Run( + EncoderStatus(EncoderStatus::Codes::kEncoderFailedEncode, msg)); return; } DrainOutputs(frame->timestamp(), frame->ColorSpace()); - std::move(done_cb).Run(OkStatus()); + std::move(done_cb).Run(EncoderStatus::Codes::kOk); } void Av1VideoEncoder::ChangeOptions(const Options& options, OutputCB output_cb, - StatusCB done_cb) { + EncoderStatusCB done_cb) { done_cb = BindToCurrentLoop(std::move(done_cb)); if (!codec_) { - std::move(done_cb).Run(StatusCode::kEncoderInitializeNeverCompleted); + std::move(done_cb).Run( + EncoderStatus::Codes::kEncoderInitializeNeverCompleted); return; } // TODO(crbug.com/1208280) Try to actually adjust setting instead of // immediately dismissing configuration change. - std::move(done_cb).Run(StatusCode::kEncoderUnsupportedConfig); + std::move(done_cb).Run(EncoderStatus::Codes::kEncoderUnsupportedConfig); } base::TimeDelta Av1VideoEncoder::GetFrameDuration(const VideoFrame& frame) { @@ -382,10 +388,11 @@ Av1VideoEncoder::~Av1VideoEncoder() = default; -void Av1VideoEncoder::Flush(StatusCB done_cb) { +void Av1VideoEncoder::Flush(EncoderStatusCB done_cb) { done_cb = BindToCurrentLoop(std::move(done_cb)); if (!codec_) { - std::move(done_cb).Run(StatusCode::kEncoderInitializeNeverCompleted); + std::move(done_cb).Run( + EncoderStatus::Codes::kEncoderInitializeNeverCompleted); return; } @@ -396,11 +403,12 @@ base::StringPrintf("AOM encoding error: %s (%d)", aom_codec_error_detail(codec_.get()), codec_->err); DLOG(ERROR) << msg; - std::move(done_cb).Run(Status(StatusCode::kEncoderFailedEncode, msg)); + std::move(done_cb).Run( + EncoderStatus(EncoderStatus::Codes::kEncoderFailedEncode, msg)); return; } DrainOutputs(base::TimeDelta(), gfx::ColorSpace()); - std::move(done_cb).Run(OkStatus()); + std::move(done_cb).Run(EncoderStatus::Codes::kOk); } } // namespace media
diff --git a/media/video/av1_video_encoder.h b/media/video/av1_video_encoder.h index 3474ecc..7a10b01 100644 --- a/media/video/av1_video_encoder.h +++ b/media/video/av1_video_encoder.h
@@ -27,14 +27,14 @@ void Initialize(VideoCodecProfile profile, const Options& options, OutputCB output_cb, - StatusCB done_cb) override; + EncoderStatusCB done_cb) override; void Encode(scoped_refptr<VideoFrame> frame, bool key_frame, - StatusCB done_cb) override; + EncoderStatusCB done_cb) override; void ChangeOptions(const Options& options, OutputCB output_cb, - StatusCB done_cb) override; - void Flush(StatusCB done_cb) override; + EncoderStatusCB done_cb) override; + void Flush(EncoderStatusCB done_cb) override; private: base::TimeDelta GetFrameDuration(const VideoFrame& frame);
diff --git a/media/video/openh264_video_encoder.cc b/media/video/openh264_video_encoder.cc index dbba576..afb348e 100644 --- a/media/video/openh264_video_encoder.cc +++ b/media/video/openh264_video_encoder.cc
@@ -21,8 +21,8 @@ namespace { -Status SetUpOpenH264Params(const VideoEncoder::Options& options, - SEncParamExt* params) { +void SetUpOpenH264Params(const VideoEncoder::Options& options, + SEncParamExt* params) { params->bEnableFrameSkip = false; params->iPaddingFlag = 0; params->iComplexityMode = MEDIUM_COMPLEXITY; @@ -70,8 +70,6 @@ params->sSpatialLayers[0].iVideoHeight = params->iPicHeight; params->sSpatialLayers[0].iVideoWidth = params->iPicWidth; params->sSpatialLayers[0].sSliceArgument.uiSliceMode = SM_SINGLE_SLICE; - - return Status(); } } // namespace @@ -100,63 +98,57 @@ void OpenH264VideoEncoder::Initialize(VideoCodecProfile profile, const Options& options, OutputCB output_cb, - StatusCB done_cb) { + EncoderStatusCB done_cb) { done_cb = BindToCurrentLoop(std::move(done_cb)); if (codec_) { - std::move(done_cb).Run(StatusCode::kEncoderInitializeTwice); + std::move(done_cb).Run(EncoderStatus::Codes::kEncoderInitializeTwice); return; } profile_ = profile; if (profile != H264PROFILE_BASELINE) { - auto status = - Status(StatusCode::kEncoderInitializationError, "Unsupported profile"); - std::move(done_cb).Run(status); + std::move(done_cb).Run( + EncoderStatus(EncoderStatus::Codes::kEncoderInitializationError, + "Unsupported profile")); return; } ISVCEncoder* raw_codec = nullptr; if (WelsCreateSVCEncoder(&raw_codec) != 0) { - auto status = Status(StatusCode::kEncoderInitializationError, - "Failed to create OpenH264 encoder."); - std::move(done_cb).Run(status); + std::move(done_cb).Run( + EncoderStatus(EncoderStatus::Codes::kEncoderInitializationError, + "Failed to create OpenH264 encoder.")); return; } svc_encoder_unique_ptr codec(raw_codec, ISVCEncoderDeleter()); raw_codec = nullptr; - Status status; - SEncParamExt params = {}; if (int err = codec->GetDefaultParams(¶ms)) { - status = Status(StatusCode::kEncoderInitializationError, - "Failed to get default params.") - .WithData("error", err); - std::move(done_cb).Run(status); + std::move(done_cb).Run( + EncoderStatus(EncoderStatus::Codes::kEncoderInitializationError, + "Failed to get default params.") + .WithData("error", err)); return; } - status = SetUpOpenH264Params(options, ¶ms); - if (!status.is_ok()) { - std::move(done_cb).Run(status); - return; - } + SetUpOpenH264Params(options, ¶ms); if (int err = codec->InitializeExt(¶ms)) { - status = Status(StatusCode::kEncoderInitializationError, - "Failed to initialize OpenH264 encoder.") - .WithData("error", err); - std::move(done_cb).Run(status); + std::move(done_cb).Run( + EncoderStatus(EncoderStatus::Codes::kEncoderInitializationError, + "Failed to initialize OpenH264 encoder.") + .WithData("error", err)); return; } codec.get_deleter().MarkInitialized(); int video_format = EVideoFormatType::videoFormatI420; if (int err = codec->SetOption(ENCODER_OPTION_DATAFORMAT, &video_format)) { - status = Status(StatusCode::kEncoderInitializationError, - "Failed to set data format for OpenH264 encoder") - .WithData("error", err); - std::move(done_cb).Run(status); + std::move(done_cb).Run( + EncoderStatus(EncoderStatus::Codes::kEncoderInitializationError, + "Failed to set data format for OpenH264 encoder") + .WithData("error", err)); return; } @@ -166,12 +158,12 @@ options_ = options; output_cb_ = BindToCurrentLoop(std::move(output_cb)); codec_ = std::move(codec); - std::move(done_cb).Run(OkStatus()); + std::move(done_cb).Run(EncoderStatus::Codes::kOk); } -Status OpenH264VideoEncoder::DrainOutputs(const SFrameBSInfo& frame_info, - base::TimeDelta timestamp, - gfx::ColorSpace color_space) { +EncoderStatus OpenH264VideoEncoder::DrainOutputs(const SFrameBSInfo& frame_info, + base::TimeDelta timestamp, + gfx::ColorSpace color_space) { VideoEncoderOutput result; result.key_frame = (frame_info.eFrameType == videoFrameTypeIDR); result.timestamp = timestamp; @@ -197,13 +189,13 @@ if (result.temporal_id == -1) result.temporal_id = layer_info.uiTemporalId; else if (result.temporal_id != layer_info.uiTemporalId) - return Status(StatusCode::kEncoderFailedEncode); + return EncoderStatus::Codes::kEncoderFailedEncode; size_t layer_len = 0; for (int nal_idx = 0; nal_idx < layer_info.iNalCount; ++nal_idx) layer_len += layer_info.pNalLengthInByte[nal_idx]; if (written_size + layer_len > total_chunk_size) - return Status(StatusCode::kEncoderFailedEncode); + return EncoderStatus::Codes::kEncoderFailedEncode; memcpy(gather_buffer + written_size, layer_info.pBsBuf, layer_len); written_size += layer_len; @@ -214,7 +206,7 @@ result.size = total_chunk_size; output_cb_.Run(std::move(result), absl::optional<CodecDescription>()); - return OkStatus(); + return EncoderStatus::Codes::kOk; } size_t converted_output_size = 0; @@ -225,7 +217,8 @@ &converted_output_size); if (!status.is_ok()) - return status; + return EncoderStatus(EncoderStatus::Codes::kEncoderFailedEncode) + .AddCause(std::move(status)); result.size = converted_output_size; @@ -234,28 +227,29 @@ const auto& config = h264_converter_->GetCurrentConfig(); desc = CodecDescription(); if (!config.Serialize(desc.value())) { - return Status(StatusCode::kEncoderFailedEncode, - "Failed to serialize AVC decoder config"); + return EncoderStatus(EncoderStatus::Codes::kEncoderFailedEncode, + "Failed to serialize AVC decoder config"); } } output_cb_.Run(std::move(result), std::move(desc)); - return OkStatus(); + return EncoderStatus::Codes::kOk; } void OpenH264VideoEncoder::Encode(scoped_refptr<VideoFrame> frame, bool key_frame, - StatusCB done_cb) { - Status status; + EncoderStatusCB done_cb) { done_cb = BindToCurrentLoop(std::move(done_cb)); if (!codec_) { - std::move(done_cb).Run(StatusCode::kEncoderInitializeNeverCompleted); + std::move(done_cb).Run( + EncoderStatus::Codes::kEncoderInitializeNeverCompleted); return; } if (!frame) { - std::move(done_cb).Run(Status(StatusCode::kEncoderFailedEncode, - "No frame provided for encoding.")); + std::move(done_cb).Run( + EncoderStatus(EncoderStatus::Codes::kEncoderFailedEncode, + "No frame provided for encoding.")); return; } const bool supported_format = frame->format() == PIXEL_FORMAT_NV12 || @@ -266,11 +260,11 @@ frame->format() == PIXEL_FORMAT_ARGB; if ((!frame->IsMappable() && !frame->HasGpuMemoryBuffer()) || !supported_format) { - status = - Status(StatusCode::kEncoderFailedEncode, "Unexpected frame format.") + std::move(done_cb).Run( + EncoderStatus(EncoderStatus::Codes::kEncoderFailedEncode, + "Unexpected frame format.") .WithData("IsMappable", frame->IsMappable()) - .WithData("format", frame->format()); - std::move(done_cb).Run(std::move(status)); + .WithData("format", frame->format())); return; } @@ -278,8 +272,8 @@ frame = ConvertToMemoryMappedFrame(frame); if (!frame) { std::move(done_cb).Run( - Status(StatusCode::kEncoderFailedEncode, - "Convert GMB frame to MemoryMappedFrame failed.")); + EncoderStatus(EncoderStatus::Codes::kEncoderFailedEncode, + "Convert GMB frame to MemoryMappedFrame failed.")); return; } } @@ -290,14 +284,17 @@ auto i420_frame = frame_pool_.CreateFrame( PIXEL_FORMAT_I420, options_.frame_size, gfx::Rect(options_.frame_size), options_.frame_size, frame->timestamp()); - if (i420_frame) { - status = ConvertAndScaleFrame(*frame, *i420_frame, conversion_buffer_); - } else { - status = Status(StatusCode::kEncoderFailedEncode, - "Can't allocate an I420 frame."); + if (!i420_frame) { + std::move(done_cb).Run( + EncoderStatus(EncoderStatus::Codes::kEncoderFailedEncode, + "Can't allocate an I420 frame.")); + return; } + auto status = ConvertAndScaleFrame(*frame, *i420_frame, conversion_buffer_); if (!status.is_ok()) { - std::move(done_cb).Run(std::move(status)); + std::move(done_cb).Run( + EncoderStatus(EncoderStatus::Codes::kEncoderFailedEncode) + .AddCause(std::move(status))); return; } frame = std::move(i420_frame); @@ -323,7 +320,8 @@ if (key_frame) { if (int err = codec_->ForceIntraFrame(true)) { std::move(done_cb).Run( - Status(StatusCode::kEncoderFailedEncode, "Can't make keyframe.") + EncoderStatus(EncoderStatus::Codes::kEncoderFailedEncode, + "Can't make keyframe.") .WithData("error", err)); return; } @@ -332,47 +330,44 @@ SFrameBSInfo frame_info = {}; TRACE_EVENT0("media", "OpenH264::EncodeFrame"); if (int err = codec_->EncodeFrame(&picture, &frame_info)) { - std::move(done_cb).Run(Status(StatusCode::kEncoderFailedEncode, - "Failed to encode using OpenH264.") - .WithData("error", err)); + std::move(done_cb).Run( + EncoderStatus(EncoderStatus::Codes::kEncoderFailedEncode, + "Failed to encode using OpenH264.") + .WithData("error", err)); return; } - status = DrainOutputs(frame_info, frame->timestamp(), frame->ColorSpace()); - std::move(done_cb).Run(std::move(status)); + std::move(done_cb).Run( + DrainOutputs(frame_info, frame->timestamp(), frame->ColorSpace())); } void OpenH264VideoEncoder::ChangeOptions(const Options& options, OutputCB output_cb, - StatusCB done_cb) { + EncoderStatusCB done_cb) { done_cb = BindToCurrentLoop(std::move(done_cb)); if (!codec_) { - std::move(done_cb).Run(StatusCode::kEncoderInitializeNeverCompleted); + std::move(done_cb).Run( + EncoderStatus::Codes::kEncoderInitializeNeverCompleted); return; } - Status status; SEncParamExt params = {}; if (int err = codec_->GetDefaultParams(¶ms)) { - status = Status(StatusCode::kEncoderInitializationError, - "Failed to get default params.") - .WithData("error", err); - std::move(done_cb).Run(status); + std::move(done_cb).Run( + EncoderStatus(EncoderStatus::Codes::kEncoderInitializationError, + "Failed to get default params.") + .WithData("error", err)); return; } - status = SetUpOpenH264Params(options, ¶ms); - if (!status.is_ok()) { - std::move(done_cb).Run(status); - return; - } + SetUpOpenH264Params(options, ¶ms); if (int err = codec_->SetOption(ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, ¶ms)) { - status = Status(StatusCode::kEncoderInitializationError, - "OpenH264 encoder failed to set new SEncParamExt.") - .WithData("error", err); - std::move(done_cb).Run(status); + std::move(done_cb).Run( + EncoderStatus(EncoderStatus::Codes::kEncoderInitializationError, + "OpenH264 encoder failed to set new SEncParamExt.") + .WithData("error", err)); return; } @@ -385,18 +380,19 @@ options_ = options; if (!output_cb.is_null()) output_cb_ = BindToCurrentLoop(std::move(output_cb)); - std::move(done_cb).Run(OkStatus()); + std::move(done_cb).Run(EncoderStatus::Codes::kOk); } -void OpenH264VideoEncoder::Flush(StatusCB done_cb) { +void OpenH264VideoEncoder::Flush(EncoderStatusCB done_cb) { done_cb = BindToCurrentLoop(std::move(done_cb)); if (!codec_) { - std::move(done_cb).Run(StatusCode::kEncoderInitializeNeverCompleted); + std::move(done_cb).Run( + EncoderStatus::Codes::kEncoderInitializeNeverCompleted); return; } // Nothing to do really. - std::move(done_cb).Run(OkStatus()); + std::move(done_cb).Run(EncoderStatus::Codes::kOk); } } // namespace media
diff --git a/media/video/openh264_video_encoder.h b/media/video/openh264_video_encoder.h index f3fb9cb..fc48a8d 100644 --- a/media/video/openh264_video_encoder.h +++ b/media/video/openh264_video_encoder.h
@@ -26,19 +26,19 @@ void Initialize(VideoCodecProfile profile, const Options& options, OutputCB output_cb, - StatusCB done_cb) override; + EncoderStatusCB done_cb) override; void Encode(scoped_refptr<VideoFrame> frame, bool key_frame, - StatusCB done_cb) override; + EncoderStatusCB done_cb) override; void ChangeOptions(const Options& options, OutputCB output_cb, - StatusCB done_cb) override; - void Flush(StatusCB done_cb) override; + EncoderStatusCB done_cb) override; + void Flush(EncoderStatusCB done_cb) override; private: - Status DrainOutputs(const SFrameBSInfo& frame_info, - base::TimeDelta timestamp, - gfx::ColorSpace color_space); + EncoderStatus DrainOutputs(const SFrameBSInfo& frame_info, + base::TimeDelta timestamp, + gfx::ColorSpace color_space); class ISVCEncoderDeleter { public:
diff --git a/media/video/software_video_encoder_test.cc b/media/video/software_video_encoder_test.cc index 70c9155..2c5618f 100644 --- a/media/video/software_video_encoder_test.cc +++ b/media/video/software_video_encoder_test.cc
@@ -100,7 +100,7 @@ } EXPECT_NE(decoder_, nullptr); - decoder_->Initialize(config, false, nullptr, ValidatingStatusCB(), + decoder_->Initialize(config, false, nullptr, DecoderStatusCB(), std::move(output_cb), base::NullCallback()); RunUntilIdle(); } @@ -187,7 +187,28 @@ } } - VideoEncoder::StatusCB ValidatingStatusCB(base::Location loc = FROM_HERE) { + VideoEncoder::EncoderStatusCB ValidatingStatusCB( + base::Location loc = FROM_HERE) { + struct CallEnforcer { + bool called = false; + std::string location; + ~CallEnforcer() { + EXPECT_TRUE(called) << "Callback created: " << location; + } + }; + auto enforcer = std::make_unique<CallEnforcer>(); + enforcer->location = loc.ToString(); + return base::BindLambdaForTesting( + [enforcer{std::move(enforcer)}](EncoderStatus s) { + EXPECT_TRUE(s.is_ok()) + << " Callback created: " << enforcer->location + << " Code: " << std::hex << static_cast<StatusCodeType>(s.code()) + << " Error: " << s.message(); + enforcer->called = true; + }); + } + + VideoDecoder::DecodeCB DecoderStatusCB(base::Location loc = FROM_HERE) { struct CallEnforcer { bool called = false; std::string location; @@ -403,7 +424,7 @@ DecoderBuffer::FromArray(std::move(output.data), output.size); buffer->set_timestamp(output.timestamp); buffer->set_is_key_frame(output.key_frame); - decoder_->Decode(std::move(buffer), ValidatingStatusCB()); + decoder_->Decode(std::move(buffer), DecoderStatusCB()); }); VideoDecoder::OutputCB decoder_output_cb =
diff --git a/media/video/video_encode_accelerator_adapter.cc b/media/video/video_encode_accelerator_adapter.cc index 01919d9..2044980 100644 --- a/media/video/video_encode_accelerator_adapter.cc +++ b/media/video/video_encode_accelerator_adapter.cc
@@ -140,7 +140,7 @@ void VideoEncodeAcceleratorAdapter::Initialize(VideoCodecProfile profile, const Options& options, OutputCB output_cb, - StatusCB done_cb) { + EncoderStatusCB done_cb) { DCHECK(!accelerator_task_runner_->RunsTasksInCurrentSequence()); accelerator_task_runner_->PostTask( FROM_HERE, @@ -155,34 +155,34 @@ VideoCodecProfile profile, const Options& options, OutputCB output_cb, - StatusCB done_cb) { + EncoderStatusCB done_cb) { DCHECK_CALLED_ON_VALID_SEQUENCE(accelerator_sequence_checker_); if (state_ != State::kNotInitialized) { - auto status = Status(StatusCode::kEncoderInitializeTwice, - "Encoder has already been initialized."); - std::move(done_cb).Run(status); + std::move(done_cb).Run( + EncoderStatus(EncoderStatus::Codes::kEncoderInitializeTwice, + "Encoder has already been initialized.")); return; } accelerator_ = gpu_factories_->CreateVideoEncodeAccelerator(); if (!accelerator_) { - auto status = Status(StatusCode::kEncoderInitializationError, - "Failed to create video encode accelerator."); - std::move(done_cb).Run(status); + std::move(done_cb).Run( + EncoderStatus(EncoderStatus::Codes::kEncoderInitializationError, + "Failed to create video encode accelerator.")); return; } if (options.frame_size.width() <= 0 || options.frame_size.height() <= 0) { - auto status = Status(StatusCode::kEncoderUnsupportedConfig, - "Negative width or height values."); - std::move(done_cb).Run(status); + std::move(done_cb).Run( + EncoderStatus(EncoderStatus::Codes::kEncoderUnsupportedConfig, + "Negative width or height values.")); return; } if (!options.frame_size.GetCheckedArea().IsValid()) { - auto status = - Status(StatusCode::kEncoderUnsupportedConfig, "Frame is too large."); - std::move(done_cb).Run(status); + std::move(done_cb).Run( + EncoderStatus(EncoderStatus::Codes::kEncoderUnsupportedConfig, + "Frame is too large.")); return; } @@ -198,7 +198,7 @@ } #endif // BUILDFLAG(USE_PROPRIETARY_CODECS) - std::move(done_cb).Run(Status()); + std::move(done_cb).Run(EncoderStatus::Codes::kOk); // The accelerator will be initialized for real once we have the first frame. } @@ -218,10 +218,9 @@ const bool supported_format = format == PIXEL_FORMAT_NV12 || format == PIXEL_FORMAT_I420 || is_rgb; if (!supported_format) { - auto status = - Status(StatusCode::kEncoderFailedEncode, "Unexpected frame format.") - .WithData("frame", first_frame->AsHumanReadableString()); - InitCompleted(std::move(status)); + InitCompleted(EncoderStatus(EncoderStatus::Codes::kEncoderFailedEncode, + "Unexpected frame format.") + .WithData("frame", first_frame->AsHumanReadableString())); return; } @@ -244,9 +243,9 @@ #endif if (!accelerator_->Initialize(vea_config, this)) { - auto status = Status(StatusCode::kEncoderInitializationError, - "Failed to initialize video encode accelerator."); - InitCompleted(status); + InitCompleted( + EncoderStatus(EncoderStatus::Codes::kEncoderInitializationError, + "Failed to initialize video encode accelerator.")); return; } @@ -256,7 +255,7 @@ void VideoEncodeAcceleratorAdapter::Encode(scoped_refptr<VideoFrame> frame, bool key_frame, - StatusCB done_cb) { + EncoderStatusCB done_cb) { DCHECK(!accelerator_task_runner_->RunsTasksInCurrentSequence()); accelerator_task_runner_->PostTask( FROM_HERE, @@ -268,7 +267,7 @@ void VideoEncodeAcceleratorAdapter::EncodeOnAcceleratorThread( scoped_refptr<VideoFrame> frame, bool key_frame, - StatusCB done_cb) { + EncoderStatusCB done_cb) { DCHECK_CALLED_ON_VALID_SEQUENCE(accelerator_sequence_checker_); if (state_ == State::kWaitingForFirstFrame || @@ -284,9 +283,9 @@ } if (state_ != State::kReadyToEncode) { - auto status = - Status(StatusCode::kEncoderFailedEncode, "Encoder can't encode now."); - std::move(done_cb).Run(status); + std::move(done_cb).Run( + EncoderStatus(EncoderStatus::Codes::kEncoderFailedEncode, + "Encoder can't encode now.")); return; } @@ -306,16 +305,18 @@ if (input_buffer_preference_ == InputBufferKind::CpuMemBuf) use_gpu_buffer = false; - StatusOr<scoped_refptr<VideoFrame>> result(nullptr); + EncoderStatus::Or<scoped_refptr<VideoFrame>> result(nullptr); if (use_gpu_buffer) result = PrepareGpuFrame(input_coded_size_, frame); else result = PrepareCpuFrame(input_coded_size_, frame); if (result.has_error()) { - auto status = std::move(result).error(); - status.WithData("frame", frame->AsHumanReadableString()); - std::move(done_cb).Run(std::move(status).AddHere()); + std::move(done_cb).Run( + std::move(result) + .error() + .WithData("frame", frame->AsHumanReadableString()) + .AddHere()); return; } @@ -336,7 +337,7 @@ void VideoEncodeAcceleratorAdapter::ChangeOptions(const Options& options, OutputCB output_cb, - StatusCB done_cb) { + EncoderStatusCB done_cb) { DCHECK(!accelerator_task_runner_->RunsTasksInCurrentSequence()); accelerator_task_runner_->PostTask( FROM_HERE, @@ -349,15 +350,16 @@ void VideoEncodeAcceleratorAdapter::ChangeOptionsOnAcceleratorThread( const Options options, OutputCB output_cb, - StatusCB done_cb) { + EncoderStatusCB done_cb) { DCHECK_CALLED_ON_VALID_SEQUENCE(accelerator_sequence_checker_); DCHECK(active_encodes_.empty()); DCHECK(pending_encodes_.empty()); DCHECK_EQ(state_, State::kReadyToEncode); if (options.frame_size != options_.frame_size) { - auto status = Status(StatusCode::kEncoderInitializationError, - "Resolution change is not supported."); + auto status = + EncoderStatus(EncoderStatus::Codes::kEncoderInitializationError, + "Resolution change is not supported."); std::move(done_cb).Run(status); return; } @@ -386,10 +388,10 @@ options_ = options; if (!output_cb.is_null()) output_cb_ = std::move(output_cb); - std::move(done_cb).Run(Status()); + std::move(done_cb).Run(EncoderStatus::Codes::kOk); } -void VideoEncodeAcceleratorAdapter::Flush(StatusCB done_cb) { +void VideoEncodeAcceleratorAdapter::Flush(EncoderStatusCB done_cb) { DCHECK(!accelerator_task_runner_->RunsTasksInCurrentSequence()); accelerator_task_runner_->PostTask( FROM_HERE, @@ -397,24 +399,24 @@ base::Unretained(this), WrapCallback(std::move(done_cb)))); } -void VideoEncodeAcceleratorAdapter::FlushOnAcceleratorThread(StatusCB done_cb) { +void VideoEncodeAcceleratorAdapter::FlushOnAcceleratorThread( + EncoderStatusCB done_cb) { DCHECK_CALLED_ON_VALID_SEQUENCE(accelerator_sequence_checker_); if (state_ == State::kWaitingForFirstFrame) { // Nothing to do since we haven't actually initialized yet. - std::move(done_cb).Run(Status()); + std::move(done_cb).Run(EncoderStatus::Codes::kOk); return; } if (state_ != State::kReadyToEncode && state_ != State::kInitializing) { - auto status = - Status(StatusCode::kEncoderFailedFlush, "Encoder can't flush now"); - std::move(done_cb).Run(status); + std::move(done_cb).Run(EncoderStatus( + EncoderStatus::Codes::kEncoderFailedFlush, "Encoder can't flush now")); return; } if (active_encodes_.empty() && pending_encodes_.empty()) { // No active or pending encodes, nothing to flush. - std::move(done_cb).Run(Status()); + std::move(done_cb).Run(EncoderStatus::Codes::kOk); return; } @@ -449,7 +451,7 @@ output_handle_holder_ = output_pool_->MaybeAllocateBuffer(output_buffer_size); if (!output_handle_holder_) { - InitCompleted(Status(StatusCode::kEncoderInitializationError)); + InitCompleted(EncoderStatus::Codes::kEncoderInitializationError); return; } @@ -458,7 +460,7 @@ // There is always one output buffer. accelerator_->UseOutputBitstreamBuffer( BitstreamBuffer(0, region.Duplicate(), region.GetSize())); - InitCompleted(Status()); + InitCompleted(EncoderStatus::Codes::kOk); } void VideoEncodeAcceleratorAdapter::BitstreamBufferReady( @@ -543,7 +545,7 @@ for (auto it = active_encodes_.begin(); it != active_encodes_.end(); ++it) { if ((*it)->timestamp == result.timestamp) { result.color_space = (*it)->color_space; - std::move((*it)->done_callback).Run(Status()); + std::move((*it)->done_callback).Run(EncoderStatus::Codes::kOk); active_encodes_.erase(it); erased_active_encode = true; break; @@ -561,8 +563,8 @@ VideoEncodeAccelerator::Error error) { if (state_ == State::kInitializing) { InitCompleted( - Status(StatusCode::kEncoderInitializationError, - "VideoEncodeAccelerator encountered an error") + EncoderStatus(EncoderStatus::Codes::kEncoderInitializationError, + "VideoEncodeAccelerator encountered an error") .WithData("VideoEncodeAccelerator::Error", int32_t{error})); return; } @@ -573,10 +575,10 @@ // Report the error to all encoding-done callbacks for (auto& encode : active_encodes_) { auto status = - Status(StatusCode::kEncoderFailedEncode, - "VideoEncodeAccelerator encountered an error") + EncoderStatus(EncoderStatus::Codes::kEncoderFailedEncode, + "VideoEncodeAccelerator encountered an error") .WithData("VideoEncodeAccelerator::Error", int32_t{error}); - std::move(encode->done_callback).Run(Status()); + std::move(encode->done_callback).Run(EncoderStatus::Codes::kOk); } active_encodes_.clear(); state_ = State::kNotInitialized; @@ -585,7 +587,7 @@ void VideoEncodeAcceleratorAdapter::NotifyEncoderInfoChange( const VideoEncoderInfo& info) {} -void VideoEncodeAcceleratorAdapter::InitCompleted(Status status) { +void VideoEncodeAcceleratorAdapter::InitCompleted(EncoderStatus status) { DCHECK_CALLED_ON_VALID_SEQUENCE(accelerator_sequence_checker_); if (!status.is_ok()) { @@ -630,8 +632,9 @@ if (!pending_flush_) return; - auto status = success ? Status() : Status(StatusCode::kEncoderFailedFlush); - std::move(pending_flush_->done_callback).Run(status); + std::move(pending_flush_->done_callback) + .Run(success ? EncoderStatus::Codes::kOk + : EncoderStatus::Codes::kEncoderFailedFlush); pending_flush_.reset(); state_ = State::kReadyToEncode; } @@ -646,13 +649,13 @@ // Copy a frame into a shared mem buffer and resize it as the same time. Input // frames can I420, NV12, or RGB -- they'll be converted to I420 if needed. -StatusOr<scoped_refptr<VideoFrame>> +EncoderStatus::Or<scoped_refptr<VideoFrame>> VideoEncodeAcceleratorAdapter::PrepareCpuFrame( const gfx::Size& size, scoped_refptr<VideoFrame> src_frame) { auto handle = input_pool_->MaybeAllocateBuffer(input_buffer_size_); if (!handle) - return Status(StatusCode::kEncoderFailedEncode); + return EncoderStatus(EncoderStatus::Codes::kEncoderFailedEncode); const base::UnsafeSharedMemoryRegion& region = handle->GetRegion(); const base::WritableSharedMemoryMapping& mapping = handle->GetMapping(); @@ -666,7 +669,7 @@ src_frame->timestamp()); if (!shared_frame || !mapped_src_frame) - return Status(StatusCode::kEncoderFailedEncode); + return EncoderStatus(EncoderStatus::Codes::kEncoderFailedEncode); shared_frame->BackWithSharedMemory(®ion); // Keep the SharedMemoryHolder until the frame is destroyed so that the @@ -677,14 +680,15 @@ auto status = ConvertAndScaleFrame(*mapped_src_frame, *shared_frame, resize_buf_); if (!status.is_ok()) - return std::move(status).AddHere(); + return EncoderStatus(EncoderStatus::Codes::kEncoderFailedEncode) + .AddCause(std::move(status)); return shared_frame; } // Copy a frame into a GPU buffer and resize it as the same time. Input frames // can I420, NV12, or RGB -- they'll be converted to NV12 if needed. -StatusOr<scoped_refptr<VideoFrame>> +EncoderStatus::Or<scoped_refptr<VideoFrame>> VideoEncodeAcceleratorAdapter::PrepareGpuFrame( const gfx::Size& size, scoped_refptr<VideoFrame> src_frame) { @@ -702,7 +706,7 @@ gfx::BufferUsage::VEA_READ_CAMERA_AND_CPU_READ_WRITE); if (!gmb) - return Status(StatusCode::kEncoderFailedEncode); + return EncoderStatus(EncoderStatus::Codes::kEncoderFailedEncode); gmb->SetColorSpace(src_frame->ColorSpace()); gpu::MailboxHolder empty_mailboxes[media::VideoFrame::kMaxPlanes]; @@ -724,12 +728,13 @@ ? ConvertToMemoryMappedFrame(src_frame) : src_frame; if (!mapped_gpu_frame || !mapped_src_frame) - return Status(StatusCode::kEncoderFailedEncode); + return EncoderStatus(EncoderStatus::Codes::kEncoderFailedEncode); auto status = ConvertAndScaleFrame(*mapped_src_frame, *mapped_gpu_frame, resize_buf_); if (!status.is_ok()) - return std::move(status).AddHere(); + return EncoderStatus(EncoderStatus::Codes::kEncoderFailedEncode) + .AddCause(std::move(status)); return gpu_frame; }
diff --git a/media/video/video_encode_accelerator_adapter.h b/media/video/video_encode_accelerator_adapter.h index 2eb96b8..30a4ef5 100644 --- a/media/video/video_encode_accelerator_adapter.h +++ b/media/video/video_encode_accelerator_adapter.h
@@ -51,14 +51,14 @@ void Initialize(VideoCodecProfile profile, const Options& options, OutputCB output_cb, - StatusCB done_cb) override; + EncoderStatusCB done_cb) override; void Encode(scoped_refptr<VideoFrame> frame, bool key_frame, - StatusCB done_cb) override; + EncoderStatusCB done_cb) override; void ChangeOptions(const Options& options, OutputCB output_cb, - StatusCB done_cb) override; - void Flush(StatusCB done_cb) override; + EncoderStatusCB done_cb) override; + void Flush(EncoderStatusCB done_cb) override; // VideoEncodeAccelerator::Client implementation void RequireBitstreamBuffers(unsigned int input_count, @@ -87,32 +87,32 @@ PendingOp(); ~PendingOp(); - StatusCB done_callback; + EncoderStatusCB done_callback; base::TimeDelta timestamp; gfx::ColorSpace color_space; }; void FlushCompleted(bool success); - void InitCompleted(Status status); + void InitCompleted(EncoderStatus status); void InitializeOnAcceleratorThread(VideoCodecProfile profile, const Options& options, OutputCB output_cb, - StatusCB done_cb); + EncoderStatusCB done_cb); void InitializeInternalOnAcceleratorThread(); void EncodeOnAcceleratorThread(scoped_refptr<VideoFrame> frame, bool key_frame, - StatusCB done_cb); - void FlushOnAcceleratorThread(StatusCB done_cb); + EncoderStatusCB done_cb); + void FlushOnAcceleratorThread(EncoderStatusCB done_cb); void ChangeOptionsOnAcceleratorThread(const Options options, OutputCB output_cb, - StatusCB done_cb); + EncoderStatusCB done_cb); template <class T> T WrapCallback(T cb); - StatusOr<scoped_refptr<VideoFrame>> PrepareGpuFrame( + EncoderStatus::Or<scoped_refptr<VideoFrame>> PrepareGpuFrame( const gfx::Size& size, scoped_refptr<VideoFrame> src_frame); - StatusOr<scoped_refptr<VideoFrame>> PrepareCpuFrame( + EncoderStatus::Or<scoped_refptr<VideoFrame>> PrepareCpuFrame( const gfx::Size& size, scoped_refptr<VideoFrame> src_frame);
diff --git a/media/video/video_encode_accelerator_adapter_test.cc b/media/video/video_encode_accelerator_adapter_test.cc index 68a5ccd..6147b03 100644 --- a/media/video/video_encode_accelerator_adapter_test.cc +++ b/media/video/video_encode_accelerator_adapter_test.cc
@@ -147,7 +147,8 @@ } } - VideoEncoder::StatusCB ValidatingStatusCB(base::Location loc = FROM_HERE) { + VideoEncoder::EncoderStatusCB ValidatingStatusCB( + base::Location loc = FROM_HERE) { struct CallEnforcer { bool called = false; std::string location; @@ -158,7 +159,7 @@ auto enforcer = std::make_unique<CallEnforcer>(); enforcer->location = loc.ToString(); return base::BindLambdaForTesting( - [this, enforcer{std::move(enforcer)}](Status s) { + [this, enforcer{std::move(enforcer)}](EncoderStatus s) { EXPECT_TRUE(callback_runner_->RunsTasksInCurrentSequence()); EXPECT_TRUE(s.is_ok()) << " Callback created: " << enforcer->location << " Error: " << s.message(); @@ -298,7 +299,7 @@ auto frame = CreateGreenFrame(options.frame_size, pixel_format, base::Milliseconds(1)); adapter()->Encode(frame, true, ValidatingStatusCB()); - adapter()->Flush(base::BindLambdaForTesting([&](Status s) { + adapter()->Flush(base::BindLambdaForTesting([&](EncoderStatus s) { EXPECT_TRUE(s.is_ok()); EXPECT_EQ(outputs_count, 1); })); @@ -315,8 +316,9 @@ outputs_count++; }); - VideoEncoder::StatusCB expect_error_done_cb = - base::BindLambdaForTesting([&](Status s) { EXPECT_FALSE(s.is_ok()); }); + VideoEncoder::EncoderStatusCB expect_error_done_cb = + base::BindLambdaForTesting( + [&](EncoderStatus s) { EXPECT_FALSE(s.is_ok()); }); vea()->SetEncodingCallback(base::BindLambdaForTesting( [&](BitstreamBuffer&, bool keyframe, scoped_refptr<VideoFrame> frame) {
diff --git a/media/video/video_encoder_fallback.cc b/media/video/video_encoder_fallback.cc index 6c631f1..0197d62 100644 --- a/media/video/video_encoder_fallback.cc +++ b/media/video/video_encoder_fallback.cc
@@ -25,7 +25,7 @@ void VideoEncoderFallback::Initialize(VideoCodecProfile profile, const Options& options, OutputCB output_cb, - StatusCB done_cb) { + EncoderStatusCB done_cb) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); init_done_cb_ = std::move(done_cb); @@ -33,7 +33,7 @@ profile_ = profile; options_ = options; auto done_callback = [](base::WeakPtr<VideoEncoderFallback> self, - Status status) { + EncoderStatus status) { if (!self) return; if (status.is_ok()) { @@ -53,7 +53,7 @@ VideoEncoder::PendingEncode VideoEncoderFallback::MakePendingEncode( scoped_refptr<VideoFrame> frame, bool key_frame, - StatusCB done_cb) { + EncoderStatusCB done_cb) { PendingEncode result; result.done_callback = std::move(done_cb); result.frame = std::move(frame); @@ -63,7 +63,7 @@ void VideoEncoderFallback::Encode(scoped_refptr<VideoFrame> frame, bool key_frame, - StatusCB done_cb) { + EncoderStatusCB done_cb) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (use_fallback_) { @@ -77,7 +77,7 @@ } auto done_callback = [](base::WeakPtr<VideoEncoderFallback> self, - PendingEncode args, Status status) { + PendingEncode args, EncoderStatus status) { if (!self) return; DCHECK(self->encoder_); @@ -96,20 +96,20 @@ void VideoEncoderFallback::ChangeOptions(const Options& options, OutputCB output_cb, - StatusCB done_cb) { + EncoderStatusCB done_cb) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); options_ = options; if (encoder_) encoder_->ChangeOptions(options, std::move(output_cb), std::move(done_cb)); } -void VideoEncoderFallback::Flush(StatusCB done_cb) { +void VideoEncoderFallback::Flush(EncoderStatusCB done_cb) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (encoder_) encoder_->Flush(std::move(done_cb)); } -void VideoEncoderFallback::FallbackInitCompleted(Status status) { +void VideoEncoderFallback::FallbackInitCompleted(EncoderStatus status) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(encoder_); if (init_done_cb_) @@ -133,8 +133,9 @@ use_fallback_ = true; encoder_ = std::move(create_fallback_cb_).Run(); if (!encoder_) { - std::move(init_done_cb_).Run(StatusCode::kEncoderInitializationError); - FallbackInitCompleted(StatusCode::kEncoderInitializationError); + std::move(init_done_cb_) + .Run(EncoderStatus::Codes::kEncoderInitializationError); + FallbackInitCompleted(EncoderStatus::Codes::kEncoderInitializationError); return; } @@ -153,7 +154,7 @@ encoder_ = std::move(create_fallback_cb_).Run(); if (!encoder_) { std::move(args.done_callback) - .Run(StatusCode::kEncoderInitializationError); + .Run(EncoderStatus::Codes::kEncoderInitializationError); return; } @@ -179,4 +180,4 @@ output_cb_.Run(std::move(output), std::move(desc)); } -} // namespace media \ No newline at end of file +} // namespace media
diff --git a/media/video/video_encoder_fallback.h b/media/video/video_encoder_fallback.h index 0072441..324d6b3 100644 --- a/media/video/video_encoder_fallback.h +++ b/media/video/video_encoder_fallback.h
@@ -33,22 +33,22 @@ void Initialize(VideoCodecProfile profile, const Options& options, OutputCB output_cb, - StatusCB done_cb) override; + EncoderStatusCB done_cb) override; void Encode(scoped_refptr<VideoFrame> frame, bool key_frame, - StatusCB done_cb) override; + EncoderStatusCB done_cb) override; void ChangeOptions(const Options& options, OutputCB output_cb, - StatusCB done_cb) override; - void Flush(StatusCB done_cb) override; + EncoderStatusCB done_cb) override; + void Flush(EncoderStatusCB done_cb) override; private: void FallbackInitialize(); void FallbackEncode(PendingEncode args); - void FallbackInitCompleted(Status status); + void FallbackInitCompleted(EncoderStatus status); PendingEncode MakePendingEncode(scoped_refptr<VideoFrame> frame, bool key_frame, - StatusCB done_cb); + EncoderStatusCB done_cb); void CallOutput(VideoEncoderOutput output, absl::optional<CodecDescription> desc); @@ -66,7 +66,7 @@ std::vector<std::unique_ptr<PendingEncode>> encodes_to_retry_; CreateFallbackCB create_fallback_cb_; - StatusCB init_done_cb_; + EncoderStatusCB init_done_cb_; OutputCB output_cb_; VideoCodecProfile profile_; Options options_;
diff --git a/media/video/video_encoder_fallback_test.cc b/media/video/video_encoder_fallback_test.cc index ab534bc..8787118 100644 --- a/media/video/video_encoder_fallback_test.cc +++ b/media/video/video_encoder_fallback_test.cc
@@ -51,13 +51,15 @@ bool FallbackHappened() { return !secondary_video_encoder_holder_; } - void RunStatusCallbackAync(VideoEncoder::StatusCB callback, - StatusCode code = StatusCode::kOk) { + void RunStatusCallbackAync( + VideoEncoder::EncoderStatusCB callback, + EncoderStatus::Codes code = EncoderStatus::Codes::kOk) { base::BindPostTask(callback_runner_, std::move(callback)).Run(code); } - VideoEncoder::StatusCB ValidatingStatusCB(StatusCode code = StatusCode::kOk, - base::Location loc = FROM_HERE) { + VideoEncoder::EncoderStatusCB ValidatingStatusCB( + EncoderStatus::Codes code = EncoderStatus::Codes::kOk, + base::Location loc = FROM_HERE) { struct CallEnforcer { bool called = false; std::string location; @@ -68,7 +70,7 @@ auto enforcer = std::make_unique<CallEnforcer>(); enforcer->location = loc.ToString(); return BindToCurrentLoop(base::BindLambdaForTesting( - [code, this, enforcer{std::move(enforcer)}](Status s) { + [code, this, enforcer{std::move(enforcer)}](EncoderStatus s) { EXPECT_TRUE(callback_runner_->RunsTasksInCurrentSequence()); EXPECT_EQ(s.code(), code) << " Callback created: " << enforcer->location; @@ -98,7 +100,7 @@ .WillOnce(Invoke([&, this](VideoCodecProfile profile, const VideoEncoder::Options& options, VideoEncoder::OutputCB output_cb, - VideoEncoder::StatusCB done_cb) { + VideoEncoder::EncoderStatusCB done_cb) { saved_output_cb = std::move(output_cb); RunStatusCallbackAync(std::move(done_cb)); })); @@ -106,7 +108,7 @@ EXPECT_CALL(*main_video_encoder_, Encode(_, _, _)) .WillRepeatedly( Invoke([&, this](scoped_refptr<VideoFrame> frame, bool key_frame, - VideoEncoder::StatusCB done_cb) { + VideoEncoder::EncoderStatusCB done_cb) { VideoEncoderOutput output; output.timestamp = frame->timestamp(); saved_output_cb.Run(std::move(output), {}); @@ -145,9 +147,10 @@ .WillOnce(Invoke([&, this](VideoCodecProfile profile, const VideoEncoder::Options& options, VideoEncoder::OutputCB output_cb, - VideoEncoder::StatusCB done_cb) { - RunStatusCallbackAync(std::move(done_cb), - StatusCode::kEncoderInitializationError); + VideoEncoder::EncoderStatusCB done_cb) { + RunStatusCallbackAync( + std::move(done_cb), + EncoderStatus::Codes::kEncoderInitializationError); })); // Initialize() on the second encoder should succeed @@ -155,7 +158,7 @@ .WillOnce(Invoke([&, this](VideoCodecProfile profile, const VideoEncoder::Options& options, VideoEncoder::OutputCB output_cb, - VideoEncoder::StatusCB done_cb) { + VideoEncoder::EncoderStatusCB done_cb) { saved_output_cb = std::move(output_cb); RunStatusCallbackAync(std::move(done_cb)); })); @@ -164,7 +167,7 @@ EXPECT_CALL(*secondary_video_encoder_, Encode(_, _, _)) .WillRepeatedly( Invoke([&, this](scoped_refptr<VideoFrame> frame, bool key_frame, - VideoEncoder::StatusCB done_cb) { + VideoEncoder::EncoderStatusCB done_cb) { VideoEncoderOutput output; output.timestamp = frame->timestamp(); saved_output_cb.Run(std::move(output), {}); @@ -204,7 +207,7 @@ .WillOnce(Invoke([&, this](VideoCodecProfile profile, const VideoEncoder::Options& options, VideoEncoder::OutputCB output_cb, - VideoEncoder::StatusCB done_cb) { + VideoEncoder::EncoderStatusCB done_cb) { primary_output_cb = std::move(output_cb); RunStatusCallbackAync(std::move(done_cb)); })); @@ -214,7 +217,7 @@ .WillOnce(Invoke([&, this](VideoCodecProfile profile, const VideoEncoder::Options& options, VideoEncoder::OutputCB output_cb, - VideoEncoder::StatusCB done_cb) { + VideoEncoder::EncoderStatusCB done_cb) { secondary_output_cb = std::move(output_cb); RunStatusCallbackAync(std::move(done_cb)); })); @@ -223,27 +226,27 @@ // Start failing encodes after half of the frames. EXPECT_CALL(*main_video_encoder_, Encode(_, _, _)) - .WillRepeatedly( - Invoke([&, this](scoped_refptr<VideoFrame> frame, bool key_frame, - VideoEncoder::StatusCB done_cb) { - EXPECT_TRUE(frame); - EXPECT_TRUE(done_cb); - if (frame->timestamp() > encoder_switch_time) { - std::move(done_cb).Run(StatusCode::kEncoderFailedEncode); - return; - } + .WillRepeatedly(Invoke([&, this](scoped_refptr<VideoFrame> frame, + bool key_frame, + VideoEncoder::EncoderStatusCB done_cb) { + EXPECT_TRUE(frame); + EXPECT_TRUE(done_cb); + if (frame->timestamp() > encoder_switch_time) { + std::move(done_cb).Run(EncoderStatus::Codes::kEncoderFailedEncode); + return; + } - VideoEncoderOutput output; - output.timestamp = frame->timestamp(); - primary_output_cb.Run(std::move(output), {}); - RunStatusCallbackAync(std::move(done_cb)); - })); + VideoEncoderOutput output; + output.timestamp = frame->timestamp(); + primary_output_cb.Run(std::move(output), {}); + RunStatusCallbackAync(std::move(done_cb)); + })); // All encodes should come to the secondary encoder. EXPECT_CALL(*secondary_video_encoder_, Encode(_, _, _)) .WillRepeatedly( Invoke([&, this](scoped_refptr<VideoFrame> frame, bool key_frame, - VideoEncoder::StatusCB done_cb) { + VideoEncoder::EncoderStatusCB done_cb) { EXPECT_TRUE(frame); EXPECT_TRUE(done_cb); EXPECT_GT(frame->timestamp(), encoder_switch_time); @@ -282,9 +285,9 @@ .WillOnce(Invoke([&, this](VideoCodecProfile profile, const VideoEncoder::Options& options, VideoEncoder::OutputCB output_cb, - VideoEncoder::StatusCB done_cb) { + VideoEncoder::EncoderStatusCB done_cb) { RunStatusCallbackAync(std::move(done_cb), - StatusCode::kEncoderUnsupportedProfile); + EncoderStatus::Codes::kEncoderUnsupportedProfile); })); // Initialize() on the second encoder should also fail @@ -292,30 +295,31 @@ .WillOnce(Invoke([&, this](VideoCodecProfile profile, const VideoEncoder::Options& options, VideoEncoder::OutputCB output_cb, - VideoEncoder::StatusCB done_cb) { + VideoEncoder::EncoderStatusCB done_cb) { RunStatusCallbackAync(std::move(done_cb), - StatusCode::kEncoderUnsupportedCodec); + EncoderStatus::Codes::kEncoderUnsupportedCodec); })); EXPECT_CALL(*main_video_encoder_, Encode(_, _, _)) .WillRepeatedly( Invoke([&, this](scoped_refptr<VideoFrame> frame, bool key_frame, - VideoEncoder::StatusCB done_cb) { - RunStatusCallbackAync(std::move(done_cb), - StatusCode::kEncoderInitializeNeverCompleted); + VideoEncoder::EncoderStatusCB done_cb) { + RunStatusCallbackAync( + std::move(done_cb), + EncoderStatus::Codes::kEncoderInitializeNeverCompleted); })); fallback_encoder_->Initialize( profile, options, std::move(output_cb), - ValidatingStatusCB(StatusCode::kEncoderUnsupportedCodec)); + ValidatingStatusCB(EncoderStatus::Codes::kEncoderUnsupportedCodec)); for (int i = 0; i < kFrameCount; i++) { auto frame = VideoFrame::CreateFrame(PIXEL_FORMAT_I420, kFrameSize, gfx::Rect(kFrameSize), kFrameSize, base::Seconds(i)); - auto done_callback = base::BindLambdaForTesting([this](Status s) { + auto done_callback = base::BindLambdaForTesting([this](EncoderStatus s) { EXPECT_TRUE(callback_runner_->RunsTasksInCurrentSequence()); - EXPECT_EQ(s.code(), StatusCode::kEncoderUnsupportedCodec); + EXPECT_EQ(s.code(), EncoderStatus::Codes::kEncoderUnsupportedCodec); callback_runner_->DeleteSoon(FROM_HERE, std::move(fallback_encoder_)); }); fallback_encoder_->Encode(frame, true, std::move(done_callback)); @@ -325,4 +329,4 @@ EXPECT_TRUE(FallbackHappened()); } -} // namespace media \ No newline at end of file +} // namespace media
diff --git a/media/video/vpx_video_encoder.cc b/media/video/vpx_video_encoder.cc index 523bdf42..e80e08a 100644 --- a/media/video/vpx_video_encoder.cc +++ b/media/video/vpx_video_encoder.cc
@@ -82,14 +82,15 @@ return desired_threads; } -Status SetUpVpxConfig(const VideoEncoder::Options& opts, - vpx_codec_enc_cfg_t* config) { +EncoderStatus SetUpVpxConfig(const VideoEncoder::Options& opts, + vpx_codec_enc_cfg_t* config) { if (opts.frame_size.width() <= 0 || opts.frame_size.height() <= 0) - return Status(StatusCode::kEncoderUnsupportedConfig, - "Negative width or height values."); + return EncoderStatus(EncoderStatus::Codes::kEncoderUnsupportedConfig, + "Negative width or height values."); if (!opts.frame_size.GetCheckedArea().IsValid()) - return Status(StatusCode::kEncoderUnsupportedConfig, "Frame is too large."); + return EncoderStatus(EncoderStatus::Codes::kEncoderUnsupportedConfig, + "Frame is too large."); config->g_pass = VPX_RC_ONE_PASS; config->g_lag_in_frames = 0; @@ -131,7 +132,7 @@ config->g_h = opts.frame_size.height(); if (!opts.scalability_mode) - return Status(); + return EncoderStatus::Codes::kOk; switch (opts.scalability_mode.value()) { case SVCScalabilityMode::kL1T2: @@ -183,12 +184,12 @@ config->g_error_resilient = VPX_ERROR_RESILIENT_DEFAULT; break; default: { - return Status(StatusCode::kEncoderUnsupportedConfig, - "Unsupported number of temporal layers."); + return EncoderStatus(EncoderStatus::Codes::kEncoderUnsupportedConfig, + "Unsupported number of temporal layers."); } } - return Status(); + return EncoderStatus::Codes::kOk; } vpx_svc_extra_cfg_t MakeSvcExtraConfig(const vpx_codec_enc_cfg_t& config) { @@ -203,21 +204,21 @@ return result; } -Status ReallocateVpxImageIfNeeded(vpx_image_t* vpx_image, - const vpx_img_fmt fmt, - int width, - int height) { +EncoderStatus ReallocateVpxImageIfNeeded(vpx_image_t* vpx_image, + const vpx_img_fmt fmt, + int width, + int height) { if (vpx_image->fmt != fmt || static_cast<int>(vpx_image->w) != width || static_cast<int>(vpx_image->h) != height) { vpx_img_free(vpx_image); if (vpx_image != vpx_img_alloc(vpx_image, fmt, width, height, 1)) { - return Status(StatusCode::kEncoderFailedEncode, - "Invalid format or frame size."); + return EncoderStatus(EncoderStatus::Codes::kEncoderFailedEncode, + "Invalid format or frame size."); } vpx_image->bit_depth = (fmt & VPX_IMG_FMT_HIGHBITDEPTH) ? 16 : 8; } // else no-op since the image don't need to change format. - return Status(); + return EncoderStatus::Codes::kOk; } void FreeCodecCtx(vpx_codec_ctx_t* codec_ctx) { @@ -237,10 +238,10 @@ void VpxVideoEncoder::Initialize(VideoCodecProfile profile, const Options& options, OutputCB output_cb, - StatusCB done_cb) { + EncoderStatusCB done_cb) { done_cb = BindToCurrentLoop(std::move(done_cb)); if (codec_) { - std::move(done_cb).Run(StatusCode::kEncoderInitializeTwice); + std::move(done_cb).Run(EncoderStatus::Codes::kEncoderInitializeTwice); return; } profile_ = profile; @@ -254,17 +255,19 @@ is_vp9 = true; iface = vpx_codec_vp9_cx(); } else { - auto status = Status(StatusCode::kEncoderUnsupportedProfile) - .WithData("profile", profile); + auto status = + EncoderStatus(EncoderStatus::Codes::kEncoderUnsupportedProfile) + .WithData("profile", profile); std::move(done_cb).Run(status); return; } auto vpx_error = vpx_codec_enc_config_default(iface, &codec_config_, 0); if (vpx_error != VPX_CODEC_OK) { - auto status = Status(StatusCode::kEncoderInitializationError, - "Failed to get default VPX config.") - .WithData("vpx_error", vpx_error); + auto status = + EncoderStatus(EncoderStatus::Codes::kEncoderInitializationError, + "Failed to get default VPX config.") + .WithData("vpx_error", vpx_error); std::move(done_cb).Run(status); return; } @@ -294,7 +297,7 @@ break; } - Status status = SetUpVpxConfig(options, &codec_config_); + auto status = SetUpVpxConfig(options, &codec_config_); if (!status.is_ok()) { std::move(done_cb).Run(status); return; @@ -310,8 +313,8 @@ "VPX encoder initialization error: %s %s", vpx_codec_err_to_string(vpx_error), codec->err_detail); DLOG(ERROR) << msg; - status = Status(StatusCode::kEncoderInitializationError, msg); - std::move(done_cb).Run(status); + std::move(done_cb).Run( + EncoderStatus(EncoderStatus::Codes::kEncoderInitializationError, msg)); return; } @@ -327,17 +330,17 @@ base::StringPrintf("VPX encoder VP8E_SET_CPUUSED error: %s", vpx_codec_err_to_string(vpx_error)); DLOG(ERROR) << msg; - status = Status(StatusCode::kEncoderInitializationError, msg); - std::move(done_cb).Run(status); + std::move(done_cb).Run( + EncoderStatus(EncoderStatus::Codes::kEncoderInitializationError, msg)); return; } if (&vpx_image_ != vpx_img_alloc(&vpx_image_, img_fmt, options.frame_size.width(), options.frame_size.height(), 1)) { - status = Status(StatusCode::kEncoderInitializationError, - "Invalid format or frame size."); - std::move(done_cb).Run(status); + std::move(done_cb).Run( + EncoderStatus(EncoderStatus::Codes::kEncoderInitializationError, + "Invalid format or frame size.")); return; } vpx_image_.bit_depth = bits_for_storage; @@ -364,7 +367,8 @@ base::StringPrintf("Can't activate SVC encoding: %s", vpx_codec_err_to_string(vpx_error)); DLOG(ERROR) << msg; - status = Status(StatusCode::kEncoderInitializationError, msg); + status = EncoderStatus( + EncoderStatus::Codes::kEncoderInitializationError, msg); std::move(done_cb).Run(status); return; } @@ -379,21 +383,23 @@ originally_configured_size_ = options.frame_size; output_cb_ = BindToCurrentLoop(std::move(output_cb)); codec_ = std::move(codec); - std::move(done_cb).Run(Status()); + std::move(done_cb).Run(EncoderStatus::Codes::kOk); } void VpxVideoEncoder::Encode(scoped_refptr<VideoFrame> frame, bool key_frame, - StatusCB done_cb) { + EncoderStatusCB done_cb) { done_cb = BindToCurrentLoop(std::move(done_cb)); if (!codec_) { - std::move(done_cb).Run(StatusCode::kEncoderInitializeNeverCompleted); + std::move(done_cb).Run( + EncoderStatus::Codes::kEncoderInitializeNeverCompleted); return; } if (!frame) { - std::move(done_cb).Run(Status(StatusCode::kEncoderFailedEncode, - "No frame provided for encoding.")); + std::move(done_cb).Run( + EncoderStatus(EncoderStatus::Codes::kEncoderFailedEncode, + "No frame provided for encoding.")); return; } bool supported_format = frame->format() == PIXEL_FORMAT_NV12 || @@ -404,11 +410,11 @@ frame->format() == PIXEL_FORMAT_ARGB; if ((!frame->IsMappable() && !frame->HasGpuMemoryBuffer()) || !supported_format) { - Status status = - Status(StatusCode::kEncoderFailedEncode, "Unexpected frame format.") + std::move(done_cb).Run( + EncoderStatus(EncoderStatus::Codes::kEncoderFailedEncode, + "Unexpected frame format.") .WithData("IsMappable", frame->IsMappable()) - .WithData("format", frame->format()); - std::move(done_cb).Run(std::move(status)); + .WithData("format", frame->format())); return; } @@ -416,8 +422,8 @@ frame = ConvertToMemoryMappedFrame(frame); if (!frame) { std::move(done_cb).Run( - Status(StatusCode::kEncoderFailedEncode, - "Convert GMB frame to MemoryMappedFrame failed.")); + EncoderStatus(EncoderStatus::Codes::kEncoderFailedEncode, + "Convert GMB frame to MemoryMappedFrame failed.")); return; } } @@ -428,15 +434,20 @@ is_yuv ? frame->format() : PIXEL_FORMAT_I420, options_.frame_size, gfx::Rect(options_.frame_size), options_.frame_size, frame->timestamp()); - Status status; - if (resized_frame) { - status = ConvertAndScaleFrame(*frame, *resized_frame, resize_buf_); - } else { - status = Status(StatusCode::kEncoderFailedEncode, - "Can't allocate a resized frame."); + + if (!resized_frame) { + std::move(done_cb).Run( + EncoderStatus(EncoderStatus::Codes::kEncoderFailedEncode, + "Can't allocate a resized frame")); + return; } - if (!status.is_ok()) { - std::move(done_cb).Run(std::move(status)); + + auto convert_status = + ConvertAndScaleFrame(*frame, *resized_frame, resize_buf_); + if (!convert_status.is_ok()) { + std::move(done_cb).Run( + EncoderStatus(EncoderStatus::Codes::kEncoderFailedEncode) + .AddCause(std::move(convert_status))); return; } frame = std::move(resized_frame); @@ -468,7 +479,7 @@ vpx_img_fmt_t fmt = frame->format() == PIXEL_FORMAT_NV12 ? VPX_IMG_FMT_NV12 : VPX_IMG_FMT_I420; - Status status = ReallocateVpxImageIfNeeded( + EncoderStatus status = ReallocateVpxImageIfNeeded( &vpx_image_, fmt, codec_config_.g_w, codec_config_.g_h); if (!status.is_ok()) { std::move(done_cb).Run(status); @@ -539,22 +550,23 @@ vpx_codec_err_to_string(vpx_error), vpx_codec_error_detail(codec_.get())); DLOG(ERROR) << msg; - Status status = Status(StatusCode::kEncoderFailedEncode, msg) - .WithData("vpx_error", vpx_error); - std::move(done_cb).Run(std::move(status)); + std::move(done_cb).Run( + EncoderStatus(EncoderStatus::Codes::kEncoderFailedEncode, msg) + .WithData("vpx_error", vpx_error)); return; } DrainOutputs(temporal_id, frame->timestamp(), frame->ColorSpace()); - std::move(done_cb).Run(Status()); + std::move(done_cb).Run(EncoderStatus::Codes::kOk); } void VpxVideoEncoder::ChangeOptions(const Options& options, OutputCB output_cb, - StatusCB done_cb) { + EncoderStatusCB done_cb) { done_cb = BindToCurrentLoop(std::move(done_cb)); if (!codec_) { - std::move(done_cb).Run(StatusCode::kEncoderInitializeNeverCompleted); + std::move(done_cb).Run( + EncoderStatus::Codes::kEncoderInitializeNeverCompleted); return; } @@ -578,8 +590,8 @@ auto new_area = options.frame_size.GetCheckedArea(); DCHECK(old_area.IsValid()); if (!new_area.IsValid() || new_area.ValueOrDie() > old_area.ValueOrDie()) { - auto status = Status( - StatusCode::kEncoderUnsupportedConfig, + auto status = EncoderStatus( + EncoderStatus::Codes::kEncoderUnsupportedConfig, "libvpx/VP8 doesn't support dynamically increasing frame area"); std::move(done_cb).Run(std::move(status)); return; @@ -588,8 +600,8 @@ // VP9 resize restrictions if (options.frame_size.width() > originally_configured_size_.width() || options.frame_size.height() > originally_configured_size_.height()) { - auto status = Status( - StatusCode::kEncoderUnsupportedConfig, + auto status = EncoderStatus( + EncoderStatus::Codes::kEncoderUnsupportedConfig, "libvpx/VP9 doesn't support dynamically increasing frame dimentions"); std::move(done_cb).Run(std::move(status)); return; @@ -624,8 +636,8 @@ if (!output_cb.is_null()) output_cb_ = BindToCurrentLoop(std::move(output_cb)); } else { - status = Status(StatusCode::kEncoderUnsupportedConfig, - "Failed to set new VPX config") + status = EncoderStatus(EncoderStatus::Codes::kEncoderUnsupportedConfig, + "Failed to set new VPX config") .WithData("vpx_error", error); } @@ -659,10 +671,11 @@ vpx_img_free(&vpx_image_); } -void VpxVideoEncoder::Flush(StatusCB done_cb) { +void VpxVideoEncoder::Flush(EncoderStatusCB done_cb) { done_cb = BindToCurrentLoop(std::move(done_cb)); if (!codec_) { - std::move(done_cb).Run(StatusCode::kEncoderInitializeNeverCompleted); + std::move(done_cb).Run( + EncoderStatus::Codes::kEncoderInitializeNeverCompleted); return; } @@ -672,13 +685,13 @@ vpx_codec_err_to_string(vpx_error), vpx_codec_error_detail(codec_.get())); DLOG(ERROR) << msg; - Status status = Status(StatusCode::kEncoderFailedEncode, msg) - .WithData("vpx_error", vpx_error); + auto status = EncoderStatus(EncoderStatus::Codes::kEncoderFailedEncode, msg) + .WithData("vpx_error", vpx_error); std::move(done_cb).Run(std::move(status)); return; } DrainOutputs(0, base::TimeDelta(), gfx::ColorSpace()); - std::move(done_cb).Run(Status()); + std::move(done_cb).Run(EncoderStatus::Codes::kOk); } void VpxVideoEncoder::DrainOutputs(int temporal_id,
diff --git a/media/video/vpx_video_encoder.h b/media/video/vpx_video_encoder.h index 1b69d51..a807af4 100644 --- a/media/video/vpx_video_encoder.h +++ b/media/video/vpx_video_encoder.h
@@ -27,14 +27,14 @@ void Initialize(VideoCodecProfile profile, const Options& options, OutputCB output_cb, - StatusCB done_cb) override; + EncoderStatusCB done_cb) override; void Encode(scoped_refptr<VideoFrame> frame, bool key_frame, - StatusCB done_cb) override; + EncoderStatusCB done_cb) override; void ChangeOptions(const Options& options, OutputCB output_cb, - StatusCB done_cb) override; - void Flush(StatusCB done_cb) override; + EncoderStatusCB done_cb) override; + void Flush(EncoderStatusCB done_cb) override; private: base::TimeDelta GetFrameDuration(const VideoFrame& frame);
diff --git a/remoting/base/oauth_token_getter.h b/remoting/base/oauth_token_getter.h index 061bbc9..d356ede 100644 --- a/remoting/base/oauth_token_getter.h +++ b/remoting/base/oauth_token_getter.h
@@ -36,7 +36,7 @@ // This structure contains information required to perform authorization // with the authorization server. struct OAuthAuthorizationCredentials { - // |login| is used to valdiate |refresh_token| match. + // |login| is used to validate |refresh_token| match. // |is_service_account| should be True if the OAuth refresh token is for a // service account, False for a user account, to allow the correct client-ID // to be used. @@ -69,7 +69,7 @@ ~OAuthIntermediateCredentials(); - // Code used to check out a access token from the authrozation service. + // Code used to exchange for an access token from the authorization service. std::string authorization_code; // Override uri for oauth redirect. This is used for client accounts only
diff --git a/remoting/base/result.h b/remoting/base/result.h index d045fbb..6775e0d 100644 --- a/remoting/base/result.h +++ b/remoting/base/result.h
@@ -29,7 +29,7 @@ // Result() // Only present when the success value is default constructible. Default // constructs the success value. This is useful for situations like IPC -// deserialization where a default-costructed instance is created and the +// deserialization where a default-constructed instance is created and the // actual value is filled in later. In general, prefer using the // Result(kSuccessTag) constructor to be explicit. //
diff --git a/remoting/client/display/drawable.h b/remoting/client/display/drawable.h index daf316c..140935c8 100644 --- a/remoting/client/display/drawable.h +++ b/remoting/client/display/drawable.h
@@ -39,7 +39,7 @@ CURSOR = 300, }; - // A higher Z Index shiould be draw ontop of a lower z index. Elements with + // A higher Z Index should be draw ontop of a lower z index. Elements with // the same Z Index should draw in order inserted into the renderer. virtual int GetZIndex() = 0; };
diff --git a/remoting/client/input/keyboard_interpreter.cc b/remoting/client/input/keyboard_interpreter.cc index 3ff991f..e1d3de2 100644 --- a/remoting/client/input/keyboard_interpreter.cc +++ b/remoting/client/input/keyboard_interpreter.cc
@@ -58,7 +58,7 @@ } base::queue<KeyEvent> keys; - // TODO(nicholss): Handle modifers. + // TODO(nicholss): Handle modifiers. // Key press. keys.push({static_cast<uint32_t>(ui::DomCode::BACKSPACE), true});
diff --git a/remoting/client/input/text_keyboard_input_strategy.cc b/remoting/client/input/text_keyboard_input_strategy.cc index 04a1bc96..b5287f80 100644 --- a/remoting/client/input/text_keyboard_input_strategy.cc +++ b/remoting/client/input/text_keyboard_input_strategy.cc
@@ -20,7 +20,7 @@ void TextKeyboardInputStrategy::HandleTextEvent(const std::string& text, uint8_t modifiers) { - // TODO(nicholss): Handle modifers. + // TODO(nicholss): Handle modifiers. input_injector_->SendTextEvent(text); }
diff --git a/remoting/client/notification/notification_client.cc b/remoting/client/notification/notification_client.cc index 48ccfb64..403d403 100644 --- a/remoting/client/notification/notification_client.cc +++ b/remoting/client/notification/notification_client.cc
@@ -12,6 +12,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_refptr.h" #include "base/strings/stringize_macros.h" +#include "base/system/sys_info.h" #include "base/values.h" #include "build/build_config.h" #include "net/traffic_annotation/network_traffic_annotation.h" @@ -195,6 +196,7 @@ std::make_unique<GstaticJsonFetcher>(network_task_runner), kCurrentPlatform, kCurrentVersion, + base::SysInfo::OperatingSystemVersion(), #if defined(OS_ANDROID) // GetApplicationLocale() returns empty string on Android since we // don't pack any .pak file into the apk, so we need to get the locale @@ -211,11 +213,13 @@ NotificationClient::NotificationClient(std::unique_ptr<JsonFetcher> fetcher, const std::string& current_platform, const std::string& current_version, + const std::string& current_os_version, const std::string& locale, bool should_ignore_dev_messages) : fetcher_(std::move(fetcher)), current_platform_(current_platform), current_version_(current_version), + current_os_version_(current_os_version), locale_(locale), should_ignore_dev_messages_(should_ignore_dev_messages) { VLOG(1) << "Platform: " << current_platform_ @@ -309,6 +313,21 @@ return absl::nullopt; } + // OS version check is not performed if |os_version| is not specified. + std::string os_version_spec_string; + if (FindKeyAndGet(rule, "os_version", &os_version_spec_string)) { + VersionRange os_version_range(os_version_spec_string); + if (!os_version_range.IsValid()) { + LOG(ERROR) << "Invalid OS version range: " << os_version_spec_string; + return absl::nullopt; + } + if (!os_version_range.ContainsVersion(current_os_version_)) { + VLOG(1) << "Current OS version " << current_os_version_ + << " not in range " << os_version_spec_string; + return absl::nullopt; + } + } + if (!ShouldShowNotificationForUser(user_email, percent)) { VLOG(1) << "User is not selected for notification"; return absl::nullopt;
diff --git a/remoting/client/notification/notification_client.h b/remoting/client/notification/notification_client.h index ad77fc8c..32dfcab 100644 --- a/remoting/client/notification/notification_client.h +++ b/remoting/client/notification/notification_client.h
@@ -51,6 +51,7 @@ NotificationClient(std::unique_ptr<JsonFetcher> fetcher, const std::string& current_platform, const std::string& current_version, + const std::string& current_os_version, const std::string& locale, bool should_ignore_dev_messages); @@ -75,6 +76,7 @@ std::unique_ptr<JsonFetcher> fetcher_; std::string current_platform_; std::string current_version_; + std::string current_os_version_; std::string locale_; bool should_ignore_dev_messages_; };
diff --git a/remoting/client/notification/notification_client_unittest.cc b/remoting/client/notification/notification_client_unittest.cc index 76f63d7..ec370658 100644 --- a/remoting/client/notification/notification_client_unittest.cc +++ b/remoting/client/notification/notification_client_unittest.cc
@@ -26,6 +26,7 @@ constexpr char kTestEmail[] = "test@example.com"; constexpr char kTestPlatform[] = "IOS"; constexpr char kTestVersion[] = "76.0.3809.13"; +constexpr char kTestOsVersion[] = "15.1"; constexpr char kTestLocale[] = "zh-CN"; class MockJsonFetcher : public JsonFetcher { @@ -99,9 +100,9 @@ void Reset(bool should_ignore_dev_messages) { auto fetcher = std::make_unique<MockJsonFetcher>(); fetcher_ = fetcher.get(); - client_ = base::WrapUnique( - new NotificationClient(std::move(fetcher), kTestPlatform, kTestVersion, - kTestLocale, should_ignore_dev_messages)); + client_ = base::WrapUnique(new NotificationClient( + std::move(fetcher), kTestPlatform, kTestVersion, kTestOsVersion, + kTestLocale, should_ignore_dev_messages)); } raw_ptr<MockJsonFetcher> fetcher_; @@ -159,6 +160,36 @@ client_->GetNotification(kTestEmail, callback.Get()); } +TEST_F(NotificationClientTest, OsVersionNotMatched) { + base::Value rule = CreateDefaultRule(); + rule.SetStringKey("os_version", "(-15.1)"); + base::Value rules(base::Value::Type::LIST); + rules.Append(std::move(rule)); + EXPECT_CALL(*fetcher_, FetchJsonFile("notification/rules.json")) + .WillOnce(ReturnByMove(std::move(rules))); + + base::MockCallback<NotificationClient::NotificationCallback> callback; + EXPECT_CALL(callback, Run(NoMessage())); + client_->GetNotification(kTestEmail, callback.Get()); +} + +TEST_F(NotificationClientTest, OsVersionMatched) { + base::Value rule = CreateDefaultRule(); + rule.SetStringKey("os_version", "[15-)"); + base::Value rules(base::Value::Type::LIST); + rules.Append(std::move(rule)); + EXPECT_CALL(*fetcher_, FetchJsonFile("notification/rules.json")) + .WillOnce(ReturnByMove(std::move(rules))); + EXPECT_CALL(*fetcher_, FetchJsonFile("notification/message_text.json")) + .WillOnce(ReturnByMove(CreateDefaultTranslations("message"))); + EXPECT_CALL(*fetcher_, FetchJsonFile("notification/link_text.json")) + .WillOnce(ReturnByMove(CreateDefaultTranslations("link"))); + + base::MockCallback<NotificationClient::NotificationCallback> callback; + EXPECT_CALL(callback, Run(MessageMatches(CreateDefaultNotification()))); + client_->GetNotification(kTestEmail, callback.Get()); +} + TEST_F(NotificationClientTest, UserNotSelected) { base::Value rule = CreateDefaultRule(); rule.SetIntKey("percent", 0);
diff --git a/remoting/client/ui/desktop_viewport.h b/remoting/client/ui/desktop_viewport.h index af264ac..b0ae9e3 100644 --- a/remoting/client/ui/desktop_viewport.h +++ b/remoting/client/ui/desktop_viewport.h
@@ -79,7 +79,7 @@ // Registers the callback to be called once the transformation has changed. // run_immediately: If true and the viewport is ready to be used, the callback - // will be called immedately with the transformation matrix. + // will be called immediately with the transformation matrix. void RegisterOnTransformationChangedCallback( const TransformationCallback& callback, bool run_immediately);
diff --git a/remoting/codec/webrtc_video_encoder_gpu.cc b/remoting/codec/webrtc_video_encoder_gpu.cc index 629ab03..0dde5cc 100644 --- a/remoting/codec/webrtc_video_encoder_gpu.cc +++ b/remoting/codec/webrtc_video_encoder_gpu.cc
@@ -93,7 +93,7 @@ // 3. In BeginInitialization(), the Core instance constructs the // VideoEncodeAccelerator using the saved dimensions from the DesktopFrame. // If the VideoEncodeAccelerator is constructed successfully, the state is -// set to INITIALIZING. If not, the state isset to INIITALIZATION_ERROR. +// set to INITIALIZING. If not, the state isset to INITIALIZATION_ERROR. // 4. Some time later, the VideoEncodeAccelerator sets itself up and is ready // to encode. At this point, it calls the Core instance's // RequireBitstreamBuffers() method. Once bitstream buffers are allocated,
diff --git a/remoting/host/audio_silence_detector.cc b/remoting/host/audio_silence_detector.cc index 6b4d0351d..400f6c4 100644 --- a/remoting/host/audio_silence_detector.cc +++ b/remoting/host/audio_silence_detector.cc
@@ -44,7 +44,7 @@ bool silent_packet = true; // Potentially this loop can be optimized (e.g. using SSE or adding special // case for threshold_==0), but it's not worth worrying about because the - // amount of data it processes is relaively small. + // amount of data it processes is relatively small. for (int i = 0; i < samples_count; ++i) { if (abs(samples[i]) > threshold_) { silent_packet = false;
diff --git a/remoting/host/curtain_mode_mac.cc b/remoting/host/curtain_mode_mac.cc index 0a36a0f..5000f697 100644 --- a/remoting/host/curtain_mode_mac.cc +++ b/remoting/host/curtain_mode_mac.cc
@@ -67,7 +67,7 @@ } // Used to detach the current session from the local console and disconnect -// the connnection if it gets re-attached. +// the connection if it gets re-attached. // // Because the switch-in handler can only called on the main (UI) thread, this // class installs the handler and detaches the current session from the console @@ -135,7 +135,7 @@ // Activate curtain asynchronously since it has to be done on the UI thread. // Because the curtain activation is asynchronous, it is possible that // the connection will not be curtained for a brief moment. This seems to be - // unaviodable as long as the curtain enforcement depends on processing of + // unavoidable as long as the curtain enforcement depends on processing of // the switch-in notifications. ui_task_runner_->PostTask( FROM_HERE, base::BindOnce(&SessionWatcher::ActivateCurtain, this));
diff --git a/remoting/host/desktop_resizer.h b/remoting/host/desktop_resizer.h index 478837d..8f414a8 100644 --- a/remoting/host/desktop_resizer.h +++ b/remoting/host/desktop_resizer.h
@@ -41,7 +41,7 @@ // Restore the original desktop resolution. The caller must provide the // original resolution of the desktop, as returned by |GetCurrentResolution|, - // as a hint. However, implementaions are free to ignore this. For example, + // as a hint. However, implementations are free to ignore this. For example, // virtual hosts will typically ignore it to avoid unnecessary resizes. virtual void RestoreResolution(const ScreenResolution& original) = 0; };
diff --git a/remoting/host/file_transfer/file_transfer_message_handler_unittest.cc b/remoting/host/file_transfer/file_transfer_message_handler_unittest.cc index bc248e2..89e317e 100644 --- a/remoting/host/file_transfer/file_transfer_message_handler_unittest.cc +++ b/remoting/host/file_transfer/file_transfer_message_handler_unittest.cc
@@ -296,7 +296,7 @@ fake_pipe_->ClosePipe(); const base::queue<std::string>& sent_messages = fake_pipe_->sent_messages(); - // First is the sucess message, second should be a protocol error. + // First is the success message, second should be a protocol error. ASSERT_EQ(2ul, sent_messages.size()); protocol::FileTransfer response; response.ParseFromString(sent_messages.back());
diff --git a/remoting/host/host_status_observer.h b/remoting/host/host_status_observer.h index 349a749..56165ab 100644 --- a/remoting/host/host_status_observer.h +++ b/remoting/host/host_status_observer.h
@@ -27,7 +27,7 @@ // A new client is authenticated. virtual void OnClientAuthenticated(const std::string& jid) {} - // All channels for an autheticated client are connected. + // All channels for an authenticated client are connected. virtual void OnClientConnected(const std::string& jid) {} // An authenticated client is disconnected.
diff --git a/remoting/host/input_monitor/local_hotkey_input_monitor.h b/remoting/host/input_monitor/local_hotkey_input_monitor.h index 49cb375..26af09cd 100644 --- a/remoting/host/input_monitor/local_hotkey_input_monitor.h +++ b/remoting/host/input_monitor/local_hotkey_input_monitor.h
@@ -18,7 +18,7 @@ namespace remoting { // Monitors the local input to notify about keyboard hotkeys. If implemented for -// the platform, catches the disconnection keyboard shortcut (Ctlr-Alt-Esc) and +// the platform, catches the disconnection keyboard shortcut (Ctrl-Alt-Esc) and // invokes |disconnect_callback| when this key combination is pressed. class LocalHotkeyInputMonitor { public:
diff --git a/remoting/host/native_messaging/log_message_handler.cc b/remoting/host/native_messaging/log_message_handler.cc index 15c155dd..5c6a0b5c 100644 --- a/remoting/host/native_messaging/log_message_handler.cc +++ b/remoting/host/native_messaging/log_message_handler.cc
@@ -83,7 +83,7 @@ // This method is always called under the global lock, so post a task to // handle the log message, even if we're already on the correct thread. - // This alows the lock to be released quickly. + // This allows the lock to be released quickly. // // Note that this means that LOG(FATAL) messages will be lost because the // process will exit before the message is sent to the client.
diff --git a/remoting/host/security_key/security_key_ipc_client_unittest.cc b/remoting/host/security_key/security_key_ipc_client_unittest.cc index 4e8af29..56398bd3 100644 --- a/remoting/host/security_key/security_key_ipc_client_unittest.cc +++ b/remoting/host/security_key/security_key_ipc_client_unittest.cc
@@ -327,7 +327,7 @@ mojo::NamedPlatformChannel::ServerNameFromUTF8( kNonexistentIpcChannelName)); - // Attempt to establish the conection (should fail since the IPC channel does + // Attempt to establish the connection (should fail since the IPC channel does // not exist). security_key_ipc_client_.EstablishIpcConnection( base::BindOnce(&SecurityKeyIpcClientTest::ConnectionStateHandler,
diff --git a/remoting/host/setup/test_util.cc b/remoting/host/setup/test_util.cc index ad80af6..5b82005 100644 --- a/remoting/host/setup/test_util.cc +++ b/remoting/host/setup/test_util.cc
@@ -36,4 +36,4 @@ #endif } -} // namepsace remoting +} // namespace remoting
diff --git a/remoting/host/win/elevated_native_messaging_host.h b/remoting/host/win/elevated_native_messaging_host.h index 40eb5e4d..f251b15 100644 --- a/remoting/host/win/elevated_native_messaging_host.h +++ b/remoting/host/win/elevated_native_messaging_host.h
@@ -62,7 +62,7 @@ // Handle of the parent window. intptr_t parent_window_handle_; - // Indicates whether the launched process should be elevated when lauinched. + // Indicates whether the launched process should be elevated when launched. // Note: Binaries with uiaccess run at a higher UIPI level than the launching // process so they still need to be launched and controlled by this class but // do not require traditional elevation to function.
diff --git a/remoting/host/win/worker_process_launcher_unittest.cc b/remoting/host/win/worker_process_launcher_unittest.cc index f9843f2..3829f025 100644 --- a/remoting/host/win/worker_process_launcher_unittest.cc +++ b/remoting/host/win/worker_process_launcher_unittest.cc
@@ -370,8 +370,8 @@ PROCESS_INFORMATION temp_process_info = {}; ASSERT_TRUE(CreateProcess(nullptr, notepad, - nullptr, // default process attibutes - nullptr, // default thread attibutes + nullptr, // default process attributes + nullptr, // default thread attributes FALSE, // do not inherit handles CREATE_SUSPENDED, nullptr, // no environment
diff --git a/remoting/ios/display/gl_display_handler.mm b/remoting/ios/display/gl_display_handler.mm index 57e2c9921..cb39fadc 100644 --- a/remoting/ios/display/gl_display_handler.mm +++ b/remoting/ios/display/gl_display_handler.mm
@@ -125,7 +125,7 @@ eagl_context_ = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3]; if (!eagl_context_) { - LOG(WARNING) << "Failed to create GLES3 context. Atempting to create " + LOG(WARNING) << "Failed to create GLES3 context. Attempting to create " << "GLES2 context."; eagl_context_ = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
diff --git a/remoting/signaling/fake_signal_strategy.h b/remoting/signaling/fake_signal_strategy.h index 753deba..da7cbbe 100644 --- a/remoting/signaling/fake_signal_strategy.h +++ b/remoting/signaling/fake_signal_strategy.h
@@ -28,7 +28,7 @@ using PeerCallback = base::RepeatingCallback<void( std::unique_ptr<jingle_xmpp::XmlElement> message)>; - // Calls ConenctTo() to connect |peer1| and |peer2|. Both |peer1| and |peer2| + // Calls ConnectTo() to connect |peer1| and |peer2|. Both |peer1| and |peer2| // must belong to the current thread. static void Connect(FakeSignalStrategy* peer1, FakeSignalStrategy* peer2);
diff --git a/sandbox/win/src/handle_closer_agent.cc b/sandbox/win/src/handle_closer_agent.cc index 0b0de36..a0bb656 100644 --- a/sandbox/win/src/handle_closer_agent.cc +++ b/sandbox/win/src/handle_closer_agent.cc
@@ -4,14 +4,13 @@ #include "sandbox/win/src/handle_closer_agent.h" -#include <limits.h> #include <stddef.h> -#include <cstdint> #include "base/check.h" #include "base/win/static_constants.h" -#include "base/win/win_util.h" +#include "base/win/windows_version.h" #include "sandbox/win/src/win_utils.h" +#include "third_party/abseil-cpp/absl/types/optional.h" namespace sandbox { @@ -143,56 +142,45 @@ } bool HandleCloserAgent::CloseHandles() { - DWORD handle_count = UINT_MAX; - const int kInvalidHandleThreshold = 100; - const size_t kHandleOffset = 4; // Handles are always a multiple of 4. - - if (!::GetProcessHandleCount(::GetCurrentProcess(), &handle_count)) - return false; - // Skip closing these handles when Application Verifier is in use in order to // avoid invalid-handle exceptions. if (GetModuleHandleA(base::win::kApplicationVerifierDllName)) return true; + // If the accurate handle enumeration fails then fallback to the old brute + // force approach. This should only happen on Windows 7. + absl::optional<ProcessHandleMap> handle_map = GetCurrentProcessHandles(); + if (!handle_map) { + DCHECK(base::win::GetVersion() < base::win::Version::WIN8); + handle_map = GetCurrentProcessHandlesWin7(); + } - uint32_t handle_value = 0; - int invalid_count = 0; + if (!handle_map) + return false; - // Keep incrementing until we hit the number of handles reported by - // GetProcessHandleCount(). If we hit a very long sequence of invalid - // handles we assume that we've run past the end of the table. - while (handle_count && invalid_count < kInvalidHandleThreshold) { - handle_value += kHandleOffset; - HANDLE handle = base::win::Uint32ToHandle(handle_value); - std::wstring type_name; - if (!GetTypeNameFromHandle(handle, &type_name)) { - ++invalid_count; + for (const HandleMap::value_type& handle_to_close : handles_to_close_) { + ProcessHandleMap::iterator result = handle_map->find(handle_to_close.first); + if (result == handle_map->end()) continue; - } - - --handle_count; - // Check if we're looking for this type of handle. - HandleMap::iterator result = handles_to_close_.find(type_name); - if (result == handles_to_close_.end()) - continue; - - HandleMap::mapped_type& names = result->second; - // Empty set means close all handles of this type; otherwise check name. - if (!names.empty()) { - std::wstring handle_name; - // Move on to the next handle if this name doesn't match. - if (!GetPathFromHandle(handle, &handle_name) || - !names.count(handle_name)) { - continue; + const HandleMap::mapped_type& names = handle_to_close.second; + for (HANDLE handle : result->second) { + // Empty set means close all handles of this type; otherwise check name. + if (!names.empty()) { + std::wstring handle_name; + // Move on to the next handle if this name doesn't match. + if (!GetPathFromHandle(handle, &handle_name) || + !names.count(handle_name)) { + continue; + } } - } - if (!::SetHandleInformation(handle, HANDLE_FLAG_PROTECT_FROM_CLOSE, 0)) - return false; - if (!::CloseHandle(handle)) - return false; - // Attempt to stuff this handle with a new dummy Event. - AttemptToStuffHandleSlot(handle, result->first); + // If we can't unprotect or close the handle we should keep going. + if (!::SetHandleInformation(handle, HANDLE_FLAG_PROTECT_FROM_CLOSE, 0)) + continue; + if (!::CloseHandle(handle)) + continue; + // Attempt to stuff this handle with a new dummy Event. + AttemptToStuffHandleSlot(handle, result->first); + } } return true;
diff --git a/sandbox/win/src/nt_internals.h b/sandbox/win/src/nt_internals.h index 79784aa..f9847fc 100644 --- a/sandbox/win/src/nt_internals.h +++ b/sandbox/win/src/nt_internals.h
@@ -313,7 +313,8 @@ // Partial definition only: typedef enum _PROCESSINFOCLASS { ProcessBasicInformation = 0, - ProcessExecuteFlags = 0x22 + ProcessExecuteFlags = 0x22, + ProcessHandleTable = 0x3A } PROCESSINFOCLASS; // For the structure documentation, see
diff --git a/sandbox/win/src/win_utils.cc b/sandbox/win/src/win_utils.cc index 364b2c3..611127d 100644 --- a/sandbox/win/src/win_utils.cc +++ b/sandbox/win/src/win_utils.cc
@@ -20,6 +20,7 @@ #include "base/numerics/safe_math.h" #include "base/strings/string_util.h" #include "base/win/pe_image.h" +#include "base/win/win_util.h" #include "sandbox/win/src/internal_types.h" #include "sandbox/win/src/nt_internals.h" #include "sandbox/win/src/sandbox_nt_util.h" @@ -561,6 +562,72 @@ return base_address; } +absl::optional<ProcessHandleMap> GetCurrentProcessHandles() { + NtQueryInformationProcessFunction query_information_process = nullptr; + ResolveNTFunctionPtr("NtQueryInformationProcess", &query_information_process); + if (!query_information_process) + return absl::nullopt; + + DWORD handle_count; + if (!::GetProcessHandleCount(::GetCurrentProcess(), &handle_count)) + return absl::nullopt; + + // The system call will return only handles up to the buffer size so add a + // margin of error of an additional 1000 handles. + std::vector<char> buffer((handle_count + 1000) * sizeof(uint32_t)); + DWORD return_length; + NTSTATUS status = query_information_process( + ::GetCurrentProcess(), ProcessHandleTable, buffer.data(), + static_cast<ULONG>(buffer.size()), &return_length); + + if (!NT_SUCCESS(status)) { + ::SetLastError(GetLastErrorFromNtStatus(status)); + return absl::nullopt; + } + DCHECK(buffer.size() >= return_length); + DCHECK((buffer.size() % sizeof(uint32_t)) == 0); + ProcessHandleMap handle_map; + const uint32_t* handle_values = reinterpret_cast<uint32_t*>(buffer.data()); + size_t count = return_length / sizeof(uint32_t); + for (size_t index = 0; index < count; ++index) { + HANDLE handle = base::win::Uint32ToHandle(handle_values[index]); + std::wstring type_name; + if (GetTypeNameFromHandle(handle, &type_name)) + handle_map[type_name].push_back(handle); + } + return handle_map; +} + +absl::optional<ProcessHandleMap> GetCurrentProcessHandlesWin7() { + DWORD handle_count = UINT_MAX; + const int kInvalidHandleThreshold = 100; + const size_t kHandleOffset = 4; // Handles are always a multiple of 4. + + if (!::GetProcessHandleCount(::GetCurrentProcess(), &handle_count)) + return absl::nullopt; + ProcessHandleMap handle_map; + + uint32_t handle_value = 0; + int invalid_count = 0; + + // Keep incrementing until we hit the number of handles reported by + // GetProcessHandleCount(). If we hit a very long sequence of invalid + // handles we assume that we've run past the end of the table. + while (handle_count && invalid_count < kInvalidHandleThreshold) { + handle_value += kHandleOffset; + HANDLE handle = base::win::Uint32ToHandle(handle_value); + std::wstring type_name; + if (!GetTypeNameFromHandle(handle, &type_name)) { + ++invalid_count; + continue; + } + + --handle_count; + handle_map[type_name].push_back(handle); + } + return handle_map; +} + } // namespace sandbox void ResolveNTFunctionPtr(const char* name, void* ptr) {
diff --git a/sandbox/win/src/win_utils.h b/sandbox/win/src/win_utils.h index ce96c0f..2acbe034 100644 --- a/sandbox/win/src/win_utils.h +++ b/sandbox/win/src/win_utils.h
@@ -7,11 +7,14 @@ #include <stdlib.h> +#include <map> #include <memory> #include <string> +#include <vector> #include "base/cxx17_backports.h" #include "base/win/windows_types.h" +#include "third_party/abseil-cpp/absl/types/optional.h" namespace sandbox { @@ -22,6 +25,9 @@ const wchar_t kNTDevicePrefix[] = L"\\Device\\"; const size_t kNTDevicePrefixLen = base::size(kNTDevicePrefix) - 1; +// List of handles mapped to their kernel object type name. +using ProcessHandleMap = std::map<std::wstring, std::vector<HANDLE>>; + // Basic implementation of a singleton which calls the destructor // when the exe is shutting down or the DLL is being unloaded. template <typename Derived> @@ -116,6 +122,18 @@ // the base address. This should only be called on new, suspended processes. void* GetProcessBaseAddress(HANDLE process); +// Returns a map of handles open in the current process. The call will only +// works on Windows 8+. The map is keyed by the kernel object type name. If +// querying the handles fails an empty optional value is returned. Note that +// unless all threads are suspended in the process the valid handles could +// change between the return of the list and when you use them. +absl::optional<ProcessHandleMap> GetCurrentProcessHandles(); + +// Fallback function for GetCurrentProcessHandles. Should only be needed on +// Windows 7 which doesn't support the API to query all process handles. This +// uses a brute force method to get the process handles. +absl::optional<ProcessHandleMap> GetCurrentProcessHandlesWin7(); + } // namespace sandbox // Resolves a function name in NTDLL to a function pointer. The second parameter
diff --git a/sandbox/win/src/win_utils_unittest.cc b/sandbox/win/src/win_utils_unittest.cc index a84db93..4469da4c 100644 --- a/sandbox/win/src/win_utils_unittest.cc +++ b/sandbox/win/src/win_utils_unittest.cc
@@ -8,6 +8,7 @@ #include <psapi.h> +#include <algorithm> #include <vector> #include "base/files/file_path.h" @@ -20,6 +21,7 @@ #include "base/strings/stringprintf.h" #include "base/win/scoped_handle.h" #include "base/win/scoped_process_information.h" +#include "base/win/windows_version.h" #include "sandbox/win/src/nt_internals.h" #include "sandbox/win/tests/common/test_utils.h" #include "testing/gtest/include/gtest/gtest.h" @@ -80,6 +82,35 @@ EXPECT_TRUE(base::EqualsCaseInsensitiveASCII(type_name, expected_type)); } +void FindHandle(const ProcessHandleMap& handle_map, + const wchar_t* type_name, + const base::win::ScopedHandle& handle) { + ProcessHandleMap::const_iterator entry = handle_map.find(type_name); + ASSERT_NE(handle_map.end(), entry); + const std::vector<HANDLE>& handles = entry->second; + EXPECT_NE(handles.cend(), + std::find(handles.cbegin(), handles.cend(), handle.Get())); +} + +void TestCurrentProcessHandles(absl::optional<ProcessHandleMap> (*func)()) { + std::wstring random_name = GetRandomName(); + ASSERT_FALSE(random_name.empty()); + base::win::ScopedHandle event_handle( + ::CreateEvent(nullptr, FALSE, FALSE, random_name.c_str())); + ASSERT_TRUE(event_handle.IsValid()); + std::wstring pipe_name = L"\\\\.\\pipe\\" + random_name; + base::win::ScopedHandle pipe_handle(::CreateNamedPipe( + pipe_name.c_str(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE, + PIPE_UNLIMITED_INSTANCES, 0, 0, NMPWAIT_USE_DEFAULT_WAIT, nullptr)); + ASSERT_TRUE(pipe_handle.IsValid()); + + absl::optional<ProcessHandleMap> handle_map = func(); + ASSERT_TRUE(handle_map); + EXPECT_LE(2U, handle_map->size()); + FindHandle(*handle_map, L"Event", event_handle); + FindHandle(*handle_map, L"File", pipe_handle); +} + } // namespace TEST(WinUtils, IsReparsePoint) { @@ -296,4 +327,14 @@ CompareHandleType(pipe_handle, L"File"); } +TEST(WinUtils, GetCurrentProcessHandles) { + if (base::win::GetVersion() < base::win::Version::WIN8) { + ASSERT_FALSE(GetCurrentProcessHandles()); + EXPECT_EQ(DWORD{ERROR_INVALID_PARAMETER}, ::GetLastError()); + } else { + TestCurrentProcessHandles(GetCurrentProcessHandles); + } + TestCurrentProcessHandles(GetCurrentProcessHandlesWin7); +} + } // namespace sandbox
diff --git a/testing/scripts/test_traffic_annotation_auditor.py b/testing/scripts/test_traffic_annotation_auditor.py index cae6b87..2d47de1 100755 --- a/testing/scripts/test_traffic_annotation_auditor.py +++ b/testing/scripts/test_traffic_annotation_auditor.py
@@ -10,13 +10,14 @@ import json import os +import re import sys import tempfile import common -SHEET_CONFIG = { +WINDOWS_SHEET_CONFIG = { "spreadsheet_id": "1TmBr9jnf1-hrjntiVBzT9EtkINGrtoBYFMWad2MBeaY", "annotations_sheet_name": "Annotations", "changes_sheet_name": "Changes Stats", @@ -25,63 +26,106 @@ } +CHROMEOS_SHEET_CONFIG = { + "spreadsheet_id": "1928goWKy6LVdF9Nl5nV1OD260YC10dHsdrnHEGdGsg8", + "annotations_sheet_name": "Annotations", + "changes_sheet_name": "Changes Stats", + "silent_change_columns": [], + "last_update_column_name": "Last Update", +} + def is_windows(): return os.name == 'nt' +def is_chromeos(build_path): + current_platform = get_current_platform_from_gn_args(build_path) + return current_platform == "chromeos" + + +def get_sheet_config(build_path): + if is_windows(): + return WINDOWS_SHEET_CONFIG + if is_chromeos(build_path): + return CHROMEOS_SHEET_CONFIG + return None + + +def get_current_platform_from_gn_args(build_path): + if sys.platform.startswith("linux") and build_path is not None: + try: + with open(os.path.join(build_path, "args.gn")) as f: + gn_args = f.read() + if not gn_args: + logger.info("Could not retrieve args.gn") + + pattern = re.compile(r"^\s*target_os\s*=\s*\"chromeos\"\s*$", + re.MULTILINE) + if pattern.search(gn_args): + return "chromeos" + + except(valueError, OSError) as e: + logger.info(e) + + return None def main_run(args): annotations_file = tempfile.NamedTemporaryFile() annotations_filename = annotations_file.name annotations_file.close() + build_path = os.path.join(args.paths['checkout'], 'out', args.build_config_fs) command_line = [ sys.executable, os.path.join(common.SRC_DIR, 'tools', 'traffic_annotation', 'scripts', 'traffic_annotation_auditor_tests.py'), '--build-path', - os.path.join(args.paths['checkout'], 'out', args.build_config_fs), + build_path, '--annotations-file', annotations_filename, ] rc = common.run_command(command_line) - # Update the Google Sheets on success, but only on the Windows trybot. - if rc == 0 and is_windows(): - print("Tests succeeded. Updating annotations sheet...") - - config_file = tempfile.NamedTemporaryFile(delete=False) - json.dump(SHEET_CONFIG, config_file, indent=4) - config_filename = config_file.name - config_file.close() - - command_line = [ - 'vpython.bat', - os.path.join(common.SRC_DIR, 'tools', 'traffic_annotation', 'scripts', - 'update_annotations_sheet.py'), - '--force', - '--config-file', - config_filename, - '--annotations-file', - annotations_filename, - ] - rc = common.run_command(command_line) - - try: - os.remove(config_filename) - except OSError: - pass - + # Update the Google Sheets on success, but only on the Windows and ChromeOS + # trybot. + sheet_config = get_sheet_config(build_path) try: - os.remove(annotations_filename) - except OSError: - pass + if rc == 0 and sheet_config is not None: + print("Tests succeeded. Updating annotations sheet...") - failures = ['Please refer to stdout for errors.'] if rc else [] - common.record_local_script_results( - 'test_traffic_annotation_auditor', args.output, failures, True) + config_file = tempfile.NamedTemporaryFile(delete=False) + json.dump(sheet_config, config_file, indent=4) + config_filename = config_file.name + config_file.close() + + command_line = [ + 'vpython.bat', + os.path.join(common.SRC_DIR, 'tools', 'traffic_annotation', 'scripts', + 'update_annotations_sheet.py'), + '--force', + '--config-file', + config_filename, + '--annotations-file', + annotations_filename, + ] + rc = common.run_command(command_line) + else: + print("Test failed without updating the annotations sheet.") + except (valueError, OSError) as e: + print("Error updating the annotations sheet", e) + finally: + cleanup_file(annotations_filename) + cleanup_file(config_filename) + failures = ['Please refer to stdout for errors.'] if rc else [] + common.record_local_script_results( + 'test_traffic_annotation_auditor', args.output, failures, True) return rc +def cleanup_file(filename): + try: + os.remove(filename) + except OSError: + print("Could not remove file: ", filename) def main_compile_targets(args): json.dump(['traffic_annotation_proto'], args.output)
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index bc58700..f9d5f10e 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -3658,25 +3658,6 @@ ] } ], - "EnhancedProtectionPromoCard": [ - { - "platforms": [ - "android" - ], - "experiments": [ - { - "name": "Enabled", - "params": { - "MaxEnhancedProtectionPromoImpressions": "5", - "MaxSigninPromoImpressions": "5" - }, - "enable_features": [ - "EnhancedProtectionPromoCard" - ] - } - ] - } - ], "ExperimentalAccessibilityLabels": [ { "platforms": [
diff --git a/third_party/android_deps/buildSrc/src/main/groovy/BuildConfigGenerator.groovy b/third_party/android_deps/buildSrc/src/main/groovy/BuildConfigGenerator.groovy index 3007e96..3f35ca9 100644 --- a/third_party/android_deps/buildSrc/src/main/groovy/BuildConfigGenerator.groovy +++ b/third_party/android_deps/buildSrc/src/main/groovy/BuildConfigGenerator.groovy
@@ -803,6 +803,7 @@ // chrome/android/java/proguard.flags instead. sb.append(' ignore_proguard_configs = true\n') break + case 'androidx_biometric_biometric': case 'com_google_android_gms_play_services_base': sb.append(' bytecode_rewriter_target = "//build/android/bytecode:fragment_activity_replacer"\n') break
diff --git a/third_party/blink/public/common/media/video_capture.h b/third_party/blink/public/common/media/video_capture.h index a78c52b..a408b88 100644 --- a/third_party/blink/public/common/media/video_capture.h +++ b/third_party/blink/public/common/media/video_capture.h
@@ -62,6 +62,7 @@ VIDEO_CAPTURE_STATE_STOPPING, VIDEO_CAPTURE_STATE_STOPPED, VIDEO_CAPTURE_STATE_ERROR, + VIDEO_CAPTURE_STATE_ERROR_SYSTEM_PERMISSIONS_DENIED, VIDEO_CAPTURE_STATE_ENDED, VIDEO_CAPTURE_STATE_LAST = VIDEO_CAPTURE_STATE_ENDED };
diff --git a/third_party/blink/public/web/modules/mediastream/media_stream_video_source.h b/third_party/blink/public/web/modules/mediastream/media_stream_video_source.h index a82f5757..0f87646 100644 --- a/third_party/blink/public/web/modules/mediastream/media_stream_video_source.h +++ b/third_party/blink/public/web/modules/mediastream/media_stream_video_source.h
@@ -319,7 +319,7 @@ // in the context of the callback. If gUM fails, the implementation will // simply drop the references to the blink source and track which will lead // to this object being deleted. - void FinalizeAddPendingTracks(); + void FinalizeAddPendingTracks(mojom::MediaStreamRequestResult result); // Actually adds |track| to this source, provided the source has started. void FinalizeAddTrack(MediaStreamVideoTrack* track,
diff --git a/third_party/blink/renderer/core/animation/color_property_functions.cc b/third_party/blink/renderer/core/animation/color_property_functions.cc index 432e4e14..8b5d6b8 100644 --- a/third_party/blink/renderer/core/animation/color_property_functions.cc +++ b/third_party/blink/renderer/core/animation/color_property_functions.cc
@@ -158,6 +158,9 @@ case CSSPropertyID::kTextDecorationColor: style.SetTextDecorationColor(style_color); return; + case CSSPropertyID::kTextEmphasisColor: + style.SetTextEmphasisColor(style_color); + return; case CSSPropertyID::kColumnRuleColor: style.SetColumnRuleColor(style_color); return; @@ -214,6 +217,9 @@ case CSSPropertyID::kTextDecorationColor: style.SetInternalVisitedTextDecorationColor(style_color); return; + case CSSPropertyID::kTextEmphasisColor: + style.SetInternalVisitedTextEmphasisColor(style_color); + return; case CSSPropertyID::kColumnRuleColor: style.SetInternalVisitedColumnRuleColor(style_color); return;
diff --git a/third_party/blink/renderer/core/animation/css_interpolation_types_map.cc b/third_party/blink/renderer/core/animation/css_interpolation_types_map.cc index 247de328..4719ada 100644 --- a/third_party/blink/renderer/core/animation/css_interpolation_types_map.cc +++ b/third_party/blink/renderer/core/animation/css_interpolation_types_map.cc
@@ -224,6 +224,7 @@ case CSSPropertyID::kOutlineColor: case CSSPropertyID::kStopColor: case CSSPropertyID::kTextDecorationColor: + case CSSPropertyID::kTextEmphasisColor: case CSSPropertyID::kColumnRuleColor: case CSSPropertyID::kWebkitTextStrokeColor: applicable_types->push_back(
diff --git a/third_party/blink/renderer/core/css/css_properties.json5 b/third_party/blink/renderer/core/css/css_properties.json5 index a5ef8d4..7f1a1db 100644 --- a/third_party/blink/renderer/core/css/css_properties.json5 +++ b/third_party/blink/renderer/core/css/css_properties.json5
@@ -4985,6 +4985,7 @@ { name: "text-emphasis-color", property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal", "ColorIncludingFallback"], + interpolable: true, inherited: true, field_group: "*", field_template: "external", @@ -4992,6 +4993,8 @@ default_value: "StyleColor::CurrentColor()", type_name: "StyleColor", computed_style_custom_functions: ["getter"], + keywords: ["currentcolor"], + typedom_types: ["Keyword"], converter: "ConvertStyleColor", style_builder_template: "color", valid_for_marker: true, @@ -5002,7 +5005,7 @@ property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal"], inherited: true, field_group: "*", - field_size: 2, + field_size: 3, field_template: "primitive", default_value: "TextEmphasisPosition::kOverRight", type_name: "TextEmphasisPosition",
diff --git a/third_party/blink/renderer/core/css/css_property_equality.cc b/third_party/blink/renderer/core/css/css_property_equality.cc index 0d0d448..b4749b7 100644 --- a/third_party/blink/renderer/core/css/css_property_equality.cc +++ b/third_party/blink/renderer/core/css/css_property_equality.cc
@@ -389,6 +389,8 @@ return a.MathDepth() == b.MathDepth(); case CSSPropertyID::kAccentColor: return a.AccentColor() == b.AccentColor(); + case CSSPropertyID::kTextEmphasisColor: + return a.TextEmphasisColor() == b.TextEmphasisColor(); default: NOTREACHED(); return true;
diff --git a/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc b/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc index 72a7c9f..98becd7 100644 --- a/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc +++ b/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
@@ -8229,11 +8229,10 @@ } if (!over_under) return nullptr; - if (!left_right) - left_right = CSSIdentifierValue::Create(CSSValueID::kRight); CSSValueList* list = CSSValueList::CreateSpaceSeparated(); list->Append(*over_under); - list->Append(*left_right); + if (left_right) + list->Append(*left_right); return list; } @@ -8243,6 +8242,9 @@ bool allow_visited_style) const { CSSValueList* list = CSSValueList::CreateSpaceSeparated(); switch (style.GetTextEmphasisPosition()) { + case blink::TextEmphasisPosition::kOver: + list->Append(*CSSIdentifierValue::Create(CSSValueID::kOver)); + break; case blink::TextEmphasisPosition::kOverRight: list->Append(*CSSIdentifierValue::Create(CSSValueID::kOver)); list->Append(*CSSIdentifierValue::Create(CSSValueID::kRight)); @@ -8251,6 +8253,9 @@ list->Append(*CSSIdentifierValue::Create(CSSValueID::kOver)); list->Append(*CSSIdentifierValue::Create(CSSValueID::kLeft)); break; + case blink::TextEmphasisPosition::kUnder: + list->Append(*CSSIdentifierValue::Create(CSSValueID::kUnder)); + break; case blink::TextEmphasisPosition::kUnderRight: list->Append(*CSSIdentifierValue::Create(CSSValueID::kUnder)); list->Append(*CSSIdentifierValue::Create(CSSValueID::kRight));
diff --git a/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc b/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc index f7ff8aed..6f704a1 100644 --- a/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc +++ b/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc
@@ -1731,6 +1731,13 @@ const CSSValue& value) { const auto& list = To<CSSValueList>(value); CSSValueID first = To<CSSIdentifierValue>(list.Item(0)).GetValueID(); + if (list.length() < 2) { + if (first == CSSValueID::kOver) + return TextEmphasisPosition::kOver; + if (first == CSSValueID::kUnder) + return TextEmphasisPosition::kUnder; + return TextEmphasisPosition::kOverRight; + } CSSValueID second = To<CSSIdentifierValue>(list.Item(1)).GetValueID(); if (first == CSSValueID::kOver && second == CSSValueID::kRight) return TextEmphasisPosition::kOverRight;
diff --git a/third_party/blink/renderer/core/layout/layout_block_flow.h b/third_party/blink/renderer/core/layout/layout_block_flow.h index f134e673f4..ed30ea5 100644 --- a/third_party/blink/renderer/core/layout/layout_block_flow.h +++ b/third_party/blink/renderer/core/layout/layout_block_flow.h
@@ -363,7 +363,10 @@ // Implementation detail: At some point in the future there should be no flow // threads. Callers that only want to know if this is a fragmentation context // root (and don't depend on flow threads) should call this method. - bool IsFragmentationContextRoot() const { return MultiColumnFlowThread(); } + bool IsFragmentationContextRoot() const { + NOT_DESTROYED(); + return MultiColumnFlowThread(); + } void AddVisualOverflowFromInlineChildren();
diff --git a/third_party/blink/renderer/core/layout/layout_document_transition_content.h b/third_party/blink/renderer/core/layout/layout_document_transition_content.h index 33dc27b..d4c42d9 100644 --- a/third_party/blink/renderer/core/layout/layout_document_transition_content.h +++ b/third_party/blink/renderer/core/layout/layout_document_transition_content.h
@@ -19,6 +19,7 @@ ~LayoutDocumentTransitionContent() override; const char* GetName() const override { + NOT_DESTROYED(); return "LayoutDocumentTransitionContent"; } void OnIntrinsicSizeUpdated(const LayoutSize& intrinsic_size);
diff --git a/third_party/blink/renderer/core/layout/layout_grid.h b/third_party/blink/renderer/core/layout/layout_grid.h index 425ae33..c7da127 100644 --- a/third_party/blink/renderer/core/layout/layout_grid.h +++ b/third_party/blink/renderer/core/layout/layout_grid.h
@@ -99,11 +99,13 @@ wtf_size_t AutoRepeatCountForDirection( GridTrackSizingDirection direction) const final { + NOT_DESTROYED(); return base::checked_cast<wtf_size_t>(grid_->AutoRepeatTracks(direction)); } wtf_size_t ExplicitGridStartForDirection( GridTrackSizingDirection direction) const final { + NOT_DESTROYED(); return base::checked_cast<wtf_size_t>(grid_->ExplicitGridStart(direction)); }
diff --git a/third_party/blink/renderer/core/layout/layout_object.h b/third_party/blink/renderer/core/layout/layout_object.h index 32d201e4..9ca6575 100644 --- a/third_party/blink/renderer/core/layout/layout_object.h +++ b/third_party/blink/renderer/core/layout/layout_object.h
@@ -317,10 +317,6 @@ #endif #define NOT_DESTROYED() CheckIsNotDestroyed() -#if DCHECK_IS_ON() - bool IsDestroyed() const { return is_destroyed_; } -#endif - // Returns the name of the layout object. virtual const char* GetName() const = 0; @@ -1490,6 +1486,7 @@ return bitfields_.IsAtomicInlineLevel(); } bool IsBlockInInline() const { + NOT_DESTROYED(); return IsAnonymous() && !IsInline() && !IsFloatingOrOutOfFlowPositioned() && Parent() && Parent()->IsLayoutInline(); } @@ -3158,6 +3155,7 @@ // Whether this object's Node has a blocking wheel event handler on itself or // an ancestor. bool InsideBlockingWheelEventHandler() const { + NOT_DESTROYED(); return bitfields_.InsideBlockingWheelEventHandler(); } // Mark this object as having a |InsideBlockingWheelEventHandler| changed, and @@ -3166,12 +3164,15 @@ void MarkBlockingWheelEventHandlerChanged(); void MarkDescendantBlockingWheelEventHandlerChanged(); bool BlockingWheelEventHandlerChanged() const { + NOT_DESTROYED(); return bitfields_.BlockingWheelEventHandlerChanged(); } bool DescendantBlockingWheelEventHandlerChanged() const { + NOT_DESTROYED(); return bitfields_.DescendantBlockingWheelEventHandlerChanged(); } void UpdateInsideBlockingWheelEventHandler(bool inside) { + NOT_DESTROYED(); bitfields_.SetInsideBlockingWheelEventHandler(inside); } @@ -3469,9 +3470,11 @@ } bool IsLayoutNGObjectForCanvasFormattedText() const { + NOT_DESTROYED(); return bitfields_.IsLayoutNGObjectForCanvasFormattedText(); } void SetIsLayoutNGObjectForCanvasFormattedText(bool b) { + NOT_DESTROYED(); bitfields_.SetIsLayoutNGObjectForCanvasFormattedText(b); } @@ -3492,17 +3495,21 @@ } bool ShouldSkipNextLayoutShiftTracking() const { + NOT_DESTROYED(); return bitfields_.ShouldSkipNextLayoutShiftTracking(); } void SetShouldSkipNextLayoutShiftTracking(bool b) { + NOT_DESTROYED(); bitfields_.SetShouldSkipNextLayoutShiftTracking(b); } bool ShouldAssumePaintOffsetTranslationForLayoutShiftTracking() const { + NOT_DESTROYED(); return bitfields_ .ShouldAssumePaintOffsetTranslationForLayoutShiftTracking(); } void SetShouldAssumePaintOffsetTranslationForLayoutShiftTracking(bool b) { + NOT_DESTROYED(); bitfields_.SetShouldAssumePaintOffsetTranslationForLayoutShiftTracking(b); } @@ -3742,6 +3749,7 @@ } void SetMightTraversePhysicalFragments(bool b) { + NOT_DESTROYED(); bitfields_.SetMightTraversePhysicalFragments(b); } @@ -4243,7 +4251,6 @@ HasNonCollapsedBorderDecoration); // True at start of |Destroy()| before calling |WillBeDestroyed()|. - // TODO(yukiy): Remove this bitfield ADD_BOOLEAN_BITFIELD(being_destroyed_, BeingDestroyed); // From LayoutListMarkerImage @@ -4425,6 +4432,7 @@ private: friend class LineLayoutItem; friend class LocalFrameView; + friend class SubtreeLayoutScope; scoped_refptr<const ComputedStyle> style_;
diff --git a/third_party/blink/renderer/core/layout/layout_replaced.h b/third_party/blink/renderer/core/layout/layout_replaced.h index 590253c..27f026f 100644 --- a/third_party/blink/renderer/core/layout/layout_replaced.h +++ b/third_party/blink/renderer/core/layout/layout_replaced.h
@@ -81,7 +81,10 @@ NOT_DESTROYED(); return false; } - virtual bool DrawsBackgroundOntoContentLayer() const { return false; } + virtual bool DrawsBackgroundOntoContentLayer() const { + NOT_DESTROYED(); + return false; + } virtual void PaintReplaced(const PaintInfo&, const PhysicalOffset& paint_offset) const { NOT_DESTROYED();
diff --git a/third_party/blink/renderer/core/layout/ng/custom/layout_ng_custom.h b/third_party/blink/renderer/core/layout/ng/custom/layout_ng_custom.h index f366e95..4e52568 100644 --- a/third_party/blink/renderer/core/layout/ng/custom/layout_ng_custom.h +++ b/third_party/blink/renderer/core/layout/ng/custom/layout_ng_custom.h
@@ -25,10 +25,19 @@ explicit LayoutNGCustom(Element*); - const char* GetName() const override { return "LayoutNGCustom"; } - bool CreatesNewFormattingContext() const override { return true; } + const char* GetName() const override { + NOT_DESTROYED(); + return "LayoutNGCustom"; + } + bool CreatesNewFormattingContext() const override { + NOT_DESTROYED(); + return true; + } - bool IsLoaded() { return state_ != kUnloaded; } + bool IsLoaded() { + NOT_DESTROYED(); + return state_ != kUnloaded; + } void AddChild(LayoutObject* new_child, LayoutObject* before_child) override; void RemoveChild(LayoutObject* child) override; @@ -37,11 +46,13 @@ PaginationBreakability GetPaginationBreakability( FragmentationEngine) const final { + NOT_DESTROYED(); return kForbidBreaks; } private: bool IsOfType(LayoutObjectType type) const override { + NOT_DESTROYED(); return type == kLayoutObjectNGCustom || LayoutNGBlockFlow::IsOfType(type); }
diff --git a/third_party/blink/renderer/core/layout/ng/flex/layout_ng_flexible_box.h b/third_party/blink/renderer/core/layout/ng/flex/layout_ng_flexible_box.h index 2ed02092..13d9bcf 100644 --- a/third_party/blink/renderer/core/layout/ng/flex/layout_ng_flexible_box.h +++ b/third_party/blink/renderer/core/layout/ng/flex/layout_ng_flexible_box.h
@@ -35,9 +35,18 @@ void UpdateBlockLayout(bool relayout_children) override; - bool IsFlexibleBoxIncludingDeprecatedAndNG() const final { return true; } - bool IsFlexibleBoxIncludingNG() const final { return true; } - const char* GetName() const override { return "LayoutNGFlexibleBox"; } + bool IsFlexibleBoxIncludingDeprecatedAndNG() const final { + NOT_DESTROYED(); + return true; + } + bool IsFlexibleBoxIncludingNG() const final { + NOT_DESTROYED(); + return true; + } + const char* GetName() const override { + NOT_DESTROYED(); + return "LayoutNGFlexibleBox"; + } DevtoolsFlexInfo LayoutForDevtools(); @@ -47,6 +56,7 @@ void RemoveChild(LayoutObject*) override; bool IsOfType(LayoutObjectType type) const override { + NOT_DESTROYED(); return type == kLayoutObjectNGFlexibleBox || LayoutNGMixin<LayoutBlock>::IsOfType(type); }
diff --git a/third_party/blink/renderer/core/layout/ng/grid/layout_ng_grid.h b/third_party/blink/renderer/core/layout/ng/grid/layout_ng_grid.h index c230b19..10b78ec 100644 --- a/third_party/blink/renderer/core/layout/ng/grid/layout_ng_grid.h +++ b/third_party/blink/renderer/core/layout/ng/grid/layout_ng_grid.h
@@ -20,7 +20,10 @@ void UpdateBlockLayout(bool relayout_children) override; - const char* GetName() const override { return "LayoutNGGrid"; } + const char* GetName() const override { + NOT_DESTROYED(); + return "LayoutNGGrid"; + } const LayoutNGGridInterface* ToLayoutNGGridInterface() const final; @@ -46,6 +49,7 @@ protected: bool IsOfType(LayoutObjectType type) const override { + NOT_DESTROYED(); return type == kLayoutObjectNGGrid || LayoutNGMixin<LayoutBlock>::IsOfType(type); }
diff --git a/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.h b/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.h index 48a0dfe..094aa96 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.h +++ b/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_combine.h
@@ -28,8 +28,14 @@ String GetTextContent() const; // Compressed font - const Font& CompressedFont() const { return compressed_font_.value(); } - bool UsesCompressedFont() const { return compressed_font_.has_value(); } + const Font& CompressedFont() const { + NOT_DESTROYED(); + return compressed_font_.value(); + } + bool UsesCompressedFont() const { + NOT_DESTROYED(); + return compressed_font_.has_value(); + } void SetCompressedFont(const Font& font); // Scaling @@ -62,7 +68,10 @@ void ResetLayout(); void SetScaleX(float new_scale_x); - bool UsesScaleX() const { return scale_x_.has_value(); } + bool UsesScaleX() const { + NOT_DESTROYED(); + return scale_x_.has_value(); + } // Painting // |AdjustText{Left,Top}()| are called within affine transformed @@ -91,7 +100,10 @@ private: bool IsOfType(LayoutObjectType) const override; - const char* GetName() const override { return "LayoutNGTextCombine"; } + const char* GetName() const override { + NOT_DESTROYED(); + return "LayoutNGTextCombine"; + } // Helper functions for scaling. PhysicalOffset ApplyScaleX(const PhysicalOffset& offset) const;
diff --git a/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.h b/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.h index 18c3a21..aa4c6a3 100644 --- a/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.h +++ b/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.h
@@ -25,7 +25,10 @@ void UpdateBlockLayout(bool relayout_children) override; - const char* GetName() const override { return "LayoutNGBlockFlow"; } + const char* GetName() const override { + NOT_DESTROYED(); + return "LayoutNGBlockFlow"; + } protected: bool IsOfType(LayoutObjectType) const override;
diff --git a/third_party/blink/renderer/core/layout/ng/layout_ng_button.h b/third_party/blink/renderer/core/layout/ng/layout_ng_button.h index a853861..6064ed3 100644 --- a/third_party/blink/renderer/core/layout/ng/layout_ng_button.h +++ b/third_party/blink/renderer/core/layout/ng/layout_ng_button.h
@@ -15,18 +15,25 @@ ~LayoutNGButton() override; void Trace(Visitor*) const override; - const char* GetName() const override { return "LayoutNGButton"; } + const char* GetName() const override { + NOT_DESTROYED(); + return "LayoutNGButton"; + } void AddChild(LayoutObject* new_child, LayoutObject* before_child = nullptr) override; void RemoveChild(LayoutObject*) override; - void RemoveLeftoverAnonymousBlock(LayoutBlock*) override {} - bool CreatesAnonymousWrapper() const override { return true; } + void RemoveLeftoverAnonymousBlock(LayoutBlock*) override { NOT_DESTROYED(); } + bool CreatesAnonymousWrapper() const override { + NOT_DESTROYED(); + return true; + } private: void UpdateAnonymousChildStyle(const LayoutObject* child, ComputedStyle& child_style) const override; bool IsOfType(LayoutObjectType type) const override { + NOT_DESTROYED(); return type == kLayoutObjectNGButton || LayoutNGFlexibleBox::IsOfType(type); }
diff --git a/third_party/blink/renderer/core/layout/ng/layout_ng_fieldset.h b/third_party/blink/renderer/core/layout/ng/layout_ng_fieldset.h index 2e18729..ac872ba0 100644 --- a/third_party/blink/renderer/core/layout/ng/layout_ng_fieldset.h +++ b/third_party/blink/renderer/core/layout/ng/layout_ng_fieldset.h
@@ -14,12 +14,18 @@ public: explicit LayoutNGFieldset(Element*); - const char* GetName() const override { return "LayoutNGFieldset"; } + const char* GetName() const override { + NOT_DESTROYED(); + return "LayoutNGFieldset"; + } void AddChild(LayoutObject* new_child, LayoutObject* before_child = nullptr) override; - bool CreatesNewFormattingContext() const final { return true; } + bool CreatesNewFormattingContext() const final { + NOT_DESTROYED(); + return true; + } LayoutBlock* FindAnonymousFieldsetContentBox() const; @@ -34,7 +40,10 @@ const PhysicalOffset& accumulated_offset, HitTestAction hit_test_action) override; - bool AllowsNonVisibleOverflow() const override { return false; } + bool AllowsNonVisibleOverflow() const override { + NOT_DESTROYED(); + return false; + } // Override to forward to the anonymous fieldset content box. LayoutUnit ScrollWidth() const override; LayoutUnit ScrollHeight() const override;
diff --git a/third_party/blink/renderer/core/layout/ng/layout_ng_progress.h b/third_party/blink/renderer/core/layout/ng/layout_ng_progress.h index 39d2967..6bcfc62a 100644 --- a/third_party/blink/renderer/core/layout/ng/layout_ng_progress.h +++ b/third_party/blink/renderer/core/layout/ng/layout_ng_progress.h
@@ -23,7 +23,10 @@ void UpdateBlockLayout(bool relayout_children) override; - const char* GetName() const override { return "LayoutNGProgress"; } + const char* GetName() const override { + NOT_DESTROYED(); + return "LayoutNGProgress"; + } protected: bool IsOfType(LayoutObjectType type) const override;
diff --git a/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_as_block.h b/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_as_block.h index 1797f6d..d319d6a 100644 --- a/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_as_block.h +++ b/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_as_block.h
@@ -24,7 +24,10 @@ explicit LayoutNGRubyAsBlock(Element*); ~LayoutNGRubyAsBlock() override; - const char* GetName() const override { return "LayoutNGRubyAsBlock"; } + const char* GetName() const override { + NOT_DESTROYED(); + return "LayoutNGRubyAsBlock"; + } void UpdateBlockLayout(bool relayout_children) override; };
diff --git a/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_base.h b/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_base.h index 41e2f4e..e5b174f 100644 --- a/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_base.h +++ b/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_base.h
@@ -22,7 +22,10 @@ explicit LayoutNGRubyBase(); ~LayoutNGRubyBase() override; - const char* GetName() const override { return "LayoutNGRubyBase"; } + const char* GetName() const override { + NOT_DESTROYED(); + return "LayoutNGRubyBase"; + } void UpdateBlockLayout(bool relayout_children) override; };
diff --git a/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_run.h b/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_run.h index 5dcb636..9b6052b 100644 --- a/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_run.h +++ b/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_run.h
@@ -22,7 +22,10 @@ explicit LayoutNGRubyRun(); ~LayoutNGRubyRun() override; - const char* GetName() const override { return "LayoutNGRubyRun"; } + const char* GetName() const override { + NOT_DESTROYED(); + return "LayoutNGRubyRun"; + } void UpdateBlockLayout(bool relayout_children) override; };
diff --git a/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_text.h b/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_text.h index a51b923..e0b7a31 100644 --- a/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_text.h +++ b/third_party/blink/renderer/core/layout/ng/layout_ng_ruby_text.h
@@ -22,7 +22,10 @@ explicit LayoutNGRubyText(Element* element); ~LayoutNGRubyText() override; - const char* GetName() const override { return "LayoutNGRubyText"; } + const char* GetName() const override { + NOT_DESTROYED(); + return "LayoutNGRubyText"; + } void UpdateBlockLayout(bool relayout_children) override; };
diff --git a/third_party/blink/renderer/core/layout/ng/layout_ng_view.h b/third_party/blink/renderer/core/layout/ng/layout_ng_view.h index b21ee63d..068db64 100644 --- a/third_party/blink/renderer/core/layout/ng/layout_ng_view.h +++ b/third_party/blink/renderer/core/layout/ng/layout_ng_view.h
@@ -22,7 +22,10 @@ void UpdateBlockLayout(bool relayout_children) override; - const char* GetName() const override { return "LayoutNGView"; } + const char* GetName() const override { + NOT_DESTROYED(); + return "LayoutNGView"; + } protected: bool IsOfType(LayoutObjectType) const override;
diff --git a/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.h b/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.h index ebef26d1..e6231a1 100644 --- a/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.h +++ b/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.h
@@ -16,11 +16,15 @@ public: explicit LayoutNGListItem(Element*); - ListItemOrdinal& Ordinal() { return ordinal_; } + ListItemOrdinal& Ordinal() { + NOT_DESTROYED(); + return ordinal_; + } int Value() const; LayoutObject* Marker() const { + NOT_DESTROYED(); Element* list_item = To<Element>(GetNode()); return list_item->PseudoElementLayoutObject(kPseudoIdMarker); } @@ -33,7 +37,10 @@ static const LayoutObject* FindSymbolMarkerLayoutText(const LayoutObject*); - const char* GetName() const override { return "LayoutNGListItem"; } + const char* GetName() const override { + NOT_DESTROYED(); + return "LayoutNGListItem"; + } private: bool IsOfType(LayoutObjectType) const override;
diff --git a/third_party/blink/renderer/core/layout/ng/list/layout_ng_outside_list_marker.h b/third_party/blink/renderer/core/layout/ng/list/layout_ng_outside_list_marker.h index 3c49cad..a0165a8 100644 --- a/third_party/blink/renderer/core/layout/ng/list/layout_ng_outside_list_marker.h +++ b/third_party/blink/renderer/core/layout/ng/list/layout_ng_outside_list_marker.h
@@ -25,12 +25,21 @@ void WillCollectInlines() override; - const char* GetName() const override { return "LayoutNGOutsideListMarker"; } + const char* GetName() const override { + NOT_DESTROYED(); + return "LayoutNGOutsideListMarker"; + } bool NeedsOccupyWholeLine() const; - const ListMarker& Marker() const { return list_marker_; } - ListMarker& Marker() { return list_marker_; } + const ListMarker& Marker() const { + NOT_DESTROYED(); + return list_marker_; + } + ListMarker& Marker() { + NOT_DESTROYED(); + return list_marker_; + } PaginationBreakability GetPaginationBreakability( FragmentationEngine engine) const final;
diff --git a/third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block.h b/third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block.h index d2cde00..49cbc878 100644 --- a/third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block.h +++ b/third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block.h
@@ -13,7 +13,10 @@ public: explicit LayoutNGMathMLBlock(Element*); - const char* GetName() const override { return "LayoutNGMathMLBlock"; } + const char* GetName() const override { + NOT_DESTROYED(); + return "LayoutNGMathMLBlock"; + } private: void UpdateBlockLayout(bool relayout_children) final; @@ -25,6 +28,7 @@ PaginationBreakability GetPaginationBreakability( FragmentationEngine) const final { + NOT_DESTROYED(); return kForbidBreaks; } };
diff --git a/third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block_flow.h b/third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block_flow.h index a16ddc3..e8e6893 100644 --- a/third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block_flow.h +++ b/third_party/blink/renderer/core/layout/ng/mathml/layout_ng_mathml_block_flow.h
@@ -15,17 +15,25 @@ public: explicit LayoutNGMathMLBlockFlow(Element*); - const char* GetName() const final { return "LayoutNGMathMLBlockFlow"; } + const char* GetName() const final { + NOT_DESTROYED(); + return "LayoutNGMathMLBlockFlow"; + } private: bool IsOfType(LayoutObjectType) const final; bool IsChildAllowed(LayoutObject*, const ComputedStyle&) const final { + NOT_DESTROYED(); return true; } - bool CreatesNewFormattingContext() const final { return true; } + bool CreatesNewFormattingContext() const final { + NOT_DESTROYED(); + return true; + } PaginationBreakability GetPaginationBreakability( FragmentationEngine) const final { + NOT_DESTROYED(); return kForbidBreaks; } };
diff --git a/third_party/blink/renderer/core/layout/ng/table/layout_ng_table.h b/third_party/blink/renderer/core/layout/ng/table/layout_ng_table.h index 8d20fed..d56ceeb 100644 --- a/third_party/blink/renderer/core/layout/ng/table/layout_ng_table.h +++ b/third_party/blink/renderer/core/layout/ng/table/layout_ng_table.h
@@ -178,18 +178,20 @@ unsigned absolute_column_index) const final; // NG does not need this method. Sections are not cached. - void RecalcSectionsIfNeeded() const final {} + void RecalcSectionsIfNeeded() const final { NOT_DESTROYED(); } // Not used by NG. Legacy caches sections. void ForceSectionsRecalc() final { NOT_DESTROYED(); } // Used in paint for printing. Should not be needed by NG. LayoutUnit RowOffsetFromRepeatingFooter() const final { + NOT_DESTROYED(); NOTIMPLEMENTED(); // OK, never used. return LayoutUnit(); } // Used in paint for printing. Should not be needed by NG. LayoutUnit RowOffsetFromRepeatingHeader() const final { + NOT_DESTROYED(); NOTIMPLEMENTED(); // OK, never used. return LayoutUnit(); } @@ -206,16 +208,19 @@ // Following methods are called during printing, not in TablesNG. LayoutNGTableSectionInterface* TopNonEmptySectionInterface() const final { + NOT_DESTROYED(); NOTREACHED(); return nullptr; } LayoutNGTableSectionInterface* BottomSectionInterface() const final { + NOT_DESTROYED(); NOTREACHED(); return nullptr; } LayoutNGTableSectionInterface* BottomNonEmptySectionInterface() const final { + NOT_DESTROYED(); NOTREACHED(); return nullptr; }
diff --git a/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_caption.h b/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_caption.h index f62eaa2..5857216 100644 --- a/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_caption.h +++ b/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_caption.h
@@ -26,7 +26,10 @@ void UpdateBlockLayout(bool relayout_children) override; - const char* GetName() const override { return "LayoutNGTableCaption"; } + const char* GetName() const override { + NOT_DESTROYED(); + return "LayoutNGTableCaption"; + } private: // Legacy-only API.
diff --git a/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row.h b/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row.h index 5c567cf6..9d62944 100644 --- a/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row.h +++ b/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_row.h
@@ -30,7 +30,10 @@ // LayoutBlock methods start. - void UpdateBlockLayout(bool relayout_children) override { NOTREACHED(); } + void UpdateBlockLayout(bool relayout_children) override { + NOT_DESTROYED(); + NOTREACHED(); + } const char* GetName() const override { NOT_DESTROYED();
diff --git a/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section.h b/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section.h index ceb2b58..73d97141 100644 --- a/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section.h +++ b/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_section.h
@@ -26,7 +26,10 @@ // LayoutBlock methods start. - void UpdateBlockLayout(bool relayout_children) override { NOTREACHED(); } + void UpdateBlockLayout(bool relayout_children) override { + NOT_DESTROYED(); + NOTREACHED(); + } const char* GetName() const override { NOT_DESTROYED();
diff --git a/third_party/blink/renderer/core/layout/subtree_layout_scope.cc b/third_party/blink/renderer/core/layout/subtree_layout_scope.cc index 8af6504e..39d2695 100644 --- a/third_party/blink/renderer/core/layout/subtree_layout_scope.cc +++ b/third_party/blink/renderer/core/layout/subtree_layout_scope.cc
@@ -51,7 +51,7 @@ // have been marked for layout. Skip such LayoutObject to avoid that // NOT_DESTROYED() triggers a DCHECK failure in AssertLaidOut() or // AssertFragmentTree(). - if (layout_object->IsDestroyed()) { + if (layout_object->is_destroyed_) { DCHECK(RuntimeEnabledFeatures::CSSContainerQueriesEnabled()); continue; }
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_container.h b/third_party/blink/renderer/core/layout/svg/layout_svg_container.h index 4d800dc0..2e61743 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_container.h +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_container.h
@@ -89,7 +89,10 @@ NOT_DESTROYED(); return &content_.Children(); } - SVGContentContainer& Content() { return content_; } + SVGContentContainer& Content() { + NOT_DESTROYED(); + return content_; + } bool IsOfType(LayoutObjectType type) const override { NOT_DESTROYED();
diff --git a/third_party/blink/renderer/core/paint/text_painter_base.cc b/third_party/blink/renderer/core/paint/text_painter_base.cc index c24cb3c..9f4c827 100644 --- a/third_party/blink/renderer/core/paint/text_painter_base.cc +++ b/third_party/blink/renderer/core/paint/text_painter_base.cc
@@ -54,17 +54,12 @@ if (!font_data || emphasis_mark.IsNull()) { emphasis_mark_offset_ = 0; - } else if ((horizontal_ && (position == TextEmphasisPosition::kOverRight || - position == TextEmphasisPosition::kOverLeft)) || - (!horizontal_ && - (position == TextEmphasisPosition::kOverRight || - position == TextEmphasisPosition::kUnderRight))) { + } else if ((horizontal_ && IsOver(position)) || + (!horizontal_ && IsRight(position))) { emphasis_mark_offset_ = -font_data->GetFontMetrics().Ascent() - font_.EmphasisMarkDescent(emphasis_mark); } else { - DCHECK(position == TextEmphasisPosition::kUnderRight || - position == TextEmphasisPosition::kUnderLeft || - position == TextEmphasisPosition::kOverLeft); + DCHECK(!IsOver(position) || position == TextEmphasisPosition::kOverLeft); emphasis_mark_offset_ = font_data->GetFontMetrics().Descent() + font_.EmphasisMarkAscent(emphasis_mark); }
diff --git a/third_party/blink/renderer/core/style/computed_style.cc b/third_party/blink/renderer/core/style/computed_style.cc index 4a66636d..99b9dbf 100644 --- a/third_party/blink/renderer/core/style/computed_style.cc +++ b/third_party/blink/renderer/core/style/computed_style.cc
@@ -1730,22 +1730,11 @@ LineLogicalSide ComputedStyle::GetTextEmphasisLineLogicalSide() const { TextEmphasisPosition position = GetTextEmphasisPosition(); - if (IsHorizontalWritingMode()) { - return position == TextEmphasisPosition::kOverRight || - position == TextEmphasisPosition::kOverLeft - ? LineLogicalSide::kOver - : LineLogicalSide::kUnder; - } - if (GetWritingMode() != WritingMode::kSidewaysLr) { - return position == TextEmphasisPosition::kOverRight || - position == TextEmphasisPosition::kUnderRight - ? LineLogicalSide::kOver - : LineLogicalSide::kUnder; - } - return position == TextEmphasisPosition::kOverLeft || - position == TextEmphasisPosition::kUnderLeft - ? LineLogicalSide::kOver - : LineLogicalSide::kUnder; + if (IsHorizontalWritingMode()) + return IsOver(position) ? LineLogicalSide::kOver : LineLogicalSide::kUnder; + if (GetWritingMode() != WritingMode::kSidewaysLr) + return IsRight(position) ? LineLogicalSide::kOver : LineLogicalSide::kUnder; + return IsLeft(position) ? LineLogicalSide::kOver : LineLogicalSide::kUnder; } CSSAnimationData& ComputedStyle::AccessAnimations() {
diff --git a/third_party/blink/renderer/core/style/computed_style_constants.h b/third_party/blink/renderer/core/style/computed_style_constants.h index 8f4fa0a..9d324c12 100644 --- a/third_party/blink/renderer/core/style/computed_style_constants.h +++ b/third_party/blink/renderer/core/style/computed_style_constants.h
@@ -314,12 +314,31 @@ }; enum class TextEmphasisPosition : unsigned { + kOver, // Same as kOverRight kOverRight, kOverLeft, + kUnder, // Same as kUnderRight kUnderRight, kUnderLeft, }; +inline bool IsOver(TextEmphasisPosition position) { + return position == TextEmphasisPosition::kOver || + position == TextEmphasisPosition::kOverRight || + position == TextEmphasisPosition::kOverLeft; +} + +inline bool IsRight(TextEmphasisPosition position) { + return position == TextEmphasisPosition::kOver || + position == TextEmphasisPosition::kOverRight || + position == TextEmphasisPosition::kUnder || + position == TextEmphasisPosition::kUnderRight; +} + +inline bool IsLeft(TextEmphasisPosition position) { + return !IsRight(position); +} + enum class LineLogicalSide { kOver, kUnder,
diff --git a/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler.cc b/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler.cc index 8b7a301..70c92ad 100644 --- a/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler.cc +++ b/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler.cc
@@ -215,7 +215,7 @@ std::make_unique<CanvasCaptureHandlerDelegate>(new_frame_callback); DCHECK(delegate_); ask_for_new_frame_ = true; - running_callback.Run(true); + running_callback.Run(RunState::kRunning); } void CanvasCaptureHandler::RequestRefreshFrame() {
diff --git a/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler_unittest.cc b/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler_unittest.cc index adf53c7..fc28f85 100644 --- a/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler_unittest.cc +++ b/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler_unittest.cc
@@ -18,6 +18,7 @@ #include "third_party/blink/renderer/platform/mediastream/media_stream_component.h" #include "third_party/blink/renderer/platform/mediastream/media_stream_source.h" #include "third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.h" +#include "third_party/blink/renderer/platform/video_capture/video_capturer_source.h" #include "third_party/skia/include/core/SkImage.h" #include "third_party/skia/include/core/SkRefCnt.h" #include "ui/gfx/geometry/size.h" @@ -85,7 +86,10 @@ } MOCK_METHOD1(DoOnRunning, void(bool)); - void OnRunning(bool state) { DoOnRunning(state); } + void OnRunning(blink::RunState run_state) { + bool state = (run_state == blink::RunState::kRunning) ? true : false; + DoOnRunning(state); + } // Verify returned frames. static scoped_refptr<StaticBitmapImage> GenerateTestImage(bool opaque,
diff --git a/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source.cc b/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source.cc index 206dc99c..3b6bb2d 100644 --- a/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source.cc +++ b/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source.cc
@@ -80,7 +80,7 @@ running_callback_ = running_callback; if (!web_media_player_ || !web_media_player_->HasVideo()) { - running_callback_.Run(false); + running_callback_.Run(RunState::kStopped); return; } @@ -91,7 +91,7 @@ std::min(static_cast<float>(media::limits::kMaxFramesPerSecond), params.requested_format.frame_rate)); - running_callback_.Run(true); + running_callback_.Run(RunState::kRunning); task_runner_->PostTask( FROM_HERE, WTF::Bind(&HtmlVideoElementCapturerSource::sendNewFrame, weak_factory_.GetWeakPtr()));
diff --git a/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source_unittest.cc b/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source_unittest.cc index 9ff809e..a3f9a0b 100644 --- a/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source_unittest.cc +++ b/third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source_unittest.cc
@@ -140,7 +140,10 @@ } MOCK_METHOD1(DoOnRunning, void(bool)); - void OnRunning(bool state) { DoOnRunning(state); } + void OnRunning(blink::RunState run_state) { + bool state = (run_state == blink::RunState::kRunning) ? true : false; + DoOnRunning(state); + } void SetVideoPlayerOpacity(bool opacity) { web_media_player_->is_video_opaque_ = opacity; @@ -159,6 +162,18 @@ // and its inner object(s). This is a non trivial sequence. TEST_F(HTMLVideoElementCapturerSourceTest, ConstructAndDestruct) {} +TEST_F(HTMLVideoElementCapturerSourceTest, EmptyWebMediaPlayerFailsCapture) { + web_media_player_.reset(); + EXPECT_CALL(*this, DoOnRunning(false)).Times(1); + + html_video_capturer_->StartCapture( + media::VideoCaptureParams(), + WTF::BindRepeating(&HTMLVideoElementCapturerSourceTest::OnDeliverFrame, + base::Unretained(this)), + WTF::BindRepeating(&HTMLVideoElementCapturerSourceTest::OnRunning, + base::Unretained(this))); +} + // Checks that the usual sequence of GetPreferredFormats() -> // StartCapture() -> StopCapture() works as expected and let it capture two // frames, that are tested for format vs the expected source opacity.
diff --git a/third_party/blink/renderer/modules/mediastream/local_video_capturer_source.cc b/third_party/blink/renderer/modules/mediastream/local_video_capturer_source.cc index db6b4fe4..987c5782 100644 --- a/third_party/blink/renderer/modules/mediastream/local_video_capturer_source.cc +++ b/third_party/blink/renderer/modules/mediastream/local_video_capturer_source.cc
@@ -104,18 +104,24 @@ OnLog("LocalVideoCapturerSource::OnStateUpdate discarding state update."); return; } + RunState run_state = + (state == VIDEO_CAPTURE_STATE_ERROR_SYSTEM_PERMISSIONS_DENIED) + ? RunState::kSystemPermissionsError + : RunState::kStopped; + auto* frame = LocalFrame::FromFrameToken(frame_token_); switch (state) { case VIDEO_CAPTURE_STATE_STARTED: OnLog( "LocalVideoCapturerSource::OnStateUpdate signaling to " "consumer that source is now running."); - running_callback_.Run(true); + running_callback_.Run(RunState::kRunning); break; case VIDEO_CAPTURE_STATE_STOPPING: case VIDEO_CAPTURE_STATE_STOPPED: case VIDEO_CAPTURE_STATE_ERROR: + case VIDEO_CAPTURE_STATE_ERROR_SYSTEM_PERMISSIONS_DENIED: case VIDEO_CAPTURE_STATE_ENDED: std::move(release_device_cb_).Run(); release_device_cb_ = @@ -126,7 +132,7 @@ OnLog( "LocalVideoCapturerSource::OnStateUpdate signaling to " "consumer that source is no longer running."); - running_callback_.Run(false); + running_callback_.Run(run_state); break; case VIDEO_CAPTURE_STATE_STARTING:
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source.cc b/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source.cc index 3ff92d3..3ffa30f1 100644 --- a/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source.cc +++ b/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source.cc
@@ -146,7 +146,7 @@ // Force state update for nondevice sources, since they do not // automatically update state after StopCapture(). if (device().type == mojom::blink::MediaStreamType::NO_SERVICE) - OnRunStateChanged(capture_params_, false); + OnRunStateChanged(capture_params_, RunState::kStopped); } void MediaStreamVideoCapturerSource::RestartSourceImpl( @@ -215,8 +215,9 @@ void MediaStreamVideoCapturerSource::OnRunStateChanged( const media::VideoCaptureParams& new_capture_params, - bool is_running) { + RunState run_state) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + bool is_running = (run_state == RunState::kRunning); switch (state_) { case kStarting: source_->OnLog("MediaStreamVideoCapturerSource sending OnStartDone"); @@ -226,8 +227,12 @@ OnStartDone(mojom::blink::MediaStreamRequestResult::OK); } else { state_ = kStopped; - OnStartDone( - mojom::blink::MediaStreamRequestResult::TRACK_START_FAILURE_VIDEO); + auto result = (run_state == RunState::kSystemPermissionsError) + ? mojom::blink::MediaStreamRequestResult:: + SYSTEM_PERMISSION_DENIED + : mojom::blink::MediaStreamRequestResult:: + TRACK_START_FAILURE_VIDEO; + OnStartDone(result); } break; case kStarted:
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source.h b/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source.h index 5253ec9..a1d50c0 100644 --- a/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source.h +++ b/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source.h
@@ -21,6 +21,7 @@ #include "third_party/blink/public/mojom/mediastream/media_stream.mojom-blink.h" #include "third_party/blink/public/web/modules/mediastream/media_stream_video_source.h" #include "third_party/blink/renderer/modules/modules_export.h" +#include "third_party/blink/renderer/platform/video_capture/video_capturer_source.h" namespace blink { @@ -96,7 +97,7 @@ // Method to bind as RunningCallback in VideoCapturerSource::StartCapture(). void OnRunStateChanged(const media::VideoCaptureParams& new_capture_params, - bool is_running); + RunState run_state); mojom::blink::MediaStreamDispatcherHost* GetMediaStreamDispatcherHost();
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source_test.cc b/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source_test.cc index fb88c51..136c2124 100644 --- a/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source_test.cc +++ b/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source_test.cc
@@ -56,9 +56,9 @@ } void StopCapture() override { MockStopCapture(); } void SetRunning(bool is_running) { + RunState run_state = is_running ? RunState::kRunning : RunState::kStopped; PostCrossThreadTask(*scheduler::GetSingleThreadTaskRunnerForTesting(), - FROM_HERE, - CrossThreadBindOnce(running_cb_, is_running)); + FROM_HERE, CrossThreadBindOnce(running_cb_, run_state)); } const media::VideoCaptureParams& capture_params() const { return capture_params_; @@ -163,8 +163,9 @@ EXPECT_EQ(String(source.Id()), stream_source_id_); } void OnStarted(bool result) { + RunState run_state = result ? RunState::kRunning : RunState::kStopped; video_capturer_source_->OnRunStateChanged(delegate_->capture_params(), - result); + run_state); } void SetStopCaptureFlag() { stop_capture_flag_ = true; } @@ -189,8 +190,8 @@ Persistent<MediaStreamSource> stream_source_; MockMojoMediaStreamDispatcherHost mock_dispatcher_host_; MediaStreamVideoCapturerSource* - video_capturer_source_; // owned by |stream_source_|. - MockVideoCapturerSource* delegate_; // owned by |source_|. + video_capturer_source_; // owned by |stream_source_|. + MockVideoCapturerSource* delegate_; // owned by |source_|. String stream_source_id_; bool source_stopped_; bool stop_capture_flag_ = false; @@ -238,7 +239,7 @@ EXPECT_CALL(mock_delegate(), MockStopCapture()); WebMediaStreamTrack track = StartSource(VideoTrackAdapterSettings(), absl::nullopt, false, 0.0); - running_cb.Run(true); + running_cb.Run(RunState::kRunning); base::RunLoop run_loop; base::TimeTicks reference_capture_time =
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_video_source.cc b/third_party/blink/renderer/modules/mediastream/media_stream_video_source.cc index e8c7437a..370c224 100644 --- a/third_party/blink/renderer/modules/mediastream/media_stream_video_source.cc +++ b/third_party/blink/renderer/modules/mediastream/media_stream_video_source.cc
@@ -104,9 +104,13 @@ // and OnRestartDone(). break; } - case ENDED: + case ENDED: { + FinalizeAddPendingTracks( + mojom::blink::MediaStreamRequestResult::TRACK_START_FAILURE_VIDEO); + break; + } case STARTED: { - FinalizeAddPendingTracks(); + FinalizeAddPendingTracks(mojom::blink::MediaStreamRequestResult::OK); break; } } @@ -259,7 +263,7 @@ } else { state_ = STARTED; StartFrameMonitoring(); - FinalizeAddPendingTracks(); + FinalizeAddPendingTracks(mojom::blink::MediaStreamRequestResult::OK); } DCHECK(restart_callback_); @@ -299,7 +303,7 @@ if (did_restart) { state_ = STARTED; StartFrameMonitoring(); - FinalizeAddPendingTracks(); + FinalizeAddPendingTracks(mojom::blink::MediaStreamRequestResult::OK); } else { state_ = STOPPED_FOR_RESTART; } @@ -427,20 +431,15 @@ // This object can be deleted after calling FinalizeAddPendingTracks. See // comment in the header file. - FinalizeAddPendingTracks(); + FinalizeAddPendingTracks(result); } -void MediaStreamVideoSource::FinalizeAddPendingTracks() { +void MediaStreamVideoSource::FinalizeAddPendingTracks( + mojom::blink::MediaStreamRequestResult result) { DCHECK(GetTaskRunner()->BelongsToCurrentThread()); Vector<PendingTrackInfo> pending_track_descriptors; pending_track_descriptors.swap(pending_tracks_); for (auto& track_info : pending_track_descriptors) { - auto result = mojom::blink::MediaStreamRequestResult::OK; - if (state_ != STARTED) { - result = - mojom::blink::MediaStreamRequestResult::TRACK_START_FAILURE_VIDEO; - } - if (result == mojom::blink::MediaStreamRequestResult::OK) { GetTrackAdapter()->AddTrack( track_info.track, track_info.frame_callback,
diff --git a/third_party/blink/renderer/modules/webcodecs/audio_encoder.cc b/third_party/blink/renderer/modules/webcodecs/audio_encoder.cc index 48d4157..e45470a 100644 --- a/third_party/blink/renderer/modules/webcodecs/audio_encoder.cc +++ b/third_party/blink/renderer/modules/webcodecs/audio_encoder.cc
@@ -182,7 +182,7 @@ WrapCrossThreadPersistent(active_config_.Get()), reset_count_)); auto done_callback = [](AudioEncoder* self, media::AudioCodec codec, - Request* req, media::Status status) { + Request* req, media::EncoderStatus status) { if (!self || self->reset_count_ != req->reset_count) { req->EndTracing(/*aborted=*/true); return; @@ -190,7 +190,7 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(self->sequence_checker_); if (!status.is_ok()) { self->HandleError( - self->logger_->MakeException("Encoding error.", status)); + self->logger_->MakeException("Encoding error.", std::move(status))); } else { base::UmaHistogramEnumeration("Blink.WebCodecs.AudioEncoder.Codec", codec); @@ -227,7 +227,7 @@ DCHECK(data); auto done_callback = [](AudioEncoder* self, Request* req, - media::Status status) { + media::EncoderStatus status) { if (!self || self->reset_count_ != req->reset_count) { req->EndTracing(/*aborted=*/true); return; @@ -235,7 +235,7 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(self->sequence_checker_); if (!status.is_ok()) { self->HandleError( - self->logger_->MakeException("Encoding error.", status)); + self->logger_->MakeException("Encoding error.", std::move(status))); } req->EndTracing(); @@ -244,12 +244,11 @@ if (data->channel_count() != active_config_->options.channels || data->sample_rate() != active_config_->options.sample_rate) { - media::Status error(media::StatusCode::kEncoderFailedEncode); - error.WithData("channels", data->channel_count()); - error.WithData("sampleRate", data->sample_rate()); - HandleError(logger_->MakeException( - "Input audio buffer is incompatible with codec parameters", error)); + "Input audio buffer is incompatible with codec parameters", + media::EncoderStatus(media::EncoderStatus::Codes::kEncoderFailedEncode) + .WithData("channels", data->channel_count()) + .WithData("sampleRate", data->sample_rate()))); request->EndTracing();
diff --git a/third_party/blink/renderer/modules/webcodecs/encoder_base.cc b/third_party/blink/renderer/modules/webcodecs/encoder_base.cc index 7b2268d..faed4d8 100644 --- a/third_party/blink/renderer/modules/webcodecs/encoder_base.cc +++ b/third_party/blink/renderer/modules/webcodecs/encoder_base.cc
@@ -64,8 +64,8 @@ auto* context = ExecutionContext::From(script_state); callback_runner_ = context->GetTaskRunner(TaskType::kInternalMediaRealTime); - logger_ = std::make_unique<CodecLogger<media::Status>>(GetExecutionContext(), - callback_runner_); + logger_ = std::make_unique<CodecLogger<media::EncoderStatus>>( + GetExecutionContext(), callback_runner_); media::MediaLog* log = logger_->log(); logger_->SendPlayerNameInformation(*context, Traits::GetName()); @@ -308,7 +308,7 @@ DCHECK_EQ(request->type, Request::Type::kFlush); auto done_callback = [](EncoderBase<Traits>* self, Request* req, - media::Status status) { + media::EncoderStatus status) { DCHECK(req); DCHECK(req->resolver); @@ -328,7 +328,7 @@ req->resolver.Release()->Resolve(); } else { self->HandleError( - self->logger_->MakeException("Flushing error.", status)); + self->logger_->MakeException("Flushing error.", std::move(status))); req->resolver.Release()->Reject(); } req->EndTracing();
diff --git a/third_party/blink/renderer/modules/webcodecs/encoder_base.h b/third_party/blink/renderer/modules/webcodecs/encoder_base.h index e351422..9c1cd31 100644 --- a/third_party/blink/renderer/modules/webcodecs/encoder_base.h +++ b/third_party/blink/renderer/modules/webcodecs/encoder_base.h
@@ -7,8 +7,8 @@ #include <memory> +#include "media/base/encoder_status.h" #include "media/base/media_log.h" -#include "media/base/status.h" #include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_codec_state.h" @@ -137,7 +137,7 @@ void TraceQueueSizes() const; - std::unique_ptr<CodecLogger<media::Status>> logger_; + std::unique_ptr<CodecLogger<media::EncoderStatus>> logger_; std::unique_ptr<MediaEncoderType> media_encoder_;
diff --git a/third_party/blink/renderer/modules/webcodecs/video_encoder.cc b/third_party/blink/renderer/modules/webcodecs/video_encoder.cc index 31f31babb..cc09d0a 100644 --- a/third_party/blink/renderer/modules/webcodecs/video_encoder.cc +++ b/third_party/blink/renderer/modules/webcodecs/video_encoder.cc
@@ -84,8 +84,8 @@ namespace WTF { template <> -struct CrossThreadCopier<media::Status> - : public CrossThreadCopierPassThrough<media::Status> { +struct CrossThreadCopier<media::EncoderStatus> + : public CrossThreadCopierPassThrough<media::EncoderStatus> { STATIC_ONLY(CrossThreadCopier); }; @@ -582,9 +582,10 @@ if (!media_encoder_) { HandleError(logger_->MakeException( "Encoder creation error.", - media::Status(media::StatusCode::kEncoderInitializationError, - "Unable to create encoder (most likely unsupported " - "codec/acceleration requirement combination)"))); + media::EncoderStatus( + media::EncoderStatus::Codes::kEncoderInitializationError, + "Unable to create encoder (most likely unsupported " + "codec/acceleration requirement combination)"))); request->EndTracing(); return; } @@ -596,7 +597,8 @@ WrapCrossThreadPersistent(active_config_.Get()), reset_count_)); auto done_callback = [](VideoEncoder* self, Request* req, - media::VideoCodec codec, media::Status status) { + media::VideoCodec codec, + media::EncoderStatus status) { if (!self || self->reset_count_ != req->reset_count) { req->EndTracing(/*aborted=*/true); return; @@ -606,7 +608,7 @@ if (!status.is_ok()) { self->HandleError(self->logger_->MakeException( - "Encoder initialization error.", status)); + "Encoder initialization error.", std::move(status))); } else { UMA_HISTOGRAM_ENUMERATION("Blink.WebCodecs.VideoEncoder.Codec", codec, media::VideoCodec::kMaxValue); @@ -658,7 +660,7 @@ request->StartTracingVideoEncode(keyframe); auto done_callback = [](VideoEncoder* self, Request* req, - media::Status status) { + media::EncoderStatus status) { if (!self || self->reset_count_ != req->reset_count) { req->EndTracing(/*aborted=*/true); return; @@ -668,7 +670,7 @@ self->active_encodes_--; if (!status.is_ok()) { self->HandleError( - self->logger_->MakeException("Encoding error.", status)); + self->logger_->MakeException("Encoding error.", std::move(status))); } req->EndTracing(); self->ProcessRequests(); @@ -695,27 +697,27 @@ // This will execute shortly after CopyRGBATextureToVideoFrame() // completes. |blocking_request_in_progress_| = true will ensure that // HasPendingActivity() keeps the VideoEncoder alive long enough. - auto blit_done_callback = [](VideoEncoder* self, bool keyframe, - uint32_t reset_count, - base::TimeDelta timestamp, - media::VideoFrameMetadata metadata, - media::VideoEncoder::StatusCB done_callback, - scoped_refptr<media::VideoFrame> frame) { - if (!self || self->reset_count_ != reset_count || !frame) - return; + auto blit_done_callback = + [](VideoEncoder* self, bool keyframe, uint32_t reset_count, + base::TimeDelta timestamp, media::VideoFrameMetadata metadata, + media::VideoEncoder::EncoderStatusCB done_callback, + scoped_refptr<media::VideoFrame> frame) { + if (!self || self->reset_count_ != reset_count || !frame) + return; - // CopyRGBATextureToVideoFrame() operates on mailboxes and not frames, - // so we must manually copy over properties relevant to the encoder. - frame->set_timestamp(timestamp); - frame->set_metadata(metadata); + // CopyRGBATextureToVideoFrame() operates on mailboxes and not + // frames, so we must manually copy over properties relevant to the + // encoder. + frame->set_timestamp(timestamp); + frame->set_metadata(metadata); - DCHECK_CALLED_ON_VALID_SEQUENCE(self->sequence_checker_); - --self->requested_encodes_; - self->blocking_request_in_progress_ = false; - self->media_encoder_->Encode(std::move(frame), keyframe, - std::move(done_callback)); - self->ProcessRequests(); - }; + DCHECK_CALLED_ON_VALID_SEQUENCE(self->sequence_checker_); + --self->requested_encodes_; + self->blocking_request_in_progress_ = false; + self->media_encoder_->Encode(std::move(frame), keyframe, + std::move(done_callback)); + self->ProcessRequests(); + }; auto origin = frame->metadata().texture_origin_is_top_left ? kTopLeft_GrSurfaceOrigin @@ -778,12 +780,13 @@ } if (!frame) { - auto status = media::Status(media::StatusCode::kEncoderFailedEncode, - "Can't readback frame textures."); callback_runner_->PostTask( FROM_HERE, ConvertToBaseOnceCallback(CrossThreadBindOnce( done_callback, WrapCrossThreadWeakPersistent(this), - WrapCrossThreadPersistent(request), std::move(status)))); + WrapCrossThreadPersistent(request), + media::EncoderStatus( + media::EncoderStatus::Codes::kEncoderFailedEncode, + "Can't readback frame textures.")))); return; } @@ -835,7 +838,7 @@ request->StartTracing(); auto reconf_done_callback = [](VideoEncoder* self, Request* req, - media::Status status) { + media::EncoderStatus status) { if (!self || self->reset_count_ != req->reset_count) { req->EndTracing(/*aborted=*/true); return; @@ -859,7 +862,7 @@ auto flush_done_callback = [](VideoEncoder* self, Request* req, decltype(reconf_done_callback) reconf_callback, - media::Status status) { + media::EncoderStatus status) { if (!self || self->reset_count_ != req->reset_count) { req->EndTracing(/*aborted=*/true); return; @@ -867,7 +870,7 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(self->sequence_checker_); if (!status.is_ok()) { self->HandleError(self->logger_->MakeException( - "Encoder initialization error.", status)); + "Encoder initialization error.", std::move(status))); self->blocking_request_in_progress_ = false; req->EndTracing(); return; @@ -1010,7 +1013,8 @@ auto done_callback = [](std::unique_ptr<media::VideoEncoder> sw_encoder, ScriptPromiseResolver* resolver, - VideoEncoderSupport* support, media::Status status) { + VideoEncoderSupport* support, + media::EncoderStatus status) { support->setSupported(status.is_ok()); resolver->Resolve(support); DeleteLater(resolver->GetScriptState(), std::move(sw_encoder));
diff --git a/third_party/blink/renderer/platform/video_capture/video_capture_impl.cc b/third_party/blink/renderer/platform/video_capture/video_capture_impl.cc index 2739ebf..d4414ab 100644 --- a/third_party/blink/renderer/platform/video_capture/video_capture_impl.cc +++ b/third_party/blink/renderer/platform/video_capture/video_capture_impl.cc
@@ -687,6 +687,11 @@ OnLog("VideoCaptureImpl is in error state."); state_update_cb.Run(blink::VIDEO_CAPTURE_STATE_ERROR); return; + case VIDEO_CAPTURE_STATE_ERROR_SYSTEM_PERMISSIONS_DENIED: + OnLog("VideoCaptureImpl is in system permissions error state."); + state_update_cb.Run( + blink::VIDEO_CAPTURE_STATE_ERROR_SYSTEM_PERMISSIONS_DENIED); + return; case VIDEO_CAPTURE_STATE_PAUSED: case VIDEO_CAPTURE_STATE_RESUMED: // The internal |state_| is never set to PAUSED/RESUMED since @@ -760,12 +765,19 @@ if (result->which() == media::mojom::blink::VideoCaptureResult::Tag::ERROR_CODE) { DVLOG(1) << __func__ << " Failed with an error."; - OnLog("VideoCaptureImpl changing state to VIDEO_CAPTURE_STATE_ERROR"); + if (result->get_error_code() == + media::VideoCaptureError::kWinMediaFoundationSystemPermissionDenied) { + state_ = VIDEO_CAPTURE_STATE_ERROR_SYSTEM_PERMISSIONS_DENIED; + OnLog( + "VideoCaptureImpl changing state to " + "VIDEO_CAPTURE_STATE_ERROR_SYSTEM_PERMISSIONS_DENIED"); + } else { + state_ = VIDEO_CAPTURE_STATE_ERROR; + OnLog("VideoCaptureImpl changing state to VIDEO_CAPTURE_STATE_ERROR"); + } for (const auto& client : clients_) - client.second.state_update_cb.Run(blink::VIDEO_CAPTURE_STATE_ERROR); + client.second.state_update_cb.Run(state_); clients_.clear(); - state_ = VIDEO_CAPTURE_STATE_ERROR; - RecordStartOutcomeUMA(start_timedout_ ? VideoCaptureStartOutcome::kTimedout : VideoCaptureStartOutcome::kFailed); return;
diff --git a/third_party/blink/renderer/platform/video_capture/video_capture_impl_test.cc b/third_party/blink/renderer/platform/video_capture/video_capture_impl_test.cc index 759fae8..3047776 100644 --- a/third_party/blink/renderer/platform/video_capture/video_capture_impl_test.cc +++ b/third_party/blink/renderer/platform/video_capture/video_capture_impl_test.cc
@@ -759,6 +759,18 @@ VideoCaptureStartOutcome::kStarted, 1); } +TEST_F(VideoCaptureImplTest, WinSystemPermissionsErrorUpdatesCorrectState) { + EXPECT_CALL(*this, + OnStateUpdate( + blink::VIDEO_CAPTURE_STATE_ERROR_SYSTEM_PERMISSIONS_DENIED)); + video_capture_impl_->OnStateChanged( + media::mojom::blink::VideoCaptureResult::NewErrorCode( + media::VideoCaptureError::kWinMediaFoundationSystemPermissionDenied)); + + StartCapture(0, params_small_); + StopCapture(0); +} + TEST_F(VideoCaptureImplTest, BufferReceivedBeforeOnStarted) { const int kArbitraryBufferId = 16;
diff --git a/third_party/blink/renderer/platform/video_capture/video_capturer_source.h b/third_party/blink/renderer/platform/video_capture/video_capturer_source.h index fdc0d72..73d7dc5 100644 --- a/third_party/blink/renderer/platform/video_capture/video_capturer_source.h +++ b/third_party/blink/renderer/platform/video_capture/video_capturer_source.h
@@ -20,6 +20,12 @@ namespace blink { +enum class RunState { + kRunning = 0, + kStopped, + kSystemPermissionsError, +}; + // VideoCapturerSource is an interface representing the source for captured // video. An implementation will periodically call the frame callback with new // video frames. @@ -27,7 +33,7 @@ public: virtual ~VideoCapturerSource(); - using RunningCallback = base::RepeatingCallback<void(bool)>; + using RunningCallback = base::RepeatingCallback<void(RunState)>; // Returns formats that are preferred and can currently be used. May be empty // if no formats are available or known.
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 747f215..7d42846 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -6889,6 +6889,9 @@ # Sheriff 2021-01-20 crbug.com/1168522 external/wpt/focus/iframe-activeelement-after-focusing-out-iframes.html [ Failure Pass ] +# Temporarily skipped to land crrev.com/c/3352118 +crbug.com/1282076 http/tests/devtools/console/console-message-format.js [ Skip ] + # DevTools roll crbug.com/1050549 http/tests/devtools/console/console-correct-suggestions.js [ Failure Pass ] @@ -6950,7 +6953,6 @@ # Sheriff 2021-02-18 crbug.com/1179772 [ Win7 ] http/tests/devtools/console/console-preserve-log-x-process-navigation.js [ Failure Pass ] -crbug.com/1179857 [ Linux ] http/tests/inspector-protocol/dom/dom-getFrameOwner.js [ Failure Pass ] # Sheriff 2021-02-19 crbug.com/1180227 [ Mac ] virtual/feature-policy-permissions/external/wpt/mediacapture-streams/MediaStream-default-feature-policy.https.html [ Crash Failure Pass ] @@ -8239,3 +8241,8 @@ crbug.com/1281782 [ Mac ] virtual/no-alloc-direct-call/external/wpt/html/canvas/offscreen/compositing/2d.composite.globalAlpha.default.html [ Crash Pass ] crbug.com/1281782 [ Mac ] virtual/no-alloc-direct-call/external/wpt/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.5arg.html [ Crash Pass ] crbug.com/1281792 external/wpt/event-timing/min-duration-threshold.html [ Failure Pass ] + +# Sheriff 2021-12-22 +crbug.com/1179857 [ Linux ] http/tests/inspector-protocol/dom/dom-getFrameOwner.js [ Failure Pass ] +crbug.com/1179857 [ Mac10.13 ] http/tests/inspector-protocol/dom/dom-getFrameOwner.js [ Failure Pass ] +crbug.com/1179857 [ Win ] http/tests/inspector-protocol/dom/dom-getFrameOwner.js [ Pass Timeout ]
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 8833ae3..534b3f1ab 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
@@ -1099,6 +1099,13 @@ {} ] ], + "nested-balanced-monolithic-multicol-crash.html": [ + "082bf70691c955e1ba7fac9e2c077c71a7d52f84", + [ + null, + {} + ] + ], "nested-floated-multicol-with-monolithic-child-crash.html": [ "f48ae9ff73faf1df5f9ff7247c64391f0c97d006", [ @@ -283904,6 +283911,10 @@ "c50eddd41faba2ecc8928e459288fe612b999170", [] ], + "child-navigates-parent-cross-origin-inner.html": [ + "72b92c8061a995a27442fe071cb78d8af4a42261", + [] + ], "child-navigates-parent-destination.html": [ "bb8ba4e6989597efeb1326c9acddbcfe64074d10", [] @@ -311440,6 +311451,20 @@ [] ] }, + "secure-context": { + "sender.html": [ + "05e58822a862378b736af1113e2101a4fd587e73", + [] + ], + "window.html": [ + "071a507cb33e95e5b9cfc9a0bbccadab0983efee", + [] + ] + }, + "secure-context-service-worker.js": [ + "5ba99f075362ea30cb14ca4edf51af594d98917a", + [] + ], "service-worker-csp-worker.py": [ "35a46964a7871a7ab85d4b0b181e5ff2e3f496fc", [] @@ -417500,6 +417525,24 @@ {} ] ], + "child-navigates-parent-cross-origin.window.js": [ + "c5bed0fd4c9afa85010242bfe6a7085587a3327c", + [ + "html/browsers/browsing-the-web/navigating-across-documents/child-navigates-parent-cross-origin.window.html", + { + "script_metadata": [ + [ + "script", + "/common/get-host-info.sub.js" + ], + [ + "script", + "resources/wait-for-messages.js" + ] + ] + } + ] + ], "child-navigates-parent-same-origin.window.js": [ "a40c412029b4b28ae26691deff0286dfff3ccbcd", [ @@ -498370,6 +498413,13 @@ {} ] ], + "secure-context.https.html": [ + "666a5d378760b54fd0f4fa86f9db7a05e2be5b5a", + [ + null, + {} + ] + ], "service-worker-csp-connect.https.html": [ "226f4a40e4e9ab40bbeeac4e874208af3106d2da", [
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/change-inline-color.html b/third_party/blink/web_tests/external/wpt/css/css-break/change-inline-color.html index c4334af..9da2c8e 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-break/change-inline-color.html +++ b/third_party/blink/web_tests/external/wpt/css/css-break/change-inline-color.html
@@ -1,17 +1,20 @@ <!DOCTYPE html> -<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org"> -<link rel="help" href="https://www.w3.org/TR/css-break-3/"> -<link rel="match" href="change-inline-color-ref.html"> -<p>The word PASS should be seen below.</p> -<div style="columns:4; width:4em; text-align:center; column-gap:0; orphans:1; widows:1; color:white;"> - <span id="span"> - P A S S - </span> -</div> -<script> - requestAnimationFrame(()=> { +<html class="reftest-wait"> + <link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org"> + <link rel="help" href="https://www.w3.org/TR/css-break-3/"> + <link rel="match" href="change-inline-color-ref.html"> + <p>The word PASS should be seen below.</p> + <div style="columns:4; width:4em; text-align:center; column-gap:0; orphans:1; widows:1; color:white;"> + <span id="span"> + P A S S + </span> + </div> + <script> + requestAnimationFrame(()=> { requestAnimationFrame(()=> { - span.style.color = "green"; + span.style.color = "green"; + document.documentElement.classList.remove("reftest-wait"); }); - }); -</script> + }); + </script> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-pseudo/parsing/marker-supported-properties-in-animation-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-pseudo/parsing/marker-supported-properties-in-animation-expected.txt index a389ccd..10967acc 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-pseudo/parsing/marker-supported-properties-in-animation-expected.txt +++ b/third_party/blink/web_tests/external/wpt/css/css-pseudo/parsing/marker-supported-properties-in-animation-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 94 tests; 86 PASS, 8 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 94 tests; 88 PASS, 6 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Animation of font in ::marker PASS Animation of font-family in ::marker PASS Animation of font-feature-settings in ::marker @@ -36,7 +36,7 @@ PASS Animation of word-spacing in ::marker PASS Animation of text-decoration-skip-ink in ::marker FAIL Animation of text-emphasis in ::marker assert_equals: expected "triangle rgb(50, 100, 100)" but got "" -FAIL Animation of text-emphasis-color in ::marker assert_equals: expected "rgb(50, 100, 100)" but got "rgb(100, 0, 200)" +PASS Animation of text-emphasis-color in ::marker PASS Animation of text-emphasis-position in ::marker PASS Animation of text-emphasis-style in ::marker PASS Animation of text-shadow in ::marker @@ -83,7 +83,7 @@ PASS Transition of word-spacing in ::marker PASS Transition of text-decoration-skip-ink in ::marker FAIL Transition of text-emphasis in ::marker assert_equals: expected "triangle rgb(50, 100, 100)" but got "" -FAIL Transition of text-emphasis-color in ::marker assert_equals: expected "rgb(50, 100, 100)" but got "rgb(100, 0, 200)" +PASS Transition of text-emphasis-color in ::marker PASS Transition of text-emphasis-position in ::marker PASS Transition of text-emphasis-style in ::marker PASS Transition of text-shadow in ::marker
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/parsing/text-emphasis-position-computed-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-text-decor/parsing/text-emphasis-position-computed-expected.txt deleted file mode 100644 index c242701..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-text-decor/parsing/text-emphasis-position-computed-expected.txt +++ /dev/null
@@ -1,9 +0,0 @@ -This is a testharness.js-based test. -FAIL Property text-emphasis-position value 'over' assert_equals: expected "over" but got "over right" -FAIL Property text-emphasis-position value 'under' assert_equals: expected "under" but got "under right" -PASS Property text-emphasis-position value 'over right' -PASS Property text-emphasis-position value 'over left' -PASS Property text-emphasis-position value 'under right' -PASS Property text-emphasis-position value 'under left' -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/text-emphasis-color-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/text-emphasis-color-expected.txt deleted file mode 100644 index 772c71bb..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/text-emphasis-color-expected.txt +++ /dev/null
@@ -1,20 +0,0 @@ -This is a testharness.js-based test. -PASS Can set 'text-emphasis-color' to CSS-wide keywords -PASS Can set 'text-emphasis-color' to var() references -FAIL Can set 'text-emphasis-color' to the 'currentcolor' keyword Failed to execute 'set' on 'StylePropertyMap': Invalid type for property -PASS Setting 'text-emphasis-color' to a length throws TypeError -PASS Setting 'text-emphasis-color' to a percent throws TypeError -PASS Setting 'text-emphasis-color' to a time throws TypeError -PASS Setting 'text-emphasis-color' to an angle throws TypeError -PASS Setting 'text-emphasis-color' to a flexible length throws TypeError -PASS Setting 'text-emphasis-color' to a number throws TypeError -PASS Setting 'text-emphasis-color' to a position throws TypeError -PASS Setting 'text-emphasis-color' to a URL throws TypeError -PASS Setting 'text-emphasis-color' to a transform throws TypeError -PASS 'text-emphasis-color' does not supported 'red' -PASS 'text-emphasis-color' does not supported '#bbff00' -PASS 'text-emphasis-color' does not supported 'rgb(255, 255, 128)' -PASS 'text-emphasis-color' does not supported 'hsl(50, 33%, 25%)' -PASS 'text-emphasis-color' does not supported 'transparent' -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/secure-context-service-worker.js b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/secure-context-service-worker.js new file mode 100644 index 0000000..5ba99f07 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/secure-context-service-worker.js
@@ -0,0 +1,21 @@ +self.addEventListener('fetch', event => { + let url = new URL(event.request.url); + if (url.pathname.indexOf('sender.html') != -1) { + event.respondWith(new Response( + "<script>window.parent.postMessage('interception', '*');</script>", + { headers: { 'Content-Type': 'text/html'} } + )); + } else if (url.pathname.indexOf('report') != -1) { + self.clients.matchAll().then(clients => { + for (client of clients) { + client.postMessage(url.searchParams.get('result')); + } + }); + event.respondWith( + new Response( + '<script>window.close()</script>', + { headers: { 'Content-Type': 'text/html'} } + ) + ); + } +});
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/secure-context/sender.html b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/secure-context/sender.html new file mode 100644 index 0000000..05e5882 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/secure-context/sender.html
@@ -0,0 +1 @@ +<script>window.parent.postMessage('network', '*');</script>
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/secure-context/window.html b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/secure-context/window.html new file mode 100644 index 0000000..071a507 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/secure-context/window.html
@@ -0,0 +1,15 @@ +<body> +<script src="/common/get-host-info.sub.js"></script> +<script src="../test-helpers.sub.js"></script> +<script> +const HTTPS_PREFIX = get_host_info().HTTPS_ORIGIN + base_path(); + +window.onmessage = event => { + window.location = HTTPS_PREFIX + 'report?result=' + event.data; +}; + +const frame = document.createElement('iframe'); +frame.src = HTTPS_PREFIX + 'sender.html'; +document.body.appendChild(frame); +</script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/secure-context.https.html b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/secure-context.https.html new file mode 100644 index 0000000..666a5d3 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/secure-context.https.html
@@ -0,0 +1,57 @@ +<!doctype html> +<meta charset=utf-8> +<title>Ensure service worker is bypassed in insecure contexts</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="resources/test-helpers.sub.js"></script> +<body> +<script> + +// This test checks that an HTTPS iframe embedded in an HTTP document is not +// loaded via a service worker, since it's not a secure context. To that end, we +// first register a service worker, wait for its activation, and create an +// iframe that is controlled by said service worker. We use the iframe as a +// way to receive messages from the service worker. +// The bulk of the test begins by opening an HTTP window with the noopener +// option, installing a message event handler, and embedding an HTTPS iframe. If +// the browser behaves correctly then the iframe will be loaded from the network +// and will contain a script that posts a message to the parent window, +// informing it that it was loaded from the network. If, however, the iframe is +// intercepted, the service worker will return a page with a script that posts a +// message to the parent window, informing it that it was intercepted. +// Upon getting either result, the window will report the result to the service +// worker by navigating to a reporting URL. The service worker will then inform +// all clients about the result, including the controlled iframe from the +// beginning of the test. The message event handler will verify that the result +// is as expected, concluding the test. +promise_test(t => { + const SCRIPT = "resources/secure-context-service-worker.js"; + const SCOPE = "resources/"; + const HTTP_IFRAME_URL = get_host_info().HTTP_ORIGIN + base_path() + SCOPE + "secure-context/window.html"; + return service_worker_unregister_and_register(t, SCRIPT, SCOPE) + .then(registration => { + t.add_cleanup(() => { + return registration.unregister(); + }); + return wait_for_state(t, registration.installing, 'activated'); + }) + .then(() => { + return with_iframe(SCOPE + "blank.html"); + }) + .then(iframe => { + t.add_cleanup(() => { + iframe.remove(); + }); + return new Promise(resolve => { + iframe.contentWindow.navigator.serviceWorker.onmessage = t.step_func(event => { + assert_equals(event.data, 'network'); + resolve(); + }); + window.open(HTTP_IFRAME_URL, 'MyWindow', 'noopener'); + }); + }); +}) + +</script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/web-animations/animation-model/animation-types/accumulation-per-property-002-expected.txt b/third_party/blink/web_tests/external/wpt/web-animations/animation-model/animation-types/accumulation-per-property-002-expected.txt index b508e5ab..b477cd5 100644 --- a/third_party/blink/web_tests/external/wpt/web-animations/animation-model/animation-types/accumulation-per-property-002-expected.txt +++ b/third_party/blink/web_tests/external/wpt/web-animations/animation-model/animation-types/accumulation-per-property-002-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 273 tests; 255 PASS, 18 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 273 tests; 261 PASS, 12 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Setup PASS isolation (type: discrete) has testAccumulation function PASS isolation: "isolate" onto "auto" @@ -187,12 +187,12 @@ PASS text-decoration-style: "dotted" onto "solid" PASS text-decoration-style: "solid" onto "dotted" PASS text-emphasis-color (type: color) has testAccumulation function -FAIL text-emphasis-color supports animating as color of rgb() with overflowed from and to values assert_equals: The value should be rgb(255, 128, 128) at 0ms expected "rgb(255, 128, 128)" but got "rgb(255, 0, 0)" -FAIL text-emphasis-color supports animating as color of #RGB assert_equals: The value should be rgb(255, 128, 128) at 0ms expected "rgb(255, 128, 128)" but got "rgb(255, 0, 0)" -FAIL text-emphasis-color supports animating as color of hsl() assert_equals: The value should be rgb(255, 128, 128) at 0ms expected "rgb(255, 128, 128)" but got "rgb(255, 0, 0)" -FAIL text-emphasis-color supports animating as color of #RGBa assert_equals: The value should be rgb(230, 128, 128) at 0ms expected "rgb(230, 128, 128)" but got "rgba(255, 0, 0, 0.4)" -FAIL text-emphasis-color supports animating as color of rgba() assert_equals: The value should be rgb(230, 128, 128) at 0ms expected "rgb(230, 128, 128)" but got "rgba(255, 0, 0, 0.4)" -FAIL text-emphasis-color supports animating as color of hsla() assert_equals: The value should be rgb(230, 128, 128) at 0ms expected "rgb(230, 128, 128)" but got "rgba(255, 0, 0, 0.4)" +PASS text-emphasis-color supports animating as color of rgb() with overflowed from and to values +PASS text-emphasis-color supports animating as color of #RGB +PASS text-emphasis-color supports animating as color of hsl() +PASS text-emphasis-color supports animating as color of #RGBa +PASS text-emphasis-color supports animating as color of rgba() +PASS text-emphasis-color supports animating as color of hsla() PASS text-emphasis-position (type: discrete) has testAccumulation function PASS text-emphasis-position: "under left" onto "over right" PASS text-emphasis-position: "over right" onto "under left"
diff --git a/third_party/blink/web_tests/external/wpt/web-animations/animation-model/animation-types/addition-per-property-002-expected.txt b/third_party/blink/web_tests/external/wpt/web-animations/animation-model/animation-types/addition-per-property-002-expected.txt index 2047aeaa..9a5c636 100644 --- a/third_party/blink/web_tests/external/wpt/web-animations/animation-model/animation-types/addition-per-property-002-expected.txt +++ b/third_party/blink/web_tests/external/wpt/web-animations/animation-model/animation-types/addition-per-property-002-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 269 tests; 254 PASS, 15 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 269 tests; 260 PASS, 9 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Setup PASS isolation (type: discrete) has testAddition function PASS isolation: "isolate" onto "auto" @@ -187,12 +187,12 @@ PASS text-decoration-style: "dotted" onto "solid" PASS text-decoration-style: "solid" onto "dotted" PASS text-emphasis-color (type: color) has testAddition function -FAIL text-emphasis-color supports animating as color of rgb() with overflowed from and to values assert_equals: The value should be rgb(255, 128, 128) at 0ms expected "rgb(255, 128, 128)" but got "rgb(255, 0, 0)" -FAIL text-emphasis-color supports animating as color of #RGB assert_equals: The value should be rgb(255, 128, 128) at 0ms expected "rgb(255, 128, 128)" but got "rgb(255, 0, 0)" -FAIL text-emphasis-color supports animating as color of hsl() assert_equals: The value should be rgb(255, 128, 128) at 0ms expected "rgb(255, 128, 128)" but got "rgb(255, 0, 0)" -FAIL text-emphasis-color supports animating as color of #RGBa assert_equals: The value should be rgb(230, 128, 128) at 0ms expected "rgb(230, 128, 128)" but got "rgba(255, 0, 0, 0.4)" -FAIL text-emphasis-color supports animating as color of rgba() assert_equals: The value should be rgb(230, 128, 128) at 0ms expected "rgb(230, 128, 128)" but got "rgba(255, 0, 0, 0.4)" -FAIL text-emphasis-color supports animating as color of hsla() assert_equals: The value should be rgb(230, 128, 128) at 0ms expected "rgb(230, 128, 128)" but got "rgba(255, 0, 0, 0.4)" +PASS text-emphasis-color supports animating as color of rgb() with overflowed from and to values +PASS text-emphasis-color supports animating as color of #RGB +PASS text-emphasis-color supports animating as color of hsl() +PASS text-emphasis-color supports animating as color of #RGBa +PASS text-emphasis-color supports animating as color of rgba() +PASS text-emphasis-color supports animating as color of hsla() PASS text-emphasis-position (type: discrete) has testAddition function PASS text-emphasis-position: "under left" onto "over right" PASS text-emphasis-position: "over right" onto "under left"
diff --git a/third_party/blink/web_tests/external/wpt/web-animations/animation-model/animation-types/interpolation-per-property-002-expected.txt b/third_party/blink/web_tests/external/wpt/web-animations/animation-model/animation-types/interpolation-per-property-002-expected.txt index 9e3c434..c4a07ae 100644 --- a/third_party/blink/web_tests/external/wpt/web-animations/animation-model/animation-types/interpolation-per-property-002-expected.txt +++ b/third_party/blink/web_tests/external/wpt/web-animations/animation-model/animation-types/interpolation-per-property-002-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 329 tests; 311 PASS, 18 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 329 tests; 317 PASS, 12 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Setup PASS isolation (type: discrete) has testInterpolation function PASS isolation uses discrete animation when animating between "auto" and "isolate" with linear easing @@ -224,12 +224,12 @@ PASS text-decoration-style uses discrete animation when animating between "solid" and "dotted" with effect easing PASS text-decoration-style uses discrete animation when animating between "solid" and "dotted" with keyframe easing PASS text-emphasis-color (type: color) has testInterpolation function -FAIL text-emphasis-color supports animating as color of rgb() assert_equals: The value should be rgb(128, 0, 128) at 500ms expected "rgb(128, 0, 128)" but got "rgb(0, 0, 255)" -FAIL text-emphasis-color supports animating as color of #RGB assert_equals: The value should be rgb(128, 0, 128) at 500ms expected "rgb(128, 0, 128)" but got "rgb(0, 0, 255)" -FAIL text-emphasis-color supports animating as color of hsl() assert_equals: The value should be rgb(128, 0, 128) at 500ms expected "rgb(128, 0, 128)" but got "rgb(0, 0, 255)" -FAIL text-emphasis-color supports animating as color of #RGBa assert_equals: The value should be rgba(85, 0, 170, 0.6) at 500ms expected "rgba(85, 0, 170, 0.6)" but got "rgba(0, 0, 255, 0.8)" -FAIL text-emphasis-color supports animating as color of rgba() assert_equals: The value should be rgba(85, 0, 170, 0.6) at 500ms expected "rgba(85, 0, 170, 0.6)" but got "rgba(0, 0, 255, 0.8)" -FAIL text-emphasis-color supports animating as color of hsla() assert_equals: The value should be rgba(85, 0, 170, 0.6) at 500ms expected "rgba(85, 0, 170, 0.6)" but got "rgba(0, 0, 255, 0.8)" +PASS text-emphasis-color supports animating as color of rgb() +PASS text-emphasis-color supports animating as color of #RGB +PASS text-emphasis-color supports animating as color of hsl() +PASS text-emphasis-color supports animating as color of #RGBa +PASS text-emphasis-color supports animating as color of rgba() +PASS text-emphasis-color supports animating as color of hsla() PASS text-emphasis-position (type: discrete) has testInterpolation function PASS text-emphasis-position uses discrete animation when animating between "over right" and "under left" with linear easing PASS text-emphasis-position uses discrete animation when animating between "over right" and "under left" with effect easing
diff --git a/third_party/blink/web_tests/fast/css/parsing-text-emphasis-expected.txt b/third_party/blink/web_tests/fast/css/parsing-text-emphasis-expected.txt index baa628c6..e2a04c0 100644 --- a/third_party/blink/web_tests/fast/css/parsing-text-emphasis-expected.txt +++ b/third_party/blink/web_tests/fast/css/parsing-text-emphasis-expected.txt
@@ -8,12 +8,12 @@ PASS: '-webkit-text-emphasis-position: initial;' parsed as ['', 'initial', '', ''] PASS: '-webkit-text-emphasis-position: inherit;' parsed as ['', 'inherit', '', ''] -PASS: '-webkit-text-emphasis-position: over;' parsed as ['', 'over right', '', ''] +PASS: '-webkit-text-emphasis-position: over;' parsed as ['', 'over', '', ''] PASS: '-webkit-text-emphasis-position: over right;' parsed as ['', 'over right', '', ''] PASS: '-webkit-text-emphasis-position: right over;' parsed as ['', 'over right', '', ''] PASS: '-webkit-text-emphasis-position: over left;' parsed as ['', 'over left', '', ''] PASS: '-webkit-text-emphasis-position: left over;' parsed as ['', 'over left', '', ''] -PASS: '-webkit-text-emphasis-position: under;' parsed as ['', 'under right', '', ''] +PASS: '-webkit-text-emphasis-position: under;' parsed as ['', 'under', '', ''] PASS: '-webkit-text-emphasis-position: under right;' parsed as ['', 'under right', '', ''] PASS: '-webkit-text-emphasis-position: right under;' parsed as ['', 'under right', '', ''] PASS: '-webkit-text-emphasis-position: under left;' parsed as ['', 'under left', '', '']
diff --git a/third_party/blink/web_tests/fast/css/parsing-text-emphasis.html b/third_party/blink/web_tests/fast/css/parsing-text-emphasis.html index 4bab566..67777bd 100644 --- a/third_party/blink/web_tests/fast/css/parsing-text-emphasis.html +++ b/third_party/blink/web_tests/fast/css/parsing-text-emphasis.html
@@ -36,12 +36,12 @@ log(""); test('-webkit-text-emphasis-position: initial;', '', 'initial', ''); test('-webkit-text-emphasis-position: inherit;', '', 'inherit', ''); - test('-webkit-text-emphasis-position: over;', '', 'over right', ''); + test('-webkit-text-emphasis-position: over;', '', 'over', ''); test('-webkit-text-emphasis-position: over right;', '', 'over right', ''); test('-webkit-text-emphasis-position: right over;', '', 'over right', ''); test('-webkit-text-emphasis-position: over left;', '', 'over left', ''); test('-webkit-text-emphasis-position: left over;', '', 'over left', ''); - test('-webkit-text-emphasis-position: under;', '', 'under right', ''); + test('-webkit-text-emphasis-position: under;', '', 'under', ''); test('-webkit-text-emphasis-position: under right;', '', 'under right', ''); test('-webkit-text-emphasis-position: right under;', '', 'under right', ''); test('-webkit-text-emphasis-position: under left;', '', 'under left', '');
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/external/wpt/service-workers/service-worker/resource-timing-fetch-variants.https-expected.txt b/third_party/blink/web_tests/platform/mac-mac11-arm64/external/wpt/service-workers/service-worker/resource-timing-fetch-variants.https-expected.txt new file mode 100644 index 0000000..ed296ab9 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/external/wpt/service-workers/service-worker/resource-timing-fetch-variants.https-expected.txt
@@ -0,0 +1,8 @@ +This is a testharness.js-based test. +PASS Redirects done from within a service-worker should not be exposed to client ResourceTiming +PASS Connection info from within a service-worker should not be exposed to client ResourceTiming +PASS requestStart should never be before fetchStart +PASS Delay from within service-worker (after internal fetching) should be accessible through `responseStart` +PASS Delay from within service-worker (before internal fetching) should be measured before responseStart in the client ResourceTiming entry +Harness: the test ran to completion. +
diff --git a/third_party/closure_compiler/externs/accessibility_private.js b/third_party/closure_compiler/externs/accessibility_private.js index da4fdd9..b295563 100644 --- a/third_party/closure_compiler/externs/accessibility_private.js +++ b/third_party/closure_compiler/externs/accessibility_private.js
@@ -317,6 +317,16 @@ }; /** + * @enum {string} + */ +chrome.accessibilityPrivate.SetNativeChromeVoxResponse = { + SUCCESS: 'success', + TALKBACK_NOT_INSTALLED: 'talkbackNotInstalled', + WINDOW_NOT_FOUND: 'windowNotFound', + FAILURE: 'failure', +}; + +/** * Property to indicate whether event source should default to touch. * @type {number} */ @@ -410,8 +420,11 @@ /** * Sets current ARC app to use native ARC support. * @param {boolean} enabled True for ChromeVox (native), false for TalkBack. + * @param {function(!chrome.accessibilityPrivate.SetNativeChromeVoxResponse): + * void} callback */ -chrome.accessibilityPrivate.setNativeChromeVoxArcSupportForCurrentApp = function(enabled) {}; +chrome.accessibilityPrivate.setNativeChromeVoxArcSupportForCurrentApp = + function(enabled, callback) {}; /** * Sends a fabricated key event.
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml index 2091e503..f854fa4 100644 --- a/tools/metrics/actions/actions.xml +++ b/tools/metrics/actions/actions.xml
@@ -19578,6 +19578,7 @@ </action> <action name="NewTabPage.Promo.EnhancedProtectionPromo.Accepted"> + <obsolete>Removed from code in 2021-12.</obsolete> <owner>drubery@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> <description> @@ -19586,6 +19587,7 @@ </action> <action name="NewTabPage.Promo.EnhancedProtectionPromo.Dismissed"> + <obsolete>Removed from code in 2021-12.</obsolete> <owner>drubery@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> <description>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index d82e049..6ada213 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -53980,6 +53980,7 @@ <int value="870664435" label="DownloadProgressInfoBar:disabled"/> <int value="871435095" label="EnableAggregatedMlAppRanking:disabled"/> <int value="871713352" label="ImprovedLanguageSettings:enabled"/> + <int value="872509587" label="ArcWindowPredictor:enabled"/> <int value="873323760" label="MediaFoundationClearPlayback:disabled"/> <int value="876349279" label="WebViewExtraHeadersSameDomainOnly:enabled"/> <int value="876879670" label="OfflinePagesInDownloadHomeOpenInCct:enabled"/> @@ -55679,6 +55680,7 @@ <int value="2127648677" label="OmniboxExperimentalSuggestScoring:disabled"/> <int value="2129184006" label="NTPOfflinePageDownloadSuggestions:enabled"/> <int value="2129524809" label="PasswordCheck:disabled"/> + <int value="2129639191" label="ArcWindowPredictor:disabled"/> <int value="2129814401" label="SyncTrustedVaultPassphrasePromo:enabled"/> <int value="2129929643" label="enable-use-zoom-for-dsf"/> <int value="2132335798" label="EcheSWA:disabled"/> @@ -92600,6 +92602,7 @@ <int value="6" label="Enter Site Details"/> <int value="7" label="Remove Site Group"/> <int value="8" label="Remove Origin"/> + <int value="9" label="Remove Origin Partitioned"/> </enum> <enum name="WebsiteSettingsDiscoverabilityAction">
diff --git a/tools/metrics/histograms/metadata/chromeos/histograms.xml b/tools/metrics/histograms/metadata/chromeos/histograms.xml index ccdd1b26..80fd9be 100644 --- a/tools/metrics/histograms/metadata/chromeos/histograms.xml +++ b/tools/metrics/histograms/metadata/chromeos/histograms.xml
@@ -616,6 +616,10 @@ means "no pressure" - 0%. </summary> <token key="PType"> + <variant name="ArcFull" + summary="Percentage of time ARC was fully halted waiting on memory"/> + <variant name="ArcSome" + summary="Percentage of ARC had some blocking on memory"/> <variant name="Full" summary="Percentage of time fully halted waiting on memory operations"/> <variant name="Some"
diff --git a/tools/metrics/histograms/metadata/enterprise/histograms.xml b/tools/metrics/histograms/metadata/enterprise/histograms.xml index 689ec02..3c7b3391 100644 --- a/tools/metrics/histograms/metadata/enterprise/histograms.xml +++ b/tools/metrics/histograms/metadata/enterprise/histograms.xml
@@ -2367,7 +2367,7 @@ </histogram> <histogram name="Enterprise.UserPolicyChromeOS.InitialFetch.OAuth2Error" - enum="GoogleServiceAuthError" expires_after="2021-12-26"> + enum="GoogleServiceAuthError" expires_after="2022-03-01"> <owner>igorcov@chromium.org</owner> <owner>asumaneev@google.com</owner> <summary>Service error during OAuth2 access token fetch.</summary>
diff --git a/tools/metrics/histograms/metadata/navigation/histograms.xml b/tools/metrics/histograms/metadata/navigation/histograms.xml index 13fe97f..87280ddb 100644 --- a/tools/metrics/histograms/metadata/navigation/histograms.xml +++ b/tools/metrics/histograms/metadata/navigation/histograms.xml
@@ -1627,7 +1627,7 @@ <histogram name="Prerender.Experimental.CrossOriginRedirectionDomain{PrerenderTriggerType}" - enum="PrerenderCrossOriginRedirectionDomain" expires_after="2022-01-27"> + enum="PrerenderCrossOriginRedirectionDomain" expires_after="2022-03-27"> <owner>lingqi@chromium.org</owner> <owner>nhiroki@chromium.org</owner> <owner>src/content/browser/prerender/OWNERS</owner> @@ -1645,7 +1645,7 @@ <histogram name="Prerender.Experimental.CrossOriginRedirectionProtocolChange{PrerenderTriggerType}" enum="PrerenderCrossOriginRedirectionProtocolChange" - expires_after="2022-01-27"> + expires_after="2022-03-27"> <owner>lingqi@chromium.org</owner> <owner>nhiroki@chromium.org</owner> <owner>src/content/browser/prerender/OWNERS</owner> @@ -1700,7 +1700,7 @@ <histogram name="Prerender.Experimental.PrerenderCrossOriginRedirectionMismatch{PrerenderTriggerType}" - enum="PrerenderCrossOriginRedirectionMismatch" expires_after="2022-01-27"> + enum="PrerenderCrossOriginRedirectionMismatch" expires_after="2022-03-27"> <owner>lingqi@chromium.org</owner> <owner>nhiroki@chromium.org</owner> <owner>src/content/browser/prerender/OWNERS</owner>
diff --git a/tools/metrics/histograms/metadata/new_tab_page/histograms.xml b/tools/metrics/histograms/metadata/new_tab_page/histograms.xml index 68b0e50ba..5649e31 100644 --- a/tools/metrics/histograms/metadata/new_tab_page/histograms.xml +++ b/tools/metrics/histograms/metadata/new_tab_page/histograms.xml
@@ -1355,6 +1355,9 @@ <histogram name="NewTabPage.Promo.EnhancedProtectionPromo" enum="AndroidEnhancedProtectionPromoAction" expires_after="2022-05-15"> + <obsolete> + Removed from code in 2021-12. + </obsolete> <owner>drubery@chromium.org</owner> <owner>chrome-safebrowsing-core@google.com</owner> <summary> @@ -1366,6 +1369,9 @@ <histogram name="NewTabPage.Promo.EnhancedProtectionPromo.ImpressionUntilAction" units="units" expires_after="2022-05-22"> + <obsolete> + Removed from code in 2021-12. + </obsolete> <owner>drubery@chromium.org</owner> <owner>chrome-safebrowsing-core@google.com</owner> <summary> @@ -1378,6 +1384,9 @@ <histogram name="NewTabPage.Promo.EnhancedProtectionPromo.ImpressionUntilDismissal" units="units" expires_after="2022-05-29"> + <obsolete> + Removed from code in 2021-12. + </obsolete> <owner>drubery@chromium.org</owner> <owner>chrome-safebrowsing-core@google.com</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/others/histograms.xml b/tools/metrics/histograms/metadata/others/histograms.xml index 6f4f4ee..87022dd 100644 --- a/tools/metrics/histograms/metadata/others/histograms.xml +++ b/tools/metrics/histograms/metadata/others/histograms.xml
@@ -8439,7 +8439,9 @@ </histogram> <histogram name="Linux.Wayland.Shell" enum="LinuxWaylandShellName" - expires_after="2021-12-31"> + expires_after="never"> +<!-- expires-never: Needed to measure Linux ecosystem. --> + <owner>rjkroege@chromium.org</owner> <owner>adunaev@igalia.com</owner> <summary>
diff --git a/tools/traffic_annotation/auditor/chromeos/safe_list.txt b/tools/traffic_annotation/auditor/chromeos/safe_list.txt index d30a6fbc..40f349f 100644 --- a/tools/traffic_annotation/auditor/chromeos/safe_list.txt +++ b/tools/traffic_annotation/auditor/chromeos/safe_list.txt
@@ -2,7 +2,6 @@ # Please do not add any new safelist. # missing,chrome/browser/ash/enhanced_network_tts/enhanced_network_tts_impl.cc -missing,chrome/browser/ui/ash/thumbnail_loader.cc missing,chrome/browser/ash/printing/server_printers_fetcher.cc missing,chrome/browser/ash/customization/customization_wallpaper_downloader.cc missing,ash/components/device_activity/device_activity_client.cc @@ -11,14 +10,12 @@ all,ash/webui/projector_app/projector_xhr_sender.cc all,ash/components/geolocation/simple_geolocation_request.cc all,ash/wallpaper/wallpaper_controller_impl.cc -all,ash/components/timezone/timezone_request.cc all,ash/components/trial_group/trial_group_checker.cc all,chrome/browser/ash/net/network_portal_detector_impl.cc all,chrome/browser/ash/policy/uploading/system_log_uploader.cc all,chrome/browser/ui/ash/assistant/search_and_assistant_enabled_checker.cc all,chromeos/geolocation/simple_geolocation_request.cc all,components/quirks/quirks_client.cc -all,chromeos/timezone/timezone_request.cc all,chromeos/services/device_sync/cryptauth_client_impl.cc all,chrome/browser/supervised_user/child_accounts/family_info_fetcher.cc all,chrome/services/sharing/nearby/platform/webrtc.cc
diff --git a/tools/traffic_annotation/scripts/update_annotations_sheet.py b/tools/traffic_annotation/scripts/update_annotations_sheet.py index c290a28..4d89ae29 100755 --- a/tools/traffic_annotation/scripts/update_annotations_sheet.py +++ b/tools/traffic_annotation/scripts/update_annotations_sheet.py
@@ -64,8 +64,10 @@ verbose: bool Flag requesting dump of details of actions. """ + print("Getting credential to update annotations report.") self.service = self._InitializeService( self._GetCredentials(credentials_file_path, client_secret_file_path)) + print("Successfully got credential to update annotations report.") self.spreadsheet_id = spreadsheet_id self.annotations_sheet_name = annotations_sheet_name self.changes_sheet_name = changes_sheet_name @@ -211,6 +213,7 @@ Returns: bool Flag specifying if everything was OK or not. """ + print("Generating updates for report.") sheet_contents = self.LoadAnnotationsSheet() if not sheet_contents: print("Could not read previous content.") @@ -300,6 +303,7 @@ |self.required_cell_updates| to the sheet. """ # Insert/Remove rows. + print("Applying updates for the report.") if self.required_row_updates: self.service.spreadsheets().batchUpdate( spreadsheetId=self.spreadsheet_id, @@ -377,6 +381,7 @@ help='Shows the configurations help.') args = parser.parse_args() + print("Updating annotations sheet.") if args.config_help: PrintConfigHelp() return 0 @@ -401,6 +406,7 @@ client_secret_file_path = config.get("client_secret_file_path", None), verbose = args.verbose) if not sheet_editor.GenerateUpdates(file_content): + print("Error generating updates for file content.") return -1 if sheet_editor.required_cell_updates or sheet_editor.required_row_updates:
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml index c5d4dd53..556bc46 100644 --- a/tools/traffic_annotation/summary/annotations.xml +++ b/tools/traffic_annotation/summary/annotations.xml
@@ -351,4 +351,5 @@ <item id="wallpaper_backdrop_images_info" added_in_milestone="99" content_hash_code="0010428c" os_list="chromeos" file_path="chrome/browser/ash/wallpaper_handlers/wallpaper_handlers.cc" /> <item id="wallpaper_backdrop_surprise_me_image" added_in_milestone="99" content_hash_code="0383b9db" os_list="chromeos" file_path="chrome/browser/ash/wallpaper_handlers/wallpaper_handlers.cc" /> <item id="nearby_connections_wifi_lan" added_in_milestone="99" content_hash_code="06b30010" os_list="chromeos" file_path="chrome/services/sharing/nearby/platform/wifi_lan_medium.cc" /> + <item id="timezone_lookup" added_in_milestone="98" content_hash_code="01e64e71" os_list="chromeos" file_path="ash/components/timezone/timezone_request.cc" /> </annotations>
diff --git a/tools/traffic_annotation/summary/grouping.xml b/tools/traffic_annotation/summary/grouping.xml index 9b126c2c..f5a07e5b 100644 --- a/tools/traffic_annotation/summary/grouping.xml +++ b/tools/traffic_annotation/summary/grouping.xml
@@ -79,6 +79,7 @@ <traffic_annotation unique_id="supervised_users_denylist"/> <traffic_annotation unique_id="tachyon_ice_config_fetcher"/> <traffic_annotation unique_id="terms_of_service_fetch"/> + <traffic_annotation unique_id="timezone_lookup" /> <traffic_annotation unique_id="url_icon_source_fetch"/> <traffic_annotation unique_id="wallpaper_backdrop_collection_names"/> <traffic_annotation unique_id="wallpaper_backdrop_images_info"/>
diff --git a/ui/base/ime/ash/ime_bridge.cc b/ui/base/ime/ash/ime_bridge.cc index 5771b1f..31d7556 100644 --- a/ui/base/ime/ash/ime_bridge.cc +++ b/ui/base/ime/ash/ime_bridge.cc
@@ -75,12 +75,6 @@ } // static. -void IMEBridge::Shutdown() { - delete g_ime_bridge; - g_ime_bridge = nullptr; -} - -// static. IMEBridge* IMEBridge::Get() { if (!g_ime_bridge) { g_ime_bridge = new IMEBridge();
diff --git a/ui/base/ime/ash/ime_bridge.h b/ui/base/ime/ash/ime_bridge.h index c3147f8..b864352 100644 --- a/ui/base/ime/ash/ime_bridge.h +++ b/ui/base/ime/ash/ime_bridge.h
@@ -26,14 +26,8 @@ IMEBridge& operator=(const IMEBridge&) = delete; ~IMEBridge(); - // Releases the global instance. - // TODO(crbug/1279743): This is a stateful global. Make it into true global - // singleton first, then use dependency injection instead in the next step. - static void Shutdown(); - - // Constructs the global instance (if not available yet) then returns it. - // TODO(crbug/1279743): This is a stateful global. Make it into true global - // singleton first, then use dependency injection instead in the next step. + // Constructs the global singleton (if not available yet) then returns it. + // TODO(crbug/1279743): Use dependency injection instead of global singleton. static IMEBridge* Get(); // Returns current InputContextHandler. This function returns nullptr if input
diff --git a/ui/base/ime/ash/input_method_ash_unittest.cc b/ui/base/ime/ash/input_method_ash_unittest.cc index ffdefa8..e943f98 100644 --- a/ui/base/ime/ash/input_method_ash_unittest.cc +++ b/ui/base/ime/ash/input_method_ash_unittest.cc
@@ -243,7 +243,6 @@ IMEBridge::Get()->SetCandidateWindowHandler(nullptr); mock_ime_engine_handler_.reset(); mock_ime_candidate_window_handler_.reset(); - IMEBridge::Shutdown(); ash::input_method::InputMethodManager::Shutdown(); ResetFlags();
diff --git a/ui/base/ime/ash/input_method_manager.cc b/ui/base/ime/ash/input_method_manager.cc index 816ae1a..b2e5117 100644 --- a/ui/base/ime/ash/input_method_manager.cc +++ b/ui/base/ime/ash/input_method_manager.cc
@@ -34,8 +34,6 @@ // static void InputMethodManager::Shutdown() { - DCHECK(g_input_method_manager) - << "InputMethodManager() is not initialized."; delete g_input_method_manager; g_input_method_manager = nullptr; }
diff --git a/ui/base/ime/init/input_method_initializer.cc b/ui/base/ime/init/input_method_initializer.cc index 82d387f..8ace875 100644 --- a/ui/base/ime/init/input_method_initializer.cc +++ b/ui/base/ime/init/input_method_initializer.cc
@@ -9,9 +9,8 @@ #include "build/build_config.h" #include "build/chromeos_buildflags.h" -#if BUILDFLAG(IS_CHROMEOS_ASH) -#include "ui/base/ime/ash/ime_bridge.h" -#elif defined(USE_AURA) && (defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) +#if !BUILDFLAG(IS_CHROMEOS_ASH) && defined(USE_AURA) && \ + (defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) #include "base/check.h" #include "ui/base/ime/linux/fake_input_method_context_factory.h" #elif defined(OS_WIN) @@ -37,9 +36,7 @@ } void ShutdownInputMethod() { -#if BUILDFLAG(IS_CHROMEOS_ASH) - IMEBridge::Shutdown(); -#elif defined(OS_WIN) +#if !BUILDFLAG(IS_CHROMEOS_ASH) && defined(OS_WIN) TSFBridge::Shutdown(); #endif } @@ -63,9 +60,8 @@ } void ShutdownInputMethodForTesting() { -#if BUILDFLAG(IS_CHROMEOS_ASH) - IMEBridge::Shutdown(); -#elif defined(USE_AURA) && (defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) +#if !BUILDFLAG(IS_CHROMEOS_ASH) && defined(USE_AURA) && \ + (defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) const LinuxInputMethodContextFactory* factory = LinuxInputMethodContextFactory::instance(); CHECK(!factory || factory == g_linux_input_method_context_factory_for_testing)
diff --git a/ui/gtk/gdk.sigs b/ui/gtk/gdk.sigs index 7a393ed..81e35f9 100644 --- a/ui/gtk/gdk.sigs +++ b/ui/gtk/gdk.sigs
@@ -34,3 +34,4 @@ void gdk_display_notify_startup_complete(GdkDisplay* display, const char* startup_id); guint32 gdk_keyval_to_unicode(guint keyval); gdouble gdk_screen_get_resolution(GdkScreen *screen); +guint gdk_unicode_to_keyval(guint32 wc);
diff --git a/ui/gtk/wayland/gtk_ui_platform_wayland.cc b/ui/gtk/wayland/gtk_ui_platform_wayland.cc index 4ce6921..4172497c 100644 --- a/ui/gtk/wayland/gtk_ui_platform_wayland.cc +++ b/ui/gtk/wayland/gtk_ui_platform_wayland.cc
@@ -36,6 +36,10 @@ GdkModifierType GtkUiPlatformWayland::GetGdkKeyEventState( const ui::KeyEvent& key_event) { + // We first reconstruct the state that was stored as a property by + // ui::WaylandEventSource. It is incomplete, however, and includes only the + // modifier state. Therefore, we compute and add the group manually, if + // possible. const ui::Event::Properties* properties = key_event.properties(); if (!properties) return static_cast<GdkModifierType>(0); @@ -50,12 +54,46 @@ flags |= value << bitshift; bitshift += 8; } - return ExtractGdkEventStateFromKeyEventFlags(flags); + auto state = ExtractGdkEventStateFromKeyEventFlags(flags); + + // We use the default group 0 in the following three cases: + // - we are using GTK 3 (gdk_display_map_keycode() is only available in + // GTK 4); + // - the pressed/released key is not a character (e.g. a modifier); + // - no entry in |keyvals| matches |keyval|. + unsigned int group = 0; + + if (gtk::GtkCheckVersion(4) && key_event.GetDomKey().IsCharacter()) { + guint keycode = + GetKeyEventProperty(key_event, ui::kPropertyKeyboardHwKeyCode); + guint keyval = gdk_unicode_to_keyval(key_event.GetDomKey().ToCharacter()); + GdkKeymapKey* keys; + guint* keyvals; + int n_entries; + + gdk_display_map_keycode(GetDefaultGdkDisplay(), keycode, &keys, &keyvals, + &n_entries); + + for (int i = 0; i < n_entries; ++i) { + if (keyvals[i] == keyval) { + group = keys[i].group; + break; + } + } + + g_free(keys); + g_free(keyvals); + } + + // As per Section 2.2.2 "Computing A State Field from an XKB State" of the XKB + // protocol specification. + return static_cast<GdkModifierType>(state | (group << 13)); } int GtkUiPlatformWayland::GetGdkKeyEventGroup(const ui::KeyEvent& key_event) { auto state = GetGdkKeyEventState(key_event); - // See XkbGroupForCoreState() in //ui/events/x/x11_event_translation.cc. + // As per Section 2.2.2 "Computing A State Field from an XKB State" of the XKB + // protocol specification. return (state >> 13) & 0x3; } @@ -99,6 +137,12 @@ gtk_window_present(window); } +GdkDisplay* GtkUiPlatformWayland::GetDefaultGdkDisplay() { + if (!default_display_) + default_display_ = gdk_display_get_default(); + return default_display_; +} + void GtkUiPlatformWayland::OnHandleSetTransient(GtkWidget* widget, const std::string& handle) { char* parent = const_cast<char*>(handle.c_str());
diff --git a/ui/gtk/wayland/gtk_ui_platform_wayland.h b/ui/gtk/wayland/gtk_ui_platform_wayland.h index 4e2f35d..4f495d3 100644 --- a/ui/gtk/wayland/gtk_ui_platform_wayland.h +++ b/ui/gtk/wayland/gtk_ui_platform_wayland.h
@@ -36,12 +36,14 @@ bool PreferGtkIme() override; private: + GdkDisplay* GetDefaultGdkDisplay(); // Called when xdg-foreign exports a parent window passed in // SetGtkWidgetTransientFor. void OnHandleSetTransient(GtkWidget* widget, const std::string& handle); void OnHandleForward(base::OnceCallback<void(std::string)> callback, const std::string& handle); + GdkDisplay* default_display_ = nullptr; base::WeakPtrFactory<GtkUiPlatformWayland> weak_factory_{this}; };
diff --git a/ui/webui/resources/cr_components/most_visited/most_visited.ts b/ui/webui/resources/cr_components/most_visited/most_visited.ts index 0f2bac6..0f0f6d76 100644 --- a/ui/webui/resources/cr_components/most_visited/most_visited.ts +++ b/ui/webui/resources/cr_components/most_visited/most_visited.ts
@@ -82,6 +82,7 @@ export interface MostVisitedElement { $: { actionMenu: CrActionMenuElement, + container: HTMLElement, dialog: CrDialogElement, toast: CrToastElement, addShortcut: HTMLElement,