diff --git a/DEPS b/DEPS index 7742ae635..4f34ce9 100644 --- a/DEPS +++ b/DEPS
@@ -195,11 +195,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': '652124c372e528937645533147c7da8ec8ac4e08', + 'skia_revision': 'df9ed89229db82e606c67fbf0f5c24b4c383c1e1', # 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': '9e3426ebd5780d3e984c142cc521f2c33b6e32f2', + 'v8_revision': '2bc574faad33dcdbded0b78e08f1961df1a0299a', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other. @@ -207,11 +207,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': 'cc958e0e87034f591ea2a76d2809b13dad186c93', + 'angle_revision': '07ae53f59079cde6bd97542852bac8dffbd2231d', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. - 'swiftshader_revision': 'cda86eff64617e9b48167f1aa6a31bcdb823c10b', + 'swiftshader_revision': 'abe07b9438553f741e776dedb59a2d4b502a9983', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. @@ -266,7 +266,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': '86c9a7134948a3e2f0c82edbf1cab340ed6e2c20', + 'devtools_frontend_revision': 'f20a184a017ffbe5a2123596aab54ff6af719232', # 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. @@ -302,7 +302,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. - 'spv_tools_revision': '13a65b1aee425a97b9ca73d81212d99fd2bf9227', + 'spv_tools_revision': 'df859f77dab392dbc78c213d36ba19216b3d068e', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -318,7 +318,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': '4a486be696b44151bbda5e837a784560b2d9154f', + 'dawn_revision': '2b1c0b0e92e745b96ed282f9c4f58e815fb8679d', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -545,7 +545,7 @@ }, 'src/ios/third_party/material_components_ios/src': { - 'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + 'c48cd65ade15bc29ab2329ed9e8032e1f5f01a2c', + 'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + '225cd3c0cba6ac194c77a418188d1c4421227f2e', 'condition': 'checkout_ios', }, @@ -875,7 +875,7 @@ # Build tools for Chrome OS. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'bca9dcdf05aaccf4e0c2dea6bd4cddced50f0c88', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '35492ebf6ba2deca7f54bfde94013d773a777a93', 'condition': 'checkout_chromeos', }, @@ -1248,7 +1248,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + 'dbee93ac203d9269fe93c1ff1e48eba6148e542c', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '78d7b4b8250e8fb9509115c2e0b98dd32bb5b9f4', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', @@ -1550,7 +1550,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/help_app/app', - 'version': 'yzqZBKPmH-7JzPqoGRyX5xzi_i8ljeOuLly8tsBta8YC', + 'version': 'fX1CZHk_Z55AAvLsAiH1mQ6Dr6f33Mf7P1iCopozfbEC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/PRESUBMIT.py b/PRESUBMIT.py index 6f1eeba..a5b9b75 100644 --- a/PRESUBMIT.py +++ b/PRESUBMIT.py
@@ -5099,6 +5099,11 @@ new_id_to_msg_map = grd_helper.GetGrdMessages( StringIO(unicode('\n'.join(f.NewContents()))), file_dir) + grd_name, ext = input_api.os_path.splitext( + input_api.os_path.basename(file_path)) + screenshots_dir = input_api.os_path.join( + input_api.os_path.dirname(file_path), grd_name + ext.replace('.', '_')) + # Compute added, removed and modified message IDs. old_ids = set(old_id_to_msg_map) new_ids = set(new_id_to_msg_map) @@ -5108,12 +5113,16 @@ for key in old_ids.intersection(new_ids): if (old_id_to_msg_map[key].FormatXml() != new_id_to_msg_map[key].FormatXml()): - modified_ids.add(key) - - grd_name, ext = input_api.os_path.splitext( - input_api.os_path.basename(file_path)) - screenshots_dir = input_api.os_path.join( - input_api.os_path.dirname(file_path), grd_name + ext.replace('.', '_')) + sha1_path = input_api.os_path.join( + screenshots_dir, key + '.png.sha1') + if sha1_path not in new_or_added_paths and \ + not input_api.os_path.exists(sha1_path): + # This message does not yet have a screenshot. Require one. + modified_ids.add(key) + elif (old_id_to_msg_map[key].ContentsAsXml('', True) + != new_id_to_msg_map[key].ContentsAsXml('', True)): + # The message content itself changed. Require an updated screenshot. + modified_ids.add(key) if run_screenshot_check: # Check the screenshot directory for .png files. Warn if there is any.
diff --git a/PRESUBMIT_test.py b/PRESUBMIT_test.py index cb9461d..c6f01c89f 100755 --- a/PRESUBMIT_test.py +++ b/PRESUBMIT_test.py
@@ -2872,6 +2872,22 @@ '</message>', '</grit-part>') + NEW_GRDP_CONTENTS3 = ( + '<?xml version="1.0" encoding="utf-8"?>', + '<grit-part>', + '<message name="IDS_PART_TEST1" desc="Description with typo.">', + 'Part string 1', + '</message>', + '</grit-part>') + + NEW_GRDP_CONTENTS4 = ( + '<?xml version="1.0" encoding="utf-8"?>', + '<grit-part>', + '<message name="IDS_PART_TEST1" desc="Description with typo fixed.">', + 'Part string 1', + '</message>', + '</grit-part>') + # A grdp file with one ICU syntax message without syntax errors. NEW_GRDP_CONTENTS_ICU_SYNTAX_OK1 = ( '<?xml version="1.0" encoding="utf-8"?>', @@ -2975,6 +2991,25 @@ os.path.join('test_grd', 'IDS_TEST2.png.sha1'), ], warnings[0].items) + def testModifiedMessageDescription(self): + # CL modified a message description for a message that does not yet have a + # screenshot. Should warn. + input_api = self.makeInputApi([ + MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS3, + self.NEW_GRDP_CONTENTS4, action='M')]) + warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi()) + self.assertEqual(1, len(warnings)) + + # CL modified a message description for a message that already has a + # screenshot. Should not warn. + input_api = self.makeInputApi([ + MockAffectedFile('part.grdp', self.NEW_GRDP_CONTENTS3, + self.NEW_GRDP_CONTENTS4, action='M'), + MockFile(os.path.join('part_grdp', 'IDS_PART_TEST1.png.sha1'), + 'binary', action='A')]) + warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi()) + self.assertEqual(0, len(warnings)) + def testPngAddedSha1NotAdded(self): # CL added one new message in a grd file and added the png file associated # with it, but did not add the corresponding sha1 file. This should warn
diff --git a/WATCHLISTS b/WATCHLISTS index 02bfdad..92a95be 100644 --- a/WATCHLISTS +++ b/WATCHLISTS
@@ -1541,6 +1541,10 @@ '|chrome/browser/content_settings/permission*'\ '|permission_context', }, + 'phonehub': { + 'filepath': 'chrome/browser/chromeos/phonehub/|'\ + 'chromeos/components/phonehub/', + }, 'picture_in_picture': { 'filepath': 'third_party/blink/renderer/modules/picture_in_picture/' }, @@ -2670,6 +2674,9 @@ 'hanxi+watch@chromium.org', 'mlamouri+watch-permissions@chromium.org', 'permissions-reviews@chromium.org'], + 'phonehub': ['hsuregan+watch-phonehub@chromium.org', + 'khorimoto+watch-phonehub@chromium.org', + 'themaxli+watch-phonehub@chromium.org'], 'picture_in_picture': ['beaufort.francois+pip@gmail.com'], 'polymer': ['michaelpg+watch-polymer@chromium.org'], 'popup_blocker': ['csharrison+watch-popups@chromium.org'],
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index 996e4d4..ea618988 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -469,12 +469,16 @@ "hud_display/hud_constants.h", "hud_display/hud_display.cc", "hud_display/hud_display.h", + "hud_display/hud_header_view.cc", + "hud_display/hud_header_view.h", "hud_display/hud_properties.cc", "hud_display/hud_properties.h", "hud_display/hud_settings_view.cc", "hud_display/hud_settings_view.h", "hud_display/memory_status.cc", "hud_display/memory_status.h", + "hud_display/tab_strip.cc", + "hud_display/tab_strip.h", "ime/ime_controller_impl.cc", "ime/ime_controller_impl.h", "ime/ime_mode_indicator_view.cc",
diff --git a/ash/hud_display/hud_constants.h b/ash/hud_display/hud_constants.h index db884dd..993d5b0 100644 --- a/ash/hud_display/hud_constants.h +++ b/ash/hud_display/hud_constants.h
@@ -12,6 +12,33 @@ constexpr SkAlpha kHUDAlpha = 204; // = 0.8 * 255 +// Use light orange color. +constexpr SkColor kHUDDefaultColor = + SkColorSetARGB(kHUDAlpha, 0xFF, 0xB2, 0x66); + +constexpr SkColor kHUDBackground = SkColorSetARGB(kHUDAlpha, 17, 17, 17); + +// Radius of rounded corners for tabs. +// Must be be divisible by 3 to make kTabOverlayWidth integer. +constexpr int kTabOverlayCornerRadius = 9; + +// Border around settings icon in the settings button. +constexpr int kSettingsIconBorder = 5; + +// Settings button icon size. +constexpr int kHUDSettingsIconSize = 18; + +// Visible border inside the HUDDisplayView rectangle around contents. +// HUDDisplayView does not use insets itself. Children substitute this inset +// where needed. +constexpr int kHUDInset = 5; + +// HUD display modes. +enum class DisplayModes { + MEMORY_DISPLAY, + DEFAULT = MEMORY_DISPLAY +}; + } // namespace hud_display } // namespace ash
diff --git a/ash/hud_display/hud_display.cc b/ash/hud_display/hud_display.cc index 11a834d..a738cdd 100644 --- a/ash/hud_display/hud_display.cc +++ b/ash/hud_display/hud_display.cc
@@ -8,21 +8,20 @@ #include "ash/fast_ink/view_tree_host_widget.h" #include "ash/hud_display/graphs_container_view.h" #include "ash/hud_display/hud_constants.h" +#include "ash/hud_display/hud_header_view.h" #include "ash/hud_display/hud_properties.h" #include "ash/hud_display/hud_settings_view.h" +#include "ash/hud_display/tab_strip.h" #include "ash/public/cpp/shell_window_ids.h" #include "ash/root_window_controller.h" #include "ash/shell.h" +#include "base/strings/utf_string_conversions.h" #include "components/vector_icons/vector_icons.h" #include "ui/aura/window.h" #include "ui/base/hit_test.h" #include "ui/events/base_event_utils.h" -#include "ui/gfx/canvas.h" -#include "ui/gfx/paint_vector_icon.h" -#include "ui/gfx/skia_util.h" #include "ui/views/background.h" #include "ui/views/border.h" -#include "ui/views/controls/button/image_button.h" #include "ui/views/layout/box_layout.h" #include "ui/views/layout/fill_layout.h" #include "ui/views/widget/widget.h" @@ -31,101 +30,46 @@ namespace hud_display { namespace { -constexpr int kVectorIconSize = 18; +constexpr size_t kHUDGraphsInset = 5; + +// Default HUDDisplayView height. +static constexpr size_t kDefaultHUDGraphHeight = 300; + +// Top border + Header height + margin + graph height + bottom border.. +constexpr int kHUDViewDefaultHeight = + kHUDInset + (kHUDSettingsIconSize + 2 * kSettingsIconBorder) + + kHUDGraphsInset + kDefaultHUDGraphHeight + kHUDInset; std::unique_ptr<views::Widget> g_hud_widget; -constexpr SkColor kBackground = SkColorSetARGB(kHUDAlpha, 17, 17, 17); - -// Basically views::SolidBackground with SkBlendMode::kSrc paint mode. -class SolidSourceBackground : public views::Background { +// ClientView that return HTNOWHERE by default. A child view can receive event +// by setting kHitTestComponentKey property to HTCLIENT. +class HTClientView : public views::ClientView { public: - explicit SolidSourceBackground(SkColor color) { - SetNativeControlColor(color); - } + METADATA_HEADER(HTClientView); - SolidSourceBackground(const SolidSourceBackground&) = delete; - SolidSourceBackground& operator=(const SolidSourceBackground&) = delete; + HTClientView(HUDDisplayView* hud_display, + views::Widget* widget, + views::View* contents_view) + : views::ClientView(widget, contents_view), hud_display_(hud_display) {} + HTClientView(const HTClientView&) = delete; + HTClientView& operator=(const HTClientView&) = delete; - void Paint(gfx::Canvas* canvas, views::View* /*view*/) const override { - // Fill the background. Note that we don't constrain to the bounds as - // canvas is already clipped for us. - canvas->DrawColor(get_color(), SkBlendMode::kSrc); - } -}; + ~HTClientView() override = default; -std::unique_ptr<views::View> CreateButtonsContainer() { - auto container = std::make_unique<views::View>(); - auto layout_manager = std::make_unique<views::BoxLayout>( - views::BoxLayout::Orientation::kHorizontal); - layout_manager->set_cross_axis_alignment( - views::BoxLayout::CrossAxisAlignment::kStart); - container->SetLayoutManager(std::move(layout_manager)); - return container; -} - -std::unique_ptr<views::ImageButton> CreateSettingsButton(HUDDisplayView* hud) { - auto button = std::make_unique<views::ImageButton>(hud); - button->SetVisible(false); - button->SetImage( - views::Button::ButtonState::STATE_NORMAL, - gfx::CreateVectorIcon(vector_icons::kSettingsIcon, kVectorIconSize, - HUDSettingsView::kDefaultColor)); - button->SetBorder(views::CreateEmptyBorder(gfx::Insets(5))); - button->SetProperty(kHUDClickHandler, HTCLIENT); - button->SetBackground(std::make_unique<SolidSourceBackground>(kBackground)); - return button; -} - -class HUDOverlayContainerView : public views::View { - public: - METADATA_HEADER(HUDOverlayContainerView); - - explicit HUDOverlayContainerView(HUDDisplayView* hud); - ~HUDOverlayContainerView() override = default; - - HUDOverlayContainerView(const HUDOverlayContainerView&) = delete; - HUDOverlayContainerView& operator=(const HUDOverlayContainerView&) = delete; - - HUDSettingsView* settings_view() const { return settings_view_; } - views::ImageButton* settings_trigger_button() const { - return settings_trigger_button_; + // views::ClientView + int NonClientHitTest(const gfx::Point& point) override { + return hud_display_->NonClientHitTest(point); } private: - HUDSettingsView* settings_view_ = nullptr; - views::ImageButton* settings_trigger_button_ = nullptr; + HUDDisplayView* hud_display_; }; -BEGIN_METADATA(HUDOverlayContainerView) -METADATA_PARENT_CLASS(View) +BEGIN_METADATA(HTClientView) +METADATA_PARENT_CLASS(ClientView) END_METADATA() -HUDOverlayContainerView::HUDOverlayContainerView(HUDDisplayView* hud) { - // Overlay container has two child views stacked vertically and stretched - // horizontally. - // The top is a container for "Settings" button. - // The bottom is Settings UI view. - views::BoxLayout* layout_manager = - SetLayoutManager(std::make_unique<views::BoxLayout>( - views::BoxLayout::Orientation::kVertical)); - layout_manager->set_cross_axis_alignment( - views::BoxLayout::CrossAxisAlignment::kStretch); - { - // Buttons container arranges buttons horizontally and does not alter - // button sizes. - views::View* buttons_container = AddChildView(CreateButtonsContainer()); - settings_trigger_button_ = - buttons_container->AddChildView(CreateSettingsButton(hud)); - } - // HUDSettingsView starts invisible. - settings_view_ = AddChildView(std::make_unique<HUDSettingsView>()); - - // Make settings view occupy all the remaining space. - layout_manager->SetFlexForView(settings_view_, 1, - /*use_min_size=*/false); -} - } // namespace //////////////////////////////////////////////////////////////////////////////// @@ -152,7 +96,7 @@ kShellWindowId_OverlayContainer); params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; params.bounds = - gfx::Rect(Graph::kDefaultWidth + 2 * kHUDInset, kDefaultHUDHeight); + gfx::Rect(Graph::kDefaultWidth + 2 * kHUDInset, kHUDViewDefaultHeight); auto* widget = CreateViewTreeHostWidget(std::move(params)); widget->GetLayer()->SetName("HUDDisplayView"); widget->Show(); @@ -163,43 +107,53 @@ HUDDisplayView::HUDDisplayView() { DCHECK_CALLED_ON_VALID_SEQUENCE(ui_sequence_checker_); - SetBackground(views::CreateSolidBackground(kBackground)); - SetBorder(views::CreateEmptyBorder(gfx::Insets(5))); + // Layout: + // ---------------------- + // | Header | // Buttons, tabs, controls + // ---------------------- + // | | // Data views full-size, z-stacked. + // | Data | + // | | + // ---------------------- - SetLayoutManager(std::make_unique<views::FillLayout>()); + // Create two child views for header and data. Vertically stacked. + views::BoxLayout* layout_manager = + SetLayoutManager(std::make_unique<views::BoxLayout>( + views::BoxLayout::Orientation::kVertical)); + layout_manager->set_cross_axis_alignment( + views::BoxLayout::CrossAxisAlignment::kStretch); + + header_view_ = AddChildView(std::make_unique<HUDHeaderView>(this)); + views::View* data = AddChildView(std::make_unique<views::View>()); + + // Data view takes the rest of the host view. + layout_manager->SetFlexForView(data, 1, /*use_min_size=*/false); + + // Setup header. + + // TODO: Add tab buttons via: + // header_view_->tab_strip()->AddTabButton(this, DisplayModes::MEMORY_DISPLAY, + // base::ASCIIToUTF16("RAM")); + + // Setup data. + data->SetBackground(views::CreateSolidBackground(kHUDBackground)); + data->SetBorder(views::CreateEmptyBorder( + gfx::Insets(kHUDGraphsInset, kHUDInset, kHUDInset, kHUDInset))); // We have two child views z-stacked. // The bottom one is GraphsContainerView with all the graph lines. - // The top one lays out buttons and settings UI overlays. - graphs_container_ = AddChildView(std::make_unique<GraphsContainerView>()); - - HUDOverlayContainerView* overlay_container = - AddChildView(std::make_unique<HUDOverlayContainerView>(this)); - settings_view_ = overlay_container->settings_view(); - settings_trigger_button_ = overlay_container->settings_trigger_button(); - - // Receive OnMouseEnter/OnMouseLEave when hovering over the child views too. - set_notify_enter_exit_on_child(true); + // The top one is settings UI overlay. + data->SetLayoutManager(std::make_unique<views::FillLayout>()); + graphs_container_ = + data->AddChildView(std::make_unique<GraphsContainerView>()); + settings_view_ = data->AddChildView(std::make_unique<HUDSettingsView>()); + settings_view_->SetVisible(false); } HUDDisplayView::~HUDDisplayView() { DCHECK_CALLED_ON_VALID_SEQUENCE(ui_sequence_checker_); } -//////////////////////////////////////////////////////////////////////////////// - -void HUDDisplayView::OnMouseEntered(const ui::MouseEvent& /*event*/) { - settings_trigger_button_->SetVisible(true); -} - -void HUDDisplayView::OnMouseExited(const ui::MouseEvent& /*event*/) { - // Button is always visible if Settings UI is visible. - if (settings_view_->GetVisible()) - return; - - settings_trigger_button_->SetVisible(false); -} - int HUDDisplayView::NonClientHitTest(const gfx::Point& point) { const View* view = GetEventHandlerForPoint(point); if (!view) @@ -208,24 +162,9 @@ return view->GetProperty(kHUDClickHandler); } -// ClientView that return HTNOWHERE by default. A child view can receive event -// by setting kHitTestComponentKey property to HTCLIENT. -class HTClientView : public views::ClientView { - public: - HTClientView(HUDDisplayView* hud_display, - views::Widget* widget, - views::View* contents_view) - : views::ClientView(widget, contents_view), hud_display_(hud_display) {} - ~HTClientView() override = default; - - int NonClientHitTest(const gfx::Point& point) override; - - private: - HUDDisplayView* hud_display_ = nullptr; -}; - -int HTClientView::NonClientHitTest(const gfx::Point& point) { - return hud_display_->NonClientHitTest(point); +void HUDDisplayView::TabButtonPressed(const HUDTabButton* tab_button) { + header_view_->tab_strip()->ActivateTab(tab_button); + // TODO: switch on tab_button->display_mode(). } views::ClientView* HUDDisplayView::CreateClientView(views::Widget* widget) {
diff --git a/ash/hud_display/hud_display.h b/ash/hud_display/hud_display.h index 3237bae2..99d9cfe 100644 --- a/ash/hud_display/hud_display.h +++ b/ash/hud_display/hud_display.h
@@ -5,19 +5,18 @@ #ifndef ASH_HUD_DISPLAY_HUD_DISPLAY_H_ #define ASH_HUD_DISPLAY_HUD_DISPLAY_H_ +#include "ash/hud_display/hud_constants.h" #include "base/sequence_checker.h" #include "ui/views/controls/button/button.h" #include "ui/views/widget/widget_delegate.h" -namespace views { -class ImageButton; -} - namespace ash { namespace hud_display { class GraphsContainerView; +class HUDHeaderView; class HUDSettingsView; +class HUDTabButton; // HUDDisplayView class can be used to display a system monitoring overview. class HUDDisplayView : public views::WidgetDelegateView, @@ -25,21 +24,11 @@ public: METADATA_HEADER(HUDDisplayView); - // Default HUDDisplayView height. - static constexpr size_t kDefaultHUDHeight = 300; - - // Border width inside the HUDDisplayView rectangle around contents. - static constexpr size_t kHUDInset = 5; - HUDDisplayView(); - ~HUDDisplayView() override; - HUDDisplayView(const HUDDisplayView&) = delete; HUDDisplayView& operator=(const HUDDisplayView&) = delete; - // view:: - void OnMouseEntered(const ui::MouseEvent& event) override; - void OnMouseExited(const ui::MouseEvent& event) override; + ~HUDDisplayView() override; // WidgetDelegate: views::ClientView* CreateClientView(views::Widget* widget) override; @@ -58,10 +47,13 @@ // of the children. int NonClientHitTest(const gfx::Point& point); + // Changes UI display mode. + void TabButtonPressed(const HUDTabButton* tab_button); + private: - GraphsContainerView* graphs_container_ = nullptr; // not owned - HUDSettingsView* settings_view_ = nullptr; // not owned - views::ImageButton* settings_trigger_button_ = nullptr; // not owned + HUDHeaderView* header_view_ = nullptr; // not owned + GraphsContainerView* graphs_container_ = nullptr; // not owned + HUDSettingsView* settings_view_ = nullptr; // not owned SEQUENCE_CHECKER(ui_sequence_checker_); };
diff --git a/ash/hud_display/hud_header_view.cc b/ash/hud_display/hud_header_view.cc new file mode 100644 index 0000000..fc49c698 --- /dev/null +++ b/ash/hud_display/hud_header_view.cc
@@ -0,0 +1,247 @@ +// 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. + +#include "ash/hud_display/hud_header_view.h" + +#include "ash/hud_display/hud_constants.h" +#include "ash/hud_display/hud_display.h" +#include "ash/hud_display/hud_properties.h" +#include "ash/hud_display/tab_strip.h" +#include "components/vector_icons/vector_icons.h" +#include "ui/gfx/canvas.h" +#include "ui/gfx/paint_vector_icon.h" +#include "ui/gfx/skia_util.h" +#include "ui/views/background.h" +#include "ui/views/border.h" +#include "ui/views/controls/button/image_button.h" +#include "ui/views/layout/box_layout.h" +#include "ui/views/layout/layout_manager.h" + +namespace ash { +namespace hud_display { +namespace { + +// Basically views::SolidBackground with SkBlendMode::kSrc paint mode. +class SolidSourceBackground : public views::Background { + public: + // Background will have top rounded corners with |top_rounding_radius|. + SolidSourceBackground(SkColor color, SkScalar top_rounding_radius) + : top_rounding_radius_(top_rounding_radius) { + SetNativeControlColor(color); + } + + SolidSourceBackground(const SolidSourceBackground&) = delete; + SolidSourceBackground& operator=(const SolidSourceBackground&) = delete; + + ~SolidSourceBackground() override = default; + + // views::Background + void Paint(gfx::Canvas* canvas, views::View* view) const override { + if (top_rounding_radius_ == 0) { + // Fill the background. Note that we don't constrain to the bounds as + // canvas is already clipped for us. + canvas->DrawColor(get_color(), SkBlendMode::kSrc); + } else { + const SkScalar circle_size = top_rounding_radius_ * 2; + const int right_edge = view->width(); + const int bottom_edge = view->height(); + + SkPath path; + path.moveTo(0, bottom_edge); + /* |false| will draw straight line to the start of the arc */ + path.arcTo({0, 0, circle_size, circle_size}, -180, 90, false); + path.arcTo({right_edge - circle_size, 0, right_edge, circle_size}, -90, + 90, false); + path.lineTo(right_edge, bottom_edge); + + cc::PaintFlags flags; + flags.setAntiAlias(true); + flags.setBlendMode(SkBlendMode::kSrc); + flags.setStyle(cc::PaintFlags::kFill_Style); + flags.setColor(get_color()); + canvas->DrawPath(path, flags); + } + } + + private: + SkScalar top_rounding_radius_; +}; + +// Draws bottom left rounded background triangle. +class BottomLeftOuterBackground : public views::Background { + public: + // Background will have left bottom rounded corner with |top_rounding_radius|. + BottomLeftOuterBackground(SkColor color, SkScalar top_rounding_radius) + : inner_radius_(top_rounding_radius) { + SetNativeControlColor(color); + } + + BottomLeftOuterBackground(const BottomLeftOuterBackground&) = delete; + BottomLeftOuterBackground& operator=(const BottomLeftOuterBackground&) = + delete; + + ~BottomLeftOuterBackground() override = default; + + // views::Background + void Paint(gfx::Canvas* canvas, views::View* view) const override { + const SkScalar circle_size = inner_radius_ * 2; + const int bottom_edge = view->height(); + + SkPath path; + path.moveTo(0, bottom_edge); + /* |false| will draw straight line to the start of the arc */ + path.arcTo({0, bottom_edge - circle_size, circle_size, bottom_edge}, 90, 90, + false); + path.lineTo(0, bottom_edge); + + cc::PaintFlags flags; + flags.setAntiAlias(true); + flags.setBlendMode(SkBlendMode::kSrc); + flags.setStyle(cc::PaintFlags::kFill_Style); + flags.setColor(get_color()); + canvas->DrawPath(path, flags); + } + + private: + SkScalar inner_radius_; +}; + +// ImageButton with underline +class SettingsButton : public views::ImageButton { + public: + METADATA_HEADER(SettingsButton); + + explicit SettingsButton(views::ButtonListener* listener) + : views::ImageButton(listener) { + SetImage(views::Button::ButtonState::STATE_NORMAL, + gfx::CreateVectorIcon(vector_icons::kSettingsIcon, + kHUDSettingsIconSize, kHUDDefaultColor)); + SetBorder(views::CreateEmptyBorder(gfx::Insets(kSettingsIconBorder))); + SetProperty(kHUDClickHandler, HTCLIENT); + } + + SettingsButton(const SettingsButton&) = delete; + SettingsButton& operator=(const SettingsButton&) = delete; + + ~SettingsButton() override = default; + + protected: + // ImageButton + void PaintButtonContents(gfx::Canvas* canvas) override { + views::ImageButton::PaintButtonContents(canvas); + + SkPath path; + path.moveTo(0, height()); + path.lineTo(height(), width()); + + cc::PaintFlags flags; + flags.setAntiAlias(true); + flags.setBlendMode(SkBlendMode::kSrc); + flags.setStyle(cc::PaintFlags::kStroke_Style); + flags.setStrokeWidth(1); + flags.setColor(kHUDDefaultColor); + canvas->DrawPath(path, flags); + } +}; + +BEGIN_METADATA(SettingsButton) +METADATA_PARENT_CLASS(ImageButton) +END_METADATA() + +// Basically FillLayout that matches host size to the given data view. +// Padding will take the rest of the host view to the right. +class HUDHeaderLayout : public views::LayoutManager { + public: + HUDHeaderLayout(const views::View* data_view, views::View* padding) + : data_view_(data_view), padding_(padding) {} + + HUDHeaderLayout(const HUDHeaderLayout&) = delete; + HUDHeaderLayout& operator=(const HUDHeaderLayout&) = delete; + + ~HUDHeaderLayout() override = default; + + // views::LayoutManager: + void Layout(views::View* host) override; + gfx::Size GetPreferredSize(const views::View* host) const override; + + private: + const views::View* data_view_; + views::View* padding_; +}; + +gfx::Size HUDHeaderLayout::GetPreferredSize(const views::View* host) const { + return data_view_->GetPreferredSize() + padding_->GetPreferredSize(); +} + +void HUDHeaderLayout::Layout(views::View* host) { + // Assume there are only 3 child views (data, background and padding). + DCHECK_EQ(host->children().size(), 3U); + + const gfx::Size preferred_size = data_view_->GetPreferredSize(); + + for (auto* child : host->children()) { + if (child != padding_) { + child->SetPosition({0, 0}); + child->SetSize(preferred_size); + } + } + // Layout padding + padding_->SetPosition({preferred_size.width(), 0}); + padding_->SetSize({host->width() - preferred_size.width(), host->height()}); +} + +} // namespace + +//////////////////////////////////////////////////////////////////////////////// +// HUDHeaderView + +BEGIN_METADATA(HUDHeaderView) +METADATA_PARENT_CLASS(View) +END_METADATA() + +HUDHeaderView::HUDHeaderView(HUDDisplayView* hud) { + // Header is rendered as horizontal container with three children: + // background, buttons container and padding. + + // Header should have background under the buttons area only. + // To achieve this we have buttons container view to calculate total width, + // and special layout manager that matches size of the background view to the + // size of the buttons. + // + // There is additional "padding" view an the end to draw bottom inner + // rounded piece of background. + + views::View* header_background = + AddChildView(std::make_unique<views::View>()); + header_background->SetBackground(std::make_unique<SolidSourceBackground>( + kHUDBackground, kTabOverlayCornerRadius)); + + views::View* header_buttons = AddChildView(std::make_unique<views::View>()); + header_buttons + ->SetLayoutManager(std::make_unique<views::BoxLayout>( + views::BoxLayout::Orientation::kHorizontal)) + ->set_cross_axis_alignment( + views::BoxLayout::CrossAxisAlignment::kStretch); + // Header does not have margin between header and data. + // Data has its top margin (kHUDGraphsInset). + header_buttons->SetBorder(views::CreateEmptyBorder( + gfx::Insets(kHUDInset, kHUDInset, 0, kHUDInset))); + + // Add buttons and tab strip. + header_buttons->AddChildView(std::make_unique<SettingsButton>(hud)); + tab_strip_ = header_buttons->AddChildView(std::make_unique<HUDTabStrip>(hud)); + + // Padding will take the rest of the header and draw bottom inner left + // background padding. + views::View* padding = AddChildView(std::make_unique<views::View>()); + padding->SetBackground(std::make_unique<BottomLeftOuterBackground>( + kHUDBackground, kTabOverlayCornerRadius)); + + SetLayoutManager(std::make_unique<HUDHeaderLayout>(header_buttons, padding)); +} + +HUDHeaderView::~HUDHeaderView() = default; + +} // namespace hud_display +} // namespace ash
diff --git a/ash/hud_display/hud_header_view.h b/ash/hud_display/hud_header_view.h new file mode 100644 index 0000000..743b1400 --- /dev/null +++ b/ash/hud_display/hud_header_view.h
@@ -0,0 +1,37 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_HUD_DISPLAY_HUD_HEADER_VIEW_H_ +#define ASH_HUD_DISPLAY_HUD_HEADER_VIEW_H_ + +#include "ui/views/view.h" + +namespace ash { +namespace hud_display { + +class HUDDisplayView; +class HUDTabStrip; + +// HUDHeaderView renders header (with buttons and tabs) of the HUD. +class HUDHeaderView : public views::View { + public: + METADATA_HEADER(HUDHeaderView); + + explicit HUDHeaderView(HUDDisplayView* hud); + + HUDHeaderView(const HUDHeaderView&) = delete; + HUDHeaderView& operator=(const HUDHeaderView&) = delete; + + ~HUDHeaderView() override; + + HUDTabStrip* tab_strip() { return tab_strip_; } + + private: + HUDTabStrip* tab_strip_ = nullptr; // not owned +}; + +} // namespace hud_display +} // namespace ash + +#endif // ASH_HUD_DISPLAY_HUD_HEADER_VIEW_H_
diff --git a/ash/hud_display/hud_settings_view.cc b/ash/hud_display/hud_settings_view.cc index 0853e29..b9bb882 100644 --- a/ash/hud_display/hud_settings_view.cc +++ b/ash/hud_display/hud_settings_view.cc
@@ -79,26 +79,23 @@ METADATA_PARENT_CLASS(View) END_METADATA() -constexpr SkColor HUDSettingsView::kDefaultColor; - HUDSettingsView::HUDSettingsView() { SetVisible(false); - auto layout_manager = std::make_unique<views::BoxLayout>( - views::BoxLayout::Orientation::kVertical); + views::BoxLayout* layout_manager = + SetLayoutManager(std::make_unique<views::BoxLayout>( + views::BoxLayout::Orientation::kVertical)); layout_manager->set_cross_axis_alignment( views::BoxLayout::CrossAxisAlignment::kStart); - SetLayoutManager(std::move(layout_manager)); - SetBorder(views::CreateSolidBorder(1, kDefaultColor)); + SetBorder(views::CreateSolidBorder(1, kHUDDefaultColor)); auto add_checkbox = [](HUDSettingsView* self, const base::string16& text) -> views::Checkbox* { - auto checkbox = std::make_unique<views::Checkbox>(text, self); - views::Checkbox* result = checkbox.get(); - checkbox->SetEnabledTextColors(kDefaultColor); + views::Checkbox* checkbox = + self->AddChildView(std::make_unique<views::Checkbox>(text, self)); + checkbox->SetEnabledTextColors(kHUDDefaultColor); checkbox->SetProperty(kHUDClickHandler, HTCLIENT); - self->AddChildView(std::move(checkbox)); - return result; + return checkbox; }; checkbox_handlers_.push_back(std::make_unique<HUDCheckboxHandler>(
diff --git a/ash/hud_display/hud_settings_view.h b/ash/hud_display/hud_settings_view.h index 5b742f10..60a5a0c3 100644 --- a/ash/hud_display/hud_settings_view.h +++ b/ash/hud_display/hud_settings_view.h
@@ -9,7 +9,6 @@ #include <vector> #include "ash/hud_display/hud_constants.h" -#include "third_party/skia/include/core/SkColor.h" #include "ui/views/controls/button/button.h" #include "ui/views/view.h" @@ -22,10 +21,6 @@ public: METADATA_HEADER(HUDSettingsView); - // Use light orange color. - static constexpr SkColor kDefaultColor = - SkColorSetARGB(kHUDAlpha, 0xFF, 0xB2, 0x66); - HUDSettingsView(); ~HUDSettingsView() override;
diff --git a/ash/hud_display/tab_strip.cc b/ash/hud_display/tab_strip.cc new file mode 100644 index 0000000..8c2365d --- /dev/null +++ b/ash/hud_display/tab_strip.cc
@@ -0,0 +1,215 @@ +// 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. + +#include "ash/hud_display/tab_strip.h" + +#include <cmath> + +#include "ash/hud_display/hud_display.h" +#include "ash/hud_display/hud_properties.h" +#include "third_party/skia/include/core/SkPath.h" +#include "ui/gfx/canvas.h" +#include "ui/gfx/text_constants.h" +#include "ui/views/layout/layout_manager.h" + +namespace ash { +namespace hud_display { +namespace { + +// The width in pixels of overlaying adjacent tabs. Must be even number. +constexpr int kTabOverlayWidth = 2 * kTabOverlayCornerRadius / 3; + +// Border around tab text (tab overlay width will be added to this). +constexpr int kTabTitleBorder = 3; + +class HUDTabStripLayout : public views::LayoutManager { + public: + HUDTabStripLayout() = default; + + HUDTabStripLayout(const HUDTabStripLayout&) = delete; + HUDTabStripLayout& operator=(const HUDTabStripLayout&) = delete; + + ~HUDTabStripLayout() override = default; + + // views::LayoutManager: + void Layout(views::View* host) override; + gfx::Size GetPreferredSize(const views::View* host) const override; +}; + +gfx::Size HUDTabStripLayout::GetPreferredSize(const views::View* host) const { + gfx::Size result; + for (const auto* child : host->children()) { + const gfx::Size child_preferred = child->GetPreferredSize(); + // Tab strip is always horizontal. + result.set_width(result.width() + child_preferred.width() - + kTabOverlayWidth); + result.set_height(std::max(result.height(), child_preferred.height())); + } + // Assume all children have equal left and right border, which is used to + // overlay the tabs. Add one overlay width to compensate one edge. + if (host->children().size()) + result.set_width(result.width() + kTabOverlayWidth); + + // Add right padding equal to the padding of the settings icon. + result.set_width(result.width() + kSettingsIconBorder); + return result; +} + +void HUDTabStripLayout::Layout(views::View* host) { + // Assume all children have equal left and right border, which is used to + // overlay the tabs. + int left_offset = 0; + for (auto* child : host->children()) { + const gfx::Size preferred = child->GetPreferredSize(); + const gfx::Size child_size({preferred.width(), host->height()}); + child->SetSize(child_size); + child->SetPosition({left_offset, 0}); + left_offset += child_size.width() - kTabOverlayWidth; + } +} + +} // namespace + +BEGIN_METADATA(HUDTabButton) +METADATA_PARENT_CLASS(LabelButton) +END_METADATA() + +HUDTabButton::HUDTabButton(Style style, + HUDTabStrip* tab_strip, + const DisplayModes display_mode, + const base::string16& text) + : views::LabelButton(tab_strip, text), + style_(style), + display_mode_(display_mode) { + SetHorizontalAlignment(gfx::ALIGN_CENTER); + SetEnabledTextColors(kHUDDefaultColor); + SetProperty(kHUDClickHandler, HTCLIENT); + SetBorder(views::CreateEmptyBorder( + kSettingsIconBorder, kTabOverlayWidth + kTabTitleBorder, + kSettingsIconBorder, kTabOverlayWidth + kTabTitleBorder)); +} + +void HUDTabButton::SetStyle(Style style) { + if (style_ == style) + return; + + style_ = style; + SchedulePaint(); +} + +void HUDTabButton::PaintButtonContents(gfx::Canvas* canvas) { + // Horizontal offset from tab {0,0} where two tab arcs cross. + constexpr int kTabArcCrossedX = kTabOverlayWidth / 2; + + // Reduce kTabArcCrossedX by one pixel when calculating partial arc so that + // the pixels along kTabArcCrossedX vertical line are drawn by full arc only. + static const float kTabPartialArcAngle = + 90 - 180 * + asinf((kTabOverlayCornerRadius - kTabArcCrossedX + 1) / + (float)kTabOverlayCornerRadius) / + M_PI; + + const int kCircleSize = kTabOverlayCornerRadius * 2; + const int right_edge = width(); + const int bottom_edge = height(); + + SkPath path; + + // Draw left vertical line and arc + if (style_ == Style::RIGHT) { + /* |true| - move to the start of the arc */ + path.arcTo({0, 0, kCircleSize, kCircleSize}, -90 - kTabPartialArcAngle, + kTabPartialArcAngle, true); + } else { + if (style_ == Style::LEFT) { + // Draw bottom line from the right edge. Adjust for 2 pixels crossing the + // right vertical line. + path.moveTo(right_edge - kTabOverlayWidth / 2 - 2, bottom_edge); + path.lineTo(0, bottom_edge); + } else { + // No bottom line. Just move to the start of the vertical line. + path.moveTo(0, bottom_edge); + } + /* |false| will draw straight line to the start of the arc */ + path.arcTo({0, 0, kCircleSize - 1, kCircleSize}, -180, 90, false); + } + // Draw top line, right arc and right vertical line + if (style_ == Style::LEFT) { + /* |false| will draw straight line to the start of the arc */ + path.arcTo({right_edge - kCircleSize, 0, right_edge, kCircleSize}, -90, + kTabPartialArcAngle, false); + } else { + /* |false| will draw straight line to the start of the arc */ + path.arcTo({right_edge - kCircleSize, 0, right_edge, kCircleSize}, -90, 90, + false); + path.lineTo(right_edge, bottom_edge); + if (style_ == Style::RIGHT) { + // Draw bottom line to the left edge. Adjust for 2 pixels crossing the + // left vertical line. + path.lineTo(kTabOverlayWidth / 2 + 2, bottom_edge); + } + } + + cc::PaintFlags flags; + flags.setAntiAlias(true); + flags.setBlendMode(SkBlendMode::kSrc); + flags.setStyle(cc::PaintFlags::kStroke_Style); + flags.setStrokeWidth(1); + flags.setColor(kHUDDefaultColor); + canvas->DrawPath(path, flags); +} + +BEGIN_METADATA(HUDTabStrip) +METADATA_PARENT_CLASS(View) +END_METADATA() + +HUDTabStrip::HUDTabStrip(HUDDisplayView* hud) : hud_(hud) { + SetLayoutManager(std::make_unique<HUDTabStripLayout>()); +} + +HUDTabStrip::~HUDTabStrip() = default; + +HUDTabButton* HUDTabStrip::AddTabButton(HUDDisplayView* hud, + const DisplayModes display_mode, + const base::string16& label) { + // Make first tab active by default. + HUDTabButton* tab_button = AddChildView(std::make_unique<HUDTabButton>( + tabs_.size() ? HUDTabButton::Style::RIGHT : HUDTabButton::Style::ACTIVE, + this, display_mode, label)); + tabs_.push_back(tab_button); + return tab_button; +} + +void HUDTabStrip::ButtonPressed(views::Button* sender, + const ui::Event& /*event*/) { + for (const auto* tab : tabs_) { + if (tab == sender) { + hud_->TabButtonPressed(tab); + return; + } + } + NOTREACHED(); +} + +void HUDTabStrip::ActivateTab(const views::View* active_tab_button) { + // True if we find given active tab. + bool found = false; + + for (HUDTabButton* tab : tabs_) { + if (found) { + tab->SetStyle(HUDTabButton::Style::RIGHT); + continue; + } + if (tab == active_tab_button) { + found = true; + tab->SetStyle(HUDTabButton::Style::ACTIVE); + continue; + } + tab->SetStyle(HUDTabButton::Style::LEFT); + } + DCHECK(found); +} + +} // namespace hud_display +} // namespace ash
diff --git a/ash/hud_display/tab_strip.h b/ash/hud_display/tab_strip.h new file mode 100644 index 0000000..b3ac3b0 --- /dev/null +++ b/ash/hud_display/tab_strip.h
@@ -0,0 +1,90 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_HUD_DISPLAY_TAB_STRIP_H_ +#define ASH_HUD_DISPLAY_TAB_STRIP_H_ + +#include "ash/hud_display/hud_constants.h" +#include "base/strings/string16.h" +#include "ui/views/controls/button/label_button.h" +#include "ui/views/metadata/metadata_header_macros.h" + +namespace gfx { +class Canvas; +} + +namespace views { +class View; +} + +namespace ash { +namespace hud_display { + +class HUDDisplayView; +class HUDTabStrip; + +class HUDTabButton : public views::LabelButton { + public: + // Defines tab paint style. + enum class Style { + LEFT, // Tab to the left of the active tab. + ACTIVE, // Active tab. + RIGHT // Tab to the right of the active tab. + }; + + METADATA_HEADER(HUDTabButton); + + HUDTabButton(Style style, + HUDTabStrip* tab_strip, + const DisplayModes display_mode, + const base::string16& text); + HUDTabButton(const HUDTabButton&) = delete; + HUDTabButton& operator=(const HUDTabButton&) = delete; + + ~HUDTabButton() override = default; + + void SetStyle(Style style); + + DisplayModes display_mode() const { return display_mode_; } + + protected: + // views::LabelButton: + void PaintButtonContents(gfx::Canvas* canvas) override; + + private: + Style style_ = Style::LEFT; + + // Tab activation sends this display mode to the HUD. + DisplayModes display_mode_ = DisplayModes::DEFAULT; +}; + +class HUDTabStrip : public views::View, public views::ButtonListener { + public: + METADATA_HEADER(HUDTabStrip); + + explicit HUDTabStrip(HUDDisplayView* hud); + + HUDTabStrip(const HUDTabStrip&) = delete; + HUDTabStrip& operator=(const HUDTabStrip&) = delete; + + ~HUDTabStrip() override; + + HUDTabButton* AddTabButton(HUDDisplayView* hud, + const DisplayModes display_mode, + const base::string16& label); + + // views::ButtonListener + void ButtonPressed(views::Button* sender, const ui::Event& event) override; + + // Mark tabs around the active one need repaint to modify borders. + void ActivateTab(const views::View* active_tab_button); + + private: + HUDDisplayView* hud_; + std::vector<HUDTabButton*> tabs_; // Ordered list of child tabs. +}; + +} // namespace hud_display +} // namespace ash +#endif // ASH_HUD_DISPLAY_TAB_STRIP_H_
diff --git a/ash/in_session_auth/auth_dialog_debug_view.cc b/ash/in_session_auth/auth_dialog_debug_view.cc index 18fb49f..28d444a9 100644 --- a/ash/in_session_auth/auth_dialog_debug_view.cc +++ b/ash/in_session_auth/auth_dialog_debug_view.cc
@@ -12,10 +12,12 @@ #include "ash/login/ui/non_accessible_view.h" #include "ash/login/ui/views_utils.h" #include "ash/public/cpp/in_session_auth_dialog_controller.h" +#include "ash/resources/vector_icons/vector_icons.h" #include "ash/strings/grit/ash_strings.h" #include "base/bind_helpers.h" #include "base/strings/utf_string_conversions.h" #include "ui/base/l10n/l10n_util.h" +#include "ui/gfx/paint_vector_icon.h" #include "ui/views/background.h" #include "ui/views/controls/button/md_text_button.h" #include "ui/views/controls/label.h" @@ -31,7 +33,7 @@ }; const char kTitle[] = "Verify it's you"; -const char kFingerprintPrompt[] = "Touch the fingerprint sensor"; +const char kFingerprintPrompt[] = "Authenticate with fingerprint"; // If fingerprint option is available, password input field will be hidden // until the user taps the MoreOptions button. const char kMoreOptionsButtonText[] = "More options"; @@ -47,9 +49,60 @@ const int kTitleFontSize = 14; const int kPromptFontSize = 12; +constexpr int kFingerprintIconSizeDp = 28; +constexpr int kFingerprintIconTopSpacingDp = 20; +constexpr int kSpacingBetweenFingerprintIconAndLabelDp = 15; +constexpr int kFingerprintViewWidthDp = 204; + } // namespace -AuthDialogDebugView::AuthDialogDebugView() { +// Consists of fingerprint icon view and a label. +class AuthDialogDebugView::FingerprintView : public views::View { + public: + FingerprintView() { + SetBorder(views::CreateEmptyBorder(kFingerprintIconTopSpacingDp, 0, 0, 0)); + + auto* layout = SetLayoutManager(std::make_unique<views::BoxLayout>( + views::BoxLayout::Orientation::kVertical, gfx::Insets(), + kSpacingBetweenFingerprintIconAndLabelDp)); + layout->set_main_axis_alignment( + views::BoxLayout::MainAxisAlignment::kCenter); + + icon_ = AddChildView(std::make_unique<AnimatedRoundedImageView>( + gfx::Size(kFingerprintIconSizeDp, kFingerprintIconSizeDp), + 0 /*corner_radius*/)); + icon_->SetImage(gfx::CreateVectorIcon( + kLockScreenFingerprintIcon, kFingerprintIconSizeDp, SK_ColorDKGRAY)); + + label_ = AddChildView(std::make_unique<views::Label>()); + label_->SetSubpixelRenderingEnabled(false); + label_->SetAutoColorReadabilityEnabled(false); + label_->SetEnabledColor(SK_ColorDKGRAY); + label_->SetMultiLine(true); + label_->SetText(base::UTF8ToUTF16(kFingerprintPrompt)); + + SetVisible(true); + } + FingerprintView(const FingerprintView&) = delete; + FingerprintView& operator=(const FingerprintView&) = delete; + ~FingerprintView() override = default; + + // views::View: + gfx::Size CalculatePreferredSize() const override { + gfx::Size size = views::View::CalculatePreferredSize(); + size.set_width(kFingerprintViewWidthDp); + return size; + } + + private: + views::Label* label_ = nullptr; + AnimatedRoundedImageView* icon_ = nullptr; +}; + +AuthDialogDebugView::AuthDialogDebugView(uint32_t auth_methods) + : auth_methods_(auth_methods) { + DCHECK(auth_methods_ & kAuthPassword); + SetLayoutManager(std::make_unique<views::FillLayout>()); container_ = AddChildView(std::make_unique<NonAccessibleView>()); container_->SetBackground(views::CreateSolidBackground(SK_ColorWHITE)); @@ -60,17 +113,21 @@ main_layout_->set_main_axis_alignment( views::BoxLayout::MainAxisAlignment::kStart); main_layout_->set_cross_axis_alignment( - views::BoxLayout::CrossAxisAlignment::kStart); + views::BoxLayout::CrossAxisAlignment::kCenter); AddVerticalSpacing(kTopVerticalSpacing); AddTitleView(); AddVerticalSpacing(kVerticalSpacingBetweenTitleAndPrompt); - AddPromptView(); // TODO(b/156258540): Add proper spacing once all elements are determined. AddPasswordView(); AddPinView(); AddVerticalSpacing(kVerticalSpacingBetweenPasswordAndPINKeyboard); - // TODO(b/156258540): Add fingerprint icon view and proper spacing. + + if (auth_methods_ & kAuthFingerprint) { + fingerprint_view_ = + container_->AddChildView(std::make_unique<FingerprintView>()); + } + AddActionButtonsView(); AddVerticalSpacing(kBottomVerticalSpacing); @@ -125,9 +182,11 @@ password_view_->SetFocusEnabledForChildViews(true); password_view_->SetVisible(true); - // TODO(b/156258540): Set this text according to "has PIN or not". password_view_->SetPlaceholderText( - l10n_util::GetStringUTF16(IDS_ASH_LOGIN_POD_PASSWORD_PIN_PLACEHOLDER)); + (auth_methods_ & kAuthPin) + ? l10n_util::GetStringUTF16( + IDS_ASH_LOGIN_POD_PASSWORD_PIN_PLACEHOLDER) + : l10n_util::GetStringUTF16(IDS_ASH_LOGIN_POD_PASSWORD_PLACEHOLDER)); } void AuthDialogDebugView::AddPinView() { @@ -139,7 +198,7 @@ base::Unretained(password_view_)), base::BindRepeating(&LoginPasswordView::SubmitPassword, base::Unretained(password_view_)))); - pin_view_->SetVisible(true); + pin_view_->SetVisible(auth_methods_ & kAuthPin); } void AuthDialogDebugView::InitPasswordView() {
diff --git a/ash/in_session_auth/auth_dialog_debug_view.h b/ash/in_session_auth/auth_dialog_debug_view.h index a759f8e..79de4bad 100644 --- a/ash/in_session_auth/auth_dialog_debug_view.h +++ b/ash/in_session_auth/auth_dialog_debug_view.h
@@ -25,7 +25,15 @@ // AuthDialogController. class AuthDialogDebugView : public views::View, public views::ButtonListener { public: - AuthDialogDebugView(); + // Flags which describe the set of currently visible auth methods. + enum AuthMethods { + kAuthNone = 0, // No auth methods. + kAuthPassword = 1 << 0, // Display password. + kAuthPin = 1 << 1, // Display PIN keyboard. + kAuthFingerprint = 1 << 2, // Use fingerprint to unlock. + }; + + explicit AuthDialogDebugView(uint32_t auth_methods); AuthDialogDebugView(const AuthDialogDebugView&) = delete; AuthDialogDebugView& operator=(const AuthDialogDebugView&) = delete; ~AuthDialogDebugView() override; @@ -34,6 +42,8 @@ void ButtonPressed(views::Button* sender, const ui::Event& event) override; private: + class FingerprintView; + // Add a view for dialog title. void AddTitleView(); @@ -84,6 +94,11 @@ // PIN pad view. LoginPinView* pin_view_ = nullptr; + FingerprintView* fingerprint_view_ = nullptr; + + // Flags of auth methods that should be visible. + uint32_t auth_methods_ = 0u; + // Show other authentication mechanisms if more than one. views::LabelButton* more_options_button_ = nullptr;
diff --git a/ash/in_session_auth/in_session_auth_dialog.cc b/ash/in_session_auth/in_session_auth_dialog.cc index a566d41..5a3174e 100644 --- a/ash/in_session_auth/in_session_auth_dialog.cc +++ b/ash/in_session_auth/in_session_auth_dialog.cc
@@ -15,7 +15,9 @@ namespace ash { namespace { -constexpr gfx::Size kDefaultSize(340, 224); +// The initial height does nothing except determining the vertical position of +// the dialog, since the dialog is centered with the initial height. +constexpr gfx::Size kDefaultSize(340, 490); class AuthDialogWidgetDelegate : public views::WidgetDelegate { public: @@ -54,11 +56,16 @@ } // namespace -InSessionAuthDialog::InSessionAuthDialog() { +InSessionAuthDialog::InSessionAuthDialog(uint32_t auth_methods) { if (base::CommandLine::ForCurrentProcess()->HasSwitch( chromeos::switches::kShowAuthDialogDevOverlay)) { widget_ = CreateAuthDialogWidget(nullptr); - widget_->SetContentsView(std::make_unique<AuthDialogDebugView>()); + auto* contents_view = widget_->SetContentsView( + std::make_unique<AuthDialogDebugView>(auth_methods)); + gfx::Rect bound = widget_->GetWindowBoundsInScreen(); + // Calculate initial height based on which child views are shown. + bound.set_height(contents_view->GetPreferredSize().height()); + widget_->SetBounds(bound); widget_->Show(); }
diff --git a/ash/in_session_auth/in_session_auth_dialog.h b/ash/in_session_auth/in_session_auth_dialog.h index a9d72026..41969b6 100644 --- a/ash/in_session_auth/in_session_auth_dialog.h +++ b/ash/in_session_auth/in_session_auth_dialog.h
@@ -20,7 +20,7 @@ // completed. class InSessionAuthDialog { public: - InSessionAuthDialog(); + explicit InSessionAuthDialog(uint32_t auth_methods); InSessionAuthDialog(const InSessionAuthDialog&) = delete; InSessionAuthDialog& operator=(const InSessionAuthDialog&) = delete; ~InSessionAuthDialog();
diff --git a/ash/in_session_auth/in_session_auth_dialog_controller_impl.cc b/ash/in_session_auth/in_session_auth_dialog_controller_impl.cc index 9337b75..219d355d 100644 --- a/ash/in_session_auth/in_session_auth_dialog_controller_impl.cc +++ b/ash/in_session_auth/in_session_auth_dialog_controller_impl.cc
@@ -4,7 +4,10 @@ #include "ash/in_session_auth/in_session_auth_dialog_controller_impl.h" +#include "ash/in_session_auth/auth_dialog_debug_view.h" #include "ash/public/cpp/in_session_auth_dialog_client.h" +#include "ash/session/session_controller_impl.h" +#include "ash/shell.h" #include "base/bind.h" #include "base/callback.h" #include "base/strings/string_util.h" @@ -23,7 +26,29 @@ } void InSessionAuthDialogControllerImpl::ShowAuthenticationDialog() { - dialog_ = std::make_unique<InSessionAuthDialog>(); + DCHECK(client_); + + AccountId account_id = + Shell::Get()->session_controller()->GetActiveAccountId(); + // Password should always be available. + uint32_t auth_methods = AuthDialogDebugView::kAuthPassword; + + if (client_->IsFingerprintAuthAvailable(account_id)) + auth_methods |= AuthDialogDebugView::kAuthFingerprint; + + client_->CheckPinAuthAvailability( + account_id, + base::BindOnce(&InSessionAuthDialogControllerImpl::OnPinCanAuthenticate, + weak_factory_.GetWeakPtr(), auth_methods)); +} + +void InSessionAuthDialogControllerImpl::OnPinCanAuthenticate( + uint32_t auth_methods, + bool pin_auth_available) { + if (pin_auth_available) + auth_methods |= AuthDialogDebugView::kAuthPin; + + dialog_ = std::make_unique<InSessionAuthDialog>(auth_methods); } void InSessionAuthDialogControllerImpl::DestroyAuthenticationDialog() {
diff --git a/ash/in_session_auth/in_session_auth_dialog_controller_impl.h b/ash/in_session_auth/in_session_auth_dialog_controller_impl.h index 2359fe52..ab73ff3 100644 --- a/ash/in_session_auth/in_session_auth_dialog_controller_impl.h +++ b/ash/in_session_auth/in_session_auth_dialog_controller_impl.h
@@ -13,6 +13,8 @@ #include "base/memory/weak_ptr.h" #include "base/optional.h" +class AccountId; + namespace ash { class InSessionAuthDialogClient; @@ -42,6 +44,9 @@ OnAuthenticateCallback callback) override; private: + bool IsFingerprintAvailable(const AccountId& account_id); + void OnPinCanAuthenticate(uint32_t auth_methods, bool pin_auth_available); + // Callback to execute when auth on ChromeOS side completes. void OnAuthenticateComplete(OnAuthenticateCallback callback, bool success);
diff --git a/ash/in_session_auth/mock_in_session_auth_dialog_client.h b/ash/in_session_auth/mock_in_session_auth_dialog_client.h index 81ad3f5e..e8990811 100644 --- a/ash/in_session_auth/mock_in_session_auth_dialog_client.h +++ b/ash/in_session_auth/mock_in_session_auth_dialog_client.h
@@ -26,6 +26,17 @@ bool authenticated_by_pin, base::OnceCallback<void(bool)> callback), (override)); + + MOCK_METHOD(bool, + IsFingerprintAuthAvailable, + (const AccountId& account_id), + (override)); + + MOCK_METHOD(void, + CheckPinAuthAvailability, + (const AccountId& account_id, + base::OnceCallback<void(bool)> callback), + (override)); }; } // namespace ash
diff --git a/ash/public/cpp/ash_features.cc b/ash/public/cpp/ash_features.cc index 8794eaeb..430b1d2d 100644 --- a/ash/public/cpp/ash_features.cc +++ b/ash/public/cpp/ash_features.cc
@@ -37,18 +37,9 @@ const base::Feature kDragToSnapInClamshellMode{ "DragToSnapInClamshellMode", base::FEATURE_ENABLED_BY_DEFAULT}; -const base::Feature kMovablePartialScreenshot{ - "MovablePartialScreenshot", base::FEATURE_DISABLED_BY_DEFAULT}; - -const base::Feature kEnableOverviewRoundedCorners{ - "EnableOverviewRoundedCorners", base::FEATURE_ENABLED_BY_DEFAULT}; - const base::Feature kLimitAltTabToActiveDesk{"LimitAltTabToActiveDesk", base::FEATURE_DISABLED_BY_DEFAULT}; -const base::Feature kPerDeskShelf{"PerDeskShelf", - base::FEATURE_DISABLED_BY_DEFAULT}; - const base::Feature kLockScreenNotifications{"LockScreenNotifications", base::FEATURE_DISABLED_BY_DEFAULT}; @@ -71,6 +62,9 @@ const base::Feature kMediaSessionNotification{"MediaSessionNotification", base::FEATURE_ENABLED_BY_DEFAULT}; +const base::Feature kMovablePartialScreenshot{ + "MovablePartialScreenshot", base::FEATURE_DISABLED_BY_DEFAULT}; + const base::Feature kMultiDisplayOverviewAndSplitView{ "MultiDisplayOverviewAndSplitView", base::FEATURE_ENABLED_BY_DEFAULT}; @@ -85,6 +79,9 @@ const base::Feature kNotificationScrollBar{"NotificationScrollBar", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kPerDeskShelf{"PerDeskShelf", + base::FEATURE_DISABLED_BY_DEFAULT}; + const base::Feature kPipRoundedCorners{"PipRoundedCorners", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/ash/public/cpp/ash_features.h b/ash/public/cpp/ash_features.h index 2d2a561..aa94190 100644 --- a/ash/public/cpp/ash_features.h +++ b/ash/public/cpp/ash_features.h
@@ -43,22 +43,10 @@ // TODO(crbug.com/890029): Remove this when the feature is fully launched. ASH_PUBLIC_EXPORT extern const base::Feature kDragToSnapInClamshellMode; -// Enables resizing/moving the selection region for partial screenshot. -ASH_PUBLIC_EXPORT extern const base::Feature kMovablePartialScreenshot; - -// Enables rounded corners in overview mode for testing. -// TODO(crbug.com/903486): Remove this when new rounded corners implementation -// has landed. -ASH_PUBLIC_EXPORT extern const base::Feature kEnableOverviewRoundedCorners; - // Limits the windows listed in Alt-Tab to the ones in the currently active // desk. ASH_PUBLIC_EXPORT extern const base::Feature kLimitAltTabToActiveDesk; -// Limits the items on the shelf to the ones associated with windows the -// currently active desk. -ASH_PUBLIC_EXPORT extern const base::Feature kPerDeskShelf; - // Enables notifications on the lock screen. ASH_PUBLIC_EXPORT extern const base::Feature kLockScreenNotifications; @@ -89,6 +77,9 @@ // TODO(beccahughes): Remove after launch. (https://crbug.com/897836) ASH_PUBLIC_EXPORT extern const base::Feature kMediaSessionNotification; +// Enables resizing/moving the selection region for partial screenshot. +ASH_PUBLIC_EXPORT extern const base::Feature kMovablePartialScreenshot; + // Enables multi-display support for overview and split view. // TODO(crbug.com/952461): Remove this when the feature is fully launched. ASH_PUBLIC_EXPORT extern const base::Feature kMultiDisplayOverviewAndSplitView; @@ -106,6 +97,10 @@ // Enables notification scroll bar in UnifiedSystemTray. ASH_PUBLIC_EXPORT extern const base::Feature kNotificationScrollBar; +// Limits the items on the shelf to the ones associated with windows the +// currently active desk. +ASH_PUBLIC_EXPORT extern const base::Feature kPerDeskShelf; + // Enables rounded corners for the Picture-in-picture window. ASH_PUBLIC_EXPORT extern const base::Feature kPipRoundedCorners;
diff --git a/ash/public/cpp/in_session_auth_dialog_client.h b/ash/public/cpp/in_session_auth_dialog_client.h index e6312d8..f5582198 100644 --- a/ash/public/cpp/in_session_auth_dialog_client.h +++ b/ash/public/cpp/in_session_auth_dialog_client.h
@@ -9,6 +9,7 @@ #include "ash/public/cpp/ash_public_export.h" #include "base/callback_forward.h" +#include "components/account_id/account_id.h" namespace ash { @@ -25,6 +26,14 @@ bool authenticated_by_pin, base::OnceCallback<void(bool)> callback) = 0; + // Check whether fingerprint auth is available for |account_id|. + virtual bool IsFingerprintAuthAvailable(const AccountId& account_id) = 0; + + // Check whether PIN auth is available for |account_id|. + virtual void CheckPinAuthAvailability( + const AccountId& account_id, + base::OnceCallback<void(bool)> callback) = 0; + protected: virtual ~InSessionAuthDialogClient() = default; };
diff --git a/base/trace_event/traced_value.cc b/base/trace_event/traced_value.cc index 68e7dc8..f8ee48a 100644 --- a/base/trace_event/traced_value.cc +++ b/base/trace_event/traced_value.cc
@@ -597,6 +597,11 @@ writer_->AppendString(value); } +void TracedValue::AppendPointer(void* value) { + DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray); + writer_->AppendString(PointerToString(value)); +} + void TracedValue::BeginArray() { DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray); DEBUG_PUSH_CONTAINER(kStackTypeArray); @@ -642,71 +647,202 @@ writer_->EstimateTraceMemoryOverhead(overhead); } -TracedValue::DictionaryItem::DictionaryItem(const char* name, int value) { - name_ = name; +TracedValue::Array::Array(const std::initializer_list<ArrayItem> items) { + items_ = std::move(items); +} + +TracedValue::Array::Array(TracedValue::Array&& other) { + items_ = std::move(other.items_); +} + +void TracedValue::Array::WriteToValue(TracedValue* value) const { + for (const auto& item : items_) { + item.WriteToValue(value); + } +} + +TracedValue::Dictionary::Dictionary( + const std::initializer_list<DictionaryItem> items) { + items_ = items; +} + +TracedValue::Dictionary::Dictionary(TracedValue::Dictionary&& other) { + items_ = std::move(other.items_); +} + +void TracedValue::Dictionary::WriteToValue(TracedValue* value) const { + for (const auto& item : items_) { + item.WriteToValue(value); + } +} + +TracedValue::ValueHolder::ValueHolder(int value) { kept_value_.int_value = value; kept_value_type_ = KeptValueType::kIntType; } -TracedValue::DictionaryItem::DictionaryItem(const char* name, double value) { - name_ = name; +TracedValue::ValueHolder::ValueHolder(double value) { kept_value_.double_value = value; kept_value_type_ = KeptValueType::kDoubleType; } -TracedValue::DictionaryItem::DictionaryItem(const char* name, bool value) { - name_ = name; +TracedValue::ValueHolder::ValueHolder(bool value) { kept_value_.bool_value = value; kept_value_type_ = KeptValueType::kBoolType; } -TracedValue::DictionaryItem::DictionaryItem(const char* name, - base::StringPiece value) { - name_ = name; +TracedValue::ValueHolder::ValueHolder(base::StringPiece value) { kept_value_.string_piece_value = value; kept_value_type_ = KeptValueType::kStringPieceType; } -TracedValue::DictionaryItem::DictionaryItem(const char* name, void* value) { - name_ = name; +TracedValue::ValueHolder::ValueHolder(const std::string& value) { + kept_value_.string_piece_value = value; + kept_value_type_ = KeptValueType::kStringPieceType; +} + +TracedValue::ValueHolder::ValueHolder(void* value) { kept_value_.void_ptr_value = value; kept_value_type_ = KeptValueType::kVoidPtrType; } -TracedValue::DictionaryItem::DictionaryItem(const char* name, - const char* value) { - name_ = name; +TracedValue::ValueHolder::ValueHolder(const char* value) { kept_value_.string_piece_value = value; kept_value_type_ = KeptValueType::kStringPieceType; } -void TracedValue::DictionaryItem::WriteToValue(TracedValue* value) const { - switch (kept_value_type_) { +TracedValue::ValueHolder::ValueHolder(TracedValue::Dictionary& value) { + new (&kept_value_.dictionary_value) TracedValue::Dictionary(std::move(value)); + kept_value_type_ = KeptValueType::kDictionaryType; +} + +TracedValue::ValueHolder::ValueHolder(TracedValue::Array& value) { + new (&kept_value_.array_value) TracedValue::Array(std::move(value)); + kept_value_type_ = KeptValueType::kArrayType; +} + +TracedValue::ValueHolder::ValueHolder(TracedValue::ValueHolder&& other) { + // Remember to call a destructor if ever necessary. + switch (other.kept_value_type_) { case KeptValueType::kIntType: { - value->SetInteger(name_, kept_value_.int_value); + kept_value_.int_value = other.kept_value_.int_value; break; } case KeptValueType::kDoubleType: { - value->SetDouble(name_, kept_value_.double_value); + kept_value_.double_value = other.kept_value_.double_value; break; } case KeptValueType::kBoolType: { - value->SetBoolean(name_, kept_value_.bool_value); + kept_value_.bool_value = other.kept_value_.bool_value; break; } case KeptValueType::kStringPieceType: { - value->SetString(name_, kept_value_.string_piece_value); + kept_value_.string_piece_value = other.kept_value_.string_piece_value; break; } case KeptValueType::kVoidPtrType: { - value->SetPointer(name_, kept_value_.void_ptr_value); + kept_value_.void_ptr_value = other.kept_value_.void_ptr_value; + break; + } + case KeptValueType::kArrayType: { + new (&kept_value_.array_value) + TracedValue::Array(std::move(other.kept_value_.array_value)); + break; + } + case KeptValueType::kDictionaryType: { + new (&kept_value_.dictionary_value) TracedValue::Dictionary( + std::move(other.kept_value_.dictionary_value)); + break; + } + } + kept_value_type_ = other.kept_value_type_; +} + +void TracedValue::ValueHolder::WriteToValue(TracedValue* value) const { + switch (kept_value_type_) { + case KeptValueType::kIntType: { + value->AppendInteger(kept_value_.int_value); + break; + } + case KeptValueType::kDoubleType: { + value->AppendDouble(kept_value_.double_value); + break; + } + case KeptValueType::kBoolType: { + value->AppendBoolean(kept_value_.bool_value); + break; + } + case KeptValueType::kStringPieceType: { + value->AppendString(kept_value_.string_piece_value); + break; + } + case KeptValueType::kVoidPtrType: { + value->AppendPointer(kept_value_.void_ptr_value); + break; + } + case KeptValueType::kArrayType: { + value->BeginArray(); + kept_value_.array_value.WriteToValue(value); + value->EndArray(); + break; + } + case KeptValueType::kDictionaryType: { + value->BeginDictionary(); + kept_value_.dictionary_value.WriteToValue(value); + value->EndDictionary(); break; } } } +void TracedValue::ValueHolder::WriteToValue(const char* name, + TracedValue* value) const { + switch (kept_value_type_) { + case KeptValueType::kIntType: { + value->SetInteger(name, kept_value_.int_value); + break; + } + case KeptValueType::kDoubleType: { + value->SetDouble(name, kept_value_.double_value); + break; + } + case KeptValueType::kBoolType: { + value->SetBoolean(name, kept_value_.bool_value); + break; + } + case KeptValueType::kStringPieceType: { + value->SetString(name, kept_value_.string_piece_value); + break; + } + case KeptValueType::kVoidPtrType: { + value->SetPointer(name, kept_value_.void_ptr_value); + break; + } + case KeptValueType::kArrayType: { + value->BeginArray(name); + kept_value_.array_value.WriteToValue(value); + value->EndArray(); + break; + } + case KeptValueType::kDictionaryType: { + value->BeginDictionary(name); + kept_value_.dictionary_value.WriteToValue(value); + value->EndDictionary(); + break; + } + } +} + +void TracedValue::ArrayItem::WriteToValue(TracedValue* value) const { + ValueHolder::WriteToValue(value); +} + +void TracedValue::DictionaryItem::WriteToValue(TracedValue* value) const { + ValueHolder::WriteToValue(name_, value); +} + std::unique_ptr<TracedValue> TracedValue::Build( - std::initializer_list<DictionaryItem> items) { + const std::initializer_list<DictionaryItem> items) { std::unique_ptr<TracedValue> value(new TracedValue()); for (const auto& item : items) { item.WriteToValue(value.get());
diff --git a/base/trace_event/traced_value.h b/base/trace_event/traced_value.h index bdb6784..5c8d04f 100644 --- a/base/trace_event/traced_value.h +++ b/base/trace_event/traced_value.h
@@ -57,6 +57,7 @@ void AppendDouble(double); void AppendBoolean(bool); void AppendString(base::StringPiece); + void AppendPointer(void*); void BeginArray(); void BeginDictionary(); @@ -66,57 +67,116 @@ void EstimateTraceMemoryOverhead(TraceEventMemoryOverhead* overhead) override; - // TracedValue::Build is a friend of TracedValue::DictionaryItem. + class BASE_EXPORT Array; + class BASE_EXPORT Dictionary; + class BASE_EXPORT ValueHolder; + class BASE_EXPORT ArrayItem; class BASE_EXPORT DictionaryItem; - // Helper to enable easier initialization of TracedValue. This is intended for - // quick local debugging as there is overhead of creating - // std::initializer_list of name-value objects. This method does not support - // creation of dictionaries or arrays. + // Helper to enable easier initialization of |TracedValue|. This is intended + // for quick local debugging as there is overhead of creating + // |std::initializer_list| of name-value objects (in the case of containers + // the value is also a |std::initializer_list|). Generally the helper types + // |TracedValue::Dictionary|, |TracedValue::Array|, + // |TracedValue::DictionaryItem|, |TracedValue::ArrayItem| must be valid as + // well as their internals (e.g., |base::StringPiece| data should be valid + // when |TracedValue::Build| is called; |TracedValue::Array| or + // |TracedValue::Dictionary| holds a |std::initializer_list| whose underlying + // array needs to be valid when calling |TracedValue::Build|). // // Example: // auto value = TracedValue::Build({ // {"int_var_name", 42}, // {"double_var_name", 3.14}, - // {"string_var_name", "hello world"} + // {"string_var_name", "hello world"}, + // {"empty_array", TracedValue::Array({})}, + // {"dictionary", TracedValue::Dictionary({ + // {"my_ptr", static_cast<void*>(my_ptr)}, + // {"nested_array", TracedValue::Array({1, false, 0.5})}, + // })}, // }); - // - // |name| is assumed to be a long lived "quoted" string. static std::unique_ptr<TracedValue> Build( - std::initializer_list<DictionaryItem> items); + const std::initializer_list<DictionaryItem> items); - // DictionaryItem instance represents a single name-value pair. - class DictionaryItem { + // An |Array| instance represents an array of |ArrayItem| objects. This is a + // helper to allow initializer list like construction of arrays using + // |TracedValue::Build|. + // + // An instance holds an |std::initializer_list<TracedValue::ArrayItem>| and is + // cheap to copy (copying the initializer_list does not copy the underlying + // objects). The underlying array must exist at the time when + // |TracedValue::Build| is called. + class Array { public: - // These constructors assume that |name| is a long lived "quoted" string. - DictionaryItem(const char* name, int value); - DictionaryItem(const char* name, double value); - DictionaryItem(const char* name, bool value); - DictionaryItem(const char* name, void* value); + // This constructor expects that the initializer_list is valid when + // |TracedValue::Build| is called. + Array(const std::initializer_list<ArrayItem> items); + Array(Array&&); + void WriteToValue(TracedValue* value) const; + + private: + std::initializer_list<ArrayItem> items_; + }; + + // A helper to hold a dictionary. Similar to |TracedValue::Array|. + class Dictionary { + public: + // This constructor expects that the initializer_list is valid when + // |TracedValue::Build| is called. + Dictionary(const std::initializer_list<DictionaryItem> items); + Dictionary(Dictionary&&); + void WriteToValue(TracedValue* value) const; + + private: + std::initializer_list<DictionaryItem> items_; + }; + + // A |ValueHolder| holds a single value or a container (int, double... or an + // |Array| / |Dictionary|). Not to be used outside of the context of + // |TracedValue::Build| (has one parameter implicit constructors). + // + // Base class for |TracedValue::ArrayItem| and |TracedValue::DictionaryItem|. + class ValueHolder { + public: + // Implicit constructors allow constructing |DictionaryItem| without having + // to write |{"name", TracedValue::ValueHolder(1)}|. + ValueHolder(int value); // NOLINT(google-explicit-constructor) + ValueHolder(double value); // NOLINT(google-explicit-constructor) + ValueHolder(bool value); // NOLINT(google-explicit-constructor) + ValueHolder(void* value); // NOLINT(google-explicit-constructor) // StringPiece's backing storage / const char* pointer needs to remain valid // until TracedValue::Build is called. - DictionaryItem(const char* name, base::StringPiece value); + // NOLINTNEXTLINE(google-explicit-constructor) + ValueHolder(base::StringPiece value); + // NOLINTNEXTLINE(google-explicit-constructor) + ValueHolder(const std::string& value); // Define an explicit overload for const char* to resolve the ambiguity // between the base::StringPiece, void*, and bool constructors for string // literals. - DictionaryItem(const char* name, const char* value); + ValueHolder(const char* value); // NOLINT(google-explicit-constructor) + ValueHolder(Array& value); // NOLINT(google-explicit-constructor) + ValueHolder(Dictionary& value); // NOLINT(google-explicit-constructor) + ValueHolder(ValueHolder&&); + + protected: + void WriteToValue(TracedValue* value) const; + void WriteToValue(const char* name, TracedValue* value) const; private: - friend std::unique_ptr<TracedValue> TracedValue::Build( - std::initializer_list<DictionaryItem> items); - - void WriteToValue(TracedValue* value) const; - union KeptValue { + // Copy is handled by the holder (based on + // |TracedValue::ValueHolder::kept_value_type_|). int int_value; double double_value; bool bool_value; base::StringPiece string_piece_value; void* void_ptr_value; + Array array_value; + Dictionary dictionary_value; // Default constructor is implicitly deleted because union field has a // non-trivial default constructor. - KeptValue() {} + KeptValue() {} // NOLINT(modernize-use-equals-default) }; // Reimplementing a subset of C++17 std::variant. @@ -126,13 +186,43 @@ kBoolType, kStringPieceType, kVoidPtrType, + kArrayType, + kDictionaryType, }; KeptValue kept_value_; - const char* name_; KeptValueType kept_value_type_; }; + // |ArrayItem| is a |ValueHolder| which can be used to construct an |Array|. + class ArrayItem : public ValueHolder { + public: + // Implicit constructors allow calling |TracedValue::Array({1, true, 3.14})| + // instead of |TracedValue::Array({TracedValue::ArrayItem(1), + // TracedValue::ArrayItem(true), TracedValue::ArrayItem(3.14)})|. + template <typename T> + // NOLINTNEXTLINE(google-explicit-constructor) + ArrayItem(T value) : ValueHolder(value) {} + + void WriteToValue(TracedValue* value) const; + }; + + // |DictionaryItem| instance represents a single name-value pair. + // + // |name| is assumed to be a long lived "quoted" string. + class DictionaryItem : public ValueHolder { + public: + // These constructors assume that |name| is a long lived "quoted" string. + template <typename T> + DictionaryItem(const char* name, T value) + : ValueHolder(value), name_(name) {} + + void WriteToValue(TracedValue* value) const; + + private: + const char* name_; + }; + // A custom serialization class can be supplied by implementing the // Writer interface and supplying a factory class to SetWriterFactoryCallback. // Primarily used by Perfetto to write TracedValues directly into its proto
diff --git a/base/trace_event/traced_value_unittest.cc b/base/trace_event/traced_value_unittest.cc index 86e6ec4..24238a78 100644 --- a/base/trace_event/traced_value_unittest.cc +++ b/base/trace_event/traced_value_unittest.cc
@@ -15,6 +15,31 @@ namespace base { namespace trace_event { +TEST(TraceEventArgumentTest, InitializerListCreatedContainers) { + std::string json; + TracedValue::Build( + { + {"empty_array", TracedValue::Array({})}, + {"empty_dictionary", TracedValue::Dictionary({})}, + {"nested_array", TracedValue::Array({ + TracedValue::Array({}), + TracedValue::Dictionary({}), + true, + })}, + {"nested_dictionary", TracedValue::Dictionary({ + {"d", TracedValue::Dictionary({})}, + {"a", TracedValue::Array({})}, + {"b", true}, + })}, + }) + ->AppendAsTraceFormat(&json); + EXPECT_EQ( + "{\"empty_array\":[],\"empty_dictionary\":{}," + "\"nested_array\":[[],{},true]," + "\"nested_dictionary\":{\"d\":{},\"a\":[],\"b\":true}}", + json); +} + TEST(TraceEventArgumentTest, InitializerListCreatedFlatDictionary) { std::string json; TracedValue::Build({{"bool_var", true}, @@ -28,23 +53,34 @@ json); } +std::string SayHello() { + // Create a string by concatenating two strings, so that there is no literal + // corresponding to the result. + return std::string("hello ") + std::string("world"); +} + TEST(TraceEventArgumentTest, StringAndPointerConstructors) { std::string json; const char* const_char_ptr_var = "const char* value"; - TracedValue::Build({ - {"literal_var", "literal"}, - {"std_string_var", std::string("std::string value")}, - {"base_string_piece_var", - base::StringPiece("base::StringPiece value")}, - {"const_char_ptr_var", const_char_ptr_var}, - {"void_nullptr", static_cast<void*>(nullptr)}, - {"int_nullptr", static_cast<int*>(nullptr)}, - {"void_1234ptr", reinterpret_cast<void*>(0x1234)}, - }) + TracedValue::Build( + { + {"literal_var", "literal"}, + {"std_string_var", std::string("std::string value")}, + {"string_from_function", SayHello()}, + {"string_from_lambda", []() { return std::string("hello"); }()}, + {"base_string_piece_var", + base::StringPiece("base::StringPiece value")}, + {"const_char_ptr_var", const_char_ptr_var}, + {"void_nullptr", static_cast<void*>(nullptr)}, + {"int_nullptr", static_cast<int*>(nullptr)}, + {"void_1234ptr", reinterpret_cast<void*>(0x1234)}, + }) ->AppendAsTraceFormat(&json); EXPECT_EQ( "{\"literal_var\":\"literal\"," "\"std_string_var\":\"std::string value\"," + "\"string_from_function\":\"hello world\"," + "\"string_from_lambda\":\"hello\"," "\"base_string_piece_var\":\"base::StringPiece value\"," "\"const_char_ptr_var\":\"const char* value\"," "\"void_nullptr\":\"0x0\","
diff --git a/build/android/gyp/util/diff_utils.py b/build/android/gyp/util/diff_utils.py index 674de31b..10814e58 100755 --- a/build/android/gyp/util/diff_utils.py +++ b/build/android/gyp/util/diff_utils.py
@@ -88,9 +88,9 @@ diff_text = _DiffFileContents(options.expected_file, actual_data) if not diff_text: - return - - fail_msg = """ + fail_msg = '' + else: + fail_msg = """ Expectations need updating: https://chromium.googlesource.com/chromium/src/+/HEAD/chrome/android/expectations/README.md @@ -105,10 +105,10 @@ ############ END ############ """.format(diff_text) - sys.stderr.write(fail_msg) + sys.stderr.write(fail_msg) + if options.failure_file: - build_utils.MakeDirectory(os.path.dirname(options.failure_file)) with open(options.failure_file, 'w') as f: f.write(fail_msg) - if options.fail_on_expectations: + if fail_msg and options.fail_on_expectations: sys.exit(1)
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni index bb99e54..e3530c4 100644 --- a/build/config/android/internal_rules.gni +++ b/build/config/android/internal_rules.gni
@@ -1266,7 +1266,10 @@ _failure_file = "$_expectations_failure_dir/" + string_replace(invoker.expected_proguard_config, "/", "_") - outputs = [ _actual_file ] + outputs = [ + _actual_file, + _failure_file, + ] args = _args + [ "--depfile", rebase_path(depfile, root_build_dir), @@ -2649,7 +2652,10 @@ invoker.build_config, invoker.expected_android_manifest, ] - outputs = [ _actual_file ] + outputs = [ + _actual_file, + _failure_file, + ] deps = [ invoker.android_manifest_dep, invoker.build_config_dep, @@ -2928,7 +2934,10 @@ invoker.expected_libs_and_assets, ] deps = [ invoker.build_config_dep ] - outputs = [ _actual_file ] + outputs = [ + _actual_file, + _failure_file, + ] script = _script args = _args + [ "--expected-file", @@ -4156,7 +4165,10 @@ inputs += [ invoker.secondary_abi_native_libraries_config ] deps += [ invoker.secondary_abi_native_libraries_config_target ] } - outputs = [ _actual_file ] + outputs = [ + _actual_file, + _failure_file, + ] script = _script args = _args + [ "--expected-file",
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index b0fc14ff..4903621 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -0.20200812.4.1 +0.20200813.1.1
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index b0fc14ff..6d458d1 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -0.20200812.4.1 +0.20200813.0.1
diff --git a/chrome/android/DEPS b/chrome/android/DEPS index 7a62ccb..dbafd44b 100644 --- a/chrome/android/DEPS +++ b/chrome/android/DEPS
@@ -14,7 +14,6 @@ "+chrome/browser/ui/messages/android", "+chrome/browser/util/android/java", "+chrome/browser/webauthn/android", - "+chrome/browser/xsurface/android", "+components/browser_ui/android/bottomsheet", "+components/browser_ui/banners/android", "+components/browser_ui/display_cutout/android", @@ -56,3 +55,9 @@ "+services/device/public", "+services/media_session/public", ] + +specific_include_rules = { + "chrome/android/java/src/org/chromium/chrome/browser/AppHooks.java": [ + "+chrome/browser/xsurface/android", + ], +}
diff --git a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantBackButtonIntegrationTest.java b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantBackButtonIntegrationTest.java index 44580c9..2c0363c 100644 --- a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantBackButtonIntegrationTest.java +++ b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantBackButtonIntegrationTest.java
@@ -167,18 +167,14 @@ Espresso.pressBack(); waitUntilViewMatchesCondition(withText(R.string.undo), isCompletelyDisplayed()); onView(withId(R.id.autofill_assistant)).check(doesNotExist()); - - assertThat( - ChromeTabUtils.getUrlOnUiThread(mTestRule.getActivity().getActivityTab()).getSpec(), + assertThat(mTestRule.getActivity().getActivityTab().getUrl().getSpec(), is(getURL(TEST_PAGE_B))); // Third press on back button navigates back. Espresso.pressBack(); - waitUntil( - () - -> ChromeTabUtils.getUrlOnUiThread(mTestRule.getActivity().getActivityTab()) - .getSpec() - .equals(getURL(TEST_PAGE_A))); + waitUntil(() + -> mTestRule.getActivity().getActivityTab().getUrl().getSpec().equals( + getURL(TEST_PAGE_A))); } @Test @@ -246,8 +242,7 @@ Espresso.pressBack(); waitUntilViewMatchesCondition(withText("Back button pressed"), isCompletelyDisplayed()); waitUntilViewMatchesCondition(withText("Undo"), isDisplayed()); - assertThat( - ChromeTabUtils.getUrlOnUiThread(mTestRule.getActivity().getActivityTab()).getSpec(), + assertThat(mTestRule.getActivity().getActivityTab().getUrl().getSpec(), is(getURL(TEST_PAGE_B))); // Undo should get back to the prompt state. @@ -258,18 +253,15 @@ Espresso.pressBack(); waitUntilViewMatchesCondition(withText("Back button pressed"), isCompletelyDisplayed()); waitUntilViewMatchesCondition(withText("Undo"), isDisplayed()); - assertThat( - ChromeTabUtils.getUrlOnUiThread(mTestRule.getActivity().getActivityTab()).getSpec(), + assertThat(mTestRule.getActivity().getActivityTab().getUrl().getSpec(), is(getURL(TEST_PAGE_B))); // Third press on back button destroys Autofill UI and navigates back. Espresso.pressBack(); waitUntilViewAssertionTrue(withId(R.id.autofill_assistant), doesNotExist(), 3000L); - waitUntil( - () - -> ChromeTabUtils.getUrlOnUiThread(mTestRule.getActivity().getActivityTab()) - .getSpec() - .equals(getURL(TEST_PAGE_A))); + waitUntil(() + -> mTestRule.getActivity().getActivityTab().getUrl().getSpec().equals( + getURL(TEST_PAGE_A))); } @Test @@ -303,11 +295,9 @@ withId(R.id.autofill_assistant), doesNotExist(), DEFAULT_MAX_TIME_TO_POLL); onView(withText("Shutdown")).check(doesNotExist()); onView(withText(R.string.undo)).check(doesNotExist()); - waitUntil( - () - -> ChromeTabUtils.getUrlOnUiThread(mTestRule.getActivity().getActivityTab()) - .getSpec() - .equals(getURL(TEST_PAGE_A))); + waitUntil(() + -> mTestRule.getActivity().getActivityTab().getUrl().getSpec().equals( + getURL(TEST_PAGE_A))); } @Test @@ -365,8 +355,7 @@ Espresso.pressBack(); waitUntilViewMatchesCondition(withText("Back button pressed"), isCompletelyDisplayed()); waitUntilViewMatchesCondition(withText("Undo"), isDisplayed()); - assertThat( - ChromeTabUtils.getUrlOnUiThread(mTestRule.getActivity().getActivityTab()).getSpec(), + assertThat(mTestRule.getActivity().getActivityTab().getUrl().getSpec(), is(getURL(TEST_PAGE_B))); // Navigation destroys the Autofill Assistant UI. @@ -413,11 +402,9 @@ // Second press on back button navigates back, without removing the Autofill Assistannt UI. Espresso.pressBack(); - waitUntil( - () - -> ChromeTabUtils.getUrlOnUiThread(mTestRule.getActivity().getActivityTab()) - .getSpec() - .equals(getURL(TEST_PAGE_A))); + waitUntil(() + -> mTestRule.getActivity().getActivityTab().getUrl().getSpec().equals( + getURL(TEST_PAGE_A))); onView(withId(R.id.autofill_assistant)).check(matches(isDisplayed())); onView(withId(R.id.status_message)).check(matches(withText("Prompt"))); }
diff --git a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantNavigationIntegrationTest.java b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantNavigationIntegrationTest.java index f8c6689..c58469e 100644 --- a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantNavigationIntegrationTest.java +++ b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantNavigationIntegrationTest.java
@@ -123,11 +123,9 @@ onView(withId(org.chromium.chrome.R.id.url_bar)) .perform(click(), typeText(getURL(TEST_PAGE_B)), pressImeActionButton()); waitUntilViewMatchesCondition(withText(containsString("Sorry")), isCompletelyDisplayed()); - waitUntil( - () - -> ChromeTabUtils.getUrlOnUiThread(mTestRule.getActivity().getActivityTab()) - .getSpec() - .equals(getURL(TEST_PAGE_B))); + waitUntil(() + -> mTestRule.getActivity().getActivityTab().getUrl().getSpec().equals( + getURL(TEST_PAGE_B))); } @Test @@ -159,11 +157,9 @@ startAutofillAssistantOnTab(TEST_PAGE_A); waitUntilViewMatchesCondition(withText("Prompt"), isCompletelyDisplayed()); - waitUntil( - () - -> ChromeTabUtils.getUrlOnUiThread(mTestRule.getActivity().getActivityTab()) - .getSpec() - .equals(getURL(TEST_PAGE_B))); + waitUntil(() + -> mTestRule.getActivity().getActivityTab().getUrl().getSpec().equals( + getURL(TEST_PAGE_B))); } @Test @@ -196,11 +192,9 @@ startAutofillAssistantOnTab(TEST_PAGE_A); waitUntilViewMatchesCondition(withText("Prompt"), isCompletelyDisplayed()); - waitUntil( - () - -> ChromeTabUtils.getUrlOnUiThread(mTestRule.getActivity().getActivityTab()) - .getSpec() - .equals(getURL(TEST_PAGE_B))); + waitUntil(() + -> mTestRule.getActivity().getActivityTab().getUrl().getSpec().equals( + getURL(TEST_PAGE_B))); } @Test @@ -263,28 +257,21 @@ onView(withText("Navigate")).perform(click()); waitUntilViewMatchesCondition(withText("Page A"), isCompletelyDisplayed()); - - waitUntil( - () - -> ChromeTabUtils.getUrlOnUiThread(mTestRule.getActivity().getActivityTab()) - .getSpec() - .equals(getURL(TEST_PAGE_A))); + waitUntil(() + -> mTestRule.getActivity().getActivityTab().getUrl().getSpec().equals( + getURL(TEST_PAGE_A))); onView(withText("Go back")).perform(click()); waitUntilViewMatchesCondition(withText("Page B"), isCompletelyDisplayed()); - waitUntil( - () - -> ChromeTabUtils.getUrlOnUiThread(mTestRule.getActivity().getActivityTab()) - .getSpec() - .equals(getURL(TEST_PAGE_B))); + waitUntil(() + -> mTestRule.getActivity().getActivityTab().getUrl().getSpec().equals( + getURL(TEST_PAGE_B))); onView(withText("Go forward")).perform(click()); waitUntilViewMatchesCondition(withText("Page A"), isCompletelyDisplayed()); - waitUntil( - () - -> ChromeTabUtils.getUrlOnUiThread(mTestRule.getActivity().getActivityTab()) - .getSpec() - .equals(getURL(TEST_PAGE_A))); + waitUntil(() + -> mTestRule.getActivity().getActivityTab().getUrl().getSpec().equals( + getURL(TEST_PAGE_A))); } @Test
diff --git a/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingUiCaptureTest.java b/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingUiCaptureTest.java index 73f9fb99..5c0f6d2 100644 --- a/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingUiCaptureTest.java +++ b/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingUiCaptureTest.java
@@ -66,9 +66,9 @@ @MediumTest @DisableFeatures(ChromeFeatureList.AUTOFILL_KEYBOARD_ACCESSORY) @Feature({"KeyboardAccessory", "LTR", "UiCatalogue"}) - @DisableIf. - Build(sdk_is_greater_than = VERSION_CODES.LOLLIPOP_MR1, sdk_is_less_than = VERSION_CODES.N, - message = "Flaky on Marshmallow https://crbug.com/1102302") + @DisableIf.Build(sdk_is_greater_than = VERSION_CODES.KITKAT, sdk_is_less_than = VERSION_CODES.N, + message = + "Flaky on Marshmallow https://crbug.com/1102302, Failing on Lollipop https://crbug.com/1095672") public void testCaptureKeyboardAccessoryWithPasswords() throws InterruptedException, TimeoutException { mHelper.loadTestPage(false); @@ -96,9 +96,9 @@ @MediumTest @DisableFeatures(ChromeFeatureList.AUTOFILL_KEYBOARD_ACCESSORY) @Feature({"KeyboardAccessory", "RTL", "UiCatalogue"}) - @DisableIf. - Build(sdk_is_greater_than = VERSION_CODES.LOLLIPOP_MR1, sdk_is_less_than = VERSION_CODES.N, - message = "Flaky on Marshmallow https://crbug.com/1102302") + @DisableIf.Build(sdk_is_greater_than = VERSION_CODES.KITKAT, sdk_is_less_than = VERSION_CODES.N, + message = + "Flaky on Marshmallow https://crbug.com/1102302, Failing on Lollipop https://crbug.com/1095672") public void testCaptureKeyboardAccessoryWithPasswordsRTL() throws InterruptedException, TimeoutException { mHelper.loadTestPage(true); @@ -125,9 +125,9 @@ @MediumTest @EnableFeatures(ChromeFeatureList.AUTOFILL_KEYBOARD_ACCESSORY) @Feature({"KeyboardAccessoryModern", "LTR", "UiCatalogue"}) - @DisableIf. - Build(sdk_is_greater_than = VERSION_CODES.LOLLIPOP_MR1, sdk_is_less_than = VERSION_CODES.N, - message = "Flaky on Marshmallow https://crbug.com/1102302") + @DisableIf.Build(sdk_is_greater_than = VERSION_CODES.KITKAT, sdk_is_less_than = VERSION_CODES.N, + message = + "Flaky on Marshmallow https://crbug.com/1102302, Failing on Lollipop https://crbug.com/1095672") public void testCaptureKeyboardAccessoryV2WithPasswords() throws InterruptedException, TimeoutException { mHelper.loadTestPage(false); @@ -158,9 +158,9 @@ @MediumTest @EnableFeatures(ChromeFeatureList.AUTOFILL_KEYBOARD_ACCESSORY) @Feature({"KeyboardAccessoryModern", "RTL", "UiCatalogue"}) - @DisableIf. - Build(sdk_is_greater_than = VERSION_CODES.LOLLIPOP_MR1, sdk_is_less_than = VERSION_CODES.N, - message = "Flaky on Marshmallow https://crbug.com/1102302") + @DisableIf.Build(sdk_is_greater_than = VERSION_CODES.KITKAT, sdk_is_less_than = VERSION_CODES.N, + message = + "Flaky on Marshmallow https://crbug.com/1102302, Failing on Lollipop https://crbug.com/1095672") public void testCaptureKeyboardAccessoryV2WithPasswordsRTL() throws InterruptedException, TimeoutException { mHelper.loadTestPage(true);
diff --git a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceLayoutTest.java b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceLayoutTest.java index 278391e..65cb0ee 100644 --- a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceLayoutTest.java +++ b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceLayoutTest.java
@@ -1572,7 +1572,7 @@ .check(waitForView(allOf(withText(expectedTerm), isDisplayed()))); // Click the chip and check the tab navigates back to the search result page. - assertEquals(mUrl, ChromeTabUtils.getUrlStringOnUiThread(currentTab)); + assertEquals(mUrl, currentTab.getUrlString()); OverviewModeBehaviorWatcher hideWatcher = TabUiTestHelper.createOverviewHideWatcher(cta); onView(withId(R.id.search_button)) .check(waitForView(allOf(withText(expectedTerm), isDisplayed())));
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabUiTestHelper.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabUiTestHelper.java index f08fa39b..8fb296c9 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabUiTestHelper.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabUiTestHelper.java
@@ -460,7 +460,7 @@ private static void verifyAllTabsHaveUrl(TabModel tabModel, String url) { for (int i = 0; i < tabModel.getCount(); i++) { - assertEquals(url, ChromeTabUtils.getUrlStringOnUiThread(tabModel.getTabAt(i))); + assertEquals(url, tabModel.getTabAt(i).getUrlString()); } }
diff --git a/chrome/android/feed/DEPS b/chrome/android/feed/DEPS index 18ced55..c29df56 100644 --- a/chrome/android/feed/DEPS +++ b/chrome/android/feed/DEPS
@@ -3,8 +3,11 @@ "+chrome/browser/profiles/android/java", "+chrome/browser/tab/java", "+chrome/browser/ui/messages/android/java", + "+chrome/browser/xsurface/android", "+components/background_task_scheduler", "+components/feature_engagement", "+components/feed", + + "-content", "+content/public/android/java/src/org/chromium/content_public", ]
diff --git a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/FeedNewTabPageTest.java b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/FeedNewTabPageTest.java index 79722b6..0dce68d5 100644 --- a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/FeedNewTabPageTest.java +++ b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/FeedNewTabPageTest.java
@@ -291,7 +291,7 @@ mIsCachePopulatedInAccountManagerFacade = true; TestThreadUtils.runOnUiThreadBlocking(mTab::reload); - ChromeTabUtils.waitForTabPageLoaded(mTab, ChromeTabUtils.getUrlStringOnUiThread(mTab)); + ChromeTabUtils.waitForTabPageLoaded(mTab, mTab.getUrlString()); // Check that the sign-in promo is displayed this time. onView(instanceOf(RecyclerView.class))
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/SafetyTipInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/SafetyTipInfoBar.java index 32fa31f..32c2f883 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/SafetyTipInfoBar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/SafetyTipInfoBar.java
@@ -5,12 +5,16 @@ package org.chromium.chrome.browser.infobar; import android.graphics.Bitmap; +import android.text.SpannableString; +import android.text.SpannableStringBuilder; +import android.text.Spanned; import androidx.annotation.ColorRes; import org.chromium.base.annotations.CalledByNative; import org.chromium.components.infobars.ConfirmInfoBar; import org.chromium.components.infobars.InfoBarLayout; +import org.chromium.ui.text.NoUnderlineClickableSpan; /** * An infobar to present a Safety Tip. This is a thin vineer over standard ConfirmInfoBar to provide @@ -19,6 +23,7 @@ public class SafetyTipInfoBar extends ConfirmInfoBar { private static final String TAG = "SafetyTipInfoBar"; private String mDescription; + private String mLearnMoreLinkText; /** * Creates and begins the process for showing a SafetyTipInfoBar. This constructor is similar @@ -43,14 +48,24 @@ private SafetyTipInfoBar(int iconDrawableId, @ColorRes int iconTintId, Bitmap iconBitmap, String message, String linkText, String primaryButtonText, String secondaryButtonText, String description) { - super(iconDrawableId, iconTintId, iconBitmap, message, linkText, primaryButtonText, + super(iconDrawableId, iconTintId, iconBitmap, message, null, primaryButtonText, secondaryButtonText); mDescription = description; + mLearnMoreLinkText = linkText; } @Override public void createContent(InfoBarLayout layout) { super.createContent(layout); - layout.getMessageLayout().addDescription(mDescription); + + SpannableStringBuilder descriptionMessage = new SpannableStringBuilder(mDescription); + if (mLearnMoreLinkText != null && !mLearnMoreLinkText.isEmpty()) { + SpannableString link = new SpannableString(mLearnMoreLinkText); + link.setSpan( + new NoUnderlineClickableSpan(layout.getResources(), view -> onLinkClicked()), 0, + link.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + descriptionMessage.append(" ").append(link); + } + layout.getMessageLayout().addDescription(descriptionMessage); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java index 8d113af..8c3f2ed 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java
@@ -137,6 +137,11 @@ private LoadUrlParams mPendingLoadParams; /** + * URL of the page currently loading. Used as a fall-back in case tab restore fails. + */ + private GURL mUrl; + + /** * True while a page load is in progress. */ private boolean mIsLoading; @@ -327,7 +332,6 @@ return mId; } - // TODO(crbug.com/1113249) move getUrl() and getUrlString() to CriticalPersistedTabData @Override public String getUrlString() { return getUrl().getSpec(); @@ -341,12 +345,10 @@ // If we have a ContentView, or a NativePage, or the url is not empty, we have a WebContents // so cache the WebContent's url. If not use the cached version. if (getWebContents() != null || isNativePage() || !url.getSpec().isEmpty()) { - CriticalPersistedTabData.from(this).setUrl(url); + mUrl = url; } - return CriticalPersistedTabData.from(this).getUrl() != null - ? CriticalPersistedTabData.from(this).getUrl() - : GURL.emptyGURL(); + return mUrl != null ? mUrl : GURL.emptyGURL(); } @Override @@ -758,9 +760,7 @@ CriticalPersistedTabData.from(this).setLaunchTypeAtCreation(mLaunchType); mCreationState = creationState; mPendingLoadParams = loadUrlParams; - if (loadUrlParams != null) { - CriticalPersistedTabData.from(this).setUrl(new GURL(loadUrlParams.getUrl())); - } + if (loadUrlParams != null) mUrl = new GURL(loadUrlParams.getUrl()); TabHelpers.initTabHelpers(this, parent); @@ -822,8 +822,7 @@ assert state != null; CriticalPersistedTabData.from(this).setWebContentsState(state.contentsState); CriticalPersistedTabData.from(this).setTimestampMillis(state.timestampMillis); - CriticalPersistedTabData.from(this).setUrl( - new GURL(state.contentsState.getVirtualUrlFromState())); + mUrl = new GURL(state.contentsState.getVirtualUrlFromState()); CriticalPersistedTabData.from(this).setTitle( state.contentsState.getDisplayTitleFromState()); CriticalPersistedTabData.from(this).setLaunchTypeAtCreation(state.tabLaunchTypeAtCreation); @@ -1394,9 +1393,7 @@ initWebContents(webContents); if (!restored) { - String url = CriticalPersistedTabData.from(this).getUrl().getSpec().isEmpty() - ? UrlConstants.NTP_URL - : CriticalPersistedTabData.from(this).getUrl().getSpec(); + String url = mUrl.getSpec().isEmpty() ? UrlConstants.NTP_URL : mUrl.getSpec(); loadUrl(new LoadUrlParams(url, PageTransition.GENERATED)); } } finally {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsObserver.java index c3c59f5..8ba6590 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsObserver.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsObserver.java
@@ -73,7 +73,6 @@ private final ObserverList<Callback<WebContents>> mInitObservers = new ObserverList<>(); private final Handler mHandler = new Handler(); private WebContentsObserver mObserver; - private String mLastUrl; public static TabWebContentsObserver from(Tab tab) { TabWebContentsObserver observer = get(tab); @@ -295,7 +294,6 @@ recordErrorInPolicyAuditor( navigation.getUrl(), navigation.errorDescription(), navigation.errorCode()); } - mLastUrl = navigation.getUrl(); if (!navigation.hasCommitted()) return; @@ -355,7 +353,7 @@ @Override public void destroy() { MediaCaptureNotificationService.updateMediaNotificationForTab( - ContextUtils.getApplicationContext(), mTab.getId(), null, mLastUrl); + ContextUtils.getApplicationContext(), mTab.getId(), null, mTab.getUrlString()); super.destroy(); } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/MainActivityWithURLTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/MainActivityWithURLTest.java index 35d47bf..a64c72d 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/MainActivityWithURLTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/MainActivityWithURLTest.java
@@ -63,8 +63,7 @@ public void testLaunchActivity() { // Launch chrome mActivityTestRule.startMainActivityFromLauncher(); - String currentUrl = ChromeTabUtils.getUrlStringOnUiThread( - mActivityTestRule.getActivity().getActivityTab()); + String currentUrl = mActivityTestRule.getActivity().getActivityTab().getUrlString(); Assert.assertNotNull(currentUrl); Assert.assertEquals(false, currentUrl.isEmpty()); } @@ -79,17 +78,14 @@ public void testNewTabPageLaunch() { // Launch chrome with NTP. mActivityTestRule.startMainActivityWithURL(UrlConstants.NTP_URL); - String currentUrl = ChromeTabUtils.getUrlStringOnUiThread( - mActivityTestRule.getActivity().getActivityTab()); + String currentUrl = mActivityTestRule.getActivity().getActivityTab().getUrlString(); Assert.assertNotNull(currentUrl); Assert.assertEquals(false, currentUrl.isEmpty()); // Open NTP. ChromeTabUtils.newTabFromMenu( InstrumentationRegistry.getInstrumentation(), mActivityTestRule.getActivity()); - - currentUrl = ChromeTabUtils.getUrlStringOnUiThread( - mActivityTestRule.getActivity().getActivityTab()); + currentUrl = mActivityTestRule.getActivity().getActivityTab().getUrlString(); Assert.assertNotNull(currentUrl); Assert.assertEquals(false, currentUrl.isEmpty()); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/NavigateTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/NavigateTest.java index ce7886447..343de79 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/NavigateTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/NavigateTest.java
@@ -99,10 +99,8 @@ Criteria.checkThat("urlBar is null", urlBar, Matchers.notNullValue()); Criteria.checkThat("UrlBar text wrong", urlBar.getText().toString(), Matchers.is(expectedLocation(endUrl))); - Criteria.checkThat("Tab url wrong", - ChromeTabUtils.getUrlStringOnUiThread( - mActivityTestRule.getActivity().getActivityTab()), + mActivityTestRule.getActivity().getActivityTab().getUrlString(), Matchers.is(endUrl)); }); } @@ -236,8 +234,7 @@ DOMUtils.clickNode(tab.getWebContents(), "aboutLink"); ChromeTabUtils.waitForTabPageLoaded(tab, url2); Assert.assertEquals("Desired Link not open", url2, - ChromeTabUtils.getUrlStringOnUiThread( - mActivityTestRule.getActivity().getActivityTab())); + mActivityTestRule.getActivity().getActivityTab().getUrlString()); } /** @@ -323,7 +320,7 @@ @Override public void onPageLoadStarted(Tab tab, String newUrl) { tab.removeObserver(this); - Assert.assertEquals(url1, ChromeTabUtils.getUrlStringOnUiThread(tab)); + Assert.assertEquals(url1, tab.getUrlString()); Assert.assertEquals(url2, newUrl); } }; @@ -332,8 +329,7 @@ DOMUtils.clickNode(tab.getWebContents(), "aboutLink"); ChromeTabUtils.waitForTabPageLoaded(tab, url2); Assert.assertEquals("Desired Link not open", url2, - ChromeTabUtils.getUrlStringOnUiThread( - mActivityTestRule.getActivity().getActivityTab())); + mActivityTestRule.getActivity().getActivityTab().getUrlString()); } /** @@ -351,8 +347,7 @@ typeInOmniboxAndNavigate(initialUrl, null); CriteriaHelper.pollInstrumentationThread(() -> { - Criteria.checkThat(ChromeTabUtils.getUrlStringOnUiThread( - mActivityTestRule.getActivity().getActivityTab()), + Criteria.checkThat(mActivityTestRule.getActivity().getActivityTab().getUrlString(), Matchers.is(redirectedUrl)); }); } @@ -366,9 +361,8 @@ @Feature({"Navigation"}) public void testIntentFallbackRedirection() throws Exception { InstrumentationRegistry.getInstrumentation().waitForIdleSync(); - Assert.assertEquals(NEW_TAB_PAGE, - ChromeTabUtils.getUrlStringOnUiThread( - mActivityTestRule.getActivity().getActivityTab())); + Assert.assertEquals( + NEW_TAB_PAGE, mActivityTestRule.getActivity().getActivityTab().getUrlString()); final String fallbackUrl = mTestServer.getURL("/chrome/test/data/android/redirect/about.html"); @@ -388,8 +382,7 @@ // Now intent fallback should be triggered assuming 'non_existent' scheme cannot be handled. CriteriaHelper.pollInstrumentationThread(() -> { - Criteria.checkThat(ChromeTabUtils.getUrlStringOnUiThread( - mActivityTestRule.getActivity().getActivityTab()), + Criteria.checkThat(mActivityTestRule.getActivity().getActivityTab().getUrlString(), Matchers.is(targetUrl)); }); @@ -441,9 +434,7 @@ "URL mismatch after pressing back button for the 1st time in repetition" + "%d.", i), - urls[1], - ChromeTabUtils.getUrlStringOnUiThread( - mActivityTestRule.getActivity().getActivityTab())); + urls[1], mActivityTestRule.getActivity().getActivityTab().getUrlString()); TouchCommon.singleClickView( mActivityTestRule.getActivity().findViewById(R.id.back_button)); @@ -453,9 +444,7 @@ "URL mismatch after pressing back button for the 2nd time in repetition" + "%d.", i), - urls[0], - ChromeTabUtils.getUrlStringOnUiThread( - mActivityTestRule.getActivity().getActivityTab())); + urls[0], mActivityTestRule.getActivity().getActivityTab().getUrlString()); TouchCommon.singleClickView( mActivityTestRule.getActivity().findViewById(R.id.forward_button)); @@ -465,9 +454,7 @@ "URL mismatch after pressing fwd button for the 1st time in repetition" + "%d.", i), - urls[1], - ChromeTabUtils.getUrlStringOnUiThread( - mActivityTestRule.getActivity().getActivityTab())); + urls[1], mActivityTestRule.getActivity().getActivityTab().getUrlString()); TouchCommon.singleClickView( mActivityTestRule.getActivity().findViewById(R.id.forward_button)); @@ -477,9 +464,7 @@ "URL mismatch after pressing fwd button for the 2nd time in repetition" + "%d.", i), - urls[2], - ChromeTabUtils.getUrlStringOnUiThread( - mActivityTestRule.getActivity().getActivityTab())); + urls[2], mActivityTestRule.getActivity().getActivityTab().getUrlString()); } } @@ -618,8 +603,7 @@ private String getTabUrlOnUIThread(final Tab tab) { try { - return TestThreadUtils.runOnUiThreadBlocking( - () -> ChromeTabUtils.getUrlStringOnUiThread(tab)); + return TestThreadUtils.runOnUiThreadBlocking(() -> tab.getUrlString()); } catch (ExecutionException ex) { assert false : "Unexpected ExecutionException"; }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/TabsOpenedFromExternalAppTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/TabsOpenedFromExternalAppTest.java index f6b0eff1..82701ea 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/TabsOpenedFromExternalAppTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/TabsOpenedFromExternalAppTest.java
@@ -402,8 +402,7 @@ int newTabCount = ChromeTabUtils.getNumOpenTabs(mActivityTestRule.getActivity()); Assert.assertEquals("Incorrect number of tabs open", originalTabCount + 1, newTabCount); Assert.assertEquals("Selected tab is not on the right URL.", url1, - ChromeTabUtils.getUrlStringOnUiThread( - mActivityTestRule.getActivity().getActivityTab())); + mActivityTestRule.getActivity().getActivityTab().getUrlString()); // Launch a new URL from the same app, it should open in the same tab. originalTabCount = ChromeTabUtils.getNumOpenTabs(mActivityTestRule.getActivity()); @@ -411,8 +410,7 @@ newTabCount = ChromeTabUtils.getNumOpenTabs(mActivityTestRule.getActivity()); Assert.assertEquals("Incorrect number of tabs open", originalTabCount, newTabCount); Assert.assertEquals("Selected tab is not on the right URL.", url2, - ChromeTabUtils.getUrlStringOnUiThread( - mActivityTestRule.getActivity().getActivityTab())); + mActivityTestRule.getActivity().getActivityTab().getUrlString()); // And pressing back should close Clank. Assert.assertTrue("Window does not have focus before pressing back.", @@ -440,8 +438,7 @@ launchUrlFromExternalApp(url1, EXTERNAL_APP_1_ID, false); Assert.assertEquals("Selected tab is not on the right URL.", url1, - ChromeTabUtils.getUrlStringOnUiThread( - mActivityTestRule.getActivity().getActivityTab())); + mActivityTestRule.getActivity().getActivityTab().getUrlString()); // Launch the same URL without app ID. It should open a new tab. int originalTabCount = ChromeTabUtils.getNumOpenTabs(mActivityTestRule.getActivity()); @@ -449,8 +446,7 @@ int newTabCount = ChromeTabUtils.getNumOpenTabs(mActivityTestRule.getActivity()); Assert.assertEquals("Incorrect number of tabs open", originalTabCount + 1, newTabCount); Assert.assertEquals("Selected tab is not on the right URL.", url1, - ChromeTabUtils.getUrlStringOnUiThread( - mActivityTestRule.getActivity().getActivityTab())); + mActivityTestRule.getActivity().getActivityTab().getUrlString()); // Launch another URL without app ID. It should open a new tab. originalTabCount = ChromeTabUtils.getNumOpenTabs(mActivityTestRule.getActivity()); @@ -458,8 +454,7 @@ newTabCount = ChromeTabUtils.getNumOpenTabs(mActivityTestRule.getActivity()); Assert.assertEquals("Incorrect number of tabs open", originalTabCount + 1, newTabCount); Assert.assertEquals("Selected tab is not on the right URL.", url2, - ChromeTabUtils.getUrlStringOnUiThread( - mActivityTestRule.getActivity().getActivityTab())); + mActivityTestRule.getActivity().getActivityTab().getUrlString()); // And pressing back should close Clank. Assert.assertTrue("Window does not have focus before pressing back.", @@ -490,8 +485,7 @@ int newTabCount = ChromeTabUtils.getNumOpenTabs(mActivityTestRule.getActivity()); Assert.assertEquals("Incorrect number of tabs open", originalTabCount + 1, newTabCount); Assert.assertEquals("Selected tab is not on the right URL.", url1, - ChromeTabUtils.getUrlStringOnUiThread( - mActivityTestRule.getActivity().getActivityTab())); + mActivityTestRule.getActivity().getActivityTab().getUrlString()); // Launch a new URL from the same app with the right extra to open in a new tab. originalTabCount = ChromeTabUtils.getNumOpenTabs(mActivityTestRule.getActivity()); @@ -499,8 +493,7 @@ newTabCount = ChromeTabUtils.getNumOpenTabs(mActivityTestRule.getActivity()); Assert.assertEquals("Incorrect number of tabs open", originalTabCount + 1, newTabCount); Assert.assertEquals("Selected tab is not on the right URL.", url2, - ChromeTabUtils.getUrlStringOnUiThread( - mActivityTestRule.getActivity().getActivityTab())); + mActivityTestRule.getActivity().getActivityTab().getUrlString()); // And pressing back should close Clank. Assert.assertTrue("Window does not have focus before pressing back.", @@ -524,8 +517,7 @@ // Launch Clank from the external app. mActivityTestRule.startMainActivityFromExternalApp(url1, EXTERNAL_APP_1_ID); Assert.assertEquals("Selected tab is not on the right URL.", url1, - ChromeTabUtils.getUrlStringOnUiThread( - mActivityTestRule.getActivity().getActivityTab())); + mActivityTestRule.getActivity().getActivityTab().getUrlString()); // Launch a new URL from the same app, it should open in the same tab. int originalTabCount = ChromeTabUtils.getNumOpenTabs(mActivityTestRule.getActivity()); @@ -533,8 +525,7 @@ int newTabCount = ChromeTabUtils.getNumOpenTabs(mActivityTestRule.getActivity()); Assert.assertEquals("Incorrect number of tabs open", originalTabCount, newTabCount); Assert.assertEquals("Selected tab is not on the right URL.", url2, - ChromeTabUtils.getUrlStringOnUiThread( - mActivityTestRule.getActivity().getActivityTab())); + mActivityTestRule.getActivity().getActivityTab().getUrlString()); // And pressing back should close Clank. Assert.assertTrue("Window does not have focus before pressing back.", @@ -569,8 +560,7 @@ int newTabCount = ChromeTabUtils.getNumOpenTabs(mActivityTestRule.getActivity()); Assert.assertEquals("Incorrect number of tabs open", originalTabCount + 1, newTabCount); Assert.assertEquals("Selected tab is not on the right URL.", url2, - ChromeTabUtils.getUrlStringOnUiThread( - mActivityTestRule.getActivity().getActivityTab())); + mActivityTestRule.getActivity().getActivityTab().getUrlString()); // Also try with no app id, it should also open in a new tab. originalTabCount = ChromeTabUtils.getNumOpenTabs(mActivityTestRule.getActivity()); @@ -578,8 +568,7 @@ newTabCount = ChromeTabUtils.getNumOpenTabs(mActivityTestRule.getActivity()); Assert.assertEquals("Incorrect number of tabs open", originalTabCount + 1, newTabCount); Assert.assertEquals("Selected tab is not on the right URL.", url3, - ChromeTabUtils.getUrlStringOnUiThread( - mActivityTestRule.getActivity().getActivityTab())); + mActivityTestRule.getActivity().getActivityTab().getUrlString()); } /** @@ -608,8 +597,7 @@ int newTabCount = ChromeTabUtils.getNumOpenTabs(mActivityTestRule.getActivity()); Assert.assertEquals("Incorrect number of tabs open", originalTabCount + 1, newTabCount); Assert.assertEquals("Selected tab is not on the right URL.", url2, - ChromeTabUtils.getUrlStringOnUiThread( - mActivityTestRule.getActivity().getActivityTab())); + mActivityTestRule.getActivity().getActivityTab().getUrlString()); } /** @@ -657,8 +645,7 @@ int newTabCount = ChromeTabUtils.getNumOpenTabs(mActivityTestRule.getActivity()); Assert.assertEquals("Incorrect number of tabs open", originalTabCount + 1, newTabCount); Assert.assertEquals("Selected tab is not on the right URL.", url2, - ChromeTabUtils.getUrlStringOnUiThread( - mActivityTestRule.getActivity().getActivityTab())); + mActivityTestRule.getActivity().getActivityTab().getUrlString()); } private static class TestTabObserver extends EmptyTabObserver {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuTest.java index 92818af0..9af5fab 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuTest.java
@@ -46,7 +46,6 @@ import org.chromium.chrome.browser.tabmodel.EmptyTabModelSelectorObserver; import org.chromium.chrome.browser.tabmodel.TabModel; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; -import org.chromium.chrome.test.util.ChromeTabUtils; import org.chromium.chrome.test.util.browser.Features.DisableFeatures; import org.chromium.chrome.test.util.browser.Features.EnableFeatures; import org.chromium.chrome.test.util.browser.contextmenu.ContextMenuUtils; @@ -399,9 +398,7 @@ // Only check for the URL matching as the tab will not be fully created in svelte mode. final String expectedUrl = mTestServer.getURL(expectedPath); CriteriaHelper.pollUiThread( - () - -> Criteria.checkThat(ChromeTabUtils.getUrlStringOnUiThread(newTab.get()), - Matchers.is(expectedUrl))); + () -> Criteria.checkThat(newTab.get().getUrlString(), Matchers.is(expectedUrl))); } @Test @@ -537,21 +534,17 @@ "Number of open tabs does not match", numOpenedTabs, tabModel.getCount()); // Verify the Url is still the same of Parent page. - Assert.assertEquals(mTestUrl, - ChromeTabUtils.getUrlStringOnUiThread( - mDownloadTestRule.getActivity().getActivityTab())); + Assert.assertEquals( + mTestUrl, mDownloadTestRule.getActivity().getActivityTab().getUrlString()); // Verify that the background tabs were opened in the expected order. String newTabUrl = mTestServer.getURL( "/chrome/test/data/android/contextmenu/test_link.html"); - - Assert.assertEquals(newTabUrl, - ChromeTabUtils.getUrlStringOnUiThread(tabModel.getTabAt(indexOfLinkPage))); + Assert.assertEquals(newTabUrl, tabModel.getTabAt(indexOfLinkPage).getUrlString()); String imageUrl = mTestServer.getURL( "/chrome/test/data/android/contextmenu/test_link2.html"); - Assert.assertEquals(imageUrl, - ChromeTabUtils.getUrlStringOnUiThread(tabModel.getTabAt(indexOfLinkPage2))); + Assert.assertEquals(imageUrl, tabModel.getTabAt(indexOfLinkPage2).getUrlString()); } @Test
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuTest.java index 5bf0a93..325812d 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuTest.java
@@ -36,7 +36,6 @@ import org.chromium.chrome.browser.tabmodel.EmptyTabModelSelectorObserver; import org.chromium.chrome.browser.tabmodel.TabModel; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; -import org.chromium.chrome.test.util.ChromeTabUtils; import org.chromium.chrome.test.util.browser.Features; import org.chromium.chrome.test.util.browser.contextmenu.RevampedContextMenuUtils; import org.chromium.content_public.browser.test.util.Criteria; @@ -152,9 +151,7 @@ final String expectedUrl = mTestServer.getURL("/chrome/test/data/android/contextmenu/test_image.png"); CriteriaHelper.pollUiThread( - () - -> Criteria.checkThat(ChromeTabUtils.getUrlStringOnUiThread(newTab.get()), - Matchers.is(expectedUrl))); + () -> Criteria.checkThat(newTab.get().getUrlString(), Matchers.is(expectedUrl))); } @Test @@ -282,20 +279,17 @@ "Number of open tabs does not match", numOpenedTabs, tabModel.getCount()); // Verify the Url is still the same of Parent page. - Assert.assertEquals(mTestUrl, - ChromeTabUtils.getUrlStringOnUiThread( - mDownloadTestRule.getActivity().getActivityTab())); + Assert.assertEquals( + mTestUrl, mDownloadTestRule.getActivity().getActivityTab().getUrlString()); // Verify that the background tabs were opened in the expected order. String newTabUrl = mTestServer.getURL("/chrome/test/data/android/contextmenu/test_link.html"); - Assert.assertEquals(newTabUrl, - ChromeTabUtils.getUrlStringOnUiThread(tabModel.getTabAt(indexOfLinkPage))); + Assert.assertEquals(newTabUrl, tabModel.getTabAt(indexOfLinkPage).getUrlString()); String imageUrl = mTestServer.getURL("/chrome/test/data/android/contextmenu/test_link2.html"); - Assert.assertEquals(imageUrl, - ChromeTabUtils.getUrlStringOnUiThread(tabModel.getTabAt(indexOfLinkPage2))); + Assert.assertEquals(imageUrl, tabModel.getTabAt(indexOfLinkPage2).getUrlString()); } private void saveMediaFromContextMenu(String mediaDOMElement, int saveMenuID,
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java index 653fdc5..477e31d 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
@@ -1098,9 +1098,7 @@ CustomTabsTestUtils.createMinimalCustomTabIntent(context, mTestPage2)); })); CriteriaHelper.pollInstrumentationThread(() -> { - Criteria.checkThat( - ChromeTabUtils.getUrlStringOnUiThread(getActivity().getActivityTab()), - is(mTestPage)); + Criteria.checkThat(getActivity().getActivityTab().getUrlString(), is(mTestPage)); }); Assert.assertTrue("CustomTabContentHandler can't handle intent with same session", TestThreadUtils.runOnUiThreadBlockingNoException(() -> { @@ -1117,9 +1115,7 @@ }); pageLoadFinishedHelper.waitForCallback(0); CriteriaHelper.pollInstrumentationThread(() -> { - Criteria.checkThat( - ChromeTabUtils.getUrlStringOnUiThread(getActivity().getActivityTab()), - is(mTestPage2)); + Criteria.checkThat(getActivity().getActivityTab().getUrlString(), is(mTestPage2)); }); } @@ -1367,7 +1363,7 @@ mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent); CriteriaHelper.pollUiThread(() -> { final Tab currentTab = mCustomTabActivityTestRule.getActivity().getActivityTab(); - Criteria.checkThat(ChromeTabUtils.getUrlStringOnUiThread(currentTab), is(url)); + Criteria.checkThat(currentTab.getUrlString(), is(url)); }); CriteriaHelper.pollUiThread(() -> { CustomTabToolbar toolbar = @@ -1396,7 +1392,7 @@ mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent); CriteriaHelper.pollInstrumentationThread(() -> { final Tab currentTab = mCustomTabActivityTestRule.getActivity().getActivityTab(); - Criteria.checkThat(ChromeTabUtils.getUrlStringOnUiThread(currentTab), is(mTestPage)); + Criteria.checkThat(currentTab.getUrlString(), is(mTestPage)); }); Assert.assertTrue( connection.postMessage(token, "Message", null) == CustomTabsService.RESULT_SUCCESS); @@ -1428,7 +1424,7 @@ mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent); CriteriaHelper.pollInstrumentationThread(() -> { final Tab currentTab = mCustomTabActivityTestRule.getActivity().getActivityTab(); - Criteria.checkThat(ChromeTabUtils.getUrlStringOnUiThread(currentTab), is(mTestPage)); + Criteria.checkThat(currentTab.getUrlString(), is(mTestPage)); }); Assert.assertTrue( connection.postMessage(token, "Message", null) == CustomTabsService.RESULT_SUCCESS); @@ -1466,7 +1462,7 @@ mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent); CriteriaHelper.pollInstrumentationThread(() -> { final Tab currentTab = mCustomTabActivityTestRule.getActivity().getActivityTab(); - Criteria.checkThat(ChromeTabUtils.getUrlStringOnUiThread(currentTab), is(mTestPage)); + Criteria.checkThat(currentTab.getUrlString(), is(mTestPage)); }); Assert.assertTrue(connection.postMessage(token, "Message", null) == CustomTabsService.RESULT_FAILURE_MESSAGING_ERROR); @@ -1490,7 +1486,7 @@ mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent); CriteriaHelper.pollInstrumentationThread(() -> { final Tab currentTab = mCustomTabActivityTestRule.getActivity().getActivityTab(); - Criteria.checkThat(ChromeTabUtils.getUrlStringOnUiThread(currentTab), is(url)); + Criteria.checkThat(currentTab.getUrlString(), is(url)); }); Assert.assertTrue(connection.postMessage(token, "New title", null) == CustomTabsService.RESULT_SUCCESS); @@ -1568,7 +1564,7 @@ mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent); CriteriaHelper.pollInstrumentationThread(() -> { final Tab currentTab = mCustomTabActivityTestRule.getActivity().getActivityTab(); - Criteria.checkThat(ChromeTabUtils.getUrlStringOnUiThread(currentTab), is(url)); + Criteria.checkThat(currentTab.getUrlString(), is(url)); }); session.requestPostMessageChannel(Uri.parse("https://www.example.com/")); @@ -1669,7 +1665,7 @@ CriteriaHelper.pollInstrumentationThread(() -> { final Tab currentTab = mCustomTabActivityTestRule.getActivity().getActivityTab(); - Criteria.checkThat(ChromeTabUtils.getUrlStringOnUiThread(currentTab), is(url)); + Criteria.checkThat(currentTab.getUrlString(), is(url)); }); if (requestTime == AFTER_INTENT) { @@ -1717,7 +1713,7 @@ mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent); CriteriaHelper.pollInstrumentationThread(() -> { final Tab currentTab = mCustomTabActivityTestRule.getActivity().getActivityTab(); - Criteria.checkThat(ChromeTabUtils.getUrlStringOnUiThread(currentTab), is(mTestPage)); + Criteria.checkThat(currentTab.getUrlString(), is(mTestPage)); }); Assert.assertFalse(mCustomTabActivityTestRule.getActivity().getActivityTab().canGoBack()); @@ -2176,8 +2172,8 @@ Tab tab = tabbedActivity.get().getActivityTab(); Criteria.checkThat("Tab is null", tab, Matchers.notNullValue()); Criteria.checkThat("Incognito tab not selected", tab.isIncognito(), is(true)); - Criteria.checkThat("Wrong URL loaded in incognito tab", - ChromeTabUtils.getUrlStringOnUiThread(tab), is("about:blank")); + Criteria.checkThat( + "Wrong URL loaded in incognito tab", tab.getUrlString(), is("about:blank")); }); ApplicationStatus.unregisterActivityStateListener(listener); @@ -2389,7 +2385,7 @@ mCustomTabActivityTestRule.startCustomTabActivityWithIntent( CustomTabsTestUtils.createMinimalCustomTabIntent(context, mTestPage)); Tab tab = mCustomTabActivityTestRule.getActivity().getActivityTab(); - assertEquals(mTestPage, ChromeTabUtils.getUrlStringOnUiThread(tab)); + assertEquals(mTestPage, tab.getUrlString()); } private ChromeActivity reparentAndVerifyTab() {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabControllerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabControllerTest.java index a186597..adb6e38 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabControllerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabControllerTest.java
@@ -34,7 +34,6 @@ import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.test.ChromeActivityTestRule; import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate; -import org.chromium.chrome.test.util.ChromeTabUtils; import java.util.Arrays; import java.util.List; @@ -97,8 +96,7 @@ ((CustomTabActivityTestRule) mActivityTestRule).startCustomTabActivityWithIntent(intent); CustomTabActivityTabProvider tabProvider = getActivityTabProvider(); - assertEquals( - mediaViewerUrl, ChromeTabUtils.getUrlOnUiThread(tabProvider.getTab()).getSpec()); + assertEquals(mediaViewerUrl, tabProvider.getTab().getUrl().getSpec()); assertNotEquals(TabCreationMode.FROM_STARTUP_TAB_PRELOADER, tabProvider.getInitialTabCreationMode()); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/dom_distiller/ReaderModeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/dom_distiller/ReaderModeTest.java index eef8cc8..bd37b28 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/dom_distiller/ReaderModeTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/dom_distiller/ReaderModeTest.java
@@ -209,7 +209,7 @@ // Load the page that has an offline copy. The offline page should be shown. Tab tab = mDownloadTestRule.getActivity().getActivityTab(); Assert.assertFalse(isOfflinePage(tab)); - mDownloadTestRule.loadUrl(ChromeTabUtils.getUrlOnUiThread(tab).getSpec()); + mDownloadTestRule.loadUrl(tab.getUrl().getSpec()); Assert.assertTrue(isOfflinePage(tab)); } @@ -430,9 +430,7 @@ private void waitForDistillation(@SuppressWarnings("SameParameterValue") String expectedTitle, Tab tab) throws TimeoutException { CriteriaHelper.pollUiThread( - () - -> Criteria.checkThat(ChromeTabUtils.getUrlOnUiThread(tab).getScheme(), - is("chrome-distiller"))); + () -> Criteria.checkThat(tab.getUrl().getScheme(), is("chrome-distiller"))); ChromeTabUtils.waitForTabPageLoaded(tab, null); // Distiller Viewer load the content dynamically, so waitForTabPageLoaded() is not enough. CriteriaHelper.pollUiThread(() -> Criteria.checkThat(tab.getTitle(), is(expectedTitle)));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/gesturenav/NavigationHandlerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/gesturenav/NavigationHandlerTest.java index 19a56e1..fa26608e 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/gesturenav/NavigationHandlerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/gesturenav/NavigationHandlerTest.java
@@ -97,11 +97,8 @@ private void assertNavigateOnSwipeFrom(boolean edge, String toUrl) { ChromeTabUtils.waitForTabPageLoaded(currentTab(), toUrl, () -> swipeFromEdge(edge), 10); CriteriaHelper.pollUiThread( - () - -> Criteria.checkThat(ChromeTabUtils.getUrlStringOnUiThread(currentTab()), - Matchers.is(toUrl))); - Assert.assertEquals( - "Didn't navigate back", toUrl, ChromeTabUtils.getUrlStringOnUiThread(currentTab())); + () -> Criteria.checkThat(currentTab().getUrlString(), Matchers.is(toUrl))); + Assert.assertEquals("Didn't navigate back", toUrl, currentTab().getUrlString()); } private void swipeFromEdge(boolean leftEdge) { @@ -148,7 +145,7 @@ CriteriaHelper.pollUiThread(mNavigationLayout::isLayoutDetached, "Navigation Layout should be detached after use"); Assert.assertEquals("Current page should not change", UrlConstants.NTP_URL, - ChromeTabUtils.getUrlStringOnUiThread(currentTab())); + currentTab().getUrlString()); } @Test @@ -227,7 +224,7 @@ mActivityTestRule.getActivity().isInOverviewMode()); setTabSwitcherModeAndWait(false); Assert.assertEquals("Current page should not change", UrlConstants.RECENT_TABS_URL, - ChromeTabUtils.getUrlStringOnUiThread(currentTab())); + currentTab().getUrlString()); } /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/homepage/HomepagePolicyIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/homepage/HomepagePolicyIntegrationTest.java index fab4a56..6494f8e 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/homepage/HomepagePolicyIntegrationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/homepage/HomepagePolicyIntegrationTest.java
@@ -140,8 +140,7 @@ destroyAndRestartActivity(); Assert.assertEquals("Start up homepage should be the same as the policy setting", TEST_URL, - ChromeTabUtils.getUrlStringOnUiThread( - mActivityTestRule.getActivity().getActivityTab())); + mActivityTestRule.getActivity().getActivityTab().getUrlString()); } @Test @@ -153,8 +152,7 @@ .fullyLoadUrl(anotherUrl); Assert.assertNotEquals("Did not switch to a different URL", TEST_URL, - ChromeTabUtils.getUrlStringOnUiThread( - mActivityTestRule.getActivity().getActivityTab())); + mActivityTestRule.getActivity().getActivityTab().getUrlString()); ChromeTabUtils.waitForTabPageLoaded( mActivityTestRule.getActivity().getActivityTab(), TEST_URL, () -> { @@ -175,8 +173,7 @@ }); Assert.assertEquals("After clicking HomeButton, URL should be back to Homepage", TEST_URL, - ChromeTabUtils.getUrlStringOnUiThread( - mActivityTestRule.getActivity().getActivityTab())); + mActivityTestRule.getActivity().getActivityTab().getUrlString()); } @Test @@ -229,7 +226,6 @@ // Start a new ChromeActivity. mActivityTestRule.startActivityCompletely(intent); Assert.assertEquals("Start up page is not homepage", HomepageManager.getHomepageUri(), - ChromeTabUtils.getUrlStringOnUiThread( - mActivityTestRule.getActivity().getActivityTab())); + mActivityTestRule.getActivity().getActivityTab().getUrlString()); } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageNavigationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageNavigationTest.java index 23fc7ae..35e33ab 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageNavigationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageNavigationTest.java
@@ -22,7 +22,6 @@ 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.ChromeTabUtils; import org.chromium.components.embedder_support.util.UrlConstants; import org.chromium.net.test.EmbeddedTestServer; @@ -57,7 +56,7 @@ public void testNTPIsDefault() { Tab tab = mActivityTestRule.getActivity().getActivityTab(); Assert.assertNotNull(tab); - String url = ChromeTabUtils.getUrlStringOnUiThread(tab); + String url = tab.getUrlString(); Assert.assertTrue("Unexpected url: " + url, url.startsWith("chrome-native://newtab/") || url.startsWith("chrome-native://bookmarks/") @@ -73,9 +72,7 @@ public void testNavigatingFromNTP() { String url = mTestServer.getURL("/chrome/test/data/android/google.html"); mActivityTestRule.loadUrl(url); - Assert.assertEquals(url, - ChromeTabUtils.getUrlStringOnUiThread( - mActivityTestRule.getActivity().getActivityTab())); + Assert.assertEquals(url, mActivityTestRule.getActivity().getActivityTab().getUrlString()); } /** @@ -87,14 +84,12 @@ public void testNavigateBackToNTPViaUrl() { String url = mTestServer.getURL("/chrome/test/data/android/google.html"); mActivityTestRule.loadUrl(url); - Assert.assertEquals(url, - ChromeTabUtils.getUrlStringOnUiThread( - mActivityTestRule.getActivity().getActivityTab())); + Assert.assertEquals(url, mActivityTestRule.getActivity().getActivityTab().getUrlString()); mActivityTestRule.loadUrl(UrlConstants.NTP_URL); Tab tab = mActivityTestRule.getActivity().getActivityTab(); Assert.assertNotNull(tab); - url = ChromeTabUtils.getUrlStringOnUiThread(tab); + url = tab.getUrlString(); Assert.assertEquals(UrlConstants.NTP_URL, url); // Check that the NTP is actually displayed.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java index 22a4028c..951a51554 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java
@@ -258,8 +258,7 @@ TouchCommon.singleClickView(mostVisitedItem); } }); - Assert.assertEquals( - mSiteSuggestions.get(0).url, ChromeTabUtils.getUrlStringOnUiThread(mTab)); + Assert.assertEquals(mSiteSuggestions.get(0).url, mTab.getUrlString()); } /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/cards/promo/HomepagePromoTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/cards/promo/HomepagePromoTest.java index 1e8f217..bc7da2e2 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/cards/promo/HomepagePromoTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/cards/promo/HomepagePromoTest.java
@@ -44,6 +44,7 @@ import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.DisableIf; +import org.chromium.base.test.util.DisabledTest; import org.chromium.chrome.R; import org.chromium.chrome.browser.feature_engagement.TrackerFactory; import org.chromium.chrome.browser.flags.ChromeFeatureList; @@ -288,6 +289,7 @@ @Test @SmallTest + @DisabledTest(message = "https://crbug.com/1115870") public void testToggleFeed_WithHomepage() { // Test to toggle NTP when feed is hidden. TestThreadUtils.runOnUiThreadBlocking(() -> {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorControllerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorControllerTest.java index 321e02a8..c43885a 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorControllerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorControllerTest.java
@@ -351,7 +351,7 @@ Tab tab = mActivityTestRule.getActivity().getActivityTab(); mActivityTestRule.loadUrl(pageUrl); - Assert.assertEquals(pageUrl, ChromeTabUtils.getUrlStringOnUiThread(tab)); + Assert.assertEquals(pageUrl, tab.getUrlString()); if (mIsConnected) { Assert.assertFalse(isErrorPage(tab)); Assert.assertFalse(isOfflinePage(tab));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/partnercustomizations/PartnerHomepageIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/partnercustomizations/PartnerHomepageIntegrationTest.java index 2bb2bd2..5c6eda6 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/partnercustomizations/PartnerHomepageIntegrationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/partnercustomizations/PartnerHomepageIntegrationTest.java
@@ -76,8 +76,7 @@ @Feature({"Homepage"}) public void testHomepageInitialLoading() { Assert.assertEquals(Uri.parse(TestPartnerBrowserCustomizationsProvider.HOMEPAGE_URI), - Uri.parse(ChromeTabUtils.getUrlStringOnUiThread( - mActivityTestRule.getActivity().getActivityTab()))); + Uri.parse(mActivityTestRule.getActivity().getActivityTab().getUrlString())); } /** @@ -94,8 +93,7 @@ mActivityTestRule.loadUrl(testServer.getURL(TEST_PAGE)); UiUtils.settleDownUI(InstrumentationRegistry.getInstrumentation()); Assert.assertNotSame(Uri.parse(TestPartnerBrowserCustomizationsProvider.HOMEPAGE_URI), - Uri.parse(ChromeTabUtils.getUrlStringOnUiThread( - mActivityTestRule.getActivity().getActivityTab()))); + Uri.parse(mActivityTestRule.getActivity().getActivityTab().getUrlString())); // Click homepage button. ChromeTabUtils.waitForTabPageLoaded(mActivityTestRule.getActivity().getActivityTab(), @@ -110,8 +108,7 @@ } }); Assert.assertEquals(Uri.parse(TestPartnerBrowserCustomizationsProvider.HOMEPAGE_URI), - Uri.parse(ChromeTabUtils.getUrlStringOnUiThread( - mActivityTestRule.getActivity().getActivityTab()))); + Uri.parse(mActivityTestRule.getActivity().getActivityTab().getUrlString())); } finally { testServer.stopAndDestroyServer(); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/portals/PortalsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/portals/PortalsTest.java index 99efc03e..dd5a5d18a 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/portals/PortalsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/portals/PortalsTest.java
@@ -34,6 +34,7 @@ import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; +import org.chromium.base.test.util.FlakyTest; import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeActivity; @@ -548,6 +549,7 @@ @LargeTest @Feature({"Portals"}) @MinAndroidSdkLevel(Build.VERSION_CODES.M) + @FlakyTest(message = "https://crbug.com/1115888") public void testMediaCaptureNotificationVisibleAfterAdoption() throws Exception { String mainUrl = mTestServer.getURL("/chrome/test/data/android/portals/media-capture.html"); mActivityTestRule.startMainActivityWithURL(mainUrl);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/query_tiles/OmniboxQueryTileSuggestionTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/query_tiles/OmniboxQueryTileSuggestionTest.java index c8ff83e..c72422f 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/query_tiles/OmniboxQueryTileSuggestionTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/query_tiles/OmniboxQueryTileSuggestionTest.java
@@ -45,7 +45,6 @@ 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.ChromeTabUtils; import org.chromium.chrome.test.util.NewTabPageTestUtils; import org.chromium.chrome.test.util.OmniboxTestUtils; import org.chromium.chrome.test.util.browser.Features; @@ -236,8 +235,7 @@ } private String getTabUrl() { - return ChromeTabUtils.getUrlOnUiThread(mActivityTestRule.getActivity().getActivityTab()) - .getValidSpecOrEmpty(); + return mActivityTestRule.getActivity().getActivityTab().getUrl().getValidSpecOrEmpty(); } private void waitForOmniboxQueryTileSuggestion(boolean visible) { @@ -255,8 +253,7 @@ private void waitForSearchResultsPage() { CriteriaHelper.pollUiThread(() -> { - Criteria.checkThat("The SRP was never loaded.", - ChromeTabUtils.getUrlOnUiThread(mTab).getValidSpecOrEmpty(), + Criteria.checkThat("The SRP was never loaded.", mTab.getUrl().getValidSpecOrEmpty(), Matchers.containsString(SEARCH_URL_PATTERN)); }); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/query_tiles/QueryTileSectionTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/query_tiles/QueryTileSectionTest.java index 4bb2037..7fb46ecb0 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/query_tiles/QueryTileSectionTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/query_tiles/QueryTileSectionTest.java
@@ -40,7 +40,6 @@ 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.ChromeTabUtils; import org.chromium.chrome.test.util.NewTabPageTestUtils; import org.chromium.chrome.test.util.OmniboxTestUtils; import org.chromium.chrome.test.util.browser.Features; @@ -210,14 +209,12 @@ } private String getTabUrl() { - return ChromeTabUtils.getUrlOnUiThread(mActivityTestRule.getActivity().getActivityTab()) - .getValidSpecOrEmpty(); + return mActivityTestRule.getActivity().getActivityTab().getUrl().getValidSpecOrEmpty(); } private void waitForSearchResultsPage() { CriteriaHelper.pollUiThread(() -> { - Criteria.checkThat("The SRP was never loaded.", - ChromeTabUtils.getUrlOnUiThread(mTab).getValidSpecOrEmpty(), + Criteria.checkThat("The SRP was never loaded.", mTab.getUrl().getValidSpecOrEmpty(), Matchers.containsString(SEARCH_URL_PATTERN)); }); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/reengagement/ReengagementNotificationControllerIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/reengagement/ReengagementNotificationControllerIntegrationTest.java index 1b7b9fce..2b0cd07 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/reengagement/ReengagementNotificationControllerIntegrationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/reengagement/ReengagementNotificationControllerIntegrationTest.java
@@ -54,7 +54,6 @@ import org.chromium.chrome.browser.tabmodel.TabModelSelectorObserver; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.ChromeTabbedActivityTestRule; -import org.chromium.chrome.test.util.ChromeTabUtils; import org.chromium.components.feature_engagement.EventConstants; import org.chromium.components.feature_engagement.FeatureConstants; import org.chromium.components.feature_engagement.Tracker; @@ -295,7 +294,7 @@ tabAddedCallback.waitForCallback(0); Tab tab = TestThreadUtils.runOnUiThreadBlocking( () -> mTabbedActivityTestRule.getActivity().getActivityTab()); - Assert.assertTrue(NewTabPage.isNTPUrl(ChromeTabUtils.getUrlOnUiThread(tab))); + Assert.assertTrue(NewTabPage.isNTPUrl(tab.getUrl())); Assert.assertFalse(tab.isIncognito()); Assert.assertEquals(initialTabCount + 1, mTabbedActivityTestRule.getActivity().getTabModelSelector().getTotalTabCount());
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/UndoTabModelTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/UndoTabModelTest.java index c5e501e..ef743182 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/UndoTabModelTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/UndoTabModelTest.java
@@ -1462,7 +1462,7 @@ tab0 = model.getTabAt(0); Tab tab1 = model.getTabAt(1); tabs = new Tab[]{tab0, tab1}; - Assert.assertEquals(TEST_URL_0, ChromeTabUtils.getUrlStringOnUiThread(tab1)); + Assert.assertEquals(TEST_URL_0, tab1.getUrlString()); checkState(model, tabs, tab0, EMPTY, tabs, tab0); } @@ -1537,8 +1537,8 @@ firstModelTab); checkState(secondModel, secondWindowTabs, secondModelTab, EMPTY, secondWindowTabs, secondModelTab); - Assert.assertEquals(TEST_URL_0, ChromeTabUtils.getUrlStringOnUiThread(firstWindowTabs[1])); - Assert.assertEquals(TEST_URL_1, ChromeTabUtils.getUrlStringOnUiThread(secondWindowTabs[1])); + Assert.assertEquals(TEST_URL_0, firstWindowTabs[1].getUrlString()); + Assert.assertEquals(TEST_URL_1, secondWindowTabs[1].getUrlString()); secondActivity.finishAndRemoveTask(); } @@ -1602,6 +1602,6 @@ Tab tab1 = firstModel.getTabAt(1); Tab[] firstWindowTabs = new Tab[]{tab0, tab1}; checkState(firstModel, firstWindowTabs, tab0, EMPTY, firstWindowTabs, tab0); - Assert.assertEquals(TEST_URL_1, ChromeTabUtils.getUrlStringOnUiThread(tab1)); + Assert.assertEquals(TEST_URL_1, tab1.getUrlString()); } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/ToolbarTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/ToolbarTest.java index 884ab05..be3f220c 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/ToolbarTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/ToolbarTest.java
@@ -32,7 +32,6 @@ import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.test.ChromeActivityTestRule; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; -import org.chromium.chrome.test.util.ChromeTabUtils; import org.chromium.chrome.test.util.MenuUtils; import org.chromium.chrome.test.util.OmniboxTestUtils; import org.chromium.components.browser_ui.widget.scrim.ScrimCoordinator; @@ -127,7 +126,7 @@ // Load new tab page. mActivityTestRule.loadUrl(UrlConstants.NTP_URL); - Assert.assertEquals(UrlConstants.NTP_URL, ChromeTabUtils.getUrlStringOnUiThread(tab)); + Assert.assertEquals(UrlConstants.NTP_URL, tab.getUrlString()); assertFalse(isErrorPage(tab)); // Stop the server and also disconnect the network. @@ -136,7 +135,7 @@ () -> NetworkChangeNotifier.forceConnectivityState(false)); mActivityTestRule.loadUrl(testUrl); - Assert.assertEquals(testUrl, ChromeTabUtils.getUrlStringOnUiThread(tab)); + Assert.assertEquals(testUrl, tab.getUrlString()); assertTrue(isErrorPage(tab)); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappNavigationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappNavigationTest.java index f2587a5..015f40d 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappNavigationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappNavigationTest.java
@@ -356,7 +356,7 @@ String otherInScopeUrl = WebappTestPage.getNonServiceWorkerUrl(mActivityTestRule.getTestServer()); mActivityTestRule.loadUrlInTab(otherInScopeUrl, PageTransition.LINK, tab); - assertEquals(otherInScopeUrl, ChromeTabUtils.getUrlStringOnUiThread(tab)); + assertEquals(otherInScopeUrl, tab.getUrlString()); mActivityTestRule.loadUrlInTab( offOriginUrl(), PageTransition.LINK, tab, 10 /* secondsToWait */);
diff --git a/chrome/android/junit/DEPS b/chrome/android/junit/DEPS index c399fc8..3dc7290 100644 --- a/chrome/android/junit/DEPS +++ b/chrome/android/junit/DEPS
@@ -10,6 +10,7 @@ "+chrome/browser/tabmodel", "+chrome/browser/thumbnail/generator/android/java", "+chrome/browser/ui/messages/android/java", + "+chrome/browser/xsurface/android", "+components/autofill/android/java/src/org/chromium/components/autofill", "+components/background_task_scheduler/android", "+components/bookmarks/common/android",
diff --git a/chrome/android/monochrome/scripts/monochrome_apk_checker.py b/chrome/android/monochrome/scripts/monochrome_apk_checker.py index 1bccea34..4bf3857 100755 --- a/chrome/android/monochrome/scripts/monochrome_apk_checker.py +++ b/chrome/android/monochrome/scripts/monochrome_apk_checker.py
@@ -141,7 +141,7 @@ match.group('cmpr') == 0)) return apk_entries -def VerifySameFile(monochrome_dict, apk, changes): +def VerifySameFile(monochrome_dict, apk, changes, apk_name): """Verify apk file content matches same files in monochrome. Verify files from apk are same as those in monochrome except files @@ -154,11 +154,16 @@ if m and m.CRC != a.CRC and not changes.match(m.filename): diff.append(a.filename) if len(diff): - raise Exception("The following files are not same as Monochrome:\n %s" % - '\n'.join(diff)) + msg = """\ +Unless specifcially excepted, all files in {0} should be exactly the same as +the similarly named file in Monochrome. However these files were present in +both monochrome and {0}, but had different contents: +{1} +""".format(apk_name, '\n'.join(diff)) + raise Exception(msg) -def VerifyUncompressed(monochrome, apk): +def VerifyUncompressed(monochrome, apk, apk_name): """Verify uncompressed files in apk are a subset of those in monochrome. Verify files not being compressed in apk are also uncompressed in @@ -168,10 +173,15 @@ monochrome_uncompressed = [i.filename for i in monochrome if i.uncompressed] compressed = [u for u in uncompressed if u not in monochrome_uncompressed] if len(compressed): - raise Exception("The following files are compressed in Monochrome:\n %s" % - '\n'.join(compressed)) + msg = """\ +Uncompressed files in {0} should also be uncompressed in Monochrome. +However these files were uncompressed in {0} but compressed in Monochrome: +{1} +""".format(apk_name, '\n'.join(compressed)) + raise Exception(msg) -def SuperSetOf(monochrome, apk): + +def SuperSetOf(monochrome, apk, apk_name): """Verify Monochrome is super set of apk.""" def exists_in_some_form(f): @@ -189,8 +199,12 @@ missing_files = [f for f in apk if not exists_in_some_form(f)] if len(missing_files): - raise Exception('The following files are missing in Monochrome:\n %s' % - '\n'.join(missing_files)) + msg = """\ +Monochrome is expected to have a superset of the files in {0}. +However these files were present in {0} but not in Monochrome: +{1} +""".format(apk_name, '\n'.join(missing_files)) + raise Exception(msg) def RemoveSpecific(apk_entries, specific): @@ -228,20 +242,29 @@ Returns: An Namespace from argparse.parse_args() """ - parser = argparse.ArgumentParser(prog='monochrome_apk_checker') + parser = argparse.ArgumentParser( + prog='monochrome_apk_checker', + description='This script enforces expectations about similarities ' + 'between Chrome, Monochrome and Webview APKs.', + epilog='If the release APK is obfuscated, you will find its pathmap next ' + 'to the apk in your output directory, ending with ".pathmap".') - parser.add_argument( - '--monochrome-apk', required=True, help='The monochrome APK path.') + required_args = parser.add_argument_group('required arguments') + + required_args.add_argument( + '--monochrome-apk', required=True, help='The path to the monochrome APK.') parser.add_argument( '--monochrome-pathmap', help='The monochrome APK resources pathmap path.') - parser.add_argument('--chrome-apk', - required=True, - help='The chrome APK path.') + required_args.add_argument( + '--chrome-apk', + required=True, + help='The path to the chrome APK.') parser.add_argument( '--chrome-pathmap', help='The chrome APK resources pathmap path.') - parser.add_argument('--system-webview-apk', - required=True, - help='The system webview APK path.') + required_args.add_argument( + '--system-webview-apk', + required=True, + help='The path to the system webview APK.') parser.add_argument( '--system-webview-pathmap', help='The system webview APK resources pathmap path.') @@ -265,25 +288,31 @@ chrome = RemoveSpecific(DumpAPK(options.chrome_apk), CHROME_SPECIFIC) if len(chrome) == 0: - raise Exception('Chrome should have common files with Monochrome') + raise Exception( + 'Chrome should have common files with Monochrome. However the passed ' + 'in APKs do not have any files in common. Are you sure you are passing ' + 'in the right arguments?') webview = RemoveSpecific(DumpAPK(options.system_webview_apk), WEBVIEW_SPECIFIC) if len(webview) == 0: - raise Exception('WebView should have common files with Monochrome') + raise Exception( + 'Webview should have common files with Monochrome. However the passed ' + 'in APKs do not have any files in common. Are you sure you are passing ' + 'in the right arguments?') - def check_apk(apk, pathmap): + def check_apk(apk, pathmap, apk_name): apk_files = [DeobfuscateFilename(f.filename, pathmap) for f in apk] - SuperSetOf(monochrome_files, apk_files) - VerifyUncompressed(monochrome, apk) - VerifySameFile(monochrome_dict, chrome, CHROME_CHANGES) - VerifySameFile(monochrome_dict, webview, WEBVIEW_CHANGES) + SuperSetOf(monochrome_files, apk_files, apk_name) + VerifyUncompressed(monochrome, apk, apk_name) chrome_pathmap = LoadPathmap(options.chrome_pathmap) - check_apk(chrome, chrome_pathmap) + check_apk(chrome, chrome_pathmap, 'Chrome') + VerifySameFile(monochrome_dict, chrome, CHROME_CHANGES, 'Chrome') webview_pathmap = LoadPathmap(options.system_webview_pathmap) - check_apk(webview, webview_pathmap) + check_apk(webview, webview_pathmap, 'Webview') + VerifySameFile(monochrome_dict, webview, WEBVIEW_CHANGES, 'Webview') if __name__ == '__main__': sys.exit(main())
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt index b336af2e..ed689bf 100644 --- a/chrome/android/profiles/newest.txt +++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@ -chromeos-chrome-amd64-86.0.4229.0_rc-r1-merged.afdo.bz2 +chromeos-chrome-amd64-86.0.4231.0_rc-r1-merged.afdo.bz2
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp index 4f491cf..3373ba25 100644 --- a/chrome/app/chromeos_strings.grdp +++ b/chrome/app/chromeos_strings.grdp
@@ -365,6 +365,9 @@ <message name="IDS_UPDATE_AVAILABLE" desc="Notification for available update"> System update available. Preparing to download… </message> + <message name="IDS_UPDATE_COMPLETED_REBOOTING" desc="Notification for update completed and reboot is in progress"> + Restarting to apply updates + </message> <message name="IDS_UPDATE_COMPLETED" desc="Notification for update completed"> System update complete. Please restart the system. </message>
diff --git a/chrome/app/chromeos_strings_grdp/IDS_UPDATE_COMPLETED_REBOOTING.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_UPDATE_COMPLETED_REBOOTING.png.sha1 new file mode 100644 index 0000000..b65b854 --- /dev/null +++ b/chrome/app/chromeos_strings_grdp/IDS_UPDATE_COMPLETED_REBOOTING.png.sha1
@@ -0,0 +1 @@ +5b1d9d9d154116b2fbcd85c2fad7dba0f521f1fa \ No newline at end of file
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 3058db5..cd8e168 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -10521,6 +10521,9 @@ other {# open windows} } </message> + <message name="IDS_INCOGNITO_PROFILE_MENU_CREATE_SHORTCUT_BUTTON" desc="Label of the button to create a desktop shortcut for incognito mode."> + Create shortcut + </message> <message name="IDS_INCOGNITO_PROFILE_MENU_CLOSE_BUTTON" desc="The text of the button offering to close all incognito windows."> Exit Incognito </message>
diff --git a/chrome/app/generated_resources_grd/IDS_INCOGNITO_PROFILE_MENU_CREATE_SHORTCUT_BUTTON.png.sha1 b/chrome/app/generated_resources_grd/IDS_INCOGNITO_PROFILE_MENU_CREATE_SHORTCUT_BUTTON.png.sha1 new file mode 100644 index 0000000..90c6af5 --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_INCOGNITO_PROFILE_MENU_CREATE_SHORTCUT_BUTTON.png.sha1
@@ -0,0 +1 @@ +94bf3c59a0ed0ba39d2a2c8629c81d2cc1b77504 \ No newline at end of file
diff --git a/chrome/app/profiles_strings.grdp b/chrome/app/profiles_strings.grdp index cb9d39e..7e18e04 100644 --- a/chrome/app/profiles_strings.grdp +++ b/chrome/app/profiles_strings.grdp
@@ -682,6 +682,9 @@ <message name="IDS_PROFILE_PICKER_PROFILE_MENU_REMOVE_TEXT" desc="Text of the remove button in profile card menu and on the title of the remove warning."> Remove </message> + <message name="IDS_PROFILE_PICKER_PROFILE_MENU_CUSTOMIZE_TEXT" desc="Text of the customize button in profile card menu"> + Customize + </message> <message name="IDS_PROFILE_PICKER_REMOVE_WARNING_LOCAL_PROFILE" desc="Main text shown as a warning when attempting to remove an user."> This will permanently delete your browsing data from this device. </message>
diff --git a/chrome/app/profiles_strings_grdp/IDS_PROFILE_PICKER_PROFILE_MENU_CUSTOMIZE_TEXT.png.sha1 b/chrome/app/profiles_strings_grdp/IDS_PROFILE_PICKER_PROFILE_MENU_CUSTOMIZE_TEXT.png.sha1 new file mode 100644 index 0000000..84bc98d2 --- /dev/null +++ b/chrome/app/profiles_strings_grdp/IDS_PROFILE_PICKER_PROFILE_MENU_CUSTOMIZE_TEXT.png.sha1
@@ -0,0 +1 @@ +0eb8b376ac429f0fc430c520e66c21845aeb307c \ No newline at end of file
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp index b86fb5f..a86406b 100644 --- a/chrome/app/settings_strings.grdp +++ b/chrome/app/settings_strings.grdp
@@ -1223,6 +1223,9 @@ <message name="IDS_SETTINGS_SAFETY_CHECK_SAFE_BROWSING_ENABLED_STANDARD" desc="This text points out that Safe Browsing is enabled as standard protection."> Standard Protection is on </message> + <message name="IDS_SETTINGS_SAFETY_CHECK_SAFE_BROWSING_ENABLED_STANDARD_AVAILABLE_ENHANCED" desc="This text points out that Safe Browsing is enabled as standard protection, but the user can enable enhanced protection."> + Standard protection is on. For even more security, use enhanced protection. + </message> <message name="IDS_SETTINGS_SAFETY_CHECK_SAFE_BROWSING_ENABLED_ENHANCED" desc="This text points out that Safe Browsing is enabled as enhanced protection."> Enhanced Protection is on </message>
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_SAFETY_CHECK_SAFE_BROWSING_ENABLED_STANDARD_AVAILABLE_ENHANCED.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SAFETY_CHECK_SAFE_BROWSING_ENABLED_STANDARD_AVAILABLE_ENHANCED.png.sha1 new file mode 100644 index 0000000..d93b432 --- /dev/null +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SAFETY_CHECK_SAFE_BROWSING_ENABLED_STANDARD_AVAILABLE_ENHANCED.png.sha1
@@ -0,0 +1 @@ +86ab9204e762414a4b73373a9ae2183fd571b1df \ No newline at end of file
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index d95c972c..ac06474 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -5544,11 +5544,6 @@ FEATURE_VALUE_TYPE(ash::features::kContextualNudges)}, #endif // defined(OS_CHROMEOS) - {"policy-atomic-group-enabled", - flag_descriptions::kPolicyAtomicGroupsEnabledName, - flag_descriptions::kPolicyAtomicGroupsEnabledDescription, kOsAll, - FEATURE_VALUE_TYPE(policy::features::kPolicyAtomicGroup)}, - {"decode-jpeg-images-to-yuv", flag_descriptions::kDecodeJpeg420ImagesToYUVName, flag_descriptions::kDecodeJpeg420ImagesToYUVDescription, kOsAll,
diff --git a/chrome/browser/apps/app_service/app_icon_factory.cc b/chrome/browser/apps/app_service/app_icon_factory.cc index c21bf72..6b819552 100644 --- a/chrome/browser/apps/app_service/app_icon_factory.cc +++ b/chrome/browser/apps/app_service/app_icon_factory.cc
@@ -69,6 +69,7 @@ using SizeToImageSkiaRep = std::map<int, gfx::ImageSkiaRep>; using ScaleToImageSkiaReps = std::map<float, SizeToImageSkiaRep>; using MaskImageSkiaReps = std::pair<SkBitmap, ScaleToImageSkiaReps>; +using ScaleToSize = std::map<float, int>; MaskImageSkiaReps& GetMaskResourceIconCache() { static base::NoDestructor<MaskImageSkiaReps> mask_cache; @@ -111,20 +112,23 @@ return image_rep; } -gfx::ImageSkia LoadMaskImage(const gfx::ImageSkia& image) { - std::map<float, gfx::Size> scale_to_size; - if (image.image_reps().empty()) { - scale_to_size[1.0f] = image.size(); +ScaleToSize GetScaleToSize(const gfx::ImageSkia& image_skia) { + ScaleToSize scale_to_size; + if (image_skia.image_reps().empty()) { + scale_to_size[1.0f] = image_skia.size().width(); } else { - for (const auto& rep : image.image_reps()) { - scale_to_size[rep.scale()] = rep.pixel_size(); + for (const auto& rep : image_skia.image_reps()) { + scale_to_size[rep.scale()] = rep.pixel_width(); } } + return scale_to_size; +} +gfx::ImageSkia LoadMaskImage(const ScaleToSize& scale_to_size) { gfx::ImageSkia mask_image; for (const auto& it : scale_to_size) { float scale = it.first; - int size_hint_in_dip = it.second.width(); + int size_hint_in_dip = it.second; mask_image.AddRepresentation( GetMaskAsImageSkiaRep(scale, size_hint_in_dip)); } @@ -711,8 +715,7 @@ void IconLoadingPipeline::ApplyBackgroundAndMask(const gfx::ImageSkia& image) { std::move(image_skia_callback_) .Run(gfx::ImageSkiaOperations::CreateResizedImage( - gfx::ImageSkiaOperations::CreateButtonBackground( - SK_ColorWHITE, image, LoadMaskImage(image)), + apps::ApplyBackgroundAndMask(image), skia::ImageOperations::RESIZE_LANCZOS3, gfx::Size(size_hint_in_dip_, size_hint_in_dip_))); } @@ -740,10 +743,8 @@ std::move(image_skia_callback_) .Run(gfx::ImageSkiaOperations::CreateResizedImage( - gfx::ImageSkiaOperations::CreateMaskedImage( - gfx::ImageSkiaOperations::CreateSuperimposedImage( - background_image_, foreground_image_), - LoadMaskImage(image)), + apps::CompositeImagesAndApplyMask(foreground_image_, + background_image_), skia::ImageOperations::RESIZE_BEST, gfx::Size(size_hint_in_dip_, size_hint_in_dip_))); } @@ -939,6 +940,21 @@ } #if defined(OS_CHROMEOS) + +gfx::ImageSkia ApplyBackgroundAndMask(const gfx::ImageSkia& image) { + return gfx::ImageSkiaOperations::CreateButtonBackground( + SK_ColorWHITE, image, LoadMaskImage(GetScaleToSize(image))); +} + +gfx::ImageSkia CompositeImagesAndApplyMask( + const gfx::ImageSkia& foreground_image, + const gfx::ImageSkia& background_image) { + return gfx::ImageSkiaOperations::CreateMaskedImage( + gfx::ImageSkiaOperations::CreateSuperimposedImage(background_image, + foreground_image), + LoadMaskImage(GetScaleToSize(foreground_image))); +} + void ArcRawIconPngDataToImageSkia( arc::mojom::RawIconPngDataPtr icon, int size_hint_in_dip, @@ -1015,7 +1031,7 @@ } if (icon_effects & IconEffects::kCrOsStandardMask) { - auto mask_image = LoadMaskImage(*image_skia); + auto mask_image = LoadMaskImage(GetScaleToSize(*image_skia)); *image_skia = gfx::ImageSkiaOperations::CreateMaskedImage(*image_skia, mask_image); }
diff --git a/chrome/browser/apps/app_service/app_icon_factory.h b/chrome/browser/apps/app_service/app_icon_factory.h index 475d38a..e466c9e 100644 --- a/chrome/browser/apps/app_service/app_icon_factory.h +++ b/chrome/browser/apps/app_service/app_icon_factory.h
@@ -68,6 +68,12 @@ float rep_icon_scale); #if defined(OS_CHROMEOS) +gfx::ImageSkia ApplyBackgroundAndMask(const gfx::ImageSkia& image); + +gfx::ImageSkia CompositeImagesAndApplyMask( + const gfx::ImageSkia& foreground_image, + const gfx::ImageSkia& background_image); + void ArcRawIconPngDataToImageSkia( arc::mojom::RawIconPngDataPtr icon, int size_hint_in_dip,
diff --git a/chrome/browser/apps/app_service/arc_apps.cc b/chrome/browser/apps/app_service/arc_apps.cc index c4607a1de..7bb928f 100644 --- a/chrome/browser/apps/app_service/arc_apps.cc +++ b/chrome/browser/apps/app_service/arc_apps.cc
@@ -107,10 +107,10 @@ if (base::FeatureList::IsEnabled(features::kAppServiceAdaptiveIcon)) { iv->uncompressed = icon->is_adaptive_icon() - ? gfx::ImageSkiaOperations::CreateSuperimposedImage( - icon->background_image_skia(), - icon->foreground_image_skia()) - : icon->foreground_image_skia(); + ? apps::CompositeImagesAndApplyMask( + icon->foreground_image_skia(), + icon->background_image_skia()) + : apps::ApplyBackgroundAndMask(icon->foreground_image_skia()); } else { iv->uncompressed = icon->image_skia(); } @@ -1364,10 +1364,6 @@ IconEffects ArcApps::GetIconEffects(const std::string& app_id, const ArcAppListPrefs::AppInfo& app_info) { IconEffects icon_effects = IconEffects::kNone; - if (base::FeatureList::IsEnabled(features::kAppServiceAdaptiveIcon)) { - icon_effects = - static_cast<IconEffects>(icon_effects | IconEffects::kCrOsStandardMask); - } if (app_info.suspended) { icon_effects = static_cast<IconEffects>(icon_effects | IconEffects::kBlocked);
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index f20e00d..3f9e4e71 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -1902,6 +1902,8 @@ "platform_keys/key_permissions/key_permissions.h", "platform_keys/key_permissions/key_permissions_policy_handler.cc", "platform_keys/key_permissions/key_permissions_policy_handler.h", + "platform_keys/platform_keys.cc", + "platform_keys/platform_keys.h", "platform_keys/platform_keys_service.cc", "platform_keys/platform_keys_service.h", "platform_keys/platform_keys_service_factory.cc",
diff --git a/chrome/browser/chromeos/arc/enterprise/cert_store/arc_cert_store_bridge_browsertest.cc b/chrome/browser/chromeos/arc/enterprise/cert_store/arc_cert_store_bridge_browsertest.cc index 2f7742c7..be1e008 100644 --- a/chrome/browser/chromeos/arc/enterprise/cert_store/arc_cert_store_bridge_browsertest.cc +++ b/chrome/browser/chromeos/arc/enterprise/cert_store/arc_cert_store_bridge_browsertest.cc
@@ -16,7 +16,7 @@ #include "chrome/browser/chromeos/arc/session/arc_service_launcher.h" #include "chrome/browser/chromeos/login/test/local_policy_test_server_mixin.h" #include "chrome/browser/chromeos/platform_keys/key_permissions/key_permissions.h" -#include "chrome/browser/chromeos/platform_keys/platform_keys_service.h" +#include "chrome/browser/chromeos/platform_keys/platform_keys.h" #include "chrome/browser/chromeos/policy/user_policy_test_helper.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/net/nss_context.h" @@ -269,8 +269,7 @@ client_cert1_->derPublicKey.data, client_cert1_->derPublicKey.data + client_cert1_->derPublicKey.len); permissions_for_ext->RegisterKeyForCorporateUsage( - client_cert1_spki, - {chromeos::platform_keys::KeyPermissions::KeyLocation::kUserSlot}); + client_cert1_spki, {chromeos::platform_keys::TokenId::kUser}); done_callback.Run(); }
diff --git a/chrome/browser/chromeos/arc/enterprise/cert_store/arc_smart_card_manager_bridge.cc b/chrome/browser/chromeos/arc/enterprise/cert_store/arc_smart_card_manager_bridge.cc index 6a65553..e1a6bfd 100644 --- a/chrome/browser/chromeos/arc/enterprise/cert_store/arc_smart_card_manager_bridge.cc +++ b/chrome/browser/chromeos/arc/enterprise/cert_store/arc_smart_card_manager_bridge.cc
@@ -15,7 +15,7 @@ #include "chrome/browser/chromeos/arc/policy/arc_policy_bridge.h" #include "chrome/browser/chromeos/certificate_provider/certificate_provider_service.h" #include "chrome/browser/chromeos/certificate_provider/certificate_provider_service_factory.h" -#include "chrome/browser/chromeos/platform_keys/platform_keys_service.h" +#include "chrome/browser/chromeos/platform_keys/platform_keys.h" #include "chrome/common/net/x509_certificate_model_nss.h" #include "components/arc/arc_browser_context_keyed_service_factory_base.h" #include "components/policy/core/common/policy_map.h"
diff --git a/chrome/browser/chromeos/cert_provisioning/cert_provisioning_common.cc b/chrome/browser/chromeos/cert_provisioning/cert_provisioning_common.cc index 9a21d841..46b8242f 100644 --- a/chrome/browser/chromeos/cert_provisioning/cert_provisioning_common.cc +++ b/chrome/browser/chromeos/cert_provisioning/cert_provisioning_common.cc
@@ -8,6 +8,7 @@ #include "base/notreached.h" #include "base/optional.h" #include "base/time/time.h" +#include "chrome/browser/chromeos/platform_keys/platform_keys.h" #include "chrome/browser/chromeos/platform_keys/platform_keys_service.h" #include "chrome/browser/chromeos/platform_keys/platform_keys_service_factory.h" #include "chrome/browser/chromeos/profiles/profile_helper.h"
diff --git a/chrome/browser/chromeos/cert_provisioning/cert_provisioning_common.h b/chrome/browser/chromeos/cert_provisioning/cert_provisioning_common.h index b497dc1..4ce13af 100644 --- a/chrome/browser/chromeos/cert_provisioning/cert_provisioning_common.h +++ b/chrome/browser/chromeos/cert_provisioning/cert_provisioning_common.h
@@ -12,6 +12,7 @@ #include "base/optional.h" #include "base/time/time.h" #include "base/values.h" +#include "chrome/browser/chromeos/platform_keys/platform_keys.h" #include "chrome/browser/chromeos/platform_keys/platform_keys_service.h" #include "chromeos/dbus/constants/attestation_constants.h" #include "components/policy/proto/device_management_backend.pb.h"
diff --git a/chrome/browser/chromeos/cert_provisioning/cert_provisioning_platform_keys_helpers.cc b/chrome/browser/chromeos/cert_provisioning/cert_provisioning_platform_keys_helpers.cc index c4e80bd..4d49c0a8 100644 --- a/chrome/browser/chromeos/cert_provisioning/cert_provisioning_platform_keys_helpers.cc +++ b/chrome/browser/chromeos/cert_provisioning/cert_provisioning_platform_keys_helpers.cc
@@ -12,6 +12,7 @@ #include "base/optional.h" #include "base/stl_util.h" #include "chrome/browser/chromeos/cert_provisioning/cert_provisioning_common.h" +#include "chrome/browser/chromeos/platform_keys/platform_keys.h" #include "chrome/browser/chromeos/platform_keys/platform_keys_service.h" namespace chromeos {
diff --git a/chrome/browser/chromeos/cert_provisioning/cert_provisioning_platform_keys_helpers_unittest.cc b/chrome/browser/chromeos/cert_provisioning/cert_provisioning_platform_keys_helpers_unittest.cc index bb0752b3..e66d270 100644 --- a/chrome/browser/chromeos/cert_provisioning/cert_provisioning_platform_keys_helpers_unittest.cc +++ b/chrome/browser/chromeos/cert_provisioning/cert_provisioning_platform_keys_helpers_unittest.cc
@@ -16,6 +16,7 @@ #include "chrome/browser/chromeos/cert_provisioning/cert_provisioning_common.h" #include "chrome/browser/chromeos/cert_provisioning/cert_provisioning_test_helpers.h" #include "chrome/browser/chromeos/platform_keys/mock_platform_keys_service.h" +#include "chrome/browser/chromeos/platform_keys/platform_keys.h" #include "chrome/browser/chromeos/platform_keys/platform_keys_service.h" #include "chrome/browser/chromeos/platform_keys/platform_keys_service_factory.h" #include "content/public/test/browser_task_environment.h"
diff --git a/chrome/browser/chromeos/cert_provisioning/cert_provisioning_scheduler.cc b/chrome/browser/chromeos/cert_provisioning/cert_provisioning_scheduler.cc index 3b3ab8f..1a4b08b 100644 --- a/chrome/browser/chromeos/cert_provisioning/cert_provisioning_scheduler.cc +++ b/chrome/browser/chromeos/cert_provisioning/cert_provisioning_scheduler.cc
@@ -22,6 +22,7 @@ #include "chrome/browser/chromeos/cert_provisioning/cert_provisioning_common.h" #include "chrome/browser/chromeos/cert_provisioning/cert_provisioning_metrics.h" #include "chrome/browser/chromeos/cert_provisioning/cert_provisioning_worker.h" +#include "chrome/browser/chromeos/platform_keys/platform_keys.h" #include "chrome/browser/chromeos/platform_keys/platform_keys_service.h" #include "chrome/browser/chromeos/platform_keys/platform_keys_service_factory.h" #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
diff --git a/chrome/browser/chromeos/cert_provisioning/cert_provisioning_scheduler.h b/chrome/browser/chromeos/cert_provisioning/cert_provisioning_scheduler.h index 5d0cd77..cf0d4af0 100644 --- a/chrome/browser/chromeos/cert_provisioning/cert_provisioning_scheduler.h +++ b/chrome/browser/chromeos/cert_provisioning/cert_provisioning_scheduler.h
@@ -16,6 +16,7 @@ #include "chrome/browser/chromeos/cert_provisioning/cert_provisioning_common.h" #include "chrome/browser/chromeos/cert_provisioning/cert_provisioning_invalidator.h" #include "chrome/browser/chromeos/cert_provisioning/cert_provisioning_platform_keys_helpers.h" +#include "chrome/browser/chromeos/platform_keys/platform_keys.h" #include "chrome/browser/chromeos/platform_keys/platform_keys_service.h" #include "chromeos/network/network_state_handler_observer.h" #include "components/prefs/pref_change_registrar.h"
diff --git a/chrome/browser/chromeos/cert_provisioning/cert_provisioning_scheduler_unittest.cc b/chrome/browser/chromeos/cert_provisioning/cert_provisioning_scheduler_unittest.cc index ee82f0d..2e0150d 100644 --- a/chrome/browser/chromeos/cert_provisioning/cert_provisioning_scheduler_unittest.cc +++ b/chrome/browser/chromeos/cert_provisioning/cert_provisioning_scheduler_unittest.cc
@@ -13,6 +13,7 @@ #include "chrome/browser/chromeos/cert_provisioning/cert_provisioning_worker.h" #include "chrome/browser/chromeos/cert_provisioning/mock_cert_provisioning_worker.h" #include "chrome/browser/chromeos/platform_keys/mock_platform_keys_service.h" +#include "chrome/browser/chromeos/platform_keys/platform_keys.h" #include "chrome/browser/chromeos/platform_keys/platform_keys_service.h" #include "chrome/common/pref_names.h" #include "chromeos/network/network_state_test_helper.h"
diff --git a/chrome/browser/chromeos/cert_provisioning/cert_provisioning_test_helpers.h b/chrome/browser/chromeos/cert_provisioning/cert_provisioning_test_helpers.h index 5050fb181..52e63c64 100644 --- a/chrome/browser/chromeos/cert_provisioning/cert_provisioning_test_helpers.h +++ b/chrome/browser/chromeos/cert_provisioning/cert_provisioning_test_helpers.h
@@ -9,7 +9,7 @@ #include "chrome/browser/chromeos/cert_provisioning/cert_provisioning_common.h" #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h" #include "chrome/browser/chromeos/platform_keys/mock_platform_keys_service.h" -#include "chrome/browser/chromeos/platform_keys/platform_keys_service.h" +#include "chrome/browser/chromeos/platform_keys/platform_keys.h" #include "chrome/test/base/testing_profile_manager.h" #include "chromeos/dbus/cryptohome/fake_cryptohome_client.h" #include "testing/gmock/include/gmock/gmock.h"
diff --git a/chrome/browser/chromeos/cert_provisioning/cert_provisioning_worker.cc b/chrome/browser/chromeos/cert_provisioning/cert_provisioning_worker.cc index ccd7a2a..aa7d1a6 100644 --- a/chrome/browser/chromeos/cert_provisioning/cert_provisioning_worker.cc +++ b/chrome/browser/chromeos/cert_provisioning/cert_provisioning_worker.cc
@@ -15,6 +15,7 @@ #include "chrome/browser/chromeos/cert_provisioning/cert_provisioning_invalidator.h" #include "chrome/browser/chromeos/cert_provisioning/cert_provisioning_metrics.h" #include "chrome/browser/chromeos/cert_provisioning/cert_provisioning_serializer.h" +#include "chrome/browser/chromeos/platform_keys/platform_keys.h" #include "chrome/browser/chromeos/platform_keys/platform_keys_service.h" #include "chrome/browser/chromeos/platform_keys/platform_keys_service_factory.h" #include "chrome/browser/profiles/profile.h"
diff --git a/chrome/browser/chromeos/cert_provisioning/cert_provisioning_worker.h b/chrome/browser/chromeos/cert_provisioning/cert_provisioning_worker.h index 103b30a..556a7bb 100644 --- a/chrome/browser/chromeos/cert_provisioning/cert_provisioning_worker.h +++ b/chrome/browser/chromeos/cert_provisioning/cert_provisioning_worker.h
@@ -12,6 +12,7 @@ #include "base/time/time.h" #include "chrome/browser/chromeos/attestation/tpm_challenge_key_subtle.h" #include "chrome/browser/chromeos/cert_provisioning/cert_provisioning_common.h" +#include "chrome/browser/chromeos/platform_keys/platform_keys.h" #include "chrome/browser/chromeos/platform_keys/platform_keys_service.h" #include "components/policy/core/common/cloud/cloud_policy_constants.h" #include "net/base/backoff_entry.h"
diff --git a/chrome/browser/chromeos/cert_provisioning/cert_provisioning_worker_unittest.cc b/chrome/browser/chromeos/cert_provisioning/cert_provisioning_worker_unittest.cc index c468917..4a52666 100644 --- a/chrome/browser/chromeos/cert_provisioning/cert_provisioning_worker_unittest.cc +++ b/chrome/browser/chromeos/cert_provisioning/cert_provisioning_worker_unittest.cc
@@ -20,6 +20,7 @@ #include "chrome/browser/chromeos/cert_provisioning/cert_provisioning_test_helpers.h" #include "chrome/browser/chromeos/cert_provisioning/mock_cert_provisioning_invalidator.h" #include "chrome/browser/chromeos/platform_keys/mock_platform_keys_service.h" +#include "chrome/browser/chromeos/platform_keys/platform_keys.h" #include "chrome/browser/chromeos/platform_keys/platform_keys_service.h" #include "chrome/browser/chromeos/platform_keys/platform_keys_service_factory.h" #include "components/policy/core/common/cloud/mock_cloud_policy_client.h"
diff --git a/chrome/browser/chromeos/login/error_screen_browsertest.cc b/chrome/browser/chromeos/login/error_screen_browsertest.cc index d75e945..5bd96de 100644 --- a/chrome/browser/chromeos/login/error_screen_browsertest.cc +++ b/chrome/browser/chromeos/login/error_screen_browsertest.cc
@@ -333,7 +333,8 @@ }; // Verify that certificate manager dialog opens. -IN_PROC_BROWSER_TEST_F(KioskErrorScreenTest, OpenCertificateConfig) { +// Disabled for being flaky. See crbug.com/1116058. +IN_PROC_BROWSER_TEST_F(KioskErrorScreenTest, DISABLED_OpenCertificateConfig) { apps_loaded_waiter()->Wait(); EXPECT_TRUE(ash::LoginScreenTestApi::LaunchApp(kTestKioskAppId));
diff --git a/chrome/browser/chromeos/login/kiosk_browsertest.cc b/chrome/browser/chromeos/login/kiosk_browsertest.cc index 2240b88..8ee63d42 100644 --- a/chrome/browser/chromeos/login/kiosk_browsertest.cc +++ b/chrome/browser/chromeos/login/kiosk_browsertest.cc
@@ -1035,13 +1035,12 @@ WaitForAppLaunchSuccess(); } -// TODO(https://crbug.com/964333): Flakily seg faults. -IN_PROC_BROWSER_TEST_F(KioskTest, DISABLED_LaunchAppUserCancel) { - // Make fake_cws_ return empty update response. - set_test_app_version(""); - OobeScreenWaiter splash_waiter(AppLaunchSplashScreenView::kScreenId); +IN_PROC_BROWSER_TEST_F(KioskTest, LaunchAppUserCancel) { StartAppLaunchFromLoginScreen( - NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_OFFLINE); + NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE); + OobeScreenWaiter splash_waiter(AppLaunchSplashScreenView::kScreenId); + // Do not let the app be run to avoid race condition. + BlockAppLaunch(true); splash_waiter.Wait(); settings_helper_.SetBoolean(
diff --git a/chrome/browser/chromeos/login/screens/mock_update_screen.h b/chrome/browser/chromeos/login/screens/mock_update_screen.h index 2f9aa13f..d0bc772 100644 --- a/chrome/browser/chromeos/login/screens/mock_update_screen.h +++ b/chrome/browser/chromeos/login/screens/mock_update_screen.h
@@ -41,6 +41,7 @@ MOCK_METHOD(void, SetShowEstimatedTimeLeft, (bool value)); MOCK_METHOD(void, SetUpdateCompleted, (bool value)); MOCK_METHOD(void, SetShowCurtain, (bool value)); + MOCK_METHOD(void, SetManualRebootNeeded, (bool value)); MOCK_METHOD(void, SetProgressMessage, (const base::string16& value)); MOCK_METHOD(void, SetProgress, (int value)); MOCK_METHOD(void, SetRequiresPermissionForCellular, (bool value));
diff --git a/chrome/browser/chromeos/login/screens/update_screen.cc b/chrome/browser/chromeos/login/screens/update_screen.cc index b27e1d5..0e7ecba 100644 --- a/chrome/browser/chromeos/login/screens/update_screen.cc +++ b/chrome/browser/chromeos/login/screens/update_screen.cc
@@ -36,6 +36,10 @@ const char kUpdateDeadlineFile[] = "/tmp/update-check-response-deadline"; +// Time in seconds after which we initiate reboot. +constexpr const base::TimeDelta kWaitBeforeRebootTime = + base::TimeDelta::FromSeconds(2); + // Delay before showing error message if captive portal is detected. // We wait for this delay to let captive portal to perform redirect and show // its login page before error message appears. @@ -108,6 +112,7 @@ histogram_helper_( std::make_unique<ErrorScreensHistogramHelper>("Update")), version_updater_(std::make_unique<VersionUpdater>(this)), + wait_before_reboot_time_(kWaitBeforeRebootTime), tick_clock_(base::DefaultTickClock::GetInstance()) { if (chromeos::features::IsBetterUpdateEnabled()) PowerManagerClient::Get()->AddObserver(this); @@ -216,8 +221,13 @@ void UpdateScreen::OnWaitForRebootTimeElapsed() { LOG(ERROR) << "Unable to reboot - asking user for a manual reboot."; MakeSureScreenIsShown(); - if (view_) + if (!view_) + return; + if (chromeos::features::IsBetterUpdateEnabled()) { + view_->SetManualRebootNeeded(true); + } else { view_->SetUpdateCompleted(true); + } } void UpdateScreen::PrepareForUpdateCheck() { @@ -344,7 +354,14 @@ finalize_time_); RecordDownloadingTime(tick_clock_->NowTicks() - start_update_downloading_); - version_updater_->RebootAfterUpdate(); + if (chromeos::features::IsBetterUpdateEnabled()) { + ShowRebootInProgress(); + wait_reboot_timer_.Start(FROM_HERE, wait_before_reboot_time_, + version_updater_.get(), + &VersionUpdater::RebootAfterUpdate); + } else { + version_updater_->RebootAfterUpdate(); + } } else { hide_progress_on_exit_ = true; ExitUpdate(Result::UPDATE_NOT_REQUIRED); @@ -387,6 +404,12 @@ UpdateBatteryWarningVisibility(); } +void UpdateScreen::ShowRebootInProgress() { + MakeSureScreenIsShown(); + if (view_) + view_->SetUpdateCompleted(true); +} + void UpdateScreen::UpdateBatteryWarningVisibility() { if (!view_) return;
diff --git a/chrome/browser/chromeos/login/screens/update_screen.h b/chrome/browser/chromeos/login/screens/update_screen.h index eb9973d..b7d5d2f 100644 --- a/chrome/browser/chromeos/login/screens/update_screen.h +++ b/chrome/browser/chromeos/login/screens/update_screen.h
@@ -107,6 +107,15 @@ tick_clock_ = tick_clock; } + void set_wait_before_reboot_time_for_testing( + base::TimeDelta wait_before_reboot_time) { + wait_before_reboot_time_ = wait_before_reboot_time; + } + + base::OneShotTimer* GetWaitRebootTimerForTesting() { + return &wait_reboot_timer_; + } + protected: // BaseScreen: bool MaybeSkip(WizardContext* context) override; @@ -144,6 +153,9 @@ // stages. Called when power or update status changes. void UpdateBatteryWarningVisibility(); + // Show reboot waiting screen. + void ShowRebootInProgress(); + UpdateView* view_; ErrorScreen* error_screen_; ScreenExitCallback exit_callback_; @@ -187,6 +199,13 @@ // instead. base::OneShotTimer error_message_timer_; + // Timer for the interval to wait for the reboot progress screen to be shown + // for at least wait_before_reboot_time_ before reboot call. + base::OneShotTimer wait_reboot_timer_; + + // Time in seconds after which we initiate reboot. + base::TimeDelta wait_before_reboot_time_; + const base::TickClock* tick_clock_; base::TimeTicks start_update_downloading_;
diff --git a/chrome/browser/chromeos/login/screens/update_screen_browsertest.cc b/chrome/browser/chromeos/login/screens/update_screen_browsertest.cc index 1a3704b..b61da657 100644 --- a/chrome/browser/chromeos/login/screens/update_screen_browsertest.cc +++ b/chrome/browser/chromeos/login/screens/update_screen_browsertest.cc
@@ -12,6 +12,7 @@ #include "base/run_loop.h" #include "base/strings/string_util.h" #include "base/test/scoped_feature_list.h" +#include "base/test/scoped_mock_time_message_loop_task_runner.h" #include "base/test/simple_test_tick_clock.h" #include "base/time/time.h" #include "chrome/browser/chromeos/login/login_wizard.h" @@ -66,6 +67,11 @@ "battery-warning"}; const test::UIPath kErrorMessage = {"error-message"}; +// Paths for better update screen https://crbug.com/1101317 +const test::UIPath kRestartingDialog = {"oobe-update", "restarting-dialog"}; +const test::UIPath kBetterUpdateCompletedDialog = { + "oobe-update", "better-update-complete-dialog"}; + // UMA names for better test reading. const char kTimeCheck[] = "OOBE.UpdateScreen.StageTime.Check"; const char kTimeDownload[] = "OOBE.UpdateScreen.StageTime.Download"; @@ -86,6 +92,8 @@ base::TimeDelta::FromSeconds(10); constexpr base::TimeDelta kTimeAdvanceSeconds60 = base::TimeDelta::FromSeconds(60); +constexpr base::TimeDelta kTimeDefaultWaiting = + base::TimeDelta::FromSeconds(10); std::string GetDownloadingString(int status_resource_id) { return l10n_util::GetStringFUTF8( @@ -181,6 +189,17 @@ } ~BetterUpdateScreenTest() override = default; + void SetTickClockAndDefaultDelaysForTesting( + const base::TickClock* tick_clock) { + version_updater_->set_tick_clock_for_testing(tick_clock); + update_screen_->set_tick_clock_for_testing(tick_clock); + // Set time for waiting in the test to not update constants manually, if + // they change. + version_updater_->set_wait_for_reboot_time_for_testing(kTimeDefaultWaiting); + update_screen_->set_wait_before_reboot_time_for_testing( + kTimeDefaultWaiting); + } + protected: chromeos::FakePowerManagerClient* power_manager_client() { return chromeos::FakePowerManagerClient::Get(); @@ -778,6 +797,9 @@ IN_PROC_BROWSER_TEST_F(BetterUpdateScreenTest, TestBatteryWarningDuringUpdateStages) { + base::ScopedMockTimeMessageLoopTaskRunner mocked_task_runner; + SetTickClockAndDefaultDelaysForTesting( + mocked_task_runner->GetMockTickClock()); update_screen_->set_ignore_update_deadlines_for_testing(true); ShowUpdateScreen(); EXPECT_TRUE(power_manager_client()->HasObserver(update_screen_)); @@ -832,6 +854,10 @@ update_engine_client()->set_default_status(status); update_engine_client()->NotifyObserversThatStatusChanged(status); + // Show waiting for reboot screen for several seconds. + ASSERT_TRUE(update_screen_->GetWaitRebootTimerForTesting()->IsRunning()); + mocked_task_runner->FastForwardBy(kTimeDefaultWaiting); + // UpdateStatusChanged(status) calls RebootAfterUpdate(). EXPECT_EQ(update_engine_client()->reboot_after_update_call_count(), 1); test::OobeJS().ExpectVisiblePath(kLowBatteryWarningMessage); @@ -884,4 +910,42 @@ test::OobeJS().ExpectHiddenPath(kLowBatteryWarningMessage); } +IN_PROC_BROWSER_TEST_F(BetterUpdateScreenTest, + TestUpdateCompletedRebootNeeded) { + base::ScopedMockTimeMessageLoopTaskRunner mocked_task_runner; + SetTickClockAndDefaultDelaysForTesting( + mocked_task_runner->GetMockTickClock()); + update_screen_->set_ignore_update_deadlines_for_testing(true); + ShowUpdateScreen(); + + update_engine::StatusResult status; + status.set_current_operation(update_engine::Operation::UPDATED_NEED_REBOOT); + status.set_new_version("latest and greatest"); + status.set_new_size(1'000'000'000); + update_engine_client()->set_default_status(status); + update_engine_client()->NotifyObserversThatStatusChanged(status); + + test::OobeJS().CreateVisibilityWaiter(true, kRestartingDialog)->Wait(); + test::OobeJS().ExpectHiddenPath(kCheckingForUpdatesDialog); + test::OobeJS().ExpectHiddenPath(kCellularPermissionDialog); + test::OobeJS().ExpectHiddenPath(kUpdatingDialog); + test::OobeJS().ExpectHiddenPath(kBetterUpdateCompletedDialog); + + // Make sure that after the screen is shown waiting timer starts. + mocked_task_runner->RunUntilIdle(); + // Show waiting for reboot screen for several seconds. + ASSERT_TRUE(update_screen_->GetWaitRebootTimerForTesting()->IsRunning()); + mocked_task_runner->FastForwardBy(kTimeDefaultWaiting); + + // UpdateStatusChanged(status) calls RebootAfterUpdate(). + ASSERT_EQ(update_engine_client()->reboot_after_update_call_count(), 1); + + // Simulate the situation where reboot does not happen in time. + ASSERT_TRUE(version_updater_->GetRebootTimerForTesting()->IsRunning()); + mocked_task_runner->FastForwardBy(kTimeDefaultWaiting); + + test::OobeJS().ExpectHiddenPath(kRestartingDialog); + test::OobeJS().ExpectVisiblePath(kBetterUpdateCompletedDialog); +} + } // namespace chromeos
diff --git a/chrome/browser/chromeos/phonehub/OWNERS b/chrome/browser/chromeos/phonehub/OWNERS new file mode 100644 index 0000000..f603cffa --- /dev/null +++ b/chrome/browser/chromeos/phonehub/OWNERS
@@ -0,0 +1,3 @@ +file://chromeos/components/phonehub/OWNERS + +# COMPONENT: OS>Systems>Multidevice>PhoneHub
diff --git a/chrome/browser/chromeos/platform_keys/extension_platform_keys_service.cc b/chrome/browser/chromeos/platform_keys/extension_platform_keys_service.cc index ee9037d..c578eef 100644 --- a/chrome/browser/chromeos/platform_keys/extension_platform_keys_service.cc +++ b/chrome/browser/chromeos/platform_keys/extension_platform_keys_service.cc
@@ -16,6 +16,7 @@ #include "base/optional.h" #include "base/stl_util.h" #include "base/values.h" +#include "chrome/browser/chromeos/platform_keys/platform_keys.h" #include "chrome/browser/chromeos/platform_keys/platform_keys_service.h" #include "chrome/browser/chromeos/platform_keys/platform_keys_service_factory.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" @@ -53,26 +54,6 @@ } #endif // defined(OS_CHROMEOS) -// Converts |token_ids| (string-based token identifiers used in the -// platformKeys API) to a vector of KeyPermissions::KeyLocation. -std::vector<platform_keys::KeyPermissions::KeyLocation> TokenIdsToKeyLocations( - const std::vector<platform_keys::TokenId>& token_ids) { - std::vector<platform_keys::KeyPermissions::KeyLocation> key_locations; - for (const auto& token_id : token_ids) { - switch (token_id) { - case platform_keys::TokenId::kUser: - key_locations.push_back( - platform_keys::KeyPermissions::KeyLocation::kUserSlot); - break; - case platform_keys::TokenId::kSystem: - key_locations.push_back( - platform_keys::KeyPermissions::KeyLocation::kSystemSlot); - break; - } - } - return key_locations; -} - } // namespace class ExtensionPlatformKeysService::Task { @@ -172,8 +153,7 @@ } void UpdatePermissionsAndCallBack() { - std::vector<platform_keys::KeyPermissions::KeyLocation> key_locations = - TokenIdsToKeyLocations({token_id_}); + std::vector<platform_keys::TokenId> key_locations = {token_id_}; extension_permissions_->RegisterKeyForCorporateUsage(public_key_spki_der_, key_locations); callback_.Run(public_key_spki_der_, platform_keys::Status::kSuccess); @@ -368,7 +348,7 @@ return; } - key_locations_ = TokenIdsToKeyLocations(token_ids); + key_locations_ = token_ids; DoStep(); } @@ -424,7 +404,7 @@ std::unique_ptr<platform_keys::KeyPermissions::PermissionsForExtension> extension_permissions_; platform_keys::KeyPermissions* const key_permissions_; - std::vector<platform_keys::KeyPermissions::KeyLocation> key_locations_; + std::vector<platform_keys::TokenId> key_locations_; ExtensionPlatformKeysService* const service_; base::WeakPtrFactory<SignTask> weak_factory_{this}; @@ -615,17 +595,14 @@ const std::string public_key_spki_der( platform_keys::GetSubjectPublicKeyInfo(certificate)); - std::vector<platform_keys::KeyPermissions::KeyLocation> key_locations = - TokenIdsToKeyLocations(token_ids); - // Use this key if the user can use it for signing or can grant permission // for it. if (key_permissions_->CanUserGrantPermissionFor(public_key_spki_der, - key_locations) || + token_ids) || extension_permissions_->CanUseKeyForSigning(public_key_spki_der, - key_locations)) { + token_ids)) { matches_.push_back(certificate); - key_locations_for_matches_[public_key_spki_der] = key_locations; + key_locations_for_matches_[public_key_spki_der] = token_ids; } DoStep(); } @@ -729,10 +706,9 @@ std::deque<scoped_refptr<net::X509Certificate>> matches_pending_key_locations_; net::CertificateList matches_; - // Mapping of DER-encoded Subject Public Key Info to the KeyLocations - // determined for the corresponding private key. - base::flat_map<std::string, - std::vector<platform_keys::KeyPermissions::KeyLocation>> + // Mapping of DER-encoded Subject Public Key Info to the TokenIds determined + // for the corresponding private key. + base::flat_map<std::string, std::vector<platform_keys::TokenId>> key_locations_for_matches_; scoped_refptr<net::X509Certificate> selected_cert_; platform_keys::ClientCertificateRequest request_;
diff --git a/chrome/browser/chromeos/platform_keys/extension_platform_keys_service.h b/chrome/browser/chromeos/platform_keys/extension_platform_keys_service.h index 47f7be1..d4fd2a29 100644 --- a/chrome/browser/chromeos/platform_keys/extension_platform_keys_service.h +++ b/chrome/browser/chromeos/platform_keys/extension_platform_keys_service.h
@@ -14,6 +14,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "chrome/browser/chromeos/platform_keys/key_permissions/key_permissions.h" +#include "chrome/browser/chromeos/platform_keys/platform_keys.h" #include "chrome/browser/chromeos/platform_keys/platform_keys_service.h" #include "components/keyed_service/core/keyed_service.h"
diff --git a/chrome/browser/chromeos/platform_keys/key_permissions/key_permissions.cc b/chrome/browser/chromeos/platform_keys/key_permissions/key_permissions.cc index 705b6a4..523727f 100644 --- a/chrome/browser/chromeos/platform_keys/key_permissions/key_permissions.cc +++ b/chrome/browser/chromeos/platform_keys/key_permissions/key_permissions.cc
@@ -12,6 +12,7 @@ #include "base/logging.h" #include "base/stl_util.h" #include "base/values.h" +#include "chrome/browser/chromeos/platform_keys/platform_keys.h" #include "chrome/common/pref_names.h" #include "components/policy/core/common/policy_map.h" #include "components/policy/core/common/policy_namespace.h" @@ -146,9 +147,8 @@ return allow_corporate_key_usage; } -bool IsKeyOnUserSlot( - const std::vector<KeyPermissions::KeyLocation>& key_locations) { - return base::Contains(key_locations, KeyPermissions::KeyLocation::kUserSlot); +bool IsKeyOnUserSlot(const std::vector<TokenId>& key_locations) { + return base::Contains(key_locations, TokenId::kUser); } } // namespace @@ -194,7 +194,7 @@ bool KeyPermissions::PermissionsForExtension::CanUseKeyForSigning( const std::string& public_key_spki_der, - const std::vector<KeyLocation>& key_locations) { + const std::vector<TokenId>& key_locations) { if (key_locations.empty()) return false; @@ -227,7 +227,7 @@ void KeyPermissions::PermissionsForExtension::SetKeyUsedForSigning( const std::string& public_key_spki_der, - const std::vector<KeyLocation>& key_locations) { + const std::vector<TokenId>& key_locations) { if (key_locations.empty()) return; @@ -248,7 +248,7 @@ void KeyPermissions::PermissionsForExtension::RegisterKeyForCorporateUsage( const std::string& public_key_spki_der, - const std::vector<KeyLocation>& key_locations) { + const std::vector<TokenId>& key_locations) { if (key_locations.empty()) { NOTREACHED(); return; @@ -287,7 +287,7 @@ void KeyPermissions::PermissionsForExtension::SetUserGrantedPermission( const std::string& public_key_spki_der, - const std::vector<KeyLocation>& key_locations) { + const std::vector<TokenId>& key_locations) { if (!key_permissions_->CanUserGrantPermissionFor(public_key_spki_der, key_locations)) { LOG(WARNING) << "Tried to grant permission for a key although prohibited " @@ -422,7 +422,7 @@ bool KeyPermissions::CanUserGrantPermissionFor( const std::string& public_key_spki_der, - const std::vector<KeyLocation>& key_locations) const { + const std::vector<TokenId>& key_locations) const { if (key_locations.empty()) return false; @@ -480,14 +480,14 @@ bool KeyPermissions::IsCorporateKey( const std::string& public_key_spki_der_b64, - const std::vector<KeyPermissions::KeyLocation>& key_locations) const { - for (const KeyLocation key_location : key_locations) { + const std::vector<TokenId>& key_locations) const { + for (const auto key_location : key_locations) { switch (key_location) { - case KeyLocation::kUserSlot: + case TokenId::kUser: if (IsCorporateKeyForProfile(public_key_spki_der_b64, profile_prefs_)) return true; break; - case KeyLocation::kSystemSlot: + case TokenId::kSystem: return true; default: NOTREACHED();
diff --git a/chrome/browser/chromeos/platform_keys/key_permissions/key_permissions.h b/chrome/browser/chromeos/platform_keys/key_permissions/key_permissions.h index e2c3874f..148a8601 100644 --- a/chrome/browser/chromeos/platform_keys/key_permissions/key_permissions.h +++ b/chrome/browser/chromeos/platform_keys/key_permissions/key_permissions.h
@@ -12,6 +12,7 @@ #include "base/callback_forward.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" +#include "chrome/browser/chromeos/platform_keys/platform_keys.h" class PrefService; @@ -73,21 +74,6 @@ // permitted by the administrator. class KeyPermissions { public: - // Specifies where a private key is stored. - enum class KeyLocation { - // The key resides on the user's private slot. This is user-specific - // hardware-backed storage. Therefore the key is only available while the - // corresponding user is signed in. - kUserSlot, - - // The key resides on the system slot. This is system-wide hardware-backed - // storage. The key is potentially accessible throughout all types of - // sessions, however, additional constraints may be imposed by the API logic - // - for instance, depending on the session type (e.g. affiliated user - // session or unaffiliated user session). - kSystemSlot - }; - // Allows querying and modifying permissions and registering keys for a // specific extension. class PermissionsForExtension { @@ -108,8 +94,9 @@ // used for signing by the extension with id |extension_id_|. // |key_locations| must describe locations available to the user the private // key is stored on. - bool CanUseKeyForSigning(const std::string& public_key_spki_der, - const std::vector<KeyLocation>& key_locations); + bool CanUseKeyForSigning( + const std::string& public_key_spki_der, + const std::vector<platform_keys::TokenId>& key_locations); // Registers the private key matching |public_key_spki_der| as being // generated by the extension with id |extension_id| and marks it for @@ -117,7 +104,7 @@ // user the private key is stored on. void RegisterKeyForCorporateUsage( const std::string& public_key_spki_der, - const std::vector<KeyLocation>& key_locations); + const std::vector<platform_keys::TokenId>& key_locations); // Sets the user granted permission that the extension with id // |extension_id| can use the private key matching |public_key_spki_der| for @@ -125,7 +112,7 @@ // the private key is stored on. void SetUserGrantedPermission( const std::string& public_key_spki_der, - const std::vector<KeyLocation>& key_locations); + const std::vector<platform_keys::TokenId>& key_locations); // Must be called when the extension with id |extension_id| used the private // key matching |public_key_spki_der| for signing. |key_locations| must @@ -133,8 +120,9 @@ // Updates the permissions accordingly. E.g. if this extension generated // the key and no other permission was granted then the permission to sign // with this key is removed. - void SetKeyUsedForSigning(const std::string& public_key_spki_der, - const std::vector<KeyLocation>& key_locations); + void SetKeyUsedForSigning( + const std::string& public_key_spki_der, + const std::vector<platform_keys::TokenId>& key_locations); private: struct KeyEntry; @@ -197,7 +185,7 @@ // locations available to the user the private key is stored on. bool CanUserGrantPermissionFor( const std::string& public_key_spki_der, - const std::vector<KeyLocation>& key_locations) const; + const std::vector<platform_keys::TokenId>& key_locations) const; static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); @@ -212,8 +200,9 @@ policy::PolicyService* const profile_policies); private: - bool IsCorporateKey(const std::string& public_key_spki_der_b64, - const std::vector<KeyLocation>& key_locations) const; + bool IsCorporateKey( + const std::string& public_key_spki_der_b64, + const std::vector<platform_keys::TokenId>& key_locations) const; // Creates a PermissionsForExtension object from |extension_id| and |value| // and passes the object to |callback|.
diff --git a/chrome/browser/chromeos/platform_keys/platform_keys.cc b/chrome/browser/chromeos/platform_keys/platform_keys.cc new file mode 100644 index 0000000..7abfcac --- /dev/null +++ b/chrome/browser/chromeos/platform_keys/platform_keys.cc
@@ -0,0 +1,108 @@ +// 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. + +#include "chrome/browser/chromeos/platform_keys/platform_keys.h" + +#include <map> +#include <memory> +#include <string> + +#include "base/callback.h" +#include "base/task/task_traits.h" +#include "base/task/thread_pool.h" +#include "net/base/hash_value.h" +#include "net/base/net_errors.h" +#include "net/cert/x509_certificate.h" + +namespace { + +void IntersectOnWorkerThread(const net::CertificateList& certs1, + const net::CertificateList& certs2, + net::CertificateList* intersection) { + std::map<net::SHA256HashValue, scoped_refptr<net::X509Certificate>> + fingerprints2; + + // Fill the map with fingerprints of certs from |certs2|. + for (const auto& cert2 : certs2) { + fingerprints2[net::X509Certificate::CalculateFingerprint256( + cert2->cert_buffer())] = cert2; + } + + // Compare each cert from |certs1| with the entries of the map. + for (const auto& cert1 : certs1) { + const net::SHA256HashValue fingerprint1 = + net::X509Certificate::CalculateFingerprint256(cert1->cert_buffer()); + const auto it = fingerprints2.find(fingerprint1); + if (it == fingerprints2.end()) + continue; + const auto& cert2 = it->second; + DCHECK(cert1->EqualsExcludingChain(cert2.get())); + intersection->push_back(cert1); + } +} + +} // namespace + +namespace chromeos { +namespace platform_keys { + +std::string StatusToString(Status status) { + switch (status) { + case Status::kSuccess: + return "The operation was successfully executed."; + case Status::kErrorAlgorithmNotSupported: + return "Algorithm not supported."; + case Status::kErrorCertificateNotFound: + return "Certificate could not be found."; + case Status::kErrorInternal: + return "Internal Error."; + case Status::kErrorKeyAttributeRetrievalFailed: + return "Key attribute value retrieval failed."; + case Status::kErrorKeyAttributeSettingFailed: + return "Setting key attribute value failed."; + case Status::kErrorKeyNotAllowedForSigning: + return "This key is not allowed for signing. Either it was used for " + "signing before or it was not correctly generated."; + case Status::kErrorKeyNotFound: + return "Key not found."; + case Status::kErrorShutDown: + return "Delegate shut down."; + case Status::kNetErrorAddUserCertFailed: + return net::ErrorToString(net::ERR_ADD_USER_CERT_FAILED); + case Status::kNetErrorCertificateDateInvalid: + return net::ErrorToString(net::ERR_CERT_DATE_INVALID); + case Status::kNetErrorCertificateInvalid: + return net::ErrorToString(net::ERR_CERT_INVALID); + } +} + +void IntersectCertificates( + const net::CertificateList& certs1, + const net::CertificateList& certs2, + const base::Callback<void(std::unique_ptr<net::CertificateList>)>& + callback) { + std::unique_ptr<net::CertificateList> intersection(new net::CertificateList); + net::CertificateList* const intersection_ptr = intersection.get(); + + // This is triggered by a call to the + // chrome.platformKeys.selectClientCertificates extensions API. Completion + // does not affect browser responsiveness, hence the BEST_EFFORT priority. + base::ThreadPool::PostTaskAndReply( + FROM_HERE, + {base::TaskPriority::BEST_EFFORT, + base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}, + base::BindOnce(&IntersectOnWorkerThread, certs1, certs2, + intersection_ptr), + base::BindOnce(callback, base::Passed(&intersection))); +} + +ClientCertificateRequest::ClientCertificateRequest() = default; + +ClientCertificateRequest::ClientCertificateRequest( + const ClientCertificateRequest& other) = default; + +ClientCertificateRequest::~ClientCertificateRequest() = default; + +} // namespace platform_keys +} // namespace chromeos
diff --git a/chrome/browser/chromeos/platform_keys/platform_keys.h b/chrome/browser/chromeos/platform_keys/platform_keys.h new file mode 100644 index 0000000..2409d4e8 --- /dev/null +++ b/chrome/browser/chromeos/platform_keys/platform_keys.h
@@ -0,0 +1,115 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROMEOS_PLATFORM_KEYS_PLATFORM_KEYS_H_ +#define CHROME_BROWSER_CHROMEOS_PLATFORM_KEYS_PLATFORM_KEYS_H_ + +#include <memory> +#include <string> +#include <vector> + +#include "base/callback.h" +#include "net/cert/x509_certificate.h" + +namespace chromeos { +namespace platform_keys { + +// Supported key types. +enum class KeyType { kRsassaPkcs1V15, kEcdsa }; + +// Supported key attribute types. +enum class KeyAttributeType { kCertificateProvisioningId }; + +// Supported hash algorithms. +enum HashAlgorithm { + HASH_ALGORITHM_NONE, // The value if no hash function is selected. + HASH_ALGORITHM_SHA1, + HASH_ALGORITHM_SHA256, + HASH_ALGORITHM_SHA384, + HASH_ALGORITHM_SHA512 +}; + +// Supported token IDs. +// A token is a store for keys or certs and can provide cryptographic +// operations. +// ChromeOS provides itself a user token and conditionally a system wide token. +enum class TokenId { kUser, kSystem }; + +// The service possible statuses. +// For every platform keys service operation callback, a status is passed +// signaling the success or failure of the operation. +enum class Status { + kSuccess, + kErrorAlgorithmNotSupported, + kErrorCertificateNotFound, + kErrorInternal, + kErrorKeyAttributeRetrievalFailed, + kErrorKeyAttributeSettingFailed, + kErrorKeyNotAllowedForSigning, + kErrorKeyNotFound, + kErrorShutDown, + // kNetError* are for errors occurred during net::* operations. + kNetErrorAddUserCertFailed, + kNetErrorCertificateDateInvalid, + kNetErrorCertificateInvalid, +}; + +// These strings can be used to be passed to extensions as well as for logging +// purposes. +// Note: Do not change already existing status-to-string translations, since +// extensions may hardcode specific messages. +std::string StatusToString(Status status); + +// Returns the DER encoding of the X.509 Subject Public Key Info of the public +// key in |certificate|. +std::string GetSubjectPublicKeyInfo( + const scoped_refptr<net::X509Certificate>& certificate); + +// Intersects the two certificate lists |certs1| and |certs2| and passes the +// intersection to |callback|. The intersction preserves the order of |certs1|. +void IntersectCertificates( + const net::CertificateList& certs1, + const net::CertificateList& certs2, + const base::Callback<void(std::unique_ptr<net::CertificateList>)>& + callback); + +// Obtains information about the public key in |certificate|. +// If |certificate| contains an RSA key, sets |key_size_bits| to the modulus +// length, and |key_type| to type RSA and returns true. +// If |certificate| contains any other key type, or if the public exponent of +// the RSA key in |certificate| is not F4, returns false and does not update any +// of the output parameters. +// All pointer arguments must not be null. +bool GetPublicKey(const scoped_refptr<net::X509Certificate>& certificate, + net::X509Certificate::PublicKeyType* key_type, + size_t* key_size_bits); + +// Obtains information about the public key in |spki|. +// If |spki| is an RSA key, sets |key_size_bits| to the modulus +// length, and |key_type| to type RSA and returns true. +// If |spki| is any other key type, returns false and does not update any +// of the output parameters. +// All pointer arguments must not be null. +bool GetPublicKeyBySpki(const std::string& spki, + net::X509Certificate::PublicKeyType* key_type, + size_t* key_size_bits); + +struct ClientCertificateRequest { + ClientCertificateRequest(); + ClientCertificateRequest(const ClientCertificateRequest& other); + ~ClientCertificateRequest(); + + // The list of the types of certificates requested, sorted in order of the + // server's preference. + std::vector<net::X509Certificate::PublicKeyType> certificate_key_types; + + // List of distinguished names of certificate authorities allowed by the + // server. Each entry must be a DER-encoded X.509 DistinguishedName. + std::vector<std::string> certificate_authorities; +}; + +} // namespace platform_keys +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_PLATFORM_KEYS_PLATFORM_KEYS_H_
diff --git a/chrome/browser/chromeos/platform_keys/platform_keys_service.cc b/chrome/browser/chromeos/platform_keys/platform_keys_service.cc index 6f56822..6d8d650 100644 --- a/chrome/browser/chromeos/platform_keys/platform_keys_service.cc +++ b/chrome/browser/chromeos/platform_keys/platform_keys_service.cc
@@ -13,101 +13,12 @@ #include "base/task/post_task.h" #include "base/task/thread_pool.h" #include "content/public/browser/browser_thread.h" -#include "net/base/hash_value.h" #include "net/base/net_errors.h" #include "net/cert/x509_certificate.h" namespace chromeos { namespace platform_keys { -namespace { - -void IntersectOnWorkerThread(const net::CertificateList& certs1, - const net::CertificateList& certs2, - net::CertificateList* intersection) { - std::map<net::SHA256HashValue, scoped_refptr<net::X509Certificate>> - fingerprints2; - - // Fill the map with fingerprints of certs from |certs2|. - for (const auto& cert2 : certs2) { - fingerprints2[net::X509Certificate::CalculateFingerprint256( - cert2->cert_buffer())] = cert2; - } - - // Compare each cert from |certs1| with the entries of the map. - for (const auto& cert1 : certs1) { - const net::SHA256HashValue fingerprint1 = - net::X509Certificate::CalculateFingerprint256(cert1->cert_buffer()); - const auto it = fingerprints2.find(fingerprint1); - if (it == fingerprints2.end()) - continue; - const auto& cert2 = it->second; - DCHECK(cert1->EqualsExcludingChain(cert2.get())); - intersection->push_back(cert1); - } -} - -} // namespace - -std::string StatusToString(Status status) { - switch (status) { - case Status::kSuccess: - return "The operation was successfully executed."; - case Status::kErrorAlgorithmNotSupported: - return "Algorithm not supported."; - case Status::kErrorCertificateNotFound: - return "Certificate could not be found."; - case Status::kErrorInternal: - return "Internal Error."; - case Status::kErrorKeyAttributeRetrievalFailed: - return "Key attribute value retrieval failed."; - case Status::kErrorKeyAttributeSettingFailed: - return "Setting key attribute value failed."; - case Status::kErrorKeyNotAllowedForSigning: - return "This key is not allowed for signing. Either it was used for " - "signing before or it was not correctly generated."; - case Status::kErrorKeyNotFound: - return "Key not found."; - case Status::kErrorShutDown: - return "Delegate shut down."; - case Status::kNetErrorAddUserCertFailed: - return net::ErrorToString(net::ERR_ADD_USER_CERT_FAILED); - case Status::kNetErrorCertificateDateInvalid: - return net::ErrorToString(net::ERR_CERT_DATE_INVALID); - case Status::kNetErrorCertificateInvalid: - return net::ErrorToString(net::ERR_CERT_INVALID); - } -} - -void IntersectCertificates( - const net::CertificateList& certs1, - const net::CertificateList& certs2, - const base::Callback<void(std::unique_ptr<net::CertificateList>)>& - callback) { - std::unique_ptr<net::CertificateList> intersection(new net::CertificateList); - net::CertificateList* const intersection_ptr = intersection.get(); - - // This is triggered by a call to the - // chrome.platformKeys.selectClientCertificates extensions API. Completion - // does not affect browser responsiveness, hence the BEST_EFFORT priority. - base::ThreadPool::PostTaskAndReply( - FROM_HERE, - {base::TaskPriority::BEST_EFFORT, - base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}, - base::BindOnce(&IntersectOnWorkerThread, certs1, certs2, - intersection_ptr), - base::BindOnce(callback, base::Passed(&intersection))); -} - -// =================== ClientCertificateRequest ================================ - -ClientCertificateRequest::ClientCertificateRequest() = default; - -ClientCertificateRequest::ClientCertificateRequest( - const ClientCertificateRequest& other) = default; - -ClientCertificateRequest::~ClientCertificateRequest() = default; - // =============== PlatformKeysServiceImplDelegate ============================= PlatformKeysServiceImplDelegate::PlatformKeysServiceImplDelegate() = default;
diff --git a/chrome/browser/chromeos/platform_keys/platform_keys_service.h b/chrome/browser/chromeos/platform_keys/platform_keys_service.h index e6237dc0..29b572f 100644 --- a/chrome/browser/chromeos/platform_keys/platform_keys_service.h +++ b/chrome/browser/chromeos/platform_keys/platform_keys_service.h
@@ -17,6 +17,7 @@ #include "base/observer_list.h" #include "base/observer_list_types.h" #include "base/optional.h" +#include "chrome/browser/chromeos/platform_keys/platform_keys.h" #include "components/keyed_service/core/keyed_service.h" #include "net/cert/x509_certificate.h" @@ -28,100 +29,6 @@ namespace chromeos { namespace platform_keys { -// Supported key types. -enum class KeyType { kRsassaPkcs1V15, kEcdsa }; - -// Supported key attribute types. -enum class KeyAttributeType { kCertificateProvisioningId }; - -// Supported hash algorithms. -enum HashAlgorithm { - HASH_ALGORITHM_NONE, // The value if no hash function is selected. - HASH_ALGORITHM_SHA1, - HASH_ALGORITHM_SHA256, - HASH_ALGORITHM_SHA384, - HASH_ALGORITHM_SHA512 -}; - -// Supported token IDs. -// A token is a store for keys or certs and can provide cryptographic -// operations. -// ChromeOS provides itself a user token and conditionally a system wide token. -enum class TokenId { kUser, kSystem }; - -// The service possible statuses. -// For every platform keys service operation callback, a status is passed -// signaling the success or failure of the operation. -enum class Status { - kSuccess, - kErrorAlgorithmNotSupported, - kErrorCertificateNotFound, - kErrorInternal, - kErrorKeyAttributeRetrievalFailed, - kErrorKeyAttributeSettingFailed, - kErrorKeyNotAllowedForSigning, - kErrorKeyNotFound, - kErrorShutDown, - // kNetError* are for errors occurred during net::* operations. - kNetErrorAddUserCertFailed, - kNetErrorCertificateDateInvalid, - kNetErrorCertificateInvalid, -}; - -// These strings can be used to be passed to extensions as well as for logging -// purposes. -// Note: Do not change already existing status-to-string translations, since -// extensions may hardcode specific messages. -std::string StatusToString(Status status); - -// Returns the DER encoding of the X.509 Subject Public Key Info of the public -// key in |certificate|. -std::string GetSubjectPublicKeyInfo( - const scoped_refptr<net::X509Certificate>& certificate); - -// Intersects the two certificate lists |certs1| and |certs2| and passes the -// intersection to |callback|. The intersction preserves the order of |certs1|. -void IntersectCertificates( - const net::CertificateList& certs1, - const net::CertificateList& certs2, - const base::Callback<void(std::unique_ptr<net::CertificateList>)>& - callback); - -// Obtains information about the public key in |certificate|. -// If |certificate| contains an RSA key, sets |key_size_bits| to the modulus -// length, and |key_type| to type RSA and returns true. -// If |certificate| contains any other key type, or if the public exponent of -// the RSA key in |certificate| is not F4, returns false and does not update any -// of the output parameters. -// All pointer arguments must not be null. -bool GetPublicKey(const scoped_refptr<net::X509Certificate>& certificate, - net::X509Certificate::PublicKeyType* key_type, - size_t* key_size_bits); - -// Obtains information about the public key in |spki|. -// If |spki| is an RSA key, sets |key_size_bits| to the modulus -// length, and |key_type| to type RSA and returns true. -// If |spki| is any other key type, returns false and does not update any -// of the output parameters. -// All pointer arguments must not be null. -bool GetPublicKeyBySpki(const std::string& spki, - net::X509Certificate::PublicKeyType* key_type, - size_t* key_size_bits); - -struct ClientCertificateRequest { - ClientCertificateRequest(); - ClientCertificateRequest(const ClientCertificateRequest& other); - ~ClientCertificateRequest(); - - // The list of the types of certificates requested, sorted in order of the - // server's preference. - std::vector<net::X509Certificate::PublicKeyType> certificate_key_types; - - // List of distinguished names of certificate authorities allowed by the - // server. Each entry must be a DER-encoded X.509 DistinguishedName. - std::vector<std::string> certificate_authorities; -}; - using GenerateKeyCallback = base::Callback<void(const std::string& public_key_spki_der, Status status)>;
diff --git a/chrome/browser/chromeos/platform_keys/platform_keys_service_browsertest.cc b/chrome/browser/chromeos/platform_keys/platform_keys_service_browsertest.cc index f5f0c77..fb7b28d2 100644 --- a/chrome/browser/chromeos/platform_keys/platform_keys_service_browsertest.cc +++ b/chrome/browser/chromeos/platform_keys/platform_keys_service_browsertest.cc
@@ -24,6 +24,7 @@ #include "chrome/browser/chromeos/login/test/login_manager_mixin.h" #include "chrome/browser/chromeos/login/test/scoped_policy_update.h" #include "chrome/browser/chromeos/login/test/user_policy_mixin.h" +#include "chrome/browser/chromeos/platform_keys/platform_keys.h" #include "chrome/browser/chromeos/platform_keys/platform_keys_service.h" #include "chrome/browser/chromeos/platform_keys/platform_keys_service_factory.h" #include "chrome/browser/chromeos/profiles/profile_helper.h"
diff --git a/chrome/browser/chromeos/platform_keys/platform_keys_service_nss.cc b/chrome/browser/chromeos/platform_keys/platform_keys_service_nss.cc index 1aa472e..69efabd4 100644 --- a/chrome/browser/chromeos/platform_keys/platform_keys_service_nss.cc +++ b/chrome/browser/chromeos/platform_keys/platform_keys_service_nss.cc
@@ -32,6 +32,7 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process_platform_part_chromeos.h" #include "chrome/browser/chromeos/net/client_cert_store_chromeos.h" +#include "chrome/browser/chromeos/platform_keys/platform_keys.h" #include "chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.h" #include "components/policy/core/common/cloud/cloud_policy_constants.h" #include "content/public/browser/browser_context.h"
diff --git a/chrome/browser/component_updater/zxcvbn_data_component_installer.cc b/chrome/browser/component_updater/zxcvbn_data_component_installer.cc index b1ac18c..d757a50 100644 --- a/chrome/browser/component_updater/zxcvbn_data_component_installer.cc +++ b/chrome/browser/component_updater/zxcvbn_data_component_installer.cc
@@ -19,6 +19,7 @@ #include "base/location.h" #include "base/logging.h" #include "base/memory/scoped_refptr.h" +#include "base/strings/string_split.h" #include "base/task/post_task.h" #include "base/task/thread_pool.h" #include "base/util/ranges/algorithm.h" @@ -30,6 +31,7 @@ #include "components/update_client/update_client_errors.h" #include "components/update_client/utils.h" #include "third_party/zxcvbn-cpp/native-src/zxcvbn/frequency_lists.hpp" +#include "third_party/zxcvbn-cpp/native-src/zxcvbn/frequency_lists_common.hpp" namespace component_updater { @@ -69,33 +71,27 @@ ZxcvbnDataComponentInstallerPolicy::kUsTvAndFilmTxtFileName}, }}; -using DictionaryMap = base::flat_map<zxcvbn::DictionaryTag, std::string>; -DictionaryMap ReadDictionaries(const base::FilePath& install_dir) { - DictionaryMap result; - result.reserve(kTagAndFileNamePairs.size()); +using RankedDictionaries = + std::unordered_map<zxcvbn::DictionaryTag, zxcvbn::RankedDict>; +RankedDictionaries ParseRankedDictionaries(const base::FilePath& install_dir) { + RankedDictionaries result; for (const auto& pair : kTagAndFileNamePairs) { base::FilePath dictionary_path = install_dir.Append(pair.file_name); DVLOG(1) << "Reading Dictionary from file: " << dictionary_path; std::string dictionary; - if (base::ReadFileToString(dictionary_path, &dictionary)) - result.try_emplace(result.end(), pair.tag, std::move(dictionary)); - else + if (base::ReadFileToString(dictionary_path, &dictionary)) { + result.emplace(pair.tag, zxcvbn::build_ranked_dict(base::SplitStringPiece( + dictionary, "\r\n", base::TRIM_WHITESPACE, + base::SPLIT_WANT_NONEMPTY))); + } else { VLOG(1) << "Failed reading from " << dictionary_path; + } } return result; } -void ParseDictionaries(const DictionaryMap& dictionaries) { - for (const auto& pair : dictionaries) { - if (!zxcvbn::ParseRankedDictionary(pair.first, pair.second)) { - VLOG(1) << "Failed to parse dictionary for tag " - << static_cast<int>(pair.first) << ". Contents: " << pair.second; - } - } -} - // The SHA256 of the SubjectPublicKeyInfo used to sign the extension. // The extension id is: ojhpjlocmbogdgmfpkhlaaeamibhnphh constexpr std::array<uint8_t, 32> kZxcvbnDataPublicKeySha256 = { @@ -141,8 +137,8 @@ base::ThreadPool::PostTaskAndReplyWithResult( FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT}, - base::BindOnce(&ReadDictionaries, install_dir), - base::BindOnce(&ParseDictionaries)); + base::BindOnce(&ParseRankedDictionaries, install_dir), + base::BindOnce(&zxcvbn::SetRankedDicts)); } base::FilePath ZxcvbnDataComponentInstallerPolicy::GetRelativeInstallDir()
diff --git a/chrome/browser/component_updater/zxcvbn_data_component_installer_unittest.cc b/chrome/browser/component_updater/zxcvbn_data_component_installer_unittest.cc index 781b1a7..2ac9781 100644 --- a/chrome/browser/component_updater/zxcvbn_data_component_installer_unittest.cc +++ b/chrome/browser/component_updater/zxcvbn_data_component_installer_unittest.cc
@@ -17,8 +17,8 @@ namespace { -using ::testing::ElementsAre; using ::testing::Pair; +using ::testing::UnorderedElementsAre; } // namespace @@ -103,15 +103,15 @@ base::WriteFile( GetPath().Append( ZxcvbnDataComponentInstallerPolicy::kEnglishWikipediaTxtFileName), - "english_wikipedia"); + "english\nwikipedia"); base::WriteFile( GetPath().Append( ZxcvbnDataComponentInstallerPolicy::kFemaleNamesTxtFileName), - "female_names"); + "female\nnames"); base::WriteFile( GetPath().Append( ZxcvbnDataComponentInstallerPolicy::kMaleNamesTxtFileName), - "male_names"); + "male\nnames"); base::WriteFile( GetPath().Append( ZxcvbnDataComponentInstallerPolicy::kPasswordsTxtFileName), @@ -122,26 +122,28 @@ base::WriteFile( GetPath().Append( ZxcvbnDataComponentInstallerPolicy::kUsTvAndFilmTxtFileName), - "us_tv_and_film"); + "us\ntv\nand\nfilm"); policy().ComponentReady(version(), GetPath(), nullptr); task_env().RunUntilIdle(); zxcvbn::RankedDicts ranked_dicts = zxcvbn::default_ranked_dicts(); - EXPECT_THAT(zxcvbn::default_ranked_dicts(), - ::testing::UnorderedElementsAre( - Pair(zxcvbn::DictionaryTag::ENGLISH_WIKIPEDIA, - ElementsAre(Pair("english_wikipedia", 1))), - Pair(zxcvbn::DictionaryTag::FEMALE_NAMES, - ElementsAre(Pair("female_names", 1))), - Pair(zxcvbn::DictionaryTag::MALE_NAMES, - ElementsAre(Pair("male_names", 1))), - Pair(zxcvbn::DictionaryTag::PASSWORDS, - ElementsAre(Pair("passwords", 1))), - Pair(zxcvbn::DictionaryTag::SURNAMES, - ElementsAre(Pair("surnames", 1))), - Pair(zxcvbn::DictionaryTag::US_TV_AND_FILM, - ElementsAre(Pair("us_tv_and_film", 1))))); + EXPECT_THAT( + zxcvbn::default_ranked_dicts(), + UnorderedElementsAre( + Pair(zxcvbn::DictionaryTag::ENGLISH_WIKIPEDIA, + UnorderedElementsAre(Pair("english", 1), Pair("wikipedia", 2))), + Pair(zxcvbn::DictionaryTag::FEMALE_NAMES, + UnorderedElementsAre(Pair("female", 1), Pair("names", 2))), + Pair(zxcvbn::DictionaryTag::MALE_NAMES, + UnorderedElementsAre(Pair("male", 1), Pair("names", 2))), + Pair(zxcvbn::DictionaryTag::PASSWORDS, + UnorderedElementsAre(Pair("passwords", 1))), + Pair(zxcvbn::DictionaryTag::SURNAMES, + UnorderedElementsAre(Pair("surnames", 1))), + Pair(zxcvbn::DictionaryTag::US_TV_AND_FILM, + UnorderedElementsAre(Pair("us", 1), Pair("tv", 2), + Pair("and", 3), Pair("film", 4))))); } } // namespace component_updater
diff --git a/chrome/browser/devtools/devtools_ui_bindings.cc b/chrome/browser/devtools/devtools_ui_bindings.cc index ddd8f65..20f850f2 100644 --- a/chrome/browser/devtools/devtools_ui_bindings.cc +++ b/chrome/browser/devtools/devtools_ui_bindings.cc
@@ -1523,11 +1523,13 @@ return agent_host_.get() == agent_host; } -void DevToolsUIBindings::CallClientMethod(const std::string& object_name, - const std::string& method_name, - const base::Value& arg1, - const base::Value& arg2, - const base::Value& arg3) { +void DevToolsUIBindings::CallClientMethod( + const std::string& object_name, + const std::string& method_name, + const base::Value& arg1, + const base::Value& arg2, + const base::Value& arg3, + base::OnceCallback<void(base::Value)> completion_callback) { // If we're not exposing bindings, we shouldn't call functions either. if (!frontend_host_) return; @@ -1547,7 +1549,7 @@ } javascript.append(");"); web_contents_->GetMainFrame()->ExecuteJavaScript( - base::UTF8ToUTF16(javascript), base::NullCallback()); + base::UTF8ToUTF16(javascript), std::move(completion_callback)); } void DevToolsUIBindings::ReadyToCommitNavigation(
diff --git a/chrome/browser/devtools/devtools_ui_bindings.h b/chrome/browser/devtools/devtools_ui_bindings.h index b3e3ad1d..d7d4361 100644 --- a/chrome/browser/devtools/devtools_ui_bindings.h +++ b/chrome/browser/devtools/devtools_ui_bindings.h
@@ -80,11 +80,14 @@ // Takes ownership over the |delegate|. void SetDelegate(Delegate* delegate); - void CallClientMethod(const std::string& object_name, - const std::string& method_name, - const base::Value& arg1 = {}, - const base::Value& arg2 = {}, - const base::Value& arg3 = {}); + void CallClientMethod( + const std::string& object_name, + const std::string& method_name, + const base::Value& arg1 = {}, + const base::Value& arg2 = {}, + const base::Value& arg3 = {}, + base::OnceCallback<void(base::Value)> completion_callback = + base::OnceCallback<void(base::Value)>()); void AttachTo(const scoped_refptr<content::DevToolsAgentHost>& agent_host); void Detach(); bool IsAttachedTo(content::DevToolsAgentHost* agent_host);
diff --git a/chrome/browser/devtools/devtools_window.cc b/chrome/browser/devtools/devtools_window.cc index 3c29640d..7ebe9562 100644 --- a/chrome/browser/devtools/devtools_window.cc +++ b/chrome/browser/devtools/devtools_window.cc
@@ -406,6 +406,10 @@ if (throttle_) throttle_->ResumeThrottle(); + if (reattach_complete_callback_) { + std::move(reattach_complete_callback_).Run(); + } + life_stage_ = kClosing; UpdateBrowserWindow(); @@ -767,12 +771,19 @@ } void DevToolsWindow::UpdateInspectedWebContents( - content::WebContents* new_web_contents) { + content::WebContents* new_web_contents, + base::OnceCallback<void()> callback) { + DCHECK(!reattach_complete_callback_); + reattach_complete_callback_ = std::move(callback); + inspected_contents_observer_ = std::make_unique<ObserverWithAccessor>(new_web_contents); bindings_->AttachTo( content::DevToolsAgentHost::GetOrCreateFor(new_web_contents)); - bindings_->CallClientMethod("DevToolsAPI", "reattachMainTarget"); + bindings_->CallClientMethod( + "DevToolsAPI", "reattachMainTarget", {}, {}, {}, + base::BindOnce(&DevToolsWindow::OnReattachMainTargetComplete, + base::Unretained(this))); } void DevToolsWindow::ScheduleShow(const DevToolsToggleAction& action) { @@ -1640,3 +1651,7 @@ web_modal::WebContentsModalDialogManager::FromWebContents(main_web_contents_) ->SetDelegate(browser); } + +void DevToolsWindow::OnReattachMainTargetComplete(base::Value) { + std::move(reattach_complete_callback_).Run(); +}
diff --git a/chrome/browser/devtools/devtools_window.h b/chrome/browser/devtools/devtools_window.h index e2c979c..18fa5e9 100644 --- a/chrome/browser/devtools/devtools_window.h +++ b/chrome/browser/devtools/devtools_window.h
@@ -128,7 +128,8 @@ // Updates the WebContents inspected by the DevToolsWindow by reattaching // the binding to |new_web_contents|. Called when swapping an outer // WebContents with its inner WebContents. - void UpdateInspectedWebContents(content::WebContents* new_web_contents); + void UpdateInspectedWebContents(content::WebContents* new_web_contents, + base::OnceCallback<void()> callback); // Sets closure to be called after load is done. If already loaded, calls // closure immediately. @@ -381,6 +382,8 @@ // display web modal dialogs triggered by it. void RegisterModalDialogManager(Browser* browser); + void OnReattachMainTargetComplete(base::Value); + std::unique_ptr<ObserverWithAccessor> inspected_contents_observer_; FrontendType frontend_type_; @@ -426,6 +429,8 @@ Throttle* throttle_ = nullptr; bool open_new_window_for_popups_ = false; + base::OnceCallback<void()> reattach_complete_callback_; + friend class DevToolsEventForwarder; DISALLOW_COPY_AND_ASSIGN(DevToolsWindow); };
diff --git a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_ash.cc b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_ash.cc index df8bfc03..42e7751 100644 --- a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_ash.cc +++ b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_ash.cc
@@ -11,6 +11,7 @@ #include "base/values.h" #include "chrome/browser/chromeos/platform_keys/extension_platform_keys_service.h" #include "chrome/browser/chromeos/platform_keys/extension_platform_keys_service_factory.h" +#include "chrome/browser/chromeos/platform_keys/platform_keys.h" #include "chrome/browser/chromeos/platform_keys/platform_keys_service.h" #include "chrome/browser/chromeos/platform_keys/platform_keys_service_factory.h" #include "chrome/browser/extensions/api/platform_keys/platform_keys_api.h"
diff --git a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_ash.h b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_ash.h index 782e09ea..c66964f2 100644 --- a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_ash.h +++ b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_ash.h
@@ -10,7 +10,7 @@ #include <vector> #include "base/memory/ref_counted.h" -#include "chrome/browser/chromeos/platform_keys/platform_keys_service.h" +#include "chrome/browser/chromeos/platform_keys/platform_keys.h" #include "chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.h" #include "extensions/browser/extension_function.h"
diff --git a/chrome/browser/extensions/api/platform_keys/platform_keys_api.cc b/chrome/browser/extensions/api/platform_keys/platform_keys_api.cc index 4c2c914..473e04a 100644 --- a/chrome/browser/extensions/api/platform_keys/platform_keys_api.cc +++ b/chrome/browser/extensions/api/platform_keys/platform_keys_api.cc
@@ -16,7 +16,7 @@ #include "base/values.h" #include "chrome/browser/chromeos/platform_keys/extension_platform_keys_service.h" #include "chrome/browser/chromeos/platform_keys/extension_platform_keys_service_factory.h" -#include "chrome/browser/chromeos/platform_keys/platform_keys_service.h" +#include "chrome/browser/chromeos/platform_keys/platform_keys.h" #include "chrome/browser/extensions/api/platform_keys/verify_trust_api.h" #include "chrome/common/extensions/api/platform_keys_internal.h" #include "components/web_modal/web_contents_modal_dialog_manager.h"
diff --git a/chrome/browser/extensions/api/platform_keys/platform_keys_api.h b/chrome/browser/extensions/api/platform_keys/platform_keys_api.h index b51daf6..f629cae7 100644 --- a/chrome/browser/extensions/api/platform_keys/platform_keys_api.h +++ b/chrome/browser/extensions/api/platform_keys/platform_keys_api.h
@@ -9,7 +9,7 @@ #include <vector> #include "base/optional.h" -#include "chrome/browser/chromeos/platform_keys/platform_keys_service.h" +#include "chrome/browser/chromeos/platform_keys/platform_keys.h" #include "extensions/browser/extension_function.h" namespace net {
diff --git a/chrome/browser/extensions/api/platform_keys/platform_keys_apitest_nss.cc b/chrome/browser/extensions/api/platform_keys/platform_keys_apitest_nss.cc index 3c46570..384c4ad 100644 --- a/chrome/browser/extensions/api/platform_keys/platform_keys_apitest_nss.cc +++ b/chrome/browser/extensions/api/platform_keys/platform_keys_apitest_nss.cc
@@ -14,6 +14,7 @@ #include "base/strings/stringprintf.h" #include "chrome/browser/chromeos/platform_keys/extension_platform_keys_service.h" #include "chrome/browser/chromeos/platform_keys/extension_platform_keys_service_factory.h" +#include "chrome/browser/chromeos/platform_keys/platform_keys.h" #include "chrome/browser/extensions/api/platform_keys/platform_keys_test_base.h" #include "chrome/browser/net/nss_context.h" #include "chrome/browser/policy/profile_policy_connector.h" @@ -174,8 +175,7 @@ std::string client_cert1_spki = chromeos::platform_keys::GetSubjectPublicKeyInfo(client_cert1_); permissions_for_ext->RegisterKeyForCorporateUsage( - client_cert1_spki, - {chromeos::platform_keys::KeyPermissions::KeyLocation::kUserSlot}); + client_cert1_spki, {chromeos::platform_keys::TokenId::kUser}); done_callback.Run(); }
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index d3eac89e..3494c6884 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -1875,12 +1875,6 @@ "to true, pointer movements wil not be affected by the underlying platform " "modications such as mouse accelaration."; -const char kPolicyAtomicGroupsEnabledName[] = "Policy Atomic Groups Enabled"; -const char kPolicyAtomicGroupsEnabledDescription[] = - "Enables the concept of policy atomic groups that makes policies of an " - "atomic group that do not share the highest priority source from that group" - "ignored."; - const char kPreviewsAllowedName[] = "Previews Allowed"; const char kPreviewsAllowedDescription[] = "Allows previews to be shown subject to specific preview types being "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index dafd34d..465f449 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -1083,9 +1083,6 @@ extern const char kPointerLockOptionsName[]; extern const char kPointerLockOptionsDescription[]; -extern const char kPolicyAtomicGroupsEnabledName[]; -extern const char kPolicyAtomicGroupsEnabledDescription[]; - extern const char kPreviewsAllowedName[]; extern const char kPreviewsAllowedDescription[];
diff --git a/chrome/browser/metrics/ukm_browsertest.cc b/chrome/browser/metrics/ukm_browsertest.cc index 8a229986..4f0fc2d 100644 --- a/chrome/browser/metrics/ukm_browsertest.cc +++ b/chrome/browser/metrics/ukm_browsertest.cc
@@ -616,20 +616,12 @@ } #endif // !defined(OS_ANDROID) -// https://crbug.com/1102747 -#if defined(OS_ANDROID) -#define MAYBE_AddSyncedUserBirthYearAndGenderToProtoData \ - DISABLED_AddSyncedUserBirthYearAndGenderToProtoData -#else -#define MAYBE_AddSyncedUserBirthYearAndGenderToProtoData \ - AddSyncedUserBirthYearAndGenderToProtoData -#endif // TODO(crbug/1016118): Add the remaining test cases. // Keep this test in sync with testUKMDemographicsReportingWithFeatureEnabled // and testUKMDemographicsReportingWithFeatureDisabled in // ios/chrome/browser/metrics/demographics_egtest.mm. IN_PROC_BROWSER_TEST_P(UkmBrowserTestWithDemographics, - MAYBE_AddSyncedUserBirthYearAndGenderToProtoData) { + AddSyncedUserBirthYearAndGenderToProtoData) { ukm::UkmTestHelper ukm_test_helper(GetUkmService()); test::DemographicsTestParams param = GetParam(); MetricsConsentOverride metrics_consent(true); @@ -679,7 +671,12 @@ histogram.ExpectTotalCount("UKM.UserDemographics.Status", /*count=*/0); } - harness->service()->GetUserSettings()->SetSyncRequested(false); +#if !defined(OS_CHROMEOS) + // Sign out the user to revoke all refresh tokens. This prevents any posted + // tasks from successfully fetching an access token during the tear-down + // phase and crashing on a DCHECK. See crbug/1102746 for more details. + harness->SignOutPrimaryAccount(); +#endif // !defined(OS_CHROMEOS) ClosePlatformBrowser(browser); } @@ -975,11 +972,13 @@ // ChromeOS doesn't have the concept of sign-out so this test doesn't make sense // there. +// // Flaky on Android: https://crbug.com/1096047. -#if !defined(OS_CHROMEOS) && !defined(OS_ANDROID) +// // Make sure that UKM is disabled when the profile signs out of Sync. // Keep in sync with testSingleSyncSignout in ios/chrome/browser/metrics/ // ukm_egtest.mm. +#if !defined(OS_CHROMEOS) && !defined(OS_ANDROID) IN_PROC_BROWSER_TEST_F(UkmBrowserTest, SingleSyncSignoutCheck) { ukm::UkmTestHelper ukm_test_helper(GetUkmService()); MetricsConsentOverride metrics_consent(true);
diff --git a/chrome/browser/native_file_system/chrome_native_file_system_permission_context.cc b/chrome/browser/native_file_system/chrome_native_file_system_permission_context.cc index ae34a44..14fafd1c 100644 --- a/chrome/browser/native_file_system/chrome_native_file_system_permission_context.cc +++ b/chrome/browser/native_file_system/chrome_native_file_system_permission_context.cc
@@ -336,6 +336,12 @@ /*provider_id=*/std::string()); } +bool ChromeNativeFileSystemPermissionContext::CanObtainReadPermission( + const url::Origin& origin) { + return GetReadGuardContentSetting(origin) == CONTENT_SETTING_ASK || + GetReadGuardContentSetting(origin) == CONTENT_SETTING_ALLOW; +} + bool ChromeNativeFileSystemPermissionContext::CanObtainWritePermission( const url::Origin& origin) { return GetWriteGuardContentSetting(origin) == CONTENT_SETTING_ASK ||
diff --git a/chrome/browser/native_file_system/chrome_native_file_system_permission_context.h b/chrome/browser/native_file_system/chrome_native_file_system_permission_context.h index ac9eb52..49d1fa6 100644 --- a/chrome/browser/native_file_system/chrome_native_file_system_permission_context.h +++ b/chrome/browser/native_file_system/chrome_native_file_system_permission_context.h
@@ -56,6 +56,7 @@ std::unique_ptr<content::NativeFileSystemWriteItem> item, content::GlobalFrameRoutingId frame_id, base::OnceCallback<void(AfterWriteCheckResult)> callback) override; + bool CanObtainReadPermission(const url::Origin& origin) override; bool CanObtainWritePermission(const url::Origin& origin) override; ContentSetting GetReadGuardContentSetting(const url::Origin& origin);
diff --git a/chrome/browser/native_file_system/origin_scoped_native_file_system_permission_context.cc b/chrome/browser/native_file_system/origin_scoped_native_file_system_permission_context.cc index 3bc2546e..7f5f68f 100644 --- a/chrome/browser/native_file_system/origin_scoped_native_file_system_permission_context.cc +++ b/chrome/browser/native_file_system/origin_scoped_native_file_system_permission_context.cc
@@ -331,12 +331,20 @@ existing_grant->SetStatus(PermissionStatus::GRANTED); break; case CONTENT_SETTING_ASK: - // Files automatically get read access when picked by the user, - // directories need to first be confirmed. - if (user_action != UserAction::kLoadFromStorage && - handle_type == HandleType::kFile) { - existing_grant->SetStatus(PermissionStatus::GRANTED); - ScheduleUsageIconUpdate(); + switch (user_action) { + case UserAction::kOpen: + case UserAction::kSave: + // Open and Save dialog only grant read access for individual files. + if (handle_type == HandleType::kDirectory) + break; + FALLTHROUGH; + case UserAction::kDragAndDrop: + // Drag&drop grants read access for all handles. + existing_grant->SetStatus(PermissionStatus::GRANTED); + ScheduleUsageIconUpdate(); + break; + case UserAction::kLoadFromStorage: + break; } break; case CONTENT_SETTING_BLOCK: @@ -391,9 +399,16 @@ existing_grant->SetStatus(PermissionStatus::GRANTED); break; case CONTENT_SETTING_ASK: - if (user_action == UserAction::kSave) { - existing_grant->SetStatus(PermissionStatus::GRANTED); - ScheduleUsageIconUpdate(); + switch (user_action) { + case UserAction::kSave: + // Only automatically grant write access for save dialogs. + existing_grant->SetStatus(PermissionStatus::GRANTED); + ScheduleUsageIconUpdate(); + break; + case UserAction::kOpen: + case UserAction::kDragAndDrop: + case UserAction::kLoadFromStorage: + break; } break; case CONTENT_SETTING_BLOCK:
diff --git a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc index 309a958..e8f9a923 100644 --- a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc +++ b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc
@@ -567,11 +567,12 @@ // Once get the advertisement, the first thing to do is decrypt the // certificate. - std::vector<uint8_t> encrypted_metadata = advertisement->encrypted_metadata; + std::vector<uint8_t> encrypted_metadata_key = + advertisement->encrypted_metadata_key; std::vector<uint8_t> salt = advertisement->salt; GetCertificateManager()->GetDecryptedPublicCertificate( - std::move(encrypted_metadata), std::move(salt), + std::move(encrypted_metadata_key), std::move(salt), base::BindOnce(&NearbySharingServiceImpl::OnOutgoingDecryptedCertificate, weak_ptr_factory_.GetWeakPtr(), endpoint_id, std::move(advertisement))); @@ -1334,11 +1335,12 @@ return; } - std::vector<uint8_t> encrypted_metadata = advertisement->encrypted_metadata; + std::vector<uint8_t> encrypted_metadata_key = + advertisement->encrypted_metadata_key; std::vector<uint8_t> salt = advertisement->salt; GetCertificateManager()->GetDecryptedPublicCertificate( - std::move(encrypted_metadata), std::move(salt), + std::move(encrypted_metadata_key), std::move(salt), base::BindOnce(&NearbySharingServiceImpl::OnIncomingDecryptedCertificate, weak_ptr_factory_.GetWeakPtr(), endpoint_id, connection, std::move(advertisement)));
diff --git a/chrome/browser/password_check/android/internal/BUILD.gn b/chrome/browser/password_check/android/internal/BUILD.gn index 82b53e7..f1e93d7 100644 --- a/chrome/browser/password_check/android/internal/BUILD.gn +++ b/chrome/browser/password_check/android/internal/BUILD.gn
@@ -67,6 +67,8 @@ "//components/embedder_support/android:util_java", "//third_party/android_deps:androidx_annotation_annotation_java", "//third_party/android_deps:androidx_appcompat_appcompat_java", + "//third_party/android_deps:androidx_appcompat_appcompat_resources_java", + "//third_party/android_deps:androidx_core_core_java", "//third_party/android_deps:androidx_fragment_fragment_java", "//third_party/android_deps:androidx_lifecycle_lifecycle_common_java", "//third_party/android_deps:androidx_preference_preference_java",
diff --git a/chrome/browser/password_check/android/internal/java/res/layout/password_check_compromised_credential_item.xml b/chrome/browser/password_check/android/internal/java/res/layout/password_check_compromised_credential_item.xml index f141ef69..29b06579 100644 --- a/chrome/browser/password_check/android/internal/java/res/layout/password_check_compromised_credential_item.xml +++ b/chrome/browser/password_check/android/internal/java/res/layout/password_check_compromised_credential_item.xml
@@ -43,9 +43,13 @@ <org.chromium.ui.widget.ButtonCompat android:id="@+id/credential_change_button" + android:drawablePadding="@dimen/compromised_credential_row_button_icon_padding" + android:drawableStart="@drawable/permission_popups" android:layout_marginTop="@dimen/compromised_credential_row_button_margin_top" android:layout_height="wrap_content" android:layout_width="wrap_content" + android:paddingStart="@dimen/compromised_credential_row_button_icon_start_padding" + android:paddingEnd="@dimen/compromised_credential_row_button_icon_end_padding" android:text="@string/password_check_credential_row_change_button_caption" style="@style/FilledButton.Flat" />
diff --git a/chrome/browser/password_check/android/internal/java/res/layout/password_check_compromised_credential_with_script_item.xml b/chrome/browser/password_check/android/internal/java/res/layout/password_check_compromised_credential_with_script_item.xml index 96cd250..6c633f2c7 100644 --- a/chrome/browser/password_check/android/internal/java/res/layout/password_check_compromised_credential_with_script_item.xml +++ b/chrome/browser/password_check/android/internal/java/res/layout/password_check_compromised_credential_with_script_item.xml
@@ -46,8 +46,10 @@ android:layout_marginTop="@dimen/compromised_credential_row_button_margin_top" android:layout_height="wrap_content" android:layout_width="wrap_content" + android:paddingStart="@dimen/compromised_credential_row_button_icon_start_padding" + android:paddingEnd="@dimen/compromised_credential_row_button_icon_end_padding" android:text="@string/password_check_credential_row_change_button_caption" - android:drawablePadding="3dp" + android:drawablePadding="@dimen/compromised_credential_row_button_icon_padding" android:drawableStart="@drawable/ic_autofill_assistant_white_24dp" style="@style/FilledButton.Flat" /> @@ -64,6 +66,8 @@ android:layout_marginTop="@dimen/compromised_credential_row_button_margin_top" android:layout_height="wrap_content" android:layout_width="wrap_content" + android:paddingStart="0dp" + android:paddingEnd="0dp" android:text="@string/password_check_credential_row_change_manually_button_caption" style="@style/TextButton"/>
diff --git a/chrome/browser/password_check/android/internal/java/res/values/dimens.xml b/chrome/browser/password_check/android/internal/java/res/values/dimens.xml index f254933d..da937db 100644 --- a/chrome/browser/password_check/android/internal/java/res/values/dimens.xml +++ b/chrome/browser/password_check/android/internal/java/res/values/dimens.xml
@@ -18,6 +18,9 @@ <dimen name="check_status_message_idle_margin_vertical">27dp</dimen> <dimen name="check_status_message_running_margin_vertical">36dp</dimen> + <dimen name="compromised_credential_row_button_icon_padding">8dp</dimen> + <dimen name="compromised_credential_row_button_icon_start_padding">12dp</dimen> + <dimen name="compromised_credential_row_button_icon_end_padding">16dp</dimen> <dimen name="compromised_credential_row_button_margin_top">16dp</dimen> <dimen name="compromised_credential_row_more_padding_end">8dp</dimen> <dimen name="compromised_credential_row_more_padding_start">16dp</dimen>
diff --git a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckViewBinder.java b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckViewBinder.java index facc2be..e868167 100644 --- a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckViewBinder.java +++ b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckViewBinder.java
@@ -19,6 +19,7 @@ import android.content.Context; import android.content.res.Resources; +import android.graphics.drawable.Drawable; import android.util.Pair; import android.view.View; import android.view.ViewGroup; @@ -27,7 +28,10 @@ import android.widget.LinearLayout; import android.widget.TextView; +import androidx.annotation.ColorRes; import androidx.annotation.VisibleForTesting; +import androidx.appcompat.content.res.AppCompatResources; +import androidx.core.graphics.drawable.DrawableCompat; import org.chromium.chrome.browser.password_check.PasswordCheckProperties.ItemType; import org.chromium.chrome.browser.password_check.internal.R; @@ -144,6 +148,8 @@ button.setOnClickListener(unusedView -> { model.get(CREDENTIAL_HANDLER).onChangePasswordButtonClick(credential); }); + setTintListForCompoundDrawables(button.getCompoundDrawablesRelative(), + view.getContext(), org.chromium.ui.R.color.default_text_color_inverse); if (credential.hasScript()) { ButtonCompat button_with_script = view.findViewById(R.id.credential_change_button_with_script); @@ -468,4 +474,13 @@ private static int getDimensionPixelOffset(View view, int resourceId) { return view.getContext().getResources().getDimensionPixelOffset(resourceId); } + + private static void setTintListForCompoundDrawables( + Drawable[] compoundDrawables, Context context, @ColorRes int tintColorList) { + for (Drawable drawable : compoundDrawables) { + if (drawable == null) continue; + DrawableCompat.setTintList( + drawable, AppCompatResources.getColorStateList(context, tintColorList)); + } + } }
diff --git a/chrome/browser/password_manager/password_manager_browsertest.cc b/chrome/browser/password_manager/password_manager_browsertest.cc index 827f118..b275fd38 100644 --- a/chrome/browser/password_manager/password_manager_browsertest.cc +++ b/chrome/browser/password_manager/password_manager_browsertest.cc
@@ -36,13 +36,18 @@ #include "chrome/browser/ui/test/test_browser_dialog.h" #include "chrome/common/chrome_paths.h" #include "chrome/test/base/ui_test_utils.h" +#include "components/autofill/content/browser/content_autofill_driver.h" +#include "components/autofill/content/browser/content_autofill_driver_factory.h" #include "components/autofill/core/browser/autofill_test_utils.h" #include "components/autofill/core/browser/test_autofill_client.h" #include "components/autofill/core/common/autofill_features.h" #include "components/autofill/core/common/autofill_switches.h" +#include "components/autofill/core/common/form_field_data.h" #include "components/autofill/core/common/password_form.h" +#include "components/autofill/core/common/renderer_id.h" #include "components/password_manager/content/browser/content_password_manager_driver.h" #include "components/password_manager/content/browser/content_password_manager_driver_factory.h" +#include "components/password_manager/core/browser/form_parsing/password_field_prediction.h" #include "components/password_manager/core/browser/http_auth_manager.h" #include "components/password_manager/core/browser/http_auth_observer.h" #include "components/password_manager/core/browser/password_form_manager.h" @@ -77,6 +82,8 @@ using base::Feature; using testing::_; using testing::ElementsAre; +using FieldPrediction = + autofill::AutofillQueryResponseContents::Field::FieldPrediction; namespace password_manager { namespace { @@ -1168,6 +1175,169 @@ // The only thing we check here is that there is no use-after-free reported. } +// Get form data for /password/nonplaceholder_username.html +autofill::FormData GetPlaceholderUsernameFormData( + autofill::PasswordForm signin_form) { + // Build server predictions + autofill::FormData form_data; + constexpr autofill::FormRendererId form_id(0); + form_data.unique_renderer_id = form_id; + form_data.name_attribute = ASCIIToUTF16("testform"); + form_data.name = form_data.name_attribute; + form_data.action = GURL(signin_form.action.spec() + "password/done.html"); + form_data.url = signin_form.url; + // Username + autofill::FormFieldData username_field; + username_field.form_control_type = "text"; + username_field.id_attribute = ASCIIToUTF16("username_field"); + username_field.name = username_field.id_attribute; + username_field.value = ASCIIToUTF16("example@example.com"); + username_field.label = username_field.value; + username_field.unique_renderer_id = autofill::FieldRendererId(0); + form_data.fields.push_back(username_field); + // Password + autofill::FormFieldData password_field; + password_field.form_control_type = "password"; + password_field.id_attribute = ASCIIToUTF16("password_field"); + password_field.name = password_field.id_attribute; + password_field.value = ASCIIToUTF16("htmlPass"); + password_field.label = password_field.value; + password_field.unique_renderer_id = autofill::FieldRendererId(1); + form_data.fields.push_back(password_field); + + return form_data; +} + +// If there is a username and password with prefilled values, do not overwrite +// the password if the username does not look like a placeholder value +IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, + NonPlaceholderPasswordNotOverwritten) { + // Save a credential to the password store. + scoped_refptr<password_manager::TestPasswordStore> password_store = + static_cast<password_manager::TestPasswordStore*>( + PasswordStoreFactory::GetForProfile( + browser()->profile(), ServiceAccessType::IMPLICIT_ACCESS) + .get()); + autofill::PasswordForm signin_form; + signin_form.signon_realm = embedded_test_server()->base_url().spec(); + signin_form.url = embedded_test_server()->base_url(); + signin_form.action = embedded_test_server()->base_url(); + signin_form.username_value = base::ASCIIToUTF16("example@example.com"); + signin_form.password_value = base::ASCIIToUTF16("savedPass"); + password_store->AddLogin(signin_form); + + password_manager::PasswordFormManager:: + set_wait_for_server_predictions_for_filling(true); + + // Get form data + autofill::FormData form_data = GetPlaceholderUsernameFormData(signin_form); + + // Username + bool is_placeholder = false; + autofill::FormStructure form_structure(form_data); + form_structure.field(0)->set_server_type(autofill::USERNAME); + std::vector<FieldPrediction> username_predictions; + FieldPrediction username_prediction; + username_prediction.set_type(autofill::USERNAME); + username_prediction.set_may_use_prefilled_placeholder(is_placeholder); + username_predictions.push_back(username_prediction); + form_structure.field(0)->set_server_predictions(username_predictions); + + // Password + form_structure.field(1)->set_server_type(autofill::PASSWORD); + std::vector<FieldPrediction> password_predictions; + FieldPrediction password_prediction; + password_prediction.set_type(autofill::PASSWORD); + password_predictions.push_back(password_prediction); + form_structure.field(1)->set_server_predictions(password_predictions); + + // Navigate to the page + NavigateToFile("/password/nonplaceholder_username.html"); + + // Use autofill predictions + autofill::ChromeAutofillClient* autofill_client = + autofill::ChromeAutofillClient::FromWebContents(WebContents()); + autofill_client->PropagateAutofillPredictions(WebContents()->GetMainFrame(), + {&form_structure}); + + // Check original values before interaction + CheckElementValue("username_field", "example@example.com"); + CheckElementValue("password_field", "htmlPass"); + + // Have user interact with the page + content::SimulateMouseClickAt( + WebContents(), 0, blink::WebMouseEvent::Button::kLeft, gfx::Point(1, 1)); + + // Now make sure the fields aren't overwritten + CheckElementValue("username_field", "example@example.com"); + CheckElementValue("password_field", "htmlPass"); +} + +// If there is a username and password with prefilled values, overwrite the +// password if the username looks like a placeholder value +IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, + PlaceholderPasswordOverwritten) { + // Save a credential to the password store. + scoped_refptr<password_manager::TestPasswordStore> password_store = + static_cast<password_manager::TestPasswordStore*>( + PasswordStoreFactory::GetForProfile( + browser()->profile(), ServiceAccessType::IMPLICIT_ACCESS) + .get()); + autofill::PasswordForm signin_form; + signin_form.signon_realm = embedded_test_server()->base_url().spec(); + signin_form.url = embedded_test_server()->base_url(); + signin_form.action = embedded_test_server()->base_url(); + signin_form.username_value = base::ASCIIToUTF16("example@example.com"); + signin_form.password_value = base::ASCIIToUTF16("savedPass"); + password_store->AddLogin(signin_form); + + password_manager::PasswordFormManager:: + set_wait_for_server_predictions_for_filling(true); + + // Get form data + autofill::FormData form_data = GetPlaceholderUsernameFormData(signin_form); + + // Username + bool is_placeholder = true; + autofill::FormStructure form_structure(form_data); + form_structure.field(0)->set_server_type(autofill::USERNAME); + std::vector<FieldPrediction> username_predictions; + FieldPrediction username_prediction; + username_prediction.set_type(autofill::USERNAME); + username_prediction.set_may_use_prefilled_placeholder(is_placeholder); + username_predictions.push_back(username_prediction); + form_structure.field(0)->set_server_predictions(username_predictions); + + // Password + form_structure.field(1)->set_server_type(autofill::PASSWORD); + std::vector<FieldPrediction> password_predictions; + FieldPrediction password_prediction; + password_prediction.set_type(autofill::PASSWORD); + password_predictions.push_back(password_prediction); + form_structure.field(1)->set_server_predictions(password_predictions); + + // Navigate to the page + NavigateToFile("/password/nonplaceholder_username.html"); + + // Use autofill predictions + autofill::ChromeAutofillClient* autofill_client = + autofill::ChromeAutofillClient::FromWebContents(WebContents()); + autofill_client->PropagateAutofillPredictions(WebContents()->GetMainFrame(), + {&form_structure}); + + // Check original values before interaction + CheckElementValue("username_field", "example@example.com"); + CheckElementValue("password_field", "htmlPass"); + + // Have user interact with the page + content::SimulateMouseClickAt( + WebContents(), 0, blink::WebMouseEvent::Button::kLeft, gfx::Point(1, 1)); + + // Now make sure the fields are overwritten + CheckElementValue("username_field", "example@example.com"); + CheckElementValue("password_field", "savedPass"); +} + IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, UsernameAndPasswordValueAccessible) { // At first let us save a credential to the password store.
diff --git a/chrome/browser/payments/ssl_validity_checker.cc b/chrome/browser/payments/ssl_validity_checker.cc index fd4e82e..a8e21d7 100644 --- a/chrome/browser/payments/ssl_validity_checker.cc +++ b/chrome/browser/payments/ssl_validity_checker.cc
@@ -15,6 +15,21 @@ #include "url/gurl.h" namespace payments { +namespace { + +// Returns the security level of |web_contents|. The |web_contents| parameter +// should not be null. +security_state::SecurityLevel GetSecurityLevel( + content::WebContents* web_contents) { + DCHECK(web_contents); + SecurityStateTabHelper::CreateForWebContents(web_contents); + SecurityStateTabHelper* helper = + SecurityStateTabHelper::FromWebContents(web_contents); + DCHECK(helper); + return helper->GetSecurityLevel(); +} + +} // namespace // static std::string std::string SslValidityChecker::GetInvalidSslCertificateErrorMessage( @@ -82,17 +97,4 @@ return true; } -// static -// Returns the security level of |web_contents|. The |web_contents| -// parameter should not be null. -security_state::SecurityLevel SslValidityChecker::GetSecurityLevel( - content::WebContents* web_contents) { - DCHECK(web_contents); - SecurityStateTabHelper::CreateForWebContents(web_contents); - SecurityStateTabHelper* helper = - SecurityStateTabHelper::FromWebContents(web_contents); - DCHECK(helper); - return helper->GetSecurityLevel(); -} - } // namespace payments
diff --git a/chrome/browser/payments/ssl_validity_checker.h b/chrome/browser/payments/ssl_validity_checker.h index 9e38d1f..7cd70d5a 100644 --- a/chrome/browser/payments/ssl_validity_checker.h +++ b/chrome/browser/payments/ssl_validity_checker.h
@@ -8,7 +8,6 @@ #include <string> #include "base/macros.h" -#include "components/security_state/core/security_state.h" namespace content { class WebContents; @@ -34,9 +33,6 @@ static bool IsValidPageInPaymentHandlerWindow( content::WebContents* web_contents); - static security_state::SecurityLevel GetSecurityLevel( - content::WebContents* web_contents); - private: DISALLOW_IMPLICIT_CONSTRUCTORS(SslValidityChecker); };
diff --git a/chrome/browser/portal/portal_browsertest.cc b/chrome/browser/portal/portal_browsertest.cc index 25cba5f..038d741 100644 --- a/chrome/browser/portal/portal_browsertest.cc +++ b/chrome/browser/portal/portal_browsertest.cc
@@ -110,6 +110,26 @@ browser()->tab_strip_model()->GetActiveWebContents(), nullptr)); } +IN_PROC_BROWSER_TEST_F( + PortalBrowserTest, + DevToolsWindowIsAttachedToOriginalWebContentsWhenActivationFails) { + ASSERT_TRUE(embedded_test_server()->Start()); + GURL url(embedded_test_server()->GetURL("/portal/portal-no-src.html")); + ui_test_utils::NavigateToURL(browser(), url); + WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents(); + DevToolsWindow* dev_tools_window = + DevToolsWindowTesting::OpenDevToolsWindowSync(browser(), true); + WebContents* main_web_contents = + DevToolsWindowTesting::Get(dev_tools_window)->main_web_contents(); + EXPECT_EQ(main_web_contents, + DevToolsWindow::GetInTabWebContents(contents, nullptr)); + + EXPECT_EQ(true, content::EvalJs(contents, "activate()")); + EXPECT_EQ(main_web_contents, + DevToolsWindow::GetInTabWebContents( + browser()->tab_strip_model()->GetActiveWebContents(), nullptr)); +} + IN_PROC_BROWSER_TEST_F(PortalBrowserTest, HttpBasicAuthenticationInPortal) { ASSERT_TRUE(embedded_test_server()->Start()); GURL url(embedded_test_server()->GetURL("/title1.html"));
diff --git a/chrome/browser/profiles/profile_shortcut_manager.h b/chrome/browser/profiles/profile_shortcut_manager.h index 38e5550..43304ac6 100644 --- a/chrome/browser/profiles/profile_shortcut_manager.h +++ b/chrome/browser/profiles/profile_shortcut_manager.h
@@ -31,6 +31,11 @@ // profile created. virtual void CreateProfileShortcut(const base::FilePath& profile_path) = 0; + // Create an incognito desktop shortcut for the profile with path + // |profile_path| + virtual void CreateIncognitoProfileShortcut( + const base::FilePath& profile_path) = 0; + // Removes any desktop profile shortcuts for the profile corresponding to // |profile_path|. virtual void RemoveProfileShortcuts(const base::FilePath& profile_path) = 0;
diff --git a/chrome/browser/profiles/profile_shortcut_manager_unittest_win.cc b/chrome/browser/profiles/profile_shortcut_manager_unittest_win.cc index 199e1ca9..d23d212a 100644 --- a/chrome/browser/profiles/profile_shortcut_manager_unittest_win.cc +++ b/chrome/browser/profiles/profile_shortcut_manager_unittest_win.cc
@@ -397,6 +397,21 @@ profiles::internal::CreateProfileShortcutFlags(profile_path)); } +// Test ensures that the incognito switch and parent profile are added when +// creating profile shortcut flags for incognito mode. +TEST_F(ProfileShortcutManagerTest, IncognitoShortcutFlags) { + const base::string16 kProfileName = L"MyProfileX"; + const base::FilePath profile_path = + profile_manager_->profiles_dir().Append(kProfileName); + const base::string16 shortcut_flags = + profiles::internal::CreateProfileShortcutFlags(profile_path, + /*incognito=*/true); + EXPECT_NE( + shortcut_flags.find(L"--profile-directory=\"" + kProfileName + L"\""), + shortcut_flags.size()); + EXPECT_NE(shortcut_flags.find(L"--incognito"), shortcut_flags.size()); +} + TEST_F(ProfileShortcutManagerTest, DesktopShortcutsCreate) { SetupDefaultProfileShortcut(FROM_HERE); // Validation is done by |ValidateProfileShortcutAtPath()| which is called
diff --git a/chrome/browser/profiles/profile_shortcut_manager_win.cc b/chrome/browser/profiles/profile_shortcut_manager_win.cc index 54da82ca..1263c0e 100644 --- a/chrome/browser/profiles/profile_shortcut_manager_win.cc +++ b/chrome/browser/profiles/profile_shortcut_manager_win.cc
@@ -385,11 +385,13 @@ base::FilePath profile_path, ProfileShortcutManagerWin::CreateOrUpdateMode create_mode, ProfileShortcutManagerWin::NonProfileShortcutAction action, - bool single_profile) + bool single_profile, + bool incognito = false) : create_mode(create_mode), action(action), profile_path(profile_path), - single_profile(single_profile) {} + single_profile(single_profile), + incognito(incognito) {} ~CreateOrUpdateShortcutsParams() {} ProfileShortcutManagerWin::CreateOrUpdateMode create_mode; @@ -406,6 +408,10 @@ // badged icon or the name of profile in the shortcut name. bool single_profile; + // If true, this adds an incognito switch that allows the user to open an + // incognito window directly from the desktop shortcut. + bool incognito; + // Avatar images for this profile. SkBitmap avatar_image_1x; SkBitmap avatar_image_2x; @@ -438,7 +444,8 @@ std::set<base::FilePath> desktop_contents = ListUserDesktopContents(nullptr); const base::string16 command_line = - profiles::internal::CreateProfileShortcutFlags(params.profile_path); + profiles::internal::CreateProfileShortcutFlags(params.profile_path, + params.incognito); ChromeCommandLineFilter filter( chrome_exe, command_line, params.action == ProfileShortcutManagerWin::UPDATE_NON_PROFILE_SHORTCUTS); @@ -689,10 +696,18 @@ iswdigit); } -base::string16 CreateProfileShortcutFlags(const base::FilePath& profile_path) { - return base::StringPrintf( +base::string16 CreateProfileShortcutFlags(const base::FilePath& profile_path, + const bool incognito) { + base::string16 flags = base::StringPrintf( L"--%ls=\"%ls\"", base::ASCIIToUTF16(switches::kProfileDirectory).c_str(), profile_path.BaseName().value().c_str()); + + if (incognito) { + flags.append(base::StringPrintf( + L" --%ls", base::ASCIIToUTF16(switches::kIncognito).c_str())); + } + + return flags; } } // namespace internal @@ -748,13 +763,25 @@ void ProfileShortcutManagerWin::CreateOrUpdateProfileIcon( const base::FilePath& profile_path) { CreateOrUpdateShortcutsForProfileAtPath( - profile_path, CREATE_OR_UPDATE_ICON_ONLY, IGNORE_NON_PROFILE_SHORTCUTS); + profile_path, CREATE_OR_UPDATE_ICON_ONLY, IGNORE_NON_PROFILE_SHORTCUTS, + /*incognito=*/false); +} + +// Creates an incognito desktop shortcut for the current profile. +// TODO(crbug.com/1113162): Update the shortcut label and icon to chrome + +// incognito. +void ProfileShortcutManagerWin::CreateIncognitoProfileShortcut( + const base::FilePath& profile_path) { + CreateOrUpdateShortcutsForProfileAtPath(profile_path, CREATE_WHEN_NONE_FOUND, + IGNORE_NON_PROFILE_SHORTCUTS, + /*incognito=*/true); } void ProfileShortcutManagerWin::CreateProfileShortcut( const base::FilePath& profile_path) { CreateOrUpdateShortcutsForProfileAtPath(profile_path, CREATE_WHEN_NONE_FOUND, - IGNORE_NON_PROFILE_SHORTCUTS); + IGNORE_NON_PROFILE_SHORTCUTS, + /*incognito=*/false); } void ProfileShortcutManagerWin::RemoveProfileShortcuts( @@ -815,9 +842,9 @@ // When the second profile is added, make existing non-profile and // non-badged shortcuts point to the first profile and be badged/named // appropriately. - CreateOrUpdateShortcutsForProfileAtPath(GetOtherProfilePath(profile_path), - UPDATE_EXISTING_ONLY, - UPDATE_NON_PROFILE_SHORTCUTS); + CreateOrUpdateShortcutsForProfileAtPath( + GetOtherProfilePath(profile_path), UPDATE_EXISTING_ONLY, + UPDATE_NON_PROFILE_SHORTCUTS, /*incognito=*/false); } } @@ -834,7 +861,8 @@ // This is needed to unbadge the icon. CreateOrUpdateShortcutsForProfileAtPath( storage.GetAllProfilesAttributes().front()->GetPath(), - UPDATE_EXISTING_ONLY, IGNORE_NON_PROFILE_SHORTCUTS); + UPDATE_EXISTING_ONLY, IGNORE_NON_PROFILE_SHORTCUTS, + /*incognito=*/false); } base::FilePath first_profile_path; @@ -853,7 +881,8 @@ const base::FilePath& profile_path, const base::string16& old_profile_name) { CreateOrUpdateShortcutsForProfileAtPath(profile_path, UPDATE_EXISTING_ONLY, - IGNORE_NON_PROFILE_SHORTCUTS); + IGNORE_NON_PROFILE_SHORTCUTS, + /*incognito=*/false); } void ProfileShortcutManagerWin::OnProfileAvatarChanged( @@ -892,7 +921,8 @@ void ProfileShortcutManagerWin::CreateOrUpdateShortcutsForProfileAtPath( const base::FilePath& profile_path, CreateOrUpdateMode create_mode, - NonProfileShortcutAction action) { + NonProfileShortcutAction action, + bool incognito) { DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) || BrowserThread::CurrentlyOn(BrowserThread::UI)); ProfileAttributesStorage& storage = @@ -905,7 +935,8 @@ bool remove_badging = storage.GetNumberOfProfiles() == 1u; CreateOrUpdateShortcutsParams params(profile_path, create_mode, action, - /*single_profile=*/remove_badging); + /*single_profile=*/remove_badging, + incognito); params.old_profile_name = entry->GetShortcutName();
diff --git a/chrome/browser/profiles/profile_shortcut_manager_win.h b/chrome/browser/profiles/profile_shortcut_manager_win.h index 6d5ad2e6..298bbe5 100644 --- a/chrome/browser/profiles/profile_shortcut_manager_win.h +++ b/chrome/browser/profiles/profile_shortcut_manager_win.h
@@ -55,7 +55,8 @@ }; // Returns the command-line flags to launch Chrome with the given profile. -base::string16 CreateProfileShortcutFlags(const base::FilePath& profile_path); +base::string16 CreateProfileShortcutFlags(const base::FilePath& profile_path, + const bool incognito = false); } // namespace internal } // namespace profiles @@ -84,6 +85,8 @@ ~ProfileShortcutManagerWin() override; // ProfileShortcutManager implementation: + void CreateIncognitoProfileShortcut( + const base::FilePath& profile_path) override; void CreateOrUpdateProfileIcon(const base::FilePath& profile_path) override; void CreateProfileShortcut(const base::FilePath& profile_path) override; void RemoveProfileShortcuts(const base::FilePath& profile_path) override; @@ -111,12 +114,13 @@ base::FilePath GetOtherProfilePath(const base::FilePath& profile_path); // Creates or updates shortcuts for the profile at |profile_path| according - // to the specified |create_mode| and |action|. This will always involve - // creating or updating the icon file for this profile. + // to the specified |create_mode|, |action|, and |incognito|. This will always + // involve creating or updating the icon file for this profile. void CreateOrUpdateShortcutsForProfileAtPath( const base::FilePath& profile_path, CreateOrUpdateMode create_mode, - NonProfileShortcutAction action); + NonProfileShortcutAction action, + bool incognito); ProfileManager* profile_manager_;
diff --git a/chrome/browser/reputation/safety_tip_infobar_delegate.cc b/chrome/browser/reputation/safety_tip_infobar_delegate.cc index f8d1481..3354d34 100644 --- a/chrome/browser/reputation/safety_tip_infobar_delegate.cc +++ b/chrome/browser/reputation/safety_tip_infobar_delegate.cc
@@ -100,6 +100,15 @@ ->SetUserIgnore(web_contents_, url_, action_taken_); } +base::string16 SafetyTipInfoBarDelegate::GetLinkText() const { + return l10n_util::GetStringUTF16(IDS_PAGE_INFO_SAFETY_TIP_MORE_INFO_LINK); +} + +bool SafetyTipInfoBarDelegate::LinkClicked(WindowOpenDisposition disposition) { + OpenHelpCenterFromSafetyTip(web_contents_); + return false; +} + base::string16 SafetyTipInfoBarDelegate::GetDescriptionText() const { return GetSafetyTipDescription(safety_tip_status_, suggested_url_); }
diff --git a/chrome/browser/reputation/safety_tip_infobar_delegate.h b/chrome/browser/reputation/safety_tip_infobar_delegate.h index 3329110..a970025 100644 --- a/chrome/browser/reputation/safety_tip_infobar_delegate.h +++ b/chrome/browser/reputation/safety_tip_infobar_delegate.h
@@ -31,6 +31,8 @@ infobars::InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override; int GetIconId() const override; void InfoBarDismissed() override; + base::string16 GetLinkText() const override; + bool LinkClicked(WindowOpenDisposition disposition) override; // This function is the equivalent of GetMessageText(), but for the portion of // the infobar below the 'message' title.
diff --git a/chrome/browser/resources/chromeos/login/oobe_update.html b/chrome/browser/resources/chromeos/login/oobe_update.html index 9e030266..8c059e9 100644 --- a/chrome/browser/resources/chromeos/login/oobe_update.html +++ b/chrome/browser/resources/chromeos/login/oobe_update.html
@@ -50,7 +50,26 @@ </oobe-dialog> </div> <div hidden="[[!betterUpdateScreenFeatureEnabled_]]"> - <oobe-dialog> + <oobe-dialog footer-shrinkable id="restarting-dialog" + hidden="[[!isRebootProgressBarShown_(manualRebootNeeded, + updateCompleted)]]" + title-key="updateCompeletedRebootingMsg" + aria-live="polite"> + <hd-iron-icon slot="oobe-icon" + icon1x="oobe-32:googleg" icon2x="oobe-64:googleg"> + </hd-iron-icon> + <paper-progress slot="progress" id="restarting-progress" indeterminate> + </paper-progress> + </oobe-dialog> + <oobe-dialog footer-shrinkable id="better-update-complete-dialog" + hidden="[[!manualRebootNeeded]]" + title-key="updateCompeletedMsg" + aria-live="polite"> + <hd-iron-icon slot="oobe-icon" + icon1x="oobe-32:googleg" icon2x="oobe-64:googleg"> + </hd-iron-icon> + </oobe-dialog> + <oobe-dialog hidden="[[!showLowBatteryWarning]]"> <div hidden="[[!showLowBatteryWarning]]" id="battery-warning" slot="footer"> </div>
diff --git a/chrome/browser/resources/chromeos/login/oobe_update.js b/chrome/browser/resources/chromeos/login/oobe_update.js index eb877e6..c7da373 100644 --- a/chrome/browser/resources/chromeos/login/oobe_update.js +++ b/chrome/browser/resources/chromeos/login/oobe_update.js
@@ -23,6 +23,7 @@ 'setEstimatedTimeLeft', 'showEstimatedTimeLeft', 'setUpdateCompleted', + 'setManualRebootNeeded', 'showUpdateCurtain', 'setProgressMessage', 'setUpdateProgress', @@ -101,6 +102,14 @@ }, /** + * True if update is fully completed and manual action is required. + */ + manualRebootNeeded: { + type: Boolean, + value: false, + }, + + /** * If update cancellation is allowed. */ cancelAllowed: { @@ -140,8 +149,10 @@ }, onBeforeShow() { - cr.ui.login.invokePolymerMethod( - this.$['checking-downloading-update'], 'onBeforeShow'); + if (!this.betterUpdateScreenFeatureEnabled_) { + cr.ui.login.invokePolymerMethod( + this.$['checking-downloading-update'], 'onBeforeShow'); + } }, onBackClicked_() { @@ -210,6 +221,13 @@ }, /** + * @param {boolean} is_needed True if manual reboot after update is needed. + */ + setManualRebootNeeded(is_needed) { + this.manualRebootNeeded = is_needed; + }, + + /** * Shows or hides update curtain. * @param {boolean} visible Are curtains visible? */ @@ -225,5 +243,15 @@ this.showLowBatteryWarning = visible; }, + /** + * Calculates visibility of the reboot progress dialog. + * @param {Boolean} manualRebootNeeded If the automatic reboot timer has + * elapsed and manual reboot is needed. + * @param {Boolean} updateCompleted If update is completed and all + * intermediate status elements are hidden. + */ + isRebootProgressBarShown_(manualRebootNeeded, updateCompleted) { + return updateCompleted && !manualRebootNeeded; + }, }); })();
diff --git a/chrome/browser/resources/settings/autofill_page/merge_exceptions_store_copies_behavior.js b/chrome/browser/resources/settings/autofill_page/merge_exceptions_store_copies_behavior.js index 0a204f2..456143d 100644 --- a/chrome/browser/resources/settings/autofill_page/merge_exceptions_store_copies_behavior.js +++ b/chrome/browser/resources/settings/autofill_page/merge_exceptions_store_copies_behavior.js
@@ -67,7 +67,16 @@ const frontendIdToMergedEntry = new Map(); for (const entry of exceptionList) { if (frontendIdToMergedEntry.has(entry.frontendId)) { - frontendIdToMergedEntry.get(entry.frontendId).merge(entry); + const mergeSucceded = + frontendIdToMergedEntry.get(entry.frontendId).mergeInPlace(entry); + if (mergeSucceded) { + // The merge is in-place, so nothing to be done. + } else { + // The merge can fail in weird cases despite |frontendId| matching. + // If so, just create another entry in the UI for |entry|. See also + // crbug.com/1114697. + multiStoreEntries.push(new MultiStoreExceptionEntry(entry)); + } } else { const multiStoreEntry = new MultiStoreExceptionEntry(entry); frontendIdToMergedEntry.set(entry.frontendId, multiStoreEntry);
diff --git a/chrome/browser/resources/settings/autofill_page/merge_passwords_store_copies_behavior.js b/chrome/browser/resources/settings/autofill_page/merge_passwords_store_copies_behavior.js index 87ded984..8d7db83 100644 --- a/chrome/browser/resources/settings/autofill_page/merge_passwords_store_copies_behavior.js +++ b/chrome/browser/resources/settings/autofill_page/merge_passwords_store_copies_behavior.js
@@ -77,7 +77,16 @@ const frontendIdToMergedEntry = new Map(); for (const entry of passwordList) { if (frontendIdToMergedEntry.has(entry.frontendId)) { - frontendIdToMergedEntry.get(entry.frontendId).merge(entry); + const mergeSucceded = + frontendIdToMergedEntry.get(entry.frontendId).mergeInPlace(entry); + if (mergeSucceded) { + // The merge is in-place, so nothing to be done. + } else { + // The merge can fail in weird cases despite |frontendId| matching. + // If so, just create another entry in the UI for |entry|. See also + // crbug.com/1114697. + multiStoreEntries.push(new MultiStorePasswordUiEntry(entry)); + } } else { const multiStoreEntry = new MultiStorePasswordUiEntry(entry); frontendIdToMergedEntry.set(entry.frontendId, multiStoreEntry);
diff --git a/chrome/browser/resources/settings/autofill_page/multi_store_exception_entry.js b/chrome/browser/resources/settings/autofill_page/multi_store_exception_entry.js index 67c6f6a..7c552e34 100644 --- a/chrome/browser/resources/settings/autofill_page/multi_store_exception_entry.js +++ b/chrome/browser/resources/settings/autofill_page/multi_store_exception_entry.js
@@ -18,37 +18,37 @@ */ export class MultiStoreExceptionEntry extends MultiStoreIdHandler { /** - * Creates a multi-store entry from duplicates |entry1| and (optional) - * |entry2|. If both arguments are passed, they should have the same contents - * but should be from different stores. - * @param {!PasswordManagerProxy.ExceptionEntry} entry1 - * @param {PasswordManagerProxy.ExceptionEntry=} entry2 + * @param {!PasswordManagerProxy.ExceptionEntry} entry */ - constructor(entry1, entry2) { + constructor(entry) { super(); /** @type {!PasswordManagerProxy.UrlCollection} */ - this.urls_ = entry1.urls; + this.urls_ = entry.urls; - this.setId(entry1.id, entry1.fromAccountStore); - - if (entry2) { - this.merge(entry2); - } + this.setId(entry.id, entry.fromAccountStore); } /** * Incorporates the id of |otherEntry|, as long as |otherEntry| matches - * |contents_| and the id corresponding to its store is not set. + * |contents_| and the id corresponding to its store is not set. If these + * preconditions are not satisfied, results in a no-op. * @param {!PasswordManagerProxy.ExceptionEntry} otherEntry + * @return {boolean} Returns whether the merge succeeded. */ // TODO(crbug.com/1102294) Consider asserting frontendId as well. - merge(otherEntry) { - assert( - (this.isPresentInAccount() && !otherEntry.fromAccountStore) || - (this.isPresentOnDevice() && otherEntry.fromAccountStore)); - assert(JSON.stringify(this.urls_) === JSON.stringify(otherEntry.urls)); + mergeInPlace(otherEntry) { + const alreadyHasCopyFromStore = + (this.isPresentInAccount() && otherEntry.fromAccountStore) || + (this.isPresentOnDevice() && !otherEntry.fromAccountStore); + if (alreadyHasCopyFromStore) { + return false; + } + if (JSON.stringify(this.urls_) !== JSON.stringify(otherEntry.urls)) { + return false; + } this.setId(otherEntry.id, otherEntry.fromAccountStore); + return true; } get urls() {
diff --git a/chrome/browser/resources/settings/autofill_page/multi_store_password_ui_entry.js b/chrome/browser/resources/settings/autofill_page/multi_store_password_ui_entry.js index d5a4ea40..fa164968 100644 --- a/chrome/browser/resources/settings/autofill_page/multi_store_password_ui_entry.js +++ b/chrome/browser/resources/settings/autofill_page/multi_store_password_ui_entry.js
@@ -18,42 +18,41 @@ */ export class MultiStorePasswordUiEntry extends MultiStoreIdHandler { /** - * Creates a multi-store item from duplicates |entry1| and (optional) - * |entry2|. If both arguments are passed, they should have the same contents - * but should be from different stores. - * @param {!PasswordManagerProxy.PasswordUiEntry} entry1 - * @param {PasswordManagerProxy.PasswordUiEntry=} entry2 + * @param {!PasswordManagerProxy.PasswordUiEntry} entry */ - constructor(entry1, entry2) { + constructor(entry) { super(); /** @type {!MultiStorePasswordUiEntry.Contents} */ - this.contents_ = MultiStorePasswordUiEntry.getContents_(entry1); + this.contents_ = MultiStorePasswordUiEntry.getContents_(entry); /** @type {string} */ this.password_ = ''; - this.setId(entry1.id, entry1.fromAccountStore); - - if (entry2) { - this.merge(entry2); - } + this.setId(entry.id, entry.fromAccountStore); } /** * Incorporates the id of |otherEntry|, as long as |otherEntry| matches - * |contents_| and the id corresponding to its store is not set. + * |contents_| and the id corresponding to its store is not set. If these + * preconditions are not satisfied, results in a no-op. * @param {!PasswordManagerProxy.PasswordUiEntry} otherEntry + * @return {boolean} Returns whether the merge succeeded. */ // TODO(crbug.com/1102294) Consider asserting frontendId as well. - merge(otherEntry) { - assert( - (this.isPresentInAccount() && !otherEntry.fromAccountStore) || - (this.isPresentOnDevice() && otherEntry.fromAccountStore)); - assert( - JSON.stringify(this.contents_) === - JSON.stringify(MultiStorePasswordUiEntry.getContents_(otherEntry))); + mergeInPlace(otherEntry) { + const alreadyHasCopyFromStore = + (this.isPresentInAccount() && otherEntry.fromAccountStore) || + (this.isPresentOnDevice() && !otherEntry.fromAccountStore); + if (alreadyHasCopyFromStore) { + return false; + } + if (JSON.stringify(this.contents_) !== + JSON.stringify(MultiStorePasswordUiEntry.getContents_(otherEntry))) { + return false; + } this.setId(otherEntry.id, otherEntry.fromAccountStore); + return true; } /** @return {!PasswordManagerProxy.UrlCollection} */
diff --git a/chrome/browser/resources/settings/safety_check_page/safety_check_browser_proxy.js b/chrome/browser/resources/settings/safety_check_page/safety_check_browser_proxy.js index 227552c..ce842a2 100644 --- a/chrome/browser/resources/settings/safety_check_page/safety_check_browser_proxy.js +++ b/chrome/browser/resources/settings/safety_check_page/safety_check_browser_proxy.js
@@ -88,6 +88,7 @@ DISABLED_BY_EXTENSION: 4, ENABLED_STANDARD: 5, ENABLED_ENHANCED: 6, + ENABLED_STANDARD_AVAILABLE_ENHANCED: 7, }; /**
diff --git a/chrome/browser/resources/settings/safety_check_page/safety_check_safe_browsing_child.js b/chrome/browser/resources/settings/safety_check_page/safety_check_safe_browsing_child.js index 17b0fd4c..072c938 100644 --- a/chrome/browser/resources/settings/safety_check_page/safety_check_safe_browsing_child.js +++ b/chrome/browser/resources/settings/safety_check_page/safety_check_safe_browsing_child.js
@@ -86,6 +86,7 @@ return SafetyCheckIconStatus.RUNNING; case SafetyCheckSafeBrowsingStatus.ENABLED_STANDARD: case SafetyCheckSafeBrowsingStatus.ENABLED_ENHANCED: + case SafetyCheckSafeBrowsingStatus.ENABLED_STANDARD_AVAILABLE_ENHANCED: return SafetyCheckIconStatus.SAFE; case SafetyCheckSafeBrowsingStatus.ENABLED: // ENABLED is deprecated.
diff --git a/chrome/browser/resources/signin/profile_picker/BUILD.gn b/chrome/browser/resources/signin/profile_picker/BUILD.gn index be443e29..25f9d0b 100644 --- a/chrome/browser/resources/signin/profile_picker/BUILD.gn +++ b/chrome/browser/resources/signin/profile_picker/BUILD.gn
@@ -43,7 +43,6 @@ deps = [ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", "//ui/webui/resources/js:assert.m", - "//ui/webui/resources/js:load_time_data.m", ] }
diff --git a/chrome/browser/resources/signin/profile_picker/manage_profiles_browser_proxy.js b/chrome/browser/resources/signin/profile_picker/manage_profiles_browser_proxy.js index c59bfa2..189c052 100644 --- a/chrome/browser/resources/signin/profile_picker/manage_profiles_browser_proxy.js +++ b/chrome/browser/resources/signin/profile_picker/manage_profiles_browser_proxy.js
@@ -39,6 +39,13 @@ */ launchSelectedProfile(profilePath) {} + /** + * Opens profile on manage profile settings sub page and closes the + * profile picker. + * @param {string} profilePath + */ + openManageProfileSettingsSubPage(profilePath) {} + /** Launches Guest profile. */ launchGuestProfile() {} @@ -85,6 +92,11 @@ } /** @override */ + openManageProfileSettingsSubPage(profilePath) { + chrome.send('openManageProfileSettingsSubPage', [profilePath]); + } + + /** @override */ launchGuestProfile() { chrome.send('launchGuestProfile'); }
diff --git a/chrome/browser/resources/signin/profile_picker/navigation_behavior.js b/chrome/browser/resources/signin/profile_picker/navigation_behavior.js index 754a7e7..6f09aa4 100644 --- a/chrome/browser/resources/signin/profile_picker/navigation_behavior.js +++ b/chrome/browser/resources/signin/profile_picker/navigation_behavior.js
@@ -3,9 +3,8 @@ // found in the LICENSE file. import {assert, assertNotReached} from 'chrome://resources/js/assert.m.js'; -import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; -import './strings.js'; +import {isForceSigninEnabled, isSignInProfileCreationSupported} from './policy_helper.js'; /** * Valid route pathnames. @@ -36,14 +35,16 @@ case Routes.MAIN: return 'mainView'; case Routes.NEW_PROFILE: - // TODO(msalama): Add support in profile creation mode for policies like: - // - ForceSignIn --> load signin page directly. - // - DisallowSignIn --> open local profile customization. - if (loadTimeData.getBoolean('signInProfileCreationFlow')) { - return ProfileCreationSteps.PROFILE_TYPE_CHOICE; - } else { + // TODO(msalama): Adjust once sign in profile creation is supported. + // Check DisallowSignIn policy. + if (!isSignInProfileCreationSupported()) { + assert(!isForceSigninEnabled()); return ProfileCreationSteps.LOCAL_PROFILE_CUSTOMIZATION; } + if (isForceSigninEnabled()) { + return ProfileCreationSteps.LOAD_SIGNIN; + } + return ProfileCreationSteps.PROFILE_TYPE_CHOICE; default: assertNotReached(); } @@ -146,4 +147,4 @@ * @param {string} step */ onRouteChange: function(route, step) {}, -}; \ No newline at end of file +};
diff --git a/chrome/browser/resources/signin/profile_picker/policy_helper.js b/chrome/browser/resources/signin/profile_picker/policy_helper.js new file mode 100644 index 0000000..17cc602 --- /dev/null +++ b/chrome/browser/resources/signin/profile_picker/policy_helper.js
@@ -0,0 +1,31 @@ +// 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. + +import {assert, assertNotReached} from 'chrome://resources/js/assert.m.js'; +import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; +import './strings.js'; + +/** @return {boolean} */ +export function isGuestModeEnabled() { + return loadTimeData.getBoolean('isGuestModeEnabled'); +} + +/** @return {boolean} */ +export function isProfileCreationAllowed() { + return loadTimeData.getBoolean('isProfileCreationAllowed'); +} + +/** @return {boolean} */ +export function isForceSigninEnabled() { + const enabled = loadTimeData.getBoolean('isForceSigninEnabled'); + // Force sign in policy is not supported yet. The picker should not be shown + // in case this policy exists. + assert(!enabled); + return enabled; +} + +/** @return {boolean} */ +export function isSignInProfileCreationSupported() { + return loadTimeData.getBoolean('signInProfileCreationFlowSupported'); +}
diff --git a/chrome/browser/resources/signin/profile_picker/profile_card_menu.html b/chrome/browser/resources/signin/profile_picker/profile_card_menu.html index b193eeb..21bf57b1 100644 --- a/chrome/browser/resources/signin/profile_picker/profile_card_menu.html +++ b/chrome/browser/resources/signin/profile_picker/profile_card_menu.html
@@ -86,6 +86,9 @@ <button class="dropdown-item" on-click="onRemoveButtonClicked_"> $i18n{profileMenuRemoveText} </button> + <button class="dropdown-item" on-click="onCustomizeButtonClicked_"> + $i18n{profileMenuCustomizeText} + </button> </cr-action-menu> <cr-action-menu id="removeActionMenu" role-description="$i18n{menu}">
diff --git a/chrome/browser/resources/signin/profile_picker/profile_card_menu.js b/chrome/browser/resources/signin/profile_picker/profile_card_menu.js index a3f0f55..1e0d1dc 100644 --- a/chrome/browser/resources/signin/profile_picker/profile_card_menu.js +++ b/chrome/browser/resources/signin/profile_picker/profile_card_menu.js
@@ -222,4 +222,11 @@ this.$.actionMenu.close(); this.$.removeActionMenu.close(); }, + + /** @private */ + onCustomizeButtonClicked_() { + this.manageProfilesBrowserProxy_.openManageProfileSettingsSubPage( + this.profileState.profilePath); + this.$.actionMenu.close(); + }, });
diff --git a/chrome/browser/resources/signin/profile_picker/profile_picker_app.js b/chrome/browser/resources/signin/profile_picker/profile_picker_app.js index 2f41a02..f34e21f3 100644 --- a/chrome/browser/resources/signin/profile_picker/profile_picker_app.js +++ b/chrome/browser/resources/signin/profile_picker/profile_picker_app.js
@@ -11,7 +11,8 @@ import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {AutogeneratedThemeColorInfo, ManageProfilesBrowserProxy, ManageProfilesBrowserProxyImpl} from './manage_profiles_browser_proxy.js'; -import {NavigationBehavior, ProfileCreationSteps, Routes} from './navigation_behavior.js'; +import {navigateTo, NavigationBehavior, ProfileCreationSteps, Routes} from './navigation_behavior.js'; +import {isProfileCreationAllowed} from './policy_helper.js'; import {ensureLazyLoaded} from './profile_creation_flow/ensure_lazy_loaded.js'; Polymer({ @@ -50,6 +51,11 @@ * @private */ onRouteChange(route, step) { + if (!isProfileCreationAllowed() && route === Routes.NEW_PROFILE) { + navigateTo(Routes.MAIN); + return; + } + if (step == ProfileCreationSteps.LOAD_SIGNIN) { this.manageProfilesBrowserProxy_.loadSignInProfileCreationFlow(); return;
diff --git a/chrome/browser/resources/signin/profile_picker/profile_picker_main_view.js b/chrome/browser/resources/signin/profile_picker/profile_picker_main_view.js index d161b9b3..11dfd30 100644 --- a/chrome/browser/resources/signin/profile_picker/profile_picker_main_view.js +++ b/chrome/browser/resources/signin/profile_picker/profile_picker_main_view.js
@@ -16,7 +16,7 @@ import {ManageProfilesBrowserProxy, ManageProfilesBrowserProxyImpl, ProfileState} from './manage_profiles_browser_proxy.js'; import {navigateTo, NavigationBehavior, Routes} from './navigation_behavior.js'; - +import {isGuestModeEnabled, isProfileCreationAllowed} from './policy_helper.js'; Polymer({ is: 'profile-picker-main-view', @@ -48,6 +48,14 @@ /** @override */ ready() { + if (!isGuestModeEnabled()) { + this.$.browseAsGuestButton.style.display = 'none'; + } + + if (!isProfileCreationAllowed()) { + this.$.addProfile.style.display = 'none'; + } + this.manageProfilesBrowserProxy_ = ManageProfilesBrowserProxyImpl.getInstance(); }, @@ -92,11 +100,17 @@ /** @private */ onAddProfileClick_() { + if (!isProfileCreationAllowed()) { + return; + } navigateTo(Routes.NEW_PROFILE); }, /** @private */ onLaunchGuestProfileClick_() { + if (!isGuestModeEnabled()) { + return; + } this.manageProfilesBrowserProxy_.launchGuestProfile(); },
diff --git a/chrome/browser/resources/signin/profile_picker/profile_picker_resources.grd b/chrome/browser/resources/signin/profile_picker/profile_picker_resources.grd index 465789f..604da43 100644 --- a/chrome/browser/resources/signin/profile_picker/profile_picker_resources.grd +++ b/chrome/browser/resources/signin/profile_picker/profile_picker_resources.grd
@@ -65,6 +65,11 @@ type="chrome_html" compress="false"/> <structure + name="IDR_PROFILE_PICKER_POLICY_HELPER_JS" + file="policy_helper.js" + type="chrome_html" + compress="false"/> + <structure name="IDR_PROFILE_PICKER_ICONS_JS" file="icons.js" type="chrome_html"
diff --git a/chrome/browser/resources/signin/signin_reauth/signin_reauth_app.html b/chrome/browser/resources/signin/signin_reauth/signin_reauth_app.html index 76816769..7782702 100644 --- a/chrome/browser/resources/signin/signin_reauth/signin_reauth_app.html +++ b/chrome/browser/resources/signin/signin_reauth/signin_reauth_app.html
@@ -61,23 +61,31 @@ padding-inline-start: 16px; } </style> + +<!-- + Use the 'consent-description' attribute to annotate all the UI elements + that are part of the text the user reads before consenting to use passwords + from their account. Similarly, use 'consent-confirmation' on the UI element on + which user clicks to indicate consent. +--> + <div id="illustrationContainer"> <div id="illustration"></div> <img src="[[accountImageSrc_]]"> </div> <div id="contentContainer"> - <h1 id="signinReauthTitle"> + <h1 id="signinReauthTitle" consent-description> $i18n{signinReauthTitle} </h1> <div class="message-container"> - <div>$i18n{signinReauthDesc}</div> + <div consent-description>$i18n{signinReauthDesc}</div> </div> </div> <div class="action-container"> <paper-spinner-lite active hidden$="[[!confirmButtonHidden_]]"> </paper-spinner-lite> <cr-button id="confirmButton" class="action-button" on-click="onConfirm_" - hidden="[[confirmButtonHidden_]]"> + hidden="[[confirmButtonHidden_]]" consent-confirmation> [[confirmButtonLabel_]] </cr-button> <cr-button id="cancelButton" on-click="onCancel_"
diff --git a/chrome/browser/resources/signin/signin_reauth/signin_reauth_app.js b/chrome/browser/resources/signin/signin_reauth/signin_reauth_app.js index e2c6b4e..6ce8e1f 100644 --- a/chrome/browser/resources/signin/signin_reauth/signin_reauth_app.js +++ b/chrome/browser/resources/signin/signin_reauth/signin_reauth_app.js
@@ -8,6 +8,7 @@ import './strings.m.js'; import './signin_shared_css.js'; +import {assert, assertNotReached} from 'chrome://resources/js/assert.m.js'; import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; import {WebUIListenerBehavior} from 'chrome://resources/js/web_ui_listener_behavior.m.js'; @@ -52,9 +53,14 @@ this.signinReauthBrowserProxy_.initialize(); }, - /** @private */ - onConfirm_() { - this.signinReauthBrowserProxy_.confirm(); + /** + * @param {!Event} e + * @private + */ + onConfirm_(e) { + this.signinReauthBrowserProxy_.confirm( + this.getConsentDescription_(), + this.getConsentConfirmation_(e.composedPath())); }, /** @private */ @@ -75,4 +81,31 @@ this.i18n('signinReauthNextLabel') : this.i18n('signinReauthConfirmLabel'); }, + + /** @return {!Array<string>} Text of the consent description elements. */ + getConsentDescription_() { + const consentDescription = + Array.from(this.shadowRoot.querySelectorAll('[consent-description]')) + .filter(element => element.clientWidth * element.clientHeight > 0) + .map(element => element.innerHTML.trim()); + assert(consentDescription); + return consentDescription; + }, + + /** + * @param {!Array<!HTMLElement>} path Path of the click event. Must contain + * a consent confirmation element. + * @return {string} The text of the consent confirmation element. + * @private + */ + getConsentConfirmation_(path) { + for (const element of path) { + if (element.nodeType !== Node.DOCUMENT_FRAGMENT_NODE && + element.hasAttribute('consent-confirmation')) { + return element.innerHTML.trim(); + } + } + assertNotReached('No consent confirmation element found.'); + return ''; + }, });
diff --git a/chrome/browser/resources/signin/signin_reauth/signin_reauth_browser_proxy.js b/chrome/browser/resources/signin/signin_reauth/signin_reauth_browser_proxy.js index d4a0404..4dfbe1a 100644 --- a/chrome/browser/resources/signin/signin_reauth/signin_reauth_browser_proxy.js +++ b/chrome/browser/resources/signin/signin_reauth/signin_reauth_browser_proxy.js
@@ -17,8 +17,12 @@ /** * Called when the user confirms the signin reauth dialog. + * @param {!Array<string>} description Strings that the user was presented + * with in the UI. + * @param {string} confirmation Text of the element that the user + * clicked on. */ - confirm() {} + confirm(description, confirmation) {} /** * Called when the user cancels the signin reauth. @@ -34,8 +38,8 @@ } /** @override */ - confirm() { - chrome.send('confirm'); + confirm(description, confirmation) { + chrome.send('confirm', [description, confirmation]); } /** @override */
diff --git a/chrome/browser/safety_check/android/java/src/org/chromium/chrome/browser/safety_check/SafetyCheckProperties.java b/chrome/browser/safety_check/android/java/src/org/chromium/chrome/browser/safety_check/SafetyCheckProperties.java index b1eca24f..6cfe5fc 100644 --- a/chrome/browser/safety_check/android/java/src/org/chromium/chrome/browser/safety_check/SafetyCheckProperties.java +++ b/chrome/browser/safety_check/android/java/src/org/chromium/chrome/browser/safety_check/SafetyCheckProperties.java
@@ -95,6 +95,7 @@ return SafeBrowsingState.CHECKING; case SafeBrowsingStatus.ENABLED: case SafeBrowsingStatus.ENABLED_STANDARD: + case SafeBrowsingStatus.ENABLED_STANDARD_AVAILABLE_ENHANCED: return SafeBrowsingState.ENABLED_STANDARD; case SafeBrowsingStatus.ENABLED_ENHANCED: return SafeBrowsingState.ENABLED_ENHANCED;
diff --git a/chrome/browser/signin/dice_signed_in_profile_creator.cc b/chrome/browser/signin/dice_signed_in_profile_creator.cc index 8836c954..490ad96 100644 --- a/chrome/browser/signin/dice_signed_in_profile_creator.cc +++ b/chrome/browser/signin/dice_signed_in_profile_creator.cc
@@ -7,6 +7,8 @@ #include "base/check.h" #include "base/memory/ptr_util.h" #include "base/no_destructor.h" +#include "base/strings/string16.h" +#include "base/strings/utf_string_conversions.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/profiles/profile_attributes_storage.h" #include "chrome/browser/profiles/profile_avatar_icon_util.h" @@ -129,6 +131,7 @@ DiceSignedInProfileCreator::DiceSignedInProfileCreator( Profile* source_profile, CoreAccountId account_id, + const std::string& local_profile_name, base::OnceCallback<void(Profile*)> callback) : source_profile_(source_profile), account_id_(account_id), @@ -137,9 +140,12 @@ g_browser_process->profile_manager()->GetProfileAttributesStorage(); size_t icon_index = storage.ChooseAvatarIconIndexForNewProfile(); + base::string16 name = local_profile_name.empty() + ? storage.ChooseNameForNewProfile(icon_index) + : base::UTF8ToUTF16(local_profile_name); + ProfileManager::CreateMultiProfileAsync( - storage.ChooseNameForNewProfile(icon_index), - profiles::GetDefaultAvatarIconUrl(icon_index), + name, profiles::GetDefaultAvatarIconUrl(icon_index), base::BindRepeating(&DiceSignedInProfileCreator::OnNewProfileCreated, weak_pointer_factory_.GetWeakPtr())); }
diff --git a/chrome/browser/signin/dice_signed_in_profile_creator.h b/chrome/browser/signin/dice_signed_in_profile_creator.h index 65ad8fc..d144576 100644 --- a/chrome/browser/signin/dice_signed_in_profile_creator.h +++ b/chrome/browser/signin/dice_signed_in_profile_creator.h
@@ -5,6 +5,8 @@ #ifndef CHROME_BROWSER_SIGNIN_DICE_SIGNED_IN_PROFILE_CREATOR_H_ #define CHROME_BROWSER_SIGNIN_DICE_SIGNED_IN_PROFILE_CREATOR_H_ +#include <string> + #include "base/callback.h" #include "base/memory/weak_ptr.h" #include "chrome/browser/profiles/profile.h" @@ -18,8 +20,11 @@ // Creates a new profile and moves the account from source_profile to the new // profile. The callback is called with the new profile or nullptr in case of // failure. The callback is never called synchronously. + // If |local_profile_name| is not empty, it will be set as local name for the + // new profile. DiceSignedInProfileCreator(Profile* source_profile, CoreAccountId account_id, + const std::string& local_profile_name, base::OnceCallback<void(Profile*)> callback); ~DiceSignedInProfileCreator(); @@ -36,8 +41,9 @@ // Callback invoked once the token service is ready for the new profile. void OnNewProfileTokensLoaded(Profile* new_profile); - Profile* source_profile_; - CoreAccountId account_id_; + Profile* const source_profile_; + const CoreAccountId account_id_; + base::OnceCallback<void(Profile*)> callback_; std::unique_ptr<TokensLoadedCallbackRunner> tokens_loaded_callback_runner_;
diff --git a/chrome/browser/signin/dice_signed_in_profile_creator_unittest.cc b/chrome/browser/signin/dice_signed_in_profile_creator_unittest.cc index c0c6f0e..e357bfb 100644 --- a/chrome/browser/signin/dice_signed_in_profile_creator_unittest.cc +++ b/chrome/browser/signin/dice_signed_in_profile_creator_unittest.cc
@@ -10,7 +10,10 @@ #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/run_loop.h" +#include "base/strings/utf_string_conversions.h" #include "base/threading/thread_task_runner_handle.h" +#include "chrome/browser/profiles/profile_attributes_entry.h" +#include "chrome/browser/profiles/profile_attributes_storage.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/profiles/profile_manager_observer.h" #include "chrome/browser/signin/identity_manager_factory.h" @@ -24,6 +27,8 @@ namespace { +const char kProfileTestName[] = "profile_test_name"; + std::unique_ptr<TestingProfile> BuildTestingProfile(const base::FilePath& path, Profile::Delegate* delegate, bool tokens_loaded) { @@ -158,7 +163,7 @@ base::RunLoop loop; std::unique_ptr<DiceSignedInProfileCreator> creator = std::make_unique<DiceSignedInProfileCreator>( - profile(), account_info.account_id, + profile(), account_info.account_id, kProfileTestName, base::BindOnce(&DiceSignedInProfileCreatorTest::OnProfileCreated, base::Unretained(this), loop.QuitClosure())); loop.Run(); @@ -175,6 +180,15 @@ .size()); EXPECT_TRUE(IdentityManagerFactory::GetForProfile(signed_in_profile()) ->HasAccountWithRefreshToken(account_info.account_id)); + + // Check the profile name. + ProfileAttributesEntry* entry = nullptr; + ProfileAttributesStorage& storage = + profile_manager()->GetProfileAttributesStorage(); + ASSERT_TRUE(storage.GetProfileAttributesWithPath( + signed_in_profile()->GetPath(), &entry)); + ASSERT_TRUE(entry); + EXPECT_EQ(base::UTF8ToUTF16(kProfileTestName), entry->GetLocalProfileName()); } TEST_F(DiceSignedInProfileCreatorTest, CreateWithTokensNotLoaded) { @@ -187,7 +201,7 @@ set_profile_added_closure(profile_added_loop.QuitClosure()); std::unique_ptr<DiceSignedInProfileCreator> creator = std::make_unique<DiceSignedInProfileCreator>( - profile(), account_info.account_id, + profile(), account_info.account_id, kProfileTestName, base::BindOnce(&DiceSignedInProfileCreatorTest::OnProfileCreated, base::Unretained(this), creator_loop.QuitClosure())); profile_added_loop.Run(); @@ -222,7 +236,7 @@ identity_test_env()->MakeAccountAvailable("bob@example.com"); std::unique_ptr<DiceSignedInProfileCreator> creator = std::make_unique<DiceSignedInProfileCreator>( - profile(), account_info.account_id, + profile(), account_info.account_id, kProfileTestName, base::BindOnce(&DiceSignedInProfileCreatorTest::OnProfileCreated, base::Unretained(this), base::OnceClosure())); EXPECT_FALSE(creator_callback_called()); @@ -241,7 +255,7 @@ set_profile_added_closure(profile_added_loop.QuitClosure()); std::unique_ptr<DiceSignedInProfileCreator> creator = std::make_unique<DiceSignedInProfileCreator>( - profile(), account_info.account_id, + profile(), account_info.account_id, kProfileTestName, base::BindOnce(&DiceSignedInProfileCreatorTest::OnProfileCreated, base::Unretained(this), creator_loop.QuitClosure())); profile_added_loop.Run();
diff --git a/chrome/browser/signin/dice_web_signin_interceptor.cc b/chrome/browser/signin/dice_web_signin_interceptor.cc index 6272dacc..01684db 100644 --- a/chrome/browser/signin/dice_web_signin_interceptor.cc +++ b/chrome/browser/signin/dice_web_signin_interceptor.cc
@@ -265,11 +265,23 @@ return; } + std::string profile_name; + base::Optional<AccountInfo> account_info = + identity_manager_ + ->FindExtendedAccountInfoForAccountWithRefreshTokenByAccountId( + account_id_); + if (account_info) { + bool is_managed = !account_info->hosted_domain.empty() && + account_info->hosted_domain != kNoHostedDomainFound; + profile_name = + is_managed ? account_info->hosted_domain : account_info->given_name; + } + DCHECK(!dice_signed_in_profile_creator_); // Unretained is fine because the profile creator is owned by this. dice_signed_in_profile_creator_ = std::make_unique<DiceSignedInProfileCreator>( - profile_, account_id_, + profile_, account_id_, profile_name, base::BindOnce(&DiceWebSigninInterceptor::OnNewSignedInProfileCreated, base::Unretained(this))); }
diff --git a/chrome/browser/signin/dice_web_signin_interceptor_browsertest.cc b/chrome/browser/signin/dice_web_signin_interceptor_browsertest.cc index aeca348..68a2d6d 100644 --- a/chrome/browser/signin/dice_web_signin_interceptor_browsertest.cc +++ b/chrome/browser/signin/dice_web_signin_interceptor_browsertest.cc
@@ -5,7 +5,10 @@ #include "chrome/browser/signin/dice_web_signin_interceptor.h" #include "base/scoped_observer.h" +#include "base/strings/utf_string_conversions.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/profiles/profile_attributes_entry.h" +#include "chrome/browser/profiles/profile_attributes_storage.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/profiles/profile_manager_observer.h" #include "chrome/browser/signin/chrome_signin_client_factory.h" @@ -181,6 +184,15 @@ EXPECT_TRUE(new_identity_manager->HasAccountWithRefreshToken( account_info.account_id)); + // Check the profile name. + ProfileAttributesEntry* entry = nullptr; + ProfileAttributesStorage& storage = + g_browser_process->profile_manager()->GetProfileAttributesStorage(); + ASSERT_TRUE( + storage.GetProfileAttributesWithPath(new_profile->GetPath(), &entry)); + ASSERT_TRUE(entry); + EXPECT_EQ("givenname", base::UTF16ToUTF8(entry->GetLocalProfileName())); + // Add the account to the cookies (simulates the account reconcilor). EXPECT_EQ(BrowserList::GetInstance()->size(), 1u); signin::SetCookieAccounts(new_identity_manager, test_url_loader_factory(),
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabData.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabData.java index 1d107bc6..788bae1 100644 --- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabData.java +++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabData.java
@@ -19,7 +19,6 @@ import org.chromium.chrome.browser.tab.TabLaunchType; import org.chromium.chrome.browser.tab.WebContentsState; import org.chromium.chrome.browser.tab.proto.CriticalPersistedTabData.CriticalPersistedTabDataProto; -import org.chromium.url.GURL; import java.nio.ByteBuffer; import java.util.Locale; @@ -39,11 +38,6 @@ * Title of the ContentViews webpage. */ private String mTitle; - - /** - * URL of the page currently loading. Used as a fall-back in case tab restore fails. - */ - private GURL mUrl; private int mParentId; private int mRootId; private long mTimestampMillis; @@ -324,21 +318,6 @@ } /** - * @return {@link GURL} for the {@link Tab} - */ - public GURL getUrl() { - return mUrl; - } - - /** - * Set {@link GURL} for the {@link Tab} - * @param url to set - */ - public void setUrl(GURL url) { - mUrl = url; - } - - /** * @return identifier for the {@link Tab} */ public int getTabId() {
diff --git a/chrome/browser/ui/ash/in_session_auth_dialog_client.cc b/chrome/browser/ui/ash/in_session_auth_dialog_client.cc index ef99b31..a078d4f8 100644 --- a/chrome/browser/ui/ash/in_session_auth_dialog_client.cc +++ b/chrome/browser/ui/ash/in_session_auth_dialog_client.cc
@@ -10,8 +10,11 @@ #include "base/bind.h" #include "base/logging.h" #include "base/strings/utf_string_conversions.h" +#include "chrome/browser/chromeos/login/quick_unlock/fingerprint_storage.h" +#include "chrome/browser/chromeos/login/quick_unlock/pin_backend.h" #include "chrome/browser/chromeos/login/quick_unlock/quick_unlock_factory.h" #include "chrome/browser/chromeos/login/quick_unlock/quick_unlock_storage.h" +#include "components/account_id/account_id.h" #include "components/user_manager/user_manager.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" @@ -49,6 +52,22 @@ return g_auth_dialog_client_instance; } +bool InSessionAuthDialogClient::IsFingerprintAuthAvailable( + const AccountId& account_id) { + chromeos::quick_unlock::QuickUnlockStorage* quick_unlock_storage = + chromeos::quick_unlock::QuickUnlockFactory::GetForAccountId(account_id); + return quick_unlock_storage && + quick_unlock_storage->fingerprint_storage()->IsFingerprintAvailable(); +} + +void InSessionAuthDialogClient::CheckPinAuthAvailability( + const AccountId& account_id, + base::OnceCallback<void(bool)> callback) { + // PinBackend may be using cryptohome backend or prefs backend. + chromeos::quick_unlock::PinBackend::GetInstance()->CanAuthenticate( + account_id, std::move(callback)); +} + void InSessionAuthDialogClient::AuthenticateUserWithPasswordOrPin( const std::string& password, bool authenticated_by_pin,
diff --git a/chrome/browser/ui/ash/in_session_auth_dialog_client.h b/chrome/browser/ui/ash/in_session_auth_dialog_client.h index f1c84e5..6d92d8d 100644 --- a/chrome/browser/ui/ash/in_session_auth_dialog_client.h +++ b/chrome/browser/ui/ash/in_session_auth_dialog_client.h
@@ -14,6 +14,8 @@ #include "chromeos/login/auth/extended_authenticator.h" #include "chromeos/login/auth/user_context.h" +class AccountId; + // Handles method calls sent from Ash to ChromeOS. class InSessionAuthDialogClient : public ash::InSessionAuthDialogClient, public chromeos::AuthStatusConsumer { @@ -34,6 +36,10 @@ const std::string& password, bool authenticated_by_pin, AuthenticateCallback callback) override; + bool IsFingerprintAuthAvailable(const AccountId& account_id) override; + void CheckPinAuthAvailability( + const AccountId& account_id, + base::OnceCallback<void(bool)> callback) override; // AuthStatusConsumer: void OnAuthFailure(const chromeos::AuthFailure& error) override;
diff --git a/chrome/browser/ui/blocked_content/popup_blocker_browsertest.cc b/chrome/browser/ui/blocked_content/popup_blocker_browsertest.cc index 37a3ec2..6dc0cf6 100644 --- a/chrome/browser/ui/blocked_content/popup_blocker_browsertest.cc +++ b/chrome/browser/ui/blocked_content/popup_blocker_browsertest.cc
@@ -269,8 +269,8 @@ kDontCheckTitle); } -#if defined(OS_MAC) && defined(ADDRESS_SANITIZER) -// Flaky on ASAN on Mac. See https://crbug.com/674497. +// TODO(crbug.com/1115886): Flaky on Mac ASAN and Chrome OS. +#if (defined(OS_MAC) && defined(ADDRESS_SANITIZER)) || defined(OS_CHROMEOS) #define MAYBE_BlockWebContentsCreationIncognito \ DISABLED_BlockWebContentsCreationIncognito #else
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc index 6689b358..af67ed8 100644 --- a/chrome/browser/ui/browser.cc +++ b/chrome/browser/ui/browser.cc
@@ -1491,6 +1491,20 @@ return SwapWebContents(predecessor_contents, std::move(portal_contents)); } +void Browser::UpdateInspectedWebContentsIfNecessary( + content::WebContents* old_contents, + content::WebContents* new_contents, + base::OnceCallback<void()> callback) { + DevToolsWindow* dev_tools_window = + DevToolsWindow::GetInstanceForInspectedWebContents(old_contents); + if (dev_tools_window) { + dev_tools_window->UpdateInspectedWebContents(new_contents, + std::move(callback)); + } else { + std::move(callback).Run(); + } +} + std::unique_ptr<content::WebContents> Browser::SwapWebContents( content::WebContents* old_contents, std::unique_ptr<content::WebContents> new_contents) { @@ -1506,11 +1520,6 @@ new_view->TakeFallbackContentFrom(old_view); } - DevToolsWindow* dev_tools_window = - DevToolsWindow::GetInstanceForInspectedWebContents(old_contents); - if (dev_tools_window) - dev_tools_window->UpdateInspectedWebContents(new_contents.get()); - // TODO(crbug.com/836409): TabLoadTracker should not rely on being notified // directly about tab contents swaps. resource_coordinator::TabLoadTracker::Get()->SwapTabContents(
diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h index 44b517f0..443a039 100644 --- a/chrome/browser/ui/browser.h +++ b/chrome/browser/ui/browser.h
@@ -610,6 +610,10 @@ std::unique_ptr<content::WebContents> ActivatePortalWebContents( content::WebContents* predecessor_contents, std::unique_ptr<content::WebContents> portal_contents) override; + void UpdateInspectedWebContentsIfNecessary( + content::WebContents* old_contents, + content::WebContents* new_contents, + base::OnceCallback<void()> callback) override; bool ShouldShowStaleContentOnEviction(content::WebContents* source) override; bool IsFrameLowPriority( const content::WebContents* web_contents,
diff --git a/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc b/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc index e804f54..a3692e25 100644 --- a/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc +++ b/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc
@@ -13,6 +13,7 @@ #include "base/timer/timer.h" #include "build/build_config.h" #include "chrome/app/chrome_command_ids.h" +#include "chrome/browser/feature_engagement/tracker_factory.h" #include "chrome/browser/password_manager/account_password_store_factory.h" #include "chrome/browser/password_manager/chrome_password_manager_client.h" #include "chrome/browser/password_manager/password_store_factory.h" @@ -36,6 +37,7 @@ #include "chrome/common/url_constants.h" #include "chrome/grit/generated_resources.h" #include "components/browsing_data/content/browsing_data_helper.h" +#include "components/feature_engagement/public/tracker.h" #include "components/password_manager/core/browser/browser_save_password_progress_logger.h" #include "components/password_manager/core/browser/form_saver_impl.h" #include "components/password_manager/core/browser/password_bubble_experiment.h" @@ -503,6 +505,19 @@ } save_fallback_timer_.Stop(); passwords_data_.form_manager()->Save(); + + if (base::FeatureList::IsEnabled( + password_manager::features::kEnablePasswordsAccountStorage)) { + // If we just saved a password to the account store, notify the IPH tracker + // about it (so it can decide not to show the IPH again). + if (GetPasswordFeatureManager()->GetDefaultPasswordStore() == + autofill::PasswordForm::Store::kAccountStore) { + feature_engagement::TrackerFactory::GetForBrowserContext( + Profile::FromBrowserContext(web_contents()->GetBrowserContext())) + ->NotifyEvent("passwords_account_storage_used"); + } + } + if (base::FeatureList::IsEnabled( password_manager::features::kCompromisedPasswordsReengagement)) { post_save_compromised_helper_ =
diff --git a/chrome/browser/ui/signin/dice_web_signin_interceptor_delegate.cc b/chrome/browser/ui/signin/dice_web_signin_interceptor_delegate.cc index f120248..9910433c 100644 --- a/chrome/browser/ui/signin/dice_web_signin_interceptor_delegate.cc +++ b/chrome/browser/ui/signin/dice_web_signin_interceptor_delegate.cc
@@ -17,9 +17,9 @@ content::WebContents* web_contents, const BubbleParameters& bubble_parameters, base::OnceCallback<void(bool)> callback) { - if (bubble_parameters.interception_type != - DiceWebSigninInterceptor::SigninInterceptionType::kEnterprise) { - // Only the enterprise interception is currently implemented. + if (bubble_parameters.interception_type == + DiceWebSigninInterceptor::SigninInterceptionType::kProfileSwitch) { + // The bubble for profile switch is not implemented. std::move(callback).Run(false); return; }
diff --git a/chrome/browser/ui/signin_reauth_view_controller.cc b/chrome/browser/ui/signin_reauth_view_controller.cc index b5d08bc..fc0cf00 100644 --- a/chrome/browser/ui/signin_reauth_view_controller.cc +++ b/chrome/browser/ui/signin_reauth_view_controller.cc
@@ -13,6 +13,7 @@ #include "base/optional.h" #include "base/task_runner.h" #include "base/time/time.h" +#include "chrome/browser/consent_auditor/consent_auditor_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/signin/reauth_result.h" #include "chrome/browser/signin/reauth_tab_helper.h" @@ -21,6 +22,7 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_navigator_params.h" #include "chrome/browser/ui/webui/signin/signin_reauth_ui.h" +#include "components/consent_auditor/consent_auditor.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/site_instance.h" @@ -125,10 +127,15 @@ CompleteReauth(signin::ReauthResult::kDismissedByUser); } -void SigninReauthViewController::OnReauthConfirmed() { +void SigninReauthViewController::OnReauthConfirmed( + sync_pb::UserConsentTypes::AccountPasswordsConsent consent) { if (user_confirmed_reauth_) return; + // Cache the consent. It will be actually recorded later, in CompleteReauth(), + // if the user successfully completed the reauth. + consent_ = consent; + user_confirmed_reauth_ = true; user_confirmed_reauth_time_ = base::TimeTicks::Now(); OnStateChanged(); @@ -219,6 +226,12 @@ raw_reauth_web_contents_ = nullptr; } + if (result == signin::ReauthResult::kSuccess) { + CHECK(consent_.has_value()); + ConsentAuditorFactory::GetForProfile(browser_->profile()) + ->RecordAccountPasswordsConsent(account_id_, *consent_); + } + signin_ui_util::RecordTransactionalReauthResult(access_point_, result); if (reauth_callback_) std::move(reauth_callback_).Run(result);
diff --git a/chrome/browser/ui/signin_reauth_view_controller.h b/chrome/browser/ui/signin_reauth_view_controller.h index 3a52cc5..b256ea7 100644 --- a/chrome/browser/ui/signin_reauth_view_controller.h +++ b/chrome/browser/ui/signin_reauth_view_controller.h
@@ -13,6 +13,7 @@ #include "base/time/time.h" #include "chrome/browser/ui/signin_view_controller_delegate.h" #include "components/signin/public/base/signin_metrics.h" +#include "components/sync/protocol/user_consent_types.pb.h" #include "google_apis/gaia/core_account_id.h" class Browser; @@ -134,7 +135,8 @@ // Called when the user clicks the confirm button in the reauth confirmation // dialog. // This happens before the Gaia reauth page is shown. - void OnReauthConfirmed(); + void OnReauthConfirmed( + sync_pb::UserConsentTypes::AccountPasswordsConsent consent); // Called when the user clicks the cancel button in the reauth confirmation // dialog. // This happens before the Gaia reauth page is shown. @@ -199,6 +201,7 @@ // The state of the reauth flow. bool user_confirmed_reauth_ = false; + base::Optional<sync_pb::UserConsentTypes::AccountPasswordsConsent> consent_; GaiaReauthPageState gaia_reauth_page_state_ = GaiaReauthPageState::kStarted; base::Optional<signin::ReauthResult> gaia_reauth_page_result_;
diff --git a/chrome/browser/ui/signin_reauth_view_controller_browsertest.cc b/chrome/browser/ui/signin_reauth_view_controller_browsertest.cc index 4d84afc..b0f0e5e6 100644 --- a/chrome/browser/ui/signin_reauth_view_controller_browsertest.cc +++ b/chrome/browser/ui/signin_reauth_view_controller_browsertest.cc
@@ -300,6 +300,7 @@ IN_PROC_BROWSER_TEST_F(SigninReauthViewControllerBrowserTest, CancelReauthDialog) { ShowReauthPrompt(); + RedirectGaiaChallengeTo(https_server()->GetURL(kReauthDonePath)); ASSERT_TRUE(login_ui_test_utils::CancelReauthConfirmationDialog( browser(), kReauthDialogTimeout)); EXPECT_EQ(WaitForReauthResult(), signin::ReauthResult::kDismissedByUser); @@ -312,17 +313,26 @@ IN_PROC_BROWSER_TEST_F(SigninReauthViewControllerBrowserTest, GaiaChallengeLoadFailed) { ShowReauthPrompt(); - ASSERT_TRUE(login_ui_test_utils::ConfirmReauthConfirmationDialog( - browser(), kReauthDialogTimeout)); + + // Make the Gaia page fail to load. const GURL target_url = https_server()->GetURL("/close-socket"); content::TestNavigationObserver target_content_observer(target_url); target_content_observer.WatchExistingWebContents(); RedirectGaiaChallengeTo(target_url); target_content_observer.Wait(); + EXPECT_TRUE(browser()->signin_view_controller()->ShowsModalDialog()); EXPECT_FALSE(target_content_observer.last_navigation_succeeded()); - // Check that |kLoadFailed| is returned as the result. + // Now confirm the pre-reauth confirmation dialog, and wait for the Gaia page + // (an error page in this case) to show up. + ReauthTestObserver reauth_observer(signin_reauth_view_controller()); + ASSERT_TRUE(login_ui_test_utils::ConfirmReauthConfirmationDialog( + browser(), kReauthDialogTimeout)); + reauth_observer.WaitUntilGaiaReauthPageIsShown(); + + // Close the modal dialog and check that |kLoadFailed| is returned as the + // result. SimulateCloseButtonClick(); EXPECT_EQ(WaitForReauthResult(), signin::ReauthResult::kLoadFailed); EXPECT_THAT( @@ -337,7 +347,7 @@ // Tests clicking on the confirm button in the reauth dialog. Reauth completes // before the confirmation. IN_PROC_BROWSER_TEST_F(SigninReauthViewControllerBrowserTest, - ConfirmReauthDialog_AfterReauthSuccess) { + ConfirmReauthDialog) { ShowReauthPrompt(); RedirectGaiaChallengeTo(https_server()->GetURL(kReauthDonePath)); ASSERT_TRUE(login_ui_test_utils::ConfirmReauthConfirmationDialog( @@ -355,27 +365,6 @@ kReauthGaiaNavigationDurationFromConfirmClickHistogramName, 1); } -// Tests clicking on the confirm button in the reauth dialog. Reauth completes -// after the confirmation. -IN_PROC_BROWSER_TEST_F(SigninReauthViewControllerBrowserTest, - ConfirmReauthDialog_BeforeReauthSuccess) { - ShowReauthPrompt(); - ASSERT_TRUE(login_ui_test_utils::ConfirmReauthConfirmationDialog( - browser(), kReauthDialogTimeout)); - RedirectGaiaChallengeTo(https_server()->GetURL(kReauthDonePath)); - EXPECT_EQ(WaitForReauthResult(), signin::ReauthResult::kSuccess); - histogram_tester()->ExpectUniqueSample( - kReauthUserActionHistogramName, - SigninReauthViewController::UserAction::kClickConfirmButton, 1); - histogram_tester()->ExpectUniqueSample( - kReauthUserActionToFillPasswordHistogramName, - SigninReauthViewController::UserAction::kClickConfirmButton, 1); - histogram_tester()->ExpectTotalCount( - kReauthGaiaNavigationDurationFromReauthStartHistogramName, 1); - histogram_tester()->ExpectTotalCount( - kReauthGaiaNavigationDurationFromConfirmClickHistogramName, 1); -} - // Tests completing the Gaia reauth challenge in a dialog. IN_PROC_BROWSER_TEST_F(SigninReauthViewControllerBrowserTest, CompleteReauthInDialog) {
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc index 8b490f8..59d5eeb 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc
@@ -3264,7 +3264,8 @@ // Tests that in the reveal-on-hover field trial variation (without // hide-on-interaction), the path is faded back in after focus, then blur, then // hover. -TEST_P(OmniboxViewViewsRevealOnHoverTest, AfterBlur) { +// TODO(crbug.com/1115551): Test is flaky. +TEST_P(OmniboxViewViewsRevealOnHoverTest, DISABLED_AfterBlur) { SetUpSimplifiedDomainTest(); // Focus and blur the omnibox, then hover over it. The URL should unelide.
diff --git a/chrome/browser/ui/views/passwords/password_save_update_with_account_store_view.cc b/chrome/browser/ui/views/passwords/password_save_update_with_account_store_view.cc index 588de90..e548ee4 100644 --- a/chrome/browser/ui/views/passwords/password_save_update_with_account_store_view.cc +++ b/chrome/browser/ui/views/passwords/password_save_update_with_account_store_view.cc
@@ -505,12 +505,21 @@ void PasswordSaveUpdateWithAccountStoreView::OnPerformAction( views::Combobox* combobox) { - controller_.OnToggleAccountStore( - /*is_account_store_selected=*/combobox->GetSelectedIndex() == 0); + bool is_account_store_selected = combobox->GetSelectedIndex() == 0; + controller_.OnToggleAccountStore(is_account_store_selected); + // If the user explicitly switched to "save on this device only", record this + // with the IPH tracker (so it can decide not to show the IPH again). + if (!is_account_store_selected) { + if (!iph_tracker_) { + iph_tracker_ = feature_engagement::TrackerFactory::GetForBrowserContext( + controller_.GetProfile()); + } + iph_tracker_->NotifyEvent("passwords_account_storage_unselected"); + } // The IPH shown upon failure in reauth is used to informs the user that the // password will be stored on device. This is why it's important to close it // if the user changes the destination to account. - if (currenly_shown_iph_type == IPHType::kFailedReauth) + if (currenly_shown_iph_type_ == IPHType::kFailedReauth) CloseIPHBubbleIfOpen(); } @@ -521,12 +530,12 @@ observed_account_storage_promo_.Remove(widget); // If the reauth failed, we have shown the IPH unconditionally. No need to // inform the tracker. Only regular IPH's are tracked - if (currenly_shown_iph_type == IPHType::kRegular) { + if (currenly_shown_iph_type_ == IPHType::kRegular) { DCHECK(iph_tracker_); iph_tracker_->Dismissed( feature_engagement::kIPHPasswordsAccountStorageFeature); } - currenly_shown_iph_type = IPHType::kNone; + currenly_shown_iph_type_ = IPHType::kNone; account_storage_promo_ = nullptr; } } @@ -730,7 +739,7 @@ set_close_on_deactivate(close_save_bubble_on_deactivate_original_value); observed_account_storage_promo_.Add(account_storage_promo_->GetWidget()); - currenly_shown_iph_type = type; + currenly_shown_iph_type_ = type; } void PasswordSaveUpdateWithAccountStoreView::CloseIPHBubbleIfOpen() {
diff --git a/chrome/browser/ui/views/passwords/password_save_update_with_account_store_view.h b/chrome/browser/ui/views/passwords/password_save_update_with_account_store_view.h index 4ed037c..a2154ac 100644 --- a/chrome/browser/ui/views/passwords/password_save_update_with_account_store_view.h +++ b/chrome/browser/ui/views/passwords/password_save_update_with_account_store_view.h
@@ -132,7 +132,7 @@ // its NativeWidget. FeaturePromoBubbleView* account_storage_promo_ = nullptr; - IPHType currenly_shown_iph_type = IPHType::kNone; + IPHType currenly_shown_iph_type_ = IPHType::kNone; // Observes the |account_storage_promo_|'s Widget. Used to tell whether the // promo is open and get called back when it closes.
diff --git a/chrome/browser/ui/views/payments/payment_handler_web_flow_view_controller.cc b/chrome/browser/ui/views/payments/payment_handler_web_flow_view_controller.cc index 9ad892d6..7cd2eb1f 100644 --- a/chrome/browser/ui/views/payments/payment_handler_web_flow_view_controller.cc +++ b/chrome/browser/ui/views/payments/payment_handler_web_flow_view_controller.cc
@@ -10,21 +10,14 @@ #include "chrome/app/vector_icons/vector_icons.h" #include "chrome/browser/payments/ssl_validity_checker.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/themes/theme_service.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_tabstrip.h" -#include "chrome/browser/ui/omnibox/omnibox_theme.h" #include "chrome/browser/ui/views/payments/payment_request_dialog_view.h" #include "chrome/browser/ui/views/payments/payment_request_views_util.h" #include "chrome/grit/generated_resources.h" -#include "components/omnibox/browser/location_bar_model_util.h" #include "components/payments/content/icon/icon_size.h" -#include "components/payments/core/features.h" #include "components/payments/core/native_error_strings.h" -#include "components/payments/core/payments_experimental_features.h" #include "components/payments/core/url_util.h" -#include "components/security_state/core/security_state.h" -#include "components/vector_icons/vector_icons.h" #include "components/web_modal/web_contents_modal_dialog_manager.h" #include "components/web_modal/web_contents_modal_dialog_manager_delegate.h" #include "content/public/browser/navigation_handle.h" @@ -36,7 +29,6 @@ #include "ui/gfx/color_palette.h" #include "ui/gfx/color_utils.h" #include "ui/gfx/image/image_skia.h" -#include "ui/gfx/paint_vector_icon.h" #include "ui/views/background.h" #include "ui/views/border.h" #include "ui/views/controls/image_view.h" @@ -71,8 +63,6 @@ ReadOnlyOriginView(const base::string16& page_title, const GURL& origin, const SkBitmap* icon_bitmap, - Profile* profile, - security_state::SecurityLevel security_level, SkColor background_color, views::ButtonListener* site_settings_listener) { auto title_origin_container = std::make_unique<views::View>(); @@ -100,30 +90,8 @@ title_label->SetEnabledColor(foreground); } - auto origin_container = std::make_unique<views::View>(); - views::GridLayout* origin_layout = origin_container->SetLayoutManager( - std::make_unique<views::GridLayout>()); - - columns = origin_layout->AddColumnSet(0); - columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER, - 1.0, views::GridLayout::ColumnSize::kUsePreferred, 0, 0); - columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::LEADING, - 1.0, views::GridLayout::ColumnSize::kUsePreferred, 0, 0); - origin_layout->StartRow(views::GridLayout::kFixedSize, 0); - if (PaymentsExperimentalFeatures::IsEnabled( - features::kPaymentHandlerSecurityIcon)) { - // TODO(https://crbug.com/1052493): - // Selecting the correct icon based on the SSL certificate state - // and adding test coverage for this code path. - auto security_icon = std::make_unique<views::ImageView>(); - const ui::ThemeProvider& theme_provider = - ThemeService::GetThemeProviderForProfile(profile); - security_icon->SetImage(gfx::CreateVectorIcon( - location_bar_model::GetSecurityVectorIcon(security_level), 16, - GetOmniboxSecurityChipColor(&theme_provider, security_level))); - origin_layout->AddView(std::move(security_icon)); - } - auto* origin_label = origin_layout->AddView( + title_origin_layout->StartRow(views::GridLayout::kFixedSize, 0); + auto* origin_label = title_origin_layout->AddView( std::make_unique<views::Label>(base::UTF8ToUTF16(origin.host()))); origin_label->SetElideBehavior(gfx::ELIDE_HEAD); if (!title_is_valid) { @@ -140,8 +108,6 @@ origin_label->SetAutoColorReadabilityEnabled(false); origin_label->SetEnabledColor(foreground); origin_label->SetBackgroundColor(background_color); - title_origin_layout->StartRow(views::GridLayout::kFixedSize, 0); - title_origin_layout->AddView(std::move(origin_container)); views::GridLayout* top_level_layout = SetLayoutManager(std::make_unique<views::GridLayout>()); @@ -272,10 +238,7 @@ GetHeaderBackground(header_view); return std::make_unique<ReadOnlyOriginView>( GetPaymentHandlerDialogTitle(web_contents()), origin, - state()->selected_app()->icon_bitmap(), profile_, - web_contents() ? SslValidityChecker::GetSecurityLevel(web_contents()) - : security_state::NONE, - background->get_color(), this); + state()->selected_app()->icon_bitmap(), background->get_color(), this); } std::unique_ptr<views::Background> @@ -304,11 +267,8 @@ void PaymentHandlerWebFlowViewController::VisibleSecurityStateChanged( content::WebContents* source) { DCHECK_EQ(source, web_contents()); - if (!SslValidityChecker::IsValidPageInPaymentHandlerWindow(source)) { + if (!SslValidityChecker::IsValidPageInPaymentHandlerWindow(source)) AbortPayment(); - } else { - UpdateHeaderView(); - } } void PaymentHandlerWebFlowViewController::DidStartNavigation(
diff --git a/chrome/browser/ui/views/profiles/incognito_menu_view.cc b/chrome/browser/ui/views/profiles/incognito_menu_view.cc index f4eac332..67d7d51f 100644 --- a/chrome/browser/ui/views/profiles/incognito_menu_view.cc +++ b/chrome/browser/ui/views/profiles/incognito_menu_view.cc
@@ -26,6 +26,12 @@ #include "ui/views/controls/image_view.h" #include "ui/views/style/typography.h" +#if defined(OS_WIN) +#include "chrome/browser/browser_process.h" +#include "chrome/browser/profiles/profile_manager.h" +#include "chrome/common/chrome_features.h" +#endif + IncognitoMenuView::IncognitoMenuView(views::Button* anchor_button, Browser* browser) : ProfileMenuViewBase(anchor_button, browser) { @@ -57,6 +63,19 @@ incognito_window_count) : base::string16()); +#if defined(OS_WIN) + if (ProfileShortcutManager::IsFeatureEnabled() && + base::FeatureList::IsEnabled( + features::kEnableIncognitoShortcutOnDesktop)) { + // TODO(crbug.com/1113162): Add desktop shortcut icon to the menu entry. + AddFeatureButton( + l10n_util::GetStringUTF16( + IDS_INCOGNITO_PROFILE_MENU_CREATE_SHORTCUT_BUTTON), + base::BindRepeating(&IncognitoMenuView::OnCreateShortcutButtonClicked, + base::Unretained(this))); + } +#endif + AddFeatureButton( l10n_util::GetStringUTF16(IDS_INCOGNITO_PROFILE_MENU_CLOSE_BUTTON), base::BindRepeating(&IncognitoMenuView::OnExitButtonClicked, @@ -71,6 +90,19 @@ browser()->profile())); } +#if defined(OS_WIN) +void IncognitoMenuView::OnCreateShortcutButtonClicked() { + RecordClick(ActionableItem::kCreateIncognitoShortcutButton); + ProfileShortcutManager* shortcut_manager = + g_browser_process->profile_manager()->profile_shortcut_manager(); + + DCHECK(shortcut_manager); + if (shortcut_manager) + shortcut_manager->CreateIncognitoProfileShortcut( + browser()->profile()->GetPath()); +} +#endif + void IncognitoMenuView::OnExitButtonClicked() { RecordClick(ActionableItem::kExitProfileButton); base::RecordAction(base::UserMetricsAction("IncognitoMenu_ExitClicked"));
diff --git a/chrome/browser/ui/views/profiles/incognito_menu_view.h b/chrome/browser/ui/views/profiles/incognito_menu_view.h index 92dc032..60c25ba 100644 --- a/chrome/browser/ui/views/profiles/incognito_menu_view.h +++ b/chrome/browser/ui/views/profiles/incognito_menu_view.h
@@ -10,6 +10,7 @@ #include <memory> #include "base/macros.h" +#include "build/build_config.h" #include "chrome/browser/ui/views/profiles/profile_menu_view_base.h" namespace views { @@ -34,6 +35,9 @@ base::string16 GetAccessibleWindowTitle() const override; // Button actions. +#if defined(OS_WIN) + void OnCreateShortcutButtonClicked(); +#endif void OnExitButtonClicked(); DISALLOW_COPY_AND_ASSIGN(IncognitoMenuView);
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view_base.h b/chrome/browser/ui/views/profiles/profile_menu_view_base.h index c2641d7..045c45d8 100644 --- a/chrome/browser/ui/views/profiles/profile_menu_view_base.h +++ b/chrome/browser/ui/views/profiles/profile_menu_view_base.h
@@ -63,7 +63,8 @@ kAddNewProfileButton = 15, kSyncSettingsButton = 16, kEditProfileButton = 17, - kMaxValue = kEditProfileButton, + kCreateIncognitoShortcutButton = 18, + kMaxValue = kCreateIncognitoShortcutButton, }; enum class SyncInfoContainerBackgroundState {
diff --git a/chrome/browser/ui/views/read_later/read_later_bubble_view_browsertest.cc b/chrome/browser/ui/views/read_later/read_later_bubble_view_browsertest.cc index 872b2cf4..4de2c36 100644 --- a/chrome/browser/ui/views/read_later/read_later_bubble_view_browsertest.cc +++ b/chrome/browser/ui/views/read_later/read_later_bubble_view_browsertest.cc
@@ -7,6 +7,7 @@ #include <string> #include "base/test/scoped_feature_list.h" +#include "build/build_config.h" #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_commands.h" @@ -54,6 +55,12 @@ DISALLOW_COPY_AND_ASSIGN(ReadLaterBubbleViewBrowserTest); }; -IN_PROC_BROWSER_TEST_F(ReadLaterBubbleViewBrowserTest, InvokeUi_default) { +// TODO(1115950): Flaky on Windows. +#if defined(OS_WIN) +#define MAYBE_InvokeUi_default DISABLED_InvokeUi_default +#else +#define MAYBE_InvokeUi_default InvokeUi_default +#endif +IN_PROC_BROWSER_TEST_F(ReadLaterBubbleViewBrowserTest, MAYBE_InvokeUi_default) { ShowAndVerifyUi(); }
diff --git a/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc b/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc index dd9f6d9..4926ee5 100644 --- a/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc +++ b/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc
@@ -711,6 +711,9 @@ } void TabHoverCardBubbleView::FadeInToShow() { + // Make sure the hover card isn't accidentally shown if the anchor is gone. + if (!GetAnchorView()) + return; fade_animation_delegate_->FadeIn(); }
diff --git a/chrome/browser/ui/web_applications/web_app_browser_controller.cc b/chrome/browser/ui/web_applications/web_app_browser_controller.cc index f70e6c8..435db0d7 100644 --- a/chrome/browser/ui/web_applications/web_app_browser_controller.cc +++ b/chrome/browser/ui/web_applications/web_app_browser_controller.cc
@@ -48,7 +48,8 @@ bool WebAppBrowserController::HasMinimalUiButtons() const { if (has_tab_strip()) return false; - DisplayMode app_display_mode = registrar().GetAppDisplayMode(GetAppId()); + DisplayMode app_display_mode = + registrar().GetEffectiveDisplayModeFromManifest(GetAppId()); return app_display_mode == DisplayMode::kBrowser || app_display_mode == DisplayMode::kMinimalUi; }
diff --git a/chrome/browser/ui/web_applications/web_app_browsertest.cc b/chrome/browser/ui/web_applications/web_app_browsertest.cc index 1a7c7d27..0df6439 100644 --- a/chrome/browser/ui/web_applications/web_app_browsertest.cc +++ b/chrome/browser/ui/web_applications/web_app_browsertest.cc
@@ -295,6 +295,8 @@ /*open_as_window=*/true)); EXPECT_FALSE(has_buttons(DisplayMode::kStandalone, /*open_as_window=*/true)); + EXPECT_FALSE(has_buttons(DisplayMode::kFullscreen, + /*open_as_window=*/true)); EXPECT_TRUE(has_buttons(DisplayMode::kBrowser, /*open_as_window=*/false)); @@ -302,6 +304,8 @@ /*open_as_window=*/false)); EXPECT_FALSE(has_buttons(DisplayMode::kStandalone, /*open_as_window=*/false)); + EXPECT_FALSE(has_buttons(DisplayMode::kFullscreen, + /*open_as_window=*/false)); } IN_PROC_BROWSER_TEST_P(WebAppBrowserTest_DisplayOverride, DisplayOverride) { @@ -321,6 +325,63 @@ EXPECT_EQ(DisplayMode::kStandalone, app_display_mode_override[1]); } +IN_PROC_BROWSER_TEST_P(WebAppBrowserTest_DisplayOverride, HasMinimalUiButtons) { + int index = 0; + auto has_buttons = [this, &index](DisplayMode display_override_mode, + bool open_as_window) -> bool { + base::HistogramTester tester; + const std::string base_url = "https://example.com/path"; + auto web_app_info = std::make_unique<WebApplicationInfo>(); + web_app_info->app_url = GURL(base_url + base::NumberToString(index++)); + web_app_info->scope = web_app_info->app_url; + + DisplayMode display_mode = DisplayMode::kStandalone; + + if (display_override_mode == DisplayMode::kFullscreen || + display_override_mode == DisplayMode::kStandalone) { + display_mode = DisplayMode::kMinimalUi; + } + + web_app_info->display_mode = display_mode; + web_app_info->open_as_window = open_as_window; + web_app_info->display_override.push_back(display_override_mode); + + AppId app_id = InstallWebApp(std::move(web_app_info)); + Browser* app_browser = LaunchWebAppBrowser(app_id); + DCHECK(app_browser->app_controller()); + tester.ExpectUniqueSample(kLaunchWebAppDisplayModeHistogram, display_mode, + 1); + + bool matches; + EXPECT_TRUE(ExecuteScriptAndExtractBool( + app_browser->tab_strip_model()->GetActiveWebContents(), + "window.domAutomationController.send(window.matchMedia('(display-mode: " + "minimal-ui)').matches)", + &matches)); + EXPECT_EQ(app_browser->app_controller()->HasMinimalUiButtons(), matches); + + return matches; + }; + + EXPECT_TRUE(has_buttons(DisplayMode::kBrowser, + /*open_as_window=*/true)); + EXPECT_TRUE(has_buttons(DisplayMode::kMinimalUi, + /*open_as_window=*/true)); + EXPECT_FALSE(has_buttons(DisplayMode::kStandalone, + /*open_as_window=*/true)); + EXPECT_FALSE(has_buttons(DisplayMode::kFullscreen, + /*open_as_window=*/true)); + + EXPECT_TRUE(has_buttons(DisplayMode::kBrowser, + /*open_as_window=*/false)); + EXPECT_TRUE(has_buttons(DisplayMode::kMinimalUi, + /*open_as_window=*/false)); + EXPECT_FALSE(has_buttons(DisplayMode::kStandalone, + /*open_as_window=*/false)); + EXPECT_FALSE(has_buttons(DisplayMode::kFullscreen, + /*open_as_window=*/false)); +} + // Tests that desktop PWAs open links in the browser. IN_PROC_BROWSER_TEST_P(WebAppBrowserTest, DesktopPWAsOpenLinksInApp) { const GURL app_url = GetSecureAppURL();
diff --git a/chrome/browser/ui/webui/chromeos/login/update_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/update_screen_handler.cc index ead15df7..ea640407 100644 --- a/chrome/browser/ui/webui/chromeos/login/update_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/update_screen_handler.cc
@@ -62,6 +62,10 @@ CallJS("login.UpdateScreen.setUpdateCompleted", value); } +void UpdateScreenHandler::SetManualRebootNeeded(bool value) { + CallJS("login.UpdateScreen.setManualRebootNeeded", value); +} + void UpdateScreenHandler::SetShowCurtain(bool value) { CallJS("login.UpdateScreen.showUpdateCurtain", value); } @@ -92,6 +96,7 @@ builder->AddF("installingUpdateDesc", IDS_UPDATE_MSG, ui::GetChromeOSDeviceName()); builder->Add("updateCompeletedMsg", IDS_UPDATE_COMPLETED); + builder->Add("updateCompeletedRebootingMsg", IDS_UPDATE_COMPLETED_REBOOTING); builder->Add("updateScreenAccessibleTitle", IDS_UPDATE_SCREEN_ACCESSIBLE_TITLE); builder->Add("checkingForUpdates", IDS_CHECKING_FOR_UPDATES);
diff --git a/chrome/browser/ui/webui/chromeos/login/update_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/update_screen_handler.h index 9c1bc3c..ed5c44c 100644 --- a/chrome/browser/ui/webui/chromeos/login/update_screen_handler.h +++ b/chrome/browser/ui/webui/chromeos/login/update_screen_handler.h
@@ -39,6 +39,7 @@ virtual void SetEstimatedTimeLeft(int value) = 0; virtual void SetShowEstimatedTimeLeft(bool value) = 0; virtual void SetUpdateCompleted(bool value) = 0; + virtual void SetManualRebootNeeded(bool value) = 0; virtual void SetShowCurtain(bool value) = 0; virtual void SetProgressMessage(const base::string16& value) = 0; virtual void SetProgress(int value) = 0; @@ -63,6 +64,7 @@ void SetEstimatedTimeLeft(int value) override; void SetShowEstimatedTimeLeft(bool value) override; void SetUpdateCompleted(bool value) override; + void SetManualRebootNeeded(bool value) override; void SetShowCurtain(bool value) override; void SetProgressMessage(const base::string16& value) override; void SetProgress(int value) override;
diff --git a/chrome/browser/ui/webui/settings/safety_check_handler.cc b/chrome/browser/ui/webui/settings/safety_check_handler.cc index 9a5cb44..0ed79e3 100644 --- a/chrome/browser/ui/webui/settings/safety_check_handler.cc +++ b/chrome/browser/ui/webui/settings/safety_check_handler.cc
@@ -515,6 +515,9 @@ case SafeBrowsingStatus::kDisabledByExtension: return l10n_util::GetStringUTF16( IDS_SETTINGS_SAFETY_CHECK_SAFE_BROWSING_DISABLED_BY_EXTENSION); + case SafeBrowsingStatus::kEnabledStandardAvailableEnhanced: + return l10n_util::GetStringUTF16( + IDS_SETTINGS_SAFETY_CHECK_SAFE_BROWSING_ENABLED_STANDARD_AVAILABLE_ENHANCED); } }
diff --git a/chrome/browser/ui/webui/settings/safety_check_handler_unittest.cc b/chrome/browser/ui/webui/settings/safety_check_handler_unittest.cc index 3d9194c..aba8ab6 100644 --- a/chrome/browser/ui/webui/settings/safety_check_handler_unittest.cc +++ b/chrome/browser/ui/webui/settings/safety_check_handler_unittest.cc
@@ -518,12 +518,11 @@ } TEST_F(SafetyCheckHandlerTest, CheckSafeBrowsing_EnabledStandard) { - Profile::FromWebUI(&test_web_ui_) - ->GetPrefs() - ->SetBoolean(prefs::kSafeBrowsingEnabled, true); - Profile::FromWebUI(&test_web_ui_) - ->GetPrefs() - ->SetBoolean(prefs::kSafeBrowsingEnhanced, false); + TestingProfile::FromWebUI(&test_web_ui_) + ->AsTestingProfile() + ->GetTestingPrefService() + ->SetManagedPref(prefs::kSafeBrowsingEnabled, + std::make_unique<base::Value>(true)); safety_check_->PerformSafetyCheck(); const base::DictionaryValue* event = GetSafetyCheckStatusChangedWithDataIfExists( @@ -537,6 +536,30 @@ SafetyCheckHandler::SafeBrowsingStatus::kEnabledStandard, 1); } +TEST_F(SafetyCheckHandlerTest, + CheckSafeBrowsing_EnabledStandardAvailableEnhanced) { + Profile::FromWebUI(&test_web_ui_) + ->GetPrefs() + ->SetBoolean(prefs::kSafeBrowsingEnabled, true); + Profile::FromWebUI(&test_web_ui_) + ->GetPrefs() + ->SetBoolean(prefs::kSafeBrowsingEnhanced, false); + safety_check_->PerformSafetyCheck(); + const base::DictionaryValue* event = + GetSafetyCheckStatusChangedWithDataIfExists( + kSafeBrowsing, + static_cast<int>(SafetyCheckHandler::SafeBrowsingStatus:: + kEnabledStandardAvailableEnhanced)); + ASSERT_TRUE(event); + VerifyDisplayString(event, + "Standard protection is on. For even more security, use " + "enhanced protection."); + histogram_tester_.ExpectBucketCount( + "Settings.SafetyCheck.SafeBrowsingResult", + SafetyCheckHandler::SafeBrowsingStatus::kEnabledStandardAvailableEnhanced, + 1); +} + TEST_F(SafetyCheckHandlerTest, CheckSafeBrowsing_EnabledEnhanced) { Profile::FromWebUI(&test_web_ui_) ->GetPrefs()
diff --git a/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.cc b/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.cc index c418b7e..86f687d 100644 --- a/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.cc +++ b/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.cc
@@ -371,6 +371,7 @@ dice_signed_in_profile_creator_ = std::make_unique<DiceSignedInProfileCreator>( profile_, account_info_.account_id, + /*local_profile_name=*/std::string(), base::BindOnce(&DiceTurnSyncOnHelper::OnNewSignedInProfileCreated, base::Unretained(this))); }
diff --git a/chrome/browser/ui/webui/signin/login_ui_test_utils.cc b/chrome/browser/ui/webui/signin/login_ui_test_utils.cc index 8d8acc2..66beae0 100644 --- a/chrome/browser/ui/webui/signin/login_ui_test_utils.cc +++ b/chrome/browser/ui/webui/signin/login_ui_test_utils.cc
@@ -254,10 +254,12 @@ " window.domAutomationController.send('DocumentNotReady');" "} else if (%s == null) {" " window.domAutomationController.send('NotFound');" + "} else if (%s.hidden) {" + " window.domAutomationController.send('Hidden');" "} else {" " window.domAutomationController.send('Ok');" "}", - element_selector.c_str()); + element_selector.c_str(), element_selector.c_str()); EXPECT_TRUE(content::ExecuteScriptAndExtractString( web_contents, find_element_js, &message)); return message == "Ok";
diff --git a/chrome/browser/ui/webui/signin/profile_picker_handler.cc b/chrome/browser/ui/webui/signin/profile_picker_handler.cc index 71750b6..76d802e 100644 --- a/chrome/browser/ui/webui/signin/profile_picker_handler.cc +++ b/chrome/browser/ui/webui/signin/profile_picker_handler.cc
@@ -18,10 +18,12 @@ #include "chrome/browser/profiles/profile_window.h" #include "chrome/browser/profiles/profiles_state.h" #include "chrome/browser/ui/browser_finder.h" +#include "chrome/browser/ui/chrome_pages.h" #include "chrome/browser/ui/profile_picker.h" #include "chrome/browser/ui/webui/profile_helper.h" #include "chrome/common/pref_names.h" #include "chrome/common/search/generated_colors_info.h" +#include "chrome/common/webui_url_constants.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/webui/web_ui_util.h" #include "ui/gfx/color_utils.h" @@ -45,7 +47,11 @@ web_ui()->RegisterMessageCallback( "launchSelectedProfile", base::BindRepeating(&ProfilePickerHandler::HandleLaunchSelectedProfile, - base::Unretained(this))); + base::Unretained(this), /*open_settings=*/false)); + web_ui()->RegisterMessageCallback( + "openManageProfileSettingsSubPage", + base::BindRepeating(&ProfilePickerHandler::HandleLaunchSelectedProfile, + base::Unretained(this), /*open_settings=*/true)); web_ui()->RegisterMessageCallback( "launchGuestProfile", base::BindRepeating(&ProfilePickerHandler::HandleLaunchGuestProfile, @@ -92,6 +98,7 @@ } void ProfilePickerHandler::HandleLaunchSelectedProfile( + bool open_settings, const base::ListValue* args) { const base::Value* profile_path_value = nullptr; if (!args->Get(0, &profile_path_value)) @@ -119,8 +126,8 @@ profiles::SwitchToProfile( *profile_path, /*always_create=*/false, - base::Bind(&ProfilePickerHandler::OnSwitchToProfileComplete, - weak_factory_.GetWeakPtr())); + base::BindRepeating(&ProfilePickerHandler::OnSwitchToProfileComplete, + weak_factory_.GetWeakPtr(), open_settings)); } void ProfilePickerHandler::HandleLaunchGuestProfile( @@ -129,7 +136,7 @@ // checking has been added to the UI. profiles::SwitchToGuestProfile( base::Bind(&ProfilePickerHandler::OnSwitchToProfileComplete, - weak_factory_.GetWeakPtr())); + weak_factory_.GetWeakPtr(), false)); } void ProfilePickerHandler::HandleAskOnStartupChanged( @@ -232,11 +239,15 @@ } void ProfilePickerHandler::OnSwitchToProfileComplete( + bool open_settings, Profile* profile, Profile::CreateStatus profile_create_status) { Browser* browser = chrome::FindAnyBrowser(profile, false); DCHECK(browser); DCHECK(browser->window()); + if (open_settings) { + chrome::ShowSettingsSubPage(browser, chrome::kManageProfileSubPage); + } ProfilePicker::Hide(); }
diff --git a/chrome/browser/ui/webui/signin/profile_picker_handler.h b/chrome/browser/ui/webui/signin/profile_picker_handler.h index d85d7f5..68c66fd 100644 --- a/chrome/browser/ui/webui/signin/profile_picker_handler.h +++ b/chrome/browser/ui/webui/signin/profile_picker_handler.h
@@ -26,7 +26,8 @@ private: void HandleMainViewInitialize(const base::ListValue* args); - void HandleLaunchSelectedProfile(const base::ListValue* args); + void HandleLaunchSelectedProfile(bool open_settings, + const base::ListValue* args); void HandleLaunchGuestProfile(const base::ListValue* args); void HandleAskOnStartupChanged(const base::ListValue* args); void HandleGetNewProfileSuggestedThemeInfo(const base::ListValue* args); @@ -37,7 +38,8 @@ void GatherProfileStatistics(Profile* profile); void OnProfileStatisticsReceived(base::FilePath profile_path, profiles::ProfileCategoryStats result); - void OnSwitchToProfileComplete(Profile* profile, + void OnSwitchToProfileComplete(bool open_settings, + Profile* profile, Profile::CreateStatus profile_create_status); void PushProfilesList(); base::Value GetProfilesList();
diff --git a/chrome/browser/ui/webui/signin/profile_picker_ui.cc b/chrome/browser/ui/webui/signin/profile_picker_ui.cc index 936ea7e..18b074e 100644 --- a/chrome/browser/ui/webui/signin/profile_picker_ui.cc +++ b/chrome/browser/ui/webui/signin/profile_picker_ui.cc
@@ -7,6 +7,7 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/signin/signin_util.h" #include "chrome/browser/ui/ui_features.h" #include "chrome/browser/ui/webui/signin/profile_picker_handler.h" #include "chrome/browser/ui/webui/webui_util.h" @@ -22,6 +23,17 @@ #include "ui/base/webui/web_ui_util.h" namespace { +bool IsProfileCreationAllowed() { + PrefService* service = g_browser_process->local_state(); + DCHECK(service); + return service->GetBoolean(prefs::kBrowserAddPersonEnabled); +} + +bool IsGuestModeEnabled() { + PrefService* service = g_browser_process->local_state(); + DCHECK(service); + return service->GetBoolean(prefs::kBrowserGuestModeEnabled); +} void AddStrings(content::WebUIDataSource* html_source) { static constexpr webui::LocalizedString kLocalizedStrings[] = { @@ -33,6 +45,8 @@ {"menu", IDS_MENU}, {"profileMenuName", IDS_PROFILE_PICKER_PROFILE_MENU_BUTTON_NAME}, {"profileMenuRemoveText", IDS_PROFILE_PICKER_PROFILE_MENU_REMOVE_TEXT}, + {"profileMenuCustomizeText", + IDS_PROFILE_PICKER_PROFILE_MENU_CUSTOMIZE_TEXT}, {"removeWarningLocalProfile", IDS_PROFILE_PICKER_REMOVE_WARNING_LOCAL_PROFILE}, {"removeWarningSignedInProfile", @@ -58,8 +72,16 @@ g_browser_process->local_state()->GetBoolean( prefs::kBrowserShowProfilePickerOnStartup)); html_source->AddBoolean( - "signInProfileCreationFlow", + "signInProfileCreationFlowSupported", base::FeatureList::IsEnabled(features::kSignInProfileCreationFlow)); + + // Add policies. + html_source->AddBoolean("isForceSigninEnabled", + signin_util::IsForceSigninEnabled()); + html_source->AddBoolean("isGuestModeEnabled", IsGuestModeEnabled()); + html_source->AddBoolean("isProfileCreationAllowed", + IsProfileCreationAllowed()); + // TODO(crbug.com/1063856): Check if |BrowserSignin| device policy exists. } } // namespace
diff --git a/chrome/browser/ui/webui/signin/signin_reauth_handler.cc b/chrome/browser/ui/webui/signin/signin_reauth_handler.cc index b56edbb..3b127dc 100644 --- a/chrome/browser/ui/webui/signin/signin_reauth_handler.cc +++ b/chrome/browser/ui/webui/signin/signin_reauth_handler.cc
@@ -4,13 +4,20 @@ #include "chrome/browser/ui/webui/signin/signin_reauth_handler.h" +#include <vector> + #include "base/bind.h" +#include "base/logging.h" #include "chrome/browser/ui/signin_reauth_view_controller.h" +#include "components/sync/protocol/user_consent_types.pb.h" #include "content/public/browser/web_ui.h" #include "ui/base/webui/web_ui_util.h" -SigninReauthHandler::SigninReauthHandler(SigninReauthViewController* controller) - : controller_(controller) { +SigninReauthHandler::SigninReauthHandler( + SigninReauthViewController* controller, + base::flat_map<std::string, int> string_to_grd_id_map) + : controller_(controller), + string_to_grd_id_map_(std::move(string_to_grd_id_map)) { DCHECK(controller_); controller_observer_.Add(controller_); } @@ -63,10 +70,44 @@ void SigninReauthHandler::HandleConfirm(const base::ListValue* args) { if (controller_) - controller_->OnReauthConfirmed(); + controller_->OnReauthConfirmed(BuildConsent(args)); } void SigninReauthHandler::HandleCancel(const base::ListValue* args) { if (controller_) controller_->OnReauthDismissed(); } + +sync_pb::UserConsentTypes::AccountPasswordsConsent +SigninReauthHandler::BuildConsent(const base::ListValue* args) const { + CHECK_EQ(2U, args->GetSize()); + base::Value::ConstListView consent_description = args->GetList()[0].GetList(); + const std::string& consent_confirmation = args->GetList()[1].GetString(); + + // The strings returned by the WebUI are not free-form, they must belong into + // a pre-determined set of strings (stored in |string_to_grd_id_map_|). As + // this has privacy and legal implications, CHECK the integrity of the strings + // received from the renderer process before recording the consent. + std::vector<int> consent_description_ids; + for (const base::Value& description : consent_description) { + auto iter = string_to_grd_id_map_.find(description.GetString()); + CHECK(iter != string_to_grd_id_map_.end()) << "Unexpected string:\n" + << description.GetString(); + consent_description_ids.push_back(iter->second); + } + + auto iter = string_to_grd_id_map_.find(consent_confirmation); + CHECK(iter != string_to_grd_id_map_.end()) << "Unexpected string:\n" + << consent_confirmation; + int consent_confirmation_id = iter->second; + + sync_pb::UserConsentTypes::AccountPasswordsConsent consent; + consent.set_confirmation_grd_id(consent_confirmation_id); + for (int id : consent_description_ids) { + consent.add_description_grd_ids(id); + } + consent.set_status(sync_pb::UserConsentTypes::ConsentStatus:: + UserConsentTypes_ConsentStatus_GIVEN); + + return consent; +}
diff --git a/chrome/browser/ui/webui/signin/signin_reauth_handler.h b/chrome/browser/ui/webui/signin/signin_reauth_handler.h index 2ab5bd48..0e4912de 100644 --- a/chrome/browser/ui/webui/signin/signin_reauth_handler.h +++ b/chrome/browser/ui/webui/signin/signin_reauth_handler.h
@@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_UI_WEBUI_SIGNIN_SIGNIN_REAUTH_HANDLER_H_ #define CHROME_BROWSER_UI_WEBUI_SIGNIN_SIGNIN_REAUTH_HANDLER_H_ +#include "base/containers/flat_map.h" #include "chrome/browser/ui/signin_reauth_view_controller.h" #include "content/public/browser/web_ui_message_handler.h" @@ -17,7 +18,8 @@ public SigninReauthViewController::Observer { public: // Creates a SigninReauthHandler for the |controller|. - explicit SigninReauthHandler(SigninReauthViewController* controller); + SigninReauthHandler(SigninReauthViewController* controller, + base::flat_map<std::string, int> string_to_grd_id_map); ~SigninReauthHandler() override; SigninReauthHandler(const SigninReauthHandler&) = delete; @@ -46,12 +48,19 @@ virtual void HandleCancel(const base::ListValue* args); private: + sync_pb::UserConsentTypes::AccountPasswordsConsent BuildConsent( + const base::ListValue* args) const; + // May be null if |controller_| gets destroyed earlier than |this|. SigninReauthViewController* controller_; ScopedObserver<SigninReauthViewController, SigninReauthViewController::Observer> controller_observer_{this}; + + // Mapping between strings displayed in the UI corresponding to this handler + // and their respective GRD IDs. + base::flat_map<std::string, int> string_to_grd_id_map_; }; #endif // CHROME_BROWSER_UI_WEBUI_SIGNIN_SIGNIN_REAUTH_HANDLER_H_
diff --git a/chrome/browser/ui/webui/signin/signin_reauth_ui.cc b/chrome/browser/ui/webui/signin/signin_reauth_ui.cc index b455aac6..a102575 100644 --- a/chrome/browser/ui/webui/signin/signin_reauth_ui.cc +++ b/chrome/browser/ui/webui/signin/signin_reauth_ui.cc
@@ -7,6 +7,7 @@ #include <string> #include "base/check.h" +#include "base/containers/flat_map.h" #include "base/optional.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_avatar_icon_util.h" @@ -24,6 +25,7 @@ #include "content/public/browser/web_ui_data_source.h" #include "google_apis/gaia/core_account_id.h" #include "services/network/public/mojom/content_security_policy.mojom.h" +#include "ui/base/l10n/l10n_util.h" #include "ui/base/webui/web_ui_util.h" #include "ui/gfx/image/image.h" #include "ui/resources/grit/webui_resources.h" @@ -114,16 +116,16 @@ source->AddResourcePath( "images/signin_reauth_illustration_dark.svg", IDR_SIGNIN_REAUTH_IMAGES_ACCOUNT_PASSWORDS_REAUTH_ILLUSTRATION_DARK_SVG); - source->AddLocalizedString("signinReauthTitle", - GetReauthTitleStringId(access_point)); - source->AddLocalizedString("signinReauthDesc", - IDS_ACCOUNT_PASSWORDS_REAUTH_DESC); - source->AddLocalizedString("signinReauthConfirmLabel", - GetReauthConfirmButtonLabelStringId(access_point)); - source->AddLocalizedString("signinReauthNextLabel", - IDS_ACCOUNT_PASSWORDS_REAUTH_NEXT_BUTTON_LABEL); - source->AddLocalizedString("signinReauthCloseLabel", - IDS_ACCOUNT_PASSWORDS_REAUTH_CLOSE_BUTTON_LABEL); + AddStringResource(source, "signinReauthTitle", + GetReauthTitleStringId(access_point)); + AddStringResource(source, "signinReauthDesc", + IDS_ACCOUNT_PASSWORDS_REAUTH_DESC); + AddStringResource(source, "signinReauthConfirmLabel", + GetReauthConfirmButtonLabelStringId(access_point)); + AddStringResource(source, "signinReauthNextLabel", + IDS_ACCOUNT_PASSWORDS_REAUTH_NEXT_BUTTON_LABEL); + AddStringResource(source, "signinReauthCloseLabel", + IDS_ACCOUNT_PASSWORDS_REAUTH_CLOSE_BUTTON_LABEL); content::WebUIDataSource::Add(profile, source); } @@ -132,8 +134,28 @@ void SigninReauthUI::InitializeMessageHandlerWithReauthController( SigninReauthViewController* controller) { - web_ui()->AddMessageHandler( - std::make_unique<SigninReauthHandler>(controller)); + web_ui()->AddMessageHandler(std::make_unique<SigninReauthHandler>( + controller, + base::flat_map<std::string, int>(js_localized_string_to_ids_))); } void SigninReauthUI::InitializeMessageHandlerWithBrowser(Browser* browser) {} + +void SigninReauthUI::AddStringResource(content::WebUIDataSource* source, + base::StringPiece name, + int ids) { + source->AddLocalizedString(name, ids); + + // When the strings are passed to the HTML, the Unicode NBSP symbol (\u00A0) + // will be automatically replaced with " ". This change must be mirrored + // in the string-to-ids map. Note that "\u00A0" is actually two characters, + // so we must use base::ReplaceSubstrings* rather than base::ReplaceChars. + // TODO(treib): De-dupe this with the similar code in SyncConfirmationUI, + // SyncConsentScreenHandler, and possibly other places. + std::string sanitized_string = + base::UTF16ToUTF8(l10n_util::GetStringUTF16(ids)); + base::ReplaceSubstringsAfterOffset(&sanitized_string, 0, "\u00A0" /* NBSP */, + " "); + + js_localized_string_to_ids_.emplace_back(sanitized_string, ids); +}
diff --git a/chrome/browser/ui/webui/signin/signin_reauth_ui.h b/chrome/browser/ui/webui/signin/signin_reauth_ui.h index e32947e..bdebd68 100644 --- a/chrome/browser/ui/webui/signin/signin_reauth_ui.h +++ b/chrome/browser/ui/webui/signin/signin_reauth_ui.h
@@ -5,6 +5,9 @@ #ifndef CHROME_BROWSER_UI_WEBUI_SIGNIN_SIGNIN_REAUTH_UI_H_ #define CHROME_BROWSER_UI_WEBUI_SIGNIN_SIGNIN_REAUTH_UI_H_ +#include <string> +#include <vector> + #include "chrome/browser/ui/webui/signin/signin_web_dialog_ui.h" class Browser; @@ -12,6 +15,7 @@ namespace content { class WebUI; +class WebUIDataSource; } // WebUI controller for the signin reauth dialog. @@ -44,6 +48,18 @@ // This class relies on InitializeMessageHandlerWithReauthController() so this // method does nothing. void InitializeMessageHandlerWithBrowser(Browser* browser) override; + + private: + // Adds a string resource with the given GRD |ids| to the WebUI data |source| + // named as |name|. Also stores a reverse mapping from the localized version + // of the string to the |ids| in order to later pass it to + // SigninReauthHandler. + void AddStringResource(content::WebUIDataSource* source, + base::StringPiece name, + int ids); + + // For consent auditing. + std::vector<std::pair<std::string, int>> js_localized_string_to_ids_; }; #endif // CHROME_BROWSER_UI_WEBUI_SIGNIN_SIGNIN_REAUTH_UI_H_
diff --git a/chrome/browser/web_applications/components/app_registrar.cc b/chrome/browser/web_applications/components/app_registrar.cc index 398019f..3d1ab56c 100644 --- a/chrome/browser/web_applications/components/app_registrar.cc +++ b/chrome/browser/web_applications/components/app_registrar.cc
@@ -275,6 +275,19 @@ user_display_mode); } +DisplayMode AppRegistrar::GetEffectiveDisplayModeFromManifest( + const AppId& app_id) const { + if (base::FeatureList::IsEnabled(features::kWebAppManifestDisplayOverride)) { + std::vector<DisplayMode> display_mode_overrides = + GetAppDisplayModeOverride(app_id); + + if (!display_mode_overrides.empty()) + return display_mode_overrides[0]; + } + + return GetAppDisplayMode(app_id); +} + bool AppRegistrar::IsInExperimentalTabbedWindowMode(const AppId& app_id) const { return base::FeatureList::IsEnabled(features::kDesktopPWAsTabStrip) && GetBoolWebAppPref(profile()->GetPrefs(), app_id,
diff --git a/chrome/browser/web_applications/components/app_registrar.h b/chrome/browser/web_applications/components/app_registrar.h index d82c433..439954f 100644 --- a/chrome/browser/web_applications/components/app_registrar.h +++ b/chrome/browser/web_applications/components/app_registrar.h
@@ -163,8 +163,14 @@ // complete installation via the PendingAppManager. bool IsPlaceholderApp(const AppId& app_id) const; + // Computes and returns the DisplayMode, accounting for user preference + // to launch in a browser window and entries in the web app manifest. DisplayMode GetAppEffectiveDisplayMode(const AppId& app_id) const; + // Computes and returns the DisplayMode only accounting for + // entries in the web app manifest. + DisplayMode GetEffectiveDisplayModeFromManifest(const AppId& app_id) const; + // TODO(crbug.com/897314): Finish experiment by legitimising it as a // DisplayMode or removing entirely. bool IsInExperimentalTabbedWindowMode(const AppId& app_id) const;
diff --git a/chrome/browser/web_applications/web_app_registrar_unittest.cc b/chrome/browser/web_applications/web_app_registrar_unittest.cc index 8d4e528c4..0d1c6499 100644 --- a/chrome/browser/web_applications/web_app_registrar_unittest.cc +++ b/chrome/browser/web_applications/web_app_registrar_unittest.cc
@@ -813,4 +813,28 @@ registrar().GetAppEffectiveDisplayMode(app_id)); } +TEST_F(WebAppRegistrarTest_DisplayOverride, + CheckDisplayOverrideFromGetEffectiveDisplayModeFromManifest) { + controller().Init(); + + auto web_app = CreateWebApp("https://example.com/path"); + const AppId app_id = web_app->app_id(); + std::vector<DisplayMode> display_mode_overrides; + display_mode_overrides.push_back(DisplayMode::kFullscreen); + display_mode_overrides.push_back(DisplayMode::kMinimalUi); + + web_app->SetDisplayMode(DisplayMode::kStandalone); + web_app->SetUserDisplayMode(DisplayMode::kStandalone); + web_app->SetDisplayModeOverride(display_mode_overrides); + web_app->SetIsLocallyInstalled(false); + RegisterApp(std::move(web_app)); + + EXPECT_EQ(DisplayMode::kFullscreen, + registrar().GetEffectiveDisplayModeFromManifest(app_id)); + + sync_bridge().SetAppIsLocallyInstalled(app_id, true); + EXPECT_EQ(DisplayMode::kFullscreen, + registrar().GetEffectiveDisplayModeFromManifest(app_id)); +} + } // namespace web_app
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index 8c90f1ae..6b88243 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-master-1597275686-7da657e756f53f89a89030a34195741313ee681f.profdata +chrome-mac-master-1597319582-be9645d468b25404b91084b442e1381733e63a51.profdata
diff --git a/chrome/services/sharing/nearby/decoder/nearby_decoder_unittest.cc b/chrome/services/sharing/nearby/decoder/nearby_decoder_unittest.cc index 643455c..692448ac 100644 --- a/chrome/services/sharing/nearby/decoder/nearby_decoder_unittest.cc +++ b/chrome/services/sharing/nearby/decoder/nearby_decoder_unittest.cc
@@ -14,6 +14,7 @@ #include "base/test/bind_test_util.h" #include "base/test/task_environment.h" #include "chrome/services/sharing/public/cpp/advertisement.h" +#include "chrome/services/sharing/public/cpp/conversions.h" #include "chrome/services/sharing/public/mojom/nearby_decoder_types.mojom.h" #include "chrome/services/sharing/public/proto/wire_format.pb.h" #include "mojo/public/cpp/bindings/remote.h" @@ -35,55 +36,7 @@ const mojom::AdvertisementPtr& other) { EXPECT_EQ(self.device_name(), other->device_name); EXPECT_EQ(self.salt(), other->salt); - EXPECT_EQ(self.encrypted_metadata_key(), other->encrypted_metadata); -} - -sharing::nearby::FileMetadata_Type ConvertFileMetadataType( - mojom::FileMetadata::Type type) { - switch (type) { - case mojom::FileMetadata::Type::kImage: - return sharing::nearby::FileMetadata_Type_IMAGE; - case mojom::FileMetadata::Type::kVideo: - return sharing::nearby::FileMetadata_Type_VIDEO; - case mojom::FileMetadata::Type::kApp: - return sharing::nearby::FileMetadata_Type_APP; - case mojom::FileMetadata::Type::kAudio: - return sharing::nearby::FileMetadata_Type_AUDIO; - case mojom::FileMetadata::Type::kUnknown: - return sharing::nearby::FileMetadata_Type_UNKNOWN; - } -} - -sharing::nearby::TextMetadata_Type ConvertTextMetadataType( - mojom::TextMetadata::Type type) { - switch (type) { - case mojom::TextMetadata::Type::kText: - return sharing::nearby::TextMetadata_Type_TEXT; - case mojom::TextMetadata::Type::kUrl: - return sharing::nearby::TextMetadata_Type_URL; - case mojom::TextMetadata::Type::kAddress: - return sharing::nearby::TextMetadata_Type_ADDRESS; - case mojom::TextMetadata::Type::kPhoneNumber: - return sharing::nearby::TextMetadata_Type_PHONE_NUMBER; - case mojom::TextMetadata::Type::kUnknown: - return sharing::nearby::TextMetadata_Type_UNKNOWN; - } -} - -sharing::nearby::WifiCredentialsMetadata_SecurityType -ConvertWifiCredentialsMetadataType( - mojom::WifiCredentialsMetadata::SecurityType type) { - switch (type) { - case mojom::WifiCredentialsMetadata::SecurityType::kOpen: - return sharing::nearby::WifiCredentialsMetadata_SecurityType_OPEN; - case mojom::WifiCredentialsMetadata::SecurityType::kWpaPsk: - return sharing::nearby::WifiCredentialsMetadata_SecurityType_WPA_PSK; - case mojom::WifiCredentialsMetadata::SecurityType::kWep: - return sharing::nearby::WifiCredentialsMetadata_SecurityType_WEP; - case mojom::WifiCredentialsMetadata::SecurityType::kUnknownSecurityType: - return sharing::nearby:: - WifiCredentialsMetadata_SecurityType_UNKNOWN_SECURITY_TYPE; - } + EXPECT_EQ(self.encrypted_metadata_key(), other->encrypted_metadata_key); } void ExpectFrameContainsIntroduction(
diff --git a/chrome/services/sharing/public/cpp/BUILD.gn b/chrome/services/sharing/public/cpp/BUILD.gn index 93b26231..8c23b9d 100644 --- a/chrome/services/sharing/public/cpp/BUILD.gn +++ b/chrome/services/sharing/public/cpp/BUILD.gn
@@ -6,12 +6,16 @@ sources = [ "advertisement.cc", "advertisement.h", + "conversions.cc", + "conversions.h", "sharing_webrtc_metrics.cc", "sharing_webrtc_metrics.h", ] public_deps = [ "//base", + "//chrome/services/sharing/public/mojom", + "//chrome/services/sharing/public/proto", "//mojo/public/cpp/bindings", ] }
diff --git a/chrome/services/sharing/public/cpp/advertisement.h b/chrome/services/sharing/public/cpp/advertisement.h index 661d0a0..7169970 100644 --- a/chrome/services/sharing/public/cpp/advertisement.h +++ b/chrome/services/sharing/public/cpp/advertisement.h
@@ -56,11 +56,14 @@ // ways of parsing the endpoint id. int version_; - // A randomized salt used in the hash of the account identifier. + // Random bytes that were used as salt during encryption of public certificate + // metadata. std::vector<uint8_t> salt_; - // A salted hash of an account identifier that signifies who the remote device - // is. + // An encrypted symmetric key that was used to encrypt public certificate + // metadata, including an account identifier signifying the remote device. + // The key can be decrypted using |salt| and the corresponding public + // certificate's secret/authenticity key. std::vector<uint8_t> encrypted_metadata_key_; // The human readable name of the remote device.
diff --git a/chrome/services/sharing/public/cpp/conversions.cc b/chrome/services/sharing/public/cpp/conversions.cc new file mode 100644 index 0000000..ec7055a7 --- /dev/null +++ b/chrome/services/sharing/public/cpp/conversions.cc
@@ -0,0 +1,55 @@ +// 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. + +#include "chrome/services/sharing/public/cpp/conversions.h" + +namespace sharing { + +nearby::FileMetadata_Type ConvertFileMetadataType( + mojom::FileMetadata::Type type) { + switch (type) { + case mojom::FileMetadata::Type::kImage: + return nearby::FileMetadata_Type_IMAGE; + case mojom::FileMetadata::Type::kVideo: + return nearby::FileMetadata_Type_VIDEO; + case mojom::FileMetadata::Type::kApp: + return nearby::FileMetadata_Type_APP; + case mojom::FileMetadata::Type::kAudio: + return nearby::FileMetadata_Type_AUDIO; + case mojom::FileMetadata::Type::kUnknown: + return nearby::FileMetadata_Type_UNKNOWN; + } +} + +nearby::TextMetadata_Type ConvertTextMetadataType( + mojom::TextMetadata::Type type) { + switch (type) { + case mojom::TextMetadata::Type::kText: + return nearby::TextMetadata_Type_TEXT; + case mojom::TextMetadata::Type::kUrl: + return nearby::TextMetadata_Type_URL; + case mojom::TextMetadata::Type::kAddress: + return nearby::TextMetadata_Type_ADDRESS; + case mojom::TextMetadata::Type::kPhoneNumber: + return nearby::TextMetadata_Type_PHONE_NUMBER; + case mojom::TextMetadata::Type::kUnknown: + return nearby::TextMetadata_Type_UNKNOWN; + } +} + +nearby::WifiCredentialsMetadata_SecurityType ConvertWifiCredentialsMetadataType( + mojom::WifiCredentialsMetadata::SecurityType type) { + switch (type) { + case mojom::WifiCredentialsMetadata::SecurityType::kOpen: + return nearby::WifiCredentialsMetadata_SecurityType_OPEN; + case mojom::WifiCredentialsMetadata::SecurityType::kWpaPsk: + return nearby::WifiCredentialsMetadata_SecurityType_WPA_PSK; + case mojom::WifiCredentialsMetadata::SecurityType::kWep: + return nearby::WifiCredentialsMetadata_SecurityType_WEP; + case mojom::WifiCredentialsMetadata::SecurityType::kUnknownSecurityType: + return nearby::WifiCredentialsMetadata_SecurityType_UNKNOWN_SECURITY_TYPE; + } +} + +} // namespace sharing
diff --git a/chrome/services/sharing/public/cpp/conversions.h b/chrome/services/sharing/public/cpp/conversions.h new file mode 100644 index 0000000..e08491a --- /dev/null +++ b/chrome/services/sharing/public/cpp/conversions.h
@@ -0,0 +1,24 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_SERVICES_SHARING_PUBLIC_CPP_CONVERSIONS_H_ +#define CHROME_SERVICES_SHARING_PUBLIC_CPP_CONVERSIONS_H_ + +#include "chrome/services/sharing/public/mojom/nearby_decoder_types.mojom.h" +#include "chrome/services/sharing/public/proto/wire_format.pb.h" + +namespace sharing { + +nearby::FileMetadata_Type ConvertFileMetadataType( + mojom::FileMetadata::Type type); + +nearby::TextMetadata_Type ConvertTextMetadataType( + mojom::TextMetadata::Type type); + +nearby::WifiCredentialsMetadata_SecurityType ConvertWifiCredentialsMetadataType( + mojom::WifiCredentialsMetadata::SecurityType type); + +} // namespace sharing + +#endif // CHROME_SERVICES_SHARING_PUBLIC_CPP_CONVERSIONS_H_
diff --git a/chrome/services/sharing/public/mojom/nearby_decoder_types.mojom b/chrome/services/sharing/public/mojom/nearby_decoder_types.mojom index 12bd12b..4d4694d6 100644 --- a/chrome/services/sharing/public/mojom/nearby_decoder_types.mojom +++ b/chrome/services/sharing/public/mojom/nearby_decoder_types.mojom
@@ -8,11 +8,14 @@ // An advertisement send by a device in receiving mode. struct Advertisement { - // Random data erived from a device's private key. + // Random bytes that were used as salt during encryption of public + // certificate metadata. array<uint8, 2> salt; - // Derived from a device's private key. Identifying data for the device. - array<uint8, 14> encrypted_metadata; + // An encrypted symmetric key that was used to encrypt public certificate + // metadata. The key can be decrypted using |salt| and the corresponding + // public certificate's secret/authenticity key. + array<uint8, 14> encrypted_metadata_key; // If present, the device is visible to everyone rather than contacts only. string? device_name;
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java index 073546f..5756bb0 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java
@@ -421,7 +421,7 @@ ChromeTabUtils.waitForTabPageLoaded(tab, (String) null); - if (tab != null && NewTabPage.isNTPUrl(ChromeTabUtils.getUrlStringOnUiThread(tab)) + if (tab != null && NewTabPage.isNTPUrl(tab.getUrlString()) && !getActivity().isInOverviewMode()) { NewTabPageTestUtils.waitForNtpLoaded(tab); }
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeTabUtils.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeTabUtils.java index f418e10..437c158 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeTabUtils.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeTabUtils.java
@@ -40,7 +40,6 @@ import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.content_public.browser.test.util.TestTouchUtils; import org.chromium.content_public.browser.test.util.TouchCommon; -import org.chromium.url.GURL; import java.util.List; import java.util.Locale; @@ -120,8 +119,7 @@ } private static boolean loadComplete(Tab tab, String url) { - return !tab.isLoading() - && (url == null || TextUtils.equals(getUrlStringOnUiThread(tab), url)) + return !tab.isLoading() && (url == null || TextUtils.equals(tab.getUrlString(), url)) && !tab.getWebContents().isLoadingToDifferentDocument(); } @@ -131,18 +129,6 @@ return res.get(); } - public static String getUrlStringOnUiThread(Tab tab) { - AtomicReference<String> res = new AtomicReference<>(); - TestThreadUtils.runOnUiThreadBlocking(() -> { res.set(tab.getUrlString()); }); - return res.get(); - } - - public static GURL getUrlOnUiThread(Tab tab) { - AtomicReference<GURL> res = new AtomicReference<>(); - TestThreadUtils.runOnUiThreadBlocking(() -> { res.set(tab.getUrl()); }); - return res.get(); - } - /** * Waits for the given tab to finish loading the given URL, or, if the given URL is * null, waits for the current page to load.
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/AccountManagerTestRule.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/AccountManagerTestRule.java index 10e9e9c..4bd1108 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/AccountManagerTestRule.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/AccountManagerTestRule.java
@@ -67,7 +67,12 @@ * Tears down the AccountManagerFacade mock and signs out if user is signed in. */ public void tearDownRule() { - if (mIsSignedIn) { + if (mIsSignedIn && getCurrentSignedInAccount() != null) { + // For android_browsertests that sign out during the test body, like + // UkmBrowserTest.SingleSyncSignoutCheck, we should sign out during tear-down test stage + // only if an account is signed in. Otherwise, tearDownRule() ultimately results a crash + // in SignoutManager::signOut(). This is because sign out is attempted when a sign-out + // operation is already in progress. See crbug/1102746 for more details. signOut(); } AccountManagerFacadeProvider.resetInstanceForTests();
diff --git a/chrome/test/data/password/nonplaceholder_username.html b/chrome/test/data/password/nonplaceholder_username.html new file mode 100644 index 0000000..f7dd46d --- /dev/null +++ b/chrome/test/data/password/nonplaceholder_username.html
@@ -0,0 +1,9 @@ +<html> +<body> +<form method="POST" action="done.html" onsubmit="return true;" id="testform"> + <input type="text" id="username_field" name="username_field" value="example@example.com"> + <input type="password" id="password_field" name="password_field" value="htmlPass"> + <input type="submit" id="input_submit_button" name="input_submit_button"> +</form> +</body> +</html>
diff --git a/chrome/test/data/portal/portal-no-src.html b/chrome/test/data/portal/portal-no-src.html new file mode 100644 index 0000000..6172ffa --- /dev/null +++ b/chrome/test/data/portal/portal-no-src.html
@@ -0,0 +1,9 @@ +<!DOCTYPE html> +<body> + <portal></portal> + <script> + function activate() { + return document.querySelector("portal").activate().catch(err => true); + } + </script> +</body>
diff --git a/chrome/test/data/webui/settings/multi_store_exception_entry_test.js b/chrome/test/data/webui/settings/multi_store_exception_entry_test.js index 0623259..5785550 100644 --- a/chrome/test/data/webui/settings/multi_store_exception_entry_test.js +++ b/chrome/test/data/webui/settings/multi_store_exception_entry_test.js
@@ -26,12 +26,30 @@ expectTrue(multiStoreAccountEntry.isPresentInAccount()); expectEquals(multiStoreAccountEntry.getAnyId(), 1); - const multiStoreEntryFromBoth = - new MultiStoreExceptionEntry(deviceEntry, accountEntry); + const multiStoreEntryFromBoth = new MultiStoreExceptionEntry(deviceEntry); + expectTrue(multiStoreEntryFromBoth.mergeInPlace(accountEntry)); expectTrue(multiStoreEntryFromBoth.isPresentOnDevice()); expectTrue(multiStoreEntryFromBoth.isPresentInAccount()); expectTrue( multiStoreEntryFromBoth.getAnyId() === 0 || multiStoreEntryFromBoth.getAnyId() === 1); }); + + test('mergeFailsForRepeatedStore', function() { + const deviceEntry1 = + createExceptionEntry({url: 'g.com', id: 0, fromAccountStore: false}); + const deviceEntry2 = + createExceptionEntry({url: 'g.com', id: 1, fromAccountStore: false}); + expectFalse( + new MultiStoreExceptionEntry(deviceEntry1).mergeInPlace(deviceEntry2)); + }); + + test('mergeFailsForDifferentContents', function() { + const deviceEntry = + createExceptionEntry({url: 'a.com', id: 0, fromAccountStore: false}); + const accountEntry = + createExceptionEntry({url: 'b.com', id: 1, fromAccountStore: true}); + expectFalse( + new MultiStoreExceptionEntry(deviceEntry).mergeInPlace(accountEntry)); + }); });
diff --git a/chrome/test/data/webui/settings/multi_store_password_ui_entry_test.js b/chrome/test/data/webui/settings/multi_store_password_ui_entry_test.js index b5c35c7..d3f7984 100644 --- a/chrome/test/data/webui/settings/multi_store_password_ui_entry_test.js +++ b/chrome/test/data/webui/settings/multi_store_password_ui_entry_test.js
@@ -26,12 +26,30 @@ expectTrue(multiStoreAccountEntry.isPresentInAccount()); expectEquals(multiStoreAccountEntry.getAnyId(), 1); - const multiStoreEntryFromBoth = - new MultiStorePasswordUiEntry(deviceEntry, accountEntry); + const multiStoreEntryFromBoth = new MultiStorePasswordUiEntry(deviceEntry); + expectTrue(multiStoreEntryFromBoth.mergeInPlace(accountEntry)); expectTrue(multiStoreEntryFromBoth.isPresentOnDevice()); expectTrue(multiStoreEntryFromBoth.isPresentInAccount()); expectTrue( multiStoreEntryFromBoth.getAnyId() === 0 || multiStoreEntryFromBoth.getAnyId() === 1); }); + + test('mergeFailsForRepeatedStore', function() { + const deviceEntry1 = createPasswordEntry( + {url: 'g.com', username: 'user', id: 0, fromAccountStore: false}); + const deviceEntry2 = createPasswordEntry( + {url: 'g.com', username: 'user', id: 1, fromAccountStore: false}); + expectFalse( + new MultiStorePasswordUiEntry(deviceEntry1).mergeInPlace(deviceEntry2)); + }); + + test('mergeFailsForDifferentContents', function() { + const deviceEntry = createPasswordEntry( + {url: 'g.com', username: 'user', id: 0, fromAccountStore: false}); + const accountEntry = createPasswordEntry( + {url: 'g.com', username: 'user2', id: 1, fromAccountStore: true}); + expectFalse( + new MultiStorePasswordUiEntry(deviceEntry).mergeInPlace(accountEntry)); + }); });
diff --git a/chrome/test/data/webui/settings/passwords_and_autofill_fake_data.js b/chrome/test/data/webui/settings/passwords_and_autofill_fake_data.js index 9dacdea..48b8dd73 100644 --- a/chrome/test/data/webui/settings/passwords_and_autofill_fake_data.js +++ b/chrome/test/data/webui/settings/passwords_and_autofill_fake_data.js
@@ -87,8 +87,13 @@ }); } + if (deviceEntry && accountEntry) { + const mergedEntry = new MultiStorePasswordUiEntry(deviceEntry); + mergedEntry.mergeInPlace(accountEntry); + return mergedEntry; + } if (deviceEntry) { - return new MultiStorePasswordUiEntry(deviceEntry, accountEntry); + return new MultiStorePasswordUiEntry(deviceEntry); } if (accountEntry) { return new MultiStorePasswordUiEntry(accountEntry); @@ -158,8 +163,13 @@ }); } + if (deviceEntry && accountEntry) { + const mergedEntry = new MultiStoreExceptionEntry(deviceEntry); + mergedEntry.mergeInPlace(accountEntry); + return mergedEntry; + } if (deviceEntry) { - return new MultiStoreExceptionEntry(deviceEntry, accountEntry); + return new MultiStoreExceptionEntry(deviceEntry); } if (accountEntry) { return new MultiStoreExceptionEntry(accountEntry);
diff --git a/chrome/test/data/webui/settings/safety_check_page_test.js b/chrome/test/data/webui/settings/safety_check_page_test.js index 618f473a..9942d54 100644 --- a/chrome/test/data/webui/settings/safety_check_page_test.js +++ b/chrome/test/data/webui/settings/safety_check_page_test.js
@@ -647,6 +647,17 @@ }); }); + test('safeBrowsingEnabledStandardAvailableEnhancedUiTest', function() { + fireSafetyCheckSafeBrowsingEvent( + SafetyCheckSafeBrowsingStatus.ENABLED_STANDARD_AVAILABLE_ENHANCED); + flush(); + assertSafetyCheckChild({ + page: page, + iconStatus: SafetyCheckIconStatus.SAFE, + label: 'Safe Browsing', + }); + }); + test('safeBrowsingEnabledEnhancedUiTest', function() { fireSafetyCheckSafeBrowsingEvent( SafetyCheckSafeBrowsingStatus.ENABLED_ENHANCED);
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index a82be5d7..39a593f 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -13402.0.0 \ No newline at end of file +13405.0.0 \ No newline at end of file
diff --git a/chromeos/components/phonehub/OWNERS b/chromeos/components/phonehub/OWNERS new file mode 100644 index 0000000..0269806 --- /dev/null +++ b/chromeos/components/phonehub/OWNERS
@@ -0,0 +1,3 @@ +khorimoto@chromium.org + +# COMPONENT: OS>Systems>Multidevice>PhoneHub
diff --git a/components/arc/BUILD.gn b/components/arc/BUILD.gn index 955a732..f209925 100644 --- a/components/arc/BUILD.gn +++ b/components/arc/BUILD.gn
@@ -309,6 +309,8 @@ static_library("arc_test_support") { testonly = true sources = [ + "test/arc_payment_app_bridge_test_support.cc", + "test/arc_payment_app_bridge_test_support.h", "test/fake_accessibility_helper_instance.cc", "test/fake_accessibility_helper_instance.h", "test/fake_app_instance.cc",
diff --git a/components/arc/mojom/payment_app.mojom b/components/arc/mojom/payment_app.mojom index b46a1b5..a52ba82 100644 --- a/components/arc/mojom/payment_app.mojom +++ b/components/arc/mojom/payment_app.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: 2 +// Next MinVersion: 3 module arc.mojom; @@ -77,14 +77,44 @@ // schemelessIframeOrigin" parameter to createIsReadyToPayIntent() and // createPayIntent() methods. string payment_request_origin; + + // The free-form identifier for this pending transaction as set either by the + // merchant website in PaymentRequest() constructor in JavaScript, or (more + // commonly) a browser-generated GUID string. This is the "String id" + // parameter to createPayIntent() method. The createIsReadyToPayIntent() does + // not currently need this parameter. + [MinVersion=2] + string? payment_request_id; }; -// After the browser calls IsReadyToPay(), ARC sends this back in response. +// After the browser calls IsReadyToPay(), ARC sends back this result. union IsReadyToPayResult { bool response; string error; }; +// After the browser calls InvokePaymentApp(), ARC sends back this result, if +// there are no errors. +struct InvokePaymentAppValidResult { + // Whether the intent return status is Activity.RESULT_OK. + bool is_activity_result_ok; + + // The JSON serialization of a JavaScript object that's the response to + // PaymentRequest API. For example: + // + // {"receiptIdentifier": "test_receipt_identifier"} + // + // This string is serialized in TWA and is parsed in Blink. The browser does + // not parse this string. + string stringified_details; +}; + +// After the browser calls InvokePaymentApp(), ARC sends back this result. +union InvokePaymentAppResult { + InvokePaymentAppValidResult valid; + string error; +}; + // The service that runs in ARC and allows the browser to invoke the TWA payment // app that is installed in ARC, if it implements payment intents as described // in https://web.dev/android-payment-apps-overview/. At first, only @@ -99,7 +129,7 @@ // | | | | // -------------------- -------------------------------------------------- // -// Next method ID: 2 +// Next method ID: 3 interface PaymentAppInstance { // Called by the browser to check whether the TWA with |package_name| (e.g., // "com.example.app") in ARC has intent filters for @@ -122,5 +152,17 @@ // or guest mode. [MinVersion=1] IsReadyToPay@1(PaymentParameters parameters) - => (IsReadyToPayResult result); + => (IsReadyToPayResult response); + + // Forwards the request to WebPaymentIntentHelper.createPayIntent() and fires + // the resulting intent. This invokes the payment flow. + // + // The "String merchantName" parameter to createPayIntent() should be empty + // (but not null). + // + // The total amount for createPayIntent() should always be "0" with currency + // "ZZZ". + [MinVersion=2] + InvokePaymentApp@2(PaymentParameters parameters) + => (InvokePaymentAppResult response); };
diff --git a/components/arc/pay/arc_payment_app_bridge.cc b/components/arc/pay/arc_payment_app_bridge.cc index 535fbcb..33c435d0 100644 --- a/components/arc/pay/arc_payment_app_bridge.cc +++ b/components/arc/pay/arc_payment_app_bridge.cc
@@ -86,4 +86,18 @@ payment_app->IsReadyToPay(std::move(parameters), std::move(callback)); } +void ArcPaymentAppBridge::InvokePaymentApp( + mojom::PaymentParametersPtr parameters, + InvokePaymentAppCallback callback) { + mojom::PaymentAppInstance* payment_app = ARC_GET_INSTANCE_FOR_METHOD( + arc_bridge_service_->payment_app(), InvokePaymentApp); + if (!payment_app) { + std::move(callback).Run( + mojom::InvokePaymentAppResult::NewError(kUnableToConnectErrorMessage)); + return; + } + + payment_app->InvokePaymentApp(std::move(parameters), std::move(callback)); +} + } // namespace arc
diff --git a/components/arc/pay/arc_payment_app_bridge.h b/components/arc/pay/arc_payment_app_bridge.h index 710135d..2d8583bd 100644 --- a/components/arc/pay/arc_payment_app_bridge.h +++ b/components/arc/pay/arc_payment_app_bridge.h
@@ -26,6 +26,8 @@ base::OnceCallback<void(mojom::IsPaymentImplementedResultPtr)>; using IsReadyToPayCallback = base::OnceCallback<void(mojom::IsReadyToPayResultPtr)>; + using InvokePaymentAppCallback = + base::OnceCallback<void(mojom::InvokePaymentAppResultPtr)>; // Returns the instance owned by the given BrowserContext, or nullptr if the // browser |context| is not allowed to use ARC. @@ -54,6 +56,10 @@ void IsReadyToPay(mojom::PaymentParametersPtr parameters, IsReadyToPayCallback callback); + // Invokes the TWA payment app flow. + void InvokePaymentApp(mojom::PaymentParametersPtr parameters, + InvokePaymentAppCallback callback); + private: ArcBridgeService* const arc_bridge_service_; // Owned by ArcServiceManager. };
diff --git a/components/arc/pay/arc_payment_app_bridge_unittest.cc b/components/arc/pay/arc_payment_app_bridge_unittest.cc index 2a44b65..57876c4e 100644 --- a/components/arc/pay/arc_payment_app_bridge_unittest.cc +++ b/components/arc/pay/arc_payment_app_bridge_unittest.cc
@@ -8,6 +8,7 @@ #include "components/arc/arc_service_manager.h" #include "components/arc/session/arc_bridge_service.h" +#include "components/arc/test/arc_payment_app_bridge_test_support.h" #include "components/arc/test/test_browser_context.h" #include "content/public/test/browser_task_environment.h" #include "testing/gmock/include/gmock/gmock.h" @@ -16,17 +17,6 @@ namespace arc { namespace { -class MockPaymentAppInstance : public mojom::PaymentAppInstance { - public: - MOCK_METHOD2( - IsPaymentImplemented, - void(const std::string& package_name, - ArcPaymentAppBridge::IsPaymentImplementedCallback callback)); - MOCK_METHOD2(IsReadyToPay, - void(mojom::PaymentParametersPtr, - ArcPaymentAppBridge::IsReadyToPayCallback)); -}; - class ArcPaymentAppBridgeTest : public testing::Test { public: ArcPaymentAppBridgeTest() = default; @@ -45,45 +35,24 @@ is_ready_to_pay_ = std::move(response); } - // The |manager_| must be used on the same thread as where it was created, so - // create it in the test instead of using ArcServiceManager::Get(). - ArcServiceManager manager_; - MockPaymentAppInstance instance_; + void OnInvokePaymentAppResponse(mojom::InvokePaymentAppResultPtr response) { + invoke_app_ = std::move(response); + } - // Required for the TestBrowserContext. - content::BrowserTaskEnvironment task_environment_; - - // Used for retrieving an instance of ArcPaymentAppBridge owned by a - // BrowserContext. - TestBrowserContext context_; - + ArcPaymentAppBridgeTestSupport support_; mojom::IsPaymentImplementedResultPtr is_implemented_; mojom::IsReadyToPayResultPtr is_ready_to_pay_; -}; - -class ScopedSetInstance { - public: - ScopedSetInstance(ArcServiceManager* manager, - MockPaymentAppInstance* instance) - : manager_(manager), instance_(instance) { - manager_->arc_bridge_service()->payment_app()->SetInstance(instance_); - } - - ~ScopedSetInstance() { - manager_->arc_bridge_service()->payment_app()->CloseInstance(instance_); - } - - private: - ArcServiceManager* manager_; - MockPaymentAppInstance* instance_; + mojom::InvokePaymentAppResultPtr invoke_app_; }; TEST_F(ArcPaymentAppBridgeTest, UnableToConnectInIsImplemented) { // Intentionally do not set an instance. - EXPECT_CALL(instance_, IsPaymentImplemented(testing::_, testing::_)).Times(0); + EXPECT_CALL(*support_.instance(), + IsPaymentImplemented(testing::_, testing::_)) + .Times(0); - ArcPaymentAppBridge::GetForBrowserContextForTesting(&context_) + ArcPaymentAppBridge::GetForBrowserContextForTesting(support_.context()) ->IsPaymentImplemented( "com.example.app", base::BindOnce(&ArcPaymentAppBridgeTest::OnPaymentImplementedResponse, @@ -96,9 +65,10 @@ } TEST_F(ArcPaymentAppBridgeTest, IsImplemented) { - ScopedSetInstance scoped_set_instance(&manager_, &instance_); + auto scoped_set_instance = support_.CreateScopedSetInstance(); - EXPECT_CALL(instance_, IsPaymentImplemented(testing::_, testing::_)) + EXPECT_CALL(*support_.instance(), + IsPaymentImplemented(testing::_, testing::_)) .WillOnce(testing::Invoke( [](const std::string& package_name, ArcPaymentAppBridge::IsPaymentImplementedCallback callback) { @@ -109,7 +79,7 @@ mojom::IsPaymentImplementedResult::NewValid(std::move(valid))); })); - ArcPaymentAppBridge::GetForBrowserContextForTesting(&context_) + ArcPaymentAppBridge::GetForBrowserContextForTesting(support_.context()) ->IsPaymentImplemented( "com.example.app", base::BindOnce(&ArcPaymentAppBridgeTest::OnPaymentImplementedResponse, @@ -126,9 +96,10 @@ } TEST_F(ArcPaymentAppBridgeTest, IsNotImplemented) { - ScopedSetInstance scoped_set_instance(&manager_, &instance_); + auto scoped_set_instance = support_.CreateScopedSetInstance(); - EXPECT_CALL(instance_, IsPaymentImplemented(testing::_, testing::_)) + EXPECT_CALL(*support_.instance(), + IsPaymentImplemented(testing::_, testing::_)) .WillOnce(testing::Invoke( [](const std::string& package_name, ArcPaymentAppBridge::IsPaymentImplementedCallback callback) { @@ -136,7 +107,7 @@ mojom::IsPaymentImplementedValidResult::New())); })); - ArcPaymentAppBridge::GetForBrowserContextForTesting(&context_) + ArcPaymentAppBridge::GetForBrowserContextForTesting(support_.context()) ->IsPaymentImplemented( "com.example.app", base::BindOnce(&ArcPaymentAppBridgeTest::OnPaymentImplementedResponse, @@ -151,9 +122,10 @@ } TEST_F(ArcPaymentAppBridgeTest, ImplementationCheckError) { - ScopedSetInstance scoped_set_instance(&manager_, &instance_); + auto scoped_set_instance = support_.CreateScopedSetInstance(); - EXPECT_CALL(instance_, IsPaymentImplemented(testing::_, testing::_)) + EXPECT_CALL(*support_.instance(), + IsPaymentImplemented(testing::_, testing::_)) .WillOnce(testing::Invoke( [](const std::string& package_name, ArcPaymentAppBridge::IsPaymentImplementedCallback callback) { @@ -161,7 +133,7 @@ mojom::IsPaymentImplementedResult::NewError("Error message.")); })); - ArcPaymentAppBridge::GetForBrowserContextForTesting(&context_) + ArcPaymentAppBridge::GetForBrowserContextForTesting(support_.context()) ->IsPaymentImplemented( "com.example.app", base::BindOnce(&ArcPaymentAppBridgeTest::OnPaymentImplementedResponse, @@ -176,12 +148,14 @@ TEST_F(ArcPaymentAppBridgeTest, UnableToConnectInIsReadyToPay) { // Intentionally do not set an instance. - EXPECT_CALL(instance_, IsReadyToPay(testing::_, testing::_)).Times(0); + EXPECT_CALL(*support_.instance(), IsReadyToPay(testing::_, testing::_)) + .Times(0); - ArcPaymentAppBridge::GetForBrowserContextForTesting(&context_)->IsReadyToPay( - mojom::PaymentParameters::New(), - base::BindOnce(&ArcPaymentAppBridgeTest::OnIsReadyToPayResponse, - base::Unretained(this))); + ArcPaymentAppBridge::GetForBrowserContextForTesting(support_.context()) + ->IsReadyToPay( + mojom::PaymentParameters::New(), + base::BindOnce(&ArcPaymentAppBridgeTest::OnIsReadyToPayResponse, + base::Unretained(this))); ASSERT_FALSE(is_ready_to_pay_.is_null()); EXPECT_FALSE(is_ready_to_pay_->is_response()); @@ -190,9 +164,9 @@ } TEST_F(ArcPaymentAppBridgeTest, IsReadyToPay) { - ScopedSetInstance scoped_set_instance(&manager_, &instance_); + auto scoped_set_instance = support_.CreateScopedSetInstance(); - EXPECT_CALL(instance_, IsReadyToPay(testing::_, testing::_)) + EXPECT_CALL(*support_.instance(), IsReadyToPay(testing::_, testing::_)) .WillOnce(testing::Invoke( [](mojom::PaymentParametersPtr parameters, ArcPaymentAppBridge::IsReadyToPayCallback callback) { @@ -200,10 +174,11 @@ mojom::IsReadyToPayResult::NewResponse(true)); })); - ArcPaymentAppBridge::GetForBrowserContextForTesting(&context_)->IsReadyToPay( - mojom::PaymentParameters::New(), - base::BindOnce(&ArcPaymentAppBridgeTest::OnIsReadyToPayResponse, - base::Unretained(this))); + ArcPaymentAppBridge::GetForBrowserContextForTesting(support_.context()) + ->IsReadyToPay( + mojom::PaymentParameters::New(), + base::BindOnce(&ArcPaymentAppBridgeTest::OnIsReadyToPayResponse, + base::Unretained(this))); ASSERT_FALSE(is_ready_to_pay_.is_null()); EXPECT_FALSE(is_ready_to_pay_->is_error()); @@ -212,9 +187,9 @@ } TEST_F(ArcPaymentAppBridgeTest, IsNotReadyToPay) { - ScopedSetInstance scoped_set_instance(&manager_, &instance_); + auto scoped_set_instance = support_.CreateScopedSetInstance(); - EXPECT_CALL(instance_, IsReadyToPay(testing::_, testing::_)) + EXPECT_CALL(*support_.instance(), IsReadyToPay(testing::_, testing::_)) .WillOnce(testing::Invoke( [](mojom::PaymentParametersPtr parameters, ArcPaymentAppBridge::IsReadyToPayCallback callback) { @@ -222,10 +197,11 @@ mojom::IsReadyToPayResult::NewResponse(false)); })); - ArcPaymentAppBridge::GetForBrowserContextForTesting(&context_)->IsReadyToPay( - mojom::PaymentParameters::New(), - base::BindOnce(&ArcPaymentAppBridgeTest::OnIsReadyToPayResponse, - base::Unretained(this))); + ArcPaymentAppBridge::GetForBrowserContextForTesting(support_.context()) + ->IsReadyToPay( + mojom::PaymentParameters::New(), + base::BindOnce(&ArcPaymentAppBridgeTest::OnIsReadyToPayResponse, + base::Unretained(this))); ASSERT_FALSE(is_ready_to_pay_.is_null()); EXPECT_FALSE(is_ready_to_pay_->is_error()); @@ -233,5 +209,101 @@ EXPECT_FALSE(is_ready_to_pay_->get_response()); } +TEST_F(ArcPaymentAppBridgeTest, UnableToConnectInInvokePaymentApp) { + // Intentionally do not set an instance. + + EXPECT_CALL(*support_.instance(), InvokePaymentApp(testing::_, testing::_)) + .Times(0); + + ArcPaymentAppBridge::GetForBrowserContextForTesting(support_.context()) + ->InvokePaymentApp( + mojom::PaymentParameters::New(), + base::BindOnce(&ArcPaymentAppBridgeTest::OnInvokePaymentAppResponse, + base::Unretained(this))); + + ASSERT_FALSE(invoke_app_.is_null()); + EXPECT_FALSE(invoke_app_->is_valid()); + ASSERT_TRUE(invoke_app_->is_error()); + EXPECT_EQ("Unable to invoke Android apps.", invoke_app_->get_error()); +} + +TEST_F(ArcPaymentAppBridgeTest, InvokePaymentAppResultOK) { + auto scoped_set_instance = support_.CreateScopedSetInstance(); + + EXPECT_CALL(*support_.instance(), InvokePaymentApp(testing::_, testing::_)) + .WillOnce(testing::Invoke( + [](mojom::PaymentParametersPtr parameters, + ArcPaymentAppBridge::InvokePaymentAppCallback callback) { + auto valid = mojom::InvokePaymentAppValidResult::New(); + valid->is_activity_result_ok = true; + valid->stringified_details = "{}"; + std::move(callback).Run( + mojom::InvokePaymentAppResult::NewValid(std::move(valid))); + })); + + ArcPaymentAppBridge::GetForBrowserContextForTesting(support_.context()) + ->InvokePaymentApp( + mojom::PaymentParameters::New(), + base::BindOnce(&ArcPaymentAppBridgeTest::OnInvokePaymentAppResponse, + base::Unretained(this))); + + ASSERT_FALSE(invoke_app_.is_null()); + EXPECT_FALSE(invoke_app_->is_error()); + ASSERT_TRUE(invoke_app_->is_valid()); + ASSERT_FALSE(invoke_app_->get_valid().is_null()); + EXPECT_TRUE(invoke_app_->get_valid()->is_activity_result_ok); + EXPECT_EQ("{}", invoke_app_->get_valid()->stringified_details); +} + +TEST_F(ArcPaymentAppBridgeTest, InvokePaymentAppResultCancelled) { + auto scoped_set_instance = support_.CreateScopedSetInstance(); + + EXPECT_CALL(*support_.instance(), InvokePaymentApp(testing::_, testing::_)) + .WillOnce(testing::Invoke( + [](mojom::PaymentParametersPtr parameters, + ArcPaymentAppBridge::InvokePaymentAppCallback callback) { + auto valid = mojom::InvokePaymentAppValidResult::New(); + // User cancelled payment. + valid->is_activity_result_ok = false; + std::move(callback).Run( + mojom::InvokePaymentAppResult::NewValid(std::move(valid))); + })); + + ArcPaymentAppBridge::GetForBrowserContextForTesting(support_.context()) + ->InvokePaymentApp( + mojom::PaymentParameters::New(), + base::BindOnce(&ArcPaymentAppBridgeTest::OnInvokePaymentAppResponse, + base::Unretained(this))); + + ASSERT_FALSE(invoke_app_.is_null()); + EXPECT_FALSE(invoke_app_->is_error()); + ASSERT_TRUE(invoke_app_->is_valid()); + ASSERT_FALSE(invoke_app_->get_valid().is_null()); + EXPECT_FALSE(invoke_app_->get_valid()->is_activity_result_ok); +} + +TEST_F(ArcPaymentAppBridgeTest, InvokePaymentAppError) { + auto scoped_set_instance = support_.CreateScopedSetInstance(); + + EXPECT_CALL(*support_.instance(), InvokePaymentApp(testing::_, testing::_)) + .WillOnce(testing::Invoke( + [](mojom::PaymentParametersPtr parameters, + ArcPaymentAppBridge::InvokePaymentAppCallback callback) { + std::move(callback).Run( + mojom::InvokePaymentAppResult::NewError("Error message.")); + })); + + ArcPaymentAppBridge::GetForBrowserContextForTesting(support_.context()) + ->InvokePaymentApp( + mojom::PaymentParameters::New(), + base::BindOnce(&ArcPaymentAppBridgeTest::OnInvokePaymentAppResponse, + base::Unretained(this))); + + ASSERT_FALSE(invoke_app_.is_null()); + EXPECT_FALSE(invoke_app_->is_valid()); + ASSERT_TRUE(invoke_app_->is_error()); + EXPECT_EQ("Error message.", invoke_app_->get_error()); +} + } // namespace } // namespace arc
diff --git a/components/arc/test/DEPS b/components/arc/test/DEPS index cc564af..03ebaac 100644 --- a/components/arc/test/DEPS +++ b/components/arc/test/DEPS
@@ -1,6 +1,3 @@ -specific_include_rules = { - "test_browser_context.h": [ - "+content/public/test/test_browser_context.h", - ] +include_rules = { + "+content/public/test", } -
diff --git a/components/arc/test/OWNERS b/components/arc/test/OWNERS index 4a73d756..96e956b 100644 --- a/components/arc/test/OWNERS +++ b/components/arc/test/OWNERS
@@ -1 +1,2 @@ per-file fake_*_instance.*=* +per-file payment_app_service_test_support.cc=file://components/arc/pay/OWNERS
diff --git a/components/arc/test/arc_payment_app_bridge_test_support.cc b/components/arc/test/arc_payment_app_bridge_test_support.cc new file mode 100644 index 0000000..eb8c6ee --- /dev/null +++ b/components/arc/test/arc_payment_app_bridge_test_support.cc
@@ -0,0 +1,37 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/arc/test/arc_payment_app_bridge_test_support.h" + +#include "components/arc/session/arc_bridge_service.h" + +namespace arc { + +ArcPaymentAppBridgeTestSupport::MockPaymentAppInstance:: + MockPaymentAppInstance() = default; + +ArcPaymentAppBridgeTestSupport::MockPaymentAppInstance:: + ~MockPaymentAppInstance() = default; + +ArcPaymentAppBridgeTestSupport::ScopedSetInstance::ScopedSetInstance( + ArcServiceManager* manager, + mojom::PaymentAppInstance* instance) + : manager_(manager), instance_(instance) { + manager_->arc_bridge_service()->payment_app()->SetInstance(instance_); +} + +ArcPaymentAppBridgeTestSupport::ScopedSetInstance::~ScopedSetInstance() { + manager_->arc_bridge_service()->payment_app()->CloseInstance(instance_); +} + +ArcPaymentAppBridgeTestSupport::ArcPaymentAppBridgeTestSupport() = default; + +ArcPaymentAppBridgeTestSupport::~ArcPaymentAppBridgeTestSupport() = default; + +std::unique_ptr<ArcPaymentAppBridgeTestSupport::ScopedSetInstance> +ArcPaymentAppBridgeTestSupport::CreateScopedSetInstance() { + return std::make_unique<ScopedSetInstance>(manager(), instance()); +} + +} // namespace arc
diff --git a/components/arc/test/arc_payment_app_bridge_test_support.h b/components/arc/test/arc_payment_app_bridge_test_support.h new file mode 100644 index 0000000..7c14fa2 --- /dev/null +++ b/components/arc/test/arc_payment_app_bridge_test_support.h
@@ -0,0 +1,104 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_ARC_TEST_ARC_PAYMENT_APP_BRIDGE_TEST_SUPPORT_H_ +#define COMPONENTS_ARC_TEST_ARC_PAYMENT_APP_BRIDGE_TEST_SUPPORT_H_ + +#include <memory> +#include <string> + +#include "components/arc/arc_service_manager.h" +#include "components/arc/mojom/payment_app.mojom.h" +#include "components/arc/pay/arc_payment_app_bridge.h" +#include "components/arc/test/test_browser_context.h" +#include "content/public/test/browser_task_environment.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace content { +class BrowserContext; +} // namespace content + +namespace arc { + +// Common support utility for tests of payment_app.mojom interface. +class ArcPaymentAppBridgeTestSupport { + public: + // The mock payment_app.mojom interface. + class MockPaymentAppInstance : public mojom::PaymentAppInstance { + public: + MockPaymentAppInstance(); + ~MockPaymentAppInstance() override; + + MockPaymentAppInstance(const MockPaymentAppInstance& other) = delete; + MockPaymentAppInstance& operator=(const MockPaymentAppInstance& other) = + delete; + + MOCK_METHOD2( + IsPaymentImplemented, + void(const std::string& package_name, + ArcPaymentAppBridge::IsPaymentImplementedCallback callback)); + MOCK_METHOD2(IsReadyToPay, + void(mojom::PaymentParametersPtr, + ArcPaymentAppBridge::IsReadyToPayCallback)); + MOCK_METHOD2(InvokePaymentApp, + void(mojom::PaymentParametersPtr, + ArcPaymentAppBridge::InvokePaymentAppCallback)); + }; + + // Sets up the payment_app.mojom connection in the constructor and disconnects + // in the destructor. + class ScopedSetInstance { + public: + ScopedSetInstance(ArcServiceManager* manager, + mojom::PaymentAppInstance* instance); + ~ScopedSetInstance(); + + ScopedSetInstance(const ScopedSetInstance& other) = delete; + ScopedSetInstance& operator=(const ScopedSetInstance& other) = delete; + + private: + ArcServiceManager* manager_; + mojom::PaymentAppInstance* instance_; + }; + + ArcPaymentAppBridgeTestSupport(); + ~ArcPaymentAppBridgeTestSupport(); + + ArcPaymentAppBridgeTestSupport(const ArcPaymentAppBridgeTestSupport& other) = + delete; + ArcPaymentAppBridgeTestSupport& operator=( + const ArcPaymentAppBridgeTestSupport& other) = delete; + + // Creates a ScopedSetInstance to be placed on the stack, so that + // payment_app.mojom connection is available in the test and is cleaned up + // when the returned value goes out of scope. + std::unique_ptr<ScopedSetInstance> CreateScopedSetInstance(); + + // The ARC service manager. + ArcServiceManager* manager() { return ArcServiceManager::Get(); } + + // The mock payment_app.mojom connection. + MockPaymentAppInstance* instance() { return &instance_; } + + // The browser context that should be used in the test. + content::BrowserContext* context() { return &context_; } + + private: + // Required for the TestBrowserContext and ArcServiceManager. + content::BrowserTaskEnvironment task_environment_; + + // Used for retrieving an instance of ArcPaymentAppBridge owned by a + // BrowserContext. + TestBrowserContext context_; + + // The unit test must create an instance of ArcServiceManager for + // ArcServiceManager::Get() to work correctly. + ArcServiceManager manager_; + + MockPaymentAppInstance instance_; +}; + +} // namespace arc + +#endif // COMPONENTS_ARC_TEST_ARC_PAYMENT_APP_BRIDGE_TEST_SUPPORT_H_
diff --git a/components/autofill/core/common/autofill_regex_constants.cc b/components/autofill/core/common/autofill_regex_constants.cc index fef8cd6..da36233 100644 --- a/components/autofill/core/common/autofill_regex_constants.cc +++ b/components/autofill/core/common/autofill_regex_constants.cc
@@ -317,9 +317,7 @@ "|(\\b|_|\\*)(isim|ad|ad(i|ı|iniz|ınız)?)(\\b|_|\\*)" // tr "|नाम"; // hi const char kMiddleInitialRe[] = "middle.*initial|m\\.i\\.|mi$|\\bmi\\b"; -const char kMiddleNameRe[] = - "middle.*name|mname|middle$" - "|apellido.?materno|lastlastname"; // es +const char kMiddleNameRe[] = "middle.*name|mname|middle$"; const char kLastNameRe[] = "last.*name|lname|surname(?!\\d)|last$|secondname|family.*name" "|nachname" // de-DE
diff --git a/components/autofill/core/common/password_form.h b/components/autofill/core/common/password_form.h index 40b29f2..ef87deb 100644 --- a/components/autofill/core/common/password_form.h +++ b/components/autofill/core/common/password_form.h
@@ -118,6 +118,9 @@ // form parsing and not persisted. FieldRendererId username_element_renderer_id; + // True if the server-side classification was successful. + bool server_side_classification_successful = false; + // True if the server-side classification believes that the field may be // pre-filled with a placeholder in the value attribute. It is set during // form parsing and not persisted.
diff --git a/components/browser_ui/strings/android/site_settings.grdp b/components/browser_ui/strings/android/site_settings.grdp index af65c55..767e05e 100644 --- a/components/browser_ui/strings/android/site_settings.grdp +++ b/components/browser_ui/strings/android/site_settings.grdp
@@ -211,7 +211,7 @@ You'll be signed out of all sites. </message> <message name="IDS_STORAGE_CLEAR_SITE_STORAGE_TITLE" desc="Title of clear storage dialogs used in a couple different places to confirm clearing site storage data. [CHAR-LIMIT=24]"> - Clear site storage? + Clear site data? </message> <message name="IDS_STORAGE_CLEAR_DIALOG_CLEAR_STORAGE_OPTION" desc="Text of the button that will clear website storage."> Clear
diff --git a/components/browser_ui/strings/android/site_settings_grdp/IDS_STORAGE_CLEAR_SITE_STORAGE_TITLE.png.sha1 b/components/browser_ui/strings/android/site_settings_grdp/IDS_STORAGE_CLEAR_SITE_STORAGE_TITLE.png.sha1 new file mode 100644 index 0000000..91d626e --- /dev/null +++ b/components/browser_ui/strings/android/site_settings_grdp/IDS_STORAGE_CLEAR_SITE_STORAGE_TITLE.png.sha1
@@ -0,0 +1 @@ +870987174981c44e16485836e453676f4129b6dc \ No newline at end of file
diff --git a/components/exo/data_offer.cc b/components/exo/data_offer.cc index 9027d77c..cb558f5 100644 --- a/components/exo/data_offer.cc +++ b/components/exo/data_offer.cc
@@ -31,6 +31,8 @@ namespace exo { namespace { +constexpr char kTextMimeTypeUtf8[] = "text/plain;charset=utf-8"; +constexpr char kUtf8String[] = "UTF8_STRING"; constexpr char kTextMimeTypeUtf16[] = "text/plain;charset=utf-16"; constexpr char kTextHtmlMimeTypeUtf8[] = "text/html;charset=utf-8"; constexpr char kTextHtmlMimeTypeUtf16[] = "text/html;charset=utf-16"; @@ -277,7 +279,7 @@ base::string16 string_content; if (data.HasString() && data.GetString(&string_content)) { - const std::string utf8_mime_type = std::string(ui::kMimeTypeTextUtf8); + const std::string utf8_mime_type = std::string(kTextMimeTypeUtf8); data_.emplace(utf8_mime_type, EncodeAsRefCountedString(string_content, kUTF8)); delegate_->OnOffer(utf8_mime_type); @@ -319,11 +321,10 @@ /* data_dst = */ nullptr)) { auto utf8_callback = base::BindRepeating(&ReadTextFromClipboard, std::string(kUTF8)); - delegate_->OnOffer(std::string(ui::kMimeTypeTextUtf8)); - data_callbacks_.emplace(std::string(ui::kMimeTypeTextUtf8), utf8_callback); - delegate_->OnOffer(std::string(ui::kMimeTypeLinuxUtf8String)); - data_callbacks_.emplace(std::string(ui::kMimeTypeLinuxUtf8String), - utf8_callback); + delegate_->OnOffer(std::string(kTextMimeTypeUtf8)); + data_callbacks_.emplace(std::string(kTextMimeTypeUtf8), utf8_callback); + delegate_->OnOffer(std::string(kUtf8String)); + data_callbacks_.emplace(std::string(kUtf8String), utf8_callback); delegate_->OnOffer(std::string(kTextMimeTypeUtf16)); data_callbacks_.emplace( std::string(kTextMimeTypeUtf16),
diff --git a/components/exo/data_source.cc b/components/exo/data_source.cc index e612082731..53765d91 100644 --- a/components/exo/data_source.cc +++ b/components/exo/data_source.cc
@@ -22,7 +22,6 @@ #include "net/base/mime_util.h" #include "third_party/blink/public/common/mime_util/mime_util.h" #include "third_party/icu/source/common/unicode/ucnv.h" -#include "ui/base/clipboard/clipboard_constants.h" namespace exo { @@ -249,7 +248,7 @@ for (auto mime_type : mime_types_) { if (net::MatchesMimeType(std::string(kTextPlain), mime_type) || - mime_type == ui::kMimeTypeLinuxUtf8String) { + mime_type == kEncodingUTF8Legacy) { if (text_reader.is_null()) continue;
diff --git a/components/exo/mime_utils.cc b/components/exo/mime_utils.cc index 40ae71f4..b988607 100644 --- a/components/exo/mime_utils.cc +++ b/components/exo/mime_utils.cc
@@ -4,8 +4,6 @@ #include "components/exo/mime_utils.h" -#include "ui/base/clipboard/clipboard_constants.h" - namespace { constexpr char kCharset[] = ";charset="; @@ -18,7 +16,7 @@ std::string GetCharset(const std::string& mime_type) { // We special case UTF8_STRING to provide minimal handling of X11 apps. - if (mime_type == ui::kMimeTypeLinuxUtf8String) + if (mime_type == kEncodingUTF8Legacy) return std::string(kEncodingUTF8Charset); auto pos = mime_type.find(kCharset);
diff --git a/components/exo/mime_utils.h b/components/exo/mime_utils.h index 5905e17..8e2b4b5 100644 --- a/components/exo/mime_utils.h +++ b/components/exo/mime_utils.h
@@ -9,6 +9,8 @@ namespace exo { +constexpr char kEncodingUTF8Legacy[] = "UTF8_STRING"; + // Takes a text/* mime type and returns the name of the character set specified // in the type. If no character set is specified, defaults to US-ASCII. std::string GetCharset(const std::string& mime_type);
diff --git a/components/management/resources/images/enterprise_icon.svg b/components/management/resources/images/enterprise_icon.svg new file mode 100644 index 0000000..436a7d6 --- /dev/null +++ b/components/management/resources/images/enterprise_icon.svg
@@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="48px" viewBox="0 0 24 24" width="48px" fill="#5f6368"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M12 7V3H2v18h20V7H12zM6 19H4v-2h2v2zm0-4H4v-2h2v2zm0-4H4V9h2v2zm0-4H4V5h2v2zm4 12H8v-2h2v2zm0-4H8v-2h2v2zm0-4H8V9h2v2zm0-4H8V5h2v2zm10 12h-8v-2h2v-2h-2v-2h2v-2h-2V9h8v10zm-2-8h-2v2h2v-2zm0 4h-2v2h2v-2z"/></svg> \ No newline at end of file
diff --git a/components/management/resources/management.css b/components/management/resources/management.css index 9243ca8..6f01ff0 100644 --- a/components/management/resources/management.css +++ b/components/management/resources/management.css
@@ -3,14 +3,14 @@ * found in the LICENSE file. */ -/* TODO(crbug.com/1108981): adjust the style when the design is finalized. */ body { color: rgb(95, 99, 104); font-size: 2em; - margin: 10%; + line-height: 1.5; + margin: 5%; min-width: 500; /* Wrap content to screen on mobile. */ text-align: start; - width: 80%; + width: 90%; } a { @@ -18,10 +18,20 @@ text-decoration: none; } -#main-message { - margin-bottom: 2em; +img { + height: auto; + margin-top: 2em; + width: 15%; +} + +#main-message, +#unmanaged-info { + color: black; + font-size: 1.5em; + margin-bottom: 1em; + margin-top: 2em; } .hidden { display: none; -} \ No newline at end of file +}
diff --git a/components/management/resources/management.html b/components/management/resources/management.html index b5a8d96..168c8bbf 100644 --- a/components/management/resources/management.html +++ b/components/management/resources/management.html
@@ -24,6 +24,7 @@ </script> </head> <body> + <img src="images/enterprise_icon.svg"> <div id="managed-info" class="hidden"> <div id="main-message">$i18n{managementMessage}</div> <div id="secondary-message">$i18n{managedInfo}
diff --git a/components/omnibox/browser/BUILD.gn b/components/omnibox/browser/BUILD.gn index 8064739..618f750 100644 --- a/components/omnibox/browser/BUILD.gn +++ b/components/omnibox/browser/BUILD.gn
@@ -275,8 +275,6 @@ "location_bar_model_delegate.h", "location_bar_model_impl.cc", "location_bar_model_impl.h", - "location_bar_model_util.cc", - "location_bar_model_util.h", ] public_deps = [
diff --git a/components/omnibox/browser/autocomplete_classifier.cc b/components/omnibox/browser/autocomplete_classifier.cc index 5ea9964..a7c54964 100644 --- a/components/omnibox/browser/autocomplete_classifier.cc +++ b/components/omnibox/browser/autocomplete_classifier.cc
@@ -43,19 +43,9 @@ #if !defined(OS_ANDROID) && !defined(OS_IOS) // Custom search engines cannot be used on mobile. AutocompleteProvider::TYPE_KEYWORD | -#endif -#if defined(OS_ANDROID) +#else AutocompleteProvider::TYPE_CLIPBOARD | #endif -#if defined(OS_IOS) - // On iOS 14, a notification appears whenever the clipboard is accessed. - // The clipboard provider accesses the clipboard every time the omnibox is - // opened. Until a better solution is found, disable the clipboard - // provider temporarily. See crbug.com/1098722. - (!base::ios::IsRunningOnIOS14OrLater() - ? AutocompleteProvider::TYPE_CLIPBOARD - : 0) | -#endif AutocompleteProvider::TYPE_ZERO_SUGGEST | AutocompleteProvider::TYPE_ZERO_SUGGEST_LOCAL_HISTORY | (base::FeatureList::IsEnabled(omnibox::kDocumentProvider)
diff --git a/components/omnibox/browser/autocomplete_controller.cc b/components/omnibox/browser/autocomplete_controller.cc index 345ff70..f66274cd 100644 --- a/components/omnibox/browser/autocomplete_controller.cc +++ b/components/omnibox/browser/autocomplete_controller.cc
@@ -320,9 +320,10 @@ // ClipboardRecentContent can be null in iOS tests. For non-iOS, we // create a ClipboardRecentContent as above (for both Chrome and tests). if (ClipboardRecentContent::GetInstance()) { - providers_.push_back(new ClipboardProvider( + clipboard_provider_ = new ClipboardProvider( provider_client_.get(), this, history_url_provider_, - ClipboardRecentContent::GetInstance())); + ClipboardRecentContent::GetInstance()); + providers_.push_back(clipboard_provider_); } }
diff --git a/components/omnibox/browser/autocomplete_controller.h b/components/omnibox/browser/autocomplete_controller.h index 7b4f0ff..a2f127e 100644 --- a/components/omnibox/browser/autocomplete_controller.h +++ b/components/omnibox/browser/autocomplete_controller.h
@@ -24,6 +24,7 @@ #include "components/omnibox/browser/autocomplete_provider_listener.h" #include "components/omnibox/browser/autocomplete_result.h" +class ClipboardProvider; class DocumentProvider; class HistoryURLProvider; class KeywordProvider; @@ -160,6 +161,7 @@ } KeywordProvider* keyword_provider() const { return keyword_provider_; } SearchProvider* search_provider() const { return search_provider_; } + ClipboardProvider* clipboard_provider() const { return clipboard_provider_; } const AutocompleteInput& input() const { return input_; } const AutocompleteResult& result() const { return result_; } @@ -294,6 +296,8 @@ OnDeviceHeadProvider* on_device_head_provider_; + ClipboardProvider* clipboard_provider_; + // Input passed to Start. AutocompleteInput input_;
diff --git a/components/omnibox/browser/clipboard_provider.cc b/components/omnibox/browser/clipboard_provider.cc index d15b6c3..25b3b18 100644 --- a/components/omnibox/browser/clipboard_provider.cc +++ b/components/omnibox/browser/clipboard_provider.cc
@@ -150,16 +150,37 @@ if (CreateImageMatch(input)) return; - base::Optional<AutocompleteMatch> optional_match = CreateURLMatch(input); - if (!optional_match) - optional_match = CreateTextMatch(input); + bool read_clipboard_content = false; + bool read_clipboard_url; + base::Optional<AutocompleteMatch> optional_match = + CreateURLMatch(input, &read_clipboard_url); + read_clipboard_content |= read_clipboard_url; + if (!optional_match) { + bool read_clipboard_text; + optional_match = CreateTextMatch(input, &read_clipboard_text); + read_clipboard_content |= read_clipboard_text; + } - // The clipboard does not contain any suggestions - if (!optional_match) + if (optional_match) { + AddCreatedMatchWithTracking(input, std::move(optional_match).value(), + clipboard_content_->GetClipboardContentAge()); return; + } - AddCreatedMatchWithTracking(input, std::move(optional_match).value(), - clipboard_content_->GetClipboardContentAge()); + // If there was clipboard content, but no match, don't proceed. There was + // some other reason for not creating a match (e.g. copied URL but the URL was + // the same as the current URL). + if (read_clipboard_content) { + return; + } + + // On iOS 14, accessing the clipboard contents shows a notification to the + // user. To avoid this, all the methods above will not check the contents and + // will return false/base::nullopt. Instead, check the existence of content + // without accessing the actual content and create blank matches. + done_ = false; + // Image matched was kicked off asynchronously, so proceed when that ends. + CheckClipboardContent(input); } void ClipboardProvider::Stop(bool clear_cached_results, @@ -226,7 +247,6 @@ current_url_suggested_times_ = 1; } - // If the omnibox is not empty, add a default match. // This match will be opened when the user presses "Enter". if (!input.text().empty()) { @@ -247,14 +267,97 @@ matches_.push_back(match); } +bool ClipboardProvider::TemplateURLSupportsTextSearch() { + TemplateURLService* url_service = client_->GetTemplateURLService(); + const TemplateURL* default_url = url_service->GetDefaultSearchProvider(); + if (!default_url) + return false; + + DCHECK(!default_url->url().empty()); + DCHECK(default_url->url_ref().IsValid(url_service->search_terms_data())); + return true; +} + +bool ClipboardProvider::TemplateURLSupportsImageSearch() { + TemplateURLService* url_service = client_->GetTemplateURLService(); + const TemplateURL* default_url = url_service->GetDefaultSearchProvider(); + + return default_url && !default_url->image_url().empty() && + default_url->image_url_ref().IsValid(url_service->search_terms_data()); +} + +void ClipboardProvider::CheckClipboardContent(const AutocompleteInput& input) { + std::set<ClipboardContentType> desired_types; + desired_types.insert(ClipboardContentType::URL); + + if (TemplateURLSupportsTextSearch()) { + desired_types.insert(ClipboardContentType::Text); + } + + if (base::FeatureList::IsEnabled( + omnibox::kEnableClipboardProviderImageSuggestions) && + TemplateURLSupportsImageSearch()) { + desired_types.insert(ClipboardContentType::Image); + } + + // We want to get the age here because the contents of the clipboard could + // change after this point. We want the age of the contents we actually use, + // not the age of whatever's on the clipboard when the histogram is created + // (i.e when the match is created). + base::TimeDelta clipboard_contents_age = + clipboard_content_->GetClipboardContentAge(); + clipboard_content_->HasRecentContentFromClipboard( + desired_types, + base::BindOnce(&ClipboardProvider::OnReceiveClipboardContent, + callback_weak_ptr_factory_.GetWeakPtr(), input, + clipboard_contents_age)); +} + +void ClipboardProvider::OnReceiveClipboardContent( + const AutocompleteInput& input, + base::TimeDelta clipboard_contents_age, + std::set<ClipboardContentType> matched_types) { + if (matched_types.find(ClipboardContentType::Image) != matched_types.end()) { + // The image content will be added in later. If the image is large, encoding + // the image may take some time, so just be wary whenever that step happens + // (e.g OmniboxView::OpenMatch). + AutocompleteMatch match = NewBlankImageMatch(); + field_trial_triggered_ = true; + field_trial_triggered_in_session_ = true; + // Some users may be in a counterfactual study arm in which we perform all + // necessary work but do not forward the autocomplete matches. + bool in_counterfactual_group = base::GetFieldTrialParamByFeatureAsBool( + omnibox::kEnableClipboardProviderImageSuggestions, + "ClipboardProviderImageSuggestionsCounterfactualArm", false); + if (!in_counterfactual_group) { + AddCreatedMatchWithTracking(input, match, clipboard_contents_age); + listener_->OnProviderUpdate(true); + } + } else if (matched_types.find(ClipboardContentType::URL) != + matched_types.end()) { + AutocompleteMatch match = NewBlankURLMatch(); + AddCreatedMatchWithTracking(input, match, clipboard_contents_age); + listener_->OnProviderUpdate(true); + } else if (matched_types.find(ClipboardContentType::Text) != + matched_types.end()) { + AutocompleteMatch match = NewBlankTextMatch(); + AddCreatedMatchWithTracking(input, match, clipboard_contents_age); + listener_->OnProviderUpdate(true); + } + done_ = true; +} + base::Optional<AutocompleteMatch> ClipboardProvider::CreateURLMatch( - const AutocompleteInput& input) { + const AutocompleteInput& input, + bool* read_clipboard_content) { + *read_clipboard_content = false; // The clipboard does not contain a URL worth suggesting. base::Optional<GURL> optional_gurl = clipboard_content_->GetRecentURLFromClipboard(); if (!optional_gurl) return base::nullopt; + *read_clipboard_content = true; GURL url = std::move(optional_gurl).value(); // The URL on the page is the same as the URL in the clipboard. Don't @@ -262,11 +365,103 @@ if (url == input.current_url()) return base::nullopt; - DCHECK(url.is_valid()); + return NewClipboardURLMatch(url); +} +base::Optional<AutocompleteMatch> ClipboardProvider::CreateTextMatch( + const AutocompleteInput& input, + bool* read_clipboard_content) { + *read_clipboard_content = false; + base::Optional<base::string16> optional_text = + clipboard_content_->GetRecentTextFromClipboard(); + if (!optional_text) + return base::nullopt; + + *read_clipboard_content = true; + base::string16 text = std::move(optional_text).value(); + + // The clipboard can contain the empty string, which shouldn't be suggested. + if (text.empty()) + return base::nullopt; + + // The text in the clipboard is a url. We don't want to prompt the user to + // search for a url. + if (GURL(text).is_valid()) + return base::nullopt; + + return NewClipboardTextMatch(text); +} + +bool ClipboardProvider::CreateImageMatch(const AutocompleteInput& input) { + // Only try image match if feature is enabled + if (!base::FeatureList::IsEnabled( + omnibox::kEnableClipboardProviderImageSuggestions)) { + return false; + } + + if (!clipboard_content_->HasRecentImageFromClipboard()) { + return false; + } + + if (!TemplateURLSupportsImageSearch()) { + return false; + } + + done_ = false; + + // We want to get the age here because the contents of the clipboard could + // change after this point. We want the age of the image we actually use, not + // the age of whatever's on the clipboard when the histogram is created (i.e + // when the match is created). + base::TimeDelta clipboard_contents_age = + clipboard_content_->GetClipboardContentAge(); + clipboard_content_->GetRecentImageFromClipboard(base::BindOnce( + &ClipboardProvider::CreateImageMatchCallback, + callback_weak_ptr_factory_.GetWeakPtr(), input, clipboard_contents_age)); + return true; +} + +void ClipboardProvider::CreateImageMatchCallback( + const AutocompleteInput& input, + const base::TimeDelta clipboard_contents_age, + base::Optional<gfx::Image> optional_image) { + if (!optional_image) { + return; + } + NewClipboardImageMatch( + optional_image.value(), + base::BindOnce(&ClipboardProvider::AddImageMatchCallback, + callback_weak_ptr_factory_.GetWeakPtr(), input, + clipboard_contents_age)); +} +void ClipboardProvider::AddImageMatchCallback( + const AutocompleteInput& input, + const base::TimeDelta clipboard_contents_age, + base::Optional<AutocompleteMatch> match) { + if (!match) { + return; + } + AddCreatedMatchWithTracking(input, match.value(), clipboard_contents_age); + listener_->OnProviderUpdate(true); + done_ = true; +} + +AutocompleteMatch ClipboardProvider::NewBlankURLMatch() { AutocompleteMatch match(this, kClipboardMatchRelevanceScore, IsMatchDeletionEnabled(), AutocompleteMatchType::CLIPBOARD_URL); + + match.description.assign(l10n_util::GetStringUTF16(IDS_LINK_FROM_CLIPBOARD)); + if (!match.description.empty()) + match.description_class.push_back({0, ACMatchClassification::NONE}); + return match; +} + +AutocompleteMatch ClipboardProvider::NewClipboardURLMatch(GURL url) { + DCHECK(url.is_valid()); + + AutocompleteMatch match = NewBlankURLMatch(); + match.destination_url = url; // Because the user did not type a related input to get this clipboard @@ -279,35 +474,30 @@ match.fill_into_edit = AutocompleteInput::FormattedStringWithEquivalentMeaning( url, match.contents, client_->GetSchemeClassifier(), nullptr); - - match.description.assign(l10n_util::GetStringUTF16(IDS_LINK_FROM_CLIPBOARD)); - if (!match.description.empty()) - match.description_class.push_back({0, ACMatchClassification::NONE}); - return match; } -base::Optional<AutocompleteMatch> ClipboardProvider::CreateTextMatch( - const AutocompleteInput& input) { - base::Optional<base::string16> optional_text = - clipboard_content_->GetRecentTextFromClipboard(); - if (!optional_text) - return base::nullopt; +AutocompleteMatch ClipboardProvider::NewBlankTextMatch() { + AutocompleteMatch match(this, kClipboardMatchRelevanceScore, + IsMatchDeletionEnabled(), + AutocompleteMatchType::CLIPBOARD_TEXT); - base::string16 text = std::move(optional_text).value(); + match.description.assign(l10n_util::GetStringUTF16(IDS_TEXT_FROM_CLIPBOARD)); + if (!match.description.empty()) + match.description_class.push_back({0, ACMatchClassification::NONE}); - // The clipboard can contain the empty string, which shouldn't be suggested. - if (text.empty()) - return base::nullopt; + match.transition = ui::PAGE_TRANSITION_GENERATED; + return match; +} +base::Optional<AutocompleteMatch> ClipboardProvider::NewClipboardTextMatch( + base::string16 text) { // The text in the clipboard is a url. We don't want to prompt the user to // search for a url. if (GURL(text).is_valid()) return base::nullopt; - AutocompleteMatch match(this, kClipboardMatchRelevanceScore, - IsMatchDeletionEnabled(), - AutocompleteMatchType::CLIPBOARD_TEXT); + AutocompleteMatch match = NewBlankTextMatch(); match.fill_into_edit = text; TemplateURLService* url_service = client_->GetTemplateURLService(); @@ -327,65 +517,51 @@ if (!match.contents.empty()) match.contents_class.push_back({0, ACMatchClassification::NONE}); - match.description.assign(l10n_util::GetStringUTF16(IDS_TEXT_FROM_CLIPBOARD)); + match.keyword = default_url->keyword(); + + return match; +} + +AutocompleteMatch ClipboardProvider::NewBlankImageMatch() { + AutocompleteMatch match(this, kClipboardMatchRelevanceScore, + IsMatchDeletionEnabled(), + AutocompleteMatchType::CLIPBOARD_IMAGE); + + match.description.assign(l10n_util::GetStringUTF16(IDS_IMAGE_FROM_CLIPBOARD)); if (!match.description.empty()) match.description_class.push_back({0, ACMatchClassification::NONE}); - match.keyword = default_url->keyword(); + // This will end up being something like "Search for Copied Image." This may + // seem strange to use for |fill_into_edit|, but it is because iOS requires + // some text in the text field for the Enter key to work when using keyboard + // navigation. + match.fill_into_edit = match.description; match.transition = ui::PAGE_TRANSITION_GENERATED; return match; } -bool ClipboardProvider::CreateImageMatch(const AutocompleteInput& input) { - // Only try image match if feature is enabled - if (!base::FeatureList::IsEnabled( - omnibox::kEnableClipboardProviderImageSuggestions)) { - return false; - } - - if (!clipboard_content_->HasRecentImageFromClipboard()) { - return false; - } - - // Make sure current provider supports image search - TemplateURLService* url_service = client_->GetTemplateURLService(); - const TemplateURL* default_url = url_service->GetDefaultSearchProvider(); - - if (!default_url || default_url->image_url().empty() || - !default_url->image_url_ref().IsValid(url_service->search_terms_data())) { - return false; - } - - // We want to get the age here because the contents of the clipboard could - // change after this point. We want the age of the image we actually use, not - // the age of whatever's on the clipboard when the histogram is created (i.e - // when the match is created). - base::TimeDelta clipboard_contents_age = - clipboard_content_->GetClipboardContentAge(); - clipboard_content_->GetRecentImageFromClipboard( - base::BindOnce(&ClipboardProvider::OnReceiveImage, - callback_weak_ptr_factory_.GetWeakPtr(), input, - url_service, clipboard_contents_age)); - return true; +void ClipboardProvider::NewClipboardImageMatch( + gfx::Image image, + ClipboardImageMatchCallback callback) { + clipboard_content_->GetRecentImageFromClipboard(base::BindOnce( + &ClipboardProvider::OnReceiveImage, + callback_weak_ptr_factory_.GetWeakPtr(), std::move(callback))); } void ClipboardProvider::OnReceiveImage( - const AutocompleteInput& input, - TemplateURLService* url_service, - base::TimeDelta clipboard_contents_age, + ClipboardImageMatchCallback callback, base::Optional<gfx::Image> optional_image) { if (!optional_image) - return; - done_ = false; + std::move(callback).Run(base::nullopt); gfx::ImageSkia image_skia = *optional_image.value().ToImageSkia(); image_skia.MakeThreadSafe(); base::ThreadPool::PostTaskAndReplyWithResult( FROM_HERE, base::BindOnce(&ClipboardProvider::EncodeClipboardImage, image_skia), base::BindOnce(&ClipboardProvider::ConstructImageMatchCallback, - callback_weak_ptr_factory_.GetWeakPtr(), input, - url_service, clipboard_contents_age)); + callback_weak_ptr_factory_.GetWeakPtr(), + std::move(callback))); } scoped_refptr<base::RefCountedMemory> ClipboardProvider::EncodeClipboardImage( @@ -396,26 +572,13 @@ } void ClipboardProvider::ConstructImageMatchCallback( - const AutocompleteInput& input, - TemplateURLService* url_service, - base::TimeDelta clipboard_contents_age, + ClipboardImageMatchCallback callback, scoped_refptr<base::RefCountedMemory> image_bytes) { + TemplateURLService* url_service = client_->GetTemplateURLService(); const TemplateURL* default_url = url_service->GetDefaultSearchProvider(); DCHECK(default_url); - AutocompleteMatch match(this, kClipboardMatchRelevanceScore, - IsMatchDeletionEnabled(), - AutocompleteMatchType::CLIPBOARD_IMAGE); - - match.description.assign(l10n_util::GetStringUTF16(IDS_IMAGE_FROM_CLIPBOARD)); - if (!match.description.empty()) - match.description_class.push_back({0, ACMatchClassification::NONE}); - - // This will end up being something like "Search for Copied Image." This may - // seem strange to use for |fill_into_edit, but it is because iOS requires - // some text in the text field for the Enter key to work when using keyboard - // navigation. - match.fill_into_edit = match.description; + AutocompleteMatch match = NewBlankImageMatch(); match.search_terms_args = std::make_unique<TemplateURLRef::SearchTermsArgs>(base::ASCIIToUTF16("")); @@ -436,19 +599,5 @@ match.post_content = std::make_unique<TemplateURLRef::PostContent>(post_content); - match.transition = ui::PAGE_TRANSITION_GENERATED; - - field_trial_triggered_ = true; - field_trial_triggered_in_session_ = true; - done_ = true; - - // Some users may be in a counterfactual study arm in which we perform all - // necessary work but do not forward the autocomplete matches. - bool in_counterfactual_group = base::GetFieldTrialParamByFeatureAsBool( - omnibox::kEnableClipboardProviderImageSuggestions, - "ClipboardProviderImageSuggestionsCounterfactualArm", false); - if (!in_counterfactual_group) { - AddCreatedMatchWithTracking(input, match, clipboard_contents_age); - listener_->OnProviderUpdate(true); - } + std::move(callback).Run(match); }
diff --git a/components/omnibox/browser/clipboard_provider.h b/components/omnibox/browser/clipboard_provider.h index e75d819..20d3117 100644 --- a/components/omnibox/browser/clipboard_provider.h +++ b/components/omnibox/browser/clipboard_provider.h
@@ -12,6 +12,7 @@ class AutocompleteProviderClient; class ClipboardRecentContent; class HistoryURLProvider; +enum class ClipboardContentType; // Autocomplete provider offering content based on the clipboard's content. class ClipboardProvider : public AutocompleteProvider { @@ -24,6 +25,23 @@ ClipboardProvider(const ClipboardProvider&) = delete; ClipboardProvider& operator=(const ClipboardProvider&) = delete; + // Returns a new AutocompleteMatch clipboard match that will navigate to the + // given copied url. Used to construct a match later when the URL is not + // available at match creation time (e.g. iOS 14). + AutocompleteMatch NewClipboardURLMatch(GURL url); + // Returns a new AutocompleteMatch clipboard match that will search for the + // given copied text. Used to construct a match later when the text is not + // available at match creation time (e.g. iOS 14). + base::Optional<AutocompleteMatch> NewClipboardTextMatch(base::string16 text); + + using ClipboardImageMatchCallback = + base::OnceCallback<void(base::Optional<AutocompleteMatch>)>; + // Returns a new AutocompleteMatch clipboard match that will search for the + // given copied image. Used to construct a match later when the image is not + // available at match creation time (e.g. iOS 14). + void NewClipboardImageMatch(gfx::Image image, + ClipboardImageMatchCallback callback); + // AutocompleteProvider implementation. void Start(const AutocompleteInput& input, bool minimal_changes) override; void Stop(bool clear_cached_results, bool due_to_user_inactivity) override; @@ -43,23 +61,72 @@ const AutocompleteMatch& match, const base::TimeDelta clipboard_contents_age); - // If there is a url copied to the clipboard, use it to create a match. + // Uses asynchronous clipboard APIs to check which content types have + // clipboard data without actually accessing the data. If any do, then one + // clipboard match is created. Calls back to |OnReceiveClipboardContent| with + // the result. + void CheckClipboardContent(const AutocompleteInput& input); + // Called when the clipboard data is returned from the asynchronous call. + void OnReceiveClipboardContent(const AutocompleteInput& input, + base::TimeDelta clipboard_contents_age, + std::set<ClipboardContentType> matched_types); + + // Checks whether the current template url supports text searches. + bool TemplateURLSupportsTextSearch(); + // Checks whether the current template url supports image searches. + bool TemplateURLSupportsImageSearch(); + + // Returns a URL match with no URL. This can be used if the clipboard content + // is inaccessible at match creation time (e.g. iOS 14). + AutocompleteMatch NewBlankURLMatch(); + + // Returns a text match with no text. This can be used if the clipboard + // content is inaccessible at match creation time (e.g. iOS 14). + AutocompleteMatch NewBlankTextMatch(); + + // Returns a image match with no attached image. This can be used if the + // clipboard content is inaccessible at match creation time (e.g. iOS 14). + AutocompleteMatch NewBlankImageMatch(); + + // If there is a url copied to the clipboard and accessing it will not show a + // clipboard access notification (e.g. iOS 14), use it to create a match. + // |read_clipboard_content| will be filled with false if the clipboard didn't + // have any content (either because there was none or because accessing it + // would have shown a clipboard access notification, and true if there was + // content. base::Optional<AutocompleteMatch> CreateURLMatch( - const AutocompleteInput& input); - // If there is text copied to the clipboard, use it to create a match. + const AutocompleteInput& input, + bool* read_clipboard_content); + // If there is text copied to the clipboard and accessing it will not show a + // clipboard access notification (e.g. iOS 14), use it to create a match. + // |read_clipboard_content| will be filled with false if the clipboard didn't + // have any content (either because there was none or because accessing it + // would have shown a clipboard access notification, and true if there was + // content. base::Optional<AutocompleteMatch> CreateTextMatch( - const AutocompleteInput& input); - // If there is an image copied to the clipboard, use it to create a match. + const AutocompleteInput& input, + bool* read_clipboard_content); + // If there is an image copied to the clipboard and accessing it will not show + // a clipboard access notification (e.g. iOS 14), use it to create a match. // The image match is asynchronous (because constructing the image post data // takes time), so instead of returning an optional match like the other // Create functions, it returns a boolean indicating whether there will be a // match. bool CreateImageMatch(const AutocompleteInput& input); - // Called when received image data from clipboard. - void OnReceiveImage(const AutocompleteInput& input, - TemplateURLService* url_service, - base::TimeDelta clipboard_contents_age, + // Handles the callback response from |CreateImageMatch| and turns the image + // into an AutocompleteMatch. + void CreateImageMatchCallback(const AutocompleteInput& input, + const base::TimeDelta clipboard_contents_age, + base::Optional<gfx::Image>); + // Handles the callback response from |CreateImageMatchCallback| and adds the + // created AutocompleteMatch to the matches list. + void AddImageMatchCallback(const AutocompleteInput& input, + const base::TimeDelta clipboard_contents_age, + base::Optional<AutocompleteMatch> match); + + // Called when image data is received from clipboard. + void OnReceiveImage(ClipboardImageMatchCallback callback, base::Optional<gfx::Image> optional_image); // Resize and encode the image data into bytes. This can take some time if the @@ -69,9 +136,7 @@ // Construct the actual image match once the image has been encoded into // bytes. This should be called back on the main thread. void ConstructImageMatchCallback( - const AutocompleteInput& input, - TemplateURLService* url_service, - base::TimeDelta clipboard_contents_age, + ClipboardImageMatchCallback callback, scoped_refptr<base::RefCountedMemory> image_bytes); AutocompleteProviderClient* client_;
diff --git a/components/omnibox/browser/clipboard_provider_unittest.cc b/components/omnibox/browser/clipboard_provider_unittest.cc index dde3293..82ed6091 100644 --- a/components/omnibox/browser/clipboard_provider_unittest.cc +++ b/components/omnibox/browser/clipboard_provider_unittest.cc
@@ -82,6 +82,10 @@ return input; } + void MatchesImageCallback(base::Optional<AutocompleteMatch> match) { + matches_image_match_ = match; + } + protected: // AutocompleteProviderListener: void OnProviderUpdate(bool updated_matches) override; @@ -90,6 +94,8 @@ FakeClipboardRecentContent clipboard_content_; std::unique_ptr<MockAutocompleteProviderClient> client_; scoped_refptr<ClipboardProvider> provider_; + + base::Optional<AutocompleteMatch> matches_image_match_; }; void ClipboardProviderTest::OnProviderUpdate(bool updated_matches) { @@ -102,12 +108,18 @@ } TEST_F(ClipboardProviderTest, EmptyClipboard) { + auto template_url_service = std::make_unique<TemplateURLService>( + /*initializers=*/nullptr, /*count=*/0); + client_->set_template_url_service(std::move(template_url_service)); ClearClipboard(); provider_->Start(CreateAutocompleteInput(OmniboxFocusType::ON_FOCUS), false); EXPECT_TRUE(provider_->matches().empty()); } TEST_F(ClipboardProviderTest, ClipboardIsCurrentURL) { + auto template_url_service = std::make_unique<TemplateURLService>( + /*initializers=*/nullptr, /*count=*/0); + client_->set_template_url_service(std::move(template_url_service)); SetClipboardUrl(GURL(kCurrentURL)); provider_->Start(CreateAutocompleteInput(OmniboxFocusType::ON_FOCUS), false); EXPECT_TRUE(provider_->matches().empty()); @@ -152,20 +164,21 @@ base::Feature imageFeature = omnibox::kEnableClipboardProviderImageSuggestions; feature_list.InitAndEnableFeature(imageFeature); - TemplateURLService template_url_service(/*initializers=*/nullptr, - /*count=*/0); - base::TimeDelta clipboard_age = base::TimeDelta::FromSeconds(5); + auto template_url_service = + std::make_unique<TemplateURLService>(/*initializers=*/nullptr, + /*count=*/0); + client_->set_template_url_service(std::move(template_url_service)); gfx::Image test_image = gfx::test::CreateImage(/*height=*/10, /*width=*/10); scoped_refptr<base::RefCountedMemory> image_bytes = provider_->EncodeClipboardImage(*test_image.ToImageSkia()); ASSERT_TRUE(image_bytes); provider_->ConstructImageMatchCallback( - CreateAutocompleteInput(OmniboxFocusType::ON_FOCUS), - &template_url_service, clipboard_age, image_bytes); - ASSERT_GE(provider_->matches().size(), 1U); - EXPECT_EQ(AutocompleteMatchType::CLIPBOARD_IMAGE, - provider_->matches().back().type); + base::BindOnce(&ClipboardProviderTest::MatchesImageCallback, + base::Unretained(this)), + image_bytes); + ASSERT_TRUE(matches_image_match_); + EXPECT_EQ(AutocompleteMatchType::CLIPBOARD_IMAGE, matches_image_match_->type); } TEST_F(ClipboardProviderTest, DeleteMatch) {
diff --git a/components/omnibox/browser/location_bar_model_impl.cc b/components/omnibox/browser/location_bar_model_impl.cc index 4fe8d91..5270e37 100644 --- a/components/omnibox/browser/location_bar_model_impl.cc +++ b/components/omnibox/browser/location_bar_model_impl.cc
@@ -15,7 +15,6 @@ #include "components/dom_distiller/core/url_utils.h" #include "components/omnibox/browser/buildflags.h" #include "components/omnibox/browser/location_bar_model_delegate.h" -#include "components/omnibox/browser/location_bar_model_util.h" #include "components/omnibox/common/omnibox_features.h" #include "components/search_engines/template_url_service.h" #include "components/security_state/core/security_state.h" @@ -30,6 +29,7 @@ #if (!defined(OS_ANDROID) || BUILDFLAG(ENABLE_VR)) && !defined(OS_IOS) #include "components/omnibox/browser/vector_icons.h" // nogncheck +#include "components/vector_icons/vector_icons.h" // nogncheck #endif using metrics::OmniboxEventProto; @@ -205,9 +205,35 @@ if (IsOfflinePage()) return omnibox::kOfflinePinIcon; -#endif - return location_bar_model::GetSecurityVectorIcon(GetSecurityLevel()); + security_state::SecurityLevel security_level = GetSecurityLevel(); + switch (security_level) { + case security_state::NONE: + return omnibox::kHttpIcon; + case security_state::WARNING: + // When kMarkHttpAsParameterDangerWarning is enabled, show a danger + // triangle icon. + if (security_state::ShouldShowDangerTriangleForWarningLevel()) { + return omnibox::kNotSecureWarningIcon; + } + return omnibox::kHttpIcon; + case security_state::SECURE: + return omnibox::kHttpsValidIcon; + case security_state::SECURE_WITH_POLICY_INSTALLED_CERT: + return vector_icons::kBusinessIcon; + case security_state::DANGEROUS: + return omnibox::kNotSecureWarningIcon; + case security_state::SECURITY_LEVEL_COUNT: + NOTREACHED(); + return omnibox::kHttpIcon; + } + NOTREACHED(); + return omnibox::kHttpIcon; +#else + NOTREACHED(); + static const gfx::VectorIcon dummy = {}; + return dummy; +#endif } base::string16 LocationBarModelImpl::GetSecureDisplayText() const {
diff --git a/components/omnibox/browser/location_bar_model_util.cc b/components/omnibox/browser/location_bar_model_util.cc deleted file mode 100644 index 27c4ec8..0000000 --- a/components/omnibox/browser/location_bar_model_util.cc +++ /dev/null
@@ -1,50 +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. - -#include "components/omnibox/browser/location_bar_model_util.h" - -#include "build/build_config.h" -#include "components/omnibox/browser/buildflags.h" -#include "ui/gfx/vector_icon_types.h" - -#if (!defined(OS_ANDROID) || BUILDFLAG(ENABLE_VR)) && !defined(OS_IOS) -#include "components/omnibox/browser/vector_icons.h" // nogncheck -#include "components/vector_icons/vector_icons.h" // nogncheck -#endif - -namespace location_bar_model { - -const gfx::VectorIcon& GetSecurityVectorIcon( - security_state::SecurityLevel security_level) { -#if (!defined(OS_ANDROID) || BUILDFLAG(ENABLE_VR)) && !defined(OS_IOS) - switch (security_level) { - case security_state::NONE: - return omnibox::kHttpIcon; - case security_state::WARNING: - // When kMarkHttpAsParameterDangerWarning is enabled, show a danger - // triangle icon. - if (security_state::ShouldShowDangerTriangleForWarningLevel()) { - return omnibox::kNotSecureWarningIcon; - } - return omnibox::kHttpIcon; - case security_state::SECURE: - return omnibox::kHttpsValidIcon; - case security_state::SECURE_WITH_POLICY_INSTALLED_CERT: - return vector_icons::kBusinessIcon; - case security_state::DANGEROUS: - return omnibox::kNotSecureWarningIcon; - case security_state::SECURITY_LEVEL_COUNT: - NOTREACHED(); - return omnibox::kHttpIcon; - } - NOTREACHED(); - return omnibox::kHttpIcon; -#else - NOTREACHED(); - static const gfx::VectorIcon dummy = {}; - return dummy; -#endif -} - -} // namespace location_bar_model
diff --git a/components/omnibox/browser/location_bar_model_util.h b/components/omnibox/browser/location_bar_model_util.h deleted file mode 100644 index 00803fc..0000000 --- a/components/omnibox/browser/location_bar_model_util.h +++ /dev/null
@@ -1,23 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_OMNIBOX_BROWSER_LOCATION_BAR_MODEL_UTIL_H_ -#define COMPONENTS_OMNIBOX_BROWSER_LOCATION_BAR_MODEL_UTIL_H_ - -#include "components/security_state/core/security_state.h" - -namespace gfx { -struct VectorIcon; -} // namespace gfx - -namespace location_bar_model { - -// Get the vector icon according to security level. -// It indicates security state of the page. -const gfx::VectorIcon& GetSecurityVectorIcon( - security_state::SecurityLevel security_level); - -} // namespace location_bar_model - -#endif // COMPONENTS_OMNIBOX_BROWSER_LOCATION_BAR_MODEL_UTIL_H_
diff --git a/components/open_from_clipboard/clipboard_recent_content.h b/components/open_from_clipboard/clipboard_recent_content.h index 6b383bda..075a8ec 100644 --- a/components/open_from_clipboard/clipboard_recent_content.h +++ b/components/open_from_clipboard/clipboard_recent_content.h
@@ -33,21 +33,17 @@ static void SetInstance(std::unique_ptr<ClipboardRecentContent> new_instance); // Returns clipboard content as URL, if it has a compatible type, - // is recent enough and has not been suppressed. + // is recent enough, has not been suppressed and will not trigger a system + // notification that the clipboard has been accessed. virtual base::Optional<GURL> GetRecentURLFromClipboard() = 0; // Returns clipboard content as text, if it has a compatible type, - // is recent enough and has not been suppressed. + // is recent enough, has not been suppressed and will not trigger a system + // notification that the clipboard has been accessed. virtual base::Optional<base::string16> GetRecentTextFromClipboard() = 0; - using GetRecentImageCallback = - base::OnceCallback<void(base::Optional<gfx::Image>)>; - - // Returns clipboard content as image to |GetRecentImageCallback|, if it has a - // compatible type, is recent enough and has not been suppressed. - virtual void GetRecentImageFromClipboard(GetRecentImageCallback callback) = 0; - - // Return if system's clipboard contains an image. + // Return if system's clipboard contains an image that will not trigger a + // system notification that the clipboard has been accessed. virtual bool HasRecentImageFromClipboard() = 0; /* @@ -59,19 +55,27 @@ using GetRecentURLCallback = base::OnceCallback<void(base::Optional<GURL>)>; using GetRecentTextCallback = base::OnceCallback<void(base::Optional<base::string16>)>; + using GetRecentImageCallback = + base::OnceCallback<void(base::Optional<gfx::Image>)>; // Returns whether the clipboard contains a URL to |HasDataCallback| if it // is recent enough and has not been suppressed. virtual void HasRecentContentFromClipboard( std::set<ClipboardContentType> types, HasDataCallback callback) = 0; + // Returns clipboard content as URL to |GetRecentURLCallback|, if it has a // compatible type, is recent enough and has not been suppressed. virtual void GetRecentURLFromClipboard(GetRecentURLCallback callback) = 0; + // Returns clipboard content as a string to |GetRecentTextCallback|, if it has // a compatible type, is recent enough and has not been suppressed. virtual void GetRecentTextFromClipboard(GetRecentTextCallback callback) = 0; + // Returns clipboard content as image to |GetRecentImageCallback|, if it has a + // compatible type, is recent enough and has not been suppressed. + virtual void GetRecentImageFromClipboard(GetRecentImageCallback callback) = 0; + // Returns how old the content of the clipboard is. virtual base::TimeDelta GetClipboardContentAge() const = 0;
diff --git a/components/open_from_clipboard/clipboard_recent_content_impl_ios.h b/components/open_from_clipboard/clipboard_recent_content_impl_ios.h index 38f708b..a865a8b 100644 --- a/components/open_from_clipboard/clipboard_recent_content_impl_ios.h +++ b/components/open_from_clipboard/clipboard_recent_content_impl_ios.h
@@ -39,15 +39,18 @@ - (instancetype)init NS_UNAVAILABLE; // Returns the copied URL if the clipboard contains a recent URL that has not -// been supressed. Otherwise, returns nil. +// been suppressed and will not trigger a pasteboard access notification. +// Otherwise, returns nil. - (NSURL*)recentURLFromClipboard; // Returns the copied string if the clipboard contains a recent string that has -// not been suppresed. Otherwise, returns nil. +// not been suppresed and will not trigger a pasteboard access notification. +// Otherwise, returns nil. - (NSString*)recentTextFromClipboard; // Returns the copied image if the clipboard contains a recent image that has -// not been suppressed. Otherwise, returns nil. +// not been suppressed and will not trigger a pasteboard access notification. +// Otherwise, returns nil. - (UIImage*)recentImageFromClipboard; // Uses the new iOS 14 pasteboard detection pattern API to asynchronously detect
diff --git a/components/open_from_clipboard/clipboard_recent_content_impl_ios.mm b/components/open_from_clipboard/clipboard_recent_content_impl_ios.mm index 20b1ce34..1ff61e1b 100644 --- a/components/open_from_clipboard/clipboard_recent_content_impl_ios.mm +++ b/components/open_from_clipboard/clipboard_recent_content_impl_ios.mm
@@ -131,8 +131,13 @@ if (![self shouldReturnValueOfClipboard]) return nil; - if (!self.cachedURL) { - self.cachedURL = [self URLFromPasteboard]; + if (@available(iOS 14, *)) { + // On iOS 14, don't actually access the pasteboard in this method. This + // prevents the pasteboard access notification from appearing. + } else { + if (!self.cachedURL) { + self.cachedURL = [self URLFromPasteboard]; + } } return self.cachedURL; } @@ -143,8 +148,13 @@ if (![self shouldReturnValueOfClipboard]) return nil; - if (!self.cachedText) { - self.cachedText = UIPasteboard.generalPasteboard.string; + if (@available(iOS 14, *)) { + // On iOS 14, don't actually access the pasteboard in this method. This + // prevents the pasteboard access notification from appearing. + } else { + if (!self.cachedText) { + self.cachedText = UIPasteboard.generalPasteboard.string; + } } return self.cachedText; } @@ -155,8 +165,13 @@ if (![self shouldReturnValueOfClipboard]) return nil; - if (!self.cachedImage) { - self.cachedImage = UIPasteboard.generalPasteboard.image; + if (@available(iOS 14, *)) { + // On iOS 14, don't actually access the pasteboard in this method. This + // prevents the pasteboard access notification from appearing. + } else { + if (!self.cachedImage) { + self.cachedImage = UIPasteboard.generalPasteboard.image; + } } return self.cachedImage;
diff --git a/components/open_from_clipboard/clipboard_recent_content_ios.mm b/components/open_from_clipboard/clipboard_recent_content_ios.mm index 3bec1c0..5bba010 100644 --- a/components/open_from_clipboard/clipboard_recent_content_ios.mm +++ b/components/open_from_clipboard/clipboard_recent_content_ios.mm
@@ -14,6 +14,7 @@ #include "base/stl_util.h" #include "base/strings/sys_string_conversions.h" #include "base/system/sys_info.h" +#include "base/threading/sequenced_task_runner_handle.h" #import "components/open_from_clipboard/clipboard_recent_content_impl_ios.h" #import "net/base/mac/url_conversions.h" #include "url/gurl.h" @@ -116,19 +117,6 @@ return base::SysNSStringToUTF16(text_from_pasteboard); } -void ClipboardRecentContentIOS::GetRecentImageFromClipboard( - GetRecentImageCallback callback) { - __block GetRecentImageCallback callback_for_block = std::move(callback); - [implementation_ recentImageFromClipboardAsync:^(UIImage* image) { - if (!image) { - std::move(callback_for_block).Run(base::nullopt); - return; - } - - std::move(callback_for_block).Run(gfx::Image(image)); - }]; -} - bool ClipboardRecentContentIOS::HasRecentImageFromClipboard() { return GetRecentImageFromClipboardInternal().has_value(); } @@ -141,39 +129,93 @@ for (ClipboardContentType type : types) { [ios_types addObject:ContentTypeFromClipboardContentType(type)]; } - [implementation_ hasContentMatchingTypes:ios_types - completionHandler:^(NSSet<ContentType>* results) { - std::set<ClipboardContentType> matching_types; - for (ContentType type in results) { - matching_types.insert( - ClipboardContentTypeFromContentType(type)); - } - std::move(callback_for_block).Run(matching_types); - }]; + // The iOS methods for checking clipboard content call their callbacks on an + // arbitrary thread. As Objective-C doesn't have very good thread-management + // techniques, make sure this method calls its callback on the same thread + // that it was called on. + scoped_refptr<base::SequencedTaskRunner> task_runner = + base::SequencedTaskRunnerHandle::Get(); + [implementation_ + hasContentMatchingTypes:ios_types + completionHandler:^(NSSet<ContentType>* results) { + std::set<ClipboardContentType> matching_types; + for (ContentType type in results) { + matching_types.insert( + ClipboardContentTypeFromContentType(type)); + } + task_runner->PostTask( + FROM_HERE, base::BindOnce(^{ + std::move(callback_for_block).Run(matching_types); + })); + }]; } void ClipboardRecentContentIOS::GetRecentURLFromClipboard( GetRecentURLCallback callback) { __block GetRecentURLCallback callback_for_block = std::move(callback); + // The iOS methods for checking clipboard content call their callbacks on an + // arbitrary thread. As Objective-C doesn't have very good thread-management + // techniques, make sure this method calls its callback on the same thread + // that it was called on. + scoped_refptr<base::SequencedTaskRunner> task_runner = + base::SequencedTaskRunnerHandle::Get(); [implementation_ recentURLFromClipboardAsync:^(NSURL* url) { GURL converted_url = net::GURLWithNSURL(url); if (!converted_url.is_valid()) { - std::move(callback_for_block).Run(base::nullopt); + task_runner->PostTask(FROM_HERE, base::BindOnce(^{ + std::move(callback_for_block).Run(base::nullopt); + })); return; } - std::move(callback_for_block).Run(converted_url); + task_runner->PostTask(FROM_HERE, base::BindOnce(^{ + std::move(callback_for_block).Run(converted_url); + })); }]; } void ClipboardRecentContentIOS::GetRecentTextFromClipboard( GetRecentTextCallback callback) { __block GetRecentTextCallback callback_for_block = std::move(callback); + // The iOS methods for checking clipboard content call their callbacks on an + // arbitrary thread. As Objective-C doesn't have very good thread-management + // techniques, make sure this method calls its callback on the same thread + // that it was called on. + scoped_refptr<base::SequencedTaskRunner> task_runner = + base::SequencedTaskRunnerHandle::Get(); [implementation_ recentTextFromClipboardAsync:^(NSString* text) { if (!text) { - std::move(callback_for_block).Run(base::nullopt); + task_runner->PostTask(FROM_HERE, base::BindOnce(^{ + std::move(callback_for_block).Run(base::nullopt); + })); return; } - std::move(callback_for_block).Run(base::SysNSStringToUTF16(text)); + task_runner->PostTask( + FROM_HERE, base::BindOnce(^{ + std::move(callback_for_block).Run(base::SysNSStringToUTF16(text)); + })); + }]; +} + +void ClipboardRecentContentIOS::GetRecentImageFromClipboard( + GetRecentImageCallback callback) { + __block GetRecentImageCallback callback_for_block = std::move(callback); + // The iOS methods for checking clipboard content call their callbacks on an + // arbitrary thread. As Objective-C doesn't have very good thread-management + // techniques, make sure this method calls its callback on the same thread + // that it was called on. + scoped_refptr<base::SequencedTaskRunner> task_runner = + base::SequencedTaskRunnerHandle::Get(); + [implementation_ recentImageFromClipboardAsync:^(UIImage* image) { + if (!image) { + task_runner->PostTask(FROM_HERE, base::BindOnce(^{ + std::move(callback_for_block).Run(base::nullopt); + })); + return; + } + task_runner->PostTask( + FROM_HERE, base::BindOnce(^{ + std::move(callback_for_block).Run(gfx::Image(image)); + })); }]; }
diff --git a/components/password_manager/core/browser/form_parsing/form_parser.cc b/components/password_manager/core/browser/form_parsing/form_parser.cc index 0acfce13..2aeadaf 100644 --- a/components/password_manager/core/browser/form_parsing/form_parser.cc +++ b/components/password_manager/core/browser/form_parsing/form_parser.cc
@@ -915,6 +915,7 @@ result->scheme = PasswordForm::Scheme::kHtml; result->blocked_by_user = false; result->type = PasswordForm::Type::kManual; + result->server_side_classification_successful = form_predictions.has_value(); result->username_may_use_prefilled_placeholder = GetMayUsePrefilledPlaceholder(form_predictions, significant_fields); result->is_new_password_reliable =
diff --git a/components/password_manager/core/browser/form_parsing/form_parser_unittest.cc b/components/password_manager/core/browser/form_parsing/form_parser_unittest.cc index 65dca71..76c7d7e 100644 --- a/components/password_manager/core/browser/form_parsing/form_parser_unittest.cc +++ b/components/password_manager/core/browser/form_parsing/form_parser_unittest.cc
@@ -90,6 +90,7 @@ // null means no checking const autofill::ValueElementVector* all_possible_passwords = nullptr; const autofill::ValueElementVector* all_possible_usernames = nullptr; + bool server_side_classification_successful = true; bool username_may_use_prefilled_placeholder = false; base::Optional<FormDataParser::ReadonlyPasswordFields> readonly_status; base::Optional<FormDataParser::ReadonlyPasswordFields> @@ -358,6 +359,8 @@ EXPECT_EQ(PasswordForm::Scheme::kHtml, parsed_form->scheme); EXPECT_FALSE(parsed_form->blocked_by_user); EXPECT_EQ(PasswordForm::Type::kManual, parsed_form->type); + EXPECT_EQ(test_case.server_side_classification_successful, + parsed_form->server_side_classification_successful); EXPECT_EQ(test_case.username_may_use_prefilled_placeholder, parsed_form->username_may_use_prefilled_placeholder); EXPECT_EQ(test_case.submission_event, parsed_form->submission_event); @@ -1243,6 +1246,7 @@ .prediction = {.type = autofill::PASSWORD, .may_use_prefilled_placeholder = true}}, }, + .server_side_classification_successful = true, .username_may_use_prefilled_placeholder = false, }, }); @@ -1290,6 +1294,7 @@ .prediction = {.type = autofill::PASSWORD, .may_use_prefilled_placeholder = true}}, }, + .server_side_classification_successful = true, .username_may_use_prefilled_placeholder = true, }, { @@ -1327,6 +1332,22 @@ .form_control_type = "password"}, }, }, + { + .description_for_logging = "Username not a placeholder", + .fields = + { + {.role = ElementRole::USERNAME, + .form_control_type = "text", + .prediction = {.type = autofill::USERNAME_AND_EMAIL_ADDRESS, + .may_use_prefilled_placeholder = false}}, + {.role = ElementRole::CURRENT_PASSWORD, + .form_control_type = "password", + .prediction = {.type = autofill::PASSWORD, + .may_use_prefilled_placeholder = false}}, + }, + .server_side_classification_successful = true, + .username_may_use_prefilled_placeholder = false, + }, }); }
diff --git a/components/password_manager/core/browser/password_form_filling.cc b/components/password_manager/core/browser/password_form_filling.cc index 5910626f..bcc720dc 100644 --- a/components/password_manager/core/browser/password_form_filling.cc +++ b/components/password_manager/core/browser/password_form_filling.cc
@@ -179,6 +179,13 @@ } else if (no_sign_in_form) { // If the parser did not find a current password element, don't fill. wait_for_username_reason = WaitForUsernameReason::kFormNotGoodForFilling; + } else if (observed_form.HasUsernameElement() && + observed_form.HasNonEmptyPasswordValue() && + observed_form.server_side_classification_successful && + !observed_form.username_may_use_prefilled_placeholder) { + // Password is already filled in and we don't think the username is a + // placeholder, so don't overwrite. + wait_for_username_reason = WaitForUsernameReason::kPasswordPrefilled; } else if (!client->IsCommittedMainFrameSecure()) { wait_for_username_reason = WaitForUsernameReason::kInsecureOrigin; } else if (autofill::IsTouchToFillEnabled()) {
diff --git a/components/password_manager/core/browser/password_form_filling_unittest.cc b/components/password_manager/core/browser/password_form_filling_unittest.cc index e7edb59..486384d 100644 --- a/components/password_manager/core/browser/password_form_filling_unittest.cc +++ b/components/password_manager/core/browser/password_form_filling_unittest.cc
@@ -261,6 +261,67 @@ } } +// Test autofill when username and password are prefilled. Overwrite password +// if server side classification thought the username was a placeholder or the +// classification failed. Do not overwrite if username doesn't look like a +// placeholder. +// Skip for Android since it uses touch to fill (kAutofillTouchToFill), meaning +// placeholders will never be overwritten. +#if !defined(OS_ANDROID) +TEST_F(PasswordFormFillingTest, TestFillOnLoadSuggestionWithPrefill) { + const struct { + const char* description; + bool username_may_use_prefilled_placeholder; + bool server_side_classification_successful; + LikelyFormFilling likely_form_filling; + } kTestCases[] = { + { + .description = "Username not placeholder", + .username_may_use_prefilled_placeholder = false, + .server_side_classification_successful = true, + .likely_form_filling = LikelyFormFilling::kFillOnAccountSelect, + }, + { + .description = "Username is placeholder", + .username_may_use_prefilled_placeholder = true, + .server_side_classification_successful = true, + .likely_form_filling = LikelyFormFilling::kFillOnPageLoad, + }, + { + .description = "No server classification", + .username_may_use_prefilled_placeholder = false, + .server_side_classification_successful = false, + .likely_form_filling = LikelyFormFilling::kFillOnPageLoad, + }, + }; + for (const auto& test_case : kTestCases) { + SCOPED_TRACE(test_case.description); + PasswordForm preferred_match = saved_match_; + std::vector<const PasswordForm*> best_matches = {&preferred_match}; + + PasswordForm observed_form = observed_form_; + // Set username to match preferred match + observed_form.username_value = preferred_match.username_value; + // Set a different password than saved + observed_form.password_value = ASCIIToUTF16("New Passwd"); + // Set classification results + observed_form.server_side_classification_successful = + test_case.server_side_classification_successful; + observed_form.username_may_use_prefilled_placeholder = + test_case.username_may_use_prefilled_placeholder; + + EXPECT_CALL(driver_, FillPasswordForm); + EXPECT_CALL(client_, PasswordWasAutofilled); + + LikelyFormFilling likely_form_filling = SendFillInformationToRenderer( + &client_, &driver_, observed_form, best_matches, federated_matches_, + &preferred_match, metrics_recorder_.get()); + + EXPECT_EQ(test_case.likely_form_filling, likely_form_filling); + } +} +#endif + TEST_F(PasswordFormFillingTest, AutofillPSLMatch) { std::vector<const PasswordForm*> best_matches = {&psl_saved_match_}; @@ -535,6 +596,7 @@ form_on_page.username_element = ASCIIToUTF16("username"); form_on_page.password_element = ASCIIToUTF16("password"); form_on_page.username_may_use_prefilled_placeholder = true; + form_on_page.server_side_classification_successful = true; // Create an exact match in the database. PasswordForm preferred_match = form_on_page; @@ -638,4 +700,5 @@ IsLogin(kDuplicateLocalUsername, kDuplicateLocalPassword, false), IsLogin(kSyncedUsername, kSyncedPassword, true))); } + } // namespace password_manager
diff --git a/components/password_manager/core/browser/password_form_metrics_recorder.h b/components/password_manager/core/browser/password_form_metrics_recorder.h index 341e540..f51f5b1 100644 --- a/components/password_manager/core/browser/password_form_metrics_recorder.h +++ b/components/password_manager/core/browser/password_form_metrics_recorder.h
@@ -226,7 +226,9 @@ kFoasFeature = 6, // Re-authenticaion for filling passwords is required. kReauthRequired = 7, - kMaxValue = kReauthRequired, + // Password is already filled + kPasswordPrefilled = 8, + kMaxValue = kPasswordPrefilled, }; // This metric records the user experience with the passwords filling. The
diff --git a/components/password_manager/core/browser/password_scripts_fetcher_impl.cc b/components/password_manager/core/browser/password_scripts_fetcher_impl.cc index fac8f5f8..89c8357 100644 --- a/components/password_manager/core/browser/password_scripts_fetcher_impl.cc +++ b/components/password_manager/core/browser/password_scripts_fetcher_impl.cc
@@ -14,10 +14,60 @@ #include "url/origin.h" namespace { + constexpr int kCacheTimeoutInMinutes = 5; constexpr int kFetchTimeoutInSeconds = 3; constexpr int kMaxDownloadSizeInBytes = 10 * 1024; + +using ParsingResult = + password_manager::PasswordScriptsFetcherImpl::ParsingResult; + +// Extracts the domains for which password changes are supported and adds them +// to |supported_domains|. +// |script_config| is the dictionary passed for a domain, representig the +// configuration data of one password change script. +// For example, the fetched JSON might look like this: +// { +// 'example.com': { +// 'domains': [ 'https://www.example.com', 'https://m.example.com' ] +// } +// } +// In this case |script_config| would represent the dictionary value +// of 'example.com'. +// Returns a set of warnings. +// The function tries to be lax about errors and prefers to skip them +// with warnings rather than bail the parsing. This is for forward +// compatibility. +base::flat_set<ParsingResult> ExtractPasswordDomains( + const base::Value& script_config, + base::flat_set<url::Origin>& supported_domains) { + if (!script_config.is_dict()) + return {ParsingResult::kInvalidJson}; + + const base::Value* supported_domains_list = + script_config.FindListKey("domains"); + if (!supported_domains_list || !supported_domains_list->is_list()) + return {ParsingResult::kInvalidJson}; + + base::flat_set<ParsingResult> warnings; + for (const base::Value& domain : supported_domains_list->GetList()) { + if (!domain.is_string()) { + warnings.insert(ParsingResult::kInvalidJson); + continue; + } + + GURL url(domain.GetString()); + if (!url.is_valid()) { + warnings.insert(ParsingResult::kInvalidUrl); + continue; + } + supported_domains.insert(url::Origin::Create(url)); + } + + return warnings; +} + } // namespace namespace password_manager { @@ -139,9 +189,14 @@ url_loader_.reset(); last_fetch_timestamp_ = base::TimeTicks::Now(); - ParsingResult parsing_result = ParseResponse(std::move(response_body)); - base::UmaHistogramEnumeration( - "PasswordManager.PasswordScriptsFetcher.ParsingResult", parsing_result); + base::flat_set<ParsingResult> parsing_warnings = + ParseResponse(std::move(response_body)); + if (parsing_warnings.empty()) + parsing_warnings.insert(ParsingResult::kOk); + for (ParsingResult warning : parsing_warnings) { + base::UmaHistogramEnumeration( + "PasswordManager.PasswordScriptsFetcher.ParsingResult", warning); + } for (auto& callback : std::exchange(fetch_finished_callbacks_, {})) std::move(callback).Run(); @@ -149,33 +204,32 @@ RunResponseCallback(std::move(callback.first), std::move(callback.second)); } -PasswordScriptsFetcherImpl::ParsingResult -PasswordScriptsFetcherImpl::ParseResponse( +base::flat_set<ParsingResult> PasswordScriptsFetcherImpl::ParseResponse( std::unique_ptr<std::string> response_body) { password_change_domains_.clear(); if (!response_body) - return ParsingResult::kNoResponse; + return {ParsingResult::kNoResponse}; - base::Optional<base::Value> data = base::JSONReader::Read(*response_body); - if (data == base::nullopt) - return ParsingResult::kNotJsonString; - if (!data->is_dict()) - return ParsingResult::kNotDictionary; + base::JSONReader::ValueWithError data = + base::JSONReader::ReadAndReturnValueWithError(*response_body); - bool invalid_urls_found = false; - for (const auto& it : data->DictItems()) { - // |it.second| is not used at the moment and reserved for - // domain-specific parameters. - GURL url(it.first); - if (url.is_valid()) { - url::Origin origin = url::Origin::Create(url); - password_change_domains_.insert(origin); - } else { - invalid_urls_found = true; - } + if (data.value == base::nullopt) { + DVLOG(1) << "Parse error: " << data.error_message; + return {ParsingResult::kInvalidJson}; } - return invalid_urls_found ? ParsingResult::kInvalidUrl : ParsingResult::kOk; + if (!data.value->is_dict()) + return {ParsingResult::kInvalidJson}; + + base::flat_set<ParsingResult> warnings; + for (const auto& script_it : data.value->DictItems()) { + // |script_it.first| is an identifier that we don't care about. + // |script_it.second| provides domain-sepcific parameters. + base::flat_set<ParsingResult> warnings_for_script = + ExtractPasswordDomains(script_it.second, password_change_domains_); + warnings.insert(warnings_for_script.begin(), warnings_for_script.end()); + } + return warnings; } bool PasswordScriptsFetcherImpl::IsCacheStale() const {
diff --git a/components/password_manager/core/browser/password_scripts_fetcher_impl.h b/components/password_manager/core/browser/password_scripts_fetcher_impl.h index 159846f..1a97f66 100644 --- a/components/password_manager/core/browser/password_scripts_fetcher_impl.h +++ b/components/password_manager/core/browser/password_scripts_fetcher_impl.h
@@ -47,15 +47,15 @@ enum class ParsingResult { // No response from the server. kNoResponse = 0, - // Response is not a properly formed JSON string. - kNotJsonString = 1, - // Parsing result is not a dictionary. - kNotDictionary = 2, // There was at least one invalid URL. kInvalidUrl = 3, // No errors occurred. kOk = 4, - kMaxValue = kOk, + // Invalid JSON (either syntactically, e.g. ill-formed lists, dictionaries, + // strings, etc., or structurally, e.g. a dictionary that does not contain + // the expected keys). + kInvalidJson = 5, + kMaxValue = kInvalidJson, }; explicit PasswordScriptsFetcherImpl( @@ -84,8 +84,11 @@ std::unique_ptr<std::string> response_body); // Parses |response_body| and stores the result in |password_change_domains_| // (always overwrites the old list). Sets an empty list if |response_body| is - // invalid. Returns a parsing result for a histogram. - ParsingResult ParseResponse(std::unique_ptr<std::string> response_body); + // invalid. Returns a parsing result for a histogram. The function tries to be + // forgiving and rather return warnings and skip an entry than cancel the + // parsing. + base::flat_set<ParsingResult> ParseResponse( + std::unique_ptr<std::string> response_body); // Returns whether a re-fetch is needed. bool IsCacheStale() const; // Runs |callback| immediately with the script availability for |origin|.
diff --git a/components/password_manager/core/browser/password_scripts_fetcher_impl_unittests.cc b/components/password_manager/core/browser/password_scripts_fetcher_impl_unittests.cc index 9530c96..9341c93 100644 --- a/components/password_manager/core/browser/password_scripts_fetcher_impl_unittests.cc +++ b/components/password_manager/core/browser/password_scripts_fetcher_impl_unittests.cc
@@ -18,11 +18,24 @@ namespace { constexpr char kOriginWithScript1[] = "https://example.com"; -constexpr char kOriginWithScript2[] = "https://test.com"; +constexpr char kOriginWithScript2[] = "https://mobile.example.com"; +constexpr char kOriginWithScript3[] = "https://test.com"; constexpr char kOriginWithoutScript[] = "https://no-script.com"; constexpr char kTestResponseContent[] = - "{\"https://example.com\" : {}, \"https://test.com\" : {}}"; + R"json( + { + "example.com": { + "domains": [ + "https://example.com", + "https://mobile.example.com" + ] + }, + "test.com": { + "domains": ["https://test.com"] + } + } + )json"; url::Origin GetOriginWithScript1() { return url::Origin::Create(GURL(kOriginWithScript1)); @@ -32,6 +45,10 @@ return url::Origin::Create(GURL(kOriginWithScript2)); } +url::Origin GetOriginWithScript3() { + return url::Origin::Create(GURL(kOriginWithScript3)); +} + url::Origin GetOriginWithoutScript() { return url::Origin::Create(GURL(kOriginWithoutScript)); } @@ -76,6 +93,7 @@ base::Unretained(this))); RequestSingleScriptAvailability(GetOriginWithScript1()); RequestSingleScriptAvailability(GetOriginWithScript2()); + RequestSingleScriptAvailability(GetOriginWithScript3()); RequestSingleScriptAvailability(GetOriginWithoutScript()); } @@ -136,6 +154,7 @@ EXPECT_THAT(recorded_responses(), UnorderedElementsAre(Pair(GetOriginWithScript1(), true), Pair(GetOriginWithScript2(), true), + Pair(GetOriginWithScript3(), true), Pair(GetOriginWithoutScript(), false))); EXPECT_EQ(0, GetNumberOfPendingRequests()); histogram_tester->ExpectUniqueSample( @@ -150,12 +169,14 @@ StartBulkCheck(); EXPECT_EQ(1, GetNumberOfPendingRequests()); // OriginWithScript2 (test.com) is not available anymore. - SimulateResponseWithContent("{\"https://example.com\" : {}}"); + SimulateResponseWithContent( + R"({"example.com": {"domains": ["https://example.com"]}})"); base::RunLoop().RunUntilIdle(); EXPECT_THAT(recorded_responses(), UnorderedElementsAre(Pair(GetOriginWithScript1(), true), Pair(GetOriginWithScript2(), false), + Pair(GetOriginWithScript3(), false), Pair(GetOriginWithoutScript(), false))); EXPECT_EQ(0, GetNumberOfPendingRequests()); histogram_tester->ExpectUniqueSample( @@ -186,6 +207,7 @@ EXPECT_THAT(recorded_responses(), UnorderedElementsAre(Pair(GetOriginWithScript1(), true), Pair(GetOriginWithScript2(), true), + Pair(GetOriginWithScript3(), true), Pair(GetOriginWithoutScript(), false))); EXPECT_EQ(0, GetNumberOfPendingRequests()); @@ -202,16 +224,18 @@ net::HttpStatusCode::HTTP_OK, 1u); } -TEST_F(PasswordScriptsFetcherImplTest, InvalidJson) { +TEST_F(PasswordScriptsFetcherImplTest, InvalidResponseBody) { const struct TestCase { const char* const response; PasswordScriptsFetcherImpl::ParsingResult histogram_value; } kTestCases[]{ - {"", PasswordScriptsFetcherImpl::ParsingResult::kNotJsonString}, - {"{{{", PasswordScriptsFetcherImpl::ParsingResult::kNotJsonString}, - {"[\"1\", \"2\"]", - PasswordScriptsFetcherImpl::ParsingResult::kNotDictionary}, - {"{ \"not-url.com\" : {}}", + {"", PasswordScriptsFetcherImpl::ParsingResult::kInvalidJson}, + {"{{{", PasswordScriptsFetcherImpl::ParsingResult::kInvalidJson}, + {R"(["1", "2"])", + PasswordScriptsFetcherImpl::ParsingResult::kInvalidJson}, + {R"({"no-domains-attribute.com" : {}})", + PasswordScriptsFetcherImpl::ParsingResult::kInvalidJson}, + {R"({"not-url.com" : {"domains": ["scheme-forgotten.com"]}})", PasswordScriptsFetcherImpl::ParsingResult::kInvalidUrl}}; for (const auto& test_case : kTestCases) { SCOPED_TRACE(testing::Message() << "test_case=" << test_case.response); @@ -227,6 +251,7 @@ EXPECT_THAT(recorded_responses(), UnorderedElementsAre(Pair(GetOriginWithScript1(), false), Pair(GetOriginWithScript2(), false), + Pair(GetOriginWithScript3(), false), Pair(GetOriginWithoutScript(), false))); histogram_tester.ExpectUniqueSample( "PasswordManager.PasswordScriptsFetcher.ParsingResult", @@ -243,6 +268,7 @@ EXPECT_THAT(recorded_responses(), UnorderedElementsAre(Pair(GetOriginWithScript1(), false), Pair(GetOriginWithScript2(), false), + Pair(GetOriginWithScript3(), false), Pair(GetOriginWithoutScript(), false))); histogram_tester.ExpectUniqueSample( "PasswordManager.PasswordScriptsFetcher.ParsingResult", @@ -259,6 +285,7 @@ // default value (false). EXPECT_FALSE(fetcher()->IsScriptAvailable(GetOriginWithScript1())); EXPECT_FALSE(fetcher()->IsScriptAvailable(GetOriginWithScript2())); + EXPECT_FALSE(fetcher()->IsScriptAvailable(GetOriginWithScript3())); EXPECT_FALSE(fetcher()->IsScriptAvailable(GetOriginWithoutScript())); EXPECT_EQ(0, GetNumberOfPendingRequests()); @@ -273,12 +300,14 @@ // Cache is ready. EXPECT_TRUE(fetcher()->IsScriptAvailable(GetOriginWithScript1())); EXPECT_TRUE(fetcher()->IsScriptAvailable(GetOriginWithScript2())); + EXPECT_TRUE(fetcher()->IsScriptAvailable(GetOriginWithScript3())); EXPECT_FALSE(fetcher()->IsScriptAvailable(GetOriginWithoutScript())); // |IsScriptAvailable| does not trigger refetching and returns stale values. fetcher()->make_cache_stale_for_testing(); EXPECT_TRUE(fetcher()->IsScriptAvailable(GetOriginWithScript1())); EXPECT_TRUE(fetcher()->IsScriptAvailable(GetOriginWithScript2())); + EXPECT_TRUE(fetcher()->IsScriptAvailable(GetOriginWithScript3())); EXPECT_FALSE(fetcher()->IsScriptAvailable(GetOriginWithoutScript())); EXPECT_EQ(0, GetNumberOfPendingRequests()); }
diff --git a/components/payments/core/features.cc b/components/payments/core/features.cc index c4c9717..bda13aa 100644 --- a/components/payments/core/features.cc +++ b/components/payments/core/features.cc
@@ -77,9 +77,6 @@ "AllowJITInstallationWhenAppIconIsMissing", base::FEATURE_DISABLED_BY_DEFAULT}; -const base::Feature kPaymentHandlerSecurityIcon{ - "PaymentHandlerSecurityIcon", base::FEATURE_DISABLED_BY_DEFAULT}; - const base::Feature kEnforceFullDelegation{"EnforceFullDelegation", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/components/payments/core/features.h b/components/payments/core/features.h index b7716bff..b92ea8e 100644 --- a/components/payments/core/features.h +++ b/components/payments/core/features.h
@@ -79,11 +79,6 @@ // Used to test icon refetch for JIT installed apps with missing icons. extern const base::Feature kAllowJITInstallationWhenAppIconIsMissing; -// Desktop only, if enabled the security icon would be showed next to the -// payment handler's URL bar. It indicate that only secure content is -// allowed inside the payment handler. -extern const base::Feature kPaymentHandlerSecurityIcon; - // Used to reject the apps with partial delegation. extern const base::Feature kEnforceFullDelegation;
diff --git a/components/performance_manager/OWNERS b/components/performance_manager/OWNERS index 6726b9e..085920a 100644 --- a/components/performance_manager/OWNERS +++ b/components/performance_manager/OWNERS
@@ -1,7 +1,7 @@ chrisha@chromium.org fdoray@chromium.org siggi@chromium.org -joenotcharles@google.com +joenotcharles@chromium.org # For IPC security review per-file *.mojom=set noparent
diff --git a/components/policy/core/common/features.cc b/components/policy/core/common/features.cc index 2890847c..c38e3d2c 100644 --- a/components/policy/core/common/features.cc +++ b/components/policy/core/common/features.cc
@@ -8,9 +8,6 @@ namespace features { -const base::Feature kPolicyAtomicGroup{"PolicyAtomicGroup", - base::FEATURE_DISABLED_BY_DEFAULT}; - const base::Feature kCBCMPolicyInvalidations{"CBCMPolicyInvalidations", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/components/policy/core/common/features.h b/components/policy/core/common/features.h index 65c42f0c..f098584 100644 --- a/components/policy/core/common/features.h +++ b/components/policy/core/common/features.h
@@ -12,9 +12,6 @@ namespace policy { namespace features { -// TODO(994227) Remove references to this now unused feature. -POLICY_EXPORT extern const base::Feature kPolicyAtomicGroup; - #if defined(OS_APPLE) // Feature that controls whether the browser ignores sensitive policies on an // unmanaged Mac.
diff --git a/components/policy/tools/template_writers/writers/adm_writer.py b/components/policy/tools/template_writers/writers/adm_writer.py index 3e38528..4b480c4 100755 --- a/components/policy/tools/template_writers/writers/adm_writer.py +++ b/components/policy/tools/template_writers/writers/adm_writer.py
@@ -124,15 +124,15 @@ builder.AddLine('VALUENAME "%s"' % policy['name']) if policy['type'] == 'int': # The default max for NUMERIC values is 9999 which is too small for us. - max = '2000000000' - min = '0' + max = 2000000000 + min = 0 if self.PolicyHasRestrictions(policy): schema = policy['schema'] if 'minimum' in schema: min = schema['minimum'] if 'maximum' in schema: max = schema['maximum'] - builder.AddLine('MIN ' + str(min) + ' MAX ' + max) + builder.AddLine('MIN %d MAX %d' % (min, max)) if policy['type'] in ('string', 'dict', 'external'): # The default max for EDITTEXT values is 1023, which is too small for # big JSON blobs and other string policies.
diff --git a/components/policy/tools/template_writers/writers/adm_writer_unittest.py b/components/policy/tools/template_writers/writers/adm_writer_unittest.py index 92bbfbd..38389e0d 100755 --- a/components/policy/tools/template_writers/writers/adm_writer_unittest.py +++ b/components/policy/tools/template_writers/writers/adm_writer_unittest.py
@@ -474,6 +474,76 @@ ''') self.CompareOutputs(output, expected_output) + def testIntPolicyWithRange(self): + # Tests a policy group with a single policy of type 'int' with a min and + # max value. + policy_json = ''' + { + 'policy_definitions': [ + { + 'name': 'IntPolicy', + 'type': 'int', + 'schema': { 'type': 'integer', 'minimum': 5, 'maximum': 10 }, + 'caption': 'Caption of policy.', + 'features': { 'can_be_recommended': True }, + 'desc': 'Description of policy.', + 'supported_on': ['chrome.win:8-'] + }, + ], + 'policy_atomic_group_definitions': [], + 'placeholders': [], + 'messages': %s + }''' % MESSAGES + output = self.GetOutput(policy_json, {'_chromium': '1'}, 'adm') + expected_output = self.ConstructOutput(['MACHINE', 'USER'], ''' + CATEGORY !!chromium + KEYNAME "Software\\Policies\\Chromium" + + POLICY !!IntPolicy_Policy + #if version >= 4 + SUPPORTED !!SUPPORTED_WIN7 + #endif + EXPLAIN !!IntPolicy_Explain + + PART !!IntPolicy_Part NUMERIC + VALUENAME "IntPolicy" + MIN 5 MAX 10 + END PART + END POLICY + + END CATEGORY + + CATEGORY !!chromium_recommended + KEYNAME "Software\\Policies\\Chromium\\Recommended" + + POLICY !!IntPolicy_Policy + #if version >= 4 + SUPPORTED !!SUPPORTED_WIN7 + #endif + EXPLAIN !!IntPolicy_Explain + + PART !!IntPolicy_Part NUMERIC + VALUENAME "IntPolicy" + MIN 5 MAX 10 + END PART + END POLICY + + END CATEGORY + + +''', '''[Strings] +SUPPORTED_WIN7="Microsoft Windows 7 or later" +SUPPORTED_WIN7_ONLY="Microsoft Windows 7" +chromium="Chromium" +chromium_recommended="Chromium - Recommended" +IntPolicy_Policy="Caption of policy." +IntPolicy_Explain="Description of policy.\\n\\n\ +Reference: \ +https://cloud.google.com/docs/chrome-enterprise/policies/?policy=IntPolicy" +IntPolicy_Part="Caption of policy." +''') + self.CompareOutputs(output, expected_output) + def testIntEnumPolicy(self): # Tests a policy group with a single policy of type 'int-enum'. policy_json = '''
diff --git a/components/safety_check/safety_check.cc b/components/safety_check/safety_check.cc index e9539b25..e09f9d7 100644 --- a/components/safety_check/safety_check.cc +++ b/components/safety_check/safety_check.cc
@@ -18,13 +18,17 @@ void SafetyCheck::CheckSafeBrowsing(PrefService* pref_service) { const PrefService::Preference* enabled_pref = pref_service->FindPreference(prefs::kSafeBrowsingEnabled); - bool enabled = pref_service->GetBoolean(prefs::kSafeBrowsingEnabled); + bool is_sb_enabled = pref_service->GetBoolean(prefs::kSafeBrowsingEnabled); + bool is_sb_managed = enabled_pref->IsManaged(); + SafeBrowsingStatus status; - if (enabled && pref_service->GetBoolean(prefs::kSafeBrowsingEnhanced)) { + if (is_sb_enabled && pref_service->GetBoolean(prefs::kSafeBrowsingEnhanced)) { status = SafeBrowsingStatus::kEnabledEnhanced; - } else if (enabled) { + } else if (is_sb_enabled && is_sb_managed) { status = SafeBrowsingStatus::kEnabledStandard; - } else if (enabled_pref->IsManaged()) { + } else if (is_sb_enabled && !is_sb_managed) { + status = SafeBrowsingStatus::kEnabledStandardAvailableEnhanced; + } else if (is_sb_managed) { status = SafeBrowsingStatus::kDisabledByAdmin; } else if (enabled_pref->IsExtensionControlled()) { status = SafeBrowsingStatus::kDisabledByExtension;
diff --git a/components/safety_check/safety_check.h b/components/safety_check/safety_check.h index 2bd457a..37663d5 100644 --- a/components/safety_check/safety_check.h +++ b/components/safety_check/safety_check.h
@@ -29,8 +29,9 @@ kDisabledByExtension = 4, kEnabledStandard = 5, kEnabledEnhanced = 6, + kEnabledStandardAvailableEnhanced = 7, // New enum values must go above here. - kMaxValue = kEnabledEnhanced, + kMaxValue = kEnabledStandardAvailableEnhanced, }; class SafetyCheckHandlerInterface {
diff --git a/components/services/storage/public/mojom/service_worker_storage_control.mojom b/components/services/storage/public/mojom/service_worker_storage_control.mojom index f653334..0fa69076 100644 --- a/components/services/storage/public/mojom/service_worker_storage_control.mojom +++ b/components/services/storage/public/mojom/service_worker_storage_control.mojom
@@ -93,7 +93,6 @@ // lifetime of user data is tied up with the registration. // It will be deleted when the corresponding registration is deleted. struct ServiceWorkerUserData { - int64 registration_id; string key; string value; }; @@ -249,14 +248,14 @@ (ServiceWorkerDatabaseStatus status); // Gets the user data from all registrations that have user data for |key|. + // Returns a map from registration IDs to their values. GetUserDataForAllRegistrations(string key) => - (ServiceWorkerDatabaseStatus status, - array<ServiceWorkerUserData> values); + (ServiceWorkerDatabaseStatus status, map<int64, string> values); // Gets the user data from all registrations that have user data for - // |key_prefix| where |key_prefix| is a prefix of keys. + // |key_prefix| where |key_prefix| is a prefix of keys. Returns a map from + // registration IDs to their values. GetUserDataForAllRegistrationsByKeyPrefix(string key_prefix) => - (ServiceWorkerDatabaseStatus status, - array<ServiceWorkerUserData> values); + (ServiceWorkerDatabaseStatus status, map<int64, string> values); // Clears the user data from all registrations using |key_prefix| as a prefix // of keys. ClearUserDataForAllRegistrationsByKeyPrefix(string key_prefix) =>
diff --git a/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc b/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc index d5eea0f4..25dd40b 100644 --- a/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc +++ b/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc
@@ -36,18 +36,16 @@ capabilities_.preserve_buffer_content = true; capabilities_.only_invalidates_damage_rect = false; capabilities_.number_of_buffers = 3; -#if defined(OS_ANDROID) capabilities_.orientation_mode = OutputSurface::OrientationMode::kHardware; - // With vulkan and android surface control, if the chrome is launched in - // landscape mode, the chrome is always blank until chrome window is rotated - // once. Workaround this problem by using logic rotation mode. +#if defined(OS_ANDROID) + // With vulkan, if the chrome is launched in landscape mode, the chrome is + // always blank until chrome window is rotated once. Workaround this problem + // by using logic rotation mode. // TODO(https://crbug.com/1115065): use hardware orientation mode for vulkan, if (dependency_->GetSharedContextState()->GrContextIsVulkan() && base::FeatureList::GetFieldTrial(features::kVulkan)) { capabilities_.orientation_mode = OutputSurface::OrientationMode::kLogic; } -#else - capabilities_.orientation_mode = OutputSurface::OrientationMode::kHardware; #endif // Force the number of max pending frames to one when the switch
diff --git a/components/viz/service/display_embedder/skia_output_device_vulkan.cc b/components/viz/service/display_embedder/skia_output_device_vulkan.cc index 57154ac..d69c465 100644 --- a/components/viz/service/display_embedder/skia_output_device_vulkan.cc +++ b/components/viz/service/display_embedder/skia_output_device_vulkan.cc
@@ -7,11 +7,13 @@ #include <utility> #include "base/compiler_specific.h" +#include "base/feature_list.h" #include "base/logging.h" #include "base/threading/scoped_blocking_call.h" #include "build/build_config.h" #include "components/viz/common/gpu/vulkan_context_provider.h" #include "gpu/command_buffer/service/memory_tracking.h" +#include "gpu/config/gpu_finch_features.h" #include "gpu/ipc/common/gpu_surface_lookup.h" #include "gpu/vulkan/vulkan_function_pointers.h" #include "gpu/vulkan/vulkan_implementation.h" @@ -292,6 +294,14 @@ capabilities_.output_surface_origin = gfx::SurfaceOrigin::kTopLeft; capabilities_.supports_post_sub_buffer = true; capabilities_.orientation_mode = OutputSurface::OrientationMode::kHardware; +#if defined(OS_ANDROID) + // With vulkan, if the chrome is launched in landscape mode, the chrome is + // always blank until chrome window is rotated once. Workaround this problem + // by using logic rotation mode. + // TODO(https://crbug.com/1115065): use hardware orientation mode for vulkan, + if (base::FeatureList::GetFieldTrial(features::kVulkan)) + capabilities_.orientation_mode = OutputSurface::OrientationMode::kLogic; +#endif // We don't know the number of buffers until the VulkanSwapChain is // initialized, so set it to 0. Since |damage_area_from_skia_output_device| is // assigned to true, so |number_of_buffers| will not be used for tracking
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl.cc b/components/viz/service/display_embedder/skia_output_surface_impl.cc index b9cdd83..4afabfa 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl.cc +++ b/components/viz/service/display_embedder/skia_output_surface_impl.cc
@@ -268,8 +268,6 @@ return gfx::OverlayTransform::OVERLAY_TRANSFORM_NONE; case OutputSurface::OrientationMode::kHardware: return display_transform_; - default: - NOTREACHED(); } }
diff --git a/content/browser/back_forward_cache_browsertest.cc b/content/browser/back_forward_cache_browsertest.cc index 41fcc60..352a655 100644 --- a/content/browser/back_forward_cache_browsertest.cc +++ b/content/browser/back_forward_cache_browsertest.cc
@@ -6599,6 +6599,8 @@ IN_PROC_BROWSER_TEST_F( BackForwardCacheBrowserTest, ProcessKilledIfMessageReceivedOnAssociatedInterfaceWhileCached) { + base::HistogramTester histogram_tester; + ASSERT_TRUE(embedded_test_server()->Start()); GURL url_a(embedded_test_server()->GetURL("a.com", "/title1.html")); GURL url_b(embedded_test_server()->GetURL("b.com", "/title1.html")); @@ -6632,6 +6634,11 @@ testing::Optional( bad_message::RFH_RECEIVED_ASSOCIATED_MESSAGE_WHILE_BFCACHED)); EXPECT_TRUE(delete_observer_rfh_a.deleted()); + histogram_tester.ExpectBucketCount( + "BackForwardCache.UnexpectedRendererToBrowserMessage.InterfaceName", + base::HistogramBase::Sample( + static_cast<int32_t>(base::HashMetricName(mojom::Echo::Name_))), + 1); } IN_PROC_BROWSER_TEST_F(
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc index 19ae61c..8ecb7872 100644 --- a/content/browser/frame_host/render_frame_host_impl.cc +++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -408,6 +408,10 @@ "KillIfInBackForwardCacheMessageFilter::WillDispatch bad_message", "interface_name", interface_name_, "message_name", message->name()); + base::UmaHistogramSparse( + "BackForwardCache.UnexpectedRendererToBrowserMessage.InterfaceName", + static_cast<int32_t>(base::HashMetricName(interface_name_))); + switch (policy_) { case BackForwardCacheImpl::kMessagePolicyNone: case BackForwardCacheImpl::kMessagePolicyLog: @@ -1360,6 +1364,13 @@ return it == portals_.end() ? nullptr : it->get(); } +std::vector<Portal*> RenderFrameHostImpl::GetPortals() const { + std::vector<Portal*> result; + for (const auto& portal : portals_) + result.push_back(portal.get()); + return result; +} + void RenderFrameHostImpl::DestroyPortal(Portal* portal) { auto it = portals_.find(portal); CHECK(it != portals_.end());
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h index ff48cc63..321131b1 100644 --- a/content/browser/frame_host/render_frame_host_impl.h +++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -1191,6 +1191,9 @@ // Look up a portal by its token (as received from the renderer process). Portal* FindPortalByToken(const blink::PortalToken& portal_token); + // Return portals owned by |this|. + std::vector<Portal*> GetPortals() const; + // Called when a Portal needs to be destroyed. void DestroyPortal(Portal* portal);
diff --git a/content/browser/native_file_system/file_system_chooser_browsertest.cc b/content/browser/native_file_system/file_system_chooser_browsertest.cc index 58a76ab5..356842d 100644 --- a/content/browser/native_file_system/file_system_chooser_browsertest.cc +++ b/content/browser/native_file_system/file_system_chooser_browsertest.cc
@@ -179,6 +179,34 @@ EXPECT_FALSE(IsFullscreen()); } +IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, + OpenFile_BlockedPermission) { + const base::FilePath test_file = CreateTestFile("Save File"); + SelectFileDialogParams dialog_params; + ui::SelectFileDialog::SetFactory( + new FakeSelectFileDialogFactory({test_file}, &dialog_params)); + + testing::StrictMock<MockNativeFileSystemPermissionContext> permission_context; + static_cast<NativeFileSystemManagerImpl*>( + BrowserContext::GetStoragePartition( + shell()->web_contents()->GetBrowserContext(), + shell()->web_contents()->GetSiteInstance()) + ->GetNativeFileSystemEntryFactory()) + ->SetPermissionContextForTesting(&permission_context); + + EXPECT_CALL(permission_context, + CanObtainReadPermission(url::Origin::Create( + embedded_test_server()->GetURL("/title1.html")))) + .WillOnce(testing::Return(false)); + + ASSERT_TRUE( + NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"))); + auto result = EvalJs(shell(), "self.showOpenFilePicker()"); + EXPECT_TRUE(result.error.find("not allowed") != std::string::npos) + << result.error; + EXPECT_EQ(ui::SelectFileDialog::SELECT_NONE, dialog_params.type); +} + IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, SaveFile_NonExistingFile) { const std::string file_contents = "file contents to write"; const base::FilePath test_file = CreateTestFile(""); @@ -254,6 +282,10 @@ ->SetPermissionContextForTesting(&permission_context); EXPECT_CALL(permission_context, + CanObtainReadPermission(url::Origin::Create( + embedded_test_server()->GetURL("/title1.html")))) + .WillOnce(testing::Return(true)); + EXPECT_CALL(permission_context, CanObtainWritePermission(url::Origin::Create( embedded_test_server()->GetURL("/title1.html")))) .WillOnce(testing::Return(false)); @@ -355,6 +387,34 @@ EXPECT_FALSE(IsFullscreen()); } +IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, + OpenDirectory_BlockedPermission) { + base::FilePath test_dir = CreateTestDir(); + SelectFileDialogParams dialog_params; + ui::SelectFileDialog::SetFactory( + new FakeSelectFileDialogFactory({test_dir}, &dialog_params)); + + testing::StrictMock<MockNativeFileSystemPermissionContext> permission_context; + static_cast<NativeFileSystemManagerImpl*>( + BrowserContext::GetStoragePartition( + shell()->web_contents()->GetBrowserContext(), + shell()->web_contents()->GetSiteInstance()) + ->GetNativeFileSystemEntryFactory()) + ->SetPermissionContextForTesting(&permission_context); + + EXPECT_CALL(permission_context, + CanObtainReadPermission(url::Origin::Create( + embedded_test_server()->GetURL("/title1.html")))) + .WillOnce(testing::Return(false)); + + ASSERT_TRUE( + NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"))); + auto result = EvalJs(shell(), "self.showDirectoryPicker()"); + EXPECT_TRUE(result.error.find("not allowed") != std::string::npos) + << result.error; + EXPECT_EQ(ui::SelectFileDialog::SELECT_NONE, dialog_params.type); +} + IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, OpenDirectory_DenyAccess) { base::FilePath test_dir = CreateTestDir(); SelectFileDialogParams dialog_params; @@ -375,6 +435,11 @@ PermissionStatus::ASK); EXPECT_CALL(permission_context, + CanObtainReadPermission(url::Origin::Create( + embedded_test_server()->GetURL("/title1.html")))) + .WillOnce(testing::Return(true)); + + EXPECT_CALL(permission_context, ConfirmSensitiveDirectoryAccess_( testing::_, testing::_, testing::_, testing::_, testing::_)) .WillOnce(RunOnceCallback<4>(SensitiveDirectoryResult::kAllowed)); @@ -437,6 +502,10 @@ .WillOnce(RunOnceCallback<4>(SensitiveDirectoryResult::kAbort)); EXPECT_CALL(permission_context, + CanObtainReadPermission(url::Origin::Create( + embedded_test_server()->GetURL("/title1.html")))) + .WillOnce(testing::Return(true)); + EXPECT_CALL(permission_context, CanObtainWritePermission(url::Origin::Create( embedded_test_server()->GetURL("/title1.html")))) .WillOnce(testing::Return(true)); @@ -484,6 +553,10 @@ .WillOnce(RunOnceCallback<4>(SensitiveDirectoryResult::kAbort)); EXPECT_CALL(permission_context, + CanObtainReadPermission(url::Origin::Create( + embedded_test_server()->GetURL("/title1.html")))) + .WillOnce(testing::Return(true)); + EXPECT_CALL(permission_context, CanObtainWritePermission(url::Origin::Create( embedded_test_server()->GetURL("/title1.html")))) .WillOnce(testing::Return(true));
diff --git a/content/browser/native_file_system/mock_native_file_system_permission_context.h b/content/browser/native_file_system/mock_native_file_system_permission_context.h index 82fe8a2..79d5389 100644 --- a/content/browser/native_file_system/mock_native_file_system_permission_context.h +++ b/content/browser/native_file_system/mock_native_file_system_permission_context.h
@@ -53,6 +53,7 @@ GlobalFrameRoutingId frame_id, base::OnceCallback<void(AfterWriteCheckResult)>& callback)); + MOCK_METHOD1(CanObtainReadPermission, bool(const url::Origin& origin)); MOCK_METHOD1(CanObtainWritePermission, bool(const url::Origin& origin)); };
diff --git a/content/browser/native_file_system/native_file_system_manager_impl.cc b/content/browser/native_file_system/native_file_system_manager_impl.cc index e7630d2..03787ae 100644 --- a/content/browser/native_file_system/native_file_system_manager_impl.cc +++ b/content/browser/native_file_system/native_file_system_manager_impl.cc
@@ -246,16 +246,17 @@ return; } - // When site setting is block, it's better not to show file chooser for save. - if (type == blink::mojom::ChooseFileSystemEntryType::kSaveFile && - permission_context_ && - !permission_context_->CanObtainWritePermission(context.origin)) { - std::move(callback).Run( - native_file_system_error::FromStatus( - NativeFileSystemStatus::kPermissionDenied), - std::vector<blink::mojom::NativeFileSystemEntryPtr>()); - - return; + if (permission_context_) { + // When site setting is block, it's better not to show file chooser. + if (!permission_context_->CanObtainReadPermission(context.origin) || + (type == blink::mojom::ChooseFileSystemEntryType::kSaveFile && + !permission_context_->CanObtainWritePermission(context.origin))) { + std::move(callback).Run( + native_file_system_error::FromStatus( + NativeFileSystemStatus::kPermissionDenied), + std::vector<blink::mojom::NativeFileSystemEntryPtr>()); + return; + } } RenderFrameHost* rfh = RenderFrameHost::FromID(context.frame_id);
diff --git a/content/browser/portal/portal.cc b/content/browser/portal/portal.cc index 4da15e4..edf8114 100644 --- a/content/browser/portal/portal.cc +++ b/content/browser/portal/portal.cc
@@ -307,169 +307,34 @@ void Portal::Activate(blink::TransferableMessage data, base::TimeTicks activation_time, ActivateCallback callback) { - WebContentsImpl* outer_contents = GetPortalHostContents(); - - if (outer_contents->portal()) { + if (GetPortalHostContents()->portal()) { mojo::ReportBadMessage("Portal::Activate called on nested portal"); - DestroySelf(); // Also deletes |this|. + DestroySelf(); return; } - DCHECK(owner_render_frame_host_->IsCurrent()) - << "The binding should have been closed when the portal's outer " - "FrameTreeNode was deleted due to swap out."; - - DCHECK(portal_contents_); - NavigationControllerImpl& portal_controller = - portal_contents_->GetController(); - NavigationControllerImpl& predecessor_controller = - outer_contents->GetController(); - - // If no navigation has yet committed in the portal, it cannot be activated as - // this would lead to an empty tab contents (without even an about:blank). - if (portal_controller.GetLastCommittedEntryIndex() < 0) { - std::move(callback).Run( - blink::mojom::PortalActivateResult::kRejectedDueToPortalNotReady); - return; - } - DCHECK(predecessor_controller.GetLastCommittedEntry()); - - // Error pages and interstitials may not host portals due to the HTTP(S) - // restriction. - DCHECK_EQ(PAGE_TYPE_NORMAL, - predecessor_controller.GetLastCommittedEntry()->GetPageType()); - - // If the portal is crashed or is showing an error page, reject activation. - if (portal_contents_->IsCrashed() || - portal_controller.GetLastCommittedEntry()->GetPageType() != - PAGE_TYPE_NORMAL) { - std::move(callback).Run( - blink::mojom::PortalActivateResult::kRejectedDueToErrorInPortal); + if (is_activating_) { + mojo::ReportBadMessage("Portal::Activate called twice on the same portal"); + DestroySelf(); return; } - // If a navigation in the main frame is occurring, stop it if possible and - // reject the activation if it's too late or if an ongoing navigation takes - // precedence. There are a few cases here: - // - a different RenderFrameHost has been assigned to the FrameTreeNode - // - the same RenderFrameHost is being used, but it is committing a navigation - // - the FrameTreeNode holds a navigation request that can't turn back but has - // not yet been handed off to a RenderFrameHost - FrameTreeNode* outer_root_node = owner_render_frame_host_->frame_tree_node(); - NavigationRequest* outer_navigation = outer_root_node->navigation_request(); - const bool has_user_gesture = - owner_render_frame_host_->HasTransientUserActivation(); - - // WILL_PROCESS_RESPONSE is slightly early: it happens - // immediately before READY_TO_COMMIT (unless it's deferred), but - // WILL_PROCESS_RESPONSE is easier to hook for tests using a - // NavigationThrottle. - if (owner_render_frame_host_->HasPendingCommitNavigation() || - (outer_navigation && - outer_navigation->state() >= NavigationRequest::WILL_PROCESS_RESPONSE) || - Navigator::ShouldIgnoreIncomingRendererRequest(outer_navigation, - has_user_gesture)) { - std::move(callback).Run(blink::mojom::PortalActivateResult:: - kRejectedDueToPredecessorNavigation); - return; - } - outer_root_node->navigator().CancelNavigation(outer_root_node); - - DCHECK(!is_closing_) << "Portal should not be shutting down when contents " - "ownership is yielded"; - - WebContentsDelegate* delegate = outer_contents->GetDelegate(); - std::unique_ptr<WebContents> successor_contents; - - if (portal_contents_->GetOuterWebContents()) { - FrameTreeNode* outer_frame_tree_node = FrameTreeNode::GloballyFindByID( - portal_contents_->GetOuterDelegateFrameTreeNodeId()); - outer_frame_tree_node->RemoveObserver(this); - successor_contents = portal_contents_->DetachFromOuterWebContents(); - owner_render_frame_host_->RemoveChild(outer_frame_tree_node); - } else { - // Portals created for predecessor pages during activation may not be - // attached to an outer WebContents, and may not have an outer frame tree - // node created (i.e. CreateProxyAndAttachPortal isn't called). In this - // case, we can skip a few of the detachment steps above. - for (auto& render_view_host : - portal_contents_->GetFrameTree()->render_view_hosts()) { - CreatePortalRenderWidgetHostView(portal_contents_.get(), - render_view_host.second); + for (Portal* portal : owner_render_frame_host()->GetPortals()) { + if (portal != this && portal->is_activating_) { + mojo::ReportBadMessage( + "Portal::Activate called on portal whose owner RenderFrameHost has " + "another portal that is activating"); + DestroySelf(); + return; } - successor_contents = portal_contents_.ReleaseOwnership(); - } - DCHECK(!portal_contents_.OwnsContents()); - - // This assumes that the delegate keeps the new contents alive long enough to - // notify it of activation, at least. - WebContentsImpl* successor_contents_raw = - static_cast<WebContentsImpl*>(successor_contents.get()); - - auto* outer_contents_main_frame_view = static_cast<RenderWidgetHostViewBase*>( - outer_contents->GetMainFrame()->GetView()); - DCHECK(!outer_contents->GetPendingMainFrame()); - auto* portal_contents_main_frame_view = - static_cast<RenderWidgetHostViewBase*>( - successor_contents_raw->GetMainFrame()->GetView()); - - std::vector<std::unique_ptr<ui::TouchEvent>> touch_events; - - if (outer_contents_main_frame_view) { - // Take fallback contents from previous WebContents so that the activation - // is smooth without flashes. - portal_contents_main_frame_view->TakeFallbackContentFrom( - outer_contents_main_frame_view); - touch_events = - outer_contents_main_frame_view->ExtractAndCancelActiveTouches(); - FlushTouchEventQueues(outer_contents_main_frame_view->host()); } - TakeHistoryForActivation(successor_contents_raw, outer_contents); - - devtools_instrumentation::PortalActivated(outer_contents->GetMainFrame()); - successor_contents_raw->set_portal(nullptr); - - std::unique_ptr<WebContents> predecessor_web_contents = - delegate->ActivatePortalWebContents(outer_contents, - std::move(successor_contents)); - DCHECK_EQ(predecessor_web_contents.get(), outer_contents); - - if (outer_contents_main_frame_view) { - portal_contents_main_frame_view->TransferTouches(touch_events); - // Takes ownership of SyntheticGestureController from the predecessor's - // RenderWidgetHost. This allows the controller to continue sending events - // to the new RenderWidgetHostView. - portal_contents_main_frame_view->host()->TakeSyntheticGestureController( - outer_contents_main_frame_view->host()); - outer_contents_main_frame_view->Destroy(); - } - - // These pointers are cleared so that they don't dangle in the event this - // object isn't immediately deleted. It isn't done sooner because - // ActivatePortalWebContents misbehaves if the WebContents doesn't appear to - // be a portal at that time. - portal_contents_.Clear(); - - mojo::PendingAssociatedRemote<blink::mojom::Portal> pending_portal; - auto portal_receiver = pending_portal.InitWithNewEndpointAndPassReceiver(); - mojo::PendingAssociatedRemote<blink::mojom::PortalClient> pending_client; - auto client_receiver = pending_client.InitWithNewEndpointAndPassReceiver(); - - RenderFrameHostImpl* successor_main_frame = - successor_contents_raw->GetMainFrame(); - auto predecessor = std::make_unique<Portal>( - successor_main_frame, std::move(predecessor_web_contents)); - predecessor->Bind(std::move(portal_receiver), std::move(pending_client)); - successor_main_frame->OnPortalActivated( - std::move(predecessor), std::move(pending_portal), - std::move(client_receiver), std::move(data), std::move(callback)); - - // Notifying of activation happens later than ActivatePortalWebContents so - // that it is observed after predecessor_web_contents has been moved into a - // portal. - DCHECK(outer_contents->IsPortal()); - successor_contents_raw->DidActivatePortal(outer_contents, activation_time); + is_activating_ = true; + WebContentsImpl* outer_contents = GetPortalHostContents(); + outer_contents->GetDelegate()->UpdateInspectedWebContentsIfNecessary( + outer_contents, portal_contents_.get(), + base::BindOnce(&Portal::ActivateImpl, weak_factory_.GetWeakPtr(), + std::move(data), activation_time, std::move(callback))); } void Portal::PostMessageToGuest( @@ -574,6 +439,186 @@ WebContents::FromRenderFrameHost(owner_render_frame_host_)); } +std::pair<bool, blink::mojom::PortalActivateResult> Portal::CanActivate() { + WebContentsImpl* outer_contents = GetPortalHostContents(); + + DCHECK(owner_render_frame_host_->IsCurrent()) + << "The binding should have been closed when the portal's outer " + "FrameTreeNode was deleted due to swap out."; + + DCHECK(portal_contents_); + NavigationControllerImpl& portal_controller = + portal_contents_->GetController(); + NavigationControllerImpl& predecessor_controller = + outer_contents->GetController(); + + // If no navigation has yet committed in the portal, it cannot be activated as + // this would lead to an empty tab contents (without even an about:blank). + if (portal_controller.GetLastCommittedEntryIndex() < 0) { + return std::make_pair( + false, + blink::mojom::PortalActivateResult::kRejectedDueToPortalNotReady); + } + DCHECK(predecessor_controller.GetLastCommittedEntry()); + + // Error pages and interstitials may not host portals due to the HTTP(S) + // restriction. + DCHECK_EQ(PAGE_TYPE_NORMAL, + predecessor_controller.GetLastCommittedEntry()->GetPageType()); + + // If the portal is crashed or is showing an error page, reject activation. + if (portal_contents_->IsCrashed() || + portal_controller.GetLastCommittedEntry()->GetPageType() != + PAGE_TYPE_NORMAL) { + return std::make_pair( + false, blink::mojom::PortalActivateResult::kRejectedDueToErrorInPortal); + } + + // If a navigation in the main frame is occurring, stop it if possible and + // reject the activation if it's too late or if an ongoing navigation takes + // precedence. There are a few cases here: + // - a different RenderFrameHost has been assigned to the FrameTreeNode + // - the same RenderFrameHost is being used, but it is committing a navigation + // - the FrameTreeNode holds a navigation request that can't turn back but has + // not yet been handed off to a RenderFrameHost + FrameTreeNode* outer_root_node = owner_render_frame_host_->frame_tree_node(); + NavigationRequest* outer_navigation = outer_root_node->navigation_request(); + const bool has_user_gesture = + owner_render_frame_host_->HasTransientUserActivation(); + + // WILL_PROCESS_RESPONSE is slightly early: it happens + // immediately before READY_TO_COMMIT (unless it's deferred), but + // WILL_PROCESS_RESPONSE is easier to hook for tests using a + // NavigationThrottle. + if (owner_render_frame_host_->HasPendingCommitNavigation() || + (outer_navigation && + outer_navigation->state() >= NavigationRequest::WILL_PROCESS_RESPONSE) || + Navigator::ShouldIgnoreIncomingRendererRequest(outer_navigation, + has_user_gesture)) { + return std::make_pair(false, blink::mojom::PortalActivateResult:: + kRejectedDueToPredecessorNavigation); + } + return std::make_pair(true, + blink::mojom::PortalActivateResult::kAbortedDueToBug); +} + +void Portal::ActivateImpl(blink::TransferableMessage data, + base::TimeTicks activation_time, + ActivateCallback callback) { + WebContentsImpl* outer_contents = GetPortalHostContents(); + WebContentsDelegate* delegate = outer_contents->GetDelegate(); + + is_activating_ = false; + + bool can_activate; + blink::mojom::PortalActivateResult activate_error; + std::tie(can_activate, activate_error) = CanActivate(); + if (!can_activate) { + outer_contents->GetDelegate()->UpdateInspectedWebContentsIfNecessary( + portal_contents_.get(), outer_contents, base::DoNothing()); + std::move(callback).Run(activate_error); + return; + } + + FrameTreeNode* outer_root_node = owner_render_frame_host_->frame_tree_node(); + outer_root_node->navigator().CancelNavigation(outer_root_node); + + DCHECK(!is_closing_) << "Portal should not be shutting down when contents " + "ownership is yielded"; + + std::unique_ptr<WebContents> successor_contents; + + if (portal_contents_->GetOuterWebContents()) { + FrameTreeNode* outer_frame_tree_node = FrameTreeNode::GloballyFindByID( + portal_contents_->GetOuterDelegateFrameTreeNodeId()); + outer_frame_tree_node->RemoveObserver(this); + successor_contents = portal_contents_->DetachFromOuterWebContents(); + owner_render_frame_host_->RemoveChild(outer_frame_tree_node); + } else { + // Portals created for predecessor pages during activation may not be + // attached to an outer WebContents, and may not have an outer frame tree + // node created (i.e. CreateProxyAndAttachPortal isn't called). In this + // case, we can skip a few of the detachment steps above. + for (auto& render_view_host : + portal_contents_->GetFrameTree()->render_view_hosts()) { + CreatePortalRenderWidgetHostView(portal_contents_.get(), + render_view_host.second); + } + successor_contents = portal_contents_.ReleaseOwnership(); + } + DCHECK(!portal_contents_.OwnsContents()); + + // This assumes that the delegate keeps the new contents alive long enough to + // notify it of activation, at least. + WebContentsImpl* successor_contents_raw = + static_cast<WebContentsImpl*>(successor_contents.get()); + + auto* outer_contents_main_frame_view = static_cast<RenderWidgetHostViewBase*>( + outer_contents->GetMainFrame()->GetView()); + DCHECK(!outer_contents->GetPendingMainFrame()); + auto* portal_contents_main_frame_view = + static_cast<RenderWidgetHostViewBase*>( + successor_contents_raw->GetMainFrame()->GetView()); + + std::vector<std::unique_ptr<ui::TouchEvent>> touch_events; + + if (outer_contents_main_frame_view) { + // Take fallback contents from previous WebContents so that the activation + // is smooth without flashes. + portal_contents_main_frame_view->TakeFallbackContentFrom( + outer_contents_main_frame_view); + touch_events = + outer_contents_main_frame_view->ExtractAndCancelActiveTouches(); + FlushTouchEventQueues(outer_contents_main_frame_view->host()); + } + + TakeHistoryForActivation(successor_contents_raw, outer_contents); + + devtools_instrumentation::PortalActivated(outer_contents->GetMainFrame()); + successor_contents_raw->set_portal(nullptr); + + std::unique_ptr<WebContents> predecessor_web_contents = + delegate->ActivatePortalWebContents(outer_contents, + std::move(successor_contents)); + DCHECK_EQ(predecessor_web_contents.get(), outer_contents); + + if (outer_contents_main_frame_view) { + portal_contents_main_frame_view->TransferTouches(touch_events); + // Takes ownership of SyntheticGestureController from the predecessor's + // RenderWidgetHost. This allows the controller to continue sending events + // to the new RenderWidgetHostView. + portal_contents_main_frame_view->host()->TakeSyntheticGestureController( + outer_contents_main_frame_view->host()); + outer_contents_main_frame_view->Destroy(); + } + + // These pointers are cleared so that they don't dangle in the event this + // object isn't immediately deleted. It isn't done sooner because + // ActivatePortalWebContents misbehaves if the WebContents doesn't appear to + // be a portal at that time. + portal_contents_.Clear(); + + mojo::PendingAssociatedRemote<blink::mojom::Portal> pending_portal; + auto portal_receiver = pending_portal.InitWithNewEndpointAndPassReceiver(); + mojo::PendingAssociatedRemote<blink::mojom::PortalClient> pending_client; + auto client_receiver = pending_client.InitWithNewEndpointAndPassReceiver(); + + RenderFrameHostImpl* successor_main_frame = + successor_contents_raw->GetMainFrame(); + auto predecessor = std::make_unique<Portal>( + successor_main_frame, std::move(predecessor_web_contents)); + predecessor->Bind(std::move(portal_receiver), std::move(pending_client)); + successor_main_frame->OnPortalActivated( + std::move(predecessor), std::move(pending_portal), + std::move(client_receiver), std::move(data), std::move(callback)); + + // Notifying of activation happens later than ActivatePortalWebContents so + // that it is observed after predecessor_web_contents has been moved into a + // portal. + DCHECK(outer_contents->IsPortal()); + successor_contents_raw->DidActivatePortal(outer_contents, activation_time); +} + Portal::WebContentsHolder::WebContentsHolder(Portal* portal) : portal_(portal) {}
diff --git a/content/browser/portal/portal.h b/content/browser/portal/portal.h index a5fbaa6..f6192f4 100644 --- a/content/browser/portal/portal.h +++ b/content/browser/portal/portal.h
@@ -191,6 +191,11 @@ void SetPortalContents(std::unique_ptr<WebContents> web_contents); + std::pair<bool, blink::mojom::PortalActivateResult> CanActivate(); + void ActivateImpl(blink::TransferableMessage data, + base::TimeTicks activation_time, + ActivateCallback callback); + RenderFrameHostImpl* owner_render_frame_host_; // Uniquely identifies the portal, this token is used by the browser process @@ -214,9 +219,14 @@ // Set when |Close| is called. Destruction will occur shortly thereafter. bool is_closing_ = false; + // Set when portal is activating. + bool is_activating_ = false; + // Another implementation of blink::mojom::Portal to bind instead. // For use in testing only. std::unique_ptr<blink::mojom::Portal> interceptor_; + + base::WeakPtrFactory<Portal> weak_factory_{this}; }; } // namespace content
diff --git a/content/browser/portal/portal_browsertest.cc b/content/browser/portal/portal_browsertest.cc index aa58c907..32654b1 100644 --- a/content/browser/portal/portal_browsertest.cc +++ b/content/browser/portal/portal_browsertest.cc
@@ -2172,6 +2172,76 @@ EXPECT_FALSE(download_observer.AwaitDownload()); } +IN_PROC_BROWSER_TEST_F(PortalBrowserTest, CallActivateOnTwoPortals) { + EXPECT_TRUE(NavigateToURL( + shell(), embedded_test_server()->GetURL("portal.test", "/title1.html"))); + WebContentsImpl* web_contents_impl = + static_cast<WebContentsImpl*>(shell()->web_contents()); + RenderFrameHostImpl* main_frame = web_contents_impl->GetMainFrame(); + shell()->ShowDevTools(); + + GURL url_a = embedded_test_server()->GetURL("a.com", "/title1.html"); + Portal* portal_a = CreatePortalToUrl(web_contents_impl, url_a); + GURL url_b = embedded_test_server()->GetURL("b.com", "/title1.html"); + Portal* portal_b = CreatePortalToUrl(web_contents_impl, url_b); + + PortalInterceptorForTesting* portal_interceptor = + PortalInterceptorForTesting::From(portal_a); + // Hijacks navigate request and calls Activate on both portals. + portal_interceptor->SetNavigateCallback(base::BindRepeating( + [](Portal* portal_a, Portal* portal_b, const GURL&, + blink::mojom::ReferrerPtr, + blink::mojom::Portal::NavigateCallback callback) { + portal_a->Activate(blink::TransferableMessage(), base::TimeTicks::Now(), + base::DoNothing()); + portal_b->Activate(blink::TransferableMessage(), base::TimeTicks::Now(), + base::DoNothing()); + std::move(callback).Run(); + }, + portal_a, portal_b)); + + RenderProcessHostBadIpcMessageWaiter rph_kill_waiter( + main_frame->GetProcess()); + GURL dummy_url = embedded_test_server()->GetURL("c.com", "/title1.html"); + ExecuteScriptAsync( + main_frame, + JsReplace("document.querySelector('portal').src = $1", dummy_url)); + EXPECT_EQ(bad_message::RPH_MOJO_PROCESS_ERROR, rph_kill_waiter.Wait()); +} + +IN_PROC_BROWSER_TEST_F(PortalBrowserTest, CallActivateTwice) { + EXPECT_TRUE(NavigateToURL( + shell(), embedded_test_server()->GetURL("portal.test", "/title1.html"))); + WebContentsImpl* web_contents_impl = + static_cast<WebContentsImpl*>(shell()->web_contents()); + RenderFrameHostImpl* main_frame = web_contents_impl->GetMainFrame(); + shell()->ShowDevTools(); + + GURL url = embedded_test_server()->GetURL("a.com", "/title1.html"); + Portal* portal = CreatePortalToUrl(web_contents_impl, url); + PortalInterceptorForTesting* portal_interceptor = + PortalInterceptorForTesting::From(portal); + // Hijacks navigate request and calls Activate twice instead. + portal_interceptor->SetNavigateCallback(base::BindRepeating( + [](Portal* portal, const GURL&, blink::mojom::ReferrerPtr, + blink::mojom::Portal::NavigateCallback callback) { + portal->Activate(blink::TransferableMessage(), base::TimeTicks::Now(), + base::DoNothing()); + portal->Activate(blink::TransferableMessage(), base::TimeTicks::Now(), + base::DoNothing()); + std::move(callback).Run(); + }, + portal)); + + RenderProcessHostBadIpcMessageWaiter rph_kill_waiter( + main_frame->GetProcess()); + GURL dummy_url = embedded_test_server()->GetURL("b.com", "/title1.html"); + ExecuteScriptAsync( + main_frame, + JsReplace("document.querySelector('portal').src = $1", dummy_url)); + EXPECT_EQ(bad_message::RPH_MOJO_PROCESS_ERROR, rph_kill_waiter.Wait()); +} + namespace { static constexpr struct {
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc index ee8379b..82aeb50 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.cc +++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -1030,8 +1030,6 @@ if (!using_browser_compositor_) { SynchronousCopyContents(src_subrect, output_size, std::move(callback)); - UMA_HISTOGRAM_TIMES("Compositing.CopyFromSurfaceTimeSynchronous", - base::TimeTicks::Now() - start_time); return; }
diff --git a/content/browser/service_worker/service_worker_database.cc b/content/browser/service_worker/service_worker_database.cc index 01a2eaf..38f3457 100644 --- a/content/browser/service_worker/service_worker_database.cc +++ b/content/browser/service_worker/service_worker_database.cc
@@ -1111,7 +1111,7 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadUserDataForAllRegistrations( const std::string& user_data_name, - std::vector<storage::mojom::ServiceWorkerUserDataPtr>* user_data) { + std::vector<std::pair<int64_t, std::string>>* user_data) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(user_data->empty()); @@ -1153,8 +1153,7 @@ user_data->clear(); break; } - user_data->emplace_back(storage::mojom::ServiceWorkerUserData::New( - registration_id, user_data_name, value)); + user_data->push_back(std::make_pair(registration_id, value)); } } @@ -1165,7 +1164,7 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadUserDataForAllRegistrationsByKeyPrefix( const std::string& user_data_name_prefix, - std::vector<storage::mojom::ServiceWorkerUserDataPtr>* user_data) { + std::vector<std::pair<int64_t, std::string>>* user_data) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(user_data->empty()); @@ -1222,8 +1221,7 @@ user_data->clear(); break; } - user_data->push_back(storage::mojom::ServiceWorkerUserData::New( - registration_id, parts[0], value)); + user_data->push_back(std::make_pair(registration_id, value)); } }
diff --git a/content/browser/service_worker/service_worker_database.h b/content/browser/service_worker/service_worker_database.h index 49f9cd9..3ee09fdd 100644 --- a/content/browser/service_worker/service_worker_database.h +++ b/content/browser/service_worker/service_worker_database.h
@@ -217,14 +217,14 @@ // from the database. Returns OK if they are successfully read or not found. Status ReadUserDataForAllRegistrations( const std::string& user_data_name, - std::vector<storage::mojom::ServiceWorkerUserDataPtr>* user_data); + std::vector<std::pair<int64_t, std::string>>* user_data); // Reads user data for all registrations that have data with // |user_data_name_prefix| from the database. Returns OK if they are // successfully read or not found. Status ReadUserDataForAllRegistrationsByKeyPrefix( const std::string& user_data_name_prefix, - std::vector<storage::mojom::ServiceWorkerUserDataPtr>* user_data); + std::vector<std::pair<int64_t, std::string>>* user_data); // Deletes user data for all registrations that have data with // |user_data_name_prefix| from the database. Returns OK if all are
diff --git a/content/browser/service_worker/service_worker_database_unittest.cc b/content/browser/service_worker/service_worker_database_unittest.cc index 0fa08fe..c5caaa2 100644 --- a/content/browser/service_worker/service_worker_database_unittest.cc +++ b/content/browser/service_worker/service_worker_database_unittest.cc
@@ -106,12 +106,11 @@ } std::vector<storage::mojom::ServiceWorkerUserDataPtr> CreateUserData( - int64_t registration_id, const std::vector<std::pair<std::string, std::string>>& key_value_pairs) { std::vector<storage::mojom::ServiceWorkerUserDataPtr> out; for (auto& kv : key_value_pairs) { - out.push_back(storage::mojom::ServiceWorkerUserData::New( - registration_id, kv.first, kv.second)); + out.push_back( + storage::mojom::ServiceWorkerUserData::New(kv.first, kv.second)); } return out; } @@ -1084,9 +1083,8 @@ // Write user data associated with the stored registration. std::vector<std::string> user_data_out; EXPECT_EQ(ServiceWorkerDatabase::Status::kOk, - database->WriteUserData( - data.registration_id, kOrigin, - CreateUserData(data.registration_id, {{"key1", "data"}}))); + database->WriteUserData(data.registration_id, kOrigin, + CreateUserData({{"key1", "data"}}))); EXPECT_EQ( ServiceWorkerDatabase::Status::kOk, database->ReadUserData(data.registration_id, {"key1"}, &user_data_out)); @@ -1096,15 +1094,13 @@ // Writing user data not associated with the stored registration should be // failed. EXPECT_EQ(ServiceWorkerDatabase::Status::kErrorNotFound, - database->WriteUserData( - 300, kOrigin, - CreateUserData(data.registration_id, {{"key1", "data"}}))); + database->WriteUserData(300, kOrigin, + CreateUserData({{"key1", "data"}}))); // Write empty user data for a different key. EXPECT_EQ(ServiceWorkerDatabase::Status::kOk, database->WriteUserData(data.registration_id, kOrigin, - CreateUserData(data.registration_id, - {{"key2", std::string()}}))); + CreateUserData({{"key2", std::string()}}))); EXPECT_EQ( ServiceWorkerDatabase::Status::kOk, database->ReadUserData(data.registration_id, {"key2"}, &user_data_out)); @@ -1118,9 +1114,8 @@ // Overwrite the existing user data. EXPECT_EQ(ServiceWorkerDatabase::Status::kOk, - database->WriteUserData( - data.registration_id, kOrigin, - CreateUserData(data.registration_id, {{"key1", "overwrite"}}))); + database->WriteUserData(data.registration_id, kOrigin, + CreateUserData({{"key1", "overwrite"}}))); EXPECT_EQ( ServiceWorkerDatabase::Status::kOk, database->ReadUserData(data.registration_id, {"key1"}, &user_data_out)); @@ -1142,11 +1137,10 @@ // Write/overwrite multiple user data keys. EXPECT_EQ(ServiceWorkerDatabase::Status::kOk, - database->WriteUserData( - data.registration_id, kOrigin, - CreateUserData(data.registration_id, {{"key2", "overwrite2"}, - {"key3", "data3"}, - {"key4", "data4"}}))); + database->WriteUserData(data.registration_id, kOrigin, + CreateUserData({{"key2", "overwrite2"}, + {"key3", "data3"}, + {"key4", "data4"}}))); EXPECT_EQ( ServiceWorkerDatabase::Status::kErrorNotFound, database->ReadUserData(data.registration_id, {"key1"}, &user_data_out)); @@ -1218,63 +1212,51 @@ ASSERT_EQ( ServiceWorkerDatabase::Status::kOk, database->WriteUserData(data1.registration_id, kOrigin, - CreateUserData(data1.registration_id, - {{"key_prefix:key1", "value1"}}))); + CreateUserData({{"key_prefix:key1", "value1"}}))); ASSERT_EQ( ServiceWorkerDatabase::Status::kOk, database->WriteUserData(data1.registration_id, kOrigin, - CreateUserData(data1.registration_id, - {{"key_prefix:key2", "value2"}}))); + CreateUserData({{"key_prefix:key2", "value2"}}))); ASSERT_EQ( ServiceWorkerDatabase::Status::kOk, database->WriteUserData(data1.registration_id, kOrigin, - CreateUserData(data1.registration_id, - {{"key_prefix:key3", "value3"}}))); + CreateUserData({{"key_prefix:key3", "value3"}}))); // Write user data associated with the registration2. ASSERT_EQ( ServiceWorkerDatabase::Status::kOk, database->WriteUserData(data2.registration_id, kOrigin, - CreateUserData(data2.registration_id, - {{"key_prefix:key1", "value1"}}))); + CreateUserData({{"key_prefix:key1", "value1"}}))); ASSERT_EQ( ServiceWorkerDatabase::Status::kOk, database->WriteUserData(data2.registration_id, kOrigin, - CreateUserData(data2.registration_id, - {{"key_prefix:key2", "value2"}}))); + CreateUserData({{"key_prefix:key2", "value2"}}))); ASSERT_EQ(ServiceWorkerDatabase::Status::kOk, database->WriteUserData( data2.registration_id, kOrigin, - CreateUserData(data2.registration_id, - {{"another_key_prefix:key1", "value1"}}))); + CreateUserData({{"another_key_prefix:key1", "value1"}}))); ASSERT_EQ(ServiceWorkerDatabase::Status::kOk, database->WriteUserData( data2.registration_id, kOrigin, - CreateUserData(data2.registration_id, - {{"another_key_prefix:key2", "value2"}}))); + CreateUserData({{"another_key_prefix:key2", "value2"}}))); // Get all registrations with user data by key prefix. - std::vector<storage::mojom::ServiceWorkerUserDataPtr> user_data_list; + std::vector<std::pair<int64_t, std::string>> user_data_list; ASSERT_EQ(ServiceWorkerDatabase::Status::kOk, database->ReadUserDataForAllRegistrationsByKeyPrefix( "key_prefix:", &user_data_list)); ASSERT_EQ(5u, user_data_list.size()); - EXPECT_EQ(data1.registration_id, user_data_list[0]->registration_id); - EXPECT_EQ("key_prefix:key1", user_data_list[0]->key); - EXPECT_EQ("value1", user_data_list[0]->value); - EXPECT_EQ(data2.registration_id, user_data_list[1]->registration_id); - EXPECT_EQ("key_prefix:key1", user_data_list[1]->key); - EXPECT_EQ("value1", user_data_list[1]->value); - EXPECT_EQ(data1.registration_id, user_data_list[2]->registration_id); - EXPECT_EQ("key_prefix:key2", user_data_list[2]->key); - EXPECT_EQ("value2", user_data_list[2]->value); - EXPECT_EQ(data2.registration_id, user_data_list[3]->registration_id); - EXPECT_EQ("key_prefix:key2", user_data_list[3]->key); - EXPECT_EQ("value2", user_data_list[3]->value); - EXPECT_EQ(data1.registration_id, user_data_list[4]->registration_id); - EXPECT_EQ("key_prefix:key3", user_data_list[4]->key); - EXPECT_EQ("value3", user_data_list[4]->value); + EXPECT_EQ(data1.registration_id, user_data_list[0].first); + EXPECT_EQ("value1", user_data_list[0].second); + EXPECT_EQ(data2.registration_id, user_data_list[1].first); + EXPECT_EQ("value1", user_data_list[1].second); + EXPECT_EQ(data1.registration_id, user_data_list[2].first); + EXPECT_EQ("value2", user_data_list[2].second); + EXPECT_EQ(data2.registration_id, user_data_list[3].first); + EXPECT_EQ("value2", user_data_list[3].second); + EXPECT_EQ(data1.registration_id, user_data_list[4].first); + EXPECT_EQ("value3", user_data_list[4].second); } TEST(ServiceWorkerDatabaseTest, ReadUserDataByKeyPrefix) { @@ -1298,8 +1280,7 @@ ASSERT_EQ(ServiceWorkerDatabase::Status::kOk, database->WriteUserData( data.registration_id, kOrigin, - CreateUserData(data.registration_id, - {{"key_prefix:key1", "value_c1"}, + CreateUserData({{"key_prefix:key1", "value_c1"}, {"key_prefix:key2", "value_c2"}, {"other_key_prefix:k1", "value_d1"}, {"other_key_prefix:k2", "value_d2"}}))); @@ -1344,8 +1325,7 @@ ASSERT_EQ(ServiceWorkerDatabase::Status::kOk, database->WriteUserData( data.registration_id, kOrigin, - CreateUserData(data.registration_id, - {{"key_prefix:key1", "value_c1"}, + CreateUserData({{"key_prefix:key1", "value_c1"}, {"key_prefix:key2", "value_c2"}, {"other_key_prefix:k1", "value_d1"}, {"other_key_prefix:k2", "value_d2"}}))); @@ -1407,8 +1387,7 @@ ASSERT_EQ(ServiceWorkerDatabase::Status::kOk, database->WriteUserData( data1.registration_id, kOrigin, - CreateUserData(data1.registration_id, - {{"key_prefix:key1", "value_a1"}, + CreateUserData({{"key_prefix:key1", "value_a1"}, {"key_prefix:key2", "value_a2"}, {"key_prefix:key3", "value_a3"}, {"kept_key_prefix:key1", "value_b1"}}))); @@ -1417,8 +1396,7 @@ ASSERT_EQ(ServiceWorkerDatabase::Status::kOk, database->WriteUserData( data2.registration_id, kOrigin, - CreateUserData(data2.registration_id, - {{"key_prefix:key1", "value_c1"}, + CreateUserData({{"key_prefix:key1", "value_c1"}, {"key_prefix:key2", "value_c2"}, {"other_key_prefix:key1", "value_d1"}, {"other_key_prefix:key2", "value_d2"}, @@ -1440,20 +1418,17 @@ {"key_prefix:", "other_key_prefix:", "not_found_key_prefix:"})); // User data with deleted "key_prefix:" should only remain for registration 1. - std::vector<storage::mojom::ServiceWorkerUserDataPtr> user_data_list; + std::vector<std::pair<int64_t, std::string>> user_data_list; ASSERT_EQ(ServiceWorkerDatabase::Status::kOk, database->ReadUserDataForAllRegistrationsByKeyPrefix( "key_prefix:", &user_data_list)); ASSERT_EQ(3u, user_data_list.size()); - EXPECT_EQ(data1.registration_id, user_data_list[0]->registration_id); - EXPECT_EQ("key_prefix:key1", user_data_list[0]->key); - EXPECT_EQ("value_a1", user_data_list[0]->value); - EXPECT_EQ(data1.registration_id, user_data_list[1]->registration_id); - EXPECT_EQ("key_prefix:key2", user_data_list[1]->key); - EXPECT_EQ("value_a2", user_data_list[1]->value); - EXPECT_EQ(data1.registration_id, user_data_list[2]->registration_id); - EXPECT_EQ("key_prefix:key3", user_data_list[2]->key); - EXPECT_EQ("value_a3", user_data_list[2]->value); + EXPECT_EQ(data1.registration_id, user_data_list[0].first); + EXPECT_EQ("value_a1", user_data_list[0].second); + EXPECT_EQ(data1.registration_id, user_data_list[1].first); + EXPECT_EQ("value_a2", user_data_list[1].second); + EXPECT_EQ(data1.registration_id, user_data_list[2].first); + EXPECT_EQ("value_a3", user_data_list[2].second); // User data for second deleted key prefix should also have been deleted. user_data_list.clear(); @@ -1469,15 +1444,12 @@ database->ReadUserDataForAllRegistrationsByKeyPrefix( "kept_key_prefix:", &user_data_list)); ASSERT_EQ(3u, user_data_list.size()); - EXPECT_EQ(data1.registration_id, user_data_list[0]->registration_id); - EXPECT_EQ("kept_key_prefix:key1", user_data_list[0]->key); - EXPECT_EQ("value_b1", user_data_list[0]->value); - EXPECT_EQ(data2.registration_id, user_data_list[1]->registration_id); - EXPECT_EQ("kept_key_prefix:key1", user_data_list[1]->key); - EXPECT_EQ("value_e1", user_data_list[1]->value); - EXPECT_EQ(data2.registration_id, user_data_list[2]->registration_id); - EXPECT_EQ("kept_key_prefix:key2", user_data_list[2]->key); - EXPECT_EQ("value_e2", user_data_list[2]->value); + EXPECT_EQ(data1.registration_id, user_data_list[0].first); + EXPECT_EQ("value_b1", user_data_list[0].second); + EXPECT_EQ(data2.registration_id, user_data_list[1].first); + EXPECT_EQ("value_e1", user_data_list[1].second); + EXPECT_EQ(data2.registration_id, user_data_list[2].first); + EXPECT_EQ("value_e2", user_data_list[2].second); } TEST(ServiceWorkerDatabaseTest, @@ -1515,8 +1487,7 @@ ASSERT_EQ(ServiceWorkerDatabase::Status::kOk, database->WriteUserData( data1.registration_id, kOrigin, - CreateUserData(data1.registration_id, - {{"key_prefix:key1", "value_a1"}, + CreateUserData({{"key_prefix:key1", "value_a1"}, {"key_prefix:key2", "value_a2"}, {"key_prefix:key3", "value_a3"}, {"kept_key_prefix:key1", "value_b1"}}))); @@ -1525,8 +1496,7 @@ ASSERT_EQ(ServiceWorkerDatabase::Status::kOk, database->WriteUserData( data2.registration_id, kOrigin, - CreateUserData(data2.registration_id, - {{"key_prefix:key1", "value_c1"}, + CreateUserData({{"key_prefix:key1", "value_c1"}, {"key_prefix:key2", "value_c2"}, {"kept_key_prefix:key1", "value_d1"}, {"kept_key_prefix:key2", "value_d2"}}))); @@ -1544,7 +1514,7 @@ database->DeleteUserDataForAllRegistrationsByKeyPrefix("key_prefix:")); // User data with deleted "key_prefix:" should be deleted. - std::vector<storage::mojom::ServiceWorkerUserDataPtr> user_data_list; + std::vector<std::pair<int64_t, std::string>> user_data_list; ASSERT_EQ(ServiceWorkerDatabase::Status::kOk, database->ReadUserDataForAllRegistrationsByKeyPrefix( "key_prefix:", &user_data_list)); @@ -1557,15 +1527,12 @@ "kept_key_prefix:", &user_data_list)); ASSERT_EQ(3u, user_data_list.size()); - EXPECT_EQ(data1.registration_id, user_data_list[0]->registration_id); - EXPECT_EQ("kept_key_prefix:key1", user_data_list[0]->key); - EXPECT_EQ("value_b1", user_data_list[0]->value); - EXPECT_EQ(data2.registration_id, user_data_list[1]->registration_id); - EXPECT_EQ("kept_key_prefix:key1", user_data_list[1]->key); - EXPECT_EQ("value_d1", user_data_list[1]->value); - EXPECT_EQ(data2.registration_id, user_data_list[2]->registration_id); - EXPECT_EQ("kept_key_prefix:key2", user_data_list[2]->key); - EXPECT_EQ("value_d2", user_data_list[2]->value); + EXPECT_EQ(data1.registration_id, user_data_list[0].first); + EXPECT_EQ("value_b1", user_data_list[0].second); + EXPECT_EQ(data2.registration_id, user_data_list[1].first); + EXPECT_EQ("value_d1", user_data_list[1].second); + EXPECT_EQ(data2.registration_id, user_data_list[2].first); + EXPECT_EQ("value_d2", user_data_list[2].second); } TEST(ServiceWorkerDatabaseTest, UserData_DataIsolation) { @@ -1602,14 +1569,13 @@ // Write user data associated with the registration1. std::vector<std::string> user_data_out; ASSERT_EQ(ServiceWorkerDatabase::Status::kOk, - database->WriteUserData( - data1.registration_id, kOrigin, - CreateUserData(data1.registration_id, {{"key", "value1"}}))); + database->WriteUserData(data1.registration_id, kOrigin, + CreateUserData({{"key", "data1"}}))); EXPECT_EQ( ServiceWorkerDatabase::Status::kOk, database->ReadUserData(data1.registration_id, {"key"}, &user_data_out)); ASSERT_EQ(1u, user_data_out.size()); - EXPECT_EQ("value1", user_data_out[0]); + EXPECT_EQ("data1", user_data_out[0]); EXPECT_EQ( ServiceWorkerDatabase::Status::kErrorNotFound, database->ReadUserData(data2.registration_id, {"key"}, &user_data_out)); @@ -1617,31 +1583,28 @@ // Write user data associated with the registration2. This shouldn't overwrite // the data associated with registration1. ASSERT_EQ(ServiceWorkerDatabase::Status::kOk, - database->WriteUserData( - data2.registration_id, kOrigin, - CreateUserData(data2.registration_id, {{"key", "value2"}}))); + database->WriteUserData(data2.registration_id, kOrigin, + CreateUserData({{"key", "data2"}}))); EXPECT_EQ( ServiceWorkerDatabase::Status::kOk, database->ReadUserData(data1.registration_id, {"key"}, &user_data_out)); ASSERT_EQ(1u, user_data_out.size()); - EXPECT_EQ("value1", user_data_out[0]); + EXPECT_EQ("data1", user_data_out[0]); EXPECT_EQ( ServiceWorkerDatabase::Status::kOk, database->ReadUserData(data2.registration_id, {"key"}, &user_data_out)); ASSERT_EQ(1u, user_data_out.size()); - EXPECT_EQ("value2", user_data_out[0]); + EXPECT_EQ("data2", user_data_out[0]); // Get all registrations with user data. - std::vector<storage::mojom::ServiceWorkerUserDataPtr> user_data_list; + std::vector<std::pair<int64_t, std::string>> user_data_list; ASSERT_EQ(ServiceWorkerDatabase::Status::kOk, database->ReadUserDataForAllRegistrations("key", &user_data_list)); EXPECT_EQ(2u, user_data_list.size()); - EXPECT_EQ(data1.registration_id, user_data_list[0]->registration_id); - EXPECT_EQ("key", user_data_list[0]->key); - EXPECT_EQ("value1", user_data_list[0]->value); - EXPECT_EQ(data2.registration_id, user_data_list[1]->registration_id); - EXPECT_EQ("key", user_data_list[1]->key); - EXPECT_EQ("value2", user_data_list[1]->value); + EXPECT_EQ(data1.registration_id, user_data_list[0].first); + EXPECT_EQ("data1", user_data_list[0].second); + EXPECT_EQ(data2.registration_id, user_data_list[1].first); + EXPECT_EQ("data2", user_data_list[1].second); // Delete the data associated with the registration2. This shouldn't delete // the data associated with registration1. @@ -1651,7 +1614,7 @@ ServiceWorkerDatabase::Status::kOk, database->ReadUserData(data1.registration_id, {"key"}, &user_data_out)); ASSERT_EQ(1u, user_data_out.size()); - EXPECT_EQ("value1", user_data_out[0]); + EXPECT_EQ("data1", user_data_out[0]); EXPECT_EQ( ServiceWorkerDatabase::Status::kErrorNotFound, database->ReadUserData(data2.registration_id, {"key"}, &user_data_out)); @@ -1661,9 +1624,8 @@ ASSERT_EQ(ServiceWorkerDatabase::Status::kOk, database->ReadUserDataForAllRegistrations("key", &user_data_list)); EXPECT_EQ(1u, user_data_list.size()); - EXPECT_EQ(data1.registration_id, user_data_list[0]->registration_id); - EXPECT_EQ("key", user_data_list[0]->key); - EXPECT_EQ("value1", user_data_list[0]->value); + EXPECT_EQ(data1.registration_id, user_data_list[0].first); + EXPECT_EQ("data1", user_data_list[0].second); } TEST(ServiceWorkerDatabaseTest, UserData_DeleteRegistration) { @@ -1699,34 +1661,31 @@ // Write user data associated with the registration1. std::vector<std::string> user_data_out; ASSERT_EQ(ServiceWorkerDatabase::Status::kOk, - database->WriteUserData( - data1.registration_id, kOrigin, - CreateUserData(data1.registration_id, {{"key1", "value1"}}))); + database->WriteUserData(data1.registration_id, kOrigin, + CreateUserData({{"key1", "data1"}}))); ASSERT_EQ(ServiceWorkerDatabase::Status::kOk, - database->WriteUserData( - data1.registration_id, kOrigin, - CreateUserData(data1.registration_id, {{"key2", "value2"}}))); + database->WriteUserData(data1.registration_id, kOrigin, + CreateUserData({{"key2", "data2"}}))); ASSERT_EQ( ServiceWorkerDatabase::Status::kOk, database->ReadUserData(data1.registration_id, {"key1"}, &user_data_out)); ASSERT_EQ(1u, user_data_out.size()); - ASSERT_EQ("value1", user_data_out[0]); + ASSERT_EQ("data1", user_data_out[0]); ASSERT_EQ( ServiceWorkerDatabase::Status::kOk, database->ReadUserData(data1.registration_id, {"key2"}, &user_data_out)); ASSERT_EQ(1u, user_data_out.size()); - ASSERT_EQ("value2", user_data_out[0]); + ASSERT_EQ("data2", user_data_out[0]); // Write user data associated with the registration2. ASSERT_EQ(ServiceWorkerDatabase::Status::kOk, - database->WriteUserData( - data2.registration_id, kOrigin, - CreateUserData(data2.registration_id, {{"key3", "value3"}}))); + database->WriteUserData(data2.registration_id, kOrigin, + CreateUserData({{"key3", "data3"}}))); ASSERT_EQ( ServiceWorkerDatabase::Status::kOk, database->ReadUserData(data2.registration_id, {"key3"}, &user_data_out)); ASSERT_EQ(1u, user_data_out.size()); - ASSERT_EQ("value3", user_data_out[0]); + ASSERT_EQ("data3", user_data_out[0]); // Delete all data associated with the registration1. This shouldn't delete // the data associated with registration2. @@ -1743,7 +1702,7 @@ ServiceWorkerDatabase::Status::kOk, database->ReadUserData(data2.registration_id, {"key3"}, &user_data_out)); ASSERT_EQ(1u, user_data_out.size()); - EXPECT_EQ("value3", user_data_out[0]); + EXPECT_EQ("data3", user_data_out[0]); } TEST(ServiceWorkerDatabaseTest, UserData_UninitializedDatabase) { @@ -1756,9 +1715,9 @@ database->ReadUserData(100, {"key"}, &user_data_out)); // Should be failed because the associated registration does not exist. - EXPECT_EQ(ServiceWorkerDatabase::Status::kErrorNotFound, - database->WriteUserData(100, kOrigin, - CreateUserData(100, {{"key", "value"}}))); + EXPECT_EQ( + ServiceWorkerDatabase::Status::kErrorNotFound, + database->WriteUserData(100, kOrigin, CreateUserData({{"key", "data"}}))); // Deleting non-existent entry should succeed. EXPECT_EQ(ServiceWorkerDatabase::Status::kOk, @@ -1772,9 +1731,9 @@ database->state_); EXPECT_EQ(ServiceWorkerDatabase::Status::kErrorNotFound, database->ReadUserData(100, {"key"}, &user_data_out)); - EXPECT_EQ(ServiceWorkerDatabase::Status::kErrorNotFound, - database->WriteUserData(100, kOrigin, - CreateUserData(100, {{"key", "value"}}))); + EXPECT_EQ( + ServiceWorkerDatabase::Status::kErrorNotFound, + database->WriteUserData(100, kOrigin, CreateUserData({{"key", "data"}}))); // Deleting non-existent entry should succeed. EXPECT_EQ(ServiceWorkerDatabase::Status::kOk, @@ -1967,13 +1926,11 @@ ASSERT_EQ(ServiceWorkerDatabase::Status::kOk, database->WriteRegistration(data1, resources1, &deleted_version)); ASSERT_EQ(ServiceWorkerDatabase::Status::kOk, - database->WriteUserData( - data1.registration_id, origin1, - CreateUserData(data1.registration_id, {{"key1", "value1"}}))); + database->WriteUserData(data1.registration_id, origin1, + CreateUserData({{"key1", "data1"}}))); ASSERT_EQ(ServiceWorkerDatabase::Status::kOk, - database->WriteUserData( - data1.registration_id, origin1, - CreateUserData(data1.registration_id, {{"key2", "value2"}}))); + database->WriteUserData(data1.registration_id, origin1, + CreateUserData({{"key2", "data2"}}))); RegistrationData data2; data2.registration_id = 11; @@ -1988,13 +1945,11 @@ ASSERT_EQ(ServiceWorkerDatabase::Status::kOk, database->WriteRegistration(data2, resources2, &deleted_version)); ASSERT_EQ(ServiceWorkerDatabase::Status::kOk, - database->WriteUserData( - data2.registration_id, origin1, - CreateUserData(data2.registration_id, {{"key3", "value3"}}))); + database->WriteUserData(data2.registration_id, origin1, + CreateUserData({{"key3", "data3"}}))); ASSERT_EQ(ServiceWorkerDatabase::Status::kOk, - database->WriteUserData( - data2.registration_id, origin1, - CreateUserData(data2.registration_id, {{"key4", "value4"}}))); + database->WriteUserData(data2.registration_id, origin1, + CreateUserData({{"key4", "data4"}}))); // |origin2| has one registration (registration3). RegistrationData data3; @@ -2010,13 +1965,11 @@ ASSERT_EQ(ServiceWorkerDatabase::Status::kOk, database->WriteRegistration(data3, resources3, &deleted_version)); ASSERT_EQ(ServiceWorkerDatabase::Status::kOk, - database->WriteUserData( - data3.registration_id, origin2, - CreateUserData(data3.registration_id, {{"key5", "value5"}}))); + database->WriteUserData(data3.registration_id, origin2, + CreateUserData({{"key5", "data5"}}))); ASSERT_EQ(ServiceWorkerDatabase::Status::kOk, - database->WriteUserData( - data3.registration_id, origin2, - CreateUserData(data3.registration_id, {{"key6", "value6"}}))); + database->WriteUserData(data3.registration_id, origin2, + CreateUserData({{"key6", "data6"}}))); std::set<GURL> origins_to_delete; std::vector<int64_t> newly_purgeable_resources; @@ -2086,12 +2039,12 @@ ServiceWorkerDatabase::Status::kOk, database->ReadUserData(data3.registration_id, {"key5"}, &user_data_out)); ASSERT_EQ(1u, user_data_out.size()); - EXPECT_EQ("value5", user_data_out[0]); + EXPECT_EQ("data5", user_data_out[0]); EXPECT_EQ( ServiceWorkerDatabase::Status::kOk, database->ReadUserData(data3.registration_id, {"key6"}, &user_data_out)); ASSERT_EQ(1u, user_data_out.size()); - EXPECT_EQ("value6", user_data_out[0]); + EXPECT_EQ("data6", user_data_out[0]); } TEST(ServiceWorkerDatabaseTest, DestroyDatabase) {
diff --git a/content/browser/service_worker/service_worker_registry.cc b/content/browser/service_worker/service_worker_registry.cc index cb2a54b..6908880 100644 --- a/content/browser/service_worker/service_worker_registry.cc +++ b/content/browser/service_worker/service_worker_registry.cc
@@ -616,8 +616,8 @@ blink::ServiceWorkerStatusCode::kErrorFailed)); return; } - user_data.push_back(storage::mojom::ServiceWorkerUserData::New( - registration_id, kv.first, kv.second)); + user_data.push_back( + storage::mojom::ServiceWorkerUserData::New(kv.first, kv.second)); } GetRemoteStorageControl()->StoreUserData( @@ -708,7 +708,7 @@ return; } - GetRemoteStorageControl()->GetUserDataForAllRegistrations( + storage()->GetUserDataForAllRegistrations( key, base::BindOnce(&ServiceWorkerRegistry::DidGetUserDataForAllRegistrations, weak_factory_.GetWeakPtr(), std::move(callback))); @@ -726,7 +726,7 @@ return; } - GetRemoteStorageControl()->GetUserDataForAllRegistrationsByKeyPrefix( + storage()->GetUserDataForAllRegistrationsByKeyPrefix( key_prefix, base::BindOnce(&ServiceWorkerRegistry::DidGetUserDataForAllRegistrations, weak_factory_.GetWeakPtr(), std::move(callback))); @@ -1287,18 +1287,11 @@ void ServiceWorkerRegistry::DidGetUserDataForAllRegistrations( GetUserDataForAllRegistrationsCallback callback, - storage::mojom::ServiceWorkerDatabaseStatus status, - std::vector<storage::mojom::ServiceWorkerUserDataPtr> entries) { + const std::vector<std::pair<int64_t, std::string>>& user_data, + storage::mojom::ServiceWorkerDatabaseStatus status) { DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId()); - // TODO(crbug.com/1055677): Update call sites of - // GetUserDataForAllRegistrations so that we can avoid converting mojo struct - // to a pair. - std::vector<std::pair<int64_t, std::string>> user_data; if (status != storage::mojom::ServiceWorkerDatabaseStatus::kOk) ScheduleDeleteAndStartOver(); - for (auto& entry : entries) { - user_data.emplace_back(entry->registration_id, entry->value); - } std::move(callback).Run(user_data, DatabaseStatusToStatusCode(status)); }
diff --git a/content/browser/service_worker/service_worker_registry.h b/content/browser/service_worker/service_worker_registry.h index f6afb1e..2349bbdd 100644 --- a/content/browser/service_worker/service_worker_registry.h +++ b/content/browser/service_worker/service_worker_registry.h
@@ -337,8 +337,8 @@ storage::mojom::ServiceWorkerDatabaseStatus status); void DidGetUserDataForAllRegistrations( GetUserDataForAllRegistrationsCallback callback, - storage::mojom::ServiceWorkerDatabaseStatus status, - std::vector<storage::mojom::ServiceWorkerUserDataPtr> entries); + const std::vector<std::pair<int64_t, std::string>>& user_data, + storage::mojom::ServiceWorkerDatabaseStatus status); void DidGetNewRegistrationId( blink::mojom::ServiceWorkerRegistrationOptions options,
diff --git a/content/browser/service_worker/service_worker_storage.cc b/content/browser/service_worker/service_worker_storage.cc index c536cea..0fb0a953 100644 --- a/content/browser/service_worker/service_worker_storage.cc +++ b/content/browser/service_worker/service_worker_storage.cc
@@ -770,10 +770,9 @@ switch (state_) { case STORAGE_STATE_DISABLED: RunSoon(FROM_HERE, - base::BindOnce( - std::move(callback), - ServiceWorkerDatabase::Status::kErrorDisabled, - std::vector<storage::mojom::ServiceWorkerUserDataPtr>())); + base::BindOnce(std::move(callback), + std::vector<std::pair<int64_t, std::string>>(), + ServiceWorkerDatabase::Status::kErrorDisabled)); return; case STORAGE_STATE_INITIALIZING: // Fall-through. case STORAGE_STATE_UNINITIALIZED: @@ -802,10 +801,9 @@ switch (state_) { case STORAGE_STATE_DISABLED: RunSoon(FROM_HERE, - base::BindOnce( - std::move(callback), - ServiceWorkerDatabase::Status::kErrorDisabled, - std::vector<storage::mojom::ServiceWorkerUserDataPtr>())); + base::BindOnce(std::move(callback), + std::vector<std::pair<int64_t, std::string>>(), + ServiceWorkerDatabase::Status::kErrorDisabled)); return; case STORAGE_STATE_INITIALIZING: // Fall-through. case STORAGE_STATE_UNINITIALIZED: @@ -1593,12 +1591,11 @@ scoped_refptr<base::SequencedTaskRunner> original_task_runner, const std::string& key, GetUserDataForAllRegistrationsInDBCallback callback) { - std::vector<storage::mojom::ServiceWorkerUserDataPtr> user_data; + std::vector<std::pair<int64_t, std::string>> user_data; ServiceWorkerDatabase::Status status = database->ReadUserDataForAllRegistrations(key, &user_data); original_task_runner->PostTask( - FROM_HERE, - base::BindOnce(std::move(callback), status, std::move(user_data))); + FROM_HERE, base::BindOnce(std::move(callback), user_data, status)); } void ServiceWorkerStorage::GetUserDataForAllRegistrationsByKeyPrefixInDB( @@ -1606,13 +1603,12 @@ scoped_refptr<base::SequencedTaskRunner> original_task_runner, const std::string& key_prefix, GetUserDataForAllRegistrationsInDBCallback callback) { - std::vector<storage::mojom::ServiceWorkerUserDataPtr> user_data; + std::vector<std::pair<int64_t, std::string>> user_data; ServiceWorkerDatabase::Status status = database->ReadUserDataForAllRegistrationsByKeyPrefix(key_prefix, &user_data); original_task_runner->PostTask( - FROM_HERE, - base::BindOnce(std::move(callback), status, std::move(user_data))); + FROM_HERE, base::BindOnce(std::move(callback), user_data, status)); } void ServiceWorkerStorage::DeleteAllDataForOriginsFromDB(
diff --git a/content/browser/service_worker/service_worker_storage.h b/content/browser/service_worker/service_worker_storage.h index 4e0541c..532ad1e 100644 --- a/content/browser/service_worker/service_worker_storage.h +++ b/content/browser/service_worker/service_worker_storage.h
@@ -107,8 +107,8 @@ using GetUserKeysAndDataInDBCallback = storage::mojom:: ServiceWorkerStorageControl::GetUserKeysAndDataByKeyPrefixCallback; using GetUserDataForAllRegistrationsInDBCallback = base::OnceCallback<void( - ServiceWorkerDatabase::Status, - std::vector<storage::mojom::ServiceWorkerUserDataPtr>)>; + const std::vector<std::pair<int64_t, std::string>>& user_data, + ServiceWorkerDatabase::Status)>; ~ServiceWorkerStorage();
diff --git a/content/browser/service_worker/service_worker_storage_control_impl.cc b/content/browser/service_worker/service_worker_storage_control_impl.cc index 81c094d..8d68e304 100644 --- a/content/browser/service_worker/service_worker_storage_control_impl.cc +++ b/content/browser/service_worker/service_worker_storage_control_impl.cc
@@ -13,6 +13,20 @@ namespace { +void DidGetUserDataForAllRegistrations( + ServiceWorkerStorageControlImpl::GetUserDataForAllRegistrationsCallback + callback, + const std::vector<std::pair<int64_t, std::string>>& user_data, + storage::mojom::ServiceWorkerDatabaseStatus status) { + // TODO(bashi): Change ServiceWorkerStorage::GetUserDataForAllRegistrations() + // to return base::flat_map. + base::flat_map<int64_t, std::string> values; + for (auto& entry : user_data) { + values[entry.first] = entry.second; + } + std::move(callback).Run(status, std::move(values)); +} + void DidGetAllRegistrations( ServiceWorkerStorageControlImpl::GetAllRegistrationsDeprecatedCallback callback, @@ -335,14 +349,17 @@ void ServiceWorkerStorageControlImpl::GetUserDataForAllRegistrations( const std::string& key, GetUserDataForAllRegistrationsCallback callback) { - storage_->GetUserDataForAllRegistrations(key, std::move(callback)); + storage_->GetUserDataForAllRegistrations( + key, + base::BindOnce(&DidGetUserDataForAllRegistrations, std::move(callback))); } void ServiceWorkerStorageControlImpl::GetUserDataForAllRegistrationsByKeyPrefix( const std::string& key_prefix, GetUserDataForAllRegistrationsByKeyPrefixCallback callback) { - storage_->GetUserDataForAllRegistrationsByKeyPrefix(key_prefix, - std::move(callback)); + storage_->GetUserDataForAllRegistrationsByKeyPrefix( + key_prefix, + base::BindOnce(&DidGetUserDataForAllRegistrations, std::move(callback))); } void ServiceWorkerStorageControlImpl::
diff --git a/content/browser/service_worker/service_worker_storage_control_impl_unittest.cc b/content/browser/service_worker/service_worker_storage_control_impl_unittest.cc index ca11258..cb8fb095 100644 --- a/content/browser/service_worker/service_worker_storage_control_impl_unittest.cc +++ b/content/browser/service_worker/service_worker_storage_control_impl_unittest.cc
@@ -84,7 +84,7 @@ struct GetUserDataForAllRegistrationsResult { DatabaseStatus status; - std::vector<storage::mojom::ServiceWorkerUserDataPtr> values; + base::flat_map<int64_t, std::string> values; }; ReadResponseHeadResult ReadResponseHead( @@ -536,14 +536,13 @@ GetUserDataForAllRegistrationsResult result; base::RunLoop loop; storage()->GetUserDataForAllRegistrations( - key, - base::BindLambdaForTesting( - [&](DatabaseStatus status, - std::vector<storage::mojom::ServiceWorkerUserDataPtr> values) { - result.status = status; - result.values = std::move(values); - loop.Quit(); - })); + key, base::BindLambdaForTesting( + [&](DatabaseStatus status, + const base::flat_map<int64_t, std::string>& values) { + result.status = status; + result.values = values; + loop.Quit(); + })); loop.Run(); return result; } @@ -556,9 +555,9 @@ key_prefix, base::BindLambdaForTesting( [&](DatabaseStatus status, - std::vector<storage::mojom::ServiceWorkerUserDataPtr> values) { + const base::flat_map<int64_t, std::string>& values) { result.status = status; - result.values = std::move(values); + result.values = values; loop.Quit(); })); loop.Run(); @@ -1163,10 +1162,10 @@ // Store user data with two entries. { std::vector<storage::mojom::ServiceWorkerUserDataPtr> user_data; - user_data.push_back(storage::mojom::ServiceWorkerUserData::New( - registration_id, "key1", "value1")); - user_data.push_back(storage::mojom::ServiceWorkerUserData::New( - registration_id, "key2", "value2")); + user_data.push_back( + storage::mojom::ServiceWorkerUserData::New("key1", "value1")); + user_data.push_back( + storage::mojom::ServiceWorkerUserData::New("key2", "value2")); status = StoreUserData(registration_id, kScope.GetOrigin(), std::move(user_data)); @@ -1253,14 +1252,14 @@ // Store some user data with prefixes. std::vector<storage::mojom::ServiceWorkerUserDataPtr> user_data; - user_data.push_back(storage::mojom::ServiceWorkerUserData::New( - registration_id, "prefixA", "value1")); - user_data.push_back(storage::mojom::ServiceWorkerUserData::New( - registration_id, "prefixA2", "value2")); - user_data.push_back(storage::mojom::ServiceWorkerUserData::New( - registration_id, "prefixB", "value3")); - user_data.push_back(storage::mojom::ServiceWorkerUserData::New( - registration_id, "prefixC", "value4")); + user_data.push_back( + storage::mojom::ServiceWorkerUserData::New("prefixA", "value1")); + user_data.push_back( + storage::mojom::ServiceWorkerUserData::New("prefixA2", "value2")); + user_data.push_back( + storage::mojom::ServiceWorkerUserData::New("prefixB", "value3")); + user_data.push_back( + storage::mojom::ServiceWorkerUserData::New("prefixC", "value4")); status = StoreUserData(registration_id, kScope.GetOrigin(), std::move(user_data)); ASSERT_EQ(status, DatabaseStatus::kOk); @@ -1341,11 +1340,11 @@ { std::vector<storage::mojom::ServiceWorkerUserDataPtr> user_data; user_data.push_back(storage::mojom::ServiceWorkerUserData::New( - registration_id1, "key1", "registration1_value1")); + "key1", "registration1_value1")); user_data.push_back(storage::mojom::ServiceWorkerUserData::New( - registration_id1, "key2", "registration1_value2")); + "key2", "registration1_value2")); user_data.push_back(storage::mojom::ServiceWorkerUserData::New( - registration_id1, "prefix1", "registration1_prefix_value1")); + "prefix1", "registration1_prefix_value1")); status = StoreUserData(registration_id1, kScope1.GetOrigin(), std::move(user_data)); ASSERT_EQ(status, DatabaseStatus::kOk); @@ -1353,11 +1352,11 @@ { std::vector<storage::mojom::ServiceWorkerUserDataPtr> user_data; user_data.push_back(storage::mojom::ServiceWorkerUserData::New( - registration_id1, "key1", "registration2_value1")); + "key1", "registration2_value1")); user_data.push_back(storage::mojom::ServiceWorkerUserData::New( - registration_id1, "key3", "registration2_value3")); + "key3", "registration2_value3")); user_data.push_back(storage::mojom::ServiceWorkerUserData::New( - registration_id1, "prefix2", "registration2_prefix_value2")); + "prefix2", "registration2_prefix_value2")); status = StoreUserData(registration_id2, kScope2.GetOrigin(), std::move(user_data)); ASSERT_EQ(status, DatabaseStatus::kOk); @@ -1368,23 +1367,19 @@ result = GetUserDataForAllRegistrations("key1"); ASSERT_EQ(result.status, DatabaseStatus::kOk); ASSERT_EQ(result.values.size(), 2UL); - EXPECT_EQ(result.values[0]->registration_id, registration_id1); - EXPECT_EQ(result.values[0]->value, "registration1_value1"); - EXPECT_EQ(result.values[1]->registration_id, registration_id2); - EXPECT_EQ(result.values[1]->value, "registration2_value1"); + EXPECT_EQ(result.values[registration_id1], "registration1_value1"); + EXPECT_EQ(result.values[registration_id2], "registration2_value1"); // Get uncommon user data. result = GetUserDataForAllRegistrations("key2"); ASSERT_EQ(result.status, DatabaseStatus::kOk); ASSERT_EQ(result.values.size(), 1UL); - EXPECT_EQ(result.values[0]->registration_id, registration_id1); - EXPECT_EQ(result.values[0]->value, "registration1_value2"); + EXPECT_EQ(result.values[registration_id1], "registration1_value2"); result = GetUserDataForAllRegistrations("key3"); ASSERT_EQ(result.status, DatabaseStatus::kOk); ASSERT_EQ(result.values.size(), 1UL); - EXPECT_EQ(result.values[0]->registration_id, registration_id2); - EXPECT_EQ(result.values[0]->value, "registration2_value3"); + EXPECT_EQ(result.values[registration_id2], "registration2_value3"); // Getting unknown key succeeds but returns an empty value. // TODO(bashi): Make sure this is an intentional behavior. The existing @@ -1400,17 +1395,14 @@ result = GetUserDataForAllRegistrations("key1"); ASSERT_EQ(result.status, DatabaseStatus::kOk); ASSERT_EQ(result.values.size(), 1UL); - EXPECT_EQ(result.values[0]->registration_id, registration_id2); - EXPECT_EQ(result.values[0]->value, "registration2_value1"); + EXPECT_EQ(result.values[registration_id2], "registration2_value1"); // Get prefixed user data. result = GetUserDataForAllRegistrationsByKeyPrefix("prefix"); ASSERT_EQ(result.status, DatabaseStatus::kOk); ASSERT_EQ(result.values.size(), 2UL); - EXPECT_EQ(result.values[0]->registration_id, registration_id1); - EXPECT_EQ(result.values[0]->value, "registration1_prefix_value1"); - EXPECT_EQ(result.values[1]->registration_id, registration_id2); - EXPECT_EQ(result.values[1]->value, "registration2_prefix_value2"); + EXPECT_EQ(result.values[registration_id1], "registration1_prefix_value1"); + EXPECT_EQ(result.values[registration_id2], "registration2_prefix_value2"); // Clear prefixed user data. status = ClearUserDataForAllRegistrationsByKeyPrefix("prefix");
diff --git a/content/public/android/java/src/org/chromium/content/browser/JavascriptInjectorImpl.java b/content/public/android/java/src/org/chromium/content/browser/JavascriptInjectorImpl.java index 7916f055..e09218b 100644 --- a/content/public/android/java/src/org/chromium/content/browser/JavascriptInjectorImpl.java +++ b/content/public/android/java/src/org/chromium/content/browser/JavascriptInjectorImpl.java
@@ -10,6 +10,7 @@ import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; import org.chromium.base.annotations.NativeMethods; +import org.chromium.content.browser.remoteobjects.RemoteObjectInjector; import org.chromium.content.browser.webcontents.WebContentsImpl; import org.chromium.content.browser.webcontents.WebContentsImpl.UserDataFactory; import org.chromium.content_public.browser.JavascriptInjector; @@ -34,20 +35,37 @@ private final Set<Object> mRetainedObjects = new HashSet<>(); private final Map<String, Pair<Object, Class>> mInjectedObjects = new HashMap<>(); private long mNativePtr; + private RemoteObjectInjector mInjector; + private Boolean mUseMojo; /** * @param webContents {@link WebContents} object. + * @param useMojo Whether to use {@link RemoteObjectInjector} methods * @return {@link JavascriptInjector} object used for the give WebContents. * Creates one if not present. */ - public static JavascriptInjector fromWebContents(WebContents webContents) { - return ((WebContentsImpl) webContents) - .getOrSetUserData(JavascriptInjectorImpl.class, UserDataFactoryLazyHolder.INSTANCE); + public static JavascriptInjector fromWebContents(WebContents webContents, boolean useMojo) { + JavascriptInjectorImpl javascriptInjector = + ((WebContentsImpl) webContents) + .getOrSetUserData( + JavascriptInjectorImpl.class, UserDataFactoryLazyHolder.INSTANCE); + javascriptInjector.setUseMojo(useMojo); + return javascriptInjector; } public JavascriptInjectorImpl(WebContents webContents) { mNativePtr = JavascriptInjectorImplJni.get().init( JavascriptInjectorImpl.this, webContents, mRetainedObjects); + mInjector = new RemoteObjectInjector(webContents); + webContents.addObserver(mInjector); + } + + public void setUseMojo(boolean useMojo) { + if (mUseMojo == null) { + mUseMojo = useMojo; + } else { + assert mUseMojo == useMojo; + } } @CalledByNative @@ -62,15 +80,21 @@ @Override public void setAllowInspection(boolean allow) { - if (mNativePtr != 0) + if (mNativePtr != 0) { JavascriptInjectorImplJni.get().setAllowInspection( mNativePtr, JavascriptInjectorImpl.this, allow); + } } @Override public void addPossiblyUnsafeInterface( Object object, String name, Class<? extends Annotation> requiredAnnotation) { - if (mNativePtr != 0 && object != null) { + if (object == null) return; + + assert mUseMojo != null; + if (mUseMojo) { + mInjector.addInterface(object, name); + } else if (mNativePtr != 0) { mInjectedObjects.put(name, new Pair<Object, Class>(object, requiredAnnotation)); JavascriptInjectorImplJni.get().addInterface( mNativePtr, JavascriptInjectorImpl.this, object, name, requiredAnnotation); @@ -80,9 +104,10 @@ @Override public void removeInterface(String name) { mInjectedObjects.remove(name); - if (mNativePtr != 0) + if (mNativePtr != 0) { JavascriptInjectorImplJni.get().removeInterface( mNativePtr, JavascriptInjectorImpl.this, name); + } } @NativeMethods
diff --git a/content/public/android/java/src/org/chromium/content_public/browser/JavascriptInjector.java b/content/public/android/java/src/org/chromium/content_public/browser/JavascriptInjector.java index 9d37f1ac..8f71faf7 100644 --- a/content/public/android/java/src/org/chromium/content_public/browser/JavascriptInjector.java +++ b/content/public/android/java/src/org/chromium/content_public/browser/JavascriptInjector.java
@@ -22,7 +22,17 @@ * Creates one if not present. */ static JavascriptInjector fromWebContents(WebContents webContents) { - return JavascriptInjectorImpl.fromWebContents(webContents); + return fromWebContents(webContents, false); + } + + /** + * @param webContents {@link WebContents} object. + * @param useMojo Whether to use {@link RemoteObjectInjector} methods + * @return {@link JavascriptInjector} object used for the give WebContents. + * Creates one if not present. + */ + static JavascriptInjector fromWebContents(WebContents webContents, boolean useMojo) { + return JavascriptInjectorImpl.fromWebContents(webContents, useMojo); } /**
diff --git a/content/public/browser/native_file_system_permission_context.h b/content/public/browser/native_file_system_permission_context.h index af40f0e..15653e24 100644 --- a/content/public/browser/native_file_system_permission_context.h +++ b/content/public/browser/native_file_system_permission_context.h
@@ -24,8 +24,9 @@ // use to automatically grant write access to the path. enum class UserAction { // The path for which a permission grant is requested was the result of a - // "open" dialog, and as such the grant should probably not start out as - // granted. + // "open" dialog. As such, only read access to files should be automatically + // granted, but read access to directories as well as write access to files + // or directories should not be granted without needing to request it. kOpen, // The path for which a permission grant is requested was the result of a // "save" dialog, and as such it could make sense to return a grant that @@ -35,6 +36,10 @@ // loading a handle from storage. As such the grant should not start out // as granted, even for read access. kLoadFromStorage, + // The path for which a permission grant is requested was the result of a + // drag&drop operation. Read access should start out granted, but write + // access will require a prompt. + kDragAndDrop, }; // This enum helps distinguish between file or directory Native File System @@ -87,6 +92,11 @@ GlobalFrameRoutingId frame_id, base::OnceCallback<void(AfterWriteCheckResult)> callback) = 0; + // Returns whether the give |origin| already allows read permission, or it is + // possible to request one. This is used to block file dialogs from being + // shown if permission won't be granted anyway. + virtual bool CanObtainReadPermission(const url::Origin& origin) = 0; + // Returns whether the give |origin| already allows write permission, or it is // possible to request one. This is used to block save file dialogs from being // shown if there is no need to ask for it.
diff --git a/content/public/browser/web_contents_delegate.cc b/content/public/browser/web_contents_delegate.cc index 5631ce9..3c009a7 100644 --- a/content/public/browser/web_contents_delegate.cc +++ b/content/public/browser/web_contents_delegate.cc
@@ -341,6 +341,13 @@ return portal_contents; } +void WebContentsDelegate::UpdateInspectedWebContentsIfNecessary( + WebContents* old_contents, + WebContents* new_contents, + base::OnceCallback<void()> callback) { + std::move(callback).Run(); +} + bool WebContentsDelegate::ShouldShowStaleContentOnEviction( WebContents* source) { return false;
diff --git a/content/public/browser/web_contents_delegate.h b/content/public/browser/web_contents_delegate.h index 61ed37a5..61f786b 100644 --- a/content/public/browser/web_contents_delegate.h +++ b/content/public/browser/web_contents_delegate.h
@@ -712,6 +712,15 @@ WebContents* predecessor_contents, std::unique_ptr<WebContents> portal_contents); + // If |old_contents| is being inspected by a DevTools window, it updates the + // window to inspect |new_contents| instead and calls |callback| after it + // finishes asynchronously. If no window is present, or no update is + // necessary, |callback| is run synchronously (immediately on the same stack). + virtual void UpdateInspectedWebContentsIfNecessary( + WebContents* old_contents, + WebContents* new_contents, + base::OnceCallback<void()> callback); + // Returns true if the widget's frame content needs to be stored before // eviction and displayed until a new frame is generated. If false, a white // solid color is displayed instead.
diff --git a/content/shell/browser/shell.cc b/content/shell/browser/shell.cc index b2ea0f0..88fa09bd 100644 --- a/content/shell/browser/shell.cc +++ b/content/shell/browser/shell.cc
@@ -600,11 +600,6 @@ DCHECK_EQ(predecessor_contents, web_contents_.get()); portal_contents->SetDelegate(this); web_contents_->SetDelegate(nullptr); - for (auto* shell_devtools_bindings : - ShellDevToolsBindings::GetInstancesForWebContents( - predecessor_contents)) { - shell_devtools_bindings->UpdateInspectedWebContents(portal_contents.get()); - } std::swap(web_contents_, portal_contents); g_platform->SetContents(this); g_platform->SetAddressBarURL(this, web_contents_->GetVisibleURL()); @@ -612,6 +607,34 @@ return portal_contents; } +namespace { +class PendingCallback : public base::RefCounted<PendingCallback> { + public: + explicit PendingCallback(base::OnceCallback<void()> cb) + : callback_(std::move(cb)) {} + + private: + friend class base::RefCounted<PendingCallback>; + ~PendingCallback() { std::move(callback_).Run(); } + base::OnceCallback<void()> callback_; +}; +} // namespace + +void Shell::UpdateInspectedWebContentsIfNecessary( + content::WebContents* old_contents, + content::WebContents* new_contents, + base::OnceCallback<void()> callback) { + scoped_refptr<PendingCallback> pending_callback = + base::MakeRefCounted<PendingCallback>(std::move(callback)); + for (auto* shell_devtools_bindings : + ShellDevToolsBindings::GetInstancesForWebContents(old_contents)) { + shell_devtools_bindings->UpdateInspectedWebContents( + new_contents, + base::BindOnce(base::DoNothing::Once<scoped_refptr<PendingCallback>>(), + pending_callback)); + } +} + bool Shell::ShouldAllowRunningInsecureContent(WebContents* web_contents, bool allowed_per_prefs, const url::Origin& origin,
diff --git a/content/shell/browser/shell.h b/content/shell/browser/shell.h index 1c0ce7d5..871f642f 100644 --- a/content/shell/browser/shell.h +++ b/content/shell/browser/shell.h
@@ -161,9 +161,14 @@ RenderWidgetHost* render_widget_host, base::RepeatingClosure hang_monitor_restarter) override; void ActivateContents(WebContents* contents) override; + std::unique_ptr<content::WebContents> ActivatePortalWebContents( content::WebContents* predecessor_contents, std::unique_ptr<content::WebContents> portal_contents) override; + void UpdateInspectedWebContentsIfNecessary( + content::WebContents* old_contents, + content::WebContents* new_contents, + base::OnceCallback<void()> callback) override; bool ShouldAllowRunningInsecureContent(content::WebContents* web_contents, bool allowed_per_prefs, const url::Origin& origin,
diff --git a/content/shell/browser/shell_devtools_bindings.cc b/content/shell/browser/shell_devtools_bindings.cc index e52411eb..d939f35 100644 --- a/content/shell/browser/shell_devtools_bindings.cc +++ b/content/shell/browser/shell_devtools_bindings.cc
@@ -234,13 +234,17 @@ } void ShellDevToolsBindings::UpdateInspectedWebContents( - WebContents* new_contents) { + WebContents* new_contents, + base::OnceCallback<void()> callback) { inspected_contents_ = new_contents; if (!agent_host_) return; AttachInternal(); - CallClientFunction("DevToolsAPI.reattachMainTarget", nullptr, nullptr, - nullptr); + CallClientFunction( + "DevToolsAPI.reattachMainTarget", nullptr, nullptr, nullptr, + base::BindOnce([](base::OnceCallback<void()> callback, + base::Value) { std::move(callback).Run(); }, + std::move(callback))); } void ShellDevToolsBindings::WebContentsDestroyed() { @@ -405,10 +409,12 @@ } } -void ShellDevToolsBindings::CallClientFunction(const std::string& function_name, - const base::Value* arg1, - const base::Value* arg2, - const base::Value* arg3) { +void ShellDevToolsBindings::CallClientFunction( + const std::string& function_name, + const base::Value* arg1, + const base::Value* arg2, + const base::Value* arg3, + base::OnceCallback<void(base::Value)> cb) { std::string javascript = function_name + "("; if (arg1) { std::string json; @@ -425,7 +431,7 @@ } javascript.append(");"); web_contents()->GetMainFrame()->ExecuteJavaScriptForTests( - base::UTF8ToUTF16(javascript), base::NullCallback()); + base::UTF8ToUTF16(javascript), std::move(cb)); } void ShellDevToolsBindings::SendMessageAck(int request_id,
diff --git a/content/shell/browser/shell_devtools_bindings.h b/content/shell/browser/shell_devtools_bindings.h index 09c3b6f..6d9c5394 100644 --- a/content/shell/browser/shell_devtools_bindings.h +++ b/content/shell/browser/shell_devtools_bindings.h
@@ -51,12 +51,15 @@ void InspectElementAt(int x, int y); virtual void Attach(); - void UpdateInspectedWebContents(WebContents* new_contents); + void UpdateInspectedWebContents(WebContents* new_contents, + base::OnceCallback<void()> callback); - void CallClientFunction(const std::string& function_name, - const base::Value* arg1, - const base::Value* arg2, - const base::Value* arg3); + void CallClientFunction( + const std::string& function_name, + const base::Value* arg1, + const base::Value* arg2, + const base::Value* arg3, + base::OnceCallback<void(base::Value)> cb = base::NullCallback()); ~ShellDevToolsBindings() override; WebContents* inspected_contents() { return inspected_contents_; }
diff --git a/infra/config/generated/cr-buildbucket.cfg b/infra/config/generated/cr-buildbucket.cfg index dc5b3c1..f5791db 100644 --- a/infra/config/generated/cr-buildbucket.cfg +++ b/infra/config/generated/cr-buildbucket.cfg
@@ -11620,6 +11620,34 @@ } } builders { + name: "win-omaha-builder-rel" + swarming_host: "chromium-swarm.appspot.com" + swarming_tags: "vpython:native-python-wrapper" + dimensions: "builder:win-omaha-builder-rel" + dimensions: "cores:8" + dimensions: "cpu:x86-64" + dimensions: "os:Windows-10" + dimensions: "pool:luci.chromium.ci" + exe { + cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" + cipd_version: "refs/heads/master" + cmd: "recipes" + } + properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"mastername\":\"chromium.fyi\",\"recipe\":\"chromium\"}" + execution_timeout_secs: 36000 + build_numbers: YES + service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" + resultdb { + enable: true + bq_exports { + project: "luci-resultdb" + dataset: "chromium" + table: "ci_test_results" + test_results {} + } + } + } + builders { name: "win-pixel-builder-rel" swarming_host: "chromium-swarm.appspot.com" swarming_tags: "vpython:native-python-wrapper" @@ -11936,6 +11964,34 @@ } } builders { + name: "win10-omaha-tester-rel" + swarming_host: "chromium-swarm.appspot.com" + swarming_tags: "vpython:native-python-wrapper" + dimensions: "builder:win10-omaha-tester-rel" + dimensions: "cores:8" + dimensions: "cpu:x86-64" + dimensions: "os:Windows-10" + dimensions: "pool:luci.chromium.ci" + exe { + cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" + cipd_version: "refs/heads/master" + cmd: "recipes" + } + properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"mastername\":\"chromium.fyi\",\"recipe\":\"chromium\"}" + execution_timeout_secs: 36000 + build_numbers: YES + service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" + resultdb { + enable: true + bq_exports { + project: "luci-resultdb" + dataset: "chromium" + table: "ci_test_results" + test_results {} + } + } + } + builders { name: "win32-archive-dbg" swarming_host: "chromium-swarm.appspot.com" swarming_tags: "vpython:native-python-wrapper"
diff --git a/infra/config/generated/luci-milo.cfg b/infra/config/generated/luci-milo.cfg index 24b6ae9..911222b81 100644 --- a/infra/config/generated/luci-milo.cfg +++ b/infra/config/generated/luci-milo.cfg
@@ -8295,6 +8295,10 @@ category: "win10" } builders { + name: "buildbucket/luci.chromium.ci/win-omaha-builder-rel" + category: "win10" + } + builders { name: "buildbucket/luci.chromium.ci/win-pixel-builder-rel" category: "win10" } @@ -8303,6 +8307,10 @@ category: "win10" } builders { + name: "buildbucket/luci.chromium.ci/win10-omaha-tester-rel" + category: "win10" + } + builders { name: "buildbucket/luci.chromium.ci/Win10 Tests x64 1803" category: "win10|1803" }
diff --git a/infra/config/generated/luci-scheduler.cfg b/infra/config/generated/luci-scheduler.cfg index 59e3dc78..64b4b5ba 100644 --- a/infra/config/generated/luci-scheduler.cfg +++ b/infra/config/generated/luci-scheduler.cfg
@@ -11224,6 +11224,16 @@ } } job { + id: "ci-win-omaha-builder-rel" + realm: "ci" + acl_sets: "ci" + buildbucket { + server: "cr-buildbucket.appspot.com" + bucket: "luci.chromium.ci" + builder: "win-omaha-builder-rel" + } +} +job { id: "ci-win-pixel-builder-rel" realm: "ci" acl_sets: "ci" @@ -11328,6 +11338,20 @@ } } job { + id: "ci-win10-omaha-tester-rel" + realm: "ci" + acls { + role: TRIGGERER + granted_to: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" + } + acl_sets: "ci" + buildbucket { + server: "cr-buildbucket.appspot.com" + bucket: "luci.chromium.ci" + builder: "win10-omaha-tester-rel" + } +} +job { id: "ci-win32-archive-dbg" realm: "ci" acl_sets: "ci" @@ -12325,6 +12349,16 @@ } } job { + id: "win-omaha-builder-rel" + realm: "ci" + acl_sets: "ci" + buildbucket { + server: "cr-buildbucket.appspot.com" + bucket: "luci.chromium.ci" + builder: "win-omaha-builder-rel" + } +} +job { id: "win-pixel-builder-rel" realm: "ci" acl_sets: "ci" @@ -12440,6 +12474,20 @@ } } job { + id: "win10-omaha-tester-rel" + realm: "ci" + acls { + role: TRIGGERER + granted_to: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" + } + acl_sets: "ci" + buildbucket { + server: "cr-buildbucket.appspot.com" + bucket: "luci.chromium.ci" + builder: "win10-omaha-tester-rel" + } +} +job { id: "win32-archive-dbg" realm: "ci" acl_sets: "ci" @@ -13020,6 +13068,7 @@ triggers: "win-archive-rel" triggers: "win-asan" triggers: "win-official" + triggers: "win-omaha-builder-rel" triggers: "win-pixel-builder-rel" triggers: "win-swangle-chromium-x86" triggers: "win-swangle-tot-angle-x64"
diff --git a/infra/config/subprojects/chromium/master-only/ci.star b/infra/config/subprojects/chromium/master-only/ci.star index 2ff67c92..ea2728d 100644 --- a/infra/config/subprojects/chromium/master-only/ci.star +++ b/infra/config/subprojects/chromium/master-only/ci.star
@@ -1621,6 +1621,24 @@ ) ci.fyi_builder( + name = "win-omaha-builder-rel", + console_view_entry = ci.console_view_entry( + category = "win10", + ), + os = os.WINDOWS_DEFAULT, + cpu = cpu.X86_64, +) + +ci.fyi_builder( + name = "win10-omaha-tester-rel", + console_view_entry = ci.console_view_entry( + category = "win10", + ), + os = os.WINDOWS_10, + triggered_by = ["win-omaha-builder-rel"], +) + +ci.fyi_builder( name = "win-pixel-builder-rel", console_view_entry = ci.console_view_entry( category = "win10",
diff --git a/ios/chrome/browser/flags/about_flags.mm b/ios/chrome/browser/flags/about_flags.mm index 7924e9dc..c17988f 100644 --- a/ios/chrome/browser/flags/about_flags.mm +++ b/ios/chrome/browser/flags/about_flags.mm
@@ -708,6 +708,9 @@ web::BuildMobileUserAgent(product)); } + // Shared policy dictionary for all enterprise experimental flags. + NSMutableDictionary* testing_policies = [[NSMutableDictionary alloc] init]; + // Set some sample policy values for testing if EnableSamplePolicies is // enabled. if ([defaults boolForKey:@"EnableSamplePolicies"]) { @@ -726,7 +729,7 @@ ]; // Define sample policies to enable. - NSDictionary* testing_policies = @{ + [testing_policies addEntriesFromDictionary:@{ base::SysUTF8ToNSString(policy::key::kEnableExperimentalPolicies) : experimental_policies, @@ -751,7 +754,22 @@ base::SysUTF8ToNSString(policy::key::kPasswordManagerEnabled) : @NO, base::SysUTF8ToNSString(policy::key::kTranslateEnabled) : @NO, - }; + }]; + } + + // If a CBCM enrollment token is provided, force Chrome Browser Cloud + // Management to enabled and add the token to the list of policies. + NSString* token_key = + base::SysUTF8ToNSString(policy::key::kCloudManagementEnrollmentToken); + NSString* token = [defaults stringForKey:token_key]; + + if ([token length] > 0) { + command_line->AppendSwitch(switches::kEnableChromeBrowserCloudManagement); + [testing_policies setValue:token forKey:token_key]; + } + + // If some policies were set, commit them to the app's registration defaults. + if ([testing_policies count] > 0) { NSDictionary* registration_defaults = @{kPolicyLoaderIOSConfigurationKey : testing_policies}; [defaults registerDefaults:registration_defaults];
diff --git a/ios/chrome/browser/metrics/ukm_egtest.mm b/ios/chrome/browser/metrics/ukm_egtest.mm index b8045ba4..3162de7 100644 --- a/ios/chrome/browser/metrics/ukm_egtest.mm +++ b/ios/chrome/browser/metrics/ukm_egtest.mm
@@ -6,7 +6,6 @@ #include "base/macros.h" #import "ios/chrome/browser/metrics/metrics_app_interface.h" #import "ios/chrome/browser/ui/authentication/signin_earl_grey.h" -#import "ios/chrome/browser/ui/authentication/signin_earl_grey_app_interface.h" #import "ios/chrome/browser/ui/authentication/signin_earl_grey_ui.h" #import "ios/chrome/test/earl_grey/chrome_actions.h" #import "ios/chrome/test/earl_grey/chrome_earl_grey.h" @@ -93,9 +92,7 @@ // Note: URL-keyed anonymized data collection is turned off as part of the // flow to Sign out of Chrome and Turn sync off. This matches the main user // flow that disables UKM. - if (![SigninEarlGreyAppInterface isSignedOut]) { - [SigninEarlGreyAppInterface signOut]; - } + [SigninEarlGrey signOut]; [ChromeEarlGrey waitForSyncInitialized:NO syncTimeout:syncher::kSyncUKMOperationsTimeout]; @@ -274,7 +271,7 @@ // Corresponds to ConsentAddedButNoSyncCheck in //chrome/browser/metrics/ // ukm_browsertest.cc. - (void)testConsentAddedButNoSync { - [SigninEarlGreyAppInterface signOut]; + [SigninEarlGrey signOut]; [MetricsAppInterface setMetricsAndCrashReportingForTesting:NO]; GREYAssert([MetricsAppInterface checkUKMRecordingEnabled:NO], @"Failed to assert that UKM was not enabled."); @@ -347,7 +344,7 @@ #endif const uint64_t clientID1 = [MetricsAppInterface UKMClientID]; - [SigninEarlGreyAppInterface signOut]; + [SigninEarlGrey signOut]; GREYAssert([MetricsAppInterface checkUKMRecordingEnabled:NO], @"Failed to assert that UKM was not enabled.");
diff --git a/ios/chrome/browser/overlays/public/infobar_banner/save_password_infobar_banner_overlay.mm b/ios/chrome/browser/overlays/public/infobar_banner/save_password_infobar_banner_overlay.mm index 2ffe3ec..c746a681 100644 --- a/ios/chrome/browser/overlays/public/infobar_banner/save_password_infobar_banner_overlay.mm +++ b/ios/chrome/browser/overlays/public/infobar_banner/save_password_infobar_banner_overlay.mm
@@ -19,7 +19,7 @@ namespace { // The name of the icon image for the save passwords banner. -NSString* const kIconImageName = @"infobar_passwords_icon"; +NSString* const kIconImageName = @"password_key"; } OVERLAY_USER_DATA_SETUP_IMPL(SavePasswordInfobarBannerOverlayRequestConfig);
diff --git a/ios/chrome/browser/resources/Settings.bundle/Experimental.plist b/ios/chrome/browser/resources/Settings.bundle/Experimental.plist index eb674c8..eb67d4e5 100644 --- a/ios/chrome/browser/resources/Settings.bundle/Experimental.plist +++ b/ios/chrome/browser/resources/Settings.bundle/Experimental.plist
@@ -132,6 +132,12 @@ </dict> <dict> <key>Type</key> + <string>PSGroupSpecifier</string> + <key>Title</key> + <string>Enterprise Settings</string> + </dict> + <dict> + <key>Type</key> <string>PSToggleSwitchSpecifier</string> <key>Title</key> <string>Enable Sample Policies</string> @@ -142,6 +148,18 @@ </dict> <dict> <key>Type</key> + <string>PSTextFieldSpecifier</string> + <key>Title</key> + <string>CBCM Enrollment Token</string> + <key>Key</key> + <string>CloudManagementEnrollmentToken</string> + <key>DefaultValue</key> + <string></string> + <key>AutocorrectionType</key> + <string>No</string> + </dict> + <dict> + <key>Type</key> <string>PSGroupSpecifier</string> <key>Title</key> <string>Google App Ecosystem</string>
diff --git a/ios/chrome/browser/translate/BUILD.gn b/ios/chrome/browser/translate/BUILD.gn index 003e6fb..3ddba5a 100644 --- a/ios/chrome/browser/translate/BUILD.gn +++ b/ios/chrome/browser/translate/BUILD.gn
@@ -108,38 +108,6 @@ ] } -source_set("eg2_tests") { - defines = [ "CHROME_EARL_GREY_2" ] - configs += [ - "//build/config/compiler:enable_arc", - "//build/config/ios:xctest_config", - ] - testonly = true - sources = [ "translate_egtest.mm" ] - deps = [ - ":eg_test_support+eg2", - "//base/test:test_support", - "//components/strings:components_strings_grit", - "//components/translate/core/browser:browser", - "//components/translate/core/common:common", - "//ios/chrome/app/strings:ios_strings_grit", - "//ios/chrome/browser:chrome_url_constants", - "//ios/chrome/browser/ui/infobars:feature_flags", - "//ios/chrome/browser/ui/popup_menu:constants", - "//ios/chrome/browser/ui/translate:legacy_translate_constants", - "//ios/chrome/browser/ui/translate:translate_ui_constants", - "//ios/chrome/test/earl_grey:eg_test_support+eg2", - "//ios/components/webui:url_constants", - "//ios/testing/earl_grey:eg_test_support+eg2", - "//ios/third_party/earl_grey2:test_lib", - "//ios/web/public:public", - "//ios/web/public/test/http_server:http_server", - "//ui/base:base", - "//url:url", - ] - frameworks = [ "UIKit.framework" ] -} - source_set("test_support") { testonly = true sources = [
diff --git a/ios/chrome/browser/translate/translate_egtest.mm b/ios/chrome/browser/translate/translate_egtest.mm deleted file mode 100644 index 67dbff28..0000000 --- a/ios/chrome/browser/translate/translate_egtest.mm +++ /dev/null
@@ -1,1750 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import <XCTest/XCTest.h> - -#include <memory> -#include <string> - -#include "base/strings/stringprintf.h" -#include "base/strings/sys_string_conversions.h" -#include "base/strings/utf_string_conversions.h" -#import "base/test/ios/wait_util.h" -#include "components/strings/grit/components_strings.h" -#include "components/translate/core/browser/translate_pref_names.h" -#include "components/translate/core/common/translate_constants.h" -#include "ios/chrome/browser/chrome_url_constants.h" -#import "ios/chrome/browser/translate/translate_app_interface.h" -#import "ios/chrome/browser/ui/infobars/infobar_feature.h" -#import "ios/chrome/browser/ui/popup_menu/popup_menu_constants.h" -#import "ios/chrome/browser/ui/translate/legacy_translate_infobar_constants.h" -#import "ios/chrome/browser/ui/translate/translate_infobar_view_constants.h" -#include "ios/chrome/grit/ios_strings.h" -#import "ios/chrome/test/earl_grey/chrome_earl_grey.h" -#import "ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.h" -#import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h" -#import "ios/chrome/test/earl_grey/chrome_matchers.h" -#import "ios/chrome/test/earl_grey/chrome_test_case.h" -#include "ios/components/webui/web_ui_url_constants.h" -#import "ios/testing/earl_grey/earl_grey_test.h" -#include "ios/web/public/test/http_server/data_response_provider.h" -#import "ios/web/public/test/http_server/http_server.h" -#include "ios/web/public/test/http_server/http_server_util.h" -#include "net/base/url_util.h" -#include "ui/base/l10n/l10n_util_mac.h" -#include "url/gurl.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -using base::test::ios::WaitUntilConditionOrTimeout; -using base::test::ios::kWaitForJSCompletionTimeout; -using base::test::ios::kWaitForUIElementTimeout; -using chrome_test_util::ButtonWithAccessibilityLabel; -using chrome_test_util::ButtonWithAccessibilityLabelId; -using chrome_test_util::CloseButton; -using chrome_test_util::ToolsMenuView; -using chrome_test_util::WebStateScrollViewMatcher; - -namespace { - -// Paragraph height height for test pages. This must be large enough to trigger -// the fullscreen mode. -const int kParagraphHeightEM = 200; - -// Some text in English language. -const char kEnglishText[] = - "After flying to an altitude of 39,045 meters (128,100 feet) in a " - "helium-filled balloon, Felix Baumgartner completed a record breaking jump " - "for the ages from the edge of space, exactly 65 years after Chuck Yeager " - "first broke the sound barrier flying in an experimental rocket-powered " - "airplane. Felix reached a maximum of speed of 1,342.8 km/h (833mph) " - "through the near vacuum of the stratosphere before being slowed by the " - "atmosphere later during his 4:20 minute long freefall. The 43-year-old " - "Austrian skydiving expert also broke two other world records (highest " - "freefall, highest manned balloon flight), leaving the one for the longest " - "freefall to project mentor Col. Joe Kittinger."; - -// Some text in French language. -const char kFrenchText[] = - "Des yeux qui font baisser les miens. Un rire qui se perd sur sa bouche." - "Voilà le portrait sans retouches de l'homme auquel j'appartiens " - "Quand il me prend dans ses bras Il me parle tout bas " - "Je vois la vie en rose Il me dit des mots d'amour " - "Des mots de tous les jours Et ça me fait quelque chose " - "Il est entré dans mon cœur Une part de bonheur Dont je connais la cause " - "C'est lui pour moi, moi pour lui, dans la vie " - "Il me l'a dit, l'a juré, pour la vie Et dès que je l'aperçois " - "Alors je sens en moi, Mon cœur qui bat Des nuits d'amour à plus finir " - "Un grand bonheur qui prend sa place Les ennuis, les chagrins s'effacent " - "Heureux, heureux à en mourir Quand il me prend dans ses bras " - "Il me parle tout bas Je vois la vie en rose Il me dit des mots d'amour " - "Des mots de tous les jours Et ça me fait quelque chose " - "Il est entré dans mon cœur Une part de bonheur Dont je connais la cause " - "C'est toi pour moi, moi pour toi, dans la vie " - "Tu me l'as dit, l'as juré, pour la vie Et dès que je t'aperçois " - "Alors je sens en moi Mon cœur qui bat"; - -// Various HTML tags. -const char kHtmlAttribute[] = "<html>"; -const char kHtmlAttributeWithDeLang[] = "<html lang=\"de\">"; -const char kMetaNotranslateContent[] = - "<meta name=\"google\" content=\"notranslate\">"; -const char kMetaNotranslateValue[] = - "<meta name=\"google\" value=\"notranslate\">"; -const char kMetaItContentLanguage[] = - "<meta http-equiv=\"content-language\" content=\"it\">"; - -// Various link components. -// TODO(crbug.com/729195): Re-write the hardcoded address. -const char kHttpServerDomain[] = "127.0.0.1"; -const char kLanguagePath[] = "/languagepath/"; -const char kLinkPath[] = "/linkpath/"; -const char kSubresourcePath[] = "/subresourcepath/"; -const char kSomeLanguageUrl[] = "http://languagepath/?http=es"; -const char kFrenchPagePath[] = "/frenchpage/"; -const char kFrenchPageWithLinkPath[] = "/frenchpagewithlink/"; -const char kFrenchPageNoTranslateContent[] = "/frenchpagenotranslatecontent/"; -const char kFrenchPageNoTranslateValue[] = "/frenchpagenotranslatevalue/"; -const char kTranslateScriptPath[] = "/translatescript/"; -const char kTranslateScript[] = "Fake Translate Script"; - -// Body text for /languagepath/. -const char kLanguagePathText[] = "Some text here."; - -// Builds a HTML document with a French text and the given |html| and |meta| -// tags. -std::string GetFrenchPageHtml(const std::string& html_tag, - const std::string& meta_tags) { - return html_tag + meta_tags + "<body>" + - base::StringPrintf("<p style='height:%dem'>%s</p>", kParagraphHeightEM, - kFrenchText) + - "</body></html>"; -} - -// Returns a matcher for the translate infobar view. -id<GREYMatcher> TranslateInfobar() { - return grey_accessibilityID(kTranslateInfobarViewId); -} - -// Returns a matcher for the translate infobar's options button. -id<GREYMatcher> OptionsButton() { - return ButtonWithAccessibilityLabelId( - IDS_IOS_TRANSLATE_INFOBAR_OPTIONS_ACCESSIBILITY_LABEL); -} - -// Returns a matcher for the translate options menu. -id<GREYMatcher> OptionsMenu() { - return grey_accessibilityID(kTranslateOptionsPopupMenuId); -} - -// Returns a matcher for the language selection menu. -id<GREYMatcher> LanguagesMenu() { - return grey_accessibilityID(kLanguageSelectorPopupMenuId); -} - -// Returns a matcher for the "More Languages" entry in translate options menu. -id<GREYMatcher> MoreLanguages() { - return ButtonWithAccessibilityLabelId( - IDS_TRANSLATE_INFOBAR_OPTIONS_MORE_LANGUAGE); -} - -// Returns a matcher for the "Always translate ..." entry in translate options -// menu. -id<GREYMatcher> AlwaysTranslate(NSString* language) { - return ButtonWithAccessibilityLabel( - l10n_util::GetNSStringF(IDS_TRANSLATE_INFOBAR_OPTIONS_ALWAYS, - base::SysNSStringToUTF16(language))); -} - -// Returns a matcher for the "Never translate ..." entry in translate options -// menu. -id<GREYMatcher> NeverTranslate(NSString* language) { - return ButtonWithAccessibilityLabel(l10n_util::GetNSStringF( - IDS_TRANSLATE_INFOBAR_OPTIONS_NEVER_TRANSLATE_LANG, - base::SysNSStringToUTF16(language))); -} - -// Returns a matcher for the "Never translate this site" entry in translate -// options menu. -id<GREYMatcher> NeverTranslateSite() { - return ButtonWithAccessibilityLabel(l10n_util::GetNSString( - IDS_TRANSLATE_INFOBAR_OPTIONS_NEVER_TRANSLATE_SITE)); -} - -// Returns a matcher for the "Page not in ..." entry in translate options menu. -id<GREYMatcher> PageNotIn(NSString* language) { - return ButtonWithAccessibilityLabel( - l10n_util::GetNSStringF(IDS_TRANSLATE_INFOBAR_OPTIONS_NOT_SOURCE_LANGUAGE, - base::SysNSStringToUTF16(language))); -} - -// Returns a matcher for the notification snackbar's "UNDO" button. -id<GREYMatcher> UndoButton() { - return ButtonWithAccessibilityLabelId(IDS_TRANSLATE_NOTIFICATION_UNDO); -} - -// Returns a matcher for the Translate manual trigger button in the tools menu. -id<GREYMatcher> toolsMenuTranslateButton() { - return grey_allOf(grey_accessibilityID(kToolsMenuTranslateId), - grey_interactable(), nil); -} - -// Returns a matcher for an element with or without the -// UIAccessibilityTraitSelected accessibility trait depending on |selected|. -id<GREYMatcher> ElementIsSelected(BOOL selected) { - return grey_allOf( - grey_sufficientlyVisible(), - selected - ? grey_accessibilityTrait(UIAccessibilityTraitSelected) - : grey_not(grey_accessibilityTrait(UIAccessibilityTraitSelected)), - nil); -} - -#pragma mark - TestResponseProvider - -// A ResponseProvider that provides html responses of texts in different -// languages or links. -class TestResponseProvider : public web::DataResponseProvider { - public: - // TestResponseProvider implementation. - bool CanHandleRequest(const Request& request) override; - void GetResponseHeadersAndBody( - const Request& request, - scoped_refptr<net::HttpResponseHeaders>* headers, - std::string* response_body) override; - - private: - // Generates a page with a HTTP "Content-Language" header and "httpEquiv" meta - // tag. - // The URL in |request| has two parameters, "http" and "meta", that can be - // used to set the values of the header and the meta tag. For example: - // http://someurl?http=en&meta=fr generates a page with a "en" HTTP header and - // a "fr" meta tag. - void GetLanguageResponse(const Request& request, - scoped_refptr<net::HttpResponseHeaders>* headers, - std::string* response_body); -}; - -bool TestResponseProvider::CanHandleRequest(const Request& request) { - const GURL& url = request.url; - return (url.host() == kHttpServerDomain && - (url.path() == kLanguagePath || url.path() == kLinkPath || - url.path() == kSubresourcePath || url.path() == kFrenchPagePath || - url.path() == kFrenchPageWithLinkPath || - url.path() == kFrenchPageNoTranslateContent || - url.path() == kFrenchPageNoTranslateValue || - url.path() == kTranslateScriptPath)) || - url.SchemeIs(kChromeUIScheme); -} - -void TestResponseProvider::GetResponseHeadersAndBody( - const Request& request, - scoped_refptr<net::HttpResponseHeaders>* headers, - std::string* response_body) { - const GURL& url = request.url; - *headers = web::ResponseProvider::GetDefaultResponseHeaders(); - if (url.SchemeIs(kChromeUIScheme)) { - *response_body = url.spec(); - return; - } else if (url.path() == kLanguagePath) { - // HTTP header and meta tag read from parameters. - return GetLanguageResponse(request, headers, response_body); - } else if (url.path() == kSubresourcePath) { - // Different "Content-Language" headers in the main page and subresource. - (*headers)->AddHeader("Content-Language", "fr"); - *response_body = base::StringPrintf( - "<html><body><img src=%s></body></html>", kSomeLanguageUrl); - return; - } else if (url.path() == kLinkPath) { - // Link to a page with "Content Language" headers. - GURL url = web::test::HttpServer::MakeUrl(kSomeLanguageUrl); - *response_body = base::StringPrintf( - "<html><body><a href='%s' id='click'>Click</a></body></html>", - url.spec().c_str()); - return; - } else if (url.path() == kFrenchPagePath) { - *response_body = GetFrenchPageHtml(kHtmlAttribute, ""); - return; - } else if (url.path() == kFrenchPageWithLinkPath) { - GURL page_path_url = web::test::HttpServer::MakeUrl( - base::StringPrintf("http://%s", kFrenchPagePath)); - *response_body = base::StringPrintf( - "<html><body>%s<br/><a href='%s' id='link'>link</a></body></html>", - kFrenchText, page_path_url.spec().c_str()); - return; - } else if (url.path() == kFrenchPageNoTranslateContent) { - GURL page_path_url = web::test::HttpServer::MakeUrl( - base::StringPrintf("http://%s", kFrenchPagePath)); - // A page with French text and a 'content' attribute with "notranslate". - *response_body = GetFrenchPageHtml(kHtmlAttribute, kMetaNotranslateContent); - return; - } else if (url.path() == kFrenchPageNoTranslateValue) { - GURL page_path_url = web::test::HttpServer::MakeUrl( - base::StringPrintf("http://%s", kFrenchPagePath)); - // A page with French text and a 'value' attribute with "notranslate". - *response_body = GetFrenchPageHtml(kHtmlAttribute, kMetaNotranslateValue); - return; - } else if (url.path() == kTranslateScriptPath) { - *response_body = kTranslateScript; - return; - } - NOTREACHED(); -} - -void TestResponseProvider::GetLanguageResponse( - const Request& request, - scoped_refptr<net::HttpResponseHeaders>* headers, - std::string* response_body) { - const GURL& url = request.url; - // HTTP headers. - std::string http; - net::GetValueForKeyInQuery(url, "http", &http); - if (!http.empty()) - (*headers)->AddHeader("Content-Language", http); - // Response body. - std::string meta; - net::GetValueForKeyInQuery(url, "meta", &meta); - *response_body = "<html>"; - if (!meta.empty()) { - *response_body += - "<head>" - "<meta http-equiv='content-language' content='" + - meta + - "'>" - "</head>"; - } - *response_body += - base::StringPrintf("<html><body>%s</body></html>", kLanguagePathText); -} - -} // namespace - -#pragma mark - TranslateTestCase - -// Tests for translate. -@interface TranslateTestCase : ChromeTestCase -@end - -@implementation TranslateTestCase - -- (void)setUp { - [super setUp]; - - // Set up the fake URL for the translate script to hit the mock HTTP server. - GURL translateScriptURL = web::test::HttpServer::MakeUrl( - base::StringPrintf("http://%s", kTranslateScriptPath)); - NSString* translateScriptSwitchValue = - base::SysUTF8ToNSString(translateScriptURL.spec()); - [TranslateAppInterface setUpWithScriptServer:translateScriptSwitchValue]; -} - -- (void)tearDown { - [TranslateAppInterface tearDown]; - [super tearDown]; -} - -#pragma mark - Test Cases - -// Tests that different language signals are detected correcty. -- (void)testLanguageDetection { - if (IsInfobarUIRebootEnabled()) { - EARL_GREY_TEST_DISABLED(@"Legacy Test."); - } - const GURL URL = - web::test::HttpServer::MakeUrl("http://scenarioLanguageDetection"); - std::map<GURL, std::string> responses; - // A page with French text, German "lang" attribute and Italian content - // language. - responses[URL] = - GetFrenchPageHtml(kHtmlAttributeWithDeLang, kMetaItContentLanguage); - web::test::SetUpSimpleHttpServer(responses); - - [ChromeEarlGrey loadURL:URL]; - [self assertContentLanguage:@"it" - htmlRootLanguage:@"de" - adoptedLanguage:base::SysUTF8ToNSString( - translate::kUnknownLanguageCode)]; -} - -// Tests that hidden text is not considered during detection. -- (void)testLanguageDetectionIgnoreHiddenText { - if (IsInfobarUIRebootEnabled()) { - EARL_GREY_TEST_DISABLED(@"Legacy Test."); - } - const GURL URL = web::test::HttpServer::MakeUrl( - "http://scenarioLanguageDetectionIgnoreHiddenText"); - std::map<GURL, std::string> responses; - // A page with French text that's hidden via CSS. - responses[URL] = base::StringPrintf( - "<html><body style='display:none'>%s</body></html>", kFrenchText); - web::test::SetUpSimpleHttpServer(responses); - - [ChromeEarlGrey loadURL:URL]; - // Check for no language detected. - [self assertContentLanguage:@"" - htmlRootLanguage:@"" - adoptedLanguage:base::SysUTF8ToNSString( - translate::kUnknownLanguageCode)]; -} - -// Tests that language detection is not performed when the page specifies that -// it should not be translated. -- (void)testLanguageDetectionNoTranslate { - if (IsInfobarUIRebootEnabled()) { - EARL_GREY_TEST_DISABLED(@"Legacy Test."); - } - // Start the HTTP server. - std::unique_ptr<web::DataResponseProvider> provider(new TestResponseProvider); - web::test::SetUpHttpServer(std::move(provider)); - - const GURL noTranslateContentURL = web::test::HttpServer::MakeUrl( - base::StringPrintf("http://%s", kFrenchPageNoTranslateContent)); - const GURL noTranslateValueURL = web::test::HttpServer::MakeUrl( - base::StringPrintf("http://%s", kFrenchPageNoTranslateValue)); - - // Load some french page with |content="notranslate"| meta tag. - [ChromeEarlGrey loadURL:noTranslateContentURL]; - - // Check that no language has been detected. - GREYAssertFalse([self waitForLanguageDetection], - @"A language has been detected"); - - // Load some french page with |value="notranslate"| meta tag. - [ChromeEarlGrey loadURL:noTranslateValueURL]; - - // Check that no language has been detected. - GREYAssertFalse([self waitForLanguageDetection], - @"A language has been detected"); -} - -// Tests that history.pushState triggers a new detection. -- (void)testLanguageDetectionWithPushState { - if (IsInfobarUIRebootEnabled()) { - EARL_GREY_TEST_DISABLED(@"Legacy Test."); - } - const GURL URL = web::test::HttpServer::MakeUrl( - "http://scenarioLanguageDetectionPushState"); - std::map<GURL, std::string> responses; - // Page without meaningful text, language should be undefined ("und"). - responses[URL] = "<html><body>Blahrg :)</body></html>"; - web::test::SetUpSimpleHttpServer(responses); - - [ChromeEarlGrey loadURL:URL]; - // Check for no language detected. - [self assertContentLanguage:@"" - htmlRootLanguage:@"" - adoptedLanguage:base::SysUTF8ToNSString( - translate::kUnknownLanguageCode)]; - - // Resets state before triggering a new round of language detection. - [TranslateAppInterface resetLanguageDetectionTabHelperObserver]; - // Change the text of the page. - NSError* error = nil; - [ChromeEarlGreyAppInterface - executeJavaScript:[NSString stringWithFormat:@"document.write('%s');", - kEnglishText] - error:&error]; - // Trigger a new detection with pushState. - error = nil; - [ChromeEarlGreyAppInterface - executeJavaScript:@"history.pushState(null, null, null);" - error:&error]; - // Check that the new language has been detected. - [self assertContentLanguage:@"" htmlRootLanguage:@"" adoptedLanguage:@"en"]; -} - -// Tests that language detection is performed on hash changes. -- (void)testLanguageDetectionWithHashChange { - if (IsInfobarUIRebootEnabled()) { - EARL_GREY_TEST_DISABLED(@"Legacy Test."); - } - // Generate a page with French text and a button that changes the text to - // English and triggers a hash change. - std::string html = base::StringPrintf( - "<html><head><script>" - "function hash() {" - " document.getElementById('text').innerHTML = '%s';" - " location.href='#1';" - "}" - "</script></head><body>" - "<input type='button' value='Hash' id='Hash' onclick='hash()'>" - "<div id='text'>%s</div>" - "</body></html>", - kEnglishText, kFrenchText); - - // Set up the mock server. - std::map<GURL, std::string> responses; - const GURL URL = - web::test::HttpServer::MakeUrl("http://hashChangeLanguageDetected"); - responses[URL] = html; - web::test::SetUpSimpleHttpServer(responses); - - [ChromeEarlGrey loadURL:URL]; - // Check that language has been detected. - [self assertContentLanguage:@"" htmlRootLanguage:@"" adoptedLanguage:@"fr"]; - - // Resets state before triggering a new round of language detection. - [TranslateAppInterface resetLanguageDetectionTabHelperObserver]; - // Trigger the hash change. - [ChromeEarlGrey tapWebStateElementWithID:@"Hash"]; - // Check that language detection has been re-run. - [self assertContentLanguage:@"" htmlRootLanguage:@"" adoptedLanguage:@"en"]; -} - -// Tests that language in http content is detected. -- (void)testLanguageDetectionHttpContentLanguage { - if (IsInfobarUIRebootEnabled()) { - EARL_GREY_TEST_DISABLED(@"Legacy Test."); - } - // Start the HTTP server. - std::unique_ptr<web::DataResponseProvider> provider(new TestResponseProvider); - web::test::SetUpHttpServer(std::move(provider)); - - // The HTTP header is detected. - GURL URL = web::test::HttpServer::MakeUrl(std::string("http://") + - kLanguagePath + "?http=fr"); - [ChromeEarlGrey loadURL:URL]; - [self assertContentLanguage:@"fr" htmlRootLanguage:@"" adoptedLanguage:@"fr"]; - - // Resets state before triggering a new round of language detection. - [TranslateAppInterface resetLanguageDetectionTabHelperObserver]; - // Everything after the comma is truncated. - URL = web::test::HttpServer::MakeUrl(std::string("http://") + kLanguagePath + - "?http=fr,ornot"); - [ChromeEarlGrey loadURL:URL]; - [self assertContentLanguage:@"fr" htmlRootLanguage:@"" adoptedLanguage:@"fr"]; - - // Resets state before triggering a new round of language detection. - [TranslateAppInterface resetLanguageDetectionTabHelperObserver]; - // The HTTP header is overriden by meta tag. - URL = web::test::HttpServer::MakeUrl(std::string("http://") + kLanguagePath + - "?http=fr&meta=it"); - [ChromeEarlGrey loadURL:URL]; - [self assertContentLanguage:@"it" htmlRootLanguage:@"" adoptedLanguage:@"it"]; - - // Resets state before triggering a new round of language detection. - [TranslateAppInterface resetLanguageDetectionTabHelperObserver]; - // Only the header of the main page is detected. - URL = - web::test::HttpServer::MakeUrl(std::string("http://") + kSubresourcePath); - [ChromeEarlGrey loadURL:URL]; - [self assertContentLanguage:@"fr" htmlRootLanguage:@"" adoptedLanguage:@"fr"]; -} - -// Tests that language in http content is detected when navigating to a link. -- (void)testLanguageDetectionHttpContentLanguageBehindLink { - if (IsInfobarUIRebootEnabled()) { - EARL_GREY_TEST_DISABLED(@"Legacy Test."); - } - // Start the HTTP server. - std::unique_ptr<web::DataResponseProvider> provider(new TestResponseProvider); - web::test::SetUpHttpServer(std::move(provider)); - - // Detection works when clicking on a link. - GURL URL = web::test::HttpServer::MakeUrl(std::string("http://") + kLinkPath); - GURL someLanguageURL = web::test::HttpServer::MakeUrl(kSomeLanguageUrl); - [ChromeEarlGrey loadURL:URL]; - [ChromeEarlGrey tapWebStateElementWithID:@"click"]; - [ChromeEarlGrey waitForWebStateContainingText:kLanguagePathText]; - [[EarlGrey selectElementWithMatcher:chrome_test_util::OmniboxText( - someLanguageURL.GetContent())] - assertWithMatcher:grey_notNil()]; - [self assertContentLanguage:@"es" htmlRootLanguage:@"" adoptedLanguage:@"es"]; -} - -// Tests that language detection still happens when a very large quantity of -// text is present on the page. -- (void)testLanguageDetectionLargePage { - if (IsInfobarUIRebootEnabled()) { - EARL_GREY_TEST_DISABLED(@"Legacy Test."); - } - // Generate very large page. - std::string html = "<html lang='fr'><body>"; - NSUInteger targetSize = 1024 * 1024; // More than 1 MB of page content. - while (html.length() < targetSize) { - html.append("<p>"); - html.append(kFrenchText); - html.append("</p>"); - } - html.append("</body></html>"); - - // Create map of canned responses and set up the test HTML server. - std::map<GURL, std::string> responses; - const GURL URL = - web::test::HttpServer::MakeUrl("http://languageDetectionLargePage"); - responses[URL] = html; - web::test::SetUpSimpleHttpServer(responses); - [ChromeEarlGrey loadURL:URL]; - - // Check that language has been detected. - [self assertContentLanguage:@"" htmlRootLanguage:@"fr" adoptedLanguage:@"fr"]; -} - -// Tests that language detection is not performed when translate is disabled. -- (void)testLanguageDetectionDisabled { - if (IsInfobarUIRebootEnabled()) { - EARL_GREY_TEST_DISABLED(@"Legacy Test."); - } - const GURL URL = web::test::HttpServer::MakeUrl( - "http://scenarioLanguageDetectionDisabled"); - std::map<GURL, std::string> responses; - // A page with some text. - responses[URL] = "<html><body>Hello world!</body></html>"; - web::test::SetUpSimpleHttpServer(responses); - - // Disable translate. - [ChromeEarlGreyAppInterface - setBoolValue:NO - forUserPref:base::SysUTF8ToNSString(prefs::kOfferTranslateEnabled)]; - - // Open some webpage. - [ChromeEarlGrey loadURL:URL]; - // Check that no language has been detected. - GREYAssertFalse([self waitForLanguageDetection], - @"A language has been detected"); - - // Enable translate. - [ChromeEarlGreyAppInterface - setBoolValue:YES - forUserPref:base::SysUTF8ToNSString(prefs::kOfferTranslateEnabled)]; -} - -// Tests that the infobar hides/shows as the browser enters/exits the fullscreen -// mode as well as it can be dimissed. -- (void)testInfobarShowHideDismiss { - if (IsInfobarUIRebootEnabled()) { - EARL_GREY_TEST_DISABLED(@"Legacy Test."); - } - // Start the HTTP server. - std::unique_ptr<web::DataResponseProvider> provider(new TestResponseProvider); - web::test::SetUpHttpServer(std::move(provider)); - - // Load a page with French text. - GURL URL = web::test::HttpServer::MakeUrl( - base::StringPrintf("http://%s", kFrenchPagePath)); - [ChromeEarlGrey loadURL:URL]; - - [self assertTranslateInfobarIsVisible]; - - // Scroll down to enter the fullscreen mode. - [[EarlGrey selectElementWithMatcher:WebStateScrollViewMatcher()] - performAction:grey_swipeFastInDirection(kGREYDirectionUp)]; - - // Expect the translate infobar to be hidden. - [[EarlGrey selectElementWithMatcher:TranslateInfobar()] - assertWithMatcher:grey_notVisible()]; - - // Scroll up to exit the fullscreen mode. - [[EarlGrey selectElementWithMatcher:WebStateScrollViewMatcher()] - performAction:grey_swipeFastInDirection(kGREYDirectionDown)]; - - [self assertTranslateInfobarIsVisible]; - - // Dismiss the translate infobar. - [[EarlGrey selectElementWithMatcher:CloseButton()] performAction:grey_tap()]; - - // Wait until the translate infobar disappears. - ConditionBlock condition = ^{ - NSError* error = nil; - [[EarlGrey selectElementWithMatcher:TranslateInfobar()] - assertWithMatcher:grey_nil() - error:&error]; - return error == nil; - }; - GREYAssert(WaitUntilConditionOrTimeout(kWaitForUIElementTimeout, condition), - @"Translate infobar failed to disappear."); -} - -// Tests that the infobar's popup menu can be dimissed. -- (void)testInfobarDismissPopupMenu { - if (IsInfobarUIRebootEnabled()) { - EARL_GREY_TEST_DISABLED(@"Legacy Test."); - } - // Start the HTTP server. - std::unique_ptr<web::DataResponseProvider> provider(new TestResponseProvider); - web::test::SetUpHttpServer(std::move(provider)); - - // Load a page with French text. - GURL URL = web::test::HttpServer::MakeUrl( - base::StringPrintf("http://%s", kFrenchPagePath)); - [ChromeEarlGrey loadURL:URL]; - - [self assertTranslateInfobarIsVisible]; - - // Open the translate options menu. - [[EarlGrey selectElementWithMatcher:OptionsButton()] - performAction:grey_tap()]; - - // Expect the translate options menu to have appeared. - [[EarlGrey selectElementWithMatcher:OptionsMenu()] - assertWithMatcher:grey_sufficientlyVisible()]; - - // When the popup menu is visible, a scrim covers the whole window and tapping - // it dismisses the popup menu. The options button is outside of the bounds of - // the popup menu and is a convenient place to tap to activate the scrim. - [[EarlGrey selectElementWithMatcher:OptionsButton()] - performAction:grey_tap()]; - - // Expect the translate options menu to have disappeared. - [[EarlGrey selectElementWithMatcher:OptionsMenu()] - assertWithMatcher:grey_nil()]; -} - -// Tests that the page can be translated and that translation can be reverted -// using the source and the target language tabs. -- (void)testInfobarTranslateRevert { - if (IsInfobarUIRebootEnabled()) { - EARL_GREY_TEST_DISABLED(@"Legacy Test."); - } - // Start the HTTP server. - std::unique_ptr<web::DataResponseProvider> provider(new TestResponseProvider); - web::test::SetUpHttpServer(std::move(provider)); - - // Load a page with French text. - GURL URL = web::test::HttpServer::MakeUrl( - base::StringPrintf("http://%s", kFrenchPagePath)); - [ChromeEarlGrey loadURL:URL]; - - [self translateThenRevert]; -} - -// Tests that the page can be translated and that translation can be reverted -// using the source and the target language tabs in incognito mode. -- (void)testInfobarTranslateRevertIncognito { - if (IsInfobarUIRebootEnabled()) { - EARL_GREY_TEST_DISABLED(@"Legacy Test."); - } - // Start the HTTP server. - std::unique_ptr<web::DataResponseProvider> provider(new TestResponseProvider); - web::test::SetUpHttpServer(std::move(provider)); - - // Load a page with French text in an incognito tab. - GURL URL = web::test::HttpServer::MakeUrl( - base::StringPrintf("http://%s", kFrenchPagePath)); - // Stop observing the current IOSLanguageDetectionTabHelper before opening the - // incognito tab. - [TranslateAppInterface tearDownLanguageDetectionTabHelperObserver]; - [ChromeEarlGrey openNewIncognitoTab]; - [ChromeEarlGrey loadURL:URL]; - - // Since current web state has changed to Incognito, a new fake translation - // manager has to be set up for the rest of this test. - [TranslateAppInterface setUpFakeJSTranslateManagerInCurrentTab]; - - [self translateThenRevert]; -} - -// Translates the page and reverts the translation using the language tabs. -- (void)translateThenRevert { - if (IsInfobarUIRebootEnabled()) { - EARL_GREY_TEST_DISABLED(@"Legacy Test."); - } - [self assertTranslateInfobarIsVisible]; - - // Make sure the page is not translated. - [ChromeEarlGrey waitForWebStateNotContainingText:"Translated"]; - - // The source language tab must be selected and the target language tab must - // not. Translate the page by tapping the target language tab. - [[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabel(@"French")] - assertWithMatcher:ElementIsSelected(YES)]; - [[[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabel(@"English")] - assertWithMatcher:ElementIsSelected(NO)] performAction:grey_tap()]; - - // Make sure the page is translated. - [ChromeEarlGrey waitForWebStateContainingText:"Translated"]; - - // The target language tab must be selected and the source language tab must - // not. Revert the translation by tapping the source language tab. - [[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabel(@"English")] - assertWithMatcher:ElementIsSelected(YES)]; - [[[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabel(@"French")] - assertWithMatcher:ElementIsSelected(NO)] performAction:grey_tap()]; - - // Make sure the translation is reverted. - [ChromeEarlGrey waitForWebStateNotContainingText:"Translated"]; - - // The source language tab must be selected and the target language tab must - // not. - [[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabel(@"French")] - assertWithMatcher:ElementIsSelected(YES)]; - [[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabel(@"English")] - assertWithMatcher:ElementIsSelected(NO)]; -} - -// Tests that translation occurs automatically on second navigation to an -// already translated page. -- (void)testInfobarAutoTranslate { - if (IsInfobarUIRebootEnabled()) { - EARL_GREY_TEST_DISABLED(@"Legacy Test."); - } - // Start the HTTP server. - std::unique_ptr<web::DataResponseProvider> provider(new TestResponseProvider); - web::test::SetUpHttpServer(std::move(provider)); - - // Load a page with French text and a link. - GURL URL = web::test::HttpServer::MakeUrl( - base::StringPrintf("http://%s", kFrenchPageWithLinkPath)); - [ChromeEarlGrey loadURL:URL]; - - [self assertTranslateInfobarIsVisible]; - - // Make sure the page is not translated. - [ChromeEarlGrey waitForWebStateNotContainingText:"Translated"]; - - // The target language tab must not be selected. Translate the page by - // tapping the target language tab. - [[[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabel(@"English")] - assertWithMatcher:ElementIsSelected(NO)] performAction:grey_tap()]; - - // Make sure the page is translated. - [ChromeEarlGrey waitForWebStateContainingText:"Translated"]; - - // Click on the link. - [ChromeEarlGrey tapWebStateElementWithID:@"link"]; - - // Make sure the navigation is completed. - GURL frenchPagePathURL = web::test::HttpServer::MakeUrl( - base::StringPrintf("http://%s", kFrenchPagePath)); - [[EarlGrey selectElementWithMatcher:chrome_test_util::OmniboxText( - frenchPagePathURL.GetContent())] - assertWithMatcher:grey_notNil()]; - - // Make sure the page is automatically translated. - [ChromeEarlGrey waitForWebStateContainingText:"Translated"]; -} - -// Tests that the source and the target languages can be changed. -- (void)testInfobarChangeLanguages { - if (IsInfobarUIRebootEnabled()) { - EARL_GREY_TEST_DISABLED(@"Legacy Test."); - } - // Start the HTTP server. - std::unique_ptr<web::DataResponseProvider> provider(new TestResponseProvider); - web::test::SetUpHttpServer(std::move(provider)); - - // Load a page with French text. - GURL URL = web::test::HttpServer::MakeUrl( - base::StringPrintf("http://%s", kFrenchPagePath)); - [ChromeEarlGrey loadURL:URL]; - - [self assertTranslateInfobarIsVisible]; - - // The source language tab must be selected and the target language tab must - // not. - [[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabel(@"French")] - assertWithMatcher:ElementIsSelected(YES)]; - [[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabel(@"English")] - assertWithMatcher:ElementIsSelected(NO)]; - - // Open the translate options menu. - [[EarlGrey selectElementWithMatcher:OptionsButton()] - performAction:grey_tap()]; - - // Expect the translate options menu to have appeared. - [[EarlGrey selectElementWithMatcher:OptionsMenu()] - assertWithMatcher:grey_sufficientlyVisible()]; - - // Select the "More Languages" entry in the options popup menu. - [[EarlGrey selectElementWithMatcher:MoreLanguages()] - performAction:grey_tap()]; - - // Expect the translate options menu to have disappeared. - [[EarlGrey selectElementWithMatcher:OptionsMenu()] - assertWithMatcher:grey_nil()]; - - // Expect the language selection menu to have appeared. - [[EarlGrey selectElementWithMatcher:LanguagesMenu()] - assertWithMatcher:grey_sufficientlyVisible()]; - - // Select "Dutch" from the the popup menu. - [[[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabel(@"Dutch")] - usingSearchAction:grey_scrollInDirection(kGREYDirectionDown, 200) - onElementWithMatcher:LanguagesMenu()] performAction:grey_tap()]; - - // Expect the language selection menu to have disappeared. - [[EarlGrey selectElementWithMatcher:LanguagesMenu()] - assertWithMatcher:grey_nil()]; - - // Make sure the page is translated. - [ChromeEarlGrey waitForWebStateContainingText:"Translated"]; - - // Make sure the target language changes to "Dutch". The target language - // tab must be selected and the source language tab must not. Revert the - // translation by tapping the source language tab. - [[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabel(@"Dutch")] - assertWithMatcher:ElementIsSelected(YES)]; - [[[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabel(@"French")] - assertWithMatcher:ElementIsSelected(NO)] performAction:grey_tap()]; - - // Make sure the translation is reverted. - [ChromeEarlGrey waitForWebStateNotContainingText:"Translated"]; - - // Open the translate options menu. - [[EarlGrey selectElementWithMatcher:OptionsButton()] - performAction:grey_tap()]; - - // Select the "Page not in French" entry in the options popup menu. - [[EarlGrey selectElementWithMatcher:PageNotIn(@"French")] - performAction:grey_tap()]; - - // Expect the translate options menu to have disappeared. - [[EarlGrey selectElementWithMatcher:OptionsMenu()] - assertWithMatcher:grey_nil()]; - - // Expect the language selection menu to have appeared. - [[EarlGrey selectElementWithMatcher:LanguagesMenu()] - assertWithMatcher:grey_sufficientlyVisible()]; - - // Select "English" from the the popup menu. - [[[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabel(@"English")] - usingSearchAction:grey_scrollInDirection(kGREYDirectionDown, 200) - onElementWithMatcher:LanguagesMenu()] performAction:grey_tap()]; - - // Make sure the page is translated. - [ChromeEarlGrey waitForWebStateContainingText:"Translated"]; - - // Make sure the source language changes to "English". The target language - // tab must be selected and the source language tab must not. - [[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabel(@"English")] - assertWithMatcher:ElementIsSelected(NO)]; - [[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabel(@"Dutch")] - assertWithMatcher:ElementIsSelected(YES)]; -} - -// Tests that the "Always Translate" options can be toggled and the prefs are -// updated accordingly. -- (void)testInfobarAlwaysTranslate { - if (IsInfobarUIRebootEnabled()) { - EARL_GREY_TEST_DISABLED(@"Legacy Test."); - } - // Start the HTTP server. - std::unique_ptr<web::DataResponseProvider> provider(new TestResponseProvider); - web::test::SetUpHttpServer(std::move(provider)); - - // Load a page with French text. - GURL URL = web::test::HttpServer::MakeUrl( - base::StringPrintf("http://%s", kFrenchPagePath)); - [ChromeEarlGrey loadURL:URL]; - - [self assertTranslateInfobarIsVisible]; - - // Make sure that French to English translation is not automatic. - GREYAssert(![TranslateAppInterface shouldAutoTranslateFromLanguage:@"fr" - toLanguage:@"en"], - @"French to English translation is automatic"); - - // Open the translate options menu. - [[EarlGrey selectElementWithMatcher:OptionsButton()] - performAction:grey_tap()]; - - // Make sure the "Always Translate French" entry is not selected and tap it. - [[[EarlGrey selectElementWithMatcher:AlwaysTranslate(@"French")] - assertWithMatcher:ElementIsSelected(NO)] performAction:grey_tap()]; - - // Expect the translate options menu to have disappeared. - [[EarlGrey selectElementWithMatcher:OptionsMenu()] - assertWithMatcher:grey_nil()]; - - // Make sure the page is not translated yet. - [ChromeEarlGrey waitForWebStateNotContainingText:"Translated"]; - - // Make sure that French to English translation is not automatic yet. - GREYAssert(![TranslateAppInterface shouldAutoTranslateFromLanguage:@"fr" - toLanguage:@"en"], - @"French to English translation is automatic"); - - // Tap the notification snackbar to dismiss it. - NSString* snackbarTitle = - l10n_util::GetNSStringF(IDS_TRANSLATE_NOTIFICATION_ALWAYS_TRANSLATE, - base::SysNSStringToUTF16(@"French"), - base::SysNSStringToUTF16(@"English")); - [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(snackbarTitle)] - performAction:grey_tap()]; - - // Make sure the page is translated after the snackbar is dismissed. - [ChromeEarlGrey waitForWebStateContainingText:"Translated"]; - - // Make sure that French to English translation is automatic after the - // snackbar is dismissed. - GREYAssert([TranslateAppInterface shouldAutoTranslateFromLanguage:@"fr" - toLanguage:@"en"], - @"French to English translation is not automatic"); - - // Reload the page. - [ChromeEarlGrey reload]; - - [self assertTranslateInfobarIsVisible]; - - // Make sure the page is translated. - [ChromeEarlGrey waitForWebStateContainingText:"Translated"]; - - // The target language tab must be selected and the source language tab must - // not. - [[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabel(@"French")] - assertWithMatcher:ElementIsSelected(NO)]; - [[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabel(@"English")] - assertWithMatcher:ElementIsSelected(YES)]; - - // Open the translate options menu. - [[EarlGrey selectElementWithMatcher:OptionsButton()] - performAction:grey_tap()]; - - // Make sure the "Always Translate French" entry is now selected and tap it. - [[[EarlGrey selectElementWithMatcher:AlwaysTranslate(@"French")] - assertWithMatcher:ElementIsSelected(YES)] performAction:grey_tap()]; - - // Make sure that French to English translation is no longer automatic. - GREYAssert(![TranslateAppInterface shouldAutoTranslateFromLanguage:@"fr" - toLanguage:@"en"], - @"French to English translation is automatic"); - - // Open the translate options menu. - [[EarlGrey selectElementWithMatcher:OptionsButton()] - performAction:grey_tap()]; - - // Make sure the "Always Translate French" entry is not selected and tap it. - [[[EarlGrey selectElementWithMatcher:AlwaysTranslate(@"French")] - assertWithMatcher:ElementIsSelected(NO)] performAction:grey_tap()]; - - // Tap the notification snackbar's "UNDO" button. - [[EarlGrey selectElementWithMatcher:UndoButton()] performAction:grey_tap()]; - - // Open the translate options menu. - [[EarlGrey selectElementWithMatcher:OptionsButton()] - performAction:grey_tap()]; - - // Make sure the "Always Translate French" entry is still not selected. - [[EarlGrey selectElementWithMatcher:AlwaysTranslate(@"French")] - assertWithMatcher:ElementIsSelected(NO)]; - - // Make sure that French to English translation is not automatic. - GREYAssert(![TranslateAppInterface shouldAutoTranslateFromLanguage:@"fr" - toLanguage:@"en"], - @"French to English translation is automatic"); -} - -// Tests that "Always Translate" is automatically triggered after a minimum -// number of translate attempts by the user. -- (void)testInfobarAutoAlwaysTranslate { - if (IsInfobarUIRebootEnabled()) { - EARL_GREY_TEST_DISABLED(@"Legacy Test."); - } - // Start the HTTP server. - std::unique_ptr<web::DataResponseProvider> provider(new TestResponseProvider); - web::test::SetUpHttpServer(std::move(provider)); - - // Load a page with French text. - GURL URL = web::test::HttpServer::MakeUrl( - base::StringPrintf("http://%s", kFrenchPagePath)); - [ChromeEarlGrey loadURL:URL]; - - [self assertTranslateInfobarIsVisible]; - - // Make sure that French to English translation is not automatic. - GREYAssert(![TranslateAppInterface shouldAutoTranslateFromLanguage:@"fr" - toLanguage:@"en"], - @"French to English translation is automatic"); - - // Translate the page by tapping the target language tab until - // "Always Translate" is automatically triggered. - for (int i = 0; i <= [TranslateAppInterface infobarAutoAlwaysThreshold]; - i++) { - [[EarlGrey - selectElementWithMatcher:ButtonWithAccessibilityLabel(@"English")] - performAction:grey_tap()]; - [[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabel(@"French")] - performAction:grey_tap()]; - } - - // Make sure that French to English translation is not automatic yet. - GREYAssert(![TranslateAppInterface shouldAutoTranslateFromLanguage:@"fr" - toLanguage:@"en"], - @"French to English translation is automatic"); - - // Tap the notification snackbar to dismiss it. - NSString* snackbarTitle = - l10n_util::GetNSStringF(IDS_TRANSLATE_NOTIFICATION_ALWAYS_TRANSLATE, - base::SysNSStringToUTF16(@"French"), - base::SysNSStringToUTF16(@"English")); - [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(snackbarTitle)] - performAction:grey_tap()]; - - // Make sure that French to English translation is automatic after the - // snackbar is dismissed. - GREYAssert([TranslateAppInterface shouldAutoTranslateFromLanguage:@"fr" - toLanguage:@"en"], - @"French to English translation is not automatic"); -} - -// Tests that "Always Translate" is automatically triggered only for a maximum -// number of times if refused by the user. -- (void)testInfobarAutoAlwaysTranslateMaxTries { - if (IsInfobarUIRebootEnabled()) { - EARL_GREY_TEST_DISABLED(@"Legacy Test."); - } - // Start the HTTP server. - std::unique_ptr<web::DataResponseProvider> provider(new TestResponseProvider); - web::test::SetUpHttpServer(std::move(provider)); - - // Load a page with French text. - GURL URL = web::test::HttpServer::MakeUrl( - base::StringPrintf("http://%s", kFrenchPagePath)); - [ChromeEarlGrey loadURL:URL]; - - [self assertTranslateInfobarIsVisible]; - - // Make sure that French to English translation is not automatic. - GREYAssert(![TranslateAppInterface shouldAutoTranslateFromLanguage:@"fr" - toLanguage:@"en"], - @"French to English translation is automatic"); - - // Trigger and refuse the auto "Always Translate". - for (int i = 0; i < [TranslateAppInterface infobarMaximumNumberOfAutoAlways]; - i++) { - // Translate the page by tapping the target language tab until - // "Always Translate" is automatically triggered. - for (int j = 0; j <= [TranslateAppInterface infobarAutoAlwaysThreshold]; - j++) { - [[EarlGrey - selectElementWithMatcher:ButtonWithAccessibilityLabel(@"English")] - performAction:grey_tap()]; - [[EarlGrey - selectElementWithMatcher:ButtonWithAccessibilityLabel(@"French")] - performAction:grey_tap()]; - } - // Tap the notification snackbar's "UNDO" button. - [[EarlGrey selectElementWithMatcher:UndoButton()] performAction:grey_tap()]; - } - - // Translate the page by tapping the target language tab in order to - // automatically trigger "Always Translate". - for (int i = 0; i <= [TranslateAppInterface infobarAutoAlwaysThreshold]; - i++) { - [[EarlGrey - selectElementWithMatcher:ButtonWithAccessibilityLabel(@"English")] - performAction:grey_tap()]; - } - - // Make sure "Always Translate" is not triggered. - NSString* snackbarTitle = - l10n_util::GetNSStringF(IDS_TRANSLATE_NOTIFICATION_ALWAYS_TRANSLATE, - base::SysNSStringToUTF16(@"French"), - base::SysNSStringToUTF16(@"English")); - GREYAssertFalse([self waitForElementToAppearOrTimeout:grey_accessibilityLabel( - snackbarTitle)], - @"Always Translate was triggered."); -} - -// Tests that the "Never Translate ..." options dismisses the infobar and -// updates the prefs accordingly. -- (void)testInfobarNeverTranslate { - if (IsInfobarUIRebootEnabled()) { - EARL_GREY_TEST_DISABLED(@"Legacy Test."); - } - // Start the HTTP server. - std::unique_ptr<web::DataResponseProvider> provider(new TestResponseProvider); - web::test::SetUpHttpServer(std::move(provider)); - - // Load a page with French text. - GURL URL = web::test::HttpServer::MakeUrl( - base::StringPrintf("http://%s", kFrenchPagePath)); - [ChromeEarlGrey loadURL:URL]; - - [self assertTranslateInfobarIsVisible]; - - // Make sure that translation from French is not blocked. - GREYAssert(![TranslateAppInterface isBlockedLanguage:@"fr"], - @"Translation from French is blocked"); - - // Open the translate options menu. - [[EarlGrey selectElementWithMatcher:OptionsButton()] - performAction:grey_tap()]; - - // Tap the "Never Translate French" entry. - [[EarlGrey selectElementWithMatcher:NeverTranslate(@"French")] - performAction:grey_tap()]; - - // Expect the translate options menu to have disappeared. - [[EarlGrey selectElementWithMatcher:OptionsMenu()] - assertWithMatcher:grey_nil()]; - - // Tap the notification snackbar's "UNDO" button. - [[EarlGrey selectElementWithMatcher:UndoButton()] performAction:grey_tap()]; - - // Make sure that translation from French is still not blocked. - GREYAssert(![TranslateAppInterface isBlockedLanguage:@"fr"], - @"Translation from French is blocked"); - - // Open the translate options menu. - [[EarlGrey selectElementWithMatcher:OptionsButton()] - performAction:grey_tap()]; - - // Tap the "Never Translate French" entry. - [[EarlGrey selectElementWithMatcher:NeverTranslate(@"French")] - performAction:grey_tap()]; - - // Make sure that translation from French is not blocked yet. - GREYAssert(![TranslateAppInterface isBlockedLanguage:@"fr"], - @"Translation from French is blocked"); - - // Tap the notification snackbar to dismiss it. - NSString* snackbarTitle = - l10n_util::GetNSStringF(IDS_TRANSLATE_NOTIFICATION_LANGUAGE_NEVER, - base::SysNSStringToUTF16(@"French")); - [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(snackbarTitle)] - performAction:grey_tap()]; - - // Wait until the translate infobar disappears. - GREYAssert([self waitForElementToDisappearOrTimeout:TranslateInfobar()], - @"Translate infobar failed to disappear."); - - // Make sure that translation from French is blocked after the snackbar is - // dismissed. - GREYAssert([TranslateAppInterface isBlockedLanguage:@"fr"], - @"Translation from French is not blocked"); - - // Reload the page. - [ChromeEarlGrey reload]; - - // Make sure the translate infobar does not appear. - GREYAssertFalse([self waitForElementToAppearOrTimeout:TranslateInfobar()], - @"Translate infobar appeared."); -} - -// Tests that "Never Translate ..." is automatically triggered after a minimum -// number of translate infobar dismissals by the user. -- (void)testInfobarAutoNeverTranslate { - if (IsInfobarUIRebootEnabled()) { - EARL_GREY_TEST_DISABLED(@"Legacy Test."); - } - // Start the HTTP server. - std::unique_ptr<web::DataResponseProvider> provider(new TestResponseProvider); - web::test::SetUpHttpServer(std::move(provider)); - - // Load a page with French text. - GURL URL = web::test::HttpServer::MakeUrl( - base::StringPrintf("http://%s", kFrenchPagePath)); - [ChromeEarlGrey loadURL:URL]; - - [self assertTranslateInfobarIsVisible]; - - // Make sure that translation from French is not blocked. - GREYAssert(![TranslateAppInterface isBlockedLanguage:@"fr"], - @"Translation from French is blocked"); - - // Dismiss the translate infobar until "Never Translate ..." is automatically - // triggered. - for (int i = 0; i < [TranslateAppInterface infobarAutoNeverThreshold]; i++) { - // Reload the page. - [ChromeEarlGrey reload]; - - [self assertTranslateInfobarIsVisible]; - - // Dismiss the translate infobar. - [[EarlGrey selectElementWithMatcher:CloseButton()] - performAction:grey_tap()]; - } - - // Make sure that translation from French is not blocked yet. - GREYAssert(![TranslateAppInterface isBlockedLanguage:@"fr"], - @"Translation from French is blocked"); - - // Tap the notification snackbar to dismiss it. - NSString* snackbarTitle = - l10n_util::GetNSStringF(IDS_TRANSLATE_NOTIFICATION_LANGUAGE_NEVER, - base::SysNSStringToUTF16(@"French")); - [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(snackbarTitle)] - performAction:grey_tap()]; - - // Wait until the translate infobar disappears. - GREYAssert([self waitForElementToDisappearOrTimeout:TranslateInfobar()], - @"Translate infobar failed to disappear."); - - // Make sure that translation from French is blocked after the snackbar is - // dismissed. - GREYAssert([TranslateAppInterface isBlockedLanguage:@"fr"], - @"Translation from French is not blocked"); -} - -// Tests that "Never Translate ..." is automatically triggered only for a -// maximum number of times if refused by the user. -// TODO(crbug.com/945118): Re-enable when fixed. -- (void)DISABLED_testInfobarAutoNeverTranslateMaxTries { - if (IsInfobarUIRebootEnabled()) { - EARL_GREY_TEST_DISABLED(@"Legacy Test."); - } - // Start the HTTP server. - std::unique_ptr<web::DataResponseProvider> provider(new TestResponseProvider); - web::test::SetUpHttpServer(std::move(provider)); - - // Load a page with French text. - GURL URL = web::test::HttpServer::MakeUrl( - base::StringPrintf("http://%s", kFrenchPagePath)); - [ChromeEarlGrey loadURL:URL]; - - [self assertTranslateInfobarIsVisible]; - - // Make sure that translation from French is not blocked. - GREYAssert(![TranslateAppInterface isBlockedLanguage:@"fr"], - @"Translation from French is blocked"); - - // Trigger and refuse the auto "Never Translate ...". - for (int i = 0; i < [TranslateAppInterface infobarMaximumNumberOfAutoNever]; - i++) { - // Dismiss the translate infobar until "Never Translate ..." is - // automatically triggered. - for (int j = 0; j < [TranslateAppInterface infobarAutoNeverThreshold]; - j++) { - // Reload the page. - [ChromeEarlGrey reload]; - - [self assertTranslateInfobarIsVisible]; - - // Dismiss the translate infobar. - [[EarlGrey selectElementWithMatcher:CloseButton()] - performAction:grey_tap()]; - } - // Tap the notification snackbar's "UNDO" button. - [[EarlGrey selectElementWithMatcher:UndoButton()] performAction:grey_tap()]; - - // Wait until the translate infobar disappears. - GREYAssert([self waitForElementToDisappearOrTimeout:TranslateInfobar()], - @"Translate infobar failed to disappear."); - } - - // Dismiss the translate infobar in order to automatically trigger - // "Never Translate ...". - for (int i = 0; i < [TranslateAppInterface infobarAutoNeverThreshold]; i++) { - // Reload the page. - [ChromeEarlGrey reload]; - - [self assertTranslateInfobarIsVisible]; - - // Dismiss the translate infobar. - [[EarlGrey selectElementWithMatcher:CloseButton()] - performAction:grey_tap()]; - } - - // Make sure "Never Translate ..." is not triggered. - NSString* snackbarTitle = - l10n_util::GetNSStringF(IDS_TRANSLATE_NOTIFICATION_LANGUAGE_NEVER, - base::SysNSStringToUTF16(@"French")); - GREYAssertFalse([self waitForElementToAppearOrTimeout:grey_accessibilityLabel( - snackbarTitle)], - @"Never Translate French was triggered."); -} - -// Tests that the "Never Translate this site" option dismisses the infobar and -// updates the prefs accordingly. -- (void)testInfobarNeverTranslateSite { - if (IsInfobarUIRebootEnabled()) { - EARL_GREY_TEST_DISABLED(@"Legacy Test."); - } - // Start the HTTP server. - std::unique_ptr<web::DataResponseProvider> provider(new TestResponseProvider); - web::test::SetUpHttpServer(std::move(provider)); - - // Load a page with French text. - GURL URL = web::test::HttpServer::MakeUrl( - base::StringPrintf("http://%s", kFrenchPagePath)); - [ChromeEarlGrey loadURL:URL]; - - [self assertTranslateInfobarIsVisible]; - - NSString* URLHost = base::SysUTF8ToNSString(URL.HostNoBrackets()); - // Make sure that translation for the site is not blocked. - GREYAssert(![TranslateAppInterface isBlockedSite:URLHost], - @"Translation is blocked for the site"); - - // Open the translate options menu. - [[EarlGrey selectElementWithMatcher:OptionsButton()] - performAction:grey_tap()]; - - // Tap the "Never Translate this site" entry. - [[EarlGrey selectElementWithMatcher:NeverTranslateSite()] - performAction:grey_tap()]; - - // Expect the translate options menu to have disappeared. - [[EarlGrey selectElementWithMatcher:OptionsMenu()] - assertWithMatcher:grey_nil()]; - - // Tap the notification snackbar's "UNDO" button. - [[EarlGrey selectElementWithMatcher:UndoButton()] performAction:grey_tap()]; - - // Make sure that translation for the site is still not blocked. - GREYAssert(![TranslateAppInterface isBlockedSite:URLHost], - @"Translation is blocked for the site"); - - // Open the translate options menu. - [[EarlGrey selectElementWithMatcher:OptionsButton()] - performAction:grey_tap()]; - - // Tap the "Never Translate this site" entry. - [[EarlGrey selectElementWithMatcher:NeverTranslateSite()] - performAction:grey_tap()]; - - // Make sure that translation for the site is not blocked yet. - GREYAssert(![TranslateAppInterface isBlockedSite:URLHost], - @"Translation is blocked for the site"); - - // Tap the notification snackbar to dismiss it. - NSString* snackbarTitle = - l10n_util::GetNSString(IDS_TRANSLATE_NOTIFICATION_SITE_NEVER); - [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(snackbarTitle)] - performAction:grey_tap()]; - - // Make sure that translation for the site is blocked after the snackbar is - // dismissed. - GREYAssert([TranslateAppInterface isBlockedSite:URLHost], - @"Translation is not blocked for the site"); - - // Wait until the translate infobar disappears. - GREYAssert([self waitForElementToDisappearOrTimeout:TranslateInfobar()], - @"Translate infobar failed to disappear."); - - // Reload the page. - [ChromeEarlGrey reload]; - - // Make sure the translate infobar does not appear. - GREYAssertFalse([self waitForElementToAppearOrTimeout:TranslateInfobar()], - @"Translate infobar appeared."); -} - -// Tests that the "Translate..." button in the tools menu is enabled if -// translate is available and it brings up the Translate infobar and translates -// the page when tapped. If the page is already translated the infobar should -// appear in "after translate" state. -- (void)testTranslateManualTrigger { - if (IsInfobarUIRebootEnabled()) { - EARL_GREY_TEST_DISABLED(@"Legacy Test."); - } - // Start the HTTP server. - std::unique_ptr<web::DataResponseProvider> provider(new TestResponseProvider); - web::test::SetUpHttpServer(std::move(provider)); - - // Load a page with French text. - GURL URL = web::test::HttpServer::MakeUrl( - base::StringPrintf("http://%s", kFrenchPagePath)); - [ChromeEarlGrey loadURL:URL]; - - [self assertTranslateInfobarIsVisible]; - - // The source language tab must be selected and the target language tab must - // not. - [[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabel(@"French")] - assertWithMatcher:ElementIsSelected(YES)]; - [[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabel(@"English")] - assertWithMatcher:ElementIsSelected(NO)]; - - // Dismiss the translate infobar. - [[EarlGrey selectElementWithMatcher:CloseButton()] performAction:grey_tap()]; - - // Wait until the translate infobar disappears. - ConditionBlock condition = ^{ - NSError* error = nil; - [[EarlGrey selectElementWithMatcher:TranslateInfobar()] - assertWithMatcher:grey_nil() - error:&error]; - return error == nil; - }; - GREYAssert(WaitUntilConditionOrTimeout(kWaitForUIElementTimeout, condition), - @"Translate infobar failed to disappear."); - - // Make sure the Translate manual trigger button is enabled and tap it. - [ChromeEarlGreyUI openToolsMenu]; - [[[[EarlGrey selectElementWithMatcher:toolsMenuTranslateButton()] - usingSearchAction:grey_scrollInDirection(kGREYDirectionDown, 250) - onElementWithMatcher:ToolsMenuView()] - assertWithMatcher:grey_not(grey_accessibilityTrait( - UIAccessibilityTraitNotEnabled))] - performAction:grey_tap()]; - - // Make sure the infobar reappears. - [self assertTranslateInfobarIsVisible]; - - // The target language tab must be selected and the source language tab must - // not. - [[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabel(@"English")] - assertWithMatcher:ElementIsSelected(YES)]; - [[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabel(@"French")] - assertWithMatcher:ElementIsSelected(NO)]; - - // Make sure the page is translated. - [ChromeEarlGrey waitForWebStateContainingText:"Translated"]; - - // Dismiss the translate infobar. - [[EarlGrey selectElementWithMatcher:CloseButton()] performAction:grey_tap()]; - - // Make sure the Translate manual trigger button is enabled and tap it. - [ChromeEarlGreyUI openToolsMenu]; - [[[[EarlGrey selectElementWithMatcher:toolsMenuTranslateButton()] - usingSearchAction:grey_scrollInDirection(kGREYDirectionDown, 250) - onElementWithMatcher:ToolsMenuView()] - assertWithMatcher:grey_not(grey_accessibilityTrait( - UIAccessibilityTraitNotEnabled))] - performAction:grey_tap()]; - - // Make sure the infobar reappears. - [self assertTranslateInfobarIsVisible]; - - // The target language tab must be selected and the source language tab must - // not. - [[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabel(@"English")] - assertWithMatcher:ElementIsSelected(YES)]; - [[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabel(@"French")] - assertWithMatcher:ElementIsSelected(NO)]; -} - -// Tests that the "Translate..." button in the tools menu brings up the -// Translate infobar even if user has previously selected not to translate the -// the source language. -- (void)testTranslateManualTriggerNeverTranslate { - if (IsInfobarUIRebootEnabled()) { - EARL_GREY_TEST_DISABLED(@"Legacy Test."); - } - // Start the HTTP server. - std::unique_ptr<web::DataResponseProvider> provider(new TestResponseProvider); - web::test::SetUpHttpServer(std::move(provider)); - - // Load a page with French text. - GURL URL = web::test::HttpServer::MakeUrl( - base::StringPrintf("http://%s", kFrenchPagePath)); - [ChromeEarlGrey loadURL:URL]; - - [self assertTranslateInfobarIsVisible]; - - // Open the translate options menu. - [[EarlGrey selectElementWithMatcher:OptionsButton()] - performAction:grey_tap()]; - - // Tap the "Never Translate French" entry. - [[EarlGrey selectElementWithMatcher:NeverTranslate(@"French")] - performAction:grey_tap()]; - - // Tap the notification snackbar to dismiss it. - NSString* snackbarTitle = - l10n_util::GetNSStringF(IDS_TRANSLATE_NOTIFICATION_LANGUAGE_NEVER, - base::SysNSStringToUTF16(@"French")); - [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(snackbarTitle)] - performAction:grey_tap()]; - - // Wait until the translate infobar disappears. - GREYAssert([self waitForElementToDisappearOrTimeout:TranslateInfobar()], - @"Translate infobar failed to disappear."); - - // Reload the page. - [ChromeEarlGrey reload]; - - // Make sure the translate infobar does not appear. - GREYAssertFalse([self waitForElementToAppearOrTimeout:TranslateInfobar()], - @"Translate infobar appeared."); - - // Tap the Translate manual trigger button. - [ChromeEarlGreyUI openToolsMenu]; - [[[EarlGrey selectElementWithMatcher:toolsMenuTranslateButton()] - usingSearchAction:grey_scrollInDirection(kGREYDirectionDown, 250) - onElementWithMatcher:ToolsMenuView()] performAction:grey_tap()]; - - // Make sure the infobar reappears. - [self assertTranslateInfobarIsVisible]; -} - -// Tests that the "Translate..." button in the tools menu brings up the -// Translate infobar even if user has previously selected not to translate the -// the site. -- (void)testTranslateManualTriggerNeverTranslateSite { - if (IsInfobarUIRebootEnabled()) { - EARL_GREY_TEST_DISABLED(@"Legacy Test."); - } - // Start the HTTP server. - std::unique_ptr<web::DataResponseProvider> provider(new TestResponseProvider); - web::test::SetUpHttpServer(std::move(provider)); - - // Load a page with French text. - GURL URL = web::test::HttpServer::MakeUrl( - base::StringPrintf("http://%s", kFrenchPagePath)); - [ChromeEarlGrey loadURL:URL]; - - [self assertTranslateInfobarIsVisible]; - - // Open the translate options menu. - [[EarlGrey selectElementWithMatcher:OptionsButton()] - performAction:grey_tap()]; - - // Tap the "Never Translate this site" entry. - [[EarlGrey selectElementWithMatcher:NeverTranslateSite()] - performAction:grey_tap()]; - - // Tap the notification snackbar to dismiss it. - NSString* snackbarTitle = - l10n_util::GetNSString(IDS_TRANSLATE_NOTIFICATION_SITE_NEVER); - [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(snackbarTitle)] - performAction:grey_tap()]; - - // Wait until the translate infobar disappears. - GREYAssert([self waitForElementToDisappearOrTimeout:TranslateInfobar()], - @"Translate infobar failed to disappear."); - - // Reload the page. - [ChromeEarlGrey reload]; - - // Make sure the translate infobar does not appear. - GREYAssertFalse([self waitForElementToAppearOrTimeout:TranslateInfobar()], - @"Translate infobar appeared."); - - // Tap the Translate manual trigger button. - [ChromeEarlGreyUI openToolsMenu]; - [[[EarlGrey selectElementWithMatcher:toolsMenuTranslateButton()] - usingSearchAction:grey_scrollInDirection(kGREYDirectionDown, 250) - onElementWithMatcher:ToolsMenuView()] performAction:grey_tap()]; - - // Make sure the infobar reappears. - [self assertTranslateInfobarIsVisible]; -} - -// Tests that the "Translate..." button in the tools menu is disabled if -// translate is not available. -- (void)testTranslateManualTriggerNotEnabled { - if (IsInfobarUIRebootEnabled()) { - EARL_GREY_TEST_DISABLED(@"Legacy Test."); - } - // Start the HTTP server. - std::unique_ptr<web::DataResponseProvider> provider(new TestResponseProvider); - web::test::SetUpHttpServer(std::move(provider)); - - // Load a page with French text with |content="notranslate"| meta tag. - GURL noTranslateContentURL = web::test::HttpServer::MakeUrl( - base::StringPrintf("http://%s", kFrenchPageNoTranslateContent)); - [ChromeEarlGrey loadURL:noTranslateContentURL]; - - // Make sure no language has been detected. - GREYAssertFalse([self waitForLanguageDetection], - @"A language has been detected"); - - // Make sure the Translate manual trigger button is not enabled. - [ChromeEarlGreyUI openToolsMenu]; - [[[EarlGrey selectElementWithMatcher:toolsMenuTranslateButton()] - usingSearchAction:grey_scrollInDirection(kGREYDirectionDown, 200) - onElementWithMatcher:ToolsMenuView()] - assertWithMatcher:grey_accessibilityTrait( - UIAccessibilityTraitNotEnabled)]; - // Close the tools menu. - [ChromeTestCase removeAnyOpenMenusAndInfoBars]; - - // Load a page with French text with |value="notranslate"| meta tag. - GURL noTranslateValueURL = web::test::HttpServer::MakeUrl( - base::StringPrintf("http://%s", kFrenchPageNoTranslateValue)); - [ChromeEarlGrey loadURL:noTranslateValueURL]; - - // Make sure no language has been detected. - GREYAssertFalse([self waitForLanguageDetection], - @"A language has been detected"); - - // Make sure the Translate manual trigger button is not enabled. - [ChromeEarlGreyUI openToolsMenu]; - [[[EarlGrey selectElementWithMatcher:toolsMenuTranslateButton()] - usingSearchAction:grey_scrollInDirection(kGREYDirectionDown, 200) - onElementWithMatcher:ToolsMenuView()] - assertWithMatcher:grey_accessibilityTrait( - UIAccessibilityTraitNotEnabled)]; - // Close the tools menu. - [ChromeTestCase removeAnyOpenMenusAndInfoBars]; - - // Load a chrome:// page. - GURL URL = web::test::HttpServer::MakeUrl("chrome://something-internal"); - [ChromeEarlGrey loadURL:URL]; - - // Make sure the Translate manual trigger button is not enabled. - [ChromeEarlGreyUI openToolsMenu]; - [[[EarlGrey selectElementWithMatcher:toolsMenuTranslateButton()] - usingSearchAction:grey_scrollInDirection(kGREYDirectionDown, 200) - onElementWithMatcher:ToolsMenuView()] - assertWithMatcher:grey_accessibilityTrait( - UIAccessibilityTraitNotEnabled)]; - // Close the tools menu. - [ChromeTestCase removeAnyOpenMenusAndInfoBars]; -} - -#pragma mark - Utility methods - -- (void)assertTranslateInfobarIsVisible { - // Wait until the translate infobar becomes visible. - GREYAssert([self waitForElementToAppearOrTimeout:TranslateInfobar()], - @"Translate infobar failed to show."); - - // Check that the translate infobar is fully visible. - [[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabel(@"French")] - assertWithMatcher:grey_sufficientlyVisible()]; - [[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabel(@"English")] - assertWithMatcher:grey_sufficientlyVisible()]; - [[EarlGrey selectElementWithMatcher:OptionsButton()] - assertWithMatcher:grey_sufficientlyVisible()]; - [[EarlGrey selectElementWithMatcher:CloseButton()] - assertWithMatcher:grey_sufficientlyVisible()]; -} - -- (BOOL)waitForElementToAppearOrTimeout:(id<GREYMatcher>)matcher { - ConditionBlock condition = ^{ - NSError* error = nil; - [[EarlGrey selectElementWithMatcher:matcher] assertWithMatcher:grey_notNil() - error:&error]; - return error == nil; - }; - return WaitUntilConditionOrTimeout(kWaitForUIElementTimeout, condition); -} - -- (BOOL)waitForElementToDisappearOrTimeout:(id<GREYMatcher>)matcher { - ConditionBlock condition = ^{ - NSError* error = nil; - [[EarlGrey selectElementWithMatcher:matcher] assertWithMatcher:grey_nil() - error:&error]; - return error == nil; - }; - return WaitUntilConditionOrTimeout(kWaitForUIElementTimeout, condition); -} - -// Returns whether a language has been detected on the current page. Returns -// false if a timeout was detected while waiting for language detection. -- (BOOL)waitForLanguageDetection { - bool detected = WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{ - return [TranslateAppInterface isLanguageDetected]; - }); - return detected; -} - -// Waits until language details have been detected then verifies them. -// Checks expectation for Content-Language, HTML root element language, and -// detected language on page. Use @"" for expected values that are expected -// to be not set. -- (void)assertContentLanguage:(NSString*)expectedContentLanguage - htmlRootLanguage:(NSString*)expectedHtmlRootLanguage - adoptedLanguage:(NSString*)expectedAdoptedLanguage { - GREYAssert([self waitForLanguageDetection], @"Language not detected"); - - NSString* contentLanguage = [TranslateAppInterface contentLanguage]; - NSString* contentLanguageError = - [NSString stringWithFormat:@"Wrong content-language: %@ (expected %@)", - contentLanguage, expectedContentLanguage]; - GREYAssertEqualObjects(expectedContentLanguage, contentLanguage, - contentLanguageError); - - NSString* htmlRootLanguage = [TranslateAppInterface htmlRootLanguage]; - NSString* htmlRootLanguageError = - [NSString stringWithFormat:@"Wrong html root language: %@ (expected %@)", - htmlRootLanguage, expectedHtmlRootLanguage]; - GREYAssertEqualObjects(expectedHtmlRootLanguage, htmlRootLanguage, - htmlRootLanguageError); - - NSString* adoptedLanguage = [TranslateAppInterface adoptedLanguage]; - NSString* adoptedLanguageError = - [NSString stringWithFormat:@"Wrong adopted language: %@ (expected %@)", - adoptedLanguage, expectedAdoptedLanguage]; - GREYAssertEqualObjects(expectedAdoptedLanguage, adoptedLanguage, - adoptedLanguageError); -} - -@end
diff --git a/ios/chrome/browser/ui/authentication/BUILD.gn b/ios/chrome/browser/ui/authentication/BUILD.gn index d9c54b1..49ff4e43 100644 --- a/ios/chrome/browser/ui/authentication/BUILD.gn +++ b/ios/chrome/browser/ui/authentication/BUILD.gn
@@ -147,6 +147,7 @@ "signin_earl_grey_app_interface.h", "signin_earl_grey_app_interface.mm", ] + visibility = [ "//ios/chrome/test/earl_grey:eg_app_support+eg2" ] deps = [ ":authentication", "unified_consent",
diff --git a/ios/chrome/browser/ui/authentication/signin/signin_coordinator_egtest.mm b/ios/chrome/browser/ui/authentication/signin/signin_coordinator_egtest.mm index 463279b8..e561194a 100644 --- a/ios/chrome/browser/ui/authentication/signin/signin_coordinator_egtest.mm +++ b/ios/chrome/browser/ui/authentication/signin/signin_coordinator_egtest.mm
@@ -101,7 +101,7 @@ performAction:grey_tap()]; // Check the signed-in user did change. - [SigninEarlGrey checkSignedInWithFakeIdentity:fakeIdentity2]; + [SigninEarlGrey verifySignedInWithFakeIdentity:fakeIdentity2]; [[EarlGrey selectElementWithMatcher:SettingsDoneButton()] performAction:grey_tap()]; @@ -133,7 +133,7 @@ [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; // Check |fakeIdentity| is signed-in. - [SigninEarlGrey checkSignedInWithFakeIdentity:fakeIdentity]; + [SigninEarlGrey verifySignedInWithFakeIdentity:fakeIdentity]; } // Tests signing in with one account, switching sync account to a second and @@ -174,7 +174,7 @@ signOutWithSignOutConfirmation:SignOutConfirmationManagedUser]; // Check that there is no signed in user. - [SigninEarlGrey checkSignedOut]; + [SigninEarlGrey verifySignedOut]; } // Tests that signing in, tapping the Settings link on the confirmation screen @@ -196,7 +196,7 @@ [[EarlGrey selectElementWithMatcher:settings_matcher] assertWithMatcher:grey_sufficientlyVisible()]; // Test the user is signed in. - [SigninEarlGrey checkSignedInWithFakeIdentity:fakeIdentity]; + [SigninEarlGrey verifySignedInWithFakeIdentity:fakeIdentity]; } // Opens the sign in screen and then cancel it by opening a new tab. Ensures @@ -290,7 +290,7 @@ performAction:grey_tap()]; [[EarlGrey selectElementWithMatcher:SettingsDoneButton()] performAction:grey_tap()]; - [SigninEarlGrey checkSignedOut]; + [SigninEarlGrey verifySignedOut]; } // Opens the sign in screen from the bookmarks and then cancel it by tapping on @@ -420,7 +420,7 @@ ButtonWithAccessibilityLabel(GetNSString( IDS_IOS_ADVANCED_SIGNIN_SETTINGS_CANCEL_SYNC_ALERT_CANCEL_SYNC_BUTTON))] performAction:grey_tap()]; - [SigninEarlGrey checkSignedOut]; + [SigninEarlGrey verifySignedOut]; } #pragma mark - Utils @@ -482,10 +482,10 @@ if (tapSettingsLink) { // Should be signed in. - [SigninEarlGrey checkSignedInWithFakeIdentity:fakeIdentity]; + [SigninEarlGrey verifySignedInWithFakeIdentity:fakeIdentity]; } else { // Should be not signed in. - [SigninEarlGrey checkSignedOut]; + [SigninEarlGrey verifySignedOut]; } } @@ -493,7 +493,7 @@ // onscreen. - (void)assertFakeSSOScreenIsVisible { // Check for the fake SSO screen. - [SigninEarlGrey + [ChromeEarlGrey waitForMatcher:grey_accessibilityID(kFakeAddAccountViewIdentifier)]; // Close the SSO view controller. id<GREYMatcher> matcher = @@ -540,7 +540,7 @@ // Open the identity chooser. [ChromeEarlGreyUI openSettingsMenu]; [ChromeEarlGreyUI tapSettingsMenuButton:SecondarySignInButton()]; - [SigninEarlGrey waitForMatcher:identityChooserButtonMatcherWithEmail( + [ChromeEarlGrey waitForMatcher:identityChooserButtonMatcherWithEmail( fakeIdentity.userEmail)]; // Remove the fake identity.
diff --git a/ios/chrome/browser/ui/authentication/signin_earl_grey.h b/ios/chrome/browser/ui/authentication/signin_earl_grey.h index ba2004c..4d5e07b 100644 --- a/ios/chrome/browser/ui/authentication/signin_earl_grey.h +++ b/ios/chrome/browser/ui/authentication/signin_earl_grey.h
@@ -36,15 +36,19 @@ // simulate identity removal from the device. - (void)forgetFakeIdentity:(FakeChromeIdentity*)fakeIdentity; +// Signs the user out of the primary account. Induces a GREYAssert if the +// app fails to sign out. +- (void)signOut; + // Induces a GREYAssert if |fakeIdentity| is not signed in to the active // profile. -- (void)checkSignedInWithFakeIdentity:(FakeChromeIdentity*)fakeIdentity; +- (void)verifySignedInWithFakeIdentity:(FakeChromeIdentity*)fakeIdentity; // Induces a GREYAssert if an identity is signed in. -- (void)checkSignedOut; +- (void)verifySignedOut; -// Wait until |matcher| is accessible (not nil). -- (void)waitForMatcher:(id<GREYMatcher>)matcher; +// Induces a GREYAssert if there are no signed-in identities. +- (void)verifyAuthenticated; @end
diff --git a/ios/chrome/browser/ui/authentication/signin_earl_grey.mm b/ios/chrome/browser/ui/authentication/signin_earl_grey.mm index 6c6763b..72ff0411 100644 --- a/ios/chrome/browser/ui/authentication/signin_earl_grey.mm +++ b/ios/chrome/browser/ui/authentication/signin_earl_grey.mm
@@ -35,7 +35,12 @@ [SigninEarlGreyAppInterface forgetFakeIdentity:fakeIdentity]; } -- (void)checkSignedInWithFakeIdentity:(FakeChromeIdentity*)fakeIdentity { +- (void)signOut { + [SigninEarlGreyAppInterface signOut]; + [self verifySignedOut]; +} + +- (void)verifySignedInWithFakeIdentity:(FakeChromeIdentity*)fakeIdentity { BOOL fakeIdentityIsNonNil = fakeIdentity != nil; EG_TEST_HELPER_ASSERT_TRUE(fakeIdentityIsNonNil, @"Need to give an identity"); @@ -63,7 +68,7 @@ [fakeIdentity.gaiaID isEqualToString:primaryAccountGaiaID], errorStr); } -- (void)checkSignedOut { +- (void)verifySignedOut { // Required to avoid any problem since the following test is not dependant to // UI, and the previous action has to be totally finished before going through // the assert. @@ -73,16 +78,9 @@ @"Unexpected signed in user"); } -- (void)waitForMatcher:(id<GREYMatcher>)matcher { - ConditionBlock condition = ^{ - NSError* error = nil; - [[EarlGrey selectElementWithMatcher:matcher] assertWithMatcher:grey_notNil() - error:&error]; - return error == nil; - }; - GREYAssert(base::test::ios::WaitUntilConditionOrTimeout( - base::test::ios::kWaitForUIElementTimeout, condition), - @"Waiting for matcher %@ failed.", matcher); +- (void)verifyAuthenticated { + EG_TEST_HELPER_ASSERT_TRUE([SigninEarlGreyAppInterface isAuthenticated], + @"User is not signed in"); } @end
diff --git a/ios/chrome/browser/ui/authentication/signin_earl_grey_ui.mm b/ios/chrome/browser/ui/authentication/signin_earl_grey_ui.mm index 648ba391..830242a 100644 --- a/ios/chrome/browser/ui/authentication/signin_earl_grey_ui.mm +++ b/ios/chrome/browser/ui/authentication/signin_earl_grey_ui.mm
@@ -11,6 +11,7 @@ #import "ios/chrome/browser/ui/authentication/unified_consent/unified_consent_constants.h" #import "ios/chrome/browser/ui/settings/google_services/accounts_table_view_controller_constants.h" #include "ios/chrome/grit/ios_strings.h" +#import "ios/chrome/test/earl_grey/chrome_earl_grey.h" #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h" #import "ios/chrome/test/earl_grey/chrome_matchers.h" #import "ios/chrome/test/earl_grey/chrome_matchers_app_interface.h" @@ -49,7 +50,7 @@ } [[EarlGrey selectElementWithMatcher:SettingsDoneButton()] performAction:grey_tap()]; - [SigninEarlGrey checkSignedInWithFakeIdentity:fakeIdentity]; + [SigninEarlGrey verifySignedInWithFakeIdentity:fakeIdentity]; } + (void)selectIdentityWithEmail:(NSString*)userEmail { @@ -74,7 +75,7 @@ ScopedSynchronizationDisabler disabler; id<GREYMatcher> acceptButton = [ChromeMatchersAppInterface buttonWithAccessibilityLabelID:IDS_IOS_MANAGED_SIGNIN_ACCEPT_BUTTON]; - [SigninEarlGrey waitForMatcher:acceptButton]; + [ChromeEarlGrey waitForMatcher:acceptButton]; [[EarlGrey selectElementWithMatcher:acceptButton] performAction:grey_tap()]; } @@ -224,7 +225,7 @@ [ChromeEarlGreyUI waitForAppToIdle]; [[EarlGrey selectElementWithMatcher:SettingsDoneButton()] performAction:grey_tap()]; - [SigninEarlGrey checkSignedOut]; + [SigninEarlGrey verifySignedOut]; } + (void)tapRemoveAccountFromDeviceWithFakeIdentity:
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/address_view_controller_egtest.mm b/ios/chrome/browser/ui/autofill/manual_fill/address_view_controller_egtest.mm index 00abbdf..55ecb67 100644 --- a/ios/chrome/browser/ui/autofill/manual_fill/address_view_controller_egtest.mm +++ b/ios/chrome/browser/ui/autofill/manual_fill/address_view_controller_egtest.mm
@@ -87,7 +87,15 @@ // Tests that the addresses view controller contains the "Manage Addresses..." // action. -- (void)testAddressesViewControllerContainsManageAddressesAction { +// TODO(crbug.com/1116043): Flaky on ios simulator. +#if TARGET_IPHONE_SIMULATOR +#define MAYBE_testAddressesViewControllerContainsManageAddressesAction \ + DISABLED_testAddressesViewControllerContainsManageAddressesAction +#else +#define MAYBE_testAddressesViewControllerContainsManageAddressesAction \ + testAddressesViewControllerContainsManageAddressesAction +#endif +- (void)MAYBE_testAddressesViewControllerContainsManageAddressesAction { // Bring up the keyboard. [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()] performAction:chrome_test_util::TapWebElementWithId(kFormElementName)];
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/fallback_coordinator_egtest.mm b/ios/chrome/browser/ui/autofill/manual_fill/fallback_coordinator_egtest.mm index e22026e..886523b 100644 --- a/ios/chrome/browser/ui/autofill/manual_fill/fallback_coordinator_egtest.mm +++ b/ios/chrome/browser/ui/autofill/manual_fill/fallback_coordinator_egtest.mm
@@ -355,8 +355,7 @@ // When keyboard is split, icons are not visible, so we rely on timeout before // docking again, because EarlGrey synchronization isn't working properly with // the keyboard. - [self waitForMatcherToBeVisible:ManualFallbackProfilesIconMatcher() - timeout:base::test::ios::kWaitForUIElementTimeout]; + [ChromeEarlGrey waitForMatcher:ManualFallbackProfilesIconMatcher()]; DockKeyboard(); @@ -432,8 +431,7 @@ // When keyboard is split, icons are not visible, so we rely on timeout before // docking again, because EarlGrey synchronization isn't working properly with // the keyboard. - [self waitForMatcherToBeVisible:ManualFallbackProfilesIconMatcher() - timeout:base::test::ios::kWaitForUIElementTimeout]; + [ChromeEarlGrey waitForMatcher:ManualFallbackProfilesIconMatcher()]; DockKeyboard(); @@ -605,22 +603,4 @@ assertWithMatcher:grey_sufficientlyVisible()]; } -#pragma mark - Utilities - -// Waits for the passed matcher to be visible with a given timeout. -- (void)waitForMatcherToBeVisible:(id<GREYMatcher>)matcher - timeout:(CFTimeInterval)timeout { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunused-result" - [[GREYCondition conditionWithName:@"Wait for visible matcher condition" - block:^BOOL { - NSError* error; - [[EarlGrey selectElementWithMatcher:matcher] - assertWithMatcher:grey_sufficientlyVisible() - error:&error]; - return error == nil; - }] waitWithTimeout:timeout]; -#pragma clang diagnostic pop -} - @end
diff --git a/ios/chrome/browser/ui/badges/badge_button_factory.mm b/ios/chrome/browser/ui/badges/badge_button_factory.mm index b0c29f6..b4113627 100644 --- a/ios/chrome/browser/ui/badges/badge_button_factory.mm +++ b/ios/chrome/browser/ui/badges/badge_button_factory.mm
@@ -47,7 +47,7 @@ - (BadgeButton*)passwordsSaveBadgeButton { BadgeButton* button = [self createButtonForType:BadgeType::kBadgeTypePasswordSave - imageNamed:@"infobar_passwords_icon" + imageNamed:@"password_key" renderingMode:UIImageRenderingModeAlwaysTemplate]; [button addTarget:self.delegate action:@selector(passwordsBadgeButtonTapped:) @@ -62,7 +62,7 @@ - (BadgeButton*)passwordsUpdateBadgeButton { BadgeButton* button = [self createButtonForType:BadgeType::kBadgeTypePasswordUpdate - imageNamed:@"infobar_passwords_icon" + imageNamed:@"password_key" renderingMode:UIImageRenderingModeAlwaysTemplate]; [button addTarget:self.delegate action:@selector(passwordsBadgeButtonTapped:)
diff --git a/ios/chrome/browser/ui/badges/badge_popup_menu_item.mm b/ios/chrome/browser/ui/badges/badge_popup_menu_item.mm index e80626a..12f2e80 100644 --- a/ios/chrome/browser/ui/badges/badge_popup_menu_item.mm +++ b/ios/chrome/browser/ui/badges/badge_popup_menu_item.mm
@@ -93,7 +93,7 @@ switch (self.badgeType) { case BadgeType::kBadgeTypePasswordSave: case BadgeType::kBadgeTypePasswordUpdate: - badgeImage = [[UIImage imageNamed:@"infobar_passwords_icon"] + badgeImage = [[UIImage imageNamed:@"password_key"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; break; case BadgeType::kBadgeTypeSaveCard:
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm b/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm index 5c1247a0..a7193da 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm
@@ -2267,6 +2267,29 @@ return [UIMenu menuWithTitle:@"" children:menuElements]; }; + } else if (node->is_folder()) { + actionProvider = ^(NSArray<UIMenuElement*>* suggestedActions) { + RecordMenuShown(MenuScenario::kBookmarkFolder); + + ActionFactory* actionFactory = + [[ActionFactory alloc] initWithBrowser:self.browser + scenario:MenuScenario::kBookmarkFolder]; + + NSMutableArray<UIMenuElement*>* menuElements = + [[NSMutableArray alloc] init]; + + [menuElements addObject:[actionFactory actionToEditWithBlock:^{ + [self editNode:node]; + }]]; + + [menuElements addObject:[actionFactory actionToMoveFolderWithBlock:^{ + std::set<const BookmarkNode*> nodes; + nodes.insert(node); + [self moveNodes:nodes]; + }]]; + + return [UIMenu menuWithTitle:@"" children:menuElements]; + }; } return
diff --git a/ios/chrome/browser/ui/content_suggestions/BUILD.gn b/ios/chrome/browser/ui/content_suggestions/BUILD.gn index bd39910..a42ffbd0 100644 --- a/ios/chrome/browser/ui/content_suggestions/BUILD.gn +++ b/ios/chrome/browser/ui/content_suggestions/BUILD.gn
@@ -283,6 +283,7 @@ ":constants", ":content_suggestions_constant", ":eg_test_support+eg2", + ":feature_flags", "//base", "//base/test:test_support", "//components/strings",
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_egtest.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_egtest.mm index 5852eb61..4528577 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_egtest.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_egtest.mm
@@ -14,6 +14,7 @@ #include "components/strings/grit/components_strings.h" #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_app_interface.h" #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_constants.h" +#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_feature.h" #import "ios/chrome/browser/ui/content_suggestions/ntp_home_constant.h" #include "ios/chrome/grit/ios_strings.h" #import "ios/chrome/test/earl_grey/chrome_earl_grey.h" @@ -141,6 +142,9 @@ // Tests that the additional items (when more is pressed) are kept when // switching tabs. - (void)testAdditionalItemsKept { + if (IsDiscoverFeedEnabled()) { + EARL_GREY_TEST_DISABLED(@"Legacy Feed Test."); + } // Set server up. self.testServer->RegisterRequestHandler(base::Bind(&StandardResponse)); GREYAssertTrue(self.testServer->Start(), @"Test server failed to start."); @@ -175,6 +179,9 @@ // Tests that when the page is reloaded using the tools menu, the suggestions // are updated. - (void)testReloadPage { + if (IsDiscoverFeedEnabled()) { + EARL_GREY_TEST_DISABLED(@"Legacy Feed Test."); + } // Add 2 suggestions, persisted accross page loads. [ContentSuggestionsAppInterface addNumberOfSuggestions:2 additionalSuggestionsURL:nil]; @@ -200,6 +207,9 @@ // disposition of the collection takes into account the previous scroll, even // when more is tapped. - (void)testOpenPageAndGoBackWithMoreContent { + if (IsDiscoverFeedEnabled()) { + EARL_GREY_TEST_DISABLED(@"Legacy Feed Test."); + } // Set server up. self.testServer->RegisterRequestHandler(base::Bind(&StandardResponse)); GREYAssertTrue(self.testServer->Start(), @"Test server failed to start."); @@ -248,6 +258,9 @@ // Tests that the "Learn More" cell is present only if there is a suggestion in // the section. - (void)testLearnMore { + if (IsDiscoverFeedEnabled()) { + EARL_GREY_TEST_DISABLED(@"Legacy Feed Test."); + } id<GREYAction> action = grey_scrollInDirectionWithStartPoint(kGREYDirectionDown, 200, 0.5, 0.5); [[[EarlGrey
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 1d15030..172a446 100644 --- a/ios/chrome/browser/ui/first_run/first_run_egtest.mm +++ b/ios/chrome/browser/ui/first_run/first_run_egtest.mm
@@ -140,7 +140,7 @@ [[EarlGrey selectElementWithMatcher:SyncSettingsConfirmButton()] performAction:grey_tap()]; - [SigninEarlGrey checkSignedInWithFakeIdentity:fakeIdentity]; + [SigninEarlGrey verifySignedInWithFakeIdentity:fakeIdentity]; GREYAssertTrue([FirstRunAppInterface isSyncFirstSetupComplete], @"Sync should have finished its original setup");
diff --git a/ios/chrome/browser/ui/infobars/BUILD.gn b/ios/chrome/browser/ui/infobars/BUILD.gn index 820563c..d7af0e60 100644 --- a/ios/chrome/browser/ui/infobars/BUILD.gn +++ b/ios/chrome/browser/ui/infobars/BUILD.gn
@@ -76,7 +76,6 @@ ":public", "resources:infobar_downloading", "resources:infobar_hide_password_icon", - "resources:infobar_passwords_icon", "resources:infobar_popup_blocker", "resources:infobar_reveal_password_icon", "resources:infobar_save_card_icon", @@ -94,6 +93,7 @@ "//ios/chrome/browser/ui/fancy_ui", "//ios/chrome/browser/ui/fullscreen", "//ios/chrome/browser/ui/fullscreen:ui", + "//ios/chrome/browser/ui/resources:password_key", "//ios/chrome/browser/ui/toolbar/public", "//ios/chrome/browser/ui/util", "//ios/chrome/common/ui/colors",
diff --git a/ios/chrome/browser/ui/infobars/coordinators/infobar_password_coordinator.mm b/ios/chrome/browser/ui/infobars/coordinators/infobar_password_coordinator.mm index 46ee8927..76acd1f 100644 --- a/ios/chrome/browser/ui/infobars/coordinators/infobar_password_coordinator.mm +++ b/ios/chrome/browser/ui/infobars/coordinators/infobar_password_coordinator.mm
@@ -86,8 +86,7 @@ self.bannerViewController.buttonText = base::SysUTF16ToNSString(self.passwordInfoBarDelegate->GetButtonLabel( ConfirmInfoBarDelegate::BUTTON_OK)); - self.bannerViewController.iconImage = - [UIImage imageNamed:@"infobar_passwords_icon"]; + self.bannerViewController.iconImage = [UIImage imageNamed:@"password_key"]; NSString* hiddenPasswordText = l10n_util::GetNSString(IDS_IOS_SETTINGS_PASSWORD_HIDDEN_LABEL); [self.bannerViewController
diff --git a/ios/chrome/browser/ui/infobars/resources/BUILD.gn b/ios/chrome/browser/ui/infobars/resources/BUILD.gn index 8966145..60b4ef7 100644 --- a/ios/chrome/browser/ui/infobars/resources/BUILD.gn +++ b/ios/chrome/browser/ui/infobars/resources/BUILD.gn
@@ -31,15 +31,6 @@ ] } -imageset("infobar_passwords_icon") { - sources = [ - "infobar_passwords_icon.imageset/Contents.json", - "infobar_passwords_icon.imageset/infobar_passwords_icon.png", - "infobar_passwords_icon.imageset/infobar_passwords_icon@2x.png", - "infobar_passwords_icon.imageset/infobar_passwords_icon@3x.png", - ] -} - imageset("infobar_reveal_password_icon") { sources = [ "infobar_reveal_password_icon.imageset/Contents.json",
diff --git a/ios/chrome/browser/ui/infobars/resources/infobar_passwords_icon.imageset/Contents.json b/ios/chrome/browser/ui/infobars/resources/infobar_passwords_icon.imageset/Contents.json deleted file mode 100644 index 7be13cb..0000000 --- a/ios/chrome/browser/ui/infobars/resources/infobar_passwords_icon.imageset/Contents.json +++ /dev/null
@@ -1,23 +0,0 @@ -{ - "images": [ - { - "idiom": "universal", - "scale": "1x", - "filename": "infobar_passwords_icon.png" - }, - { - "idiom": "universal", - "scale": "2x", - "filename": "infobar_passwords_icon@2x.png" - }, - { - "idiom": "universal", - "scale": "3x", - "filename": "infobar_passwords_icon@3x.png" - } - ], - "info": { - "version": 1, - "author": "xcode" - } -}
diff --git a/ios/chrome/browser/ui/infobars/resources/infobar_passwords_icon.imageset/infobar_passwords_icon.png b/ios/chrome/browser/ui/infobars/resources/infobar_passwords_icon.imageset/infobar_passwords_icon.png deleted file mode 100644 index ccc86e8..0000000 --- a/ios/chrome/browser/ui/infobars/resources/infobar_passwords_icon.imageset/infobar_passwords_icon.png +++ /dev/null Binary files differ
diff --git a/ios/chrome/browser/ui/infobars/resources/infobar_passwords_icon.imageset/infobar_passwords_icon@2x.png b/ios/chrome/browser/ui/infobars/resources/infobar_passwords_icon.imageset/infobar_passwords_icon@2x.png deleted file mode 100644 index 0935d37..0000000 --- a/ios/chrome/browser/ui/infobars/resources/infobar_passwords_icon.imageset/infobar_passwords_icon@2x.png +++ /dev/null Binary files differ
diff --git a/ios/chrome/browser/ui/infobars/resources/infobar_passwords_icon.imageset/infobar_passwords_icon@3x.png b/ios/chrome/browser/ui/infobars/resources/infobar_passwords_icon.imageset/infobar_passwords_icon@3x.png deleted file mode 100644 index 6151d22..0000000 --- a/ios/chrome/browser/ui/infobars/resources/infobar_passwords_icon.imageset/infobar_passwords_icon@3x.png +++ /dev/null Binary files differ
diff --git a/ios/chrome/browser/ui/infobars/translate_infobar_egtest.mm b/ios/chrome/browser/ui/infobars/translate_infobar_egtest.mm index 845f7897..73213c5 100644 --- a/ios/chrome/browser/ui/infobars/translate_infobar_egtest.mm +++ b/ios/chrome/browser/ui/infobars/translate_infobar_egtest.mm
@@ -740,6 +740,11 @@ // Tests that the target language can be changed. TODO(crbug.com/1046629): // implement test for changing source langauge. - (void)testInfobarChangeTargetLanguage { + // TODO(crbug.com/1116012): This test is failing flaky on iOS14. + if (@available(iOS 14, *)) { + EARL_GREY_TEST_DISABLED(@"Test disabled on iOS14."); + } + // Start the HTTP server. std::unique_ptr<web::DataResponseProvider> provider(new TestResponseProvider); web::test::SetUpHttpServer(std::move(provider));
diff --git a/ios/chrome/browser/ui/menu/BUILD.gn b/ios/chrome/browser/ui/menu/BUILD.gn index ab8d181..f690200a 100644 --- a/ios/chrome/browser/ui/menu/BUILD.gn +++ b/ios/chrome/browser/ui/menu/BUILD.gn
@@ -15,6 +15,7 @@ "resources:copy_link_url", "resources:delete", "resources:edit", + "resources:move_folder", "resources:open_in_incognito", "resources:open_in_new_tab", "resources:open_new_window", @@ -41,6 +42,7 @@ "resources:copy_link_url", "resources:delete", "resources:edit", + "resources:move_folder", "resources:open_in_incognito", "resources:open_in_new_tab", "resources:open_new_window",
diff --git a/ios/chrome/browser/ui/menu/action_factory.h b/ios/chrome/browser/ui/menu/action_factory.h index e39cbec9..7d89887 100644 --- a/ios/chrome/browser/ui/menu/action_factory.h +++ b/ios/chrome/browser/ui/menu/action_factory.h
@@ -90,6 +90,10 @@ // the given hiding |block| when executed. - (UIAction*)actionToHideWithBlock:(ProceduralBlock)block; +// Creates a UIAction instance configured for moving a folder which will invoke +// the given |block| when executed. +- (UIAction*)actionToMoveFolderWithBlock:(ProceduralBlock)block; + @end #endif // IOS_CHROME_BROWSER_UI_MENU_ACTION_FACTORY_H_
diff --git a/ios/chrome/browser/ui/menu/action_factory.mm b/ios/chrome/browser/ui/menu/action_factory.mm index 822b6f5..d323892 100644 --- a/ios/chrome/browser/ui/menu/action_factory.mm +++ b/ios/chrome/browser/ui/menu/action_factory.mm
@@ -183,4 +183,12 @@ return action; } +- (UIAction*)actionToMoveFolderWithBlock:(ProceduralBlock)block { + return [self + actionWithTitle:l10n_util::GetNSString(IDS_IOS_BOOKMARK_CONTEXT_MENU_MOVE) + image:[UIImage imageNamed:@"move_folder"] + type:MenuActionType::Move + block:block]; +} + @end
diff --git a/ios/chrome/browser/ui/menu/action_factory_unittest.mm b/ios/chrome/browser/ui/menu/action_factory_unittest.mm index e82c646..f60976c 100644 --- a/ios/chrome/browser/ui/menu/action_factory_unittest.mm +++ b/ios/chrome/browser/ui/menu/action_factory_unittest.mm
@@ -296,4 +296,24 @@ } } +// Tests that the Move Folder action has the right title and image. +TEST_F(ActionFactoryTest, MoveFolderAction) { + if (@available(iOS 13.0, *)) { + ActionFactory* factory = + [[ActionFactory alloc] initWithBrowser:test_browser_.get() + scenario:kTestMenuScenario]; + + UIImage* expectedImage = [UIImage imageNamed:@"move_folder"]; + + NSString* expectedTitle = + l10n_util::GetNSString(IDS_IOS_BOOKMARK_CONTEXT_MENU_MOVE); + + UIAction* action = [factory actionToMoveFolderWithBlock:^{ + }]; + + EXPECT_TRUE([expectedTitle isEqualToString:action.title]); + EXPECT_EQ(expectedImage, action.image); + } +} + #endif // defined(__IPHONE_13_0)
diff --git a/ios/chrome/browser/ui/menu/menu_action_type.h b/ios/chrome/browser/ui/menu/menu_action_type.h index 9a19fa2..825fde5f 100644 --- a/ios/chrome/browser/ui/menu/menu_action_type.h +++ b/ios/chrome/browser/ui/menu/menu_action_type.h
@@ -19,7 +19,8 @@ Share = 7, OpenAllInNewTabs = 8, Hide = 9, - kMaxValue = Hide + Move = 10, + kMaxValue = Move }; #endif // IOS_CHROME_BROWSER_UI_MENU_MENU_ACTION_TYPE_H_
diff --git a/ios/chrome/browser/ui/menu/menu_histograms.h b/ios/chrome/browser/ui/menu/menu_histograms.h index b7c1ef5..f951aa4 100644 --- a/ios/chrome/browser/ui/menu/menu_histograms.h +++ b/ios/chrome/browser/ui/menu/menu_histograms.h
@@ -15,7 +15,8 @@ kRecentTabsEntry = 3, kContentSuggestionsEntry = 4, kRecentTabsHeader = 5, - kMaxValue = kRecentTabsHeader + kBookmarkFolder = 6, + kMaxValue = kBookmarkFolder }; // Records a menu shown histogram metric for the |scenario|.
diff --git a/ios/chrome/browser/ui/menu/menu_histograms.mm b/ios/chrome/browser/ui/menu/menu_histograms.mm index 47a5d289..cb649f7 100644 --- a/ios/chrome/browser/ui/menu/menu_histograms.mm +++ b/ios/chrome/browser/ui/menu/menu_histograms.mm
@@ -19,14 +19,16 @@ "Mobile.ContextMenu.HistoryEntry.Actions"; const char kBookmarkEntryActionsHistogram[] = "Mobile.ContextMenu.BookmarkEntry.Actions"; -const char ReadingListEntryActionsHistogram[] = +const char kReadingListEntryActionsHistogram[] = "Mobile.ContextMenu.ReadingListEntry.Actions"; -const char RecentTabsEntryActionsHistogram[] = +const char kRecentTabsEntryActionsHistogram[] = "Mobile.ContextMenu.RecentTabsEntry.Actions"; -const char RecentTabsHeaderActionsHistogram[] = +const char kRecentTabsHeaderActionsHistogram[] = "Mobile.ContextMenu.RecentTabsHeader.Actions"; -const char ContentSuggestionsEntryActionsHistogram[] = +const char kContentSuggestionsEntryActionsHistogram[] = "Mobile.ContextMenu.ContentSuggestionsEntry.Actions"; +const char kBookmarkFolderActionsHistogram[] = + "Mobile.ContextMenu.BookmarkFolder.Actions"; } // namespace void RecordMenuShown(MenuScenario scenario) { @@ -40,12 +42,14 @@ case MenuScenario::kBookmarkEntry: return kBookmarkEntryActionsHistogram; case MenuScenario::kReadingListEntry: - return ReadingListEntryActionsHistogram; + return kReadingListEntryActionsHistogram; case MenuScenario::kRecentTabsEntry: - return RecentTabsEntryActionsHistogram; + return kRecentTabsEntryActionsHistogram; case MenuScenario::kRecentTabsHeader: - return RecentTabsHeaderActionsHistogram; + return kRecentTabsHeaderActionsHistogram; case MenuScenario::kContentSuggestionsEntry: - return ContentSuggestionsEntryActionsHistogram; + return kContentSuggestionsEntryActionsHistogram; + case MenuScenario::kBookmarkFolder: + return kBookmarkFolderActionsHistogram; } }
diff --git a/ios/chrome/browser/ui/menu/resources/BUILD.gn b/ios/chrome/browser/ui/menu/resources/BUILD.gn index f490f62..e5bbe0b 100644 --- a/ios/chrome/browser/ui/menu/resources/BUILD.gn +++ b/ios/chrome/browser/ui/menu/resources/BUILD.gn
@@ -67,3 +67,11 @@ "share.imageset/share@3x.png", ] } + +imageset("move_folder") { + sources = [ + "move_folder.imageset/Contents.json", + "move_folder.imageset/move_folder@2x.png", + "move_folder.imageset/move_folder@3x.png", + ] +}
diff --git a/ios/chrome/browser/ui/menu/resources/move_folder.imageset/Contents.json b/ios/chrome/browser/ui/menu/resources/move_folder.imageset/Contents.json new file mode 100644 index 0000000..08ac2ef --- /dev/null +++ b/ios/chrome/browser/ui/menu/resources/move_folder.imageset/Contents.json
@@ -0,0 +1,21 @@ +{ + "images": [ + { + "idiom": "universal", + "filename": "move_folder@2x.png", + "scale": "2x" + }, + { + "idiom": "universal", + "filename": "move_folder@3x.png", + "scale": "3x" + } + ], + "info": { + "author": "xcode", + "version": 1 + }, + "properties": { + "template-rendering-intent": "template" + } +} \ No newline at end of file
diff --git a/ios/chrome/browser/ui/menu/resources/move_folder.imageset/move_folder@2x.png b/ios/chrome/browser/ui/menu/resources/move_folder.imageset/move_folder@2x.png new file mode 100644 index 0000000..c62530cd --- /dev/null +++ b/ios/chrome/browser/ui/menu/resources/move_folder.imageset/move_folder@2x.png Binary files differ
diff --git a/ios/chrome/browser/ui/menu/resources/move_folder.imageset/move_folder@3x.png b/ios/chrome/browser/ui/menu/resources/move_folder.imageset/move_folder@3x.png new file mode 100644 index 0000000..ef3716a35 --- /dev/null +++ b/ios/chrome/browser/ui/menu/resources/move_folder.imageset/move_folder@3x.png Binary files differ
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.mm b/ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.mm index af53275..feedb0a 100644 --- a/ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.mm +++ b/ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.mm
@@ -614,8 +614,8 @@ } // If there is pasteboard content, show paste. - if (UIPasteboard.generalPasteboard.string.length > 0 && action == @selector - (paste:)) { + if (UIPasteboard.generalPasteboard.hasStrings && action == @selector + (paste:)) { return YES; }
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_view_ios.h b/ios/chrome/browser/ui/omnibox/omnibox_view_ios.h index ae25572c..fa14adf 100644 --- a/ios/chrome/browser/ui/omnibox/omnibox_view_ios.h +++ b/ios/chrome/browser/ui/omnibox/omnibox_view_ios.h
@@ -39,6 +39,8 @@ ChromeBrowserState* browser_state, id<OmniboxCommands> omnibox_focuser); + ~OmniboxViewIOS() override; + void SetPopupProvider(OmniboxPopupProvider* provider) { popup_provider_ = provider; } @@ -49,6 +51,41 @@ security_state::SecurityLevel security_level, bool in_dark_mode); + void OnReceiveClipboardURLForOpenMatch( + const AutocompleteMatch& match, + WindowOpenDisposition disposition, + const GURL& alternate_nav_url, + const base::string16& pasted_text, + size_t selected_line, + base::TimeTicks match_selection_timestamp, + base::Optional<GURL> optional_gurl); + + void OnReceiveClipboardTextForOpenMatch( + const AutocompleteMatch& match, + WindowOpenDisposition disposition, + const GURL& alternate_nav_url, + const base::string16& pasted_text, + size_t selected_line, + base::TimeTicks match_selection_timestamp, + base::Optional<base::string16> optional_text); + + void OnReceiveClipboardImageForOpenMatch( + const AutocompleteMatch& match, + WindowOpenDisposition disposition, + const GURL& alternate_nav_url, + const base::string16& pasted_text, + size_t selected_line, + base::TimeTicks match_selection_timestamp, + base::Optional<gfx::Image> optional_image); + + void OnReceiveImageMatchForOpenMatch( + WindowOpenDisposition disposition, + const GURL& alternate_nav_url, + const base::string16& pasted_text, + size_t selected_line, + base::TimeTicks match_selection_timestamp, + base::Optional<AutocompleteMatch> optional_match); + // OmniboxView implementation. void OpenMatch(const AutocompleteMatch& match, WindowOpenDisposition disposition, @@ -199,6 +236,9 @@ NSMutableAttributedString* attributing_display_string_; OmniboxPopupProvider* popup_provider_; // weak + + // Used to cancel clipboard callbacks if this is deallocated; + base::WeakPtrFactory<OmniboxViewIOS> weak_ptr_factory_{this}; }; #endif // IOS_CHROME_BROWSER_UI_OMNIBOX_OMNIBOX_VIEW_IOS_H_
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_view_ios.mm b/ios/chrome/browser/ui/omnibox/omnibox_view_ios.mm index 03a259ff..4725004a 100644 --- a/ios/chrome/browser/ui/omnibox/omnibox_view_ios.mm +++ b/ios/chrome/browser/ui/omnibox/omnibox_view_ios.mm
@@ -17,10 +17,12 @@ #include "base/strings/sys_string_conversions.h" #include "components/omnibox/browser/autocomplete_input.h" #include "components/omnibox/browser/autocomplete_match.h" +#include "components/omnibox/browser/clipboard_provider.h" #include "components/omnibox/browser/location_bar_model.h" #include "components/omnibox/browser/omnibox_edit_model.h" #include "components/omnibox/browser/omnibox_popup_model.h" #include "components/omnibox/common/omnibox_focus_state.h" +#include "components/open_from_clipboard/clipboard_recent_content.h" #include "ios/chrome/browser/autocomplete/autocomplete_scheme_classifier_impl.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" #import "ios/chrome/browser/ui/commands/omnibox_commands.h" @@ -95,6 +97,8 @@ !base::ios::IsRunningOnOrLater(11, 2, 0); } +OmniboxViewIOS::~OmniboxViewIOS() = default; + void OmniboxViewIOS::OpenMatch(const AutocompleteMatch& match, WindowOpenDisposition disposition, const GURL& alternate_nav_url, @@ -106,10 +110,125 @@ return; } + // Fill in clipboard matches if they don't have a destination URL. + if (match.destination_url.is_empty()) { + if (match.type == AutocompleteMatchType::CLIPBOARD_URL) { + ClipboardRecentContent* clipboard_recent_content = + ClipboardRecentContent::GetInstance(); + clipboard_recent_content->GetRecentURLFromClipboard(base::BindOnce( + &OmniboxViewIOS::OnReceiveClipboardURLForOpenMatch, + weak_ptr_factory_.GetWeakPtr(), match, disposition, alternate_nav_url, + pasted_text, selected_line, match_selection_timestamp)); + return; + } else if (match.type == AutocompleteMatchType::CLIPBOARD_TEXT) { + ClipboardRecentContent* clipboard_recent_content = + ClipboardRecentContent::GetInstance(); + clipboard_recent_content->GetRecentTextFromClipboard(base::BindOnce( + &OmniboxViewIOS::OnReceiveClipboardTextForOpenMatch, + weak_ptr_factory_.GetWeakPtr(), match, disposition, alternate_nav_url, + pasted_text, selected_line, match_selection_timestamp)); + return; + } else if (match.type == AutocompleteMatchType::CLIPBOARD_IMAGE) { + ClipboardRecentContent* clipboard_recent_content = + ClipboardRecentContent::GetInstance(); + clipboard_recent_content->GetRecentImageFromClipboard(base::BindOnce( + &OmniboxViewIOS::OnReceiveClipboardImageForOpenMatch, + weak_ptr_factory_.GetWeakPtr(), match, disposition, alternate_nav_url, + pasted_text, selected_line, match_selection_timestamp)); + return; + } + } + OmniboxView::OpenMatch(match, disposition, alternate_nav_url, pasted_text, selected_line, match_selection_timestamp); } +void OmniboxViewIOS::OnReceiveClipboardURLForOpenMatch( + const AutocompleteMatch& match, + WindowOpenDisposition disposition, + const GURL& alternate_nav_url, + const base::string16& pasted_text, + size_t selected_line, + base::TimeTicks match_selection_timestamp, + base::Optional<GURL> optional_gurl) { + if (!optional_gurl) { + return; + } + + GURL url = std::move(optional_gurl).value(); + + ClipboardProvider* clipboard_provider = + model()->autocomplete_controller()->clipboard_provider(); + AutocompleteMatch new_match = clipboard_provider->NewClipboardURLMatch(url); + + OmniboxView::OpenMatch(new_match, disposition, alternate_nav_url, pasted_text, + selected_line, match_selection_timestamp); +} + +void OmniboxViewIOS::OnReceiveClipboardTextForOpenMatch( + const AutocompleteMatch& match, + WindowOpenDisposition disposition, + const GURL& alternate_nav_url, + const base::string16& pasted_text, + size_t selected_line, + base::TimeTicks match_selection_timestamp, + base::Optional<base::string16> optional_text) { + if (!optional_text) { + return; + } + + base::string16 text = std::move(optional_text).value(); + + ClipboardProvider* clipboard_provider = + model()->autocomplete_controller()->clipboard_provider(); + base::Optional<AutocompleteMatch> new_match = + clipboard_provider->NewClipboardTextMatch(text); + + if (!new_match) { + return; + } + + OmniboxView::OpenMatch(new_match.value(), disposition, alternate_nav_url, + pasted_text, selected_line, match_selection_timestamp); +} + +void OmniboxViewIOS::OnReceiveClipboardImageForOpenMatch( + const AutocompleteMatch& match, + WindowOpenDisposition disposition, + const GURL& alternate_nav_url, + const base::string16& pasted_text, + size_t selected_line, + base::TimeTicks match_selection_timestamp, + base::Optional<gfx::Image> optional_image) { + if (!optional_image) { + return; + } + + gfx::Image image = std::move(optional_image).value(); + + ClipboardProvider* clipboard_provider = + model()->autocomplete_controller()->clipboard_provider(); + clipboard_provider->NewClipboardImageMatch( + image, base::BindOnce(&OmniboxViewIOS::OnReceiveImageMatchForOpenMatch, + weak_ptr_factory_.GetWeakPtr(), disposition, + alternate_nav_url, pasted_text, selected_line, + match_selection_timestamp)); +} + +void OmniboxViewIOS::OnReceiveImageMatchForOpenMatch( + WindowOpenDisposition disposition, + const GURL& alternate_nav_url, + const base::string16& pasted_text, + size_t selected_line, + base::TimeTicks match_selection_timestamp, + base::Optional<AutocompleteMatch> optional_match) { + if (!optional_match) { + return; + } + OmniboxView::OpenMatch(optional_match.value(), disposition, alternate_nav_url, + pasted_text, selected_line, match_selection_timestamp); +} + base::string16 OmniboxViewIOS::GetText() const { return base::SysNSStringToUTF16([field_ displayedText]); }
diff --git a/ios/chrome/browser/ui/overlays/infobar_banner/confirm/confirm_infobar_banner_overlay_mediator.mm b/ios/chrome/browser/ui/overlays/infobar_banner/confirm/confirm_infobar_banner_overlay_mediator.mm index 2bd473e..2c31c4a0 100644 --- a/ios/chrome/browser/ui/overlays/infobar_banner/confirm/confirm_infobar_banner_overlay_mediator.mm +++ b/ios/chrome/browser/ui/overlays/infobar_banner/confirm/confirm_infobar_banner_overlay_mediator.mm
@@ -53,8 +53,6 @@ if (!self.consumer || !config) return; - [self.consumer setBannerAccessibilityLabel:base::SysUTF16ToNSString( - config->button_label_text())]; [self.consumer setButtonText:base::SysUTF16ToNSString(config->button_label_text())]; if (!config->icon_image().IsEmpty())
diff --git a/ios/chrome/browser/ui/overlays/infobar_banner/passwords/BUILD.gn b/ios/chrome/browser/ui/overlays/infobar_banner/passwords/BUILD.gn index 199a1f9..059618a 100644 --- a/ios/chrome/browser/ui/overlays/infobar_banner/passwords/BUILD.gn +++ b/ios/chrome/browser/ui/overlays/infobar_banner/passwords/BUILD.gn
@@ -46,6 +46,7 @@ "//ios/chrome/browser/ui/infobars/banners/test", "//ios/chrome/browser/ui/infobars/test", "//ios/chrome/browser/ui/overlays/test", + "//ios/chrome/browser/ui/resources:password_key", "//testing/gmock", "//testing/gtest", "//ui/base",
diff --git a/ios/chrome/browser/ui/overlays/infobar_banner/passwords/save_password_infobar_banner_overlay_mediator_unittest.mm b/ios/chrome/browser/ui/overlays/infobar_banner/passwords/save_password_infobar_banner_overlay_mediator_unittest.mm index d28d9c8..95fca1b 100644 --- a/ios/chrome/browser/ui/overlays/infobar_banner/passwords/save_password_infobar_banner_overlay_mediator_unittest.mm +++ b/ios/chrome/browser/ui/overlays/infobar_banner/passwords/save_password_infobar_banner_overlay_mediator_unittest.mm
@@ -84,7 +84,6 @@ consumer.buttonText); EXPECT_NSEQ(title, consumer.titleText); EXPECT_NSEQ(subtitle, consumer.subtitleText); - EXPECT_NSEQ([UIImage imageNamed:@"infobar_passwords_icon"], - consumer.iconImage); + EXPECT_NSEQ([UIImage imageNamed:@"password_key"], consumer.iconImage); EXPECT_TRUE(consumer.presentsModal); }
diff --git a/ios/chrome/browser/ui/overlays/infobar_banner/save_card/save_card_infobar_banner_overlay_mediator.mm b/ios/chrome/browser/ui/overlays/infobar_banner/save_card/save_card_infobar_banner_overlay_mediator.mm index c34954d6..0d72d5d1 100644 --- a/ios/chrome/browser/ui/overlays/infobar_banner/save_card/save_card_infobar_banner_overlay_mediator.mm +++ b/ios/chrome/browser/ui/overlays/infobar_banner/save_card/save_card_infobar_banner_overlay_mediator.mm
@@ -73,8 +73,6 @@ if (!self.consumer || !config) return; - [self.consumer setBannerAccessibilityLabel:base::SysUTF16ToNSString( - config->button_label_text())]; [self.consumer setButtonText:base::SysUTF16ToNSString(self.config->button_label_text())]; [self.consumer setIconImage:[UIImage imageNamed:config->icon_image_name()]];
diff --git a/ios/chrome/browser/ui/page_info/page_info_legacy_coordinator.mm b/ios/chrome/browser/ui/page_info/page_info_legacy_coordinator.mm index bbd872e..d52f9a17 100644 --- a/ios/chrome/browser/ui/page_info/page_info_legacy_coordinator.mm +++ b/ios/chrome/browser/ui/page_info/page_info_legacy_coordinator.mm
@@ -87,13 +87,14 @@ CGPoint originPresentationCoordinates = [self.presentationProvider convertToPresentationCoordinatesForOrigin:self.originPoint]; + // TODO(crbug.com/1045047): Use HandlerForProtocol() when BrowserCommands is + // broken up. self.pageInfoViewController = [[LegacyPageInfoViewController alloc] initWithModel:config sourcePoint:originPresentationCoordinates presentationProvider:self.presentationProvider - handler:HandlerForProtocol( - self.browser->GetCommandDispatcher(), - BrowserCommands)]; + handler:static_cast<id<BrowserCommands>>( + self.browser->GetCommandDispatcher())]; } - (void)stop {
diff --git a/ios/chrome/browser/ui/resources/BUILD.gn b/ios/chrome/browser/ui/resources/BUILD.gn index f22869b..ac7c768 100644 --- a/ios/chrome/browser/ui/resources/BUILD.gn +++ b/ios/chrome/browser/ui/resources/BUILD.gn
@@ -12,3 +12,11 @@ "menu_shadow.imageset/menu_shadow@3x.png", ] } + +imageset("password_key") { + sources = [ + "password_key.imageset/Contents.json", + "password_key.imageset/password_key@2x.png", + "password_key.imageset/password_key@3x.png", + ] +}
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_passwords.imageset/Contents.json b/ios/chrome/browser/ui/resources/password_key.imageset/Contents.json similarity index 67% rename from ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_passwords.imageset/Contents.json rename to ios/chrome/browser/ui/resources/password_key.imageset/Contents.json index a31b671..fc983739 100644 --- a/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_passwords.imageset/Contents.json +++ b/ios/chrome/browser/ui/resources/password_key.imageset/Contents.json
@@ -3,12 +3,12 @@ { "idiom": "universal", "scale": "2x", - "filename": "clear_browsing_data_passwords@2x.png" + "filename": "password_key@2x.png" }, { "idiom": "universal", "scale": "3x", - "filename": "clear_browsing_data_passwords@3x.png" + "filename": "password_key@3x.png" } ], "info": {
diff --git a/ios/chrome/browser/ui/resources/password_key.imageset/password_key@2x.png b/ios/chrome/browser/ui/resources/password_key.imageset/password_key@2x.png new file mode 100644 index 0000000..cc90103 --- /dev/null +++ b/ios/chrome/browser/ui/resources/password_key.imageset/password_key@2x.png Binary files differ
diff --git a/ios/chrome/browser/ui/resources/password_key.imageset/password_key@3x.png b/ios/chrome/browser/ui/resources/password_key.imageset/password_key@3x.png new file mode 100644 index 0000000..5f1fd300 --- /dev/null +++ b/ios/chrome/browser/ui/resources/password_key.imageset/password_key@3x.png Binary files differ
diff --git a/ios/chrome/browser/ui/settings/BUILD.gn b/ios/chrome/browser/ui/settings/BUILD.gn index 2ab85ca..44f3d49 100644 --- a/ios/chrome/browser/ui/settings/BUILD.gn +++ b/ios/chrome/browser/ui/settings/BUILD.gn
@@ -88,7 +88,9 @@ "resources:settings_passwords", "resources:settings_payment_methods", "resources:settings_privacy", + "resources:settings_safe_browsing", "resources:settings_safe_state", + "resources:settings_safety_check", "resources:settings_search_engine", "resources:settings_unsafe_state", "resources:settings_voice_search", @@ -153,6 +155,7 @@ "//ios/chrome/browser/ui/icons", "//ios/chrome/browser/ui/keyboard", "//ios/chrome/browser/ui/list_model", + "//ios/chrome/browser/ui/resources:password_key", "//ios/chrome/browser/ui/settings/autofill", "//ios/chrome/browser/ui/settings/cells", "//ios/chrome/browser/ui/settings/cells:public",
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/BUILD.gn b/ios/chrome/browser/ui/settings/clear_browsing_data/BUILD.gn index c8fabea..0506d18 100644 --- a/ios/chrome/browser/ui/settings/clear_browsing_data/BUILD.gn +++ b/ios/chrome/browser/ui/settings/clear_browsing_data/BUILD.gn
@@ -23,7 +23,6 @@ "resources:clear_browsing_data_cached_images", "resources:clear_browsing_data_cookies", "resources:clear_browsing_data_history", - "resources:clear_browsing_data_passwords", "//components/browsing_data/core", "//components/feature_engagement/public", "//components/history/core/browser", @@ -48,6 +47,7 @@ "//ios/chrome/browser/ui/elements:elements_internal", "//ios/chrome/browser/ui/icons", "//ios/chrome/browser/ui/list_model", + "//ios/chrome/browser/ui/resources:password_key", "//ios/chrome/browser/ui/settings:settings_root", "//ios/chrome/browser/ui/settings/cells", "//ios/chrome/browser/ui/table_view",
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_manager.mm b/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_manager.mm index 1e52c5a..47c7af9 100644 --- a/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_manager.mm +++ b/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_manager.mm
@@ -90,8 +90,7 @@ @"clear_browsing_data_cookies", [NSNumber numberWithInteger:ItemTypeDataTypeCache] : @"clear_browsing_data_cached_images", - [NSNumber numberWithInteger:ItemTypeDataTypeSavedPasswords] : - @"clear_browsing_data_passwords", + [NSNumber numberWithInteger:ItemTypeDataTypeSavedPasswords] : @"password_key", [NSNumber numberWithInteger:ItemTypeDataTypeAutofill] : @"clear_browsing_data_autofill", };
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/resources/BUILD.gn b/ios/chrome/browser/ui/settings/clear_browsing_data/resources/BUILD.gn index 7b2c9c50c..e6640f9 100644 --- a/ios/chrome/browser/ui/settings/clear_browsing_data/resources/BUILD.gn +++ b/ios/chrome/browser/ui/settings/clear_browsing_data/resources/BUILD.gn
@@ -35,11 +35,3 @@ "clear_browsing_data_history.imageset/clear_browsing_data_history@3x.png", ] } - -imageset("clear_browsing_data_passwords") { - sources = [ - "clear_browsing_data_passwords.imageset/Contents.json", - "clear_browsing_data_passwords.imageset/clear_browsing_data_passwords@2x.png", - "clear_browsing_data_passwords.imageset/clear_browsing_data_passwords@3x.png", - ] -}
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_passwords.imageset/clear_browsing_data_passwords@2x.png b/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_passwords.imageset/clear_browsing_data_passwords@2x.png deleted file mode 100644 index 5128543..0000000 --- a/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_passwords.imageset/clear_browsing_data_passwords@2x.png +++ /dev/null Binary files differ
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_passwords.imageset/clear_browsing_data_passwords@3x.png b/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_passwords.imageset/clear_browsing_data_passwords@3x.png deleted file mode 100644 index d78f4c77..0000000 --- a/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_passwords.imageset/clear_browsing_data_passwords@3x.png +++ /dev/null Binary files differ
diff --git a/ios/chrome/browser/ui/settings/google_services/accounts_table_egtest.mm b/ios/chrome/browser/ui/settings/google_services/accounts_table_egtest.mm index d774aea7..2999a8c 100644 --- a/ios/chrome/browser/ui/settings/google_services/accounts_table_egtest.mm +++ b/ios/chrome/browser/ui/settings/google_services/accounts_table_egtest.mm
@@ -89,7 +89,7 @@ [[EarlGrey selectElementWithMatcher:PrimarySignInButton()] assertWithMatcher:grey_sufficientlyVisible()]; - [SigninEarlGrey checkSignedOut]; + [SigninEarlGrey verifySignedOut]; [[EarlGrey selectElementWithMatcher:SettingsDoneButton()] performAction:grey_tap()]; @@ -113,7 +113,7 @@ [[EarlGrey selectElementWithMatcher:PrimarySignInButton()] assertWithMatcher:grey_sufficientlyVisible()]; - [SigninEarlGrey checkSignedOut]; + [SigninEarlGrey verifySignedOut]; [[EarlGrey selectElementWithMatcher:SettingsDoneButton()] performAction:grey_tap()]; @@ -148,7 +148,7 @@ fakeIdentity2.userEmail), grey_sufficientlyVisible(), nil)] assertWithMatcher:grey_nil()]; - [SigninEarlGrey checkSignedInWithFakeIdentity:fakeIdentity1]; + [SigninEarlGrey verifySignedInWithFakeIdentity:fakeIdentity1]; [[EarlGrey selectElementWithMatcher:SettingsDoneButton()] performAction:grey_tap()]; @@ -177,7 +177,7 @@ // Check that the user is signed out and the Main Settings screen is shown. [[EarlGrey selectElementWithMatcher:PrimarySignInButton()] assertWithMatcher:grey_sufficientlyVisible()]; - [SigninEarlGrey checkSignedOut]; + [SigninEarlGrey verifySignedOut]; [[EarlGrey selectElementWithMatcher:SettingsDoneButton()] performAction:grey_tap()]; @@ -290,7 +290,7 @@ [[EarlGrey selectElementWithMatcher:chrome_test_util:: SettingsAccountsCollectionView()] assertWithMatcher:grey_sufficientlyVisible()]; - [SigninEarlGrey checkSignedInWithFakeIdentity:fakeIdentity]; + [SigninEarlGrey verifySignedInWithFakeIdentity:fakeIdentity]; [[EarlGrey selectElementWithMatcher:SettingsDoneButton()] performAction:grey_tap()];
diff --git a/ios/chrome/browser/ui/settings/password/BUILD.gn b/ios/chrome/browser/ui/settings/password/BUILD.gn index 1e87a1b..88e7a8e9 100644 --- a/ios/chrome/browser/ui/settings/password/BUILD.gn +++ b/ios/chrome/browser/ui/settings/password/BUILD.gn
@@ -5,9 +5,9 @@ source_set("password") { configs += [ "//build/config/compiler:enable_arc" ] sources = [ - "password_details_table_view_controller.h", - "password_details_table_view_controller.mm", - "password_details_table_view_controller_delegate.h", + "legacy_password_details_table_view_controller.h", + "legacy_password_details_table_view_controller.mm", + "legacy_password_details_table_view_controller_delegate.h", "password_exporter.h", "password_exporter.mm", "password_issue_with_form.h", @@ -111,7 +111,7 @@ configs += [ "//build/config/compiler:enable_arc" ] testonly = true sources = [ - "password_details_table_view_controller+testing.h", + "legacy_password_details_table_view_controller+testing.h", "password_exporter_for_testing.h", ] deps = [ ":password" ] @@ -121,7 +121,7 @@ configs += [ "//build/config/compiler:enable_arc" ] testonly = true sources = [ - "password_details_table_view_controller_unittest.mm", + "legacy_password_details_table_view_controller_unittest.mm", "password_exporter_unittest.mm", "password_issues_mediator_unittest.mm", "password_issues_table_view_controller_unittest.mm",
diff --git a/ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller+testing.h b/ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller+testing.h new file mode 100644 index 0000000..be2d212c --- /dev/null +++ b/ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller+testing.h
@@ -0,0 +1,22 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_LEGACY_PASSWORD_DETAILS_TABLE_VIEW_CONTROLLER_TESTING_H_ +#define IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_LEGACY_PASSWORD_DETAILS_TABLE_VIEW_CONTROLLER_TESTING_H_ + +#import "ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller.h" + +// TODO(crbug.com/943523): Refactor the PasswordTableViewController and +// PasswordsSettingsTestCase to remove this Category file. +@interface LegacyPasswordDetailsTableViewController (Testing) + +// Allows to replace a |reauthenticationModule| for a fake one in integration +// tests, where the testing code cannot control the creation of the +// controller. +- (void)setReauthenticationModule: + (id<ReauthenticationProtocol>)reauthenticationModule; + +@end + +#endif // IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_LEGACY_PASSWORD_DETAILS_TABLE_VIEW_CONTROLLER_TESTING_H_
diff --git a/ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller.h b/ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller.h new file mode 100644 index 0000000..965066db --- /dev/null +++ b/ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller.h
@@ -0,0 +1,42 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_LEGACY_PASSWORD_DETAILS_TABLE_VIEW_CONTROLLER_H_ +#define IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_LEGACY_PASSWORD_DETAILS_TABLE_VIEW_CONTROLLER_H_ + +#import "ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller_delegate.h" +#import "ios/chrome/browser/ui/settings/settings_root_table_view_controller.h" + +namespace autofill { +struct PasswordForm; +} // namespace autofill + +@protocol ReauthenticationProtocol; + +// TODO(crbug.com/1096986): Delete this view controller after Password Check +// launch. + +// Displays details of a password item, including URL of the site, username and +// password in masked state as default. User can copy the URL and username, +// pass the iOS security check to see and copy the password , or delete the +// password item. +@interface LegacyPasswordDetailsTableViewController + : SettingsRootTableViewController + +// The designated initializer. +- (nullable instancetype) + initWithPasswordForm:(const autofill::PasswordForm&)passwordForm + delegate: + (nonnull + id<LegacyPasswordDetailsTableViewControllerDelegate>) + delegate + reauthenticationModule: + (nonnull id<ReauthenticationProtocol>)reauthenticationModule + NS_DESIGNATED_INITIALIZER; + +- (nullable instancetype)initWithStyle:(UITableViewStyle)style NS_UNAVAILABLE; + +@end + +#endif // IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_LEGACY_PASSWORD_DETAILS_TABLE_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/settings/password/password_details_table_view_controller.mm b/ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller.mm similarity index 93% rename from ios/chrome/browser/ui/settings/password/password_details_table_view_controller.mm rename to ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller.mm index be4593d..8469733 100644 --- a/ios/chrome/browser/ui/settings/password/password_details_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller.mm
@@ -2,7 +2,7 @@ // 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/password/password_details_table_view_controller.h" +#import "ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller.h" #import <UIKit/UIKit.h> @@ -66,7 +66,7 @@ } // namespace -@interface PasswordDetailsTableViewController () { +@interface LegacyPasswordDetailsTableViewController () { // The username to which the saved password belongs. NSString* _username; // The saved password. @@ -92,21 +92,22 @@ // Instance of the parent view controller needed in order to update the // password list when a password is deleted. -@property(nonatomic, weak) id<PasswordDetailsTableViewControllerDelegate> +@property(nonatomic, weak) id<LegacyPasswordDetailsTableViewControllerDelegate> delegate; @end -@implementation PasswordDetailsTableViewController +@implementation LegacyPasswordDetailsTableViewController @synthesize deleteConfirmation = _deleteConfirmation; -- (instancetype)initWithPasswordForm:(const autofill::PasswordForm&)passwordForm - delegate: - (id<PasswordDetailsTableViewControllerDelegate>) - delegate - reauthenticationModule: - (id<ReauthenticationProtocol>)reauthenticationModule { +- (instancetype) + initWithPasswordForm:(const autofill::PasswordForm&)passwordForm + delegate: + (id<LegacyPasswordDetailsTableViewControllerDelegate>) + delegate + reauthenticationModule: + (id<ReauthenticationProtocol>)reauthenticationModule { DCHECK(delegate); DCHECK(reauthenticationModule); UITableViewStyle style = base::FeatureList::IsEnabled(kSettingsRefresh) @@ -349,25 +350,25 @@ } if ([_weakReauthenticationModule canAttemptReauth]) { - __weak PasswordDetailsTableViewController* weakSelf = self; - void (^showPasswordHandler)(ReauthenticationResult) = ^( - ReauthenticationResult result) { - PasswordDetailsTableViewController* strongSelf = weakSelf; - if (!strongSelf) - return; - [strongSelf logPasswordSettingsReauthResult:result]; - if (result == ReauthenticationResult::kFailure) - return; - TableViewTextItem* passwordItem = strongSelf->_passwordItem; - passwordItem.masked = NO; - [strongSelf reconfigureCellsForItems:@[ passwordItem ]]; - strongSelf->_plainTextPasswordShown = YES; - [strongSelf toggleShowHideButton]; - UMA_HISTOGRAM_ENUMERATION( - "PasswordManager.AccessPasswordInSettings", - password_manager::metrics_util::ACCESS_PASSWORD_VIEWED, - password_manager::metrics_util::ACCESS_PASSWORD_COUNT); - }; + __weak LegacyPasswordDetailsTableViewController* weakSelf = self; + void (^showPasswordHandler)(ReauthenticationResult) = + ^(ReauthenticationResult result) { + LegacyPasswordDetailsTableViewController* strongSelf = weakSelf; + if (!strongSelf) + return; + [strongSelf logPasswordSettingsReauthResult:result]; + if (result == ReauthenticationResult::kFailure) + return; + TableViewTextItem* passwordItem = strongSelf->_passwordItem; + passwordItem.masked = NO; + [strongSelf reconfigureCellsForItems:@[ passwordItem ]]; + strongSelf->_plainTextPasswordShown = YES; + [strongSelf toggleShowHideButton]; + UMA_HISTOGRAM_ENUMERATION( + "PasswordManager.AccessPasswordInSettings", + password_manager::metrics_util::ACCESS_PASSWORD_VIEWED, + password_manager::metrics_util::ACCESS_PASSWORD_COUNT); + }; [_weakReauthenticationModule attemptReauthWithLocalizedReason: @@ -409,10 +410,10 @@ password_manager::metrics_util::LogPasswordSettingsReauthResult( password_manager::metrics_util::ReauthResult::kSkipped); } else if ([_weakReauthenticationModule canAttemptReauth]) { - __weak PasswordDetailsTableViewController* weakSelf = self; + __weak LegacyPasswordDetailsTableViewController* weakSelf = self; void (^copyPasswordHandler)(ReauthenticationResult) = ^( ReauthenticationResult result) { - PasswordDetailsTableViewController* strongSelf = weakSelf; + LegacyPasswordDetailsTableViewController* strongSelf = weakSelf; if (!strongSelf) return; [strongSelf logPasswordSettingsReauthResult:result]; @@ -491,7 +492,7 @@ // Deletes the password with a deletion confirmation alert. - (void)deletePassword { - __weak PasswordDetailsTableViewController* weakSelf = self; + __weak LegacyPasswordDetailsTableViewController* weakSelf = self; self.deleteConfirmation = [UIAlertController alertControllerWithTitle:nil
diff --git a/ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller_delegate.h b/ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller_delegate.h new file mode 100644 index 0000000..d9c5e1a36 --- /dev/null +++ b/ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller_delegate.h
@@ -0,0 +1,27 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_LEGACY_PASSWORD_DETAILS_TABLE_VIEW_CONTROLLER_DELEGATE_H_ +#define IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_LEGACY_PASSWORD_DETAILS_TABLE_VIEW_CONTROLLER_DELEGATE_H_ + +#import <Foundation/Foundation.h> + +namespace autofill { +struct PasswordForm; +} // namespace autofill + +@class LegacyPasswordDetailsTableViewController; + +// PasswordDetailsTableViewController uses this protocol to interact with higher +// level password controller. +@protocol LegacyPasswordDetailsTableViewControllerDelegate + +- (void)passwordDetailsTableViewController: + (LegacyPasswordDetailsTableViewController*)controller + deletePassword: + (const autofill::PasswordForm&)passwordForm; + +@end + +#endif // IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_LEGACY_PASSWORD_DETAILS_TABLE_VIEW_CONTROLLER_DELEGATE_H_
diff --git a/ios/chrome/browser/ui/settings/password/password_details_table_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller_unittest.mm similarity index 91% rename from ios/chrome/browser/ui/settings/password/password_details_table_view_controller_unittest.mm rename to ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller_unittest.mm index 5f49f10..77b64ade 100644 --- a/ios/chrome/browser/ui/settings/password/password_details_table_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller_unittest.mm
@@ -2,7 +2,7 @@ // 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/password/password_details_table_view_controller.h" +#import "ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller.h" #include "base/mac/foundation_util.h" #include "base/strings/sys_string_conversions.h" @@ -47,10 +47,10 @@ const int kDeleteSection = 3; const int kDeleteButtonItem = 0; -class PasswordDetailsTableViewControllerTest +class LegacyPasswordDetailsTableViewControllerTest : public ChromeTableViewControllerTest { protected: - PasswordDetailsTableViewControllerTest() { + LegacyPasswordDetailsTableViewControllerTest() { origin_ = kSite; form_.username_value = base::SysNSStringToUTF16(kUsername); form_.password_value = base::SysNSStringToUTF16(kPassword); @@ -65,10 +65,11 @@ } ChromeTableViewController* InstantiateController() override { - return [[PasswordDetailsTableViewController alloc] + return [[LegacyPasswordDetailsTableViewController alloc] initWithPasswordForm:form_ - delegate:OCMProtocolMock(@protocol( - PasswordDetailsTableViewControllerDelegate)) + delegate: + OCMProtocolMock(@protocol( + LegacyPasswordDetailsTableViewControllerDelegate)) reauthenticationModule:reauthentication_module_]; } @@ -78,7 +79,7 @@ autofill::PasswordForm form_; }; -TEST_F(PasswordDetailsTableViewControllerTest, +TEST_F(LegacyPasswordDetailsTableViewControllerTest, TestInitialization_NormalPassword) { CreateController(); CheckController(); @@ -119,7 +120,8 @@ kDeleteSection, kDeleteButtonItem); } -TEST_F(PasswordDetailsTableViewControllerTest, TestInitialization_Blocked) { +TEST_F(LegacyPasswordDetailsTableViewControllerTest, + TestInitialization_Blocked) { constexpr int kBlockedSiteSection = 0; constexpr int kBlockedSiteItem = 0; constexpr int kBlockedCopySiteButtonItem = 1; @@ -149,7 +151,8 @@ kBlockedDeleteSection, kBlockedDeleteButtonItem); } -TEST_F(PasswordDetailsTableViewControllerTest, TestInitialization_Federated) { +TEST_F(LegacyPasswordDetailsTableViewControllerTest, + TestInitialization_Federated) { constexpr int kFederatedSiteSection = 0; constexpr int kFederatedSiteItem = 0; constexpr int kFederatedCopySiteButtonItem = 1; @@ -210,7 +213,7 @@ NSString* expectedSimplifiedOrigin; }; -TEST_F(PasswordDetailsTableViewControllerTest, SimplifyOrigin) { +TEST_F(LegacyPasswordDetailsTableViewControllerTest, SimplifyOrigin) { SimplifyOriginTestData test_data[] = { {GURL("http://test.com/index.php"), @"test.com"}, {GURL("https://example.com/index.php"), @"example.com"}, @@ -230,7 +233,7 @@ } } -TEST_F(PasswordDetailsTableViewControllerTest, CopySite) { +TEST_F(LegacyPasswordDetailsTableViewControllerTest, CopySite) { CreateController(); [controller() tableView:[controller() tableView] didSelectRowAtIndexPath:[NSIndexPath indexPathForRow:kCopySiteButtonItem @@ -239,7 +242,7 @@ EXPECT_NSEQ(origin_, generalPasteboard.string); } -TEST_F(PasswordDetailsTableViewControllerTest, CopyUsername) { +TEST_F(LegacyPasswordDetailsTableViewControllerTest, CopyUsername) { CreateController(); [controller() tableView:[controller() tableView] didSelectRowAtIndexPath:[NSIndexPath @@ -249,7 +252,7 @@ EXPECT_NSEQ(kUsername, generalPasteboard.string); } -TEST_F(PasswordDetailsTableViewControllerTest, ShowPassword) { +TEST_F(LegacyPasswordDetailsTableViewControllerTest, ShowPassword) { CreateController(); [controller() tableView:[controller() tableView] didSelectRowAtIndexPath:[NSIndexPath indexPathForRow:kShowHideButtonItem @@ -265,7 +268,7 @@ kPasswordSection, kShowHideButtonItem); } -TEST_F(PasswordDetailsTableViewControllerTest, HidePassword) { +TEST_F(LegacyPasswordDetailsTableViewControllerTest, HidePassword) { CreateController(); // First show the password. [controller() tableView:[controller() tableView] @@ -283,7 +286,7 @@ kPasswordSection, kShowHideButtonItem); } -TEST_F(PasswordDetailsTableViewControllerTest, CopyPassword) { +TEST_F(LegacyPasswordDetailsTableViewControllerTest, CopyPassword) { CreateController(); [controller() tableView:[controller() tableView] didSelectRowAtIndexPath:[NSIndexPath
diff --git a/ios/chrome/browser/ui/settings/password/password_details/BUILD.gn b/ios/chrome/browser/ui/settings/password/password_details/BUILD.gn index 4a56a48..27c7271 100644 --- a/ios/chrome/browser/ui/settings/password/password_details/BUILD.gn +++ b/ios/chrome/browser/ui/settings/password/password_details/BUILD.gn
@@ -43,9 +43,9 @@ "password_details_handler.h", "password_details_table_view_constants.h", "password_details_table_view_constants.mm", - "password_details_view_controller.h", - "password_details_view_controller.mm", - "password_details_view_controller_delegate.h", + "password_details_table_view_controller.h", + "password_details_table_view_controller.mm", + "password_details_table_view_controller_delegate.h", ] deps = [ "//base", @@ -75,7 +75,7 @@ source_set("unit_tests") { configs += [ "//build/config/compiler:enable_arc" ] testonly = true - sources = [ "password_details_view_controller_unittest.mm" ] + sources = [ "password_details_table_view_controller_unittest.mm" ] deps = [ ":password_details", ":password_details_ui",
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator.mm b/ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator.mm index eccaf2c..1326a0b 100644 --- a/ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator.mm +++ b/ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator.mm
@@ -17,7 +17,7 @@ #import "ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator_delegate.h" #import "ios/chrome/browser/ui/settings/password/password_details/password_details_handler.h" #import "ios/chrome/browser/ui/settings/password/password_details/password_details_mediator.h" -#import "ios/chrome/browser/ui/settings/password/password_details/password_details_view_controller.h" +#import "ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller.h" #include "ios/chrome/browser/ui/ui_feature_flags.h" #import "ios/chrome/common/ui/reauthentication/reauthentication_module.h" #include "ios/chrome/grit/ios_strings.h" @@ -35,7 +35,7 @@ } // Main view controller for this coordinator. -@property(nonatomic, strong) PasswordDetailsViewController* viewController; +@property(nonatomic, strong) PasswordDetailsTableViewController* viewController; // Main mediator for this coordinator. @property(nonatomic, strong) PasswordDetailsMediator* mediator; @@ -83,7 +83,7 @@ : UITableViewStyleGrouped; self.viewController = - [[PasswordDetailsViewController alloc] initWithStyle:style]; + [[PasswordDetailsTableViewController alloc] initWithStyle:style]; self.mediator = [[PasswordDetailsMediator alloc] initWithPassword:_password passwordCheckManager:_manager]; @@ -105,7 +105,7 @@ #pragma mark - PasswordDetailsHandler -- (void)passwordDetailsViewControllerDidDisappear { +- (void)passwordDetailsTableViewControllerDidDisappear { [self.delegate passwordDetailsCoordinatorDidRemove:self]; }
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_details_handler.h b/ios/chrome/browser/ui/settings/password/password_details/password_details_handler.h index c276ca9..4245539c 100644 --- a/ios/chrome/browser/ui/settings/password/password_details/password_details_handler.h +++ b/ios/chrome/browser/ui/settings/password/password_details/password_details_handler.h
@@ -9,7 +9,7 @@ @protocol PasswordDetailsHandler // Called when the view controller was dismissed. -- (void)passwordDetailsViewControllerDidDisappear; +- (void)passwordDetailsTableViewControllerDidDisappear; // Shows a dialog offering the user to set a passcode in order to see the // password.
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_details_mediator.h b/ios/chrome/browser/ui/settings/password/password_details/password_details_mediator.h index 73341f3..60aefde 100644 --- a/ios/chrome/browser/ui/settings/password/password_details/password_details_mediator.h +++ b/ios/chrome/browser/ui/settings/password/password_details/password_details_mediator.h
@@ -7,7 +7,7 @@ #import <Foundation/Foundation.h> -#import "ios/chrome/browser/ui/settings/password/password_details/password_details_view_controller_delegate.h" +#import "ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller_delegate.h" class IOSChromePasswordCheckManager; @protocol PasswordDetailsConsumer; @@ -18,7 +18,7 @@ // This mediator fetches and organises the credentials for its consumer. @interface PasswordDetailsMediator - : NSObject <PasswordDetailsViewControllerDelegate> + : NSObject <PasswordDetailsTableViewControllerDelegate> // PasswordForm is converted to the PasswordDetails and passed to a consumer. - (instancetype)initWithPassword:(const autofill::PasswordForm&)passwordForm
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_details_mediator.mm b/ios/chrome/browser/ui/settings/password/password_details/password_details_mediator.mm index 7c75595..0e940ea 100644 --- a/ios/chrome/browser/ui/settings/password/password_details/password_details_mediator.mm +++ b/ios/chrome/browser/ui/settings/password/password_details/password_details_mediator.mm
@@ -9,7 +9,7 @@ #include "ios/chrome/browser/passwords/password_check_observer_bridge.h" #import "ios/chrome/browser/ui/settings/password/password_details/password_details.h" #import "ios/chrome/browser/ui/settings/password/password_details/password_details_consumer.h" -#import "ios/chrome/browser/ui/settings/password/password_details/password_details_view_controller_delegate.h" +#import "ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller_delegate.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -18,8 +18,9 @@ using CompromisedCredentialsView = password_manager::CompromisedCredentialsManager::CredentialsView; -@interface PasswordDetailsMediator () <PasswordCheckObserver, - PasswordDetailsViewControllerDelegate> { +@interface PasswordDetailsMediator () < + PasswordCheckObserver, + PasswordDetailsTableViewControllerDelegate> { // Password Check manager. IOSChromePasswordCheckManager* _manager; @@ -55,9 +56,10 @@ _manager->RemoveObserver(_passwordCheckObserver.get()); } -#pragma mark - PasswordDetailsViewControllerDelegate +#pragma mark - PasswordDetailsTableViewControllerDelegate + - (void)passwordDetailsViewController: - (PasswordDetailsViewController*)viewController + (PasswordDetailsTableViewController*)viewController didEditPasswordDetails:(PasswordDetails*)password { if ([password.password length] != 0) { password.compromised
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_details_view_controller.h b/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller.h similarity index 80% rename from ios/chrome/browser/ui/settings/password/password_details/password_details_view_controller.h rename to ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller.h index 763ab1d0..ae34cc9 100644 --- a/ios/chrome/browser/ui/settings/password/password_details/password_details_view_controller.h +++ b/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller.h
@@ -2,26 +2,27 @@ // 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_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_VIEW_CONTROLLER_H_ -#define IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_VIEW_CONTROLLER_H_ +#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_TABLE_VIEW_CONTROLLER_H_ +#define IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_TABLE_VIEW_CONTROLLER_H_ #import "ios/chrome/browser/ui/settings/autofill/autofill_edit_table_view_controller.h" #import "ios/chrome/browser/ui/settings/password/password_details/password_details_consumer.h" @protocol ApplicationCommands; @protocol PasswordDetailsHandler; -@protocol PasswordDetailsViewControllerDelegate; +@protocol PasswordDetailsTableViewControllerDelegate; @protocol ReauthenticationProtocol; // Screen which shows password details and allows to edit it. -@interface PasswordDetailsViewController +@interface PasswordDetailsTableViewController : AutofillEditTableViewController <PasswordDetailsConsumer> // Handler for PasswordDetails related actions. @property(nonatomic, weak) id<PasswordDetailsHandler> handler; // Delegate for PasswordDetails related actions e.g. Password editing. -@property(nonatomic, weak) id<PasswordDetailsViewControllerDelegate> delegate; +@property(nonatomic, weak) id<PasswordDetailsTableViewControllerDelegate> + delegate; // Dispatcher for this ViewController. @property(nonatomic, weak) id<ApplicationCommands> commandsDispatcher; @@ -35,4 +36,4 @@ @end -#endif // IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_VIEW_CONTROLLER_H_ +#endif // IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_TABLE_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_details_view_controller.mm b/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller.mm similarity index 97% rename from ios/chrome/browser/ui/settings/password/password_details/password_details_view_controller.mm rename to ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller.mm index 03e9570f3..8c50090 100644 --- a/ios/chrome/browser/ui/settings/password/password_details/password_details_view_controller.mm +++ b/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller.mm
@@ -2,7 +2,7 @@ // 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/password/password_details/password_details_view_controller.h" +#import "ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller.h" #include "base/ios/ios_util.h" #include "base/mac/foundation_util.h" @@ -16,7 +16,7 @@ #import "ios/chrome/browser/ui/settings/password/password_details/password_details_consumer.h" #import "ios/chrome/browser/ui/settings/password/password_details/password_details_handler.h" #import "ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_constants.h" -#import "ios/chrome/browser/ui/settings/password/password_details/password_details_view_controller_delegate.h" +#import "ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller_delegate.h" #import "ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h" #import "ios/chrome/browser/ui/table_view/cells/table_view_text_edit_item.h" #import "ios/chrome/browser/ui/table_view/cells/table_view_text_item.h" @@ -61,7 +61,7 @@ } // namespace -@interface PasswordDetailsViewController () +@interface PasswordDetailsTableViewController () // Password which is shown on the screen. @property(nonatomic, strong) PasswordDetails* password; @@ -74,7 +74,7 @@ @end -@implementation PasswordDetailsViewController +@implementation PasswordDetailsTableViewController #pragma mark - UIViewController @@ -92,7 +92,7 @@ } - (void)viewDidDisappear:(BOOL)animated { - [self.handler passwordDetailsViewControllerDidDisappear]; + [self.handler passwordDetailsTableViewControllerDidDisappear]; [super viewDidDisappear:animated]; } @@ -349,7 +349,7 @@ __weak __typeof(self) weakSelf = self; void (^showPasswordHandler)(ReauthenticationResult) = ^(ReauthenticationResult result) { - PasswordDetailsViewController* strongSelf = weakSelf; + PasswordDetailsTableViewController* strongSelf = weakSelf; if (!strongSelf) return; [strongSelf logPasswordSettingsReauthResult:result];
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_details_view_controller_delegate.h b/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller_delegate.h similarity index 63% rename from ios/chrome/browser/ui/settings/password/password_details/password_details_view_controller_delegate.h rename to ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller_delegate.h index 85e8a17..4567e4f7 100644 --- a/ios/chrome/browser/ui/settings/password/password_details/password_details_view_controller_delegate.h +++ b/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller_delegate.h
@@ -2,19 +2,19 @@ // 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_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_VIEW_CONTROLLER_DELEGATE_H_ -#define IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_VIEW_CONTROLLER_DELEGATE_H_ +#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_TABLE_VIEW_CONTROLLER_DELEGATE_H_ +#define IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_TABLE_VIEW_CONTROLLER_DELEGATE_H_ @class PasswordDetails; -@class PasswordDetailsViewController; +@class PasswordDetailsTableViewController; -@protocol PasswordDetailsViewControllerDelegate +@protocol PasswordDetailsTableViewControllerDelegate // Called when user finished editing a password. - (void)passwordDetailsViewController: - (PasswordDetailsViewController*)viewController + (PasswordDetailsTableViewController*)viewController didEditPasswordDetails:(PasswordDetails*)password; @end -#endif // IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_VIEW_CONTROLLER_DELEGATE_H_ +#endif // IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_TABLE_VIEW_CONTROLLER_DELEGATE_H_
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_details_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller_unittest.mm similarity index 81% rename from ios/chrome/browser/ui/settings/password/password_details/password_details_view_controller_unittest.mm rename to ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller_unittest.mm index 7d91e77..7ed767f 100644 --- a/ios/chrome/browser/ui/settings/password/password_details/password_details_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller_unittest.mm
@@ -2,7 +2,7 @@ // 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/password/password_details/password_details_view_controller.h" +#import "ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller.h" #include <memory> @@ -15,7 +15,7 @@ #import "ios/chrome/browser/ui/settings/password/password_details/password_details.h" #import "ios/chrome/browser/ui/settings/password/password_details/password_details_consumer.h" #import "ios/chrome/browser/ui/settings/password/password_details/password_details_handler.h" -#import "ios/chrome/browser/ui/settings/password/password_details/password_details_view_controller_delegate.h" +#import "ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller_delegate.h" #import "ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h" #import "ios/chrome/browser/ui/table_view/cells/table_view_text_edit_item.h" #import "ios/chrome/browser/ui/table_view/chrome_table_view_controller_test.h" @@ -44,8 +44,7 @@ @implementation FakePasswordDetailsHandler -// Called when the view controller was dismissed. -- (void)passwordDetailsViewControllerDidDisappear { +- (void)passwordDetailsTableViewControllerDidDisappear { } - (void)showPasscodeDialog { @@ -64,7 +63,7 @@ // Test class that conforms to PasswordDetailsViewControllerDelegate in order to // test the delegate methods are called correctly. @interface FakePasswordDetailsDelegate - : NSObject <PasswordDetailsViewControllerDelegate> + : NSObject <PasswordDetailsTableViewControllerDelegate> @property(nonatomic, strong) PasswordDetails* password; @@ -73,7 +72,7 @@ @implementation FakePasswordDetailsDelegate - (void)passwordDetailsViewController: - (PasswordDetailsViewController*)viewController + (PasswordDetailsTableViewController*)viewController didEditPasswordDetails:(PasswordDetails*)password { self.password = password; } @@ -81,9 +80,10 @@ @end // Unit tests for PasswordIssuesTableViewController. -class PasswordDetailsViewControllerTest : public ChromeTableViewControllerTest { +class PasswordDetailsTableViewControllerTest + : public ChromeTableViewControllerTest { protected: - PasswordDetailsViewControllerTest() { + PasswordDetailsTableViewControllerTest() { handler_ = [[FakePasswordDetailsHandler alloc] init]; delegate_ = [[FakePasswordDetailsDelegate alloc] init]; reauthentication_module_ = [[MockReauthenticationModule alloc] init]; @@ -91,8 +91,8 @@ } ChromeTableViewController* InstantiateController() override { - PasswordDetailsViewController* controller = - [[PasswordDetailsViewController alloc] + PasswordDetailsTableViewController* controller = + [[PasswordDetailsTableViewController alloc] initWithStyle:UITableViewStylePlain]; controller.handler = handler_; controller.delegate = delegate_; @@ -115,8 +115,8 @@ [[PasswordDetails alloc] initWithPasswordForm:form]; password.compromised = isCompromised; - PasswordDetailsViewController* passwords_controller = - static_cast<PasswordDetailsViewController*>(controller()); + PasswordDetailsTableViewController* passwords_controller = + static_cast<PasswordDetailsTableViewController*>(controller()); [passwords_controller setPassword:password]; } @@ -146,9 +146,9 @@ MockReauthenticationModule* reauthentication_module_; }; -// Tests PasswordDetailsViewController is set up with appropriate items +// Tests PasswordDetailsTableViewController is set up with appropriate items // and sections. -TEST_F(PasswordDetailsViewControllerTest, TestModel) { +TEST_F(PasswordDetailsTableViewControllerTest, TestModel) { CreateController(); CheckController(); EXPECT_EQ(1, NumberOfSections()); @@ -157,7 +157,7 @@ } // Tests that password is displayed properly. -TEST_F(PasswordDetailsViewControllerTest, TestPassword) { +TEST_F(PasswordDetailsTableViewControllerTest, TestPassword) { SetPassword(); EXPECT_EQ(1, NumberOfSections()); EXPECT_EQ(3, NumberOfItemsInSection(0)); @@ -168,7 +168,7 @@ } // Tests that compromised password is displayed properly. -TEST_F(PasswordDetailsViewControllerTest, TestCompromisedPassword) { +TEST_F(PasswordDetailsTableViewControllerTest, TestCompromisedPassword) { SetPassword(true); EXPECT_EQ(2, NumberOfSections()); EXPECT_EQ(3, NumberOfItemsInSection(0)); @@ -184,7 +184,7 @@ } // Tests that password is shown/hidden. -TEST_F(PasswordDetailsViewControllerTest, TestShowHidePassword) { +TEST_F(PasswordDetailsTableViewControllerTest, TestShowHidePassword) { SetPassword(); CheckEditCellText(kMaskedPassword, 0, 2); @@ -208,7 +208,7 @@ } // Tests that passwords was not shown in case reauth failed. -TEST_F(PasswordDetailsViewControllerTest, TestShowPasswordReauthFailed) { +TEST_F(PasswordDetailsTableViewControllerTest, TestShowPasswordReauthFailed) { SetPassword(); CheckEditCellText(kMaskedPassword, 0, 2); @@ -227,12 +227,13 @@ } // Tests that password was revealed during editing. -TEST_F(PasswordDetailsViewControllerTest, TestPasswordShownDuringEditing) { +TEST_F(PasswordDetailsTableViewControllerTest, TestPasswordShownDuringEditing) { SetPassword(); CheckEditCellText(kMaskedPassword, 0, 2); - PasswordDetailsViewController* passwordDetails = - base::mac::ObjCCastStrict<PasswordDetailsViewController>(controller()); + PasswordDetailsTableViewController* passwordDetails = + base::mac::ObjCCastStrict<PasswordDetailsTableViewController>( + controller()); [passwordDetails editButtonPressed]; EXPECT_TRUE(passwordDetails.tableView.editing); CheckEditCellText(@"test", 0, 2); @@ -243,25 +244,27 @@ } // Tests that editing mode was not entered because reauth failed. -TEST_F(PasswordDetailsViewControllerTest, TestEditingReauthFailed) { +TEST_F(PasswordDetailsTableViewControllerTest, TestEditingReauthFailed) { SetPassword(); CheckEditCellText(kMaskedPassword, 0, 2); reauth().expectedResult = ReauthenticationResult::kFailure; - PasswordDetailsViewController* passwordDetails = - base::mac::ObjCCastStrict<PasswordDetailsViewController>(controller()); + PasswordDetailsTableViewController* passwordDetails = + base::mac::ObjCCastStrict<PasswordDetailsTableViewController>( + controller()); [passwordDetails editButtonPressed]; EXPECT_FALSE(passwordDetails.tableView.editing); CheckEditCellText(kMaskedPassword, 0, 2); } // Tests that delete button trigger showing password delete dialog. -TEST_F(PasswordDetailsViewControllerTest, TestPasswordDelete) { +TEST_F(PasswordDetailsTableViewControllerTest, TestPasswordDelete) { SetPassword(); EXPECT_FALSE(handler().deletionCalled); - PasswordDetailsViewController* passwordDetails = - base::mac::ObjCCastStrict<PasswordDetailsViewController>(controller()); + PasswordDetailsTableViewController* passwordDetails = + base::mac::ObjCCastStrict<PasswordDetailsTableViewController>( + controller()); [passwordDetails editButtonPressed]; [[UIApplication sharedApplication] sendAction:passwordDetails.deleteButton.action @@ -272,11 +275,12 @@ } // Tests password editing. User confirmed this action. -TEST_F(PasswordDetailsViewControllerTest, TestEditPasswordConfirmed) { +TEST_F(PasswordDetailsTableViewControllerTest, TestEditPasswordConfirmed) { SetPassword(); - PasswordDetailsViewController* passwordDetails = - base::mac::ObjCCastStrict<PasswordDetailsViewController>(controller()); + PasswordDetailsTableViewController* passwordDetails = + base::mac::ObjCCastStrict<PasswordDetailsTableViewController>( + controller()); [passwordDetails editButtonPressed]; EXPECT_FALSE(handler().editingCalled); EXPECT_FALSE(delegate().password); @@ -297,11 +301,12 @@ } // Tests password editing. User cancelled this action. -TEST_F(PasswordDetailsViewControllerTest, TestEditPasswordCancel) { +TEST_F(PasswordDetailsTableViewControllerTest, TestEditPasswordCancel) { SetPassword(); - PasswordDetailsViewController* passwordDetails = - base::mac::ObjCCastStrict<PasswordDetailsViewController>(controller()); + PasswordDetailsTableViewController* passwordDetails = + base::mac::ObjCCastStrict<PasswordDetailsTableViewController>( + controller()); [passwordDetails editButtonPressed]; EXPECT_FALSE(delegate().password); EXPECT_TRUE(passwordDetails.tableView.editing);
diff --git a/ios/chrome/browser/ui/settings/password/password_details_table_view_controller+testing.h b/ios/chrome/browser/ui/settings/password/password_details_table_view_controller+testing.h deleted file mode 100644 index c8c1386b..0000000 --- a/ios/chrome/browser/ui/settings/password/password_details_table_view_controller+testing.h +++ /dev/null
@@ -1,22 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_DETAILS_TABLE_VIEW_CONTROLLER_TESTING_H_ -#define IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_DETAILS_TABLE_VIEW_CONTROLLER_TESTING_H_ - -#import "ios/chrome/browser/ui/settings/password/password_details_table_view_controller.h" - -// TODO(crbug.com/943523): Refactor the PasswordTableViewController and -// PasswordsSettingsTestCase to remove this Category file. -@interface PasswordDetailsTableViewController (Testing) - -// Allows to replace a |reauthenticationModule| for a fake one in integration -// tests, where the testing code cannot control the creation of the -// controller. -- (void)setReauthenticationModule: - (id<ReauthenticationProtocol>)reauthenticationModule; - -@end - -#endif // IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_DETAILS_TABLE_VIEW_CONTROLLER_TESTING_H_
diff --git a/ios/chrome/browser/ui/settings/password/password_details_table_view_controller.h b/ios/chrome/browser/ui/settings/password/password_details_table_view_controller.h deleted file mode 100644 index 160d538d..0000000 --- a/ios/chrome/browser/ui/settings/password/password_details_table_view_controller.h +++ /dev/null
@@ -1,37 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_DETAILS_TABLE_VIEW_CONTROLLER_H_ -#define IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_DETAILS_TABLE_VIEW_CONTROLLER_H_ - -#import "ios/chrome/browser/ui/settings/password/password_details_table_view_controller_delegate.h" -#import "ios/chrome/browser/ui/settings/settings_root_table_view_controller.h" - -namespace autofill { -struct PasswordForm; -} // namespace autofill - -@protocol ReauthenticationProtocol; - -// Displays details of a password item, including URL of the site, username and -// password in masked state as default. User can copy the URL and username, -// pass the iOS security check to see and copy the password , or delete the -// password item. -@interface PasswordDetailsTableViewController : SettingsRootTableViewController - -// The designated initializer. -- (nullable instancetype) - initWithPasswordForm:(const autofill::PasswordForm&)passwordForm - delegate: - (nonnull id<PasswordDetailsTableViewControllerDelegate>) - delegate - reauthenticationModule: - (nonnull id<ReauthenticationProtocol>)reauthenticationModule - NS_DESIGNATED_INITIALIZER; - -- (nullable instancetype)initWithStyle:(UITableViewStyle)style NS_UNAVAILABLE; - -@end - -#endif // IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_DETAILS_TABLE_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/settings/password/password_details_table_view_controller_delegate.h b/ios/chrome/browser/ui/settings/password/password_details_table_view_controller_delegate.h deleted file mode 100644 index 4373925..0000000 --- a/ios/chrome/browser/ui/settings/password/password_details_table_view_controller_delegate.h +++ /dev/null
@@ -1,27 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_DETAILS_TABLE_VIEW_CONTROLLER_DELEGATE_H_ -#define IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_DETAILS_TABLE_VIEW_CONTROLLER_DELEGATE_H_ - -#import <Foundation/Foundation.h> - -namespace autofill { -struct PasswordForm; -} // namespace autofill - -@class PasswordDetailsTableViewController; - -// PasswordDetailsTableViewController uses this protocal to interact with higher -// level password controller. -@protocol PasswordDetailsTableViewControllerDelegate - -- (void)passwordDetailsTableViewController: - (PasswordDetailsTableViewController*)controller - deletePassword: - (const autofill::PasswordForm&)passwordForm; - -@end - -#endif // IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_DETAILS_TABLE_VIEW_CONTROLLER_DELEGATE_H_
diff --git a/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.h b/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.h index f53420e..e5edaac 100644 --- a/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.h +++ b/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.h
@@ -5,7 +5,7 @@ #ifndef IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORDS_TABLE_VIEW_CONTROLLER_H_ #define IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORDS_TABLE_VIEW_CONTROLLER_H_ -#import "ios/chrome/browser/ui/settings/password/password_details_table_view_controller_delegate.h" +#import "ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller_delegate.h" #import "ios/chrome/browser/ui/settings/settings_controller_protocol.h" #import "ios/chrome/browser/ui/settings/settings_navigation_controller.h" #import "ios/chrome/browser/ui/settings/settings_root_table_view_controller.h" @@ -28,7 +28,7 @@ @end @interface PasswordsTableViewController (Testing) < - PasswordDetailsTableViewControllerDelegate> + LegacyPasswordDetailsTableViewControllerDelegate> // Initializes the password exporter with a (fake) |reauthenticationModule|. - (void)setReauthenticationModuleForExporter:
diff --git a/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.mm b/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.mm index 1c289c8..0c2a5a6 100644 --- a/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.mm
@@ -49,8 +49,8 @@ #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/elements/enterprise_info_popover_view_controller.h" -#import "ios/chrome/browser/ui/settings/password/password_details_table_view_controller.h" -#import "ios/chrome/browser/ui/settings/password/password_details_table_view_controller_delegate.h" +#import "ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller.h" +#import "ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller_delegate.h" #import "ios/chrome/browser/ui/settings/password/password_exporter.h" #import "ios/chrome/browser/ui/settings/password/password_issues_coordinator.h" #import "ios/chrome/browser/ui/settings/password/passwords_consumer.h" @@ -177,7 +177,7 @@ @interface PasswordsTableViewController () < BooleanObserver, ChromeIdentityServiceObserver, - PasswordDetailsTableViewControllerDelegate, + LegacyPasswordDetailsTableViewControllerDelegate, PasswordExporterDelegate, PasswordExportActivityViewControllerDelegate, PasswordsConsumer, @@ -1208,8 +1208,8 @@ } - (void)openDetailedViewForForm:(const autofill::PasswordForm&)form { - PasswordDetailsTableViewController* controller = - [[PasswordDetailsTableViewController alloc] + LegacyPasswordDetailsTableViewController* controller = + [[LegacyPasswordDetailsTableViewController alloc] initWithPasswordForm:form delegate:self reauthenticationModule:_reauthenticationModule]; @@ -1462,10 +1462,10 @@ return cell; } -#pragma mark PasswordDetailsTableViewControllerDelegate +#pragma mark LegacyPasswordDetailsTableViewControllerDelegate - (void)passwordDetailsTableViewController: - (PasswordDetailsTableViewController*)controller + (LegacyPasswordDetailsTableViewController*)controller deletePassword:(const autofill::PasswordForm&)form { _passwordStore->RemoveLogin(form);
diff --git a/ios/chrome/browser/ui/settings/password/passwords_table_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/password/passwords_table_view_controller_unittest.mm index e1ecbf0..2c3479d 100644 --- a/ios/chrome/browser/ui/settings/password/passwords_table_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/settings/password/passwords_table_view_controller_unittest.mm
@@ -25,7 +25,7 @@ #include "ios/chrome/browser/passwords/password_check_observer_bridge.h" #include "ios/chrome/browser/passwords/save_passwords_consumer.h" #import "ios/chrome/browser/ui/settings/cells/settings_check_item.h" -#import "ios/chrome/browser/ui/settings/password/password_details_table_view_controller.h" +#import "ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller.h" #import "ios/chrome/browser/ui/settings/password/password_issues_coordinator.h" #import "ios/chrome/browser/ui/settings/password/passwords_consumer.h" #import "ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h"
diff --git a/ios/chrome/browser/ui/settings/resources/BUILD.gn b/ios/chrome/browser/ui/settings/resources/BUILD.gn index 9c89d8e..43bca9f 100644 --- a/ios/chrome/browser/ui/settings/resources/BUILD.gn +++ b/ios/chrome/browser/ui/settings/resources/BUILD.gn
@@ -128,6 +128,14 @@ ] } +imageset("settings_safe_browsing") { + sources = [ + "settings_safe_browsing.imageset/Contents.json", + "settings_safe_browsing.imageset/settings_safe_browsing@2x.png", + "settings_safe_browsing.imageset/settings_safe_browsing@3x.png", + ] +} + imageset("settings_search_engine") { sources = [ "settings_search_engine.imageset/Contents.json",
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_passwords.imageset/Contents.json b/ios/chrome/browser/ui/settings/resources/settings_safe_browsing.imageset/Contents.json similarity index 67% copy from ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_passwords.imageset/Contents.json copy to ios/chrome/browser/ui/settings/resources/settings_safe_browsing.imageset/Contents.json index a31b671..8f859ab 100644 --- a/ios/chrome/browser/ui/settings/clear_browsing_data/resources/clear_browsing_data_passwords.imageset/Contents.json +++ b/ios/chrome/browser/ui/settings/resources/settings_safe_browsing.imageset/Contents.json
@@ -3,12 +3,12 @@ { "idiom": "universal", "scale": "2x", - "filename": "clear_browsing_data_passwords@2x.png" + "filename": "settings_safe_browsing@2x.png" }, { "idiom": "universal", "scale": "3x", - "filename": "clear_browsing_data_passwords@3x.png" + "filename": "settings_safe_browsing@3x.png" } ], "info": {
diff --git a/ios/chrome/browser/ui/settings/resources/settings_safe_browsing.imageset/settings_safe_browsing@2x.png b/ios/chrome/browser/ui/settings/resources/settings_safe_browsing.imageset/settings_safe_browsing@2x.png new file mode 100644 index 0000000..62209991a --- /dev/null +++ b/ios/chrome/browser/ui/settings/resources/settings_safe_browsing.imageset/settings_safe_browsing@2x.png Binary files differ
diff --git a/ios/chrome/browser/ui/settings/resources/settings_safe_browsing.imageset/settings_safe_browsing@3x.png b/ios/chrome/browser/ui/settings/resources/settings_safe_browsing.imageset/settings_safe_browsing@3x.png new file mode 100644 index 0000000..26d037e --- /dev/null +++ b/ios/chrome/browser/ui/settings/resources/settings_safe_browsing.imageset/settings_safe_browsing@3x.png Binary files differ
diff --git a/ios/chrome/browser/ui/settings/safety_check/safety_check_mediator.mm b/ios/chrome/browser/ui/settings/safety_check/safety_check_mediator.mm index ff65023..0cae299 100644 --- a/ios/chrome/browser/ui/settings/safety_check/safety_check_mediator.mm +++ b/ios/chrome/browser/ui/settings/safety_check/safety_check_mediator.mm
@@ -206,18 +206,33 @@ _updateCheckItem = [[SettingsCheckItem alloc] initWithType:UpdateItemType]; _updateCheckItem.text = l10n_util::GetNSString(IDS_IOS_SETTINGS_SAFETY_CHECK_UPDATES_TITLE); + UIImage* updateCheckIcon = [[UIImage imageNamed:@"settings_info"] + imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + _updateCheckItem.leadingImage = updateCheckIcon; + _updateCheckItem.leadingImageTintColor = [UIColor colorNamed:kGrey400Color]; _passwordCheckRowState = PasswordCheckRowStateDefault; _passwordCheckItem = [[SettingsCheckItem alloc] initWithType:PasswordItemType]; _passwordCheckItem.text = l10n_util::GetNSString(IDS_IOS_SETTINGS_SAFETY_CHECK_PASSWORDS_TITLE); + UIImage* passwordCheckIcon = [[UIImage imageNamed:@"password_key"] + imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + _passwordCheckItem.leadingImage = passwordCheckIcon; + _passwordCheckItem.leadingImageTintColor = + [UIColor colorNamed:kGrey400Color]; _safeBrowsingCheckRowState = SafeBrowsingCheckRowStateDefault; _safeBrowsingCheckItem = [[SettingsCheckItem alloc] initWithType:SafeBrowsingItemType]; _safeBrowsingCheckItem.text = l10n_util::GetNSString( IDS_IOS_SETTINGS_SAFETY_CHECK_SAFE_BROWSING_TITLE); + UIImage* safeBrowsingCheckIcon = + [[UIImage imageNamed:@"settings_safe_browsing"] + imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + _safeBrowsingCheckItem.leadingImage = safeBrowsingCheckIcon; + _safeBrowsingCheckItem.leadingImageTintColor = + [UIColor colorNamed:kGrey400Color]; _checkStartState = CheckStartStateDefault; _checkStartItem =
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 0a99154a..916d3b88 100644 --- a/ios/chrome/browser/ui/settings/settings_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/settings_table_view_controller.mm
@@ -111,6 +111,7 @@ @"settings_payment_methods"; NSString* const kSettingsAutofillProfileImageName = @"settings_addresses"; NSString* const kSettingsVoiceSearchImageName = @"settings_voice_search"; +NSString* const kSettingsSafetyCheckImageName = @"settings_safety_check"; NSString* const kSettingsPrivacyImageName = @"settings_privacy"; NSString* const kSettingsLanguageSettingsImageName = @"settings_language_settings"; @@ -635,7 +636,7 @@ return [self detailItemWithType:ItemTypeSafetyCheck text:safetyCheckTitle detailText:nil - iconImageName:kSettingsPrivacyImageName + iconImageName:kSettingsSafetyCheckImageName accessibilityIdentifier:nil]; }
diff --git a/ios/chrome/browser/ui/settings/signin_settings_egtest.mm b/ios/chrome/browser/ui/settings/signin_settings_egtest.mm index 95a46c7..d3fea67 100644 --- a/ios/chrome/browser/ui/settings/signin_settings_egtest.mm +++ b/ios/chrome/browser/ui/settings/signin_settings_egtest.mm
@@ -65,7 +65,7 @@ [SigninEarlGreyUI confirmSigninConfirmationDialog]; // User signed in. - [SigninEarlGrey checkSignedInWithFakeIdentity:fakeIdentity]; + [SigninEarlGrey verifySignedInWithFakeIdentity:fakeIdentity]; [SigninEarlGreyUI checkSigninPromoNotVisible]; [[EarlGrey selectElementWithMatcher:SettingsAccountButton()] assertWithMatcher:grey_interactable()]; @@ -84,7 +84,7 @@ [SigninEarlGreyUI confirmSigninConfirmationDialog]; // User signed in. - [SigninEarlGrey checkSignedInWithFakeIdentity:fakeIdentity]; + [SigninEarlGrey verifySignedInWithFakeIdentity:fakeIdentity]; [SigninEarlGreyUI checkSigninPromoNotVisible]; [[EarlGrey selectElementWithMatcher:SettingsAccountButton()] assertWithMatcher:grey_interactable()];
diff --git a/ios/chrome/browser/ui/settings/sync/utils/sync_fake_server_egtest.mm b/ios/chrome/browser/ui/settings/sync/utils/sync_fake_server_egtest.mm index 7763918..a01c525 100644 --- a/ios/chrome/browser/ui/settings/sync/utils/sync_fake_server_egtest.mm +++ b/ios/chrome/browser/ui/settings/sync/utils/sync_fake_server_egtest.mm
@@ -4,7 +4,7 @@ #include "base/strings/sys_string_conversions.h" #import "base/test/ios/wait_util.h" -#import "ios/chrome/browser/ui/authentication/signin_earl_grey_app_interface.h" +#import "ios/chrome/browser/ui/authentication/signin_earl_grey.h" #import "ios/chrome/browser/ui/authentication/signin_earl_grey_ui.h" #import "ios/chrome/browser/ui/bookmarks/bookmark_earl_grey.h" #import "ios/chrome/test/earl_grey/chrome_earl_grey.h" @@ -69,8 +69,8 @@ [BookmarkEarlGrey addBookmarkWithTitle:@"foo" URL:@"https://www.foo.com"]; // Sign in to sync, after a bookmark has been added. - FakeChromeIdentity* fakeIdentity = [SigninEarlGreyAppInterface fakeIdentity1]; - [SigninEarlGreyAppInterface addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1]; + [SigninEarlGrey addFakeIdentity:fakeIdentity]; [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; // Assert that the correct number of bookmarks have been synced. @@ -80,8 +80,8 @@ // Tests that a bookmark added on the client is uploaded to the Sync server. - (void)testSyncUploadBookmark { - FakeChromeIdentity* fakeIdentity = [SigninEarlGreyAppInterface fakeIdentity1]; - [SigninEarlGreyAppInterface addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1]; + [SigninEarlGrey addFakeIdentity:fakeIdentity]; [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; // Add a bookmark after sync is initialized. @@ -98,8 +98,8 @@ [ChromeEarlGrey addFakeSyncServerBookmarkWithURL:URL title:"hoo"]; // Sign in to sync, after a bookmark has been injected in the sync server. - FakeChromeIdentity* fakeIdentity = [SigninEarlGreyAppInterface fakeIdentity1]; - [SigninEarlGreyAppInterface addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1]; + [SigninEarlGrey addFakeIdentity:fakeIdentity]; [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; [ChromeEarlGrey waitForSyncInitialized:YES syncTimeout:kSyncOperationTimeout]; [BookmarkEarlGrey verifyBookmarksWithTitle:@"hoo" expectedCount:1]; @@ -108,8 +108,8 @@ // Tests that the local cache guid does not change when sync is restarted. - (void)testSyncCheckSameCacheGuid_SyncRestarted { // Sign in the fake identity. - FakeChromeIdentity* fakeIdentity = [SigninEarlGreyAppInterface fakeIdentity1]; - [SigninEarlGreyAppInterface addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1]; + [SigninEarlGrey addFakeIdentity:fakeIdentity]; [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; [ChromeEarlGrey waitForSyncInitialized:YES syncTimeout:kSyncOperationTimeout]; @@ -129,15 +129,14 @@ // signs back in with the same account. - (void)testSyncCheckDifferentCacheGuid_SignOutAndSignIn { // Sign in a fake identity, and store the initial sync guid. - FakeChromeIdentity* fakeIdentity = [SigninEarlGreyAppInterface fakeIdentity1]; - [SigninEarlGreyAppInterface addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1]; + [SigninEarlGrey addFakeIdentity:fakeIdentity]; [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; [ChromeEarlGrey waitForSyncInitialized:YES syncTimeout:kSyncOperationTimeout]; std::string original_guid = [ChromeEarlGrey syncCacheGUID]; - GREYAssert([SigninEarlGreyAppInterface isAuthenticated], - @"User is not signed in."); - [SigninEarlGreyAppInterface signOut]; + [SigninEarlGrey verifyAuthenticated]; + [SigninEarlGrey signOut]; [ChromeEarlGrey waitForSyncInitialized:NO syncTimeout:kSyncOperationTimeout]; // Sign the user back in, and verify the guid has changed. @@ -153,14 +152,13 @@ // Test for http://crbug.com/413611 . - (void)testSyncCheckSameCacheGuid_SyncRestartedAfterSignOutAndSignIn { // Sign in a fake idenitty. - FakeChromeIdentity* fakeIdentity = [SigninEarlGreyAppInterface fakeIdentity1]; - [SigninEarlGreyAppInterface addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1]; + [SigninEarlGrey addFakeIdentity:fakeIdentity]; [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; [ChromeEarlGrey waitForSyncInitialized:YES syncTimeout:kSyncOperationTimeout]; - GREYAssert([SigninEarlGreyAppInterface isAuthenticated], - @"User is not signed in."); - [SigninEarlGreyAppInterface signOut]; + [SigninEarlGrey verifyAuthenticated]; + [SigninEarlGrey signOut]; [ChromeEarlGrey waitForSyncInitialized:NO syncTimeout:kSyncOperationTimeout]; // Sign the user back in. @@ -193,8 +191,8 @@ }]; // Sign in to sync. - FakeChromeIdentity* fakeIdentity = [SigninEarlGreyAppInterface fakeIdentity1]; - [SigninEarlGreyAppInterface addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1]; + [SigninEarlGrey addFakeIdentity:fakeIdentity]; [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; // Verify that the autofill profile has been downloaded. @@ -221,8 +219,8 @@ }]; // Sign in to sync. - FakeChromeIdentity* fakeIdentity = [SigninEarlGreyAppInterface fakeIdentity1]; - [SigninEarlGreyAppInterface addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1]; + [SigninEarlGrey addFakeIdentity:fakeIdentity]; [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; // Verify that the autofill profile has been downloaded. @@ -266,8 +264,8 @@ }]; // Sign in to sync. - FakeChromeIdentity* fakeIdentity = [SigninEarlGreyAppInterface fakeIdentity1]; - [SigninEarlGreyAppInterface addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1]; + [SigninEarlGrey addFakeIdentity:fakeIdentity]; [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; // Verify that the autofill profile has been downloaded @@ -306,8 +304,8 @@ [ChromeEarlGrey loadURL:URL2]; // Sign in to sync, after opening two tabs. - FakeChromeIdentity* fakeIdentity = [SigninEarlGreyAppInterface fakeIdentity1]; - [SigninEarlGreyAppInterface addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1]; + [SigninEarlGrey addFakeIdentity:fakeIdentity]; [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; // Verify the sessions on the sync server. @@ -333,8 +331,8 @@ [ChromeEarlGrey addHistoryServiceTypedURL:mockURL]; // Sign in to sync. - FakeChromeIdentity* fakeIdentity = [SigninEarlGreyAppInterface fakeIdentity1]; - [SigninEarlGreyAppInterface addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1]; + [SigninEarlGrey addFakeIdentity:fakeIdentity]; [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; [ChromeEarlGrey waitForSyncInitialized:YES syncTimeout:kSyncOperationTimeout]; @@ -360,8 +358,8 @@ [ChromeEarlGrey addFakeSyncServerTypedURL:mockURL]; // Sign in to sync. - FakeChromeIdentity* fakeIdentity = [SigninEarlGreyAppInterface fakeIdentity1]; - [SigninEarlGreyAppInterface addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1]; + [SigninEarlGrey addFakeIdentity:fakeIdentity]; [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; [ChromeEarlGrey waitForSyncInitialized:YES syncTimeout:kSyncOperationTimeout]; @@ -386,8 +384,8 @@ [ChromeEarlGrey addFakeSyncServerTypedURL:mockURL]; // Sign in to sync. - FakeChromeIdentity* fakeIdentity = [SigninEarlGreyAppInterface fakeIdentity1]; - [SigninEarlGreyAppInterface addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1]; + [SigninEarlGrey addFakeIdentity:fakeIdentity]; [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; [ChromeEarlGrey waitForSyncInitialized:YES syncTimeout:kSyncOperationTimeout]; @@ -420,8 +418,8 @@ [ChromeEarlGrey addHistoryServiceTypedURL:mockURL]; // Sign in to sync. - FakeChromeIdentity* fakeIdentity = [SigninEarlGreyAppInterface fakeIdentity1]; - [SigninEarlGreyAppInterface addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1]; + [SigninEarlGrey addFakeIdentity:fakeIdentity]; [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; [ChromeEarlGrey waitForSyncInitialized:YES syncTimeout:kSyncOperationTimeout]; @@ -462,8 +460,8 @@ originator_client_item_id:"1"]; // Sign in to sync. - FakeChromeIdentity* fakeIdentity = [SigninEarlGreyAppInterface fakeIdentity1]; - [SigninEarlGreyAppInterface addFakeIdentity:fakeIdentity]; + FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1]; + [SigninEarlGrey addFakeIdentity:fakeIdentity]; [SigninEarlGreyUI signinWithFakeIdentity:fakeIdentity]; [ChromeEarlGrey waitForSyncInitialized:YES syncTimeout:kSyncOperationTimeout];
diff --git a/ios/chrome/test/app/password_test_util.mm b/ios/chrome/test/app/password_test_util.mm index 187a0c0..370884e 100644 --- a/ios/chrome/test/app/password_test_util.mm +++ b/ios/chrome/test/app/password_test_util.mm
@@ -5,7 +5,7 @@ #include "ios/chrome/test/app/password_test_util.h" #include "base/mac/foundation_util.h" -#import "ios/chrome/browser/ui/settings/password/password_details_table_view_controller+testing.h" +#import "ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller+testing.h" #import "ios/chrome/browser/ui/settings/password/passwords_table_view_controller.h" #import "ios/chrome/browser/ui/settings/settings_navigation_controller.h" #import "ios/chrome/browser/ui/util/top_view_controller.h" @@ -53,9 +53,10 @@ SettingsNavigationController* settings_navigation_controller = base::mac::ObjCCastStrict<SettingsNavigationController>( top_view_controller::TopPresentedViewController()); - PasswordDetailsTableViewController* password_details_table_view_controller = - base::mac::ObjCCastStrict<PasswordDetailsTableViewController>( - settings_navigation_controller.topViewController); + LegacyPasswordDetailsTableViewController* + password_details_table_view_controller = + base::mac::ObjCCastStrict<LegacyPasswordDetailsTableViewController>( + settings_navigation_controller.topViewController); [password_details_table_view_controller setReauthenticationModule:mock_reauthentication_module]; return mock_reauthentication_module;
diff --git a/ios/chrome/test/earl_grey/chrome_earl_grey.h b/ios/chrome/test/earl_grey/chrome_earl_grey.h index 0699e90..19ff4a7f 100644 --- a/ios/chrome/test/earl_grey/chrome_earl_grey.h +++ b/ios/chrome/test/earl_grey/chrome_earl_grey.h
@@ -39,6 +39,11 @@ // will properly synchronize the UI for Earl Grey tests. @interface ChromeEarlGreyImpl : BaseEGTestHelperImpl +#pragma mark - Test Utilities + +// Wait until |matcher| is accessible (not nil) on the device. +- (void)waitForMatcher:(id<GREYMatcher>)matcher; + #pragma mark - Device Utilities // Simulate the user action to rotate the device to a certain orientation. @@ -348,11 +353,6 @@ // the operation fails. - (void)signOutAndClearIdentities; -// Same as signOutAndClearIdentities. -// -// DEPRECATED in favor of signOutAndClearIdentities -- (void)signOutAndClearAccounts; - #pragma mark - Sync Utilities (EG2) // Waits for sync to be initialized or not. If not succeeded a GREYAssert is
diff --git a/ios/chrome/test/earl_grey/chrome_earl_grey.mm b/ios/chrome/test/earl_grey/chrome_earl_grey.mm index 8b10d7d..281972b 100644 --- a/ios/chrome/test/earl_grey/chrome_earl_grey.mm +++ b/ios/chrome/test/earl_grey/chrome_earl_grey.mm
@@ -72,6 +72,23 @@ @implementation ChromeEarlGreyImpl +#pragma mark - Test Utilities + +- (void)waitForMatcher:(id<GREYMatcher>)matcher { + ConditionBlock condition = ^{ + NSError* error = nil; + [[EarlGrey selectElementWithMatcher:matcher] assertWithMatcher:grey_notNil() + error:&error]; + return error == nil; + }; + NSString* errorString = + [NSString stringWithFormat:@"Waiting for matcher %@ failed.", matcher]; + EG_TEST_HELPER_ASSERT_TRUE( + base::test::ios::WaitUntilConditionOrTimeout( + base::test::ios::kWaitForUIElementTimeout, condition), + errorString); +} + #pragma mark - Device Utilities - (void)rotateDeviceToOrientation:(UIDeviceOrientation)deviceOrientation @@ -833,16 +850,12 @@ @"Failed waiting for identities to be cleared"); } -- (void)signOutAndClearAccounts { - [self signOutAndClearIdentities]; -} +#pragma mark - Bookmarks Utilities (EG2) - (void)addBookmarkWithSyncPassphrase:(NSString*)syncPassphrase { [ChromeEarlGreyAppInterface addBookmarkWithSyncPassphrase:syncPassphrase]; } -#pragma mark - Bookmarks Utilities (EG2) - - (void)waitForBookmarksToFinishLoading { EG_TEST_HELPER_ASSERT_NO_ERROR( [ChromeEarlGreyAppInterface waitForBookmarksToFinishinLoading]);
diff --git a/ios/chrome/test/earl_grey2/BUILD.gn b/ios/chrome/test/earl_grey2/BUILD.gn index b878822..0efc635 100644 --- a/ios/chrome/test/earl_grey2/BUILD.gn +++ b/ios/chrome/test/earl_grey2/BUILD.gn
@@ -84,7 +84,6 @@ "//ios/chrome/browser/policy_url_blocking:eg2_tests", "//ios/chrome/browser/prerender:eg2_tests", "//ios/chrome/browser/safe_browsing:eg2_tests", - "//ios/chrome/browser/translate:eg2_tests", "//ios/chrome/browser/ui/autofill:eg2_tests", "//ios/chrome/browser/ui/autofill/manual_fill:eg2_tests", "//ios/chrome/browser/ui/content_suggestions:eg2_tests",
diff --git a/media/gpu/vaapi/h264_vaapi_video_decoder_delegate.cc b/media/gpu/vaapi/h264_vaapi_video_decoder_delegate.cc index 05427a7..0a23c7bb 100644 --- a/media/gpu/vaapi/h264_vaapi_video_decoder_delegate.cc +++ b/media/gpu/vaapi/h264_vaapi_video_decoder_delegate.cc
@@ -7,6 +7,7 @@ #include <va/va.h> #include "base/stl_util.h" +#include "base/trace_event/trace_event.h" #include "media/gpu/decode_surface_handler.h" #include "media/gpu/h264_dpb.h" #include "media/gpu/macros.h" @@ -67,6 +68,8 @@ const H264Picture::Vector& ref_pic_listb1, scoped_refptr<H264Picture> pic) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + TRACE_EVENT0("media,gpu", + "H264VaapiVideoDecoderDelegate::SubmitFrameMetadata"); VAPictureParameterBufferH264 pic_param; memset(&pic_param, 0, sizeof(pic_param)); @@ -183,6 +186,7 @@ size_t size, const std::vector<SubsampleEntry>& subsamples) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + TRACE_EVENT0("media,gpu", "H264VaapiVideoDecoderDelegate::SubmitSlice"); VASliceParameterBufferH264 slice_param; memset(&slice_param, 0, sizeof(slice_param)); @@ -282,6 +286,7 @@ DecodeStatus H264VaapiVideoDecoderDelegate::SubmitDecode( scoped_refptr<H264Picture> pic) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + TRACE_EVENT0("media,gpu", "H264VaapiVideoDecoderDelegate::SubmitDecode"); const bool success = vaapi_wrapper_->ExecuteAndDestroyPendingBuffers( pic->AsVaapiH264Picture()->va_surface()->id());
diff --git a/media/gpu/vaapi/vaapi_video_decoder.cc b/media/gpu/vaapi/vaapi_video_decoder.cc index 39a64a5..4818406 100644 --- a/media/gpu/vaapi/vaapi_video_decoder.cc +++ b/media/gpu/vaapi/vaapi_video_decoder.cc
@@ -83,7 +83,7 @@ buffer_id_to_timestamp_(kTimestampCacheSize), weak_this_factory_(this) { VLOGF(2); - DCHECK(decoder_task_runner->RunsTasksInCurrentSequence()); + DCHECK(decoder_task_runner_->RunsTasksInCurrentSequence()); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); weak_this_ = weak_this_factory_.GetWeakPtr();
diff --git a/media/gpu/vaapi/vaapi_wrapper.cc b/media/gpu/vaapi/vaapi_wrapper.cc index c17b7b8..5c7441ba 100644 --- a/media/gpu/vaapi/vaapi_wrapper.cc +++ b/media/gpu/vaapi/vaapi_wrapper.cc
@@ -1692,9 +1692,13 @@ TRACE_EVENT0("media,gpu", "VaapiWrapper::SubmitBufferLocked"); VABufferID buffer_id; - VAStatus va_res = vaCreateBuffer(va_display_, va_context_id_, va_buffer_type, - size, 1, nullptr, &buffer_id); - VA_SUCCESS_OR_RETURN(va_res, "vaCreateBuffer", false); + { + TRACE_EVENT0("media,gpu", "VaapiWrapper::SubmitBuffer_vaCreateBuffer"); + const VAStatus va_res = + vaCreateBuffer(va_display_, va_context_id_, va_buffer_type, size, 1, + nullptr, &buffer_id); + VA_SUCCESS_OR_RETURN(va_res, "vaCreateBuffer", false); + } ScopedVABufferMapping mapping( va_lock_, va_display_, buffer_id, @@ -1706,18 +1710,7 @@ // such as libyuv::CopyX and family. memcpy(mapping.data(), buffer, size); - switch (va_buffer_type) { - case VASliceParameterBufferType: - case VASliceDataBufferType: - case VAEncSliceParameterBufferType: - pending_slice_bufs_.push_back(buffer_id); - break; - - default: - pending_va_bufs_.push_back(buffer_id); - break; - } - + pending_va_buffers_.push_back(buffer_id); return true; } @@ -1743,7 +1736,7 @@ params->type = misc_param_type; memcpy(params->data, buffer, size); - pending_va_bufs_.push_back(buffer_id); + pending_va_buffers_.push_back(buffer_id); return true; } @@ -1756,18 +1749,11 @@ void VaapiWrapper::DestroyPendingBuffers_Locked() { TRACE_EVENT0("media,gpu", "VaapiWrapper::DestroyPendingBuffers_Locked"); va_lock_->AssertAcquired(); - for (const auto& pending_va_buf : pending_va_bufs_) { + for (const auto& pending_va_buf : pending_va_buffers_) { VAStatus va_res = vaDestroyBuffer(va_display_, pending_va_buf); VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer"); } - - for (const auto& pending_slice_buf : pending_slice_bufs_) { - VAStatus va_res = vaDestroyBuffer(va_display_, pending_slice_buf); - VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer"); - } - - pending_va_bufs_.clear(); - pending_slice_bufs_.clear(); + pending_va_buffers_.clear(); } bool VaapiWrapper::ExecuteAndDestroyPendingBuffers(VASurfaceID va_surface_id) { @@ -2376,8 +2362,7 @@ TRACE_EVENT0("media,gpu", "VaapiWrapper::Execute_Locked"); va_lock_->AssertAcquired(); - DVLOG(4) << "Pending VA bufs to commit: " << pending_va_bufs_.size(); - DVLOG(4) << "Pending slice bufs to commit: " << pending_slice_bufs_.size(); + DVLOG(4) << "Pending VA bufs to commit: " << pending_va_buffers_.size(); DVLOG(4) << "Target VA surface " << va_surface_id; const auto decode_start_time = base::TimeTicks::Now(); @@ -2385,20 +2370,12 @@ VAStatus va_res = vaBeginPicture(va_display_, va_context_id_, va_surface_id); VA_SUCCESS_OR_RETURN(va_res, "vaBeginPicture", false); - if (pending_va_bufs_.size() > 0) { + if (pending_va_buffers_.size() > 0) { // Commit parameter and slice buffers. - va_res = vaRenderPicture(va_display_, va_context_id_, &pending_va_bufs_[0], - pending_va_bufs_.size()); - VA_SUCCESS_OR_RETURN(va_res, "vaRenderPicture for |pending_va_bufs_|", - false); - } - - if (pending_slice_bufs_.size() > 0) { va_res = - vaRenderPicture(va_display_, va_context_id_, &pending_slice_bufs_[0], - pending_slice_bufs_.size()); - VA_SUCCESS_OR_RETURN(va_res, "vaRenderPicture for |pending_slice_bufs_|", - false); + vaRenderPicture(va_display_, va_context_id_, &pending_va_buffers_[0], + pending_va_buffers_.size()); + VA_SUCCESS_OR_RETURN(va_res, "vaRenderPicture", false); } // Instruct HW codec to start processing the submitted commands. In theory,
diff --git a/media/gpu/vaapi/vaapi_wrapper.h b/media/gpu/vaapi/vaapi_wrapper.h index c4d005b..ea451e5 100644 --- a/media/gpu/vaapi/vaapi_wrapper.h +++ b/media/gpu/vaapi/vaapi_wrapper.h
@@ -456,8 +456,7 @@ VAEntrypoint va_entrypoint_; // Data queued up for HW codec, to be committed on next execution. - std::vector<VABufferID> pending_slice_bufs_; - std::vector<VABufferID> pending_va_bufs_; + std::vector<VABufferID> pending_va_buffers_; // Buffers for kEncode or kVideoProcess. std::set<VABufferID> va_buffers_;
diff --git a/media/gpu/vaapi/vp8_vaapi_video_decoder_delegate.cc b/media/gpu/vaapi/vp8_vaapi_video_decoder_delegate.cc index bc75725f..c68ca3b 100644 --- a/media/gpu/vaapi/vp8_vaapi_video_decoder_delegate.cc +++ b/media/gpu/vaapi/vp8_vaapi_video_decoder_delegate.cc
@@ -4,6 +4,7 @@ #include "media/gpu/vaapi/vp8_vaapi_video_decoder_delegate.h" +#include "base/trace_event/trace_event.h" #include "media/gpu/decode_surface_handler.h" #include "media/gpu/vaapi/va_surface.h" #include "media/gpu/vaapi/vaapi_common.h" @@ -31,6 +32,7 @@ bool VP8VaapiVideoDecoderDelegate::SubmitDecode( scoped_refptr<VP8Picture> pic, const Vp8ReferenceFrameVector& reference_frames) { + TRACE_EVENT0("media,gpu", "VP8VaapiVideoDecoderDelegate::SubmitDecode"); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); auto va_surface_id = pic->AsVaapiVP8Picture()->va_surface()->id();
diff --git a/media/gpu/vaapi/vp9_vaapi_video_decoder_delegate.cc b/media/gpu/vaapi/vp9_vaapi_video_decoder_delegate.cc index dca0183..6d6089b 100644 --- a/media/gpu/vaapi/vp9_vaapi_video_decoder_delegate.cc +++ b/media/gpu/vaapi/vp9_vaapi_video_decoder_delegate.cc
@@ -7,6 +7,7 @@ #include <type_traits> #include "base/stl_util.h" +#include "base/trace_event/trace_event.h" #include "media/gpu/decode_surface_handler.h" #include "media/gpu/macros.h" #include "media/gpu/vaapi/va_surface.h" @@ -37,6 +38,7 @@ const Vp9LoopFilterParams& lf, const Vp9ReferenceFrameVector& ref_frames, base::OnceClosure done_cb) { + TRACE_EVENT0("media,gpu", "VP9VaapiVideoDecoderDelegate::SubmitDecode"); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // |done_cb| should be null as we return false from IsFrameContextRequired(). DCHECK(!done_cb);
diff --git a/media/test/data/test-25fps.vp9_2.json b/media/test/data/test-25fps.vp9_2.json index 8d3036d..fc38be3 100644 --- a/media/test/data/test-25fps.vp9_2.json +++ b/media/test/data/test-25fps.vp9_2.json
@@ -6,256 +6,256 @@ "num_frames": 250, "num_fragments": 250, "md5_checksums": [ - "9c8d2359e9a386af75805e18ec985961", - "57c1de8f7c8c712098acc78d88ff4b3e", - "10d2824b4b5224bbe483e4030f937d87", - "44a157abbe00572269ee6cd308e11329", - "6c668f802d3945b5df04f12fdcbadd58", - "50828e75f435c4950d89ab54a4c2cb57", - "707a97e75ceacedfb644b1c600dcce0f", - "51b8a2d6d19d72a66c35c1b16ccf6d23", - "8efadd6cddd4498b985d22a0f5a087e5", - "445d78cf7bdfbd258819bfbbc284dbac", - "7e43e1cbb16030027400ddcde5ac4b1f", - "dc72a49f119a10e358eb91a74bcca0a7", - "0744410b6182cbdecc7b52a75bb8a519", - "87f572a1ccb96b70e7cfe49b7c1be9ab", - "55f2802a408417972c7af23c391b8c44", - "34978d638ea2a137926b801130c4f18d", - "fb16afccef3fd0a2542d3f886e3bc76e", - "22f838188988d72cc3c82aadc6c1de85", - "d825769ed309c32356711b8ea7976a98", - "eec173a8c7979145f8af625857e5a446", - "964dc0e71ac4b0acab184c499f69933d", - "f7a2b524ef638dfbb1a8a8151ec668ac", - "5acdec2e3b9b4df67fbefe41c43b55eb", - "04e7d42e6b2843bdf4be46cdd984250a", - "d9e2695475faace4124c19f219d192b4", - "82a477bc93bff493eeef4419dc795364", - "7f6a1012b842badf22a96302e52d1c9f", - "72e9217e59d03dd9e3c7ceb44d390222", - "7ec11e9f20c7e7842c8b1f65be6a7f79", - "f650b9cf36b221b9371c2b373620261c", - "1be04f17c85fffb9059e909db472df17", - "f64acfd484eb6ab1289b806c78103243", - "75ee71fa45d8a5f4e551d9d4c087d715", - "6092e2320de1858170f4e94f370c3cbc", - "ecae6e91a65706b74214ea17e65982e3", - "489cb0430901612ba6cfb54b415cad86", - "416c0bfbe0fb303d2ebb677e0cebc2c3", - "450b55553f5d4ccee41d6bafddc8d66f", - "31a08830592579be51c54a36eed02ca5", - "c3c7fb2eccc757436c17e041a56265db", - "96797f2fd84a8b072ea81f06fd36b161", - "44c4f28fe56481e49841d8a1196aca73", - "27fbdac1ac2d3172893b3a372be1dcaf", - "8dd0e468258e6a7641cc00bce5933a3a", - "d1a0c5d9ae55512e24147e4b0b6bd2d0", - "2e6415fc0a171e65af7687c57a869707", - "707e29961513add6f8bb0ba96e773c23", - "faf3fdf60e84ece33c7d85b4a73d2e4b", - "1c689c78dbbf0f4656cadc83438db77b", - "353e37243a25f5bc18de5a9c895e761d", - "088f6f072527e0ce0fd2289a90822b79", - "9199724ac90a61857be49aba874d2b05", - "b0fef1e0e18a9397dd95f40d0366b14b", - "2d1f148dc258f311e4e78c069fc8279a", - "a1844ba1b7022418fa660ac07978565b", - "275b8950b6db868f8ef6daab76751f26", - "dd2611b54ba903d22c490248796c0770", - "34e1af274cceae16c1af581b74a2bfed", - "2c2631e1e7f986f9fb314a8fccda3416", - "54eb141d09babc58ab1d4fae1f3fabb6", - "b8a36207caca157b80bbdfe0b3bab84c", - "dca5651dbf37f9e68daae11bc379c9c3", - "981d282c2ca643c67d7a5d3e8fae083b", - "072b62e0fea29d0554ffae727bad28aa", - "fbf200c751dd34f12201d649b3c9761f", - "741793c713d9ea7e1280c3c54dbed3ab", - "da0f631880f9d1f977df3685039bfb36", - "753f23fdf2e24cdec879a78bf99e45cd", - "d6bae48cec01deeef406850a8766c394", - "197cb360c601ca6fbec8c48d7601814a", - "299c8aa6ad085707da9a8c6ce9313d66", - "c3da551786a43fcfaa015fedecefc6e4", - "7f2290dcec74191321dc751becb660e5", - "36ce0d47afec42e276ae58121011ce19", - "4436670d6ff987dac66ef725e7b738be", - "f4b1de84c1e1d243fb84fd8533a5034d", - "4eb8547b6f5959897c17ca3d6e5095ce", - "0df7d40e75b61421275903f49d5bf433", - "e247fbd3fb4165e9671dc2e3b58f4330", - "17b70d99ae075eba2604038e73b78f7e", - "476efb80455eb9a910415558d20e678f", - "c7e4ae096e9c01fa4fb309d8d55ebaa9", - "534f701fdb032a4a8f1ffeac6ca7e382", - "eeaa58a6e51bd05b7f5992ddaa98cebe", - "1ab34252d9333a6b90614763e6292ecf", - "f38232d49c9a0bceeaa8a4fc70cdff53", - "f430c6a6eaf0bca74510af92f1fb0285", - "94c70343e8d247cc76aca65a9d970579", - "225c5c349d1b9f3285f600c5faab2696", - "971b496ac2f6d77e89e9324457edaf02", - "78d83325ba3ae1fb78253edbbed9411e", - "ad49ed47dcf40f2093f74fb3a022c06a", - "b1630fe2eca7dc580ba195cb59551050", - "6dc6bd1491344192a34628ac76eeb9a0", - "2d942bf3670f1a64ce22d79f48061a42", - "882184c577f9ca601cea95381be975ec", - "f898aac1c4dca650d07b16fedee014e5", - "c2f3f2a63489984ff8b6a971914330b4", - "ee355a981b5a42ca3b515a49bf380dba", - "d7a61e44eec316815897cd86994b1235", - "68139f52ccb8705dd22ebe4bb9524ee3", - "2e7a0870e9f8f4a1ec4204b0c06218ec", - "be548ed3a0c64356c14457ceae01dc38", - "04e1f67e239f0f73da7c232c9294072e", - "403bc2f26f8a9de3ba63ad9e19815670", - "27c5a416fa50602b028b4767d6ca6313", - "33855b39710bc55f06d8d3a7cd6187d9", - "acbcdf202836c60b42e666a7fba81d09", - "02368ff27221dd277557bc82470d6367", - "865328ba8e13bde83a50b46b85e1b076", - "a973b4473645a6634800d14f6dda1d97", - "e4e72d4d40860ccf2ea0267af5b72489", - "5ed66a2fe444483a300bf4c87996d708", - "0362687d3a2ce08a13d9a0af351ae7e5", - "294a0202e60f468a4a0111b0dac74545", - "113aa715f07345eb183a84e7f5d1c14d", - "076072a893a559dc51c4ead9b41b67e2", - "96fc3ac5086234bb89332a72d4a3f05b", - "2d9a85feb30528560700ecc75077b34a", - "5b4ff61881281f2cdcd7ec68994bf000", - "1703491c88136f11432095be8c8cd9ec", - "aa90c0ff07e92edee5cd9388533d862a", - "8959ac9fdc0d5cf54b2f4b73ec8ad269", - "b8cf1d36559b4e18a3668af2746bcfd7", - "79117f25d8fabc44b77c841f53138c41", - "dbcb468a686d34a27e7bf79af5087046", - "b3df5e803085d66d573a000b03bb5768", - "b8beb470fb3e6670d46402823554915d", - "bfc550bc5ddba1c3dba83edb301e3ee4", - "5f6d0d25dddbca7e0c6bb42d4dba89b6", - "d98738374520a5bb7e1d21fdb5e87407", - "c355489f09f82d736cdf5bb2ccc82261", - "304d7bc869ba553e3523de59009997bc", - "fc9728b3bc1bd368763336a00fab9e54", - "310bf813ca94275ca55db36f64c94229", - "2be2f6385fcc9547b93e242ae6c6d0f0", - "1d44e33800065aa5e07e0c14f5fde547", - "8b0be65793c3d03cf77e0c90dbb046e6", - "9e3e6c1399a81f26b53d9ea5462a0ff4", - "65368dac9c1d08eadb56a76e9c8daa3b", - "210ab55b98e741ad8fa44ebf8ce1643d", - "9dec552fac1955003119c487c3c374ab", - "b806750076ddf0b11f8ebb693ada10aa", - "2ed5d34e65c1658f79543dc90ce04f7e", - "31caf9b589d6b18ac08bc12d99c53dcb", - "77445ea1f386da761abb9df0a5df2931", - "c6cefb579b056dca6cbec2eadb479367", - "d62b2fd426a1ba28e7653fbe4539cdc4", - "ead3d369c77c0313e5b26fb3e3f30ff4", - "4ba709ab0ff256366ba1a583ef8e9d5f", - "e3ada41c1ac6045871b5cc0b4271e53c", - "a1ca36927d9f19613d40fcdbf1e54e1c", - "9317cf6eb772e225fd74b4bbe6aac481", - "44fcf37d4c6b9e902de29a41f6549d4b", - "ee97e17e6e8522d60ad29b171a511d13", - "980295287a80c6d6751504f396ded0a6", - "3ee20ecc430e0c09ca9ac22ae14b5d44", - "49f9b05ab4a9ff7cf0984d259b6c328f", - "e60dcf6053ef6be7b18fb92888dd56ea", - "9b74df9ab4615375faf17398f98b6faa", - "11fcad52840b47e8115d39b320494d48", - "88a4a8a095a5bb138ce98e39e5ec136c", - "2a02e8ea5207d99a36104b5c87ad373f", - "2287ed564f063b811f897baca2c5eea6", - "bc8aa50f126350ce32a8755b229eab63", - "c5520093169c46ea2c0ed299f29f6f56", - "10a53939eba7b29d0687db5a01f5bfd3", - "b519a65817702c79e4ee81341f238b17", - "44f637d4e72a64ca67764e1ab4e4e775", - "3f55610f9057a187556e68691c5aa25c", - "e27044a23e24e93e96c3331ac1ae89c3", - "fa986c7410f3c7164716783169715b8a", - "aaba77fcfc5c380c0178c0e5d423fa73", - "e01e7089da41fb47bc7289e7eaddef91", - "ff092fb21d050e46134dec7d522a3d12", - "82fd84dc3c20fc315fc924a036636ddb", - "17a986aaa4cb079c5e772b28ab7ea4a0", - "25fcb0f1ea2dcc658cc941a5f7e1a368", - "9177407682d5d3add1d2cd28d111835c", - "059337dc93f280591c3940b2384c6b68", - "0bece31e5dec6a8376187d7674919676", - "9e7ef48e848a8585be3711f376f05b23", - "3e204cbe59b95226d0f21fc25219920d", - "1faa664937e7afaf408e5e0b3fef0377", - "cdcf11c4d5434d6ba4dcf2cabb50b401", - "bf8dece1593a2d3d557f4a1ca947e89b", - "71f41d00990f902c9d300a4cd36e7f55", - "c2f2cb98a370dd1906f3e2d0a9345bd5", - "54fe13e1aa4442fbe3115faedec60dd7", - "1397873cd572460c90009dffa5fa6418", - "54cda5502c1c6c639f88a8d056198d41", - "dd995b9ad824d8bcca8d2d1df52a945f", - "63288ceb960a870a9272be3684851240", - "eac81c0630ff9c9e66e56335acc0f883", - "3ae643b7245d997d3c6ca7dd65b40e42", - "9deeff4a6ccd87c9c8f402cd0fe7c112", - "15b5fa016db2ea9a0c552276116d29d8", - "b1e4f7b117972c131d04f5b7577f5356", - "f4ef1489090d8ac2a2a9a097b9468fbc", - "dba800c799a259615c5cb85ddd075189", - "a3c74b815cf875c1895b7af24d2d9d1a", - "53557ad9a04fec9ce85a797dabf5f416", - "10242f9b71a44fa79094b26165436b9f", - "6a703674d91480bc24fb8e066158d53b", - "d925c0dc0e19a676b01490d050b7152e", - "357f045ec25d88e4473c8c9bb1271163", - "26d9053c54b31cd616d4711d0e49158e", - "d8fbb4d8bf9db88d6cfe7c2354ea03ef", - "58a976cc6cf903121aa1c29925aae94a", - "e77ec312b75326e7868f8f938e6c3195", - "423b2ff3e7d99a6997866b5a4583496c", - "9a5578dcf1b53b5e624f4c750df4916d", - "5e2cde9533a57da707aa0360674a6810", - "ba45f35c5dd9881bbd4cfe3a712fd045", - "5c4754d7610a6f8831a53dd30f1340cf", - "25ba552ca55e8961311fe067c1078291", - "57f4073e98ecd969730a83d7e54dc1ab", - "76956a1564ebedaffd76814402b4647a", - "7558b862412061a5ce82a0b0c7bf56ae", - "85013cf9653d384f1de2f186767ec933", - "0b9fd790fdfef148d5e95583ff1a0258", - "1edc6486684000f16a880d4522b77882", - "a4dd0e3f6362b5848f5a5655e8df5e7a", - "5d8d566682d44334c8af1bf9ab70d68b", - "fb4f617b09fd9f3df670612fb6d4e087", - "4e8f3a63d536b59a44dbf1bd64758052", - "bd4f9f8d74989ad67835b6f134c4ca14", - "c2334251188056cb45e2627b5a953ba3", - "83e5706f503558a5645e567430bf2670", - "6c1e98da202f4a7d2c40a6e9e848e494", - "ea088ac8d9fd7e0af2ab557c5f005db9", - "f70fb5f97ff9c763d18f27da53003d08", - "fb2d4cd555540acaada343faba6e2271", - "fd3dad9490b627f226595cf2cac3a172", - "15cab446131cc42616317e4e256a5625", - "e322972f6fd72c72c46000fee4e68c91", - "aeb53d75520cac68e37c5743b0644f9a", - "19893ca56b715a1abe2167077e1485ed", - "4f8985ce61045e203e2095effa1058ef", - "6758ad39404c9ae4966550c9699d27c5", - "2ad303311377498de85fdbc0db007259", - "518d296c6b2d1ffa7bb6a8e05ae24521", - "6183d06dd93892d2619c55cc733a35f0", - "c3b81884db7c5ad2a63f184aa9979c14", - "7e9103458073436993f05254c42e2f33", - "ce7133eb15db513ada44e1637bf2dc13", - "ab9bf0d935045d25050b3da7016af3a4", - "70c3771a7abcebfb0e318e71704f1230", - "4a2f3dfed38e13d939a84d80c02e1726", - "33b05476d513c7a1d2de6bae77031685" + "0f3489c0340ccdcd4fb457621caf6918", + "fd5db934b5acbfb178b4c829f982d29b", + "201461a4256783d5776df7b403435c99", + "dad4bc94e234a55cd87dd936a2f70b5e", + "604fa6fc46744bb01713e0c74c889f6b", + "7eb563e7b078bb04d2853701a8eea29c", + "c073d8876d177b6129b947a486280a8f", + "6195248b702eb41bd20b4495bacdebbf", + "6c9404ec3cdd61f78204e280140371ce", + "611b4b9c318423386affacb9150cb7ac", + "bbaf4acd466b835f47ae96b107b336ad", + "a1d80a407f30aaa9d9f720f1cbd93d92", + "a5068703a449fdcbf90bd0da894bd6ad", + "81e1227d81e55cd6b3b8b5a358390748", + "8d7f30b985c2895ec087344b7b45f8f6", + "8a9a8b717c3591698691bd70a80d9508", + "e4d2762a4032b9b2fdb8b4cbae0882c1", + "27a20c25cd80a5fc60072b394f2d09cd", + "292efafb2f6eeb49e92180bcc72a2b28", + "83aee86ca149819318e03ce370be7ac5", + "ecaa285f3e1227583165280ce21b597d", + "da29f499d0bb7e81751c067aba59b537", + "3e1929c6d28f90d89d1f6b61c980b692", + "d6d2048316efb031c138a708b98c57b8", + "77284b06772bd77ed805bb096845f164", + "558e39a75ae807ec73015504f54634e4", + "c875be23f1e777ebaf24387ff68ca229", + "69db7ca5a69326e8b021ccfd2c75cdea", + "0a8dfade147d2e881632427220a13252", + "990b3fbf36dfde95b7ceb7acb082f831", + "a5297a9c0c863cd1518763a185fbdf94", + "3f8463cd1fc3e487d6d1f5d216b4c0f3", + "f2fc958318e91979ea320f6aa3bfd065", + "d158530e239435344a84760450a90242", + "8f186d82e75f056500b7a749d2931132", + "e078418bae9910822b7b7b107c8e9243", + "eec9c070873d93ac2a58e3e790e184af", + "aae8fee06da9e72fefbc2cf1f3c1e7af", + "aa7f79dc4ebe43325c16c47e53797aeb", + "5f65c81f6dec5596ef4cecbc9dd02129", + "aeb650ae40a2f64b6bdf061851b0d43c", + "b72f17167237f5f2c1a6936ced0654f9", + "c32c2785d616aac7ed1a579c7d3b4323", + "28d8d8a4a10710b2c7b97348b59117a5", + "1e13f2ded8cd48c0966f255e6c8df27d", + "84aee7d099bf370c6ec2feb9d306487e", + "d3a9615e7b36ad3364750a8028af3752", + "93d0c1173013f9c4ce4dedfb6a36a3ba", + "2c0a44e3adcea3d29591c16a17ddbd62", + "e23bde64aa4f57dd37c1063fa685a185", + "a1857a186ca7a80c10e4d0f53cebe5b4", + "632dcc8d6139f5b37853df3135d8893d", + "31e2c6995b1bef1e61251535e74d5aed", + "5a741ce3fe3cfbb37ee49ee18b370c97", + "d950225312a18feb644e185d46aa0821", + "7a283d81f5cc2dfe00103718d49222da", + "33d4dcc6c8df9dba9eedd10f7bcdfc81", + "e347cb6b05771f547a5d29ab6a4813aa", + "9cfc800c6185730ba881ba0c17038a72", + "4092590ff97327fe2a5fba8d7e81221f", + "0a84e993b89b11926120dbd5553a2692", + "a8e2672bbeeac54c04b0f645d0e51c69", + "efebc22877ba88144a807f85f8e0532b", + "60c8176ea51763f6e79831ed9e98eb15", + "bae091d7986a906a00a2c77bd81e913d", + "1d6701a28d686cb4a49b27e258932914", + "c3783425e90d64bdaaaadf375152d8b1", + "5460b46e999cc31fa08346960b647d5f", + "fe0f689aa615812ae88ca0fe5881f9b5", + "364effe8252a50aff00c098ff7b9dbc7", + "80d20971450192b92f8b975e673041f0", + "2eb1fdba702b2696769c988853c8ab62", + "96f39fa9b0556fbe686658ea76de3fc9", + "62656259ce12eb78e998a57c0504cf6c", + "60b402c81cde258a5b0ec7b7dc23e5c6", + "021dedc5b91c40449ab4d666ebd1390a", + "abc63ada241672284d538ec187c4d095", + "2697e649e2ac772566d9914f68b4d9e3", + "e08f68efb197aa11b82e6c5c1f5fe594", + "7afa749293be296fccb15ba5d4bad014", + "9b94bedc7e233a38cba241de620b03ce", + "c065e45486502ac97d5075a8255ead47", + "571c9aefdfdf2d63dc3d8a1c7c53f0d3", + "d8057bd424ef3270d21093a240b64b69", + "6515d657e051654f1bd2598a94fc629c", + "ba438c1a28cbc1c97e44c1e11ef0d5da", + "1c2609c77764bad37678deb82214e787", + "711b39c69640fd5322a179465e41800a", + "9c00cbf308c9e68eddf5dcf601837ec4", + "847a6885565416bbdb5cc10e3e3f56ad", + "9d6c4b5b1e85fe5b482b085bf59dbe08", + "47eb3a8661e1339441c99e45cab4cef2", + "8ac09ac3ee2cd9a69698b4a947905065", + "131497b7046103209b27d3a96ee058e5", + "cc257659350a6882101622f71f3bda17", + "06851634f7f93caefcb0bf3b7d2d9d62", + "79c2638d1284951d454c8a76b8925e5d", + "2973bb8b5db306f43b7fedd60a408322", + "128cdebd0276eb5649f47b6629b0d94a", + "ab3e86d0e05ed3d51ff8831f597cf1c8", + "b7604da3da48464e6171d3d00d64e99b", + "eef8db4bb3c03db811142de97cddd270", + "9376c4f9de5adc65afdd3f2054643370", + "2c4a96ce061ae939b12e91248e936557", + "0b30d5a80f23b0d5a07c5ac381fa22e5", + "fc4865f313d1e5993782787b347372e2", + "16155944c6c14fd6b1b83bc892a7267d", + "cc2d9e3a55a4bbd3ee8b58e0ec86b491", + "3035fc1cd983c4bcf983a65619847aa4", + "c7e2d818fea2eae3a95fc0af7674b7b4", + "56e2048b6b9569c77a559cc9402ee897", + "26dafb151f10dfe4bb58396b3ffd32c4", + "78eb1ff731e1d6d1747223231a7d32b8", + "395cceaaa3b5932f9235663808cfd4e9", + "9ab5f8bd2e01bf4ddcaadffd3d787714", + "d82d2f4418dcce19890bba694cad7d5f", + "4659660690a5eba2f5200c085c244111", + "318f4f6a746880f8d6a86a02fd6de2d8", + "286535a6f7a724afa2249bf424b30c92", + "c035911ccf6e970c79f0928cd58b1214", + "130b1e7d213c33726d51155774fda125", + "0cf5ac85baae39d43f0d8f88e50069c1", + "2804279d43189e6b6251fe4d791617e5", + "d672530e9c18ed0b862224760eab80d1", + "e0909510e4c51736d79c41c9b0bb8380", + "64b7380b87a84131eac615bc5e3a804e", + "f9d8703cd5b2dcdf363c5eb30a484e90", + "f230aea12bcd311bd4903c15949a49d4", + "7a0bdd68e197a0a104264a92ebd0b318", + "991fd7cd93a82ba301475430607f8b48", + "5f2cb6e7de63f6796756c327fc40f6ef", + "c4252228508d6a28deab3acf71309cb2", + "a6d2d02593f3087bab61109295937179", + "23b21446852c850b8bca5589ce1ea2c0", + "52d3032d6c9cd04e2f6425663d3da1b2", + "8b7bdc2dc4e6dfeb73ca7478faf1d9b3", + "c8d120e273be1dd2166e476b5ebd213a", + "ae7a5ab883aee28e543885432ae08363", + "d918c8c3cc0752379edc1bc571132458", + "0e82b56e2a3d4d86f92e5ce7ddf34e28", + "8a582d932d92f1b4cf714c4cef49e5f6", + "df74150037a5bf28850e9f69b9f625b4", + "3e63178b48ca6c4fa48548b406a0bbd5", + "77c0bf1195bb67e71e82bb63fb71e0aa", + "031a593b74a0bc536c14620c53a4d1f3", + "3199b239cf03dcf90161176fff02df60", + "8c34bdf2a2916f2da6ca47ef1f9bde00", + "fe621468c2d24b94ed96248c145ad5b1", + "bd27d6e49d96390e25f9510dbab86c90", + "1fe1a0ec743fa0f7029e4fd6f4d9ace6", + "38299f8d19e46e55cf5e889fb9299004", + "fd3b8e5df584881116033bf970ef4d77", + "5c715e6075e4acf384b318bf8fee3102", + "32f5f0d56f8ad79cf7850affc0c1fd48", + "47261104af6afec10bc1dc7541832fc9", + "de766d1080f625a50e8a7d797f2a9bb8", + "cd9ea735cf1a403136e08b3bd2b7e54d", + "9ccc88d0df2d7bb73cfc9de65332419d", + "13b9b29df7319c6604cbc9e2d02fc961", + "a5ebd7e17783f1dd92f6fcd3d78a2518", + "0705294fcdc639fefdc8c2117aeb5a9a", + "789e52b1c006ed9b3506b9a2915280c4", + "d94771050db81f2d9246743d658f6eed", + "7d6ceed6dee010932ed1e3e39f0f6587", + "a70f44135f31052f0c8deb81bd3a4196", + "b6fa23ee33a3d79e0247168f35e61562", + "687b3ef6600561f638c7db70f6e144be", + "9e1ca84bf1dec1226687bff5e6e00ef6", + "3e6c30b7dd84657ea47e16d195974379", + "7470f69d16208cb64defd7575d58e9a2", + "26600e013e452ad8432a6540d37e4297", + "e75066cc80c00185149eb905ce9e2d1d", + "76f83db132a075ab97a9aa8e8bdcdb58", + "332d38fab44ac872721b8fd874f5a6af", + "ff633252c0e9771e98cccb9011bc29fa", + "3d7b9ca6d8162be2b9fa5814ed5b41be", + "f840034ca0f19aeb460c0eef9416ac07", + "acca06f0f82cd219e4bfb1dd26d4e264", + "e1fc461818170a3a8a16baa4137a1e2a", + "28aebeb6642a6468a640a5d5cee9df80", + "56c6b2af5b2ffb60b9ee925fc26a00ed", + "9d840473ef0459f211c9aa2539712692", + "00b430c3560cac9d92b5bd6506f0c622", + "d6c4e17016a130925ef237a3555678f6", + "88ae296bae40574eac053af329da81cc", + "17533fd613286b431415e0c7dbb79061", + "cc60f6d82fea281cf5181f5e171b77d0", + "13443591288f6a25b76ce4cf5297177f", + "a01d2cb7efa082a6c96425c887f1b5e5", + "b3b7254e6816b8186fb496b4b664302a", + "47122ad5f33d09659fcfbb7c037587d7", + "2ae3f2f3fa05f333d2949c17ceeac8b8", + "cbcc16c6cd32662a78514c1da87ec3ab", + "c610f59aaceff811fb0f1dafb9210f19", + "1979b26d6234a0edfbeb15bb89c3270f", + "c4e5b0d94056ac1cb37196676efd39e6", + "c137cdc306a9dfef82be3b523e822548", + "bec6394e185db543b1fb840cddc8bf1c", + "d77bc4d3a7b9d450c4209a4dad33bee1", + "36ec9a9d7e9844c2bb8834804b92666b", + "9ef62d46f1d58ac606b09a4b2964b892", + "3c2ecc69e6d170a344e82f68070929fa", + "8ced6945737b30202c7436b4bb4ffe16", + "1164f3265cb50988131b857a1a95bf24", + "1ffd7e6b4cf6c03eb76de9c5731683e6", + "e3dc292fe56fdef69ac37551b4e6b7d1", + "2a8929041005f39e37ac12313c04858e", + "beb8660893cad60b217d316ec53df5f1", + "cdba1d861af5802cdbdc5110a2bb0b0e", + "51e64a56ed1647d76f5c4742f3e097ed", + "39410553bc6a4f7a5bf052fddade2dbe", + "53a26137a12e990598bdd2435cbc53a2", + "0be23327fd1d3bb06f5f5c7b172bc0b1", + "8fee322f97127596a32b078a2bdb0fed", + "2d979904bcbb32c4f8150fb5f8bc1520", + "277bfef37afe4927026088332cfa93ac", + "ba9748dfc3d5dc6666d7cca405ee9b10", + "2b712e5d6aaaa5270981e04fa54ab552", + "43ab8642b2a305aa0c3a750a8caeb8be", + "d3a82966ccf04c8428eaa1cf53cbcc7d", + "895b009ce5e7e783953d11ae7d26b0c7", + "9a3b11600f2cdf585f91c50694f95483", + "b9086011edce02c3359e7935c607f51f", + "1ed778f001666554b4325a1780325e1d", + "c8ff0c1c8a68461e0a5d54ce70349d77", + "e2cdd8639d5e44f87cb40e8d3c2d8388", + "9884eed47f96e40ef99b9e56cceffcea", + "c9666735fe424feb2b01dae39a73ec1a", + "f6cfe3cd15a2f412d803868d4a2c443d", + "028407903ad54460111d0b2f424ba293", + "1881557cabc055d8b82c79b6a6ec9a46", + "d4441c4cc53125fee0c5b8184efb825d", + "4b7aae7bc87b4fdf38099dc745422fdd", + "82d2179e3f27a822a532977ef8689c89", + "e1b0fa3da0f08963ccb94855720be942", + "d3cdb020ddaa3f4231584385324da03a", + "89033e7d8999713f959a0cb5a5bc6e25", + "6cf4a3194b8c5f9b6e5d72b80f8d6e58", + "44496a268163bdefc0f24bb3b0735298", + "3a9cf4e4bcc2fae4889342527a95f447", + "676016517bc7a1536c72b20c94531424", + "f7b03d19d41ec57d3162b3d40a6196d0", + "1bfce8405b703068f4ce063c219f80c6", + "5a4a33a778b8689d3f71d0dda49eb15e", + "5451241f22cdd192e4719585d2614e17", + "bfdf52ca5639550dbfa6c83d68cf68e7", + "1b9e832447082d52fcc6024880a4c0d7", + "2beaf5a356d5fd00568bc38774babb93", + "f4effc0d0d64f080cc3b4eaeb13a2ab8", + "fcd59329e6f64603be8672d62e1c08d1" ], "thumbnail_checksums": [ "# Intel",
diff --git a/remoting/codec/webrtc_video_encoder_selector.cc b/remoting/codec/webrtc_video_encoder_selector.cc index 1de9f855e..aae403a 100644 --- a/remoting/codec/webrtc_video_encoder_selector.cc +++ b/remoting/codec/webrtc_video_encoder_selector.cc
@@ -57,6 +57,16 @@ DCHECK_GE(codec, 0); DCHECK_LT(codec, static_cast<int>(encoders_.size())); preferred_codec_ = codec; + + // Reset so that the next call to CreateEncoder() creates an encoder which + // matches the one negotiated over SDP. Otherwise, repeated calls to + // CreateEncoder() would cycle through every codec that could encode at the + // current resolution, even when they do not match the codec "created" by + // WebRTC via the DummyVideoEncoderFactory. + + // TODO(crbug.com/1115789): Review the CreateEncoder() logic to ensure it only + // creates encoders that are compatible with the SDP-selected codec. + last_codec_ = -1; } int WebrtcVideoEncoderSelector::RegisterEncoder(
diff --git a/remoting/codec/webrtc_video_encoder_selector.h b/remoting/codec/webrtc_video_encoder_selector.h index 82e28328..071fc807 100644 --- a/remoting/codec/webrtc_video_encoder_selector.h +++ b/remoting/codec/webrtc_video_encoder_selector.h
@@ -35,6 +35,8 @@ // 6. If the encoder failed, go back to 3 with the failed DesktopFrame. // // Selector will return nullptr if there is no more codec supporting |profile_|. +// Calling SetPreferredCodec() again will reset the cycle, so that the next call +// to CreateEncoder() will start with the codec from SDP. class WebrtcVideoEncoderSelector final { public: struct Profile {
diff --git a/remoting/protocol/webrtc_video_stream.cc b/remoting/protocol/webrtc_video_stream.cc index a05b067..e96df4c3 100644 --- a/remoting/protocol/webrtc_video_stream.cc +++ b/remoting/protocol/webrtc_video_stream.cc
@@ -351,6 +351,16 @@ webrtc::VideoCodecType codec_type, const webrtc::SdpVideoFormat::Parameters& parameters) { DCHECK(thread_checker_.CalledOnValidThread()); + + // Reset the encoder in case a previous one was being used and SDP + // re-negotiation selected a different one. The proper codec will be + // created after the next frame is captured. + // An optimization would be to reset only if the new encoder is different + // from the current one. However, SDP renegotiation is expected to occur + // infrequently (only when the user changes a setting), and should typically + // not cause the same codec to be repeatedly selected. + encoder_.reset(); + // The preferred codec id depends on the order of // |encoder_selector_|.RegisterEncoder(). if (codec_type == webrtc::kVideoCodecVP8) {
diff --git a/sandbox/policy/mac/gpu_v2.sb b/sandbox/policy/mac/gpu_v2.sb index c1ee3ca..543a2724 100644 --- a/sandbox/policy/mac/gpu_v2.sb +++ b/sandbox/policy/mac/gpu_v2.sb
@@ -14,6 +14,7 @@ ; Allow communication between the GPU process and the UI server. (allow mach-lookup (global-name "com.apple.bsd.dirhelper") + (global-name "com.apple.CARenderServer") (global-name "com.apple.cfprefsd.agent") (global-name "com.apple.cfprefsd.daemon") (global-name "com.apple.CoreServices.coreservicesd")
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json index bf17e62..0b5e702bb 100644 --- a/testing/buildbot/chromium.chromiumos.json +++ b/testing/buildbot/chromium.chromiumos.json
@@ -4455,7 +4455,6 @@ "args": [ "--gtest_filter=-NetExportFileWriterTest*" ], - "experiment_percentage": 100, "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -4483,7 +4482,6 @@ "args": [ "--gtest_filter=-OutOfProcessPPAPITest.TrueTypeFont" ], - "experiment_percentage": 100, "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -4591,7 +4589,6 @@ "args": [ "--gtest_filter=-BluetoothShellApiTest.ApiSanityCheck:BluetoothSocketApiTest.Listen:BluetoothSocketApiTest.PermissionDenied" ], - "experiment_percentage": 100, "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -4608,7 +4605,6 @@ "--enable-features=StorageServiceOutOfProcess", "--gtest_filter=-BluetoothShellApiTest.ApiSanityCheck:BluetoothSocketApiTest.Listen:BluetoothSocketApiTest.PermissionDenied" ], - "experiment_percentage": 100, "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -5049,7 +5045,6 @@ "args": [ "--gtest_filter=-SingleClientSessionsSyncTestWithFaviconTestServer.ShouldDeleteOnDemandIconsOnSessionsDisabled" ], - "experiment_percentage": 100, "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py"
diff --git a/testing/buildbot/chromium.ci.json b/testing/buildbot/chromium.ci.json index fa762a6..dfbb7145 100644 --- a/testing/buildbot/chromium.ci.json +++ b/testing/buildbot/chromium.ci.json
@@ -19067,24 +19067,6 @@ ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "updater_tests", - "test_id_prefix": "ninja://chrome/updater:updater_tests/" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Windows-10-15063" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" }, @@ -20756,24 +20738,6 @@ ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "updater_tests", - "test_id_prefix": "ninja://chrome/updater:updater_tests/" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Windows-10-15063" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" }, @@ -115796,18 +115760,6 @@ "can_use_on_swarming_builders": true, "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "updater_tests", - "test_id_prefix": "ninja://chrome/updater:updater_tests/" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com" - }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" }, @@ -117035,18 +116987,6 @@ "can_use_on_swarming_builders": true, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "updater_tests", - "test_id_prefix": "ninja://chrome/updater:updater_tests/" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" }, @@ -118240,18 +118180,6 @@ "can_use_on_swarming_builders": true, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "updater_tests", - "test_id_prefix": "ninja://chrome/updater:updater_tests/" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" }, @@ -119995,24 +119923,6 @@ ], "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "updater_tests", - "test_id_prefix": "ninja://chrome/updater:updater_tests/" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Windows-10-15063" - } - ], - "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com" - }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" }, @@ -121818,24 +121728,6 @@ ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "updater_tests", - "test_id_prefix": "ninja://chrome/updater:updater_tests/" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Windows-10-15063" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" }, @@ -123641,24 +123533,6 @@ ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "updater_tests", - "test_id_prefix": "ninja://chrome/updater:updater_tests/" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Windows-10-15063" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" }, @@ -124953,18 +124827,6 @@ "can_use_on_swarming_builders": true, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "updater_tests", - "test_id_prefix": "ninja://chrome/updater:updater_tests/" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" }, @@ -126192,18 +126054,6 @@ "can_use_on_swarming_builders": true, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "updater_tests", - "test_id_prefix": "ninja://chrome/updater:updater_tests/" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" }, @@ -127431,18 +127281,6 @@ "can_use_on_swarming_builders": true, "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "updater_tests", - "test_id_prefix": "ninja://chrome/updater:updater_tests/" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com" - }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" }, @@ -128670,18 +128508,6 @@ "can_use_on_swarming_builders": true, "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "updater_tests", - "test_id_prefix": "ninja://chrome/updater:updater_tests/" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com" - }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" }, @@ -133093,17 +132919,6 @@ "swarming": { "can_use_on_swarming_builders": false }, - "test": "updater_tests", - "test_id_prefix": "ninja://chrome/updater:updater_tests/" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": false - }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" }, @@ -134275,18 +134090,6 @@ "can_use_on_swarming_builders": true, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "updater_tests", - "test_id_prefix": "ninja://chrome/updater:updater_tests/" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" }, @@ -145404,24 +145207,6 @@ ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "updater_tests", - "test_id_prefix": "ninja://chrome/updater:updater_tests/" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Windows-10-15063" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" }, @@ -147533,24 +147318,6 @@ ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "updater_tests", - "test_id_prefix": "ninja://chrome/updater:updater_tests/" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Windows-10-15063" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" }, @@ -149588,24 +149355,6 @@ ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "updater_tests", - "test_id_prefix": "ninja://chrome/updater:updater_tests/" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Windows-10-17134" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" }, @@ -151743,24 +151492,6 @@ ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "updater_tests", - "test_id_prefix": "ninja://chrome/updater:updater_tests/" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Windows-10-18363" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" }, @@ -158180,18 +157911,6 @@ "can_use_on_swarming_builders": true, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "updater_tests", - "test_id_prefix": "ninja://chrome/updater:updater_tests/" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" }, @@ -159654,18 +159373,6 @@ "can_use_on_swarming_builders": true, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "updater_tests", - "test_id_prefix": "ninja://chrome/updater:updater_tests/" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" }, @@ -255700,7 +255407,6 @@ "args": [ "--gtest_filter=-NetExportFileWriterTest*" ], - "experiment_percentage": 100, "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -255728,7 +255434,6 @@ "args": [ "--gtest_filter=-OutOfProcessPPAPITest.TrueTypeFont" ], - "experiment_percentage": 100, "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -255836,7 +255541,6 @@ "args": [ "--gtest_filter=-BluetoothShellApiTest.ApiSanityCheck:BluetoothSocketApiTest.Listen:BluetoothSocketApiTest.PermissionDenied" ], - "experiment_percentage": 100, "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -255853,7 +255557,6 @@ "--enable-features=StorageServiceOutOfProcess", "--gtest_filter=-BluetoothShellApiTest.ApiSanityCheck:BluetoothSocketApiTest.Listen:BluetoothSocketApiTest.PermissionDenied" ], - "experiment_percentage": 100, "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -256294,7 +255997,6 @@ "args": [ "--gtest_filter=-SingleClientSessionsSyncTestWithFaviconTestServer.ShouldDeleteOnDemandIconsOnSessionsDisabled" ], - "experiment_percentage": 100, "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -261318,23 +261020,6 @@ ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "updater_tests", - "test_id_prefix": "ninja://chrome/updater:updater_tests/" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "os": "Windows-10-15063" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" }, @@ -267450,23 +267135,6 @@ ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "updater_tests", - "test_id_prefix": "ninja://chrome/updater:updater_tests/" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "os": "Windows-10-15063" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" }, @@ -270205,19 +269873,6 @@ "can_use_on_swarming_builders": true, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "updater_tests", - "test_id_prefix": "ninja://chrome/updater:updater_tests/" - }, - { - "isolate_profile_data": true, - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" }, @@ -270340,6 +269995,27 @@ } ] }, + "win10-omaha-tester-rel": { + "gtest_tests": [ + { + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "integrity": "high" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "updater_tests", + "test_id_prefix": "ninja://chrome/updater:updater_tests/" + } + ] + }, "win32-archive-dbg": { "additional_compile_targets": [ "all"
diff --git a/testing/buildbot/chromium.clang.json b/testing/buildbot/chromium.clang.json index d484e682..615b8f6 100644 --- a/testing/buildbot/chromium.clang.json +++ b/testing/buildbot/chromium.clang.json
@@ -3060,24 +3060,6 @@ ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "updater_tests", - "test_id_prefix": "ninja://chrome/updater:updater_tests/" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Windows-10-15063" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" }, @@ -4749,24 +4731,6 @@ ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "updater_tests", - "test_id_prefix": "ninja://chrome/updater:updater_tests/" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Windows-10-15063" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" }, @@ -27160,18 +27124,6 @@ "can_use_on_swarming_builders": true, "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "updater_tests", - "test_id_prefix": "ninja://chrome/updater:updater_tests/" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com" - }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" }, @@ -28399,18 +28351,6 @@ "can_use_on_swarming_builders": true, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "updater_tests", - "test_id_prefix": "ninja://chrome/updater:updater_tests/" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" }, @@ -29604,18 +29544,6 @@ "can_use_on_swarming_builders": true, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "updater_tests", - "test_id_prefix": "ninja://chrome/updater:updater_tests/" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" }, @@ -31359,24 +31287,6 @@ ], "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "updater_tests", - "test_id_prefix": "ninja://chrome/updater:updater_tests/" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Windows-10-15063" - } - ], - "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com" - }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" }, @@ -33182,24 +33092,6 @@ ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "updater_tests", - "test_id_prefix": "ninja://chrome/updater:updater_tests/" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Windows-10-15063" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" }, @@ -35005,24 +34897,6 @@ ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "updater_tests", - "test_id_prefix": "ninja://chrome/updater:updater_tests/" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Windows-10-15063" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" }, @@ -36317,18 +36191,6 @@ "can_use_on_swarming_builders": true, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "updater_tests", - "test_id_prefix": "ninja://chrome/updater:updater_tests/" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" }, @@ -37556,18 +37418,6 @@ "can_use_on_swarming_builders": true, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "updater_tests", - "test_id_prefix": "ninja://chrome/updater:updater_tests/" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" }, @@ -38795,18 +38645,6 @@ "can_use_on_swarming_builders": true, "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "updater_tests", - "test_id_prefix": "ninja://chrome/updater:updater_tests/" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com" - }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" }, @@ -40034,18 +39872,6 @@ "can_use_on_swarming_builders": true, "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "updater_tests", - "test_id_prefix": "ninja://chrome/updater:updater_tests/" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com" - }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" }, @@ -44691,23 +44517,6 @@ ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "updater_tests", - "test_id_prefix": "ninja://chrome/updater:updater_tests/" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "os": "Windows-10-15063" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" },
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index b982281..e25acd85 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -1667,17 +1667,6 @@ "swarming": { "can_use_on_swarming_builders": false }, - "test": "updater_tests", - "test_id_prefix": "ninja://chrome/updater:updater_tests/" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": false - }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" }, @@ -3393,24 +3382,6 @@ ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "updater_tests", - "test_id_prefix": "ninja://chrome/updater:updater_tests/" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Windows-10-17134" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" }, @@ -5548,24 +5519,6 @@ ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "updater_tests", - "test_id_prefix": "ninja://chrome/updater:updater_tests/" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Windows-10-18363" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" }, @@ -65576,19 +65529,6 @@ "can_use_on_swarming_builders": true, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "updater_tests", - "test_id_prefix": "ninja://chrome/updater:updater_tests/" - }, - { - "isolate_profile_data": true, - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" }, @@ -65711,6 +65651,27 @@ } ] }, + "win10-omaha-tester-rel": { + "gtest_tests": [ + { + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "integrity": "high" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "updater_tests", + "test_id_prefix": "ninja://chrome/updater:updater_tests/" + } + ] + }, "win7-blink-rel-dummy": { "isolated_scripts": [ {
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json index fbb1703..4a3d7501 100644 --- a/testing/buildbot/chromium.memory.json +++ b/testing/buildbot/chromium.memory.json
@@ -19157,23 +19157,6 @@ ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "updater_tests", - "test_id_prefix": "ninja://chrome/updater:updater_tests/" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "os": "Windows-10-15063" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" },
diff --git a/testing/buildbot/chromium.win.json b/testing/buildbot/chromium.win.json index 6444471..9f4bc8c1 100644 --- a/testing/buildbot/chromium.win.json +++ b/testing/buildbot/chromium.win.json
@@ -1097,18 +1097,6 @@ "can_use_on_swarming_builders": true, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "updater_tests", - "test_id_prefix": "ninja://chrome/updater:updater_tests/" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" }, @@ -3226,24 +3214,6 @@ ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "updater_tests", - "test_id_prefix": "ninja://chrome/updater:updater_tests/" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Windows-10-15063" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" }, @@ -5355,24 +5325,6 @@ ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "updater_tests", - "test_id_prefix": "ninja://chrome/updater:updater_tests/" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Windows-10-15063" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" }, @@ -6962,18 +6914,6 @@ "can_use_on_swarming_builders": true, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "updater_tests", - "test_id_prefix": "ninja://chrome/updater:updater_tests/" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" }, @@ -8436,18 +8376,6 @@ "can_use_on_swarming_builders": true, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "updater_tests", - "test_id_prefix": "ninja://chrome/updater:updater_tests/" - }, - { - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, "test": "url_unittests", "test_id_prefix": "ninja://url:url_unittests/" },
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl index daeca87f..31b7635 100644 --- a/testing/buildbot/test_suite_exceptions.pyl +++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -837,7 +837,6 @@ }, # https://crbug.com/1111979, 'linux-lacros-tester-rel': { - 'experiment_percentage': 100, 'args': [ '--gtest_filter=-NetExportFileWriterTest*', ], @@ -976,7 +975,6 @@ }, # https://crbug.com/1111979, 'linux-lacros-tester-rel': { - 'experiment_percentage': 100, 'args': [ '--gtest_filter=-OutOfProcessPPAPITest.TrueTypeFont', ], @@ -1155,7 +1153,6 @@ }, # https://crbug.com/1111979, 'linux-lacros-tester-rel': { - 'experiment_percentage': 100, 'args': [ '--gtest_filter=-BluetoothShellApiTest.ApiSanityCheck:BluetoothSocketApiTest.Listen:BluetoothSocketApiTest.PermissionDenied', ], @@ -2365,7 +2362,6 @@ }, # https://crbug.com/1111979, 'linux-lacros-tester-rel': { - 'experiment_percentage': 100, 'args': [ '--gtest_filter=-BluetoothShellApiTest.ApiSanityCheck:BluetoothSocketApiTest.Listen:BluetoothSocketApiTest.PermissionDenied', ], @@ -2442,7 +2438,6 @@ }, # https://crbug.com/1111979, 'linux-lacros-tester-rel': { - 'experiment_percentage': 100, 'args': [ '--gtest_filter=-SingleClientSessionsSyncTestWithFaviconTestServer.ShouldDeleteOnDemandIconsOnSessionsDisabled', ],
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index 2897562..cb927226 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -3686,6 +3686,10 @@ }, }, + 'omaha_gtests': { + 'updater_tests': {}, + }, + 'opus_tests': { 'opus_tests': { 'args': [ @@ -4360,7 +4364,6 @@ ], }, }, - 'updater_tests': {}, 'zucchini_unittests': {}, },
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl index 6c0565a..13373af 100644 --- a/testing/buildbot/waterfalls.pyl +++ b/testing/buildbot/waterfalls.pyl
@@ -2472,6 +2472,18 @@ 'gtest_tests': 'chromium_win_gtests', }, }, + 'win10-omaha-tester-rel': { + 'test_suites': { + 'gtest_tests': 'omaha_gtests', + }, + 'swarming': { + 'dimension_sets': [ + { + 'integrity': 'high', + } + ] + }, + }, 'win7-blink-rel-dummy': { 'swarming': { 'dimension_sets': [
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 15a5123..041a5991 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -1675,6 +1675,25 @@ ] } ], + "CompositingOptimizations": [ + { + "platforms": [ + "android", + "chromeos", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "CompositingOptimizations" + ] + } + ] + } + ], "ContentCapture": [ { "platforms": [ @@ -3545,6 +3564,21 @@ ] } ], + "IOSMessagesOverlay": [ + { + "platforms": [ + "ios" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "InfobarOverlayUI" + ] + } + ] + } + ], "IOSPageInfoRefactoring": [ { "platforms": [ @@ -5156,26 +5190,6 @@ ] } ], - "PaintHolding": [ - { - "platforms": [ - "android", - "android_weblayer", - "chromeos", - "linux", - "mac", - "windows" - ], - "experiments": [ - { - "name": "Enabled", - "enable_features": [ - "PaintHolding" - ] - } - ] - } - ], "PaintHoldingCrossOrigin": [ { "platforms": [ @@ -8375,6 +8389,21 @@ ] } ], + "WebViewHeaderInjection": [ + { + "platforms": [ + "android_webview" + ], + "experiments": [ + { + "name": "SameDomainOnly", + "enable_features": [ + "WebViewExtraHeadersSameDomainOnly" + ] + } + ] + } + ], "WebViewOriginCheckForStreamReader": [ { "platforms": [
diff --git a/third_party/abseil-cpp/.github/ISSUE_TEMPLATE/00-bug_report.md b/third_party/abseil-cpp/.github/ISSUE_TEMPLATE/00-bug_report.md new file mode 100644 index 0000000..1edf3de0 --- /dev/null +++ b/third_party/abseil-cpp/.github/ISSUE_TEMPLATE/00-bug_report.md
@@ -0,0 +1,41 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: 'bug' +assignees: '' +--- + +**Describe the bug** + +Include a clear and concise description of what the problem is, including what +you expected to happen, and what actually happened. + +**Steps to reproduce the bug** + +It's important that we are able to reproduce the problem that you are +experiencing. Please provide all code and relevant steps to reproduce the +problem, including your `BUILD`/`CMakeLists.txt` file and build commands. Links +to a GitHub branch or [godbolt.org](https://godbolt.org/) that demonstrate the +problem are also helpful. + +**What version of Abseil are you using?** + +**What operating system and version are you using** + +If you are using a Linux distribution please include the name and version of the +distribution as well. + +**What compiler and version are you using?** + +Please include the output of `gcc -v` or `clang -v`, or the equivalent for your +compiler. + +**What build system are you using?** + +Please include the output of `bazel --version` or `cmake --version`, or the +equivalent for your build system. + +**Additional context** + +Add any other context about the problem here.
diff --git a/third_party/abseil-cpp/.github/ISSUE_TEMPLATE/90-question.md b/third_party/abseil-cpp/.github/ISSUE_TEMPLATE/90-question.md new file mode 100644 index 0000000..84cf349 --- /dev/null +++ b/third_party/abseil-cpp/.github/ISSUE_TEMPLATE/90-question.md
@@ -0,0 +1,7 @@ +--- +name: Question +about: Have a question? Ask us anything! :-) +title: '' +labels: 'question' +assignees: '' +---
diff --git a/third_party/abseil-cpp/.github/ISSUE_TEMPLATE/config.yml b/third_party/abseil-cpp/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..9794ae1 --- /dev/null +++ b/third_party/abseil-cpp/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1 @@ +blank_issues_enables: true
diff --git a/third_party/abseil-cpp/CMake/AbseilDll.cmake b/third_party/abseil-cpp/CMake/AbseilDll.cmake index c001621..af7c004 100644 --- a/third_party/abseil-cpp/CMake/AbseilDll.cmake +++ b/third_party/abseil-cpp/CMake/AbseilDll.cmake
@@ -138,7 +138,6 @@ "random/internal/distribution_caller.h" "random/internal/fastmath.h" "random/internal/fast_uniform_bits.h" - "random/internal/gaussian_distribution_gentables.cc" "random/internal/generate_real.h" "random/internal/iostream_state_saver.h" "random/internal/mock_helpers.h"
diff --git a/third_party/abseil-cpp/README.chromium b/third_party/abseil-cpp/README.chromium index bf23d0a..edf51b4 100644 --- a/third_party/abseil-cpp/README.chromium +++ b/third_party/abseil-cpp/README.chromium
@@ -4,7 +4,7 @@ License: Apache 2.0 License File: LICENSE Version: 0 -Revision: f66bc749282dd7cffc68b641f527740e95e90cfa +Revision: 1beb3191c20ea315186dc761540d25c4939f1892 Security Critical: yes Description:
diff --git a/third_party/abseil-cpp/absl/base/internal/bits.h b/third_party/abseil-cpp/absl/base/internal/bits.h index 14c51d8b..81648e2 100644 --- a/third_party/abseil-cpp/absl/base/internal/bits.h +++ b/third_party/abseil-cpp/absl/base/internal/bits.h
@@ -83,10 +83,11 @@ #elif defined(_MSC_VER) && !defined(__clang__) // MSVC does not have __buitin_clzll. Compose two calls to _BitScanReverse unsigned long result = 0; // NOLINT(runtime/int) - if ((n >> 32) && _BitScanReverse(&result, n >> 32)) { + if ((n >> 32) && + _BitScanReverse(&result, static_cast<unsigned long>(n >> 32))) { return 31 - result; } - if (_BitScanReverse(&result, n)) { + if (_BitScanReverse(&result, static_cast<unsigned long>(n))) { return 63 - result; } return 64; @@ -170,10 +171,10 @@ #elif defined(_MSC_VER) && !defined(__clang__) unsigned long result = 0; // NOLINT(runtime/int) if (static_cast<uint32_t>(n) == 0) { - _BitScanForward(&result, n >> 32); + _BitScanForward(&result, static_cast<unsigned long>(n >> 32)); return result + 32; } - _BitScanForward(&result, n); + _BitScanForward(&result, static_cast<unsigned long>(n)); return result; #elif defined(__GNUC__) || defined(__clang__) static_assert(sizeof(unsigned long long) == sizeof(n), // NOLINT(runtime/int)
diff --git a/third_party/abseil-cpp/absl/container/internal/raw_hash_set.h b/third_party/abseil-cpp/absl/container/internal/raw_hash_set.h index 1f304b6..48a1a8c 100644 --- a/third_party/abseil-cpp/absl/container/internal/raw_hash_set.h +++ b/third_party/abseil-cpp/absl/container/internal/raw_hash_set.h
@@ -523,7 +523,8 @@ // if they are equal, false if they are not. If two keys compare equal, then // their hash values as defined by Hash MUST be equal. // -// Allocator: an Allocator [https://devdocs.io/cpp/concept/allocator] with which +// Allocator: an Allocator +// [https://en.cppreference.com/w/cpp/named_req/Allocator] with which // the storage of the hashtable will be allocated and the elements will be // constructed and destroyed. template <class Policy, class Hash, class Eq, class Alloc>
diff --git a/third_party/abseil-cpp/absl/copts/GENERATED_AbseilCopts.cmake b/third_party/abseil-cpp/absl/copts/GENERATED_AbseilCopts.cmake index 935eb6d..97bd283e 100644 --- a/third_party/abseil-cpp/absl/copts/GENERATED_AbseilCopts.cmake +++ b/third_party/abseil-cpp/absl/copts/GENERATED_AbseilCopts.cmake
@@ -89,6 +89,7 @@ "-Wwrite-strings" "-Wno-missing-field-initializers" "-Wno-sign-compare" + "-DNOMINMAX" ) list(APPEND ABSL_GCC_TEST_FLAGS @@ -146,6 +147,7 @@ "-Wobjc-literal-conversion" "-Wno-sign-conversion" "-Wstring-conversion" + "-DNOMINMAX" ) list(APPEND ABSL_LLVM_TEST_FLAGS
diff --git a/third_party/abseil-cpp/absl/copts/GENERATED_copts.bzl b/third_party/abseil-cpp/absl/copts/GENERATED_copts.bzl index dad5b28..bcdd61e 100644 --- a/third_party/abseil-cpp/absl/copts/GENERATED_copts.bzl +++ b/third_party/abseil-cpp/absl/copts/GENERATED_copts.bzl
@@ -90,6 +90,7 @@ "-Wwrite-strings", "-Wno-missing-field-initializers", "-Wno-sign-compare", + "-DNOMINMAX", ] ABSL_GCC_TEST_FLAGS = [ @@ -147,6 +148,7 @@ "-Wobjc-literal-conversion", "-Wno-sign-conversion", "-Wstring-conversion", + "-DNOMINMAX", ] ABSL_LLVM_TEST_FLAGS = [
diff --git a/third_party/abseil-cpp/absl/copts/copts.py b/third_party/abseil-cpp/absl/copts/copts.py index 7c3edb6..a3437c1 100644 --- a/third_party/abseil-cpp/absl/copts/copts.py +++ b/third_party/abseil-cpp/absl/copts/copts.py
@@ -141,6 +141,8 @@ # Google style does not use unsigned integers, though STL containers # have unsigned types. "-Wno-sign-compare", + # Don't define min and max macros (Build on Windows using gcc) + "-DNOMINMAX", ], "ABSL_GCC_TEST_FLAGS": [ "-Wno-conversion-null", @@ -152,7 +154,10 @@ "-Wno-unused-private-field", ], "ABSL_LLVM_FLAGS": - LLVM_BIG_WARNING_FLAGS + LLVM_DISABLE_WARNINGS_FLAGS, + LLVM_BIG_WARNING_FLAGS + LLVM_DISABLE_WARNINGS_FLAGS + [ + # Don't define min and max macros (Build on Windows using clang) + "-DNOMINMAX", + ], "ABSL_LLVM_TEST_FLAGS": LLVM_TEST_DISABLE_WARNINGS_FLAGS, "ABSL_CLANG_CL_FLAGS":
diff --git a/third_party/abseil-cpp/absl/flags/BUILD.bazel b/third_party/abseil-cpp/absl/flags/BUILD.bazel index 524e702..92bd4f15 100644 --- a/third_party/abseil-cpp/absl/flags/BUILD.bazel +++ b/third_party/abseil-cpp/absl/flags/BUILD.bazel
@@ -465,6 +465,7 @@ ":marshalling", ":reflection", "//absl/memory", + "//absl/strings", "@com_google_googletest//:gtest_main", ], )
diff --git a/third_party/abseil-cpp/absl/flags/BUILD.gn b/third_party/abseil-cpp/absl/flags/BUILD.gn index a9fbbcb1..99c61ca 100644 --- a/third_party/abseil-cpp/absl/flags/BUILD.gn +++ b/third_party/abseil-cpp/absl/flags/BUILD.gn
@@ -4,13 +4,7 @@ import("//third_party/abseil-cpp/absl.gni") -# Build targets in this module are marked as "testonly" because it is not clear -# how ABSL_FLAG will interact with //base/command_line.h. -# If this is a problem, feel free to remove "testonly" and use "assert_no_deps" -# on the main Chrome binary. - absl_source_set("path_util") { - testonly = true public = [ "internal/path_util.h" ] deps = [ "//third_party/abseil-cpp/absl/base:config", @@ -20,7 +14,6 @@ } absl_source_set("program_name") { - testonly = true sources = [ "internal/program_name.cc" ] public = [ "internal/program_name.h" ] deps = [ @@ -34,7 +27,6 @@ } absl_source_set("config") { - testonly = true sources = [ "usage_config.cc" ] public = [ "config.h", @@ -51,7 +43,6 @@ } absl_source_set("marshalling") { - testonly = true sources = [ "marshalling.cc" ] public = [ "marshalling.h" ] deps = [ @@ -64,7 +55,6 @@ } absl_source_set("commandlineflag_internal") { - testonly = true public = [ "internal/commandlineflag.h" ] sources = [ "internal/commandlineflag.cc" ] deps = [ @@ -75,7 +65,6 @@ } absl_source_set("commandlineflag") { - testonly = true sources = [ "commandlineflag.cc" ] public = [ "commandlineflag.h" ] deps = [ @@ -88,7 +77,6 @@ } absl_source_set("private_handle_accessor") { - testonly = true sources = [ "internal/private_handle_accessor.cc" ] public = [ "internal/private_handle_accessor.h" ] deps = [ @@ -101,7 +89,6 @@ } absl_source_set("reflection") { - testonly = true sources = [ "reflection.cc" ] public = [ "internal/registry.h", @@ -120,7 +107,6 @@ } absl_source_set("flag_internal") { - testonly = true sources = [ "internal/flag.cc" ] public = [ "internal/flag.h" ] deps = [ @@ -145,7 +131,6 @@ } absl_source_set("flag") { - testonly = true sources = [ "flag.cc" ] public = [ "declare.h", @@ -163,7 +148,6 @@ } absl_source_set("usage_internal") { - testonly = true sources = [ "internal/usage.cc" ] public = [ "internal/usage.h" ] deps = [ @@ -183,7 +167,6 @@ } absl_source_set("usage") { - testonly = true sources = [ "usage.cc" ] public = [ "usage.h" ] deps = [ @@ -196,7 +179,6 @@ } absl_source_set("parse") { - testonly = true sources = [ "parse.cc" ] public = [ "internal/parse.h",
diff --git a/third_party/abseil-cpp/absl/flags/reflection_test.cc b/third_party/abseil-cpp/absl/flags/reflection_test.cc index 9781e59..2da0a0e 100644 --- a/third_party/abseil-cpp/absl/flags/reflection_test.cc +++ b/third_party/abseil-cpp/absl/flags/reflection_test.cc
@@ -23,6 +23,8 @@ #include "absl/flags/internal/commandlineflag.h" #include "absl/flags/marshalling.h" #include "absl/memory/memory.h" +#include "absl/strings/str_cat.h" +#include "absl/strings/str_split.h" ABSL_FLAG(int, int_flag, 1, "int_flag help"); ABSL_FLAG(std::string, string_flag, "dflt", "string_flag help"); @@ -57,4 +59,183 @@ EXPECT_NE(handle, nullptr); } +// -------------------------------------------------------------------- + +struct CustomUDT { + CustomUDT() : a(1), b(1) {} + CustomUDT(int a_, int b_) : a(a_), b(b_) {} + + friend bool operator==(const CustomUDT& f1, const CustomUDT& f2) { + return f1.a == f2.a && f1.b == f2.b; + } + + int a; + int b; +}; +bool AbslParseFlag(absl::string_view in, CustomUDT* f, std::string*) { + std::vector<absl::string_view> parts = + absl::StrSplit(in, ':', absl::SkipWhitespace()); + + if (parts.size() != 2) return false; + + if (!absl::SimpleAtoi(parts[0], &f->a)) return false; + + if (!absl::SimpleAtoi(parts[1], &f->b)) return false; + + return true; +} +std::string AbslUnparseFlag(const CustomUDT& f) { + return absl::StrCat(f.a, ":", f.b); +} + +} // namespace + +// -------------------------------------------------------------------- + +ABSL_FLAG(bool, test_flag_01, true, ""); +ABSL_FLAG(int, test_flag_02, 1234, ""); +ABSL_FLAG(int16_t, test_flag_03, -34, ""); +ABSL_FLAG(uint16_t, test_flag_04, 189, ""); +ABSL_FLAG(int32_t, test_flag_05, 10765, ""); +ABSL_FLAG(uint32_t, test_flag_06, 40000, ""); +ABSL_FLAG(int64_t, test_flag_07, -1234567, ""); +ABSL_FLAG(uint64_t, test_flag_08, 9876543, ""); +ABSL_FLAG(double, test_flag_09, -9.876e-50, ""); +ABSL_FLAG(float, test_flag_10, 1.234e12f, ""); +ABSL_FLAG(std::string, test_flag_11, "", ""); +ABSL_FLAG(absl::Duration, test_flag_12, absl::Minutes(10), ""); +static int counter = 0; +ABSL_FLAG(int, test_flag_13, 200, "").OnUpdate([]() { counter++; }); +ABSL_FLAG(CustomUDT, test_flag_14, {}, ""); + +namespace { + +TEST_F(ReflectionTest, TestFlagSaverInScope) { + { + absl::FlagSaver s; + counter = 0; + absl::SetFlag(&FLAGS_test_flag_01, false); + absl::SetFlag(&FLAGS_test_flag_02, -1021); + absl::SetFlag(&FLAGS_test_flag_03, 6009); + absl::SetFlag(&FLAGS_test_flag_04, 44); + absl::SetFlag(&FLAGS_test_flag_05, +800); + absl::SetFlag(&FLAGS_test_flag_06, -40978756); + absl::SetFlag(&FLAGS_test_flag_07, 23405); + absl::SetFlag(&FLAGS_test_flag_08, 975310); + absl::SetFlag(&FLAGS_test_flag_09, 1.00001); + absl::SetFlag(&FLAGS_test_flag_10, -3.54f); + absl::SetFlag(&FLAGS_test_flag_11, "asdf"); + absl::SetFlag(&FLAGS_test_flag_12, absl::Hours(20)); + absl::SetFlag(&FLAGS_test_flag_13, 4); + absl::SetFlag(&FLAGS_test_flag_14, CustomUDT{-1, -2}); + } + + EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_01), true); + EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_02), 1234); + EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_03), -34); + EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_04), 189); + EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_05), 10765); + EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_06), 40000); + EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_07), -1234567); + EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 9876543); + EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_09), -9.876e-50, 1e-55); + EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_10), 1.234e12f, 1e5f); + EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_11), ""); + EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_12), absl::Minutes(10)); + EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_13), 200); + EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_14), CustomUDT{}); + EXPECT_EQ(counter, 2); +} + +// -------------------------------------------------------------------- + +TEST_F(ReflectionTest, TestFlagSaverVsUpdateViaReflection) { + { + absl::FlagSaver s; + counter = 0; + std::string error; + EXPECT_TRUE( + absl::FindCommandLineFlag("test_flag_01")->ParseFrom("false", &error)) + << error; + EXPECT_TRUE( + absl::FindCommandLineFlag("test_flag_02")->ParseFrom("-4536", &error)) + << error; + EXPECT_TRUE( + absl::FindCommandLineFlag("test_flag_03")->ParseFrom("111", &error)) + << error; + EXPECT_TRUE( + absl::FindCommandLineFlag("test_flag_04")->ParseFrom("909", &error)) + << error; + EXPECT_TRUE( + absl::FindCommandLineFlag("test_flag_05")->ParseFrom("-2004", &error)) + << error; + EXPECT_TRUE( + absl::FindCommandLineFlag("test_flag_06")->ParseFrom("1000023", &error)) + << error; + EXPECT_TRUE( + absl::FindCommandLineFlag("test_flag_07")->ParseFrom("69305", &error)) + << error; + EXPECT_TRUE(absl::FindCommandLineFlag("test_flag_08") + ->ParseFrom("1000000001", &error)) + << error; + EXPECT_TRUE( + absl::FindCommandLineFlag("test_flag_09")->ParseFrom("2.09021", &error)) + << error; + EXPECT_TRUE( + absl::FindCommandLineFlag("test_flag_10")->ParseFrom("-33.1", &error)) + << error; + EXPECT_TRUE( + absl::FindCommandLineFlag("test_flag_11")->ParseFrom("ADD_FOO", &error)) + << error; + EXPECT_TRUE(absl::FindCommandLineFlag("test_flag_12") + ->ParseFrom("3h11m16s", &error)) + << error; + EXPECT_TRUE( + absl::FindCommandLineFlag("test_flag_13")->ParseFrom("0", &error)) + << error; + EXPECT_TRUE( + absl::FindCommandLineFlag("test_flag_14")->ParseFrom("10:1", &error)) + << error; + } + + EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_01), true); + EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_02), 1234); + EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_03), -34); + EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_04), 189); + EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_05), 10765); + EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_06), 40000); + EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_07), -1234567); + EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 9876543); + EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_09), -9.876e-50, 1e-55); + EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_10), 1.234e12f, 1e5f); + EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_11), ""); + EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_12), absl::Minutes(10)); + EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_13), 200); + EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_14), CustomUDT{}); + EXPECT_EQ(counter, 2); +} + +// -------------------------------------------------------------------- + +TEST_F(ReflectionTest, TestMultipleFlagSaversInEnclosedScopes) { + { + absl::FlagSaver s; + absl::SetFlag(&FLAGS_test_flag_08, 10); + EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 10); + { + absl::FlagSaver s; + absl::SetFlag(&FLAGS_test_flag_08, 20); + EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 20); + { + absl::FlagSaver s; + absl::SetFlag(&FLAGS_test_flag_08, -200); + EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), -200); + } + EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 20); + } + EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 10); + } + EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 9876543); +} + } // namespace
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_libc.cc b/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_libc.cc index 3fcc75b..a14982a93 100644 --- a/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_libc.cc +++ b/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_libc.cc
@@ -153,7 +153,8 @@ std::tm tm; while (lo + 1 != hi) { const std::time_t mid = lo + (hi - lo) / 2; - if (std::tm* tmp = local_time(&mid, &tm)) { + std::tm* tmp = local_time(&mid, &tm); + if (tmp != nullptr) { if (tm_gmtoff(*tmp) == offset) { hi = mid; } else { @@ -163,7 +164,8 @@ // If std::tm cannot hold some result we resort to a linear search, // ignoring all failed conversions. Slow, but never really happens. while (++lo != hi) { - if (std::tm* tmp = local_time(&lo, &tm)) { + tmp = local_time(&lo, &tm); + if (tmp != nullptr) { if (tm_gmtoff(*tmp) == offset) break; } }
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup_test.cc b/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup_test.cc index 8f7ab15..53641bfe 100644 --- a/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup_test.cc +++ b/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup_test.cc
@@ -1004,13 +1004,13 @@ #if defined(_WIN32) || defined(_WIN64) // localtime_s() and gmtime_s() don't believe in years outside [1970:3000]. #else - const time_zone utc = LoadZone("libc:UTC"); + const time_zone cut = LoadZone("libc:UTC"); const year_t max_tm_year = year_t{std::numeric_limits<int>::max()} + 1900; - tp = convert(civil_second(max_tm_year, 12, 31, 23, 59, 59), utc); - EXPECT_EQ("2147485547-12-31T23:59:59+00:00", format(RFC3339, tp, utc)); + tp = convert(civil_second(max_tm_year, 12, 31, 23, 59, 59), cut); + EXPECT_EQ("2147485547-12-31T23:59:59+00:00", format(RFC3339, tp, cut)); const year_t min_tm_year = year_t{std::numeric_limits<int>::min()} + 1900; - tp = convert(civil_second(min_tm_year, 1, 1, 0, 0, 0), utc); - EXPECT_EQ("-2147481748-01-01T00:00:00+00:00", format(RFC3339, tp, utc)); + tp = convert(civil_second(min_tm_year, 1, 1, 0, 0, 0), cut); + EXPECT_EQ("-2147481748-01-01T00:00:00+00:00", format(RFC3339, tp, cut)); #endif } }
diff --git a/third_party/blink/public/mojom/web_feature/web_feature.mojom b/third_party/blink/public/mojom/web_feature/web_feature.mojom index c6d8ff0..35406b21 100644 --- a/third_party/blink/public/mojom/web_feature/web_feature.mojom +++ b/third_party/blink/public/mojom/web_feature/web_feature.mojom
@@ -2706,6 +2706,7 @@ kV8RTCRtpTransceiver_Stop_Method = 3375, kSecurePaymentConfirmation = 3376, kCSSInvalidVariableUnset = 3377, + kElementInternalsShadowRoot = 3378, // Add new features immediately above this line. Don't change assigned // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/blink/renderer/bindings/core/v8/generated_code_helper.cc b/third_party/blink/renderer/bindings/core/v8/generated_code_helper.cc index 37f6ed6..6fdce97 100644 --- a/third_party/blink/renderer/bindings/core/v8/generated_code_helper.cc +++ b/third_party/blink/renderer/bindings/core/v8/generated_code_helper.cc
@@ -395,7 +395,7 @@ const QualifiedName& content_attribute, const char* interface_name, const char* attribute_name) { - PerformAttributeSetCEReactionsReflect<IDLStringV2, AtomicString, + PerformAttributeSetCEReactionsReflect<IDLStringV2, const AtomicString&, &Element::setAttribute>( info, content_attribute, interface_name, attribute_name); } @@ -406,7 +406,8 @@ const char* interface_name, const char* attribute_name) { PerformAttributeSetCEReactionsReflect<IDLStringTreatNullAsEmptyStringV2, - AtomicString, &Element::setAttribute>( + const AtomicString&, + &Element::setAttribute>( info, content_attribute, interface_name, attribute_name); } @@ -415,8 +416,8 @@ const QualifiedName& content_attribute, const char* interface_name, const char* attribute_name) { - PerformAttributeSetCEReactionsReflect<IDLNullable<IDLStringV2>, AtomicString, - &Element::setAttribute>( + PerformAttributeSetCEReactionsReflect< + IDLNullable<IDLStringV2>, const AtomicString&, &Element::setAttribute>( info, content_attribute, interface_name, attribute_name); }
diff --git a/third_party/blink/renderer/bindings/generated_in_modules.gni b/third_party/blink/renderer/bindings/generated_in_modules.gni index 69023367..6fb6c65 100644 --- a/third_party/blink/renderer/bindings/generated_in_modules.gni +++ b/third_party/blink/renderer/bindings/generated_in_modules.gni
@@ -639,6 +639,8 @@ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_save_file_picker_options.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_scheduler_post_task_options.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_scheduler_post_task_options.h", + "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_secure_payment_confirmation_request.cc", + "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_secure_payment_confirmation_request.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_sensor_error_event_init.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_sensor_error_event_init.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_sensor_options.cc", @@ -1022,6 +1024,8 @@ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_screen_idle_state.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_sdp_semantics.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_sdp_semantics.h", + "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_secure_payment_confirmation_action.cc", + "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_secure_payment_confirmation_action.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_service_worker_state.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_service_worker_state.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_service_worker_update_via_cache.cc", @@ -2140,6 +2144,8 @@ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_serial_port_request_options.h", ] generated_enumeration_sources_in_modules += [ + "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_flow_control_type.cc", + "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_flow_control_type.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_parity_type.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_parity_type.h", ]
diff --git a/third_party/blink/renderer/core/css/style_change_reason.cc b/third_party/blink/renderer/core/css/style_change_reason.cc index 9a660dd1..28a564ce 100644 --- a/third_party/blink/renderer/core/css/style_change_reason.cc +++ b/third_party/blink/renderer/core/css/style_change_reason.cc
@@ -19,9 +19,7 @@ const char kDeclarativeContent[] = "Extension declarativeContent.css"; const char kDesignMode[] = "DesignMode"; const char kDisplayLock[] = "DisplayLock"; -const char kFindInvisible[] = "FindInvisible"; const char kFlatTreeChange[] = "FlatTreeChange"; -const char kFontSizeChange[] = "FontSizeChange"; const char kFonts[] = "Fonts"; const char kFrame[] = "Frame"; const char kFullscreen[] = "Fullscreen"; @@ -31,24 +29,18 @@ "Inline CSS style declaration was mutated"; const char kInspector[] = "Inspector"; const char kLanguage[] = "Language"; -const char kInvisibleChange[] = "InvisibleChange"; -const char kLazyReattach[] = "LazyReattach"; const char kLinkColorChange[] = "LinkColorChange"; const char kPlatformColorChange[] = "PlatformColorChange"; const char kPluginChanged[] = "Plugin Changed"; -const char kPolicyViolation[] = "Feature Policy Violation"; const char kPropertyRegistration[] = "PropertyRegistration"; -const char kPropertyUnregistration[] = "PropertyUnregistration"; const char kPseudoClass[] = "PseudoClass"; const char kSVGContainerSizeChange[] = "SVGContainerSizeChange"; -const char kSVGCursor[] = "SVGCursor"; const char kSettings[] = "Settings"; const char kShadow[] = "Shadow"; const char kStyleInvalidator[] = "StyleInvalidator"; const char kStyleSheetChange[] = "StyleSheetChange"; const char kUseFallback[] = "UseFallback"; const char kViewportUnits[] = "ViewportUnits"; -const char kVisitedLink[] = "VisitedLink"; const char kVisuallyOrdered[] = "VisuallyOrdered"; const char kWritingModeChange[] = "WritingModeChange"; const char kZoom[] = "Zoom";
diff --git a/third_party/blink/renderer/core/css/style_change_reason.h b/third_party/blink/renderer/core/css/style_change_reason.h index bece22e6..4415e46294 100644 --- a/third_party/blink/renderer/core/css/style_change_reason.h +++ b/third_party/blink/renderer/core/css/style_change_reason.h
@@ -24,32 +24,24 @@ extern const char kDisplayLock[]; extern const char kFrame[]; extern const char kFlatTreeChange[]; -extern const char kFontSizeChange[]; extern const char kFonts[]; extern const char kFullscreen[]; -extern const char kFindInvisible[]; extern const char kInheritedStyleChangeFromParentFrame[]; extern const char kInlineCSSStyleMutated[]; extern const char kInspector[]; -extern const char kInvisibleChange[]; extern const char kLanguage[]; -extern const char kLazyReattach[]; extern const char kLinkColorChange[]; extern const char kPlatformColorChange[]; extern const char kPluginChanged[]; -extern const char kPolicyViolation[]; extern const char kPropertyRegistration[]; -extern const char kPropertyUnregistration[]; extern const char kPseudoClass[]; extern const char kSVGContainerSizeChange[]; -extern const char kSVGCursor[]; extern const char kSettings[]; extern const char kShadow[]; extern const char kStyleInvalidator[]; extern const char kStyleSheetChange[]; extern const char kUseFallback[]; extern const char kViewportUnits[]; -extern const char kVisitedLink[]; extern const char kVisuallyOrdered[]; extern const char kWritingModeChange[]; extern const char kZoom[];
diff --git a/third_party/blink/renderer/core/frame/csp/content_security_policy.cc b/third_party/blink/renderer/core/frame/csp/content_security_policy.cc index b8b7a5ef..43c72ec3 100644 --- a/third_party/blink/renderer/core/frame/csp/content_security_policy.cc +++ b/third_party/blink/renderer/core/frame/csp/content_security_policy.cc
@@ -856,24 +856,6 @@ return is_allowed; } -bool ContentSecurityPolicy::AllowAncestors( - LocalFrame* frame, - const KURL& url, - ReportingDisposition reporting_disposition) const { - bool is_allowed = true; - for (const auto& policy : policies_) - is_allowed &= policy->AllowAncestors(frame, url, reporting_disposition); - return is_allowed; -} - -bool ContentSecurityPolicy::IsFrameAncestorsEnforced() const { - for (const auto& policy : policies_) { - if (policy->IsFrameAncestorsEnforced()) - return true; - } - return false; -} - bool ContentSecurityPolicy::AllowTrustedTypeAssignmentFailure( const String& message, const String& sample,
diff --git a/third_party/blink/renderer/core/frame/csp/content_security_policy.h b/third_party/blink/renderer/core/frame/csp/content_security_policy.h index 3d820757..1ffbbe5c 100644 --- a/third_party/blink/renderer/core/frame/csp/content_security_policy.h +++ b/third_party/blink/renderer/core/frame/csp/content_security_policy.h
@@ -311,18 +311,6 @@ static bool IsScriptInlineType(InlineType); - // |allowAncestors| does not need to know whether the resource was a - // result of a redirect. After a redirect, source paths are usually - // ignored to stop a page from learning the path to which the - // request was redirected, but this is not a concern for ancestors, - // because a child frame can't manipulate the URL of a cross-origin - // parent. - bool AllowAncestors( - LocalFrame*, - const KURL&, - ReportingDisposition = ReportingDisposition::kReport) const; - bool IsFrameAncestorsEnforced() const; - // TODO(crbug.com/889751): Remove "mojom::RequestContextType" once // all the code migrates. bool AllowRequestWithoutIntegrity(
diff --git a/third_party/blink/renderer/core/frame/csp/content_security_policy_test.cc b/third_party/blink/renderer/core/frame/csp/content_security_policy_test.cc index 86c23184..797e4179 100644 --- a/third_party/blink/renderer/core/frame/csp/content_security_policy_test.cc +++ b/third_party/blink/renderer/core/frame/csp/content_security_policy_test.cc
@@ -189,23 +189,6 @@ ReportingDisposition::kSuppressReporting)); } -TEST_F(ContentSecurityPolicyTest, IsFrameAncestorsEnforced) { - csp->DidReceiveHeader("script-src 'none';", - ContentSecurityPolicyType::kEnforce, - ContentSecurityPolicySource::kHTTP); - EXPECT_FALSE(csp->IsFrameAncestorsEnforced()); - - csp->DidReceiveHeader("frame-ancestors 'self'", - ContentSecurityPolicyType::kReport, - ContentSecurityPolicySource::kHTTP); - EXPECT_FALSE(csp->IsFrameAncestorsEnforced()); - - csp->DidReceiveHeader("frame-ancestors 'self'", - ContentSecurityPolicyType::kEnforce, - ContentSecurityPolicySource::kHTTP); - EXPECT_TRUE(csp->IsFrameAncestorsEnforced()); -} - TEST_F(ContentSecurityPolicyTest, IsActiveForConnectionsWithConnectSrc) { EXPECT_FALSE(csp->IsActiveForConnections()); csp->DidReceiveHeader("connect-src 'none';", @@ -222,20 +205,6 @@ EXPECT_TRUE(csp->IsActiveForConnections()); } -// Tests that frame-ancestors directives are discarded from policies -// delivered in <meta> elements. -TEST_F(ContentSecurityPolicyTest, FrameAncestorsInMeta) { - csp->BindToDelegate(execution_context->GetContentSecurityPolicyDelegate()); - csp->DidReceiveHeader("frame-ancestors 'none';", - ContentSecurityPolicyType::kEnforce, - ContentSecurityPolicySource::kMeta); - EXPECT_FALSE(csp->IsFrameAncestorsEnforced()); - csp->DidReceiveHeader("frame-ancestors 'none';", - ContentSecurityPolicyType::kEnforce, - ContentSecurityPolicySource::kHTTP); - EXPECT_TRUE(csp->IsFrameAncestorsEnforced()); -} - // Tests that sandbox directives are discarded from policies // delivered in <meta> elements. TEST_F(ContentSecurityPolicyTest, SandboxInMeta) { @@ -1364,8 +1333,6 @@ EXPECT_TRUE(csp->AllowInline(ContentSecurityPolicy::InlineType::kStyle, element, source, nonce, context_url, ordinal_number)); - EXPECT_TRUE(csp->AllowAncestors(document->GetFrame(), example_url)); - EXPECT_FALSE(csp->IsFrameAncestorsEnforced()); EXPECT_TRUE(csp->AllowRequest(mojom::RequestContextType::SCRIPT, network::mojom::RequestDestination::kScript, example_url, nonce, IntegrityMetadataSet(),
diff --git a/third_party/blink/renderer/core/frame/csp/csp_directive_list.cc b/third_party/blink/renderer/core/frame/csp/csp_directive_list.cc index 3581ff0..5aec2ca 100644 --- a/third_party/blink/renderer/core/frame/csp/csp_directive_list.cc +++ b/third_party/blink/renderer/core/frame/csp/csp_directive_list.cc
@@ -358,27 +358,6 @@ redirect_status); } -bool CSPDirectiveList::CheckAncestors(SourceListDirective* directive, - LocalFrame* frame) const { - if (!frame || !directive) - return true; - - for (Frame* current = frame->Tree().Parent(); current; - current = current->Tree().Parent()) { - // The |current| frame might be a remote frame which has no URL, so use - // its origin instead. This should suffice for this check since it - // doesn't do path comparisons. See https://crbug.com/582544. - // - // TODO(mkwst): Move this check up into the browser process. See - // https://crbug.com/555418. - KURL url(NullURL(), - current->GetSecurityContext()->GetSecurityOrigin()->ToString()); - if (!directive->Allows(url, ResourceRequest::RedirectStatus::kNoRedirect)) - return false; - } - return true; -} - bool CSPDirectiveList::CheckMediaType(MediaListDirective* directive, const String& type, const String& type_attribute) const { @@ -585,25 +564,6 @@ return DenyIfEnforcingPolicy(); } -bool CSPDirectiveList::CheckAncestorsAndReportViolation( - SourceListDirective* directive, - LocalFrame* frame, - const KURL& url) const { - if (CheckAncestors(directive, frame)) - return true; - - ReportViolationWithFrame( - directive->GetText(), - ContentSecurityPolicy::DirectiveType::kFrameAncestors, - "Refused to display '" + url.ElidedString() + - "' in a frame because an ancestor violates the " - "following Content Security Policy directive: " - "\"" + - directive->GetText() + "\".", - url, frame); - return DenyIfEnforcingPolicy(); -} - bool CSPDirectiveList::AllowInline( ContentSecurityPolicy::InlineType inline_type, Element* element, @@ -819,21 +779,6 @@ return DenyIfEnforcingPolicy(); } -bool CSPDirectiveList::AllowAncestors( - LocalFrame* frame, - const KURL& url, - ReportingDisposition reporting_disposition) const { - return reporting_disposition == ReportingDisposition::kReport - ? CheckAncestorsAndReportViolation( - OperativeDirective( - ContentSecurityPolicy::DirectiveType::kFrameAncestors), - frame, url) - : CheckAncestors( - OperativeDirective( - ContentSecurityPolicy::DirectiveType::kFrameAncestors), - frame); -} - bool CSPDirectiveList::AllowHash( const CSPHashValue& hash_value, const ContentSecurityPolicy::InlineType inline_type) const {
diff --git a/third_party/blink/renderer/core/frame/csp/csp_directive_list.h b/third_party/blink/renderer/core/frame/csp/csp_directive_list.h index a6c45b9..7185ce0 100644 --- a/third_party/blink/renderer/core/frame/csp/csp_directive_list.h +++ b/third_party/blink/renderer/core/frame/csp/csp_directive_list.h
@@ -89,13 +89,6 @@ bool AllowTrustedTypePolicy(const String& policy_name, bool is_duplicate) const; - // |allowAncestors| does not need to know whether the resource was a - // result of a redirect. After a redirect, source paths are usually - // ignored to stop a page from learning the path to which the - // request was redirected, but this is not a concern for ancestors, - // because a child frame can't manipulate the URL of a cross-origin - // parent. - bool AllowAncestors(LocalFrame*, const KURL&, ReportingDisposition) const; bool AllowDynamic(ContentSecurityPolicy::DirectiveType) const; bool AllowDynamicWorker() const; @@ -127,9 +120,6 @@ } const Vector<String>& ReportEndpoints() const { return report_endpoints_; } bool UseReportingApi() const { return use_reporting_api_; } - bool IsFrameAncestorsEnforced() const { - return frame_ancestors_.Get() && !IsReportOnly(); - } // Used to copy plugin-types into a plugin document in a nested // browsing context. @@ -257,7 +247,6 @@ bool CheckMediaType(MediaListDirective*, const String& type, const String& type_attribute) const; - bool CheckAncestors(SourceListDirective*, LocalFrame*) const; void SetEvalDisabledErrorMessage(const String& error_message) { eval_disabled_error_message_ = error_message; @@ -291,9 +280,6 @@ const String& type, const String& type_attribute, const String& console_message) const; - bool CheckAncestorsAndReportViolation(SourceListDirective*, - LocalFrame*, - const KURL&) const; bool DenyIfEnforcingPolicy() const { return IsReportOnly(); }
diff --git a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc index 69c97eac..12f94d4 100644 --- a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc +++ b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
@@ -814,7 +814,7 @@ if (!context_ && !OffscreenCanvasFrame()) return; - if (HasResourceProvider() && !canvas_is_clear_) + if (!canvas_is_clear_) PaintTiming::From(GetDocument()).MarkFirstContentfulPaint(); // If the canvas is gpu composited, it has another way of getting to screen
diff --git a/third_party/blink/renderer/core/html/custom/element_internals.cc b/third_party/blink/renderer/core/html/custom/element_internals.cc index e879e1f..70f3934 100644 --- a/third_party/blink/renderer/core/html/custom/element_internals.cc +++ b/third_party/blink/renderer/core/html/custom/element_internals.cc
@@ -238,6 +238,10 @@ return custom_states_ && custom_states_->contains(state); } +ShadowRoot* ElementInternals::shadowRoot() const { + return Target().AuthorShadowRoot(); +} + const AtomicString& ElementInternals::FastGetAttribute( const QualifiedName& attribute) const { return accessibility_semantics_map_.at(attribute);
diff --git a/third_party/blink/renderer/core/html/custom/element_internals.h b/third_party/blink/renderer/core/html/custom/element_internals.h index 35e9b9354..695e1e8 100644 --- a/third_party/blink/renderer/core/html/custom/element_internals.h +++ b/third_party/blink/renderer/core/html/custom/element_internals.h
@@ -54,6 +54,8 @@ bool HasState(const AtomicString& state) const; + ShadowRoot* shadowRoot() const; + // We need these functions because we are reflecting ARIA attributes. // See dom/aria_attributes.idl. const AtomicString& FastGetAttribute(const QualifiedName&) const;
diff --git a/third_party/blink/renderer/core/html/custom/element_internals.idl b/third_party/blink/renderer/core/html/custom/element_internals.idl index 2364642..1734883f 100644 --- a/third_party/blink/renderer/core/html/custom/element_internals.idl +++ b/third_party/blink/renderer/core/html/custom/element_internals.idl
@@ -27,5 +27,9 @@ // Custom state // https://github.com/w3c/webcomponents/blob/gh-pages/proposals/custom-states-and-state-pseudo-class.md [RuntimeEnabled=CustomStatePseudoClass] readonly attribute DOMTokenList states; + + // Access to shadowRoot from custom elements. See crbug.com/1042130 and + // https://github.com/w3c/webcomponents/issues/871#issuecomment-672082936 + [RuntimeEnabled=DeclarativeShadowDOM, MeasureAs=ElementInternalsShadowRoot] readonly attribute ShadowRoot? shadowRoot; };
diff --git a/third_party/blink/renderer/core/html/media/media_source_attachment.cc b/third_party/blink/renderer/core/html/media/media_source_attachment.cc index ec3a128..4a571900 100644 --- a/third_party/blink/renderer/core/html/media/media_source_attachment.cc +++ b/third_party/blink/renderer/core/html/media/media_source_attachment.cc
@@ -24,7 +24,7 @@ // The only expected caller is an HTMLMediaElement on the main thread. DCHECK(IsMainThread()); - if (!registry_) + if (!registry_ || url.IsEmpty()) return nullptr; // This cast is safe because the only setter of |registry_| is SetRegistry().
diff --git a/third_party/blink/renderer/core/html/media/media_source_registry.h b/third_party/blink/renderer/core/html/media/media_source_registry.h index d578df7..528131e 100644 --- a/third_party/blink/renderer/core/html/media/media_source_registry.h +++ b/third_party/blink/renderer/core/html/media/media_source_registry.h
@@ -18,6 +18,10 @@ // scoped_refptr. class CORE_EXPORT MediaSourceRegistry : public URLRegistry { public: + // Finds the attachment, if any, registered with |url| in the + // MediaSourceRegistry implementation. |url| must be non-empty. If such an + // active registration for |url| is not found, returns an unset + // scoped_refptr<MediaSourceAttachment>. virtual scoped_refptr<MediaSourceAttachment> LookupMediaSource( const String& url) = 0; };
diff --git a/third_party/blink/renderer/core/inspector/inspector_highlight.cc b/third_party/blink/renderer/core/inspector/inspector_highlight.cc index dd30039..76a6ca2 100644 --- a/third_party/blink/renderer/core/inspector/inspector_highlight.cc +++ b/third_party/blink/renderer/core/inspector/inspector_highlight.cc
@@ -718,6 +718,13 @@ return result; } +LayoutUnit GetColumnPosition(const LayoutGrid* layout_grid, size_t index) { + LayoutUnit position = layout_grid->ColumnPositions().at(index); + return layout_grid->StyleRef().IsLeftToRightDirection() + ? position + : layout_grid->TranslateRTLCoordinate(position); +} + std::unique_ptr<protocol::DictionaryValue> BuildGridInfo( Node* node, const InspectorGridHighlightConfig& grid_highlight_config, @@ -796,21 +803,27 @@ PathBuilder column_gap_builder; LayoutUnit column_top = rows.front(); LayoutUnit column_height = rows.back() - rows.front(); + bool is_ltr = layout_grid->StyleRef().IsLeftToRightDirection(); for (size_t i = 1; i < columns.size(); ++i) { - PhysicalOffset position(columns.at(i - 1), column_top); PhysicalSize size(columns.at(i) - columns.at(i - 1), column_height); if (i != columns.size() - 1) size.width -= column_gap; + LayoutUnit line_left = + is_ltr ? GetColumnPosition(layout_grid, i - 1) + : GetColumnPosition(layout_grid, i - 1) - size.width; + PhysicalOffset position(line_left, column_top); PhysicalRect column(position, size); FloatQuad column_quad = layout_grid->LocalRectToAbsoluteQuad(column); FrameQuadToViewport(containing_view, column_quad); + bool draw_end_line = is_ltr ? i == columns.size() - 1 : i == 1; column_builder.AppendPath( - ColumnQuadToPath(column_quad, - i == columns.size() - 1 || column_gap > 0), - scale); + ColumnQuadToPath(column_quad, draw_end_line || column_gap > 0), scale); // Column Gaps if (i != columns.size() - 1) { - PhysicalOffset gap_position(columns.at(i) - column_gap, column_top); + LayoutUnit gap_left = is_ltr + ? GetColumnPosition(layout_grid, i) - column_gap + : GetColumnPosition(layout_grid, i); + PhysicalOffset gap_position(gap_left, column_top); PhysicalSize gap_size(column_gap, column_height); PhysicalRect gap(gap_position, gap_size); FloatQuad gap_quad = layout_grid->LocalRectToAbsoluteQuad(gap);
diff --git a/third_party/blink/renderer/core/layout/layout_grid.h b/third_party/blink/renderer/core/layout/layout_grid.h index 6599f923..e925619 100644 --- a/third_party/blink/renderer/core/layout/layout_grid.h +++ b/third_party/blink/renderer/core/layout/layout_grid.h
@@ -92,6 +92,8 @@ return grid_->ExplicitGridStart(direction); } + LayoutUnit TranslateRTLCoordinate(LayoutUnit) const; + LayoutUnit TranslateOutOfFlowRTLCoordinate(const LayoutBox&, LayoutUnit) const; @@ -297,8 +299,6 @@ size_t NonCollapsedTracks(GridTrackSizingDirection) const; size_t NumTracks(GridTrackSizingDirection, const Grid&) const; - LayoutUnit TranslateRTLCoordinate(LayoutUnit) const; - static LayoutUnit OverrideContainingBlockContentSizeForChild( const LayoutBox& child, GridTrackSizingDirection);
diff --git a/third_party/blink/renderer/core/paint/html_canvas_painter.cc b/third_party/blink/renderer/core/paint/html_canvas_painter.cc index 990ef25..2694fe78 100644 --- a/third_party/blink/renderer/core/paint/html_canvas_painter.cc +++ b/third_party/blink/renderer/core/paint/html_canvas_painter.cc
@@ -9,6 +9,7 @@ #include "third_party/blink/renderer/core/layout/layout_html_canvas.h" #include "third_party/blink/renderer/core/paint/box_painter.h" #include "third_party/blink/renderer/core/paint/paint_info.h" +#include "third_party/blink/renderer/core/paint/paint_timing.h" #include "third_party/blink/renderer/platform/geometry/layout_point.h" #include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h" #include "third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.h" @@ -44,6 +45,8 @@ if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled() && !flatten_composited_layers) { if (auto* layer = canvas->ContentsCcLayer()) { + PaintTiming::From(layout_html_canvas_.GetDocument()) + .MarkFirstContentfulPaint(); IntRect pixel_snapped_rect = PixelSnappedIntRect(paint_rect); layer->SetBounds(gfx::Size(pixel_snapped_rect.Size())); layer->SetIsDrawable(true);
diff --git a/third_party/blink/renderer/core/paint/image_painter.cc b/third_party/blink/renderer/core/paint/image_painter.cc index 4f068f6..54bae23 100644 --- a/third_party/blink/renderer/core/paint/image_painter.cc +++ b/third_party/blink/renderer/core/paint/image_painter.cc
@@ -50,11 +50,16 @@ if (layout_size.IsEmpty() || image_size.IsEmpty()) return false; - double dpr = layout_image.GetDocument().GetFrame()->DevicePixelRatio(); - double downscale_ratio_width = - image_size.Width() / (dpr * layout_size.Width()); - double downscale_ratio_height = - image_size.Height() / (dpr * layout_size.Height()); + // Note: Do not use frame->GetDevicePixelRatio() here, because it + // leads to different behaviour on MacOS platform. https://crbug.com/716231. + // virtual/scalefactor200/http/tests/images/document-policy/document-policy-oversized-images-edge-cases.html + // verifies the behaviour. + const double dsf = + layout_image.GetDocument().GetPage()->DeviceScaleFactorDeprecated(); + const double downscale_ratio_width = + image_size.Width() / layout_size.Width() / dsf; + const double downscale_ratio_height = + image_size.Height() / layout_size.Height() / dsf; const LayoutImageResource* image_resource = layout_image.ImageResource(); const ImageResourceContent* cached_image =
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.cc b/third_party/blink/renderer/modules/accessibility/ax_object.cc index 2a36de59..6106ec1b 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_object.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_object.cc
@@ -3968,6 +3968,7 @@ case ax::mojom::blink::Role::kLineBreak: case ax::mojom::blink::Role::kLink: case ax::mojom::blink::Role::kListBoxOption: + case ax::mojom::blink::Role::kMenuButton: case ax::mojom::blink::Role::kMenuItem: case ax::mojom::blink::Role::kMenuItemCheckBox: case ax::mojom::blink::Role::kMenuItemRadio: @@ -4072,8 +4073,6 @@ case ax::mojom::blink::Role::kMenuListPopup: case ax::mojom::blink::Role::kMenu: case ax::mojom::blink::Role::kMenuBar: - case ax::mojom::blink::Role::kMenuButton: // Only value from content, not - // name. case ax::mojom::blink::Role::kMeter: case ax::mojom::blink::Role::kNavigation: case ax::mojom::blink::Role::kNote:
diff --git a/third_party/blink/renderer/modules/mediasource/media_source_registry_impl.cc b/third_party/blink/renderer/modules/mediasource/media_source_registry_impl.cc index 65181d602..2cda907 100644 --- a/third_party/blink/renderer/modules/mediasource/media_source_registry_impl.cc +++ b/third_party/blink/renderer/modules/mediasource/media_source_registry_impl.cc
@@ -47,6 +47,7 @@ URLRegistrable* registrable) { DCHECK(IsMainThread()); DCHECK_EQ(®istrable->Registry(), this); + DCHECK(!url.IsEmpty()); // Caller of interface should already enforce this. DVLOG(1) << __func__ << " url=" << url; @@ -58,6 +59,7 @@ void MediaSourceRegistryImpl::UnregisterURL(const KURL& url) { DVLOG(1) << __func__ << " url=" << url; DCHECK(IsMainThread()); + DCHECK(!url.IsEmpty()); // Caller of interface should already enforce this. auto iter = media_sources_.find(url.GetString()); if (iter == media_sources_.end()) @@ -71,8 +73,8 @@ scoped_refptr<MediaSourceAttachment> MediaSourceRegistryImpl::LookupMediaSource( const String& url) { DCHECK(IsMainThread()); - return url.IsNull() ? scoped_refptr<MediaSourceAttachment>() - : media_sources_.at(url); + DCHECK(!url.IsEmpty()); + return media_sources_.at(url); } MediaSourceRegistryImpl::MediaSourceRegistryImpl() {
diff --git a/third_party/blink/renderer/modules/mediasource/media_source_registry_impl.h b/third_party/blink/renderer/modules/mediasource/media_source_registry_impl.h index c38ab9b..49e19f6 100644 --- a/third_party/blink/renderer/modules/mediasource/media_source_registry_impl.h +++ b/third_party/blink/renderer/modules/mediasource/media_source_registry_impl.h
@@ -39,7 +39,7 @@ // MediaSourceRegistry override that finds |url| in |media_sources_| and // returns the corresponding scoped_refptr if found. Otherwise, returns an - // unset scoped_refptr. + // unset scoped_refptr. |url| must be non-empty. scoped_refptr<MediaSourceAttachment> LookupMediaSource( const String& url) override;
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream.cc b/third_party/blink/renderer/modules/mediastream/media_stream.cc index 293efe7e..f73c1d14 100644 --- a/third_party/blink/renderer/modules/mediastream/media_stream.cc +++ b/third_party/blink/renderer/modules/mediastream/media_stream.cc
@@ -148,7 +148,10 @@ } if (number_of_video_tracks == 0) { - std::move(media_stream_initialized_callback_).Run(this); + context->GetTaskRunner(TaskType::kInternalMedia) + ->PostTask(FROM_HERE, + WTF::Bind(std::move(media_stream_initialized_callback_), + WrapPersistent(this))); } }
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_track.cc b/third_party/blink/renderer/modules/mediastream/media_stream_track.cc index c9add9fd..6604b5e 100644 --- a/third_party/blink/renderer/modules/mediastream/media_stream_track.cc +++ b/third_party/blink/renderer/modules/mediastream/media_stream_track.cc
@@ -256,7 +256,8 @@ image_capture_ = MakeGarbageCollected<ImageCapture>( context, this, pan_tilt_zoom_allowed, std::move(callback)); } else { - std::move(callback).Run(); + execution_context_->GetTaskRunner(TaskType::kInternalMedia) + ->PostTask(FROM_HERE, std::move(callback)); } }
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.idl b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.idl index 0972dfa..4756e6bb 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.idl +++ b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.idl
@@ -9,7 +9,7 @@ readonly attribute RTCDtlsTransport? transport; readonly attribute RTCDtlsTransport? rtcpTransport; static RTCRtpCapabilities? getCapabilities(DOMString kind); - [CallWith=ScriptState] Promise<void> setParameters(optional RTCRtpSendParameters parameters = {}); + [CallWith=ScriptState] Promise<void> setParameters(RTCRtpSendParameters parameters); RTCRtpSendParameters getParameters(); [Measure, CallWith=ScriptState] Promise<void> replaceTrack(MediaStreamTrack? withTrack); [Measure] readonly attribute RTCDTMFSender? dtmf;
diff --git a/third_party/blink/renderer/modules/plugins/navigator_plugins.cc b/third_party/blink/renderer/modules/plugins/navigator_plugins.cc index 6ea9da60..3a21ecc 100644 --- a/third_party/blink/renderer/modules/plugins/navigator_plugins.cc +++ b/third_party/blink/renderer/modules/plugins/navigator_plugins.cc
@@ -5,6 +5,7 @@ #include "third_party/blink/renderer/modules/plugins/navigator_plugins.h" #include "third_party/blink/public/common/privacy_budget/identifiability_metric_builder.h" +#include "third_party/blink/public/common/privacy_budget/identifiability_study_settings.h" #include "third_party/blink/public/common/privacy_budget/identifiable_token_builder.h" #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/frame/navigator.h" @@ -56,7 +57,7 @@ plugins_ = MakeGarbageCollected<DOMPluginArray>(frame); DOMPluginArray* result = plugins_.Get(); - if (!frame) + if (!IdentifiabilityStudySettings::Get()->IsActive() || !frame) return result; Document* document = frame->GetDocument(); if (!document)
diff --git a/third_party/blink/renderer/modules/service_worker/fetch_respond_with_observer.cc b/third_party/blink/renderer/modules/service_worker/fetch_respond_with_observer.cc index ba12555..9da92f6 100644 --- a/third_party/blink/renderer/modules/service_worker/fetch_respond_with_observer.cc +++ b/third_party/blink/renderer/modules/service_worker/fetch_respond_with_observer.cc
@@ -25,6 +25,7 @@ #include "third_party/blink/renderer/core/fetch/body_stream_buffer.h" #include "third_party/blink/renderer/core/inspector/console_message.h" #include "third_party/blink/renderer/modules/service_worker/cross_origin_resource_policy_checker.h" +#include "third_party/blink/renderer/modules/service_worker/fetch_event.h" #include "third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h" #include "third_party/blink/renderer/modules/service_worker/wait_until_observer.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" @@ -213,8 +214,7 @@ service_worker_global_scope->RespondToFetchEvent( event_id_, request_url_, std::move(response), event_dispatch_time_, base::TimeTicks::Now()); - service_worker_global_scope->RejectFetchEventHandledPromise(event_id_, - error_message); + event_->RejectHandledPromise(error_message); } void FetchRespondWithObserver::OnResponseFulfilled( @@ -337,7 +337,7 @@ service_worker_global_scope->RespondToFetchEvent( event_id_, request_url_, std::move(fetch_api_response), event_dispatch_time_, base::TimeTicks::Now()); - service_worker_global_scope->ResolveFetchEventHandledPromise(event_id_); + event_->ResolveHandledPromise(); return; } @@ -364,13 +364,13 @@ service_worker_global_scope->RespondToFetchEventWithResponseStream( event_id_, request_url_, std::move(fetch_api_response), std::move(stream_handle), event_dispatch_time_, base::TimeTicks::Now()); - service_worker_global_scope->ResolveFetchEventHandledPromise(event_id_); + event_->ResolveHandledPromise(); return; } service_worker_global_scope->RespondToFetchEvent( event_id_, request_url_, std::move(fetch_api_response), event_dispatch_time_, base::TimeTicks::Now()); - service_worker_global_scope->ResolveFetchEventHandledPromise(event_id_); + event_->ResolveHandledPromise(); } void FetchRespondWithObserver::OnNoResponse() { @@ -379,7 +379,7 @@ To<ServiceWorkerGlobalScope>(GetExecutionContext()); service_worker_global_scope->RespondToFetchEventWithNoResponse( event_id_, request_url_, event_dispatch_time_, base::TimeTicks::Now()); - service_worker_global_scope->ResolveFetchEventHandledPromise(event_id_); + event_->ResolveHandledPromise(); } FetchRespondWithObserver::FetchRespondWithObserver( @@ -398,6 +398,7 @@ task_runner_(context->GetTaskRunner(TaskType::kNetworking)) {} void FetchRespondWithObserver::Trace(Visitor* visitor) const { + visitor->Trace(event_); RespondWithObserver::Trace(visitor); }
diff --git a/third_party/blink/renderer/modules/service_worker/fetch_respond_with_observer.h b/third_party/blink/renderer/modules/service_worker/fetch_respond_with_observer.h index 808cfe0..2de7884 100644 --- a/third_party/blink/renderer/modules/service_worker/fetch_respond_with_observer.h +++ b/third_party/blink/renderer/modules/service_worker/fetch_respond_with_observer.h
@@ -17,6 +17,7 @@ class CrossOriginResourcePolicyChecker; class ExecutionContext; +class FetchEvent; class ScriptValue; class WaitUntilObserver; @@ -46,6 +47,11 @@ const char* property_name) override; void OnNoResponse() override; + void SetEvent(FetchEvent* event) { + DCHECK(!event_); + event_ = event; + } + void Trace(Visitor*) const override; private: @@ -54,6 +60,7 @@ const network::mojom::RedirectMode redirect_mode_; const mojom::RequestContextFrameType frame_type_; const network::mojom::RequestDestination request_destination_; + Member<FetchEvent> event_; base::WeakPtr<CrossOriginResourcePolicyChecker> corp_checker_; scoped_refptr<base::SingleThreadTaskRunner> task_runner_; };
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc index 84f2915..dd1c4d9 100644 --- a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc +++ b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
@@ -808,7 +808,6 @@ visitor->Trace(payment_response_callbacks_); visitor->Trace(fetch_response_callbacks_); visitor->Trace(pending_preload_fetch_events_); - visitor->Trace(pending_fetch_events_); visitor->Trace(controller_receivers_); WorkerGlobalScope::Trace(visitor); } @@ -823,20 +822,6 @@ return features::kInstallingServiceWorkerOutstandingThrottledLimit.Get(); } -void ServiceWorkerGlobalScope::ResolveFetchEventHandledPromise(int event_id) { - FetchEvent* fetch_event = pending_fetch_events_.Take(event_id); - DCHECK(fetch_event); - fetch_event->ResolveHandledPromise(); -} - -void ServiceWorkerGlobalScope::RejectFetchEventHandledPromise( - int event_id, - const String& error_message) { - FetchEvent* fetch_event = pending_fetch_events_.Take(event_id); - DCHECK(fetch_event); - fetch_event->RejectHandledPromise(error_message); -} - void ServiceWorkerGlobalScope::importScripts(const Vector<String>& urls, ExceptionState& exception_state) { for (const String& string_url : urls) { @@ -1537,14 +1522,14 @@ mojo::PendingRemote<mojom::blink::WorkerTimingContainer>( std::move(params->worker_timing_remote)), navigation_preload_sent); + respond_with_observer->SetEvent(fetch_event); + if (navigation_preload_sent) { // Keep |fetchEvent| until OnNavigationPreloadComplete() or // onNavigationPreloadError() will be called. pending_preload_fetch_events_.insert(event_id, fetch_event); } - pending_fetch_events_.insert(event_id, fetch_event); - NoteNewFetchEvent(request->url()); DispatchExtendableEventWithRespondWith(fetch_event, wait_until_observer,
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h index 57beea8..e4ae567 100644 --- a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h +++ b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h
@@ -316,9 +316,6 @@ int GetOutstandingThrottledLimit() const override; const ServiceWorkerToken& token() const { return token_; } - void ResolveFetchEventHandledPromise(int event_id); - void RejectFetchEventHandledPromise(int event_id, - const String& error_message); protected: // EventTarget @@ -691,10 +688,6 @@ HeapHashMap<int, Member<FetchEvent>> pending_preload_fetch_events_; - // Fetch events that are being handled are stored here and will be removed - // after being handled. - HeapHashMap<int, Member<FetchEvent>> pending_fetch_events_; - // Track outstanding FetchEvent objects still waiting for a response by // request URL. This information can be used as a hint that cache_storage // or fetch requests to the same URL is likely to be used to satisfy a
diff --git a/third_party/blink/renderer/platform/fonts/font_matching_metrics.cc b/third_party/blink/renderer/platform/fonts/font_matching_metrics.cc index 23a1e4f67..354fdbd 100644 --- a/third_party/blink/renderer/platform/fonts/font_matching_metrics.cc +++ b/third_party/blink/renderer/platform/fonts/font_matching_metrics.cc
@@ -7,6 +7,7 @@ #include "services/metrics/public/cpp/metrics_utils.h" #include "services/metrics/public/cpp/ukm_builders.h" #include "services/metrics/public/cpp/ukm_recorder.h" +#include "third_party/blink/public/common/privacy_budget/identifiability_study_settings.h" #include "third_party/blink/public/common/privacy_budget/identifiable_token.h" #include "third_party/blink/renderer/platform/privacy_budget/identifiability_digest_helpers.h" @@ -41,7 +42,9 @@ identifiability_metrics_timer_( task_runner, this, - &FontMatchingMetrics::IdentifiabilityMetricsTimerFired) { + &FontMatchingMetrics::IdentifiabilityMetricsTimerFired), + identifiability_study_enabled_( + IdentifiabilityStudySettings::Get()->IsActive()) { // Estimate of average page font use from anecdotal browsing session. constexpr unsigned kEstimatedFontCount = 7; local_fonts_succeeded_.ReserveCapacityForSize(kEstimatedFontCount); @@ -84,6 +87,9 @@ LocalFontLookupType check_type, SimpleFontData* resulting_font_data, bool is_loading_fallback) { + if (!identifiability_study_enabled_) { + return; + } OnFontLookup(); uint64_t hash = GetHashForFontData(resulting_font_data); LocalFontLookupKey key(name, font_description.GetFontSelectionRequest()); @@ -96,6 +102,9 @@ const FontDescription& font_description, LocalFontLookupType check_type, SimpleFontData* resulting_font_data) { + if (!identifiability_study_enabled_) { + return; + } OnFontLookup(); uint64_t hash = GetHashForFontData(resulting_font_data); LocalFontLookupKey key(fallback_character, @@ -109,6 +118,9 @@ const FontDescription& font_description, LocalFontLookupType check_type, SimpleFontData* resulting_font_data) { + if (!identifiability_study_enabled_) { + return; + } OnFontLookup(); uint64_t hash = GetHashForFontData(resulting_font_data); LocalFontLookupKey key(font_description.GetFontSelectionRequest()); @@ -122,6 +134,9 @@ UScriptCode script, FontDescription::GenericFamilyType generic_family_type, const AtomicString& resulting_font_name) { + if (!identifiability_study_enabled_) { + return; + } OnFontLookup(); GenericFontLookupKey key(generic_font_family_name, script, generic_family_type); @@ -130,6 +145,8 @@ } void FontMatchingMetrics::PublishIdentifiabilityMetrics() { + DCHECK(identifiability_study_enabled_); + IdentifiabilityMetricBuilder builder(source_id_); for (const auto& entry : font_lookups_) { @@ -188,6 +205,7 @@ } void FontMatchingMetrics::OnFontLookup() { + DCHECK(identifiability_study_enabled_); if (!identifiability_metrics_timer_.IsActive()) { identifiability_metrics_timer_.StartOneShot(base::TimeDelta::FromMinutes(1), FROM_HERE); @@ -199,7 +217,9 @@ } void FontMatchingMetrics::PublishAllMetrics() { - PublishIdentifiabilityMetrics(); + if (identifiability_study_enabled_) { + PublishIdentifiabilityMetrics(); + } PublishUkmMetrics(); }
diff --git a/third_party/blink/renderer/platform/fonts/font_matching_metrics.h b/third_party/blink/renderer/platform/fonts/font_matching_metrics.h index f7333631..4e9f7c2 100644 --- a/third_party/blink/renderer/platform/fonts/font_matching_metrics.h +++ b/third_party/blink/renderer/platform/fonts/font_matching_metrics.h
@@ -277,6 +277,8 @@ const ukm::SourceId source_id_; TaskRunnerTimer<FontMatchingMetrics> identifiability_metrics_timer_; + + const bool identifiability_study_enabled_; }; } // namespace blink
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/agent_scheduling_strategy.cc b/third_party/blink/renderer/platform/scheduler/main_thread/agent_scheduling_strategy.cc index 51fa85b..c923687 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/agent_scheduling_strategy.cc +++ b/third_party/blink/renderer/platform/scheduler/main_thread/agent_scheduling_strategy.cc
@@ -226,12 +226,21 @@ SetWaitingForInput(true); main_frames_.insert(&frame_scheduler); - main_frames_waiting_for_signal_.insert(&frame_scheduler); + + // Only add ordinary page frames to the set of waiting frames, as + // non-ordinary ones don't report any signals. + if (frame_scheduler.IsOrdinary()) + main_frames_waiting_for_signal_.insert(&frame_scheduler); return ShouldUpdatePolicy::kYes; } bool ShouldAffectQueue(const MainThreadTaskQueue& task_queue) const { + // Queues that don't have a frame scheduler are, by definition, not + // associated with a frame (or agent). + if (!task_queue.GetFrameScheduler()) + return false; + if (affected_queue_types_ == PerAgentAffectedQueues::kTimerQueues && task_queue.GetPrioritisationType() != PrioritisationType::kJavaScriptTimer) {
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/agent_scheduling_strategy_unittest.cc b/third_party/blink/renderer/platform/scheduler/main_thread/agent_scheduling_strategy_unittest.cc index d5e6c54..ed6d6d3 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/agent_scheduling_strategy_unittest.cc +++ b/third_party/blink/renderer/platform/scheduler/main_thread/agent_scheduling_strategy_unittest.cc
@@ -30,6 +30,7 @@ using ::base::test::ScopedFeatureList; using ::testing::_; using ::testing::NiceMock; +using ::testing::Return; using ::testing::ReturnRef; using ::testing::Test; @@ -43,9 +44,9 @@ base::TimeDelta delay)); }; -class MockFrameDelegate : public FrameScheduler::Delegate { +class MockFrameSchedulerDelegate : public FrameScheduler::Delegate { public: - MockFrameDelegate() { + MockFrameSchedulerDelegate() { ON_CALL(*this, GetAgentClusterId) .WillByDefault(ReturnRef(agent_cluster_id_)); } @@ -70,10 +71,14 @@ /*parent_page_scheduler=*/nullptr, /*delegate=*/&delegate_, /*blame_context=*/nullptr, - /*frame_type=*/frame_type) {} + /*frame_type=*/frame_type) { + ON_CALL(*this, IsOrdinary).WillByDefault(Return(true)); + } + + MOCK_METHOD(bool, IsOrdinary, (), (const)); private: - NiceMock<MockFrameDelegate> delegate_; + NiceMock<MockFrameSchedulerDelegate> delegate_; }; } // namespace @@ -494,5 +499,29 @@ EXPECT_FALSE(strategy_->QueuePriority(*timer_queue_).has_value()); } +class PerAgentNonOrdinaryPageTest : public PerAgentSchedulingBaseTest { + public: + PerAgentNonOrdinaryPageTest() + : PerAgentSchedulingBaseTest({{"queues", "timer-queues"}, + {"method", "disable"}, + {"signal", "onload"}}) { + ON_CALL(non_ordinary_frame_scheduler_, IsOrdinary) + .WillByDefault(Return(false)); + } + + protected: + NiceMock<MockFrameScheduler> non_ordinary_frame_scheduler_{ + FrameScheduler::FrameType::kMainFrame}; +}; + +TEST_F(PerAgentNonOrdinaryPageTest, DoesntWaitForNonOrdinaryFrames) { + EXPECT_EQ(strategy_->OnFrameAdded(non_ordinary_frame_scheduler_), + ShouldUpdatePolicy::kYes); + EXPECT_FALSE(strategy_->QueueEnabledState(*timer_queue_).has_value()); + EXPECT_FALSE(strategy_->QueuePriority(*timer_queue_).has_value()); + EXPECT_FALSE(strategy_->QueueEnabledState(*non_timer_queue_).has_value()); + EXPECT_FALSE(strategy_->QueuePriority(*non_timer_queue_).has_value()); +} + } // namespace scheduler } // namespace blink
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc index e22f8234e..9bd2928 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc +++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc
@@ -941,6 +941,12 @@ return waiting_for_meaningful_paint_; } +bool FrameSchedulerImpl::IsOrdinary() const { + if (!parent_page_scheduler_) + return true; + return parent_page_scheduler_->IsOrdinary(); +} + bool FrameSchedulerImpl::ShouldThrottleTaskQueues() const { // TODO(crbug.com/1078387): Convert the CHECK to a DCHECK once enough time has // passed to confirm that it is correct. (November 2020).
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h index 6bae895a..18808184 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h +++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h
@@ -125,6 +125,11 @@ bool IsWaitingForContentfulPaint() const; bool IsWaitingForMeaningfulPaint() const; + // An "ordinary" FrameScheduler is responsible for a frame whose parent page + // is a fully-featured page owned by a web view (as opposed to, e.g.: a Page + // created by an SVGImage). Virtual for testing. + virtual bool IsOrdinary() const; + void AsValueInto(base::trace_event::TracedValue* state) const; bool IsExemptFromBudgetBasedThrottling() const override; std::unique_ptr<blink::mojom::blink::PauseSubresourceLoadingHandle>
diff --git a/third_party/blink/tools/blinkpy/web_tests/models/test_expectations.py b/third_party/blink/tools/blinkpy/web_tests/models/test_expectations.py index a1c47bb5..475b86c 100644 --- a/third_party/blink/tools/blinkpy/web_tests/models/test_expectations.py +++ b/third_party/blink/tools/blinkpy/web_tests/models/test_expectations.py
@@ -29,13 +29,11 @@ import copy import logging -import itertools import re from collections import defaultdict from collections import OrderedDict -from blinkpy.common import path_finder from blinkpy.common.memoized import memoized from blinkpy.web_tests.models import typ_types @@ -46,8 +44,7 @@ SPECIAL_PREFIXES = ('# tags:', '# results:', '# conflicts_allowed:') _PLATFORM_TOKENS_LIST = [ - 'Android', 'Fuchsia', 'IOS', 'IOS12.2', 'IOS13.0', 'Linux', 'Mac', - 'Mac10.10', 'Mac10.11', 'Retina', 'Mac10.12', 'Mac10.13', 'Mac10.14', + 'Android', 'Fuchsia', 'Linux', 'Mac', 'Mac10.12', 'Mac10.13', 'Mac10.14', 'Win', 'Win7', 'Win10' ]
diff --git a/third_party/blink/tools/blinkpy/web_tests/port/base.py b/third_party/blink/tools/blinkpy/web_tests/port/base.py index e4ad2a8..c1411025 100644 --- a/third_party/blink/tools/blinkpy/web_tests/port/base.py +++ b/third_party/blink/tools/blinkpy/web_tests/port/base.py
@@ -139,17 +139,13 @@ ('win10', 'x86'), ('trusty', 'x86_64'), ('fuchsia', 'x86_64'), - ('ios12.2', 'x86_64'), - ('ios13.0', 'x86_64'), ) CONFIGURATION_SPECIFIER_MACROS = { - 'mac': - ['mac10.12', 'mac10.13', 'mac10.14', 'mac10.15'], + 'mac': ['mac10.12', 'mac10.13', 'mac10.14', 'mac10.15'], 'win': ['win7', 'win10'], 'linux': ['trusty'], 'fuschia': ['fuchsia'], - 'ios': ['ios12.2', 'ios13.0'], } # List of ports open on the host that the tests will connect to. When tests
diff --git a/third_party/blink/tools/blinkpy/web_tests/port/factory.py b/third_party/blink/tools/blinkpy/web_tests/port/factory.py index 50691180..2345de24 100644 --- a/third_party/blink/tools/blinkpy/web_tests/port/factory.py +++ b/third_party/blink/tools/blinkpy/web_tests/port/factory.py
@@ -39,7 +39,6 @@ PORT_CLASSES = ( 'android.AndroidPort', 'fuchsia.FuchsiaPort', - 'ios.IOSPort', 'linux.LinuxPort', 'mac.MacPort', 'mock_drt.MockDRTPort',
diff --git a/third_party/blink/tools/blinkpy/web_tests/port/ios.py b/third_party/blink/tools/blinkpy/web_tests/port/ios.py deleted file mode 100644 index e496d70..0000000 --- a/third_party/blink/tools/blinkpy/web_tests/port/ios.py +++ /dev/null
@@ -1,53 +0,0 @@ -# Copyright (C) 2019 Google Inc. All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -"""Chromium iOS implementation of the Port interface.""" - -import logging - -from blinkpy.web_tests.port import base - -_log = logging.getLogger(__name__) - - -class IOSPort(base.Port): - SUPPORTED_VERSIONS = ('ios12.2', 'ios13.0') - port_name = 'ios' - - FALLBACK_PATHS = {} - - FALLBACK_PATHS['ios13.0'] = ['ios'] - FALLBACK_PATHS['ios12.2'] = ['ios12.2', 'ios'] - - def __init__(self, host, port_name, **kwargs): - super(IOSPort, self).__init__(host, port_name, **kwargs) - self._architecture = 'x86_64' - self._version = port_name[port_name.index('ios-') + len('ios-'):] - assert self._version in self.SUPPORTED_VERSIONS - - def operating_system(self): - return 'ios'
diff --git a/third_party/blink/web_tests/ASANExpectations b/third_party/blink/web_tests/ASANExpectations index fb252f6..d0c2d43 100644 --- a/third_party/blink/web_tests/ASANExpectations +++ b/third_party/blink/web_tests/ASANExpectations
@@ -1,4 +1,4 @@ -# tags: [ Android Fuchsia IOS IOS12.2 IOS13.0 Linux Mac Mac10.12 Mac10.13 Win Win7 Win10 ] +# tags: [ Android Fuchsia Linux Mac Mac10.12 Mac10.13 Win Win7 Win10 ] # tags: [ Release Debug ] # results: [ Timeout Crash Pass Failure Slow Skip ]
diff --git a/third_party/blink/web_tests/FlagExpectations/composite-after-paint b/third_party/blink/web_tests/FlagExpectations/composite-after-paint index 804625a..68db8417 100644 --- a/third_party/blink/web_tests/FlagExpectations/composite-after-paint +++ b/third_party/blink/web_tests/FlagExpectations/composite-after-paint
@@ -1,4 +1,4 @@ -# tags: [ Android Fuchsia IOS IOS12.2 IOS13.0 Linux Mac Mac10.12 Mac10.13 Win Win7 Win10 ] +# tags: [ Android Fuchsia Linux Mac Mac10.12 Mac10.13 Win Win7 Win10 ] # tags: [ Release Debug ] # results: [ Timeout Crash Pass Failure Slow Skip ]
diff --git a/third_party/blink/web_tests/FlagExpectations/disable-features=OutOfBlinkCors b/third_party/blink/web_tests/FlagExpectations/disable-features=OutOfBlinkCors index 4bc9f017..b39d97dd 100644 --- a/third_party/blink/web_tests/FlagExpectations/disable-features=OutOfBlinkCors +++ b/third_party/blink/web_tests/FlagExpectations/disable-features=OutOfBlinkCors
@@ -1,4 +1,4 @@ -# tags: [ Android Fuchsia IOS IOS12.2 IOS13.0 Linux Mac Mac10.12 Mac10.13 Win Win7 Win10 ] +# tags: [ Android Fuchsia Linux Mac Mac10.12 Mac10.13 Win Win7 Win10 ] # tags: [ Release Debug ] # results: [ Timeout Crash Pass Failure Slow Skip ]
diff --git a/third_party/blink/web_tests/FlagExpectations/disable-layout-ng b/third_party/blink/web_tests/FlagExpectations/disable-layout-ng index f1bc5ce..541b07e 100644 --- a/third_party/blink/web_tests/FlagExpectations/disable-layout-ng +++ b/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
@@ -1,4 +1,4 @@ -# tags: [ Android Fuchsia IOS IOS12.2 IOS13.0 Linux Mac Mac10.12 Mac10.13 Win Win7 Win10 ] +# tags: [ Android Fuchsia Linux Mac Mac10.12 Mac10.13 Win Win7 Win10 ] # tags: [ Release Debug ] # results: [ Timeout Crash Pass Failure Slow Skip ]
diff --git a/third_party/blink/web_tests/FlagExpectations/disable-site-isolation-trials b/third_party/blink/web_tests/FlagExpectations/disable-site-isolation-trials index 0ff1e97..fb0f5082 100644 --- a/third_party/blink/web_tests/FlagExpectations/disable-site-isolation-trials +++ b/third_party/blink/web_tests/FlagExpectations/disable-site-isolation-trials
@@ -1,4 +1,4 @@ -# tags: [ Android Fuchsia IOS IOS12.2 IOS13.0 Linux Mac Mac10.12 Mac10.13 Win Win7 Win10 ] +# tags: [ Android Fuchsia Linux Mac Mac10.12 Mac10.13 Win Win7 Win10 ] # tags: [ Release Debug ] # results: [ Timeout Crash Pass Failure Slow Skip ]
diff --git a/third_party/blink/web_tests/FlagExpectations/enable-features=BackForwardCache b/third_party/blink/web_tests/FlagExpectations/enable-features=BackForwardCache index 6f7748a..d8ff56256 100644 --- a/third_party/blink/web_tests/FlagExpectations/enable-features=BackForwardCache +++ b/third_party/blink/web_tests/FlagExpectations/enable-features=BackForwardCache
@@ -1,4 +1,4 @@ -# tags: [ Android Fuchsia IOS IOS12.2 IOS13.0 Linux Mac Mac10.12 Mac10.13 Win Win7 Win10 ] +# tags: [ Android Fuchsia Linux Mac Mac10.12 Mac10.13 Win Win7 Win10 ] # tags: [ Release Debug ] # results: [ Timeout Crash Pass Failure Slow Skip ]
diff --git a/third_party/blink/web_tests/FlagExpectations/enable-features=UseSkiaRenderer b/third_party/blink/web_tests/FlagExpectations/enable-features=UseSkiaRenderer index cdbe7c03..2bf7dd1 100644 --- a/third_party/blink/web_tests/FlagExpectations/enable-features=UseSkiaRenderer +++ b/third_party/blink/web_tests/FlagExpectations/enable-features=UseSkiaRenderer
@@ -1,4 +1,4 @@ -# tags: [ Android Fuchsia IOS IOS12.2 IOS13.0 Linux Mac Mac10.12 Mac10.13 Win Win7 Win10 ] +# tags: [ Android Fuchsia Linux Mac Mac10.12 Mac10.13 Win Win7 Win10 ] # tags: [ Release Debug ] # results: [ Timeout Crash Pass Failure Slow Skip ]
diff --git a/third_party/blink/web_tests/FlagExpectations/enable-gpu-rasterization b/third_party/blink/web_tests/FlagExpectations/enable-gpu-rasterization index 4653d6e..28e5246 100644 --- a/third_party/blink/web_tests/FlagExpectations/enable-gpu-rasterization +++ b/third_party/blink/web_tests/FlagExpectations/enable-gpu-rasterization
@@ -1,4 +1,4 @@ -# tags: [ Android Fuchsia IOS IOS12.2 IOS13.0 Linux Mac Mac10.12 Mac10.13 Win Win7 Win10 ] +# tags: [ Android Fuchsia Linux Mac Mac10.12 Mac10.13 Win Win7 Win10 ] # tags: [ Release Debug ] # results: [ Timeout Crash Pass Failure Slow Skip ]
diff --git a/third_party/blink/web_tests/FlagExpectations/enable-threaded-compositing b/third_party/blink/web_tests/FlagExpectations/enable-threaded-compositing index 109097a..24c6388 100644 --- a/third_party/blink/web_tests/FlagExpectations/enable-threaded-compositing +++ b/third_party/blink/web_tests/FlagExpectations/enable-threaded-compositing
@@ -1,4 +1,4 @@ -# tags: [ Android Fuchsia IOS IOS12.2 IOS13.0 Linux Mac Mac10.12 Mac10.13 Win Win7 Win10 ] +# tags: [ Android Fuchsia Linux Mac Mac10.12 Mac10.13 Win Win7 Win10 ] # tags: [ Release Debug ] # results: [ Timeout Crash Pass Failure Slow Skip ]
diff --git a/third_party/blink/web_tests/FlagExpectations/layout-ng-fragment-item b/third_party/blink/web_tests/FlagExpectations/layout-ng-fragment-item index e4641c23..153fc6d 100644 --- a/third_party/blink/web_tests/FlagExpectations/layout-ng-fragment-item +++ b/third_party/blink/web_tests/FlagExpectations/layout-ng-fragment-item
@@ -1,4 +1,4 @@ -# tags: [ Android Fuchsia IOS IOS12.2 IOS13.0 Linux Mac Mac10.12 Mac10.13 Win Win7 Win10 ] +# tags: [ Android Fuchsia Linux Mac Mac10.12 Mac10.13 Win Win7 Win10 ] # results: [ Timeout Crash Pass Failure Slow Skip ] # tags: [ Release Debug ]
diff --git a/third_party/blink/web_tests/FlagExpectations/use-gl=any b/third_party/blink/web_tests/FlagExpectations/use-gl=any index 360deb1..7a1b8612 100644 --- a/third_party/blink/web_tests/FlagExpectations/use-gl=any +++ b/third_party/blink/web_tests/FlagExpectations/use-gl=any
@@ -1,4 +1,4 @@ -# tags: [ Android Fuchsia IOS IOS12.2 IOS13.0 Linux Mac Mac10.12 Mac10.13 Win Win7 Win10 ] +# tags: [ Android Fuchsia Linux Mac Mac10.12 Mac10.13 Win Win7 Win10 ] # tags: [ Release Debug ] # results: [ Timeout Crash Pass Failure Slow Skip ]
diff --git a/third_party/blink/web_tests/FlagExpectations/use-vulkan=native b/third_party/blink/web_tests/FlagExpectations/use-vulkan=native index 1f466b8..433b19e 100644 --- a/third_party/blink/web_tests/FlagExpectations/use-vulkan=native +++ b/third_party/blink/web_tests/FlagExpectations/use-vulkan=native
@@ -1,4 +1,4 @@ -# tags: [ Android Fuchsia IOS IOS12.2 IOS13.0 Linux Mac Mac10.12 Mac10.13 Win Win7 Win10 ] +# tags: [ Android Fuchsia Linux Mac Mac10.12 Mac10.13 Win Win7 Win10 ] # tags: [ Release Debug ] # results: [ Timeout Crash Pass Failure Slow Skip ]
diff --git a/third_party/blink/web_tests/FlagExpectations/use-vulkan=swiftshader b/third_party/blink/web_tests/FlagExpectations/use-vulkan=swiftshader index 2c9d2de3..40d99841 100644 --- a/third_party/blink/web_tests/FlagExpectations/use-vulkan=swiftshader +++ b/third_party/blink/web_tests/FlagExpectations/use-vulkan=swiftshader
@@ -1,4 +1,4 @@ -# tags: [ Android Fuchsia IOS IOS12.2 IOS13.0 Linux Mac Mac10.12 Mac10.13 Win Win7 Win10 ] +# tags: [ Android Fuchsia Linux Mac Mac10.12 Mac10.13 Win Win7 Win10 ] # tags: [ Release Debug ] # results: [ Timeout Crash Pass Failure Slow Skip ]
diff --git a/third_party/blink/web_tests/LeakExpectations b/third_party/blink/web_tests/LeakExpectations index 3decd13..5f0929d 100644 --- a/third_party/blink/web_tests/LeakExpectations +++ b/third_party/blink/web_tests/LeakExpectations
@@ -1,4 +1,4 @@ -# tags: [ Android Fuchsia IOS IOS12.2 IOS13.0 Linux Mac Mac10.12 Mac10.13 Win Win7 Win10 ] +# tags: [ Android Fuchsia Linux Mac Mac10.12 Mac10.13 Win Win7 Win10 ] # tags: [ Release Debug ] # results: [ Timeout Crash Pass Failure Slow Skip ]
diff --git a/third_party/blink/web_tests/MSANExpectations b/third_party/blink/web_tests/MSANExpectations index f8a7256..58b3a2f 100644 --- a/third_party/blink/web_tests/MSANExpectations +++ b/third_party/blink/web_tests/MSANExpectations
@@ -1,4 +1,4 @@ -# tags: [ Android Fuchsia IOS IOS12.2 IOS13.0 Linux Mac Mac10.12 Mac10.13 Win Win7 Win10 ] +# tags: [ Android Fuchsia Linux Mac Mac10.12 Mac10.13 Win Win7 Win10 ] # tags: [ Release Debug ] # results: [ Timeout Crash Pass Failure Slow Skip ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index b171cd2..12fc1e1 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -1,4 +1,4 @@ -# tags: [ Android Fuchsia IOS IOS12.2 IOS13.0 Linux Mac Mac10.12 Mac10.13 Mac10.14 Mac10.15 Win Win7 Win10 ] +# tags: [ Android Fuchsia Linux Mac Mac10.12 Mac10.13 Mac10.14 Mac10.15 Win Win7 Win10 ] # tags: [ Release Debug ] # results: [ Timeout Crash Pass Failure Skip ] @@ -3324,8 +3324,6 @@ crbug.com/626703 [ Win10 ] external/wpt/fetch/api/redirect/redirect-count.any.html [ Timeout ] crbug.com/626703 external/wpt/css/cssom-view/scroll-behavior-smooth.html [ Timeout Crash ] -crbug.com/626703 [ IOS ] external/wpt/websockets/Create-Secure-extensions-empty.any.html [ Timeout ] -crbug.com/626703 [ IOS ] external/wpt/websockets/Create-Secure-extensions-empty.any.worker.html [ Timeout ] crbug.com/626703 external/wpt/html/browsers/history/joint-session-history/joint-session-history-remove-iframe.html [ Timeout ] crbug.com/626703 external/wpt/css/css-shapes/shape-outside/shape-image/gradients/shape-outside-linear-gradient-008.html [ Failure ] crbug.com/626703 external/wpt/css/css-shapes/shape-outside/shape-image/gradients/shape-outside-linear-gradient-006.html [ Failure ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites index f1ed4ad..4f55295 100644 --- a/third_party/blink/web_tests/VirtualTestSuites +++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -203,7 +203,8 @@ "external/wpt/css/filter-effects", "external/wpt/largest-contentful-paint", "fast/hidpi/static", - "http/tests/csspaint/hidpi"], + "http/tests/csspaint/hidpi", + "http/tests/images/document-policy"], "args": ["--force-device-scale-factor=2"] }, {
diff --git a/third_party/blink/web_tests/W3CImportExpectations b/third_party/blink/web_tests/W3CImportExpectations index 3d5f8a0..d653d5999 100644 --- a/third_party/blink/web_tests/W3CImportExpectations +++ b/third_party/blink/web_tests/W3CImportExpectations
@@ -1,4 +1,4 @@ -# tags: [ Android Fuchsia IOS IOS12.2 IOS13.0 Linux Mac Mac10.12 Mac10.13 Win Win7 Win10 ] +# tags: [ Android Fuchsia Linux Mac Mac10.12 Mac10.13 Win Win7 Win10 ] # tags: [ Release Debug ] # results: [ Skip ]
diff --git a/third_party/blink/web_tests/WPTOverrideExpectations b/third_party/blink/web_tests/WPTOverrideExpectations index 4174419..4d74e90 100644 --- a/third_party/blink/web_tests/WPTOverrideExpectations +++ b/third_party/blink/web_tests/WPTOverrideExpectations
@@ -1,4 +1,4 @@ -# tags: [ Android Fuchsia IOS IOS12.2 IOS13.0 Linux Mac Mac10.12 Mac10.13 Win Win7 Win10 ] +# tags: [ Android Fuchsia Linux Mac Mac10.12 Mac10.13 Win Win7 Win10 ] # tags: [ Release Debug ] # results: [ Timeout Crash Pass Failure Slow Skip ]
diff --git a/third_party/blink/web_tests/WebDriverExpectations b/third_party/blink/web_tests/WebDriverExpectations index b6d5928..a589dbf 100644 --- a/third_party/blink/web_tests/WebDriverExpectations +++ b/third_party/blink/web_tests/WebDriverExpectations
@@ -1,4 +1,4 @@ -# tags: [ Android Fuchsia IOS IOS12.2 IOS13.0 Linux Mac Mac10.12 Mac10.13 Win Win7 Win10 ] +# tags: [ Android Fuchsia Linux Mac Mac10.12 Mac10.13 Win Win7 Win10 ] # tags: [ Release Debug ] # results: [ Timeout Crash Pass Failure Slow Skip ]
diff --git a/third_party/blink/web_tests/WebGPUExpectations b/third_party/blink/web_tests/WebGPUExpectations index 2d41eb87..a2f21c95 100644 --- a/third_party/blink/web_tests/WebGPUExpectations +++ b/third_party/blink/web_tests/WebGPUExpectations
@@ -1,4 +1,4 @@ -# tags: [ Android Fuchsia IOS IOS12.2 IOS13.0 Linux Mac Mac10.12 Mac10.13 Win Win7 Win10 ] +# tags: [ Android Fuchsia Linux Mac Mac10.12 Mac10.13 Win Win7 Win10 ] # tags: [ Release Debug ] # results: [ Timeout Crash Pass Failure Slow Skip RetryOnFailure ]
diff --git a/third_party/blink/web_tests/accessibility/computed-name-expected.txt b/third_party/blink/web_tests/accessibility/computed-name-expected.txt index c46aa329..f635db5 100644 --- a/third_party/blink/web_tests/accessibility/computed-name-expected.txt +++ b/third_party/blink/web_tests/accessibility/computed-name-expected.txt
@@ -60,6 +60,8 @@ PASS name is "menubar name" PASS name is "menuitem name" PASS name is "menuitem name" +PASS name is "group name" +PASS name is "menuitem name" PASS name is "menuitemcheckbox name" PASS name is "menuitemcheckbox name" PASS name is "menuitemradio name"
diff --git a/third_party/blink/web_tests/accessibility/computed-name.html b/third_party/blink/web_tests/accessibility/computed-name.html index af775adf..7e1fe99 100644 --- a/third_party/blink/web_tests/accessibility/computed-name.html +++ b/third_party/blink/web_tests/accessibility/computed-name.html
@@ -118,6 +118,9 @@ <div role="menuitem">menuitem name</div> <div role="menuitem" aria-label="menuitem name">This is a menuitem</div> + <div role="group" aria-label="group name"> + <div role="menuitem">menuitem name</div> + </div> <menu type="popup"> <menuitem command="doSomething" data-role="menuitem" aria-label="implicit menuitem name" data-knownFailure>This is a menuitem</menuitem> </menu>
diff --git a/third_party/blink/web_tests/android/ChromiumWPTExpectations b/third_party/blink/web_tests/android/ChromiumWPTExpectations index 59ab398..5e7e13a 100644 --- a/third_party/blink/web_tests/android/ChromiumWPTExpectations +++ b/third_party/blink/web_tests/android/ChromiumWPTExpectations
@@ -3709,7 +3709,6 @@ crbug.com/1050754 external/wpt/service-workers/service-worker/fetch-canvas-tainting-video.https.html [ Failure ] crbug.com/1050754 external/wpt/service-workers/service-worker/fetch-cors-xhr.https.html [ Failure ] crbug.com/1050754 external/wpt/service-workers/service-worker/fetch-error.https.html [ Failure ] -crbug.com/1050754 external/wpt/service-workers/service-worker/fetch-event-handled.https.html [ Failure ] crbug.com/1050754 external/wpt/service-workers/service-worker/fetch-event-redirect.https.html [ Failure ] crbug.com/1050754 external/wpt/service-workers/service-worker/fetch-event-referrer-policy.https.html [ Failure ] crbug.com/1050754 external/wpt/service-workers/service-worker/fetch-event-respond-with-custom-response.https.html [ Failure ]
diff --git a/third_party/blink/web_tests/android/WeblayerWPTExpectations b/third_party/blink/web_tests/android/WeblayerWPTExpectations index 0fd8a017..fc11743 100644 --- a/third_party/blink/web_tests/android/WeblayerWPTExpectations +++ b/third_party/blink/web_tests/android/WeblayerWPTExpectations
@@ -3747,7 +3747,6 @@ crbug.com/1050754 external/wpt/service-workers/service-worker/fetch-canvas-tainting-video-with-range-request.https.html [ Failure ] crbug.com/1050754 external/wpt/service-workers/service-worker/fetch-canvas-tainting-video.https.html [ Failure ] crbug.com/1050754 external/wpt/service-workers/service-worker/fetch-error.https.html [ Failure ] -crbug.com/1050754 external/wpt/service-workers/service-worker/fetch-event-handled.https.html [ Failure ] crbug.com/1050754 external/wpt/service-workers/service-worker/fetch-event-redirect.https.html [ Failure ] crbug.com/1050754 external/wpt/service-workers/service-worker/fetch-event-referrer-policy.https.html [ Failure ] crbug.com/1050754 external/wpt/service-workers/service-worker/fetch-event-respond-with-custom-response.https.html [ Failure ]
diff --git a/third_party/blink/web_tests/android/WebviewWPTExpectations b/third_party/blink/web_tests/android/WebviewWPTExpectations index 51fb9a8..4f3105f 100644 --- a/third_party/blink/web_tests/android/WebviewWPTExpectations +++ b/third_party/blink/web_tests/android/WebviewWPTExpectations
@@ -3984,7 +3984,6 @@ crbug.com/1050754 external/wpt/service-workers/service-worker/fetch-canvas-tainting-video-with-range-request.https.html [ Timeout ] crbug.com/1050754 external/wpt/service-workers/service-worker/fetch-canvas-tainting-video.https.html [ Failure ] crbug.com/1050754 external/wpt/service-workers/service-worker/fetch-error.https.html [ Failure ] -crbug.com/1050754 external/wpt/service-workers/service-worker/fetch-event-handled.https.html [ Failure ] crbug.com/1050754 external/wpt/service-workers/service-worker/fetch-event-redirect.https.html [ Failure ] crbug.com/1050754 external/wpt/service-workers/service-worker/fetch-event-referrer-policy.https.html [ Failure ] crbug.com/1050754 external/wpt/service-workers/service-worker/fetch-event-respond-with-custom-response.https.html [ Failure ]
diff --git a/third_party/blink/web_tests/external/wpt/paint-timing/first-contentful-canvas-none.html b/third_party/blink/web_tests/external/wpt/paint-timing/first-contentful-canvas-none.html new file mode 100644 index 0000000..33a4352 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/paint-timing/first-contentful-canvas-none.html
@@ -0,0 +1,23 @@ +<!DOCTYPE html> + +<head> + <title>Performance Paint Timing Test: FCP due to canvas</title> +</head> + +<body> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="resources/utils.js"></script> + <canvas id="canvas" width="200" height="200"></canvas> + + <script> + setup({"hide_test_state": true}); + promise_test(async t => { + assert_implements(window.PerformancePaintTiming, "Paint Timing isn't supported."); + await new Promise(r => window.addEventListener('load', r)); + await assertNoFirstContentfulPaint(t); + }, 'First contentful paint should not fire for canvas type none'); + </script> +</body> + +</html>
diff --git a/third_party/blink/web_tests/external/wpt/paint-timing/first-contentful-canvas-webgl2.html b/third_party/blink/web_tests/external/wpt/paint-timing/first-contentful-canvas-webgl2.html new file mode 100644 index 0000000..f7c5f50 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/paint-timing/first-contentful-canvas-webgl2.html
@@ -0,0 +1,47 @@ +<!DOCTYPE html> + +<head> + <title>Performance Paint Timing Test: FCP due to canvas</title> +</head> + +<body> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <canvas id="canvas" width="200" height="200"></canvas> + + <script> + setup({ "hide_test_state": true }); + async_test(function (t) { + assert_implements(window.PerformancePaintTiming, "Paint Timing isn't supported."); + const canvas = document.getElementById("canvas"); + const context = canvas.getContext("webgl2"); + if (!context) { + assert_implements_optional(context, "WebGL 2 Canvas isn't supported.") + } + context.clearColor(0.3, 0.3, 0.3, 1); + context.clear(context.COLOR_BUFFER_BIT); + function testPaintEntries() { + const bufferedEntries = performance.getEntriesByType('paint'); + if (bufferedEntries.length < 2) { + t.step_timeout(function () { + testPaintEntries(); + }, 20); + return; + } + t.step(function () { + assert_equals(bufferedEntries.length, 2, "There should be two paint timing instances."); + assert_equals(bufferedEntries[0].entryType, "paint"); + assert_equals(bufferedEntries[0].name, "first-paint"); + assert_equals(bufferedEntries[1].entryType, "paint"); + assert_equals(bufferedEntries[1].name, "first-contentful-paint"); + t.done(); + }); + }; + t.step(function () { + testPaintEntries(); + }); + }, "First contentful paint fires due to webgl2 canvas render."); + </script> +</body> + +</html>
diff --git a/third_party/blink/web_tests/external/wpt/shadow-dom/declarative/element-internals-shadowroot.tentative.html b/third_party/blink/web_tests/external/wpt/shadow-dom/declarative/element-internals-shadowroot.tentative.html new file mode 100644 index 0000000..0f01cc4 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/shadow-dom/declarative/element-internals-shadowroot.tentative.html
@@ -0,0 +1,44 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>ElementInternals.shadowRoot</title> +<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="help" href="https://github.com/w3c/webcomponents/issues/871"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script> + +test(() => { + let constructed = false; + customElements.define('custom-open', class extends HTMLElement { + constructor() { + super(); + const elementInternals = this.attachInternals(); + assert_equals(elementInternals.shadowRoot, null); + const shadow = this.attachShadow({mode: 'open'}); + assert_equals(elementInternals.shadowRoot, shadow); + constructed = true; + } + }); + const element = document.createElement('custom-open'); + assert_true(constructed); +}, 'ElementInternals.shadowRoot allows access to open shadow root'); + +test(() => { + let constructed = false; + customElements.define('custom-closed', class extends HTMLElement { + constructor() { + super(); + const elementInternals = this.attachInternals(); + assert_equals(elementInternals.shadowRoot, null); + const shadow = this.attachShadow({mode: 'closed'}); + assert_equals(elementInternals.shadowRoot, shadow); + assert_equals(this.shadowRoot, null); + constructed = true; + } + }); + const element = document.createElement('custom-closed'); + assert_true(constructed); +}, 'ElementInternals.shadowRoot allows access to closed shadow root'); + +</script>
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/idlharness.https.window-expected.txt b/third_party/blink/web_tests/external/wpt/webrtc/idlharness.https.window-expected.txt index 8b39ad8..222565c 100644 --- a/third_party/blink/web_tests/external/wpt/webrtc/idlharness.https.window-expected.txt +++ b/third_party/blink/web_tests/external/wpt/webrtc/idlharness.https.window-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 496 tests; 479 PASS, 17 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 496 tests; 480 PASS, 16 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS idl_test setup PASS idl_test validation PASS Test driver for asyncInitCertificate @@ -235,7 +235,7 @@ PASS RTCRtpSender interface: attribute track PASS RTCRtpSender interface: attribute transport PASS RTCRtpSender interface: operation getCapabilities(DOMString) -FAIL RTCRtpSender interface: operation setParameters(RTCRtpSendParameters) assert_equals: property has wrong .length expected 1 but got 0 +PASS RTCRtpSender interface: operation setParameters(RTCRtpSendParameters) PASS RTCRtpSender interface: operation getParameters() PASS RTCRtpSender interface: operation replaceTrack(MediaStreamTrack?) PASS RTCRtpSender interface: operation setStreams(MediaStream...)
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/highlight/highlight-css-grid-direction-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/highlight/highlight-css-grid-direction-expected.txt new file mode 100644 index 0000000..0cfe4961 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/devtools/elements/highlight/highlight-css-grid-direction-expected.txt
@@ -0,0 +1,1051 @@ +This test verifies that grids with direction rtl and ltr are correctly highlighted. + +ltrGrid{ + "paths": [ + { + "path": [ + "M", + 8, + 44, + "L", + 108, + 44, + "L", + 108, + 144, + "L", + 8, + 144, + "Z" + ], + "fillColor": "rgba(255, 0, 0, 0)", + "outlineColor": "rgba(128, 0, 0, 0)", + "name": "content" + }, + { + "path": [ + "M", + 8, + 44, + "L", + 108, + 44, + "L", + 108, + 144, + "L", + 8, + 144, + "Z" + ], + "fillColor": "rgba(0, 255, 0, 0)", + "name": "padding" + }, + { + "path": [ + "M", + 8, + 44, + "L", + 108, + 44, + "L", + 108, + 144, + "L", + 8, + 144, + "Z" + ], + "fillColor": "rgba(0, 0, 255, 0)", + "name": "border" + }, + { + "path": [ + "M", + 8, + 44, + "L", + 108, + 44, + "L", + 108, + 144, + "L", + 8, + 144, + "Z" + ], + "fillColor": "rgba(255, 255, 255, 0)", + "name": "margin" + } + ], + "showRulers": true, + "showExtensionLines": true, + "showAccessibilityInfo": true, + "colorFormat": "hex", + "elementInfo": { + "tagName": "div", + "idValue": "ltrGrid", + "className": ".grid.ltr-dir", + "nodeWidth": "100", + "nodeHeight": "100", + "isKeyboardFocusable": false, + "accessibleName": "", + "accessibleRole": "generic", + "layoutObjectName": "LayoutGrid", + "showAccessibilityInfo": true + }, + "gridInfo": [ + { + "rotationAngle": 0, + "columnTrackSizes": [ + { + "x": 18, + "y": 44, + "computedSize": 20, + "authoredSize": "20px" + }, + { + "x": 53, + "y": 44, + "computedSize": 50, + "authoredSize": "50px" + } + ], + "rowTrackSizes": [ + { + "x": 8, + "y": 94, + "computedSize": 100, + "authoredSize": "100px" + } + ], + "rows": [ + "M", + 8, + 44, + "L", + 78, + 44, + "M", + 78, + 144, + "L", + 8, + 144 + ], + "rowGaps": [], + "columns": [ + "M", + 8, + 44, + "L", + 8, + 144, + "M", + 28, + 44, + "L", + 28, + 144, + "M", + 78, + 144, + "L", + 78, + 44 + ], + "columnGaps": [ + "M", + 28, + 44, + "L", + 28, + 44, + "L", + 28, + 144, + "L", + 28, + 144, + "Z" + ], + "positiveRowLineNumberPositions": [ + { + "x": 8, + "y": 44 + }, + { + "x": 8, + "y": 144 + } + ], + "positiveColumnLineNumberPositions": [ + { + "x": 8, + "y": 44 + }, + { + "x": 28, + "y": 44 + }, + { + "x": 78, + "y": 44 + } + ], + "negativeRowLineNumberPositions": [ + { + "x": 78, + "y": 44 + }, + { + "x": 78, + "y": 144 + } + ], + "negativeColumnLineNumberPositions": [ + { + "x": 8, + "y": 144 + }, + { + "x": 28, + "y": 144 + }, + { + "x": 78, + "y": 144 + } + ], + "areaNames": {}, + "rowLineNameOffsets": [], + "columnLineNameOffsets": [], + "gridBorder": [ + "M", + 8, + 44, + "L", + 78, + 44, + "L", + 78, + 144, + "L", + 8, + 144, + "Z" + ], + "gridHighlightConfig": { + "gridBorderDash": false, + "rowLineDash": true, + "columnLineDash": true, + "showGridExtensionLines": true, + "showPositiveLineNumbers": true, + "showNegativeLineNumbers": true, + "showAreaNames": true, + "showLineNames": true, + "gridBorderColor": "rgba(255, 0, 0, 0)", + "rowLineColor": "rgba(128, 0, 0, 0)", + "columnLineColor": "rgba(128, 0, 0, 0)", + "rowGapColor": "rgba(0, 255, 0, 0)", + "columnGapColor": "rgba(0, 0, 255, 0)", + "rowHatchColor": "rgba(255, 255, 255, 0)", + "columnHatchColor": "rgba(128, 128, 128, 0)", + "areaBorderColor": "rgba(255, 0, 0, 0)" + }, + "isPrimaryGrid": true + } + ] +} +rtlGrid{ + "paths": [ + { + "path": [ + "M", + 8, + 44, + "L", + 108, + 44, + "L", + 108, + 144, + "L", + 8, + 144, + "Z" + ], + "fillColor": "rgba(255, 0, 0, 0)", + "outlineColor": "rgba(128, 0, 0, 0)", + "name": "content" + }, + { + "path": [ + "M", + 8, + 44, + "L", + 108, + 44, + "L", + 108, + 144, + "L", + 8, + 144, + "Z" + ], + "fillColor": "rgba(0, 255, 0, 0)", + "name": "padding" + }, + { + "path": [ + "M", + 8, + 44, + "L", + 108, + 44, + "L", + 108, + 144, + "L", + 8, + 144, + "Z" + ], + "fillColor": "rgba(0, 0, 255, 0)", + "name": "border" + }, + { + "path": [ + "M", + 8, + 44, + "L", + 108, + 44, + "L", + 108, + 144, + "L", + 8, + 144, + "Z" + ], + "fillColor": "rgba(255, 255, 255, 0)", + "name": "margin" + } + ], + "showRulers": true, + "showExtensionLines": true, + "showAccessibilityInfo": true, + "colorFormat": "hex", + "elementInfo": { + "tagName": "div", + "idValue": "rtlGrid", + "className": ".grid.rtl-dir", + "nodeWidth": "100", + "nodeHeight": "100", + "isKeyboardFocusable": false, + "accessibleName": "", + "accessibleRole": "generic", + "layoutObjectName": "LayoutGrid", + "showAccessibilityInfo": true + }, + "gridInfo": [ + { + "rotationAngle": 0, + "columnTrackSizes": [ + { + "x": 48, + "y": 44, + "computedSize": 20, + "authoredSize": "20px" + }, + { + "x": 83, + "y": 44, + "computedSize": 50, + "authoredSize": "50px" + } + ], + "rowTrackSizes": [ + { + "x": 38, + "y": 94, + "computedSize": 100, + "authoredSize": "100px" + } + ], + "rows": [ + "M", + 38, + 44, + "L", + 108, + 44, + "M", + 108, + 144, + "L", + 38, + 144 + ], + "rowGaps": [], + "columns": [ + "M", + 88, + 44, + "L", + 88, + 144, + "M", + 108, + 144, + "L", + 108, + 44, + "M", + 38, + 44, + "L", + 38, + 144 + ], + "columnGaps": [ + "M", + 88, + 44, + "L", + 88, + 44, + "L", + 88, + 144, + "L", + 88, + 144, + "Z" + ], + "positiveRowLineNumberPositions": [ + { + "x": 38, + "y": 44 + }, + { + "x": 38, + "y": 144 + } + ], + "positiveColumnLineNumberPositions": [ + { + "x": 38, + "y": 44 + }, + { + "x": 58, + "y": 44 + }, + { + "x": 108, + "y": 44 + } + ], + "negativeRowLineNumberPositions": [ + { + "x": 108, + "y": 44 + }, + { + "x": 108, + "y": 144 + } + ], + "negativeColumnLineNumberPositions": [ + { + "x": 38, + "y": 144 + }, + { + "x": 58, + "y": 144 + }, + { + "x": 108, + "y": 144 + } + ], + "areaNames": {}, + "rowLineNameOffsets": [], + "columnLineNameOffsets": [], + "gridBorder": [ + "M", + 38, + 44, + "L", + 108, + 44, + "L", + 108, + 144, + "L", + 38, + 144, + "Z" + ], + "gridHighlightConfig": { + "gridBorderDash": false, + "rowLineDash": true, + "columnLineDash": true, + "showGridExtensionLines": true, + "showPositiveLineNumbers": true, + "showNegativeLineNumbers": true, + "showAreaNames": true, + "showLineNames": true, + "gridBorderColor": "rgba(255, 0, 0, 0)", + "rowLineColor": "rgba(128, 0, 0, 0)", + "columnLineColor": "rgba(128, 0, 0, 0)", + "rowGapColor": "rgba(0, 255, 0, 0)", + "columnGapColor": "rgba(0, 0, 255, 0)", + "rowHatchColor": "rgba(255, 255, 255, 0)", + "columnHatchColor": "rgba(128, 128, 128, 0)", + "areaBorderColor": "rgba(255, 0, 0, 0)" + }, + "isPrimaryGrid": true + } + ] +} +ltrGridGap{ + "paths": [ + { + "path": [ + "M", + 8, + 44, + "L", + 108, + 44, + "L", + 108, + 144, + "L", + 8, + 144, + "Z" + ], + "fillColor": "rgba(255, 0, 0, 0)", + "outlineColor": "rgba(128, 0, 0, 0)", + "name": "content" + }, + { + "path": [ + "M", + 8, + 44, + "L", + 108, + 44, + "L", + 108, + 144, + "L", + 8, + 144, + "Z" + ], + "fillColor": "rgba(0, 255, 0, 0)", + "name": "padding" + }, + { + "path": [ + "M", + 8, + 44, + "L", + 108, + 44, + "L", + 108, + 144, + "L", + 8, + 144, + "Z" + ], + "fillColor": "rgba(0, 0, 255, 0)", + "name": "border" + }, + { + "path": [ + "M", + 8, + 44, + "L", + 108, + 44, + "L", + 108, + 144, + "L", + 8, + 144, + "Z" + ], + "fillColor": "rgba(255, 255, 255, 0)", + "name": "margin" + } + ], + "showRulers": true, + "showExtensionLines": true, + "showAccessibilityInfo": true, + "colorFormat": "hex", + "elementInfo": { + "tagName": "div", + "idValue": "ltrGridGap", + "className": ".grid.ltr-dir.with-gap", + "nodeWidth": "100", + "nodeHeight": "100", + "isKeyboardFocusable": false, + "accessibleName": "", + "accessibleRole": "generic", + "layoutObjectName": "LayoutGrid", + "showAccessibilityInfo": true + }, + "gridInfo": [ + { + "rotationAngle": 0, + "columnTrackSizes": [ + { + "x": 18, + "y": 44, + "computedSize": 20, + "authoredSize": "20px" + }, + { + "x": 69, + "y": 44, + "computedSize": 50, + "authoredSize": "50px" + } + ], + "rowTrackSizes": [ + { + "x": 8, + "y": 94, + "computedSize": 100, + "authoredSize": "100px" + } + ], + "rows": [ + "M", + 8, + 44, + "L", + 94, + 44, + "M", + 94, + 144, + "L", + 8, + 144 + ], + "rowGaps": [], + "columns": [ + "M", + 8, + 44, + "L", + 8, + 144, + "M", + 28, + 144, + "L", + 28, + 44, + "M", + 44, + 44, + "L", + 44, + 144, + "M", + 94, + 144, + "L", + 94, + 44 + ], + "columnGaps": [ + "M", + 28, + 44, + "L", + 44, + 44, + "L", + 44, + 144, + "L", + 28, + 144, + "Z" + ], + "positiveRowLineNumberPositions": [ + { + "x": 8, + "y": 44 + }, + { + "x": 8, + "y": 144 + } + ], + "positiveColumnLineNumberPositions": [ + { + "x": 8, + "y": 44 + }, + { + "x": 36, + "y": 44 + }, + { + "x": 94, + "y": 44 + } + ], + "negativeRowLineNumberPositions": [ + { + "x": 94, + "y": 44 + }, + { + "x": 94, + "y": 144 + } + ], + "negativeColumnLineNumberPositions": [ + { + "x": 8, + "y": 144 + }, + { + "x": 36, + "y": 144 + }, + { + "x": 94, + "y": 144 + } + ], + "areaNames": {}, + "rowLineNameOffsets": [], + "columnLineNameOffsets": [], + "gridBorder": [ + "M", + 8, + 44, + "L", + 94, + 44, + "L", + 94, + 144, + "L", + 8, + 144, + "Z" + ], + "gridHighlightConfig": { + "gridBorderDash": false, + "rowLineDash": true, + "columnLineDash": true, + "showGridExtensionLines": true, + "showPositiveLineNumbers": true, + "showNegativeLineNumbers": true, + "showAreaNames": true, + "showLineNames": true, + "gridBorderColor": "rgba(255, 0, 0, 0)", + "rowLineColor": "rgba(128, 0, 0, 0)", + "columnLineColor": "rgba(128, 0, 0, 0)", + "rowGapColor": "rgba(0, 255, 0, 0)", + "columnGapColor": "rgba(0, 0, 255, 0)", + "rowHatchColor": "rgba(255, 255, 255, 0)", + "columnHatchColor": "rgba(128, 128, 128, 0)", + "areaBorderColor": "rgba(255, 0, 0, 0)" + }, + "isPrimaryGrid": true + } + ] +} +rtlGridGap{ + "paths": [ + { + "path": [ + "M", + 8, + 44, + "L", + 108, + 44, + "L", + 108, + 144, + "L", + 8, + 144, + "Z" + ], + "fillColor": "rgba(255, 0, 0, 0)", + "outlineColor": "rgba(128, 0, 0, 0)", + "name": "content" + }, + { + "path": [ + "M", + 8, + 44, + "L", + 108, + 44, + "L", + 108, + 144, + "L", + 8, + 144, + "Z" + ], + "fillColor": "rgba(0, 255, 0, 0)", + "name": "padding" + }, + { + "path": [ + "M", + 8, + 44, + "L", + 108, + 44, + "L", + 108, + 144, + "L", + 8, + 144, + "Z" + ], + "fillColor": "rgba(0, 0, 255, 0)", + "name": "border" + }, + { + "path": [ + "M", + 8, + 44, + "L", + 108, + 44, + "L", + 108, + 144, + "L", + 8, + 144, + "Z" + ], + "fillColor": "rgba(255, 255, 255, 0)", + "name": "margin" + } + ], + "showRulers": true, + "showExtensionLines": true, + "showAccessibilityInfo": true, + "colorFormat": "hex", + "elementInfo": { + "tagName": "div", + "idValue": "rtlGridGap", + "className": ".grid.rtl-dir.with-gap", + "nodeWidth": "100", + "nodeHeight": "100", + "isKeyboardFocusable": false, + "accessibleName": "", + "accessibleRole": "generic", + "layoutObjectName": "LayoutGrid", + "showAccessibilityInfo": true + }, + "gridInfo": [ + { + "rotationAngle": 0, + "columnTrackSizes": [ + { + "x": 32, + "y": 44, + "computedSize": 20, + "authoredSize": "20px" + }, + { + "x": 83, + "y": 44, + "computedSize": 50, + "authoredSize": "50px" + } + ], + "rowTrackSizes": [ + { + "x": 22, + "y": 94, + "computedSize": 100, + "authoredSize": "100px" + } + ], + "rows": [ + "M", + 22, + 44, + "L", + 108, + 44, + "M", + 108, + 144, + "L", + 22, + 144 + ], + "rowGaps": [], + "columns": [ + "M", + 88, + 44, + "L", + 88, + 144, + "M", + 108, + 144, + "L", + 108, + 44, + "M", + 22, + 44, + "L", + 22, + 144, + "M", + 72, + 144, + "L", + 72, + 44 + ], + "columnGaps": [ + "M", + 72, + 44, + "L", + 88, + 44, + "L", + 88, + 144, + "L", + 72, + 144, + "Z" + ], + "positiveRowLineNumberPositions": [ + { + "x": 22, + "y": 44 + }, + { + "x": 22, + "y": 144 + } + ], + "positiveColumnLineNumberPositions": [ + { + "x": 22, + "y": 44 + }, + { + "x": 50, + "y": 44 + }, + { + "x": 108, + "y": 44 + } + ], + "negativeRowLineNumberPositions": [ + { + "x": 108, + "y": 44 + }, + { + "x": 108, + "y": 144 + } + ], + "negativeColumnLineNumberPositions": [ + { + "x": 22, + "y": 144 + }, + { + "x": 50, + "y": 144 + }, + { + "x": 108, + "y": 144 + } + ], + "areaNames": {}, + "rowLineNameOffsets": [], + "columnLineNameOffsets": [], + "gridBorder": [ + "M", + 22, + 44, + "L", + 108, + 44, + "L", + 108, + 144, + "L", + 22, + 144, + "Z" + ], + "gridHighlightConfig": { + "gridBorderDash": false, + "rowLineDash": true, + "columnLineDash": true, + "showGridExtensionLines": true, + "showPositiveLineNumbers": true, + "showNegativeLineNumbers": true, + "showAreaNames": true, + "showLineNames": true, + "gridBorderColor": "rgba(255, 0, 0, 0)", + "rowLineColor": "rgba(128, 0, 0, 0)", + "columnLineColor": "rgba(128, 0, 0, 0)", + "rowGapColor": "rgba(0, 255, 0, 0)", + "columnGapColor": "rgba(0, 0, 255, 0)", + "rowHatchColor": "rgba(255, 255, 255, 0)", + "columnHatchColor": "rgba(128, 128, 128, 0)", + "areaBorderColor": "rgba(255, 0, 0, 0)" + }, + "isPrimaryGrid": true + } + ] +} +
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/highlight/highlight-css-grid-direction.js b/third_party/blink/web_tests/http/tests/devtools/elements/highlight/highlight-css-grid-direction.js new file mode 100644 index 0000000..443a3c6 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/devtools/elements/highlight/highlight-css-grid-direction.js
@@ -0,0 +1,61 @@ +// 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. + +(async function() { + TestRunner.addResult(`This test verifies that grids with direction rtl and ltr are correctly highlighted.\n`); + await TestRunner.loadModule('elements_test_runner'); + await TestRunner.showPanel('elements'); + await TestRunner.loadHTML(` + <style> + .grid { + position: absolute; + top: 44px; + left: 8px; + grid-template-columns: 20px 50px; + grid-template-rows: 100px; + width: 100px; + display: grid; + } + .ltr-dir { + direction: ltr; + } + .rtl-dir { + direction: rtl; + } + .with-gap { + grid-gap: 1em; + } + </style> + + <p id="description">This test verifies that grids with direction rtl and ltr are correctly highlighted.</p> + <div> + <div class="grid ltr-dir" id="ltrGrid"> + <div style="background: burlywood"></div> + <div style="background: cadetblue"></div> + </div> + <div class="grid rtl-dir" id="rtlGrid"> + <div style="background: burlywood"></div> + <div style="background: cadetblue"></div> + </div> + <div class="grid ltr-dir with-gap" id="ltrGridGap"> + <div style="background: burlywood"></div> + <div style="background: cadetblue"></div> + </div> + <div class="grid rtl-dir with-gap" id="rtlGridGap"> + <div style="background: burlywood"></div> + <div style="background: cadetblue"></div> + </div> + </div> +`); + function dumpGridHighlight(id) { + return new Promise(resolve => ElementsTestRunner.dumpInspectorHighlightJSON(id, resolve)); + } + + await dumpGridHighlight('ltrGrid'); + await dumpGridHighlight('rtlGrid'); + await dumpGridHighlight('ltrGridGap'); + await dumpGridHighlight('rtlGridGap'); + + TestRunner.completeTest(); +})();
diff --git a/third_party/blink/web_tests/http/tests/devtools/portals/portals-sources-activate-expected.txt b/third_party/blink/web_tests/http/tests/devtools/portals/portals-sources-activate-expected.txt new file mode 100644 index 0000000..b5ce4e2 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/devtools/portals/portals-sources-activate-expected.txt
@@ -0,0 +1,7 @@ +Checks that breakpoint set inside a portalactivate event handler is hit on activation +error: Item to refresh is not present +Script execution paused. +Call stack: + 0) window.onportalactivate (append-predecessor.html:5) +Script execution resumed. +
diff --git a/third_party/blink/web_tests/http/tests/devtools/portals/portals-sources-activate.js b/third_party/blink/web_tests/http/tests/devtools/portals/portals-sources-activate.js new file mode 100644 index 0000000..bd98d8a2 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/devtools/portals/portals-sources-activate.js
@@ -0,0 +1,20 @@ +// 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. + + +(async function () { + TestRunner.addResult(`Checks that breakpoint set inside a portalactivate event handler is hit on activation`); + await TestRunner.loadModule('sources_test_runner'); + await TestRunner.showPanel('sources'); + + await TestRunner.navigatePromise('resources/append-predecessor-host.html'); + + await SourcesTestRunner.startDebuggerTestPromise(); + const sourceFrame = await SourcesTestRunner.showScriptSourcePromise('append-predecessor.html'); + await SourcesTestRunner.toggleBreakpoint(sourceFrame, 4); + TestRunner.evaluateInPage(`setTimeout(() => document.querySelector('portal').activate());`); + const callFrames = await SourcesTestRunner.waitUntilPausedPromise(); + await SourcesTestRunner.captureStackTrace(callFrames); + SourcesTestRunner.completeDebuggerTest(); +})();
diff --git a/third_party/blink/web_tests/http/tests/images/document-policy/document-policy-oversized-images-edge-cases-expected.txt b/third_party/blink/web_tests/http/tests/images/document-policy/document-policy-oversized-images-edge-cases-expected.txt new file mode 100644 index 0000000..5e471995 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/images/document-policy/document-policy-oversized-images-edge-cases-expected.txt
@@ -0,0 +1,4 @@ +CONSOLE ERROR: Document policy violation: oversized-images is not allowed in this document. +CONSOLE ERROR: Document policy violation: oversized-images is not allowed in this document. +CONSOLE ERROR: Document policy violation: oversized-images is not allowed in this document. +CONSOLE ERROR: Document policy violation: oversized-images is not allowed in this document.
diff --git a/third_party/blink/web_tests/http/tests/images/document-policy-oversized-images-edge-cases.html b/third_party/blink/web_tests/http/tests/images/document-policy/document-policy-oversized-images-edge-cases.html similarity index 100% rename from third_party/blink/web_tests/http/tests/images/document-policy-oversized-images-edge-cases.html rename to third_party/blink/web_tests/http/tests/images/document-policy/document-policy-oversized-images-edge-cases.html
diff --git a/third_party/blink/web_tests/http/tests/images/document-policy/resources/frame-with-oversized-images-edge-cases.php b/third_party/blink/web_tests/http/tests/images/document-policy/resources/frame-with-oversized-images-edge-cases.php new file mode 100644 index 0000000..a9b796a --- /dev/null +++ b/third_party/blink/web_tests/http/tests/images/document-policy/resources/frame-with-oversized-images-edge-cases.php
@@ -0,0 +1,24 @@ +<?php +header("Document-Policy: oversized-images=2.0"); +?> +<!DOCTYPE html> + +<!-- + Images should be replaced by placeholders if there are considered + oversized, i.e. having + image_size / (container_size * pixel_ratio) > threshold. + Threshold is set by the document policy header(2.0 in this test). +--> +<body> + <img src="green-256x256.jpg"> + <!-- Following cases are for device pixel ratio = 1.0 --> + <!-- Image with size < 128 should all be replaced with placeholders --> + <img src="green-256x256.jpg" width="128" height="128"> + <img src="green-256x256.jpg" width="127" height="127"> + <img src="green-256x256.jpg" width="129" height="129"> + <!-- Following cases are for device pixel ratio = 2.0 --> + <!-- Image with size < 64 should all be replaced with placeholders --> + <img src="green-256x256.jpg" width="64" height="64"> + <img src="green-256x256.jpg" width="63" height="63"> + <img src="green-256x256.jpg" width="65" height="65"> +</body> \ No newline at end of file
diff --git a/third_party/blink/web_tests/http/tests/images/document-policy/resources/green-256x256.jpg b/third_party/blink/web_tests/http/tests/images/document-policy/resources/green-256x256.jpg new file mode 100644 index 0000000..497ed770 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/images/document-policy/resources/green-256x256.jpg Binary files differ
diff --git a/third_party/blink/web_tests/http/tests/images/resources/frame-with-oversized-images-edge-cases.php b/third_party/blink/web_tests/http/tests/images/resources/frame-with-oversized-images-edge-cases.php deleted file mode 100644 index b43e2c5..0000000 --- a/third_party/blink/web_tests/http/tests/images/resources/frame-with-oversized-images-edge-cases.php +++ /dev/null
@@ -1,10 +0,0 @@ -<?php -header("Document-Policy: oversized-images=2.0"); -?> -<!DOCTYPE html> -<body> -<img src="green-256x256.jpg"> -<img src="green-256x256.jpg" width="128" height="128" > -<img src="green-256x256.jpg" width="127" height="127" > -<img src="green-256x256.jpg" width="129" height="129" > -</body>
diff --git a/third_party/blink/web_tests/platform/linux/http/tests/images/document-policy-oversized-images-edge-cases-expected.png b/third_party/blink/web_tests/platform/linux/http/tests/images/document-policy-oversized-images-edge-cases-expected.png deleted file mode 100644 index e8dd3dc6..0000000 --- a/third_party/blink/web_tests/platform/linux/http/tests/images/document-policy-oversized-images-edge-cases-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/http/tests/images/document-policy/document-policy-oversized-images-edge-cases-expected.png b/third_party/blink/web_tests/platform/linux/http/tests/images/document-policy/document-policy-oversized-images-edge-cases-expected.png new file mode 100644 index 0000000..d97f50a3 --- /dev/null +++ b/third_party/blink/web_tests/platform/linux/http/tests/images/document-policy/document-policy-oversized-images-edge-cases-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/scalefactor200/http/tests/images/document-policy/document-policy-oversized-images-edge-cases-expected.png b/third_party/blink/web_tests/platform/linux/virtual/scalefactor200/http/tests/images/document-policy/document-policy-oversized-images-edge-cases-expected.png new file mode 100644 index 0000000..8ab930aa --- /dev/null +++ b/third_party/blink/web_tests/platform/linux/virtual/scalefactor200/http/tests/images/document-policy/document-policy-oversized-images-edge-cases-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/http/tests/images/document-policy-oversized-images-edge-cases-expected.png b/third_party/blink/web_tests/platform/mac/http/tests/images/document-policy-oversized-images-edge-cases-expected.png deleted file mode 100644 index 66bfd22..0000000 --- a/third_party/blink/web_tests/platform/mac/http/tests/images/document-policy-oversized-images-edge-cases-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/http/tests/images/document-policy/document-policy-oversized-images-edge-cases-expected.png b/third_party/blink/web_tests/platform/mac/http/tests/images/document-policy/document-policy-oversized-images-edge-cases-expected.png new file mode 100644 index 0000000..38b9ed5 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/http/tests/images/document-policy/document-policy-oversized-images-edge-cases-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/scalefactor200/http/tests/images/document-policy/document-policy-oversized-images-edge-cases-expected.png b/third_party/blink/web_tests/platform/mac/virtual/scalefactor200/http/tests/images/document-policy/document-policy-oversized-images-edge-cases-expected.png new file mode 100644 index 0000000..8ab930aa --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/scalefactor200/http/tests/images/document-policy/document-policy-oversized-images-edge-cases-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/http/tests/images/document-policy-oversized-images-edge-cases-expected.png b/third_party/blink/web_tests/platform/win/http/tests/images/document-policy-oversized-images-edge-cases-expected.png deleted file mode 100644 index fbf990d..0000000 --- a/third_party/blink/web_tests/platform/win/http/tests/images/document-policy-oversized-images-edge-cases-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/http/tests/images/document-policy/document-policy-oversized-images-edge-cases-expected.png b/third_party/blink/web_tests/platform/win/http/tests/images/document-policy/document-policy-oversized-images-edge-cases-expected.png new file mode 100644 index 0000000..44c0c0d7 --- /dev/null +++ b/third_party/blink/web_tests/platform/win/http/tests/images/document-policy/document-policy-oversized-images-edge-cases-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/scalefactor200/http/tests/images/document-policy/document-policy-oversized-images-edge-cases-expected.png b/third_party/blink/web_tests/platform/win/virtual/scalefactor200/http/tests/images/document-policy/document-policy-oversized-images-edge-cases-expected.png new file mode 100644 index 0000000..dc7f6ad0 --- /dev/null +++ b/third_party/blink/web_tests/platform/win/virtual/scalefactor200/http/tests/images/document-policy/document-policy-oversized-images-edge-cases-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/virtual/scalefactor200/http/tests/images/document-policy/README.txt b/third_party/blink/web_tests/virtual/scalefactor200/http/tests/images/document-policy/README.txt new file mode 100644 index 0000000..3879583e --- /dev/null +++ b/third_party/blink/web_tests/virtual/scalefactor200/http/tests/images/document-policy/README.txt
@@ -0,0 +1 @@ +# This suite runs tests in http/tests/images/document-policy with --force-device-scale-factor=2 \ No newline at end of file
diff --git a/third_party/blink/web_tests/http/tests/images/document-policy-oversized-images-edge-cases-expected.txt b/third_party/blink/web_tests/virtual/scalefactor200/http/tests/images/document-policy/document-policy-oversized-images-edge-cases-expected.txt similarity index 100% rename from third_party/blink/web_tests/http/tests/images/document-policy-oversized-images-edge-cases-expected.txt rename to third_party/blink/web_tests/virtual/scalefactor200/http/tests/images/document-policy/document-policy-oversized-images-edge-cases-expected.txt
diff --git a/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/idlharness.https.window-expected.txt b/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/idlharness.https.window-expected.txt index a48e141..a343612 100644 --- a/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/idlharness.https.window-expected.txt +++ b/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/idlharness.https.window-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 496 tests; 411 PASS, 85 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 496 tests; 412 PASS, 84 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS idl_test setup PASS idl_test validation PASS Test driver for asyncInitCertificate @@ -235,7 +235,7 @@ PASS RTCRtpSender interface: attribute track PASS RTCRtpSender interface: attribute transport PASS RTCRtpSender interface: operation getCapabilities(DOMString) -FAIL RTCRtpSender interface: operation setParameters(RTCRtpSendParameters) assert_equals: property has wrong .length expected 1 but got 0 +PASS RTCRtpSender interface: operation setParameters(RTCRtpSendParameters) PASS RTCRtpSender interface: operation getParameters() PASS RTCRtpSender interface: operation replaceTrack(MediaStreamTrack?) PASS RTCRtpSender interface: operation setStreams(MediaStream...)
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt index 1610113b..1f6f3e5 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -2245,6 +2245,7 @@ getter form getter labels getter role + getter shadowRoot getter states getter validationMessage getter validity
diff --git a/third_party/shell-encryption/src/int256_test.cc b/third_party/shell-encryption/src/int256_test.cc index 01e8927..b1a88056 100644 --- a/third_party/shell-encryption/src/int256_test.cc +++ b/third_party/shell-encryption/src/int256_test.cc
@@ -368,22 +368,6 @@ EXPECT_EQ(x4, x3); } -TEST(Int256, DivideByZeroCheckFails) { - uint256 a = 0; - uint256 b = 0; - EXPECT_DEATH(a / b, "Division or mod by zero:"); - a = 123; - EXPECT_DEATH(a / b, "Division or mod by zero:"); -} - -TEST(Int256, ModByZeroCheckFails) { - uint256 a = 0; - uint256 b = 0; - EXPECT_DEATH(a % b, "Division or mod by zero:"); - a = 123; - EXPECT_DEATH(a % b, "Division or mod by zero:"); -} - TEST(Int256, DivideAndMod) { // a := q * b + r uint256 a, b, q, r;
diff --git a/third_party/zxcvbn-cpp/native-src/zxcvbn/frequency_lists.cpp b/third_party/zxcvbn-cpp/native-src/zxcvbn/frequency_lists.cpp index 17c73a67..a7adbe95a 100644 --- a/third_party/zxcvbn-cpp/native-src/zxcvbn/frequency_lists.cpp +++ b/third_party/zxcvbn-cpp/native-src/zxcvbn/frequency_lists.cpp
@@ -1,10 +1,9 @@ #include <zxcvbn/frequency_lists.hpp> #include <unordered_map> +#include <utility> #include "base/no_destructor.h" -#include "base/strings/string_split.h" -#include "base/strings/string_piece.h" namespace zxcvbn { @@ -16,16 +15,10 @@ return *ranked_dicts; } -} +} // namespace -bool ParseRankedDictionary(DictionaryTag tag, base::StringPiece str) { - RankedDict& dict = ranked_dicts()[tag]; - if (!dict.empty()) - return false; - - dict = build_ranked_dict(base::SplitStringPiece( - str, "\r\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY)); - return true; +void SetRankedDicts(std::unordered_map<DictionaryTag, RankedDict> dicts) { + ranked_dicts() = std::move(dicts); } RankedDicts convert_to_ranked_dicts(std::unordered_map<DictionaryTag, RankedDict> & ranked_dicts) {
diff --git a/third_party/zxcvbn-cpp/native-src/zxcvbn/frequency_lists.hpp b/third_party/zxcvbn-cpp/native-src/zxcvbn/frequency_lists.hpp index 191842fb..33da027 100644 --- a/third_party/zxcvbn-cpp/native-src/zxcvbn/frequency_lists.hpp +++ b/third_party/zxcvbn-cpp/native-src/zxcvbn/frequency_lists.hpp
@@ -38,7 +38,7 @@ using RankedDicts = std::unordered_map<DictionaryTag, const RankedDict &>; -bool ParseRankedDictionary(DictionaryTag tag, base::StringPiece str); +void SetRankedDicts(std::unordered_map<DictionaryTag, RankedDict> dicts); RankedDicts convert_to_ranked_dicts(std::unordered_map<DictionaryTag, RankedDict> & ranked_dicts); RankedDicts default_ranked_dicts();
diff --git a/third_party/zxcvbn-cpp/patches/dictionary_component.diff b/third_party/zxcvbn-cpp/patches/dictionary_component.diff index dd2195e1..b597bae 100644 --- a/third_party/zxcvbn-cpp/patches/dictionary_component.diff +++ b/third_party/zxcvbn-cpp/patches/dictionary_component.diff
@@ -1,5 +1,5 @@ diff --git a/third_party/zxcvbn-cpp/data-scripts/build_frequency_lists.py b/third_party/zxcvbn-cpp/data-scripts/build_frequency_lists.py -index d5504e073cb3..9be1391c5aa9 100755 +index d5504e0..9be1391 100755 --- a/third_party/zxcvbn-cpp/data-scripts/build_frequency_lists.py +++ b/third_party/zxcvbn-cpp/data-scripts/build_frequency_lists.py @@ -122,8 +122,7 @@ def to_kv(lst, lst_name): @@ -37,20 +37,19 @@ output_fn = output_coffee diff --git a/third_party/zxcvbn-cpp/native-src/zxcvbn/frequency_lists.cpp b/third_party/zxcvbn-cpp/native-src/zxcvbn/frequency_lists.cpp -index 4e4b72756e34..17c73a67bd0a 100644 +index 4e4b727..a7adbe9 100644 --- a/third_party/zxcvbn-cpp/native-src/zxcvbn/frequency_lists.cpp +++ b/third_party/zxcvbn-cpp/native-src/zxcvbn/frequency_lists.cpp -@@ -1,11 +1,33 @@ +@@ -1,11 +1,26 @@ #include <zxcvbn/frequency_lists.hpp> -#include <zxcvbn/_frequency_lists.hpp> - #include <unordered_map> - -+#include "base/no_destructor.h" -+#include "base/strings/string_split.h" -+#include "base/strings/string_piece.h" ++#include <utility> + ++#include "base/no_destructor.h" + namespace zxcvbn { +namespace { @@ -61,22 +60,16 @@ + return *ranked_dicts; +} + -+} ++} // namespace + -+bool ParseRankedDictionary(DictionaryTag tag, base::StringPiece str) { -+ RankedDict& dict = ranked_dicts()[tag]; -+ if (!dict.empty()) -+ return false; -+ -+ dict = build_ranked_dict(base::SplitStringPiece( -+ str, "\r\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY)); -+ return true; ++void SetRankedDicts(std::unordered_map<DictionaryTag, RankedDict> dicts) { ++ ranked_dicts() = std::move(dicts); +} + RankedDicts convert_to_ranked_dicts(std::unordered_map<DictionaryTag, RankedDict> & ranked_dicts) { RankedDicts build; -@@ -17,8 +39,7 @@ RankedDicts convert_to_ranked_dicts(std::unordered_map<DictionaryTag, RankedDict +@@ -17,8 +32,7 @@ RankedDicts convert_to_ranked_dicts(std::unordered_map<DictionaryTag, RankedDict } RankedDicts default_ranked_dicts() { @@ -87,10 +80,10 @@ - } diff --git a/third_party/zxcvbn-cpp/native-src/zxcvbn/frequency_lists.hpp b/third_party/zxcvbn-cpp/native-src/zxcvbn/frequency_lists.hpp -index c75ea30d5a91..191842fb530c 100644 +index c75ea30..634ecb2 100644 --- a/third_party/zxcvbn-cpp/native-src/zxcvbn/frequency_lists.hpp +++ b/third_party/zxcvbn-cpp/native-src/zxcvbn/frequency_lists.hpp -@@ -2,15 +2,24 @@ +@@ -2,7 +2,6 @@ #define __ZXCVBN__FREQUENCY_LISTS_HPP #include <zxcvbn/frequency_lists_common.hpp> @@ -98,10 +91,8 @@ #include <unordered_map> - #include <cstdint> +@@ -10,7 +9,15 @@ -+#include "base/strings/string_piece.h" -+ namespace zxcvbn { -using DictionaryTag = _frequency_lists::DictionaryTag; @@ -117,11 +108,11 @@ } -@@ -29,6 +38,8 @@ namespace zxcvbn { +@@ -29,6 +36,8 @@ namespace zxcvbn { using RankedDicts = std::unordered_map<DictionaryTag, const RankedDict &>; -+bool ParseRankedDictionary(DictionaryTag tag, base::StringPiece str); ++void SetRankedDicts(std::unordered_map<DictionaryTag, RankedDict> dicts); + RankedDicts convert_to_ranked_dicts(std::unordered_map<DictionaryTag, RankedDict> & ranked_dicts); RankedDicts default_ranked_dicts();
diff --git a/third_party/zxcvbn-cpp/test/matching_unittest.cc b/third_party/zxcvbn-cpp/test/matching_unittest.cc index 4def546..07a4913 100644 --- a/third_party/zxcvbn-cpp/test/matching_unittest.cc +++ b/third_party/zxcvbn-cpp/test/matching_unittest.cc
@@ -304,7 +304,7 @@ { // default dictionaries - ParseRankedDictionary(DictionaryTag::US_TV_AND_FILM, "wow"); + SetRankedDicts({{DictionaryTag::US_TV_AND_FILM, {{"wow", 1}}}}); std::vector<Match> matches = dictionary_match("wow", default_ranked_dicts()); EXPECT_THAT(matches, ElementsAre(ExpectedDictionaryMatch{ @@ -319,7 +319,7 @@ { // matches with provided user input dictionary - ParseRankedDictionary(DictionaryTag::USER_INPUTS, "foo\nbar"); + SetRankedDicts({{DictionaryTag::USER_INPUTS, {{"foo", 1}, {"bar", 2}}}}); std::vector<Match> matches = dictionary_match("foobar", default_ranked_dicts()); EXPECT_THAT(matches, ElementsAre( @@ -1004,7 +1004,8 @@ TEST(ZxcvbnTest, Omnimatch) { EXPECT_THAT(omnimatch(""), IsEmpty()); - ParseRankedDictionary(DictionaryTag::ENGLISH_WIKIPEDIA, "rosebud\nmaelstrom"); + SetRankedDicts( + {{DictionaryTag::ENGLISH_WIKIPEDIA, {{"rosebud", 1}, {"maelstrom", 2}}}}); std::string password = "r0sebudmaelstrom11/20/91aaaa"; std::vector<Match> matches = omnimatch(password);
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index e761565..c08c2b1d 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -94,15 +94,15 @@ 'android-cronet-x86-dbg': 'android_cronet_debug_static_bot_x86', 'android-cronet-x86-rel': 'android_cronet_release_bot_minimal_symbols_x86', 'android-incremental-dbg': 'android_incremental_debug_bot', - 'android-lollipop-arm-rel': 'android_release_bot_minimal_symbols_webview_google', + 'android-lollipop-arm-rel': 'android_release_bot_minimal_symbols_fastbuild_webview_google', # This bot must use the gpu_tests mixin to match 'Android FYI Release (Nexus 5X)' # on the chromium.gpu waterfall, which it mirrors via trybots.pyl. - 'android-marshmallow-arm64-rel': 'gpu_tests_android_release_bot_minimal_symbols_arm64', + 'android-marshmallow-arm64-rel': 'gpu_tests_android_release_bot_minimal_symbols_arm64_fastbuild', 'android-marshmallow-x86-rel': 'android_release_bot_minimal_symbols_x86_fastbuild_resource_whitelisting_webview_google', 'android-nougat-arm64-rel': 'android_release_bot_minimal_symbols_arm64_fastbuild_webview_google', - 'android-pie-arm64-rel': 'android_release_bot_minimal_symbols_arm64_webview_google_fastbuild', + 'android-pie-arm64-rel': 'android_release_bot_minimal_symbols_arm64_webview_google', 'android-pie-x86-rel': 'android_release_bot_minimal_symbols_x86_fastbuild_webview_google', 'android-10-arm64-rel': 'android_release_bot_minimal_symbols_arm64_fastbuild_webview_google', }, @@ -302,6 +302,7 @@ 'mac-upload-perfetto': 'release_bot', 'win-annotator-rel': 'release_bot', 'win-celab-builder-rel': 'release_bot_minimal_symbols', + 'win-omaha-builder-rel': 'omaha_release_bot', 'win-pixel-builder-rel': 'release_bot', 'win-upload-perfetto': 'release_bot', 'win10-code-coverage': 'clang_code_coverage', @@ -550,10 +551,10 @@ 'chromium.dev': { # This should be the same with 'android-lollipop-arm-rel'. - 'android-lollipop-arm-rel-swarming': 'android_release_bot_minimal_symbols_webview_google', + 'android-lollipop-arm-rel-swarming': 'android_release_bot_minimal_symbols_fastbuild_webview_google', # This should be the same with 'android-marshmallow-arm64-rel'. - 'android-marshmallow-arm64-rel-swarming': 'gpu_tests_android_release_bot_minimal_symbols_arm64', + 'android-marshmallow-arm64-rel-swarming': 'gpu_tests_android_release_bot_minimal_symbols_arm64_fastbuild', # These should be the same with 'Linux Builder'. 'linux-rel-swarming': 'gpu_tests_release_bot', @@ -707,7 +708,7 @@ # TODO(crbug/597596): Switch this back to debug_trybot when cronet's # shared library loading is fixed. 'android-cronet-arm-dbg': 'android_cronet_debug_static_bot_arm_no_neon', - 'android-lollipop-arm-rel': 'android_release_trybot_webview_google', + 'android-lollipop-arm-rel': 'android_release_trybot_fastbuild_webview_google', 'android-marshmallow-arm64-rel': 'gpu_tests_android_release_trybot_arm64_resource_whitelisting_fastbuild_java_coverage', 'android-marshmallow-x86-fyi-rel': 'android_release_trybot_x86_fastbuild_resource_whitelisting_webview_google', 'android-marshmallow-x86-rel': 'android_release_trybot_x86_fastbuild_resource_whitelisting_webview_google', @@ -1259,15 +1260,9 @@ 'strip_debug_info', 'webview_google', ], - 'android_release_bot_minimal_symbols_arm64_webview_google_fastbuild': [ - 'android', 'release_bot', 'minimal_symbols', 'arm64', - 'strip_debug_info', 'webview_google', 'android_fastbuild', - 'android_no_proguard', - ], - - 'android_release_bot_minimal_symbols_webview_google': [ + 'android_release_bot_minimal_symbols_fastbuild_webview_google': [ 'android', 'release_bot', 'minimal_symbols', - 'strip_debug_info', 'webview_google', + 'strip_debug_info', 'android_fastbuild', 'webview_google', ], 'android_release_bot_minimal_symbols_x86_fastbuild_resource_whitelisting_webview_google': [ @@ -1309,9 +1304,9 @@ 'use_clang_coverage', 'partial_code_coverage_instrumentation', ], - 'android_release_trybot_webview_google': [ - 'android', 'release_trybot', 'strip_debug_info', 'android_no_proguard', - 'webview_google', + 'android_release_trybot_fastbuild_webview_google': [ + 'android', 'release_trybot', 'strip_debug_info', 'android_fastbuild', + 'android_no_proguard', 'webview_google', ], 'android_release_trybot_x86_fastbuild_resource_whitelisting_webview_google': [ @@ -1820,9 +1815,10 @@ 'gpu_fyi_tests', 'release_trybot', 'x86', ], - 'gpu_tests_android_release_bot_minimal_symbols_arm64': [ + 'gpu_tests_android_release_bot_minimal_symbols_arm64_fastbuild': [ 'gpu_tests', 'android', 'release_bot', 'minimal_symbols', 'arm64', - 'resource_whitelisting', 'static_angle', 'webview_google', + 'resource_whitelisting', 'static_angle', 'android_fastbuild', 'webview_google', + 'android_no_proguard', ], 'gpu_tests_android_release_bot_minimal_symbols_arm64_fastbuild_java_coverage': [ @@ -1854,6 +1850,7 @@ 'gpu_tests_android_release_trybot_arm64_resource_whitelisting_fastbuild_java_coverage': [ 'gpu_tests', 'android', 'release_trybot', 'arm64', 'static_angle', 'resource_whitelisting', 'android_fastbuild', 'webview_google', + 'android_no_proguard', 'use_java_coverage', 'partial_code_coverage_instrumentation', ], @@ -2189,6 +2186,10 @@ 'official_optimize_goma_trybot', ], + 'omaha_release_bot': [ + 'omaha_on_win_mac', 'release', + ], + 'ozone_linux_release_bot': [ 'ozone_linux', 'release_bot', ], @@ -2861,6 +2862,10 @@ 'mixins': ['official_optimize_goma', 'minimal_symbols', 'dcheck_always_on'], }, + 'omaha_on_win_mac': { + 'gn_args': 'is_google_branded=true', + }, + 'optimize_for_fuzzing': { 'gn_args': 'optimize_for_fuzzing=true', },
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 48373a8..0afa40d7 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -28713,6 +28713,7 @@ <int value="3375" label="V8RTCRtpTransceiver_Stop_Method"/> <int value="3376" label="SecurePaymentConfirmation"/> <int value="3377" label="CSSInvalidVariableUnset"/> + <int value="3378" label="ElementInternalsShadowRoot"/> </enum> <enum name="FeaturePolicyAllowlistType"> @@ -37309,6 +37310,7 @@ <int value="7" label="Share"/> <int value="8" label="Open all in New Tabs"/> <int value="9" label="Hide"/> + <int value="10" label="Move"/> </enum> <enum name="IOSMenuScenario"> @@ -37318,6 +37320,7 @@ <int value="3" label="RecentTabs Entry"/> <int value="4" label="ContentSuggestions Entry"/> <int value="5" label="RecentTabs Header"/> + <int value="6" label="Bookmark Folder"/> </enum> <enum name="IOSNTPImpression"> @@ -47318,6 +47321,16 @@ <int value="2" label="ntdll.dll"/> </enum> +<enum name="MojoInterfaceName"> + <int value="-1403116593" label="content.mojom.FrameHost"/> + <int value="-1370606112" label="blink.mojom.LocalFrameHost"/> + <int value="-1324568928" label="blink.mojom.LocalMainFrameHost"/> + <int value="-1001040796" label="blink.mojom.ManifestUrlChangeObserver"/> + <int value="163955581" label="blink.mojom.PortalHost"/> + <int value="374886440" label="content.mojom.Echo"/> + <int value="1755985492" label="content.mojom.RenderAccessibilityHost"/> +</enum> + <enum name="MojoMachPortRelayBrokerError"> <int value="0" label="SUCCESS"> The Mach port was successfully sent or received. @@ -54487,6 +54500,9 @@ <int value="7" label="Reauth required"> Re-authenticaion for filling passwords is required. </int> + <int value="8" label="Password is already filled"> + Password field is already filled in and it doesn't look like a placeholder. + </int> </enum> <enum name="PasswordManagerHttpCredentialType"> @@ -54976,10 +54992,11 @@ <enum name="PasswordScriptsFetcherParsingResult"> <int value="0" label="No response from server"/> - <int value="1" label="Invalid JSON string"/> - <int value="2" label="Not a JSON dictionary"/> + <int value="1" label="Invalid JSON string - deprecated"/> + <int value="2" label="Not a JSON dictionary - deprecated"/> <int value="3" label="Invalid URLs found"/> <int value="4" label="OK"/> + <int value="5" label="Invalid JSON (either syntactically or structurally)"/> </enum> <enum name="PasswordStoreChange"> @@ -57990,6 +58007,7 @@ <int value="15" label="Add new profile button"/> <int value="16" label="Sync settings(sync on) button"/> <int value="17" label="Edit profile button"/> + <int value="18" label="Create incognito shortcut button"/> </enum> <enum name="ProfileNameState"> @@ -61645,6 +61663,7 @@ <int value="4" label="DISABLED_BY_EXTENSION"/> <int value="5" label="ENABLED_STANDARD"/> <int value="6" label="ENABLED_ENHANCED"/> + <int value="7" label="ENABLED_STANDARD_AVAILABLE_ENHANCED"/> </enum> <enum name="SafetyCheckUpdateStatus"> @@ -65101,11 +65120,15 @@ <enum name="SigninSSOIdentityListRequestCacheState"> <int value="0" - label="SSO identity cache is stale, the identity list is synchronously - fetched."/> + label="SSO identity cache is stale, M85: the identity list is + synchronously fetched and then returned, M86: the stale identity + list is returned."/> <int value="1" - label="SSO identity cache is valid, the identity list from the cache is + label="SSO identity cache is valid, the valid identity list is returned."/> + <int value="2" + label="SSO identity cache is not populated, the identity list is + synchronously fetched and then returned."/> </enum> <enum name="SigninSSOWKWebViewGetAllCookiesRequest">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 9a99973..1bb1737 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -17749,6 +17749,27 @@ </summary> </histogram> +<histogram + name="BackForwardCache.UnexpectedRendererToBrowserMessage.InterfaceName" + enum="MojoInterfaceName" expires_after="2021-01-01"> + <owner>carlscab@google.com</owner> + <owner>bfcache-dev@chromium.org</owner> + <summary> + Hash (base::HashMetricName) of a mojo interface name. + + A sample is recorded for every message the browser receives from a renderer + for a page that is in the back-forward cache. Logging can be disabled via + the back-forward cache feature parameter + "message_handling_when_cached". + + Renderers should not be sending messages back to the browser for pages that + are in the back-forward cache. Eventually we will be killing such renderers + (as we could assume that it is misbehaving because it got compromised). But + first we must make sure that we are not sending messages by mistake (i.e. + bugs in the renderer). + </summary> +</histogram> + <histogram base="true" name="BackgroundFetch.EventDispatchFailure.Dispatch" enum="ServiceWorkerStatusCode" expires_after="2021-06-30"> <!-- Name completed by histogram_suffixes name="BackgroundFetchEvents" --> @@ -28465,7 +28486,7 @@ <histogram name="Compositing.CopyFromSurfaceTimeSynchronous" units="ms" expires_after="2016-04-29"> <obsolete> - Removed 04/2016 as doesn't have data nor owner. + Made obsolete 04/2016. Logging removed 08/2020. </obsolete> <owner>Please list the metric's owners. Add more owner tags as needed.</owner> <summary> @@ -214478,6 +214499,8 @@ <histogram_suffixes name="SigninSSOIdentityListRequestDurationCacheState" separator="."> + <suffix name="NotPopulated" + label="The SSOAuth identity list is not populated."/> <suffix name="Stale" label="The SSOAuth identity list is stale."/> <suffix name="Valid" label="The SSOAuth identity list is valid."/> <affected-histogram name="Signin.SSOIdentityListRequest.Duration"/>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index 6c44d5ce..c116905 100644 --- a/tools/perf/core/perfetto_binary_roller/binary_deps.json +++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -5,12 +5,12 @@ "remote_path": "perfetto_binaries/trace_processor_shell/win/dbee93ac203d9269fe93c1ff1e48eba6148e542c/trace_processor_shell.exe" }, "mac": { - "hash": "27f63277ace856aad218ce2806fcd2a3d5ca0839", - "remote_path": "perfetto_binaries/trace_processor_shell/mac/dbee93ac203d9269fe93c1ff1e48eba6148e542c/trace_processor_shell" + "hash": "5653df7850d5d9418d72896ee3b06ecc5d10a5f5", + "remote_path": "perfetto_binaries/trace_processor_shell/mac/e1360ddcec9e7e29e6d0739fbe360374ab66b712/trace_processor_shell" }, "linux": { - "hash": "d1080003a68b2a808256bed9d034529030f1aca9", - "remote_path": "perfetto_binaries/trace_processor_shell/linux/dbee93ac203d9269fe93c1ff1e48eba6148e542c/trace_processor_shell" + "hash": "35f5be0660c5b16796877db5a64765d7b99a3daf", + "remote_path": "perfetto_binaries/trace_processor_shell/linux/e1360ddcec9e7e29e6d0739fbe360374ab66b712/trace_processor_shell" } }, "power_profile.sql": {
diff --git a/ui/base/clipboard/clipboard_constants.cc b/ui/base/clipboard/clipboard_constants.cc index e435dd2..3ea7842 100644 --- a/ui/base/clipboard/clipboard_constants.cc +++ b/ui/base/clipboard/clipboard_constants.cc
@@ -10,12 +10,15 @@ const char kMimeTypeTextUtf8[] = "text/plain;charset=utf-8"; const char kMimeTypeURIList[] = "text/uri-list"; const char kMimeTypeMozillaURL[] = "text/x-moz-url"; +// Unstandardized format for downloading files after drop events. Now only +// works in Windows, but used to also work in Linux and MacOS. +// See https://crbug.com/860557 and https://crbug.com/425170. const char kMimeTypeDownloadURL[] = "downloadurl"; const char kMimeTypeHTML[] = "text/html"; const char kMimeTypeRTF[] = "text/rtf"; const char kMimeTypePNG[] = "image/png"; - #if !defined(OS_APPLE) +// TODO(dcheng): This name is temporary. See crbug.com/106449. const char kMimeTypeWebCustomData[] = "chromium/x-web-custom-data"; const char kMimeTypeWebkitSmartPaste[] = "chromium/x-webkit-paste"; const char kMimeTypePepperCustomData[] = "chromium/x-pepper-custom-data";
diff --git a/ui/base/clipboard/clipboard_constants.h b/ui/base/clipboard/clipboard_constants.h index bdc32ecba..d749751 100644 --- a/ui/base/clipboard/clipboard_constants.h +++ b/ui/base/clipboard/clipboard_constants.h
@@ -24,9 +24,6 @@ COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES) extern const char kMimeTypeText[]; COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES) extern const char kMimeTypeTextUtf8[]; COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES) extern const char kMimeTypeURIList[]; -// Unstandardized format for downloading files after drop events. Now only -// works in Windows, but used to also work in Linux and MacOS. -// See https://crbug.com/860557 and https://crbug.com/425170. COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES) extern const char kMimeTypeDownloadURL[]; COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES) @@ -34,19 +31,7 @@ COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES) extern const char kMimeTypeHTML[]; COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES) extern const char kMimeTypeRTF[]; COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES) extern const char kMimeTypePNG[]; - -// Linux-specific MIME type constants (also used in Fuchsia). -#if defined(OS_LINUX) || defined(OS_FUCHSIA) -COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES) -constexpr char kMimeTypeLinuxUtf8String[] = "UTF8_STRING"; -COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES) -constexpr char kMimeTypeLinuxString[] = "STRING"; -COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES) -constexpr char kMimeTypeLinuxText[] = "TEXT"; -#endif // defined(OS_LINUX) || defined(OS_FUCHSIA) - #if !defined(OS_APPLE) -// TODO(dcheng): This name is temporary. See crbug.com/106449. COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES) extern const char kMimeTypeWebCustomData[]; COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES)
diff --git a/ui/base/clipboard/clipboard_ozone.cc b/ui/base/clipboard/clipboard_ozone.cc index 5f46a62..4db9efa6 100644 --- a/ui/base/clipboard/clipboard_ozone.cc +++ b/ui/base/clipboard/clipboard_ozone.cc
@@ -38,6 +38,12 @@ namespace { +// TODO(crbug.com/1105892): those three constants can be found in a few other +// places. Perhaps it would be worth finding some common place for them? +constexpr char kMimeTypeX11String[] = "STRING"; +constexpr char kMimeTypeX11Text[] = "TEXT"; +constexpr char kMimeTypeX11Utf8String[] = "UTF8_STRING"; + // The amount of time to wait for a request to complete before aborting it. constexpr base::TimeDelta kRequestTimeout = base::TimeDelta::FromSeconds(10); @@ -558,8 +564,8 @@ void ClipboardOzone::WriteText(const char* text_data, size_t text_len) { std::vector<uint8_t> data(text_data, text_data + text_len); async_clipboard_ozone_->InsertData( - std::move(data), {kMimeTypeText, kMimeTypeLinuxText, kMimeTypeLinuxString, - kMimeTypeTextUtf8, kMimeTypeLinuxUtf8String}); + std::move(data), {kMimeTypeText, kMimeTypeX11Text, kMimeTypeX11String, + kMimeTypeTextUtf8, kMimeTypeX11Utf8String}); } void ClipboardOzone::WriteHTML(const char* markup_data,
diff --git a/ui/base/clipboard/clipboard_test_template.h b/ui/base/clipboard/clipboard_test_template.h index f0cf758..61b7dfa 100644 --- a/ui/base/clipboard/clipboard_test_template.h +++ b/ui/base/clipboard/clipboard_test_template.h
@@ -27,7 +27,6 @@ #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" -#include "build/chromecast_buildflags.h" #include "testing/gmock/include/gmock/gmock-matchers.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -168,11 +167,6 @@ EXPECT_THAT(this->GetAvailableTypes(ClipboardBuffer::kCopyPaste), Contains(ASCIIToUTF16(kMimeTypeText))); -#if defined(USE_OZONE) && !defined(OS_CHROMEOS) && !defined(OS_FUCHSIA) && \ - !BUILDFLAG(IS_CHROMECAST) - EXPECT_THAT(this->GetAvailableTypes(ClipboardBuffer::kCopyPaste), - Contains(ASCIIToUTF16(kMimeTypeTextUtf8))); -#endif EXPECT_TRUE(this->clipboard().IsFormatAvailable( ClipboardFormatType::GetPlainTextType(), ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr)); @@ -248,13 +242,10 @@ } #endif // !defined(OS_ANDROID) -#if defined(OS_LINUX) && !defined(OS_CHROMEOS) +// TODO(msisov, tonikitoo): Enable test once ClipboardOzone implements +// selection support. https://crbug.com/911992 +#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && !defined(USE_OZONE) TYPED_TEST(ClipboardTest, MultipleBufferTest) { -#if defined(USE_OZONE) - if (!this->clipboard().IsSelectionBufferAvailable()) - return; -#endif - base::string16 text(ASCIIToUTF16("Standard")), text_result; base::string16 markup(ASCIIToUTF16("<string>Selection</string>")); std::string url("http://www.example.com/"), url_result;
diff --git a/ui/base/clipboard/clipboard_x11.cc b/ui/base/clipboard/clipboard_x11.cc index fff2b73e..f5119b6 100644 --- a/ui/base/clipboard/clipboard_x11.cc +++ b/ui/base/clipboard/clipboard_x11.cc
@@ -758,9 +758,9 @@ base::RefCountedString::TakeString(&str)); x11_details_->InsertMapping(kMimeTypeText, mem); - x11_details_->InsertMapping(kMimeTypeLinuxText, mem); - x11_details_->InsertMapping(kMimeTypeLinuxString, mem); - x11_details_->InsertMapping(kMimeTypeLinuxUtf8String, mem); + x11_details_->InsertMapping(kText, mem); + x11_details_->InsertMapping(kString, mem); + x11_details_->InsertMapping(kUtf8String, mem); } void ClipboardX11::WriteHTML(const char* markup_data,
diff --git a/ui/base/x/selection_utils.cc b/ui/base/x/selection_utils.cc index 72e02bc..34533b9 100644 --- a/ui/base/x/selection_utils.cc +++ b/ui/base/x/selection_utils.cc
@@ -19,13 +19,19 @@ namespace ui { +const char kString[] = "STRING"; +const char kText[] = "TEXT"; +const char kTextPlain[] = "text/plain"; +const char kTextPlainUtf8[] = "text/plain;charset=utf-8"; +const char kUtf8String[] = "UTF8_STRING"; + std::vector<x11::Atom> GetTextAtomsFrom() { std::vector<x11::Atom> atoms; - atoms.push_back(gfx::GetAtom(kMimeTypeLinuxUtf8String)); - atoms.push_back(gfx::GetAtom(kMimeTypeLinuxString)); - atoms.push_back(gfx::GetAtom(kMimeTypeLinuxText)); - atoms.push_back(gfx::GetAtom(kMimeTypeText)); - atoms.push_back(gfx::GetAtom(kMimeTypeTextUtf8)); + atoms.push_back(gfx::GetAtom(kUtf8String)); + atoms.push_back(gfx::GetAtom(kString)); + atoms.push_back(gfx::GetAtom(kText)); + atoms.push_back(gfx::GetAtom(kTextPlain)); + atoms.push_back(gfx::GetAtom(kTextPlainUtf8)); return atoms; } @@ -170,12 +176,11 @@ } std::string SelectionData::GetText() const { - if (type_ == gfx::GetAtom(kMimeTypeLinuxUtf8String) || - type_ == gfx::GetAtom(kMimeTypeLinuxText) || - type_ == gfx::GetAtom(kMimeTypeTextUtf8)) { + if (type_ == gfx::GetAtom(kUtf8String) || type_ == gfx::GetAtom(kText) || + type_ == gfx::GetAtom(kTextPlainUtf8)) { return RefCountedMemoryToString(memory_); - } else if (type_ == gfx::GetAtom(kMimeTypeLinuxString) || - type_ == gfx::GetAtom(kMimeTypeText)) { + } else if (type_ == gfx::GetAtom(kString) || + type_ == gfx::GetAtom(kTextPlain)) { std::string result; base::ConvertToUtf8AndNormalize(RefCountedMemoryToString(memory_), base::kCodepageLatin1, &result);
diff --git a/ui/base/x/selection_utils.h b/ui/base/x/selection_utils.h index 3e90ed3..9ca25b3 100644 --- a/ui/base/x/selection_utils.h +++ b/ui/base/x/selection_utils.h
@@ -15,6 +15,10 @@ namespace ui { class SelectionData; +COMPONENT_EXPORT(UI_BASE_X) extern const char kString[]; +COMPONENT_EXPORT(UI_BASE_X) extern const char kText[]; +COMPONENT_EXPORT(UI_BASE_X) extern const char kUtf8String[]; + // Returns a list of all text atoms that we handle. COMPONENT_EXPORT(UI_BASE_X) std::vector<x11::Atom> GetTextAtomsFrom();
diff --git a/ui/base/x/x11_os_exchange_data_provider.cc b/ui/base/x/x11_os_exchange_data_provider.cc index ef6463f..e7a374f 100644 --- a/ui/base/x/x11_os_exchange_data_provider.cc +++ b/ui/base/x/x11_os_exchange_data_provider.cc
@@ -97,9 +97,9 @@ base::RefCountedString::TakeString(&utf8)); format_map_.Insert(gfx::GetAtom(kMimeTypeText), mem); - format_map_.Insert(gfx::GetAtom(kMimeTypeLinuxText), mem); - format_map_.Insert(gfx::GetAtom(kMimeTypeLinuxString), mem); - format_map_.Insert(gfx::GetAtom(kMimeTypeLinuxUtf8String), mem); + format_map_.Insert(gfx::GetAtom(kText), mem); + format_map_.Insert(gfx::GetAtom(kString), mem); + format_map_.Insert(gfx::GetAtom(kUtf8String), mem); } void XOSExchangeDataProvider::SetURL(const GURL& url,
diff --git a/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.cc b/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.cc index 339cf87..c60c35e 100644 --- a/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.cc +++ b/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.cc
@@ -807,9 +807,18 @@ TRACE_EVENT0("wayland", "WaylandBufferManagerHost::CommitOverlays"); DCHECK(error_message_.empty()); + + if (widget == gfx::kNullAcceleratedWidget) { + error_message_ = "Invalid widget."; + TerminateGpuProcess(); + } WaylandWindow* window = connection_->wayland_window_manager()->GetWindow(widget); - DCHECK(window); + // In tab dragging, window may have been destroyed when buffers reach here. We + // omit buffer commits and OnSubmission, because the corresponding buffer + // queue in gpu process should be destroyed soon. + if (!window) + return; window->CommitOverlays(overlays); }
diff --git a/ui/ozone/platform/wayland/host/wayland_data_offer_base.cc b/ui/ozone/platform/wayland/host/wayland_data_offer_base.cc index cbdd82a..8656f41 100644 --- a/ui/ozone/platform/wayland/host/wayland_data_offer_base.cc +++ b/ui/ozone/platform/wayland/host/wayland_data_offer_base.cc
@@ -9,6 +9,14 @@ namespace ui { +namespace { + +const char kString[] = "STRING"; +const char kText[] = "TEXT"; +const char kUtf8String[] = "UTF8_STRING"; + +} // namespace + WaylandDataOfferBase::WaylandDataOfferBase() = default; WaylandDataOfferBase::~WaylandDataOfferBase() = default; @@ -18,10 +26,9 @@ if (std::any_of(mime_types_.begin(), mime_types_.end(), [](const std::string& mime_type) { - return mime_type == kMimeTypeLinuxString || - mime_type == kMimeTypeLinuxText || + return mime_type == kString || mime_type == kText || mime_type == kMimeTypeTextUtf8 || - mime_type == kMimeTypeLinuxUtf8String; + mime_type == kUtf8String; })) { mime_types_.push_back(kMimeTypeText); text_plain_mime_type_inserted_ = true;
diff --git a/ui/ozone/platform/x11/x11_clipboard_ozone.cc b/ui/ozone/platform/x11/x11_clipboard_ozone.cc index 16a0476..d4fed35 100644 --- a/ui/ozone/platform/x11/x11_clipboard_ozone.cc +++ b/ui/ozone/platform/x11/x11_clipboard_ozone.cc
@@ -25,21 +25,23 @@ const char kChromeSelection[] = "CHROME_SELECTION"; const char kClipboard[] = "CLIPBOARD"; +const char kString[] = "STRING"; const char kTargets[] = "TARGETS"; const char kTimestamp[] = "TIMESTAMP"; +const char kUtf8String[] = "UTF8_STRING"; // Helps to allow conversions for text/plain[;charset=utf-8] <=> [UTF8_]STRING. void ExpandTypes(std::vector<std::string>* list) { bool has_mime_type_text = Contains(*list, ui::kMimeTypeText); - bool has_string = Contains(*list, kMimeTypeLinuxString); + bool has_string = Contains(*list, kString); bool has_mime_type_utf8 = Contains(*list, kMimeTypeTextUtf8); - bool has_utf8_string = Contains(*list, kMimeTypeLinuxUtf8String); + bool has_utf8_string = Contains(*list, kUtf8String); if (has_mime_type_text && !has_string) - list->push_back(kMimeTypeLinuxString); + list->push_back(kString); if (has_string && !has_mime_type_text) list->push_back(ui::kMimeTypeText); if (has_mime_type_utf8 && !has_utf8_string) - list->push_back(kMimeTypeLinuxUtf8String); + list->push_back(kUtf8String); if (has_utf8_string && !has_mime_type_utf8) list->push_back(kMimeTypeTextUtf8); } @@ -161,11 +163,9 @@ std::string key = target_name; // Allow conversions for text/plain[;charset=utf-8] <=> [UTF8_]STRING. - if (key == kMimeTypeLinuxUtf8String && - !Contains(offer_data_map, kMimeTypeLinuxUtf8String)) { + if (key == kUtf8String && !Contains(offer_data_map, kUtf8String)) { key = kMimeTypeTextUtf8; - } else if (key == kMimeTypeLinuxString && - !Contains(offer_data_map, kMimeTypeLinuxString)) { + } else if (key == kString && !Contains(offer_data_map, kString)) { key = kMimeTypeText; } auto it = offer_data_map.find(key); @@ -314,9 +314,9 @@ std::string target = selection_state.data_mime_type; if (!Contains(selection_state.mime_types, target)) { if (target == kMimeTypeText) { - target = kMimeTypeLinuxString; + target = kString; } else if (target == kMimeTypeTextUtf8) { - target = kMimeTypeLinuxUtf8String; + target = kUtf8String; } }