diff --git a/DEPS b/DEPS index 9a34191..9850e9d 100644 --- a/DEPS +++ b/DEPS
@@ -116,11 +116,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': 'd7157b2ccf53febde957a2c229e5f59fbd4f5cf2', + 'skia_revision': '44764000b49cddcec8b6733375078404f97a00fc', # 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': 'ebedb7ebb3f46fb54efc4601bbd5580989cb575f', + 'v8_revision': 'c10b42544e3c97ecb259ede63fa2ccb78c8396dc', # 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. @@ -128,7 +128,7 @@ # 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': 'd1a55e393e65601ba26e2d76bd46a12fc6bc4e3e', + 'angle_revision': 'ccad5e333472572ecda3c0ec80a702c7dcc5e95f', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling build tools # and whatever else without interference from each other. @@ -140,7 +140,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': 'a89ef2b38df07e4e19c8f43e8f58e265c190336b', + 'pdfium_revision': '2585eafdcba3fff4b6357f133cd9a74e8d4e84a5', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling openmax_dl # and whatever else without interference from each other. @@ -176,7 +176,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': '6b8b30c8a1b138f083cb474871e500662397b3f2', + 'catapult_revision': '4925b069e1cfc5b50ead614e28d3367bfcd72349', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -224,7 +224,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': '5beeee15c175a15e904ad7ce3df37d1d0d55bd06', + 'spv_tools_revision': 'a6150a3fe778f62ac85b9fc8a2547c69e7607337', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -655,7 +655,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'd5fa47311da1d0457f3ba3c12a0480bcb77449af', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '88c15c341d97a21a2fe5511bc9f91d207cd570f4', 'condition': 'checkout_linux', }, @@ -946,7 +946,7 @@ # Minizip library. Used on Chrome OS. 'src/third_party/minizip/src': { - 'url': Var('chromium_git') + '/external/github.com/nmoinvaz/minizip' + '@' + 'c47090678d687742eddc60d07c5430279af416d8', + 'url': Var('chromium_git') + '/external/github.com/nmoinvaz/minizip' + '@' + '4d4c9db5b019e71b4a40fb41ab21fb47de12ae69', 'condition': 'checkout_linux', }, @@ -1166,7 +1166,7 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '0d55c887e92b645f6effe753528323ab2ffd94c2', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + 'fdc635d2a8ffceeec44b57a83c9ca102fba1a88f', + Var('webrtc_git') + '/src.git' + '@' + '83aa5ace99a52bbe85055d89ed6837930f8d1f2c', 'src/third_party/xdg-utils': { 'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d', @@ -1197,7 +1197,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@8eae8558004a4404a5f6ea5437fdf5b4cc92ac55', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@e04de3408e65f698419363302c17410eb78bb42d', 'condition': 'checkout_src_internal', },
diff --git a/android_webview/java/src/org/chromium/android_webview/AwPicture.java b/android_webview/java/src/org/chromium/android_webview/AwPicture.java index c8c8d3b5..8993543 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwPicture.java +++ b/android_webview/java/src/org/chromium/android_webview/AwPicture.java
@@ -68,7 +68,6 @@ nativeDraw(mNativeAwPicture, canvas); } - @Override @SuppressWarnings("deprecation") public void writeToStream(OutputStream stream) { unsupportedOperation();
diff --git a/android_webview/renderer/aw_content_renderer_client.cc b/android_webview/renderer/aw_content_renderer_client.cc index 7e76648..02354579 100644 --- a/android_webview/renderer/aw_content_renderer_client.cc +++ b/android_webview/renderer/aw_content_renderer_client.cc
@@ -195,15 +195,12 @@ content::RenderFrame* render_frame, const blink::WebURLRequest& failed_request, const blink::WebURLError& error, - std::string* error_html, - base::string16* error_description) { + std::string* error_html) { std::string err; if (error.reason() == net::ERR_TEMPORARILY_THROTTLED) err = kThrottledErrorDescription; else err = net::ErrorToString(error.reason()); - if (error_description) - *error_description = base::ASCIIToUTF16(err); if (!error_html) return;
diff --git a/android_webview/renderer/aw_content_renderer_client.h b/android_webview/renderer/aw_content_renderer_client.h index e15b497..9c6906e 100644 --- a/android_webview/renderer/aw_content_renderer_client.h +++ b/android_webview/renderer/aw_content_renderer_client.h
@@ -40,8 +40,7 @@ void PrepareErrorPage(content::RenderFrame* render_frame, const blink::WebURLRequest& failed_request, const blink::WebURLError& error, - std::string* error_html, - base::string16* error_description) override; + std::string* error_html) override; unsigned long long VisitedLinkHash(const char* canonical_url, size_t length) override; bool IsLinkVisited(unsigned long long link_hash) override;
diff --git a/android_webview/test/BUILD.gn b/android_webview/test/BUILD.gn index 1a21e3a..89ab61a 100644 --- a/android_webview/test/BUILD.gn +++ b/android_webview/test/BUILD.gn
@@ -17,23 +17,26 @@ ] } -group("webview_cts_tests") { - _py_files = read_file("//android_webview/tools/run_cts.pydeps", "list lines") - deps = [ - "//android_webview:system_webview_apk", - ] +if (public_android_sdk) { + group("webview_cts_tests") { + _py_files = + read_file("//android_webview/tools/run_cts.pydeps", "list lines") + deps = [ + "//android_webview:system_webview_apk", + ] - data_deps = [ - "//build/android:logdog_wrapper_py", - "//build/android:test_runner_py", - ] + data_deps = [ + "//build/android:logdog_wrapper_py", + "//build/android:test_runner_py", + ] - # Filter out comments. - set_sources_assignment_filter([ "#*" ]) - sources = _py_files + # Filter out comments. + set_sources_assignment_filter([ "#*" ]) + sources = _py_files - data = sources - data += [ "//android_webview/tools/cts_config/" ] + data = sources + data += [ "//android_webview/tools/cts_config/" ] + } } android_apk("webview_instrumentation_apk") {
diff --git a/ash/login/ui/lock_contents_view.cc b/ash/login/ui/lock_contents_view.cc index 43be2f3..20eb722 100644 --- a/ash/login/ui/lock_contents_view.cc +++ b/ash/login/ui/lock_contents_view.cc
@@ -695,7 +695,7 @@ auth_error_bubble_->ShowErrorBubble( container, big_view->auth_user()->password_view() /*anchor_view*/, - LoginBubble::kFlagPersistent); + true /*show_persistently*/); } } @@ -814,7 +814,7 @@ label->SetEnabledColor(SK_ColorWHITE); warning_banner_bubble_->ShowErrorBubble( label, CurrentBigUserView()->auth_user()->password_view() /*anchor_view*/, - LoginBubble::kFlagPersistent); + true /*show_persistently*/); } void LockContentsView::OnHideWarningBanner() { @@ -973,7 +973,7 @@ detachable_base_error_bubble_->ShowErrorBubble( label, CurrentBigUserView()->auth_user()->password_view() /*anchor_view*/, - LoginBubble::kFlagPersistent); + true /*show_persistently*/); // Remove the focus from the password field, to make user less likely to enter // the password without seeing the warning about detachable base change. @@ -1487,7 +1487,7 @@ supervised_user_deprecation_bubble_->ShowErrorBubble( label, CurrentBigUserView()->auth_user()->password_view() /*anchor_view*/, - LoginBubble::kFlagPersistent); + true /*show_persistently*/); } // The new auth user might have different last used detachable base - make @@ -1593,7 +1593,7 @@ auth_error_bubble_->ShowErrorBubble( container, big_view->auth_user()->password_view() /*anchor_view*/, - LoginBubble::kFlagsNone); + false /*show_persistently*/); } void LockContentsView::OnEasyUnlockIconHovered() {
diff --git a/ash/login/ui/login_base_bubble_view.cc b/ash/login/ui/login_base_bubble_view.cc index bc1dd484..6aa1919f 100644 --- a/ash/login/ui/login_base_bubble_view.cc +++ b/ash/login/ui/login_base_bubble_view.cc
@@ -46,6 +46,10 @@ LoginBaseBubbleView::~LoginBaseBubbleView() = default; +bool LoginBaseBubbleView::IsPersistent() const { + return false; +} + void LoginBaseBubbleView::OnBeforeBubbleWidgetInit( views::Widget::InitParams* params, views::Widget* widget) const {
diff --git a/ash/login/ui/login_base_bubble_view.h b/ash/login/ui/login_base_bubble_view.h index 5dfd3ef3..1dbc008 100644 --- a/ash/login/ui/login_base_bubble_view.h +++ b/ash/login/ui/login_base_bubble_view.h
@@ -21,6 +21,9 @@ gfx::NativeView parent_window); ~LoginBaseBubbleView() override; + // Returns whether or not this bubble should show persistently. + virtual bool IsPersistent() const; + // views::BubbleDialogDelegateView: void OnBeforeBubbleWidgetInit(views::Widget::InitParams* params, views::Widget* widget) const override;
diff --git a/ash/login/ui/login_bubble.cc b/ash/login/ui/login_bubble.cc index 5af28309..23a8f04 100644 --- a/ash/login/ui/login_bubble.cc +++ b/ash/login/ui/login_bubble.cc
@@ -96,8 +96,10 @@ public: LoginErrorBubbleView(views::View* content, views::View* anchor_view, - aura::Window* container) - : LoginBaseBubbleView(anchor_view, container) { + aura::Window* container, + bool show_persistently) + : LoginBaseBubbleView(anchor_view, container), + show_persistently_(show_persistently) { set_anchor_view_insets( gfx::Insets(kAnchorViewErrorBubbleVerticalSpacingDp, 0)); @@ -125,6 +127,9 @@ ~LoginErrorBubbleView() override = default; + // LoginBaseBubbleView: + bool IsPersistent() const override { return show_persistently_; } + // views::View: const char* GetClassName() const override { return "LoginErrorBubbleView"; } void GetAccessibleNodeData(ui::AXNodeData* node_data) override { @@ -132,6 +137,8 @@ } private: + bool show_persistently_; + DISALLOW_COPY_AND_ASSIGN(LoginErrorBubbleView); }; @@ -447,14 +454,14 @@ void LoginBubble::ShowErrorBubble(views::View* content, views::View* anchor_view, - uint32_t flags) { + bool show_persistently) { if (bubble_view_) CloseImmediately(); - flags_ = flags; aura::Window* menu_container = Shell::GetContainer( Shell::GetPrimaryRootWindow(), kShellWindowId_MenuContainer); - bubble_view_ = new LoginErrorBubbleView(content, anchor_view, menu_container); + bubble_view_ = new LoginErrorBubbleView(content, anchor_view, menu_container, + show_persistently); Show(); } @@ -471,7 +478,6 @@ if (bubble_view_) CloseImmediately(); - flags_ = kFlagsNone; bubble_opener_ = bubble_opener; bubble_view_ = new LoginUserMenuView(this, username, email, type, is_owner, anchor_view, show_remove_user, @@ -490,7 +496,6 @@ if (bubble_view_) CloseImmediately(); - flags_ = kFlagsNone; bubble_view_ = new LoginTooltipView(message, anchor_view); Show(); } @@ -500,7 +505,6 @@ if (bubble_view_) CloseImmediately(); - flags_ = kFlagsNone; bubble_opener_ = bubble_opener; const bool had_focus = bubble_opener_->HasFocus(); @@ -573,7 +577,7 @@ if (bubble_view_->GetWidget()->IsActive()) return; - if (!(flags_ & kFlagPersistent)) { + if (!bubble_view_->IsPersistent()) { Close(); } } @@ -597,7 +601,7 @@ if (gained_focus && bubble_window->Contains(gained_focus)) return; - if (!(flags_ & kFlagPersistent)) + if (!bubble_view_->IsPersistent()) Close(); } @@ -638,7 +642,7 @@ return; } - if (!(flags_ & kFlagPersistent)) + if (!bubble_view_->IsPersistent()) Close(); } @@ -687,7 +691,6 @@ is_visible_ = false; bubble_opener_ = nullptr; bubble_view_ = nullptr; - flags_ = kFlagsNone; } void LoginBubble::EnsureBubbleInScreen() {
diff --git a/ash/login/ui/login_bubble.h b/ash/login/ui/login_bubble.h index 48bb440..e7f77941 100644 --- a/ash/login/ui/login_bubble.h +++ b/ash/login/ui/login_bubble.h
@@ -40,12 +40,6 @@ static const int kUserMenuRemoveUserButtonIdForTest; - // Flags passed to ShowErrorBubble(). - static constexpr uint32_t kFlagsNone = 0; - // If set, the shown error bubble will not be closed due to an unrelated user - // action - e.g. the bubble will not be closed if the user starts typing. - static constexpr uint32_t kFlagPersistent = 1 << 0; - LoginBubble(); ~LoginBubble() override; @@ -53,7 +47,7 @@ // |anchor_view| is the anchor for placing the bubble view. void ShowErrorBubble(views::View* content, views::View* anchor_view, - uint32_t flags); + bool show_persistently); // Shows a user menu bubble. // |anchor_view| is the anchor for placing the bubble view. @@ -128,9 +122,6 @@ // Repositions the bubble view if it extends too far right or down. void EnsureBubbleInScreen(); - // Flags passed to ShowErrorBubble(). - uint32_t flags_ = kFlagsNone; - LoginBaseBubbleView* bubble_view_ = nullptr; // A button that could open/close the bubble.
diff --git a/ash/login/ui/login_bubble_unittest.cc b/ash/login/ui/login_bubble_unittest.cc index 1934f6a..b93cba5 100644 --- a/ash/login/ui/login_bubble_unittest.cc +++ b/ash/login/ui/login_bubble_unittest.cc
@@ -288,7 +288,7 @@ EXPECT_FALSE(bubble_->IsVisible()); views::Label* error_text = new views::Label(base::ASCIIToUTF16("Error text")); - bubble_->ShowErrorBubble(error_text, container_, LoginBubble::kFlagsNone); + bubble_->ShowErrorBubble(error_text, container_, false /*show_persistently*/); EXPECT_TRUE(bubble_->IsVisible()); // Verifies that key event on a view other than error closes the error bubble. @@ -302,7 +302,7 @@ EXPECT_FALSE(bubble_->IsVisible()); views::Label* error_text = new views::Label(base::ASCIIToUTF16("Error text")); - bubble_->ShowErrorBubble(error_text, container_, LoginBubble::kFlagsNone); + bubble_->ShowErrorBubble(error_text, container_, false /*show_persistently*/); EXPECT_TRUE(bubble_->IsVisible()); // Verifies that mouse event on the bubble itself won't close the bubble. @@ -322,7 +322,7 @@ EXPECT_FALSE(bubble_->IsVisible()); views::Label* error_text = new views::Label(base::ASCIIToUTF16("Error text")); - bubble_->ShowErrorBubble(error_text, container_, LoginBubble::kFlagsNone); + bubble_->ShowErrorBubble(error_text, container_, false /*show_persistently*/); EXPECT_TRUE(bubble_->IsVisible()); // Verifies that gesture event on the bubble itself won't close the bubble. @@ -340,8 +340,7 @@ EXPECT_FALSE(bubble_->IsVisible()); views::Label* error_text = new views::Label(base::ASCIIToUTF16("Error text")); - bubble_->ShowErrorBubble(error_text, container_, - LoginBubble::kFlagPersistent); + bubble_->ShowErrorBubble(error_text, container_, true /*show_persistently*/); EXPECT_TRUE(bubble_->IsVisible()); // Verifies that mouse event on the bubble itself won't close the bubble.
diff --git a/ash/login/ui/login_expanded_public_account_view.cc b/ash/login/ui/login_expanded_public_account_view.cc index 700c5da..1a5abdd 100644 --- a/ash/login/ui/login_expanded_public_account_view.cc +++ b/ash/login/ui/login_expanded_public_account_view.cc
@@ -18,7 +18,6 @@ #include "ash/shell.h" #include "ash/strings/grit/ash_strings.h" #include "base/strings/utf_string_conversions.h" -#include "components/vector_icons/vector_icons.h" #include "ui/base/l10n/l10n_util.h" #include "ui/gfx/canvas.h" #include "ui/gfx/paint_vector_icon.h" @@ -75,7 +74,6 @@ constexpr char kMonitoringWarningClassName[] = "MonitoringWarning"; constexpr int kSpacingBetweenMonitoringWarningIconAndLabelDp = 8; -constexpr int kMonitoringWarningIconSizeDp = 20; views::Label* CreateLabel(const base::string16& text, SkColor color) { auto* label = new views::Label(text); @@ -181,8 +179,7 @@ DISALLOW_COPY_AND_ASSIGN(SelectionButtonView); }; -// Container for the device monitoring warning. Contains the warning icon on -// the left side, and text on the right side. +// Container for the device monitoring warning. class MonitoringWarningView : public NonAccessibleView { public: MonitoringWarningView() : NonAccessibleView(kMonitoringWarningClassName) { @@ -190,13 +187,6 @@ views::BoxLayout::kHorizontal, gfx::Insets(), kSpacingBetweenMonitoringWarningIconAndLabelDp)); - views::ImageView* image = new views::ImageView(); - image->SetImage(gfx::CreateVectorIcon( - vector_icons::kWarningIcon, kMonitoringWarningIconSizeDp, SK_ColorRED)); - image->SetPreferredSize( - gfx::Size(kMonitoringWarningIconSizeDp, kMonitoringWarningIconSizeDp)); - AddChildView(image); - const base::string16 label_text = l10n_util::GetStringUTF16( IDS_ASH_LOGIN_PUBLIC_ACCOUNT_MONITORING_WARNING); views::Label* label = CreateLabel(label_text, SK_ColorWHITE);
diff --git a/ash/media/media_notification_controller.cc b/ash/media/media_notification_controller.cc index c65181a..3ddc2a27 100644 --- a/ash/media/media_notification_controller.cc +++ b/ash/media/media_notification_controller.cc
@@ -67,13 +67,19 @@ MediaNotificationController::~MediaNotificationController() = default; -void MediaNotificationController::OnFocusGained( - media_session::mojom::MediaSessionInfoPtr session_info, - media_session::mojom::AudioFocusType type) { +void MediaNotificationController::OnActiveSessionChanged( + media_session::mojom::AudioFocusRequestStatePtr session) { + // Hide the notification if the active session is null. + if (session.is_null()) { + message_center::MessageCenter::Get()->RemoveNotification( + kMediaSessionNotificationId, false); + return; + } + if (IsMediaSessionNotificationVisible()) return; - session_info_ = std::move(session_info); + session_info_ = std::move(session->session_info); std::unique_ptr<message_center::Notification> notification = ash::CreateSystemNotification( @@ -101,15 +107,6 @@ std::move(notification)); } -void MediaNotificationController::OnFocusLost( - media_session::mojom::MediaSessionInfoPtr session_info) { - if (!IsMediaSessionNotificationVisible()) - return; - - message_center::MessageCenter::Get()->RemoveNotification( - kMediaSessionNotificationId, false); -} - void MediaNotificationController::MediaSessionInfoChanged( media_session::mojom::MediaSessionInfoPtr session_info) { session_info_ = std::move(session_info);
diff --git a/ash/media/media_notification_controller.h b/ash/media/media_notification_controller.h index 130bd23..927f19b3 100644 --- a/ash/media/media_notification_controller.h +++ b/ash/media/media_notification_controller.h
@@ -34,9 +34,11 @@ // media_session::mojom::AudioFocusObserver: void OnFocusGained(media_session::mojom::MediaSessionInfoPtr session_info, - media_session::mojom::AudioFocusType type) override; + media_session::mojom::AudioFocusType type) override {} void OnFocusLost( - media_session::mojom::MediaSessionInfoPtr session_info) override; + media_session::mojom::MediaSessionInfoPtr session_info) override {} + void OnActiveSessionChanged( + media_session::mojom::AudioFocusRequestStatePtr session) override; // media_session::mojom::MediaSessionObserver: void MediaSessionInfoChanged(
diff --git a/ash/media/media_notification_controller_unittest.cc b/ash/media/media_notification_controller_unittest.cc index 5e34807..3fc8739 100644 --- a/ash/media/media_notification_controller_unittest.cc +++ b/ash/media/media_notification_controller_unittest.cc
@@ -17,8 +17,7 @@ namespace ash { -using media_session::mojom::AudioFocusType; -using media_session::mojom::MediaSessionInfo; +using media_session::mojom::AudioFocusRequestState; namespace { @@ -56,43 +55,43 @@ DISALLOW_COPY_AND_ASSIGN(MediaNotificationControllerTest); }; -TEST_F(MediaNotificationControllerTest, OnFocusGainedLost) { +TEST_F(MediaNotificationControllerTest, OnActiveSessionChanged) { EXPECT_FALSE(IsMediaNotificationShown()); EXPECT_EQ(0, GetVisibleNotificationCount()); EXPECT_EQ(0, GetPopupNotificationCount()); - Shell::Get()->media_notification_controller()->OnFocusGained( - MediaSessionInfo::New(), AudioFocusType::kGain); + Shell::Get()->media_notification_controller()->OnActiveSessionChanged( + AudioFocusRequestState::New()); EXPECT_TRUE(IsMediaNotificationShown()); EXPECT_EQ(1, GetVisibleNotificationCount()); EXPECT_EQ(0, GetPopupNotificationCount()); - Shell::Get()->media_notification_controller()->OnFocusGained( - MediaSessionInfo::New(), AudioFocusType::kGain); + Shell::Get()->media_notification_controller()->OnActiveSessionChanged( + AudioFocusRequestState::New()); EXPECT_TRUE(IsMediaNotificationShown()); EXPECT_EQ(1, GetVisibleNotificationCount()); EXPECT_EQ(0, GetPopupNotificationCount()); - Shell::Get()->media_notification_controller()->OnFocusLost( - MediaSessionInfo::New()); + Shell::Get()->media_notification_controller()->OnActiveSessionChanged( + nullptr); EXPECT_FALSE(IsMediaNotificationShown()); EXPECT_EQ(0, GetVisibleNotificationCount()); EXPECT_EQ(0, GetPopupNotificationCount()); } -TEST_F(MediaNotificationControllerTest, OnFocusLost_Noop) { +TEST_F(MediaNotificationControllerTest, OnActiveSessionChanged_Noop) { EXPECT_FALSE(IsMediaNotificationShown()); - Shell::Get()->media_notification_controller()->OnFocusLost( - MediaSessionInfo::New()); + Shell::Get()->media_notification_controller()->OnActiveSessionChanged( + nullptr); EXPECT_FALSE(IsMediaNotificationShown()); } TEST_F(MediaNotificationControllerTest, NotificationHasCustomViewType) { EXPECT_FALSE(IsMediaNotificationShown()); - Shell::Get()->media_notification_controller()->OnFocusGained( - MediaSessionInfo::New(), AudioFocusType::kGain); + Shell::Get()->media_notification_controller()->OnActiveSessionChanged( + AudioFocusRequestState::New()); message_center::Notification* notification = message_center::MessageCenter::Get()->FindVisibleNotificationById( kMediaSessionNotificationId);
diff --git a/ash/media/media_notification_view_unittest.cc b/ash/media/media_notification_view_unittest.cc index ff521b2..14c9515b 100644 --- a/ash/media/media_notification_view_unittest.cc +++ b/ash/media/media_notification_view_unittest.cc
@@ -78,8 +78,11 @@ base::Unretained(this))); // Show the notification. - Shell::Get()->media_notification_controller()->OnFocusGained( - std::move(session_info), media_session::mojom::AudioFocusType::kGain); + media_session::mojom::AudioFocusRequestStatePtr session( + media_session::mojom::AudioFocusRequestState::New()); + session->session_info = std::move(session_info); + Shell::Get()->media_notification_controller()->OnActiveSessionChanged( + std::move(session)); message_center::Notification* notification = message_center::MessageCenter::Get()->FindVisibleNotificationById( @@ -229,7 +232,7 @@ EXPECT_EQ(0, media_controller()->toggle_suspend_resume_count()); } -TEST_F(MediaNotificationViewTest, PlayToggle_FromFocusGain) { +TEST_F(MediaNotificationViewTest, PlayToggle_FromActiveSessionChanged) { { views::ToggleImageButton* button = static_cast<views::ToggleImageButton*>(button_row()->child_at(1)); @@ -237,8 +240,8 @@ EXPECT_FALSE(button->toggled_for_testing()); } - Shell::Get()->media_notification_controller()->OnFocusLost( - media_session::mojom::MediaSessionInfo::New()); + Shell::Get()->media_notification_controller()->OnActiveSessionChanged( + nullptr); // Disable the tray and run the loop to make sure that the existing view is // destroyed.
diff --git a/ash/public/cpp/ash_features.cc b/ash/public/cpp/ash_features.cc index 47ec75a..7183df4 100644 --- a/ash/public/cpp/ash_features.cc +++ b/ash/public/cpp/ash_features.cc
@@ -46,9 +46,6 @@ const base::Feature kNotificationScrollBar{"NotificationScrollBar", base::FEATURE_DISABLED_BY_DEFAULT}; -const base::Feature kOverviewSwipeToClose{"OverviewSwipeToClose", - base::FEATURE_ENABLED_BY_DEFAULT}; - const base::Feature kTrilinearFiltering{"TrilinearFiltering", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/ash/public/cpp/ash_features.h b/ash/public/cpp/ash_features.h index 25f14c4..96b16001 100644 --- a/ash/public/cpp/ash_features.h +++ b/ash/public/cpp/ash_features.h
@@ -63,11 +63,6 @@ // Enables notification scroll bar in UnifiedSystemTray. ASH_PUBLIC_EXPORT extern const base::Feature kNotificationScrollBar; -// Enables swipe to close in overview mode. -// TODO(sammiequon): Remove this after the feature is fully launched. -// https://crbug.com/828646. -ASH_PUBLIC_EXPORT extern const base::Feature kOverviewSwipeToClose; - // Enables trilinear filtering. ASH_PUBLIC_EXPORT extern const base::Feature kTrilinearFiltering;
diff --git a/ash/wm/overview/overview_utils.cc b/ash/wm/overview/overview_utils.cc index 24ada41..77ca82fb 100644 --- a/ash/wm/overview/overview_utils.cc +++ b/ash/wm/overview/overview_utils.cc
@@ -114,10 +114,6 @@ return wm::GetWindowState(window)->IsMaximizedOrFullscreenOrPinned(); } -bool IsOverviewSwipeToCloseEnabled() { - return base::FeatureList::IsEnabled(features::kOverviewSwipeToClose); -} - void FadeInWidgetAndMaybeSlideOnEnter(views::Widget* widget, OverviewAnimationType animation_type, bool slide) {
diff --git a/ash/wm/overview/overview_utils.h b/ash/wm/overview/overview_utils.h index 3109019a..a93f7c1a 100644 --- a/ash/wm/overview/overview_utils.h +++ b/ash/wm/overview/overview_utils.h
@@ -27,8 +27,6 @@ // Returns true if |window| can cover available workspace. bool CanCoverAvailableWorkspace(aura::Window* window); -bool IsOverviewSwipeToCloseEnabled(); - // Fades |widget| to opacity one with the enter overview settings. Additionally // place |widget| closer to the top of screen and slide it down if |slide| is // true.
diff --git a/ash/wm/overview/overview_window_drag_controller.cc b/ash/wm/overview/overview_window_drag_controller.cc index 57c623d..0ec2e11f 100644 --- a/ash/wm/overview/overview_window_drag_controller.cc +++ b/ash/wm/overview/overview_window_drag_controller.cc
@@ -75,8 +75,7 @@ return; } - if (IsOverviewSwipeToCloseEnabled() && - std::abs(distance.x()) < std::abs(distance.y())) { + if (std::abs(distance.x()) < std::abs(distance.y())) { current_drag_behavior_ = DragBehavior::kDragToClose; original_opacity_ = item_->GetOpacity(); window_selector_->GetGridWithRootWindow(item_->root_window())
diff --git a/ash/wm/overview/window_selector_unittest.cc b/ash/wm/overview/window_selector_unittest.cc index 293e5f3..1cc8ebd 100644 --- a/ash/wm/overview/window_selector_unittest.cc +++ b/ash/wm/overview/window_selector_unittest.cc
@@ -50,7 +50,6 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "base/test/metrics/user_action_tester.h" -#include "base/test/scoped_feature_list.h" #include "ui/aura/client/aura_constants.h" #include "ui/aura/client/focus_client.h" #include "ui/aura/client/window_types.h" @@ -3573,9 +3572,6 @@ TEST_F(SplitViewWindowSelectorTest, OverviewDragControllerBehavior) { Shell::Get()->aura_env()->set_throttle_input_on_resize_for_testing(false); - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndEnableFeature(features::kOverviewSwipeToClose); - std::unique_ptr<aura::Window> window1 = CreateTestWindow(); std::unique_ptr<aura::Window> window2 = CreateTestWindow(); @@ -3617,9 +3613,6 @@ // Verify that if the window item has been dragged enough vertically, the window // will be closed. TEST_F(SplitViewWindowSelectorTest, DragToClose) { - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndEnableFeature(features::kOverviewSwipeToClose); - // This test requires a widget. const gfx::Rect bounds(400, 400); std::unique_ptr<views::Widget> widget1(CreateWindowWidget(bounds)); @@ -3651,9 +3644,6 @@ // Verify that if the window item has been flung enough vertically, the window // will be closed. TEST_F(SplitViewWindowSelectorTest, FlingToClose) { - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndEnableFeature(features::kOverviewSwipeToClose); - // This test requires a widget. const gfx::Rect bounds(400, 400); std::unique_ptr<views::Widget> widget1(CreateWindowWidget(bounds)); @@ -3694,9 +3684,6 @@ // we still only have one row, so the other items should nudge while the item is // being dragged. TEST_F(SplitViewWindowSelectorTest, BasicNudging) { - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndEnableFeature(features::kOverviewSwipeToClose); - // Set up three equal windows, which take up one row on the overview grid. // When one of them is deleted we are still left with all the windows on one // row. @@ -3741,9 +3728,6 @@ // if the item to be deleted results in the overview grid to change number of // rows. TEST_F(SplitViewWindowSelectorTest, NoNudgingWhenNumRowsChange) { - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndEnableFeature(features::kOverviewSwipeToClose); - // Set up four equal windows, which would split into two rows in overview // mode. Removing one window would leave us with three windows, which only // takes a single row in overview. @@ -3779,9 +3763,6 @@ // from the previous row to drop down to the current row, thus causing the items // to the right of the item to be shifted right, which is visually unacceptable. TEST_F(SplitViewWindowSelectorTest, NoNudgingWhenLastItemOnPreviousRowDrops) { - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndEnableFeature(features::kOverviewSwipeToClose); - // Set up five equal windows, which would split into two rows in overview // mode. Removing one window would cause the rows to rearrange, with the third // item dropping down from the first row to the second row. Create the windows
diff --git a/ash/wm/tablet_mode/tablet_mode_window_drag_delegate.cc b/ash/wm/tablet_mode/tablet_mode_window_drag_delegate.cc index 521bca5..53ddb42 100644 --- a/ash/wm/tablet_mode/tablet_mode_window_drag_delegate.cc +++ b/ash/wm/tablet_mode/tablet_mode_window_drag_delegate.cc
@@ -79,6 +79,11 @@ void TabletModeWindowDragDelegate::StartWindowDrag( aura::Window* dragged_window, const gfx::Point& location_in_screen) { + // TODO(oshima): Consider doing the same for normal window dragging as well + // crbug.com/904631. + DCHECK(!occlusion_excluder_); + occlusion_excluder_.emplace(dragged_window); + dragged_window_ = dragged_window; initial_location_in_screen_ = location_in_screen; @@ -199,6 +204,7 @@ // For child class to do its special handling if any. EndedWindowDrag(location_in_screen); + occlusion_excluder_.reset(); dragged_window_ = nullptr; did_move_ = false; }
diff --git a/ash/wm/tablet_mode/tablet_mode_window_drag_delegate.h b/ash/wm/tablet_mode/tablet_mode_window_drag_delegate.h index 87592eb..4d9880c 100644 --- a/ash/wm/tablet_mode/tablet_mode_window_drag_delegate.h +++ b/ash/wm/tablet_mode/tablet_mode_window_drag_delegate.h
@@ -11,6 +11,8 @@ #include "ash/wm/splitview/split_view_controller.h" #include "ash/wm/wm_toplevel_window_event_handler.h" #include "base/memory/weak_ptr.h" +#include "base/optional.h" +#include "ui/aura/window_occlusion_tracker.h" #include "ui/wm/core/shadow_types.h" namespace ash { @@ -141,6 +143,9 @@ // the window is moved, it will stay as 'moved'. bool did_move_ = false; + base::Optional<aura::WindowOcclusionTracker::ScopedExclude> + occlusion_excluder_; + base::WeakPtrFactory<TabletModeWindowDragDelegate> weak_ptr_factory_; private:
diff --git a/base/BUILD.gn b/base/BUILD.gn index f5d50e9..a60ced7 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -2161,7 +2161,7 @@ } if (is_win || is_mac) { - if (current_cpu == "x64") { + if (current_cpu == "x64" || (current_cpu == "arm64" && is_win)) { # Must be a shared library so that it can be unloaded during testing. shared_library("base_profiler_test_support_library") { sources = [ @@ -2957,6 +2957,7 @@ "android/java/src/org/chromium/base/PackageUtils.java", "android/java/src/org/chromium/base/PathService.java", "android/java/src/org/chromium/base/PathUtils.java", + "android/java/src/org/chromium/base/PiiElider.java", "android/java/src/org/chromium/base/PowerMonitor.java", "android/java/src/org/chromium/base/Promise.java", "android/java/src/org/chromium/base/SecureRandomInitializer.java", @@ -3185,6 +3186,7 @@ "android/junit/src/org/chromium/base/DiscardableReferencePoolTest.java", "android/junit/src/org/chromium/base/LogTest.java", "android/junit/src/org/chromium/base/NonThreadSafeTest.java", + "android/junit/src/org/chromium/base/PiiEliderTest.java", "android/junit/src/org/chromium/base/PromiseTest.java", "android/junit/src/org/chromium/base/memory/MemoryPressureMonitorTest.java", "android/junit/src/org/chromium/base/process_launcher/ChildConnectionAllocatorTest.java",
diff --git a/base/allocator/allocator_shim_unittest.cc b/base/allocator/allocator_shim_unittest.cc index 20a2dace..dea8d6b8 100644 --- a/base/allocator/allocator_shim_unittest.cc +++ b/base/allocator/allocator_shim_unittest.cc
@@ -24,6 +24,7 @@ #if defined(OS_WIN) #include <windows.h> +#include <malloc.h> #elif defined(OS_MACOSX) #include <malloc/malloc.h> #include "base/allocator/allocator_interception_mac.h"
diff --git a/base/android/java/src/org/chromium/base/JavaExceptionReporter.java b/base/android/java/src/org/chromium/base/JavaExceptionReporter.java index f192f78c..91c491be 100644 --- a/base/android/java/src/org/chromium/base/JavaExceptionReporter.java +++ b/base/android/java/src/org/chromium/base/JavaExceptionReporter.java
@@ -51,7 +51,7 @@ @UiThread public static void reportStackTrace(String stackTrace) { assert ThreadUtils.runningOnUiThread(); - nativeReportJavaStackTrace(stackTrace); + nativeReportJavaStackTrace(PiiElider.sanitizeStacktrace(stackTrace)); } @CalledByNative
diff --git a/base/android/java/src/org/chromium/base/PiiElider.java b/base/android/java/src/org/chromium/base/PiiElider.java new file mode 100644 index 0000000..8474f0f --- /dev/null +++ b/base/android/java/src/org/chromium/base/PiiElider.java
@@ -0,0 +1,186 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.base; + +import android.text.TextUtils; +import android.util.Patterns; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Provides public methods for detecting and eliding sensitive PII. + */ +public class PiiElider { + private static final String EMAIL_ELISION = "XXX@EMAIL.ELIDED"; + + private static final String URL_ELISION = "HTTP://WEBADDRESS.ELIDED"; + + private static final String GOOD_IRI_CHAR = "a-zA-Z0-9\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF"; + + private static final Pattern IP_ADDRESS = Pattern.compile( + "((25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.(25[0-5]|2[0-4]" + + "[0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]" + + "[0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}" + + "|[1-9][0-9]|[0-9]))"); + + private static final String IRI = + "[" + GOOD_IRI_CHAR + "]([" + GOOD_IRI_CHAR + "\\-]{0,61}[" + GOOD_IRI_CHAR + "]){0,1}"; + + private static final String GOOD_GTLD_CHAR = "a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF"; + private static final String GTLD = "[" + GOOD_GTLD_CHAR + "]{2,63}"; + private static final String HOST_NAME = "(" + IRI + "\\.)+" + GTLD; + + private static final Pattern DOMAIN_NAME = + Pattern.compile("(" + HOST_NAME + "|" + IP_ADDRESS + ")"); + + private static final Pattern LIKELY_EXCEPTION_LOG = + Pattern.compile("\\sat\\sorg\\.chromium\\.[^ ]+."); + + private static final Pattern WEB_URL = + Pattern.compile("(?:\\b|^)((?:(http|https|Http|Https|rtsp|Rtsp):" + + "\\/\\/(?:(?:[a-zA-Z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)" + + "\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,64}(?:\\:(?:[a-zA-Z0-9\\$\\-\\_" + + "\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,25})?\\@)?)?" + + "(?:" + DOMAIN_NAME + ")" + + "(?:\\:\\d{1,5})?)" + + "(\\/(?:(?:[" + GOOD_IRI_CHAR + "\\;\\/\\?\\:\\@\\&\\=\\#\\~" + + "\\-\\.\\+\\!\\*\\'\\(\\)\\,\\_])|(?:\\%[a-fA-F0-9]{2}))*)?" + + "(?:\\b|$)"); + + private static final String IP_ELISION = "1.2.3.4"; + private static final String MAC_ELISION = "01:23:45:67:89:AB"; + private static final String CONSOLE_ELISION = "[ELIDED:CONSOLE(0)] ELIDED CONSOLE MESSAGE"; + + private static final Pattern MAC_ADDRESS = + Pattern.compile("([0-9a-fA-F]{2}[-:]+){5}[0-9a-fA-F]{2}"); + + private static final Pattern CONSOLE_MSG = Pattern.compile("\\[\\w*:CONSOLE.*\\].*"); + + private static final String[] APP_NAMESPACE = new String[] {"org.chromium.", "com.google."}; + + private static final String[] SYSTEM_NAMESPACE = new String[] {"android.accessibilityservice", + "android.accounts", "android.animation", "android.annotation", "android.app", + "android.appwidget", "android.bluetooth", "android.content", "android.database", + "android.databinding", "android.drm", "android.gesture", "android.graphics", + "android.hardware", "android.inputmethodservice", "android.location", "android.media", + "android.mtp", "android.net", "android.nfc", "android.opengl", "android.os", + "android.preference", "android.print", "android.printservice", "android.provider", + "android.renderscript", "android.sax", "android.security", "android.service", + "android.speech", "android.support", "android.system", "android.telecom", + "android.telephony", "android.test", "android.text", "android.transition", + "android.util", "android.view", "android.webkit", "android.widget", "com.android.", + "dalvik.", "java.", "javax.", "org.apache.", "org.json.", "org.w3c.dom.", "org.xml.", + "org.xmlpull."}; + + /** + * Elides any emails in the specified {@link String} with + * {@link #EMAIL_ELISION}. + * + * @param original String potentially containing emails. + * @return String with elided emails. + */ + public static String elideEmail(String original) { + return Patterns.EMAIL_ADDRESS.matcher(original).replaceAll(EMAIL_ELISION); + } + + /** + * Elides any URLs in the specified {@link String} with + * {@link #URL_ELISION}. + * + * @param original String potentially containing URLs. + * @return String with elided URLs. + */ + public static String elideUrl(String original) { + // Url-matching is fussy. If something looks like an exception message, just return. + if (LIKELY_EXCEPTION_LOG.matcher(original).find()) return original; + StringBuilder buffer = new StringBuilder(original); + Matcher matcher = WEB_URL.matcher(buffer); + int start = 0; + while (matcher.find(start)) { + start = matcher.start(); + int end = matcher.end(); + String url = buffer.substring(start, end); + if (!likelyToBeAppNamespace(url) && !likelyToBeSystemNamespace(url)) { + buffer.replace(start, end, URL_ELISION); + end = start + URL_ELISION.length(); + matcher = WEB_URL.matcher(buffer); + } + start = end; + } + return buffer.toString(); + } + + private static boolean likelyToBeAppNamespace(String url) { + for (String ns : APP_NAMESPACE) { + if (url.startsWith(ns)) { + return true; + } + } + return false; + } + + private static boolean likelyToBeSystemNamespace(String url) { + for (String ns : SYSTEM_NAMESPACE) { + if (url.startsWith(ns)) { + return true; + } + } + return false; + } + + /** + * Elides any IP addresses in the specified {@link String} with + * {@link #IP_ELISION}. + * + * @param original String potentially containing IPs. + * @return String with elided IPs. + */ + public static String elideIp(String original) { + return Patterns.IP_ADDRESS.matcher(original).replaceAll(IP_ELISION); + } + + /** + * Elides any MAC addresses in the specified {@link String} with + * {@link #MAC_ELISION}. + * + * @param original String potentially containing MACs. + * @return String with elided MACs. + */ + public static String elideMac(String original) { + return MAC_ADDRESS.matcher(original).replaceAll(MAC_ELISION); + } + + /** + * Elides any console messages in the specified {@link String} with + * {@link #CONSOLE_ELISION}. + * + * @param original String potentially containing console messages. + * @return String with elided console messages. + */ + public static String elideConsole(String original) { + return CONSOLE_MSG.matcher(original).replaceAll(CONSOLE_ELISION); + } + + /** + * Elides any URL in the exception messages contained inside a stacktrace with + * {@link #URL_ELISION}. + * + * @param stacktrace Multiline stacktrace as a string. + * @return Stacktrace with elided URLs. + */ + public static String sanitizeStacktrace(String stacktrace) { + String[] frames = stacktrace.split("\\n"); + // Sanitize first stacktrace line which contains the exception message. + frames[0] = elideUrl(frames[0]); + for (int i = 1; i < frames.length; i++) { + // Nested exceptions should also have their message sanitized. + if (frames[i].startsWith("Caused by:")) { + frames[i] = elideUrl(frames[i]); + } + } + return TextUtils.join("\n", frames); + } +}
diff --git a/base/android/jni_android.cc b/base/android/jni_android.cc index 598e884..aae65a65 100644 --- a/base/android/jni_android.cc +++ b/base/android/jni_android.cc
@@ -250,53 +250,30 @@ } std::string GetJavaExceptionInfo(JNIEnv* env, jthrowable java_throwable) { - ScopedJavaLocalRef<jclass> throwable_clazz = - GetClass(env, "java/lang/Throwable"); - jmethodID throwable_printstacktrace = - MethodID::Get<MethodID::TYPE_INSTANCE>( - env, throwable_clazz.obj(), "printStackTrace", - "(Ljava/io/PrintStream;)V"); + ScopedJavaLocalRef<jclass> log_clazz = GetClass(env, "android/util/Log"); + jmethodID log_getstacktracestring = MethodID::Get<MethodID::TYPE_STATIC>( + env, log_clazz.obj(), "getStackTraceString", + "(Ljava/lang/Throwable;)Ljava/lang/String;"); - // Create an instance of ByteArrayOutputStream. - ScopedJavaLocalRef<jclass> bytearray_output_stream_clazz = - GetClass(env, "java/io/ByteArrayOutputStream"); - jmethodID bytearray_output_stream_constructor = - MethodID::Get<MethodID::TYPE_INSTANCE>( - env, bytearray_output_stream_clazz.obj(), "<init>", "()V"); - jmethodID bytearray_output_stream_tostring = - MethodID::Get<MethodID::TYPE_INSTANCE>( - env, bytearray_output_stream_clazz.obj(), "toString", - "()Ljava/lang/String;"); - ScopedJavaLocalRef<jobject> bytearray_output_stream(env, - env->NewObject(bytearray_output_stream_clazz.obj(), - bytearray_output_stream_constructor)); - CheckException(env); - - // Create an instance of PrintStream. - ScopedJavaLocalRef<jclass> printstream_clazz = - GetClass(env, "java/io/PrintStream"); - jmethodID printstream_constructor = - MethodID::Get<MethodID::TYPE_INSTANCE>( - env, printstream_clazz.obj(), "<init>", - "(Ljava/io/OutputStream;)V"); - ScopedJavaLocalRef<jobject> printstream(env, - env->NewObject(printstream_clazz.obj(), printstream_constructor, - bytearray_output_stream.obj())); - CheckException(env); - - // Call Throwable.printStackTrace(PrintStream) - env->CallVoidMethod(java_throwable, throwable_printstacktrace, - printstream.obj()); - CheckException(env); - - // Call ByteArrayOutputStream.toString() + // Call Log.getStackTraceString() ScopedJavaLocalRef<jstring> exception_string( - env, static_cast<jstring>( - env->CallObjectMethod(bytearray_output_stream.obj(), - bytearray_output_stream_tostring))); + env, static_cast<jstring>(env->CallStaticObjectMethod( + log_clazz.obj(), log_getstacktracestring, java_throwable))); CheckException(env); - return ConvertJavaStringToUTF8(exception_string); + ScopedJavaLocalRef<jclass> piielider_clazz = + GetClass(env, "org/chromium/base/PiiElider"); + jmethodID piielider_sanitize_stacktrace = + MethodID::Get<MethodID::TYPE_STATIC>( + env, piielider_clazz.obj(), "sanitizeStacktrace", + "(Ljava/lang/String;)Ljava/lang/String;"); + ScopedJavaLocalRef<jstring> sanitized_exception_string( + env, static_cast<jstring>(env->CallStaticObjectMethod( + piielider_clazz.obj(), piielider_sanitize_stacktrace, + exception_string.obj()))); + CheckException(env); + + return ConvertJavaStringToUTF8(sanitized_exception_string); } #if BUILDFLAG(CAN_UNWIND_WITH_FRAME_POINTERS)
diff --git a/base/android/junit/src/org/chromium/base/PiiEliderTest.java b/base/android/junit/src/org/chromium/base/PiiEliderTest.java new file mode 100644 index 0000000..d93d228 --- /dev/null +++ b/base/android/junit/src/org/chromium/base/PiiEliderTest.java
@@ -0,0 +1,136 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.base; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.annotation.Config; + +import org.chromium.base.test.BaseRobolectricTestRunner; + +/** + * junit tests for {@link PiiElider}. + */ +@RunWith(BaseRobolectricTestRunner.class) +@Config(manifest = Config.NONE) +public class PiiEliderTest { + private static final int MAX_LINES = 5; + + @Test + public void testElideEmail() { + String original = "email me at someguy@mailservice.com"; + String expected = "email me at XXX@EMAIL.ELIDED"; + assertEquals(expected, PiiElider.elideEmail(original)); + } + + @Test + public void testElideUrl() { + String original = "file bugs at crbug.com"; + String expected = "file bugs at HTTP://WEBADDRESS.ELIDED"; + assertEquals(expected, PiiElider.elideUrl(original)); + } + + @Test + public void testElideUrl2() { + String original = "exception at org.chromium.base.PiiEliderTest"; + assertEquals(original, PiiElider.elideUrl(original)); + } + + @Test + public void testElideUrl3() { + String original = "file bugs at crbug.com or code.google.com"; + String expected = "file bugs at HTTP://WEBADDRESS.ELIDED or HTTP://WEBADDRESS.ELIDED"; + assertEquals(expected, PiiElider.elideUrl(original)); + } + + @Test + public void testElideUrl4() { + String original = "test shorturl.com !!!"; + String expected = "test HTTP://WEBADDRESS.ELIDED !!!"; + assertEquals(expected, PiiElider.elideUrl(original)); + } + + @Test + public void testElideUrl5() { + String original = "test just.the.perfect.len.url !!!"; + String expected = "test HTTP://WEBADDRESS.ELIDED !!!"; + assertEquals(expected, PiiElider.elideUrl(original)); + } + + @Test + public void testElideUrl6() { + String original = "test a.very.very.very.very.very.long.url !!!"; + String expected = "test HTTP://WEBADDRESS.ELIDED !!!"; + assertEquals(expected, PiiElider.elideUrl(original)); + } + + @Test + public void testElideUrl7() { + String original = " at android.content.Intent \n at java.util.ArrayList"; + assertEquals(original, PiiElider.elideUrl(original)); + } + + @Test + public void testElideUrl8() { + String original = "exception at org.chromium.chrome.browser.compositor.scene_layer." + + "TabListSceneLayer.nativeUpdateLayer(Native Method)"; + assertEquals(original, PiiElider.elideUrl(original)); + } + + @Test + public void testElideUrl9() { + String original = "I/dalvikvm( 5083): at org.chromium.chrome.browser.compositor." + + "scene_layer.TabListSceneLayer.nativeUpdateLayer(Native Method)"; + assertEquals(original, PiiElider.elideUrl(original)); + } + + @Test + public void testDontElideFileSuffixes() { + String original = "chromium_android_linker.so"; + assertEquals(original, PiiElider.elideUrl(original)); + } + + @Test + public void testElideIp() { + String original = "traceroute 127.0.0.1"; + String expected = "traceroute 1.2.3.4"; + assertEquals(expected, PiiElider.elideIp(original)); + } + + @Test + public void testElideMac1() { + String original = "MAC: AB-AB-AB-AB-AB-AB"; + String expected = "MAC: 01:23:45:67:89:AB"; + assertEquals(expected, PiiElider.elideMac(original)); + } + + @Test + public void testElideMac2() { + String original = "MAC: AB:AB:AB:AB:AB:AB"; + String expected = "MAC: 01:23:45:67:89:AB"; + assertEquals(expected, PiiElider.elideMac(original)); + } + + @Test + public void testElideConsole() { + String original = "I/chromium(123): [INFO:CONSOLE(2)] hello!"; + String expected = "I/chromium(123): [ELIDED:CONSOLE(0)] ELIDED CONSOLE MESSAGE"; + assertEquals(expected, PiiElider.elideConsole(original)); + } + + @Test + public void testElideUrlInStacktrace() { + String original = "java.lang.RuntimeException: Outer Exception crbug.com/12345\n" + + " at org.chromium.base.PiiElider.sanitizeStacktrace (PiiElider.java:120)\n" + + "Caused by: java.lang.NullPointerException: Inner Exception shorturl.com/bxyj5"; + String expected = "java.lang.RuntimeException: Outer Exception HTTP://WEBADDRESS.ELIDED\n" + + " at org.chromium.base.PiiElider.sanitizeStacktrace (PiiElider.java:120)\n" + + "Caused by: java.lang.NullPointerException: Inner Exception " + + "HTTP://WEBADDRESS.ELIDED"; + assertEquals(expected, PiiElider.sanitizeStacktrace(original)); + } +}
diff --git a/base/android/proguard/chromium_code.flags b/base/android/proguard/chromium_code.flags index 19347af..8a3ec58 100644 --- a/base/android/proguard/chromium_code.flags +++ b/base/android/proguard/chromium_code.flags
@@ -38,6 +38,9 @@ -keepclasseswithmembers class * { @org.chromium.base.annotations.UsedByReflection <fields>; } +-keepclasseswithmembers,includedescriptorclasses class * { + native <methods>; +} # Remove methods annotated with this if their return value is unused. -assumenosideeffects class ** {
diff --git a/base/android/proguard/explicit_jni_registration.flags b/base/android/proguard/explicit_jni_registration.flags deleted file mode 100644 index f95ea5d..0000000 --- a/base/android/proguard/explicit_jni_registration.flags +++ /dev/null
@@ -1,10 +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. - -# -keepclasseswithmembers rather than -keepclasseswithmembernames to avoid -# shrinking of unused native methods. Explicit JNI registration requires even -# unused classes to be present during RegisterNatives(). --keepclasseswithmembers,includedescriptorclasses class * { - native <methods>; -}
diff --git a/base/android/proguard/implicit_jni_registration.flags b/base/android/proguard/implicit_jni_registration.flags deleted file mode 100644 index 2495f7b..0000000 --- a/base/android/proguard/implicit_jni_registration.flags +++ /dev/null
@@ -1,9 +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. - -# -keepclasseswithmembernames rather than -keepclasseswithmembers to allow -# shrinking of unused native methods. --keepclasseswithmembernames,includedescriptorclasses class * { - native <methods>; -}
diff --git a/base/profiler/native_stack_sampler_win.cc b/base/profiler/native_stack_sampler_win.cc index c4ed209a..d7d6c31 100644 --- a/base/profiler/native_stack_sampler_win.cc +++ b/base/profiler/native_stack_sampler_win.cc
@@ -24,6 +24,7 @@ #include "base/stl_util.h" #include "base/time/time.h" #include "base/trace_event/trace_event.h" +#include "build/build_config.h" namespace base { @@ -157,10 +158,19 @@ uintptr_t bottom, CONTEXT* context, void* stack_copy) { -#if defined(_WIN64) +#if defined(ARCH_CPU_64_BITS) DWORD64 CONTEXT::*const nonvolatile_registers[] = { +#if defined(ARCH_CPU_X86_64) &CONTEXT::R12, &CONTEXT::R13, &CONTEXT::R14, &CONTEXT::R15, &CONTEXT::Rdi, - &CONTEXT::Rsi, &CONTEXT::Rbx, &CONTEXT::Rbp, &CONTEXT::Rsp}; + &CONTEXT::Rsi, &CONTEXT::Rbx, &CONTEXT::Rbp, &CONTEXT::Rsp +#elif defined(ARCH_CPU_ARM64) + &CONTEXT::X19, &CONTEXT::X20, &CONTEXT::X21, &CONTEXT::X22, &CONTEXT::X23, + &CONTEXT::X24, &CONTEXT::X25, &CONTEXT::X26, &CONTEXT::X27, &CONTEXT::X28, + &CONTEXT::Fp, &CONTEXT::Lr +#else +#error Unsupported Windows 64-bit Arch +#endif + }; // Rewrite pointers in the context. for (size_t i = 0; i < size(nonvolatile_registers); ++i) { @@ -213,9 +223,9 @@ stack->reserve(128); Win32StackFrameUnwinder frame_unwinder; - while (context->Rip) { + while (ContextPC(context)) { const void* instruction_pointer = - reinterpret_cast<const void*>(context->Rip); + reinterpret_cast<const void*>(ContextPC(context)); ScopedModuleHandle module; if (!frame_unwinder.TryUnwind(context, &module)) return NATIVE_STACK_SAMPLER_TRY_UNWIND_FAILED; @@ -355,8 +365,10 @@ if (!::GetThreadContext(thread_handle, &thread_context)) return NATIVE_STACK_SAMPLER_GET_THREAD_CONTEXT_FAILED; -#if defined(_WIN64) +#if defined(ARCH_CPU_X86_64) bottom = thread_context.Rsp; +#elif defined(ARCH_CPU_ARM64) + bottom = thread_context.Sp; #else bottom = thread_context.Esp; #endif
diff --git a/base/profiler/win32_stack_frame_unwinder.cc b/base/profiler/win32_stack_frame_unwinder.cc index b5db93b4..a6d1d45 100644 --- a/base/profiler/win32_stack_frame_unwinder.cc +++ b/base/profiler/win32_stack_frame_unwinder.cc
@@ -9,6 +9,7 @@ #include <utility> #include "base/macros.h" +#include "build/build_config.h" namespace base { @@ -121,7 +122,7 @@ // TODO(chengx): update base::ModuleCache to return a ScopedModuleHandle and // use it for this module lookup. ScopedModuleHandle frame_module = - unwind_functions_->GetModuleForProgramCounter(context->Rip); + unwind_functions_->GetModuleForProgramCounter(ContextPC(context)); if (!frame_module.IsValid()) { // There's no loaded module containing the instruction pointer. This can be // due to executing code that is not in a module. In particular, @@ -142,20 +143,31 @@ ULONG64 image_base; // Try to look up unwind metadata for the current function. PRUNTIME_FUNCTION runtime_function = - unwind_functions_->LookupFunctionEntry(context->Rip, &image_base); + unwind_functions_->LookupFunctionEntry(ContextPC(context), &image_base); if (runtime_function) { - unwind_functions_->VirtualUnwind(image_base, context->Rip, runtime_function, - context); + unwind_functions_->VirtualUnwind(image_base, ContextPC(context), + runtime_function, context); at_top_frame_ = false; } else { if (at_top_frame_) { at_top_frame_ = false; // This is a leaf function (i.e. a function that neither calls a function, - // nor allocates any stack space itself) so the return address is at RSP. + // nor allocates any stack space itself). +#if defined(ARCH_CPU_X86_64) + // For X64, return address is at RSP. context->Rip = *reinterpret_cast<DWORD64*>(context->Rsp); context->Rsp += 8; +#elif defined(ARCH_CPU_ARM64) + // For leaf function on Windows ARM64, return address is at LR(X30). + // Add CONTEXT_UNWOUND_TO_CALL flag to avoid unwind ambiguity for tailcall + // on ARM64, because padding after tailcall is not guaranteed. + context->Pc = context->Lr; + context->ContextFlags |= CONTEXT_UNWOUND_TO_CALL; +#else +#error Unsupported Windows 64-bit Arch +#endif } else { // In theory we shouldn't get here, as it means we've encountered a // function without unwind information below the top of the stack, which
diff --git a/base/profiler/win32_stack_frame_unwinder.h b/base/profiler/win32_stack_frame_unwinder.h index c92d50cd2..144cc6e 100644 --- a/base/profiler/win32_stack_frame_unwinder.h +++ b/base/profiler/win32_stack_frame_unwinder.h
@@ -12,6 +12,7 @@ #include "base/base_export.h" #include "base/macros.h" #include "base/win/scoped_handle.h" +#include "build/build_config.h" namespace base { @@ -25,6 +26,18 @@ using PRUNTIME_FUNCTION = RUNTIME_FUNCTION*; #endif // !defined(_WIN64) +#if defined(ARCH_CPU_64_BITS) +inline ULONG64 ContextPC(CONTEXT* context) { +#if defined(ARCH_CPU_X86_64) + return context->Rip; +#elif defined(ARCH_CPU_ARM64) + return context->Pc; +#else +#error Unsupported Windows 64-bit Arch +#endif +} +#endif + // Traits class to adapt GenericScopedHandle for HMODULES. class ModuleHandleTraits : public win::HandleTraits { public:
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni index 79e282d..498fcf8b 100644 --- a/build/config/android/rules.gni +++ b/build/config/android/rules.gni
@@ -2433,13 +2433,6 @@ proguard_configs += [ "//build/android/multidex.flags" ] } proguard_mapping_path = _proguard_mapping_path - if (_use_chromium_linker) { - proguard_configs += - [ "//base/android/proguard/explicit_jni_registration.flags" ] - } else { - proguard_configs += - [ "//base/android/proguard/implicit_jni_registration.flags" ] - } } # Don't depend on the runtime_deps target in order to avoid having to
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index b9a7e0eb..66a80a8d 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -95394b4e05ae49a15270dca82cce5b3aab91ad7a \ No newline at end of file +089bba31a40b8d2ec9018064aeb2617bbf8ee985 \ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index 04f615b4..71929b1 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -87a02c667580a1720ea4ee2c94ece6adad1e38cd \ No newline at end of file +ea1cb7ce191f61d3351efe3e141233d454b96db0 \ No newline at end of file
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 38d52361..815d857 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -978,6 +978,8 @@ # symbols required for lazy JNI registration. # enable_compressed_relocations: Optional. If true, enable compressed # ELF relocations to reduce native library size. +# use_gnu_hash_style: If true, the final library will include only GNU hash +# tables, rather than both SysV and GNU types (the default). template("chrome_common_shared_library") { shared_library(target_name) { forward_variables_from(invoker, @@ -985,6 +987,7 @@ [ "enable_compressed_relocations", "export_java_symbols", + "use_gnu_hash_style", ]) _export_java_symbols = defined(invoker.export_java_symbols) && invoker.export_java_symbols @@ -1018,6 +1021,20 @@ invoker.enable_compressed_relocations) { configs += [ "//build/config/android:lld_pack_relocations" ] } + + if (invoker.use_gnu_hash_style && target_cpu != "mipsel" && + target_cpu != "mips64el") { + # By default, the static linker will create ELF executables with both + # SysV and GNU hash tables. Now that the chromium linker supports the GNU + # format, which is considerably smaller, ensure that the SysV one is + # never compiled in the final library (http://crbug.com/742525#c28). GNU + # hash support was added in Android M. Also not supported on MIPS + # architecture (http://crbug.com/811306). + if (!defined(ldflags)) { + ldflags = [] + } + ldflags += [ "-Wl,--hash-style=gnu" ] + } } } @@ -1034,20 +1051,8 @@ ldflags = [ "-Wl,--long-plt" ] } - if (chromium_linker_supported && target_cpu != "mipsel" && - target_cpu != "mipsel64") { - # By default, the static linker will create ELF executables with both - # SysV and GNU hash tables. Now that the chromium linker supports the - # GNU format, which is considerably smaller, ensure that the SysV one - # is never compiled in the final library. Note that MIPS platforms do - # not support the GNU format though. - if (!defined(ldflags)) { - ldflags = [] - } - ldflags += [ "-Wl,--hash-style=gnu" ] - } - enable_compressed_relocations = chromium_linker_supported && use_lld + use_gnu_hash_style = chromium_linker_supported } } @@ -1315,14 +1320,7 @@ export_java_symbols = true enable_compressed_relocations = use_lld - - if (target_cpu != "mipsel" && target_cpu != "mips64el") { - # .gnu.hash support added in Android M. Without this flag, library will also - # contain an unused .hash section. (http://crbug.com/742525#c28) - # Not to be used for MIPS arhitecture since MIPS does not - # support hashstyle gnu: http://crbug.com/811306 - ldflags = [ "-Wl,--hash-style=gnu" ] - } + use_gnu_hash_style = true } } else { group("monochrome_secondary_abi_lib") {
diff --git a/chrome/android/java/res/layout/bottom_toolbar_browsing.xml b/chrome/android/java/res/layout/bottom_toolbar_browsing.xml index e337157..70e4b116 100644 --- a/chrome/android/java/res/layout/bottom_toolbar_browsing.xml +++ b/chrome/android/java/res/layout/bottom_toolbar_browsing.xml
@@ -3,7 +3,7 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> -<org.chromium.chrome.browser.toolbar.ScrollingBottomViewResourceFrameLayout +<org.chromium.chrome.browser.toolbar.bottom.ScrollingBottomViewResourceFrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" @@ -37,14 +37,14 @@ android:paddingStart="@dimen/bottom_toolbar_start_padding" android:paddingEnd="@dimen/bottom_toolbar_end_padding" > - <org.chromium.chrome.browser.toolbar.HomeButton + <org.chromium.chrome.browser.toolbar.bottom.HomeButton android:id="@+id/home_button" style="@style/BottomToolbarButton" android:contentDescription="@string/accessibility_toolbar_btn_home" /> <include layout="@layout/toolbar_space" /> - <org.chromium.chrome.browser.toolbar.ShareButton + <org.chromium.chrome.browser.toolbar.bottom.ShareButton android:id="@+id/share_button" style="@style/BottomToolbarButton" android:src="@drawable/ic_share_white_24dp" @@ -53,7 +53,7 @@ <include layout="@layout/toolbar_space" /> - <org.chromium.chrome.browser.toolbar.SearchAccelerator + <org.chromium.chrome.browser.toolbar.bottom.SearchAccelerator android:id="@+id/search_accelerator" android:layout_width="@dimen/search_accelerator_width" android:layout_height="@dimen/search_accelerator_height" @@ -78,4 +78,4 @@ </org.chromium.chrome.browser.widget.bottomsheet.TouchRestrictingFrameLayout> -</org.chromium.chrome.browser.toolbar.ScrollingBottomViewResourceFrameLayout> +</org.chromium.chrome.browser.toolbar.bottom.ScrollingBottomViewResourceFrameLayout>
diff --git a/chrome/android/java/res_autofill_assistant/drawable/autofill_assistant_checkbox_bg.xml b/chrome/android/java/res_autofill_assistant/drawable/autofill_assistant_checkbox_bg.xml new file mode 100644 index 0000000..08605a2 --- /dev/null +++ b/chrome/android/java/res_autofill_assistant/drawable/autofill_assistant_checkbox_bg.xml
@@ -0,0 +1,11 @@ +<!-- 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. --> +<shape + xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="rectangle"> + <corners + android:radius="4dp" /> + <solid + android:color="@color/autofill_assistant_light_blue" /> +</shape>
diff --git a/chrome/android/java/res_autofill_assistant/layout/autofill_assistant_payment_request.xml b/chrome/android/java/res_autofill_assistant/layout/autofill_assistant_payment_request.xml index bca6084..95452f09 100644 --- a/chrome/android/java/res_autofill_assistant/layout/autofill_assistant_payment_request.xml +++ b/chrome/android/java/res_autofill_assistant/layout/autofill_assistant_payment_request.xml
@@ -34,13 +34,38 @@ </org.chromium.chrome.browser.widget.FadingEdgeScrollView> - <CheckBox - android:id="@+id/terms_checkbox" - android:layout_width="match_parent" + <!-- + Padding on the checkbox does not affect the padding to the left of the + checkbox field, so we wrap it in a FrameLayout and control the margins and + padding there. + --> + <FrameLayout android:layout_height="wrap_content" - android:layout_marginStart="5dp" - android:padding="2dp" - android:text="@string/autofill_assistant_terms" /> + android:layout_width="match_parent" + android:layout_marginStart="16dp" + android:layout_marginEnd="16dp" + android:layout_marginTop="28dp" + android:layout_marginBottom="20dp" + android:paddingTop="9dp" + android:paddingBottom="9dp" + android:paddingStart="12dp" + android:paddingEnd="12dp" + android:background="@drawable/autofill_assistant_checkbox_bg" > + + <!-- + TODO(crbug.com/806868): Remove the tint and text color to be compliant + with Chrome style. + --> + <android.support.v7.widget.AppCompatCheckBox + android:id="@+id/terms_checkbox" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_margin="0dp" + android:padding="0dp" + android:paddingStart="12dp" + android:text="@string/autofill_assistant_terms" /> + + </FrameLayout> <include layout="@layout/autofill_assistant_payment_request_bottom_bar" />
diff --git a/chrome/android/java/res_autofill_assistant/values-v17/colors.xml b/chrome/android/java/res_autofill_assistant/values-v17/colors.xml new file mode 100644 index 0000000..3d758fd --- /dev/null +++ b/chrome/android/java/res_autofill_assistant/values-v17/colors.xml
@@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2014 The Chromium Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. --> + +<resources> + <!-- + TODO(crbuc.com/806868): Use a Chrome approved color and remove this. + + Please see src/ui/android/java/res/values/colors.xml for the shared common colors. + --> + <color name="autofill_assistant_light_blue">#e9f0fd</color> +</resources>
diff --git a/chrome/android/java/res_autofill_assistant/values-v17/styles.xml b/chrome/android/java/res_autofill_assistant/values-v17/styles.xml index 25b517b..862d31a 100644 --- a/chrome/android/java/res_autofill_assistant/values-v17/styles.xml +++ b/chrome/android/java/res_autofill_assistant/values-v17/styles.xml
@@ -23,7 +23,8 @@ <style name="TextAppearance.AutofillAssistantFilledButton" parent="RobotoMediumStyle"> - <item name="android:textColor">@color/modern_grey_50</item> + <item name="android:textColor">@color/modern_grey_50</item> <item name="android:textSize">@dimen/text_size_medium</item> </style> + </resources>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/ui/PaymentRequestUI.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/ui/PaymentRequestUI.java index f8aecce..704412f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/ui/PaymentRequestUI.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/ui/PaymentRequestUI.java
@@ -20,6 +20,7 @@ import android.text.SpannableString; import android.text.TextUtils; import android.text.method.LinkMovementMethod; +import android.text.style.StyleSpan; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; @@ -319,6 +320,10 @@ // Terms and services accepted checkbox. The state is passively propagated along to the // client when the pay/continue button is clicked. mTermsCheckBox = (CheckBox) mRequestView.findViewById(R.id.terms_checkbox); + StyleSpan boldSpan = new StyleSpan(android.graphics.Typeface.BOLD); + String termsString = context.getString(R.string.autofill_assistant_terms, origin); + mTermsCheckBox.setText( + SpanApplier.applySpans(termsString, new SpanInfo("<b>", "</b>", boldSpan))); // Create all the possible sections. mSectionSeparators = new ArrayList<>();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java index 7b970a1..58a761e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
@@ -301,14 +301,7 @@ mShowingFullscreen = isInFullscreen; if (mSystemUiFullscreenResizeRunnable == null) { - mSystemUiFullscreenResizeRunnable = () -> { - View contentView = getContentView(); - if (contentView != null) { - Point viewportSize = getViewportSize(); - setSize(getWebContents(), contentView, viewportSize.x, viewportSize.y); - } - onViewportChanged(); - }; + mSystemUiFullscreenResizeRunnable = this::handleWindowInsetChanged; } else { getHandler().removeCallbacks(mSystemUiFullscreenResizeRunnable); } @@ -367,13 +360,25 @@ mInsetObserverView = view; if (mInsetObserverView != null) { mInsetObserverView.addObserver(this); - onViewportChanged(); + handleWindowInsetChanged(); } } @Override public void onInsetChanged(int left, int top, int right, int bottom) { - if (mShowingFullscreen) onViewportChanged(); + if (mShowingFullscreen) handleWindowInsetChanged(); + } + + private void handleWindowInsetChanged() { + // Notify the WebContents that the size has changed. + View contentView = getContentView(); + if (contentView != null) { + Point viewportSize = getViewportSize(); + setSize(getWebContents(), contentView, viewportSize.x, viewportSize.y); + } + // Notify the compositor layout that the size has changed. The layout does not drive + // the WebContents sizing, so this needs to be done in addition to the above size update. + onViewportChanged(); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/crash/LogcatExtractionRunnable.java b/chrome/android/java/src/org/chromium/chrome/browser/crash/LogcatExtractionRunnable.java index c3e06cf2e..6dc3c0e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/crash/LogcatExtractionRunnable.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/crash/LogcatExtractionRunnable.java
@@ -5,10 +5,10 @@ package org.chromium.chrome.browser.crash; import android.os.Build; -import android.util.Patterns; import org.chromium.base.ContextUtils; import org.chromium.base.Log; +import org.chromium.base.PiiElider; import org.chromium.base.VisibleForTesting; import org.chromium.components.minidump_uploader.CrashFileManager; @@ -20,8 +20,6 @@ import java.util.Collections; import java.util.LinkedList; import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; /** * Extracts the recent logcat output from an Android device, elides PII sensitive info from it, @@ -37,43 +35,6 @@ protected static final int LOGCAT_SIZE = 256; // Number of lines. - protected static final String EMAIL_ELISION = "XXX@EMAIL.ELIDED"; - - @VisibleForTesting - protected static final String URL_ELISION = "HTTP://WEBADDRESS.ELIDED"; - - private static final String GOOD_IRI_CHAR = "a-zA-Z0-9\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF"; - - private static final Pattern IP_ADDRESS = Pattern.compile( - "((25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.(25[0-5]|2[0-4]" - + "[0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]" - + "[0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}" - + "|[1-9][0-9]|[0-9]))"); - - private static final String IRI = - "[" + GOOD_IRI_CHAR + "]([" + GOOD_IRI_CHAR + "\\-]{0,61}[" + GOOD_IRI_CHAR + "]){0,1}"; - - private static final String GOOD_GTLD_CHAR = "a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF"; - private static final String GTLD = "[" + GOOD_GTLD_CHAR + "]{2,63}"; - private static final String HOST_NAME = "(" + IRI + "\\.)+" + GTLD; - - private static final Pattern DOMAIN_NAME = - Pattern.compile("(" + HOST_NAME + "|" + IP_ADDRESS + ")"); - - private static final Pattern LIKELY_EXCEPTION_LOG = - Pattern.compile("\\sat\\sorg\\.chromium\\.[^ ]+."); - - private static final Pattern WEB_URL = - Pattern.compile("(?:\\b|^)((?:(http|https|Http|Https|rtsp|Rtsp):" - + "\\/\\/(?:(?:[a-zA-Z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)" - + "\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,64}(?:\\:(?:[a-zA-Z0-9\\$\\-\\_" - + "\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,25})?\\@)?)?" - + "(?:" + DOMAIN_NAME + ")" - + "(?:\\:\\d{1,5})?)" - + "(\\/(?:(?:[" + GOOD_IRI_CHAR + "\\;\\/\\?\\:\\@\\&\\=\\#\\~" - + "\\-\\.\\+\\!\\*\\'\\(\\)\\,\\_])|(?:\\%[a-fA-F0-9]{2}))*)?" - + "(?:\\b|$)"); - @VisibleForTesting protected static final String BEGIN_MICRODUMP = "-----BEGIN BREAKPAD MICRODUMP-----"; @VisibleForTesting @@ -82,36 +43,6 @@ protected static final String SNIPPED_MICRODUMP = "-----SNIPPED OUT BREAKPAD MICRODUMP FOR THIS CRASH-----"; - @VisibleForTesting - protected static final String IP_ELISION = "1.2.3.4"; - - @VisibleForTesting - protected static final String MAC_ELISION = "01:23:45:67:89:AB"; - - @VisibleForTesting - protected static final String CONSOLE_ELISION = "[ELIDED:CONSOLE(0)] ELIDED CONSOLE MESSAGE"; - - private static final Pattern MAC_ADDRESS = - Pattern.compile("([0-9a-fA-F]{2}[-:]+){5}[0-9a-fA-F]{2}"); - - private static final Pattern CONSOLE_MSG = Pattern.compile("\\[\\w*:CONSOLE.*\\].*"); - - private static final String[] CHROME_NAMESPACE = new String[] {"org.chromium.", "com.google."}; - - private static final String[] SYSTEM_NAMESPACE = new String[] {"android.accessibilityservice", - "android.accounts", "android.animation", "android.annotation", "android.app", - "android.appwidget", "android.bluetooth", "android.content", "android.database", - "android.databinding", "android.drm", "android.gesture", "android.graphics", - "android.hardware", "android.inputmethodservice", "android.location", "android.media", - "android.mtp", "android.net", "android.nfc", "android.opengl", "android.os", - "android.preference", "android.print", "android.printservice", "android.provider", - "android.renderscript", "android.sax", "android.security", "android.service", - "android.speech", "android.support", "android.system", "android.telecom", - "android.telephony", "android.test", "android.text", "android.transition", - "android.util", "android.view", "android.webkit", "android.widget", "com.android.", - "dalvik.", "java.", "javax.", "org.apache.", "org.json.", "org.w3c.dom.", "org.xml.", - "org.xmlpull."}; - private final File mMinidumpFile; /** @@ -254,107 +185,13 @@ protected static List<String> elideLogcat(List<String> rawLogcat) { List<String> elided = new ArrayList<String>(rawLogcat.size()); for (String ln : rawLogcat) { - ln = elideEmail(ln); - ln = elideUrl(ln); - ln = elideIp(ln); - ln = elideMac(ln); - ln = elideConsole(ln); + ln = PiiElider.elideEmail(ln); + ln = PiiElider.elideUrl(ln); + ln = PiiElider.elideIp(ln); + ln = PiiElider.elideMac(ln); + ln = PiiElider.elideConsole(ln); elided.add(ln); } return elided; } - - /** - * Elides any emails in the specified {@link String} with - * {@link #EMAIL_ELISION}. - * - * @param original String potentially containing emails. - * @return String with elided emails. - */ - @VisibleForTesting - protected static String elideEmail(String original) { - return Patterns.EMAIL_ADDRESS.matcher(original).replaceAll(EMAIL_ELISION); - } - - /** - * Elides any URLs in the specified {@link String} with - * {@link #URL_ELISION}. - * - * @param original String potentially containing URLs. - * @return String with elided URLs. - */ - @VisibleForTesting - protected static String elideUrl(String original) { - // Url-matching is fussy. If something looks like an exception message, just return. - if (LIKELY_EXCEPTION_LOG.matcher(original).find()) return original; - StringBuilder buffer = new StringBuilder(original); - Matcher matcher = WEB_URL.matcher(buffer); - int start = 0; - while (matcher.find(start)) { - start = matcher.start(); - int end = matcher.end(); - String url = buffer.substring(start, end); - if (!likelyToBeChromeNamespace(url) && !likelyToBeSystemNamespace(url)) { - buffer.replace(start, end, URL_ELISION); - end = start + URL_ELISION.length(); - matcher = WEB_URL.matcher(buffer); - } - start = end; - } - return buffer.toString(); - } - - public static boolean likelyToBeChromeNamespace(String url) { - for (String ns : CHROME_NAMESPACE) { - if (url.startsWith(ns)) { - return true; - } - } - return false; - } - - public static boolean likelyToBeSystemNamespace(String url) { - for (String ns : SYSTEM_NAMESPACE) { - if (url.startsWith(ns)) { - return true; - } - } - return false; - } - - /** - * Elides any IP addresses in the specified {@link String} with - * {@link #IP_ELISION}. - * - * @param original String potentially containing IPs. - * @return String with elided IPs. - */ - @VisibleForTesting - protected static String elideIp(String original) { - return Patterns.IP_ADDRESS.matcher(original).replaceAll(IP_ELISION); - } - - /** - * Elides any MAC addresses in the specified {@link String} with - * {@link #MAC_ELISION}. - * - * @param original String potentially containing MACs. - * @return String with elided MACs. - */ - @VisibleForTesting - protected static String elideMac(String original) { - return MAC_ADDRESS.matcher(original).replaceAll(MAC_ELISION); - } - - /** - * Elides any console messages in the specified {@link String} with - * {@link #CONSOLE_ELISION}. - * - * @param original String potentially containing console messages. - * @return String with elided console messages. - */ - @VisibleForTesting - protected static String elideConsole(String original) { - return CONSOLE_MSG.matcher(original).replaceAll(CONSOLE_ELISION); - } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/crash/PureJavaExceptionReporter.java b/chrome/android/java/src/org/chromium/chrome/browser/crash/PureJavaExceptionReporter.java index ee45085d..87b0e07a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/crash/PureJavaExceptionReporter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/crash/PureJavaExceptionReporter.java
@@ -15,6 +15,7 @@ import org.chromium.base.BuildConfig; import org.chromium.base.BuildInfo; import org.chromium.base.ContextUtils; +import org.chromium.base.PiiElider; import org.chromium.base.StrictModeContext; import org.chromium.base.VisibleForTesting; import org.chromium.base.annotations.MainDex; @@ -137,7 +138,8 @@ addPairedString(GMS_CORE_VERSION, buildInfo.gmsVersionCode); addPairedString(INSTALLER_PACKAGE_NAME, buildInfo.installerPackageName); addPairedString(ABI_NAME, buildInfo.abiString); - addPairedString(EXCEPTION_INFO, Log.getStackTraceString(javaException)); + addPairedString(EXCEPTION_INFO, + PiiElider.sanitizeStacktrace(Log.getStackTraceString(javaException))); addPairedString(EARLY_JAVA_EXCEPTION, "true"); addPairedString(PACKAGE, String.format("%s v%s (%s)", BuildConfig.FIREBASE_APP_ID, buildInfo.versionCode,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/MenuButton.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/MenuButton.java index 7001932a..a2bb725 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/MenuButton.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/MenuButton.java
@@ -48,7 +48,7 @@ * @param onTouchListener An {@link OnTouchListener} that is triggered when the menu button is * clicked. */ - void setTouchListener(OnTouchListener onTouchListener) { + public void setTouchListener(OnTouchListener onTouchListener) { mMenuImageButton.setOnTouchListener(onTouchListener); } @@ -113,7 +113,7 @@ /** * @return Whether the update badge is showing. */ - boolean isShowingAppMenuUpdateBadge() { + public boolean isShowingAppMenuUpdateBadge() { return mUpdateBadgeView.getVisibility() == View.VISIBLE; } @@ -149,7 +149,7 @@ return mMenuImageButton; } - void setThemeColorProvider(ThemeColorProvider themeColorProvider) { + public void setThemeColorProvider(ThemeColorProvider themeColorProvider) { mThemeColorProvider = themeColorProvider; mThemeColorProvider.addObserver(this); } @@ -160,7 +160,7 @@ setUseLightDrawables(ColorUtils.shouldUseLightForegroundOnBackground(primaryColor)); } - void destroy() { + public void destroy() { if (mThemeColorProvider != null) { mThemeColorProvider.removeObserver(this); mThemeColorProvider = null;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabCountProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabCountProvider.java index 0fbc2514..ddd50c61 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabCountProvider.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabCountProvider.java
@@ -15,9 +15,7 @@ import java.util.List; -/** - * Provides the number of open regular tabs for display in the tab switcher icon. - */ +/** A provider that notifies its observers when the number of tabs changes. */ public class TabCountProvider { /** An observer that is notified of changes to the number of open tabs. */ public interface TabCountObserver {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java index b2e83c23..18f8162 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -88,6 +88,7 @@ import org.chromium.chrome.browser.tabmodel.TabModelObserver; import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.tabmodel.TabModelSelectorObserver; +import org.chromium.chrome.browser.toolbar.bottom.BottomToolbarCoordinator; import org.chromium.chrome.browser.toolbar.top.ActionModeController; import org.chromium.chrome.browser.toolbar.top.ActionModeController.ActionBarDelegate; import org.chromium.chrome.browser.toolbar.top.Toolbar;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarCoordinator.java similarity index 96% rename from chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarCoordinator.java rename to chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarCoordinator.java index cf1bac1..bc65fc4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarCoordinator.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.toolbar; +package org.chromium.chrome.browser.toolbar.bottom; import android.view.View; import android.view.View.OnClickListener; @@ -16,6 +16,9 @@ import org.chromium.chrome.browser.compositor.layouts.ToolbarSwipeLayout; import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager; import org.chromium.chrome.browser.tabmodel.TabModelSelector; +import org.chromium.chrome.browser.toolbar.IncognitoStateProvider; +import org.chromium.chrome.browser.toolbar.MenuButton; +import org.chromium.chrome.browser.toolbar.TabCountProvider; import org.chromium.ui.base.WindowAndroid; import org.chromium.ui.resources.ResourceManager;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BrowsingModeBottomToolbarCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarCoordinator.java similarity index 95% rename from chrome/android/java/src/org/chromium/chrome/browser/toolbar/BrowsingModeBottomToolbarCoordinator.java rename to chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarCoordinator.java index 27ef91c32..0f79804 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BrowsingModeBottomToolbarCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarCoordinator.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.toolbar; +package org.chromium.chrome.browser.toolbar.bottom; import android.view.View; import android.view.View.OnClickListener; @@ -19,7 +19,11 @@ import org.chromium.chrome.browser.modelutil.PropertyModelChangeProcessor; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tabmodel.TabModelSelector; -import org.chromium.chrome.browser.toolbar.BrowsingModeBottomToolbarViewBinder.ViewHolder; +import org.chromium.chrome.browser.toolbar.MenuButton; +import org.chromium.chrome.browser.toolbar.TabCountProvider; +import org.chromium.chrome.browser.toolbar.TabSwitcherButtonCoordinator; +import org.chromium.chrome.browser.toolbar.ThemeColorProvider; +import org.chromium.chrome.browser.toolbar.bottom.BrowsingModeBottomToolbarViewBinder.ViewHolder; import org.chromium.ui.base.WindowAndroid; import org.chromium.ui.resources.ResourceManager;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BrowsingModeBottomToolbarMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarMediator.java similarity index 98% rename from chrome/android/java/src/org/chromium/chrome/browser/toolbar/BrowsingModeBottomToolbarMediator.java rename to chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarMediator.java index 748ec83d..103528b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BrowsingModeBottomToolbarMediator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarMediator.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.toolbar; +package org.chromium.chrome.browser.toolbar.bottom; import android.content.res.ColorStateList; import android.content.res.Resources; @@ -19,6 +19,7 @@ import org.chromium.chrome.browser.compositor.layouts.eventfilter.EdgeSwipeHandler; import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager; import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager.FullscreenListener; +import org.chromium.chrome.browser.toolbar.ThemeColorProvider; import org.chromium.chrome.browser.toolbar.ThemeColorProvider.ThemeColorObserver; import org.chromium.chrome.browser.widget.textbubble.TextBubble; import org.chromium.components.feature_engagement.FeatureConstants;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BrowsingModeBottomToolbarModel.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarModel.java similarity index 97% rename from chrome/android/java/src/org/chromium/chrome/browser/toolbar/BrowsingModeBottomToolbarModel.java rename to chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarModel.java index 4b33b4b6..d587f84 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BrowsingModeBottomToolbarModel.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarModel.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.toolbar; +package org.chromium.chrome.browser.toolbar.bottom; import org.chromium.chrome.browser.compositor.layouts.LayoutManager; import org.chromium.chrome.browser.compositor.layouts.ToolbarSwipeLayout;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BrowsingModeBottomToolbarViewBinder.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarViewBinder.java similarity index 98% rename from chrome/android/java/src/org/chromium/chrome/browser/toolbar/BrowsingModeBottomToolbarViewBinder.java rename to chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarViewBinder.java index 17cc1fa..5aa1ace 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BrowsingModeBottomToolbarViewBinder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarViewBinder.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.toolbar; +package org.chromium.chrome.browser.toolbar.bottom; import android.view.View; import android.view.ViewGroup;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/HomeButton.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/HomeButton.java similarity index 93% rename from chrome/android/java/src/org/chromium/chrome/browser/toolbar/HomeButton.java rename to chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/HomeButton.java index 59c7c9ed..fb84ab90 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/HomeButton.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/HomeButton.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.toolbar; +package org.chromium.chrome.browser.toolbar.bottom; import android.content.Context; import android.content.res.ColorStateList; @@ -11,6 +11,7 @@ import org.chromium.base.ApiCompatibilityUtils; import org.chromium.chrome.R; +import org.chromium.chrome.browser.toolbar.ThemeColorProvider; import org.chromium.chrome.browser.toolbar.ThemeColorProvider.ThemeColorObserver; import org.chromium.chrome.browser.util.FeatureUtilities; import org.chromium.ui.widget.ChromeImageButton;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ScrollingBottomViewResourceFrameLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/ScrollingBottomViewResourceFrameLayout.java similarity index 98% rename from chrome/android/java/src/org/chromium/chrome/browser/toolbar/ScrollingBottomViewResourceFrameLayout.java rename to chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/ScrollingBottomViewResourceFrameLayout.java index 0aeac71..0200eb7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ScrollingBottomViewResourceFrameLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/ScrollingBottomViewResourceFrameLayout.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.toolbar; +package org.chromium.chrome.browser.toolbar.bottom; import android.content.Context; import android.graphics.Canvas;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/SearchAccelerator.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/SearchAccelerator.java similarity index 94% rename from chrome/android/java/src/org/chromium/chrome/browser/toolbar/SearchAccelerator.java rename to chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/SearchAccelerator.java index 03ac1943..7fdcc90 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/SearchAccelerator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/SearchAccelerator.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.toolbar; +package org.chromium.chrome.browser.toolbar.bottom; import android.content.Context; import android.content.res.ColorStateList; @@ -13,6 +13,7 @@ import org.chromium.base.ApiCompatibilityUtils; import org.chromium.chrome.R; +import org.chromium.chrome.browser.toolbar.ThemeColorProvider; import org.chromium.chrome.browser.toolbar.ThemeColorProvider.ThemeColorObserver; import org.chromium.chrome.browser.util.ColorUtils; import org.chromium.ui.widget.ChromeImageButton;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ShareButton.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/ShareButton.java similarity index 96% rename from chrome/android/java/src/org/chromium/chrome/browser/toolbar/ShareButton.java rename to chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/ShareButton.java index 638164f..9c7fc0ce 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ShareButton.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/ShareButton.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.toolbar; +package org.chromium.chrome.browser.toolbar.bottom; import android.content.Context; import android.content.res.ColorStateList; @@ -15,6 +15,7 @@ import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabObserver; +import org.chromium.chrome.browser.toolbar.ThemeColorProvider; import org.chromium.chrome.browser.toolbar.ThemeColorProvider.ThemeColorObserver; import org.chromium.ui.widget.ChromeImageButton;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherBottomToolbarCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/TabSwitcherBottomToolbarCoordinator.java similarity index 93% rename from chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherBottomToolbarCoordinator.java rename to chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/TabSwitcherBottomToolbarCoordinator.java index ecb5d21..4db47f7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherBottomToolbarCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/TabSwitcherBottomToolbarCoordinator.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.toolbar; +package org.chromium.chrome.browser.toolbar.bottom; import android.view.View; import android.view.View.OnClickListener; @@ -15,6 +15,11 @@ import org.chromium.chrome.browser.device.DeviceClassManager; import org.chromium.chrome.browser.modelutil.PropertyModelChangeProcessor; import org.chromium.chrome.browser.tabmodel.TabModelSelector; +import org.chromium.chrome.browser.toolbar.IncognitoStateProvider; +import org.chromium.chrome.browser.toolbar.IncognitoToggleTabLayout; +import org.chromium.chrome.browser.toolbar.MenuButton; +import org.chromium.chrome.browser.toolbar.NewTabButton; +import org.chromium.chrome.browser.toolbar.TabCountProvider; /** * The coordinator for the tab switcher mode bottom toolbar. This class handles all interactions
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherBottomToolbarMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/TabSwitcherBottomToolbarMediator.java similarity index 96% rename from chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherBottomToolbarMediator.java rename to chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/TabSwitcherBottomToolbarMediator.java index 9457f9d..49e9359 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherBottomToolbarMediator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/TabSwitcherBottomToolbarMediator.java
@@ -2,12 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.toolbar; +package org.chromium.chrome.browser.toolbar.bottom; import android.content.res.ColorStateList; import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior; import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior.OverviewModeObserver; +import org.chromium.chrome.browser.toolbar.ThemeColorProvider; import org.chromium.chrome.browser.toolbar.ThemeColorProvider.ThemeColorObserver; /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherBottomToolbarModel.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/TabSwitcherBottomToolbarModel.java similarity index 94% rename from chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherBottomToolbarModel.java rename to chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/TabSwitcherBottomToolbarModel.java index 010399bd7..7897f53 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherBottomToolbarModel.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/TabSwitcherBottomToolbarModel.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.toolbar; +package org.chromium.chrome.browser.toolbar.bottom; import org.chromium.chrome.browser.modelutil.PropertyModel;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherBottomToolbarViewBinder.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/TabSwitcherBottomToolbarViewBinder.java similarity index 96% rename from chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherBottomToolbarViewBinder.java rename to chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/TabSwitcherBottomToolbarViewBinder.java index aacfe6d5..cf5afeb 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherBottomToolbarViewBinder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/TabSwitcherBottomToolbarViewBinder.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.toolbar; +package org.chromium.chrome.browser.toolbar.bottom; import android.view.View;
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni index 4eb1cbc9..fc6e61d 100644 --- a/chrome/android/java_sources.gni +++ b/chrome/android/java_sources.gni
@@ -1565,27 +1565,14 @@ "java/src/org/chromium/chrome/browser/tabmodel/document/StorageDelegate.java", "java/src/org/chromium/chrome/browser/tabmodel/document/TabDelegate.java", "java/src/org/chromium/chrome/browser/tasks/TasksUma.java", - "java/src/org/chromium/chrome/browser/toolbar/BottomToolbarCoordinator.java", - "java/src/org/chromium/chrome/browser/toolbar/BrowsingModeBottomToolbarCoordinator.java", - "java/src/org/chromium/chrome/browser/toolbar/BrowsingModeBottomToolbarMediator.java", - "java/src/org/chromium/chrome/browser/toolbar/BrowsingModeBottomToolbarModel.java", - "java/src/org/chromium/chrome/browser/toolbar/BrowsingModeBottomToolbarViewBinder.java", "java/src/org/chromium/chrome/browser/toolbar/HomePageButton.java", - "java/src/org/chromium/chrome/browser/toolbar/HomeButton.java", "java/src/org/chromium/chrome/browser/toolbar/IncognitoStateProvider.java", "java/src/org/chromium/chrome/browser/toolbar/IncognitoToggleTabLayout.java", "java/src/org/chromium/chrome/browser/toolbar/KeyboardNavigationListener.java", "java/src/org/chromium/chrome/browser/toolbar/LocationBarModel.java", "java/src/org/chromium/chrome/browser/toolbar/MenuButton.java", "java/src/org/chromium/chrome/browser/toolbar/NewTabButton.java", - "java/src/org/chromium/chrome/browser/toolbar/ScrollingBottomViewResourceFrameLayout.java", - "java/src/org/chromium/chrome/browser/toolbar/SearchAccelerator.java", - "java/src/org/chromium/chrome/browser/toolbar/ShareButton.java", "java/src/org/chromium/chrome/browser/toolbar/TabCountProvider.java", - "java/src/org/chromium/chrome/browser/toolbar/TabSwitcherBottomToolbarCoordinator.java", - "java/src/org/chromium/chrome/browser/toolbar/TabSwitcherBottomToolbarMediator.java", - "java/src/org/chromium/chrome/browser/toolbar/TabSwitcherBottomToolbarModel.java", - "java/src/org/chromium/chrome/browser/toolbar/TabSwitcherBottomToolbarViewBinder.java", "java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonViewBinder.java", "java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonCoordinator.java", "java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonProperties.java", @@ -1596,6 +1583,19 @@ "java/src/org/chromium/chrome/browser/toolbar/ToolbarDataProvider.java", "java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java", "java/src/org/chromium/chrome/browser/toolbar/ToolbarTabController.java", + "java/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarCoordinator.java", + "java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarCoordinator.java", + "java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarMediator.java", + "java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarModel.java", + "java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarViewBinder.java", + "java/src/org/chromium/chrome/browser/toolbar/bottom/HomeButton.java", + "java/src/org/chromium/chrome/browser/toolbar/bottom/ScrollingBottomViewResourceFrameLayout.java", + "java/src/org/chromium/chrome/browser/toolbar/bottom/SearchAccelerator.java", + "java/src/org/chromium/chrome/browser/toolbar/bottom/ShareButton.java", + "java/src/org/chromium/chrome/browser/toolbar/bottom/TabSwitcherBottomToolbarCoordinator.java", + "java/src/org/chromium/chrome/browser/toolbar/bottom/TabSwitcherBottomToolbarMediator.java", + "java/src/org/chromium/chrome/browser/toolbar/bottom/TabSwitcherBottomToolbarModel.java", + "java/src/org/chromium/chrome/browser/toolbar/bottom/TabSwitcherBottomToolbarViewBinder.java", "java/src/org/chromium/chrome/browser/toolbar/top/ActionModeController.java", "java/src/org/chromium/chrome/browser/toolbar/top/CustomTabToolbar.java", "java/src/org/chromium/chrome/browser/toolbar/top/CustomTabToolbarAnimationDelegate.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserControllerInputTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserControllerInputTest.java index d48e57c34..4cbb6529 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserControllerInputTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserControllerInputTest.java
@@ -339,7 +339,7 @@ Assert.assertTrue("Page did not enter fullscreen", DOMUtils.isFullscreen(mVrBrowserTestFramework.getFirstTabWebContents())); - mController.pressReleaseAppButton(); + NativeUiUtils.clickAppButton(UserFriendlyElementName.NONE, new PointF()); CriteriaHelper.pollInstrumentationThread( () -> { @@ -406,10 +406,11 @@ // is not actually visible, we'll hit a DCHECK in the native code. NativeUiUtils.clickElementAndWaitForUiQuiescence( UserFriendlyElementName.OMNIBOX_TEXT_FIELD, new PointF()); - NativeUiUtils.revertToRealInput(); // Wait for the URL bar to re-appear, which we take as a signal that we've exited omnibox // text input mode. - NativeUiUtils.performActionAndWaitForVisibilityStatus(UserFriendlyElementName.URL, - true /* visible */, () -> { mController.pressReleaseAppButton(); }); + NativeUiUtils.performActionAndWaitForVisibilityStatus( + UserFriendlyElementName.URL, true /* visible */, () -> { + NativeUiUtils.clickAppButton(UserFriendlyElementName.NONE, new PointF()); + }); } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserTransitionTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserTransitionTest.java index 6f0651be..7c91c0b 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserTransitionTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserTransitionTest.java
@@ -15,6 +15,7 @@ import android.app.Activity; import android.content.Context; import android.content.Intent; +import android.graphics.PointF; import android.support.test.InstrumentationRegistry; import android.support.test.filters.LargeTest; import android.support.test.filters.MediumTest; @@ -316,7 +317,6 @@ private void reEntryFromVrBrowserImpl(String url, WebXrVrTestFramework framework) throws InterruptedException { VrBrowserTransitionUtils.forceEnterVrBrowserOrFail(POLL_TIMEOUT_LONG_MS); - EmulatedVrController controller = new EmulatedVrController(mTestRule.getActivity()); framework.loadUrlAndAwaitInitialization(url, PAGE_LOAD_TIMEOUT_S); framework.enterSessionWithUserGestureOrFail(); @@ -324,7 +324,7 @@ framework.executeStepAndWait("stepVerifyFirstPresent()"); // The bug did not reproduce with vrDisplay.exitPresent(), so it might not reproduce with // session.end(). Instead, use the controller to exit. - controller.pressReleaseAppButton(); + NativeUiUtils.clickAppButton(UserFriendlyElementName.NONE, new PointF()); framework.executeStepAndWait("stepVerifyMagicWindow()"); framework.enterSessionWithUserGestureOrFail();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserWebInputEditingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserWebInputEditingTest.java index 7fad88ac..ce67975 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserWebInputEditingTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserWebInputEditingTest.java
@@ -404,12 +404,7 @@ "Keyboard did not show from focusing a web input box", POLL_TIMEOUT_SHORT_MS, POLL_CHECK_INTERVAL_SHORT_MS); - NativeUiUtils.revertToRealInput(); - EmulatedVrController controller = new EmulatedVrController(mVrTestRule.getActivity()); - // Do this several times to help combat the flakiness of the emulated controller. - for (int i = 0; i < 3; ++i) { - controller.pressReleaseAppButton(); - } + NativeUiUtils.clickAppButton(UserFriendlyElementName.NONE, new PointF()); CriteriaHelper.pollInstrumentationThread( () -> {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrInputTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrInputTest.java index 2f7a566a..d3e5f4f9 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrInputTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrInputTest.java
@@ -300,7 +300,6 @@ @CommandLineFlags.Add({"enable-features=WebXR"}) @XrActivityRestriction({XrActivityRestriction.SupportedActivity.ALL}) public void testScreenTapsRegisteredOnCardboard_WebXr() throws InterruptedException { - EmulatedVrController controller = new EmulatedVrController(mTestRule.getActivity()); mWebXrVrTestFramework.loadUrlAndAwaitInitialization( WebXrVrTestFramework.getFileUrlForHtmlTestFile("test_webxr_input"), PAGE_LOAD_TIMEOUT_S); @@ -397,8 +396,7 @@ throws InterruptedException { framework.loadUrlAndAwaitInitialization(url, PAGE_LOAD_TIMEOUT_S); framework.enterSessionWithUserGestureOrFail(); - EmulatedVrController controller = new EmulatedVrController(mTestRule.getActivity()); - controller.pressReleaseAppButton(); + NativeUiUtils.clickAppButton(UserFriendlyElementName.NONE, new PointF()); assertAppButtonEffect(true /* shouldHaveExited */, framework); framework.assertNoJavaScriptErrors(); } @@ -477,8 +475,7 @@ MockVrDaydreamApi mockApi = new MockVrDaydreamApi(); VrShellDelegateUtils.getDelegateInstance().overrideDaydreamApiForTesting(mockApi); - EmulatedVrController controller = new EmulatedVrController(mTestRule.getActivity()); - controller.pressReleaseAppButton(); + NativeUiUtils.clickAppButton(UserFriendlyElementName.NONE, new PointF()); Assert.assertFalse("App button left Chrome", ThreadUtils.runOnUiThreadBlocking(new Callable<Boolean>() { @Override @@ -557,8 +554,7 @@ framework.enterSessionWithUserGestureOrFail(); // Wait for page to stop submitting frames. framework.waitOnJavaScriptStep(); - EmulatedVrController controller = new EmulatedVrController(mTestRule.getActivity()); - controller.pressReleaseAppButton(); + NativeUiUtils.clickAppButton(UserFriendlyElementName.NONE, new PointF()); assertAppButtonEffect(true /* shouldHaveExited */, framework); framework.assertNoJavaScriptErrors(); } @@ -742,7 +738,6 @@ private void testAppButtonLongPressDisplaysPermissionsImpl() throws InterruptedException { // Note that we need to pass in the WebContents to use throughout this because automatically // using the first tab's WebContents doesn't work in Incognito. - EmulatedVrController controller = new EmulatedVrController(mTestRule.getActivity()); EmbeddedTestServer server = mTestRule.getTestServer(); boolean teardownServer = false; if (server == null) { @@ -767,12 +762,13 @@ NativeUiUtils.performActionAndWaitForVisibilityStatus( UserFriendlyElementName.WEB_XR_AUDIO_INDICATOR, false /* visible */, () -> {}); NativeUiUtils.performActionAndWaitForVisibilityStatus( - UserFriendlyElementName.WEB_XR_AUDIO_INDICATOR, true /* visible */, - () -> { controller.sendAppButtonToggleEvent(); }); + UserFriendlyElementName.WEB_XR_AUDIO_INDICATOR, true /* visible */, () -> { + NativeUiUtils.pressAppButton(UserFriendlyElementName.NONE, new PointF()); + }); // The toast should automatically disappear after ~5 second after the button is pressed, // regardless of whether it's released or not. SystemClock.sleep(1000); - controller.sendAppButtonToggleEvent(); + NativeUiUtils.releaseAppButton(UserFriendlyElementName.NONE, new PointF()); SystemClock.sleep(3500); // Make sure it's still present shortly before we expect it to disappear. NativeUiUtils.performActionAndWaitForVisibilityStatus( @@ -781,8 +777,9 @@ UserFriendlyElementName.WEB_XR_AUDIO_INDICATOR, false /* visible */, () -> {}); // Do the same, but make sure the toast disappears even with the button still held. NativeUiUtils.performActionAndWaitForVisibilityStatus( - UserFriendlyElementName.WEB_XR_AUDIO_INDICATOR, true /* visible */, - () -> { controller.sendAppButtonToggleEvent(); }); + UserFriendlyElementName.WEB_XR_AUDIO_INDICATOR, true /* visible */, () -> { + NativeUiUtils.pressAppButton(UserFriendlyElementName.NONE, new PointF()); + }); SystemClock.sleep(4500); NativeUiUtils.performActionAndWaitForVisibilityStatus( UserFriendlyElementName.WEB_XR_AUDIO_INDICATOR, true /* visible */, () -> {});
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/NativeUiUtils.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/NativeUiUtils.java index e2318f5..f3603af 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/NativeUiUtils.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/NativeUiUtils.java
@@ -82,7 +82,44 @@ */ public static void clickElement(int elementName, PointF position) { TestVrShellDelegate.getInstance().performControllerActionForTesting( - elementName, VrControllerTestAction.CLICK, position); + elementName, VrControllerTestAction.CLICK_DOWN, position); + TestVrShellDelegate.getInstance().performControllerActionForTesting( + elementName, VrControllerTestAction.CLICK_UP, position); + } + + /** + * Clicks the app button while pointed at a UI element. + * @param elementName The UserFriendlyElementName that will be pointed at. + * @param position A PointF specifying where on the element to point at relative to a unit + * square centered on (0, 0). + */ + public static void clickAppButton(int elementName, PointF position) { + TestVrShellDelegate.getInstance().performControllerActionForTesting( + elementName, VrControllerTestAction.APP_DOWN, position); + TestVrShellDelegate.getInstance().performControllerActionForTesting( + elementName, VrControllerTestAction.APP_UP, position); + } + + /** + * Presses the app button down while pointed at a UI element. + * @param elementName The UserFriendlyElementName that will be pointed at. + * @param position A PointF specifying where on the element to point at relative to a unit + * square centered on (0, 0). + */ + public static void pressAppButton(int elementName, PointF position) { + TestVrShellDelegate.getInstance().performControllerActionForTesting( + elementName, VrControllerTestAction.APP_DOWN, position); + } + + /** + * Releases the app button while pointed at a UI element. + * @param elementName The UserFriendlyElementName that will be pointed at. + * @param position A PointF specifying where on the element to point at relative to a unit + * square centered on (0, 0). + */ + public static void releaseAppButton(int elementName, PointF position) { + TestVrShellDelegate.getInstance().performControllerActionForTesting( + elementName, VrControllerTestAction.APP_UP, position); } /**
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/crash/LogcatExtractionRunnableUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/crash/LogcatExtractionRunnableUnitTest.java index e2c777e..68d478a 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/crash/LogcatExtractionRunnableUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/crash/LogcatExtractionRunnableUnitTest.java
@@ -30,109 +30,6 @@ private static final int MAX_LINES = 5; @Test - public void testElideEmail() { - String original = "email me at someguy@mailservice.com"; - String expected = "email me at XXX@EMAIL.ELIDED"; - assertEquals(expected, LogcatExtractionRunnable.elideEmail(original)); - } - - @Test - public void testElideUrl() { - String original = "file bugs at crbug.com"; - String expected = "file bugs at HTTP://WEBADDRESS.ELIDED"; - assertEquals(expected, LogcatExtractionRunnable.elideUrl(original)); - } - - @Test - public void testElideUrl2() { - String original = - "exception at org.chromium.chrome.browser.crash.LogcatExtractionRunnableUnitTest"; - assertEquals(original, LogcatExtractionRunnable.elideUrl(original)); - } - - @Test - public void testElideUrl3() { - String original = "file bugs at crbug.com or code.google.com"; - String expected = "file bugs at HTTP://WEBADDRESS.ELIDED or HTTP://WEBADDRESS.ELIDED"; - assertEquals(expected, LogcatExtractionRunnable.elideUrl(original)); - } - - @Test - public void testElideUrl4() { - String original = "test shorturl.com !!!"; - String expected = "test HTTP://WEBADDRESS.ELIDED !!!"; - assertEquals(expected, LogcatExtractionRunnable.elideUrl(original)); - } - - @Test - public void testElideUrl5() { - String original = "test just.the.perfect.len.url !!!"; - String expected = "test HTTP://WEBADDRESS.ELIDED !!!"; - assertEquals(expected, LogcatExtractionRunnable.elideUrl(original)); - } - - @Test - public void testElideUrl6() { - String original = "test a.very.very.very.very.very.long.url !!!"; - String expected = "test HTTP://WEBADDRESS.ELIDED !!!"; - assertEquals(expected, LogcatExtractionRunnable.elideUrl(original)); - } - - @Test - public void testElideUrl7() { - String original = " at android.content.Intent \n at java.util.ArrayList"; - assertEquals(original, LogcatExtractionRunnable.elideUrl(original)); - } - - @Test - public void testElideUrl8() { - String original = "exception at org.chromium.chrome.browser.compositor.scene_layer." - + "TabListSceneLayer.nativeUpdateLayer(Native Method)"; - assertEquals(original, LogcatExtractionRunnable.elideUrl(original)); - } - - @Test - public void testElideUrl9() { - String original = "I/dalvikvm( 5083): at org.chromium.chrome.browser.compositor." - + "scene_layer.TabListSceneLayer.nativeUpdateLayer(Native Method)"; - assertEquals(original, LogcatExtractionRunnable.elideUrl(original)); - } - - @Test - public void testDontElideFileSuffixes() { - String original = "chromium_android_linker.so"; - assertEquals(original, LogcatExtractionRunnable.elideUrl(original)); - } - - @Test - public void testElideIp() { - String original = "traceroute 127.0.0.1"; - String expected = "traceroute 1.2.3.4"; - assertEquals(expected, LogcatExtractionRunnable.elideIp(original)); - } - - @Test - public void testElideMac1() { - String original = "MAC: AB-AB-AB-AB-AB-AB"; - String expected = "MAC: 01:23:45:67:89:AB"; - assertEquals(expected, LogcatExtractionRunnable.elideMac(original)); - } - - @Test - public void testElideMac2() { - String original = "MAC: AB:AB:AB:AB:AB:AB"; - String expected = "MAC: 01:23:45:67:89:AB"; - assertEquals(expected, LogcatExtractionRunnable.elideMac(original)); - } - - @Test - public void testElideConsole() { - String original = "I/chromium(123): [INFO:CONSOLE(2)] hello!"; - String expected = "I/chromium(123): [ELIDED:CONSOLE(0)] ELIDED CONSOLE MESSAGE"; - assertEquals(expected, LogcatExtractionRunnable.elideConsole(original)); - } - - @Test public void testLogTagNotElided() { List<String> original = Arrays.asList(new String[] {"I/cr_FooBar(123): Some message"}); assertEquals(original, LogcatExtractionRunnable.elideLogcat(original));
diff --git a/chrome/android/static_initializers.gni b/chrome/android/static_initializers.gni index 8adb769..c97f976 100644 --- a/chrome/android/static_initializers.gni +++ b/chrome/android/static_initializers.gni
@@ -13,7 +13,7 @@ (!is_debug && !using_sanitizer && proprietary_codecs)) { # Define expectations only for target_cpu covered by trybots. if (target_cpu == "arm") { - expected_static_initializer_count = 5 + expected_static_initializer_count = 4 } else if (target_cpu == "arm64") { expected_static_initializer_count = 3 }
diff --git a/chrome/app/chromium_strings.grd b/chrome/app/chromium_strings.grd index d4800ed..6e92c5d 100644 --- a/chrome/app/chromium_strings.grd +++ b/chrome/app/chromium_strings.grd
@@ -680,15 +680,6 @@ </message> </if> - <if expr="toolkit_views"> - <message name="IDS_ENTERPRISE_FORCE_SIGNOUT_EXPLANATION" desc="Text of the reason to sign out"> - Authentication certificate failed. Please sign in to Chromium again as <ph name="USER_NAME">$1<ex>pat@example.com</ex></ph> or contact your administrator for more information. <ph name="ADDITIONAL_EXPLANATION">$2</ph> - </message> - <message name="IDS_ENTERPRISE_FORCE_SIGNOUT_EXPLANATION_WITHOUT_USER_NAME" desc="Text of the reason to sign out when there is no valid email address"> - Authentication certificate failed. Please sign in to Chromium again or contact your administrator for more information. <ph name="ADDITIONAL_EXPLANATION">$2</ph> - </message> - </if> - <!-- Signin Email Confirmation tab modal dialog --> <if expr="not chromeos"> <message name="IDS_SIGNIN_EMAIL_CONFIRMATION_TITLE" desc="Title of the signin email confirmation tab modal dialog.">
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 963b871c..d48b118 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -6256,21 +6256,6 @@ This account is managed by <ph name="DOMAIN">$1<ex>example.com</ex></ph> </message> - <!-- Enterprise force-sign-out dialog--> - <message name="IDS_ENTERPRISE_FORCE_SIGNOUT_TITLE" desc="The title of the dialog shown when the user closes a browser and force sign in is enabled and local auth info is not valid."> - Sign in certification is not valid, window closing in <ph name="MINUTES">{0,number,00}<ex>5</ex></ph> : <ph name="SECONDS">{1,number,00}<ex>00</ex></ph> - </message> - <message name="IDS_ENTERPRISE_FORCE_SIGNOUT_CLOSE_CONFIRM" desc="Text of the button to sign in again immediately."> - Sign in now - </message> - <message name="IDS_ENTERPRISE_FORCE_SIGNOUT_CLOSE_DELAY" desc="Text of the button to sign in again later"> - Cancel - </message> - <message name="IDS_ENTERPRISE_FORCE_SIGNOUT_ADDITIONAL_EXPLANATION" desc="Text of auto close warning"> - All browser windows will soon be closed automatically without sign in. - </message> - - <!-- Cookies Window --> <message name="IDS_COOKIES_REMOVE_LABEL" desc="The label of the 'Remove' button in the Cookies Window"> Remove
diff --git a/chrome/app/google_chrome_strings.grd b/chrome/app/google_chrome_strings.grd index 42fcce87..783a064 100644 --- a/chrome/app/google_chrome_strings.grd +++ b/chrome/app/google_chrome_strings.grd
@@ -691,15 +691,6 @@ </message> </if> - <if expr="toolkit_views"> - <message name="IDS_ENTERPRISE_FORCE_SIGNOUT_EXPLANATION" desc="Text of the reason to sign out"> - Authentication certificate failed. Please sign in to Google Chrome again as <ph name="USER_NAME">$1<ex>pat@example.com</ex></ph> or contact your administrator for more information. <ph name="ADDITIONAL_EXPLANATION">$2</ph> - </message> - <message name="IDS_ENTERPRISE_FORCE_SIGNOUT_EXPLANATION_WITHOUT_USER_NAME" desc="Text of the reason to sign out when there is no valid email address"> - Authentication certificate failed. Please sign in to Google Chrome again or contact your administrator for more information. <ph name="ADDITIONAL_EXPLANATION">$2</ph> - </message> - </if> - <!-- Signin Email Confirmation tab modal dialog --> <if expr="not chromeos"> <message name="IDS_SIGNIN_EMAIL_CONFIRMATION_TITLE" desc="Title of the signin email confirmation tab modal dialog.">
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 38158e06..bef2776b 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -4096,6 +4096,8 @@ if (enable_offline_pages) { sources += [ + "offline_pages/auto_fetch_page_load_watcher.cc", + "offline_pages/auto_fetch_page_load_watcher.h", "offline_pages/background_loader_offliner.cc", "offline_pages/background_loader_offliner.h", "offline_pages/download_archive_manager.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 4360f405..e670ad2 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -384,12 +384,12 @@ kAccountConsistencyFeatureMethodDiceFixAuthErrors}}; const FeatureEntry::FeatureVariation kAccountConsistencyFeatureVariations[] = { - {"Dice", kAccountConsistencyDice, arraysize(kAccountConsistencyDice), + {"Dice", kAccountConsistencyDice, base::size(kAccountConsistencyDice), nullptr /* variation_id */}, {"Dice (migration)", kAccountConsistencyDiceMigration, - arraysize(kAccountConsistencyDiceMigration), nullptr /* variation_id */}, + base::size(kAccountConsistencyDiceMigration), nullptr /* variation_id */}, {"Dice (fix auth errors)", kAccountConsistencyDiceFixAuthErrors, - arraysize(kAccountConsistencyDiceFixAuthErrors), + base::size(kAccountConsistencyDiceFixAuthErrors), nullptr /* variation_id */}}; #endif // BUILDFLAG(ENABLE_DICE_SUPPORT) @@ -789,6 +789,13 @@ switches::kTLS13VariantFinal}, }; +const FeatureEntry::FeatureParam kEnforceTLS13DowngradeKnownOnly[] = { + {"known_roots_only", "true"}}; + +const FeatureEntry::FeatureVariation kEnforceTLS13DowngradeFeatureVariations[] = + {{"(Known Root Only)", kEnforceTLS13DowngradeKnownOnly, + base::size(kEnforceTLS13DowngradeKnownOnly), nullptr}}; + #if !defined(OS_ANDROID) const FeatureEntry::Choice kEnableAudioFocusChoices[] = { {flag_descriptions::kEnableAudioFocusDisabled, "", ""}, @@ -985,7 +992,7 @@ const FeatureEntry::FeatureVariation kDataReductionMainMenuFeatureVariations[] = {{"(persistent)", kPersistentMenuItemEnabled, - arraysize(kPersistentMenuItemEnabled), nullptr}}; + base::size(kPersistentMenuItemEnabled), nullptr}}; #endif // OS_ANDROID const FeatureEntry::FeatureParam kDetectingHeavyPagesLowThresholdEnabled[] = { @@ -2031,10 +2038,9 @@ {"translate-force-trigger-on-english", flag_descriptions::kTranslateForceTriggerOnEnglishName, flag_descriptions::kTranslateForceTriggerOnEnglishDescription, kOsAndroid, - FEATURE_WITH_PARAMS_VALUE_TYPE( - language::kOverrideTranslateTriggerInIndia, - kTranslateForceTriggerOnEnglishVariations, - language::kOverrideTranslateTriggerInIndia.name)}, + FEATURE_WITH_PARAMS_VALUE_TYPE(language::kOverrideTranslateTriggerInIndia, + kTranslateForceTriggerOnEnglishVariations, + "OverrideTranslateTriggerInIndia")}, {"translate-explicit-ask", flag_descriptions::kTranslateExplicitLanguageAskName, flag_descriptions::kTranslateExplicitLanguageAskDescription, kOsAndroid, @@ -2498,10 +2504,9 @@ offline_pages::kOfflinePagesShowAlternateDinoPageFeature)}, {"offline-indicator-choice", flag_descriptions::kOfflineIndicatorChoiceName, flag_descriptions::kOfflineIndicatorChoiceDescription, kOsAndroid, - FEATURE_WITH_PARAMS_VALUE_TYPE( - offline_pages::kOfflineIndicatorFeature, - kOfflineIndicatorFeatureVariations, - offline_pages::kOfflineIndicatorFeature.name)}, + FEATURE_WITH_PARAMS_VALUE_TYPE(offline_pages::kOfflineIndicatorFeature, + kOfflineIndicatorFeatureVariations, + "OfflineIndicator")}, {"offline-indicator-always-http-probe", flag_descriptions::kOfflineIndicatorAlwaysHttpProbeName, flag_descriptions::kOfflineIndicatorAlwaysHttpProbeDescription, kOsAndroid, @@ -2605,7 +2610,9 @@ MULTI_VALUE_TYPE(kTLS13VariantChoices)}, {"enforce-tls13-downgrade", flag_descriptions::kEnforceTLS13DowngradeName, flag_descriptions::kEnforceTLS13DowngradeDescription, kOsAll, - FEATURE_VALUE_TYPE(net::features::kEnforceTLS13Downgrade)}, + FEATURE_WITH_PARAMS_VALUE_TYPE(net::features::kEnforceTLS13Downgrade, + kEnforceTLS13DowngradeFeatureVariations, + "EnforceTLS13Downgrade")}, {"enable-scroll-anchor-serialization", flag_descriptions::kEnableScrollAnchorSerializationName, flag_descriptions::kEnableScrollAnchorSerializationDescription, kOsAll, @@ -2631,7 +2638,7 @@ FEATURE_WITH_PARAMS_VALUE_TYPE( ntp_snippets::kCategoryOrder, kContentSuggestionsCategoryOrderFeatureVariations, - ntp_snippets::kCategoryOrder.name)}, + "ContentSuggestionsCategoryOrder")}, {"content-suggestions-category-ranker", flag_descriptions::kContentSuggestionsCategoryRankerName, flag_descriptions::kContentSuggestionsCategoryRankerDescription, @@ -2639,7 +2646,7 @@ FEATURE_WITH_PARAMS_VALUE_TYPE( ntp_snippets::kCategoryRanker, kContentSuggestionsCategoryRankerFeatureVariations, - ntp_snippets::kCategoryRanker.name)}, + "ContentSuggestionsCategoryRanker")}, {"content-suggestions-debug-log", flag_descriptions::kContentSuggestionsDebugLogName, flag_descriptions::kContentSuggestionsDebugLogDescription, kOsAndroid, @@ -2681,10 +2688,9 @@ {"enable-ntp-remote-suggestions", flag_descriptions::kEnableNtpRemoteSuggestionsName, flag_descriptions::kEnableNtpRemoteSuggestionsDescription, kOsAndroid, - FEATURE_WITH_PARAMS_VALUE_TYPE( - ntp_snippets::kArticleSuggestionsFeature, - kRemoteSuggestionsFeatureVariations, - ntp_snippets::kArticleSuggestionsFeature.name)}, + FEATURE_WITH_PARAMS_VALUE_TYPE(ntp_snippets::kArticleSuggestionsFeature, + kRemoteSuggestionsFeatureVariations, + "NTPArticleSuggestions")}, {"enable-ntp-asset-download-suggestions", flag_descriptions::kEnableNtpAssetDownloadSuggestionsName, flag_descriptions::kEnableNtpAssetDownloadSuggestionsDescription, @@ -2706,7 +2712,7 @@ FEATURE_WITH_PARAMS_VALUE_TYPE( ntp_snippets::kNotificationsFeature, kContentSuggestionsNotificationsFeatureVariations, - ntp_snippets::kNotificationsFeature.name)}, + "ContentSuggestionsNotifications")}, {"simplified-ntp", flag_descriptions::kSimplifiedNtpName, flag_descriptions::kSimplifiedNtpDescription, kOsAndroid, FEATURE_VALUE_TYPE(chrome::android::kSimplifiedNTP)}, @@ -4086,13 +4092,6 @@ flag_descriptions::kExperimentalProductivityFeaturesDescription, kOsAll, FEATURE_VALUE_TYPE(features::kExperimentalProductivityFeatures)}, -#if defined(OS_CHROMEOS) - {"enable-overview-swipe-to-close", - flag_descriptions::kEnableOverviewSwipeToCloseName, - flag_descriptions::kEnableOverviewSwipeToCloseDescription, kOsCrOS, - FEATURE_VALUE_TYPE(ash::features::kOverviewSwipeToClose)}, -#endif // OS_CHROMEOS - #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) {"ntp-backgrounds", flag_descriptions::kNtpBackgroundsName, flag_descriptions::kNtpBackgroundsDescription, kOsDesktop,
diff --git a/chrome/browser/android/vr/autocomplete_controller.cc b/chrome/browser/android/vr/autocomplete_controller.cc index 469f4d3..1b1ac73 100644 --- a/chrome/browser/android/vr/autocomplete_controller.cc +++ b/chrome/browser/android/vr/autocomplete_controller.cc
@@ -74,8 +74,7 @@ void AutocompleteController::OnResultChanged(bool default_match_changed) { auto suggestions = std::make_unique<OmniboxSuggestions>(); for (const auto& match : autocomplete_controller_->result()) { - const gfx::VectorIcon* icon = &AutocompleteMatch::TypeToVectorIcon( - match.type, false, match.document_type); + const gfx::VectorIcon* icon = &match.GetVectorIcon(false); suggestions->suggestions.emplace_back(OmniboxSuggestion( match.contents, match.description, match.contents_class, match.description_class, icon, match.destination_url,
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc index e5f9091..290b051 100644 --- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc +++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
@@ -496,8 +496,9 @@ std::unique_ptr<DomainReliabilityMonitor> CreateMonitor( scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, - scoped_refptr<base::SingleThreadTaskRunner> network_task_runner) - override { + scoped_refptr<base::SingleThreadTaskRunner> network_task_runner, + const domain_reliability::DomainReliabilityContext::UploadAllowedCallback& + upload_allowed_callback) override { NOTREACHED(); return std::unique_ptr<DomainReliabilityMonitor>(); } @@ -545,6 +546,21 @@ base::Callback<bool(const GURL&)> last_filter_; }; +class DomainReliablityKeyedServiceWrapper : public KeyedService { + public: + explicit DomainReliablityKeyedServiceWrapper( + std::unique_ptr<DomainReliabilityService> service) + : service_(std::move(service)) {} + ~DomainReliablityKeyedServiceWrapper() override = default; + + DomainReliabilityService* service() { return service_.get(); } + + private: + std::unique_ptr<DomainReliabilityService> service_; + + DISALLOW_COPY_AND_ASSIGN(DomainReliablityKeyedServiceWrapper); +}; + struct TestingDomainReliabilityServiceFactoryUserData : public base::SupportsUserData::Data { TestingDomainReliabilityServiceFactoryUserData( @@ -578,7 +594,8 @@ EXPECT_FALSE(data->attached); data->attached = true; - return base::WrapUnique(data->service); + return std::make_unique<DomainReliablityKeyedServiceWrapper>( + base::WrapUnique(data->service)); } std::unique_ptr<KeyedService> BuildProtocolHandlerRegistry(
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 82544f4..e4c89b9 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -17,10 +17,10 @@ #include "base/i18n/base_i18n_switches.h" #include "base/i18n/character_encoding.h" #include "base/json/json_reader.h" -#include "base/lazy_instance.h" #include "base/macros.h" #include "base/metrics/field_trial_params.h" #include "base/metrics/histogram_macros.h" +#include "base/no_destructor.h" #include "base/path_service.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" @@ -594,11 +594,6 @@ namespace { -// Cached version of the locale so we can return the locale on the I/O -// thread. -base::LazyInstance<std::string>::DestructorAtExit - g_io_thread_application_locale = LAZY_INSTANCE_INITIALIZER; - const storage::QuotaSettings* g_default_quota_settings; #if BUILDFLAG(ENABLE_PLUGINS) @@ -658,6 +653,13 @@ APP_LOADED_IN_TAB_SOURCE_MAX }; +// Cached version of the locale so we can return the locale on the I/O +// thread. +std::string& GetIOThreadApplicationLocale() { + static base::NoDestructor<std::string> s; + return *s; +} + // Returns a copy of the given url with its host set to given host and path set // to given path. Other parts of the url will be the same. GURL ReplaceURLHostAndPath(const GURL& url, @@ -827,7 +829,7 @@ void SetApplicationLocaleOnIOThread(const std::string& locale) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - g_io_thread_application_locale.Get() = locale; + GetIOThreadApplicationLocale() = locale; } // An implementation of the SSLCertReporter interface used by @@ -1091,7 +1093,7 @@ // before any threads are created or registered. When there are no threads, // we can just set the string without worrying about threadsafety. if (!BrowserThread::IsThreadInitialized(BrowserThread::IO)) { - g_io_thread_application_locale.Get() = locale; + GetIOThreadApplicationLocale() = locale; return; } @@ -2200,7 +2202,7 @@ std::string ChromeContentBrowserClient::GetApplicationLocale() { if (BrowserThread::CurrentlyOn(BrowserThread::IO)) - return g_io_thread_application_locale.Get(); + return GetIOThreadApplicationLocale(); return g_browser_process->GetApplicationLocale(); }
diff --git a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc index 396de6d5..15b16c6 100644 --- a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc +++ b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc
@@ -4,7 +4,7 @@ #include "chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.h" -#include <memory> +#include <set> #include <sstream> #include <utility> @@ -19,6 +19,7 @@ #include "base/metrics/statistics_recorder.h" #include "base/strings/strcat.h" #include "base/strings/string_number_conversions.h" +#include "base/task/post_task.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "base/values.h" @@ -979,6 +980,76 @@ } /////////////////////////////////////////////////////////////////////////////// +// AutotestPrivateSetAssistantEnabled +/////////////////////////////////////////////////////////////////////////////// + +AutotestPrivateSetAssistantEnabledFunction:: + AutotestPrivateSetAssistantEnabledFunction() { + auto* connection = content::ServiceManagerConnection::GetForProcess(); + assistant_state_.Init(connection->GetConnector()); + assistant_state_.AddObserver(this); +} + +AutotestPrivateSetAssistantEnabledFunction:: + ~AutotestPrivateSetAssistantEnabledFunction() { + assistant_state_.RemoveObserver(this); +} + +ExtensionFunction::ResponseAction +AutotestPrivateSetAssistantEnabledFunction::Run() { + DVLOG(1) << "AutotestPrivateSetAssistantEnabledFunction"; + + std::unique_ptr<api::autotest_private::SetAssistantEnabled::Params> params( + api::autotest_private::SetAssistantEnabled::Params::Create(*args_)); + EXTENSION_FUNCTION_VALIDATE(params); + + Profile* profile = Profile::FromBrowserContext(browser_context()); + if (arc::IsAssistantAllowedForProfile(profile) != + ash::mojom::AssistantAllowedState::ALLOWED) { + return RespondNow(Error("Assistant is not available for the current user")); + } + + profile->GetPrefs()->SetBoolean(arc::prefs::kVoiceInteractionEnabled, + params->enabled); + // |NOT_READY| means service not running + // |STOPPED| means service running but UI not shown + auto new_state = params->enabled + ? ash::mojom::VoiceInteractionState::STOPPED + : ash::mojom::VoiceInteractionState::NOT_READY; + + if (assistant_state_.voice_interaction_state() == new_state) + return RespondNow(NoArguments()); + + // Assistant service has not responded yet, set up a delayed timer to wait for + // it and holder a reference to |this|. Also make sure we stop and respond + // when timeout. + expected_state_ = new_state; + timeout_timer_.Start( + FROM_HERE, base::TimeDelta::FromMilliseconds(params->timeout_ms), + base::BindOnce(&AutotestPrivateSetAssistantEnabledFunction::Timeout, + this)); + return RespondLater(); +} + +void AutotestPrivateSetAssistantEnabledFunction:: + OnVoiceInteractionStatusChanged(ash::mojom::VoiceInteractionState state) { + DCHECK(expected_state_); + + // The service could go through |NOT_READY| then to |STOPPED| during enable + // flow if this API is called before the initial state is reported. + if (expected_state_ != state) + return; + + Respond(NoArguments()); + expected_state_.reset(); + timeout_timer_.AbandonAndStop(); +} + +void AutotestPrivateSetAssistantEnabledFunction::Timeout() { + Respond(Error("Assistant service timed out")); +} + +/////////////////////////////////////////////////////////////////////////////// // AutotestPrivateAPI ///////////////////////////////////////////////////////////////////////////////
diff --git a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.h b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.h index 05a4442..e607bd93 100644 --- a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.h +++ b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.h
@@ -5,10 +5,15 @@ #ifndef CHROME_BROWSER_CHROMEOS_EXTENSIONS_AUTOTEST_PRIVATE_AUTOTEST_PRIVATE_API_H_ #define CHROME_BROWSER_CHROMEOS_EXTENSIONS_AUTOTEST_PRIVATE_AUTOTEST_PRIVATE_API_H_ +#include <memory> #include <string> +#include <vector> +#include "ash/public/cpp/assistant/assistant_state_proxy.h" +#include "ash/public/cpp/assistant/default_voice_interaction_observer.h" #include "ash/public/interfaces/ash_message_center_controller.mojom.h" #include "base/compiler_specific.h" +#include "base/timer/timer.h" #include "chrome/browser/chromeos/printing/cups_printers_manager.h" #include "chrome/browser/extensions/chrome_extension_function.h" #include "chromeos/services/machine_learning/public/mojom/machine_learning_service.mojom.h" @@ -360,6 +365,33 @@ chromeos::machine_learning::mojom::ModelPtr model_; }; +// Enable/disable the Google Assistant feature. This toggles the Assistant user +// pref which will indirectly bring up or shut down the Assistant service. +class AutotestPrivateSetAssistantEnabledFunction + : public UIThreadExtensionFunction, + public ash::DefaultVoiceInteractionObserver { + public: + AutotestPrivateSetAssistantEnabledFunction(); + DECLARE_EXTENSION_FUNCTION("autotestPrivate.setAssistantEnabled", + AUTOTESTPRIVATE_SETASSISTANTENABLED) + + private: + ~AutotestPrivateSetAssistantEnabledFunction() override; + ResponseAction Run() override; + + // ash::DefaultVoiceInteractionObserver overrides: + void OnVoiceInteractionStatusChanged( + ash::mojom::VoiceInteractionState state) override; + + // Called when the Assistant service does not respond in a timely fashion. We + // will respond with an error. + void Timeout(); + + ash::AssistantStateProxy assistant_state_; + base::Optional<ash::mojom::VoiceInteractionState> expected_state_; + base::OneShotTimer timeout_timer_; +}; + // The profile-keyed service that manages the autotestPrivate extension API. class AutotestPrivateAPI : public BrowserContextKeyedAPI { public:
diff --git a/chrome/browser/domain_reliability/service_factory.cc b/chrome/browser/domain_reliability/service_factory.cc index ba9957c..d6d7c4c 100644 --- a/chrome/browser/domain_reliability/service_factory.cc +++ b/chrome/browser/domain_reliability/service_factory.cc
@@ -11,6 +11,7 @@ #include "chrome/common/chrome_switches.h" #include "components/domain_reliability/service.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" +#include "components/keyed_service/core/keyed_service.h" #include "content/public/browser/browser_context.h" #if defined(OS_CHROMEOS) @@ -31,15 +32,32 @@ // Identifies Chrome as the source of Domain Reliability uploads it sends. const char kUploadReporterString[] = "chrome"; +class KeyedServiceWrapper : public KeyedService { + public: + explicit KeyedServiceWrapper(DomainReliabilityService* service) + : service_(service) {} + ~KeyedServiceWrapper() override = default; + + DomainReliabilityService* service() { return service_; } + + private: + DomainReliabilityService* service_; + + DISALLOW_COPY_AND_ASSIGN(KeyedServiceWrapper); +}; + } // namespace // static DomainReliabilityService* DomainReliabilityServiceFactory::GetForBrowserContext( content::BrowserContext* context) { - return static_cast<DomainReliabilityService*>( + auto* wrapper = static_cast<KeyedServiceWrapper*>( GetInstance()->GetServiceForBrowserContext(context, /* create = */ true)); + if (!wrapper) + return nullptr; + return wrapper->service(); } // static @@ -60,7 +78,8 @@ if (!ShouldCreateService()) return NULL; - return DomainReliabilityService::Create(kUploadReporterString, context); + return new KeyedServiceWrapper( + DomainReliabilityService::Create(kUploadReporterString)); } bool DomainReliabilityServiceFactory::ShouldCreateService() const {
diff --git a/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_unittest.cc b/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_unittest.cc index 4e9bf45..5e55faf2 100644 --- a/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_unittest.cc +++ b/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_unittest.cc
@@ -67,6 +67,7 @@ std::string InitClientId() override { return client_id_; } std::string InitEnrollmentToken() override { return std::string(); } std::string InitDMToken() override { return std::string(); } + bool InitEnrollmentErrorOption() override { return true; } void SaveDMToken(const std::string& token) override {} private:
diff --git a/chrome/browser/extensions/api/web_navigation/web_navigation_api.cc b/chrome/browser/extensions/api/web_navigation/web_navigation_api.cc index b9f0f646..8cc89e22 100644 --- a/chrome/browser/extensions/api/web_navigation/web_navigation_api.cc +++ b/chrome/browser/extensions/api/web_navigation/web_navigation_api.cc
@@ -8,7 +8,7 @@ #include <memory> -#include "base/lazy_instance.h" +#include "base/no_destructor.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/extensions/api/web_navigation/web_navigation_api_constants.h" #include "chrome/browser/extensions/api/web_navigation/web_navigation_api_helpers.h" @@ -39,10 +39,13 @@ namespace { -typedef std::map<content::WebContents*, WebNavigationTabObserver*> - TabObserverMap; -static base::LazyInstance<TabObserverMap>::DestructorAtExit g_tab_observer = - LAZY_INSTANCE_INITIALIZER; +using TabObserverMap = + std::map<content::WebContents*, WebNavigationTabObserver*>; + +TabObserverMap& GetTabObserverMap() { + static base::NoDestructor<TabObserverMap> s; + return *s; +} } // namespace @@ -121,7 +124,6 @@ const content::NotificationSource& source, const content::NotificationDetails& details) { switch (type) { - case chrome::NOTIFICATION_TAB_ADDED: TabAdded(content::Details<content::WebContents>(details).ptr()); break; @@ -212,7 +214,7 @@ WebNavigationTabObserver::WebNavigationTabObserver( content::WebContents* web_contents) : WebContentsObserver(web_contents) { - g_tab_observer.Get().insert(TabObserverMap::value_type(web_contents, this)); + GetTabObserverMap().insert(TabObserverMap::value_type(web_contents, this)); navigation_state_.FrameHostCreated(web_contents->GetMainFrame()); } @@ -221,8 +223,8 @@ // static WebNavigationTabObserver* WebNavigationTabObserver::Get( content::WebContents* web_contents) { - auto i = g_tab_observer.Get().find(web_contents); - return i == g_tab_observer.Get().end() ? NULL : i->second; + auto i = GetTabObserverMap().find(web_contents); + return i == GetTabObserverMap().end() ? NULL : i->second; } void WebNavigationTabObserver::RenderFrameDeleted( @@ -400,7 +402,7 @@ } void WebNavigationTabObserver::WebContentsDestroyed() { - g_tab_observer.Get().erase(web_contents()); + GetTabObserverMap().erase(web_contents()); registrar_.RemoveAll(); }
diff --git a/chrome/browser/extensions/install_signer.cc b/chrome/browser/extensions/install_signer.cc index 93fe6da..d0aa12d 100644 --- a/chrome/browser/extensions/install_signer.cc +++ b/chrome/browser/extensions/install_signer.cc
@@ -279,7 +279,7 @@ namespace { -static int g_request_count = 0; +int g_request_count = 0; base::LazyInstance<base::TimeTicks>::DestructorAtExit g_last_request_time = LAZY_INSTANCE_INITIALIZER;
diff --git a/chrome/browser/extensions/updater/extension_update_client_base_browsertest.cc b/chrome/browser/extensions/updater/extension_update_client_base_browsertest.cc index 568a461b..55f89e4 100644 --- a/chrome/browser/extensions/updater/extension_update_client_base_browsertest.cc +++ b/chrome/browser/extensions/updater/extension_update_client_base_browsertest.cc
@@ -12,6 +12,7 @@ #include "chrome/browser/chrome_browser_main.h" #include "chrome/browser/chrome_browser_main_extra_parts.h" #include "chrome/browser/extensions/browsertest_util.h" +#include "components/update_client/protocol_handler.h" #include "components/update_client/url_loader_post_interceptor.h" #include "content/public/browser/browser_context.h" #include "extensions/browser/updater/update_service.h" @@ -30,22 +31,33 @@ : public extensions::ChromeUpdateClientConfig { public: TestChromeUpdateClientConfig(content::BrowserContext* context, + bool use_JSON, const std::vector<GURL>& update_url, const std::vector<GURL>& ping_url) : extensions::ChromeUpdateClientConfig(context), + use_JSON_(use_JSON), update_url_(update_url), ping_url_(ping_url) {} + // Overrides for update_client::Configurator. std::vector<GURL> UpdateUrl() const final { return update_url_; } std::vector<GURL> PingUrl() const final { return ping_url_; } bool EnabledCupSigning() const final { return false; } + std::unique_ptr<update_client::ProtocolHandlerFactory> + GetProtocolHandlerFactory() const final { + if (use_JSON_) + return std::make_unique<update_client::ProtocolHandlerFactoryJSON>(); + return std::make_unique<update_client::ProtocolHandlerFactoryXml>(); + } + protected: ~TestChromeUpdateClientConfig() override = default; private: + bool use_JSON_ = false; std::vector<GURL> update_url_; std::vector<GURL> ping_url_; @@ -105,9 +117,10 @@ } // namespace -ExtensionUpdateClientBaseTest::ExtensionUpdateClientBaseTest() +ExtensionUpdateClientBaseTest::ExtensionUpdateClientBaseTest(bool use_JSON) : https_server_for_update_(net::EmbeddedTestServer::TYPE_HTTPS), - https_server_for_ping_(net::EmbeddedTestServer::TYPE_HTTPS) {} + https_server_for_ping_(net::EmbeddedTestServer::TYPE_HTTPS), + use_JSON_(use_JSON) {} ExtensionUpdateClientBaseTest::~ExtensionUpdateClientBaseTest() {} @@ -123,12 +136,12 @@ ExtensionUpdateClientBaseTest::ChromeUpdateClientConfigFactory() const { return base::BindRepeating( [](const std::vector<GURL>& update_url, const std::vector<GURL>& ping_url, - content::BrowserContext* context) + bool use_JSON, content::BrowserContext* context) -> scoped_refptr<ChromeUpdateClientConfig> { return base::MakeRefCounted<TestChromeUpdateClientConfig>( - context, update_url, ping_url); + context, use_JSON, update_url, ping_url); }, - GetUpdateUrls(), GetPingUrls()); + GetUpdateUrls(), GetPingUrls(), use_JSON_); } void ExtensionUpdateClientBaseTest::SetUp() {
diff --git a/chrome/browser/extensions/updater/extension_update_client_base_browsertest.h b/chrome/browser/extensions/updater/extension_update_client_base_browsertest.h index 025e784..dd17e73 100644 --- a/chrome/browser/extensions/updater/extension_update_client_base_browsertest.h +++ b/chrome/browser/extensions/updater/extension_update_client_base_browsertest.h
@@ -5,6 +5,11 @@ #ifndef CHROME_BROWSER_EXTENSIONS_UPDATER_EXTENSION_UPDATE_CLIENT_BASE_BROWSERTEST_H_ #define CHROME_BROWSER_EXTENSIONS_UPDATER_EXTENSION_UPDATE_CLIENT_BASE_BROWSERTEST_H_ +#include <memory> +#include <string> +#include <utility> +#include <vector> + #include "base/memory/ref_counted.h" #include "chrome/browser/extensions/extension_browsertest.h" #include "chrome/browser/extensions/updater/chrome_update_client_config.h" @@ -35,7 +40,7 @@ public: using ConfigFactoryCallback = ChromeUpdateClientConfig::FactoryCallback; - ExtensionUpdateClientBaseTest(); + explicit ExtensionUpdateClientBaseTest(bool use_JSON); ~ExtensionUpdateClientBaseTest() override; // ExtensionBrowserTest: @@ -82,6 +87,8 @@ net::EmbeddedTestServer https_server_for_update_; net::EmbeddedTestServer https_server_for_ping_; + bool use_JSON_ = false; + private: bool OnRequest(content::URLLoaderInterceptor::RequestParams* params);
diff --git a/chrome/browser/extensions/updater/update_service_browsertest.cc b/chrome/browser/extensions/updater/update_service_browsertest.cc index 5141dae..7e2c0b8f 100644 --- a/chrome/browser/extensions/updater/update_service_browsertest.cc +++ b/chrome/browser/extensions/updater/update_service_browsertest.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "base/command_line.h" +#include "base/json/json_reader.h" #include "base/run_loop.h" #include "base/test/bind_test_util.h" #include "base/test/metrics/histogram_tester.h" @@ -38,9 +39,10 @@ } // namespace -class UpdateServiceTest : public ExtensionUpdateClientBaseTest { +class UpdateServiceTest : public ExtensionUpdateClientBaseTest, + public testing::WithParamInterface<bool> { public: - UpdateServiceTest() {} + UpdateServiceTest() : ExtensionUpdateClientBaseTest(GetParam()) {} ~UpdateServiceTest() override {} void SetUpCommandLine(base::CommandLine* command_line) override { @@ -53,17 +55,27 @@ bool ShouldEnableContentVerification() override { return true; } }; -IN_PROC_BROWSER_TEST_F(UpdateServiceTest, NoUpdate) { +// This test is parameterized for using JSON or XML serialization. |true| means +// JSON serialization is used. +INSTANTIATE_TEST_CASE_P(Parameterized, UpdateServiceTest, testing::Bool()); + +IN_PROC_BROWSER_TEST_P(UpdateServiceTest, NoUpdate) { // Verify that UpdateService runs correctly when there's no update. base::ScopedAllowBlockingForTesting allow_io; base::HistogramTester histogram_tester; // Mock a no-update response. - const base::FilePath update_response = - test_data_dir_.AppendASCII("updater/updatecheck_reply_noupdate_1.xml"); - ASSERT_TRUE(update_interceptor_->ExpectRequest( - std::make_unique<update_client::PartialMatch>("<updatecheck/>"), - update_response)); + if (use_JSON_) { + ASSERT_TRUE(update_interceptor_->ExpectRequest( + std::make_unique<update_client::PartialMatch>(R"("updatecheck":{)"), + test_data_dir_.AppendASCII( + "updater/updatecheck_reply_noupdate_1.json"))); + } else { + ASSERT_TRUE(update_interceptor_->ExpectRequest( + std::make_unique<update_client::PartialMatch>("<updatecheck/>"), + test_data_dir_.AppendASCII( + "updater/updatecheck_reply_noupdate_1.xml"))); + } const base::FilePath crx_path = test_data_dir_.AppendASCII("updater/v1.crx"); const Extension* extension = @@ -104,22 +116,36 @@ const std::string update_request = std::get<0>(update_interceptor_->GetRequests()[0]); - EXPECT_THAT(update_request, - ::testing::HasSubstr(base::StringPrintf( - R"(<app appid="%s" version="0.10")", kExtensionId))); - EXPECT_THAT(update_request, ::testing::HasSubstr(R"(enabled="1")")); + if (use_JSON_) { + const auto root = base::JSONReader().Read(update_request); + const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; + EXPECT_EQ(kExtensionId, app.FindKey("appid")->GetString()); + EXPECT_EQ("0.10", app.FindKey("version")->GetString()); + EXPECT_TRUE(app.FindKey("enabled")->GetBool()); + } else { + EXPECT_THAT(update_request, + ::testing::HasSubstr(base::StringPrintf( + R"(<app appid="%s" version="0.10")", kExtensionId))); + EXPECT_THAT(update_request, ::testing::HasSubstr(R"(enabled="1")")); + } } -IN_PROC_BROWSER_TEST_F(UpdateServiceTest, UpdateCheckError) { +IN_PROC_BROWSER_TEST_P(UpdateServiceTest, UpdateCheckError) { // Verify that UpdateService works correctly when there's an error in the // update check phase. base::ScopedAllowBlockingForTesting allow_io; base::HistogramTester histogram_tester; // Mock an update check error. - ASSERT_TRUE(update_interceptor_->ExpectRequest( - std::make_unique<update_client::PartialMatch>("<updatecheck/>"), - net::HTTP_FORBIDDEN)); + if (use_JSON_) { + ASSERT_TRUE(update_interceptor_->ExpectRequest( + std::make_unique<update_client::PartialMatch>(R"("updatecheck":{)"), + net::HTTP_FORBIDDEN)); + } else { + ASSERT_TRUE(update_interceptor_->ExpectRequest( + std::make_unique<update_client::PartialMatch>("<updatecheck/>"), + net::HTTP_FORBIDDEN)); + } const base::FilePath crx_path = test_data_dir_.AppendASCII("updater/v1.crx"); const Extension* extension = @@ -162,25 +188,42 @@ const std::string update_request = std::get<0>(update_interceptor_->GetRequests()[0]); - EXPECT_THAT(update_request, - ::testing::HasSubstr(base::StringPrintf( - R"(<app appid="%s" version="0.10")", kExtensionId))); - EXPECT_THAT(update_request, ::testing::HasSubstr(R"(enabled="1")")); + if (use_JSON_) { + const auto root = base::JSONReader().Read(update_request); + const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; + EXPECT_EQ(kExtensionId, app.FindKey("appid")->GetString()); + EXPECT_EQ("0.10", app.FindKey("version")->GetString()); + EXPECT_TRUE(app.FindKey("enabled")->GetBool()); + } else { + EXPECT_THAT(update_request, + ::testing::HasSubstr(base::StringPrintf( + R"(<app appid="%s" version="0.10")", kExtensionId))); + EXPECT_THAT(update_request, ::testing::HasSubstr(R"(enabled="1")")); + } } -IN_PROC_BROWSER_TEST_F(UpdateServiceTest, TwoUpdateCheckErrors) { +IN_PROC_BROWSER_TEST_P(UpdateServiceTest, TwoUpdateCheckErrors) { // Verify that the UMA counters are emitted properly when there are 2 update // checks with different number of extensions, both of which result in errors. base::ScopedAllowBlockingForTesting allow_io; base::HistogramTester histogram_tester; // Mock update check errors. - ASSERT_TRUE(update_interceptor_->ExpectRequest( - std::make_unique<update_client::PartialMatch>("<updatecheck/>"), - net::HTTP_NOT_MODIFIED)); - ASSERT_TRUE(update_interceptor_->ExpectRequest( - std::make_unique<update_client::PartialMatch>("<updatecheck/>"), - net::HTTP_USE_PROXY)); + if (use_JSON_) { + ASSERT_TRUE(update_interceptor_->ExpectRequest( + std::make_unique<update_client::PartialMatch>(R"("updatecheck":{)"), + net::HTTP_NOT_MODIFIED)); + ASSERT_TRUE(update_interceptor_->ExpectRequest( + std::make_unique<update_client::PartialMatch>(R"("updatecheck":{)"), + net::HTTP_USE_PROXY)); + } else { + ASSERT_TRUE(update_interceptor_->ExpectRequest( + std::make_unique<update_client::PartialMatch>("<updatecheck/>"), + net::HTTP_NOT_MODIFIED)); + ASSERT_TRUE(update_interceptor_->ExpectRequest( + std::make_unique<update_client::PartialMatch>("<updatecheck/>"), + net::HTTP_USE_PROXY)); + } const base::FilePath crx_path1 = test_data_dir_.AppendASCII("updater/v1.crx"); const base::FilePath crx_path2 = test_data_dir_.AppendASCII("updater/v2.crx"); @@ -230,23 +273,36 @@ << ping_interceptor_->GetRequestsAsString(); } -IN_PROC_BROWSER_TEST_F(UpdateServiceTest, SuccessfulUpdate) { +IN_PROC_BROWSER_TEST_P(UpdateServiceTest, SuccessfulUpdate) { base::ScopedAllowBlockingForTesting allow_io; base::HistogramTester histogram_tester; // Mock an update response. - const base::FilePath update_response = - test_data_dir_.AppendASCII("updater/updatecheck_reply_update_1.xml"); - const base::FilePath ping_response = - test_data_dir_.AppendASCII("updater/ping_reply_1.xml"); - const base::FilePath crx_path = test_data_dir_.AppendASCII("updater/v1.crx"); + if (use_JSON_) { + const base::FilePath update_response = + test_data_dir_.AppendASCII("updater/updatecheck_reply_update_1.json"); + const base::FilePath ping_response = + test_data_dir_.AppendASCII("updater/ping_reply_1.json"); + ASSERT_TRUE(update_interceptor_->ExpectRequest( + std::make_unique<update_client::PartialMatch>(R"("updatecheck":{)"), + update_response)); + ASSERT_TRUE(ping_interceptor_->ExpectRequest( + std::make_unique<update_client::PartialMatch>(R"("eventtype":)"), + ping_response)); + } else { + const base::FilePath update_response = + test_data_dir_.AppendASCII("updater/updatecheck_reply_update_1.xml"); + const base::FilePath ping_response = + test_data_dir_.AppendASCII("updater/ping_reply_1.xml"); + ASSERT_TRUE(update_interceptor_->ExpectRequest( + std::make_unique<update_client::PartialMatch>("<updatecheck/>"), + update_response)); + ASSERT_TRUE(ping_interceptor_->ExpectRequest( + std::make_unique<update_client::PartialMatch>("eventtype"), + ping_response)); + } - ASSERT_TRUE(update_interceptor_->ExpectRequest( - std::make_unique<update_client::PartialMatch>("<updatecheck/>"), - update_response)); - ASSERT_TRUE(ping_interceptor_->ExpectRequest( - std::make_unique<update_client::PartialMatch>("eventtype"), - ping_response)); + const base::FilePath crx_path = test_data_dir_.AppendASCII("updater/v1.crx"); set_interceptor_hook(base::BindLambdaForTesting( [&](content::URLLoaderInterceptor::RequestParams* params) { if (params->url_request.url.path() != "/download/v1.crx") @@ -295,30 +351,51 @@ const std::string update_request = std::get<0>(update_interceptor_->GetRequests()[0]); - EXPECT_THAT(update_request, - ::testing::HasSubstr(base::StringPrintf( - R"(<app appid="%s" version="0.10")", kExtensionId))); - EXPECT_THAT(update_request, ::testing::HasSubstr(R"(enabled="1")")); + if (use_JSON_) { + const auto root = base::JSONReader().Read(update_request); + const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; + EXPECT_EQ(kExtensionId, app.FindKey("appid")->GetString()); + EXPECT_EQ("0.10", app.FindKey("version")->GetString()); + EXPECT_TRUE(app.FindKey("enabled")->GetBool()); + } else { + EXPECT_THAT(update_request, + ::testing::HasSubstr(base::StringPrintf( + R"(<app appid="%s" version="0.10")", kExtensionId))); + EXPECT_THAT(update_request, ::testing::HasSubstr(R"(enabled="1")")); + } } -IN_PROC_BROWSER_TEST_F(UpdateServiceTest, PolicyCorrupted) { +IN_PROC_BROWSER_TEST_P(UpdateServiceTest, PolicyCorrupted) { base::ScopedAllowBlockingForTesting allow_io; ExtensionSystem* system = ExtensionSystem::Get(profile()); ExtensionService* service = extension_service(); - const base::FilePath update_response = - test_data_dir_.AppendASCII("updater/updatecheck_reply_update_1.xml"); - const base::FilePath ping_response = - test_data_dir_.AppendASCII("updater/ping_reply_1.xml"); - const base::FilePath crx_path = test_data_dir_.AppendASCII("updater/v1.crx"); + if (use_JSON_) { + const base::FilePath update_response = + test_data_dir_.AppendASCII("updater/updatecheck_reply_update_1.json"); + const base::FilePath ping_response = + test_data_dir_.AppendASCII("updater/ping_reply_1.json"); + ASSERT_TRUE(update_interceptor_->ExpectRequest( + std::make_unique<update_client::PartialMatch>(R"("updatecheck":{)"), + update_response)); + ASSERT_TRUE(ping_interceptor_->ExpectRequest( + std::make_unique<update_client::PartialMatch>(R"("eventtype":)"), + ping_response)); + } else { + const base::FilePath update_response = + test_data_dir_.AppendASCII("updater/updatecheck_reply_update_1.xml"); + const base::FilePath ping_response = + test_data_dir_.AppendASCII("updater/ping_reply_1.xml"); + ASSERT_TRUE(update_interceptor_->ExpectRequest( + std::make_unique<update_client::PartialMatch>("<updatecheck/>"), + update_response)); + ASSERT_TRUE(ping_interceptor_->ExpectRequest( + std::make_unique<update_client::PartialMatch>("eventtype"), + ping_response)); + } - ASSERT_TRUE(update_interceptor_->ExpectRequest( - std::make_unique<update_client::PartialMatch>("<updatecheck/>"), - update_response)); - ASSERT_TRUE(ping_interceptor_->ExpectRequest( - std::make_unique<update_client::PartialMatch>("eventtype"), - ping_response)); + const base::FilePath crx_path = test_data_dir_.AppendASCII("updater/v1.crx"); set_interceptor_hook(base::BindLambdaForTesting( [&](content::URLLoaderInterceptor::RequestParams* params) { if (params->url_request.url.path() != "/download/v1.crx") @@ -379,19 +456,32 @@ // - <disabled reason="1024"/> const std::string update_request = std::get<0>(update_interceptor_->GetRequests()[0]); - EXPECT_THAT(update_request, - ::testing::HasSubstr(base::StringPrintf( - R"(<app appid="%s" version="0.0.0.0")", kExtensionId))); - EXPECT_THAT( - update_request, - ::testing::HasSubstr( - R"(installsource="reinstall" installedby="policy" enabled="0")")); - EXPECT_THAT(update_request, ::testing::HasSubstr(base::StringPrintf( - R"(<disabled reason="%d"/>)", - disable_reason::DISABLE_CORRUPTED))); + if (use_JSON_) { + const auto root = base::JSONReader().Read(update_request); + const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; + EXPECT_EQ(kExtensionId, app.FindKey("appid")->GetString()); + EXPECT_EQ("0.0.0.0", app.FindKey("version")->GetString()); + EXPECT_EQ("reinstall", app.FindKey("installsource")->GetString()); + EXPECT_EQ("policy", app.FindKey("installedby")->GetString()); + EXPECT_FALSE(app.FindKey("enabled")->GetBool()); + const auto& disabled = app.FindKey("disabled")->GetList()[0]; + EXPECT_EQ(disable_reason::DISABLE_CORRUPTED, + disabled.FindKey("reason")->GetInt()); + } else { + EXPECT_THAT(update_request, + ::testing::HasSubstr(base::StringPrintf( + R"(<app appid="%s" version="0.0.0.0")", kExtensionId))); + EXPECT_THAT( + update_request, + ::testing::HasSubstr( + R"(installsource="reinstall" installedby="policy" enabled="0")")); + EXPECT_THAT(update_request, ::testing::HasSubstr(base::StringPrintf( + R"(<disabled reason="%d"/>)", + disable_reason::DISABLE_CORRUPTED))); + } } -IN_PROC_BROWSER_TEST_F(UpdateServiceTest, UninstallExtensionWhileUpdating) { +IN_PROC_BROWSER_TEST_P(UpdateServiceTest, UninstallExtensionWhileUpdating) { // This test is to verify that the extension updater engine (update client) // works correctly when an extension is uninstalled when the extension updater // is in progress. @@ -427,9 +517,10 @@ EXPECT_EQ(0, get_interceptor_count()); } -class PolicyUpdateServiceTest : public ExtensionUpdateClientBaseTest { +class PolicyUpdateServiceTest : public ExtensionUpdateClientBaseTest, + public testing::WithParamInterface<bool> { public: - PolicyUpdateServiceTest() {} + PolicyUpdateServiceTest() : ExtensionUpdateClientBaseTest(GetParam()) {} ~PolicyUpdateServiceTest() override {} void SetUpCommandLine(base::CommandLine* command_line) override { @@ -465,11 +556,6 @@ const base::FilePath crx_path = test_data_dir_.AppendASCII("updater/v1.crx"); - const base::FilePath update_response = - test_data_dir_.AppendASCII("updater/updatecheck_reply_update_1.xml"); - const base::FilePath ping_response = - test_data_dir_.AppendASCII("updater/ping_reply_1.xml"); - set_interceptor_hook(base::BindLambdaForTesting( [=](content::URLLoaderInterceptor::RequestParams* params) { if (params->url_request.url.path() != "/download/v1.crx") @@ -479,30 +565,67 @@ params->client.get()); return true; })); - ASSERT_TRUE(update_interceptor_->ExpectRequest( - std::make_unique<update_client::PartialMatch>("<updatecheck/>"), - update_response)); - ASSERT_TRUE(update_interceptor_->ExpectRequest( - std::make_unique<update_client::PartialMatch>("<updatecheck/>"), - update_response)); - ASSERT_TRUE(update_interceptor_->ExpectRequest( - std::make_unique<update_client::PartialMatch>("<updatecheck/>"), - update_response)); - ASSERT_TRUE(update_interceptor_->ExpectRequest( - std::make_unique<update_client::PartialMatch>("<updatecheck/>"), - update_response)); - ASSERT_TRUE(ping_interceptor_->ExpectRequest( - std::make_unique<update_client::PartialMatch>("eventtype"), - ping_response)); - ASSERT_TRUE(ping_interceptor_->ExpectRequest( - std::make_unique<update_client::PartialMatch>("eventtype"), - ping_response)); - ASSERT_TRUE(ping_interceptor_->ExpectRequest( - std::make_unique<update_client::PartialMatch>("eventtype"), - ping_response)); - ASSERT_TRUE(ping_interceptor_->ExpectRequest( - std::make_unique<update_client::PartialMatch>("eventtype"), - ping_response)); + if (use_JSON_) { + const base::FilePath update_response = + test_data_dir_.AppendASCII("updater/updatecheck_reply_update_1.json"); + const base::FilePath ping_response = + test_data_dir_.AppendASCII("updater/ping_reply_1.json"); + + ASSERT_TRUE(update_interceptor_->ExpectRequest( + std::make_unique<update_client::PartialMatch>(R"("updatecheck":{)"), + update_response)); + ASSERT_TRUE(update_interceptor_->ExpectRequest( + std::make_unique<update_client::PartialMatch>(R"("updatecheck":{)"), + update_response)); + ASSERT_TRUE(update_interceptor_->ExpectRequest( + std::make_unique<update_client::PartialMatch>(R"("updatecheck":{)"), + update_response)); + ASSERT_TRUE(update_interceptor_->ExpectRequest( + std::make_unique<update_client::PartialMatch>(R"("updatecheck":{)"), + update_response)); + ASSERT_TRUE(ping_interceptor_->ExpectRequest( + std::make_unique<update_client::PartialMatch>(R"("eventtype":)"), + ping_response)); + ASSERT_TRUE(ping_interceptor_->ExpectRequest( + std::make_unique<update_client::PartialMatch>(R"("eventtype":)"), + ping_response)); + ASSERT_TRUE(ping_interceptor_->ExpectRequest( + std::make_unique<update_client::PartialMatch>(R"("eventtype":)"), + ping_response)); + ASSERT_TRUE(ping_interceptor_->ExpectRequest( + std::make_unique<update_client::PartialMatch>(R"("eventtype":)"), + ping_response)); + } else { + const base::FilePath update_response = + test_data_dir_.AppendASCII("updater/updatecheck_reply_update_1.xml"); + const base::FilePath ping_response = + test_data_dir_.AppendASCII("updater/ping_reply_1.xml"); + + ASSERT_TRUE(update_interceptor_->ExpectRequest( + std::make_unique<update_client::PartialMatch>("<updatecheck/>"), + update_response)); + ASSERT_TRUE(update_interceptor_->ExpectRequest( + std::make_unique<update_client::PartialMatch>("<updatecheck/>"), + update_response)); + ASSERT_TRUE(update_interceptor_->ExpectRequest( + std::make_unique<update_client::PartialMatch>("<updatecheck/>"), + update_response)); + ASSERT_TRUE(update_interceptor_->ExpectRequest( + std::make_unique<update_client::PartialMatch>("<updatecheck/>"), + update_response)); + ASSERT_TRUE(ping_interceptor_->ExpectRequest( + std::make_unique<update_client::PartialMatch>("eventtype"), + ping_response)); + ASSERT_TRUE(ping_interceptor_->ExpectRequest( + std::make_unique<update_client::PartialMatch>("eventtype"), + ping_response)); + ASSERT_TRUE(ping_interceptor_->ExpectRequest( + std::make_unique<update_client::PartialMatch>("eventtype"), + ping_response)); + ASSERT_TRUE(ping_interceptor_->ExpectRequest( + std::make_unique<update_client::PartialMatch>("eventtype"), + ping_response)); + } } std::vector<GURL> GetUpdateUrls() const override { @@ -523,10 +646,16 @@ content_verifier_test::DownloaderTestDelegate downloader_; }; +// This test is parameterized for using JSON or XML serialization. |true| means +// JSON serialization is used. +INSTANTIATE_TEST_CASE_P(Parameterized, + PolicyUpdateServiceTest, + testing::Bool()); + // Tests that if CheckForExternalUpdates() fails, then we retry reinstalling // corrupted policy extensions. For example: if network is unavailable, // CheckForExternalUpdates() will fail. -IN_PROC_BROWSER_TEST_F(PolicyUpdateServiceTest, FailedUpdateRetries) { +IN_PROC_BROWSER_TEST_P(PolicyUpdateServiceTest, FailedUpdateRetries) { ExtensionRegistry* registry = ExtensionRegistry::Get(profile()); ExtensionService* service = extension_service(); ContentVerifier* verifier = @@ -573,19 +702,32 @@ // - <disabled reason="1024"/> const std::string update_request = std::get<0>(update_interceptor_->GetRequests()[0]); - EXPECT_THAT(update_request, - ::testing::HasSubstr(base::StringPrintf( - R"(<app appid="%s" version="0.0.0.0")", id_.c_str()))); - EXPECT_THAT( - update_request, - ::testing::HasSubstr( - R"(installsource="reinstall" installedby="policy" enabled="0")")); - EXPECT_THAT(update_request, ::testing::HasSubstr(base::StringPrintf( - R"(<disabled reason="%d"/>)", - disable_reason::DISABLE_CORRUPTED))); + if (use_JSON_) { + const auto root = base::JSONReader().Read(update_request); + const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; + EXPECT_EQ(id_, app.FindKey("appid")->GetString()); + EXPECT_EQ("0.0.0.0", app.FindKey("version")->GetString()); + EXPECT_EQ("reinstall", app.FindKey("installsource")->GetString()); + EXPECT_EQ("policy", app.FindKey("installedby")->GetString()); + EXPECT_FALSE(app.FindKey("enabled")->GetBool()); + const auto& disabled = app.FindKey("disabled")->GetList()[0]; + EXPECT_EQ(disable_reason::DISABLE_CORRUPTED, + disabled.FindKey("reason")->GetInt()); + } else { + EXPECT_THAT(update_request, + ::testing::HasSubstr(base::StringPrintf( + R"(<app appid="%s" version="0.0.0.0")", id_.c_str()))); + EXPECT_THAT( + update_request, + ::testing::HasSubstr( + R"(installsource="reinstall" installedby="policy" enabled="0")")); + EXPECT_THAT(update_request, ::testing::HasSubstr(base::StringPrintf( + R"(<disabled reason="%d"/>)", + disable_reason::DISABLE_CORRUPTED))); + } } -IN_PROC_BROWSER_TEST_F(PolicyUpdateServiceTest, Backoff) { +IN_PROC_BROWSER_TEST_P(PolicyUpdateServiceTest, Backoff) { ExtensionRegistry* registry = ExtensionRegistry::Get(profile()); ContentVerifier* verifier = ExtensionSystem::Get(profile())->content_verifier(); @@ -637,7 +779,7 @@ // We want to test what happens at startup with a corroption-disabled policy // force installed extension. So we set that up in the PRE test here. -IN_PROC_BROWSER_TEST_F(PolicyUpdateServiceTest, PRE_PolicyCorruptedOnStartup) { +IN_PROC_BROWSER_TEST_P(PolicyUpdateServiceTest, PRE_PolicyCorruptedOnStartup) { // This is to not allow any corrupted resintall to proceed. content_verifier_test::DelayTracker delay_tracker; ExtensionRegistry* registry = ExtensionRegistry::Get(profile()); @@ -666,7 +808,7 @@ } // Now actually test what happens on the next startup after the PRE test above. -IN_PROC_BROWSER_TEST_F(PolicyUpdateServiceTest, PolicyCorruptedOnStartup) { +IN_PROC_BROWSER_TEST_P(PolicyUpdateServiceTest, PolicyCorruptedOnStartup) { // Depdending on timing, the extension may have already been reinstalled // between SetUpInProcessBrowserTestFixture and now (usually not during local // testing on a developer machine, but sometimes on a heavily loaded system @@ -691,16 +833,29 @@ const std::string update_request = std::get<0>(update_interceptor_->GetRequests()[0]); - EXPECT_THAT(update_request, - ::testing::HasSubstr(base::StringPrintf( - R"(<app appid="%s" version="0.0.0.0")", id_.c_str()))); - EXPECT_THAT( - update_request, - ::testing::HasSubstr( - R"(installsource="reinstall" installedby="policy" enabled="0")")); - EXPECT_THAT(update_request, ::testing::HasSubstr(base::StringPrintf( - R"(<disabled reason="%d"/>)", - disable_reason::DISABLE_CORRUPTED))); + if (use_JSON_) { + const auto root = base::JSONReader().Read(update_request); + const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; + EXPECT_EQ(id_, app.FindKey("appid")->GetString()); + EXPECT_EQ("0.0.0.0", app.FindKey("version")->GetString()); + EXPECT_EQ("reinstall", app.FindKey("installsource")->GetString()); + EXPECT_EQ("policy", app.FindKey("installedby")->GetString()); + EXPECT_FALSE(app.FindKey("enabled")->GetBool()); + const auto& disabled = app.FindKey("disabled")->GetList()[0]; + EXPECT_EQ(disable_reason::DISABLE_CORRUPTED, + disabled.FindKey("reason")->GetInt()); + } else { + EXPECT_THAT(update_request, + ::testing::HasSubstr(base::StringPrintf( + R"(<app appid="%s" version="0.0.0.0")", id_.c_str()))); + EXPECT_THAT( + update_request, + ::testing::HasSubstr( + R"(installsource="reinstall" installedby="policy" enabled="0")")); + EXPECT_THAT(update_request, ::testing::HasSubstr(base::StringPrintf( + R"(<disabled reason="%d"/>)", + disable_reason::DISABLE_CORRUPTED))); + } } } // namespace extensions
diff --git a/chrome/browser/first_run/first_run.cc b/chrome/browser/first_run/first_run.cc index c0a4d14..47c026f 100644 --- a/chrome/browser/first_run/first_run.cc +++ b/chrome/browser/first_run/first_run.cc
@@ -11,11 +11,11 @@ #include "base/command_line.h" #include "base/files/file_path.h" #include "base/files/file_util.h" -#include "base/lazy_instance.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/metrics/histogram_macros.h" #include "base/metrics/user_metrics.h" +#include "base/no_destructor.h" #include "base/path_service.h" #include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" @@ -265,28 +265,27 @@ std::transform(src.begin(), src.end(), ret->begin(), &UrlFromString); } -static base::LazyInstance<base::FilePath>::DestructorAtExit - master_prefs_path_for_testing = LAZY_INSTANCE_INITIALIZER; +base::FilePath& GetMasterPrefsPathForTesting() { + static base::NoDestructor<base::FilePath> s; + return *s; +} // Loads master preferences from the master preference file into the installer // master preferences. Returns the pointer to installer::MasterPreferences -// object if successful; otherwise, returns NULL. -installer::MasterPreferences* LoadMasterPrefs() { +// object if successful; otherwise, returns nullptr. +std::unique_ptr<installer::MasterPreferences> LoadMasterPrefs() { base::FilePath master_prefs_path; - if (!master_prefs_path_for_testing.Get().empty()) { - master_prefs_path = master_prefs_path_for_testing.Get(); - } else { + if (!GetMasterPrefsPathForTesting().empty()) + master_prefs_path = GetMasterPrefsPathForTesting(); + else master_prefs_path = base::FilePath(first_run::internal::MasterPrefsPath()); - } - if (master_prefs_path.empty()) - return NULL; - installer::MasterPreferences* install_prefs = - new installer::MasterPreferences(master_prefs_path); - if (!install_prefs->read_from_file()) { - delete install_prefs; - return NULL; - } + if (master_prefs_path.empty()) + return nullptr; + auto install_prefs = + std::make_unique<installer::MasterPreferences>(master_prefs_path); + if (!install_prefs->read_from_file()) + return nullptr; return install_prefs; } @@ -489,7 +488,7 @@ } void SetMasterPrefsPathForTesting(const base::FilePath& master_prefs) { - master_prefs_path_for_testing.Get() = master_prefs; + GetMasterPrefsPathForTesting() = master_prefs; } ProcessMasterPreferencesResult ProcessMasterPreferences( @@ -497,8 +496,8 @@ MasterPrefs* out_prefs) { DCHECK(!user_data_dir.empty()); - std::unique_ptr<installer::MasterPreferences> install_prefs( - LoadMasterPrefs()); + std::unique_ptr<installer::MasterPreferences> install_prefs = + LoadMasterPrefs(); if (install_prefs.get()) { if (!internal::ShowPostInstallEULAIfNeeded(install_prefs.get()))
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index e1cc3a3..b70c920 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -700,12 +700,6 @@ const char kEnableOutOfBlinkCORSDescription[] = "CORS handling logic is moved out of blink."; -const char kEnableOverviewSwipeToCloseName[] = - "Enable overview swipe to close."; -const char kEnableOverviewSwipeToCloseDescription[] = - "Enables closing of items in overview mode by dragging or flinging " - "vertically."; - const char kExperimentalAccessibilityFeaturesName[] = "Experimental accessibility features"; const char kExperimentalAccessibilityFeaturesDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index b6b2b6a6..ab10885 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -448,9 +448,6 @@ extern const char kEnableOutOfBlinkCORSName[]; extern const char kEnableOutOfBlinkCORSDescription[]; -extern const char kEnableOverviewSwipeToCloseName[]; -extern const char kEnableOverviewSwipeToCloseDescription[]; - extern const char kVizDisplayCompositorName[]; extern const char kVizDisplayCompositorDescription[];
diff --git a/chrome/browser/navigation_predictor/navigation_predictor_browsertest.cc b/chrome/browser/navigation_predictor/navigation_predictor_browsertest.cc index f4f41ba..031a907a 100644 --- a/chrome/browser/navigation_predictor/navigation_predictor_browsertest.cc +++ b/chrome/browser/navigation_predictor/navigation_predictor_browsertest.cc
@@ -464,27 +464,3 @@ "AnchorElementMetrics.Clicked.OnNonDSE.SameHost", 0, 1); } } - -// Tests that the browser only receives anchor elements that are in the -// viewport, and from anchor elements whose target differ from document URL -// by one digit. -IN_PROC_BROWSER_TEST_P(NavigationPredictorBrowserTest, - ViewportOnlyAndUrlIncrementByOne) { - base::HistogramTester histogram_tester; - - const GURL& url = GetTestURL("/long_page_with_anchors-1.html"); - ui_test_utils::NavigateToURL(browser(), url); - base::RunLoop().RunUntilIdle(); - - if (base::FeatureList::IsEnabled( - blink::features::kRecordAnchorMetricsVisible)) { - histogram_tester.ExpectUniqueSample( - "AnchorElementMetrics.Visible.NumberOfAnchorElements", 2, 1); - // Same document anchor element should be removed after merge. - histogram_tester.ExpectUniqueSample( - "AnchorElementMetrics.Visible.NumberOfAnchorElementsAfterMerge", 2, 1); - } else { - histogram_tester.ExpectTotalCount( - "AnchorElementMetrics.Visible.NumberOfAnchorElements", 0); - } -}
diff --git a/chrome/browser/offline_pages/auto_fetch_page_load_watcher.cc b/chrome/browser/offline_pages/auto_fetch_page_load_watcher.cc new file mode 100644 index 0000000..aff91a4a --- /dev/null +++ b/chrome/browser/offline_pages/auto_fetch_page_load_watcher.cc
@@ -0,0 +1,152 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/offline_pages/auto_fetch_page_load_watcher.h" + +#include <memory> + +#include "base/macros.h" +#include "chrome/browser/offline_pages/offline_page_auto_fetcher.h" +#include "chrome/browser/offline_pages/offline_page_auto_fetcher_service.h" +#include "chrome/browser/offline_pages/offline_page_auto_fetcher_service_factory.h" +#include "chrome/browser/offline_pages/request_coordinator_factory.h" +#include "components/offline_pages/core/background/request_coordinator.h" +#include "components/offline_pages/core/client_namespace_constants.h" +#include "content/public/browser/navigation_handle.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_contents_observer.h" +#include "content/public/browser/web_contents_user_data.h" + +namespace offline_pages { + +// Observes a WebContents to relay navigation events to +// AutoFetchPageLoadWatcher. +class AutoFetchPageLoadWatcher::NavigationObserver + : public content::WebContentsObserver, + public content::WebContentsUserData< + AutoFetchPageLoadWatcher::NavigationObserver> { + public: + explicit NavigationObserver(content::WebContents* web_contents) + : content::WebContentsObserver(web_contents) { + helper_ = OfflinePageAutoFetcherServiceFactory::GetForBrowserContext( + web_contents->GetBrowserContext()) + ->page_load_watcher(); + DCHECK(helper_); + } + + // content::WebContentsObserver implementation. + void DidFinishNavigation( + content::NavigationHandle* navigation_handle) override { + if (!navigation_handle->IsInMainFrame() || + !navigation_handle->HasCommitted() || navigation_handle->IsErrorPage()) + return; + + // Note: The redirect chain includes the final URL. We consider all URLs + // along the redirect chain as successful. + for (const auto& u : navigation_handle->GetRedirectChain()) { + helper_->HandlePageNavigation(u); + } + } + + private: + AutoFetchPageLoadWatcher* helper_; + + DISALLOW_COPY_AND_ASSIGN(NavigationObserver); +}; + +// static +void AutoFetchPageLoadWatcher::CreateForWebContents( + content::WebContents* web_contents) { + OfflinePageAutoFetcherService* service = + OfflinePageAutoFetcherServiceFactory::GetForBrowserContext( + web_contents->GetBrowserContext()); + // Don't try to create if the service isn't available (happens in incognito + // mode). + if (service) { + NavigationObserver::CreateForWebContents(web_contents); + } +} + +AutoFetchPageLoadWatcher::AutoFetchPageLoadWatcher( + RequestCoordinator* request_coordinator) + : request_coordinator_(request_coordinator) { + request_coordinator_->AddObserver(this); + request_coordinator_->GetAllRequests( + base::BindOnce(&AutoFetchPageLoadWatcher::ObserverInitialize, + weak_ptr_factory_.GetWeakPtr())); +} + +AutoFetchPageLoadWatcher::~AutoFetchPageLoadWatcher() { + request_coordinator_->RemoveObserver(this); +} + +void AutoFetchPageLoadWatcher::OnAdded(const SavePageRequest& request) { + if (!observer_ready_) + return; + if (request.client_id().name_space == kAutoAsyncNamespace) { + live_auto_fetch_requests_[request.url()].push_back(request.request_id()); + } +} + +void AutoFetchPageLoadWatcher::OnCompleted( + const SavePageRequest& request, + RequestNotifier::BackgroundSavePageResult status) { + if (!observer_ready_) + return; + // A SavePageRequest is complete, remove our bookeeping of it in + // |live_auto_fetch_requests_|. + auto iter = live_auto_fetch_requests_.find(request.url()); + if (iter != live_auto_fetch_requests_.end()) { + std::vector<int64_t>& id_list = iter->second; + auto id_iter = + std::find(id_list.begin(), id_list.end(), request.request_id()); + if (id_iter != id_list.end()) { + id_list.erase(id_iter); + if (id_list.empty()) + live_auto_fetch_requests_.erase(iter); + } + } +} + +void AutoFetchPageLoadWatcher::RemoveRequests( + const std::vector<int64_t>& request_ids) { + request_coordinator_->RemoveRequests(request_ids, base::DoNothing()); +} + +void AutoFetchPageLoadWatcher::HandlePageNavigation(const GURL& url) { + // Early exit for the common-case. + if (observer_ready_ && live_auto_fetch_requests_.empty()) { + return; + } + + // Note: It is possible that this method is called before + // ObserverInitialized, in which case we have to defer handling of the + // event. Never accumulate more than a few, so we can't have a boundless + // array if ObserverInitialize is never called. + if (!observer_ready_) { + if (pages_loaded_before_observer_ready_.size() < 10) + pages_loaded_before_observer_ready_.push_back(url); + return; + } + + auto iter = live_auto_fetch_requests_.find(url); + if (iter == live_auto_fetch_requests_.end()) + return; + RemoveRequests(iter->second); +} + +void AutoFetchPageLoadWatcher::ObserverInitialize( + std::vector<std::unique_ptr<SavePageRequest>> all_requests) { + observer_ready_ = true; + for (const std::unique_ptr<SavePageRequest>& request : all_requests) { + OnAdded(*request); + } + for (const GURL& url : pages_loaded_before_observer_ready_) { + HandlePageNavigation(url); + } + pages_loaded_before_observer_ready_.clear(); +} + +} // namespace offline_pages
diff --git a/chrome/browser/offline_pages/auto_fetch_page_load_watcher.h b/chrome/browser/offline_pages/auto_fetch_page_load_watcher.h new file mode 100644 index 0000000..fa70625 --- /dev/null +++ b/chrome/browser/offline_pages/auto_fetch_page_load_watcher.h
@@ -0,0 +1,76 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_OFFLINE_PAGES_AUTO_FETCH_PAGE_LOAD_WATCHER_H_ +#define CHROME_BROWSER_OFFLINE_PAGES_AUTO_FETCH_PAGE_LOAD_WATCHER_H_ + +#include <map> +#include <memory> +#include <set> +#include <vector> + +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "components/offline_pages/core/background/request_coordinator.h" +#include "components/offline_pages/core/client_id.h" +#include "url/gurl.h" + +namespace content { +class WebContents; +} // namespace content + +namespace offline_pages { +class SavePageRequest; +class RequestCoordinator; + +// Cancels active auto fetch requests if a page loads. +class AutoFetchPageLoadWatcher : public RequestCoordinator::Observer { + public: + static void CreateForWebContents(content::WebContents* web_contents); + + explicit AutoFetchPageLoadWatcher(RequestCoordinator* request_coordinator); + ~AutoFetchPageLoadWatcher() override; + + // RequestCoordinator::Observer methods. These keep + // |live_auto_fetch_requests_| in sync with the state of RequestCoordinator. + void OnAdded(const SavePageRequest& request) override; + void OnCompleted(const SavePageRequest& request, + RequestNotifier::BackgroundSavePageResult status) override; + void OnChanged(const SavePageRequest& request) override {} + void OnNetworkProgress(const SavePageRequest& request, + int64_t received_bytes) override {} + + protected: + class NavigationObserver; + + // Virtual for testing only. + virtual void RemoveRequests(const std::vector<int64_t>& request_ids); + + // Called when navigation completes. Triggers cancellation of any + // in-flight auto fetch requests that match a successful navigation. + void HandlePageNavigation(const GURL& url); + + void ObserverInitialize( + std::vector<std::unique_ptr<SavePageRequest>> all_requests); + + offline_pages::RequestCoordinator* GetRequestCoordinator(); + + // Whether ObserverInitialize has been called. + bool observer_ready_ = false; + + RequestCoordinator* request_coordinator_; + std::vector<GURL> pages_loaded_before_observer_ready_; + + // This represents the set of auto fetch request IDs currently in the + // RequestCoordinator's queue, mapped by URL. + std::map<GURL, std::vector<int64_t>> live_auto_fetch_requests_; + + base::WeakPtrFactory<AutoFetchPageLoadWatcher> weak_ptr_factory_{this}; + + DISALLOW_COPY_AND_ASSIGN(AutoFetchPageLoadWatcher); +}; + +} // namespace offline_pages + +#endif // CHROME_BROWSER_OFFLINE_PAGES_AUTO_FETCH_PAGE_LOAD_WATCHER_H_
diff --git a/chrome/browser/offline_pages/auto_fetch_page_load_watcher_unittest.cc b/chrome/browser/offline_pages/auto_fetch_page_load_watcher_unittest.cc new file mode 100644 index 0000000..685f905 --- /dev/null +++ b/chrome/browser/offline_pages/auto_fetch_page_load_watcher_unittest.cc
@@ -0,0 +1,261 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/offline_pages/auto_fetch_page_load_watcher.h" + +#include <memory> +#include <string> +#include <utility> + +#include "base/test/bind_test_util.h" +#include "base/test/test_simple_task_runner.h" +#include "base/threading/thread_task_runner_handle.h" +#include "chrome/browser/offline_pages/request_coordinator_factory.h" +#include "chrome/test/base/chrome_render_view_host_test_harness.h" +#include "chrome/test/base/testing_profile.h" +#include "components/offline_pages/core/background/request_coordinator_stub_taco.h" +#include "components/offline_pages/core/client_namespace_constants.h" +#include "content/public/test/navigation_simulator.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace offline_pages { +namespace { +using content::NavigationSimulator; + +GURL TestURL() { + return GURL("http://www.url.com"); +} + +SavePageRequest TestRequest(int64_t id, const GURL& url = TestURL()) { + return SavePageRequest(id, url, + ClientId(kAutoAsyncNamespace, std::to_string(id)), + base::Time::Now(), false); +} + +// For access to protected methods. +class TestAutoFetchPageLoadWatcher : public AutoFetchPageLoadWatcher { + public: + explicit TestAutoFetchPageLoadWatcher(RequestCoordinator* request_coordinator) + : AutoFetchPageLoadWatcher(request_coordinator) {} + void RemoveRequests(const std::vector<int64_t>& request_ids) override { + removed_ids_ = request_ids; + } + std::vector<int64_t> removed_ids() const { return removed_ids_; } + + std::map<GURL, std::vector<int64_t>>* live_auto_fetch_requests() { + return &live_auto_fetch_requests_; + } + + using AutoFetchPageLoadWatcher::HandlePageNavigation; + using AutoFetchPageLoadWatcher::ObserverInitialize; + + private: + std::vector<int64_t> removed_ids_; +}; + +// Tests AutoFetchPageLoadWatcher in a realistic way by simulating navigations. +class AutoFetchPageLoadWatcherNavigationTest + : public ChromeRenderViewHostTestHarness { + public: + AutoFetchPageLoadWatcherNavigationTest() = default; + ~AutoFetchPageLoadWatcherNavigationTest() override = default; + + void SetUp() override { + ChromeRenderViewHostTestHarness::SetUp(); + RequestCoordinatorFactory::GetInstance()->SetTestingFactoryAndUse( + profile(), request_coordinator_taco_.FactoryFunction()); + + AutoFetchPageLoadWatcher::CreateForWebContents(web_contents()); + } + + std::unique_ptr<NavigationSimulator> CreateNavigation(const GURL& url) { + return NavigationSimulator::CreateRendererInitiated(url, main_rfh()); + } + + RequestCoordinator* request_coordinator() { + return request_coordinator_taco_.request_coordinator(); + } + + void AddAutoSavePageRequest() { + RequestCoordinator::SavePageLaterParams params; + params.url = TestURL(); + params.client_id = ClientId(kAutoAsyncNamespace, "request1"); + request_coordinator()->SavePageLater(params, base::DoNothing()); + } + + std::vector<GURL> RequestsInQueue() { + std::vector<GURL> request_urls; + request_coordinator()->GetAllRequests(base::BindLambdaForTesting( + [&](std::vector<std::unique_ptr<SavePageRequest>> requests) { + for (const auto& request : requests) { + request_urls.push_back(request->url()); + } + })); + RunUntilIdle(); + return request_urls; + } + + void RunUntilIdle() { thread_bundle()->RunUntilIdle(); } + + private: + RequestCoordinatorStubTaco request_coordinator_taco_; + + DISALLOW_COPY_AND_ASSIGN(AutoFetchPageLoadWatcherNavigationTest); +}; + +// Navigation results in an error page, and has no effect on +// AutoFetchPageLoadWatcher. +TEST_F(AutoFetchPageLoadWatcherNavigationTest, NavigateToErrorPage) { + AddAutoSavePageRequest(); + RunUntilIdle(); + + std::unique_ptr<NavigationSimulator> simulator = CreateNavigation(TestURL()); + simulator->Start(); + simulator->Fail(net::ERR_TIMED_OUT); + simulator->CommitErrorPage(); + + std::vector<GURL> expected_requests{TestURL()}; + EXPECT_EQ(expected_requests, RequestsInQueue()); +} + +// Successful navigation results in cancellation of request. +TEST_F(AutoFetchPageLoadWatcherNavigationTest, NavigateAndCancel) { + AddAutoSavePageRequest(); + RunUntilIdle(); + + std::unique_ptr<NavigationSimulator> simulator = CreateNavigation(TestURL()); + simulator->Start(); + simulator->Commit(); + + std::vector<GURL> expected_requests{}; + EXPECT_EQ(expected_requests, RequestsInQueue()); +} + +TEST_F(AutoFetchPageLoadWatcherNavigationTest, NavigateToDifferentURL) { + AddAutoSavePageRequest(); + RunUntilIdle(); + + std::unique_ptr<NavigationSimulator> simulator = + CreateNavigation(GURL("http://www.different.com")); + simulator->Start(); + simulator->Commit(); + + std::vector<GURL> expected_requests{TestURL()}; + EXPECT_EQ(expected_requests, RequestsInQueue()); +} + +TEST_F(AutoFetchPageLoadWatcherNavigationTest, RedirectToAndCancel) { + AddAutoSavePageRequest(); + RunUntilIdle(); + + std::unique_ptr<NavigationSimulator> simulator = + CreateNavigation(GURL("http://different.com")); + simulator->Start(); + simulator->Redirect(TestURL()); + simulator->Commit(); + + std::vector<GURL> expected_requests{}; + EXPECT_EQ(expected_requests, RequestsInQueue()); +} + +TEST_F(AutoFetchPageLoadWatcherNavigationTest, RedirectFromAndCancel) { + AddAutoSavePageRequest(); + RunUntilIdle(); + + std::unique_ptr<NavigationSimulator> simulator = CreateNavigation(TestURL()); + + simulator->Start(); + simulator->Redirect(GURL("http://different.com")); + simulator->Commit(); + + std::vector<GURL> expected_requests{}; + EXPECT_EQ(expected_requests, RequestsInQueue()); +} + +// Tests some details of AutoFetchPageLoadWatcher +class AutoFetchPageLoadWatcherTest : public testing::Test { + public: + AutoFetchPageLoadWatcherTest() {} + ~AutoFetchPageLoadWatcherTest() override {} + + void SetUp() override { + testing::Test::SetUp(); + + taco_.CreateRequestCoordinator(); + } + + RequestCoordinator* request_coordinator() { + return taco_.request_coordinator(); + } + + private: + scoped_refptr<base::TestSimpleTaskRunner> task_runner_ = + base::MakeRefCounted<base::TestSimpleTaskRunner>(); + base::ThreadTaskRunnerHandle handle_{task_runner_}; + + RequestCoordinatorStubTaco taco_; +}; + +// Simulate navigation to a URL prior to ObserverInitialize. Verify the +// RemoveRequests is called. +TEST_F(AutoFetchPageLoadWatcherTest, NavigateBeforeObserverInitialize) { + TestAutoFetchPageLoadWatcher tab_helper(request_coordinator()); + tab_helper.HandlePageNavigation(TestURL()); + std::vector<std::unique_ptr<SavePageRequest>> all_requests; + all_requests.push_back(std::make_unique<SavePageRequest>(TestRequest(1))); + all_requests.push_back(std::make_unique<SavePageRequest>( + TestRequest(2, GURL("http://different.com")))); + tab_helper.ObserverInitialize(std::move(all_requests)); + + std::vector<int64_t> expected_requests{1}; + EXPECT_EQ(expected_requests, tab_helper.removed_ids()); +} + +TEST_F(AutoFetchPageLoadWatcherTest, OnCompletedNoRequest) { + TestAutoFetchPageLoadWatcher tab_helper(request_coordinator()); + tab_helper.ObserverInitialize({}); + + tab_helper.OnCompleted(TestRequest(1), + RequestNotifier::BackgroundSavePageResult()); + + // Nothing happens, just verify there is no crash. + SUCCEED(); +} + +TEST_F(AutoFetchPageLoadWatcherTest, OnCompletedOneRequestWithURL) { + TestAutoFetchPageLoadWatcher tab_helper(request_coordinator()); + tab_helper.ObserverInitialize({}); + std::map<GURL, std::vector<int64_t>>* requests = + tab_helper.live_auto_fetch_requests(); + + tab_helper.OnAdded(TestRequest(1)); + ASSERT_EQ(1ul, requests->count(TestURL())); + + tab_helper.OnCompleted(TestRequest(1), + RequestNotifier::BackgroundSavePageResult()); + + EXPECT_EQ(0ul, requests->count(TestURL())); +} + +// Verify multiple requests with the same URL are handled as expected. +TEST_F(AutoFetchPageLoadWatcherTest, OnCompletedMultipleRequestsWithURL) { + TestAutoFetchPageLoadWatcher tab_helper(request_coordinator()); + tab_helper.ObserverInitialize({}); + + // Three requests with the same URL. + tab_helper.OnAdded(TestRequest(1)); + tab_helper.OnAdded(TestRequest(2)); + tab_helper.OnAdded(TestRequest(3)); + + // Only one is completed. + tab_helper.OnCompleted(TestRequest(2), + RequestNotifier::BackgroundSavePageResult()); + + std::vector<int64_t> expected_requests = {1, 3}; + EXPECT_EQ(expected_requests, + (*tab_helper.live_auto_fetch_requests())[TestURL()]); +} + +} // namespace +} // namespace offline_pages
diff --git a/chrome/browser/offline_pages/offline_page_auto_fetcher_service.cc b/chrome/browser/offline_pages/offline_page_auto_fetcher_service.cc index 74ab8f37..87d607e9 100644 --- a/chrome/browser/offline_pages/offline_page_auto_fetcher_service.cc +++ b/chrome/browser/offline_pages/offline_page_auto_fetcher_service.cc
@@ -71,7 +71,8 @@ OfflinePageAutoFetcherService::OfflinePageAutoFetcherService( RequestCoordinator* request_coordinator) - : request_coordinator_(request_coordinator) {} + : page_load_watcher_(request_coordinator), + request_coordinator_(request_coordinator) {} OfflinePageAutoFetcherService::~OfflinePageAutoFetcherService() {} void OfflinePageAutoFetcherService::TrySchedule(bool user_requested,
diff --git a/chrome/browser/offline_pages/offline_page_auto_fetcher_service.h b/chrome/browser/offline_pages/offline_page_auto_fetcher_service.h index 7474a22..2904452 100644 --- a/chrome/browser/offline_pages/offline_page_auto_fetcher_service.h +++ b/chrome/browser/offline_pages/offline_page_auto_fetcher_service.h
@@ -6,10 +6,12 @@ #define CHROME_BROWSER_OFFLINE_PAGES_OFFLINE_PAGE_AUTO_FETCHER_SERVICE_H_ #include <memory> +#include <utility> #include <vector> #include "base/callback_forward.h" #include "base/memory/weak_ptr.h" +#include "chrome/browser/offline_pages/auto_fetch_page_load_watcher.h" #include "chrome/common/offline_page_auto_fetcher.mojom.h" #include "components/keyed_service/core/keyed_service.h" #include "components/offline_pages/core/background/request_queue_results.h" @@ -55,6 +57,8 @@ RequestCoordinator* request_coordinator); ~OfflinePageAutoFetcherService() override; + AutoFetchPageLoadWatcher* page_load_watcher() { return &page_load_watcher_; } + // Auto fetching interface. Schedules and cancels fetch requests. void TrySchedule(bool user_requested, @@ -114,6 +118,7 @@ std::vector<std::unique_ptr<SavePageRequest>> requests); void CancelScheduleStep3(TaskToken token, const MultipleItemStatuses&); + AutoFetchPageLoadWatcher page_load_watcher_; RequestCoordinator* request_coordinator_; // TODO(harringtond): Pull out task management into another class, or use // offline_pages::TaskQueue.
diff --git a/chrome/browser/offline_pages/offline_page_auto_fetcher_service_factory.cc b/chrome/browser/offline_pages/offline_page_auto_fetcher_service_factory.cc index 94ca367d..5ad9b57d 100644 --- a/chrome/browser/offline_pages/offline_page_auto_fetcher_service_factory.cc +++ b/chrome/browser/offline_pages/offline_page_auto_fetcher_service_factory.cc
@@ -21,8 +21,11 @@ OfflinePageAutoFetcherService* OfflinePageAutoFetcherServiceFactory::GetForBrowserContext( content::BrowserContext* context) { - return static_cast<OfflinePageAutoFetcherService*>( - GetInstance()->GetServiceForBrowserContext(context, true)); + KeyedService* service = + GetInstance()->GetServiceForBrowserContext(context, true); + if (!service) + return nullptr; + return static_cast<OfflinePageAutoFetcherService*>(service); } OfflinePageAutoFetcherServiceFactory::OfflinePageAutoFetcherServiceFactory()
diff --git a/chrome/browser/offline_pages/offline_page_tab_helper.h b/chrome/browser/offline_pages/offline_page_tab_helper.h index 6b96422..8ca297fe 100644 --- a/chrome/browser/offline_pages/offline_page_tab_helper.h +++ b/chrome/browser/offline_pages/offline_page_tab_helper.h
@@ -204,7 +204,7 @@ bool reloading_url_on_net_error_ = false; - // Service, overlives this object. + // Service, outlives this object. PrefetchService* prefetch_service_ = nullptr; // Table of OfflinePages policies.
diff --git a/chrome/browser/policy/browser_dm_token_storage.cc b/chrome/browser/policy/browser_dm_token_storage.cc index 06acff9..6fa2d2d 100644 --- a/chrome/browser/policy/browser_dm_token_storage.cc +++ b/chrome/browser/policy/browser_dm_token_storage.cc
@@ -83,6 +83,13 @@ std::move(store_callback_).Run(success); } +bool BrowserDMTokenStorage::ShouldDisplayErrorMessageOnFailure() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + InitIfNeeded(); + return should_display_error_message_on_failure_; +} + void BrowserDMTokenStorage::ScheduleUnusedPolicyDirectoryDeletion() { // TODO(crbug.com/883869): Add a UMA metrics to track the deletion progress. content::BrowserThread::PostAfterStartupTask( @@ -113,6 +120,8 @@ dm_token_ = InitDMToken(); DVLOG(1) << "DM Token = " << dm_token_; + + should_display_error_message_on_failure_ = InitEnrollmentErrorOption(); } void BrowserDMTokenStorage::DeletePolicyDirectory() {}
diff --git a/chrome/browser/policy/browser_dm_token_storage.h b/chrome/browser/policy/browser_dm_token_storage.h index b090387..2347514c 100644 --- a/chrome/browser/policy/browser_dm_token_storage.h +++ b/chrome/browser/policy/browser_dm_token_storage.h
@@ -49,6 +49,10 @@ // invoked. void OnDMTokenStored(bool success); + // Return true if we display error message dialog when enrollment process + // fails. + virtual bool ShouldDisplayErrorMessageOnFailure(); + // Set the mock BrowserDMTokenStorage for testing. The caller owns the // instance of the storage. static void SetForTesting(BrowserDMTokenStorage* storage) { @@ -82,6 +86,9 @@ // Gets the DM token and stores it in |dm_token_|. This implementation is // platform dependant. virtual std::string InitDMToken() = 0; + // Gets the boolean value that determines if error message will be displayed + // when enrollment fails. + virtual bool InitEnrollmentErrorOption() = 0; // Saves the DM token. This implementation is platform dependant. virtual void SaveDMToken(const std::string& token) = 0; @@ -96,6 +103,7 @@ std::string client_id_; std::string enrollment_token_; std::string dm_token_; + bool should_display_error_message_on_failure_; SEQUENCE_CHECKER(sequence_checker_);
diff --git a/chrome/browser/policy/browser_dm_token_storage_linux.cc b/chrome/browser/policy/browser_dm_token_storage_linux.cc index a21bf55..ceebd05 100644 --- a/chrome/browser/policy/browser_dm_token_storage_linux.cc +++ b/chrome/browser/policy/browser_dm_token_storage_linux.cc
@@ -134,6 +134,11 @@ return token; } +bool BrowserDMTokenStorageLinux::InitEnrollmentErrorOption() { + // TODO(crbug/904983): Load the policy value for this option. + return true; +} + void BrowserDMTokenStorageLinux::SaveDMToken(const std::string& token) { std::string client_id = RetrieveClientId(); base::PostTaskWithTraitsAndReplyWithResult(
diff --git a/chrome/browser/policy/browser_dm_token_storage_linux.h b/chrome/browser/policy/browser_dm_token_storage_linux.h index c4d7702..f7fc3a049 100644 --- a/chrome/browser/policy/browser_dm_token_storage_linux.h +++ b/chrome/browser/policy/browser_dm_token_storage_linux.h
@@ -31,6 +31,7 @@ std::string InitClientId() override; std::string InitEnrollmentToken() override; std::string InitDMToken() override; + bool InitEnrollmentErrorOption() override; void SaveDMToken(const std::string& token) override; void DeletePolicyDirectory() override;
diff --git a/chrome/browser/policy/browser_dm_token_storage_mac.h b/chrome/browser/policy/browser_dm_token_storage_mac.h index c0ba3c4..5c9dda4 100644 --- a/chrome/browser/policy/browser_dm_token_storage_mac.h +++ b/chrome/browser/policy/browser_dm_token_storage_mac.h
@@ -31,6 +31,7 @@ std::string InitClientId() override; std::string InitEnrollmentToken() override; std::string InitDMToken() override; + bool InitEnrollmentErrorOption() override; void SaveDMToken(const std::string& token) override; void DeletePolicyDirectory() override;
diff --git a/chrome/browser/policy/browser_dm_token_storage_mac.mm b/chrome/browser/policy/browser_dm_token_storage_mac.mm index d7f8e37..34a1951 100644 --- a/chrome/browser/policy/browser_dm_token_storage_mac.mm +++ b/chrome/browser/policy/browser_dm_token_storage_mac.mm
@@ -181,6 +181,11 @@ return token; } +bool BrowserDMTokenStorageMac::InitEnrollmentErrorOption() { + // TODO(crbug/904983): Load the policy value for this option. + return true; +} + void BrowserDMTokenStorageMac::SaveDMToken(const std::string& token) { std::string client_id = RetrieveClientId(); base::PostTaskWithTraitsAndReplyWithResult(
diff --git a/chrome/browser/policy/browser_dm_token_storage_unittest.cc b/chrome/browser/policy/browser_dm_token_storage_unittest.cc index ba32c995..0feabb3 100644 --- a/chrome/browser/policy/browser_dm_token_storage_unittest.cc +++ b/chrome/browser/policy/browser_dm_token_storage_unittest.cc
@@ -34,12 +34,14 @@ set_test_client_id(kClientId1); set_test_enrollment_token(kEnrollmentToken1); set_test_dm_token(kDMToken1); + set_test_error_option(false); } // BrowserDMTokenStorage override std::string InitClientId() override { return test_client_id_; } std::string InitEnrollmentToken() override { return test_enrollment_token_; } std::string InitDMToken() override { return test_dm_token_; } + bool InitEnrollmentErrorOption() override { return test_error_option_; } void SaveDMToken(const std::string& dm_token) override { NOTREACHED(); } @@ -52,11 +54,15 @@ void set_test_dm_token(std::string test_dm_token) { test_dm_token_ = test_dm_token; } + void set_test_error_option(bool error_option) { + test_error_option_ = error_option; + } private: std::string test_client_id_; std::string test_enrollment_token_; std::string test_dm_token_; + bool test_error_option_; }; class BrowserDMTokenStorageTest : public testing::Test { @@ -93,4 +99,14 @@ EXPECT_EQ(kDMToken1, storage.RetrieveDMToken()); } +TEST_F(BrowserDMTokenStorageTest, ShouldDisplayErrorMessageOnFailure) { + MockBrowserDMTokenStorage storage; + EXPECT_FALSE(storage.ShouldDisplayErrorMessageOnFailure()); + + // The error option should be cached in memory and not read from the system + // again. + storage.set_test_error_option(true); + EXPECT_FALSE(storage.ShouldDisplayErrorMessageOnFailure()); +} + } // namespace policy
diff --git a/chrome/browser/policy/browser_dm_token_storage_win.cc b/chrome/browser/policy/browser_dm_token_storage_win.cc index 00083133..5127a046 100644 --- a/chrome/browser/policy/browser_dm_token_storage_win.cc +++ b/chrome/browser/policy/browser_dm_token_storage_win.cc
@@ -190,6 +190,11 @@ return dm_token; } +bool BrowserDMTokenStorageWin::InitEnrollmentErrorOption() { + // TODO(crbug/904983): Load the policy value for this option. + return true; +} + void BrowserDMTokenStorageWin::SaveDMToken(const std::string& token) { base::PostTaskAndReplyWithResult( com_sta_task_runner_.get(), FROM_HERE,
diff --git a/chrome/browser/policy/browser_dm_token_storage_win.h b/chrome/browser/policy/browser_dm_token_storage_win.h index 57a82ff..cc5d9e0 100644 --- a/chrome/browser/policy/browser_dm_token_storage_win.h +++ b/chrome/browser/policy/browser_dm_token_storage_win.h
@@ -31,6 +31,7 @@ std::string InitClientId() override; std::string InitEnrollmentToken() override; std::string InitDMToken() override; + bool InitEnrollmentErrorOption() override; void SaveDMToken(const std::string& token) override; scoped_refptr<base::SingleThreadTaskRunner> com_sta_task_runner_;
diff --git a/chrome/browser/policy/cloud/machine_level_user_cloud_policy_browsertest.cc b/chrome/browser/policy/cloud/machine_level_user_cloud_policy_browsertest.cc index addf04e5..9deea9a0 100644 --- a/chrome/browser/policy/cloud/machine_level_user_cloud_policy_browsertest.cc +++ b/chrome/browser/policy/cloud/machine_level_user_cloud_policy_browsertest.cc
@@ -116,6 +116,7 @@ std::move(callback).Run(storage_enabled_); } std::string RetrieveDMToken() override { return dm_token_; } + bool ShouldDisplayErrorMessageOnFailure() override { return true; } void SetEnrollmentToken(const std::string& enrollment_token) { enrollment_token_ = enrollment_token; @@ -135,6 +136,11 @@ NOTREACHED(); return std::string(); } + bool InitEnrollmentErrorOption() override { + NOTREACHED(); + return true; + } + void SaveDMToken(const std::string& dm_token) override { NOTREACHED(); } void EnableStorage(bool storage_enabled) {
diff --git a/chrome/browser/policy/machine_level_user_cloud_policy_register_watcher_unittest.cc b/chrome/browser/policy/machine_level_user_cloud_policy_register_watcher_unittest.cc index 50728e5..52af0ae8 100644 --- a/chrome/browser/policy/machine_level_user_cloud_policy_register_watcher_unittest.cc +++ b/chrome/browser/policy/machine_level_user_cloud_policy_register_watcher_unittest.cc
@@ -38,6 +38,7 @@ std::string RetrieveDMToken() override { return dm_token_; } std::string RetrieveEnrollmentToken() override { return enrollment_token_; } std::string RetrieveClientId() override { return kClientId; } + bool ShouldDisplayErrorMessageOnFailure() override { return true; } std::string InitClientId() override { NOTREACHED(); @@ -51,6 +52,10 @@ NOTREACHED(); return std::string(); } + bool InitEnrollmentErrorOption() override { + NOTREACHED(); + return true; + } void SaveDMToken(const std::string& dm_token) override { NOTREACHED(); }
diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc index e28e22c..888962b 100644 --- a/chrome/browser/policy/policy_browsertest.cc +++ b/chrome/browser/policy/policy_browsertest.cc
@@ -21,6 +21,7 @@ #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" +#include "base/json/json_reader.h" #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/memory/ref_counted.h" @@ -4166,8 +4167,8 @@ } private: - DISALLOW_COPY_AND_ASSIGN(PolicyWebStoreIconTest); base::test::ScopedFeatureList scoped_feature_list; + DISALLOW_COPY_AND_ASSIGN(PolicyWebStoreIconTest); }; IN_PROC_BROWSER_TEST_F(PolicyWebStoreIconTest, AppsWebStoreIconHidden) { @@ -4249,8 +4250,8 @@ } private: - DISALLOW_COPY_AND_ASSIGN(PolicyWebStoreIconHiddenTest); base::test::ScopedFeatureList scoped_feature_list; + DISALLOW_COPY_AND_ASSIGN(PolicyWebStoreIconHiddenTest); }; IN_PROC_BROWSER_TEST_F(PolicyWebStoreIconHiddenTest, NTPWebStoreIconHidden) { @@ -5444,10 +5445,31 @@ << post_interceptor_->GetRequestsAsString(); ASSERT_EQ(1, post_interceptor_->GetCount()) << post_interceptor_->GetRequestsAsString(); - EXPECT_NE(std::string::npos, - post_interceptor_->GetRequestBody(0).find(base::StringPrintf( - "<updatecheck%s/>", - update_disabled ? " updatedisabled=\"true\"" : ""))); + + const auto& request = post_interceptor_->GetRequestBody(0); + + // Handle XML and JSON protocols. + if (base::StartsWith(request, "<?xml", base::CompareCase::SENSITIVE)) { + EXPECT_NE(std::string::npos, + request.find(base::StringPrintf( + "<updatecheck%s/>", + update_disabled ? " updatedisabled=\"true\"" : ""))); + } else if (base::StartsWith(request, R"({"request":{)", + base::CompareCase::SENSITIVE)) { + const auto root = base::JSONReader().Read(request); + ASSERT_TRUE(root); + const auto* update_check = + root->FindKey("request")->FindKey("app")->GetList()[0].FindKey( + "updatecheck"); + ASSERT_TRUE(update_check); + if (update_disabled) { + EXPECT_EQ(true, update_check->FindKey("updatedisabled")->GetBool()); + } else { + EXPECT_FALSE(update_check->FindKey("updatedisabled")); + } + } else { + NOTREACHED(); + } } void ComponentUpdaterPolicyTest::DefaultPolicy_GroupPolicySupported() {
diff --git a/chrome/browser/previews/previews_lite_page_navigation_throttle_unittest.cc b/chrome/browser/previews/previews_lite_page_navigation_throttle_unittest.cc index 1fb28fdb..1199586da 100644 --- a/chrome/browser/previews/previews_lite_page_navigation_throttle_unittest.cc +++ b/chrome/browser/previews/previews_lite_page_navigation_throttle_unittest.cc
@@ -23,11 +23,12 @@ struct TestCase { std::string previews_host; std::string original_url; - std::string previews_url; + std::string expected_previews_url; std::string experiment; }; const TestCase kTestCases[]{ - // Use https://play.golang.org/p/HUM2HxmUTOW to compute |previews_url|. + // Use https://play.golang.org/p/HUM2HxmUTOW to compute + // |expected_previews_url|. { "https://previews.host.com", "https://original.host.com/path/path/path?query=yes", @@ -86,6 +87,12 @@ "&x=enable_HTCPCP", "enable_HTCPCP", }, + { + "https://previews.host.com", "https://[::1]:12345", + "https://2ikmbopbfxagkb7uer2vgfxmbzu2vw4qq3d3ixe3h2hfhgcabvua." + "previews.host.com/p?u=https%3A%2F%2F%5B%3A%3A1%5D%3A12345%2F", + "", + }, }; for (const TestCase& test_case : kTestCases) { @@ -97,6 +104,6 @@ EXPECT_EQ(PreviewsLitePageNavigationThrottle::GetPreviewsURLForURL( GURL(test_case.original_url)), - GURL(test_case.previews_url)); + GURL(test_case.expected_previews_url)); } }
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc index 73169a5c..739a0b5f 100644 --- a/chrome/browser/profiles/profile_impl.cc +++ b/chrome/browser/profiles/profile_impl.cc
@@ -123,6 +123,8 @@ #include "content/public/browser/browser_thread.h" #include "content/public/browser/dom_storage_context.h" #include "content/public/browser/notification_service.h" +#include "content/public/browser/permission_controller.h" +#include "content/public/browser/permission_type.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/storage_partition.h" #include "content/public/browser/url_data_source.h" @@ -326,6 +328,31 @@ } #endif +void CheckDomainReliablityUploadAllowedOnUIThread( + Profile* profile, + const GURL& origin, + base::OnceCallback<void(bool)> callback) { + // Profile is safe since ProfileImpl always outlives IO thread. + content::PermissionController* permission_controller = + content::BrowserContext::GetPermissionController(profile); + DCHECK(permission_controller); + bool allowed = permission_controller->GetPermissionStatus( + content::PermissionType::BACKGROUND_SYNC, origin, + origin) == blink::mojom::PermissionStatus::GRANTED; + base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO}, + base::BindOnce(std::move(callback), allowed)); +} + +void CheckDomainReliablityUploadAllowedOnIOThread( + Profile* profile, + const GURL& origin, + base::OnceCallback<void(bool)> callback) { + base::PostTaskWithTraits( + FROM_HERE, {BrowserThread::UI}, + base::BindOnce(CheckDomainReliablityUploadAllowedOnUIThread, profile, + origin, std::move(callback))); +} + } // namespace // static @@ -1476,7 +1503,8 @@ return service->CreateMonitor( base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI}), - base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO})); + base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO}), + base::BindRepeating(CheckDomainReliablityUploadAllowedOnIOThread, this)); } std::unique_ptr<service_manager::Service> ProfileImpl::CreateIdentityService() {
diff --git a/chrome/browser/profiles/profile_impl_io_data.cc b/chrome/browser/profiles/profile_impl_io_data.cc index e6d3848..cf694ac 100644 --- a/chrome/browser/profiles/profile_impl_io_data.cc +++ b/chrome/browser/profiles/profile_impl_io_data.cc
@@ -174,7 +174,8 @@ io_data_->InitializeMetricsEnabledStateOnUIThread(); if (io_data_->lazy_params_->domain_reliability_monitor) - io_data_->lazy_params_->domain_reliability_monitor->MoveToNetworkThread(); + io_data_->lazy_params_->domain_reliability_monitor + ->InitializeOnNetworkThread(); io_data_->set_data_reduction_proxy_io_data( CreateDataReductionProxyChromeIOData(
diff --git a/chrome/browser/resources/chromeos/arc_support/recommend_app_list_view.js b/chrome/browser/resources/chromeos/arc_support/recommend_app_list_view.js index 8bb839f0..ec7bf67 100644 --- a/chrome/browser/resources/chromeos/arc_support/recommend_app_list_view.js +++ b/chrome/browser/resources/chromeos/arc_support/recommend_app_list_view.js
@@ -2,6 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +let appWindow; +let appOrigin; + function generateContents(appIcon, appTitle, appPackageName) { const doc = document; const recommendAppsContainer = doc.getElementById('recommend-apps-container'); @@ -97,6 +100,8 @@ function toggleCheckStatus_(e) { const item = e.currentTarget.parentNode; item.classList.toggle('checked'); + + sendNumberOfSelectedApps(); } function getSelectedPackages() { @@ -139,3 +144,22 @@ return e.keyCode === 13 // Enter || e.keyCode === 32; // Space } + +/** + * Send the number of selected apps back to the embedding page. + */ +function sendNumberOfSelectedApps() { + if (appWindow && appOrigin) { + const checkedItems = document.querySelectorAll('.checked'); + appWindow.postMessage( + {type: 'NUM_OF_SELECTED_APPS', numOfSelected: checkedItems.length}, + appOrigin); + } +} + +function onMessage_(e) { + appWindow = e.source; + appOrigin = e.origin; +} + +window.addEventListener('message', onMessage_);
diff --git a/chrome/browser/resources/chromeos/chromevox/testing/callback_helper.js b/chrome/browser/resources/chromeos/chromevox/testing/callback_helper.js index a671637..d144464 100644 --- a/chrome/browser/resources/chromeos/chromevox/testing/callback_helper.js +++ b/chrome/browser/resources/chromeos/chromevox/testing/callback_helper.js
@@ -48,6 +48,6 @@ * @private */ CallbackHelper.testDone_ = this.testDone; -// Remove testDone for public use since direclty using it conflicts with +// Remove testDone for public use since directly using it conflicts with // this callback helper. delete this.testDone;
diff --git a/chrome/browser/resources/chromeos/login/screen_recommend_apps.js b/chrome/browser/resources/chromeos/login/screen_recommend_apps.js index 7560848..9e1f9a2 100644 --- a/chrome/browser/resources/chromeos/login/screen_recommend_apps.js +++ b/chrome/browser/resources/chromeos/login/screen_recommend_apps.js
@@ -59,6 +59,7 @@ */ ensureInitialized_: function() { $('recommend-apps-screen').screen = this; + window.addEventListener('message', this.onMessage); }, /** @@ -77,7 +78,7 @@ }, setWebview: function(contents) { - var appListView = this.getElement_('app-list-view'); + const appListView = this.getElement_('app-list-view'); appListView.src = 'data:text/html;charset=utf-8,' + encodeURIComponent(contents); }, @@ -91,21 +92,26 @@ // Hide the loading throbber and show the recommend app list. this.setThrobberVisible(false); - var appListView = this.getElement_('app-list-view'); - var subtitle = this.getElement_('subtitle'); + const appListView = this.getElement_('app-list-view'); + const subtitle = this.getElement_('subtitle'); subtitle.innerText = loadTimeData.getStringF( 'recommendAppsScreenDescription', appList.length); appListView.addEventListener('contentload', () => { + appListView.contentWindow.postMessage('initialMessage', '*'); + appListView.executeScript({file: 'recommend_app_list_view.js'}, () => { appList.forEach(function(app, index) { - var generateItemScript = 'generateContents("' + app.icon + '", "' + + let generateItemScript = 'generateContents("' + app.icon + '", "' + app.name + '", "' + app.package_name + '");'; - var generateContents = {code: generateItemScript}; + const generateContents = {code: generateItemScript}; appListView.executeScript(generateContents); }); - var addScrollShadowEffectScript = 'addScrollShadowEffect();'; + const addScrollShadowEffectScript = 'addScrollShadowEffect();'; appListView.executeScript({code: addScrollShadowEffectScript}); + const getNumOfSelectedAppsScript = 'sendNumberOfSelectedApps();'; + appListView.executeScript({code: getNumOfSelectedAppsScript}); + this.onGenerateContents(); }); }); @@ -132,12 +138,15 @@ * Handles Install button click. */ onInstall: function() { - var appListView = this.getElement_('app-list-view'); - appListView.executeScript( - {code: 'getSelectedPackages();'}, function(result) { - console.log(result[0]); - chrome.send('recommendAppsInstall', result[0]); - }); + // Only start installation if the button is not disabled. + if (!this.getElement_('recommend-apps-install-button').disabled) { + const appListView = this.getElement_('app-list-view'); + appListView.executeScript( + {code: 'getSelectedPackages();'}, function(result) { + console.log(result[0]); + chrome.send('recommendAppsInstall', result[0]); + }); + } }, /** @@ -153,6 +162,18 @@ }, /** + * Handles the message sent from the WebView. + */ + onMessage: function(event) { + if (event.data.type && (event.data.type === 'NUM_OF_SELECTED_APPS')) { + const numOfSelected = event.data.numOfSelected; + $('recommend-apps-screen') + .getElement('recommend-apps-install-button') + .disabled = (numOfSelected === 0); + } + }, + + /** * This is called to show/hide the loading UI. * @param {boolean} visible whether to show loading UI. */
diff --git a/chrome/browser/resources/local_ntp/custom_backgrounds.css b/chrome/browser/resources/local_ntp/custom_backgrounds.css index 9cbc5c78..014e137 100644 --- a/chrome/browser/resources/local_ntp/custom_backgrounds.css +++ b/chrome/browser/resources/local_ntp/custom_backgrounds.css
@@ -485,9 +485,10 @@ .selected-border { border: 2px solid rgba(26, 115, 232, .4); border-radius: 4px; - height: 113px; + box-sizing: border-box; + height: 100%; position: relative; - width: 152px; + width: 100%; } .selected-circle {
diff --git a/chrome/browser/resources/local_ntp/most_visited_single.css b/chrome/browser/resources/local_ntp/most_visited_single.css index 97f38461..455565f 100644 --- a/chrome/browser/resources/local_ntp/most_visited_single.css +++ b/chrome/browser/resources/local_ntp/most_visited_single.css
@@ -80,7 +80,8 @@ user-select: none; } -.md #mv-tiles { +.md #mv-tiles, +.md .mv-tiles-old { display: flex; flex-wrap: wrap; height: auto; @@ -91,10 +92,14 @@ * values in local_ntp.css. */ max-width: calc(var(--md-tile-width) * var(--md-max-tiles-row)); position: static; + transition-duration: 300ms; } .md .mv-tiles-old { - display: none; + left: 0; + margin: auto; + position: absolute; + right: 0; } .mv-tile,
diff --git a/chrome/browser/resources/settings/passwords_and_forms_page/passwords_shared_css.html b/chrome/browser/resources/settings/passwords_and_forms_page/passwords_shared_css.html index 7c97ad9..3dcec5c 100644 --- a/chrome/browser/resources/settings/passwords_and_forms_page/passwords_shared_css.html +++ b/chrome/browser/resources/settings/passwords_and_forms_page/passwords_shared_css.html
@@ -12,6 +12,7 @@ } .website-column { + align-items: center; display: flex; flex: 1; }
diff --git a/chrome/browser/resources_util.cc b/chrome/browser/resources_util.cc index d74bc7f..e2bbf23a9 100644 --- a/chrome/browser/resources_util.cc +++ b/chrome/browser/resources_util.cc
@@ -9,7 +9,7 @@ #include <utility> #include "base/containers/flat_map.h" -#include "base/lazy_instance.h" +#include "base/no_destructor.h" #include "build/build_config.h" #include "chrome/grit/theme_resources_map.h" #include "components/grit/components_scaled_resources_map.h" @@ -22,15 +22,22 @@ namespace { // A wrapper class that holds a map between resource strings and resource -// ids. This is done so we can use base::LazyInstance which takes care of +// ids. This is done so we can use base::NoDestructor which takes care of // thread safety in initializing the map for us. class ThemeMap { public: - typedef base::flat_map<std::string, int> StringIntMap; + using StringIntMap = base::flat_map<std::string, int>; ThemeMap() { + size_t storage_size = + kComponentsScaledResourcesSize + kThemeResourcesSize + kUiResourcesSize; +#if defined(OS_CHROMEOS) + storage_size += kUiChromeosResourcesSize; +#endif + // Construct in one-shot from a moved vector. std::vector<StringIntMap::value_type> storage; + storage.reserve(storage_size); for (size_t i = 0; i < kComponentsScaledResourcesSize; ++i) { storage.emplace_back(kComponentsScaledResources[i].name, @@ -52,22 +59,22 @@ id_map_ = StringIntMap(std::move(storage), base::KEEP_FIRST_OF_DUPES); } - int GetId(const std::string& resource_name) { + int GetId(const std::string& resource_name) const { auto it = id_map_.find(resource_name); - if (it == id_map_.end()) - return -1; - return it->second; + return it != id_map_.end() ? it->second : -1; } private: StringIntMap id_map_; }; -static base::LazyInstance<ThemeMap>::DestructorAtExit g_theme_ids = - LAZY_INSTANCE_INITIALIZER; +ThemeMap& GetThemeIdsMap() { + static base::NoDestructor<ThemeMap> s; + return *s; +} } // namespace int ResourcesUtil::GetThemeResourceId(const std::string& resource_name) { - return g_theme_ids.Get().GetId(resource_name); + return GetThemeIdsMap().GetId(resource_name); }
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 3faf0698..e5857a3 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -118,7 +118,6 @@ "find_bar/find_notification_details.h", "find_bar/find_tab_helper.cc", "find_bar/find_tab_helper.h", - "forced_reauthentication_dialog.h", "interventions/framebust_block_message_delegate.cc", "interventions/framebust_block_message_delegate.h", "interventions/intervention_delegate.h", @@ -2950,8 +2949,6 @@ "views/outdated_upgrade_bubble_view.h", "views/policy/enterprise_startup_dialog_view.cc", "views/policy/enterprise_startup_dialog_view.h", - "views/profiles/forced_reauthentication_dialog_view.cc", - "views/profiles/forced_reauthentication_dialog_view.h", "views/relaunch_notification/relaunch_notification_controller_platform_impl_desktop.cc", "views/relaunch_notification/relaunch_notification_controller_platform_impl_desktop.h", "views/relaunch_notification/relaunch_recommended_bubble_view.cc",
diff --git a/chrome/browser/ui/bookmarks/bookmark_browsertest.cc b/chrome/browser/ui/bookmarks/bookmark_browsertest.cc index b72d66d..4b1dad2 100644 --- a/chrome/browser/ui/bookmarks/bookmark_browsertest.cc +++ b/chrome/browser/ui/bookmarks/bookmark_browsertest.cc
@@ -178,16 +178,8 @@ #endif -// Flaky on Linux: http://crbug.com/504869. -#if defined(OS_LINUX) -#define MAYBE_HideStarOnNonbookmarkedInterstitial \ - DISABLED_HideStarOnNonbookmarkedInterstitial -#else -#define MAYBE_HideStarOnNonbookmarkedInterstitial \ - HideStarOnNonbookmarkedInterstitial -#endif IN_PROC_BROWSER_TEST_F(BookmarkBrowsertest, - MAYBE_HideStarOnNonbookmarkedInterstitial) { + HideStarOnNonbookmarkedInterstitial) { // Start an HTTPS server with a certificate error. net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS); https_server.SetSSLConfig(net::EmbeddedTestServer::CERT_MISMATCHED_NAME);
diff --git a/chrome/browser/ui/cocoa/permission_bubble/permission_bubble_views_cocoa_browsertest.mm b/chrome/browser/ui/cocoa/permission_bubble/permission_bubble_views_cocoa_browsertest.mm index fb212c9..249663a 100644 --- a/chrome/browser/ui/cocoa/permission_bubble/permission_bubble_views_cocoa_browsertest.mm +++ b/chrome/browser/ui/cocoa/permission_bubble/permission_bubble_views_cocoa_browsertest.mm
@@ -37,13 +37,7 @@ } bool HasVisibleLocationBarForBrowser(Browser* browser) { - if (!browser->SupportsWindowFeature(Browser::FEATURE_LOCATIONBAR)) - return false; - - if (!browser->exclusive_access_manager()->context()->IsFullscreen()) - return true; - - return false; + return browser->SupportsWindowFeature(Browser::FEATURE_LOCATIONBAR); } } // namespace @@ -81,10 +75,9 @@ EXPECT_FALSE(HasVisibleLocationBarForBrowser(app_browser)); } -// http://crbug.com/470724 -// Kiosk mode on Mac has a location bar but it shouldn't. IN_PROC_BROWSER_TEST_F(PermissionBubbleKioskBrowserTest, - DISABLED_KioskHasNoLocationBar) { + KioskHasNoLocationBar) { ShowBubble(browser()); + // Kiosk mode on Mac has no location bar. EXPECT_FALSE(HasVisibleLocationBarForBrowser(browser())); }
diff --git a/chrome/browser/ui/extensions/extension_message_bubble_factory.cc b/chrome/browser/ui/extensions/extension_message_bubble_factory.cc index 6dbe4e9ea..d64dea3 100644 --- a/chrome/browser/ui/extensions/extension_message_bubble_factory.cc +++ b/chrome/browser/ui/extensions/extension_message_bubble_factory.cc
@@ -6,8 +6,9 @@ #include "base/base_switches.h" #include "base/command_line.h" -#include "base/lazy_instance.h" #include "base/metrics/field_trial.h" +#include "base/no_destructor.h" +#include "base/stl_util.h" #include "build/build_config.h" #include "chrome/browser/extensions/dev_mode_bubble_delegate.h" #include "chrome/browser/extensions/extension_message_bubble_controller.h" @@ -26,12 +27,6 @@ namespace { -// A map of all profiles evaluated, so we can tell if it's the initial check. -// TODO(devlin): It would be nice to coalesce all the "profiles evaluated" maps -// that are in the different bubble controllers. -base::LazyInstance<std::set<Profile*>>::DestructorAtExit g_profiles_evaluated = - LAZY_INSTANCE_INITIALIZER; - // This is used to turn on override whether bubbles are enabled or disabled for // testing. ExtensionMessageBubbleFactory::OverrideForTesting g_override_for_testing = @@ -44,6 +39,14 @@ const char kEnableProxyWarningExperimentName[] = "ExtensionProxyWarning"; #endif +// A set of all profiles evaluated, so we can tell if it's the initial check. +// TODO(devlin): It would be nice to coalesce all the "profiles evaluated" maps +// that are in the different bubble controllers. +std::set<Profile*>& GetEvaluatedProfiles() { + static base::NoDestructor<std::set<Profile*>> s; + return *s; +} + bool IsExperimentEnabled(const char* experiment_name) { // Don't allow turning it off via command line. base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); @@ -115,12 +118,10 @@ std::unique_ptr<extensions::ExtensionMessageBubbleController> ExtensionMessageBubbleFactory::GetController() { Profile* original_profile = browser_->profile()->GetOriginalProfile(); - std::set<Profile*>& profiles_evaluated = g_profiles_evaluated.Get(); - bool is_initial_check = profiles_evaluated.count(original_profile) == 0; - profiles_evaluated.insert(original_profile); + std::set<Profile*>& profiles_evaluated = GetEvaluatedProfiles(); + bool is_initial_check = profiles_evaluated.insert(original_profile).second; std::unique_ptr<extensions::ExtensionMessageBubbleController> controller; - if (g_override_for_testing == OVERRIDE_DISABLED) return controller;
diff --git a/chrome/browser/ui/forced_reauthentication_dialog.h b/chrome/browser/ui/forced_reauthentication_dialog.h deleted file mode 100644 index 6beab174..0000000 --- a/chrome/browser/ui/forced_reauthentication_dialog.h +++ /dev/null
@@ -1,44 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_FORCED_REAUTHENTICATION_DIALOG_H_ -#define CHROME_BROWSER_UI_FORCED_REAUTHENTICATION_DIALOG_H_ - -#include <memory> - -#include "base/macros.h" - -namespace identity { -class IdentityManager; -} - -class Profile; - -namespace base { -class TimeDelta; -} // namespace base - -// The virtual class of ForcedReauthenticationDialog. -class ForcedReauthenticationDialog { - public: - static std::unique_ptr<ForcedReauthenticationDialog> Create(); - - virtual ~ForcedReauthenticationDialog() {} - // Show the ForcedReauthenticationDialog for |profile|. If there're no opened - // browser windows for |profile|, |identity_manager| will be called to signed - // out immediately. Otherwise, dialog will be closed with all browser windows - // are associated to |profile| after |countdown_duration| if there is no - // reauth. - virtual void ShowDialog(Profile* profile, - identity::IdentityManager* identity_manager, - base::TimeDelta countdown_duration) = 0; - - protected: - ForcedReauthenticationDialog() {} - - private: - DISALLOW_COPY_AND_ASSIGN(ForcedReauthenticationDialog); -}; - -#endif // CHROME_BROWSER_UI_FORCED_REAUTHENTICATION_DIALOG_H_
diff --git a/chrome/browser/ui/permission_bubble/permission_bubble_browser_test_util.cc b/chrome/browser/ui/permission_bubble/permission_bubble_browser_test_util.cc index 4a671d0c..03cd7df 100644 --- a/chrome/browser/ui/permission_bubble/permission_bubble_browser_test_util.cc +++ b/chrome/browser/ui/permission_bubble/permission_bubble_browser_test_util.cc
@@ -15,7 +15,9 @@ #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/common/chrome_switches.h" #include "chrome/grit/generated_resources.h" +#include "chrome/test/base/ui_test_utils.h" #include "ui/base/l10n/l10n_util.h" +#include "url/gurl.h" TestPermissionBubbleViewDelegate::TestPermissionBubbleViewDelegate() : PermissionPrompt::Delegate() { @@ -81,4 +83,8 @@ base::CommandLine* command_line) { PermissionBubbleBrowserTest::SetUpCommandLine(command_line); command_line->AppendSwitch(switches::kKioskMode); + // Navigate to a test file URL. + GURL test_file_url(ui_test_utils::GetTestUrl( + base::FilePath(), base::FilePath(FILE_PATH_LITERAL("simple.html")))); + command_line->AppendArg(test_file_url.spec()); }
diff --git a/chrome/browser/ui/sync/profile_signin_confirmation_helper.h b/chrome/browser/ui/sync/profile_signin_confirmation_helper.h index 30675726..65b6bc44 100644 --- a/chrome/browser/ui/sync/profile_signin_confirmation_helper.h +++ b/chrome/browser/ui/sync/profile_signin_confirmation_helper.h
@@ -14,10 +14,6 @@ class NativeTheme; -// Blend parameters for the dialog prompt bar. -const SkAlpha kSigninConfirmationPromptBarBackgroundAlpha = 0x0A; -const SkAlpha kSigninConfirmationPromptBarBorderAlpha = 0x1F; - // Create slightly different colors for the dialog prompt bar. SkColor GetSigninConfirmationPromptBarColor(NativeTheme* theme, SkAlpha alpha);
diff --git a/chrome/browser/ui/tab_helpers.cc b/chrome/browser/ui/tab_helpers.cc index d0266c8d..4b6f16b 100644 --- a/chrome/browser/ui/tab_helpers.cc +++ b/chrome/browser/ui/tab_helpers.cc
@@ -122,6 +122,7 @@ #endif #if BUILDFLAG(ENABLE_OFFLINE_PAGES) +#include "chrome/browser/offline_pages/auto_fetch_page_load_watcher.h" #include "chrome/browser/offline_pages/offline_page_tab_helper.h" #include "chrome/browser/offline_pages/recent_tab_helper.h" #endif @@ -323,6 +324,7 @@ #if BUILDFLAG(ENABLE_OFFLINE_PAGES) offline_pages::OfflinePageTabHelper::CreateForWebContents(web_contents); offline_pages::RecentTabHelper::CreateForWebContents(web_contents); +offline_pages::AutoFetchPageLoadWatcher::CreateForWebContents(web_contents); #endif #if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION)
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.mm b/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.mm index 3ca52ec..17ce7ce 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.mm +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.mm
@@ -4,6 +4,7 @@ #include "chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.h" +#include "base/command_line.h" #include "base/metrics/histogram_macros.h" #include "chrome/browser/themes/theme_properties.h" #include "chrome/browser/themes/theme_service.h" @@ -19,6 +20,7 @@ #include "chrome/browser/ui/views/frame/browser_view_layout.h" #include "chrome/browser/ui/views/frame/hosted_app_button_container.h" #include "chrome/browser/ui/views/toolbar/toolbar_view.h" +#include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" #include "components/prefs/pref_service.h" #include "ui/base/hit_test.h" @@ -32,6 +34,9 @@ FullscreenToolbarStyle GetUserPreferredToolbarStyle( const PrefService* pref_service) { + // In Kiosk mode, we don't show top Chrome UI. + if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kKioskMode)) + return FullscreenToolbarStyle::TOOLBAR_NONE; return pref_service->GetBoolean(prefs::kShowFullscreenToolbar) ? FullscreenToolbarStyle::TOOLBAR_PRESENT : FullscreenToolbarStyle::TOOLBAR_HIDDEN;
diff --git a/chrome/browser/ui/views/profiles/forced_reauthentication_dialog_view.cc b/chrome/browser/ui/views/profiles/forced_reauthentication_dialog_view.cc deleted file mode 100644 index 4178179..0000000 --- a/chrome/browser/ui/views/profiles/forced_reauthentication_dialog_view.cc +++ /dev/null
@@ -1,288 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/views/profiles/forced_reauthentication_dialog_view.h" - -#include <map> -#include <memory> -#include <string> -#include <utility> - -#include "base/i18n/message_formatter.h" -#include "base/strings/string16.h" -#include "base/strings/utf_string_conversions.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/browser_list.h" -#include "chrome/browser/ui/browser_window.h" -#include "chrome/browser/ui/sync/profile_signin_confirmation_helper.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/browser/ui/views/chrome_layout_provider.h" -#include "chrome/browser/ui/views/chrome_typography.h" -#include "chrome/browser/ui/views/frame/browser_view.h" -#include "chrome/grit/chromium_strings.h" -#include "chrome/grit/generated_resources.h" -#include "components/constrained_window/constrained_window_views.h" -#include "components/signin/core/browser/signin_manager.h" -#include "services/identity/public/cpp/identity_manager.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/views/background.h" -#include "ui/views/border.h" -#include "ui/views/controls/styled_label.h" -#include "ui/views/layout/grid_layout.h" -#include "ui/views/view.h" -#include "ui/views/window/dialog_client_view.h" - -namespace { - -// Refresh title of the dialog every second. -constexpr int kRefreshTitleTimer = 1; - -// If browser windows are going to be closed soon, close browser window before -// showing sign in dialog because there might not be enough time for user to -// finish sign in. -constexpr int kCloseDirectlyTimer = 60; - -void Signout(identity::IdentityManager* identity_manager) { - identity_manager->ClearPrimaryAccount( - identity::IdentityManager::ClearAccountTokensAction::kDefault, - signin_metrics::AUTHENTICATION_FAILED_WITH_FORCE_SIGNIN, - signin_metrics::SignoutDelete::KEEPING); -} - -bool IsMatchingBrowser(Browser* browser, Profile* profile) { - return browser->profile()->GetOriginalProfile() == - profile->GetOriginalProfile() && - !browser->tab_strip_model()->empty() && browser->window()->IsVisible(); -} - -// Find a browser that is associated with |profile| to show the dialog for -// Sign out warning. -Browser* FindBrowserWithProfile(Profile* profile) { - Browser* browser = BrowserList::GetInstance()->GetLastActive(); - if (browser && IsMatchingBrowser(browser, profile)) - return browser; - for (auto* browser : *BrowserList::GetInstance()) { - if (IsMatchingBrowser(browser, profile)) { - return browser; - } - } - return nullptr; -} - -// PromptLabel overrides the default insets of StyledLabel. -class PromptLabel : public views::StyledLabel { - public: - PromptLabel(const base::string16& text, views::StyledLabelListener* listener) - : views::StyledLabel(text, listener) {} - - gfx::Insets GetInsets() const override { - return ChromeLayoutProvider::Get()->GetInsetsMetric( - views::INSETS_DIALOG_SUBSECTION); - } -}; - -} // namespace - -// ForcedReauthenticationDialogView - -ForcedReauthenticationDialogView::ForcedReauthenticationDialogView( - Browser* browser, - identity::IdentityManager* identity_manager, - base::TimeDelta countdown_duration) - : browser_(browser), - identity_manager_(identity_manager), - desired_close_time_(base::TimeTicks::Now() + countdown_duration), - weak_factory_(this) { - constrained_window::CreateBrowserModalDialogViews( - this, browser->window()->GetNativeWindow()) - ->Show(); - browser->window()->FlashFrame(true); - browser->window()->Activate(); -} - -ForcedReauthenticationDialogView::~ForcedReauthenticationDialogView() {} - -// static -ForcedReauthenticationDialogView* ForcedReauthenticationDialogView::ShowDialog( - Profile* profile, - identity::IdentityManager* identity_manager, - base::TimeDelta countdown_duration) { - Browser* browser = FindBrowserWithProfile(profile); - if (browser == nullptr) { // If there is no browser, we can just sign - // out profile directly. - Signout(identity_manager); - return nullptr; - } - - return new ForcedReauthenticationDialogView(browser, identity_manager, - countdown_duration); -} - -bool ForcedReauthenticationDialogView::Accept() { - if (GetTimeRemaining() < base::TimeDelta::FromSeconds(kCloseDirectlyTimer)) { - Signout(identity_manager_); - } else { - browser_->signin_view_controller()->ShowSignin( - profiles::BubbleViewMode::BUBBLE_VIEW_MODE_GAIA_REAUTH, browser_, - signin_metrics::AccessPoint::ACCESS_POINT_FORCE_SIGNIN_WARNING); - } - return true; -} - -bool ForcedReauthenticationDialogView::Cancel() { - return true; -} - -void ForcedReauthenticationDialogView::WindowClosing() { - refresh_timer_.Stop(); -} - -base::string16 ForcedReauthenticationDialogView::GetWindowTitle() const { - base::TimeDelta time_left = GetTimeRemaining(); - return base::i18n::MessageFormatter::FormatWithNumberedArgs( - l10n_util::GetStringUTF16(IDS_ENTERPRISE_FORCE_SIGNOUT_TITLE), - time_left.InMinutes(), time_left.InSeconds() % 60); -} - -base::string16 ForcedReauthenticationDialogView::GetDialogButtonLabel( - ui::DialogButton button) const { - if (button == ui::DIALOG_BUTTON_OK) { - return l10n_util::GetStringUTF16( - IDS_ENTERPRISE_FORCE_SIGNOUT_CLOSE_CONFIRM); - } - return l10n_util::GetStringUTF16(IDS_ENTERPRISE_FORCE_SIGNOUT_CLOSE_DELAY); -} - -ui::ModalType ForcedReauthenticationDialogView::GetModalType() const { - return ui::MODAL_TYPE_WINDOW; -} - -void ForcedReauthenticationDialogView::AddedToWidget() { - const SkColor prompt_bar_background_color = - GetSigninConfirmationPromptBarColor( - GetNativeTheme(), ui::kSigninConfirmationPromptBarBackgroundAlpha); - // Create the prompt label. - size_t offset; - std::string email = identity_manager_->GetPrimaryAccountInfo().email; - const base::string16 domain = - base::ASCIIToUTF16(gaia::ExtractDomainName(email)); - const base::string16 prompt_text = - l10n_util::GetStringFUTF16(IDS_ENTERPRISE_SIGNIN_ALERT, domain, &offset); - - // Create the prompt label. - PromptLabel* prompt_label = new PromptLabel(prompt_text, nullptr); - prompt_label->SetDisplayedOnBackgroundColor(prompt_bar_background_color); - - views::StyledLabel::RangeStyleInfo bold_style; - bold_style.text_style = STYLE_EMPHASIZED; - prompt_label->AddStyleRange(gfx::Range(offset, offset + domain.size()), - bold_style); - - prompt_label->SetBorder(views::CreateSolidSidedBorder( - 1, 0, 1, 0, - ui::GetSigninConfirmationPromptBarColor( - GetNativeTheme(), ui::kSigninConfirmationPromptBarBorderAlpha))); - prompt_label->SetBackground( - views::CreateSolidBackground(prompt_bar_background_color)); - - // Create the explanation label. - base::string16 signin_explanation_text; - base::string16 close_warning; - close_warning = l10n_util::GetStringUTF16( - IDS_ENTERPRISE_FORCE_SIGNOUT_ADDITIONAL_EXPLANATION); - if (email.empty()) { - signin_explanation_text = l10n_util::GetStringFUTF16( - IDS_ENTERPRISE_FORCE_SIGNOUT_EXPLANATION_WITHOUT_USER_NAME, - close_warning); - } else { - signin_explanation_text = - l10n_util::GetStringFUTF16(IDS_ENTERPRISE_FORCE_SIGNOUT_EXPLANATION, - base::ASCIIToUTF16(email), close_warning); - } - views::StyledLabel* explanation_label = - new views::StyledLabel(signin_explanation_text, nullptr); - - ChromeLayoutProvider* provider = ChromeLayoutProvider::Get(); - // Layout the components. - const gfx::Insets dialog_insets = - provider->GetDialogInsetsForContentType(views::TEXT, views::TEXT); - SetBorder(views::CreateEmptyBorder(dialog_insets.top(), 0, - dialog_insets.bottom(), 0)); - views::GridLayout* dialog_layout = - SetLayoutManager(std::make_unique<views::GridLayout>(this)); - - // Use a column set with no padding. - dialog_layout->AddColumnSet(0)->AddColumn(views::GridLayout::FILL, - views::GridLayout::FILL, 1.0, - views::GridLayout::USE_PREF, 0, 0); - dialog_layout->StartRow(views::GridLayout::kFixedSize, 0); - dialog_layout->AddView(prompt_label, 1, 1, views::GridLayout::FILL, - views::GridLayout::FILL, 0, 0); - - // Use a new column set for the explanation label so we can add padding. - dialog_layout->AddPaddingRow(views::GridLayout::kFixedSize, - dialog_insets.top()); - views::ColumnSet* explanation_columns = dialog_layout->AddColumnSet(1); - - explanation_columns->AddPaddingColumn(views::GridLayout::kFixedSize, - dialog_insets.left()); - explanation_columns->AddColumn(views::GridLayout::FILL, - views::GridLayout::FILL, 1.0, - views::GridLayout::USE_PREF, 0, 0); - explanation_columns->AddPaddingColumn(views::GridLayout::kFixedSize, - dialog_insets.right()); - dialog_layout->StartRow(views::GridLayout::kFixedSize, 1); - const int kPreferredWidth = 440; - dialog_layout->AddView(explanation_label, 1, 1, views::GridLayout::FILL, - views::GridLayout::FILL, kPreferredWidth, - explanation_label->GetHeightForWidth(kPreferredWidth)); - refresh_timer_.Start(FROM_HERE, - base::TimeDelta::FromSeconds(kRefreshTitleTimer), this, - &ForcedReauthenticationDialogView::OnCountDown); -} - -void ForcedReauthenticationDialogView::CloseDialog() { - GetWidget()->Close(); -} - -void ForcedReauthenticationDialogView::OnCountDown() { - if (desired_close_time_ <= base::TimeTicks::Now()) { - Cancel(); - GetWidget()->Close(); - } - GetWidget()->UpdateWindowTitle(); -} - -base::TimeDelta ForcedReauthenticationDialogView::GetTimeRemaining() const { - base::TimeTicks now = base::TimeTicks::Now(); - if (desired_close_time_ <= now) - return base::TimeDelta(); - return desired_close_time_ - now; -} - -// ForcedReauthenticationDialogImpl - -ForcedReauthenticationDialogImpl::ForcedReauthenticationDialogImpl() {} -ForcedReauthenticationDialogImpl::~ForcedReauthenticationDialogImpl() { - if (dialog_view_) - dialog_view_->CloseDialog(); -} - -void ForcedReauthenticationDialogImpl::ShowDialog( - Profile* profile, - identity::IdentityManager* identity_manager, - base::TimeDelta countdown_duration) { - dialog_view_ = ForcedReauthenticationDialogView::ShowDialog( - profile, identity_manager, countdown_duration) - ->AsWeakPtr(); -} - -// ForcedReauthenticationDialog - -// static -std::unique_ptr<ForcedReauthenticationDialog> -ForcedReauthenticationDialog::Create() { - return std::make_unique<ForcedReauthenticationDialogImpl>(); -}
diff --git a/chrome/browser/ui/views/profiles/forced_reauthentication_dialog_view.h b/chrome/browser/ui/views/profiles/forced_reauthentication_dialog_view.h deleted file mode 100644 index d4a9885..0000000 --- a/chrome/browser/ui/views/profiles/forced_reauthentication_dialog_view.h +++ /dev/null
@@ -1,97 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_VIEWS_PROFILES_FORCED_REAUTHENTICATION_DIALOG_VIEW_H_ -#define CHROME_BROWSER_UI_VIEWS_PROFILES_FORCED_REAUTHENTICATION_DIALOG_VIEW_H_ - -#include <memory> -#include <string> - -#include "base/callback.h" -#include "base/macros.h" -#include "base/memory/weak_ptr.h" -#include "base/timer/timer.h" -#include "chrome/browser/ui/forced_reauthentication_dialog.h" -#include "ui/views/controls/button/button.h" -#include "ui/views/window/dialog_delegate.h" - -namespace identity { -class IdentityManager; -} - -class Browser; -class Profile; - -// A modal dialog that displays a warning message of the auth failure -// and ask user to sign in again. -class ForcedReauthenticationDialogView : public views::DialogDelegateView { - public: - ~ForcedReauthenticationDialogView() override; - - // Shows a warning dialog for |profile|. If there are no Browser windows - // associated with |profile|, signs out the profile immediately, otherwise the - // user can clicks accept to sign in again. Dialog will be closed after - // |countdown_duration| seconds. - // Dialog will delete itself after closing. - static ForcedReauthenticationDialogView* ShowDialog( - Profile* profile, - identity::IdentityManager* identity_manager, - base::TimeDelta countdown_duration); - - // override views::DialogDelegateView - bool Accept() override; - bool Cancel() override; - void WindowClosing() override; - base::string16 GetWindowTitle() const override; - base::string16 GetDialogButtonLabel(ui::DialogButton button) const override; - ui::ModalType GetModalType() const override; - - // override views::View - void AddedToWidget() override; - - // Close the dialog - void CloseDialog(); - - base::WeakPtr<ForcedReauthenticationDialogView> AsWeakPtr() { - return weak_factory_.GetWeakPtr(); - } - - private: - // Show the dialog for |browser|. The dialog will delete itself after closing. - ForcedReauthenticationDialogView(Browser* browser, - identity::IdentityManager* identity_manager, - base::TimeDelta countdown_duration); - - void OnCountDown(); - base::TimeDelta GetTimeRemaining() const; - - Browser* const browser_; - identity::IdentityManager* identity_manager_; - - const base::TimeTicks desired_close_time_; - - // The timer which is used to refresh the dialog title to display the - // remaining time. - base::RepeatingTimer refresh_timer_; - - base::WeakPtrFactory<ForcedReauthenticationDialogView> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(ForcedReauthenticationDialogView); -}; - -class ForcedReauthenticationDialogImpl : public ForcedReauthenticationDialog { - public: - ForcedReauthenticationDialogImpl(); - ~ForcedReauthenticationDialogImpl() override; - - // override ForcedReauthenticationDialog - void ShowDialog(Profile* profile, - identity::IdentityManager* identity_manager, - base::TimeDelta countdown_duration) override; - - private: - base::WeakPtr<ForcedReauthenticationDialogView> dialog_view_; -}; - -#endif // CHROME_BROWSER_UI_VIEWS_PROFILES_FORCED_REAUTHENTICATION_DIALOG_VIEW_H_
diff --git a/chrome/browser/ui/views/profiles/forced_reauthentication_dialog_view_browsertest.cc b/chrome/browser/ui/views/profiles/forced_reauthentication_dialog_view_browsertest.cc deleted file mode 100644 index 8080fdb..0000000 --- a/chrome/browser/ui/views/profiles/forced_reauthentication_dialog_view_browsertest.cc +++ /dev/null
@@ -1,72 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/views/profiles/forced_reauthentication_dialog_view.h" - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "chrome/browser/signin/identity_manager_factory.h" -#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" -#include "chrome/browser/signin/signin_manager_factory.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/browser/ui/test/test_browser_dialog.h" -#include "chrome/test/base/in_process_browser_test.h" -#include "services/identity/public/cpp/identity_manager.h" -#include "services/identity/public/cpp/identity_test_utils.h" -#include "ui/base/ui_base_types.h" - -class ForcedReauthenticationDialogViewBrowserTest : public DialogBrowserTest { - public: - ForcedReauthenticationDialogViewBrowserTest() {} - - // override DialogBrowserTest - void ShowUi(const std::string& name) override { - Profile* profile = browser()->profile(); - identity::IdentityManager* manager = - IdentityManagerFactory::GetForProfile(profile); - - identity::MakePrimaryAccountAvailable( - SigninManagerFactory::GetForProfile(profile), - ProfileOAuth2TokenServiceFactory::GetForProfile(profile), manager, - "test@xyz.com"); - - ForcedReauthenticationDialogView::ShowDialog( - profile, manager, base::TimeDelta::FromSeconds(60)); - } - - // An integer represents the buttons of dialog. - - private: - DISALLOW_COPY_AND_ASSIGN(ForcedReauthenticationDialogViewBrowserTest); -}; - -IN_PROC_BROWSER_TEST_F(ForcedReauthenticationDialogViewBrowserTest, - InvokeUi_default) { - ShowAndVerifyUi(); -} - -// Dialog will not be display if there is no valid browser window. -IN_PROC_BROWSER_TEST_F(ForcedReauthenticationDialogViewBrowserTest, - NotOpenDialogDueToNoBrowser) { - Profile* profile = browser()->profile(); - CloseBrowserSynchronously(browser()); - EXPECT_EQ(nullptr, - ForcedReauthenticationDialogView::ShowDialog( - profile, IdentityManagerFactory::GetForProfile(profile), - base::TimeDelta::FromSeconds(60))); -} - -IN_PROC_BROWSER_TEST_F(ForcedReauthenticationDialogViewBrowserTest, - NotOpenDialogDueToNoTabs) { - Profile* profile = browser()->profile(); - TabStripModel* model = browser()->tab_strip_model(); - ASSERT_EQ(1, model->count()); - model->CloseWebContentsAt(0, TabStripModel::CLOSE_NONE); - ASSERT_TRUE(model->empty()); - EXPECT_EQ(nullptr, - ForcedReauthenticationDialogView::ShowDialog( - profile, IdentityManagerFactory::GetForProfile(profile), - base::TimeDelta::FromSeconds(60))); -}
diff --git a/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.cc b/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.cc index eef4d37..6ff28f4 100644 --- a/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.cc +++ b/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.cc
@@ -152,8 +152,7 @@ return; const SkColor kPromptBarBackgroundColor = - ui::GetSigninConfirmationPromptBarColor( - GetNativeTheme(), ui::kSigninConfirmationPromptBarBackgroundAlpha); + ui::GetSigninConfirmationPromptBarColor(GetNativeTheme(), 0x0A); // Create business icon. int business_icon_size = 20; @@ -183,8 +182,7 @@ views::View* prompt_bar = new views::View; prompt_bar->SetBorder(views::CreateSolidSidedBorder( 1, 0, 1, 0, - ui::GetSigninConfirmationPromptBarColor( - GetNativeTheme(), ui::kSigninConfirmationPromptBarBorderAlpha))); + ui::GetSigninConfirmationPromptBarColor(GetNativeTheme(), 0x1F))); prompt_bar->SetBackground( views::CreateSolidBackground(kPromptBarBackgroundColor));
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc index 4a95bae..c6cc7cfc 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.cc +++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -429,8 +429,14 @@ void TabStrip::AddTabAt(int model_index, TabRendererData data, bool is_active) { const bool was_single_tab_mode = SingleTabMode(); + // Get view child index of where we want to insert + int view_index = 0; + if (model_index > 0) { + view_index = GetIndexOf(tab_at(model_index - 1)) + 1; + } + Tab* tab = new Tab(this, animation_container_.get()); - AddChildView(tab); + AddChildViewAt(tab, view_index); const bool pinned = data.pinned; tab->SetData(std::move(data)); UpdateTabsClosingMap(model_index, 1); @@ -487,8 +493,14 @@ int to_model_index, TabRendererData data) { DCHECK_GT(tabs_.view_size(), 0); + const Tab* last_tab = GetLastVisibleTab(); tab_at(from_model_index)->SetData(std::move(data)); + + // Keep child views in same order as tab strip model. + const int to_view_index = GetIndexOf(tab_at(to_model_index)); + ReorderChildView(tab_at(from_model_index), to_view_index); + if (touch_layout_) { tabs_.MoveViewOnly(from_model_index, to_model_index); int pinned_count = 0;
diff --git a/chrome/browser/ui/views/tabs/tab_strip_unittest.cc b/chrome/browser/ui/views/tabs/tab_strip_unittest.cc index 3ef3a6e..5e351b1 100644 --- a/chrome/browser/ui/views/tabs/tab_strip_unittest.cc +++ b/chrome/browser/ui/views/tabs/tab_strip_unittest.cc
@@ -311,6 +311,40 @@ EXPECT_EQ(0, observer.last_tab_removed()); } +namespace { + +bool TabViewsInOrder(TabStrip* tab_strip) { + for (int i = 1; i < tab_strip->tab_count(); ++i) { + Tab* left = tab_strip->tab_at(i - 1); + Tab* right = tab_strip->tab_at(i); + + if (tab_strip->GetIndexOf(right) < tab_strip->GetIndexOf(left)) { + return false; + } + } + + return true; +} + +} // namespace + +// Verifies child view order matches model order. +TEST_P(TabStripTest, TabViewOrder) { + controller_->AddTab(0, false); + controller_->AddTab(1, false); + controller_->AddTab(2, false); + EXPECT_TRUE(TabViewsInOrder(tab_strip_)); + + tab_strip_->MoveTab(0, 1, TabRendererData()); + EXPECT_TRUE(TabViewsInOrder(tab_strip_)); + tab_strip_->MoveTab(1, 2, TabRendererData()); + EXPECT_TRUE(TabViewsInOrder(tab_strip_)); + tab_strip_->MoveTab(1, 0, TabRendererData()); + EXPECT_TRUE(TabViewsInOrder(tab_strip_)); + tab_strip_->MoveTab(0, 2, TabRendererData()); + EXPECT_TRUE(TabViewsInOrder(tab_strip_)); +} + TEST_P(TabStripTest, VisibilityInOverflow) { constexpr int kInitialWidth = 250; tab_strip_->SetBounds(0, 0, kInitialWidth, 20);
diff --git a/chrome/browser/vr/BUILD.gn b/chrome/browser/vr/BUILD.gn index 96b2db8..58c08c1 100644 --- a/chrome/browser/vr/BUILD.gn +++ b/chrome/browser/vr/BUILD.gn
@@ -235,6 +235,8 @@ "location_bar_helper.cc", "location_bar_helper.h", "platform_controller.h", + "platform_controller_for_testing.cc", + "platform_controller_for_testing.h", "sample_queue.cc", "sample_queue.h", "scheduler_browser_renderer_interface.h",
diff --git a/chrome/browser/vr/input_delegate_for_testing.cc b/chrome/browser/vr/input_delegate_for_testing.cc index 1cd0d55..d244b1f 100644 --- a/chrome/browser/vr/input_delegate_for_testing.cc +++ b/chrome/browser/vr/input_delegate_for_testing.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/vr/input_delegate_for_testing.h" #include "chrome/browser/vr/input_event.h" +#include "chrome/browser/vr/platform_controller_for_testing.h" #include "chrome/browser/vr/ui_interface.h" #include "chrome/browser/vr/ui_scene_constants.h" #include "chrome/browser/vr/ui_test_input.h" @@ -35,6 +36,7 @@ namespace vr { InputDelegateForTesting::InputDelegateForTesting(UiInterface* ui) : ui_(ui) { + gesture_detector_ = std::make_unique<GestureDetector>(); cached_controller_model_.laser_direction = kForwardVector; SetOriginAndTransform(&cached_controller_model_); } @@ -54,23 +56,17 @@ DCHECK_NE(controller_input.action, VrControllerTestAction::kRevertToRealInput); ControllerModel controller_model; - auto target_point = ui_->GetTargetPointForTesting( - controller_input.element_name, controller_input.position); - auto direction = (target_point - kStartControllerPosition) - kOrigin; - direction.GetNormalized(&controller_model.laser_direction); + if (controller_input.element_name == UserFriendlyElementName::kNone) { + controller_model.laser_direction = kForwardVector; + } else { + auto target_point = ui_->GetTargetPointForTesting( + controller_input.element_name, controller_input.position); + auto direction = (target_point - kStartControllerPosition) - kOrigin; + direction.GetNormalized(&controller_model.laser_direction); + } SetOriginAndTransform(&controller_model); switch (controller_input.action) { - case VrControllerTestAction::kClick: - // Add in the button down action. - controller_model.touchpad_button_state = - ControllerModel::ButtonState::kDown; - controller_model_queue_.push(controller_model); - // Add in the button up action. - controller_model.touchpad_button_state = - ControllerModel::ButtonState::kUp; - controller_model_queue_.push(controller_model); - break; case VrControllerTestAction::kHover: FALLTHROUGH; case VrControllerTestAction::kClickUp: @@ -94,6 +90,14 @@ } controller_model_queue_.push(controller_model); break; + case VrControllerTestAction::kAppDown: + controller_model.app_button_state = ControllerModel::ButtonState::kDown; + controller_model_queue_.push(controller_model); + break; + case VrControllerTestAction::kAppUp: + controller_model.app_button_state = ControllerModel::ButtonState::kUp; + controller_model_queue_.push(controller_model); + break; default: NOTREACHED() << "Given unsupported controller action"; } @@ -106,6 +110,7 @@ void InputDelegateForTesting::UpdateController(const gfx::Transform& head_pose, base::TimeTicks current_time, bool is_webxr_frame) { + previous_controller_model_ = cached_controller_model_; if (!controller_model_queue_.empty()) { cached_controller_model_ = controller_model_queue_.front(); controller_model_queue_.pop(); @@ -121,7 +126,9 @@ InputEventList InputDelegateForTesting::GetGestures( base::TimeTicks current_time) { - return InputEventList(); + PlatformControllerForTesting controller(&previous_controller_model_, + &cached_controller_model_); + return gesture_detector_->DetectGestures(controller, current_time); } device::mojom::XRInputSourceStatePtr
diff --git a/chrome/browser/vr/input_delegate_for_testing.h b/chrome/browser/vr/input_delegate_for_testing.h index af494d6..ce56d827 100644 --- a/chrome/browser/vr/input_delegate_for_testing.h +++ b/chrome/browser/vr/input_delegate_for_testing.h
@@ -8,6 +8,7 @@ #include <queue> #include "base/macros.h" +#include "chrome/browser/vr/gesture_detector.h" #include "chrome/browser/vr/input_delegate.h" #include "chrome/browser/vr/model/controller_model.h" @@ -40,6 +41,8 @@ UiInterface* ui_; std::queue<ControllerModel> controller_model_queue_; ControllerModel cached_controller_model_; + ControllerModel previous_controller_model_; + std::unique_ptr<GestureDetector> gesture_detector_; DISALLOW_COPY_AND_ASSIGN(InputDelegateForTesting); };
diff --git a/chrome/browser/vr/platform_controller_for_testing.cc b/chrome/browser/vr/platform_controller_for_testing.cc new file mode 100644 index 0000000..7f80141 --- /dev/null +++ b/chrome/browser/vr/platform_controller_for_testing.cc
@@ -0,0 +1,99 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/vr/platform_controller_for_testing.h" +#include "base/time/time.h" +#include "chrome/browser/vr/model/controller_model.h" +#include "ui/gfx/geometry/point_f.h" + +namespace vr { + +PlatformControllerForTesting::PlatformControllerForTesting( + ControllerModel* prev_model, + ControllerModel* cur_model) + : prev_model_(prev_model), cur_model_(cur_model) {} + +bool PlatformControllerForTesting::IsButtonDown( + PlatformController::ButtonType type) const { + switch (type) { + case PlatformController::ButtonType::kButtonMenu: + return cur_model_->app_button_state == + ControllerModel::ButtonState::kDown; + case PlatformController::ButtonType::kButtonSelect: + return cur_model_->touchpad_button_state == + ControllerModel::ButtonState::kDown; + default: + return false; + } +} + +bool PlatformControllerForTesting::ButtonUpHappened( + PlatformController::ButtonType type) const { + switch (type) { + case PlatformController::ButtonType::kButtonMenu: + return (cur_model_->app_button_state == + ControllerModel::ButtonState::kUp && + cur_model_->app_button_state != prev_model_->app_button_state); + case PlatformController::ButtonType::kButtonSelect: + return (cur_model_->touchpad_button_state == + ControllerModel::ButtonState::kUp && + cur_model_->touchpad_button_state != + prev_model_->touchpad_button_state); + default: + return false; + } +} + +bool PlatformControllerForTesting::ButtonDownHappened( + PlatformController::ButtonType type) const { + switch (type) { + case PlatformController::ButtonType::kButtonMenu: + return (cur_model_->app_button_state == + ControllerModel::ButtonState::kDown && + cur_model_->app_button_state != prev_model_->app_button_state); + case PlatformController::ButtonType::kButtonSelect: + return (cur_model_->touchpad_button_state == + ControllerModel::ButtonState::kDown && + cur_model_->touchpad_button_state != + prev_model_->touchpad_button_state); + default: + return false; + } +} + +bool PlatformControllerForTesting::IsTouchingTrackpad() const { + return false; +} + +gfx::PointF PlatformControllerForTesting::GetPositionInTrackpad() const { + return gfx::PointF(); +} + +base::TimeTicks PlatformControllerForTesting::GetLastOrientationTimestamp() + const { + return prev_model_->last_orientation_timestamp; +} + +base::TimeTicks PlatformControllerForTesting::GetLastTouchTimestamp() const { + return prev_model_->last_button_timestamp; +} + +base::TimeTicks PlatformControllerForTesting::GetLastButtonTimestamp() const { + return prev_model_->last_button_timestamp; +} + +ControllerModel::Handedness PlatformControllerForTesting::GetHandedness() + const { + return ControllerModel::Handedness::kRightHanded; +} + +bool PlatformControllerForTesting::GetRecentered() const { + return false; +} + +int PlatformControllerForTesting::GetBatteryLevel() const { + return 100; +} + +} // namespace vr
diff --git a/chrome/browser/vr/platform_controller_for_testing.h b/chrome/browser/vr/platform_controller_for_testing.h new file mode 100644 index 0000000..0964c94c --- /dev/null +++ b/chrome/browser/vr/platform_controller_for_testing.h
@@ -0,0 +1,41 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_VR_PLATFORM_CONTROLLER_FOR_TESTING_H_ +#define CHROME_BROWSER_VR_PLATFORM_CONTROLLER_FOR_TESTING_H_ + +#include "base/macros.h" +#include "base/time/time.h" +#include "chrome/browser/vr/model/controller_model.h" +#include "chrome/browser/vr/platform_controller.h" + +namespace vr { + +class PlatformControllerForTesting : public PlatformController { + public: + explicit PlatformControllerForTesting(ControllerModel* prev_model, + ControllerModel* cur_model); + ~PlatformControllerForTesting() override{}; + + bool IsButtonDown(PlatformController::ButtonType type) const override; + bool ButtonUpHappened(PlatformController::ButtonType type) const override; + bool ButtonDownHappened(PlatformController::ButtonType type) const override; + bool IsTouchingTrackpad() const override; + gfx::PointF GetPositionInTrackpad() const override; + base::TimeTicks GetLastOrientationTimestamp() const override; + base::TimeTicks GetLastTouchTimestamp() const override; + base::TimeTicks GetLastButtonTimestamp() const override; + ControllerModel::Handedness GetHandedness() const override; + bool GetRecentered() const override; + int GetBatteryLevel() const override; + + private: + ControllerModel* prev_model_; + ControllerModel* cur_model_; + DISALLOW_COPY_AND_ASSIGN(PlatformControllerForTesting); +}; + +} // namespace vr + +#endif // CHROME_BROWSER_VR_PLATFORM_CONTROLLER_FOR_TESTING_H_
diff --git a/chrome/browser/vr/ui_test_input.h b/chrome/browser/vr/ui_test_input.h index cd0c03c..74bab8c 100644 --- a/chrome/browser/vr/ui_test_input.h +++ b/chrome/browser/vr/ui_test_input.h
@@ -14,7 +14,9 @@ // element names for interaction during testing. // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.vr enum class UserFriendlyElementName : int { - kUrl = 0, // URL bar + kNone = 0, // A special "element" that causes the controller to point + // straight forward. + kUrl, // URL bar kBackButton, // Back button on the URL bar kForwardButton, // Forward button in the overflow menu kReloadButton, // Reload button in the overflow menu @@ -68,13 +70,14 @@ // element using simulated controller input during testing. // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.vr enum class VrControllerTestAction : int { - kClick, kHover, kEnableMockedInput, kRevertToRealInput, kClickDown, kClickUp, kMove, + kAppDown, + kAppUp, }; // These are used to specify what type of keyboard input should be performed
diff --git a/chrome/browser/webauthn/authenticator_request_dialog_model.cc b/chrome/browser/webauthn/authenticator_request_dialog_model.cc index 30b65e3..0c782a1 100644 --- a/chrome/browser/webauthn/authenticator_request_dialog_model.cc +++ b/chrome/browser/webauthn/authenticator_request_dialog_model.cc
@@ -88,6 +88,7 @@ TransportAvailabilityInfo transport_availability, base::Optional<device::FidoTransportProtocol> last_used_transport) { DCHECK_EQ(current_step(), Step::kNotStarted); + DCHECK(!transport_availability.disable_embedder_ui); transport_availability_ = std::move(transport_availability); last_used_transport_ = last_used_transport;
diff --git a/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc b/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc index a2ec68b..bd66107 100644 --- a/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc +++ b/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc
@@ -62,10 +62,6 @@ #endif } -bool IsWebAuthnUiEnabled() { - return base::FeatureList::IsEnabled(features::kWebAuthenticationUI); -} - } // namespace #if defined(OS_MACOSX) @@ -267,6 +263,11 @@ void ChromeAuthenticatorRequestDelegate::OnTransportAvailabilityEnumerated( device::FidoRequestHandlerBase::TransportAvailabilityInfo data) { #if !defined(OS_ANDROID) + if (data.disable_embedder_ui) { + disable_ui_ = true; + return; + } + if (!IsWebAuthnUiEnabled()) return; @@ -282,11 +283,14 @@ bool ChromeAuthenticatorRequestDelegate::EmbedderControlsAuthenticatorDispatch( const device::FidoAuthenticator& authenticator) { - // TODO(hongjunchoi): Change this so that requests for BLE authenticators are - // not dispatched immediately if WebAuthN UI is enabled. + // TODO(hongjunchoi): Change this so that requests for BLE authenticators + // are not dispatched immediately if WebAuthN UI is enabled. if (!IsWebAuthnUiEnabled()) return false; + // On macOS, a native dialog is shown for the Touch ID authenticator + // immediately after dispatch to that authenticator. This dialog must not + // be triggered before Chrome's WebAuthn UI has advanced accordingly. return authenticator.AuthenticatorTransport() && *authenticator.AuthenticatorTransport() == device::FidoTransportProtocol::kInternal; @@ -384,3 +388,10 @@ Profile::FromBrowserContext(browser_context())->GetPrefs(); return prefs->GetList(kWebAuthnBlePairedMacAddressesPrefName); } + +bool ChromeAuthenticatorRequestDelegate::IsWebAuthnUiEnabled() const { + // UI can be disabled via flag or by the request handler for certain + // requests (e.g. on Windows, where the native API renders its own UI). + return base::FeatureList::IsEnabled(features::kWebAuthenticationUI) && + !disable_ui_; +}
diff --git a/chrome/browser/webauthn/chrome_authenticator_request_delegate.h b/chrome/browser/webauthn/chrome_authenticator_request_delegate.h index 6fd5c9d..680c8be 100644 --- a/chrome/browser/webauthn/chrome_authenticator_request_delegate.h +++ b/chrome/browser/webauthn/chrome_authenticator_request_delegate.h
@@ -106,6 +106,7 @@ void AddFidoBleDeviceToPairedList(std::string device_address); base::Optional<device::FidoTransportProtocol> GetLastTransportUsed() const; const base::ListValue* GetPreviouslyPairedFidoBleDeviceAddresses() const; + bool IsWebAuthnUiEnabled() const; content::RenderFrameHost* const render_frame_host_; AuthenticatorRequestDialogModel* weak_dialog_model_ = nullptr; @@ -119,6 +120,11 @@ base::OnceClosure cancel_callback_; device::FidoRequestHandlerBase::RequestCallback request_callback_; + // If in the TransportAvailabilityInfo reported by the request handler, + // disable_embedder_ui is set, this will be set to true. No UI must be + // rendered and all request handler callbacks will be ignored. + bool disable_ui_ = false; + base::WeakPtrFactory<ChromeAuthenticatorRequestDelegate> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(ChromeAuthenticatorRequestDelegate);
diff --git a/chrome/chrome_cleaner/BUILD.gn b/chrome/chrome_cleaner/BUILD.gn index 389300fb9..cffb815 100644 --- a/chrome/chrome_cleaner/BUILD.gn +++ b/chrome/chrome_cleaner/BUILD.gn
@@ -37,9 +37,9 @@ "//chrome/chrome_cleaner/http:unittest_sources", "//chrome/chrome_cleaner/interfaces/typemaps:unittest_sources", "//chrome/chrome_cleaner/ipc:unittest_sources", - "//chrome/chrome_cleaner/json_parser:unittest_sources", "//chrome/chrome_cleaner/logging:unittest_sources", "//chrome/chrome_cleaner/os:unittest_sources", + "//chrome/chrome_cleaner/parsers/json_parser:unittest_sources", "//chrome/chrome_cleaner/pup_data:unittest_sources", "//chrome/chrome_cleaner/scanner:unittest_sources", "//chrome/chrome_cleaner/settings:unittest_sources",
diff --git a/chrome/chrome_cleaner/DEPS b/chrome/chrome_cleaner/DEPS index 8f02ad1f..f7285e7 100644 --- a/chrome/chrome_cleaner/DEPS +++ b/chrome/chrome_cleaner/DEPS
@@ -1,6 +1,5 @@ include_rules = [ - "+sandbox/win/src", - "+testing/gtest", "+components/chrome_cleaner", + "+sandbox/win/src", "+third_party/protobuf/src/google/protobuf", ]
diff --git a/chrome/chrome_cleaner/chrome_utils/BUILD.gn b/chrome/chrome_cleaner/chrome_utils/BUILD.gn index d63af1a..d9fc74c 100644 --- a/chrome/chrome_cleaner/chrome_utils/BUILD.gn +++ b/chrome/chrome_cleaner/chrome_utils/BUILD.gn
@@ -24,8 +24,8 @@ deps = [ ":chrome_util_lib", "//base:base", - "//chrome/chrome_cleaner/json_parser", "//chrome/chrome_cleaner/os:common_os", + "//chrome/chrome_cleaner/parsers/json_parser", ] } @@ -40,7 +40,7 @@ ":extensions_util_lib", "//base:base", "//base/test:test_support", - "//chrome/chrome_cleaner/json_parser", + "//chrome/chrome_cleaner/parsers/json_parser", "//chrome/chrome_cleaner/test:test_util", "//testing/gtest", ]
diff --git a/chrome/chrome_cleaner/chrome_utils/extensions_util.h b/chrome/chrome_cleaner/chrome_utils/extensions_util.h index 1564fe7..37a3efc 100644 --- a/chrome/chrome_cleaner/chrome_utils/extensions_util.h +++ b/chrome/chrome_cleaner/chrome_utils/extensions_util.h
@@ -11,8 +11,8 @@ #include "base/macros.h" #include "base/strings/string16.h" #include "base/synchronization/waitable_event.h" -#include "chrome/chrome_cleaner/json_parser/json_parser_api.h" #include "chrome/chrome_cleaner/os/registry_util.h" +#include "chrome/chrome_cleaner/parsers/json_parser/json_parser_api.h" namespace chrome_cleaner {
diff --git a/chrome/chrome_cleaner/chrome_utils/extensions_util_unittest.cc b/chrome/chrome_cleaner/chrome_utils/extensions_util_unittest.cc index 8d275e7..1160219 100644 --- a/chrome/chrome_cleaner/chrome_utils/extensions_util_unittest.cc +++ b/chrome/chrome_cleaner/chrome_utils/extensions_util_unittest.cc
@@ -17,7 +17,7 @@ #include "base/test/test_reg_util_win.h" #include "base/test/test_timeouts.h" #include "base/win/registry.h" -#include "chrome/chrome_cleaner/json_parser/test_json_parser.h" +#include "chrome/chrome_cleaner/parsers/json_parser/test_json_parser.h" #include "chrome/chrome_cleaner/test/test_file_util.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/chrome_cleaner/components/BUILD.gn b/chrome/chrome_cleaner/components/BUILD.gn index 1b81bd1..422e53f9 100644 --- a/chrome/chrome_cleaner/components/BUILD.gn +++ b/chrome/chrome_cleaner/components/BUILD.gn
@@ -25,12 +25,12 @@ "//chrome/chrome_cleaner/constants:uws_id", "//chrome/chrome_cleaner/http:http", "//chrome/chrome_cleaner/http:http_status_codes", - "//chrome/chrome_cleaner/json_parser", "//chrome/chrome_cleaner/logging:common", "//chrome/chrome_cleaner/logging:scoped_timed_task_logger", "//chrome/chrome_cleaner/logging/proto:shared_data_proto", "//chrome/chrome_cleaner/os:cleaner_os", "//chrome/chrome_cleaner/os:common_os", + "//chrome/chrome_cleaner/parsers/json_parser", "//chrome/chrome_cleaner/pup_data:pup_data_base", "//components/chrome_cleaner/public/constants:constants", "//components/crx_file", @@ -58,11 +58,11 @@ "//chrome/chrome_cleaner/constants:common_strings", "//chrome/chrome_cleaner/constants:uws_id", "//chrome/chrome_cleaner/http:mock_http_agent_factory", - "//chrome/chrome_cleaner/json_parser", "//chrome/chrome_cleaner/logging:cleaner_logging", "//chrome/chrome_cleaner/logging/proto:chrome_cleaner_report_proto", "//chrome/chrome_cleaner/os:cleaner_os", "//chrome/chrome_cleaner/os:common_os", + "//chrome/chrome_cleaner/parsers/json_parser", "//chrome/chrome_cleaner/test:test_branding_header", "//chrome/chrome_cleaner/test:test_component", "//chrome/chrome_cleaner/test:test_pup_data",
diff --git a/chrome/chrome_cleaner/components/system_report_component.cc b/chrome/chrome_cleaner/components/system_report_component.cc index fb4245d..b1220c0 100644 --- a/chrome/chrome_cleaner/components/system_report_component.cc +++ b/chrome/chrome_cleaner/components/system_report_component.cc
@@ -43,7 +43,6 @@ #include "chrome/chrome_cleaner/chrome_utils/extensions_util.h" #include "chrome/chrome_cleaner/constants/chrome_cleaner_switches.h" #include "chrome/chrome_cleaner/constants/common_registry_names.h" -#include "chrome/chrome_cleaner/json_parser/json_parser_api.h" #include "chrome/chrome_cleaner/logging/logging_service_api.h" #include "chrome/chrome_cleaner/logging/proto/shared_data.pb.h" #include "chrome/chrome_cleaner/logging/scoped_timed_task_logger.h" @@ -59,6 +58,7 @@ #include "chrome/chrome_cleaner/os/system_util.h" #include "chrome/chrome_cleaner/os/system_util_cleaner.h" #include "chrome/chrome_cleaner/os/task_scheduler.h" +#include "chrome/chrome_cleaner/parsers/json_parser/json_parser_api.h" #include "components/chrome_cleaner/public/constants/constants.h" using base::WaitableEvent;
diff --git a/chrome/chrome_cleaner/components/system_report_component.h b/chrome/chrome_cleaner/components/system_report_component.h index 4ec3665..e9d8366 100644 --- a/chrome/chrome_cleaner/components/system_report_component.h +++ b/chrome/chrome_cleaner/components/system_report_component.h
@@ -8,7 +8,7 @@ #include <vector> #include "chrome/chrome_cleaner/components/component_api.h" -#include "chrome/chrome_cleaner/json_parser/json_parser_api.h" +#include "chrome/chrome_cleaner/parsers/json_parser/json_parser_api.h" namespace chrome_cleaner {
diff --git a/chrome/chrome_cleaner/components/system_report_component_unittest.cc b/chrome/chrome_cleaner/components/system_report_component_unittest.cc index e324477..927c1607 100644 --- a/chrome/chrome_cleaner/components/system_report_component_unittest.cc +++ b/chrome/chrome_cleaner/components/system_report_component_unittest.cc
@@ -22,7 +22,6 @@ #include "base/win/registry.h" #include "chrome/chrome_cleaner/constants/chrome_cleaner_switches.h" #include "chrome/chrome_cleaner/constants/uws_id.h" -#include "chrome/chrome_cleaner/json_parser/test_json_parser.h" #include "chrome/chrome_cleaner/logging/cleaner_logging_service.h" #include "chrome/chrome_cleaner/logging/logging_service_api.h" #include "chrome/chrome_cleaner/logging/proto/chrome_cleaner_report.pb.h" @@ -30,6 +29,7 @@ #include "chrome/chrome_cleaner/os/file_path_sanitization.h" #include "chrome/chrome_cleaner/os/pre_fetched_paths.h" #include "chrome/chrome_cleaner/os/registry_util.h" +#include "chrome/chrome_cleaner/parsers/json_parser/test_json_parser.h" #include "chrome/chrome_cleaner/test/test_file_util.h" #include "chrome/chrome_cleaner/test/test_pup_data.h" #include "chrome/chrome_cleaner/test/test_util.h"
diff --git a/chrome/chrome_cleaner/crash/crashpad_crash_client.cc b/chrome/chrome_cleaner/crash/crashpad_crash_client.cc index 189df2b..2058374 100644 --- a/chrome/chrome_cleaner/crash/crashpad_crash_client.cc +++ b/chrome/chrome_cleaner/crash/crashpad_crash_client.cc
@@ -196,8 +196,8 @@ case SandboxType::kEset: SetCrashKey(kProcessType, "eset"); break; - case SandboxType::kJsonParser: - SetCrashKey(kProcessType, "json_parser"); + case SandboxType::kParser: + SetCrashKey(kProcessType, "parser"); break; case SandboxType::kZipArchiver: SetCrashKey(kProcessType, "zip_archiver");
diff --git a/chrome/chrome_cleaner/interfaces/BUILD.gn b/chrome/chrome_cleaner/interfaces/BUILD.gn index be473325..3bf2b1f 100644 --- a/chrome/chrome_cleaner/interfaces/BUILD.gn +++ b/chrome/chrome_cleaner/interfaces/BUILD.gn
@@ -31,9 +31,9 @@ ] } -chrome_cleaner_mojom("json_parser_interface") { +chrome_cleaner_mojom("parser_interface") { sources = [ - "json_parser.mojom", + "parser_interface.mojom", ] deps = [ "//mojo/public/mojom/base",
diff --git a/chrome/chrome_cleaner/interfaces/json_parser.mojom b/chrome/chrome_cleaner/interfaces/json_parser.mojom deleted file mode 100644 index c588cc15..0000000 --- a/chrome/chrome_cleaner/interfaces/json_parser.mojom +++ /dev/null
@@ -1,20 +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. - -module chrome_cleaner.mojom; - -import "mojo/public/mojom/base/values.mojom"; - -// Interface copied from services/data_decoder/public/mojom/json_parser.mojom, -// which can't be used directly because it's closely tied to the service -// manager which chrome_cleaner does not support. -// -// Sends a JSON string to parse from the high-privilege sandbox broker process -// to a locked down sandbox target process where the parsing takes place. -interface JsonParser { - // Parses |json| into a structured Value object. Returns the value in - // |result| if the parse was successful, or an error message in |error| if - // not. - Parse(string json) => (mojo_base.mojom.Value? result, string? error); -};
diff --git a/chrome/chrome_cleaner/interfaces/parser_interface.mojom b/chrome/chrome_cleaner/interfaces/parser_interface.mojom new file mode 100644 index 0000000..b5a9996 --- /dev/null +++ b/chrome/chrome_cleaner/interfaces/parser_interface.mojom
@@ -0,0 +1,19 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module chrome_cleaner.mojom; + +import "mojo/public/mojom/base/values.mojom"; + +// Common interface for the parsers used on the Chrome Cleanup Tool. +interface Parser { + // JSON parser: + // Interface copied from services/data_decoder/public/mojom/json_parser.mojom, + // which can't be used directly because it's closely tied to the service + // manager which chrome_cleaner does not support. + // + // Sends a JSON string to parse from the high-privilege sandbox broker process + // to a locked down sandbox target process where the parsing takes place. + ParseJson(string json) => (mojo_base.mojom.Value? result, string? error); +};
diff --git a/chrome/chrome_cleaner/ipc/sandbox.cc b/chrome/chrome_cleaner/ipc/sandbox.cc index d3c4fa0..96da7fa 100644 --- a/chrome/chrome_cleaner/ipc/sandbox.cc +++ b/chrome/chrome_cleaner/ipc/sandbox.cc
@@ -407,7 +407,9 @@ case SandboxType::kEset: result_code = RESULT_CODE_ESET_SANDBOX_DISCONNECTED_TOO_SOON; break; - case SandboxType::kJsonParser: + case SandboxType::kParser: + // TODO(joenotcharles): This needs to be renamed to + // RESULT_CODE_PARSER_SANDBOX_DISCONNECTED_TOO_SOON. result_code = RESULT_CODE_JSON_PARSER_SANDBOX_DISCONNECTED_TOO_SOON; break; case SandboxType::kZipArchiver:
diff --git a/chrome/chrome_cleaner/json_parser/DEPS b/chrome/chrome_cleaner/json_parser/DEPS deleted file mode 100644 index ef8ad28..0000000 --- a/chrome/chrome_cleaner/json_parser/DEPS +++ /dev/null
@@ -1,3 +0,0 @@ -include_rules = [ - "+mojo/public", -]
diff --git a/chrome/chrome_cleaner/json_parser/json_parser_impl.h b/chrome/chrome_cleaner/json_parser/json_parser_impl.h deleted file mode 100644 index bead474..0000000 --- a/chrome/chrome_cleaner/json_parser/json_parser_impl.h +++ /dev/null
@@ -1,28 +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 CHROME_CHROME_CLEANER_JSON_PARSER_JSON_PARSER_IMPL_H_ -#define CHROME_CHROME_CLEANER_JSON_PARSER_JSON_PARSER_IMPL_H_ - -#include "chrome/chrome_cleaner/interfaces/json_parser.mojom.h" -#include "mojo/public/cpp/bindings/binding.h" - -namespace chrome_cleaner { - -class JsonParserImpl : public mojom::JsonParser { - public: - explicit JsonParserImpl(mojom::JsonParserRequest request, - base::OnceClosure connection_error_handler); - ~JsonParserImpl() override; - - // mojom::JsonParser - void Parse(const std::string& json, ParseCallback callback) override; - - private: - mojo::Binding<mojom::JsonParser> binding_; -}; - -} // namespace chrome_cleaner - -#endif // CHROME_CHROME_CLEANER_JSON_PARSER_JSON_PARSER_IMPL_H_
diff --git a/chrome/chrome_cleaner/json_parser/json_splicer.h b/chrome/chrome_cleaner/json_parser/json_splicer.h deleted file mode 100644 index b5df59d..0000000 --- a/chrome/chrome_cleaner/json_parser/json_splicer.h +++ /dev/null
@@ -1,29 +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 CHROME_CHROME_CLEANER_JSON_PARSER_JSON_SPLICER_H_ -#define CHROME_CHROME_CLEANER_JSON_PARSER_JSON_SPLICER_H_ - -#include "base/values.h" - -namespace chrome_cleaner { - -class JsonSplicer { - public: - ~JsonSplicer(); - - // Deletes the |key| entry from the |dictionary|. - // - // Returns true on success. - bool RemoveKeyFromDictionary(base::Value* dictionary, const std::string& key); - - // Deletes the entry from the |list| with |key|. - // - // Returns true on success. - bool RemoveValueFromList(base::Value* list, const std::string& key); -}; - -} // namespace chrome_cleaner - -#endif // CHROME_CHROME_CLEANER_JSON_PARSER_JSON_SPLICER_H_
diff --git a/chrome/chrome_cleaner/json_parser/sandbox_setup_hooks.cc b/chrome/chrome_cleaner/json_parser/sandbox_setup_hooks.cc deleted file mode 100644 index 45e3098..0000000 --- a/chrome/chrome_cleaner/json_parser/sandbox_setup_hooks.cc +++ /dev/null
@@ -1,65 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/chrome_cleaner/json_parser/sandbox_setup_hooks.h" - -#include <utility> - -#include "chrome/chrome_cleaner/constants/chrome_cleaner_switches.h" -#include "chrome/chrome_cleaner/settings/settings_types.h" - -namespace chrome_cleaner { - -JsonParserSandboxSetupHooks::JsonParserSandboxSetupHooks( - scoped_refptr<MojoTaskRunner> mojo_task_runner, - base::OnceClosure connection_error_handler) - : mojo_task_runner_(mojo_task_runner), - connection_error_handler_(std::move(connection_error_handler)), - json_parser_ptr_(new mojom::JsonParserPtr(), - base::OnTaskRunnerDeleter(mojo_task_runner_)) {} - -JsonParserSandboxSetupHooks::~JsonParserSandboxSetupHooks() = default; - -ResultCode JsonParserSandboxSetupHooks::UpdateSandboxPolicy( - sandbox::TargetPolicy* policy, - base::CommandLine* command_line) { - // Unretained reference is safe because the json_parser_ptr is taken by the - // caller and is expected to retain it for the life of the sandboxed process. - mojo_task_runner_->PostTask( - FROM_HERE, base::BindOnce(&JsonParserSandboxSetupHooks::BindJsonParserPtr, - base::Unretained(this), - SetupSandboxMessagePipe(policy, command_line), - base::Unretained(json_parser_ptr_.get()))); - - return RESULT_CODE_SUCCESS; -} - -void JsonParserSandboxSetupHooks::BindJsonParserPtr( - mojo::ScopedMessagePipeHandle pipe_handle, - mojom::JsonParserPtr* json_parser_ptr) { - json_parser_ptr->Bind(mojom::JsonParserPtrInfo(std::move(pipe_handle), 0)); - json_parser_ptr->set_connection_error_handler( - std::move(connection_error_handler_)); -} - -UniqueJsonParserPtr JsonParserSandboxSetupHooks::TakeJsonParserPtr() { - return std::move(json_parser_ptr_); -} - -ResultCode SpawnJsonParserSandbox( - scoped_refptr<MojoTaskRunner> mojo_task_runner, - const SandboxConnectionErrorCallback& connection_error_callback, - UniqueJsonParserPtr* json_parser_ptr) { - // Call |connection_error_callback| with json parser sandbox type. - auto error_handler = - base::BindOnce(connection_error_callback, SandboxType::kJsonParser); - JsonParserSandboxSetupHooks setup_hooks(mojo_task_runner, - std::move(error_handler)); - ResultCode result_code = SpawnSandbox(&setup_hooks, SandboxType::kJsonParser); - *json_parser_ptr = setup_hooks.TakeJsonParserPtr(); - - return result_code; -} - -} // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/json_parser/sandbox_setup_hooks.h b/chrome/chrome_cleaner/json_parser/sandbox_setup_hooks.h deleted file mode 100644 index 66e99442..0000000 --- a/chrome/chrome_cleaner/json_parser/sandbox_setup_hooks.h +++ /dev/null
@@ -1,59 +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 CHROME_CHROME_CLEANER_JSON_PARSER_SANDBOX_SETUP_HOOKS_H_ -#define CHROME_CHROME_CLEANER_JSON_PARSER_SANDBOX_SETUP_HOOKS_H_ - -#include <memory> - -#include "base/command_line.h" -#include "chrome/chrome_cleaner/interfaces/json_parser.mojom.h" -#include "chrome/chrome_cleaner/ipc/mojo_sandbox_hooks.h" -#include "chrome/chrome_cleaner/ipc/mojo_task_runner.h" -#include "chrome/chrome_cleaner/ipc/sandbox.h" -#include "components/chrome_cleaner/public/constants/result_codes.h" -#include "mojo/public/cpp/system/message_pipe.h" - -namespace chrome_cleaner { - -using UniqueJsonParserPtr = - std::unique_ptr<mojom::JsonParserPtr, base::OnTaskRunnerDeleter>; - -// Hooks to spawn a new sandboxed JSON parser process and bind a Mojo interface -// pointer to the sandboxed implementation. -class JsonParserSandboxSetupHooks : public MojoSandboxSetupHooks { - public: - JsonParserSandboxSetupHooks(scoped_refptr<MojoTaskRunner> mojo_task_runner, - base::OnceClosure connection_error_handler); - ~JsonParserSandboxSetupHooks() override; - - // Transfers ownership of |json_parser_ptr_| to the caller. - UniqueJsonParserPtr TakeJsonParserPtr(); - - // SandboxSetupHooks - ResultCode UpdateSandboxPolicy(sandbox::TargetPolicy* policy, - base::CommandLine* command_line) override; - - private: - void BindJsonParserPtr(mojo::ScopedMessagePipeHandle pipe_handle, - mojom::JsonParserPtr* json_parser_ptr); - - scoped_refptr<MojoTaskRunner> mojo_task_runner_; - base::OnceClosure connection_error_handler_; - - UniqueJsonParserPtr json_parser_ptr_; - - DISALLOW_COPY_AND_ASSIGN(JsonParserSandboxSetupHooks); -}; - -// Spawn a sandboxed process with type kJsonParser, and return the bound -// |json_parser_ptr|. -ResultCode SpawnJsonParserSandbox( - scoped_refptr<MojoTaskRunner> mojo_task_runner, - const SandboxConnectionErrorCallback& connection_error_callback, - UniqueJsonParserPtr* json_parser_ptr); - -} // namespace chrome_cleaner - -#endif // CHROME_CHROME_CLEANER_JSON_PARSER_SANDBOX_SETUP_HOOKS_H_
diff --git a/chrome/chrome_cleaner/json_parser/sandbox_target_hooks.cc b/chrome/chrome_cleaner/json_parser/sandbox_target_hooks.cc deleted file mode 100644 index 531265e..0000000 --- a/chrome/chrome_cleaner/json_parser/sandbox_target_hooks.cc +++ /dev/null
@@ -1,58 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/chrome_cleaner/json_parser/sandbox_target_hooks.h" - -#include <utility> - -#include "chrome/chrome_cleaner/constants/chrome_cleaner_switches.h" -#include "chrome/chrome_cleaner/os/early_exit.h" - -namespace chrome_cleaner { - -JsonParserSandboxTargetHooks::JsonParserSandboxTargetHooks( - MojoTaskRunner* mojo_task_runner) - : mojo_task_runner_(mojo_task_runner) {} - -JsonParserSandboxTargetHooks::~JsonParserSandboxTargetHooks() { - // Ensure Mojo objects are deleted on the IPC thread. - mojo_task_runner_->PostTask( - FROM_HERE, base::BindOnce( - [](std::unique_ptr<JsonParserImpl> json_parser_impl) { - json_parser_impl.reset(); - }, - base::Passed(&json_parser_impl_))); -} - -ResultCode JsonParserSandboxTargetHooks::TargetDroppedPrivileges( - const base::CommandLine& command_line) { - mojom::JsonParserRequest request(ExtractSandboxMessagePipe(command_line)); - - // This loop will run forever. Once the communication channel with the broker - // process is broken, mojo error handler will abort this process. - base::RunLoop run_loop; - mojo_task_runner_->PostTask( - FROM_HERE, - base::BindOnce(&JsonParserSandboxTargetHooks::CreateJsonParserImpl, - base::Unretained(this), base::Passed(&request))); - run_loop.Run(); - - return RESULT_CODE_SUCCESS; -} - -void JsonParserSandboxTargetHooks::CreateJsonParserImpl( - mojom::JsonParserRequest request) { - json_parser_impl_ = std::make_unique<JsonParserImpl>( - std::move(request), base::BindOnce(&EarlyExit, 1)); -} - -ResultCode RunJsonParserSandbox(const base::CommandLine& command_line, - sandbox::TargetServices* target_services) { - scoped_refptr<MojoTaskRunner> mojo_task_runner = MojoTaskRunner::Create(); - JsonParserSandboxTargetHooks target_hooks(mojo_task_runner.get()); - - return RunSandboxTarget(command_line, target_services, &target_hooks); -} - -} // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/json_parser/sandbox_target_hooks.h b/chrome/chrome_cleaner/json_parser/sandbox_target_hooks.h deleted file mode 100644 index cf97c94..0000000 --- a/chrome/chrome_cleaner/json_parser/sandbox_target_hooks.h +++ /dev/null
@@ -1,46 +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 CHROME_CHROME_CLEANER_JSON_PARSER_SANDBOX_TARGET_HOOKS_H_ -#define CHROME_CHROME_CLEANER_JSON_PARSER_SANDBOX_TARGET_HOOKS_H_ - -#include <memory> - -#include "base/command_line.h" -#include "chrome/chrome_cleaner/interfaces/json_parser.mojom.h" -#include "chrome/chrome_cleaner/ipc/mojo_sandbox_hooks.h" -#include "chrome/chrome_cleaner/ipc/mojo_task_runner.h" -#include "chrome/chrome_cleaner/json_parser/json_parser_impl.h" -#include "components/chrome_cleaner/public/constants/result_codes.h" - -namespace chrome_cleaner { - -// Hooks to initialize the sandboxed JSON parser process by creating a -// JsonParserImpl instance and binding it to the mojo pipe. -class JsonParserSandboxTargetHooks : public MojoSandboxTargetHooks { - public: - explicit JsonParserSandboxTargetHooks(MojoTaskRunner* mojo_task_runner); - ~JsonParserSandboxTargetHooks() override; - - // SandboxTargetHooks - ResultCode TargetDroppedPrivileges( - const base::CommandLine& command_line) override; - - private: - void CreateJsonParserImpl(mojom::JsonParserRequest request); - - MojoTaskRunner* mojo_task_runner_; - base::MessageLoop message_loop_; - std::unique_ptr<JsonParserImpl> json_parser_impl_; - - DISALLOW_COPY_AND_ASSIGN(JsonParserSandboxTargetHooks); -}; - -// Run the JSON parser, to be called in a newly spawned process. -ResultCode RunJsonParserSandbox(const base::CommandLine& command_line, - sandbox::TargetServices* target_services); - -} // namespace chrome_cleaner - -#endif // CHROME_CHROME_CLEANER_JSON_PARSER_SANDBOX_TARGET_HOOKS_H_
diff --git a/chrome/chrome_cleaner/json_parser/sandboxed_json_parser.cc b/chrome/chrome_cleaner/json_parser/sandboxed_json_parser.cc deleted file mode 100644 index a741bd51c..0000000 --- a/chrome/chrome_cleaner/json_parser/sandboxed_json_parser.cc +++ /dev/null
@@ -1,24 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/chrome_cleaner/json_parser/sandboxed_json_parser.h" - -namespace chrome_cleaner { - -SandboxedJsonParser::SandboxedJsonParser(MojoTaskRunner* mojo_task_runner, - mojom::JsonParserPtr* json_parser_ptr) - : mojo_task_runner_(mojo_task_runner), json_parser_ptr_(json_parser_ptr) {} - -void SandboxedJsonParser::Parse(const std::string& json, - ParseDoneCallback callback) { - mojo_task_runner_->PostTask( - FROM_HERE, base::BindOnce( - [](mojom::JsonParserPtr* json_parser_ptr, - const std::string& json, ParseDoneCallback callback) { - (*json_parser_ptr)->Parse(json, std::move(callback)); - }, - json_parser_ptr_, json, std::move(callback))); -} - -} // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/json_parser/sandboxed_json_parser.h b/chrome/chrome_cleaner/json_parser/sandboxed_json_parser.h deleted file mode 100644 index 0ddcae4..0000000 --- a/chrome/chrome_cleaner/json_parser/sandboxed_json_parser.h +++ /dev/null
@@ -1,29 +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 CHROME_CHROME_CLEANER_JSON_PARSER_SANDBOXED_JSON_PARSER_H_ -#define CHROME_CHROME_CLEANER_JSON_PARSER_SANDBOXED_JSON_PARSER_H_ - -#include "chrome/chrome_cleaner/interfaces/json_parser.mojom.h" -#include "chrome/chrome_cleaner/ipc/mojo_task_runner.h" -#include "chrome/chrome_cleaner/json_parser/json_parser_api.h" - -namespace chrome_cleaner { - -// An implementation of JsonParserAPI to wrap a MojoTaskRunner and -// JsonParserPtr. Parses via |json_parser_ptr_| on the |mojo_task_runner_|. -class SandboxedJsonParser : public JsonParserAPI { - public: - SandboxedJsonParser(MojoTaskRunner* mojo_task_runner, - mojom::JsonParserPtr* json_parser_ptr); - void Parse(const std::string& json, ParseDoneCallback callback) override; - - private: - MojoTaskRunner* mojo_task_runner_; - mojom::JsonParserPtr* json_parser_ptr_; -}; - -} // namespace chrome_cleaner - -#endif // CHROME_CHROME_CLEANER_JSON_PARSER_SANDBOXED_JSON_PARSER_H_
diff --git a/chrome/chrome_cleaner/logging/proto/shared_data.proto b/chrome/chrome_cleaner/logging/proto/shared_data.proto index ae14684..3a15198a 100644 --- a/chrome/chrome_cleaner/logging/proto/shared_data.proto +++ b/chrome/chrome_cleaner/logging/proto/shared_data.proto
@@ -266,7 +266,7 @@ MAIN = 1; DEPRECATED_SIGNATURE_MATCHER_SANDBOX = 2; ESET_SANDBOX = 3; - JSON_PARSER_SANDBOX = 4; + PARSER_SANDBOX = 4; ZIP_ARCHIVER_SANDBOX = 5; } optional Process process = 1;
diff --git a/chrome/chrome_cleaner/logging/utils.cc b/chrome/chrome_cleaner/logging/utils.cc index 032125d..d96439c 100644 --- a/chrome/chrome_cleaner/logging/utils.cc +++ b/chrome/chrome_cleaner/logging/utils.cc
@@ -252,8 +252,8 @@ case SandboxType::kEset: process_info.set_process(ProcessInformation::ESET_SANDBOX); break; - case SandboxType::kJsonParser: - process_info.set_process(ProcessInformation::JSON_PARSER_SANDBOX); + case SandboxType::kParser: + process_info.set_process(ProcessInformation::PARSER_SANDBOX); break; case SandboxType::kZipArchiver: process_info.set_process(ProcessInformation::ZIP_ARCHIVER_SANDBOX);
diff --git a/chrome/chrome_cleaner/parsers/DEPS b/chrome/chrome_cleaner/parsers/DEPS new file mode 100644 index 0000000..093b1d9 --- /dev/null +++ b/chrome/chrome_cleaner/parsers/DEPS
@@ -0,0 +1,3 @@ +include_rules = [ + "+mojo/public/cpp", +]
diff --git a/chrome/chrome_cleaner/parsers/broker/BUILD.gn b/chrome/chrome_cleaner/parsers/broker/BUILD.gn new file mode 100644 index 0000000..a79e3432 --- /dev/null +++ b/chrome/chrome_cleaner/parsers/broker/BUILD.gn
@@ -0,0 +1,43 @@ +# 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. + +static_library("parser_sandbox_broker") { + sources = [ + "sandbox_setup_hooks.cc", + "sandbox_setup_hooks.h", + ] + + deps = [ + "//base:base", + "//chrome/chrome_cleaner/constants:common_strings", + "//chrome/chrome_cleaner/interfaces:parser_interface", + "//chrome/chrome_cleaner/ipc:mojo_task_runner", + "//chrome/chrome_cleaner/ipc:sandbox", + "//chrome/chrome_cleaner/settings:settings_types", + "//components/chrome_cleaner/public/constants:constants", + "//mojo/public/cpp/bindings", + ] +} + +source_set("unittest_sources") { + testonly = true + + sources = [ + "json_parser_sandbox_setup_unittest.cc", + ] + deps = [ + ":parser_sandbox_broker", + "//base:base", + "//base/test:test_support", + "//chrome/chrome_cleaner/interfaces:parser_interface", + "//chrome/chrome_cleaner/ipc:mojo_task_runner", + "//chrome/chrome_cleaner/os:common_os", + "//chrome/chrome_cleaner/parsers/json_parser:json_parser", + "//chrome/chrome_cleaner/parsers/json_parser:json_splicer", + "//chrome/chrome_cleaner/parsers/target:parser_sandbox_target", + "//mojo/public/cpp/bindings:bindings", + "//sandbox/win:sandbox", + "//testing/gtest", + ] +}
diff --git a/chrome/chrome_cleaner/json_parser/sandbox_setup_unittest.cc b/chrome/chrome_cleaner/parsers/broker/json_parser_sandbox_setup_unittest.cc similarity index 62% rename from chrome/chrome_cleaner/json_parser/sandbox_setup_unittest.cc rename to chrome/chrome_cleaner/parsers/broker/json_parser_sandbox_setup_unittest.cc index 88a634c..599b574 100644 --- a/chrome/chrome_cleaner/json_parser/sandbox_setup_unittest.cc +++ b/chrome/chrome_cleaner/parsers/broker/json_parser_sandbox_setup_unittest.cc
@@ -2,15 +2,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/memory/scoped_refptr.h" #include "base/synchronization/waitable_event.h" #include "base/test/multiprocess_test.h" #include "base/test/test_timeouts.h" #include "base/time/time.h" -#include "chrome/chrome_cleaner/interfaces/json_parser.mojom.h" +#include "chrome/chrome_cleaner/interfaces/parser_interface.mojom.h" #include "chrome/chrome_cleaner/ipc/mojo_task_runner.h" -#include "chrome/chrome_cleaner/json_parser/sandbox_setup_hooks.h" -#include "chrome/chrome_cleaner/json_parser/sandbox_target_hooks.h" +#include "chrome/chrome_cleaner/parsers/broker/sandbox_setup_hooks.h" +#include "chrome/chrome_cleaner/parsers/target/sandbox_setup.h" +#include "mojo/public/cpp/bindings/interface_request.h" #include "sandbox/win/src/sandbox_factory.h" +#include "testing/gtest/include/gtest/gtest.h" #include "testing/multiprocess_func_list.h" using base::WaitableEvent; @@ -19,31 +22,30 @@ namespace { -const char kTestJsonKey[] = "name"; -const char kTestJsonValue[] = "Jason"; -const char kTestJsonText[] = "{ \"name\": \"Jason\" }"; -const char kInvalidJsonText[] = "{ name: jason }"; +const char kTestKey[] = "name"; +const char kTestValue[] = "Jason"; +const char kTestText[] = "{ \"name\": \"Jason\" }"; +const char kInvalidText[] = "{ name: jason }"; class JsonParserSandboxSetupTest : public base::MultiProcessTest { public: JsonParserSandboxSetupTest() - : json_parser_ptr_(nullptr, base::OnTaskRunnerDeleter(nullptr)) {} + : parser_ptr_(nullptr, base::OnTaskRunnerDeleter(nullptr)) {} void SetUp() override { mojo_task_runner_ = MojoTaskRunner::Create(); - JsonParserSandboxSetupHooks setup_hooks( - mojo_task_runner_.get(), base::BindOnce([] { - FAIL() << "JsonParser sandbox connection error"; - })); + ParserSandboxSetupHooks setup_hooks( + mojo_task_runner_.get(), + base::BindOnce([] { FAIL() << "Parser sandbox connection error"; })); ASSERT_EQ(RESULT_CODE_SUCCESS, StartSandboxTarget(MakeCmdLine("JsonParserSandboxTargetMain"), &setup_hooks, SandboxType::kTest)); - json_parser_ptr_ = setup_hooks.TakeJsonParserPtr(); + parser_ptr_ = setup_hooks.TakeParserPtr(); } protected: scoped_refptr<MojoTaskRunner> mojo_task_runner_; - UniqueJsonParserPtr json_parser_ptr_; + UniqueParserPtr parser_ptr_; }; void ParseCallbackExpectedKeyValue(const std::string& expected_key, @@ -79,26 +81,26 @@ CHECK(sandbox_target_services); EXPECT_EQ(RESULT_CODE_SUCCESS, - RunJsonParserSandbox(*base::CommandLine::ForCurrentProcess(), - sandbox_target_services)); + RunParserSandboxTarget(*base::CommandLine::ForCurrentProcess(), + sandbox_target_services)); return ::testing::Test::HasNonfatalFailure(); } -TEST_F(JsonParserSandboxSetupTest, ParseJsonSandboxed) { +TEST_F(JsonParserSandboxSetupTest, ParseValidJsonSandboxed) { WaitableEvent done(WaitableEvent::ResetPolicy::MANUAL, WaitableEvent::InitialState::NOT_SIGNALED); mojo_task_runner_->PostTask( - FROM_HERE, - base::BindOnce( - [](mojom::JsonParserPtr* json_parser_ptr, WaitableEvent* done) { - (*json_parser_ptr) - ->Parse(kTestJsonText, - base::BindOnce(&ParseCallbackExpectedKeyValue, - kTestJsonKey, kTestJsonValue, done)); - }, - json_parser_ptr_.get(), &done)); + FROM_HERE, base::BindOnce( + [](mojom::ParserPtr* parser_ptr, WaitableEvent* done) { + (*parser_ptr) + ->ParseJson( + kTestText, + base::BindOnce(&ParseCallbackExpectedKeyValue, + kTestKey, kTestValue, done)); + }, + parser_ptr_.get(), &done)); EXPECT_TRUE(done.TimedWait(TestTimeouts::action_timeout())); } @@ -109,12 +111,12 @@ mojo_task_runner_->PostTask( FROM_HERE, base::BindOnce( - [](mojom::JsonParserPtr* json_parser_ptr, WaitableEvent* done) { - (*json_parser_ptr) - ->Parse(kInvalidJsonText, - base::BindOnce(&ParseCallbackExpectedError, done)); + [](mojom::ParserPtr* parser_ptr, WaitableEvent* done) { + (*parser_ptr) + ->ParseJson(kInvalidText, + base::BindOnce(&ParseCallbackExpectedError, done)); }, - json_parser_ptr_.get(), &done)); + parser_ptr_.get(), &done)); EXPECT_TRUE(done.TimedWait(TestTimeouts::action_timeout())); }
diff --git a/chrome/chrome_cleaner/parsers/broker/sandbox_setup_hooks.cc b/chrome/chrome_cleaner/parsers/broker/sandbox_setup_hooks.cc new file mode 100644 index 0000000..ef7e8b3b --- /dev/null +++ b/chrome/chrome_cleaner/parsers/broker/sandbox_setup_hooks.cc
@@ -0,0 +1,64 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/chrome_cleaner/parsers/broker/sandbox_setup_hooks.h" + +#include <utility> + +#include "chrome/chrome_cleaner/constants/chrome_cleaner_switches.h" +#include "chrome/chrome_cleaner/settings/settings_types.h" + +namespace chrome_cleaner { + +ParserSandboxSetupHooks::ParserSandboxSetupHooks( + scoped_refptr<MojoTaskRunner> mojo_task_runner, + base::OnceClosure connection_error_handler) + : mojo_task_runner_(mojo_task_runner), + connection_error_handler_(std::move(connection_error_handler)), + parser_ptr_(new mojom::ParserPtr(), + base::OnTaskRunnerDeleter(mojo_task_runner_)) {} + +ParserSandboxSetupHooks::~ParserSandboxSetupHooks() = default; + +ResultCode ParserSandboxSetupHooks::UpdateSandboxPolicy( + sandbox::TargetPolicy* policy, + base::CommandLine* command_line) { + // Unretained reference is safe because the parser_ptr is taken by the + // caller and is expected to retain it for the life of the sandboxed process. + mojo_task_runner_->PostTask( + FROM_HERE, base::BindOnce(&ParserSandboxSetupHooks::BindParserPtr, + base::Unretained(this), + SetupSandboxMessagePipe(policy, command_line), + base::Unretained(parser_ptr_.get()))); + + return RESULT_CODE_SUCCESS; +} + +void ParserSandboxSetupHooks::BindParserPtr( + mojo::ScopedMessagePipeHandle pipe_handle, + mojom::ParserPtr* parser_ptr) { + parser_ptr->Bind(mojom::ParserPtrInfo(std::move(pipe_handle), 0)); + parser_ptr->set_connection_error_handler( + std::move(connection_error_handler_)); +} + +UniqueParserPtr ParserSandboxSetupHooks::TakeParserPtr() { + return std::move(parser_ptr_); +} + +ResultCode SpawnParserSandbox( + scoped_refptr<MojoTaskRunner> mojo_task_runner, + const SandboxConnectionErrorCallback& connection_error_callback, + UniqueParserPtr* parser_ptr) { + auto error_handler = + base::BindOnce(connection_error_callback, SandboxType::kParser); + ParserSandboxSetupHooks setup_hooks(mojo_task_runner, + std::move(error_handler)); + ResultCode result_code = SpawnSandbox(&setup_hooks, SandboxType::kParser); + *parser_ptr = setup_hooks.TakeParserPtr(); + + return result_code; +} + +} // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/parsers/broker/sandbox_setup_hooks.h b/chrome/chrome_cleaner/parsers/broker/sandbox_setup_hooks.h new file mode 100644 index 0000000..e41da15 --- /dev/null +++ b/chrome/chrome_cleaner/parsers/broker/sandbox_setup_hooks.h
@@ -0,0 +1,59 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_CHROME_CLEANER_PARSERS_BROKER_SANDBOX_SETUP_HOOKS_H_ +#define CHROME_CHROME_CLEANER_PARSERS_BROKER_SANDBOX_SETUP_HOOKS_H_ + +#include <memory> + +#include "base/command_line.h" +#include "chrome/chrome_cleaner/interfaces/parser_interface.mojom.h" +#include "chrome/chrome_cleaner/ipc/mojo_sandbox_hooks.h" +#include "chrome/chrome_cleaner/ipc/mojo_task_runner.h" +#include "chrome/chrome_cleaner/ipc/sandbox.h" +#include "components/chrome_cleaner/public/constants/result_codes.h" +#include "mojo/public/cpp/system/message_pipe.h" + +namespace chrome_cleaner { + +using UniqueParserPtr = + std::unique_ptr<mojom::ParserPtr, base::OnTaskRunnerDeleter>; + +// Hooks to spawn a new sandboxed Parser process and bind a Mojo interface +// pointer to the sandboxed implementation. +class ParserSandboxSetupHooks : public MojoSandboxSetupHooks { + public: + ParserSandboxSetupHooks(scoped_refptr<MojoTaskRunner> mojo_task_runner, + base::OnceClosure connection_error_handler); + ~ParserSandboxSetupHooks() override; + + // Transfers ownership of |parser_ptr_| to the caller. + UniqueParserPtr TakeParserPtr(); + + // SandboxSetupHooks + ResultCode UpdateSandboxPolicy(sandbox::TargetPolicy* policy, + base::CommandLine* command_line) override; + + private: + void BindParserPtr(mojo::ScopedMessagePipeHandle pipe_handle, + mojom::ParserPtr* parser_ptr); + + scoped_refptr<MojoTaskRunner> mojo_task_runner_; + base::OnceClosure connection_error_handler_; + + UniqueParserPtr parser_ptr_; + + DISALLOW_COPY_AND_ASSIGN(ParserSandboxSetupHooks); +}; + +// Spawn a sandboxed process with type kParser, and return the bound +// |parser_ptr|. +ResultCode SpawnParserSandbox( + scoped_refptr<MojoTaskRunner> mojo_task_runner, + const SandboxConnectionErrorCallback& connection_error_callback, + UniqueParserPtr* parser_ptr); + +} // namespace chrome_cleaner + +#endif // CHROME_CHROME_CLEANER_PARSERS_BROKER_SANDBOX_SETUP_HOOKS_H_
diff --git a/chrome/chrome_cleaner/json_parser/BUILD.gn b/chrome/chrome_cleaner/parsers/json_parser/BUILD.gn similarity index 75% rename from chrome/chrome_cleaner/json_parser/BUILD.gn rename to chrome/chrome_cleaner/parsers/json_parser/BUILD.gn index eb75e9f..0d9420db 100644 --- a/chrome/chrome_cleaner/json_parser/BUILD.gn +++ b/chrome/chrome_cleaner/parsers/json_parser/BUILD.gn
@@ -16,12 +16,6 @@ static_library("json_parser") { sources = [ "json_parser_api.h", - "json_parser_impl.cc", - "json_parser_impl.h", - "sandbox_setup_hooks.cc", - "sandbox_setup_hooks.h", - "sandbox_target_hooks.cc", - "sandbox_target_hooks.h", "sandboxed_json_parser.cc", "sandboxed_json_parser.h", "test_json_parser.cc", @@ -31,10 +25,12 @@ deps = [ "//base:base", "//chrome/chrome_cleaner/constants:common_strings", - "//chrome/chrome_cleaner/interfaces:json_parser_interface", + "//chrome/chrome_cleaner/interfaces:parser_interface", "//chrome/chrome_cleaner/ipc:mojo_task_runner", "//chrome/chrome_cleaner/ipc:sandbox", "//chrome/chrome_cleaner/os:common_os", + "//chrome/chrome_cleaner/parsers/broker:parser_sandbox_broker", + "//chrome/chrome_cleaner/parsers/target:parser_sandbox_target", "//chrome/chrome_cleaner/settings:settings_types", "//components/chrome_cleaner/public/constants", "//mojo/public/cpp/bindings", @@ -45,9 +41,7 @@ testonly = true sources = [ - "json_parser_impl_unittest.cc", "json_splicer_unittest.cc", - "sandbox_setup_unittest.cc", ] deps = [ @@ -55,8 +49,10 @@ ":json_splicer", "//base:base", "//base/test:test_support", - "//chrome/chrome_cleaner/interfaces:json_parser_interface", + "//chrome/chrome_cleaner/interfaces:parser_interface", "//chrome/chrome_cleaner/ipc:mojo_task_runner", + "//chrome/chrome_cleaner/parsers/broker:parser_sandbox_broker", + "//chrome/chrome_cleaner/parsers/target:parser_sandbox_target", "//mojo/public/cpp/bindings", "//sandbox/win:sandbox", "//testing/gtest",
diff --git a/chrome/chrome_cleaner/json_parser/json_parser_api.h b/chrome/chrome_cleaner/parsers/json_parser/json_parser_api.h similarity index 74% rename from chrome/chrome_cleaner/json_parser/json_parser_api.h rename to chrome/chrome_cleaner/parsers/json_parser/json_parser_api.h index 1d106dd..487e7f1 100644 --- a/chrome/chrome_cleaner/json_parser/json_parser_api.h +++ b/chrome/chrome_cleaner/parsers/json_parser/json_parser_api.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_CHROME_CLEANER_JSON_PARSER_JSON_PARSER_API_H_ -#define CHROME_CHROME_CLEANER_JSON_PARSER_JSON_PARSER_API_H_ +#ifndef CHROME_CHROME_CLEANER_PARSERS_JSON_PARSER_JSON_PARSER_API_H_ +#define CHROME_CHROME_CLEANER_PARSERS_JSON_PARSER_JSON_PARSER_API_H_ #include "base/callback.h" #include "base/optional.h" @@ -24,4 +24,4 @@ } // namespace chrome_cleaner -#endif // CHROME_CHROME_CLEANER_JSON_PARSER_JSON_PARSER_API_H_ +#endif // CHROME_CHROME_CLEANER_PARSERS_JSON_PARSER_JSON_PARSER_API_H_
diff --git a/chrome/chrome_cleaner/json_parser/json_splicer.cc b/chrome/chrome_cleaner/parsers/json_parser/json_splicer.cc similarity index 77% rename from chrome/chrome_cleaner/json_parser/json_splicer.cc rename to chrome/chrome_cleaner/parsers/json_parser/json_splicer.cc index 3bdbf6b..c3fb8ad 100644 --- a/chrome/chrome_cleaner/json_parser/json_splicer.cc +++ b/chrome/chrome_cleaner/parsers/json_parser/json_splicer.cc
@@ -2,16 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/chrome_cleaner/json_parser/json_splicer.h" +#include "chrome/chrome_cleaner/parsers/json_parser/json_splicer.h" + +#include <string> +#include <vector> #include "base/values.h" namespace chrome_cleaner { -JsonSplicer::~JsonSplicer() = default; - -bool JsonSplicer::RemoveKeyFromDictionary(base::Value* dictionary, - const std::string& key) { +bool RemoveKeyFromDictionary(base::Value* dictionary, const std::string& key) { bool result = false; base::DictionaryValue* entries = nullptr; if (dictionary == nullptr || !dictionary->is_dict() || @@ -28,8 +28,7 @@ return result; } -bool JsonSplicer::RemoveValueFromList(base::Value* list, - const std::string& key) { +bool RemoveValueFromList(base::Value* list, const std::string& key) { if (list == nullptr || !list->is_list()) { LOG(ERROR) << "Got a " << (list ? list->GetTypeName(list->type()) : "NULL") << " but expected a list.";
diff --git a/chrome/chrome_cleaner/parsers/json_parser/json_splicer.h b/chrome/chrome_cleaner/parsers/json_parser/json_splicer.h new file mode 100644 index 0000000..eeb7170b --- /dev/null +++ b/chrome/chrome_cleaner/parsers/json_parser/json_splicer.h
@@ -0,0 +1,26 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_CHROME_CLEANER_PARSERS_JSON_PARSER_JSON_SPLICER_H_ +#define CHROME_CHROME_CLEANER_PARSERS_JSON_PARSER_JSON_SPLICER_H_ + +#include <string> + +#include "base/values.h" + +namespace chrome_cleaner { + +// Deletes the |key| entry from the |dictionary|. +// +// Returns true on success. +bool RemoveKeyFromDictionary(base::Value* dictionary, const std::string& key); + +// Deletes the entry from the |list| with |key|. +// +// Returns true on success. +bool RemoveValueFromList(base::Value* list, const std::string& key); + +} // namespace chrome_cleaner + +#endif // CHROME_CHROME_CLEANER_PARSERS_JSON_PARSER_JSON_SPLICER_H_
diff --git a/chrome/chrome_cleaner/json_parser/json_splicer_unittest.cc b/chrome/chrome_cleaner/parsers/json_parser/json_splicer_unittest.cc similarity index 77% rename from chrome/chrome_cleaner/json_parser/json_splicer_unittest.cc rename to chrome/chrome_cleaner/parsers/json_parser/json_splicer_unittest.cc index 069cf7f6..ac081b1 100644 --- a/chrome/chrome_cleaner/json_parser/json_splicer_unittest.cc +++ b/chrome/chrome_cleaner/parsers/json_parser/json_splicer_unittest.cc
@@ -2,16 +2,20 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/chrome_cleaner/json_parser/json_splicer.h" +#include "chrome/chrome_cleaner/parsers/json_parser/json_splicer.h" + +#include <memory> +#include <string> +#include <vector> #include "base/bind.h" #include "base/synchronization/waitable_event.h" #include "base/test/test_timeouts.h" #include "base/values.h" -#include "chrome/chrome_cleaner/interfaces/json_parser.mojom.h" +#include "chrome/chrome_cleaner/interfaces/parser_interface.mojom.h" #include "chrome/chrome_cleaner/ipc/mojo_task_runner.h" -#include "chrome/chrome_cleaner/json_parser/json_parser_impl.h" -#include "chrome/chrome_cleaner/json_parser/sandboxed_json_parser.h" +#include "chrome/chrome_cleaner/parsers/json_parser/sandboxed_json_parser.h" +#include "chrome/chrome_cleaner/parsers/target/parser_impl.h" #include "mojo/public/cpp/bindings/interface_request.h" #include "testing/gtest/include/gtest/gtest.h" @@ -57,28 +61,25 @@ public: JsonSplicerImplTest() : task_runner_(MojoTaskRunner::Create()), - json_parser_ptr_(new mojom::JsonParserPtr(), - base::OnTaskRunnerDeleter(task_runner_)), - json_parser_impl_(nullptr, base::OnTaskRunnerDeleter(task_runner_)), - sandboxed_json_parser_(task_runner_.get(), json_parser_ptr_.get()) { + parser_ptr_(new mojom::ParserPtr(), + base::OnTaskRunnerDeleter(task_runner_)), + parser_impl_(nullptr, base::OnTaskRunnerDeleter(task_runner_)), + sandboxed_json_parser_(task_runner_.get(), parser_ptr_.get()) { task_runner_->PostTask( - FROM_HERE, - BindOnce(BindParser, json_parser_ptr_.get(), &json_parser_impl_)); + FROM_HERE, BindOnce(BindParser, parser_ptr_.get(), &parser_impl_)); } protected: static void BindParser( - mojom::JsonParserPtr* json_parser, - std::unique_ptr<JsonParserImpl, base::OnTaskRunnerDeleter>* - json_parser_impl) { - json_parser_impl->reset( - new JsonParserImpl(mojo::MakeRequest(json_parser), base::DoNothing())); + mojom::ParserPtr* json_parser, + std::unique_ptr<ParserImpl, base::OnTaskRunnerDeleter>* parser_impl) { + parser_impl->reset( + new ParserImpl(mojo::MakeRequest(json_parser), base::DoNothing())); } scoped_refptr<MojoTaskRunner> task_runner_; - std::unique_ptr<mojom::JsonParserPtr, base::OnTaskRunnerDeleter> - json_parser_ptr_; - std::unique_ptr<JsonParserImpl, base::OnTaskRunnerDeleter> json_parser_impl_; + std::unique_ptr<mojom::ParserPtr, base::OnTaskRunnerDeleter> parser_ptr_; + std::unique_ptr<ParserImpl, base::OnTaskRunnerDeleter> parser_impl_; SandboxedJsonParser sandboxed_json_parser_; }; @@ -92,17 +93,16 @@ base::BindOnce( [](base::WaitableEvent* done, base::Optional<base::Value> value, const base::Optional<std::string>& error) { - JsonSplicer splicer; ASSERT_FALSE(error.has_value()); ASSERT_TRUE(value.has_value()); base::DictionaryValue* dict; ASSERT_TRUE(value->GetAsDictionary(&dict)); ASSERT_TRUE(IsDaysOfWeek(dict)); std::string blank = ""; - ASSERT_FALSE(splicer.RemoveKeyFromDictionary(dict, blank)); + ASSERT_FALSE(RemoveKeyFromDictionary(dict, blank)); ASSERT_TRUE(IsDaysOfWeek(dict)); std::string random = "aoeu"; - ASSERT_FALSE(splicer.RemoveKeyFromDictionary(dict, random)); + ASSERT_FALSE(RemoveKeyFromDictionary(dict, random)); ASSERT_TRUE(IsDaysOfWeek(dict)); done->Signal(); }, @@ -118,7 +118,6 @@ base::BindOnce( [](base::WaitableEvent* done, base::Optional<base::Value> value, const base::Optional<std::string>& error) { - JsonSplicer splicer; ASSERT_FALSE(error.has_value()); ASSERT_TRUE(value.has_value()); base::DictionaryValue* dict; @@ -127,13 +126,13 @@ std::string monday = "monday"; ASSERT_TRUE(dict->HasKey(monday)); - ASSERT_TRUE(splicer.RemoveKeyFromDictionary(dict, monday)); + ASSERT_TRUE(RemoveKeyFromDictionary(dict, monday)); ASSERT_FALSE(IsDaysOfWeek(dict)); ASSERT_FALSE(dict->HasKey(monday)); std::string wednesday = "wednesday"; ASSERT_TRUE(dict->HasKey(wednesday)); - ASSERT_TRUE(splicer.RemoveKeyFromDictionary(dict, wednesday)); + ASSERT_TRUE(RemoveKeyFromDictionary(dict, wednesday)); ASSERT_FALSE(IsDaysOfWeek(dict)); ASSERT_FALSE(dict->HasKey(wednesday)); done->Signal(); @@ -150,16 +149,15 @@ base::BindOnce( [](base::WaitableEvent* done, base::Optional<base::Value> value, const base::Optional<std::string>& error) { - JsonSplicer splicer; ASSERT_FALSE(error.has_value()); ASSERT_TRUE(value.has_value()); std::vector<base::Value>& list = value->GetList(); ASSERT_TRUE(IsDaysOfWeek(list)); std::string blank = ""; - ASSERT_FALSE(splicer.RemoveValueFromList(&*value, blank)); + ASSERT_FALSE(RemoveValueFromList(&*value, blank)); ASSERT_TRUE(IsDaysOfWeek(list)); std::string random = "aoeu"; - ASSERT_FALSE(splicer.RemoveValueFromList(&*value, random)); + ASSERT_FALSE(RemoveValueFromList(&*value, random)); ASSERT_TRUE(IsDaysOfWeek(list)); done->Signal(); }, @@ -175,18 +173,17 @@ base::BindOnce( [](base::WaitableEvent* done, base::Optional<base::Value> value, const base::Optional<std::string>& error) { - JsonSplicer splicer; ASSERT_FALSE(error.has_value()); ASSERT_TRUE(value.has_value()); std::vector<base::Value>& list = value->GetList(); ASSERT_TRUE(IsDaysOfWeek(list)); std::string monday = "monday"; - ASSERT_TRUE(splicer.RemoveValueFromList(&*value, monday)); + ASSERT_TRUE(RemoveValueFromList(&*value, monday)); ASSERT_FALSE(IsDaysOfWeek(list)); ASSERT_FALSE(std::find(list.begin(), list.end(), base::Value(monday)) != list.end()); std::string wednesday = "wednesday"; - ASSERT_TRUE(splicer.RemoveValueFromList(&*value, wednesday)); + ASSERT_TRUE(RemoveValueFromList(&*value, wednesday)); ASSERT_FALSE(IsDaysOfWeek(list)); ASSERT_FALSE(std::find(list.begin(), list.end(), base::Value(monday)) != list.end());
diff --git a/chrome/chrome_cleaner/parsers/json_parser/sandboxed_json_parser.cc b/chrome/chrome_cleaner/parsers/json_parser/sandboxed_json_parser.cc new file mode 100644 index 0000000..a60091d --- /dev/null +++ b/chrome/chrome_cleaner/parsers/json_parser/sandboxed_json_parser.cc
@@ -0,0 +1,24 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/chrome_cleaner/parsers/json_parser/sandboxed_json_parser.h" + +namespace chrome_cleaner { + +SandboxedJsonParser::SandboxedJsonParser(MojoTaskRunner* mojo_task_runner, + mojom::ParserPtr* parser_ptr) + : mojo_task_runner_(mojo_task_runner), parser_ptr_(parser_ptr) {} + +void SandboxedJsonParser::Parse(const std::string& json, + ParseDoneCallback callback) { + mojo_task_runner_->PostTask( + FROM_HERE, base::BindOnce( + [](mojom::ParserPtr* parser_ptr, const std::string& json, + ParseDoneCallback callback) { + (*parser_ptr)->ParseJson(json, std::move(callback)); + }, + parser_ptr_, json, std::move(callback))); +} + +} // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/parsers/json_parser/sandboxed_json_parser.h b/chrome/chrome_cleaner/parsers/json_parser/sandboxed_json_parser.h new file mode 100644 index 0000000..5d348df --- /dev/null +++ b/chrome/chrome_cleaner/parsers/json_parser/sandboxed_json_parser.h
@@ -0,0 +1,30 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_CHROME_CLEANER_PARSERS_JSON_PARSER_SANDBOXED_JSON_PARSER_H_ +#define CHROME_CHROME_CLEANER_PARSERS_JSON_PARSER_SANDBOXED_JSON_PARSER_H_ + +#include "chrome/chrome_cleaner/interfaces/parser_interface.mojom.h" +#include "chrome/chrome_cleaner/ipc/mojo_task_runner.h" +#include "chrome/chrome_cleaner/parsers/json_parser/json_parser_api.h" + +namespace chrome_cleaner { + +// An implementation of JsonParserAPI to wrap a MojoTaskRunner and +// JsonParserPtr. Parses via |parser_ptr_| on the |mojo_task_runner_|. +// TODO(joenotcharles): Move this class to chrome_cleaner/parsers/broker. +class SandboxedJsonParser : public JsonParserAPI { + public: + SandboxedJsonParser(MojoTaskRunner* mojo_task_runner, + mojom::ParserPtr* parser_ptr); + void Parse(const std::string& json, ParseDoneCallback callback) override; + + private: + MojoTaskRunner* mojo_task_runner_; + mojom::ParserPtr* parser_ptr_; +}; + +} // namespace chrome_cleaner + +#endif // CHROME_CHROME_CLEANER_PARSERS_JSON_PARSER_SANDBOXED_JSON_PARSER_H_
diff --git a/chrome/chrome_cleaner/json_parser/test_json_parser.cc b/chrome/chrome_cleaner/parsers/json_parser/test_json_parser.cc similarity index 86% rename from chrome/chrome_cleaner/json_parser/test_json_parser.cc rename to chrome/chrome_cleaner/parsers/json_parser/test_json_parser.cc index 34cb6ac..43a205f4 100644 --- a/chrome/chrome_cleaner/json_parser/test_json_parser.cc +++ b/chrome/chrome_cleaner/parsers/json_parser/test_json_parser.cc
@@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/chrome_cleaner/json_parser/test_json_parser.h" +#include "chrome/chrome_cleaner/parsers/json_parser/test_json_parser.h" #include "base/json/json_reader.h" #include "base/values.h" -#include "chrome/chrome_cleaner/json_parser/json_parser_impl.h" +#include "chrome/chrome_cleaner/parsers/target/parser_impl.h" namespace chrome_cleaner {
diff --git a/chrome/chrome_cleaner/json_parser/test_json_parser.h b/chrome/chrome_cleaner/parsers/json_parser/test_json_parser.h similarity index 66% rename from chrome/chrome_cleaner/json_parser/test_json_parser.h rename to chrome/chrome_cleaner/parsers/json_parser/test_json_parser.h index 3e9fa11..c6e5a94 100644 --- a/chrome/chrome_cleaner/json_parser/test_json_parser.h +++ b/chrome/chrome_cleaner/parsers/json_parser/test_json_parser.h
@@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_CHROME_CLEANER_JSON_PARSER_TEST_JSON_PARSER_H_ -#define CHROME_CHROME_CLEANER_JSON_PARSER_TEST_JSON_PARSER_H_ +#ifndef CHROME_CHROME_CLEANER_PARSERS_JSON_PARSER_TEST_JSON_PARSER_H_ +#define CHROME_CHROME_CLEANER_PARSERS_JSON_PARSER_TEST_JSON_PARSER_H_ -#include "chrome/chrome_cleaner/json_parser/json_parser_api.h" +#include "chrome/chrome_cleaner/parsers/json_parser/json_parser_api.h" namespace chrome_cleaner { @@ -19,4 +19,4 @@ } // namespace chrome_cleaner -#endif // CHROME_CHROME_CLEANER_JSON_PARSER_TEST_JSON_PARSER_H_ +#endif // CHROME_CHROME_CLEANER_PARSERS_JSON_PARSER_TEST_JSON_PARSER_H_
diff --git a/chrome/chrome_cleaner/parsers/target/BUILD.gn b/chrome/chrome_cleaner/parsers/target/BUILD.gn new file mode 100644 index 0000000..4bfffe8 --- /dev/null +++ b/chrome/chrome_cleaner/parsers/target/BUILD.gn
@@ -0,0 +1,45 @@ +# 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. + +static_library("parser_sandbox_target") { + sources = [ + "parser_impl.cc", + "parser_impl.h", + "sandbox_setup.cc", + "sandbox_setup.h", + ] + + deps = [ + "//base:base", + "//chrome/chrome_cleaner/constants:common_strings", + "//chrome/chrome_cleaner/interfaces:parser_interface", + "//chrome/chrome_cleaner/ipc:mojo_task_runner", + "//chrome/chrome_cleaner/ipc:sandbox", + "//chrome/chrome_cleaner/os:common_os", + "//chrome/chrome_cleaner/settings:settings_types", + "//components/chrome_cleaner/public/constants:constants", + "//mojo/public/cpp/bindings", + "//sandbox/win:sandbox", + ] +} + +source_set("unittest_sources") { + testonly = true + + sources = [ + "parser_impl_unittest.cc", + ] + deps = [ + ":parser_sandbox_target", + "//base:base", + "//base/test:test_support", + "//chrome/chrome_cleaner/interfaces:parser_interface", + "//chrome/chrome_cleaner/ipc:mojo_task_runner", + "//chrome/chrome_cleaner/os:common_os", + "//chrome/chrome_cleaner/parsers/json_parser:json_parser", + "//chrome/chrome_cleaner/parsers/json_parser:json_splicer", + "//mojo/public/cpp/bindings:bindings", + "//testing/gtest", + ] +}
diff --git a/chrome/chrome_cleaner/json_parser/json_parser_impl.cc b/chrome/chrome_cleaner/parsers/target/parser_impl.cc similarity index 73% rename from chrome/chrome_cleaner/json_parser/json_parser_impl.cc rename to chrome/chrome_cleaner/parsers/target/parser_impl.cc index b2243e3..210c9a1 100644 --- a/chrome/chrome_cleaner/json_parser/json_parser_impl.cc +++ b/chrome/chrome_cleaner/parsers/target/parser_impl.cc
@@ -2,22 +2,23 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/chrome_cleaner/json_parser/json_parser_impl.h" +#include "chrome/chrome_cleaner/parsers/target/parser_impl.h" #include "base/json/json_reader.h" #include "base/values.h" namespace chrome_cleaner { -JsonParserImpl::JsonParserImpl(mojom::JsonParserRequest request, - base::OnceClosure connection_error_handler) +ParserImpl::ParserImpl(mojom::ParserRequest request, + base::OnceClosure connection_error_handler) : binding_(this, std::move(request)) { binding_.set_connection_error_handler(std::move(connection_error_handler)); } -JsonParserImpl::~JsonParserImpl() = default; +ParserImpl::~ParserImpl() = default; -void JsonParserImpl::Parse(const std::string& json, ParseCallback callback) { +void ParserImpl::ParseJson(const std::string& json, + ParseJsonCallback callback) { int error_code; std::string error; std::unique_ptr<base::Value> value = base::JSONReader::ReadAndReturnError(
diff --git a/chrome/chrome_cleaner/parsers/target/parser_impl.h b/chrome/chrome_cleaner/parsers/target/parser_impl.h new file mode 100644 index 0000000..1e1891a --- /dev/null +++ b/chrome/chrome_cleaner/parsers/target/parser_impl.h
@@ -0,0 +1,29 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_CHROME_CLEANER_PARSERS_TARGET_PARSER_IMPL_H_ +#define CHROME_CHROME_CLEANER_PARSERS_TARGET_PARSER_IMPL_H_ + +#include "chrome/chrome_cleaner/interfaces/parser_interface.mojom.h" +#include "mojo/public/cpp/bindings/binding.h" + +namespace chrome_cleaner { + +class ParserImpl : public mojom::Parser { + public: + explicit ParserImpl(mojom::ParserRequest request, + base::OnceClosure connection_error_handler); + ~ParserImpl() override; + + // mojom::Parser + void ParseJson(const std::string& json, + ParserImpl::ParseJsonCallback callback) override; + + private: + mojo::Binding<mojom::Parser> binding_; +}; + +} // namespace chrome_cleaner + +#endif // CHROME_CHROME_CLEANER_PARSERS_TARGET_PARSER_IMPL_H_
diff --git a/chrome/chrome_cleaner/json_parser/json_parser_impl_unittest.cc b/chrome/chrome_cleaner/parsers/target/parser_impl_unittest.cc similarity index 67% rename from chrome/chrome_cleaner/json_parser/json_parser_impl_unittest.cc rename to chrome/chrome_cleaner/parsers/target/parser_impl_unittest.cc index 597b3ea..685033bb 100644 --- a/chrome/chrome_cleaner/json_parser/json_parser_impl_unittest.cc +++ b/chrome/chrome_cleaner/parsers/target/parser_impl_unittest.cc
@@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/chrome_cleaner/json_parser/json_parser_impl.h" +#include "chrome/chrome_cleaner/parsers/target/parser_impl.h" #include "base/bind.h" #include "base/synchronization/waitable_event.h" #include "base/test/test_timeouts.h" #include "base/values.h" -#include "chrome/chrome_cleaner/interfaces/json_parser.mojom.h" +#include "chrome/chrome_cleaner/interfaces/parser_interface.mojom.h" #include "chrome/chrome_cleaner/ipc/mojo_task_runner.h" -#include "chrome/chrome_cleaner/json_parser/sandboxed_json_parser.h" +#include "chrome/chrome_cleaner/parsers/json_parser/sandboxed_json_parser.h" #include "mojo/public/cpp/bindings/interface_request.h" #include "testing/gtest/include/gtest/gtest.h" @@ -25,14 +25,14 @@ const char kTestJsonText[] = "{ \"name\": \"Jason\" }"; const char kInvalidJsonText[] = "{ name: jason }"; -class JsonParserImplTest : public testing::Test { +class ParserImplTest : public testing::Test { public: - JsonParserImplTest() + ParserImplTest() : task_runner_(MojoTaskRunner::Create()), - json_parser_ptr_(new mojom::JsonParserPtr(), - base::OnTaskRunnerDeleter(task_runner_)), - json_parser_impl_(nullptr, base::OnTaskRunnerDeleter(task_runner_)), - sandboxed_json_parser_(task_runner_.get(), json_parser_ptr_.get()) { + parser_ptr_(new mojom::ParserPtr(), + base::OnTaskRunnerDeleter(task_runner_)), + parser_impl_(nullptr, base::OnTaskRunnerDeleter(task_runner_)), + sandboxed_json_parser_(task_runner_.get(), parser_ptr_.get()) { BindParser(); } @@ -41,25 +41,24 @@ task_runner_->PostTask( FROM_HERE, base::BindOnce( - [](mojom::JsonParserPtr* json_parser, - std::unique_ptr<JsonParserImpl, base::OnTaskRunnerDeleter>* - json_parser_impl) { - json_parser_impl->reset(new JsonParserImpl( - mojo::MakeRequest(json_parser), base::DoNothing())); + [](mojom::ParserPtr* parser, + std::unique_ptr<ParserImpl, base::OnTaskRunnerDeleter>* + parser_impl) { + parser_impl->reset( + new ParserImpl(mojo::MakeRequest(parser), base::DoNothing())); }, - json_parser_ptr_.get(), &json_parser_impl_)); + parser_ptr_.get(), &parser_impl_)); } scoped_refptr<MojoTaskRunner> task_runner_; - std::unique_ptr<mojom::JsonParserPtr, base::OnTaskRunnerDeleter> - json_parser_ptr_; - std::unique_ptr<JsonParserImpl, base::OnTaskRunnerDeleter> json_parser_impl_; + std::unique_ptr<mojom::ParserPtr, base::OnTaskRunnerDeleter> parser_ptr_; + std::unique_ptr<ParserImpl, base::OnTaskRunnerDeleter> parser_impl_; SandboxedJsonParser sandboxed_json_parser_; }; } // namespace -TEST_F(JsonParserImplTest, ParseJson) { +TEST_F(ParserImplTest, ParseJson) { WaitableEvent done(WaitableEvent::ResetPolicy::MANUAL, WaitableEvent::InitialState::NOT_SIGNALED); sandboxed_json_parser_.Parse( @@ -82,7 +81,7 @@ EXPECT_TRUE(done.TimedWait(TestTimeouts::action_timeout())); } -TEST_F(JsonParserImplTest, ParseJsonError) { +TEST_F(ParserImplTest, ParseJsonError) { WaitableEvent done(WaitableEvent::ResetPolicy::MANUAL, WaitableEvent::InitialState::NOT_SIGNALED); sandboxed_json_parser_.Parse(
diff --git a/chrome/chrome_cleaner/parsers/target/sandbox_setup.cc b/chrome/chrome_cleaner/parsers/target/sandbox_setup.cc new file mode 100644 index 0000000..e5d0c2bb8d --- /dev/null +++ b/chrome/chrome_cleaner/parsers/target/sandbox_setup.cc
@@ -0,0 +1,74 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/chrome_cleaner/parsers/target/sandbox_setup.h" + +#include <utility> + +#include "chrome/chrome_cleaner/interfaces/parser_interface.mojom.h" +#include "chrome/chrome_cleaner/ipc/mojo_sandbox_hooks.h" +#include "chrome/chrome_cleaner/ipc/mojo_task_runner.h" +#include "chrome/chrome_cleaner/os/early_exit.h" +#include "chrome/chrome_cleaner/parsers/target/parser_impl.h" +#include "components/chrome_cleaner/public/constants/result_codes.h" + +namespace chrome_cleaner { + +namespace { + +class ParserSandboxTargetHooks : public MojoSandboxTargetHooks { + public: + explicit ParserSandboxTargetHooks(MojoTaskRunner* mojo_task_runner) + : mojo_task_runner_(mojo_task_runner) {} + + ~ParserSandboxTargetHooks() override { + // Delete the mojo objects on the IPC thread. + mojo_task_runner_->PostTask( + FROM_HERE, base::BindOnce( + [](std::unique_ptr<ParserImpl> parser_impl) { + parser_impl.reset(); + }, + base::Passed(&parser_impl_))); + } + + // SandboxTargetHooks + ResultCode TargetDroppedPrivileges( + const base::CommandLine& command_line) override { + mojom::ParserRequest request(ExtractSandboxMessagePipe(command_line)); + + // This loop will run forever. Once the communication channel with the + // broker process is broken, mojo error handler will abort this process. + base::RunLoop run_loop; + mojo_task_runner_->PostTask( + FROM_HERE, + base::BindOnce(&ParserSandboxTargetHooks::CreateParserImpl, + base::Unretained(this), base::Passed(&request))); + run_loop.Run(); + return RESULT_CODE_SUCCESS; + } + + private: + void CreateParserImpl(mojom::ParserRequest request) { + parser_impl_ = std::make_unique<ParserImpl>(std::move(request), + base::BindOnce(&EarlyExit, 1)); + } + + MojoTaskRunner* mojo_task_runner_; + base::MessageLoop message_loop_; + std::unique_ptr<ParserImpl> parser_impl_; + + DISALLOW_COPY_AND_ASSIGN(ParserSandboxTargetHooks); +}; + +} // namespace + +ResultCode RunParserSandboxTarget(const base::CommandLine& command_line, + sandbox::TargetServices* target_services) { + scoped_refptr<MojoTaskRunner> mojo_task_runner = MojoTaskRunner::Create(); + ParserSandboxTargetHooks target_hooks(mojo_task_runner.get()); + + return RunSandboxTarget(command_line, target_services, &target_hooks); +} + +} // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/parsers/target/sandbox_setup.h b/chrome/chrome_cleaner/parsers/target/sandbox_setup.h new file mode 100644 index 0000000..ce2d724 --- /dev/null +++ b/chrome/chrome_cleaner/parsers/target/sandbox_setup.h
@@ -0,0 +1,19 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_CHROME_CLEANER_PARSERS_TARGET_SANDBOX_SETUP_H_ +#define CHROME_CHROME_CLEANER_PARSERS_TARGET_SANDBOX_SETUP_H_ + +#include "base/command_line.h" +#include "components/chrome_cleaner/public/constants/result_codes.h" +#include "sandbox/win/src/sandbox.h" + +namespace chrome_cleaner { + +ResultCode RunParserSandboxTarget(const base::CommandLine& command_line, + sandbox::TargetServices* target_services); + +} // namespace chrome_cleaner + +#endif // CHROME_CHROME_CLEANER_PARSERS_TARGET_SANDBOX_SETUP_H_
diff --git a/chrome/chrome_cleaner/settings/settings_types.h b/chrome/chrome_cleaner/settings/settings_types.h index 6789d79..17d5d43 100644 --- a/chrome/chrome_cleaner/settings/settings_types.h +++ b/chrome/chrome_cleaner/settings/settings_types.h
@@ -14,7 +14,7 @@ kNonSandboxed = 0, kTest, kEset, - kJsonParser, + kParser, kZipArchiver, kNumValues, };
diff --git a/chrome/common/chrome_paths.cc b/chrome/common/chrome_paths.cc index e869d40e0..6cc2c913 100644 --- a/chrome/common/chrome_paths.cc +++ b/chrome/common/chrome_paths.cc
@@ -5,9 +5,9 @@ #include "chrome/common/chrome_paths.h" #include "base/files/file_util.h" -#include "base/lazy_instance.h" #include "base/logging.h" #include "base/native_library.h" +#include "base/no_destructor.h" #include "base/path_service.h" #include "base/strings/string_util.h" #include "base/system/sys_info.h" @@ -77,8 +77,10 @@ FILE_PATH_LITERAL("/run/tpm_firmware_update_srk_vulnerable_roca"); #endif // defined(OS_CHROMEOS) -static base::LazyInstance<base::FilePath>::DestructorAtExit - g_invalid_specified_user_data_dir = LAZY_INSTANCE_INITIALIZER; +base::FilePath& GetInvalidSpecifiedUserDataDirInternal() { + static base::NoDestructor<base::FilePath> s; + return *s; +} // Gets the path for internal plugins. bool GetInternalPluginsDirectory(base::FilePath* result) { @@ -606,11 +608,11 @@ } void SetInvalidSpecifiedUserDataDir(const base::FilePath& user_data_dir) { - g_invalid_specified_user_data_dir.Get() = user_data_dir; + GetInvalidSpecifiedUserDataDirInternal() = user_data_dir; } const base::FilePath& GetInvalidSpecifiedUserDataDir() { - return g_invalid_specified_user_data_dir.Get(); + return GetInvalidSpecifiedUserDataDirInternal(); } } // namespace chrome
diff --git a/chrome/common/extensions/api/autotest_private.idl b/chrome/common/extensions/api/autotest_private.idl index a7d8e6a..a4f836f 100644 --- a/chrome/common/extensions/api/autotest_private.idl +++ b/chrome/common/extensions/api/autotest_private.idl
@@ -217,5 +217,9 @@ // daemon startup, and 2. the initial D-Bus -> Mojo IPC bootstrap. // |callback|: Called when the operation has completed. static void bootstrapMachineLearningService(VoidCallback callback); + + // Enable/disable the Google Assistant + // |callback|: Called when the operation has completed. + static void setAssistantEnabled(boolean enabled, long timeout_ms, VoidCallback callback); }; };
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc index bd1218ae..6fb885ec1 100644 --- a/chrome/renderer/chrome_content_renderer_client.cc +++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -1176,13 +1176,12 @@ content::RenderFrame* render_frame, const WebURLRequest& failed_request, const blink::WebURLError& web_error, - std::string* error_html, - base::string16* error_description) { + std::string* error_html) { PrepareErrorPageInternal( render_frame, failed_request, error_page::Error::NetError(web_error.url(), web_error.reason(), web_error.has_copy_in_cache()), - error_html, error_description); + error_html); } void ChromeContentRendererClient::PrepareErrorPageForHttpStatusError( @@ -1190,12 +1189,10 @@ const WebURLRequest& failed_request, const GURL& unreachable_url, int http_status, - std::string* error_html, - base::string16* error_description) { + std::string* error_html) { PrepareErrorPageInternal( render_frame, failed_request, - error_page::Error::HttpError(unreachable_url, http_status), error_html, - error_description); + error_page::Error::HttpError(unreachable_url, http_status), error_html); } void ChromeContentRendererClient::GetErrorDescription( @@ -1213,15 +1210,12 @@ content::RenderFrame* render_frame, const WebURLRequest& failed_request, const error_page::Error& error, - std::string* error_html, - base::string16* error_description) { + std::string* error_html) { bool is_post = failed_request.HttpMethod().Ascii() == "POST"; bool is_ignoring_cache = failed_request.GetCacheMode() == FetchCacheMode::kBypassCache; NetErrorHelper::Get(render_frame) ->PrepareErrorPage(error, is_post, is_ignoring_cache, error_html); - if (error_description) - GetErrorDescriptionInternal(failed_request, error, error_description); } void ChromeContentRendererClient::GetErrorDescriptionInternal(
diff --git a/chrome/renderer/chrome_content_renderer_client.h b/chrome/renderer/chrome_content_renderer_client.h index 2c440b2..cf175024 100644 --- a/chrome/renderer/chrome_content_renderer_client.h +++ b/chrome/renderer/chrome_content_renderer_client.h
@@ -132,15 +132,13 @@ void PrepareErrorPage(content::RenderFrame* render_frame, const blink::WebURLRequest& failed_request, const blink::WebURLError& error, - std::string* error_html, - base::string16* error_description) override; + std::string* error_html) override; void PrepareErrorPageForHttpStatusError( content::RenderFrame* render_frame, const blink::WebURLRequest& failed_request, const GURL& unreachable_url, int http_status, - std::string* error_html, - base::string16* error_description) override; + std::string* error_html) override; void GetErrorDescription(const blink::WebURLRequest& failed_request, const blink::WebURLError& error, @@ -284,8 +282,7 @@ void PrepareErrorPageInternal(content::RenderFrame* render_frame, const blink::WebURLRequest& failed_request, const error_page::Error& error, - std::string* error_html, - base::string16* error_description); + std::string* error_html); void GetErrorDescriptionInternal(const blink::WebURLRequest& failed_request, const error_page::Error& error,
diff --git a/chrome/renderer/pepper/pepper_flash_renderer_host.cc b/chrome/renderer/pepper/pepper_flash_renderer_host.cc index 63a3395..42248ea 100644 --- a/chrome/renderer/pepper/pepper_flash_renderer_host.cc +++ b/chrome/renderer/pepper/pepper_flash_renderer_host.cc
@@ -9,9 +9,9 @@ #include <map> #include <vector> -#include "base/lazy_instance.h" #include "base/macros.h" #include "base/metrics/histogram_macros.h" +#include "base/no_destructor.h" #include "base/strings/string_util.h" #include "components/pdf/renderer/pepper_pdf_host.h" #include "content/public/renderer/pepper_plugin_instance.h" @@ -101,8 +101,10 @@ FLASH_NAVIGATE_USAGE_ENUM_COUNT }; -static base::LazyInstance<std::map<std::string, FlashNavigateUsage>>:: - DestructorAtExit g_rejected_headers = LAZY_INSTANCE_INITIALIZER; +std::map<std::string, FlashNavigateUsage>& GetRejectedHeaders() { + static base::NoDestructor<std::map<std::string, FlashNavigateUsage>> s; + return *s; +} bool IsSimpleHeader(const std::string& lower_case_header_name, const std::string& header_value) { @@ -303,7 +305,7 @@ return PP_ERROR_FAILED; std::map<std::string, FlashNavigateUsage>& rejected_headers = - g_rejected_headers.Get(); + GetRejectedHeaders(); if (rejected_headers.empty()) { for (size_t i = 0; i < arraysize(kRejectedHttpRequestHeaders); ++i) rejected_headers[kRejectedHttpRequestHeaders[i]] =
diff --git a/chrome/renderer/safe_browsing/phishing_classifier_delegate.cc b/chrome/renderer/safe_browsing/phishing_classifier_delegate.cc index 9f1497c..62ec6602 100644 --- a/chrome/renderer/safe_browsing/phishing_classifier_delegate.cc +++ b/chrome/renderer/safe_browsing/phishing_classifier_delegate.cc
@@ -12,6 +12,7 @@ #include "base/lazy_instance.h" #include "base/logging.h" #include "base/metrics/histogram_macros.h" +#include "base/no_destructor.h" #include "chrome/renderer/safe_browsing/feature_extractor_clock.h" #include "chrome/renderer/safe_browsing/phishing_classifier.h" #include "chrome/renderer/safe_browsing/scorer.h" @@ -30,19 +31,24 @@ namespace safe_browsing { -static GURL StripRef(const GURL& url) { +namespace { + +GURL StripRef(const GURL& url) { GURL::Replacements replacements; replacements.ClearRef(); return url.ReplaceComponents(replacements); } -typedef std::set<PhishingClassifierDelegate*> PhishingClassifierDelegates; -static base::LazyInstance<PhishingClassifierDelegates>::DestructorAtExit - g_delegates = LAZY_INSTANCE_INITIALIZER; +std::set<PhishingClassifierDelegate*> PhishingClassifierDelegates() { + static base::NoDestructor<std::set<PhishingClassifierDelegate*>> s; + return *s; +} -static base::LazyInstance<std::unique_ptr<const safe_browsing::Scorer>>:: +base::LazyInstance<std::unique_ptr<const safe_browsing::Scorer>>:: DestructorAtExit g_phishing_scorer = LAZY_INSTANCE_INITIALIZER; +} // namespace + // static void PhishingClassifierFilter::Create( mojom::PhishingModelSetterRequest request) { @@ -65,10 +71,8 @@ return; } } - PhishingClassifierDelegates::iterator i; - for (i = g_delegates.Get().begin(); i != g_delegates.Get().end(); ++i) { - (*i)->SetPhishingScorer(scorer); - } + for (auto* delegate : PhishingClassifierDelegates()) + delegate->SetPhishingScorer(scorer); g_phishing_scorer.Get().reset(scorer); } @@ -88,7 +92,7 @@ last_main_frame_transition_(ui::PAGE_TRANSITION_LINK), have_page_text_(false), is_classifying_(false) { - g_delegates.Get().insert(this); + PhishingClassifierDelegates().insert(this); if (!classifier) { classifier = new PhishingClassifier(render_frame, new FeatureExtractorClock()); @@ -106,7 +110,7 @@ PhishingClassifierDelegate::~PhishingClassifierDelegate() { CancelPendingClassification(SHUTDOWN); - g_delegates.Get().erase(this); + PhishingClassifierDelegates().erase(this); } void PhishingClassifierDelegate::SetPhishingScorer(
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index fc33066..c80ee09 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -1593,7 +1593,6 @@ sources += [ "../browser/ui/views/frame/opaque_browser_frame_view_browsertest.cc", "../browser/ui/views/policy/enterprise_startup_dialog_view_browsertest.cc", - "../browser/ui/views/profiles/forced_reauthentication_dialog_view_browsertest.cc", "../browser/ui/views/toolbar/outdated_upgrade_bubble_view_browsertest.cc", ] } @@ -2969,6 +2968,7 @@ if (enable_offline_pages) { sources += [ + "../browser/offline_pages/auto_fetch_page_load_watcher_unittest.cc", "../browser/offline_pages/background_loader_offliner_unittest.cc", "../browser/offline_pages/download_archive_manager_unittest.cc", "../browser/offline_pages/offline_page_auto_fetcher_service_unittest.cc",
diff --git a/chrome/test/data/extensions/api_test/autotest_private/test.js b/chrome/test/data/extensions/api_test/autotest_private/test.js index 7e3e2e92e..2119e4e 100644 --- a/chrome/test/data/extensions/api_test/autotest_private/test.js +++ b/chrome/test/data/extensions/api_test/autotest_private/test.js
@@ -206,5 +206,10 @@ chrome.autotestPrivate.getPrinterList(function(){ chrome.test.succeed(); }); - } + }, + function setAssistantEnabled() { + chrome.autotestPrivate.setAssistantEnabled(true, 1000 /* timeout_ms */, + chrome.test.callbackFail( + 'Assistant is not available for the current user')); + }, ]);
diff --git a/chrome/test/data/extensions/updater/ping_reply_1.json b/chrome/test/data/extensions/updater/ping_reply_1.json new file mode 100644 index 0000000..41bcae4 --- /dev/null +++ b/chrome/test/data/extensions/updater/ping_reply_1.json
@@ -0,0 +1,11 @@ +)]}' +{"response":{ + "protocol":"3.1", + "daystart":{"elapsed_days":4055, "elapsed_seconds":44620}, + "app":[ + {"appid":"aohghmighlieiainnegkcijnfilokake", + "status":"ok", + "event":[{"status":"ok"},{"status":"ok"}] + } + ] +}}
diff --git a/chrome/test/data/extensions/updater/updatecheck_reply_noupdate_1.json b/chrome/test/data/extensions/updater/updatecheck_reply_noupdate_1.json new file mode 100644 index 0000000..94d1f89 --- /dev/null +++ b/chrome/test/data/extensions/updater/updatecheck_reply_noupdate_1.json
@@ -0,0 +1,10 @@ +)]}' +{"response":{ + "protocol":"3.1", + "daystart":{"elapsed_days":4055, "elapsed_seconds":44620}, + "app":[ + {"appid":"aohghmighlieiainnegkcijnfilokake", + "updatecheck":{"status":"noupdate"} + } + ] +}}
diff --git a/chrome/test/data/extensions/updater/updatecheck_reply_update_1.json b/chrome/test/data/extensions/updater/updatecheck_reply_update_1.json new file mode 100644 index 0000000..3e2b15cd --- /dev/null +++ b/chrome/test/data/extensions/updater/updatecheck_reply_update_1.json
@@ -0,0 +1,27 @@ +)]}' +{"response":{ + "protocol":"3.1", + "server":"prod", + "daystart":{"elapsed_days":4054, "elapsed_seconds":61236}, + "app":[ + {"appid":"aohghmighlieiainnegkcijnfilokake", + "cohort":"", + "cohortname":"", + "status":"ok", + "updatecheck":{ + "status":"ok", + "urls":{"url":[{"codebase":"http://localhost/download/"}]}, + "actions":{"action":[{"run":"this"}]}, + "manifest":{ + "version":"0.1", + "packages":{"package":[{ + "fp":"1.d6f11c606729d553e9c9b3d0db9e5d51567ea969bedd98008cce7b9415a17490", + "hash_sha256":"d6f11c606729d553e9c9b3d0db9e5d51567ea969bedd98008cce7b9415a17490", + "name":"v1.crx", + "required":"true", + "size":23276 + }]}} + } + } + ] +}}
diff --git a/chrome/test/data/navigation_predictor/long_page_with_anchors-1.html b/chrome/test/data/navigation_predictor/long_page_with_anchors-1.html deleted file mode 100644 index 83a4c9cc..0000000 --- a/chrome/test/data/navigation_predictor/long_page_with_anchors-1.html +++ /dev/null
@@ -1,10 +0,0 @@ -<html> - <head> - </head> - <body> - <a id="google" href="https://google.com">Google</a> - <img src="large_image_takes_all_viewport.gif" height="4200" width="4200"> - <a id="example2" href="https://example2.com">Below viewport</a> - <a id="example3" href="long_page_with_anchors-2.html">Below viewport differ by one</a> - </body> -</html> \ No newline at end of file
diff --git a/chrome_elf/BUILD.gn b/chrome_elf/BUILD.gn index d0949dc..7f780b5 100644 --- a/chrome_elf/BUILD.gn +++ b/chrome_elf/BUILD.gn
@@ -63,6 +63,8 @@ ] if (target_cpu == "x86") { sources += [ "chrome_elf_x86.def" ] + } else if (target_cpu == "arm64") { + sources += [ "chrome_elf_arm64.def" ] } else { sources += [ "chrome_elf_x64.def" ] }
diff --git a/chrome_elf/chrome_elf_arm64.def b/chrome_elf/chrome_elf_arm64.def new file mode 100644 index 0000000..dc0fc69e --- /dev/null +++ b/chrome_elf/chrome_elf_arm64.def
@@ -0,0 +1,38 @@ +; Copyright 2013 The Chromium Authors. All rights reserved. +; Use of this source code is governed by a BSD-style license that can be +; found in the LICENSE file. +LIBRARY "chrome_elf.dll" + +EXPORTS + ; When functions are added to this file, they must also be added to + ; chrome_elf_x86.def and chrome_elf_x64.def + + ; From components/crash/content/app/crash_export_stubs.cc + CrashForException_ExportThunk + DumpHungProcessWithPtype_ExportThunk + GetCrashpadDatabasePath_ExportThunk + GetCrashReports_ExportThunk + InjectDumpForHungInput_ExportThunk + RequestSingleCrashUpload_ExportThunk + SetUploadConsent_ExportThunk + + ; From chrome_elf/crash/crash_helper.cc + SetMetricsClientId + + ; From chrome_elf/chrome_elf_main.cc + DumpProcessWithoutCrash + GetUserDataDirectoryThunk + SignalChromeElf + SignalInitializeCrashReporting + + ; From chrome/install_static + GetInstallDetailsPayload + + ; From chrome_elf/blacklist/blacklist.cc + AddDllToBlacklist + IsBlacklistInitialized + SuccessfullyBlocked + + ; From chrome_elf/third_party_dlls/logs + DrainLog + RegisterLogNotification
diff --git a/chrome_elf/chrome_elf_x64.def b/chrome_elf/chrome_elf_x64.def index f4b3dfb..a6ccf44 100644 --- a/chrome_elf/chrome_elf_x64.def +++ b/chrome_elf/chrome_elf_x64.def
@@ -5,7 +5,7 @@ EXPORTS ; When functions are added to this file, they must also be added to - ; chrome_elf_x86.def + ; chrome_elf_x86.def and chrome_elf_arm64.def ; From components/crash/content/app/crash_export_stubs.cc CrashForException_ExportThunk
diff --git a/chrome_elf/chrome_elf_x86.def b/chrome_elf/chrome_elf_x86.def index 258af5b..a695720 100644 --- a/chrome_elf/chrome_elf_x86.def +++ b/chrome_elf/chrome_elf_x86.def
@@ -5,7 +5,7 @@ EXPORTS ; When functions are added to this file, they must also be added to - ; chrome_elf_x64.def + ; chrome_elf_x64.def and chrome_elf_arm64.def ; From components/crash/content/app/crash_export_stubs.cc CrashForException_ExportThunk
diff --git a/chromeos/components/proximity_auth/metrics.cc b/chromeos/components/proximity_auth/metrics.cc index c15e71d..4ec3b2d 100644 --- a/chromeos/components/proximity_auth/metrics.cc +++ b/chromeos/components/proximity_auth/metrics.cc
@@ -56,20 +56,6 @@ rolling_rssi); } -void RecordAuthProximityTransmitPowerDelta(int transmit_power_delta) { - if (transmit_power_delta != kUnknownProximityValue) - transmit_power_delta = std::min(50, std::max(-100, transmit_power_delta)); - - base::UmaHistogramSparse("EasyUnlock.AuthProximity.TransmitPowerDelta", - transmit_power_delta); -} - -void RecordAuthProximityTimeSinceLastZeroRssi( - base::TimeDelta time_since_last_zero_rssi) { - UMA_HISTOGRAM_TIMES("EasyUnlock.AuthProximity.TimeSinceLastZeroRssi", - time_since_last_zero_rssi); -} - void RecordAuthProximityRemoteDeviceModelHash(const std::string& device_model) { base::UmaHistogramSparse("EasyUnlock.AuthProximity.RemoteDeviceModelHash", HashDeviceModelName(device_model));
diff --git a/chromeos/components/proximity_auth/metrics.h b/chromeos/components/proximity_auth/metrics.h index 2de3043..7f7c732 100644 --- a/chromeos/components/proximity_auth/metrics.h +++ b/chromeos/components/proximity_auth/metrics.h
@@ -31,16 +31,6 @@ // are available. void RecordAuthProximityRollingRssi(int rolling_rssi); -// Records the difference between the transmit power and maximum transmit power, -// upon a successful auth attempt. |transmit_power_delta| should be set to -// |kUnknownProximityValue| if no Tx power readings are available. -void RecordAuthProximityTransmitPowerDelta(int transmit_power_delta); - -// Records the time elapsed since the last zero RSSI value was read, upon a -// successful auth attempt. -void RecordAuthProximityTimeSinceLastZeroRssi( - base::TimeDelta time_since_last_zero_rssi); - // Records the phone model used for a successful auth attempt. The model is // recorded as a 32-bit hash due to the limits of UMA. |device_model| should be // set to |kUnknownDeviceModel| if the device model could not be read.
diff --git a/chromeos/services/assistant/assistant_manager_service_impl.cc b/chromeos/services/assistant/assistant_manager_service_impl.cc index 1b5afb9..5f1b378 100644 --- a/chromeos/services/assistant/assistant_manager_service_impl.cc +++ b/chromeos/services/assistant/assistant_manager_service_impl.cc
@@ -107,7 +107,6 @@ network::NetworkConnectionTracker* network_connection_tracker) : action_module_(std::make_unique<action::CrosActionModule>(this)), main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()), - chromium_api_delegate_(), assistant_settings_manager_( std::make_unique<AssistantSettingsManagerImpl>(this)), display_connection_(std::make_unique<CrosDisplayConnection>(this)), @@ -787,8 +786,6 @@ assistant_manager_internal->SetDisplayConnection(display_connection_.get()); assistant_manager_internal->RegisterActionModule(action_module_.get()); assistant_manager_internal->SetAssistantManagerDelegate(this); - assistant_manager_internal->GetFuchsiaApiHelperOrDie()->SetFuchsiaApiDelegate( - &chromium_api_delegate_); assistant_manager->AddConversationStateListener(this); assistant_manager->AddDeviceStateListener(this);
diff --git a/chromeos/services/assistant/assistant_manager_service_impl.h b/chromeos/services/assistant/assistant_manager_service_impl.h index d2ede69..420fbb1 100644 --- a/chromeos/services/assistant/assistant_manager_service_impl.h +++ b/chromeos/services/assistant/assistant_manager_service_impl.h
@@ -19,7 +19,6 @@ #include "chromeos/assistant/internal/internal_util.h" #include "chromeos/services/assistant/assistant_manager_service.h" #include "chromeos/services/assistant/assistant_settings_manager_impl.h" -#include "chromeos/services/assistant/chromium_api_delegate.h" #include "chromeos/services/assistant/platform_api_impl.h" #include "chromeos/services/assistant/public/mojom/assistant.mojom.h" #include "libassistant/shared/internal_api/assistant_manager_delegate.h" @@ -213,7 +212,6 @@ std::unique_ptr<PlatformApiImpl> platform_api_; std::unique_ptr<action::CrosActionModule> action_module_; scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_; - ChromiumApiDelegate chromium_api_delegate_; std::unique_ptr<assistant_client::AssistantManager> assistant_manager_; std::unique_ptr<AssistantSettingsManagerImpl> assistant_settings_manager_; // same ownership as assistant_manager_.
diff --git a/components/autofill_assistant_strings.grdp b/components/autofill_assistant_strings.grdp index 01f2feb..1a0e36e 100644 --- a/components/autofill_assistant_strings.grdp +++ b/components/autofill_assistant_strings.grdp
@@ -17,7 +17,7 @@ Confirm </message> <message name="IDS_AUTOFILL_ASSISTANT_TERMS" desc="The text for the terms and service acceptance checkbox. Sentence-cased." formatter_data="android_java"> - I know the terms and conditions and accept them (leave unclicked to read the terms and conditions from the website). + I know the terms and conditions, privacy policy and right of withdrawal of <ph name="BEGIN_BOLD"><b></ph><ph name="ORIGIN">%1$s<ex>google.com</ex></ph><ph name="END_BOLD"></b></ph> (leave unchecked to read). </message> </if> </grit-part>
diff --git a/components/cronet/android/BUILD.gn b/components/cronet/android/BUILD.gn index 2ea8f1a..3b00214 100644 --- a/components/cronet/android/BUILD.gn +++ b/components/cronet/android/BUILD.gn
@@ -470,7 +470,6 @@ script = "//components/cronet/tools/generate_proguard_file.py" sources = [ "//base/android/proguard/chromium_code.flags", - "//base/android/proguard/explicit_jni_registration.flags", "//components/cronet/android/cronet_impl_native_proguard.cfg", ] outputs = [
diff --git a/components/domain_reliability/BUILD.gn b/components/domain_reliability/BUILD.gn index 71f0b74..7feac4a 100644 --- a/components/domain_reliability/BUILD.gn +++ b/components/domain_reliability/BUILD.gn
@@ -86,9 +86,6 @@ deps = [ ":bake_in_configs", "//base", - "//components/keyed_service/core", - "//content/public/browser", - "//content/public/common", "//net", "//url", ] @@ -117,8 +114,6 @@ ":domain_reliability", "//base", "//base/test:test_support", - "//content/public/browser", - "//content/test:test_support", "//net:test_support", "//testing/gtest", ]
diff --git a/components/domain_reliability/DEPS b/components/domain_reliability/DEPS index bb465a77..54e5ce0 100644 --- a/components/domain_reliability/DEPS +++ b/components/domain_reliability/DEPS
@@ -4,9 +4,5 @@ include_rules = [ "+net", - "+components/keyed_service/core", - "+content/public/browser", - "+content/public/test", - "+third_party/blink/public", ]
diff --git a/components/domain_reliability/context.cc b/components/domain_reliability/context.cc index b7088e15..7c6217e8 100644 --- a/components/domain_reliability/context.cc +++ b/components/domain_reliability/context.cc
@@ -231,8 +231,8 @@ void DomainReliabilityContext::RemoveOldestBeacon() { DCHECK(!beacons_.empty()); - VLOG(1) << "Beacon queue for " << config().origin << " full; " - << "removing oldest beacon"; + DVLOG(1) << "Beacon queue for " << config().origin << " full; " + << "removing oldest beacon"; beacons_.pop_front();
diff --git a/components/domain_reliability/context_manager.cc b/components/domain_reliability/context_manager.cc index 2290eb4..b1084a3e 100644 --- a/components/domain_reliability/context_manager.cc +++ b/components/domain_reliability/context_manager.cc
@@ -36,8 +36,8 @@ std::string key = origin.host(); if (!contexts_.count(key) && !removed_contexts_.count(key)) { - LOG(WARNING) << "Ignoring NEL header for unknown origin " << origin.spec() - << "."; + DLOG(WARNING) << "Ignoring NEL header for unknown origin " << origin.spec() + << "."; return; }
diff --git a/components/domain_reliability/header.cc b/components/domain_reliability/header.cc index 092f90f7..81f19084 100644 --- a/components/domain_reliability/header.cc +++ b/components/domain_reliability/header.cc
@@ -234,7 +234,7 @@ include_subdomains = true; got_include_subdomains = true; } else { - LOG(WARNING) << "Ignoring unknown NEL header directive " << name << "."; + DLOG(WARNING) << "Ignoring unknown NEL header directive " << name << "."; } }
diff --git a/components/domain_reliability/monitor.cc b/components/domain_reliability/monitor.cc index 4a7f2f8..14b2bcf 100644 --- a/components/domain_reliability/monitor.cc +++ b/components/domain_reliability/monitor.cc
@@ -78,7 +78,7 @@ const std::string& upload_reporter_string, const DomainReliabilityContext::UploadAllowedCallback& upload_allowed_callback, - const scoped_refptr<base::SingleThreadTaskRunner>& pref_thread, + const scoped_refptr<base::SingleThreadTaskRunner>& main_thread, const scoped_refptr<base::SingleThreadTaskRunner>& network_thread) : time_(new ActualTime()), upload_reporter_string_(upload_reporter_string), @@ -87,19 +87,19 @@ DomainReliabilityScheduler::Params::GetFromFieldTrialsOrDefaults()), dispatcher_(time_.get()), context_manager_(this), - pref_task_runner_(pref_thread), + main_task_runner_(main_thread), network_task_runner_(network_thread), moved_to_network_thread_(false), discard_uploads_set_(false), weak_factory_(this) { - DCHECK(OnPrefThread()); + DCHECK(OnMainThread()); } DomainReliabilityMonitor::DomainReliabilityMonitor( const std::string& upload_reporter_string, const DomainReliabilityContext::UploadAllowedCallback& upload_allowed_callback, - const scoped_refptr<base::SingleThreadTaskRunner>& pref_thread, + const scoped_refptr<base::SingleThreadTaskRunner>& main_thread, const scoped_refptr<base::SingleThreadTaskRunner>& network_thread, std::unique_ptr<MockableTime> time) : time_(std::move(time)), @@ -109,12 +109,12 @@ DomainReliabilityScheduler::Params::GetFromFieldTrialsOrDefaults()), dispatcher_(time_.get()), context_manager_(this), - pref_task_runner_(pref_thread), + main_task_runner_(main_thread), network_task_runner_(network_thread), moved_to_network_thread_(false), discard_uploads_set_(false), weak_factory_(this) { - DCHECK(OnPrefThread()); + DCHECK(OnMainThread()); } DomainReliabilityMonitor::~DomainReliabilityMonitor() { @@ -122,12 +122,12 @@ net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this); DCHECK(OnNetworkThread()); } else { - DCHECK(OnPrefThread()); + DCHECK(OnMainThread()); } } -void DomainReliabilityMonitor::MoveToNetworkThread() { - DCHECK(OnPrefThread()); +void DomainReliabilityMonitor::InitializeOnNetworkThread() { + DCHECK(OnMainThread()); DCHECK(!moved_to_network_thread_); network_task_runner_->PostTask( @@ -410,9 +410,9 @@ std::string ignored_header_value; if (request.response_info.headers->EnumerateHeader( &iter, kHeaderNameString, &ignored_header_value)) { - LOG(WARNING) << "Request to " << request.url << " had (at least) two " - << kHeaderNameString << " headers: \"" << header_value - << "\" and \"" << ignored_header_value << "\"."; + DLOG(WARNING) << "Request to " << request.url << " had (at least) two " + << kHeaderNameString << " headers: \"" << header_value + << "\" and \"" << ignored_header_value << "\"."; return; } @@ -430,9 +430,9 @@ context_manager_.ClearConfig(origin); break; case DomainReliabilityHeader::PARSE_ERROR: - LOG(WARNING) << "Request to " << request.url << " had invalid " - << kHeaderNameString << " header \"" << header_value - << "\"."; + DLOG(WARNING) << "Request to " << request.url << " had invalid " + << kHeaderNameString << " header \"" << header_value + << "\"."; break; } }
diff --git a/components/domain_reliability/monitor.h b/components/domain_reliability/monitor.h index 512e438..b4cd430 100644 --- a/components/domain_reliability/monitor.h +++ b/components/domain_reliability/monitor.h
@@ -51,14 +51,14 @@ : public net::NetworkChangeNotifier::NetworkChangeObserver, DomainReliabilityContext::Factory { public: - // Creates a Monitor. |local_state_pref_service| must live on |pref_thread| - // (which should be the current thread); |network_thread| is the thread + // Creates a Monitor. |main_thread| is the current thread, which may or may + // not be the same as |network_thread|. |network_thread| is the thread // on which requests will actually be monitored and reported. DomainReliabilityMonitor( const std::string& upload_reporter_string, const DomainReliabilityContext::UploadAllowedCallback& upload_allowed_callback, - const scoped_refptr<base::SingleThreadTaskRunner>& pref_thread, + const scoped_refptr<base::SingleThreadTaskRunner>& main_thread, const scoped_refptr<base::SingleThreadTaskRunner>& network_thread); // Same, but specifies a mock interface for time functions for testing. @@ -66,25 +66,25 @@ const std::string& upload_reporter_string, const DomainReliabilityContext::UploadAllowedCallback& upload_allowed_callback, - const scoped_refptr<base::SingleThreadTaskRunner>& pref_thread, + const scoped_refptr<base::SingleThreadTaskRunner>& main_thread, const scoped_refptr<base::SingleThreadTaskRunner>& network_thread, std::unique_ptr<MockableTime> time); - // Must be called from the pref thread if |MoveToNetworkThread| was not + // Must be called from the main thread if |InitializeOnNetworkThread| was not // called, or from the network thread if it was called. ~DomainReliabilityMonitor() override; // Must be called before |InitURLRequestContext| on the same thread on which // the Monitor was constructed. Moves (most of) the Monitor to the network // thread passed in the constructor. - void MoveToNetworkThread(); + void InitializeOnNetworkThread(); // All public methods below this point must be called on the network thread - // after |MoveToNetworkThread| is called on the pref thread. + // after |InitializeOnNetworkThread| is called on the main thread. // Initializes the Monitor's URLRequestContextGetter. // - // Must be called on the network thread, after |MoveToNetworkThread|. + // Must be called on the network thread, after |InitializeOnNetworkThread|. void InitURLRequestContext(net::URLRequestContext* url_request_context); // Same, but for unittests where the Getter is readily available. @@ -177,8 +177,8 @@ void MaybeHandleHeader(const RequestInfo& info); - bool OnPrefThread() const { - return pref_task_runner_->BelongsToCurrentThread(); + bool OnMainThread() const { + return main_task_runner_->BelongsToCurrentThread(); } bool OnNetworkThread() const { return network_task_runner_->BelongsToCurrentThread(); @@ -195,7 +195,7 @@ std::unique_ptr<DomainReliabilityUploader> uploader_; DomainReliabilityContextManager context_manager_; - scoped_refptr<base::SingleThreadTaskRunner> pref_task_runner_; + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_; bool moved_to_network_thread_;
diff --git a/components/domain_reliability/monitor_unittest.cc b/components/domain_reliability/monitor_unittest.cc index d464ece7..c593723 100644 --- a/components/domain_reliability/monitor_unittest.cc +++ b/components/domain_reliability/monitor_unittest.cc
@@ -54,17 +54,17 @@ typedef DomainReliabilityMonitor::RequestInfo RequestInfo; DomainReliabilityMonitorTest() - : pref_task_runner_(new base::TestSimpleTaskRunner()), + : main_task_runner(new base::TestSimpleTaskRunner()), network_task_runner_(new base::TestSimpleTaskRunner()), url_request_context_getter_( new net::TestURLRequestContextGetter(network_task_runner_)), time_(new MockTime()), monitor_("test-reporter", DomainReliabilityContext::UploadAllowedCallback(), - pref_task_runner_, + main_task_runner, network_task_runner_, std::unique_ptr<MockableTime>(time_)) { - monitor_.MoveToNetworkThread(); + monitor_.InitializeOnNetworkThread(); monitor_.InitURLRequestContext(url_request_context_getter_); monitor_.SetDiscardUploads(false); } @@ -104,7 +104,7 @@ return monitor_.AddContextForTesting(std::move(config)); } - scoped_refptr<base::TestSimpleTaskRunner> pref_task_runner_; + scoped_refptr<base::TestSimpleTaskRunner> main_task_runner; scoped_refptr<base::TestSimpleTaskRunner> network_task_runner_; scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_; MockTime* time_;
diff --git a/components/domain_reliability/service.cc b/components/domain_reliability/service.cc index cf8287f..5288017 100644 --- a/components/domain_reliability/service.cc +++ b/components/domain_reliability/service.cc
@@ -15,11 +15,7 @@ #include "base/threading/thread_task_runner_handle.h" #include "components/domain_reliability/context.h" #include "components/domain_reliability/monitor.h" -#include "content/public/browser/browser_context.h" -#include "content/public/browser/permission_controller.h" -#include "content/public/browser/permission_type.h" #include "net/url_request/url_request_context_getter.h" -#include "third_party/blink/public/platform/modules/permissions/permission_status.mojom.h" #include "url/gurl.h" namespace domain_reliability { @@ -51,11 +47,8 @@ class DomainReliabilityServiceImpl : public DomainReliabilityService { public: explicit DomainReliabilityServiceImpl( - const std::string& upload_reporter_string, - content::BrowserContext* browser_context) - : upload_reporter_string_(upload_reporter_string), - browser_context_(browser_context), - weak_factory_(this) {} + const std::string& upload_reporter_string) + : upload_reporter_string_(upload_reporter_string), weak_factory_(this) {} ~DomainReliabilityServiceImpl() override {} @@ -63,18 +56,15 @@ std::unique_ptr<DomainReliabilityMonitor> CreateMonitor( scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, - scoped_refptr<base::SingleThreadTaskRunner> network_task_runner) - override { + scoped_refptr<base::SingleThreadTaskRunner> network_task_runner, + const DomainReliabilityContext::UploadAllowedCallback& + upload_allowed_callback) override { DCHECK(!network_task_runner_); std::unique_ptr<DomainReliabilityMonitor> monitor( - new DomainReliabilityMonitor( - upload_reporter_string_, - base::Bind( - &DomainReliabilityServiceImpl::CheckUploadAllowedOnIOThread, - weak_factory_.GetWeakPtr(), base::RetainedRef(ui_task_runner), - base::RetainedRef(network_task_runner)), - ui_task_runner, network_task_runner)); + new DomainReliabilityMonitor(upload_reporter_string_, + upload_allowed_callback, ui_task_runner, + network_task_runner)); monitor_ = monitor->MakeWeakPtr(); network_task_runner_ = network_task_runner; @@ -133,36 +123,7 @@ } private: - static void CheckUploadAllowedOnIOThread( - base::WeakPtr<DomainReliabilityServiceImpl> service, - scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, - scoped_refptr<base::SingleThreadTaskRunner> network_task_runner, - const GURL& origin, - base::OnceCallback<void(bool)> callback) { - ui_task_runner->PostTask( - FROM_HERE, - base::BindOnce( - &DomainReliabilityServiceImpl::CheckUploadAllowedOnUIThread, - service, base::RetainedRef(network_task_runner), origin, - std::move(callback))); - } - - void CheckUploadAllowedOnUIThread( - base::SingleThreadTaskRunner* network_task_runner, - const GURL& origin, - base::OnceCallback<void(bool)> callback) { - content::PermissionController* permission_controller = - content::BrowserContext::GetPermissionController(browser_context_); - DCHECK(permission_controller); - bool allowed = permission_controller->GetPermissionStatus( - content::PermissionType::BACKGROUND_SYNC, origin, - origin) == blink::mojom::PermissionStatus::GRANTED; - network_task_runner->PostTask(FROM_HERE, - base::BindOnce(std::move(callback), allowed)); - } - std::string upload_reporter_string_; - content::BrowserContext* browser_context_; base::WeakPtr<DomainReliabilityMonitor> monitor_; scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_; base::WeakPtrFactory<DomainReliabilityServiceImpl> weak_factory_; @@ -170,10 +131,8 @@ // static DomainReliabilityService* DomainReliabilityService::Create( - const std::string& upload_reporter_string, - content::BrowserContext* browser_context) { - return new DomainReliabilityServiceImpl(upload_reporter_string, - browser_context); + const std::string& upload_reporter_string) { + return new DomainReliabilityServiceImpl(upload_reporter_string); } DomainReliabilityService::~DomainReliabilityService() {}
diff --git a/components/domain_reliability/service.h b/components/domain_reliability/service.h index e2ac25d..78f76dda 100644 --- a/components/domain_reliability/service.h +++ b/components/domain_reliability/service.h
@@ -16,7 +16,6 @@ #include "components/domain_reliability/config.h" #include "components/domain_reliability/context.h" #include "components/domain_reliability/domain_reliability_export.h" -#include "components/keyed_service/core/keyed_service.h" class GURL; @@ -24,10 +23,6 @@ class Value; } // namespace base -namespace content { -class BrowserContext; -} // namespace content - namespace net { class URLRequestContextGetter; } // namespace net @@ -36,29 +31,30 @@ class DomainReliabilityMonitor; -// DomainReliabilityService is a KeyedService that manages a Monitor that lives -// on another thread (as provided by the URLRequestContextGetter's task runner) -// and proxies (selected) method calls to it. Destruction of the Monitor (on -// that thread) is the responsibility of the caller. -class DOMAIN_RELIABILITY_EXPORT DomainReliabilityService - : public KeyedService { +// DomainReliabilityService manages a Monitor that (could) live on another +// thread (as provided by the URLRequestContextGetter's task runner) and +// proxies (selected) method calls to it. Destruction of the Monitor (on that +// thread) is the responsibility of the caller. +class DOMAIN_RELIABILITY_EXPORT DomainReliabilityService { public: // Creates a DomainReliabilityService that will contain a Monitor with the // given upload reporter string. static DomainReliabilityService* Create( - const std::string& upload_reporter_string, - content::BrowserContext* browser_context); + const std::string& upload_reporter_string); - ~DomainReliabilityService() override; + virtual ~DomainReliabilityService(); // Initializes the Service: given the task runner on which Monitor methods // should be called, creates the Monitor and returns it. Can be called at // most once, and must be called before any of the below methods can be // called. The caller is responsible for destroying the Monitor on the given - // task runner when it is no longer needed. + // task runner when it is no longer needed. |upload_allowed_callback| is + // called on the network thread before every upload to check if it's allowed. virtual std::unique_ptr<DomainReliabilityMonitor> CreateMonitor( scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, - scoped_refptr<base::SingleThreadTaskRunner> network_task_runner) = 0; + scoped_refptr<base::SingleThreadTaskRunner> network_task_runner, + const DomainReliabilityContext::UploadAllowedCallback& + upload_allowed_callback) = 0; // Clears browsing data on the associated Monitor. |Init()| must have been // called first.
diff --git a/components/domain_reliability/service_unittest.cc b/components/domain_reliability/service_unittest.cc index 7ad37b5..3b1512e 100644 --- a/components/domain_reliability/service_unittest.cc +++ b/components/domain_reliability/service_unittest.cc
@@ -8,153 +8,35 @@ #include "base/run_loop.h" #include "base/single_thread_task_runner.h" #include "base/task/post_task.h" +#include "base/test/scoped_task_environment.h" #include "base/test/test_simple_task_runner.h" #include "base/time/time.h" #include "components/domain_reliability/monitor.h" #include "components/domain_reliability/test_util.h" -#include "content/public/browser/browser_task_traits.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/permission_controller.h" -#include "content/public/browser/permission_controller_delegate.h" -#include "content/public/browser/web_contents.h" -#include "content/public/test/test_browser_context.h" -#include "content/public/test/test_browser_thread_bundle.h" -#include "content/public/test/test_utils.h" #include "net/base/host_port_pair.h" #include "net/url_request/url_request_context_getter.h" #include "net/url_request/url_request_test_util.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/blink/public/platform/modules/permissions/permission_status.mojom.h" namespace domain_reliability { -namespace { - -class TestPermissionManager : public content::PermissionControllerDelegate { - public: - TestPermissionManager() : get_permission_status_count_(0) {} - - int get_permission_status_count() const { - return get_permission_status_count_; - } - content::PermissionType last_permission() const { return last_permission_; } - const GURL& last_requesting_origin() const { return last_requesting_origin_; } - const GURL& last_embedding_origin() const { return last_embedding_origin_; } - - void set_permission_status(blink::mojom::PermissionStatus permission_status) { - permission_status_ = permission_status; - } - - // content::PermissionManager: - - ~TestPermissionManager() override {} - - blink::mojom::PermissionStatus GetPermissionStatus( - content::PermissionType permission, - const GURL& requesting_origin, - const GURL& embedding_origin) override { - ++get_permission_status_count_; - - last_permission_ = permission; - last_requesting_origin_ = requesting_origin; - last_embedding_origin_ = embedding_origin; - - return permission_status_; - } - - blink::mojom::PermissionStatus GetPermissionStatusForFrame( - content::PermissionType permission, - content::RenderFrameHost* render_frame_host, - const GURL& requesting_origin) override { - return GetPermissionStatus( - permission, requesting_origin, - content::WebContents::FromRenderFrameHost(render_frame_host) - ->GetLastCommittedURL() - .GetOrigin()); - } - - int RequestPermission( - content::PermissionType permission, - content::RenderFrameHost* render_frame_host, - const GURL& requesting_origin, - bool user_gesture, - const base::Callback<void(blink::mojom::PermissionStatus)>& callback) - override { - NOTIMPLEMENTED(); - return content::PermissionController::kNoPendingOperation; - } - - int RequestPermissions( - const std::vector<content::PermissionType>& permission, - content::RenderFrameHost* render_frame_host, - const GURL& requesting_origin, - bool user_gesture, - const base::Callback< - void(const std::vector<blink::mojom::PermissionStatus>&)>& callback) - override { - NOTIMPLEMENTED(); - return content::PermissionController::kNoPendingOperation; - } - - void ResetPermission(content::PermissionType permission, - const GURL& requesting_origin, - const GURL& embedding_origin) override { - NOTIMPLEMENTED(); - } - - int SubscribePermissionStatusChange( - content::PermissionType permission, - content::RenderFrameHost* render_frame_host, - const GURL& requesting_origin, - const base::Callback<void(blink::mojom::PermissionStatus)>& callback) - override { - NOTIMPLEMENTED(); - return 0; - } - - void UnsubscribePermissionStatusChange(int subscription_id) override { - NOTIMPLEMENTED(); - } - - private: - // Number of calls made to GetPermissionStatus. - int get_permission_status_count_; - - // Parameters to last call to GetPermissionStatus: - - content::PermissionType last_permission_; - GURL last_requesting_origin_; - GURL last_embedding_origin_; - - // Value to return from GetPermissionStatus. - blink::mojom::PermissionStatus permission_status_; - - DISALLOW_COPY_AND_ASSIGN(TestPermissionManager); -}; - -} // namespace class DomainReliabilityServiceTest : public testing::Test { protected: using RequestInfo = DomainReliabilityMonitor::RequestInfo; - DomainReliabilityServiceTest() - : upload_reporter_string_("test"), - permission_manager_(new TestPermissionManager()) { - scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner = - base::CreateSingleThreadTaskRunnerWithTraits( - {content::BrowserThread::UI}); - scoped_refptr<base::SingleThreadTaskRunner> network_task_runner = - base::CreateSingleThreadTaskRunnerWithTraits( - {content::BrowserThread::IO}); - url_request_context_getter_ = - new net::TestURLRequestContextGetter(network_task_runner); - browser_context_.SetPermissionControllerDelegate( - base::WrapUnique(permission_manager_)); - service_ = base::WrapUnique(DomainReliabilityService::Create( - upload_reporter_string_, &browser_context_)); - monitor_ = service_->CreateMonitor(ui_task_runner, network_task_runner); - monitor_->MoveToNetworkThread(); + DomainReliabilityServiceTest() : upload_reporter_string_("test") { + url_request_context_getter_ = new net::TestURLRequestContextGetter( + scoped_task_environment_.GetMainThreadTaskRunner()); + service_ = base::WrapUnique( + DomainReliabilityService::Create(upload_reporter_string_)); + monitor_ = service_->CreateMonitor( + scoped_task_environment_.GetMainThreadTaskRunner(), + scoped_task_environment_.GetMainThreadTaskRunner(), + base::BindRepeating( + &DomainReliabilityServiceTest::CheckDomainReliablityUploadAllowed, + base::Unretained(this))); + monitor_->InitializeOnNetworkThread(); monitor_->InitURLRequestContext(url_request_context_getter_); monitor_->SetDiscardUploads(true); } @@ -172,15 +54,14 @@ return monitor_->uploader_->GetDiscardedUploadCount(); } - content::TestBrowserThreadBundle thread_bundle_; + void set_upload_allowed(bool allowed) { upload_allowed_ = allowed; } + + int upload_check_count() { return upload_check_count_; } + + base::test::ScopedTaskEnvironment scoped_task_environment_; std::string upload_reporter_string_; - content::TestBrowserContext browser_context_; - - // Owned by browser_context_, not the test class. - TestPermissionManager* permission_manager_; - std::unique_ptr<DomainReliabilityService> service_; scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_; @@ -188,6 +69,16 @@ std::unique_ptr<DomainReliabilityMonitor> monitor_; private: + void CheckDomainReliablityUploadAllowed( + const GURL& origin, + base::OnceCallback<void(bool)> callback) { + ++upload_check_count_; + std::move(callback).Run(upload_allowed_); + } + + bool upload_allowed_ = false; + int upload_check_count_ = 0; + DISALLOW_COPY_AND_ASSIGN(DomainReliabilityServiceTest); }; @@ -196,8 +87,7 @@ TEST_F(DomainReliabilityServiceTest, Create) {} TEST_F(DomainReliabilityServiceTest, UploadAllowed) { - permission_manager_->set_permission_status( - blink::mojom::PermissionStatus::GRANTED); + set_upload_allowed(true); monitor_->AddContextForTesting( MakeTestConfigWithOrigin(GURL("https://example/"))); @@ -219,16 +109,13 @@ monitor_->ForceUploadsForTesting(); - content::RunAllPendingInMessageLoop(content::BrowserThread::UI); - EXPECT_EQ(1, permission_manager_->get_permission_status_count()); - - content::RunAllPendingInMessageLoop(content::BrowserThread::IO); + scoped_task_environment_.RunUntilIdle(); + EXPECT_EQ(1, upload_check_count()); EXPECT_EQ(1, GetDiscardedUploadCount()); } TEST_F(DomainReliabilityServiceTest, UploadForbidden) { - permission_manager_->set_permission_status( - blink::mojom::PermissionStatus::DENIED); + set_upload_allowed(false); monitor_->AddContextForTesting( MakeTestConfigWithOrigin(GURL("https://example/"))); @@ -250,16 +137,13 @@ monitor_->ForceUploadsForTesting(); - content::RunAllPendingInMessageLoop(content::BrowserThread::UI); - EXPECT_EQ(1, permission_manager_->get_permission_status_count()); - - content::RunAllPendingInMessageLoop(content::BrowserThread::IO); + scoped_task_environment_.RunUntilIdle(); + EXPECT_EQ(1, upload_check_count()); EXPECT_EQ(0, GetDiscardedUploadCount()); } TEST_F(DomainReliabilityServiceTest, MonitorDestroyedBeforeCheckRuns) { - permission_manager_->set_permission_status( - blink::mojom::PermissionStatus::DENIED); + set_upload_allowed(false); monitor_->AddContextForTesting( MakeTestConfigWithOrigin(GURL("https://example/"))); @@ -284,16 +168,13 @@ monitor_->Shutdown(); monitor_.reset(); - content::RunAllPendingInMessageLoop(content::BrowserThread::UI); - EXPECT_EQ(1, permission_manager_->get_permission_status_count()); - - content::RunAllPendingInMessageLoop(content::BrowserThread::IO); + scoped_task_environment_.RunUntilIdle(); + EXPECT_EQ(1, upload_check_count()); // Makes no sense to check upload count, since monitor was destroyed. } TEST_F(DomainReliabilityServiceTest, MonitorDestroyedBeforeCheckReturns) { - permission_manager_->set_permission_status( - blink::mojom::PermissionStatus::DENIED); + set_upload_allowed(false); monitor_->AddContextForTesting( MakeTestConfigWithOrigin(GURL("https://example/"))); @@ -315,13 +196,13 @@ monitor_->ForceUploadsForTesting(); - content::RunAllPendingInMessageLoop(content::BrowserThread::UI); - EXPECT_EQ(1, permission_manager_->get_permission_status_count()); + scoped_task_environment_.RunUntilIdle(); + EXPECT_EQ(1, upload_check_count()); monitor_->Shutdown(); monitor_.reset(); - content::RunAllPendingInMessageLoop(content::BrowserThread::IO); + scoped_task_environment_.RunUntilIdle(); // Makes no sense to check upload count, since monitor was destroyed. }
diff --git a/components/domain_reliability/uploader.cc b/components/domain_reliability/uploader.cc index 1f109a5..3f7f0687d 100644 --- a/components/domain_reliability/uploader.cc +++ b/components/domain_reliability/uploader.cc
@@ -76,14 +76,14 @@ int max_upload_depth, const GURL& upload_url, const DomainReliabilityUploader::UploadCallback& callback) override { - VLOG(1) << "Uploading report to " << upload_url; - VLOG(2) << "Report JSON: " << report_json; + DVLOG(1) << "Uploading report to " << upload_url; + DVLOG(2) << "Report JSON: " << report_json; if (discard_uploads_) discarded_upload_count_++; if (discard_uploads_ || shutdown_) { - VLOG(1) << "Discarding report instead of uploading."; + DVLOG(1) << "Discarding report instead of uploading."; UploadResult result; result.status = UploadResult::SUCCESS; callback.Run(result); @@ -134,7 +134,7 @@ void SetDiscardUploads(bool discard_uploads) override { discard_uploads_ = discard_uploads; - VLOG(1) << "Setting discard_uploads to " << discard_uploads; + DVLOG(1) << "Setting discard_uploads to " << discard_uploads; } void Shutdown() override { @@ -169,9 +169,9 @@ } } - VLOG(1) << "Upload finished with net error " << net_error - << ", response code " << http_response_code - << ", retry after " << retry_after; + DVLOG(1) << "Upload finished with net error " << net_error + << ", response code " << http_response_code << ", retry after " + << retry_after; base::UmaHistogramSparse("DomainReliability.UploadResponseCode", http_response_code);
diff --git a/components/exo/keyboard_delegate.h b/components/exo/keyboard_delegate.h index 3d7d6941..f918ec5f 100644 --- a/components/exo/keyboard_delegate.h +++ b/components/exo/keyboard_delegate.h
@@ -5,6 +5,7 @@ #ifndef COMPONENTS_EXO_KEYBOARD_DELEGATE_H_ #define COMPONENTS_EXO_KEYBOARD_DELEGATE_H_ +#include "base/containers/flat_map.h" #include "base/containers/flat_set.h" #include "base/time/time.h"
diff --git a/components/exo/wayland/BUILD.gn b/components/exo/wayland/BUILD.gn index 86bb3ed..e65f3a5 100644 --- a/components/exo/wayland/BUILD.gn +++ b/components/exo/wayland/BUILD.gn
@@ -37,6 +37,10 @@ "server_util.h", "wayland_input_delegate.cc", "wayland_input_delegate.h", + "wayland_keyboard_delegate.cc", + "wayland_keyboard_delegate.h", + "wayland_pointer_delegate.cc", + "wayland_pointer_delegate.h", "zcr_notification_shell.cc", "zcr_notification_shell.h", "zwp_text_input_manager.cc",
diff --git a/components/exo/wayland/server.cc b/components/exo/wayland/server.cc index 3361faeb..6db47b2 100644 --- a/components/exo/wayland/server.cc +++ b/components/exo/wayland/server.cc
@@ -96,6 +96,8 @@ #include "components/exo/touch_stylus_delegate.h" #include "components/exo/wayland/server_util.h" #include "components/exo/wayland/wayland_input_delegate.h" +#include "components/exo/wayland/wayland_keyboard_delegate.h" +#include "components/exo/wayland/wayland_pointer_delegate.h" #include "components/exo/wayland/zcr_notification_shell.h" #include "components/exo/wayland/zwp_text_input_manager.h" #include "components/exo/wm_helper.h" @@ -3559,133 +3561,6 @@ //////////////////////////////////////////////////////////////////////////////// // wl_pointer_interface: -// Pointer delegate class that accepts events for surfaces owned by the same -// client as a pointer resource. -class WaylandPointerDelegate : public WaylandInputDelegate, - public PointerDelegate { - public: - explicit WaylandPointerDelegate(wl_resource* pointer_resource) - : pointer_resource_(pointer_resource) {} - - // Overridden from PointerDelegate: - void OnPointerDestroying(Pointer* pointer) override { delete this; } - bool CanAcceptPointerEventsForSurface(Surface* surface) const override { - wl_resource* surface_resource = GetSurfaceResource(surface); - // We can accept events for this surface if the client is the same as the - // pointer. - return surface_resource && - wl_resource_get_client(surface_resource) == client(); - } - void OnPointerEnter(Surface* surface, - const gfx::PointF& location, - int button_flags) override { - wl_resource* surface_resource = GetSurfaceResource(surface); - DCHECK(surface_resource); - // Should we be sending button events to the client before the enter event - // if client's pressed button state is different from |button_flags|? - wl_pointer_send_enter(pointer_resource_, next_serial(), surface_resource, - wl_fixed_from_double(location.x()), - wl_fixed_from_double(location.y())); - } - void OnPointerLeave(Surface* surface) override { - wl_resource* surface_resource = GetSurfaceResource(surface); - DCHECK(surface_resource); - wl_pointer_send_leave(pointer_resource_, next_serial(), surface_resource); - } - void OnPointerMotion(base::TimeTicks time_stamp, - const gfx::PointF& location) override { - SendTimestamp(time_stamp); - wl_pointer_send_motion( - pointer_resource_, TimeTicksToMilliseconds(time_stamp), - wl_fixed_from_double(location.x()), wl_fixed_from_double(location.y())); - } - void OnPointerButton(base::TimeTicks time_stamp, - int button_flags, - bool pressed) override { - struct { - ui::EventFlags flag; - uint32_t value; - } buttons[] = { - {ui::EF_LEFT_MOUSE_BUTTON, BTN_LEFT}, - {ui::EF_RIGHT_MOUSE_BUTTON, BTN_RIGHT}, - {ui::EF_MIDDLE_MOUSE_BUTTON, BTN_MIDDLE}, - {ui::EF_FORWARD_MOUSE_BUTTON, BTN_FORWARD}, - {ui::EF_BACK_MOUSE_BUTTON, BTN_BACK}, - }; - uint32_t serial = next_serial(); - for (auto button : buttons) { - if (button_flags & button.flag) { - SendTimestamp(time_stamp); - wl_pointer_send_button( - pointer_resource_, serial, TimeTicksToMilliseconds(time_stamp), - button.value, pressed ? WL_POINTER_BUTTON_STATE_PRESSED - : WL_POINTER_BUTTON_STATE_RELEASED); - } - } - } - void OnPointerScroll(base::TimeTicks time_stamp, - const gfx::Vector2dF& offset, - bool discrete) override { - // Same as Weston, the reference compositor. - const double kAxisStepDistance = 10.0 / ui::MouseWheelEvent::kWheelDelta; - - if (wl_resource_get_version(pointer_resource_) >= - WL_POINTER_AXIS_SOURCE_SINCE_VERSION) { - int32_t axis_source = discrete ? WL_POINTER_AXIS_SOURCE_WHEEL - : WL_POINTER_AXIS_SOURCE_FINGER; - wl_pointer_send_axis_source(pointer_resource_, axis_source); - } - - double x_value = offset.x() * kAxisStepDistance; - SendTimestamp(time_stamp); - wl_pointer_send_axis(pointer_resource_, TimeTicksToMilliseconds(time_stamp), - WL_POINTER_AXIS_HORIZONTAL_SCROLL, - wl_fixed_from_double(-x_value)); - - double y_value = offset.y() * kAxisStepDistance; - SendTimestamp(time_stamp); - wl_pointer_send_axis(pointer_resource_, TimeTicksToMilliseconds(time_stamp), - WL_POINTER_AXIS_VERTICAL_SCROLL, - wl_fixed_from_double(-y_value)); - } - void OnPointerScrollStop(base::TimeTicks time_stamp) override { - if (wl_resource_get_version(pointer_resource_) >= - WL_POINTER_AXIS_STOP_SINCE_VERSION) { - SendTimestamp(time_stamp); - wl_pointer_send_axis_stop(pointer_resource_, - TimeTicksToMilliseconds(time_stamp), - WL_POINTER_AXIS_HORIZONTAL_SCROLL); - SendTimestamp(time_stamp); - wl_pointer_send_axis_stop(pointer_resource_, - TimeTicksToMilliseconds(time_stamp), - WL_POINTER_AXIS_VERTICAL_SCROLL); - } - } - void OnPointerFrame() override { - if (wl_resource_get_version(pointer_resource_) >= - WL_POINTER_FRAME_SINCE_VERSION) { - wl_pointer_send_frame(pointer_resource_); - } - wl_client_flush(client()); - } - - private: - // The client who own this pointer instance. - wl_client* client() const { - return wl_resource_get_client(pointer_resource_); - } - - // Returns the next serial to use for pointer events. - uint32_t next_serial() const { - return wl_display_next_serial(wl_client_get_display(client())); - } - - // The pointer resource associated with the pointer. - wl_resource* const pointer_resource_; - - DISALLOW_COPY_AND_ASSIGN(WaylandPointerDelegate); -}; - void pointer_set_cursor(wl_client* client, wl_resource* resource, uint32_t serial, @@ -3708,195 +3583,6 @@ //////////////////////////////////////////////////////////////////////////////// // wl_keyboard_interface: -// Keyboard delegate class that accepts events for surfaces owned by the same -// client as a keyboard resource. -class WaylandKeyboardDelegate : public WaylandInputDelegate, - public KeyboardDelegate, - public KeyboardObserver -#if defined(OS_CHROMEOS) - , - public ash::ImeController::Observer -#endif -{ -#if BUILDFLAG(USE_XKBCOMMON) - public: - explicit WaylandKeyboardDelegate(wl_resource* keyboard_resource) - : keyboard_resource_(keyboard_resource), - xkb_context_(xkb_context_new(XKB_CONTEXT_NO_FLAGS)) { -#if defined(OS_CHROMEOS) - ash::ImeController* ime_controller = ash::Shell::Get()->ime_controller(); - ime_controller->AddObserver(this); - SendNamedLayout(ime_controller->keyboard_layout_name()); -#else - SendLayout(nullptr); -#endif - } -#if defined(OS_CHROMEOS) - ~WaylandKeyboardDelegate() override { - ash::Shell::Get()->ime_controller()->RemoveObserver(this); - } -#endif - - // Overridden from KeyboardDelegate: - void OnKeyboardDestroying(Keyboard* keyboard) override { delete this; } - bool CanAcceptKeyboardEventsForSurface(Surface* surface) const override { - wl_resource* surface_resource = GetSurfaceResource(surface); - // We can accept events for this surface if the client is the same as the - // keyboard. - return surface_resource && - wl_resource_get_client(surface_resource) == client(); - } - void OnKeyboardEnter( - Surface* surface, - const base::flat_map<ui::DomCode, ui::DomCode>& pressed_keys) override { - wl_resource* surface_resource = GetSurfaceResource(surface); - DCHECK(surface_resource); - wl_array keys; - wl_array_init(&keys); - for (const auto& entry : pressed_keys) { - uint32_t* value = - static_cast<uint32_t*>(wl_array_add(&keys, sizeof(uint32_t))); - DCHECK(value); - *value = DomCodeToKey(entry.second); - } - wl_keyboard_send_enter(keyboard_resource_, next_serial(), surface_resource, - &keys); - wl_array_release(&keys); - wl_client_flush(client()); - } - void OnKeyboardLeave(Surface* surface) override { - wl_resource* surface_resource = GetSurfaceResource(surface); - DCHECK(surface_resource); - wl_keyboard_send_leave(keyboard_resource_, next_serial(), surface_resource); - wl_client_flush(client()); - } - uint32_t OnKeyboardKey(base::TimeTicks time_stamp, - ui::DomCode key, - bool pressed) override { - uint32_t serial = next_serial(); - SendTimestamp(time_stamp); - wl_keyboard_send_key(keyboard_resource_, serial, - TimeTicksToMilliseconds(time_stamp), DomCodeToKey(key), - pressed ? WL_KEYBOARD_KEY_STATE_PRESSED - : WL_KEYBOARD_KEY_STATE_RELEASED); - wl_client_flush(client()); - return serial; - } - void OnKeyboardModifiers(int modifier_flags) override { - xkb_state_update_mask(xkb_state_.get(), - ModifierFlagsToXkbModifiers(modifier_flags), 0, 0, 0, - 0, 0); - wl_keyboard_send_modifiers( - keyboard_resource_, next_serial(), - xkb_state_serialize_mods(xkb_state_.get(), XKB_STATE_MODS_DEPRESSED), - xkb_state_serialize_mods(xkb_state_.get(), XKB_STATE_MODS_LOCKED), - xkb_state_serialize_mods(xkb_state_.get(), XKB_STATE_MODS_LATCHED), - xkb_state_serialize_layout(xkb_state_.get(), - XKB_STATE_LAYOUT_EFFECTIVE)); - wl_client_flush(client()); - } - -#if defined(OS_CHROMEOS) - // Overridden from ImeController::Observer: - void OnCapsLockChanged(bool enabled) override {} - void OnKeyboardLayoutNameChanged(const std::string& layout_name) override { - SendNamedLayout(layout_name); - } -#endif - - private: - // Returns the corresponding key given a dom code. - uint32_t DomCodeToKey(ui::DomCode code) const { - // This assumes KeycodeConverter has been built with evdev/xkb codes. - xkb_keycode_t xkb_keycode = static_cast<xkb_keycode_t>( - ui::KeycodeConverter::DomCodeToNativeKeycode(code)); - - // Keycodes are offset by 8 in Xkb. - DCHECK_GE(xkb_keycode, 8u); - return xkb_keycode - 8; - } - - // Returns a set of Xkb modififers given a set of modifier flags. - uint32_t ModifierFlagsToXkbModifiers(int modifier_flags) { - struct { - ui::EventFlags flag; - const char* xkb_name; - } modifiers[] = { - {ui::EF_SHIFT_DOWN, XKB_MOD_NAME_SHIFT}, - {ui::EF_CONTROL_DOWN, XKB_MOD_NAME_CTRL}, - {ui::EF_ALT_DOWN, XKB_MOD_NAME_ALT}, - {ui::EF_COMMAND_DOWN, XKB_MOD_NAME_LOGO}, - {ui::EF_ALTGR_DOWN, "Mod5"}, - {ui::EF_MOD3_DOWN, "Mod3"}, - {ui::EF_NUM_LOCK_ON, XKB_MOD_NAME_NUM}, - {ui::EF_CAPS_LOCK_ON, XKB_MOD_NAME_CAPS}, - }; - uint32_t xkb_modifiers = 0; - for (auto modifier : modifiers) { - if (modifier_flags & modifier.flag) { - xkb_modifiers |= - 1 << xkb_keymap_mod_get_index(xkb_keymap_.get(), modifier.xkb_name); - } - } - return xkb_modifiers; - } - -#if defined(OS_CHROMEOS) - // Send the named keyboard layout to the client. - void SendNamedLayout(const std::string& layout_name) { - std::string layout_id, layout_variant; - ui::XkbKeyboardLayoutEngine::ParseLayoutName(layout_name, &layout_id, - &layout_variant); - xkb_rule_names names = {.rules = nullptr, - .model = "pc101", - .layout = layout_id.c_str(), - .variant = layout_variant.c_str(), - .options = ""}; - SendLayout(&names); - } -#endif - - // Send the keyboard layout named by XKB rules to the client. - void SendLayout(const xkb_rule_names* names) { - xkb_keymap_.reset(xkb_keymap_new_from_names(xkb_context_.get(), names, - XKB_KEYMAP_COMPILE_NO_FLAGS)); - xkb_state_.reset(xkb_state_new(xkb_keymap_.get())); - std::unique_ptr<char, base::FreeDeleter> keymap_string( - xkb_keymap_get_as_string(xkb_keymap_.get(), XKB_KEYMAP_FORMAT_TEXT_V1)); - DCHECK(keymap_string.get()); - size_t keymap_size = strlen(keymap_string.get()) + 1; - base::SharedMemory shared_keymap; - bool rv = shared_keymap.CreateAndMapAnonymous(keymap_size); - DCHECK(rv); - memcpy(shared_keymap.memory(), keymap_string.get(), keymap_size); - wl_keyboard_send_keymap(keyboard_resource_, - WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, - shared_keymap.handle().GetHandle(), keymap_size); - wl_client_flush(client()); - } - - // The client who own this keyboard instance. - wl_client* client() const { - return wl_resource_get_client(keyboard_resource_); - } - - // Returns the next serial to use for keyboard events. - uint32_t next_serial() const { - return wl_display_next_serial(wl_client_get_display(client())); - } - - // The keyboard resource associated with the keyboard. - wl_resource* const keyboard_resource_; - - // The Xkb state used for the keyboard. - std::unique_ptr<xkb_context, ui::XkbContextDeleter> xkb_context_; - std::unique_ptr<xkb_keymap, ui::XkbKeymapDeleter> xkb_keymap_; - std::unique_ptr<xkb_state, ui::XkbStateDeleter> xkb_state_; - - DISALLOW_COPY_AND_ASSIGN(WaylandKeyboardDelegate); -#endif -}; - #if BUILDFLAG(USE_XKBCOMMON) void keyboard_release(wl_client* client, wl_resource* resource) {
diff --git a/components/exo/wayland/wayland_keyboard_delegate.cc b/components/exo/wayland/wayland_keyboard_delegate.cc new file mode 100644 index 0000000..f0a65de --- /dev/null +++ b/components/exo/wayland/wayland_keyboard_delegate.cc
@@ -0,0 +1,186 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/exo/wayland/wayland_keyboard_delegate.h" + +#include <wayland-server-core.h> +#include <wayland-server-protocol-core.h> + +#include "base/containers/flat_map.h" + +namespace exo { +namespace wayland { + +#if BUILDFLAG(USE_XKBCOMMON) + +WaylandKeyboardDelegate::WaylandKeyboardDelegate(wl_resource* keyboard_resource) + : keyboard_resource_(keyboard_resource), + xkb_context_(xkb_context_new(XKB_CONTEXT_NO_FLAGS)) { +#if defined(OS_CHROMEOS) + ash::ImeController* ime_controller = ash::Shell::Get()->ime_controller(); + ime_controller->AddObserver(this); + SendNamedLayout(ime_controller->keyboard_layout_name()); +#else + SendLayout(nullptr); +#endif +} + +#if defined(OS_CHROMEOS) +WaylandKeyboardDelegate::~WaylandKeyboardDelegate() { + ash::Shell::Get()->ime_controller()->RemoveObserver(this); +} +#endif + +void WaylandKeyboardDelegate::OnKeyboardDestroying(Keyboard* keyboard) { + delete this; +} + +bool WaylandKeyboardDelegate::CanAcceptKeyboardEventsForSurface( + Surface* surface) const { + wl_resource* surface_resource = GetSurfaceResource(surface); + // We can accept events for this surface if the client is the same as the + // keyboard. + return surface_resource && + wl_resource_get_client(surface_resource) == client(); +} + +void WaylandKeyboardDelegate::OnKeyboardEnter( + Surface* surface, + const base::flat_map<ui::DomCode, ui::DomCode>& pressed_keys) { + wl_resource* surface_resource = GetSurfaceResource(surface); + DCHECK(surface_resource); + wl_array keys; + wl_array_init(&keys); + for (const auto& entry : pressed_keys) { + uint32_t* value = + static_cast<uint32_t*>(wl_array_add(&keys, sizeof(uint32_t))); + DCHECK(value); + *value = DomCodeToKey(entry.second); + } + wl_keyboard_send_enter(keyboard_resource_, next_serial(), surface_resource, + &keys); + wl_array_release(&keys); + wl_client_flush(client()); +} + +void WaylandKeyboardDelegate::OnKeyboardLeave(Surface* surface) { + wl_resource* surface_resource = GetSurfaceResource(surface); + DCHECK(surface_resource); + wl_keyboard_send_leave(keyboard_resource_, next_serial(), surface_resource); + wl_client_flush(client()); +} + +uint32_t WaylandKeyboardDelegate::OnKeyboardKey(base::TimeTicks time_stamp, + ui::DomCode key, + bool pressed) { + uint32_t serial = next_serial(); + SendTimestamp(time_stamp); + wl_keyboard_send_key( + keyboard_resource_, serial, TimeTicksToMilliseconds(time_stamp), + DomCodeToKey(key), + pressed ? WL_KEYBOARD_KEY_STATE_PRESSED : WL_KEYBOARD_KEY_STATE_RELEASED); + wl_client_flush(client()); + return serial; +} + +void WaylandKeyboardDelegate::OnKeyboardModifiers(int modifier_flags) { + xkb_state_update_mask(xkb_state_.get(), + ModifierFlagsToXkbModifiers(modifier_flags), 0, 0, 0, 0, + 0); + wl_keyboard_send_modifiers( + keyboard_resource_, next_serial(), + xkb_state_serialize_mods(xkb_state_.get(), XKB_STATE_MODS_DEPRESSED), + xkb_state_serialize_mods(xkb_state_.get(), XKB_STATE_MODS_LOCKED), + xkb_state_serialize_mods(xkb_state_.get(), XKB_STATE_MODS_LATCHED), + xkb_state_serialize_layout(xkb_state_.get(), XKB_STATE_LAYOUT_EFFECTIVE)); + wl_client_flush(client()); +} + +#if defined(OS_CHROMEOS) +void WaylandKeyboardDelegate::OnCapsLockChanged(bool enabled) {} + +void WaylandKeyboardDelegate::OnKeyboardLayoutNameChanged( + const std::string& layout_name) { + SendNamedLayout(layout_name); +} +#endif + +uint32_t WaylandKeyboardDelegate::DomCodeToKey(ui::DomCode code) const { + // This assumes KeycodeConverter has been built with evdev/xkb codes. + xkb_keycode_t xkb_keycode = static_cast<xkb_keycode_t>( + ui::KeycodeConverter::DomCodeToNativeKeycode(code)); + + // Keycodes are offset by 8 in Xkb. + DCHECK_GE(xkb_keycode, 8u); + return xkb_keycode - 8; +} + +uint32_t WaylandKeyboardDelegate::ModifierFlagsToXkbModifiers( + int modifier_flags) { + struct { + ui::EventFlags flag; + const char* xkb_name; + } modifiers[] = { + {ui::EF_SHIFT_DOWN, XKB_MOD_NAME_SHIFT}, + {ui::EF_CONTROL_DOWN, XKB_MOD_NAME_CTRL}, + {ui::EF_ALT_DOWN, XKB_MOD_NAME_ALT}, + {ui::EF_COMMAND_DOWN, XKB_MOD_NAME_LOGO}, + {ui::EF_ALTGR_DOWN, "Mod5"}, + {ui::EF_MOD3_DOWN, "Mod3"}, + {ui::EF_NUM_LOCK_ON, XKB_MOD_NAME_NUM}, + {ui::EF_CAPS_LOCK_ON, XKB_MOD_NAME_CAPS}, + }; + uint32_t xkb_modifiers = 0; + for (auto modifier : modifiers) { + if (modifier_flags & modifier.flag) { + xkb_modifiers |= + 1 << xkb_keymap_mod_get_index(xkb_keymap_.get(), modifier.xkb_name); + } + } + return xkb_modifiers; +} + +#if defined(OS_CHROMEOS) +void WaylandKeyboardDelegate::SendNamedLayout(const std::string& layout_name) { + std::string layout_id, layout_variant; + ui::XkbKeyboardLayoutEngine::ParseLayoutName(layout_name, &layout_id, + &layout_variant); + xkb_rule_names names = {.rules = nullptr, + .model = "pc101", + .layout = layout_id.c_str(), + .variant = layout_variant.c_str(), + .options = ""}; + SendLayout(&names); +} +#endif + +void WaylandKeyboardDelegate::SendLayout(const xkb_rule_names* names) { + xkb_keymap_.reset(xkb_keymap_new_from_names(xkb_context_.get(), names, + XKB_KEYMAP_COMPILE_NO_FLAGS)); + xkb_state_.reset(xkb_state_new(xkb_keymap_.get())); + std::unique_ptr<char, base::FreeDeleter> keymap_string( + xkb_keymap_get_as_string(xkb_keymap_.get(), XKB_KEYMAP_FORMAT_TEXT_V1)); + DCHECK(keymap_string.get()); + size_t keymap_size = strlen(keymap_string.get()) + 1; + base::SharedMemory shared_keymap; + bool rv = shared_keymap.CreateAndMapAnonymous(keymap_size); + DCHECK(rv); + memcpy(shared_keymap.memory(), keymap_string.get(), keymap_size); + wl_keyboard_send_keymap(keyboard_resource_, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, + shared_keymap.handle().GetHandle(), keymap_size); + wl_client_flush(client()); +} + +wl_client* WaylandKeyboardDelegate::client() const { + return wl_resource_get_client(keyboard_resource_); +} + +uint32_t WaylandKeyboardDelegate::next_serial() const { + return wl_display_next_serial(wl_client_get_display(client())); +} + +#endif + +} // namespace wayland +} // namespace exo
diff --git a/components/exo/wayland/wayland_keyboard_delegate.h b/components/exo/wayland/wayland_keyboard_delegate.h new file mode 100644 index 0000000..5ca3084 --- /dev/null +++ b/components/exo/wayland/wayland_keyboard_delegate.h
@@ -0,0 +1,107 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_EXO_WAYLAND_WAYLAND_KEYBOARD_DELEGATE_H_ +#define COMPONENTS_EXO_WAYLAND_WAYLAND_KEYBOARD_DELEGATE_H_ + +#include "base/containers/flat_map.h" +#include "base/macros.h" +#include "build/buildflag.h" +#include "components/exo/keyboard_delegate.h" +#include "components/exo/keyboard_observer.h" +#include "components/exo/wayland/server_util.h" +#include "components/exo/wayland/wayland_input_delegate.h" +#include "ui/base/ui_features.h" +#include "ui/events/keycodes/dom/keycode_converter.h" + +#if defined(OS_CHROMEOS) +#include "ash/ime/ime_controller.h" +#include "ash/shell.h" +#include "ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.h" +#endif + +#if BUILDFLAG(USE_XKBCOMMON) +#include <xkbcommon/xkbcommon.h> +#include "ui/events/keycodes/scoped_xkb.h" // nogncheck +#endif + +struct wl_client; +struct wl_resource; + +namespace exo { +namespace wayland { + +// Keyboard delegate class that accepts events for surfaces owned by the same +// client as a keyboard resource. +class WaylandKeyboardDelegate : public WaylandInputDelegate, + public KeyboardDelegate, + public KeyboardObserver +#if defined(OS_CHROMEOS) + , + public ash::ImeController::Observer +#endif +{ +#if BUILDFLAG(USE_XKBCOMMON) + public: + explicit WaylandKeyboardDelegate(wl_resource* keyboard_resource); + +#if defined(OS_CHROMEOS) + ~WaylandKeyboardDelegate() override; +#endif + + // Overridden from KeyboardDelegate: + void OnKeyboardDestroying(Keyboard* keyboard) override; + bool CanAcceptKeyboardEventsForSurface(Surface* surface) const override; + void OnKeyboardEnter( + Surface* surface, + const base::flat_map<ui::DomCode, ui::DomCode>& pressed_keys) override; + void OnKeyboardLeave(Surface* surface) override; + uint32_t OnKeyboardKey(base::TimeTicks time_stamp, + ui::DomCode key, + bool pressed) override; + void OnKeyboardModifiers(int modifier_flags) override; + +#if defined(OS_CHROMEOS) + // Overridden from ImeController::Observer: + void OnCapsLockChanged(bool enabled) override; + void OnKeyboardLayoutNameChanged(const std::string& layout_name) override; +#endif + + private: + // Returns the corresponding key given a dom code. + uint32_t DomCodeToKey(ui::DomCode code) const; + + // Returns a set of Xkb modififers given a set of modifier flags. + uint32_t ModifierFlagsToXkbModifiers(int modifier_flags); + +#if defined(OS_CHROMEOS) + // Send the named keyboard layout to the client. + void SendNamedLayout(const std::string& layout_name); +#endif + + // Send the keyboard layout named by XKB rules to the client. + void SendLayout(const xkb_rule_names* names); + + // The client who own this keyboard instance. + wl_client* client() const; + + // Returns the next serial to use for keyboard events. + uint32_t next_serial() const; + + // The keyboard resource associated with the keyboard. + wl_resource* const keyboard_resource_; + + // The Xkb state used for the keyboard. + std::unique_ptr<xkb_context, ui::XkbContextDeleter> xkb_context_; + std::unique_ptr<xkb_keymap, ui::XkbKeymapDeleter> xkb_keymap_; + std::unique_ptr<xkb_state, ui::XkbStateDeleter> xkb_state_; + + DISALLOW_COPY_AND_ASSIGN(WaylandKeyboardDelegate); +#endif +}; + +} // namespace wayland +} // namespace exo + +#endif // COMPONENTS_EXO_WAYLAND_WAYLAND_KEYBOARD_DELEGATE_H_
diff --git a/components/exo/wayland/wayland_pointer_delegate.cc b/components/exo/wayland/wayland_pointer_delegate.cc new file mode 100644 index 0000000..686ba9ec0 --- /dev/null +++ b/components/exo/wayland/wayland_pointer_delegate.cc
@@ -0,0 +1,142 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/exo/wayland/wayland_pointer_delegate.h" + +#include <linux/input.h> +#include <wayland-server-core.h> +#include <wayland-server-protocol-core.h> + +#include "components/exo/pointer.h" +#include "components/exo/wayland/server_util.h" +#include "ui/events/event_constants.h" + +namespace exo { +namespace wayland { + +WaylandPointerDelegate::WaylandPointerDelegate(wl_resource* pointer_resource) + : pointer_resource_(pointer_resource) {} + +void WaylandPointerDelegate::OnPointerDestroying(Pointer* pointer) { + delete this; +} + +bool WaylandPointerDelegate::CanAcceptPointerEventsForSurface( + Surface* surface) const { + wl_resource* surface_resource = GetSurfaceResource(surface); + // We can accept events for this surface if the client is the same as the + // pointer. + return surface_resource && + wl_resource_get_client(surface_resource) == client(); +} + +void WaylandPointerDelegate::OnPointerEnter(Surface* surface, + const gfx::PointF& location, + int button_flags) { + wl_resource* surface_resource = GetSurfaceResource(surface); + DCHECK(surface_resource); + // Should we be sending button events to the client before the enter event + // if client's pressed button state is different from |button_flags|? + wl_pointer_send_enter(pointer_resource_, next_serial(), surface_resource, + wl_fixed_from_double(location.x()), + wl_fixed_from_double(location.y())); +} + +void WaylandPointerDelegate::OnPointerLeave(Surface* surface) { + wl_resource* surface_resource = GetSurfaceResource(surface); + DCHECK(surface_resource); + wl_pointer_send_leave(pointer_resource_, next_serial(), surface_resource); +} + +void WaylandPointerDelegate::OnPointerMotion(base::TimeTicks time_stamp, + const gfx::PointF& location) { + SendTimestamp(time_stamp); + wl_pointer_send_motion(pointer_resource_, TimeTicksToMilliseconds(time_stamp), + wl_fixed_from_double(location.x()), + wl_fixed_from_double(location.y())); +} + +void WaylandPointerDelegate::OnPointerButton(base::TimeTicks time_stamp, + int button_flags, + bool pressed) { + struct { + ui::EventFlags flag; + uint32_t value; + } buttons[] = { + {ui::EF_LEFT_MOUSE_BUTTON, BTN_LEFT}, + {ui::EF_RIGHT_MOUSE_BUTTON, BTN_RIGHT}, + {ui::EF_MIDDLE_MOUSE_BUTTON, BTN_MIDDLE}, + {ui::EF_FORWARD_MOUSE_BUTTON, BTN_FORWARD}, + {ui::EF_BACK_MOUSE_BUTTON, BTN_BACK}, + }; + uint32_t serial = next_serial(); + for (auto button : buttons) { + if (button_flags & button.flag) { + SendTimestamp(time_stamp); + wl_pointer_send_button(pointer_resource_, serial, + TimeTicksToMilliseconds(time_stamp), button.value, + pressed ? WL_POINTER_BUTTON_STATE_PRESSED + : WL_POINTER_BUTTON_STATE_RELEASED); + } + } +} + +void WaylandPointerDelegate::OnPointerScroll(base::TimeTicks time_stamp, + const gfx::Vector2dF& offset, + bool discrete) { + // Same as Weston, the reference compositor. + const double kAxisStepDistance = 10.0 / ui::MouseWheelEvent::kWheelDelta; + + if (wl_resource_get_version(pointer_resource_) >= + WL_POINTER_AXIS_SOURCE_SINCE_VERSION) { + int32_t axis_source = + discrete ? WL_POINTER_AXIS_SOURCE_WHEEL : WL_POINTER_AXIS_SOURCE_FINGER; + wl_pointer_send_axis_source(pointer_resource_, axis_source); + } + + double x_value = offset.x() * kAxisStepDistance; + SendTimestamp(time_stamp); + wl_pointer_send_axis(pointer_resource_, TimeTicksToMilliseconds(time_stamp), + WL_POINTER_AXIS_HORIZONTAL_SCROLL, + wl_fixed_from_double(-x_value)); + + double y_value = offset.y() * kAxisStepDistance; + SendTimestamp(time_stamp); + wl_pointer_send_axis(pointer_resource_, TimeTicksToMilliseconds(time_stamp), + WL_POINTER_AXIS_VERTICAL_SCROLL, + wl_fixed_from_double(-y_value)); +} + +void WaylandPointerDelegate::OnPointerScrollStop(base::TimeTicks time_stamp) { + if (wl_resource_get_version(pointer_resource_) >= + WL_POINTER_AXIS_STOP_SINCE_VERSION) { + SendTimestamp(time_stamp); + wl_pointer_send_axis_stop(pointer_resource_, + TimeTicksToMilliseconds(time_stamp), + WL_POINTER_AXIS_HORIZONTAL_SCROLL); + SendTimestamp(time_stamp); + wl_pointer_send_axis_stop(pointer_resource_, + TimeTicksToMilliseconds(time_stamp), + WL_POINTER_AXIS_VERTICAL_SCROLL); + } +} + +void WaylandPointerDelegate::OnPointerFrame() { + if (wl_resource_get_version(pointer_resource_) >= + WL_POINTER_FRAME_SINCE_VERSION) { + wl_pointer_send_frame(pointer_resource_); + } + wl_client_flush(client()); +} + +wl_client* WaylandPointerDelegate::client() const { + return wl_resource_get_client(pointer_resource_); +} + +uint32_t WaylandPointerDelegate::next_serial() const { + return wl_display_next_serial(wl_client_get_display(client())); +} + +} // namespace wayland +} // namespace exo
diff --git a/components/exo/wayland/wayland_pointer_delegate.h b/components/exo/wayland/wayland_pointer_delegate.h new file mode 100644 index 0000000..07d53a979 --- /dev/null +++ b/components/exo/wayland/wayland_pointer_delegate.h
@@ -0,0 +1,58 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_EXO_WAYLAND_WAYLAND_POINTER_DELEGATE_H_ +#define COMPONENTS_EXO_WAYLAND_WAYLAND_POINTER_DELEGATE_H_ + +#include "components/exo/pointer_delegate.h" +#include "components/exo/wayland/wayland_input_delegate.h" + +struct wl_client; +struct wl_resource; + +namespace exo { +namespace wayland { + +// Pointer delegate class that accepts events for surfaces owned by the same +// client as a pointer resource. +class WaylandPointerDelegate : public WaylandInputDelegate, + public PointerDelegate { + public: + explicit WaylandPointerDelegate(wl_resource* pointer_resource); + + // Overridden from PointerDelegate: + void OnPointerDestroying(Pointer* pointer) override; + bool CanAcceptPointerEventsForSurface(Surface* surface) const override; + void OnPointerEnter(Surface* surface, + const gfx::PointF& location, + int button_flags) override; + void OnPointerLeave(Surface* surface) override; + void OnPointerMotion(base::TimeTicks time_stamp, + const gfx::PointF& location) override; + void OnPointerButton(base::TimeTicks time_stamp, + int button_flags, + bool pressed) override; + void OnPointerScroll(base::TimeTicks time_stamp, + const gfx::Vector2dF& offset, + bool discrete) override; + void OnPointerScrollStop(base::TimeTicks time_stamp) override; + void OnPointerFrame() override; + + private: + // The client who own this pointer instance. + wl_client* client() const; + + // Returns the next serial to use for pointer events. + uint32_t next_serial() const; + + // The pointer resource associated with the pointer. + wl_resource* const pointer_resource_; + + DISALLOW_COPY_AND_ASSIGN(WaylandPointerDelegate); +}; + +} // namespace wayland +} // namespace exo + +#endif // COMPONENTS_EXO_WAYLAND_WAYLAND_POINTER_DELEGATE_H_
diff --git a/components/flags_ui/feature_entry.cc b/components/flags_ui/feature_entry.cc index bfda221b..e1d703fc 100644 --- a/components/flags_ui/feature_entry.cc +++ b/components/flags_ui/feature_entry.cc
@@ -6,16 +6,48 @@ #include "base/logging.h" #include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "ui/base/l10n/l10n_util.h" namespace flags_ui { +namespace { + +// WARNING: '@' is also used in the html file. If you update this constant you +// also need to update the html file. +const char kMultiSeparatorChar = '@'; + +} // namespace const char kGenericExperimentChoiceDefault[] = "Default"; const char kGenericExperimentChoiceEnabled[] = "Enabled"; const char kGenericExperimentChoiceDisabled[] = "Disabled"; const char kGenericExperimentChoiceAutomatic[] = "Automatic"; +bool FeatureEntry::InternalNameMatches(const std::string& name) const { + if (!base::StartsWith(name, internal_name, base::CompareCase::SENSITIVE)) + return false; + + const size_t internal_name_length = strlen(internal_name); + switch (type) { + case FeatureEntry::SINGLE_VALUE: + case FeatureEntry::SINGLE_DISABLE_VALUE: + case FeatureEntry::ORIGIN_LIST_VALUE: + return name.size() == internal_name_length; + + case FeatureEntry::MULTI_VALUE: + case FeatureEntry::ENABLE_DISABLE_VALUE: + case FeatureEntry::FEATURE_VALUE: + case FeatureEntry::FEATURE_WITH_PARAMS_VALUE: + // Check that the pattern matches what's produced by NameForOption(). + int index = -1; + return name.size() > internal_name_length + 1 && + name[internal_name_length] == kMultiSeparatorChar && + base::StringToInt(name.substr(internal_name_length + 1), &index) && + index >= 0 && index < num_options; + } +} + std::string FeatureEntry::NameForOption(int index) const { DCHECK(type == FeatureEntry::MULTI_VALUE || type == FeatureEntry::ENABLE_DISABLE_VALUE || @@ -100,9 +132,7 @@ namespace testing { -// WARNING: '@' is also used in the html file. If you update this constant you -// also need to update the html file. -const char kMultiSeparator[] = "@"; +const char kMultiSeparator[] = {kMultiSeparatorChar, '\0'}; } // namespace testing
diff --git a/components/flags_ui/feature_entry.h b/components/flags_ui/feature_entry.h index 15a2610..b93f1fb 100644 --- a/components/flags_ui/feature_entry.h +++ b/components/flags_ui/feature_entry.h
@@ -179,6 +179,11 @@ // FEATURE_WITH_VARIATIONS_VALUE. const char* feature_trial_name; + // Check whether internal |name| matches this FeatureEntry. Depending on the + // type of entry, this compared it to either |internal_name| or the values + // produced by NameForOption(). + bool InternalNameMatches(const std::string& name) const; + // Returns the name used in prefs for the option at the specified |index|. // Only used for types that use |num_options|. std::string NameForOption(int index) const;
diff --git a/components/flags_ui/flags_state.cc b/components/flags_ui/flags_state.cc index 774b38b..fa27d5a5 100644 --- a/components/flags_ui/flags_state.cc +++ b/components/flags_ui/flags_state.cc
@@ -114,24 +114,6 @@ } } -// Adds the internal names for the specified entry to |names|. -void AddInternalName(const FeatureEntry& e, std::set<std::string>* names) { - switch (e.type) { - case FeatureEntry::SINGLE_VALUE: - case FeatureEntry::SINGLE_DISABLE_VALUE: - case FeatureEntry::ORIGIN_LIST_VALUE: - names->insert(e.internal_name); - break; - case FeatureEntry::MULTI_VALUE: - case FeatureEntry::ENABLE_DISABLE_VALUE: - case FeatureEntry::FEATURE_VALUE: - case FeatureEntry::FEATURE_WITH_PARAMS_VALUE: - for (int i = 0; i < e.num_options; ++i) - names->insert(e.NameForOption(i)); - break; - } -} - // Confirms that an entry is valid, used in a DCHECK in // SanitizeList below. bool ValidateFeatureEntry(const FeatureEntry& e) { @@ -782,54 +764,54 @@ command_line->AppendSwitchASCII(switch_name, switch_value); } -void FlagsState::SanitizeList(FlagsStorage* flags_storage) const { - std::set<std::string> known_entries; - for (size_t i = 0; i < num_feature_entries_; ++i) { - DCHECK(ValidateFeatureEntry(feature_entries_[i])); - AddInternalName(feature_entries_[i], &known_entries); +std::set<std::string> FlagsState::SanitizeList( + const std::set<std::string>& enabled_entries, + int platform_mask) const { + std::set<std::string> new_enabled_entries; + + // For each entry in |enabled_entries|, check whether it exists in the list + // of supported features. Remove those that don't. Note: Even though this is + // an O(n^2) search, this is more efficient than creating a set from + // |feature_entries_| first because |feature_entries_| is large and + // |enabled_entries| should generally be small/empty. + const FeatureEntry* features_end = feature_entries_ + num_feature_entries_; + for (const std::string& entry_name : enabled_entries) { + if (features_end != + std::find_if(feature_entries_, features_end, + [entry_name, platform_mask](const FeatureEntry& e) { + DCHECK(ValidateFeatureEntry(e)); + return (e.supported_platforms & platform_mask) && + e.InternalNameMatches(entry_name); + })) { + new_enabled_entries.insert(entry_name); + } } - std::set<std::string> enabled_entries = flags_storage->GetFlags(); - - std::set<std::string> new_enabled_entries = - base::STLSetIntersection<std::set<std::string>>(known_entries, - enabled_entries); - - if (new_enabled_entries != enabled_entries) - flags_storage->SetFlags(new_enabled_entries); + return new_enabled_entries; } void FlagsState::GetSanitizedEnabledFlags(FlagsStorage* flags_storage, std::set<std::string>* result) const { - SanitizeList(flags_storage); - *result = flags_storage->GetFlags(); + std::set<std::string> enabled_entries = flags_storage->GetFlags(); + std::set<std::string> new_enabled_entries = SanitizeList(enabled_entries, -1); + if (new_enabled_entries.size() != enabled_entries.size()) + flags_storage->SetFlags(new_enabled_entries); + result->swap(new_enabled_entries); } void FlagsState::GetSanitizedEnabledFlagsForCurrentPlatform( FlagsStorage* flags_storage, std::set<std::string>* result) const { + // TODO(asvitkine): Consider making GetSanitizedEnabledFlags() do the platform + // filtering by default so that we don't need two calls to SanitizeList(). GetSanitizedEnabledFlags(flags_storage, result); - // Filter out any entries that aren't enabled on the current platform. We - // don't remove these from prefs else syncing to a platform with a different - // set of entries would be lossy. - std::set<std::string> platform_entries; - int current_platform = GetCurrentPlatform(); - for (size_t i = 0; i < num_feature_entries_; ++i) { - const FeatureEntry& entry = feature_entries_[i]; - if (entry.supported_platforms & current_platform) - AddInternalName(entry, &platform_entries); + int platform_mask = GetCurrentPlatform(); #if defined(OS_CHROMEOS) - if (feature_entries_[i].supported_platforms & kOsCrOSOwnerOnly) - AddInternalName(entry, &platform_entries); + platform_mask |= kOsCrOSOwnerOnly; #endif - } - - std::set<std::string> new_enabled_entries = - base::STLSetIntersection<std::set<std::string>>(platform_entries, - *result); - - result->swap(new_enabled_entries); + std::set<std::string> platform_entries = SanitizeList(*result, platform_mask); + result->swap(platform_entries); } void FlagsState::GenerateFlagsToSwitchesMapping(
diff --git a/components/flags_ui/flags_state.h b/components/flags_ui/flags_state.h index 21ad59df5..6ce8321 100644 --- a/components/flags_ui/flags_state.h +++ b/components/flags_ui/flags_state.h
@@ -176,10 +176,15 @@ bool feature_state, base::CommandLine* command_line); - // Removes all entries from prefs::kEnabledLabsExperiments that are unknown, - // to prevent this list to become very long as entries are added and removed. - void SanitizeList(FlagsStorage* flags_storage) const; + // Sanitizes |enabled_entries| to only contain entries that are defined in the + // |feature_entries_| and whose |supported_platforms| matches |platform_mask|. + // Pass -1 to |platform_mask| to not do platform filtering. + std::set<std::string> SanitizeList( + const std::set<std::string>& enabled_entries, + int platform_mask) const; + // Gets sanitized entries from |flags_storage|, filtering out any entries that + // don't exist in |feature_entries_|, and updates |flags_storage|. void GetSanitizedEnabledFlags(FlagsStorage* flags_storage, std::set<std::string>* result) const;
diff --git a/components/metrics/legacy_call_stack_profile_builder.cc b/components/metrics/legacy_call_stack_profile_builder.cc index c5b97a2..6865fc8 100644 --- a/components/metrics/legacy_call_stack_profile_builder.cc +++ b/components/metrics/legacy_call_stack_profile_builder.cc
@@ -162,7 +162,8 @@ LegacyCallStackProfileBuilder::LegacyCallStackProfileBuilder( const CallStackProfileParams& profile_params, base::OnceClosure completed_callback) - : profile_params_(profile_params), + : process_milestones_(0), + profile_params_(profile_params), profile_start_time_(base::TimeTicks::Now()) { completed_callback_ = std::move(completed_callback); } @@ -173,8 +174,7 @@ // The code inside this method must not do anything that could acquire a // mutex, including allocating memory (which includes LOG messages) because // that mutex could be held by a stopped thread, thus resulting in deadlock. - sample_.process_milestones = - base::subtle::NoBarrier_Load(&g_process_milestones); + process_milestones_ = base::subtle::NoBarrier_Load(&g_process_milestones); } void LegacyCallStackProfileBuilder::OnSampleCompleted( @@ -185,12 +185,15 @@ void LegacyCallStackProfileBuilder::OnSampleCompleted( std::vector<base::StackSamplingProfiler::Frame> frames, size_t count) { + Sample sample; + sample.process_milestones = process_milestones_; + // Assemble sample_ from |frames| first. for (const auto& frame : frames) { const base::ModuleCache::Module& module(frame.module); if (!module.is_valid) { - sample_.frames.emplace_back(frame.instruction_pointer, - kUnknownModuleIndex); + sample.frames.emplace_back(frame.instruction_pointer, + kUnknownModuleIndex); continue; } @@ -202,12 +205,12 @@ loc = module_index_.insert(std::make_pair(module.base_address, index)) .first; } - sample_.frames.emplace_back(frame.instruction_pointer, loc->second); + sample.frames.emplace_back(frame.instruction_pointer, loc->second); } - // Write CallStackProfile::Sample protocol buffer message based on sample_. + // Write CallStackProfile::Sample protocol buffer message based on sample. int existing_sample_index = -1; - auto location = sample_index_.find(sample_); + auto location = sample_index_.find(sample); if (location != sample_index_.end()) existing_sample_index = location->second; @@ -220,17 +223,15 @@ CallStackProfile::Sample* sample_proto = proto_profile_.add_deprecated_sample(); - CopySampleToProto(sample_, modules_, sample_proto); + CopySampleToProto(sample, modules_, sample_proto); sample_proto->set_count(count); - CopyAnnotationsToProto(sample_.process_milestones & ~milestones_, + CopyAnnotationsToProto(sample.process_milestones & ~milestones_, sample_proto); - milestones_ = sample_.process_milestones; + milestones_ = sample.process_milestones; sample_index_.insert(std::make_pair( - std::move(sample_), + std::move(sample), static_cast<int>(proto_profile_.deprecated_sample_size()) - 1)); - - sample_ = Sample(); } // Build a SampledProfile in the protocol buffer message format from the
diff --git a/components/metrics/legacy_call_stack_profile_builder.h b/components/metrics/legacy_call_stack_profile_builder.h index ef0dc3e..d8dee43 100644 --- a/components/metrics/legacy_call_stack_profile_builder.h +++ b/components/metrics/legacy_call_stack_profile_builder.h
@@ -132,8 +132,8 @@ // The collected stack samples in proto buffer message format. CallStackProfile proto_profile_; - // The current sample being recorded. - Sample sample_; + // The process milestones to use for the next sample. + uint32_t process_milestones_; // The indexes of samples, indexed by the sample. std::map<Sample, int> sample_index_;
diff --git a/components/metrics/legacy_call_stack_profile_builder_unittest.cc b/components/metrics/legacy_call_stack_profile_builder_unittest.cc index d47cbc8..2415693 100644 --- a/components/metrics/legacy_call_stack_profile_builder_unittest.cc +++ b/components/metrics/legacy_call_stack_profile_builder_unittest.cc
@@ -218,6 +218,7 @@ ASSERT_TRUE(proto.has_call_stack_profile()); ASSERT_EQ(1, proto.call_stack_profile().deprecated_sample_size()); ASSERT_EQ(43, proto.call_stack_profile().deprecated_sample(0).count()); + EXPECT_EQ(2, proto.call_stack_profile().deprecated_sample(0).frame_size()); } TEST(LegacyCallStackProfileBuilderTest, SamplesNotDeduped) { @@ -263,6 +264,65 @@ ASSERT_TRUE(proto.has_call_stack_profile()); ASSERT_EQ(2, proto.call_stack_profile().deprecated_sample_size()); + EXPECT_EQ(2, proto.call_stack_profile().deprecated_sample(0).frame_size()); + EXPECT_EQ(2, proto.call_stack_profile().deprecated_sample(1).frame_size()); +} + +TEST(LegacyCallStackProfileBuilderTest, SamplesDedupedAndNotDeduped) { + auto profile_builder = + std::make_unique<TestingLegacyCallStackProfileBuilder>(kProfileParams); + +#if defined(OS_WIN) + base::FilePath module_path(L"c:\\some\\path\\to\\chrome.exe"); +#else + base::FilePath module_path("/some/path/to/chrome"); +#endif + + const uintptr_t module_base_address1 = 0x1000; + Module module1 = {module_base_address1, "1", module_path}; + Frame frame1 = {module_base_address1 + 0x10, module1}; + + const uintptr_t module_base_address2 = 0x1100; + Module module2 = {module_base_address2, "2", module_path}; + Frame frame2 = {module_base_address2 + 0x20, module2}; + + std::vector<Frame> frames1 = {frame1, frame2}; + std::vector<Frame> frames2 = {frame2, frame1}; + + profile_builder->RecordAnnotations(); + profile_builder->OnSampleCompleted(frames1, 42); + + profile_builder->RecordAnnotations(); + profile_builder->OnSampleCompleted(frames1); + + profile_builder->RecordAnnotations(); + profile_builder->OnSampleCompleted(frames2); + + profile_builder->OnProfileCompleted(base::TimeDelta(), base::TimeDelta()); + + const SampledProfile& proto = profile_builder->sampled_profile(); + + EXPECT_TRUE(proto.has_process()); + EXPECT_EQ(BROWSER_PROCESS, proto.process()); + EXPECT_TRUE(proto.has_thread()); + EXPECT_EQ(MAIN_THREAD, proto.thread()); + EXPECT_TRUE(proto.has_trigger_event()); + EXPECT_EQ(SampledProfile::PROCESS_STARTUP, proto.trigger_event()); + + EXPECT_TRUE(proto.has_call_stack_profile()); + ASSERT_EQ(2, proto.call_stack_profile().deprecated_sample_size()); + EXPECT_EQ(43, proto.call_stack_profile().deprecated_sample(0).count()); + ASSERT_EQ(2, proto.call_stack_profile().deprecated_sample(0).frame_size()); + EXPECT_EQ(0x10u, + proto.call_stack_profile().deprecated_sample(0).frame(0).address()); + EXPECT_EQ(0x20u, + proto.call_stack_profile().deprecated_sample(0).frame(1).address()); + ASSERT_EQ(2, proto.call_stack_profile().deprecated_sample(1).frame_size()); + EXPECT_EQ(1, proto.call_stack_profile().deprecated_sample(1).count()); + EXPECT_EQ(0x20u, + proto.call_stack_profile().deprecated_sample(1).frame(0).address()); + EXPECT_EQ(0x10u, + proto.call_stack_profile().deprecated_sample(1).frame(1).address()); } TEST(LegacyCallStackProfileBuilderTest, Modules) {
diff --git a/components/offline_pages/core/background/request_coordinator_stub_taco.cc b/components/offline_pages/core/background/request_coordinator_stub_taco.cc index bfda496..82d545fe 100644 --- a/components/offline_pages/core/background/request_coordinator_stub_taco.cc +++ b/components/offline_pages/core/background/request_coordinator_stub_taco.cc
@@ -88,14 +88,40 @@ } void RequestCoordinatorStubTaco::CreateRequestCoordinator() { - request_coordinator_ = std::make_unique<RequestCoordinator>( + CHECK(!request_coordinator_) + << "CreateRequestCoordinator can be called only once"; + owned_request_coordinator_ = std::make_unique<RequestCoordinator>( std::move(policy_), std::move(offliner_), std::move(queue_), std::move(scheduler_), network_quality_tracker_.get(), std::move(ukm_reporter_), std::move(active_tab_info_)); + request_coordinator_ = owned_request_coordinator_.get(); } RequestCoordinator* RequestCoordinatorStubTaco::request_coordinator() { CHECK(request_coordinator_); - return request_coordinator_.get(); + return request_coordinator_; } + +base::RepeatingCallback<std::unique_ptr<KeyedService>(content::BrowserContext*)> +RequestCoordinatorStubTaco::FactoryFunction() { + return base::BindRepeating( + &RequestCoordinatorStubTaco::InternalFactoryFunction, GetWeakPtr()); +} + +// static +std::unique_ptr<KeyedService> +RequestCoordinatorStubTaco::InternalFactoryFunction( + base::WeakPtr<RequestCoordinatorStubTaco> taco, + content::BrowserContext* context) { + if (!taco) + return nullptr; + // Call CreateRequestCoordinator if it hasn't already been called. + if (!taco->request_coordinator_) { + taco->CreateRequestCoordinator(); + } + // This function can only be used once. + CHECK(taco->owned_request_coordinator_); + return std::move(taco->owned_request_coordinator_); +} + } // namespace offline_pages
diff --git a/components/offline_pages/core/background/request_coordinator_stub_taco.h b/components/offline_pages/core/background/request_coordinator_stub_taco.h index 2ffe37e..d1c0756 100644 --- a/components/offline_pages/core/background/request_coordinator_stub_taco.h +++ b/components/offline_pages/core/background/request_coordinator_stub_taco.h
@@ -14,6 +14,9 @@ #include "components/offline_pages/core/background/request_queue_store.h" #include "components/offline_pages/core/background/scheduler.h" +namespace content { +class BrowserContext; +} namespace network { class NetworkQualityTracker; } @@ -57,7 +60,21 @@ RequestCoordinator* request_coordinator(); + // A factory function that can be used with + // RequestCoordinatorFactory::SetTestingFactoryAndUse. + base::RepeatingCallback< + std::unique_ptr<KeyedService>(content::BrowserContext*)> + FactoryFunction(); + private: + base::WeakPtr<RequestCoordinatorStubTaco> GetWeakPtr() { + return weak_ptr_factory_.GetWeakPtr(); + } + + static std::unique_ptr<KeyedService> InternalFactoryFunction( + base::WeakPtr<RequestCoordinatorStubTaco> taco, + content::BrowserContext*); + bool store_overridden_ = false; bool queue_overridden_ = false; @@ -69,7 +86,12 @@ std::unique_ptr<OfflinePagesUkmReporter> ukm_reporter_; std::unique_ptr<RequestCoordinator::ActiveTabInfo> active_tab_info_; - std::unique_ptr<RequestCoordinator> request_coordinator_; + // This is null if the request coordinator was given to the + // RequestCoordinatorFactory through the factory function. + std::unique_ptr<RequestCoordinator> owned_request_coordinator_; + RequestCoordinator* request_coordinator_ = nullptr; + + base::WeakPtrFactory<RequestCoordinatorStubTaco> weak_ptr_factory_{this}; }; } // namespace offline_pages #endif // COMPONENTS_OFFLINE_PAGES_CORE_BACKGROUND_REQUEST_COORDINATOR_STUB_TACO_H_
diff --git a/components/omnibox/browser/autocomplete_match.cc b/components/omnibox/browser/autocomplete_match.cc index 2d750b2..50a47a9 100644 --- a/components/omnibox/browser/autocomplete_match.cc +++ b/components/omnibox/browser/autocomplete_match.cc
@@ -204,10 +204,8 @@ #if (!defined(OS_ANDROID) || BUILDFLAG(ENABLE_VR)) && !defined(OS_IOS) // static -const gfx::VectorIcon& AutocompleteMatch::TypeToVectorIcon( - Type type, - bool is_bookmark, - DocumentType document_type) { +const gfx::VectorIcon& AutocompleteMatch::TypeToVectorIcon(Type type, + bool is_bookmark) { if (is_bookmark) return omnibox::kBookmarkIcon; @@ -224,23 +222,8 @@ case Type::PHYSICAL_WEB_DEPRECATED: case Type::PHYSICAL_WEB_OVERFLOW_DEPRECATED: case Type::TAB_SEARCH_DEPRECATED: - return omnibox::kPageIcon; - case Type::DOCUMENT_SUGGESTION: - switch (document_type) { - case DocumentType::DRIVE_DOCS: - return omnibox::kDriveDocsIcon; - case DocumentType::DRIVE_FORMS: - return omnibox::kDriveFormsIcon; - case DocumentType::DRIVE_SHEETS: - return omnibox::kDriveSheetsIcon; - case DocumentType::DRIVE_SLIDES: - return omnibox::kDriveSlidesIcon; - case DocumentType::DRIVE_OTHER: - return omnibox::kDriveLogoIcon; - default: - return omnibox::kPageIcon; - } + return omnibox::kPageIcon; case Type::SEARCH_WHAT_YOU_TYPED: case Type::SEARCH_HISTORY: @@ -272,6 +255,33 @@ static const gfx::VectorIcon dummy = {}; return dummy; } + +const gfx::VectorIcon& AutocompleteMatch::GetVectorIcon( + bool is_bookmark) const { + if (is_bookmark) + return omnibox::kBookmarkIcon; + switch (type) { + case Type::DOCUMENT_SUGGESTION: + switch (document_type) { + case DocumentType::DRIVE_DOCS: + return omnibox::kDriveDocsIcon; + case DocumentType::DRIVE_FORMS: + return omnibox::kDriveFormsIcon; + case DocumentType::DRIVE_SHEETS: + return omnibox::kDriveSheetsIcon; + case DocumentType::DRIVE_SLIDES: + return omnibox::kDriveSlidesIcon; + case DocumentType::DRIVE_OTHER: + return omnibox::kDriveLogoIcon; + default: + return omnibox::kPageIcon; + } + case Type::PEDAL: + return (pedal ? pedal->GetVectorIcon() : omnibox::kPedalIcon); + default: + return TypeToVectorIcon(type, is_bookmark); + } +} #endif // static
diff --git a/components/omnibox/browser/autocomplete_match.h b/components/omnibox/browser/autocomplete_match.h index f1e97722..3020d87d 100644 --- a/components/omnibox/browser/autocomplete_match.h +++ b/components/omnibox/browser/autocomplete_match.h
@@ -139,9 +139,12 @@ // Gets the vector icon identifier for the icon to be shown for |type|. If // |is_bookmark| is true, returns a bookmark icon rather than what the type // would determine. - static const gfx::VectorIcon& TypeToVectorIcon(Type type, - bool is_bookmark, - DocumentType document_type); + static const gfx::VectorIcon& TypeToVectorIcon(Type type, bool is_bookmark); + + // Gets the VectorIcon to be shown for a match, which may depend on match + // contents. This is preferable to using TypeToVectorIcon when a match + // instance is available because it can make a more informed choice. + const gfx::VectorIcon& GetVectorIcon(bool is_bookmark) const; #endif // Comparison function for determining when one match is better than another.
diff --git a/components/omnibox/browser/omnibox_pedal.cc b/components/omnibox/browser/omnibox_pedal.cc index 079d5e9..176eac4 100644 --- a/components/omnibox/browser/omnibox_pedal.cc +++ b/components/omnibox/browser/omnibox_pedal.cc
@@ -10,6 +10,10 @@ #include "components/omnibox/browser/omnibox_field_trial.h" #include "ui/base/l10n/l10n_util.h" +#if (!defined(OS_ANDROID) || BUILDFLAG(ENABLE_VR)) && !defined(OS_IOS) +#include "components/omnibox/browser/vector_icons.h" // nogncheck +#endif + OmniboxPedal::LabelStrings::LabelStrings(int id_hint, int id_hint_short, int id_suggestion_contents) @@ -56,6 +60,12 @@ return true; } +#if (!defined(OS_ANDROID) || BUILDFLAG(ENABLE_VR)) && !defined(OS_IOS) +const gfx::VectorIcon& OmniboxPedal::GetVectorIcon() const { + return omnibox::kPedalIcon; +} +#endif + bool OmniboxPedal::IsTriggerMatch(const base::string16& match_text) const { return triggers_.find(match_text) != triggers_.end(); }
diff --git a/components/omnibox/browser/omnibox_pedal.h b/components/omnibox/browser/omnibox_pedal.h index d7d1e81..38db74c2 100644 --- a/components/omnibox/browser/omnibox_pedal.h +++ b/components/omnibox/browser/omnibox_pedal.h
@@ -9,8 +9,16 @@ #include "base/strings/string16.h" #include "base/time/time.h" +#include "build/build_config.h" +#include "components/omnibox/browser/buildflags.h" #include "url/gurl.h" +#if (!defined(OS_ANDROID) || BUILDFLAG(ENABLE_VR)) && !defined(OS_IOS) +namespace gfx { +struct VectorIcon; +} +#endif + class AutocompleteProviderClient; class OmniboxEditController; class OmniboxClient; @@ -86,6 +94,11 @@ // Pedal may not be ready to trigger if no update is available.) virtual bool IsReadyToTrigger(const AutocompleteProviderClient& client) const; +#if (!defined(OS_ANDROID) || BUILDFLAG(ENABLE_VR)) && !defined(OS_IOS) + // Returns the vector icon to represent this Pedal's action in suggestion. + virtual const gfx::VectorIcon& GetVectorIcon() const; +#endif + // Returns true if the preprocessed match suggestion text triggers // presentation of this Pedal. This is not intended for general use, // and only OmniboxPedalProvider should need to call this method.
diff --git a/components/omnibox/browser/omnibox_pedal_implementations.cc b/components/omnibox/browser/omnibox_pedal_implementations.cc index 6440a7f..17e00c0b 100644 --- a/components/omnibox/browser/omnibox_pedal_implementations.cc +++ b/components/omnibox/browser/omnibox_pedal_implementations.cc
@@ -5,11 +5,17 @@ #include "components/omnibox/browser/omnibox_pedal_implementations.h" #include "base/strings/utf_string_conversions.h" +#include "build/build_config.h" #include "components/omnibox/browser/autocomplete_provider_client.h" +#include "components/omnibox/browser/buildflags.h" #include "components/omnibox/browser/omnibox_client.h" #include "components/omnibox/browser/omnibox_pedal.h" #include "components/strings/grit/components_strings.h" +#if (!defined(OS_ANDROID) || BUILDFLAG(ENABLE_VR)) && !defined(OS_IOS) +#include "components/omnibox/browser/vector_icons.h" // nogncheck +#endif + // A small convenience wrapper for the common implementation pattern below. class OmniboxPedalCommon : public OmniboxPedal { public: @@ -56,6 +62,12 @@ "history clear", "history clear chrome", }) {} + +#if (!defined(OS_ANDROID) || BUILDFLAG(ENABLE_VR)) && !defined(OS_IOS) + const gfx::VectorIcon& GetVectorIcon() const override { + return omnibox::kAnswerWhenIsIcon; + } +#endif }; // =============================================================================
diff --git a/components/omnibox/browser/omnibox_popup_model.cc b/components/omnibox/browser/omnibox_popup_model.cc index cd710d1..f7321dc1 100644 --- a/components/omnibox/browser/omnibox_popup_model.cc +++ b/components/omnibox/browser/omnibox_popup_model.cc
@@ -323,8 +323,7 @@ return edit_model_->client()->GetSizedIcon(favicon); } - const auto& vector_icon_type = AutocompleteMatch::TypeToVectorIcon( - match.type, IsStarredMatch(match), match.document_type); + const auto& vector_icon_type = match.GetVectorIcon(IsStarredMatch(match)); return edit_model_->client()->GetSizedIcon(vector_icon_type, vector_icon_color);
diff --git a/components/omnibox/browser/omnibox_view.cc b/components/omnibox/browser/omnibox_view.cc index 35622cc1..bdf248f 100644 --- a/components/omnibox/browser/omnibox_view.cc +++ b/components/omnibox/browser/omnibox_view.cc
@@ -134,8 +134,7 @@ // For tests, model_ will be null. if (!model_) { const gfx::VectorIcon& vector_icon = AutocompleteMatch::TypeToVectorIcon( - AutocompleteMatchType::URL_WHAT_YOU_TYPED, false /*is_bookmark*/, - AutocompleteMatch::DocumentType::NONE); + AutocompleteMatchType::URL_WHAT_YOU_TYPED, /*is_bookmark=*/false); return gfx::CreateVectorIcon(vector_icon, dip_size, color); } @@ -165,8 +164,7 @@ const bool is_bookmarked = bookmark_model && bookmark_model->IsBookmarked(match.destination_url); - const gfx::VectorIcon& vector_icon = AutocompleteMatch::TypeToVectorIcon( - match.type, is_bookmarked, match.document_type); + const gfx::VectorIcon& vector_icon = match.GetVectorIcon(is_bookmarked); return gfx::CreateVectorIcon(vector_icon, dip_size, color); #endif // defined(OS_ANDROID) || defined(OS_IOS) }
diff --git a/components/resources/default_100_percent/autofill/amex.png b/components/resources/default_100_percent/autofill/amex.png index d012783..e999a3d 100644 --- a/components/resources/default_100_percent/autofill/amex.png +++ b/components/resources/default_100_percent/autofill/amex.png Binary files differ
diff --git a/components/resources/default_100_percent/autofill/cc-generic.png b/components/resources/default_100_percent/autofill/cc-generic.png index 68ceaf6..8fab33c 100644 --- a/components/resources/default_100_percent/autofill/cc-generic.png +++ b/components/resources/default_100_percent/autofill/cc-generic.png Binary files differ
diff --git a/components/resources/default_100_percent/autofill/credit_card_cvc_hint_amex.png b/components/resources/default_100_percent/autofill/credit_card_cvc_hint_amex.png index a6df7c5..60f2007e 100644 --- a/components/resources/default_100_percent/autofill/credit_card_cvc_hint_amex.png +++ b/components/resources/default_100_percent/autofill/credit_card_cvc_hint_amex.png Binary files differ
diff --git a/components/resources/default_100_percent/autofill/diners.png b/components/resources/default_100_percent/autofill/diners.png index 3bd2ec4..60749a1f 100644 --- a/components/resources/default_100_percent/autofill/diners.png +++ b/components/resources/default_100_percent/autofill/diners.png Binary files differ
diff --git a/components/resources/default_100_percent/autofill/discover.png b/components/resources/default_100_percent/autofill/discover.png index 9ec9baab..39e98a7 100644 --- a/components/resources/default_100_percent/autofill/discover.png +++ b/components/resources/default_100_percent/autofill/discover.png Binary files differ
diff --git a/components/resources/default_100_percent/autofill/googlepay.png b/components/resources/default_100_percent/autofill/googlepay.png index 4be53902..51e11331 100644 --- a/components/resources/default_100_percent/autofill/googlepay.png +++ b/components/resources/default_100_percent/autofill/googlepay.png Binary files differ
diff --git a/components/resources/default_100_percent/autofill/infobar_autofill_cc.png b/components/resources/default_100_percent/autofill/infobar_autofill_cc.png index b733627..0bf8335 100644 --- a/components/resources/default_100_percent/autofill/infobar_autofill_cc.png +++ b/components/resources/default_100_percent/autofill/infobar_autofill_cc.png Binary files differ
diff --git a/components/resources/default_100_percent/autofill/infobar_autofill_googlepay_with_divider.png b/components/resources/default_100_percent/autofill/infobar_autofill_googlepay_with_divider.png index 3aed9da..c2fd403 100644 --- a/components/resources/default_100_percent/autofill/infobar_autofill_googlepay_with_divider.png +++ b/components/resources/default_100_percent/autofill/infobar_autofill_googlepay_with_divider.png Binary files differ
diff --git a/components/resources/default_100_percent/autofill/mastercard.png b/components/resources/default_100_percent/autofill/mastercard.png index bac5d8c..6672bbf 100644 --- a/components/resources/default_100_percent/autofill/mastercard.png +++ b/components/resources/default_100_percent/autofill/mastercard.png Binary files differ
diff --git a/components/resources/default_100_percent/autofill/migration_header.png b/components/resources/default_100_percent/autofill/migration_header.png index 3500dc24..f72197d7 100644 --- a/components/resources/default_100_percent/autofill/migration_header.png +++ b/components/resources/default_100_percent/autofill/migration_header.png Binary files differ
diff --git a/components/resources/default_100_percent/autofill/mir.png b/components/resources/default_100_percent/autofill/mir.png index 2e094f4..eeb329917 100644 --- a/components/resources/default_100_percent/autofill/mir.png +++ b/components/resources/default_100_percent/autofill/mir.png Binary files differ
diff --git a/components/resources/default_100_percent/autofill/unionpay.png b/components/resources/default_100_percent/autofill/unionpay.png index e0ab343c..e3305c3f 100644 --- a/components/resources/default_100_percent/autofill/unionpay.png +++ b/components/resources/default_100_percent/autofill/unionpay.png Binary files differ
diff --git a/components/resources/default_100_percent/autofill/visa.png b/components/resources/default_100_percent/autofill/visa.png index c7a9d8ee..4191fde 100644 --- a/components/resources/default_100_percent/autofill/visa.png +++ b/components/resources/default_100_percent/autofill/visa.png Binary files differ
diff --git a/components/resources/default_200_percent/autofill/amex.png b/components/resources/default_200_percent/autofill/amex.png index a9749749..985c8dc 100644 --- a/components/resources/default_200_percent/autofill/amex.png +++ b/components/resources/default_200_percent/autofill/amex.png Binary files differ
diff --git a/components/resources/default_200_percent/autofill/cc-generic.png b/components/resources/default_200_percent/autofill/cc-generic.png index 5eab89e..83f5f76 100644 --- a/components/resources/default_200_percent/autofill/cc-generic.png +++ b/components/resources/default_200_percent/autofill/cc-generic.png Binary files differ
diff --git a/components/resources/default_200_percent/autofill/credit_card_cvc_hint.png b/components/resources/default_200_percent/autofill/credit_card_cvc_hint.png index 004e9c4b..1e17dfd 100644 --- a/components/resources/default_200_percent/autofill/credit_card_cvc_hint.png +++ b/components/resources/default_200_percent/autofill/credit_card_cvc_hint.png Binary files differ
diff --git a/components/resources/default_200_percent/autofill/credit_card_cvc_hint_amex.png b/components/resources/default_200_percent/autofill/credit_card_cvc_hint_amex.png index d65dc10..3c28af8 100644 --- a/components/resources/default_200_percent/autofill/credit_card_cvc_hint_amex.png +++ b/components/resources/default_200_percent/autofill/credit_card_cvc_hint_amex.png Binary files differ
diff --git a/components/resources/default_200_percent/autofill/diners.png b/components/resources/default_200_percent/autofill/diners.png index 522f0104c..79478797 100644 --- a/components/resources/default_200_percent/autofill/diners.png +++ b/components/resources/default_200_percent/autofill/diners.png Binary files differ
diff --git a/components/resources/default_200_percent/autofill/elo.png b/components/resources/default_200_percent/autofill/elo.png index ba88605..07f5fb6 100644 --- a/components/resources/default_200_percent/autofill/elo.png +++ b/components/resources/default_200_percent/autofill/elo.png Binary files differ
diff --git a/components/resources/default_200_percent/autofill/googlepay.png b/components/resources/default_200_percent/autofill/googlepay.png index 1a2c438..5cb11e8 100644 --- a/components/resources/default_200_percent/autofill/googlepay.png +++ b/components/resources/default_200_percent/autofill/googlepay.png Binary files differ
diff --git a/components/resources/default_200_percent/autofill/infobar_autofill_cc.png b/components/resources/default_200_percent/autofill/infobar_autofill_cc.png index 6cdb9ce6..18391c4 100644 --- a/components/resources/default_200_percent/autofill/infobar_autofill_cc.png +++ b/components/resources/default_200_percent/autofill/infobar_autofill_cc.png Binary files differ
diff --git a/components/resources/default_200_percent/autofill/infobar_autofill_googlepay_with_divider.png b/components/resources/default_200_percent/autofill/infobar_autofill_googlepay_with_divider.png index 067ceee..23b408d 100644 --- a/components/resources/default_200_percent/autofill/infobar_autofill_googlepay_with_divider.png +++ b/components/resources/default_200_percent/autofill/infobar_autofill_googlepay_with_divider.png Binary files differ
diff --git a/components/resources/default_200_percent/autofill/jcb.png b/components/resources/default_200_percent/autofill/jcb.png index 381c9389..f94e62e 100644 --- a/components/resources/default_200_percent/autofill/jcb.png +++ b/components/resources/default_200_percent/autofill/jcb.png Binary files differ
diff --git a/components/resources/default_200_percent/autofill/mastercard.png b/components/resources/default_200_percent/autofill/mastercard.png index e496711a..9ab8bea4 100644 --- a/components/resources/default_200_percent/autofill/mastercard.png +++ b/components/resources/default_200_percent/autofill/mastercard.png Binary files differ
diff --git a/components/resources/default_200_percent/autofill/migration_header.png b/components/resources/default_200_percent/autofill/migration_header.png index 23ad3369..1749cb5 100644 --- a/components/resources/default_200_percent/autofill/migration_header.png +++ b/components/resources/default_200_percent/autofill/migration_header.png Binary files differ
diff --git a/components/resources/default_200_percent/autofill/mir.png b/components/resources/default_200_percent/autofill/mir.png index 02fc43c..2092b4d 100644 --- a/components/resources/default_200_percent/autofill/mir.png +++ b/components/resources/default_200_percent/autofill/mir.png Binary files differ
diff --git a/components/resources/default_200_percent/autofill/unionpay.png b/components/resources/default_200_percent/autofill/unionpay.png index 78380604..5c8d633 100644 --- a/components/resources/default_200_percent/autofill/unionpay.png +++ b/components/resources/default_200_percent/autofill/unionpay.png Binary files differ
diff --git a/components/resources/default_200_percent/autofill/visa.png b/components/resources/default_200_percent/autofill/visa.png index 08e4015..e464fd6 100644 --- a/components/resources/default_200_percent/autofill/visa.png +++ b/components/resources/default_200_percent/autofill/visa.png Binary files differ
diff --git a/components/resources/default_300_percent/autofill/amex.png b/components/resources/default_300_percent/autofill/amex.png index 48a5a579..c41d6c6 100644 --- a/components/resources/default_300_percent/autofill/amex.png +++ b/components/resources/default_300_percent/autofill/amex.png Binary files differ
diff --git a/components/resources/default_300_percent/autofill/cc-generic.png b/components/resources/default_300_percent/autofill/cc-generic.png index 8861bbc0..15094939 100644 --- a/components/resources/default_300_percent/autofill/cc-generic.png +++ b/components/resources/default_300_percent/autofill/cc-generic.png Binary files differ
diff --git a/components/resources/default_300_percent/autofill/credit_card_cvc_hint.png b/components/resources/default_300_percent/autofill/credit_card_cvc_hint.png index 091974d..3574cb7 100644 --- a/components/resources/default_300_percent/autofill/credit_card_cvc_hint.png +++ b/components/resources/default_300_percent/autofill/credit_card_cvc_hint.png Binary files differ
diff --git a/components/resources/default_300_percent/autofill/credit_card_cvc_hint_amex.png b/components/resources/default_300_percent/autofill/credit_card_cvc_hint_amex.png index 931d8b17..22eae49 100644 --- a/components/resources/default_300_percent/autofill/credit_card_cvc_hint_amex.png +++ b/components/resources/default_300_percent/autofill/credit_card_cvc_hint_amex.png Binary files differ
diff --git a/components/resources/default_300_percent/autofill/diners.png b/components/resources/default_300_percent/autofill/diners.png index ed5aae44..f0451e4 100644 --- a/components/resources/default_300_percent/autofill/diners.png +++ b/components/resources/default_300_percent/autofill/diners.png Binary files differ
diff --git a/components/resources/default_300_percent/autofill/discover.png b/components/resources/default_300_percent/autofill/discover.png index ac4b02b..f221b82c 100644 --- a/components/resources/default_300_percent/autofill/discover.png +++ b/components/resources/default_300_percent/autofill/discover.png Binary files differ
diff --git a/components/resources/default_300_percent/autofill/googlepay.png b/components/resources/default_300_percent/autofill/googlepay.png index add38f1..4c04b3f 100644 --- a/components/resources/default_300_percent/autofill/googlepay.png +++ b/components/resources/default_300_percent/autofill/googlepay.png Binary files differ
diff --git a/components/resources/default_300_percent/autofill/infobar_autofill_cc.png b/components/resources/default_300_percent/autofill/infobar_autofill_cc.png index 870022b3..a58fe5f 100644 --- a/components/resources/default_300_percent/autofill/infobar_autofill_cc.png +++ b/components/resources/default_300_percent/autofill/infobar_autofill_cc.png Binary files differ
diff --git a/components/resources/default_300_percent/autofill/infobar_autofill_googlepay_with_divider.png b/components/resources/default_300_percent/autofill/infobar_autofill_googlepay_with_divider.png index 4f6c9eb6..76afa20 100644 --- a/components/resources/default_300_percent/autofill/infobar_autofill_googlepay_with_divider.png +++ b/components/resources/default_300_percent/autofill/infobar_autofill_googlepay_with_divider.png Binary files differ
diff --git a/components/resources/default_300_percent/autofill/jcb.png b/components/resources/default_300_percent/autofill/jcb.png index 628ca00..913fc0e9 100644 --- a/components/resources/default_300_percent/autofill/jcb.png +++ b/components/resources/default_300_percent/autofill/jcb.png Binary files differ
diff --git a/components/resources/default_300_percent/autofill/mastercard.png b/components/resources/default_300_percent/autofill/mastercard.png index d13be55..e273f35 100644 --- a/components/resources/default_300_percent/autofill/mastercard.png +++ b/components/resources/default_300_percent/autofill/mastercard.png Binary files differ
diff --git a/components/resources/default_300_percent/autofill/migration_header.png b/components/resources/default_300_percent/autofill/migration_header.png index 7cf5e26..ca1d6fa 100644 --- a/components/resources/default_300_percent/autofill/migration_header.png +++ b/components/resources/default_300_percent/autofill/migration_header.png Binary files differ
diff --git a/components/resources/default_300_percent/autofill/mir.png b/components/resources/default_300_percent/autofill/mir.png index cb8a805d..6bf41c0 100644 --- a/components/resources/default_300_percent/autofill/mir.png +++ b/components/resources/default_300_percent/autofill/mir.png Binary files differ
diff --git a/components/resources/default_300_percent/autofill/unionpay.png b/components/resources/default_300_percent/autofill/unionpay.png index 0ac0b38..ad9a889 100644 --- a/components/resources/default_300_percent/autofill/unionpay.png +++ b/components/resources/default_300_percent/autofill/unionpay.png Binary files differ
diff --git a/components/resources/default_300_percent/autofill/visa.png b/components/resources/default_300_percent/autofill/visa.png index fc8ac65..9c2ac18 100644 --- a/components/resources/default_300_percent/autofill/visa.png +++ b/components/resources/default_300_percent/autofill/visa.png Binary files differ
diff --git a/components/safe_browsing/android/safe_browsing_api_handler_bridge.cc b/components/safe_browsing/android/safe_browsing_api_handler_bridge.cc index ecb18aa..633c47b 100644 --- a/components/safe_browsing/android/safe_browsing_api_handler_bridge.cc +++ b/components/safe_browsing/android/safe_browsing_api_handler_bridge.cc
@@ -124,6 +124,9 @@ callback_id)); if (result_status != RESULT_STATUS_SUCCESS) { + CHECK(callback); // Remove after fixing crbug.com/889972 + CHECK(!callback->is_null()); // Remove after fixing crbug.com/889972 + if (result_status == RESULT_STATUS_TIMEOUT) { ReportUmaResult(UMA_STATUS_TIMEOUT); VLOG(1) << "Safe browsing API call timed-out"; @@ -138,10 +141,16 @@ // Shortcut for safe, so we don't have to parse JSON. if (metadata_str == "{}") { + CHECK(callback); // Remove after fixing crbug.com/889972 + CHECK(!callback->is_null()); // Remove after fixing crbug.com/889972 + ReportUmaResult(UMA_STATUS_SAFE); RunCallbackOnIOThread(std::move(callback), SB_THREAT_TYPE_SAFE, ThreatMetadata()); } else { + CHECK(callback); // Remove after fixing crbug.com/889972 + CHECK(!callback->is_null()); // Remove after fixing crbug.com/889972 + // Unsafe, assuming we can parse the JSON. SBThreatType worst_threat; ThreatMetadata threat_metadata;
diff --git a/components/signin/core/browser/signin_metrics.cc b/components/signin/core/browser/signin_metrics.cc index 6526d05..224ae04 100644 --- a/components/signin/core/browser/signin_metrics.cc +++ b/components/signin/core/browser/signin_metrics.cc
@@ -106,10 +106,6 @@ base::RecordAction( base::UserMetricsAction("Signin_Signin_FromTabSwitcher")); break; - case AccessPoint::ACCESS_POINT_FORCE_SIGNIN_WARNING: - base::RecordAction( - base::UserMetricsAction("Signin_Signin_FromForceSigninWarning")); - break; case AccessPoint::ACCESS_POINT_SAVE_CARD_BUBBLE: base::RecordAction( base::UserMetricsAction("Signin_Signin_FromSaveCardBubble")); @@ -189,7 +185,6 @@ case AccessPoint::ACCESS_POINT_AUTOFILL_DROPDOWN: case AccessPoint::ACCESS_POINT_RESIGNIN_INFOBAR: case AccessPoint::ACCESS_POINT_UNKNOWN: - case AccessPoint::ACCESS_POINT_FORCE_SIGNIN_WARNING: case AccessPoint::ACCESS_POINT_MACHINE_LOGON: NOTREACHED() << "Signin_SigninWithDefault_From* user actions" << " are not recorded for access_point " @@ -263,7 +258,6 @@ case AccessPoint::ACCESS_POINT_AUTOFILL_DROPDOWN: case AccessPoint::ACCESS_POINT_RESIGNIN_INFOBAR: case AccessPoint::ACCESS_POINT_UNKNOWN: - case AccessPoint::ACCESS_POINT_FORCE_SIGNIN_WARNING: case AccessPoint::ACCESS_POINT_MACHINE_LOGON: NOTREACHED() << "Signin_SigninNotDefault_From* user actions" << " are not recorded for access point " @@ -337,7 +331,6 @@ case AccessPoint::ACCESS_POINT_AUTOFILL_DROPDOWN: case AccessPoint::ACCESS_POINT_RESIGNIN_INFOBAR: case AccessPoint::ACCESS_POINT_UNKNOWN: - case AccessPoint::ACCESS_POINT_FORCE_SIGNIN_WARNING: case AccessPoint::ACCESS_POINT_MACHINE_LOGON: // These access points do not support personalized sign-in promos, so // |Signin_SigninNewAccountPreDice_From*| user actions should not @@ -422,7 +415,6 @@ case AccessPoint::ACCESS_POINT_AUTOFILL_DROPDOWN: case AccessPoint::ACCESS_POINT_RESIGNIN_INFOBAR: case AccessPoint::ACCESS_POINT_UNKNOWN: - case AccessPoint::ACCESS_POINT_FORCE_SIGNIN_WARNING: case AccessPoint::ACCESS_POINT_MACHINE_LOGON: // These access points do not support personalized sign-in promos, so // |Signin_SigninNewAccountNoExistingAccount_From*| user actions should @@ -503,7 +495,6 @@ case AccessPoint::ACCESS_POINT_AUTOFILL_DROPDOWN: case AccessPoint::ACCESS_POINT_RESIGNIN_INFOBAR: case AccessPoint::ACCESS_POINT_UNKNOWN: - case AccessPoint::ACCESS_POINT_FORCE_SIGNIN_WARNING: case AccessPoint::ACCESS_POINT_MACHINE_LOGON: // These access points do not support personalized sign-in promos, so // |Signin_SigninNewAccountExistingAccount_From*| user actions should not @@ -956,7 +947,6 @@ break; case AccessPoint::ACCESS_POINT_CONTENT_AREA: case AccessPoint::ACCESS_POINT_EXTENSIONS: - case AccessPoint::ACCESS_POINT_FORCE_SIGNIN_WARNING: case AccessPoint::ACCESS_POINT_SUPERVISED_USER: case AccessPoint::ACCESS_POINT_USER_MANAGER: case AccessPoint::ACCESS_POINT_UNKNOWN: @@ -1088,7 +1078,6 @@ case AccessPoint::ACCESS_POINT_AUTOFILL_DROPDOWN: case AccessPoint::ACCESS_POINT_RESIGNIN_INFOBAR: case AccessPoint::ACCESS_POINT_UNKNOWN: - case AccessPoint::ACCESS_POINT_FORCE_SIGNIN_WARNING: case AccessPoint::ACCESS_POINT_MACHINE_LOGON: NOTREACHED() << "Signin_Impression{With|WithNo}Account_From* user actions" << " are not recorded for access point "
diff --git a/components/signin/core/browser/signin_metrics.h b/components/signin/core/browser/signin_metrics.h index 4529276..efd2db2 100644 --- a/components/signin/core/browser/signin_metrics.h +++ b/components/signin/core/browser/signin_metrics.h
@@ -150,7 +150,6 @@ ACCESS_POINT_NTP_CONTENT_SUGGESTIONS, ACCESS_POINT_RESIGNIN_INFOBAR, ACCESS_POINT_TAB_SWITCHER, - ACCESS_POINT_FORCE_SIGNIN_WARNING, ACCESS_POINT_SAVE_CARD_BUBBLE, ACCESS_POINT_MANAGE_CARDS_BUBBLE, ACCESS_POINT_MACHINE_LOGON,
diff --git a/components/signin/core/browser/signin_metrics_unittest.cc b/components/signin/core/browser/signin_metrics_unittest.cc index 7f7e96f..06e3aaae8 100644 --- a/components/signin/core/browser/signin_metrics_unittest.cc +++ b/components/signin/core/browser/signin_metrics_unittest.cc
@@ -100,8 +100,6 @@ return "ReSigninInfobar"; case AccessPoint::ACCESS_POINT_TAB_SWITCHER: return "TabSwitcher"; - case AccessPoint::ACCESS_POINT_FORCE_SIGNIN_WARNING: - return "ForceSigninWarning"; case AccessPoint::ACCESS_POINT_SAVE_CARD_BUBBLE: return "SaveCardBubble"; case AccessPoint::ACCESS_POINT_MANAGE_CARDS_BUBBLE:
diff --git a/components/test/data/update_client/updatecheck_diff_reply_1.xml b/components/test/data/update_client/updatecheck_diff_reply_1.xml deleted file mode 100644 index 093cb02..0000000 --- a/components/test/data/update_client/updatecheck_diff_reply_1.xml +++ /dev/null
@@ -1,15 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<response protocol='3.1'> - <app appid='ihfokbkgjpifnbbojhneepfflplebdkc'> - <updatecheck status='ok'> - <urls> - <url codebase='http://localhost/download/'/> - </urls> - <manifest version='1.0' prodversionmin='11.0.1.0'> - <packages> - <package name='ihfokbkgjpifnbbojhneepfflplebdkc_1.crx' fp='1'/> - </packages> - </manifest> - </updatecheck> - </app> -</response>
diff --git a/components/test/data/update_client/updatecheck_diff_reply_2.xml b/components/test/data/update_client/updatecheck_diff_reply_2.xml deleted file mode 100644 index 8ea2f3b..0000000 --- a/components/test/data/update_client/updatecheck_diff_reply_2.xml +++ /dev/null
@@ -1,16 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<response protocol='3.1'> - <app appid='ihfokbkgjpifnbbojhneepfflplebdkc'> - <updatecheck status='ok'> - <urls> - <url codebase='http://localhost/download/'/> - <url codebasediff='http://localhost/download/'/> - </urls> - <manifest version='2.0' prodversionmin='11.0.1.0'> - <packages> - <package name='ihfokbkgjpifnbbojhneepfflplebdkc_2.crx' namediff='ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx' fp='22'/> - </packages> - </manifest> - </updatecheck> - </app> -</response>
diff --git a/components/test/data/update_client/updatecheck_diff_reply_3.xml b/components/test/data/update_client/updatecheck_diff_reply_3.xml deleted file mode 100644 index faf14b0..0000000 --- a/components/test/data/update_client/updatecheck_diff_reply_3.xml +++ /dev/null
@@ -1,6 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<response protocol='3.1'> - <app appid='ihfokbkgjpifnbbojhneepfflplebdkc'> - <updatecheck status='noupdate'/> - </app> -</response>
diff --git a/components/test/data/update_client/updatecheck_reply_1.json b/components/test/data/update_client/updatecheck_reply_1.json new file mode 100644 index 0000000..c9114dfc --- /dev/null +++ b/components/test/data/update_client/updatecheck_reply_1.json
@@ -0,0 +1,18 @@ +)]}' +{"response":{ + "protocol":"3.1", + "app":[ + {"appid":"jebgalgnebhfojomionfpkfelancnnkf", + "status":"ok", + "updatecheck":{ + "status":"ok", + "urls":{"url":[{"codebase":"http://localhost/download/"}]}, + "actions":{"action":[{"run":"this"}]}, + "manifest":{ + "version":"1.0", + "prodversionmin":"11.0.1.0", + "packages":{"package":[{"name":"jebgalgnebhfojomionfpkfelancnnkf.crx"}]}} + } + } + ] +}}
diff --git a/components/test/data/update_client/updatecheck_reply_2.xml b/components/test/data/update_client/updatecheck_reply_2.xml deleted file mode 100644 index 04b39683..0000000 --- a/components/test/data/update_client/updatecheck_reply_2.xml +++ /dev/null
@@ -1,15 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<response protocol='3.1'> - <app appid='jebgalgnebhfojomionfpkfelancnnkf'> - <updatecheck status='ok'> - <urls> - <url codebase='http://localhost/download/'/> - </urls> - <manifest version='2.0' prodversionmin='55.0.1.0'> - <packages> - <package name='jebgalgnebhfojomionfpkfelancnnkf.crx'/> - </packages> - </manifest> - </updatecheck> - </app> -</response>
diff --git a/components/test/data/update_client/updatecheck_reply_3.xml b/components/test/data/update_client/updatecheck_reply_3.xml deleted file mode 100644 index 819ad10..0000000 --- a/components/test/data/update_client/updatecheck_reply_3.xml +++ /dev/null
@@ -1,6 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?> -<response protocol='3.1'> - <app appid='abagagagagagagagagagagagagagagag'> - <updatecheck status='noupdate'/> - </app> -</response>
diff --git a/components/test/data/update_client/updatecheck_reply_4.json b/components/test/data/update_client/updatecheck_reply_4.json new file mode 100644 index 0000000..38580ab --- /dev/null +++ b/components/test/data/update_client/updatecheck_reply_4.json
@@ -0,0 +1,18 @@ +)]}' +{"response":{ + "protocol":"3.1", + "daystart":{"elapsed_days":3383}, + "app":[ + {"appid":"jebgalgnebhfojomionfpkfelancnnkf", + "status":"ok", + "updatecheck":{ + "status":"ok", + "urls":{"url":[{"codebase":"http://localhost/download/"}]}, + "manifest":{ + "version":"1.0", + "prodversionmin":"11.0.1.0", + "packages":{"package":[{"name":"jebgalgnebhfojomionfpkfelancnnkf.crx"}]}} + } + } + ] +}}
diff --git a/components/test/data/update_client/updatecheck_reply_empty b/components/test/data/update_client/updatecheck_reply_empty deleted file mode 100644 index 0519ecba..0000000 --- a/components/test/data/update_client/updatecheck_reply_empty +++ /dev/null
@@ -1 +0,0 @@ - \ No newline at end of file
diff --git a/components/test/data/update_client/updatecheck_reply_noupdate.json b/components/test/data/update_client/updatecheck_reply_noupdate.json new file mode 100644 index 0000000..d069050a --- /dev/null +++ b/components/test/data/update_client/updatecheck_reply_noupdate.json
@@ -0,0 +1,14 @@ +)]}' +{"response":{ + "protocol":"3.1", + "daystart":{"elapsed_days":3383}, + "app":[ + {"appid":"jebgalgnebhfojomionfpkfelancnnkf", + "status":"ok", + "updatecheck":{ + "status":"noupdate", + "actions":{"action":[{"run":"this"}]} + } + } + ] +}}
diff --git a/components/test/data/update_client/updatecheck_reply_parse_error.json b/components/test/data/update_client/updatecheck_reply_parse_error.json new file mode 100644 index 0000000..82f95fc --- /dev/null +++ b/components/test/data/update_client/updatecheck_reply_parse_error.json
@@ -0,0 +1,7 @@ +)]}' +{"response":{ + "protocol":"3.0", + "app":[ + {"appid":"jebgalgnebhfojomionfpkfelancnnkf"} + ] +}}
diff --git a/components/test/data/update_client/updatecheck_reply_unknownapp.json b/components/test/data/update_client/updatecheck_reply_unknownapp.json new file mode 100644 index 0000000..5f1b522 --- /dev/null +++ b/components/test/data/update_client/updatecheck_reply_unknownapp.json
@@ -0,0 +1,9 @@ +)]}' +{"response":{ + "protocol":"3.1", + "app":[ + {"appid":"jebgalgnebhfojomionfpkfelancnnkf", + "status":"error-unknownApplication" + } + ] +}}
diff --git a/components/update_client/BUILD.gn b/components/update_client/BUILD.gn index 593c0442..20625d5 100644 --- a/components/update_client/BUILD.gn +++ b/components/update_client/BUILD.gn
@@ -36,10 +36,14 @@ "protocol_handler.h", "protocol_parser.cc", "protocol_parser.h", + "protocol_parser_json.cc", + "protocol_parser_json.h", "protocol_parser_xml.cc", "protocol_parser_xml.h", "protocol_serializer.cc", "protocol_serializer.h", + "protocol_serializer_json.cc", + "protocol_serializer_json.h", "protocol_serializer_xml.cc", "protocol_serializer_xml.h", "request_sender.cc", @@ -139,10 +143,15 @@ "//components/test/data/update_client/ihfokbkgjpifnbbojhneepfflplebdkc_2.crx", "//components/test/data/update_client/jebgalgnebhfojomionfpkfelancnnkf.crx", "//components/test/data/update_client/runaction_test_win.crx3", + "//components/test/data/update_client/updatecheck_reply_1.json", "//components/test/data/update_client/updatecheck_reply_1.xml", + "//components/test/data/update_client/updatecheck_reply_4.json", "//components/test/data/update_client/updatecheck_reply_4.xml", + "//components/test/data/update_client/updatecheck_reply_noupdate.json", "//components/test/data/update_client/updatecheck_reply_noupdate.xml", + "//components/test/data/update_client/updatecheck_reply_parse_error.json", "//components/test/data/update_client/updatecheck_reply_parse_error.xml", + "//components/test/data/update_client/updatecheck_reply_unknownapp.json", "//components/test/data/update_client/updatecheck_reply_unknownapp.xml", ] outputs = [ @@ -159,7 +168,9 @@ "component_unpacker_unittest.cc", "persisted_data_unittest.cc", "ping_manager_unittest.cc", + "protocol_parser_json_unittest.cc", "protocol_parser_xml_unittest.cc", + "protocol_serializer_json_unittest.cc", "protocol_serializer_unittest.cc", "protocol_serializer_xml_unittest.cc", "request_sender_unittest.cc",
diff --git a/components/update_client/component.cc b/components/update_client/component.cc index ad999cd..59e50fc 100644 --- a/components/update_client/component.cc +++ b/components/update_client/component.cc
@@ -20,6 +20,7 @@ #include "components/update_client/action_runner.h" #include "components/update_client/component_unpacker.h" #include "components/update_client/configurator.h" +#include "components/update_client/protocol_definition.h" #include "components/update_client/protocol_serializer.h" #include "components/update_client/task_traits.h" #include "components/update_client/update_client.h" @@ -372,15 +373,15 @@ event.SetKey("url", base::Value(dm.url.spec())); // -1 means that the byte counts are not known. - if (dm.total_bytes != -1) - event.SetKey("total", base::Value(base::NumberToString(dm.total_bytes))); - if (dm.downloaded_bytes != -1) { + if (dm.total_bytes != -1 && dm.total_bytes < kProtocolMaxInt) + event.SetKey("total", base::Value(static_cast<double>(dm.total_bytes))); + if (dm.downloaded_bytes != -1 && dm.total_bytes < kProtocolMaxInt) { event.SetKey("downloaded", - base::Value(base::NumberToString(dm.downloaded_bytes))); + base::Value(static_cast<double>(dm.downloaded_bytes))); } - if (dm.download_time_ms) { + if (dm.download_time_ms && dm.total_bytes < kProtocolMaxInt) { event.SetKey("download_time_ms", - base::Value(base::NumberToString(dm.download_time_ms))); + base::Value(static_cast<double>(dm.download_time_ms))); } DCHECK(previous_version().IsValid()); event.SetKey("previousversion", base::Value(previous_version().GetString()));
diff --git a/components/update_client/ping_manager_unittest.cc b/components/update_client/ping_manager_unittest.cc index 503bf2b..e33a755 100644 --- a/components/update_client/ping_manager_unittest.cc +++ b/components/update_client/ping_manager_unittest.cc
@@ -4,18 +4,23 @@ #include "components/update_client/ping_manager.h" +#include <stdint.h> + +#include <limits> #include <memory> #include <string> #include <utility> #include <vector> #include "base/bind.h" +#include "base/json/json_reader.h" #include "base/memory/ref_counted.h" #include "base/run_loop.h" #include "base/test/scoped_task_environment.h" #include "base/threading/thread_task_runner_handle.h" #include "base/version.h" #include "components/update_client/component.h" +#include "components/update_client/protocol_definition.h" #include "components/update_client/protocol_serializer.h" #include "components/update_client/test_configurator.h" #include "components/update_client/update_engine.h" @@ -28,7 +33,8 @@ namespace update_client { -class PingManagerTest : public testing::Test { +class PingManagerTest : public testing::Test, + public testing::WithParamInterface<bool> { public: PingManagerTest(); ~PingManagerTest() override {} @@ -49,6 +55,8 @@ scoped_refptr<TestConfigurator> config_; scoped_refptr<PingManager> ping_manager_; + bool use_JSON_ = false; + int error_ = -1; std::string response_; @@ -64,6 +72,8 @@ } void PingManagerTest::SetUp() { + use_JSON_ = GetParam(); + config_->SetUseJSON(use_JSON_); ping_manager_ = base::MakeRefCounted<PingManager>(config_); } @@ -103,13 +113,16 @@ UpdateEngine::Callback(), nullptr); } -TEST_F(PingManagerTest, SendPing) { +// This test is parameterized for using JSON or XML serialization. |true| means +// JSON serialization is used. +INSTANTIATE_TEST_CASE_P(Parameterized, PingManagerTest, testing::Bool()); + +TEST_P(PingManagerTest, SendPing) { auto interceptor = std::make_unique<URLLoaderPostInterceptor>( config_->test_url_loader_factory()); EXPECT_TRUE(interceptor); const auto update_context = MakeMockUpdateContext(); - { // Test eventresult="1" is sent for successful updates. Component component(*update_context, "abc"); @@ -126,23 +139,60 @@ EXPECT_EQ(1, interceptor->GetCount()) << interceptor->GetRequestsAsString(); const auto msg = interceptor->GetRequestBody(0); - constexpr char regex[] = - R"(<\?xml version="1\.0" encoding="UTF-8"\?>)" - R"(<request protocol="3\.1" )" - R"(dedup="cr" acceptformat="crx2,crx3" extra="foo" )" - R"(sessionid="{[-\w]{36}}" requestid="{[-\w]{36}}" )" - R"(updater="fake_prodid" updaterversion="30\.0" prodversion="30\.0" )" - R"(lang="fake_lang" os="\w+" arch="\w+" nacl_arch="[-\w]+" )" - R"((wow64="1" )?)" - R"(updaterchannel="fake_channel_string" )" - R"(prodchannel="fake_channel_string">)" - R"(<hw physmemory="[0-9]+"/>)" - R"(<os platform="Fake Operating System" arch="[,-.\w]+" )" - R"(version="[-.\w]+"( sp="[\s\w]+")?/>)" - R"(<app appid="abc" version="1\.0">)" - R"(<event eventresult="1" eventtype="3" )" - R"(nextversion="2\.0" previousversion="1\.0"/></app></request>)"; - EXPECT_TRUE(RE2::FullMatch(msg, regex)) << msg; + if (use_JSON_) { + const auto root = base::JSONReader().Read(msg); + const auto* request = root->FindKey("request"); + ASSERT_TRUE(request); + EXPECT_TRUE(request->FindKey("@os")); + EXPECT_EQ("fake_prodid", request->FindKey("@updater")->GetString()); + EXPECT_EQ("crx2,crx3", request->FindKey("acceptformat")->GetString()); + EXPECT_TRUE(request->FindKey("arch")); + EXPECT_EQ("cr", request->FindKey("dedup")->GetString()); + EXPECT_LT(0, request->FindPath({"hw", "physmemory"})->GetInt()); + EXPECT_EQ("fake_lang", request->FindKey("lang")->GetString()); + EXPECT_TRUE(request->FindKey("nacl_arch")); + EXPECT_EQ("fake_channel_string", + request->FindKey("prodchannel")->GetString()); + EXPECT_EQ("30.0", request->FindKey("prodversion")->GetString()); + EXPECT_EQ("3.1", request->FindKey("protocol")->GetString()); + EXPECT_TRUE(request->FindKey("requestid")); + EXPECT_TRUE(request->FindKey("sessionid")); + EXPECT_EQ("fake_channel_string", + request->FindKey("updaterchannel")->GetString()); + EXPECT_EQ("30.0", request->FindKey("updaterversion")->GetString()); + + EXPECT_TRUE(request->FindPath({"os", "arch"})->is_string()); + EXPECT_EQ("Fake Operating System", + request->FindPath({"os", "platform"})->GetString()); + EXPECT_TRUE(request->FindPath({"os", "version"})->is_string()); + + const auto& app = request->FindKey("app")->GetList()[0]; + EXPECT_EQ("abc", app.FindKey("appid")->GetString()); + EXPECT_EQ("1.0", app.FindKey("version")->GetString()); + const auto& event = app.FindKey("event")->GetList()[0]; + EXPECT_EQ(1, event.FindKey("eventresult")->GetInt()); + EXPECT_EQ(3, event.FindKey("eventtype")->GetInt()); + EXPECT_EQ("2.0", event.FindKey("nextversion")->GetString()); + EXPECT_EQ("1.0", event.FindKey("previousversion")->GetString()); + } else { + constexpr char regex[] = + R"(<\?xml version="1\.0" encoding="UTF-8"\?>)" + R"(<request protocol="3\.1" )" + R"(dedup="cr" acceptformat="crx2,crx3" extra="foo" )" + R"(sessionid="{[-\w]{36}}" requestid="{[-\w]{36}}" )" + R"(updater="fake_prodid" updaterversion="30\.0" prodversion="30\.0" )" + R"(lang="fake_lang" os="\w+" arch="\w+" nacl_arch="[-\w]+" )" + R"((wow64="1" )?)" + R"(updaterchannel="fake_channel_string" )" + R"(prodchannel="fake_channel_string">)" + R"(<hw physmemory="[0-9]+"/>)" + R"(<os platform="Fake Operating System" arch="[,-.\w]+" )" + R"(version="[-.\w]+"( sp="[\s\w]+")?/>)" + R"(<app appid="abc" version="1\.0">)" + R"(<event eventresult="1" eventtype="3" )" + R"(nextversion="2\.0" previousversion="1\.0"/></app></request>)"; + EXPECT_TRUE(RE2::FullMatch(msg, regex)) << msg; + } // Check the ping request does not carry the specific extra request headers. const auto headers = std::get<1>(interceptor->GetRequests()[0]); @@ -169,11 +219,24 @@ EXPECT_EQ(1, interceptor->GetCount()) << interceptor->GetRequestsAsString(); const auto msg = interceptor->GetRequestBody(0); - constexpr char regex[] = - R"(<app appid="abc" version="1\.0">)" - R"(<event eventresult="0" eventtype="3" )" - R"(nextversion="2\.0" previousversion="1\.0"/></app>)"; - EXPECT_TRUE(RE2::PartialMatch(msg, regex)) << msg; + if (use_JSON_) { + const auto root = base::JSONReader().Read(msg); + const auto* request = root->FindKey("request"); + const auto& app = request->FindKey("app")->GetList()[0]; + EXPECT_EQ("abc", app.FindKey("appid")->GetString()); + EXPECT_EQ("1.0", app.FindKey("version")->GetString()); + const auto& event = app.FindKey("event")->GetList()[0]; + EXPECT_EQ(0, event.FindKey("eventresult")->GetInt()); + EXPECT_EQ(3, event.FindKey("eventtype")->GetInt()); + EXPECT_EQ("2.0", event.FindKey("nextversion")->GetString()); + EXPECT_EQ("1.0", event.FindKey("previousversion")->GetString()); + } else { + constexpr char regex[] = + R"(<app appid="abc" version="1\.0">)" + R"(<event eventresult="0" eventtype="3" )" + R"(nextversion="2\.0" previousversion="1\.0"/></app>)"; + EXPECT_TRUE(RE2::PartialMatch(msg, regex)) << msg; + } interceptor->Reset(); } @@ -203,14 +266,36 @@ EXPECT_EQ(1, interceptor->GetCount()) << interceptor->GetRequestsAsString(); const auto msg = interceptor->GetRequestBody(0); - constexpr char regex[] = - R"(<app appid="abc" version="1\.0">)" - R"(<event differrorcat="4" differrorcode="20" )" - R"(diffextracode1="-10" diffresult="0" errorcat="1" errorcode="2" )" - R"(eventresult="0" eventtype="3" extracode1="-1" nextfp="next fp" )" - R"(nextversion="2\.0" previousfp="prev fp" previousversion="1\.0"/>)" - R"(</app>)"; - EXPECT_TRUE(RE2::PartialMatch(msg, regex)) << msg; + if (use_JSON_) { + const auto root = base::JSONReader().Read(msg); + const auto* request = root->FindKey("request"); + const auto& app = request->FindKey("app")->GetList()[0]; + EXPECT_EQ("abc", app.FindKey("appid")->GetString()); + EXPECT_EQ("1.0", app.FindKey("version")->GetString()); + const auto& event = app.FindKey("event")->GetList()[0]; + EXPECT_EQ(0, event.FindKey("eventresult")->GetInt()); + EXPECT_EQ(3, event.FindKey("eventtype")->GetInt()); + EXPECT_EQ("2.0", event.FindKey("nextversion")->GetString()); + EXPECT_EQ("1.0", event.FindKey("previousversion")->GetString()); + EXPECT_EQ(4, event.FindKey("differrorcat")->GetInt()); + EXPECT_EQ(20, event.FindKey("differrorcode")->GetInt()); + EXPECT_EQ(-10, event.FindKey("diffextracode1")->GetInt()); + EXPECT_EQ(0, event.FindKey("diffresult")->GetInt()); + EXPECT_EQ(1, event.FindKey("errorcat")->GetInt()); + EXPECT_EQ(2, event.FindKey("errorcode")->GetInt()); + EXPECT_EQ(-1, event.FindKey("extracode1")->GetInt()); + EXPECT_EQ("next fp", event.FindKey("nextfp")->GetString()); + EXPECT_EQ("prev fp", event.FindKey("previousfp")->GetString()); + } else { + constexpr char regex[] = + R"(<app appid="abc" version="1\.0">)" + R"(<event differrorcat="4" differrorcode="20" )" + R"(diffextracode1="-10" diffresult="0" errorcat="1" errorcode="2" )" + R"(eventresult="0" eventtype="3" extracode1="-1" nextfp="next fp" )" + R"(nextversion="2\.0" previousfp="prev fp" previousversion="1\.0"/>)" + R"(</app>)"; + EXPECT_TRUE(RE2::PartialMatch(msg, regex)) << msg; + } interceptor->Reset(); } @@ -231,11 +316,23 @@ EXPECT_EQ(1, interceptor->GetCount()) << interceptor->GetRequestsAsString(); const auto msg = interceptor->GetRequestBody(0); - constexpr char regex[] = - R"(<app appid="abc" version="1\.0">)" - R"(<event eventresult="0" eventtype="3" previousversion="1\.0"/>)" - R"(</app>)"; - EXPECT_TRUE(RE2::PartialMatch(msg, regex)) << msg; + if (use_JSON_) { + const auto root = base::JSONReader().Read(msg); + const auto* request = root->FindKey("request"); + const auto& app = request->FindKey("app")->GetList()[0]; + EXPECT_EQ("abc", app.FindKey("appid")->GetString()); + EXPECT_EQ("1.0", app.FindKey("version")->GetString()); + const auto& event = app.FindKey("event")->GetList()[0]; + EXPECT_EQ(0, event.FindKey("eventresult")->GetInt()); + EXPECT_EQ(3, event.FindKey("eventtype")->GetInt()); + EXPECT_EQ("1.0", event.FindKey("previousversion")->GetString()); + } else { + constexpr char regex[] = + R"(<app appid="abc" version="1\.0">)" + R"(<event eventresult="0" eventtype="3" previousversion="1\.0"/>)" + R"(</app>)"; + EXPECT_TRUE(RE2::PartialMatch(msg, regex)) << msg; + } interceptor->Reset(); } @@ -253,11 +350,24 @@ EXPECT_EQ(1, interceptor->GetCount()) << interceptor->GetRequestsAsString(); const auto msg = interceptor->GetRequestBody(0); - constexpr char regex[] = - R"(<app appid="abc" version="1\.2\.3\.4">)" - R"(<event eventresult="1" eventtype="4" )" - R"(nextversion="0" previousversion="1\.2\.3\.4"/></app>)"; - EXPECT_TRUE(RE2::PartialMatch(msg, regex)) << msg; + if (use_JSON_) { + const auto root = base::JSONReader().Read(msg); + const auto* request = root->FindKey("request"); + const auto& app = request->FindKey("app")->GetList()[0]; + EXPECT_EQ("abc", app.FindKey("appid")->GetString()); + EXPECT_EQ("1.2.3.4", app.FindKey("version")->GetString()); + const auto& event = app.FindKey("event")->GetList()[0]; + EXPECT_EQ(1, event.FindKey("eventresult")->GetInt()); + EXPECT_EQ(4, event.FindKey("eventtype")->GetInt()); + EXPECT_EQ("1.2.3.4", event.FindKey("previousversion")->GetString()); + EXPECT_EQ("0", event.FindKey("nextversion")->GetString()); + } else { + constexpr char regex[] = + R"(<app appid="abc" version="1\.2\.3\.4">)" + R"(<event eventresult="1" eventtype="4" )" + R"(nextversion="0" previousversion="1\.2\.3\.4"/></app>)"; + EXPECT_TRUE(RE2::PartialMatch(msg, regex)) << msg; + } interceptor->Reset(); } @@ -289,31 +399,101 @@ download_metrics.download_time_ms = 9870; component.AppendEvent(component.MakeEventDownloadMetrics(download_metrics)); + download_metrics = CrxDownloader::DownloadMetrics(); + download_metrics.url = GURL("http://host3/path3"); + download_metrics.downloader = CrxDownloader::DownloadMetrics::kBits; + download_metrics.error = 0; + download_metrics.downloaded_bytes = kProtocolMaxInt; + download_metrics.total_bytes = kProtocolMaxInt - 1; + download_metrics.download_time_ms = kProtocolMaxInt - 2; + component.AppendEvent(component.MakeEventDownloadMetrics(download_metrics)); + EXPECT_TRUE(interceptor->ExpectRequest(std::make_unique<AnyMatch>())); ping_manager_->SendPing(component, MakePingCallback()); RunThreads(); EXPECT_EQ(1, interceptor->GetCount()) << interceptor->GetRequestsAsString(); const auto msg = interceptor->GetRequestBody(0); - constexpr char regex[] = - R"(<app appid="abc" version="1\.0">)" - R"(<event eventresult="1" eventtype="3" )" - R"(nextversion="2\.0" previousversion="1\.0"/>)" - R"(<event download_time_ms="987" downloaded="123" downloader="direct" )" - R"(errorcode="-1" eventresult="0" eventtype="14" )" - R"(nextversion="2\.0" previousversion="1\.0" total="456" )" - R"(url="http://host1/path1"/>)" - R"(<event download_time_ms="9870" downloaded="1230" downloader="bits" )" - R"(eventresult="1" eventtype="14" nextversion="2\.0" )" - R"(previousversion="1\.0" total="4560" url="http://host2/path2"/></app>)"; - EXPECT_TRUE(RE2::PartialMatch(msg, regex)) << msg; + if (use_JSON_) { + const auto root = base::JSONReader().Read(msg); + const auto* request = root->FindKey("request"); + const auto& app = request->FindKey("app")->GetList()[0]; + EXPECT_EQ("abc", app.FindKey("appid")->GetString()); + EXPECT_EQ("1.0", app.FindKey("version")->GetString()); + EXPECT_EQ(4u, app.FindKey("event")->GetList().size()); + { + const auto& event = app.FindKey("event")->GetList()[0]; + EXPECT_EQ(1, event.FindKey("eventresult")->GetInt()); + EXPECT_EQ(3, event.FindKey("eventtype")->GetInt()); + EXPECT_EQ("2.0", event.FindKey("nextversion")->GetString()); + EXPECT_EQ("1.0", event.FindKey("previousversion")->GetString()); + } + { + const auto& event = app.FindKey("event")->GetList()[1]; + EXPECT_EQ(0, event.FindKey("eventresult")->GetInt()); + EXPECT_EQ(14, event.FindKey("eventtype")->GetInt()); + EXPECT_EQ(987, event.FindKey("download_time_ms")->GetDouble()); + EXPECT_EQ(123, event.FindKey("downloaded")->GetDouble()); + EXPECT_EQ("direct", event.FindKey("downloader")->GetString()); + EXPECT_EQ(-1, event.FindKey("errorcode")->GetInt()); + EXPECT_EQ("2.0", event.FindKey("nextversion")->GetString()); + EXPECT_EQ("1.0", event.FindKey("previousversion")->GetString()); + EXPECT_EQ(456, event.FindKey("total")->GetDouble()); + EXPECT_EQ("http://host1/path1", event.FindKey("url")->GetString()); + } + { + const auto& event = app.FindKey("event")->GetList()[2]; + EXPECT_EQ(1, event.FindKey("eventresult")->GetInt()); + EXPECT_EQ(14, event.FindKey("eventtype")->GetInt()); + EXPECT_EQ(9870, event.FindKey("download_time_ms")->GetDouble()); + EXPECT_EQ(1230, event.FindKey("downloaded")->GetDouble()); + EXPECT_EQ("bits", event.FindKey("downloader")->GetString()); + EXPECT_EQ("2.0", event.FindKey("nextversion")->GetString()); + EXPECT_EQ("1.0", event.FindKey("previousversion")->GetString()); + EXPECT_EQ(4560, event.FindKey("total")->GetDouble()); + EXPECT_EQ("http://host2/path2", event.FindKey("url")->GetString()); + } + { + const auto& event = app.FindKey("event")->GetList()[3]; + EXPECT_EQ(1, event.FindKey("eventresult")->GetInt()); + EXPECT_EQ(14, event.FindKey("eventtype")->GetInt()); + EXPECT_EQ(9007199254740990, + event.FindKey("download_time_ms")->GetDouble()); + EXPECT_EQ(9007199254740992, event.FindKey("downloaded")->GetDouble()); + EXPECT_EQ("bits", event.FindKey("downloader")->GetString()); + EXPECT_EQ("2.0", event.FindKey("nextversion")->GetString()); + EXPECT_EQ("1.0", event.FindKey("previousversion")->GetString()); + EXPECT_EQ(9007199254740991, event.FindKey("total")->GetDouble()); + EXPECT_EQ("http://host3/path3", event.FindKey("url")->GetString()); + } + } else { + constexpr char regex[] = + R"(<app appid="abc" version="1\.0">)" + R"(<event eventresult="1" eventtype="3" )" + R"(nextversion="2\.0" previousversion="1\.0"/>)" + R"(<event download_time_ms="987" )" + R"(downloaded="123" downloader="direct" )" + R"(errorcode="-1" eventresult="0" eventtype="14" )" + R"(nextversion="2\.0" previousversion="1\.0" total="456" )" + R"(url="http://host1/path1"/>)" + R"(<event download_time_ms="9870" downloaded="1230" )" + R"(downloader="bits" )" + R"(eventresult="1" eventtype="14" nextversion="2\.0" )" + R"(previousversion="1\.0" total="4560" url="http://host2/path2"/>)" + R"(<event download_time_ms="9007199254740990" )" + R"(downloaded="9007199254740992" downloader="bits" )" + R"(eventresult="1" eventtype="14" nextversion="2.0" )" + R"(previousversion="1.0" total="9007199254740991" )" + R"(url="http://host3/path3"/></app>)"; + EXPECT_TRUE(RE2::PartialMatch(msg, regex)) << msg; + } interceptor->Reset(); } } // Tests that sending the ping fails when the component requires encryption but // the ping URL is unsecure. -TEST_F(PingManagerTest, RequiresEncryption) { +TEST_P(PingManagerTest, RequiresEncryption) { config_->SetPingUrl(GURL("http:\\foo\bar")); const auto update_context = MakeMockUpdateContext();
diff --git a/components/update_client/protocol_definition.h b/components/update_client/protocol_definition.h index e5c4f5b..aaacc76 100644 --- a/components/update_client/protocol_definition.h +++ b/components/update_client/protocol_definition.h
@@ -13,12 +13,9 @@ #include "base/containers/flat_map.h" #include "base/macros.h" #include "base/optional.h" +#include "base/values.h" #include "build/build_config.h" -namespace base { -class Value; -} - namespace update_client { // The protocol versions so far are: @@ -26,6 +23,10 @@ // * Version 3.0: it is the version implemented by the desktop updaters. constexpr char kProtocolVersion[] = "3.1"; +// Due to implementation constraints of the JSON parser and serializer, +// precision of integer numbers greater than 2^53 is lost. +constexpr int64_t kProtocolMaxInt = 1LL << 53; + namespace protocol_request { struct HW {
diff --git a/components/update_client/protocol_handler.cc b/components/update_client/protocol_handler.cc index e301461d..a6b4999 100644 --- a/components/update_client/protocol_handler.cc +++ b/components/update_client/protocol_handler.cc
@@ -3,7 +3,9 @@ // found in the LICENSE file. #include "components/update_client/protocol_handler.h" +#include "components/update_client/protocol_parser_json.h" #include "components/update_client/protocol_parser_xml.h" +#include "components/update_client/protocol_serializer_json.h" #include "components/update_client/protocol_serializer_xml.h" namespace update_client { @@ -18,4 +20,14 @@ return std::make_unique<ProtocolSerializerXml>(); } +std::unique_ptr<ProtocolParser> ProtocolHandlerFactoryJSON::CreateParser() + const { + return std::make_unique<ProtocolParserJSON>(); +} + +std::unique_ptr<ProtocolSerializer> +ProtocolHandlerFactoryJSON::CreateSerializer() const { + return std::make_unique<ProtocolSerializerJSON>(); +} + } // namespace update_client
diff --git a/components/update_client/protocol_handler.h b/components/update_client/protocol_handler.h index 40ed804..cb8e97ed 100644 --- a/components/update_client/protocol_handler.h +++ b/components/update_client/protocol_handler.h
@@ -34,6 +34,13 @@ std::unique_ptr<ProtocolSerializer> CreateSerializer() const override; }; +class ProtocolHandlerFactoryJSON final : public ProtocolHandlerFactory { + public: + // Overrides for ProtocolHandlerFactory. + std::unique_ptr<ProtocolParser> CreateParser() const override; + std::unique_ptr<ProtocolSerializer> CreateSerializer() const override; +}; + } // namespace update_client #endif // COMPONENTS_UPDATE_CLIENT_PROTOCOL_HANDLER_H_
diff --git a/components/update_client/protocol_parser.h b/components/update_client/protocol_parser.h index 58fea15f..6a0dbff 100644 --- a/components/update_client/protocol_parser.h +++ b/components/update_client/protocol_parser.h
@@ -25,6 +25,8 @@ Package(const Package& other); ~Package(); + // |fingerprint| is optional. It identifies the package, preferably + // with a modified sha256 hash of the package in hex format. std::string fingerprint; // Attributes for the full update.
diff --git a/components/update_client/protocol_parser_json.cc b/components/update_client/protocol_parser_json.cc new file mode 100644 index 0000000..3ff9f40 --- /dev/null +++ b/components/update_client/protocol_parser_json.cc
@@ -0,0 +1,330 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/update_client/protocol_parser_json.h" + +#include <utility> + +#include "base/json/json_reader.h" +#include "base/strings/strcat.h" +#include "base/strings/string_util.h" +#include "base/values.h" +#include "base/version.h" +#include "components/update_client/protocol_definition.h" + +namespace update_client { + +namespace { + +bool ParseManifest(const base::Value& manifest_node, + ProtocolParser::Result* result, + std::string* error) { + if (!manifest_node.is_dict()) { + *error = "'manifest' is not a dictionary."; + } + const auto* version = manifest_node.FindKey("version"); + if (!version || !version->is_string()) { + *error = "Missing version for manifest."; + return false; + } + + result->manifest.version = version->GetString(); + if (!base::Version(result->manifest.version).IsValid()) { + *error = + base::StrCat({"Invalid version: '", result->manifest.version, "'."}); + return false; + } + + // Get the optional minimum browser version. + const auto* browser_min_version = manifest_node.FindKey("prodversionmin"); + if (browser_min_version && browser_min_version->is_string()) { + result->manifest.browser_min_version = browser_min_version->GetString(); + if (!base::Version(result->manifest.browser_min_version).IsValid()) { + *error = base::StrCat({"Invalid prodversionmin: '", + result->manifest.browser_min_version, "'."}); + return false; + } + } + + const auto* packages_node = manifest_node.FindKey("packages"); + if (!packages_node || !packages_node->is_dict()) { + *error = "Missing packages in manifest or 'packages' is not a dictionary."; + return false; + } + const auto* package_node = packages_node->FindKey("package"); + if (!package_node || !package_node->is_list()) { + *error = "Missing package in packages."; + return false; + } + + for (const auto& package : package_node->GetList()) { + if (!package.is_dict()) { + *error = "'package' is not a dictionary."; + return false; + } + ProtocolParser::Result::Manifest::Package p; + const auto* name = package.FindKey("name"); + if (!name || !name->is_string()) { + *error = "Missing name for package."; + return false; + } + p.name = name->GetString(); + + const auto* namediff = package.FindKey("namediff"); + if (namediff && namediff->is_string()) + p.namediff = namediff->GetString(); + + const auto* fingerprint = package.FindKey("fp"); + if (fingerprint && fingerprint->is_string()) + p.fingerprint = fingerprint->GetString(); + + const auto* hash_sha256 = package.FindKey("hash_sha256"); + if (hash_sha256 && hash_sha256->is_string()) + p.hash_sha256 = hash_sha256->GetString(); + + const auto* size = package.FindKey("size"); + if (size && size->is_int()) + p.size = size->GetInt(); + + const auto* hashdiff_sha256 = package.FindKey("hashdiff_sha256"); + if (hashdiff_sha256 && hashdiff_sha256->is_string()) + p.hashdiff_sha256 = hashdiff_sha256->GetString(); + + const auto* sizediff = package.FindKey("sizediff"); + if (sizediff && sizediff->is_int()) + p.sizediff = sizediff->GetInt(); + + result->manifest.packages.push_back(std::move(p)); + } + + return true; +} + +void ParseActions(const base::Value& actions_node, + ProtocolParser::Result* result) { + if (!actions_node.is_dict()) + return; + + const auto* action_node = actions_node.FindKey("action"); + if (!action_node || !action_node->is_list()) + return; + + const auto& action_list = action_node->GetList(); + if (action_list.empty() || !action_list[0].is_dict()) + return; + + const auto* run = action_list[0].FindKey("run"); + if (run && run->is_string()) + result->action_run = run->GetString(); +} + +bool ParseUrls(const base::Value& urls_node, + ProtocolParser::Result* result, + std::string* error) { + if (!urls_node.is_dict()) { + *error = "'urls' is not a dictionary."; + return false; + } + const auto* url_node = urls_node.FindKey("url"); + if (!url_node || !url_node->is_list()) { + *error = "Missing url on urls."; + return false; + } + + for (const auto& url : url_node->GetList()) { + if (!url.is_dict()) + continue; + const auto* codebase = url.FindKey("codebase"); + if (codebase && codebase->is_string()) { + GURL crx_url(codebase->GetString()); + if (crx_url.is_valid()) + result->crx_urls.push_back(std::move(crx_url)); + } + const auto* codebasediff = url.FindKey("codebasediff"); + if (codebasediff && codebasediff->is_string()) { + GURL crx_diffurl(codebasediff->GetString()); + if (crx_diffurl.is_valid()) + result->crx_diffurls.push_back(std::move(crx_diffurl)); + } + } + + // Expect at least one url for full update. + if (result->crx_urls.empty()) { + *error = "Missing valid url for full update."; + return false; + } + + return true; +} + +bool ParseUpdateCheck(const base::Value& updatecheck_node, + ProtocolParser::Result* result, + std::string* error) { + if (!updatecheck_node.is_dict()) { + *error = "'updatecheck' is not a dictionary."; + return false; + } + const auto* status = updatecheck_node.FindKey("status"); + if (!status || !status->is_string()) { + *error = "Missing status on updatecheck node"; + return false; + } + + result->status = status->GetString(); + if (result->status == "noupdate") { + const auto* actions_node = updatecheck_node.FindKey("actions"); + if (actions_node) + ParseActions(*actions_node, result); + return true; + } + + if (result->status == "ok") { + const auto* actions_node = updatecheck_node.FindKey("actions"); + if (actions_node) + ParseActions(*actions_node, result); + + const auto* urls_node = updatecheck_node.FindKey("urls"); + if (!urls_node) { + *error = "Missing urls on updatecheck."; + return false; + } + + if (!ParseUrls(*urls_node, result, error)) + return false; + + const auto* manifest_node = updatecheck_node.FindKey("manifest"); + if (!manifest_node) { + *error = "Missing manifest on updatecheck."; + return false; + } + return ParseManifest(*manifest_node, result, error); + } + + // Return the |updatecheck| element status as a parsing error. + *error = result->status; + return false; +} + +bool ParseApp(const base::Value& app_node, + ProtocolParser::Result* result, + std::string* error) { + if (!app_node.is_dict()) { + *error = "'app' is not a dictionary."; + return false; + } + for (const auto* cohort_key : + {ProtocolParser::Result::kCohort, ProtocolParser::Result::kCohortHint, + ProtocolParser::Result::kCohortName}) { + const auto* cohort_value = app_node.FindKey(cohort_key); + if (cohort_value && cohort_value->is_string()) + result->cohort_attrs[cohort_key] = cohort_value->GetString(); + } + const auto* appid = app_node.FindKey("appid"); + if (appid && appid->is_string()) + result->extension_id = appid->GetString(); + if (result->extension_id.empty()) { + *error = "Missing appid on app node"; + return false; + } + + // Read the |status| attribute for the app. + // If the status is one of the defined app status error literals, then return + // it in the result as if it were an updatecheck status, then stop parsing, + // and return success. + const auto* status = app_node.FindKey("status"); + if (status && status->is_string()) { + result->status = status->GetString(); + if (result->status == "restricted" || + result->status == "error-unknownApplication" || + result->status == "error-invalidAppId") + return true; + + // If the status was not handled above and the status is not "ok", then + // this must be a status literal that that the parser does not know about. + if (!result->status.empty() && result->status != "ok") { + *error = "Unknown app status"; + return false; + } + } + + DCHECK(result->status.empty() || result->status == "ok"); + const auto* updatecheck_node = app_node.FindKey("updatecheck"); + if (!updatecheck_node) { + *error = "Missing updatecheck on app."; + return false; + } + + return ParseUpdateCheck(*updatecheck_node, result, error); +} + +} // namespace + +bool ProtocolParserJSON::DoParse(const std::string& response_json, + Results* results) { + DCHECK(results); + + if (response_json.empty()) { + ParseError("Empty JSON."); + return false; + } + + // The JSON response contains a prefix to prevent XSSI. + constexpr char kJSONPrefix[] = ")]}'"; + if (!base::StartsWith(response_json, kJSONPrefix, + base::CompareCase::SENSITIVE)) { + ParseError("Missing secure JSON prefix."); + return false; + } + const auto doc = base::JSONReader().Read( + {response_json.begin() + std::char_traits<char>::length(kJSONPrefix), + response_json.end()}); + if (!doc) { + ParseError("JSON read error."); + return false; + } + if (!doc->is_dict()) { + ParseError("JSON document is not a dictionary."); + return false; + } + const auto* response_node = doc->FindKey("response"); + if (!response_node || !response_node->is_dict()) { + ParseError("Missing 'response' element or 'response' is not a dictionary."); + return false; + } + const auto* protocol = response_node->FindKey("protocol"); + if (!protocol || !protocol->is_string() || + protocol->GetString() != kProtocolVersion) { + ParseError( + "Missing/incorrect protocol." + "(expected '%s', found '%s')", + kProtocolVersion, protocol->GetString().c_str()); + return false; + } + + const auto* daystart_node = response_node->FindKey("daystart"); + if (daystart_node && daystart_node->is_dict()) { + const auto* elapsed_seconds = daystart_node->FindKey("elapsed_seconds"); + if (elapsed_seconds && elapsed_seconds->is_int()) + results->daystart_elapsed_seconds = elapsed_seconds->GetInt(); + const auto* elapsed_days = daystart_node->FindKey("elapsed_days"); + if (elapsed_days && elapsed_days->is_int()) + results->daystart_elapsed_days = elapsed_days->GetInt(); + } + + const auto* app_node = response_node->FindKey("app"); + if (app_node && app_node->is_list()) { + for (const auto& app : app_node->GetList()) { + Result result; + std::string error; + if (ParseApp(app, &result, &error)) + results->list.push_back(result); + else + ParseError("%s", error.c_str()); + } + } + + return true; +} + +} // namespace update_client
diff --git a/components/update_client/protocol_parser_json.h b/components/update_client/protocol_parser_json.h new file mode 100644 index 0000000..71f96f44 --- /dev/null +++ b/components/update_client/protocol_parser_json.h
@@ -0,0 +1,30 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_UPDATE_CLIENT_PROTOCOL_PARSER_JSON_H_ +#define COMPONENTS_UPDATE_CLIENT_PROTOCOL_PARSER_JSON_H_ + +#include <string> + +#include "base/macros.h" +#include "components/update_client/protocol_parser.h" + +namespace update_client { + +// Parses responses for the update protocol version 3. +// (https://github.com/google/omaha/blob/wiki/ServerProtocolV3.md) +class ProtocolParserJSON final : public ProtocolParser { + public: + ProtocolParserJSON() = default; + + private: + // Overrides for ProtocolParser. + bool DoParse(const std::string& response_json, Results* results) override; + + DISALLOW_COPY_AND_ASSIGN(ProtocolParserJSON); +}; + +} // namespace update_client + +#endif // COMPONENTS_UPDATE_CLIENT_PROTOCOL_PARSER_JSON_H_
diff --git a/components/update_client/protocol_parser_json_unittest.cc b/components/update_client/protocol_parser_json_unittest.cc new file mode 100644 index 0000000..49f897d --- /dev/null +++ b/components/update_client/protocol_parser_json_unittest.cc
@@ -0,0 +1,492 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/update_client/protocol_parser_json.h" + +#include <memory> + +#include "testing/gtest/include/gtest/gtest.h" + +namespace update_client { + +const char* kJSONValid = R"()]}' + {"response":{ + "protocol":"3.1", + "app":[ + {"appid":"12345", + "status":"ok", + "updatecheck":{ + "status":"ok", + "urls":{"url":[{"codebase":"http://example.com/"}, + {"codebasediff":"http://diff.example.com/"}]}, + "manifest":{ + "version":"1.2.3.4", + "prodversionmin":"2.0.143.0", + "packages":{"package":[{"name":"extension_1_2_3_4.crx"}]}} + } + } + ] + }})"; + +const char* kJSONHash = R"()]}' + {"response":{ + "protocol":"3.1", + "app":[ + {"appid":"12345", + "status":"ok", + "updatecheck":{ + "status":"ok", + "urls":{"url":[{"codebase":"http://example.com/"}]}, + "manifest":{ + "version":"1.2.3.4", + "prodversionmin":"2.0.143.0", + "packages":{"package":[{"name":"extension_1_2_3_4.crx", + "hash_sha256":"1234", + "hashdiff_sha256":"5678"}]}} + } + } + ] + }})"; + +const char* kJSONInvalidSizes = R"()]}' + {"response":{ + "protocol":"3.1", + "app":[ + {"appid":"12345", + "status":"ok", + "updatecheck":{ + "status":"ok", + "urls":{"url":[{"codebase":"http://example.com/"}]}, + "manifest":{ + "version":"1.2.3.4", + "prodversionmin":"2.0.143.0", + "packages":{"package":[{"name":"1","size":1234}, + {"name":"1","size":-1234}, + {"name":"1"}, + {"name":"1","size":"-a"}, + {"name":"1","size":-123467890123456789}, + {"name":"1","size":123467890123456789}]}} + } + } + ] + }})"; + +const char* kJSONInvalidMissingCodebase = R"()]}' + {"response":{ + "protocol":"3.1", + "app":[ + {"appid":"12345", + "status":"ok", + "updatecheck":{ + "status":"ok", + "urls":{"url":[{"codebasediff":"http://diff.example.com"}]}, + "manifest":{ + "version":"1.2.3.4", + "prodversionmin":"2.0.143.0", + "packages":{"package":[{"namediff":"extension_1_2_3_4.crx"}]}} + } + } + ] + }})"; + +const char* kJSONInvalidMissingManifest = R"()]}' + {"response":{ + "protocol":"3.1", + "app":[ + {"appid":"12345", + "status":"ok", + "updatecheck":{ + "status":"ok", + "urls":{"url":[{"codebase":"http://localhost/download/"}]} + } + } + ] + }})"; + +const char* kJSONMissingAppId = R"()]}' + {"response":{ + "protocol":"3.1", + "app":[ + {"status":"ok", + "updatecheck":{ + "status":"ok", + "urls":{"url":[{"codebase":"http://localhost/download/"}]} + } + } + ] + }})"; + +const char* kJSONInvalidCodebase = R"()]}' + {"response":{ + "protocol":"3.1", + "app":[ + {"appid":"12345", + "status":"ok", + "updatecheck":{ + "status":"ok", + "urls":{"url":[{"codebase":"example.com/extension_1.2.3.4.crx", + "version":"1.2.3.4"}]} + } + } + ] + }})"; + +const char* kJSONMissingVersion = R"()]}' + {"response":{ + "protocol":"3.1", + "app":[ + {"appid":"12345", + "status":"ok", + "updatecheck":{ + "status":"ok", + "urls":{"url":[{"codebase":"http://localhost/download/"}]}, + "manifest":{ + "packages":{"package":[{"name":"jebgalgnebhfojomionfpkfelancnnkf.crx"}]}} + } + } + ] + }})"; + +const char* kJSONInvalidVersion = R"()]}' + {"response":{ + "protocol":"3.1", + "app":[ + {"appid":"12345", + "status":"ok", + "updatecheck":{ + "status":"ok", + "urls":{"url":[{"codebase":"http://localhost/download/"}]}, + "manifest":{ + "version":"1.2.3.a", + "packages":{"package":[{"name":"jebgalgnebhfojomionfpkfelancnnkf.crx"}]}} + } + } + ] + }})"; + +// Includes a <daystart> tag. +const char* kJSONWithDaystart = R"()]}' + {"response":{ + "protocol":"3.1", + "daystart":{"elapsed_seconds":456}, + "app":[ + {"appid":"12345", + "status":"ok", + "updatecheck":{ + "status":"ok", + "urls":{"url":[{"codebase":"http://example.com/"}, + {"codebasediff":"http://diff.example.com/"}]}, + "manifest":{ + "version":"1.2.3.4", + "prodversionmin":"2.0.143.0", + "packages":{"package":[{"name":"extension_1_2_3_4.crx"}]}} + } + } + ] + }})"; + +// Indicates no updates available. +const char* kJSONNoUpdate = R"()]}' + {"response":{ + "protocol":"3.1", + "app":[ + {"appid":"12345", + "status":"ok", + "updatecheck":{ + "status":"noupdate" + } + } + ] + }})"; + +// Includes two app objects, one app with an error. +const char* kJSONTwoAppsOneError = R"()]}' + {"response":{ + "protocol":"3.1", + "daystart":{"elapsed_seconds":456}, + "app":[ + {"appid":"aaaaaaaa", + "status":"error-unknownApplication", + "updatecheck":{"status":"error-internal"} + }, + {"appid":"bbbbbbbb", + "status":"ok", + "updatecheck":{ + "status":"ok", + "urls":{"url":[{"codebase":"http://example.com/"}]}, + "manifest":{ + "version":"1.2.3.4", + "prodversionmin":"2.0.143.0", + "packages":{"package":[{"name":"extension_1_2_3_4.crx"}]}} + } + } + ] + }})"; + +// Includes two <app> tags, both of which set the cohort. +const char* kJSONTwoAppsSetCohort = R"()]}' + {"response":{ + "protocol":"3.1", + "daystart":{"elapsed_seconds":456}, + "app":[ + {"appid":"aaaaaaaa", + "cohort":"1:2q3/", + "updatecheck":{"status":"noupdate"} + }, + {"appid":"bbbbbbbb", + "cohort":"1:33z@0.33", + "cohortname":"cname", + "updatecheck":{ + "status":"ok", + "urls":{"url":[{"codebase":"http://example.com/"}]}, + "manifest":{ + "version":"1.2.3.4", + "prodversionmin":"2.0.143.0", + "packages":{"package":[{"name":"extension_1_2_3_4.crx"}]}} + } + } + ] + }})"; + +// Includes a run action for an update check with status='ok'. +const char* kJSONUpdateCheckStatusOkWithRunAction = R"()]}' + {"response":{ + "protocol":"3.1", + "app":[ + {"appid":"12345", + "updatecheck":{ + "status":"ok", + "actions":{"action":[{"run":"this"}]}, + "urls":{"url":[{"codebase":"http://example.com/"}, + {"codebasediff":"http://diff.example.com/"}]}, + "manifest":{ + "version":"1.2.3.4", + "prodversionmin":"2.0.143.0", + "packages":{"package":[{"name":"extension_1_2_3_4.crx"}]}} + } + } + ] + }})"; + +// Includes a run action for an update check with status='noupdate'. +const char* kJSONUpdateCheckStatusNoUpdateWithRunAction = R"()]}' + {"response":{ + "protocol":"3.1", + "app":[ + {"appid":"12345", + "updatecheck":{ + "status":"noupdate", + "actions":{"action":[{"run":"this"}]} + } + } + ] + }})"; + +// Includes a run action for an update check with status='error'. +const char* kJSONUpdateCheckStatusErrorWithRunAction = R"()]}' + {"response":{ + "protocol":"3.1", + "app":[ + {"appid":"12345", + "updatecheck":{ + "status":"error-osnotsupported", + "actions":{"action":[{"run":"this"}]} + } + } + ] + }})"; + +// Includes four app objects with status different than 'ok'. +const char* kJSONAppsStatusError = R"()]}' + {"response":{ + "protocol":"3.1", + "app":[ + {"appid":"aaaaaaaa", + "status":"error-unknownApplication", + "updatecheck":{"status":"error-internal"} + }, + {"appid":"bbbbbbbb", + "status":"restricted", + "updatecheck":{"status":"error-internal"} + }, + {"appid":"cccccccc", + "status":"error-invalidAppId", + "updatecheck":{"status":"error-internal"} + }, + {"appid":"dddddddd", + "status":"foobar", + "updatecheck":{"status":"error-internal"} + } + ] + }})"; + +TEST(UpdateClientProtocolParserJSONTest, Parse) { + const auto parser = std::make_unique<ProtocolParserJSON>(); + + // Test parsing of a number of invalid JSON cases + EXPECT_FALSE(parser->Parse(std::string())); + EXPECT_FALSE(parser->errors().empty()); + + EXPECT_TRUE(parser->Parse(kJSONMissingAppId)); + EXPECT_TRUE(parser->results().list.empty()); + EXPECT_FALSE(parser->errors().empty()); + + EXPECT_TRUE(parser->Parse(kJSONInvalidCodebase)); + EXPECT_TRUE(parser->results().list.empty()); + EXPECT_FALSE(parser->errors().empty()); + + EXPECT_TRUE(parser->Parse(kJSONMissingVersion)); + EXPECT_TRUE(parser->results().list.empty()); + EXPECT_FALSE(parser->errors().empty()); + + EXPECT_TRUE(parser->Parse(kJSONInvalidVersion)); + EXPECT_TRUE(parser->results().list.empty()); + EXPECT_FALSE(parser->errors().empty()); + + EXPECT_TRUE(parser->Parse(kJSONInvalidMissingCodebase)); + EXPECT_TRUE(parser->results().list.empty()); + EXPECT_FALSE(parser->errors().empty()); + + EXPECT_TRUE(parser->Parse(kJSONInvalidMissingManifest)); + EXPECT_TRUE(parser->results().list.empty()); + EXPECT_FALSE(parser->errors().empty()); + + { + // Parse some valid XML, and check that all params came out as expected. + EXPECT_TRUE(parser->Parse(kJSONValid)); + EXPECT_TRUE(parser->errors().empty()); + EXPECT_EQ(1u, parser->results().list.size()); + const auto* first_result = &parser->results().list[0]; + EXPECT_STREQ("ok", first_result->status.c_str()); + EXPECT_EQ(1u, first_result->crx_urls.size()); + EXPECT_EQ(GURL("http://example.com/"), first_result->crx_urls[0]); + EXPECT_EQ(GURL("http://diff.example.com/"), first_result->crx_diffurls[0]); + EXPECT_EQ("1.2.3.4", first_result->manifest.version); + EXPECT_EQ("2.0.143.0", first_result->manifest.browser_min_version); + EXPECT_EQ(1u, first_result->manifest.packages.size()); + EXPECT_EQ("extension_1_2_3_4.crx", first_result->manifest.packages[0].name); + } + { + // Parse xml with hash value. + EXPECT_TRUE(parser->Parse(kJSONHash)); + EXPECT_TRUE(parser->errors().empty()); + EXPECT_FALSE(parser->results().list.empty()); + const auto* first_result = &parser->results().list[0]; + EXPECT_FALSE(first_result->manifest.packages.empty()); + EXPECT_EQ("1234", first_result->manifest.packages[0].hash_sha256); + EXPECT_EQ("5678", first_result->manifest.packages[0].hashdiff_sha256); + } + { + // Parse xml with package size value. + EXPECT_TRUE(parser->Parse(kJSONInvalidSizes)); + EXPECT_TRUE(parser->errors().empty()); + EXPECT_FALSE(parser->results().list.empty()); + const auto* first_result = &parser->results().list[0]; + EXPECT_FALSE(first_result->manifest.packages.empty()); + EXPECT_EQ(1234, first_result->manifest.packages[0].size); + EXPECT_EQ(-1234, first_result->manifest.packages[1].size); + EXPECT_EQ(0, first_result->manifest.packages[2].size); + EXPECT_EQ(0, first_result->manifest.packages[3].size); + EXPECT_EQ(0, first_result->manifest.packages[4].size); + EXPECT_EQ(0, first_result->manifest.packages[5].size); + } + { + // Parse xml with a <daystart> element. + EXPECT_TRUE(parser->Parse(kJSONWithDaystart)); + EXPECT_TRUE(parser->errors().empty()); + EXPECT_FALSE(parser->results().list.empty()); + EXPECT_EQ(parser->results().daystart_elapsed_seconds, 456); + } + { + // Parse a no-update response. + EXPECT_TRUE(parser->Parse(kJSONNoUpdate)); + EXPECT_TRUE(parser->errors().empty()); + EXPECT_FALSE(parser->results().list.empty()); + const auto* first_result = &parser->results().list[0]; + EXPECT_STREQ("noupdate", first_result->status.c_str()); + EXPECT_EQ(first_result->extension_id, "12345"); + EXPECT_EQ(first_result->manifest.version, ""); + } + { + // Parse xml with one error and one success <app> tag. + EXPECT_TRUE(parser->Parse(kJSONTwoAppsOneError)); + EXPECT_TRUE(parser->errors().empty()); + EXPECT_EQ(2u, parser->results().list.size()); + const auto* first_result = &parser->results().list[0]; + EXPECT_EQ(first_result->extension_id, "aaaaaaaa"); + EXPECT_STREQ("error-unknownApplication", first_result->status.c_str()); + EXPECT_TRUE(first_result->manifest.version.empty()); + const auto* second_result = &parser->results().list[1]; + EXPECT_EQ(second_result->extension_id, "bbbbbbbb"); + EXPECT_STREQ("ok", second_result->status.c_str()); + EXPECT_EQ("1.2.3.4", second_result->manifest.version); + } + { + // Parse xml with two apps setting the cohort info. + EXPECT_TRUE(parser->Parse(kJSONTwoAppsSetCohort)); + EXPECT_TRUE(parser->errors().empty()); + EXPECT_EQ(2u, parser->results().list.size()); + const auto* first_result = &parser->results().list[0]; + EXPECT_EQ(first_result->extension_id, "aaaaaaaa"); + EXPECT_NE(first_result->cohort_attrs.find("cohort"), + first_result->cohort_attrs.end()); + EXPECT_EQ(first_result->cohort_attrs.find("cohort")->second, "1:2q3/"); + EXPECT_EQ(first_result->cohort_attrs.find("cohortname"), + first_result->cohort_attrs.end()); + EXPECT_EQ(first_result->cohort_attrs.find("cohorthint"), + first_result->cohort_attrs.end()); + const auto* second_result = &parser->results().list[1]; + EXPECT_EQ(second_result->extension_id, "bbbbbbbb"); + EXPECT_NE(second_result->cohort_attrs.find("cohort"), + second_result->cohort_attrs.end()); + EXPECT_EQ(second_result->cohort_attrs.find("cohort")->second, "1:33z@0.33"); + EXPECT_NE(second_result->cohort_attrs.find("cohortname"), + second_result->cohort_attrs.end()); + EXPECT_EQ(second_result->cohort_attrs.find("cohortname")->second, "cname"); + EXPECT_EQ(second_result->cohort_attrs.find("cohorthint"), + second_result->cohort_attrs.end()); + } + { + EXPECT_TRUE(parser->Parse(kJSONUpdateCheckStatusOkWithRunAction)); + EXPECT_TRUE(parser->errors().empty()); + EXPECT_FALSE(parser->results().list.empty()); + const auto* first_result = &parser->results().list[0]; + EXPECT_STREQ("ok", first_result->status.c_str()); + EXPECT_EQ(first_result->extension_id, "12345"); + EXPECT_STREQ("this", first_result->action_run.c_str()); + } + { + EXPECT_TRUE(parser->Parse(kJSONUpdateCheckStatusNoUpdateWithRunAction)); + EXPECT_TRUE(parser->errors().empty()); + EXPECT_FALSE(parser->results().list.empty()); + const auto* first_result = &parser->results().list[0]; + EXPECT_STREQ("noupdate", first_result->status.c_str()); + EXPECT_EQ(first_result->extension_id, "12345"); + EXPECT_STREQ("this", first_result->action_run.c_str()); + } + { + EXPECT_TRUE(parser->Parse(kJSONUpdateCheckStatusErrorWithRunAction)); + EXPECT_FALSE(parser->errors().empty()); + EXPECT_TRUE(parser->results().list.empty()); + } + { + EXPECT_TRUE(parser->Parse(kJSONAppsStatusError)); + EXPECT_STREQ("Unknown app status", parser->errors().c_str()); + EXPECT_EQ(3u, parser->results().list.size()); + const auto* first_result = &parser->results().list[0]; + EXPECT_EQ(first_result->extension_id, "aaaaaaaa"); + EXPECT_STREQ("error-unknownApplication", first_result->status.c_str()); + EXPECT_TRUE(first_result->manifest.version.empty()); + const auto* second_result = &parser->results().list[1]; + EXPECT_EQ(second_result->extension_id, "bbbbbbbb"); + EXPECT_STREQ("restricted", second_result->status.c_str()); + EXPECT_TRUE(second_result->manifest.version.empty()); + const auto* third_result = &parser->results().list[2]; + EXPECT_EQ(third_result->extension_id, "cccccccc"); + EXPECT_STREQ("error-invalidAppId", third_result->status.c_str()); + EXPECT_TRUE(third_result->manifest.version.empty()); + } +} + +} // namespace update_client
diff --git a/components/update_client/protocol_serializer.cc b/components/update_client/protocol_serializer.cc index 4eb7580..67e67ed 100644 --- a/components/update_client/protocol_serializer.cc +++ b/components/update_client/protocol_serializer.cc
@@ -18,7 +18,6 @@ #include "build/build_config.h" #include "components/update_client/activity_data_service.h" #include "components/update_client/persisted_data.h" -#include "components/update_client/protocol_serializer_xml.h" #include "components/update_client/update_query_params.h" #include "components/update_client/updater_state.h" @@ -57,10 +56,6 @@ } // namespace -std::unique_ptr<ProtocolSerializer> ProtocolSerializer::Create() { - return std::make_unique<ProtocolSerializerXml>(); -} - base::flat_map<std::string, std::string> BuildUpdateCheckExtraRequestHeaders( const std::string& prod_id, const base::Version& browser_version,
diff --git a/components/update_client/protocol_serializer.h b/components/update_client/protocol_serializer.h index 066751b6..47c212a4 100644 --- a/components/update_client/protocol_serializer.h +++ b/components/update_client/protocol_serializer.h
@@ -71,7 +71,6 @@ class ProtocolSerializer { public: - static std::unique_ptr<ProtocolSerializer> Create(); virtual ~ProtocolSerializer() = default; virtual std::string Serialize( const protocol_request::Request& request) const = 0;
diff --git a/components/update_client/protocol_serializer_json.cc b/components/update_client/protocol_serializer_json.cc new file mode 100644 index 0000000..b94d2c05 --- /dev/null +++ b/components/update_client/protocol_serializer_json.cc
@@ -0,0 +1,183 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/update_client/protocol_serializer_json.h" + +#include <memory> +#include <utility> +#include <vector> + +#include "base/json/json_writer.h" +#include "base/values.h" +#include "build/build_config.h" + +#include "components/update_client/updater_state.h" + +namespace update_client { + +using Value = base::Value; + +std::string ProtocolSerializerJSON::Serialize( + const protocol_request::Request& request) const { + Value root_node(Value::Type::DICTIONARY); + auto* request_node = + root_node.SetKey("request", Value(Value::Type::DICTIONARY)); + request_node->SetKey("protocol", Value(request.protocol_version)); + request_node->SetKey("dedup", Value("cr")); + request_node->SetKey("acceptformat", Value("crx2,crx3")); + if (!request.additional_attributes.empty()) { + for (const auto& attr : request.additional_attributes) + request_node->SetKey(attr.first, Value(attr.second)); + } + request_node->SetKey("sessionid", Value(request.session_id)); + request_node->SetKey("requestid", Value(request.request_id)); + request_node->SetKey("@updater", Value(request.updatername)); + request_node->SetKey("prodversion", Value(request.updaterversion)); + request_node->SetKey("updaterversion", Value(request.prodversion)); + request_node->SetKey("lang", Value(request.lang)); + request_node->SetKey("@os", Value(request.operating_system)); + request_node->SetKey("arch", Value(request.arch)); + request_node->SetKey("nacl_arch", Value(request.nacl_arch)); +#if defined(OS_WIN) + if (request.is_wow64) + request_node->SetKey("wow64", Value(request.is_wow64)); +#endif // OS_WIN + if (!request.updaterchannel.empty()) + request_node->SetKey("updaterchannel", Value(request.updaterchannel)); + if (!request.prodchannel.empty()) + request_node->SetKey("prodchannel", Value(request.prodchannel)); + if (!request.dlpref.empty()) + request_node->SetKey("dlpref", Value(request.dlpref)); + if (request.domain_joined) { + request_node->SetKey(UpdaterState::kIsEnterpriseManaged, + Value(*request.domain_joined)); + } + + // HW platform information. + auto* hw_node = request_node->SetKey("hw", Value(Value::Type::DICTIONARY)); + hw_node->SetKey("physmemory", Value(static_cast<int>(request.hw.physmemory))); + + // OS version and platform information. + auto* os_node = request_node->SetKey("os", Value(Value::Type::DICTIONARY)); + os_node->SetKey("platform", Value(request.os.platform)); + os_node->SetKey("arch", Value(request.os.arch)); + if (!request.os.version.empty()) + os_node->SetKey("version", Value(request.os.version)); + if (!request.os.service_pack.empty()) + os_node->SetKey("sp", Value(request.os.service_pack)); + +#if defined(GOOGLE_CHROME_BUILD) + if (request.updater) { + const auto& updater = *request.updater; + auto* updater_node = + request_node->SetKey("updater", Value(Value::Type::DICTIONARY)); + updater_node->SetKey("name", Value(updater.name)); + updater_node->SetKey("ismachine", Value(updater.is_machine)); + updater_node->SetKey("autoupdatecheckenabled", + Value(updater.autoupdate_check_enabled)); + updater_node->SetKey("updatepolicy", Value(updater.update_policy)); + if (!updater.version.empty()) + updater_node->SetKey("version", Value(updater.version)); + if (updater.last_checked) + updater_node->SetKey("lastchecked", Value(*updater.last_checked)); + if (updater.last_started) + updater_node->SetKey("laststarted", Value(*updater.last_started)); + } +#endif + + std::vector<Value> app_nodes; + for (const auto& app : request.apps) { + Value app_node(Value::Type::DICTIONARY); + app_node.SetKey("appid", Value(app.app_id)); + app_node.SetKey("version", Value(app.version)); + if (!app.brand_code.empty()) + app_node.SetKey("brand", Value(app.brand_code)); + if (!app.install_source.empty()) + app_node.SetKey("installsource", Value(app.install_source)); + if (!app.install_location.empty()) + app_node.SetKey("installedby", Value(app.install_location)); + if (!app.cohort.empty()) + app_node.SetKey("cohort", Value(app.cohort)); + if (!app.cohort_name.empty()) + app_node.SetKey("cohortname", Value(app.cohort_name)); + if (!app.cohort_hint.empty()) + app_node.SetKey("cohorthint", Value(app.cohort_hint)); + if (app.enabled) + app_node.SetKey("enabled", Value(*app.enabled)); + + if (app.disabled_reasons && !app.disabled_reasons->empty()) { + std::vector<Value> disabled_nodes; + for (const int disabled_reason : *app.disabled_reasons) { + Value disabled_node(Value::Type::DICTIONARY); + disabled_node.SetKey("reason", Value(disabled_reason)); + disabled_nodes.push_back(std::move(disabled_node)); + } + app_node.SetKey("disabled", Value(disabled_nodes)); + } + + for (const auto& attr : app.installer_attributes) + app_node.SetKey(attr.first, Value(attr.second)); + + if (app.update_check) { + auto* update_check_node = + app_node.SetKey("updatecheck", Value(Value::Type::DICTIONARY)); + if (app.update_check->is_update_disabled) + update_check_node->SetKey("updatedisabled", Value(true)); + } + + if (app.ping) { + const auto& ping = *app.ping; + auto* ping_node = app_node.SetKey("ping", Value(Value::Type::DICTIONARY)); + if (!ping.ping_freshness.empty()) + ping_node->SetKey("ping_freshness", Value(ping.ping_freshness)); + + // Output "ad" or "a" only if the this app has been seen 'active'. + if (ping.date_last_active) { + ping_node->SetKey("ad", Value(*ping.date_last_active)); + } else if (ping.days_since_last_active_ping) { + ping_node->SetKey("a", Value(*ping.days_since_last_active_ping)); + } + + // Output "rd" if valid or "r" as a last resort roll call metric. + if (ping.date_last_roll_call) + ping_node->SetKey("rd", Value(*ping.date_last_roll_call)); + else + ping_node->SetKey("r", Value(ping.days_since_last_roll_call)); + } + + if (!app.fingerprint.empty()) { + std::vector<Value> package_nodes; + Value package(Value::Type::DICTIONARY); + package.SetKey("fp", Value(app.fingerprint)); + package_nodes.push_back(std::move(package)); + auto* packages_node = + app_node.SetKey("packages", Value(Value::Type::DICTIONARY)); + packages_node->SetKey("package", Value(package_nodes)); + } + + if (app.events) { + std::vector<Value> event_nodes; + for (const auto& event : *app.events) { + DCHECK(event.is_dict()); + DCHECK(!event.DictEmpty()); + event_nodes.push_back(event.Clone()); + } + app_node.SetKey("event", Value(event_nodes)); + } + + app_nodes.push_back(std::move(app_node)); + } + + if (!app_nodes.empty()) + request_node->SetKey("app", Value(std::move(app_nodes))); + + std::string msg; + return base::JSONWriter::WriteWithOptions( + root_node, base::JSONWriter::OPTIONS_OMIT_DOUBLE_TYPE_PRESERVATION, + &msg) + ? msg + : std::string(); +} + +} // namespace update_client
diff --git a/components/update_client/protocol_serializer_json.h b/components/update_client/protocol_serializer_json.h new file mode 100644 index 0000000..71f2a99 --- /dev/null +++ b/components/update_client/protocol_serializer_json.h
@@ -0,0 +1,28 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_UPDATE_CLIENT_PROTOCOL_SERIALIZER_JSON_H_ +#define COMPONENTS_UPDATE_CLIENT_PROTOCOL_SERIALIZER_JSON_H_ + +#include <string> + +#include "components/update_client/protocol_serializer.h" + +namespace update_client { + +class ProtocolSerializerJSON final : public ProtocolSerializer { + public: + ProtocolSerializerJSON() = default; + + // Overrides for ProtocolSerializer. + std::string Serialize( + const protocol_request::Request& request) const override; + + private: + DISALLOW_COPY_AND_ASSIGN(ProtocolSerializerJSON); +}; + +} // namespace update_client + +#endif // COMPONENTS_UPDATE_CLIENT_PROTOCOL_SERIALIZER_JSON_H_
diff --git a/components/update_client/protocol_serializer_json_unittest.cc b/components/update_client/protocol_serializer_json_unittest.cc new file mode 100644 index 0000000..020cc10 --- /dev/null +++ b/components/update_client/protocol_serializer_json_unittest.cc
@@ -0,0 +1,126 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <memory> +#include <string> +#include <utility> +#include <vector> + +#include "base/optional.h" +#include "base/values.h" +#include "base/version.h" +#include "components/prefs/testing_pref_service.h" +#include "components/update_client/activity_data_service.h" +#include "components/update_client/persisted_data.h" +#include "components/update_client/protocol_definition.h" +#include "components/update_client/protocol_serializer.h" +#include "components/update_client/protocol_serializer_json.h" +#include "components/update_client/updater_state.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/re2/src/re2/re2.h" + +using base::Value; +using std::string; + +namespace update_client { + +TEST(SerializeRequestJSON, Serialize) { + // When no updater state is provided, then check that the elements and + // attributes related to the updater state are not serialized. + + std::vector<base::Value> events; + events.push_back(Value(Value::Type::DICTIONARY)); + events.push_back(Value(Value::Type::DICTIONARY)); + events[0].SetKey("a", Value(1)); + events[0].SetKey("b", Value("2")); + events[1].SetKey("error", Value(0)); + + auto pref = std::make_unique<TestingPrefServiceSimple>(); + PersistedData::RegisterPrefs(pref->registry()); + auto metadata = std::make_unique<PersistedData>(pref.get(), nullptr); + std::vector<std::string> items = {"id1"}; + metadata->SetDateLastRollCall(items, 1234); + + std::vector<protocol_request::App> apps; + apps.push_back(MakeProtocolApp( + "id1", base::Version("1.0"), "brand1", "source1", "location1", "fp1", + {{"attr1", "1"}, {"attr2", "2"}}, "c1", "ch1", "cn1", {0, 1}, + MakeProtocolUpdateCheck(true), MakeProtocolPing("id1", metadata.get()))); + apps.push_back( + MakeProtocolApp("id2", base::Version("2.0"), std::move(events))); + + const auto request = std::make_unique<ProtocolSerializerJSON>()->Serialize( + MakeProtocolRequest("15160585-8ADE-4D3C-839B-1281A6035D1F", "prod_id", + "1.0", "lang", "channel", "OS", "cacheable", + {{"extra", "params"}}, nullptr, std::move(apps))); + constexpr char regex[] = + R"({"request":{"@os":"\w+","@updater":"prod_id",)" + R"("acceptformat":"crx2,crx3",)" + R"("app":\[{"appid":"id1","attr1":"1","attr2":"2","brand":"brand1",)" + R"("cohort":"c1","cohorthint":"ch1","cohortname":"cn1",)" + R"("disabled":\[{"reason":0},{"reason":1}],"enabled":false,)" + R"("installedby":"location1","installsource":"source1",)" + R"("packages":{"package":\[{"fp":"fp1"}]},)" + R"("ping":{"ping_freshness":"{[-\w]{36}}","rd":1234},)" + R"("updatecheck":{"updatedisabled":true},"version":"1.0"},)" + R"({"appid":"id2","event":\[{"a":1,"b":"2"},{"error":0}],)" + R"("version":"2.0"}],"arch":"\w+","dedup":"cr","dlpref":"cacheable",)" + R"("extra":"params","hw":{"physmemory":\d+},"lang":"lang",)" + R"("nacl_arch":"[-\w]+","os":{"arch":"[_,-.\w]+","platform":"OS",)" + R"(("sp":"[\s\w]+",)?"version":"[-.\w]+"},"prodchannel":"channel",)" + R"("prodversion":"1.0","protocol":"3.1","requestid":"{[-\w]{36}}",)" + R"("sessionid":"{[-\w]{36}}","updaterchannel":"channel",)" + R"("updaterversion":"1.0"(,"wow64":true)?}})"; + EXPECT_TRUE(RE2::FullMatch(request, regex)) << request; +} + +TEST(SerializeRequestJSON, DownloadPreference) { + // Verifies that an empty |download_preference| is not serialized. + const auto serializer = std::make_unique<ProtocolSerializerJSON>(); + auto request = serializer->Serialize( + MakeProtocolRequest("15160585-8ADE-4D3C-839B-1281A6035D1F", "", "", "", + "", "", "", {}, nullptr, {})); + EXPECT_FALSE(RE2::PartialMatch(request, R"("dlpref":)")) << request; + + // Verifies that |download_preference| is serialized. + request = serializer->Serialize( + MakeProtocolRequest("15160585-8ADE-4D3C-839B-1281A6035D1F", "", "", "", + "", "", "cacheable", {}, nullptr, {})); + EXPECT_TRUE(RE2::PartialMatch(request, R"("dlpref":"cacheable")")) << request; +} + +// When present, updater state attributes are only serialized for Google builds, +// except the |domainjoined| attribute, which is serialized in all cases. +TEST(SerializeRequestJSON, UpdaterStateAttributes) { + const auto serializer = std::make_unique<ProtocolSerializerJSON>(); + UpdaterState::Attributes attributes; + attributes["ismachine"] = "1"; + attributes["domainjoined"] = "1"; + attributes["name"] = "Omaha"; + attributes["version"] = "1.2.3.4"; + attributes["laststarted"] = "1"; + attributes["lastchecked"] = "2"; + attributes["autoupdatecheckenabled"] = "0"; + attributes["updatepolicy"] = "-1"; + const auto request = serializer->Serialize(MakeProtocolRequest( + "15160585-8ADE-4D3C-839B-1281A6035D1F", "prod_id", "1.0", "lang", + "channel", "OS", "cacheable", {{"extra", "params"}}, &attributes, {})); + constexpr char regex[] = + R"({"request":{"@os":"\w+","@updater":"prod_id",)" + R"("acceptformat":"crx2,crx3","arch":"\w+","dedup":"cr",)" + R"("dlpref":"cacheable","domainjoined":true,"extra":"params",)" + R"("hw":{"physmemory":\d+},"lang":"lang","nacl_arch":"[-\w]+",)" + R"("os":{"arch":"[,-.\w]+","platform":"OS",("sp":"[\s\w]+",)?)" + R"("version":"[-.\w]+"},"prodchannel":"channel","prodversion":"1.0",)" + R"("protocol":"3.1","requestid":"{[-\w]{36}}","sessionid":"{[-\w]{36}}",)" +#if defined(GOOGLE_CHROME_BUILD) + R"("updater":{"autoupdatecheckenabled":false,"ismachine":true,)" + R"("lastchecked":2,"laststarted":1,"name":"Omaha","updatepolicy":-1,)" + R"("version":"1\.2\.3\.4"},)" +#endif // GOOGLE_CHROME_BUILD + R"("updaterchannel":"channel","updaterversion":"1.0"(,"wow64":true)?}})"; + EXPECT_TRUE(RE2::FullMatch(request, regex)) << request; +} + +} // namespace update_client
diff --git a/components/update_client/protocol_serializer_xml.cc b/components/update_client/protocol_serializer_xml.cc index af0bbc6..5cf61e4c 100644 --- a/components/update_client/protocol_serializer_xml.cc +++ b/components/update_client/protocol_serializer_xml.cc
@@ -181,6 +181,8 @@ base::StringAppendF(&msg, "\"%s\"", value.GetString().c_str()); else if (value.is_int()) base::StringAppendF(&msg, "\"%d\"", value.GetInt()); + else if (value.is_double()) + base::StringAppendF(&msg, "\"%.0f\"", value.GetDouble()); else NOTREACHED(); }
diff --git a/components/update_client/protocol_serializer_xml_unittest.cc b/components/update_client/protocol_serializer_xml_unittest.cc index 60bdd3c..9cc8b70 100644 --- a/components/update_client/protocol_serializer_xml_unittest.cc +++ b/components/update_client/protocol_serializer_xml_unittest.cc
@@ -1,10 +1,12 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. +// Copyright 2018 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <memory> #include <string> #include "components/update_client/protocol_serializer.h" +#include "components/update_client/protocol_serializer_xml.h" #include "components/update_client/updater_state.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/re2/src/re2/re2.h" @@ -13,11 +15,11 @@ namespace update_client { -TEST(SerializeRequest, Serialize) { +TEST(SerializeRequestXml, Serialize) { // When no updater state is provided, then check that the elements and // attributes related to the updater state are not serialized. const auto request = - ProtocolSerializer::Create()->Serialize(MakeProtocolRequest( + std::make_unique<ProtocolSerializerXml>()->Serialize(MakeProtocolRequest( "15160585-8ADE-4D3C-839B-1281A6035D1F", "prod_id", "1.0", "lang", "channel", "OS", "cacheable", {{"extra", "params"}}, nullptr, {})); constexpr char regex[] = @@ -28,15 +30,15 @@ R"(updater="prod_id" updaterversion="1\.0" prodversion="1\.0" )" R"(lang="lang" os="\w+" arch="\w+" nacl_arch="[-\w]+" (wow64="1" )?)" R"(updaterchannel="channel" prodchannel="channel" dlpref="cacheable">)" - R"(<hw physmemory="[0-9]+"/>)" + R"(<hw physmemory="\d+"/>)" R"(<os platform="OS" arch="[,-.\w]+" version="[-.\w]+"( sp="[\s\w]+")?/>)" R"(</request>)"; EXPECT_TRUE(RE2::FullMatch(request, regex)) << request; } -TEST(BuildProtocolRequest, DownloadPreference) { +TEST(SerializeRequestXml, DownloadPreference) { // Verifies that an empty |download_preference| is not serialized. - const auto serializer = ProtocolSerializer::Create(); + const auto serializer = std::make_unique<ProtocolSerializerXml>(); auto request = serializer->Serialize( MakeProtocolRequest("15160585-8ADE-4D3C-839B-1281A6035D1F", "", "", "", "", "", "", {}, nullptr, {})); @@ -51,8 +53,8 @@ // When present, updater state attributes are only serialized for Google builds, // except the |domainjoined| attribute, which is serialized in all cases. -TEST(BuildProtocolRequest, UpdaterStateAttributes) { - const auto serializer = ProtocolSerializer::Create(); +TEST(SerializeRequestXml, UpdaterStateAttributes) { + const auto serializer = std::make_unique<ProtocolSerializerXml>(); UpdaterState::Attributes attributes; attributes["ismachine"] = "1"; attributes["domainjoined"] = "1"; @@ -74,7 +76,7 @@ R"(lang="lang" os="\w+" arch="\w+" nacl_arch="[-\w]+" (wow64="1" )?)" R"(updaterchannel="channel" prodchannel="channel" dlpref="cacheable" )" R"(domainjoined="1">)" - R"(<hw physmemory="[0-9]+"/>)" + R"(<hw physmemory="\d+"/>)" R"(<os platform="OS" arch="[,-.\w]+" version="[-.\w]+"( sp="[\s\w]+")?/>)" #if defined(GOOGLE_CHROME_BUILD) R"(<updater name="Omaha" version="1\.2\.3\.4" lastchecked="2" )"
diff --git a/components/update_client/test_configurator.cc b/components/update_client/test_configurator.cc index 87e5596..0c04089 100644 --- a/components/update_client/test_configurator.cc +++ b/components/update_client/test_configurator.cc
@@ -38,6 +38,7 @@ ondemand_time_(0), enabled_cup_signing_(false), enabled_component_updates_(true), + use_JSON_(false), test_shared_loader_factory_( base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( &test_url_loader_factory_)) { @@ -182,6 +183,10 @@ app_guid_ = app_guid; } +void TestConfigurator::SetUseJSON(bool use_JSON) { + use_JSON_ = use_JSON; +} + PrefService* TestConfigurator::GetPrefService() const { return nullptr; } @@ -204,6 +209,8 @@ std::unique_ptr<ProtocolHandlerFactory> TestConfigurator::GetProtocolHandlerFactory() const { + if (use_JSON_) + return std::make_unique<ProtocolHandlerFactoryJSON>(); return std::make_unique<ProtocolHandlerFactoryXml>(); }
diff --git a/components/update_client/test_configurator.h b/components/update_client/test_configurator.h index 6769892..7da9e28 100644 --- a/components/update_client/test_configurator.h +++ b/components/update_client/test_configurator.h
@@ -113,6 +113,7 @@ void SetUpdateCheckUrl(const GURL& url); void SetPingUrl(const GURL& url); void SetAppGuid(const std::string& app_guid); + void SetUseJSON(bool use_JSON); network::TestURLLoaderFactory* test_url_loader_factory() { return &test_url_loader_factory_; } @@ -132,6 +133,7 @@ GURL update_check_url_; GURL ping_url_; std::string app_guid_; + bool use_JSON_; std::unique_ptr<service_manager::TestConnectorFactory> connector_factory_; std::unique_ptr<service_manager::Connector> connector_;
diff --git a/components/update_client/update_checker_unittest.cc b/components/update_client/update_checker_unittest.cc index d98955b3..ab65a9c 100644 --- a/components/update_client/update_checker_unittest.cc +++ b/components/update_client/update_checker_unittest.cc
@@ -6,11 +6,13 @@ #include <map> #include <memory> +#include <tuple> #include <utility> #include <vector> #include "base/bind.h" #include "base/files/file_util.h" +#include "base/json/json_reader.h" #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/optional.h" @@ -109,8 +111,10 @@ } // namespace -class UpdateCheckerTest : public testing::Test, - public testing::WithParamInterface<bool> { +using UpdateCheckTestParams = + std::tuple<bool /*is_foreground*/, bool /*use_JSON*/>; + +class UpdateCheckerTest : public testing::TestWithParam<UpdateCheckTestParams> { public: UpdateCheckerTest(); ~UpdateCheckerTest() override; @@ -147,6 +151,9 @@ scoped_refptr<UpdateContext> update_context_; + bool use_JSON_ = false; + bool is_foreground_ = false; + private: scoped_refptr<UpdateContext> MakeMockUpdateContext() const; @@ -156,7 +163,10 @@ DISALLOW_COPY_AND_ASSIGN(UpdateCheckerTest); }; -INSTANTIATE_TEST_CASE_P(IsForeground, UpdateCheckerTest, testing::Bool()); +// This test is parameterized for |is_foreground and |use_JSON|. +INSTANTIATE_TEST_CASE_P(Parameterized, + UpdateCheckerTest, + testing::Combine(testing::Bool(), testing::Bool())); UpdateCheckerTest::UpdateCheckerTest() : scoped_task_environment_( @@ -166,7 +176,11 @@ } void UpdateCheckerTest::SetUp() { + std::tie(is_foreground_, use_JSON_) = GetParam(); + config_ = base::MakeRefCounted<TestConfigurator>(); + config_->SetUseJSON(use_JSON_); + pref_ = std::make_unique<TestingPrefServiceSimple>(); activity_data_service_ = std::make_unique<ActivityDataServiceTest>(); PersistedData::RegisterPrefs(pref_->registry()); @@ -182,6 +196,7 @@ error_ = 0; retry_after_sec_ = 0; update_context_ = MakeMockUpdateContext(); + update_context_->is_foreground = is_foreground_; } void UpdateCheckerTest::TearDown() { @@ -245,10 +260,10 @@ TEST_P(UpdateCheckerTest, UpdateCheckSuccess) { EXPECT_TRUE(post_interceptor_->ExpectRequest( std::make_unique<PartialMatch>("updatecheck"), - test_file("updatecheck_reply_1.xml"))); + test_file(use_JSON_ ? "updatecheck_reply_1.json" + : "updatecheck_reply_1.xml"))); update_checker_ = UpdateChecker::Create(config_, metadata_.get()); - update_context_->is_foreground = GetParam(); IdToComponentPtrMap components; components[kUpdateItemId] = MakeComponent(); @@ -270,30 +285,102 @@ // Sanity check the request. const auto& request = post_interceptor_->GetRequestBody(0); - EXPECT_THAT(request, testing::HasSubstr( - R"(request protocol="3.1" dedup="cr" )" - R"(acceptformat="crx2,crx3" extra="params" )" - R"(testrequest="1")")); - // The request must not contain any "dlpref" in the default case. - EXPECT_THAT(request, testing::Not(testing::HasSubstr(R"( dlpref=")"))); - EXPECT_THAT(request, - testing::HasSubstr( - std::string(R"(<app appid=")") + kUpdateItemId + - R"(" version="0.9" brand="TEST")" + - (GetParam() ? R"( installsource="ondemand")" : "") + - R"( ap="some_ap" enabled="1"><updatecheck/><ping r="-2"/>)")); - EXPECT_THAT( - request, - testing::HasSubstr(R"(<packages><package fp="fp1"/></packages></app>)")); - EXPECT_THAT(request, testing::HasSubstr("<hw physmemory=")); + if (use_JSON_) { + const auto root = base::JSONReader().Read(request); + const auto* request = root->FindKey("request"); + ASSERT_TRUE(request); + EXPECT_TRUE(request->FindKey("@os")); + EXPECT_EQ("fake_prodid", request->FindKey("@updater")->GetString()); + EXPECT_EQ("crx2,crx3", request->FindKey("acceptformat")->GetString()); + EXPECT_TRUE(request->FindKey("arch")); + EXPECT_EQ("cr", request->FindKey("dedup")->GetString()); + EXPECT_EQ("params", request->FindKey("extra")->GetString()); + EXPECT_LT(0, request->FindPath({"hw", "physmemory"})->GetInt()); + EXPECT_EQ("fake_lang", request->FindKey("lang")->GetString()); + EXPECT_TRUE(request->FindKey("nacl_arch")); + EXPECT_EQ("fake_channel_string", + request->FindKey("prodchannel")->GetString()); + EXPECT_EQ("30.0", request->FindKey("prodversion")->GetString()); + EXPECT_EQ("3.1", request->FindKey("protocol")->GetString()); + EXPECT_TRUE(request->FindKey("requestid")); + EXPECT_TRUE(request->FindKey("sessionid")); + EXPECT_EQ("1", request->FindKey("testrequest")->GetString()); + EXPECT_EQ("fake_channel_string", + request->FindKey("updaterchannel")->GetString()); + EXPECT_EQ("30.0", request->FindKey("updaterversion")->GetString()); - // Tests that the product id is injected correctly from the configurator. - EXPECT_THAT(request, testing::HasSubstr( - R"( updater="fake_prodid" updaterversion="30.0")" - R"( prodversion="30.0" )")); + // No "dlpref" is sent by default. + EXPECT_FALSE(request->FindKey("dlpref")); - // Tests that there is a sessionid attribute. - EXPECT_THAT(request, testing::HasSubstr(" sessionid=")); + EXPECT_TRUE(request->FindPath({"os", "arch"})->is_string()); + EXPECT_EQ("Fake Operating System", + request->FindPath({"os", "platform"})->GetString()); + EXPECT_TRUE(request->FindPath({"os", "version"})->is_string()); + + const auto& app = request->FindKey("app")->GetList()[0]; + EXPECT_EQ(kUpdateItemId, app.FindKey("appid")->GetString()); + EXPECT_EQ("0.9", app.FindKey("version")->GetString()); + EXPECT_EQ("TEST", app.FindKey("brand")->GetString()); + if (is_foreground_) + EXPECT_EQ("ondemand", app.FindKey("installsource")->GetString()); + EXPECT_EQ("some_ap", app.FindKey("ap")->GetString()); + EXPECT_EQ(true, app.FindKey("enabled")->GetBool()); + EXPECT_TRUE(app.FindKey("updatecheck")); + EXPECT_TRUE(app.FindKey("ping")); + EXPECT_EQ(-2, app.FindPath({"ping", "r"})->GetInt()); + EXPECT_EQ("fp1", app.FindPath({"packages", "package"}) + ->GetList()[0] + .FindKey("fp") + ->GetString()); + +#if (OS_WIN) + EXPECT_TRUE(request->FindKey("domainjoined")); +#if defined(GOOGLE_CHROME_BUILD) + const auto* updater = request->FindKey("updater"); + EXPECT_TRUE(updater); + EXPECT_EQ("Omaha", updater->FindKey("name")->GetString()); + EXPECT_TRUE(updater->FindKey("autoupdatecheckenabled")->is_bool()); + EXPECT_TRUE(updater->FindKey("ismachine")->is_bool()); + EXPECT_TRUE(updater->FindKey("lastchecked")->is_int()); + EXPECT_TRUE(updater->FindKey("laststarted")->is_int()); + EXPECT_TRUE(updater->FindKey("updatepolicy")->is_int()); + EXPECT_TRUE(updater->FindKey("version")->is_string()); +#endif // GOOGLE_CHROME_BUILD +#endif // OS_WINDOWS + } else { + EXPECT_THAT(request, testing::HasSubstr( + R"(request protocol="3.1" dedup="cr" )" + R"(acceptformat="crx2,crx3" extra="params" )" + R"(testrequest="1")")); + // The request must not contain any "dlpref" in the default case. + EXPECT_THAT(request, testing::Not(testing::HasSubstr(R"( dlpref=")"))); + EXPECT_THAT( + request, + testing::HasSubstr( + std::string(R"(<app appid=")") + kUpdateItemId + + R"(" version="0.9" brand="TEST")" + + (is_foreground_ ? R"( installsource="ondemand")" : "") + + R"( ap="some_ap" enabled="1"><updatecheck/><ping r="-2"/>)")); + EXPECT_THAT(request, + testing::HasSubstr( + R"(<packages><package fp="fp1"/></packages></app>)")); + EXPECT_THAT(request, testing::HasSubstr("<hw physmemory=")); + + // Tests that the product id is injected correctly from the configurator. + EXPECT_THAT(request, testing::HasSubstr( + R"( updater="fake_prodid" updaterversion="30.0")" + R"( prodversion="30.0" )")); + // Tests that there is a sessionid attribute. + EXPECT_THAT(request, testing::HasSubstr(" sessionid=")); +#if (OS_WIN) + EXPECT_THAT(request, testing::HasSubstr(" domainjoined=")); +#if defined(GOOGLE_CHROME_BUILD) + // Check the Omaha updater state data in the request. + EXPECT_THAT(request, testing::HasSubstr("<updater ")); + EXPECT_THAT(request, testing::HasSubstr(R"( name="Omaha" )")); +#endif // GOOGLE_CHROME_BUILD +#endif // OS_WINDOWS + } // Sanity check the arguments of the callback after parsing. EXPECT_EQ(ErrorCategory::kNone, error_category_); @@ -311,22 +398,13 @@ EXPECT_EQ(GURL("http://localhost/download/"), result.crx_urls.front()); EXPECT_STREQ("this", result.action_run.c_str()); -#if (OS_WIN) - EXPECT_THAT(request, testing::HasSubstr(" domainjoined=")); -#if defined(GOOGLE_CHROME_BUILD) - // Check the Omaha updater state data in the request. - EXPECT_THAT(request, testing::HasSubstr("<updater ")); - EXPECT_THAT(request, testing::HasSubstr(R"( name="Omaha" )")); -#endif // GOOGLE_CHROME_BUILD -#endif // OS_WINDOWS - // Check the DDOS protection header values. const auto extra_request_headers = std::get<1>(post_interceptor_->GetRequests()[0]); EXPECT_TRUE(extra_request_headers.HasHeader("X-Goog-Update-Interactivity")); std::string header; extra_request_headers.GetHeader("X-Goog-Update-Interactivity", &header); - EXPECT_STREQ(GetParam() ? "fg" : "bg", header.c_str()); + EXPECT_STREQ(is_foreground_ ? "fg" : "bg", header.c_str()); extra_request_headers.GetHeader("X-Goog-Update-Updater", &header); EXPECT_STREQ("fake_prodid-30.0", header.c_str()); extra_request_headers.GetHeader("X-Goog-Update-AppId", &header); @@ -334,10 +412,11 @@ } // Tests that an invalid "ap" is not serialized. -TEST_F(UpdateCheckerTest, UpdateCheckInvalidAp) { +TEST_P(UpdateCheckerTest, UpdateCheckInvalidAp) { EXPECT_TRUE(post_interceptor_->ExpectRequest( std::make_unique<PartialMatch>("updatecheck"), - test_file("updatecheck_reply_1.xml"))); + test_file(use_JSON_ ? "updatecheck_reply_1.json" + : "updatecheck_reply_1.xml"))); update_checker_ = UpdateChecker::Create(config_, metadata_.get()); @@ -356,19 +435,47 @@ RunThreads(); const auto request = post_interceptor_->GetRequestBody(0); - EXPECT_THAT(request, testing::HasSubstr( - std::string(R"(app appid=")") + kUpdateItemId + - R"(" version="0.9" brand="TEST" enabled="1">)" + - R"(<updatecheck/><ping r="-2"/>)")); - EXPECT_THAT( - request, - testing::HasSubstr(R"(<packages><package fp="fp1"/></packages></app>)")); + if (use_JSON_) { + const auto root = base::JSONReader().Read(request); + const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; + EXPECT_EQ(kUpdateItemId, app.FindKey("appid")->GetString()); + EXPECT_EQ("0.9", app.FindKey("version")->GetString()); + EXPECT_EQ("TEST", app.FindKey("brand")->GetString()); + if (is_foreground_) + EXPECT_EQ("ondemand", app.FindKey("installsource")->GetString()); + EXPECT_FALSE(app.FindKey("ap")); + EXPECT_EQ(true, app.FindKey("enabled")->GetBool()); + EXPECT_TRUE(app.FindKey("updatecheck")); + EXPECT_TRUE(app.FindKey("ping")); + EXPECT_EQ(-2, app.FindPath({"ping", "r"})->GetInt()); + EXPECT_EQ("fp1", app.FindPath({"packages", "package"}) + ->GetList()[0] + .FindKey("fp") + ->GetString()); + } else { + if (is_foreground_) { + EXPECT_THAT(request, testing::HasSubstr( + std::string(R"(app appid=")") + kUpdateItemId + + R"(" version="0.9" brand="TEST" )" + R"(installsource="ondemand" enabled="1">)" + R"(<updatecheck/><ping r="-2"/>)")); + } else { + EXPECT_THAT(request, testing::HasSubstr( + std::string(R"(app appid=")") + kUpdateItemId + + R"(" version="0.9" brand="TEST" enabled="1">)" + R"(<updatecheck/><ping r="-2"/>)")); + } + EXPECT_THAT(request, + testing::HasSubstr( + R"(<packages><package fp="fp1"/></packages></app>)")); + } } -TEST_F(UpdateCheckerTest, UpdateCheckSuccessNoBrand) { +TEST_P(UpdateCheckerTest, UpdateCheckSuccessNoBrand) { EXPECT_TRUE(post_interceptor_->ExpectRequest( std::make_unique<PartialMatch>("updatecheck"), - test_file("updatecheck_reply_1.xml"))); + test_file(use_JSON_ ? "updatecheck_reply_1.json" + : "updatecheck_reply_1.xml"))); config_->SetBrand("TOOLONG"); // Sets an invalid brand code. update_checker_ = UpdateChecker::Create(config_, metadata_.get()); @@ -384,18 +491,43 @@ RunThreads(); const auto request = post_interceptor_->GetRequestBody(0); - EXPECT_THAT( - request, - testing::HasSubstr( - std::string(R"(<app appid=")") + kUpdateItemId + - R"(" version="0.9" enabled="1"><updatecheck/><ping r="-2"/>)")); - EXPECT_THAT( - request, - testing::HasSubstr(R"(<packages><package fp="fp1"/></packages></app>)")); + + if (use_JSON_) { + const auto root = base::JSONReader().Read(request); + const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; + EXPECT_EQ(kUpdateItemId, app.FindKey("appid")->GetString()); + EXPECT_EQ("0.9", app.FindKey("version")->GetString()); + EXPECT_FALSE(app.FindKey("brand")); + if (is_foreground_) + EXPECT_EQ("ondemand", app.FindKey("installsource")->GetString()); + EXPECT_EQ(true, app.FindKey("enabled")->GetBool()); + EXPECT_TRUE(app.FindKey("updatecheck")); + EXPECT_TRUE(app.FindKey("ping")); + EXPECT_EQ(-2, app.FindPath({"ping", "r"})->GetInt()); + EXPECT_EQ("fp1", app.FindPath({"packages", "package"}) + ->GetList()[0] + .FindKey("fp") + ->GetString()); + } else { + if (is_foreground_) { + EXPECT_THAT(request, testing::HasSubstr( + std::string(R"(app appid=")") + kUpdateItemId + + R"(" version="0.9" installsource="ondemand" )" + R"(enabled="1"><updatecheck/><ping r="-2"/>)")); + } else { + EXPECT_THAT(request, testing::HasSubstr( + std::string(R"(app appid=")") + kUpdateItemId + + R"(" version="0.9" enabled="1">)" + + R"(<updatecheck/><ping r="-2"/>)")); + } + EXPECT_THAT(request, + testing::HasSubstr( + R"(<packages><package fp="fp1"/></packages></app>)")); + } } // Simulates a 403 server response error. -TEST_F(UpdateCheckerTest, UpdateCheckError) { +TEST_P(UpdateCheckerTest, UpdateCheckError) { EXPECT_TRUE(post_interceptor_->ExpectRequest( std::make_unique<PartialMatch>("updatecheck"), net::HTTP_FORBIDDEN)); @@ -420,10 +552,11 @@ EXPECT_FALSE(results_); } -TEST_F(UpdateCheckerTest, UpdateCheckDownloadPreference) { +TEST_P(UpdateCheckerTest, UpdateCheckDownloadPreference) { EXPECT_TRUE(post_interceptor_->ExpectRequest( std::make_unique<PartialMatch>("updatecheck"), - test_file("updatecheck_reply_1.xml"))); + test_file(use_JSON_ ? "updatecheck_reply_1.json" + : "updatecheck_reply_1.xml"))); config_->SetDownloadPreference(string("cacheable")); @@ -441,16 +574,23 @@ // The request must contain dlpref="cacheable". const auto request = post_interceptor_->GetRequestBody(0); - EXPECT_THAT(request, testing::HasSubstr(R"( dlpref="cacheable")")); + if (use_JSON_) { + const auto root = base::JSONReader().Read(request); + EXPECT_EQ("cacheable", + root->FindKey("request")->FindKey("dlpref")->GetString()); + } else { + EXPECT_THAT(request, testing::HasSubstr(R"( dlpref="cacheable")")); + } } // This test is checking that an update check signed with CUP fails, since there // is currently no entity that can respond with a valid signed response. // A proper CUP test requires network mocks, which are not available now. -TEST_F(UpdateCheckerTest, UpdateCheckCupError) { +TEST_P(UpdateCheckerTest, UpdateCheckCupError) { EXPECT_TRUE(post_interceptor_->ExpectRequest( std::make_unique<PartialMatch>("updatecheck"), - test_file("updatecheck_reply_1.xml"))); + test_file(use_JSON_ ? "updatecheck_reply_1.json" + : "updatecheck_reply_1.xml"))); config_->SetEnabledCupSigning(true); update_checker_ = UpdateChecker::Create(config_, metadata_.get()); @@ -472,13 +612,40 @@ // Sanity check the request. const auto& request = post_interceptor_->GetRequestBody(0); - EXPECT_THAT(request, testing::HasSubstr( - std::string(R"(<app appid=")") + kUpdateItemId + - R"(" version="0.9" brand="TEST" enabled="1">)" + - R"(<updatecheck/><ping r="-2"/>)")); - EXPECT_THAT( - request, - testing::HasSubstr(R"(<packages><package fp="fp1"/></packages></app>)")); + if (use_JSON_) { + const auto root = base::JSONReader().Read(request); + const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; + EXPECT_EQ(kUpdateItemId, app.FindKey("appid")->GetString()); + EXPECT_EQ("0.9", app.FindKey("version")->GetString()); + EXPECT_EQ("TEST", app.FindKey("brand")->GetString()); + if (is_foreground_) + EXPECT_EQ("ondemand", app.FindKey("installsource")->GetString()); + EXPECT_EQ(true, app.FindKey("enabled")->GetBool()); + EXPECT_TRUE(app.FindKey("updatecheck")); + EXPECT_TRUE(app.FindKey("ping")); + EXPECT_EQ(-2, app.FindPath({"ping", "r"})->GetInt()); + EXPECT_EQ("fp1", app.FindPath({"packages", "package"}) + ->GetList()[0] + .FindKey("fp") + ->GetString()); + + } else { + if (is_foreground_) { + EXPECT_THAT(request, testing::HasSubstr( + std::string(R"(<app appid=")") + kUpdateItemId + + R"(" version="0.9" brand="TEST" )" + R"(installsource="ondemand" enabled="1">)" + R"(<updatecheck/><ping r="-2"/>)")); + } else { + EXPECT_THAT(request, testing::HasSubstr( + std::string(R"(<app appid=")") + kUpdateItemId + + R"(" version="0.9" brand="TEST" enabled="1">)" + R"(<updatecheck/><ping r="-2"/>)")); + } + EXPECT_THAT(request, + testing::HasSubstr( + R"(<packages><package fp="fp1"/></packages></app>)")); + } // Expect an error since the response is not trusted. EXPECT_EQ(ErrorCategory::kUpdateCheck, error_category_); @@ -488,7 +655,7 @@ // Tests that the UpdateCheckers will not make an update check for a // component that requires encryption when the update check URL is unsecure. -TEST_F(UpdateCheckerTest, UpdateCheckRequiresEncryptionError) { +TEST_P(UpdateCheckerTest, UpdateCheckRequiresEncryptionError) { config_->SetUpdateCheckUrl(GURL("http:\\foo\bar")); update_checker_ = UpdateChecker::Create(config_, metadata_.get()); @@ -512,13 +679,13 @@ // Tests that the PersistedData will get correctly update and reserialize // the elapsed_days value. -TEST_F(UpdateCheckerTest, UpdateCheckLastRollCall) { +TEST_P(UpdateCheckerTest, UpdateCheckLastRollCall) { + const char* filename = + use_JSON_ ? "updatecheck_reply_4.json" : "updatecheck_reply_4.xml"; EXPECT_TRUE(post_interceptor_->ExpectRequest( - std::make_unique<PartialMatch>("updatecheck"), - test_file("updatecheck_reply_4.xml"))); + std::make_unique<PartialMatch>("updatecheck"), test_file(filename))); EXPECT_TRUE(post_interceptor_->ExpectRequest( - std::make_unique<PartialMatch>("updatecheck"), - test_file("updatecheck_reply_4.xml"))); + std::make_unique<PartialMatch>("updatecheck"), test_file(filename))); update_checker_ = UpdateChecker::Create(config_, metadata_.get()); @@ -546,22 +713,34 @@ << post_interceptor_->GetRequestsAsString(); ASSERT_EQ(2, post_interceptor_->GetCount()) << post_interceptor_->GetRequestsAsString(); - EXPECT_THAT(post_interceptor_->GetRequestBody(0), - testing::HasSubstr(R"(<ping r="5")")); - EXPECT_THAT(post_interceptor_->GetRequestBody(1), - testing::HasSubstr(R"(<ping rd="3383" ping_freshness=)")); + + if (use_JSON_) { + const auto root1 = + base::JSONReader().Read(post_interceptor_->GetRequestBody(0)); + const auto& app1 = root1->FindKey("request")->FindKey("app")->GetList()[0]; + EXPECT_EQ(5, app1.FindPath({"ping", "r"})->GetInt()); + const auto root2 = + base::JSONReader().Read(post_interceptor_->GetRequestBody(1)); + const auto& app2 = root2->FindKey("request")->FindKey("app")->GetList()[0]; + EXPECT_EQ(3383, app2.FindPath({"ping", "rd"})->GetInt()); + EXPECT_TRUE(app2.FindPath({"ping", "ping_freshness"})->is_string()); + } else { + EXPECT_THAT(post_interceptor_->GetRequestBody(0), + testing::HasSubstr(R"(<ping r="5")")); + EXPECT_THAT(post_interceptor_->GetRequestBody(1), + testing::HasSubstr(R"(<ping rd="3383" ping_freshness=)")); + } } -TEST_F(UpdateCheckerTest, UpdateCheckLastActive) { +TEST_P(UpdateCheckerTest, UpdateCheckLastActive) { + const char* filename = + use_JSON_ ? "updatecheck_reply_4.json" : "updatecheck_reply_4.xml"; EXPECT_TRUE(post_interceptor_->ExpectRequest( - std::make_unique<PartialMatch>("updatecheck"), - test_file("updatecheck_reply_4.xml"))); + std::make_unique<PartialMatch>("updatecheck"), test_file(filename))); EXPECT_TRUE(post_interceptor_->ExpectRequest( - std::make_unique<PartialMatch>("updatecheck"), - test_file("updatecheck_reply_4.xml"))); + std::make_unique<PartialMatch>("updatecheck"), test_file(filename))); EXPECT_TRUE(post_interceptor_->ExpectRequest( - std::make_unique<PartialMatch>("updatecheck"), - test_file("updatecheck_reply_4.xml"))); + std::make_unique<PartialMatch>("updatecheck"), test_file(filename))); update_checker_ = UpdateChecker::Create(config_, metadata_.get()); @@ -606,16 +785,42 @@ << post_interceptor_->GetRequestsAsString(); ASSERT_EQ(3, post_interceptor_->GetCount()) << post_interceptor_->GetRequestsAsString(); - EXPECT_THAT(post_interceptor_->GetRequestBody(0), - testing::HasSubstr(R"(<ping a="10" r="-2"/>)")); - EXPECT_THAT( - post_interceptor_->GetRequestBody(1), - testing::HasSubstr(R"(<ping ad="3383" rd="3383" ping_freshness=)")); - EXPECT_THAT(post_interceptor_->GetRequestBody(2), - testing::HasSubstr(R"(<ping rd="3383" ping_freshness=)")); + + if (use_JSON_) { + { + const auto root = + base::JSONReader().Read(post_interceptor_->GetRequestBody(0)); + const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; + EXPECT_EQ(10, app.FindPath({"ping", "a"})->GetInt()); + EXPECT_EQ(-2, app.FindPath({"ping", "r"})->GetInt()); + } + { + const auto root = + base::JSONReader().Read(post_interceptor_->GetRequestBody(1)); + const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; + EXPECT_EQ(3383, app.FindPath({"ping", "ad"})->GetInt()); + EXPECT_EQ(3383, app.FindPath({"ping", "rd"})->GetInt()); + EXPECT_TRUE(app.FindPath({"ping", "ping_freshness"})->is_string()); + } + { + const auto root = + base::JSONReader().Read(post_interceptor_->GetRequestBody(2)); + const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; + EXPECT_EQ(3383, app.FindPath({"ping", "rd"})->GetInt()); + EXPECT_TRUE(app.FindPath({"ping", "ping_freshness"})->is_string()); + } + } else { + EXPECT_THAT(post_interceptor_->GetRequestBody(0), + testing::HasSubstr(R"(<ping a="10" r="-2"/>)")); + EXPECT_THAT( + post_interceptor_->GetRequestBody(1), + testing::HasSubstr(R"(<ping ad="3383" rd="3383" ping_freshness=)")); + EXPECT_THAT(post_interceptor_->GetRequestBody(2), + testing::HasSubstr(R"(<ping rd="3383" ping_freshness=)")); + } } -TEST_F(UpdateCheckerTest, UpdateCheckInstallSource) { +TEST_P(UpdateCheckerTest, UpdateCheckInstallSource) { update_checker_ = UpdateChecker::Create(config_, metadata_.get()); IdToComponentPtrMap components; @@ -624,68 +829,113 @@ auto& component = components[kUpdateItemId]; auto crx_component = component->crx_component(); - EXPECT_TRUE(post_interceptor_->ExpectRequest( - std::make_unique<PartialMatch>("updatecheck"), - test_file("updatecheck_reply_1.xml"))); - update_checker_->CheckForUpdates( - update_context_->session_id, {kUpdateItemId}, components, {}, false, - base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete, - base::Unretained(this))); - RunThreads(); + if (is_foreground_) { + { + auto post_interceptor = std::make_unique<URLLoaderPostInterceptor>( + config_->test_url_loader_factory()); + EXPECT_TRUE(post_interceptor->ExpectRequest( + std::make_unique<PartialMatch>("updatecheck"), + test_file(use_JSON_ ? "updatecheck_reply_1.json" + : "updatecheck_reply_1.xml"))); + update_checker_->CheckForUpdates( + update_context_->session_id, {kUpdateItemId}, components, {}, false, + base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete, + base::Unretained(this))); + RunThreads(); + const auto& request = post_interceptor->GetRequestBody(0); + if (use_JSON_) { + const auto root = base::JSONReader().Read(request); + const auto& app = + root->FindKey("request")->FindKey("app")->GetList()[0]; + EXPECT_EQ("ondemand", app.FindKey("installsource")->GetString()); + EXPECT_FALSE(app.FindKey("installedby")); + } else { + EXPECT_THAT(request, testing::HasSubstr(R"(installsource="ondemand")")); + EXPECT_THAT(request, + testing::Not(testing::HasSubstr(R"(installedby=)"))); + } + } + { + auto post_interceptor = std::make_unique<URLLoaderPostInterceptor>( + config_->test_url_loader_factory()); + EXPECT_TRUE(post_interceptor->ExpectRequest( + std::make_unique<PartialMatch>("updatecheck"), + test_file(use_JSON_ ? "updatecheck_reply_1.json" + : "updatecheck_reply_1.xml"))); + crx_component->install_source = "sideload"; + crx_component->install_location = "policy"; + component->set_crx_component(*crx_component); + update_checker_->CheckForUpdates( + update_context_->session_id, {kUpdateItemId}, components, {}, false, + base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete, + base::Unretained(this))); + RunThreads(); + const auto& request = post_interceptor->GetRequestBody(0); + if (use_JSON_) { + const auto root = base::JSONReader().Read(request); + const auto& app = + root->FindKey("request")->FindKey("app")->GetList()[0]; + EXPECT_EQ("sideload", app.FindKey("installsource")->GetString()); + EXPECT_EQ("policy", app.FindKey("installedby")->GetString()); + } else { + EXPECT_THAT(request, testing::HasSubstr(R"(installsource="sideload")")); + EXPECT_THAT(request, testing::HasSubstr(R"(installedby="policy")")); + } + } + return; + } - EXPECT_THAT(post_interceptor_->GetRequestBody(0), - testing::Not(testing::HasSubstr("installsource="))); - - update_context_->is_foreground = true; - EXPECT_TRUE(post_interceptor_->ExpectRequest( - std::make_unique<PartialMatch>("updatecheck"), - test_file("updatecheck_reply_1.xml"))); - update_checker_->CheckForUpdates( - update_context_->session_id, {kUpdateItemId}, components, {}, false, - base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete, - base::Unretained(this))); - RunThreads(); - - const auto& body1 = post_interceptor_->GetRequestBody(1); - EXPECT_THAT(body1, testing::HasSubstr(R"(installsource="ondemand")")); - EXPECT_THAT(body1, testing::Not(testing::HasSubstr(R"(installedby=)"))); - - update_context_->is_foreground = false; - crx_component->install_source = "webstore"; - crx_component->install_location = "external"; - component->set_crx_component(*crx_component); - EXPECT_TRUE(post_interceptor_->ExpectRequest( - std::make_unique<PartialMatch>("updatecheck"), - test_file("updatecheck_reply_1.xml"))); - update_checker_->CheckForUpdates( - update_context_->session_id, {kUpdateItemId}, components, {}, false, - base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete, - base::Unretained(this))); - RunThreads(); - - const auto& body2 = post_interceptor_->GetRequestBody(2); - EXPECT_THAT(body2, testing::HasSubstr(R"(installsource="webstore")")); - EXPECT_THAT(body2, testing::HasSubstr(R"(installedby="external")")); - - update_context_->is_foreground = true; - crx_component->install_source = "sideload"; - crx_component->install_location = "policy"; - component->set_crx_component(*crx_component); - EXPECT_TRUE(post_interceptor_->ExpectRequest( - std::make_unique<PartialMatch>("updatecheck"), - test_file("updatecheck_reply_1.xml"))); - update_checker_->CheckForUpdates( - update_context_->session_id, {kUpdateItemId}, components, {}, false, - base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete, - base::Unretained(this))); - RunThreads(); - - const auto& body3 = post_interceptor_->GetRequestBody(3); - EXPECT_THAT(body3, testing::HasSubstr(R"(installsource="sideload")")); - EXPECT_THAT(body3, testing::HasSubstr(R"(installedby="policy")")); + DCHECK(!is_foreground_); + { + auto post_interceptor = std::make_unique<URLLoaderPostInterceptor>( + config_->test_url_loader_factory()); + EXPECT_TRUE(post_interceptor->ExpectRequest( + std::make_unique<PartialMatch>("updatecheck"), + test_file(use_JSON_ ? "updatecheck_reply_1.json" + : "updatecheck_reply_1.xml"))); + update_checker_->CheckForUpdates( + update_context_->session_id, {kUpdateItemId}, components, {}, false, + base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete, + base::Unretained(this))); + RunThreads(); + const auto& request = post_interceptor->GetRequestBody(0); + if (use_JSON_) { + const auto root = base::JSONReader().Read(request); + const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; + EXPECT_FALSE(app.FindKey("installsource")); + } else { + EXPECT_THAT(request, testing::Not(testing::HasSubstr("installsource="))); + } + } + { + auto post_interceptor = std::make_unique<URLLoaderPostInterceptor>( + config_->test_url_loader_factory()); + EXPECT_TRUE(post_interceptor->ExpectRequest( + std::make_unique<PartialMatch>("updatecheck"), + test_file(use_JSON_ ? "updatecheck_reply_1.json" + : "updatecheck_reply_1.xml"))); + crx_component->install_source = "webstore"; + crx_component->install_location = "external"; + component->set_crx_component(*crx_component); + update_checker_->CheckForUpdates( + update_context_->session_id, {kUpdateItemId}, components, {}, false, + base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete, + base::Unretained(this))); + RunThreads(); + const auto& request = post_interceptor->GetRequestBody(0); + if (use_JSON_) { + const auto root = base::JSONReader().Read(request); + const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; + EXPECT_EQ("webstore", app.FindKey("installsource")->GetString()); + EXPECT_EQ("external", app.FindKey("installedby")->GetString()); + } else { + EXPECT_THAT(request, testing::HasSubstr(R"(installsource="webstore")")); + EXPECT_THAT(request, testing::HasSubstr(R"(installedby="external")")); + } + } } -TEST_F(UpdateCheckerTest, ComponentDisabled) { +TEST_P(UpdateCheckerTest, ComponentDisabled) { update_checker_ = UpdateChecker::Create(config_, metadata_.get()); IdToComponentPtrMap components; @@ -694,105 +944,179 @@ auto& component = components[kUpdateItemId]; auto crx_component = component->crx_component(); - EXPECT_TRUE(post_interceptor_->ExpectRequest( - std::make_unique<PartialMatch>("updatecheck"), - test_file("updatecheck_reply_1.xml"))); - update_checker_->CheckForUpdates( - update_context_->session_id, {kUpdateItemId}, components, {}, false, - base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete, - base::Unretained(this))); - RunThreads(); + { + auto post_interceptor = std::make_unique<URLLoaderPostInterceptor>( + config_->test_url_loader_factory()); + EXPECT_TRUE(post_interceptor->ExpectRequest( + std::make_unique<PartialMatch>("updatecheck"), + test_file(use_JSON_ ? "updatecheck_reply_1.json" + : "updatecheck_reply_1.xml"))); + update_checker_->CheckForUpdates( + update_context_->session_id, {kUpdateItemId}, components, {}, false, + base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete, + base::Unretained(this))); + RunThreads(); + const auto& request = post_interceptor->GetRequestBody(0); + if (use_JSON_) { + const auto root = base::JSONReader().Read(request); + const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; + EXPECT_EQ(true, app.FindKey("enabled")->GetBool()); + EXPECT_FALSE(app.FindKey("disabled")); + } else { + EXPECT_THAT(request, testing::HasSubstr(R"(enabled="1")")); + EXPECT_THAT(request, testing::Not(testing::HasSubstr("<disabled"))); + } + } - const auto& body0 = post_interceptor_->GetRequestBody(0); - EXPECT_THAT(body0, testing::HasSubstr(R"(enabled="1")")); - EXPECT_THAT(body0, testing::Not(testing::HasSubstr("<disabled"))); + { + crx_component->disabled_reasons = {}; + component->set_crx_component(*crx_component); + auto post_interceptor = std::make_unique<URLLoaderPostInterceptor>( + config_->test_url_loader_factory()); + EXPECT_TRUE(post_interceptor->ExpectRequest( + std::make_unique<PartialMatch>("updatecheck"), + test_file(use_JSON_ ? "updatecheck_reply_1.json" + : "updatecheck_reply_1.xml"))); + update_checker_->CheckForUpdates( + update_context_->session_id, {kUpdateItemId}, components, {}, false, + base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete, + base::Unretained(this))); + RunThreads(); + const auto& request = post_interceptor->GetRequestBody(0); + if (use_JSON_) { + const auto root = base::JSONReader().Read(request); + const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; + EXPECT_EQ(true, app.FindKey("enabled")->GetBool()); + EXPECT_FALSE(app.FindKey("disabled")); + } else { + EXPECT_THAT(request, testing::HasSubstr(R"(enabled="1")")); + EXPECT_THAT(request, testing::Not(testing::HasSubstr("<disabled"))); + } + } - crx_component->disabled_reasons = {}; - component->set_crx_component(*crx_component); - update_checker_ = UpdateChecker::Create(config_, metadata_.get()); - EXPECT_TRUE(post_interceptor_->ExpectRequest( - std::make_unique<PartialMatch>("updatecheck"), - test_file("updatecheck_reply_1.xml"))); - update_checker_->CheckForUpdates( - update_context_->session_id, {kUpdateItemId}, components, {}, false, - base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete, - base::Unretained(this))); - RunThreads(); + { + crx_component->disabled_reasons = {0}; + component->set_crx_component(*crx_component); + auto post_interceptor = std::make_unique<URLLoaderPostInterceptor>( + config_->test_url_loader_factory()); + EXPECT_TRUE(post_interceptor->ExpectRequest( + std::make_unique<PartialMatch>("updatecheck"), + test_file(use_JSON_ ? "updatecheck_reply_1.json" + : "updatecheck_reply_1.xml"))); + update_checker_->CheckForUpdates( + update_context_->session_id, {kUpdateItemId}, components, {}, false, + base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete, + base::Unretained(this))); + RunThreads(); + const auto& request = post_interceptor->GetRequestBody(0); + if (use_JSON_) { + const auto root = base::JSONReader().Read(request); + const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; + EXPECT_EQ(false, app.FindKey("enabled")->GetBool()); + const auto& disabled = app.FindKey("disabled")->GetList(); + EXPECT_EQ(1u, disabled.size()); + EXPECT_EQ(0, disabled[0].FindKey("reason")->GetInt()); + } else { + EXPECT_THAT(request, testing::HasSubstr(R"(enabled="0")")); + EXPECT_THAT(request, testing::HasSubstr(R"(<disabled reason="0")")); + } + } + { + crx_component->disabled_reasons = {1}; + component->set_crx_component(*crx_component); + auto post_interceptor = std::make_unique<URLLoaderPostInterceptor>( + config_->test_url_loader_factory()); + EXPECT_TRUE(post_interceptor->ExpectRequest( + std::make_unique<PartialMatch>("updatecheck"), + test_file(use_JSON_ ? "updatecheck_reply_1.json" + : "updatecheck_reply_1.xml"))); + update_checker_->CheckForUpdates( + update_context_->session_id, {kUpdateItemId}, components, {}, false, + base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete, + base::Unretained(this))); + RunThreads(); + const auto& request = post_interceptor->GetRequestBody(0); + if (use_JSON_) { + const auto root = base::JSONReader().Read(request); + const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; + EXPECT_EQ(false, app.FindKey("enabled")->GetBool()); + const auto& disabled = app.FindKey("disabled")->GetList(); + EXPECT_EQ(1u, disabled.size()); + EXPECT_EQ(1, disabled[0].FindKey("reason")->GetInt()); + } else { + EXPECT_THAT(request, testing::HasSubstr(R"(enabled="0")")); + EXPECT_THAT(request, testing::HasSubstr(R"(<disabled reason="1")")); + } + } - const auto& body1 = post_interceptor_->GetRequestBody(1); - EXPECT_THAT(body1, testing::HasSubstr(R"(enabled="1")")); - EXPECT_THAT(body1, testing::Not(testing::HasSubstr("<disabled"))); + { + crx_component->disabled_reasons = {4, 8, 16}; + component->set_crx_component(*crx_component); + auto post_interceptor = std::make_unique<URLLoaderPostInterceptor>( + config_->test_url_loader_factory()); + EXPECT_TRUE(post_interceptor->ExpectRequest( + std::make_unique<PartialMatch>("updatecheck"), + test_file(use_JSON_ ? "updatecheck_reply_1.json" + : "updatecheck_reply_1.xml"))); + update_checker_->CheckForUpdates( + update_context_->session_id, {kUpdateItemId}, components, {}, false, + base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete, + base::Unretained(this))); + RunThreads(); + const auto& request = post_interceptor->GetRequestBody(0); + if (use_JSON_) { + const auto root = base::JSONReader().Read(request); + const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; + EXPECT_EQ(false, app.FindKey("enabled")->GetBool()); + const auto& disabled = app.FindKey("disabled")->GetList(); + EXPECT_EQ(3u, disabled.size()); + EXPECT_EQ(4, disabled[0].FindKey("reason")->GetInt()); + EXPECT_EQ(8, disabled[1].FindKey("reason")->GetInt()); + EXPECT_EQ(16, disabled[2].FindKey("reason")->GetInt()); + } else { + EXPECT_THAT(request, testing::HasSubstr(R"(enabled="0")")); + EXPECT_THAT(request, testing::HasSubstr(R"(<disabled reason="4")")); + EXPECT_THAT(request, testing::HasSubstr(R"(<disabled reason="8")")); + EXPECT_THAT(request, testing::HasSubstr(R"(<disabled reason="16")")); + } + } - crx_component->disabled_reasons = {0}; - component->set_crx_component(*crx_component); - EXPECT_TRUE(post_interceptor_->ExpectRequest( - std::make_unique<PartialMatch>("updatecheck"), - test_file("updatecheck_reply_1.xml"))); - update_checker_->CheckForUpdates( - update_context_->session_id, {kUpdateItemId}, components, {}, false, - base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete, - base::Unretained(this))); - RunThreads(); - - const auto& body2 = post_interceptor_->GetRequestBody(2); - EXPECT_THAT(body2, testing::HasSubstr(R"(enabled="0")")); - EXPECT_THAT(body2, testing::HasSubstr(R"(<disabled reason="0")")); - - crx_component->disabled_reasons = {1}; - component->set_crx_component(*crx_component); - update_checker_ = UpdateChecker::Create(config_, metadata_.get()); - EXPECT_TRUE(post_interceptor_->ExpectRequest( - std::make_unique<PartialMatch>("updatecheck"), - test_file("updatecheck_reply_1.xml"))); - update_checker_->CheckForUpdates( - update_context_->session_id, {kUpdateItemId}, components, {}, false, - base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete, - base::Unretained(this))); - RunThreads(); - - const auto& body3 = post_interceptor_->GetRequestBody(3); - EXPECT_THAT(body3, testing::HasSubstr(R"(enabled="0")")); - EXPECT_THAT(body3, testing::HasSubstr(R"(<disabled reason="1")")); - - crx_component->disabled_reasons = {4, 8, 16}; - component->set_crx_component(*crx_component); - update_checker_ = UpdateChecker::Create(config_, metadata_.get()); - EXPECT_TRUE(post_interceptor_->ExpectRequest( - std::make_unique<PartialMatch>("updatecheck"), - test_file("updatecheck_reply_1.xml"))); - update_checker_->CheckForUpdates( - update_context_->session_id, {kUpdateItemId}, components, {}, false, - base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete, - base::Unretained(this))); - RunThreads(); - - const auto& body4 = post_interceptor_->GetRequestBody(4); - EXPECT_THAT(body4, testing::HasSubstr(R"(enabled="0")")); - EXPECT_THAT(body4, testing::HasSubstr(R"(<disabled reason="4")")); - EXPECT_THAT(body4, testing::HasSubstr(R"(<disabled reason="8")")); - EXPECT_THAT(body4, testing::HasSubstr(R"(<disabled reason="16")")); - - crx_component->disabled_reasons = {0, 4, 8, 16}; - component->set_crx_component(*crx_component); - update_checker_ = UpdateChecker::Create(config_, metadata_.get()); - EXPECT_TRUE(post_interceptor_->ExpectRequest( - std::make_unique<PartialMatch>("updatecheck"), - test_file("updatecheck_reply_1.xml"))); - update_checker_->CheckForUpdates( - update_context_->session_id, {kUpdateItemId}, components, {}, false, - base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete, - base::Unretained(this))); - RunThreads(); - - const auto& body5 = post_interceptor_->GetRequestBody(5); - EXPECT_THAT(body5, testing::HasSubstr(R"(enabled="0")")); - EXPECT_THAT(body5, testing::HasSubstr(R"(<disabled reason="0")")); - EXPECT_THAT(body5, testing::HasSubstr(R"(<disabled reason="4")")); - EXPECT_THAT(body5, testing::HasSubstr(R"(<disabled reason="8")")); - EXPECT_THAT(body5, testing::HasSubstr(R"(<disabled reason="16")")); + { + crx_component->disabled_reasons = {0, 4, 8, 16}; + component->set_crx_component(*crx_component); + auto post_interceptor = std::make_unique<URLLoaderPostInterceptor>( + config_->test_url_loader_factory()); + EXPECT_TRUE(post_interceptor->ExpectRequest( + std::make_unique<PartialMatch>("updatecheck"), + test_file(use_JSON_ ? "updatecheck_reply_1.json" + : "updatecheck_reply_1.xml"))); + update_checker_->CheckForUpdates( + update_context_->session_id, {kUpdateItemId}, components, {}, false, + base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete, + base::Unretained(this))); + RunThreads(); + const auto& request = post_interceptor->GetRequestBody(0); + if (use_JSON_) { + const auto root = base::JSONReader().Read(request); + const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; + EXPECT_EQ(false, app.FindKey("enabled")->GetBool()); + const auto& disabled = app.FindKey("disabled")->GetList(); + EXPECT_EQ(4u, disabled.size()); + EXPECT_EQ(0, disabled[0].FindKey("reason")->GetInt()); + EXPECT_EQ(4, disabled[1].FindKey("reason")->GetInt()); + EXPECT_EQ(8, disabled[2].FindKey("reason")->GetInt()); + EXPECT_EQ(16, disabled[3].FindKey("reason")->GetInt()); + } else { + EXPECT_THAT(request, testing::HasSubstr(R"(enabled="0")")); + EXPECT_THAT(request, testing::HasSubstr(R"(<disabled reason="0")")); + EXPECT_THAT(request, testing::HasSubstr(R"(<disabled reason="4")")); + EXPECT_THAT(request, testing::HasSubstr(R"(<disabled reason="8")")); + EXPECT_THAT(request, testing::HasSubstr(R"(<disabled reason="16")")); + } + } } -TEST_F(UpdateCheckerTest, UpdateCheckUpdateDisabled) { +TEST_P(UpdateCheckerTest, UpdateCheckUpdateDisabled) { config_->SetBrand(""); update_checker_ = UpdateChecker::Create(config_, metadata_.get()); @@ -802,93 +1126,147 @@ auto& component = components[kUpdateItemId]; auto crx_component = component->crx_component(); - // Tests the scenario where: - // * the component does not support group policies. - // * the component updates are disabled. - // Expects the group policy to be ignored and the update check to not - // include the "updatedisabled" attribute. - EXPECT_FALSE(crx_component->supports_group_policy_enable_component_updates); - - EXPECT_TRUE(post_interceptor_->ExpectRequest( - std::make_unique<PartialMatch>("updatecheck"), - test_file("updatecheck_reply_1.xml"))); - update_checker_->CheckForUpdates( - update_context_->session_id, {kUpdateItemId}, components, {}, false, - base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete, - base::Unretained(this))); - RunThreads(); - EXPECT_THAT( - post_interceptor_->GetRequestBody(0), - testing::HasSubstr(std::string(R"(<app appid=")") + kUpdateItemId + - R"(" version="0.9" enabled="1"><updatecheck/>)")); - - // Tests the scenario where: - // * the component supports group policies. - // * the component updates are disabled. - // Expects the update check to include the "updatedisabled" attribute. - crx_component->supports_group_policy_enable_component_updates = true; - component->set_crx_component(*crx_component); - update_checker_ = UpdateChecker::Create(config_, metadata_.get()); - EXPECT_TRUE(post_interceptor_->ExpectRequest( - std::make_unique<PartialMatch>("updatecheck"), - test_file("updatecheck_reply_1.xml"))); - update_checker_->CheckForUpdates( - update_context_->session_id, {kUpdateItemId}, components, {}, false, - base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete, - base::Unretained(this))); - RunThreads(); - EXPECT_THAT( - post_interceptor_->GetRequestBody(1), - testing::HasSubstr(std::string(R"(<app appid=")") + kUpdateItemId + - R"(" version="0.9" enabled="1">)" + - R"(<updatecheck updatedisabled="true"/>)")); - - // Tests the scenario where: - // * the component does not support group policies. - // * the component updates are enabled. - // Expects the update check to not include the "updatedisabled" attribute. - crx_component->supports_group_policy_enable_component_updates = false; - component->set_crx_component(*crx_component); - update_checker_ = UpdateChecker::Create(config_, metadata_.get()); - EXPECT_TRUE(post_interceptor_->ExpectRequest( - std::make_unique<PartialMatch>("updatecheck"), - test_file("updatecheck_reply_1.xml"))); - update_checker_->CheckForUpdates( - update_context_->session_id, {kUpdateItemId}, components, {}, true, - base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete, - base::Unretained(this))); - RunThreads(); - EXPECT_THAT( - post_interceptor_->GetRequestBody(2), - testing::HasSubstr(std::string(R"(<app appid=")") + kUpdateItemId + - R"(" version="0.9" enabled="1"><updatecheck/>)")); - - // Tests the scenario where: - // * the component supports group policies. - // * the component updates are enabled. - // Expects the update check to not include the "updatedisabled" attribute. - crx_component->supports_group_policy_enable_component_updates = true; - component->set_crx_component(*crx_component); - update_checker_ = UpdateChecker::Create(config_, metadata_.get()); - EXPECT_TRUE(post_interceptor_->ExpectRequest( - std::make_unique<PartialMatch>("updatecheck"), - test_file("updatecheck_reply_1.xml"))); - update_checker_->CheckForUpdates( - update_context_->session_id, {kUpdateItemId}, components, {}, true, - base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete, - base::Unretained(this))); - RunThreads(); - EXPECT_THAT( - post_interceptor_->GetRequestBody(3), - testing::HasSubstr(std::string(R"(<app appid=")") + kUpdateItemId + - R"(" version="0.9" enabled="1"><updatecheck/>)")); + // Ignore this test parameter to keep the test simple. + update_context_->is_foreground = false; + { + // Tests the scenario where: + // * the component does not support group policies. + // * the component updates are disabled. + // Expects the group policy to be ignored and the update check to not + // include the "updatedisabled" attribute. + EXPECT_FALSE(crx_component->supports_group_policy_enable_component_updates); + auto post_interceptor = std::make_unique<URLLoaderPostInterceptor>( + config_->test_url_loader_factory()); + EXPECT_TRUE(post_interceptor->ExpectRequest( + std::make_unique<PartialMatch>("updatecheck"), + test_file(use_JSON_ ? "updatecheck_reply_1.json" + : "updatecheck_reply_1.xml"))); + update_checker_->CheckForUpdates( + update_context_->session_id, {kUpdateItemId}, components, {}, false, + base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete, + base::Unretained(this))); + RunThreads(); + const auto& request = post_interceptor->GetRequestBody(0); + if (use_JSON_) { + const auto root = base::JSONReader().Read(request); + const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; + EXPECT_EQ(kUpdateItemId, app.FindKey("appid")->GetString()); + EXPECT_EQ("0.9", app.FindKey("version")->GetString()); + EXPECT_EQ(true, app.FindKey("enabled")->GetBool()); + EXPECT_TRUE(app.FindKey("updatecheck")->DictEmpty()); + } else { + EXPECT_THAT( + request, + testing::HasSubstr(std::string(R"(<app appid=")") + kUpdateItemId + + R"(" version="0.9" enabled="1"><updatecheck/>)")); + } + } + { + // Tests the scenario where: + // * the component supports group policies. + // * the component updates are disabled. + // Expects the update check to include the "updatedisabled" attribute. + crx_component->supports_group_policy_enable_component_updates = true; + component->set_crx_component(*crx_component); + auto post_interceptor = std::make_unique<URLLoaderPostInterceptor>( + config_->test_url_loader_factory()); + EXPECT_TRUE(post_interceptor->ExpectRequest( + std::make_unique<PartialMatch>("updatecheck"), + test_file(use_JSON_ ? "updatecheck_reply_1.json" + : "updatecheck_reply_1.xml"))); + update_checker_->CheckForUpdates( + update_context_->session_id, {kUpdateItemId}, components, {}, false, + base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete, + base::Unretained(this))); + RunThreads(); + const auto& request = post_interceptor->GetRequestBody(0); + if (use_JSON_) { + const auto root = base::JSONReader().Read(request); + const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; + EXPECT_EQ(kUpdateItemId, app.FindKey("appid")->GetString()); + EXPECT_EQ("0.9", app.FindKey("version")->GetString()); + EXPECT_EQ(true, app.FindKey("enabled")->GetBool()); + EXPECT_TRUE(app.FindPath({"updatecheck", "updatedisabled"})->GetBool()); + } else { + EXPECT_THAT(request, testing::HasSubstr( + std::string(R"(<app appid=")") + kUpdateItemId + + R"(" version="0.9" enabled="1">)" + + R"(<updatecheck updatedisabled="true"/>)")); + } + } + { + // Tests the scenario where: + // * the component does not support group policies. + // * the component updates are enabled. + // Expects the update check to not include the "updatedisabled" attribute. + crx_component->supports_group_policy_enable_component_updates = false; + component->set_crx_component(*crx_component); + auto post_interceptor = std::make_unique<URLLoaderPostInterceptor>( + config_->test_url_loader_factory()); + EXPECT_TRUE(post_interceptor->ExpectRequest( + std::make_unique<PartialMatch>("updatecheck"), + test_file(use_JSON_ ? "updatecheck_reply_1.json" + : "updatecheck_reply_1.xml"))); + update_checker_->CheckForUpdates( + update_context_->session_id, {kUpdateItemId}, components, {}, true, + base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete, + base::Unretained(this))); + RunThreads(); + const auto& request = post_interceptor->GetRequestBody(0); + if (use_JSON_) { + const auto root = base::JSONReader().Read(request); + const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; + EXPECT_EQ(kUpdateItemId, app.FindKey("appid")->GetString()); + EXPECT_EQ("0.9", app.FindKey("version")->GetString()); + EXPECT_EQ(true, app.FindKey("enabled")->GetBool()); + EXPECT_TRUE(app.FindKey("updatecheck")->DictEmpty()); + } else { + EXPECT_THAT( + request, + testing::HasSubstr(std::string(R"(<app appid=")") + kUpdateItemId + + R"(" version="0.9" enabled="1"><updatecheck/>)")); + } + } + { + // Tests the scenario where: + // * the component supports group policies. + // * the component updates are enabled. + // Expects the update check to not include the "updatedisabled" attribute. + crx_component->supports_group_policy_enable_component_updates = true; + component->set_crx_component(*crx_component); + auto post_interceptor = std::make_unique<URLLoaderPostInterceptor>( + config_->test_url_loader_factory()); + EXPECT_TRUE(post_interceptor->ExpectRequest( + std::make_unique<PartialMatch>("updatecheck"), + test_file(use_JSON_ ? "updatecheck_reply_1.json" + : "updatecheck_reply_1.xml"))); + update_checker_->CheckForUpdates( + update_context_->session_id, {kUpdateItemId}, components, {}, true, + base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete, + base::Unretained(this))); + RunThreads(); + const auto& request = post_interceptor->GetRequestBody(0); + if (use_JSON_) { + const auto root = base::JSONReader().Read(request); + const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; + EXPECT_EQ(kUpdateItemId, app.FindKey("appid")->GetString()); + EXPECT_EQ("0.9", app.FindKey("version")->GetString()); + EXPECT_EQ(true, app.FindKey("enabled")->GetBool()); + EXPECT_TRUE(app.FindKey("updatecheck")->DictEmpty()); + } else { + EXPECT_THAT( + request, + testing::HasSubstr(std::string(R"(<app appid=")") + kUpdateItemId + + R"(" version="0.9" enabled="1"><updatecheck/>)")); + } + } } -TEST_F(UpdateCheckerTest, NoUpdateActionRun) { +TEST_P(UpdateCheckerTest, NoUpdateActionRun) { EXPECT_TRUE(post_interceptor_->ExpectRequest( std::make_unique<PartialMatch>("updatecheck"), - test_file("updatecheck_reply_noupdate.xml"))); - + test_file(use_JSON_ ? "updatecheck_reply_noupdate.json" + : "updatecheck_reply_noupdate.xml"))); update_checker_ = UpdateChecker::Create(config_, metadata_.get()); IdToComponentPtrMap components; @@ -912,13 +1290,15 @@ EXPECT_EQ(1u, results_->list.size()); const auto& result = results_->list.front(); EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", result.extension_id.c_str()); + EXPECT_STREQ("noupdate", result.status.c_str()); EXPECT_STREQ("this", result.action_run.c_str()); } -TEST_F(UpdateCheckerTest, UpdatePauseResume) { +TEST_P(UpdateCheckerTest, UpdatePauseResume) { EXPECT_TRUE(post_interceptor_->ExpectRequest( std::make_unique<PartialMatch>("updatecheck"), - test_file("updatecheck_reply_1.xml"))); + test_file(use_JSON_ ? "updatecheck_reply_noupdate.json" + : "updatecheck_reply_noupdate.xml"))); post_interceptor_->url_job_request_ready_callback(base::BindOnce( [](URLLoaderPostInterceptor* post_interceptor) { post_interceptor->Resume(); @@ -931,6 +1311,9 @@ IdToComponentPtrMap components; components[kUpdateItemId] = MakeComponent(); + // Ignore this test parameter to keep the test simple. + update_context_->is_foreground = false; + update_checker_->CheckForUpdates( update_context_->session_id, {kUpdateItemId}, components, {}, true, base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete, @@ -938,18 +1321,34 @@ RunThreads(); const auto& request = post_interceptor_->GetRequestBody(0); - EXPECT_THAT(request, testing::HasSubstr( - std::string(R"(<app appid=")") + kUpdateItemId + - R"(" version="0.9" brand="TEST" enabled="1">)" + - R"(<updatecheck/><ping r="-2"/>)")); - EXPECT_THAT( - request, - testing::HasSubstr(R"(<packages><package fp="fp1"/></packages></app>)")); + if (use_JSON_) { + const auto root = base::JSONReader().Read(request); + const auto& app = root->FindKey("request")->FindKey("app")->GetList()[0]; + EXPECT_EQ(kUpdateItemId, app.FindKey("appid")->GetString()); + EXPECT_EQ("0.9", app.FindKey("version")->GetString()); + EXPECT_EQ("TEST", app.FindKey("brand")->GetString()); + EXPECT_EQ(true, app.FindKey("enabled")->GetBool()); + EXPECT_TRUE(app.FindKey("updatecheck")->DictEmpty()); + EXPECT_EQ(-2, app.FindPath({"ping", "r"})->GetInt()); + EXPECT_EQ("fp1", app.FindKey("packages") + ->FindKey("package") + ->GetList()[0] + .FindKey("fp") + ->GetString()); + } else { + EXPECT_THAT(request, testing::HasSubstr( + std::string(R"(<app appid=")") + kUpdateItemId + + R"(" version="0.9" brand="TEST" enabled="1">)" + + R"(<updatecheck/><ping r="-2"/>)")); + EXPECT_THAT(request, + testing::HasSubstr( + R"(<packages><package fp="fp1"/></packages></app>)")); + } } // Tests that an update checker object and its underlying SimpleURLLoader can // be safely destroyed while it is paused. -TEST_F(UpdateCheckerTest, UpdateResetUpdateChecker) { +TEST_P(UpdateCheckerTest, UpdateResetUpdateChecker) { base::RunLoop runloop; auto quit_closure = runloop.QuitClosure(); @@ -974,10 +1373,11 @@ // The update response contains a protocol version which does not match the // expected protocol version. -TEST_F(UpdateCheckerTest, ParseErrorProtocolVersionMismatch) { +TEST_P(UpdateCheckerTest, ParseErrorProtocolVersionMismatch) { EXPECT_TRUE(post_interceptor_->ExpectRequest( std::make_unique<PartialMatch>("updatecheck"), - test_file("updatecheck_reply_parse_error.xml"))); + test_file(use_JSON_ ? "updatecheck_reply_parse_error.json" + : "updatecheck_reply_parse_error.xml"))); update_checker_ = UpdateChecker::Create(config_, metadata_.get()); @@ -1003,10 +1403,11 @@ // The update response contains a status |error-unknownApplication| for the // app. The response is succesfully parsed and a result is extracted to // indicate this status. -TEST_F(UpdateCheckerTest, ParseErrorAppStatusErrorUnknownApplication) { +TEST_P(UpdateCheckerTest, ParseErrorAppStatusErrorUnknownApplication) { EXPECT_TRUE(post_interceptor_->ExpectRequest( std::make_unique<PartialMatch>("updatecheck"), - test_file("updatecheck_reply_unknownapp.xml"))); + test_file(use_JSON_ ? "updatecheck_reply_unknownapp.json" + : "updatecheck_reply_unknownapp.xml"))); update_checker_ = UpdateChecker::Create(config_, metadata_.get());
diff --git a/components/update_client/update_client_unittest.cc b/components/update_client/update_client_unittest.cc index 43ec49e..2f67919e 100644 --- a/components/update_client/update_client_unittest.cc +++ b/components/update_client/update_client_unittest.cc
@@ -3710,8 +3710,8 @@ /* "<event eventtype="14" eventresult="1" downloader="unknown" " "url="http://localhost/download/runaction_test_win.crx3" - "downloaded="1843" " - "total="1843" download_time_ms="1000" previousversion="0.0" " + "downloaded=1843 " + "total=1843 download_time_ms="1000" previousversion="0.0" " "nextversion="1.0"/>" */ const auto& event0 = events()[0]; @@ -3720,9 +3720,9 @@ EXPECT_EQ("unknown", event0.FindKey("downloader")->GetString()); EXPECT_EQ("http://localhost/download/runaction_test_win.crx3", event0.FindKey("url")->GetString()); - EXPECT_EQ("1843", event0.FindKey("downloaded")->GetString()); - EXPECT_EQ("1843", event0.FindKey("total")->GetString()); - EXPECT_EQ("1000", event0.FindKey("download_time_ms")->GetString()); + EXPECT_EQ(1843, event0.FindKey("downloaded")->GetDouble()); + EXPECT_EQ(1843, event0.FindKey("total")->GetDouble()); + EXPECT_EQ(1000, event0.FindKey("download_time_ms")->GetDouble()); EXPECT_EQ("0.0", event0.FindKey("previousversion")->GetString()); EXPECT_EQ("1.0", event0.FindKey("nextversion")->GetString());
diff --git a/content/browser/android/web_contents_observer_proxy.cc b/content/browser/android/web_contents_observer_proxy.cc index 84b5241..5466fb5 100644 --- a/content/browser/android/web_contents_observer_proxy.cc +++ b/content/browser/android/web_contents_observer_proxy.cc
@@ -11,6 +11,7 @@ #include "base/android/scoped_java_ref.h" #include "base/optional.h" #include "base/strings/utf_string_conversions.h" +#include "base/trace_event/trace_event.h" #include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/common/android/media_metadata_android.h" @@ -162,6 +163,8 @@ ScopedJavaLocalRef<jstring> jerror_description = ConvertUTF8ToJavaString(env, ""); + // Remove after fixing https://crbug/905461. + TRACE_EVENT0("browser", "Java_WebContentsObserverProxy_didFinishNavigation"); Java_WebContentsObserverProxy_didFinishNavigation( env, java_observer_, jstring_url, navigation_handle->IsInMainFrame(), navigation_handle->IsErrorPage(), navigation_handle->HasCommitted(),
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc index a44d629..fd46871 100644 --- a/content/browser/frame_host/render_frame_host_impl.cc +++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -3099,13 +3099,19 @@ } } - // Call testing callback functions for each event to fire. - for (size_t i = 0; i < details.events.size(); i++) { - if (static_cast<int>(details.events[i].event_type) < 0) - continue; + if (details.events.empty()) { + // Objects were marked dirty but no events were provided. + // The callback must still run, otherwise dump event tests can hang. + accessibility_testing_callback_.Run(this, ax::mojom::Event::kNone, 0); + } else { + // Call testing callback functions for each event to fire. + for (size_t i = 0; i < details.events.size(); i++) { + if (static_cast<int>(details.events[i].event_type) < 0) + continue; - accessibility_testing_callback_.Run(this, details.events[i].event_type, - details.events[i].id); + accessibility_testing_callback_.Run( + this, details.events[i].event_type, details.events[i].id); + } } } }
diff --git a/content/browser/media/media_internals_audio_focus_helper.h b/content/browser/media/media_internals_audio_focus_helper.h index 8e3d344..ee977a8 100644 --- a/content/browser/media/media_internals_audio_focus_helper.h +++ b/content/browser/media/media_internals_audio_focus_helper.h
@@ -29,6 +29,8 @@ media_session::mojom::AudioFocusType type) override; void OnFocusLost( media_session::mojom::MediaSessionInfoPtr media_session) override; + void OnActiveSessionChanged( + media_session::mojom::AudioFocusRequestStatePtr session) override {} // Sets whether we should listen to audio focus events. void SetEnabled(bool enabled);
diff --git a/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.cc b/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.cc index ca3fcf25..7fe6479e 100644 --- a/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.cc +++ b/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.cc
@@ -7,6 +7,7 @@ #include <stddef.h> #include <memory> +#include <utility> #include "base/logging.h" #include "base/task/post_task.h" @@ -19,6 +20,7 @@ #include "content/public/browser/storage_partition.h" #include "content/public/common/socket_permission_request.h" #include "net/base/address_list.h" +#include "net/dns/public/dns_query_type.h" #include "ppapi/c/pp_errors.h" #include "ppapi/c/private/ppb_host_resolver_private.h" #include "ppapi/c/private/ppb_net_address_private.h" @@ -27,6 +29,7 @@ #include "ppapi/host/host_message_context.h" #include "ppapi/proxy/ppapi_messages.h" #include "ppapi/shared_impl/private/net_address_private_impl.h" +#include "services/network/public/mojom/network_context.mojom.h" using ppapi::host::NetErrorToPepperError; using ppapi::host::ReplyMessageContext; @@ -39,13 +42,13 @@ network::mojom::ResolveHostParameters* params) { switch (hint.family) { case PP_NETADDRESSFAMILY_PRIVATE_IPV4: - params->dns_query_type = net::HostResolver::DnsQueryType::A; + params->dns_query_type = net::DnsQueryType::A; break; case PP_NETADDRESSFAMILY_PRIVATE_IPV6: - params->dns_query_type = net::HostResolver::DnsQueryType::AAAA; + params->dns_query_type = net::DnsQueryType::AAAA; break; default: - params->dns_query_type = net::HostResolver::DnsQueryType::UNSPECIFIED; + params->dns_query_type = net::DnsQueryType::UNSPECIFIED; } if (hint.flags & PP_HOST_RESOLVER_PRIVATE_FLAGS_CANONNAME)
diff --git a/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.h b/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.h index 80b1e5c..8840d0d 100644 --- a/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.h +++ b/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.h
@@ -17,7 +17,7 @@ #include "mojo/public/cpp/bindings/binding.h" #include "ppapi/c/pp_instance.h" #include "ppapi/host/resource_message_filter.h" -#include "services/network/public/mojom/network_context.mojom.h" +#include "services/network/public/mojom/host_resolver.mojom.h" struct PP_HostResolver_Private_Hint; struct PP_NetAddress_Private;
diff --git a/content/public/renderer/content_renderer_client.h b/content/public/renderer/content_renderer_client.h index 3166cbe2..658cdc9 100644 --- a/content/public/renderer/content_renderer_client.h +++ b/content/public/renderer/content_renderer_client.h
@@ -137,23 +137,19 @@ // Returns the information to display when a navigation error occurs. // If |error_html| is not null then it may be set to a HTML page // containing the details of the error and maybe links to more info. - // If |error_description| is not null it may be set to contain a brief - // message describing the error that has occurred. - // Either of the out parameters may be not written to in certain cases + // Note that |error_html| may be not written to in certain cases // (lack of information on the error code) so the caller should take care to - // initialize the string values with safe defaults before the call. + // initialize it with a safe default before the call. virtual void PrepareErrorPage(content::RenderFrame* render_frame, const blink::WebURLRequest& failed_request, const blink::WebURLError& error, - std::string* error_html, - base::string16* error_description) {} + std::string* error_html) {} virtual void PrepareErrorPageForHttpStatusError( content::RenderFrame* render_frame, const blink::WebURLRequest& failed_request, const GURL& unreachable_url, int http_status, - std::string* error_html, - base::string16* error_description) {} + std::string* error_html) {} // Returns as |error_description| a brief description of the error that // ocurred. The out parameter may be not written to in certain cases (lack of
diff --git a/content/public/test/test_renderer_host.h b/content/public/test/test_renderer_host.h index 9120bc7..15f9c394 100644 --- a/content/public/test/test_renderer_host.h +++ b/content/public/test/test_renderer_host.h
@@ -260,6 +260,8 @@ // context. virtual BrowserContext* GetBrowserContext(); + TestBrowserThreadBundle* thread_bundle() { return thread_bundle_.get(); } + #if defined(USE_AURA) aura::Window* root_window() { return aura_test_helper_->root_window(); } #endif
diff --git a/content/renderer/accessibility/render_accessibility_impl.cc b/content/renderer/accessibility/render_accessibility_impl.cc index de1114a..760115ba 100644 --- a/content/renderer/accessibility/render_accessibility_impl.cc +++ b/content/renderer/accessibility/render_accessibility_impl.cc
@@ -415,7 +415,7 @@ if (document.IsNull()) return; - if (pending_events_.empty()) + if (pending_events_.empty() && dirty_objects_.empty()) return; ack_pending_ = true;
diff --git a/content/renderer/browser_render_view_browsertest.cc b/content/renderer/browser_render_view_browsertest.cc index 6d6bd0d..2fe5e36 100644 --- a/content/renderer/browser_render_view_browsertest.cc +++ b/content/renderer/browser_render_view_browsertest.cc
@@ -57,8 +57,7 @@ void PrepareErrorPage(content::RenderFrame* render_frame, const blink::WebURLRequest& failed_request, const blink::WebURLError& error, - std::string* error_html, - base::string16* error_description) override { + std::string* error_html) override { if (error_html) *error_html = "A suffusion of yellow."; latest_error_valid_ = true;
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index d7d8462..ed3a350c 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -2826,33 +2826,19 @@ std::string error_html; if (error_page_content.has_value()) { error_html = error_page_content.value(); + // We don't need the actual error page content, but still call this + // for any possible side effects. GetContentClient()->renderer()->PrepareErrorPage(this, failed_request, - error, nullptr, nullptr); + error, nullptr); } else { - GetContentClient()->renderer()->PrepareErrorPage( - this, failed_request, error, &error_html, nullptr); + GetContentClient()->renderer()->PrepareErrorPage(this, failed_request, + error, &error_html); } LoadNavigationErrorPageInternal(error_html, error.url(), replace, entry, std::move(navigation_params), std::move(navigation_data), &failed_request); } -void RenderFrameImpl::LoadNavigationErrorPageForHttpStatusError( - const WebURLRequest& failed_request, - const GURL& unreachable_url, - int http_status, - bool replace, - HistoryEntry* entry, - std::unique_ptr<blink::WebNavigationParams> navigation_params, - std::unique_ptr<blink::WebDocumentLoader::ExtraData> navigation_data) { - std::string error_html; - GetContentClient()->renderer()->PrepareErrorPageForHttpStatusError( - this, failed_request, unreachable_url, http_status, &error_html, nullptr); - LoadNavigationErrorPageInternal(error_html, unreachable_url, replace, entry, - std::move(navigation_params), - std::move(navigation_data), &failed_request); -} - void RenderFrameImpl::LoadNavigationErrorPageInternal( const std::string& error_html, const GURL& error_url, @@ -3005,8 +2991,7 @@ std::string error_html; GetContentClient()->renderer()->PrepareErrorPage( - this, frame_->GetDocumentLoader()->GetRequest(), error, &error_html, - nullptr); + this, frame_->GetDocumentLoader()->GetRequest(), error, &error_html); LoadNavigationErrorPageInternal( error_html, error.url(), true /* replace */, nullptr /* history_entry */, @@ -4574,10 +4559,15 @@ navigation_params->service_worker_network_provider = BuildServiceWorkerNetworkProviderForNavigation( nullptr /* request_params */, nullptr /* controller_info */); - LoadNavigationErrorPageForHttpStatusError( - frame_->GetDocumentLoader()->GetRequest(), frame_->GetDocument().Url(), - http_status_code, true /* replace */, nullptr /* entry */, - std::move(navigation_params), std::move(document_state)); + WebURLRequest failed_request = frame_->GetDocumentLoader()->GetRequest(); + WebURL unreachable_url = frame_->GetDocument().Url(); + std::string error_html; + GetContentClient()->renderer()->PrepareErrorPageForHttpStatusError( + this, failed_request, unreachable_url, http_status_code, &error_html); + LoadNavigationErrorPageInternal(error_html, unreachable_url, + true /* replace */, nullptr /* entry */, + std::move(navigation_params), + std::move(document_state), &failed_request); } // Do not use |this| or |frame_| here without checking |weak_self|. }
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h index bfdf0879..1795ed3 100644 --- a/content/renderer/render_frame_impl.h +++ b/content/renderer/render_frame_impl.h
@@ -1142,14 +1142,6 @@ const base::Optional<std::string>& error_page_content, std::unique_ptr<blink::WebNavigationParams> navigation_params, std::unique_ptr<blink::WebDocumentLoader::ExtraData> navigation_data); - void LoadNavigationErrorPageForHttpStatusError( - const blink::WebURLRequest& failed_request, - const GURL& unreachable_url, - int http_status, - bool replace, - HistoryEntry* entry, - std::unique_ptr<blink::WebNavigationParams> navigation_params, - std::unique_ptr<blink::WebDocumentLoader::ExtraData> navigation_data); void LoadNavigationErrorPageInternal( const std::string& error_html, const GURL& error_url,
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc index 3ed189a8..c3bc1e6 100644 --- a/content/renderer/render_view_browsertest.cc +++ b/content/renderer/render_view_browsertest.cc
@@ -1983,8 +1983,7 @@ void PrepareErrorPage(content::RenderFrame* render_frame, const blink::WebURLRequest& failed_request, const blink::WebURLError& error, - std::string* error_html, - base::string16* error_description) override { + std::string* error_html) override { if (error_html) *error_html = "A suffusion of yellow."; } @@ -1993,8 +1992,7 @@ const blink::WebURLRequest& failed_request, const GURL& url, int http_status_code, - std::string* error_html, - base::string16* error_description) override { + std::string* error_html) override { if (error_html) *error_html = "A suffusion of yellow."; }
diff --git a/content/shell/renderer/shell_content_renderer_client.cc b/content/shell/renderer/shell_content_renderer_client.cc index 7ea4173..5a50a0ec 100644 --- a/content/shell/renderer/shell_content_renderer_client.cc +++ b/content/shell/renderer/shell_content_renderer_client.cc
@@ -137,8 +137,7 @@ RenderFrame* render_frame, const blink::WebURLRequest& failed_request, const blink::WebURLError& error, - std::string* error_html, - base::string16* error_description) { + std::string* error_html) { if (error_html && error_html->empty()) { *error_html = "<head><title>Error</title></head><body>Could not load the requested " @@ -155,8 +154,7 @@ const blink::WebURLRequest& failed_request, const GURL& unreachable_url, int http_status, - std::string* error_html, - base::string16* error_description) { + std::string* error_html) { if (error_html) { *error_html = "<head><title>Error</title></head><body>Server returned HTTP status " +
diff --git a/content/shell/renderer/shell_content_renderer_client.h b/content/shell/renderer/shell_content_renderer_client.h index 2dd4662..e3a9864 100644 --- a/content/shell/renderer/shell_content_renderer_client.h +++ b/content/shell/renderer/shell_content_renderer_client.h
@@ -31,15 +31,13 @@ void PrepareErrorPage(RenderFrame* render_frame, const blink::WebURLRequest& failed_request, const blink::WebURLError& error, - std::string* error_html, - base::string16* error_description) override; + std::string* error_html) override; void PrepareErrorPageForHttpStatusError( content::RenderFrame* render_frame, const blink::WebURLRequest& failed_request, const GURL& unreachable_url, int http_status, - std::string* error_html, - base::string16* error_description) override; + std::string* error_html) override; // TODO(mkwst): These toggle based on the kEnablePepperTesting flag. Do we // need that outside of layout tests?
diff --git a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py index 12afb18..3c2457e 100644 --- a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
@@ -310,9 +310,6 @@ self.Fail('conformance/rendering/rendering-stencil-large-viewport.html', ['win', 'intel', 'd3d11'], bug=782317) - # Seems to cause the harness to fail immediately afterward - self.Skip('conformance2/textures/video/tex-2d-rgba16f-rgba-half_float.html', - ['win', 'intel', 'd3d11'], bug=648337) # TODO(kbr): re-enable after fix for http://crbug.com/898350 # self.Flaky('deqp/functional/gles3/lifetime.html', # ['win', 'intel', 'd3d11'], bug=620379)
diff --git a/device/fido/fido_discovery_factory.cc b/device/fido/fido_discovery_factory.cc index 5386d6af0..bcf26c5 100644 --- a/device/fido/fido_discovery_factory.cc +++ b/device/fido/fido_discovery_factory.cc
@@ -33,19 +33,6 @@ return nullptr; #else -#if defined(OS_WIN) - // On platforms where the Windows webauthn.dll is present, access to USB - // devices is blocked and we use a special authenticator that forwards - // requests to the Windows WebAuthn API instead. - if (base::FeatureList::IsEnabled(device::kWebAuthUseNativeWinApi) && - WinWebAuthnApi::GetDefault()->IsAvailable()) { - return std::make_unique<WinNativeCrossPlatformAuthenticatorDiscovery>( - WinWebAuthnApi::GetDefault(), - // TODO(martinkr): Inject the window from which the request originated. - GetForegroundWindow()); - } -#endif // defined(OS_WIN) - DCHECK(connector); return std::make_unique<FidoHidDiscovery>(connector); #endif // !defined(OS_ANDROID) @@ -74,13 +61,13 @@ return nullptr; } -} // namespace - std::unique_ptr<FidoDiscoveryBase> CreateCableDiscoveryImpl( std::vector<CableDiscoveryData> cable_data) { return std::make_unique<FidoCableDiscovery>(std::move(cable_data)); } +} // namespace + // static FidoDiscoveryFactory::FactoryFuncPtr FidoDiscoveryFactory::g_factory_func_ = &CreateFidoDiscoveryImpl; @@ -102,6 +89,26 @@ return (*g_cable_factory_func_)(std::move(cable_data)); } +// static +#if defined(OS_WIN) +std::unique_ptr<FidoDiscoveryBase> +FidoDiscoveryFactory::MaybeCreateWinWebAuthnApiDiscovery() { + if (!base::FeatureList::IsEnabled(device::kWebAuthUseNativeWinApi) || + !WinWebAuthnApi::GetDefault()->IsAvailable()) { + return nullptr; + } + return std::make_unique<WinWebAuthnApiAuthenticatorDiscovery>( + WinWebAuthnApi::GetDefault(), + // TODO(martinkr): Inject the window from which the request + // originated. Windows uses this parameter to center the + // dialog over the parent. The dialog should be centered + // over the originating Chrome Window; the foreground window + // may have changed to something else since the request was + // issued. + GetForegroundWindow()); +} +#endif // defined(OS_WIN) + // ScopedFidoDiscoveryFactory ------------------------------------------------- namespace internal {
diff --git a/device/fido/fido_discovery_factory.h b/device/fido/fido_discovery_factory.h index 573d8b1c..cc21790 100644 --- a/device/fido/fido_discovery_factory.h +++ b/device/fido/fido_discovery_factory.h
@@ -9,6 +9,7 @@ #include <vector> #include "base/component_export.h" +#include "build/build_config.h" #include "device/fido/cable/cable_discovery_data.h" #include "device/fido/fido_device_discovery.h" #include "device/fido/fido_discovery_base.h" @@ -39,6 +40,12 @@ // Instantiates a FidoDiscovery for caBLE. static std::unique_ptr<FidoDiscoveryBase> CreateCable( std::vector<CableDiscoveryData> cable_data); +#if defined(OS_WIN) + // Instantiates a FidoDiscovery for the native Windows WebAuthn + // API where available. Returns nullptr otherwise. + static std::unique_ptr<FidoDiscoveryBase> + MaybeCreateWinWebAuthnApiDiscovery(); +#endif // defined(OS_WIN) private: friend class internal::ScopedFidoDiscoveryFactory;
diff --git a/device/fido/fido_request_handler_base.cc b/device/fido/fido_request_handler_base.cc index 2143e19..d07ddc2 100644 --- a/device/fido/fido_request_handler_base.cc +++ b/device/fido/fido_request_handler_base.cc
@@ -58,7 +58,16 @@ FidoRequestHandlerBase::FidoRequestHandlerBase( service_manager::Connector* connector, const base::flat_set<FidoTransportProtocol>& available_transports) - : weak_factory_(this) { + : connector_(connector), weak_factory_(this) { +#if defined(OS_WIN) + InitDiscoveriesWin(available_transports); +#else + InitDiscoveries(available_transports); +#endif // !defined(OS_WIN) +} + +void FidoRequestHandlerBase::InitDiscoveries( + const base::flat_set<FidoTransportProtocol>& available_transports) { // The number of times |notify_observer_callback_| needs to be invoked before // Observer::OnTransportAvailabilityEnumerated is dispatched. Essentially this // is used to wait until all the parts of |transport_availability_info_| are @@ -85,7 +94,7 @@ continue; } - auto discovery = FidoDiscoveryFactory::Create(transport, connector); + auto discovery = FidoDiscoveryFactory::Create(transport, connector_); if (discovery == nullptr) { // This can occur in tests when a ScopedVirtualU2fDevice is in effect and // HID transports are not configured. @@ -116,6 +125,55 @@ weak_factory_.GetWeakPtr())); } +#if defined(OS_WIN) +void FidoRequestHandlerBase::InitDiscoveriesWin( + const base::flat_set<FidoTransportProtocol>& available_transports) { + // Try to instantiate the discovery for proxying requests to the native + // Windows WebAuthn API; or fall back to using the regular device transport + // discoveries if the API is unavailable. + auto discovery = FidoDiscoveryFactory::MaybeCreateWinWebAuthnApiDiscovery(); + if (!discovery) { + InitDiscoveries(available_transports); + return; + } + + // The Windows WebAuthn API is available. On this platform, communicating + // with authenticator devices directly is blocked by the OS, so we need to go + // through the native API instead. No device discoveries may be instantiated. + // + // The Windows API supports USB, NFC, BLE and platform authenticators, but + // not caBLE. Communicating with caBLE devices directly is subject to the + // same block by the OS, so this platform is without caBLE support for now. + // + // TODO(martinkr): Re-enable the caBLE discovery once caBLE has moved to a + // different UUID. See crbug.com/905111. + + discovery->set_observer(this); + discoveries_.push_back(std::move(discovery)); + + // Tell the embedder to not render a UI and ignore all future callbacks. Also + // don't report any available transports; the embedder is not supposed to use + // this information anyway. + transport_availability_info_.disable_embedder_ui = true; + transport_availability_info_.available_transports = {}; + + // The number of times |notify_observer_callback_| needs to be invoked before + // Observer::OnTransportAvailabilityEnumerated is dispatched. Essentially this + // is used to wait until all the parts of |transport_availability_info_| are + // filled out. In the case of Windows, there are no transport discoveries to + // wait for, so the |notify_observer_callback_| is only invoked in: + // 1) SetPlatformAuthenticatorOrMarkUnavailable(). + // 2) set_observer(). + constexpr size_t transport_info_callback_count = 2u; + + notify_observer_callback_ = base::BarrierClosure( + transport_info_callback_count, + base::BindOnce( + &FidoRequestHandlerBase::NotifyObserverTransportAvailability, + weak_factory_.GetWeakPtr())); +} +#endif // defined(OS_WIN) + FidoRequestHandlerBase::~FidoRequestHandlerBase() = default; void FidoRequestHandlerBase::StartAuthenticatorRequest(
diff --git a/device/fido/fido_request_handler_base.h b/device/fido/fido_request_handler_base.h index 575aebb..125984e 100644 --- a/device/fido/fido_request_handler_base.h +++ b/device/fido/fido_request_handler_base.h
@@ -19,6 +19,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/strings/string_piece_forward.h" +#include "build/build_config.h" #include "device/fido/fido_device_authenticator.h" #include "device/fido/fido_discovery_base.h" #include "device/fido/fido_transport_protocol.h" @@ -87,6 +88,12 @@ bool has_recognized_mac_touch_id_credential = false; bool is_ble_powered = false; bool can_power_on_ble_adapter = false; + + // If true, dispatch of the request cannot be controlled by + // the embedder. The embedder must not display a UI for this + // request and must ignore all subsequent invocations of the + // TransportAvailabilityObserver interface methods. + bool disable_embedder_ui = false; }; class COMPONENT_EXPORT(DEVICE_FIDO) TransportAvailabilityObserver { @@ -201,6 +208,13 @@ private: friend class FidoRequestHandlerTest; + void InitDiscoveries( + const base::flat_set<FidoTransportProtocol>& available_transports); +#if defined(OS_WIN) + void InitDiscoveriesWin( + const base::flat_set<FidoTransportProtocol>& available_transports); +#endif + // FidoDiscoveryBase::Observer void AuthenticatorAdded(FidoDiscoveryBase* discovery, FidoAuthenticator* authenticator) final; @@ -232,6 +246,7 @@ // TODO(martinkr): Inject platform authenticators through a new // FidoDiscoveryBase specialization and hold ownership there. std::unique_ptr<FidoAuthenticator> platform_authenticator_; + service_manager::Connector* const connector_; base::WeakPtrFactory<FidoRequestHandlerBase> weak_factory_; DISALLOW_COPY_AND_ASSIGN(FidoRequestHandlerBase);
diff --git a/device/fido/get_assertion_handler_unittest.cc b/device/fido/get_assertion_handler_unittest.cc index a33f76d..30391c3 100644 --- a/device/fido/get_assertion_handler_unittest.cc +++ b/device/fido/get_assertion_handler_unittest.cc
@@ -31,6 +31,7 @@ #include "testing/gtest/include/gtest/gtest.h" #if defined(OS_WIN) +#include "device/fido/win/authenticator.h" #include "device/fido/win/fake_webauthn_api.h" #endif // defined(OS_WIN) @@ -753,10 +754,13 @@ if (test.enable_feature_flag) scoped_feature_list.InitAndEnableFeature(kWebAuthUseNativeWinApi); + // Simulate a connected HID device. + ScopedFakeHidManager fake_hid_manager; + fake_hid_manager.AddFidoHidDevice("guid"); + TestGetAssertionRequestCallback cb; - ScopedFakeHidManager fake_hid_manager_; auto handler = std::make_unique<GetAssertionRequestHandler>( - fake_hid_manager_.service_manager_connector(), + fake_hid_manager.service_manager_connector(), base::flat_set<FidoTransportProtocol>( {FidoTransportProtocol::kUsbHumanInterfaceDevice}), CtapGetAssertionRequest(test_data::kRelyingPartyId, @@ -765,14 +769,11 @@ cb.callback()); scoped_task_environment_.RunUntilIdle(); - fake_hid_manager_.AddFidoHidDevice("guid"); - scoped_task_environment_.RunUntilIdle(); - EXPECT_EQ(1u, handler->AuthenticatorsForTesting().size()); // Crudely distinguish authenticator type by FidoAuthenticator::GetId. EXPECT_EQ(test.expect_device_type == DeviceType::kHid ? "hid:guid" - : "WinNativeCrossPlatformAuthenticator", + : WinWebAuthnApiAuthenticator::kAuthenticatorId, handler->AuthenticatorsForTesting().begin()->second->GetId()); } }
diff --git a/device/fido/win/authenticator.cc b/device/fido/win/authenticator.cc index 9c4f4b8d..3dc9d3c0 100644 --- a/device/fido/win/authenticator.cc +++ b/device/fido/win/authenticator.cc
@@ -39,7 +39,11 @@ } // namespace -WinNativeCrossPlatformAuthenticator::WinNativeCrossPlatformAuthenticator( +// static +const char WinWebAuthnApiAuthenticator::kAuthenticatorId[] = + "WinWebAuthnApiAuthenticator"; + +WinWebAuthnApiAuthenticator::WinWebAuthnApiAuthenticator( WinWebAuthnApi* win_api, HWND current_window) : FidoAuthenticator(), @@ -50,18 +54,18 @@ CoCreateGuid(&cancellation_id_); } -WinNativeCrossPlatformAuthenticator::~WinNativeCrossPlatformAuthenticator() { +WinWebAuthnApiAuthenticator::~WinWebAuthnApiAuthenticator() { // Cancel in order to dismiss any pending API request and UI dialog and shut // down |thread_|. Cancel(); } -void WinNativeCrossPlatformAuthenticator::InitializeAuthenticator( +void WinWebAuthnApiAuthenticator::InitializeAuthenticator( base::OnceClosure callback) { std::move(callback).Run(); } -void WinNativeCrossPlatformAuthenticator::MakeCredential( +void WinWebAuthnApiAuthenticator::MakeCredential( CtapMakeCredentialRequest request, MakeCredentialCallback callback) { DCHECK(!thread_); @@ -78,22 +82,21 @@ thread_->task_runner()->PostTask( FROM_HERE, base::BindOnce( - &WinNativeCrossPlatformAuthenticator::MakeCredentialBlocking, + &WinWebAuthnApiAuthenticator::MakeCredentialBlocking, // Because |thread_| and its task runner are owned by this // authenticator instance, binding to Unretained(this) here is // fine. If the instance got destroyed before invocation of the // task, so would the task. Once the task is running, destruction // of the authenticator instance blocks on the thread exiting. base::Unretained(this), std::move(request), - base::BindOnce(&WinNativeCrossPlatformAuthenticator:: - InvokeMakeCredentialCallback, - weak_factory_.GetWeakPtr(), std::move(callback)), + base::BindOnce( + &WinWebAuthnApiAuthenticator::InvokeMakeCredentialCallback, + weak_factory_.GetWeakPtr(), std::move(callback)), base::SequencedTaskRunnerHandle::Get())); } -void WinNativeCrossPlatformAuthenticator::GetAssertion( - CtapGetAssertionRequest request, - GetAssertionCallback callback) { +void WinWebAuthnApiAuthenticator::GetAssertion(CtapGetAssertionRequest request, + GetAssertionCallback callback) { DCHECK(!thread_); if (thread_) { return; @@ -104,7 +107,7 @@ thread_->task_runner()->PostTask( FROM_HERE, base::BindOnce( - &WinNativeCrossPlatformAuthenticator::GetAssertionBlocking, + &WinWebAuthnApiAuthenticator::GetAssertionBlocking, // Because |thread_| and its task runner are owned by this // authenticator instance, binding to Unretained(this) here is // fine. If the instance got destroyed before invocation of the @@ -112,7 +115,7 @@ // of the authenticator instance blocks on the thread exiting. base::Unretained(this), std::move(request), base::BindOnce( - &WinNativeCrossPlatformAuthenticator::InvokeGetAssertionCallback, + &WinWebAuthnApiAuthenticator::InvokeGetAssertionCallback, weak_factory_.GetWeakPtr(), std::move(callback)), base::SequencedTaskRunnerHandle::Get())); } @@ -120,7 +123,7 @@ // Invokes the blocking WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL API call. This // method is run on |thread_|. Note that the destructor for this class blocks // on |thread_| shutdown. -void WinNativeCrossPlatformAuthenticator::MakeCredentialBlocking( +void WinWebAuthnApiAuthenticator::MakeCredentialBlocking( CtapMakeCredentialRequest request, MakeCredentialCallback callback, scoped_refptr<base::SequencedTaskRunner> callback_runner) { @@ -190,11 +193,10 @@ kWinWebAuthnTimeoutMilliseconds, WEBAUTHN_CREDENTIALS{exclude_list.size(), exclude_list.data()}, WEBAUTHN_EXTENSIONS{extensions.size(), extensions.data()}, - // Forcibly set authenticator attachment to cross-platform in order to - // avoid triggering the platform authenticator option, which is - // generally displayed first in the Windows UI. + // TODO(martinkr): Plumb authenticator attachment into + // CtapMakeCredentialRequest and set here. use_u2f_only_ ? WEBAUTHN_AUTHENTICATOR_ATTACHMENT_CROSS_PLATFORM_U2F_V2 - : WEBAUTHN_AUTHENTICATOR_ATTACHMENT_CROSS_PLATFORM, + : WEBAUTHN_AUTHENTICATOR_ATTACHMENT_ANY, request.resident_key_required(), ToWinUserVerificationRequirement(request.user_verification()), WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_DIRECT, 0 /* flags */, @@ -270,7 +272,7 @@ // Invokes the blocking WEBAUTHN_AUTHENTICATOR_GET_ASSERTION API call. This // method is run on |thread_|. Note that the destructor for this class blocks // on |thread_| shutdown. -void WinNativeCrossPlatformAuthenticator::GetAssertionBlocking( +void WinWebAuthnApiAuthenticator::GetAssertionBlocking( CtapGetAssertionRequest request, GetAssertionCallback callback, scoped_refptr<base::SequencedTaskRunner> callback_runner) { @@ -298,8 +300,10 @@ kWinWebAuthnTimeoutMilliseconds, WEBAUTHN_CREDENTIALS{allow_list.size(), allow_list.data()}, WEBAUTHN_EXTENSIONS{0, nullptr}, + // TODO(martinkr): Plumb authenticator attachment into + // CtapMakeCredentialRequest and set here. use_u2f_only_ ? WEBAUTHN_AUTHENTICATOR_ATTACHMENT_CROSS_PLATFORM_U2F_V2 - : WEBAUTHN_AUTHENTICATOR_ATTACHMENT_CROSS_PLATFORM, + : WEBAUTHN_AUTHENTICATOR_ATTACHMENT_ANY, ToWinUserVerificationRequirement(request.user_verification()), 0, // flags use_u2f_only_ ? rp_id16.c_str() : nullptr, // pwszU2fAppId @@ -333,7 +337,7 @@ base::BindOnce(std::move(callback), status, std::move(response))); } -void WinNativeCrossPlatformAuthenticator::Cancel() { +void WinWebAuthnApiAuthenticator::Cancel() { if (!thread_ || operation_cancelled_.IsSet()) { return; } @@ -345,31 +349,31 @@ thread_->Stop(); } -std::string WinNativeCrossPlatformAuthenticator::GetId() const { - return "WinNativeCrossPlatformAuthenticator"; +std::string WinWebAuthnApiAuthenticator::GetId() const { + return kAuthenticatorId; } -base::string16 WinNativeCrossPlatformAuthenticator::GetDisplayName() const { - return L"WinNativeCrossPlatformAuthenticator"; +base::string16 WinWebAuthnApiAuthenticator::GetDisplayName() const { + return base::UTF8ToUTF16(GetId()); } -bool WinNativeCrossPlatformAuthenticator::IsInPairingMode() const { +bool WinWebAuthnApiAuthenticator::IsInPairingMode() const { return false; } -bool WinNativeCrossPlatformAuthenticator::IsPaired() const { +bool WinWebAuthnApiAuthenticator::IsPaired() const { return false; } base::Optional<FidoTransportProtocol> -WinNativeCrossPlatformAuthenticator::AuthenticatorTransport() const { +WinWebAuthnApiAuthenticator::AuthenticatorTransport() const { // The Windows API could potentially use any external or // platform authenticator. return base::nullopt; } const base::Optional<AuthenticatorSupportedOptions>& -WinNativeCrossPlatformAuthenticator::Options() const { +WinWebAuthnApiAuthenticator::Options() const { // The request can potentially be fulfilled by any device that Windows // communicates with, so returning AuthenticatorSupportedOptions really // doesn't make much sense. @@ -378,12 +382,11 @@ return no_options; } -base::WeakPtr<FidoAuthenticator> -WinNativeCrossPlatformAuthenticator::GetWeakPtr() { +base::WeakPtr<FidoAuthenticator> WinWebAuthnApiAuthenticator::GetWeakPtr() { return weak_factory_.GetWeakPtr(); } -void WinNativeCrossPlatformAuthenticator::InvokeMakeCredentialCallback( +void WinWebAuthnApiAuthenticator::InvokeMakeCredentialCallback( MakeCredentialCallback cb, CtapDeviceResponseCode status, base::Optional<AuthenticatorMakeCredentialResponse> response) { @@ -394,7 +397,7 @@ } std::move(cb).Run(status, std::move(response)); } -void WinNativeCrossPlatformAuthenticator::InvokeGetAssertionCallback( +void WinWebAuthnApiAuthenticator::InvokeGetAssertionCallback( GetAssertionCallback cb, CtapDeviceResponseCode status, base::Optional<AuthenticatorGetAssertionResponse> response) {
diff --git a/device/fido/win/authenticator.h b/device/fido/win/authenticator.h index 79ad8781..899ed90 100644 --- a/device/fido/win/authenticator.h +++ b/device/fido/win/authenticator.h
@@ -20,15 +20,17 @@ namespace device { -// WinNativeCrossPlatformAuthenticator forwards WebAuthn requests to external +// WinWebAuthnApiAuthenticator forwards WebAuthn requests to external // authenticators via the native Windows WebAuthentication API // (webauthn.dll). -class COMPONENT_EXPORT(DEVICE_FIDO) WinNativeCrossPlatformAuthenticator +class COMPONENT_EXPORT(DEVICE_FIDO) WinWebAuthnApiAuthenticator : public FidoAuthenticator { public: - WinNativeCrossPlatformAuthenticator(WinWebAuthnApi* win_api, - HWND current_window); - ~WinNativeCrossPlatformAuthenticator() override; + // The return value of |GetId|. + static const char kAuthenticatorId[]; + + WinWebAuthnApiAuthenticator(WinWebAuthnApi* win_api, HWND current_window); + ~WinWebAuthnApiAuthenticator() override; // Forces the Windows WebAuthn API not to communicate with CTAP2 devices for // this request. Dual-protocol devices will use U2F. @@ -84,8 +86,8 @@ GUID cancellation_id_ = {}; base::AtomicFlag operation_cancelled_; - base::WeakPtrFactory<WinNativeCrossPlatformAuthenticator> weak_factory_; - DISALLOW_COPY_AND_ASSIGN(WinNativeCrossPlatformAuthenticator); + base::WeakPtrFactory<WinWebAuthnApiAuthenticator> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(WinWebAuthnApiAuthenticator); }; } // namespace device
diff --git a/device/fido/win/discovery.cc b/device/fido/win/discovery.cc index 7970f6e..0e72b97 100644 --- a/device/fido/win/discovery.cc +++ b/device/fido/win/discovery.cc
@@ -6,18 +6,17 @@ namespace device { -WinNativeCrossPlatformAuthenticatorDiscovery:: - WinNativeCrossPlatformAuthenticatorDiscovery( - WinWebAuthnApi* const win_webauthn_api, - HWND parent_window) +WinWebAuthnApiAuthenticatorDiscovery::WinWebAuthnApiAuthenticatorDiscovery( + WinWebAuthnApi* const win_webauthn_api, + HWND parent_window) : FidoDiscoveryBase(FidoTransportProtocol::kUsbHumanInterfaceDevice), win_webauthn_api_(win_webauthn_api), parent_window_(parent_window) {} -WinNativeCrossPlatformAuthenticatorDiscovery:: - ~WinNativeCrossPlatformAuthenticatorDiscovery() = default; +WinWebAuthnApiAuthenticatorDiscovery::~WinWebAuthnApiAuthenticatorDiscovery() = + default; -void WinNativeCrossPlatformAuthenticatorDiscovery::Start() { +void WinWebAuthnApiAuthenticatorDiscovery::Start() { DCHECK(!authenticator_); if (!observer()) { return; @@ -29,7 +28,7 @@ } observer()->DiscoveryStarted(this, true /* success */); - authenticator_ = std::make_unique<WinNativeCrossPlatformAuthenticator>( + authenticator_ = std::make_unique<WinWebAuthnApiAuthenticator>( WinWebAuthnApi::GetDefault(), parent_window_); observer()->AuthenticatorAdded(this, authenticator_.get()); }
diff --git a/device/fido/win/discovery.h b/device/fido/win/discovery.h index b7e3d17e..ba7a803a 100644 --- a/device/fido/win/discovery.h +++ b/device/fido/win/discovery.h
@@ -16,19 +16,18 @@ // Instantiates the authenticator subclass for forwarding requests to external // authenticators via the Windows WebAuthn API. -class COMPONENT_EXPORT(DEVICE_FIDO) WinNativeCrossPlatformAuthenticatorDiscovery +class COMPONENT_EXPORT(DEVICE_FIDO) WinWebAuthnApiAuthenticatorDiscovery : public FidoDiscoveryBase { public: - WinNativeCrossPlatformAuthenticatorDiscovery( - WinWebAuthnApi* const win_webauthn_api, - HWND parent_window); - ~WinNativeCrossPlatformAuthenticatorDiscovery() override; + WinWebAuthnApiAuthenticatorDiscovery(WinWebAuthnApi* const win_webauthn_api, + HWND parent_window); + ~WinWebAuthnApiAuthenticatorDiscovery() override; // FidoDiscoveryBase: void Start() override; private: - std::unique_ptr<WinNativeCrossPlatformAuthenticator> authenticator_; + std::unique_ptr<WinWebAuthnApiAuthenticator> authenticator_; WinWebAuthnApi* const win_webauthn_api_; const HWND parent_window_; };
diff --git a/docs/adding_to_third_party.md b/docs/adding_to_third_party.md index 20f74561..693a1cf 100644 --- a/docs/adding_to_third_party.md +++ b/docs/adding_to_third_party.md
@@ -138,7 +138,8 @@ * Add chromium-third-party@google.com as a reviewer on your change. This will trigger an automatic round-robin assignment of the review to an appropriate reviewer. This list does not receive or deliver email, so only - use it as a reviewer, not for other communication. + use it as a reviewer, not for other communication. (Internally, see + b/119558132 for details about how this is configured.) Please send separate emails to the eng review and security lists.
diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h index fe736b14..2860be5 100644 --- a/extensions/browser/extension_function_histogram_value.h +++ b/extensions/browser/extension_function_histogram_value.h
@@ -1352,6 +1352,7 @@ TABS_GOFORWARD = 1289, TABS_GOBACK = 1290, BRAILLEDISPLAYPRIVATE_UPDATEBLUETOOTHBRAILLEDISPLAYADDRESS = 1291, + AUTOTESTPRIVATE_SETASSISTANTENABLED = 1292, // Last entry: Add new entries above, then run: // python tools/metrics/histograms/update_extension_histograms.py ENUM_BOUNDARY
diff --git a/extensions/common/image_util.cc b/extensions/common/image_util.cc index 9cd7bd69..21fdc66e 100644 --- a/extensions/common/image_util.cc +++ b/extensions/common/image_util.cc
@@ -6,13 +6,18 @@ #include <stddef.h> #include <stdint.h> + +#include <algorithm> #include <vector> #include "base/files/file_path.h" #include "base/files/file_util.h" +#include "base/metrics/histogram_macros.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" +#include "base/time/time.h" +#include "base/timer/elapsed_timer.h" #include "third_party/re2/src/re2/re2.h" #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkCanvas.h" @@ -176,20 +181,24 @@ // The minimum "percent" of pixels that must be visible for the icon to be // considered OK. constexpr double kMinPercentVisiblePixels = 0.05; - const unsigned int total_pixels = bitmap.height() * bitmap.width(); - unsigned int visible_pixels = 0; + const int total_pixels = bitmap.height() * bitmap.width(); + // Pre-calculate the minimum number of visible pixels so we can exit early. + // Since we expect most icons to be visible, this will perform better for + // the common case. + const int minimum_visible_pixels = + std::max(kMinPercentVisiblePixels * total_pixels, 1.0); + + int visible_pixels = 0; for (int y = 0; y < bitmap.height(); ++y) { for (int x = 0; x < bitmap.width(); ++x) { if (SkColorGetA(bitmap.getColor(x, y)) >= kAlphaThreshold) { - ++visible_pixels; + if (++visible_pixels == minimum_visible_pixels) { + return true; + } } } } - // TODO(crbug.com/805600): Add UMA stats when we move to a more - // sophisticated analysis of the image and the background display - // color. - return static_cast<double>(visible_pixels) / total_pixels >= - kMinPercentVisiblePixels; + return false; } bool IsIconAtPathSufficientlyVisible(const base::FilePath& path) { @@ -200,8 +209,23 @@ return IsIconSufficientlyVisible(icon); } +struct ScopedUmaMicrosecondHistogramTimer { + ScopedUmaMicrosecondHistogramTimer() : timer() {} + + ~ScopedUmaMicrosecondHistogramTimer() { + UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES( + "Extensions.IsRenderedIconSufficientlyVisibleTime", timer.Elapsed(), + base::TimeDelta::FromMicroseconds(1), base::TimeDelta::FromSeconds(5), + 50); + } + + const base::ElapsedTimer timer; +}; + bool IsRenderedIconSufficientlyVisible(const SkBitmap& icon, SkColor background_color) { + const ScopedUmaMicrosecondHistogramTimer timer; + // If any of a pixel's RGB values is greater than this number, the pixel is // considered visible. constexpr unsigned int kThreshold = 15; @@ -209,6 +233,11 @@ // considered OK. constexpr double kMinPercentVisiblePixels = 0.05; const int total_pixels = icon.height() * icon.width(); + // Pre-calculate the minimum number of visible pixels so we can exit early. + // Since we expect most icons to be visible, this will perform better for + // the common case. + const int minimum_visible_pixels = + std::max(kMinPercentVisiblePixels * total_pixels, 1.0); // Draw the icon onto a canvas, then draw the background color onto the // resulting bitmap, using SkBlendMode::kDifference. Then, check the RGB @@ -226,12 +255,13 @@ SkColor pixel = bitmap.getColor(x, y); if (SkColorGetR(pixel) > kThreshold || SkColorGetB(pixel) > kThreshold || SkColorGetG(pixel) > kThreshold) { - ++visible_pixels; + if (++visible_pixels == minimum_visible_pixels) { + return true; + } } } } - return static_cast<double>(visible_pixels) / total_pixels >= - kMinPercentVisiblePixels; + return false; } bool IsRenderedIconAtPathSufficientlyVisible(const base::FilePath& path,
diff --git a/extensions/common/image_util_unittest.cc b/extensions/common/image_util_unittest.cc index c2bc598..326834b 100644 --- a/extensions/common/image_util_unittest.cc +++ b/extensions/common/image_util_unittest.cc
@@ -6,8 +6,10 @@ #include "base/files/file_path.h" #include "base/path_service.h" +#include "base/test/metrics/histogram_tester.h" #include "extensions/common/extension_paths.h" #include "extensions/common/image_util.h" +#include "extensions/test/logging_timer.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkColor.h" @@ -184,7 +186,10 @@ base::FilePath test_dir; ASSERT_TRUE(base::PathService::Get(DIR_TEST_DATA, &test_dir)); base::FilePath icon_path; + const std::string metric_name = + "Extensions.IsRenderedIconSufficientlyVisibleTime"; { + base::HistogramTester histogram_tester; // This icon has all transparent pixels, so it will fail. icon_path = test_dir.AppendASCII("transparent_icon.png"); SkBitmap transparent_icon; @@ -192,8 +197,10 @@ EXPECT_FALSE(image_util::IsIconSufficientlyVisible(transparent_icon)); EXPECT_FALSE(image_util::IsRenderedIconSufficientlyVisible(transparent_icon, SK_ColorWHITE)); + histogram_tester.ExpectTotalCount(metric_name, 1); } { + base::HistogramTester histogram_tester; // Test with an icon that has one opaque pixel. icon_path = test_dir.AppendASCII("one_pixel_opaque_icon.png"); SkBitmap visible_icon; @@ -201,8 +208,10 @@ EXPECT_FALSE(image_util::IsIconSufficientlyVisible(visible_icon)); EXPECT_FALSE(image_util::IsRenderedIconSufficientlyVisible(visible_icon, SK_ColorWHITE)); + histogram_tester.ExpectTotalCount(metric_name, 1); } { + base::HistogramTester histogram_tester; // Test with an icon that has one transparent pixel. icon_path = test_dir.AppendASCII("one_pixel_transparent_icon.png"); SkBitmap visible_icon; @@ -210,8 +219,10 @@ EXPECT_TRUE(image_util::IsIconSufficientlyVisible(visible_icon)); EXPECT_TRUE(image_util::IsRenderedIconSufficientlyVisible(visible_icon, SK_ColorWHITE)); + histogram_tester.ExpectTotalCount(metric_name, 1); } { + base::HistogramTester histogram_tester; // Test with an icon that is completely opaque. icon_path = test_dir.AppendASCII("opaque_icon.png"); SkBitmap visible_icon; @@ -219,8 +230,10 @@ EXPECT_TRUE(image_util::IsIconSufficientlyVisible(visible_icon)); EXPECT_TRUE(image_util::IsRenderedIconSufficientlyVisible(visible_icon, SK_ColorWHITE)); + histogram_tester.ExpectTotalCount(metric_name, 1); } { + base::HistogramTester histogram_tester; // Test with an icon that is rectangular. icon_path = test_dir.AppendASCII("rectangle.png"); SkBitmap visible_icon; @@ -228,8 +241,10 @@ EXPECT_TRUE(image_util::IsIconSufficientlyVisible(visible_icon)); EXPECT_TRUE(image_util::IsRenderedIconSufficientlyVisible(visible_icon, SK_ColorWHITE)); + histogram_tester.ExpectTotalCount(metric_name, 1); } { + base::HistogramTester histogram_tester; // Test with a solid color icon that is completely opaque. Use the icon's // color as the background color in the call to analyze its visibility. // It should be invisible in this case. @@ -239,8 +254,10 @@ const SkColor pixel_color = solid_icon.getColor(0, 0); EXPECT_FALSE( image_util::IsRenderedIconSufficientlyVisible(solid_icon, pixel_color)); + histogram_tester.ExpectTotalCount(metric_name, 1); } { + base::HistogramTester histogram_tester; // Test with a two-color icon that is completely opaque. Use one of the // icon's colors as the background color in the call to analyze its // visibility. It should be visible in this case. @@ -250,7 +267,52 @@ const SkColor pixel_color = two_color_icon.getColor(0, 0); EXPECT_TRUE(image_util::IsRenderedIconSufficientlyVisible(two_color_icon, pixel_color)); + histogram_tester.ExpectTotalCount(metric_name, 1); } } +TEST(ImageUtilTest, MANUAL_IsIconSufficientlyVisiblePerfTest) { + base::FilePath test_dir; + ASSERT_TRUE(base::PathService::Get(DIR_TEST_DATA, &test_dir)); + base::FilePath icon_path; + // This icon has all transparent pixels. + icon_path = test_dir.AppendASCII("transparent_icon.png"); + SkBitmap invisible_icon; + ASSERT_TRUE(image_util::LoadPngFromFile(icon_path, &invisible_icon)); + // This icon is completely opaque. + icon_path = test_dir.AppendASCII("opaque_icon.png"); + SkBitmap visible_icon; + ASSERT_TRUE(image_util::LoadPngFromFile(icon_path, &visible_icon)); + + static constexpr char kInvisibleTimerId[] = "InvisibleIcon"; + static constexpr char kVisibleTimerId[] = "VisibleIcon"; + static constexpr char kInvisibleRenderedTimerId[] = "InvisibleRenderedIcon"; + static constexpr char kVisibleRenderedTimerId[] = "VisibleRenderedIcon"; + constexpr int kIterations = 100000; + + for (int i = 0; i < kIterations; ++i) { + LoggingTimer timer(kInvisibleTimerId); + EXPECT_FALSE(image_util::IsIconSufficientlyVisible(invisible_icon)); + } + + for (int i = 0; i < kIterations; ++i) { + LoggingTimer timer(kVisibleTimerId); + EXPECT_TRUE(image_util::IsIconSufficientlyVisible(visible_icon)); + } + + for (int i = 0; i < kIterations; ++i) { + LoggingTimer timer(kInvisibleRenderedTimerId); + EXPECT_FALSE(image_util::IsRenderedIconSufficientlyVisible(invisible_icon, + SK_ColorWHITE)); + } + + for (int i = 0; i < kIterations; ++i) { + LoggingTimer timer(kVisibleRenderedTimerId); + EXPECT_TRUE(image_util::IsRenderedIconSufficientlyVisible(visible_icon, + SK_ColorWHITE)); + } + + LoggingTimer::Print(); +} + } // namespace extensions
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc index c1d0063c..0d5bceef 100644 --- a/gpu/command_buffer/client/gles2_implementation.cc +++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -1657,15 +1657,15 @@ GLsizei count, const char* const* names, GLuint* indices) { + if (!PackStringsToBucket(count, names, nullptr, "glGetUniformIndices")) { + return false; + } typedef cmds::GetUniformIndices::Result Result; Result* result = GetResultAs<Result*>(); if (!result) { return false; } result->SetNumResults(0); - if (!PackStringsToBucket(count, names, nullptr, "glGetUniformIndices")) { - return false; - } helper_->GetUniformIndices(program, kResultBucketId, GetResultShmId(), GetResultShmOffset()); WaitForCmd(); @@ -3285,7 +3285,8 @@ helper_->GetActiveAttrib(program, index, kResultBucketId, GetResultShmId(), GetResultShmOffset()); WaitForCmd(); - if (result->success) { + bool success = !!result->success; + if (success) { if (size) { *size = result->size; } @@ -3294,6 +3295,7 @@ } if (length || name) { std::vector<int8_t> str; + // Note: this can invalidate |result|. GetBucketContents(kResultBucketId, &str); GLsizei max_size = std::min(static_cast<size_t>(bufsize) - 1, @@ -3307,7 +3309,7 @@ } } } - return result->success != 0; + return success; } void GLES2Implementation::GetActiveAttrib(GLuint program, @@ -3545,12 +3547,6 @@ const GLuint* indices, GLenum pname, GLint* params) { - typedef cmds::GetActiveUniformsiv::Result Result; - Result* result = GetResultAs<Result*>(); - if (!result) { - return false; - } - result->SetNumResults(0); base::CheckedNumeric<size_t> bytes = static_cast<size_t>(count); bytes *= sizeof(GLuint); if (!bytes.IsValid()) { @@ -3558,6 +3554,12 @@ return false; } SetBucketContents(kResultBucketId, indices, bytes.ValueOrDefault(0)); + typedef cmds::GetActiveUniformsiv::Result Result; + Result* result = GetResultAs<Result*>(); + if (!result) { + return false; + } + result->SetNumResults(0); helper_->GetActiveUniformsiv(program, kResultBucketId, pname, GetResultShmId(), GetResultShmOffset()); WaitForCmd();
diff --git a/ios/build/bots/chromium.fyi/ios-slimnav.json b/ios/build/bots/chromium.fyi/ios-slimnav.json index 1357a81c..78a6a7c 100644 --- a/ios/build/bots/chromium.fyi/ios-slimnav.json +++ b/ios/build/bots/chromium.fyi/ios-slimnav.json
@@ -141,12 +141,14 @@ "priority": 29 }, { - "include": "eg_tests.json", + "app": "ios_chrome_bookmarks_egtests", "test args": [ "--enable-features=SlimNavigationManager" ], "device type": "iPad Air 2", "os": "11.4", + "shard size": 2, + "xctest": true, "dimensions": [ { "os": "Mac-10.13.4", "pool": "Chrome" }, { "os": "Mac-10.13.5", "pool": "Chrome" }, @@ -155,12 +157,120 @@ "priority": 29 }, { - "include": "eg_tests.json", + "app": "ios_chrome_manual_fill_egtests", + "test args": [ + "--enable-features=AutofillManualFallback,WebFrameMessaging,SlimNavigationManager" + ], + "device type": "iPad Air 2", + "os": "11.4", + "xctest": true, + "dimensions": [ + { "os": "Mac-10.13.4", "pool": "Chrome" }, + { "os": "Mac-10.13.5", "pool": "Chrome" }, + { "os": "Mac-10.13.6", "pool": "Chrome" } + ], + "priority": 29 + }, + { + "app": "ios_chrome_web_egtests", + "test args": [ + "--enable-features=SlimNavigationManager" + ], + "device type": "iPad Air 2", + "os": "11.4", + "xctest": true, + "dimensions": [ + { "os": "Mac-10.13.4", "pool": "Chrome" }, + { "os": "Mac-10.13.5", "pool": "Chrome" }, + { "os": "Mac-10.13.6", "pool": "Chrome" } + ], + "priority": 29 + }, + { + "app": "ios_chrome_settings_egtests", + "test args": [ + "--enable-features=SlimNavigationManager" + ], + "device type": "iPad Air 2", + "os": "11.4", + "xctest": true, + "dimensions": [ + { "os": "Mac-10.13.4", "pool": "Chrome" }, + { "os": "Mac-10.13.5", "pool": "Chrome" }, + { "os": "Mac-10.13.6", "pool": "Chrome" } + ], + "priority": 29 + }, + { + "app": "ios_chrome_reading_list_egtests", + "test args": [ + "--enable-features=SlimNavigationManager" + ], + "device type": "iPad Air 2", + "os": "11.4", + "xctest": true, + "dimensions": [ + { "os": "Mac-10.13.4", "pool": "Chrome" }, + { "os": "Mac-10.13.5", "pool": "Chrome" }, + { "os": "Mac-10.13.6", "pool": "Chrome" } + ], + "priority": 29 + }, + { + "app": "ios_showcase_egtests", + "test args": [ + "--enable-features=SlimNavigationManager" + ], + "device type": "iPad Air 2", + "os": "11.4", + "xctest": true, + "dimensions": [ + { "os": "Mac-10.13.4", "pool": "Chrome" }, + { "os": "Mac-10.13.5", "pool": "Chrome" }, + { "os": "Mac-10.13.6", "pool": "Chrome" } + ], + "priority": 29 + }, + { + "app": "ios_chrome_bookmarks_egtests", + "test args": [ + "--enable-features=SlimNavigationManager" + ], + "shard size": 2, + "device type": "iPad Air 2", + "os": "12.1", + "xctest": true, + "dimensions": [ + { "os": "Mac-10.13.4", "pool": "Chrome" }, + { "os": "Mac-10.13.5", "pool": "Chrome" }, + { "os": "Mac-10.13.6", "pool": "Chrome" } + ], + "priority": 29 + }, + { + "app": "ios_chrome_manual_fill_egtests", + "test args": [ + "--enable-features=AutofillManualFallback,WebFrameMessaging,SlimNavigationManager" + ], + "xctest": true, + "device type": "iPad Air 2", + "os": "12.1", + + "dimensions": [ + { "os": "Mac-10.13.4", "pool": "Chrome" }, + { "os": "Mac-10.13.5", "pool": "Chrome" }, + { "os": "Mac-10.13.6", "pool": "Chrome" } + ], + "priority": 29 + }, + { + "app": "ios_chrome_web_egtests", "test args": [ "--enable-features=SlimNavigationManager" ], "device type": "iPad Air 2", "os": "12.1", + "xctest": true, "dimensions": [ { "os": "Mac-10.13.4", "pool": "Chrome" }, { "os": "Mac-10.13.5", "pool": "Chrome" }, @@ -169,10 +279,72 @@ "priority": 29 }, { - "include": "eg_tests.json", + "app": "ios_chrome_settings_egtests", "test args": [ "--enable-features=SlimNavigationManager" ], + "device type": "iPad Air 2", + "os": "12.1", + "xctest": true, + "dimensions": [ + { "os": "Mac-10.13.4", "pool": "Chrome" }, + { "os": "Mac-10.13.5", "pool": "Chrome" }, + { "os": "Mac-10.13.6", "pool": "Chrome" } + ], + "priority": 29 + }, + { + "app": "ios_chrome_reading_list_egtests", + "test args": [ + "--enable-features=SlimNavigationManager" + ], + "device type": "iPad Air 2", + "os": "12.1", + "xctest": true, + "dimensions": [ + { "os": "Mac-10.13.4", "pool": "Chrome" }, + { "os": "Mac-10.13.5", "pool": "Chrome" }, + { "os": "Mac-10.13.6", "pool": "Chrome" } + ], + "priority": 29 + }, + { + "app": "ios_showcase_egtests", + "test args": [ + "--enable-features=SlimNavigationManager" + ], + "device type": "iPad Air 2", + "os": "12.1", + "xctest": true, + "dimensions": [ + { "os": "Mac-10.13.4", "pool": "Chrome" }, + { "os": "Mac-10.13.5", "pool": "Chrome" }, + { "os": "Mac-10.13.6", "pool": "Chrome" } + ], + "priority": 29 + }, + { + "app": "ios_chrome_bookmarks_egtests", + "test args": [ + "--enable-features=SlimNavigationManager" + ], + "device type": "iPhone X", + "os": "11.4", + "shard size": 2, + "xctest": true, + "dimensions": [ + { "os": "Mac-10.13.4", "pool": "Chrome" }, + { "os": "Mac-10.13.5", "pool": "Chrome" }, + { "os": "Mac-10.13.6", "pool": "Chrome" } + ], + "priority": 29 + }, + { + "app": "ios_chrome_manual_fill_egtests", + "test args": [ + "--enable-features=AutofillManualFallback,WebFrameMessaging,SlimNavigationManager" + ], + "xctest": true, "device type": "iPhone X", "os": "11.4", "dimensions": [ @@ -183,12 +355,149 @@ "priority": 29 }, { - "include": "eg_tests.json", + "app": "ios_chrome_web_egtests", + "test args": [ + "--enable-features=SlimNavigationManager" + ], + "device type": "iPhone X", + "os": "11.4", + "xctest": true, + "dimensions": [ + { "os": "Mac-10.13.4", "pool": "Chrome" }, + { "os": "Mac-10.13.5", "pool": "Chrome" }, + { "os": "Mac-10.13.6", "pool": "Chrome" } + ], + "priority": 29 + }, + { + "app": "ios_chrome_settings_egtests", + "test args": [ + "--enable-features=SlimNavigationManager" + ], + "device type": "iPhone X", + "os": "11.4", + "xctest": true, + "dimensions": [ + { "os": "Mac-10.13.4", "pool": "Chrome" }, + { "os": "Mac-10.13.5", "pool": "Chrome" }, + { "os": "Mac-10.13.6", "pool": "Chrome" } + ], + "priority": 29 + }, + { + "app": "ios_chrome_reading_list_egtests", + "test args": [ + "--enable-features=SlimNavigationManager" + ], + "device type": "iPhone X", + "os": "11.4", + "xctest": true, + "dimensions": [ + { "os": "Mac-10.13.4", "pool": "Chrome" }, + { "os": "Mac-10.13.5", "pool": "Chrome" }, + { "os": "Mac-10.13.6", "pool": "Chrome" } + ], + "priority": 29 + }, + { + "app": "ios_showcase_egtests", + "test args": [ + "--enable-features=SlimNavigationManager" + ], + "device type": "iPhone X", + "os": "11.4", + "xctest": true, + "dimensions": [ + { "os": "Mac-10.13.4", "pool": "Chrome" }, + { "os": "Mac-10.13.5", "pool": "Chrome" }, + { "os": "Mac-10.13.6", "pool": "Chrome" } + ], + "priority": 29 + }, + { + "app": "ios_chrome_bookmarks_egtests", + "test args": [ + "--enable-features=SlimNavigationManager" + ], + "shard size": 2, + "device type": "iPhone X", + "os": "12.1", + "xctest": true, + "dimensions": [ + { "os": "Mac-10.13.4", "pool": "Chrome" }, + { "os": "Mac-10.13.5", "pool": "Chrome" }, + { "os": "Mac-10.13.6", "pool": "Chrome" } + ], + "priority": 29 + }, + { + "app": "ios_chrome_manual_fill_egtests", + "test args": [ + "--enable-features=AutofillManualFallback,WebFrameMessaging,SlimNavigationManager" + ], + "device type": "iPhone X", + "os": "12.1", + "xctest": true, + "dimensions": [ + { "os": "Mac-10.13.4", "pool": "Chrome" }, + { "os": "Mac-10.13.5", "pool": "Chrome" }, + { "os": "Mac-10.13.6", "pool": "Chrome" } + ], + "priority": 29 + }, + { + "app": "ios_chrome_web_egtests", "test args": [ "--enable-features=SlimNavigationManager" ], "device type": "iPhone X", "os": "12.1", + "xctest": true, + "dimensions": [ + { "os": "Mac-10.13.4", "pool": "Chrome" }, + { "os": "Mac-10.13.5", "pool": "Chrome" }, + { "os": "Mac-10.13.6", "pool": "Chrome" } + ], + "priority": 29 + }, + { + "app": "ios_chrome_settings_egtests", + "test args": [ + "--enable-features=SlimNavigationManager" + ], + "device type": "iPhone X", + "os": "12.1", + "xctest": true, + "dimensions": [ + { "os": "Mac-10.13.4", "pool": "Chrome" }, + { "os": "Mac-10.13.5", "pool": "Chrome" }, + { "os": "Mac-10.13.6", "pool": "Chrome" } + ], + "priority": 29 + }, + { + "app": "ios_chrome_reading_list_egtests", + "test args": [ + "--enable-features=SlimNavigationManager" + ], + "device type": "iPhone X", + "os": "12.1", + "xctest": true, + "dimensions": [ + { "os": "Mac-10.13.4", "pool": "Chrome" }, + { "os": "Mac-10.13.5", "pool": "Chrome" }, + { "os": "Mac-10.13.6", "pool": "Chrome" } + ], + "priority": 29 + }, + { + "app": "ios_showcase_egtests", + "test args": [ + "--enable-features=SlimNavigationManager" + ], + "device type": "iPhone X", + "os": "12.1", + "xctest": true, "dimensions": [ { "os": "Mac-10.13.4", "pool": "Chrome" }, { "os": "Mac-10.13.5", "pool": "Chrome" },
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm index fb32f26..aabc70eb 100644 --- a/ios/chrome/app/main_controller.mm +++ b/ios/chrome/app/main_controller.mm
@@ -1768,11 +1768,6 @@ return [_browserViewWrangler mainBVC]; } -- (void)setMainBVC:(BrowserViewController*)mainBVC { - DCHECK(_browserViewWrangler); - [_browserViewWrangler setMainBVC:mainBVC]; -} - - (TabModel*)mainTabModel { DCHECK(_browserViewWrangler); return [_browserViewWrangler mainTabModel]; @@ -1788,11 +1783,6 @@ return [_browserViewWrangler otrBVC]; } -- (void)setOtrBVC:(BrowserViewController*)otrBVC { - DCHECK(_browserViewWrangler); - [_browserViewWrangler setOtrBVC:otrBVC]; -} - - (TabModel*)otrTabModel { DCHECK(_browserViewWrangler); return [_browserViewWrangler otrTabModel]; @@ -2299,29 +2289,9 @@ (NTPTabOpeningPostOpeningAction)action { switch (action) { case START_VOICE_SEARCH: - if (@available(iOS 11, *)) { - return ^{ - [self startVoiceSearchInCurrentBVC]; - }; - } else { - return ^{ - // On iOS10.3.X, the launching the application using an external URL - // sometimes triggers notifications - // applicationDidBecomeActive - // applicationWillResignActive - // applicationDidBecomeActive. - // Triggering voiceSearch immediatley will cause its dismiss on - // applicationWillResignActive. - // Add a timer here and hope this will be enough so that voice search - // is triggered after second applicationDidBecomeActive. - // TODO(crbug.com/766951): remove this workaround. - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 100 * NSEC_PER_MSEC), - dispatch_get_main_queue(), ^{ - [self startVoiceSearchInCurrentBVC]; - }); - - }; - } + return ^{ + [self startVoiceSearchInCurrentBVC]; + }; case START_QR_CODE_SCANNER: return ^{ [self.currentBVC.dispatcher showQRScanner];
diff --git a/ios/chrome/browser/autofill/autofill_controller_unittest.mm b/ios/chrome/browser/autofill/autofill_controller_unittest.mm index 1f1f3b5..03747a1 100644 --- a/ios/chrome/browser/autofill/autofill_controller_unittest.mm +++ b/ios/chrome/browser/autofill/autofill_controller_unittest.mm
@@ -558,13 +558,6 @@ // Checks that focusing on and typing on one field, then changing focus before // typing again, result in suggestions. TEST_F(AutofillControllerTest, KeyValueFocusChange) { -#if !TARGET_IPHONE_SIMULATOR - if (!base::ios::IsRunningOnIOS11OrLater()) { - // TODO(crbug.com/836808): This test hangs on iOS10 devices when there are - // no breakpoint. - return; - } -#endif SetUpKeyValueData(); // Focus the dummy field and confirm no suggestions are presented.
diff --git a/ios/chrome/browser/autofill/form_input_accessory_view.mm b/ios/chrome/browser/autofill/form_input_accessory_view.mm index 08a5fb3..cb7520d 100644 --- a/ios/chrome/browser/autofill/form_input_accessory_view.mm +++ b/ios/chrome/browser/autofill/form_input_accessory_view.mm
@@ -150,7 +150,7 @@ trailingView.translatesAutoresizingMaskIntoConstraints = NO; [self addSubview:trailingView]; - id<LayoutGuideProvider> layoutGuide = SafeAreaLayoutGuideForView(self); + id<LayoutGuideProvider> layoutGuide = self.safeAreaLayoutGuide; [NSLayoutConstraint activateConstraints:@[ [leadingViewContainer.topAnchor constraintEqualToAnchor:layoutGuide.topAnchor],
diff --git a/ios/chrome/browser/autofill/form_input_accessory_view_controller.mm b/ios/chrome/browser/autofill/form_input_accessory_view_controller.mm index bb5885f1..df20ca6 100644 --- a/ios/chrome/browser/autofill/form_input_accessory_view_controller.mm +++ b/ios/chrome/browser/autofill/form_input_accessory_view_controller.mm
@@ -281,15 +281,6 @@ // On ipad we hide the views so they don't stick around at the bottom. Only // needed on iPad because we add the view directly to the keyboard view. if (IsIPadIdiom() && self.customAccessoryView) { - if (@available(iOS 11, *)) { - } else { - // [iPad iOS 10] There is a bug when constraining something to the - // keyboard view. So this updates the frame instead. - CGFloat height = autofill::kInputAccessoryHeight; - self.customAccessoryView.frame = - CGRectMake(keyboardView.frame.origin.x, -height, - keyboardView.frame.size.width, height); - } if (CGRectEqualToRect(_keyboardFrame, CGRectZero)) { self.customAccessoryView.hidden = true; self.grayBackgroundView.hidden = true; @@ -318,28 +309,18 @@ if (self.customAccessoryView && !self.customAccessoryView.superview) { if (IsIPadIdiom()) { UIView* keyboardView = [self getKeyboardView]; - // [iPad iOS 10] There is a bug when constraining something to the - // keyboard view. So this sets the frame instead. - if (@available(iOS 11, *)) { - self.customAccessoryView.translatesAutoresizingMaskIntoConstraints = NO; - [keyboardView addSubview:self.customAccessoryView]; - [NSLayoutConstraint activateConstraints:@[ - [self.customAccessoryView.leadingAnchor - constraintEqualToAnchor:keyboardView.leadingAnchor], - [self.customAccessoryView.trailingAnchor - constraintEqualToAnchor:keyboardView.trailingAnchor], - [self.customAccessoryView.bottomAnchor - constraintEqualToAnchor:keyboardView.topAnchor], - [self.customAccessoryView.heightAnchor - constraintEqualToConstant:autofill::kInputAccessoryHeight] - ]]; - } else { - CGFloat height = autofill::kInputAccessoryHeight; - self.customAccessoryView.frame = - CGRectMake(keyboardView.frame.origin.x, -height, - keyboardView.frame.size.width, height); - [keyboardView addSubview:self.customAccessoryView]; - } + self.customAccessoryView.translatesAutoresizingMaskIntoConstraints = NO; + [keyboardView addSubview:self.customAccessoryView]; + [NSLayoutConstraint activateConstraints:@[ + [self.customAccessoryView.leadingAnchor + constraintEqualToAnchor:keyboardView.leadingAnchor], + [self.customAccessoryView.trailingAnchor + constraintEqualToAnchor:keyboardView.trailingAnchor], + [self.customAccessoryView.bottomAnchor + constraintEqualToAnchor:keyboardView.topAnchor], + [self.customAccessoryView.heightAnchor + constraintEqualToConstant:autofill::kInputAccessoryHeight] + ]]; if (!self.grayBackgroundView.superview) { [keyboardView addSubview:self.grayBackgroundView]; [keyboardView sendSubviewToBack:self.grayBackgroundView];
diff --git a/ios/chrome/browser/autofill/manual_fill/passwords_fetcher.mm b/ios/chrome/browser/autofill/manual_fill/passwords_fetcher.mm index 8e53bdc..24a743c 100644 --- a/ios/chrome/browser/autofill/manual_fill/passwords_fetcher.mm +++ b/ios/chrome/browser/autofill/manual_fill/passwords_fetcher.mm
@@ -15,14 +15,44 @@ #error "This file requires ARC support." #endif -@interface PasswordFetcher ()<SavePasswordsConsumerDelegate> { +// Protocol to observe changes on the Password Store. +@protocol PasswordStoreObserver<NSObject> + +// The logins in the Password Store changed. +- (void)loginsDidChange; + +@end + +namespace { + +// Objective-C bridge to observe changes in the Password Store. +class PasswordStoreObserverBridge + : public password_manager::PasswordStore::Observer { + public: + explicit PasswordStoreObserverBridge(id<PasswordStoreObserver> observer) + : observer_(observer) {} + + PasswordStoreObserverBridge() {} + + private: + void OnLoginsChanged( + const password_manager::PasswordStoreChangeList& changes) override { + [observer_ loginsDidChange]; + } + __weak id<PasswordStoreObserver> observer_ = nil; +}; + +} // namespace + +@interface PasswordFetcher ()<SavePasswordsConsumerDelegate, + PasswordStoreObserver> { // The interface for getting and manipulating a user's saved passwords. scoped_refptr<password_manager::PasswordStore> _passwordStore; // A helper object for passing data about saved passwords from a finished // password store request to the SavePasswordsCollectionViewController. std::unique_ptr<ios::SavePasswordsConsumer> _savedPasswordsConsumer; - // The list of the user's saved passwords. - std::vector<std::unique_ptr<autofill::PasswordForm>> _savedForms; + // The object to observe changes in the Password Store. + std::unique_ptr<PasswordStoreObserverBridge> _passwordStoreObserver; } // Delegate to send the fetchted passwords. @@ -48,23 +78,37 @@ _passwordStore = passwordStore; _savedPasswordsConsumer.reset(new ios::SavePasswordsConsumer(self)); _passwordStore->GetAutofillableLogins(_savedPasswordsConsumer.get()); + _passwordStoreObserver.reset(new PasswordStoreObserverBridge(self)); + _passwordStore->AddObserver(_passwordStoreObserver.get()); } return self; } +- (void)dealloc { + _passwordStore->RemoveObserver(_passwordStoreObserver.get()); +} + #pragma mark - SavePasswordsConsumerDelegate - (void)onGetPasswordStoreResults: (std::vector<std::unique_ptr<autofill::PasswordForm>>&)result { - for (auto it = result.begin(); it != result.end(); ++it) { - if (!(*it)->blacklisted_by_user) - _savedForms.push_back(std::move(*it)); - } + result.erase( + std::remove_if(result.begin(), result.end(), + [](std::unique_ptr<autofill::PasswordForm>& form) { + return form->blacklisted_by_user; + }), + result.end()); password_manager::DuplicatesMap savedPasswordDuplicates; - password_manager::SortEntriesAndHideDuplicates(&_savedForms, + password_manager::SortEntriesAndHideDuplicates(&result, &savedPasswordDuplicates); - [self.delegate passwordFetcher:self didFetchPasswords:_savedForms]; + [self.delegate passwordFetcher:self didFetchPasswords:result]; +} + +#pragma mark - PasswordStoreObserver + +- (void)loginsDidChange { + _passwordStore->GetAutofillableLogins(_savedPasswordsConsumer.get()); } @end
diff --git a/ios/chrome/browser/autofill/manual_fill/passwords_fetcher_unittest.mm b/ios/chrome/browser/autofill/manual_fill/passwords_fetcher_unittest.mm index 5afd173a..79a67fb5 100644 --- a/ios/chrome/browser/autofill/manual_fill/passwords_fetcher_unittest.mm +++ b/ios/chrome/browser/autofill/manual_fill/passwords_fetcher_unittest.mm
@@ -74,24 +74,26 @@ .get(); } - // Creates and adds a saved password form. - void AddSavedForm1() { - auto form = std::make_unique<autofill::PasswordForm>(); - form->origin = GURL("http://www.example.com/accounts/LoginAuth"); - form->action = GURL("http://www.example.com/accounts/Login"); - form->username_element = base::ASCIIToUTF16("Email"); - form->username_value = base::ASCIIToUTF16("test@egmail.com"); - form->password_element = base::ASCIIToUTF16("Passwd"); - form->password_value = base::ASCIIToUTF16("test"); - form->submit_element = base::ASCIIToUTF16("signIn"); - form->signon_realm = "http://www.example.com/"; - form->preferred = false; - form->scheme = autofill::PasswordForm::SCHEME_HTML; - form->blacklisted_by_user = false; - GetPasswordStore()->AddLogin(*std::move(form)); + autofill::PasswordForm Form1() { + autofill::PasswordForm form; + form.origin = GURL("http://www.example.com/accounts/LoginAuth"); + form.action = GURL("http://www.example.com/accounts/Login"); + form.username_element = base::ASCIIToUTF16("Email"); + form.username_value = base::ASCIIToUTF16("test@egmail.com"); + form.password_element = base::ASCIIToUTF16("Passwd"); + form.password_value = base::ASCIIToUTF16("test"); + form.submit_element = base::ASCIIToUTF16("signIn"); + form.signon_realm = "http://www.example.com/"; + form.preferred = false; + form.scheme = autofill::PasswordForm::SCHEME_HTML; + form.blacklisted_by_user = false; + return form; } // Creates and adds a saved password form. + void AddSavedForm1() { GetPasswordStore()->AddLogin(Form1()); } + + // Creates and adds a saved password form. void AddSavedForm2() { auto form = std::make_unique<autofill::PasswordForm>(); form->origin = GURL("http://www.example2.com/accounts/LoginAuth"); @@ -227,4 +229,32 @@ EXPECT_TRUE(passwordFetcher); } +// Tests PasswordFetcher receives 0 passwords. +TEST_F(PasswordFetcherTest, ReceivesZeroPasswords) { + AddSavedForm1(); + TestPasswordFetcherDelegate* passwordFetcherDelegate = + [[TestPasswordFetcherDelegate alloc] init]; + auto passwordStore = IOSChromePasswordStoreFactory::GetForBrowserState( + chrome_browser_state_.get(), ServiceAccessType::EXPLICIT_ACCESS); + PasswordFetcher* passwordFetcher = + [[PasswordFetcher alloc] initWithPasswordStore:passwordStore + delegate:passwordFetcherDelegate]; + WaitUntilCondition( + ^bool { + return passwordFetcherDelegate.passwordNumber > 0; + }, + true, base::TimeDelta::FromSeconds(1000)); + EXPECT_EQ(passwordFetcherDelegate.passwordNumber, 1u); + + GetPasswordStore()->RemoveLogin(Form1()); + + WaitUntilCondition( + ^bool { + return passwordFetcherDelegate.passwordNumber == 0; + }, + true, base::TimeDelta::FromSeconds(1000)); + EXPECT_EQ(passwordFetcherDelegate.passwordNumber, 0u); + EXPECT_TRUE(passwordFetcher); +} + } // namespace
diff --git a/ios/chrome/browser/device_sharing/handoff_manager_egtest.mm b/ios/chrome/browser/device_sharing/handoff_manager_egtest.mm index b99f7f6..8577156 100644 --- a/ios/chrome/browser/device_sharing/handoff_manager_egtest.mm +++ b/ios/chrome/browser/device_sharing/handoff_manager_egtest.mm
@@ -114,7 +114,7 @@ // When tab 3 is closed, tab 2 is front and Handoff URL should be the URL for // tab 2. - chrome_test_util::CloseCurrentTab(); + [ChromeEarlGrey closeCurrentTab]; AssertHandoffURL(tab2URL); // Switches back to the first tab.
diff --git a/ios/chrome/browser/drag_and_drop/drop_and_navigate_interaction_unittest.mm b/ios/chrome/browser/drag_and_drop/drop_and_navigate_interaction_unittest.mm index ea0fb4a..e6393e2 100644 --- a/ios/chrome/browser/drag_and_drop/drop_and_navigate_interaction_unittest.mm +++ b/ios/chrome/browser/drag_and_drop/drop_and_navigate_interaction_unittest.mm
@@ -17,11 +17,9 @@ using DropAndNavigateTest = PlatformTest; TEST_F(DropAndNavigateTest, Instantiation) { - if (@available(iOS 11, *)) { - DropAndNavigateInteraction* interaction = - [[DropAndNavigateInteraction alloc] initWithDelegate:nil]; - DCHECK(interaction.delegate); - } + DropAndNavigateInteraction* interaction = + [[DropAndNavigateInteraction alloc] initWithDelegate:nil]; + DCHECK(interaction.delegate); } } // namespace
diff --git a/ios/chrome/browser/metrics/drag_and_drop_recorder.mm b/ios/chrome/browser/metrics/drag_and_drop_recorder.mm index 44d470082..690a7dcf 100644 --- a/ios/chrome/browser/metrics/drag_and_drop_recorder.mm +++ b/ios/chrome/browser/metrics/drag_and_drop_recorder.mm
@@ -64,12 +64,10 @@ - (instancetype)initWithView:(UIView*)view { self = [super init]; if (self) { - if (@available(iOS 11, *)) { - dropSessions_ = [NSHashTable weakObjectsHashTable]; - UIDropInteraction* dropInteraction = - [[UIDropInteraction alloc] initWithDelegate:self]; - [view addInteraction:dropInteraction]; - } + dropSessions_ = [NSHashTable weakObjectsHashTable]; + UIDropInteraction* dropInteraction = + [[UIDropInteraction alloc] initWithDelegate:self]; + [view addInteraction:dropInteraction]; } return self; }
diff --git a/ios/chrome/browser/metrics/tab_usage_recorder_egtest.mm b/ios/chrome/browser/metrics/tab_usage_recorder_egtest.mm index 38da8aa..f7558526 100644 --- a/ios/chrome/browser/metrics/tab_usage_recorder_egtest.mm +++ b/ios/chrome/browser/metrics/tab_usage_recorder_egtest.mm
@@ -94,11 +94,7 @@ // Opens 2 new tabs with different URLs. void OpenTwoTabs() { - chrome_test_util::CloseAllTabsInCurrentMode(); - // TODO(crbug.com/783192): ChromeEarlGrey should have a method to close all - // tabs and synchronize with the UI. - [[GREYUIThreadExecutor sharedInstance] drainUntilIdle]; - + [ChromeEarlGrey closeAllTabsInCurrentMode]; const GURL url1 = web::test::HttpServer::MakeUrl(kTestUrl1); const GURL url2 = web::test::HttpServer::MakeUrl(kTestUrl2); NewMainTabWithURL(url1, kURL1FirstWord); @@ -179,10 +175,7 @@ // This test opens three tabs. const int numberOfTabs = 3; - chrome_test_util::CloseAllTabsInCurrentMode(); - // TODO(crbug.com/783192): ChromeEarlGrey should have a method to close all - // tabs and synchronize with the UI. - [[GREYUIThreadExecutor sharedInstance] drainUntilIdle]; + [ChromeEarlGrey closeAllTabsInCurrentMode]; // Open three tabs with http:// urls. for (NSUInteger i = 0; i < numberOfTabs; i++) { @@ -345,11 +338,7 @@ GREYFail(error); }; - chrome_test_util::CloseAllTabsInCurrentMode(); - // TODO(crbug.com/783192): ChromeEarlGrey should have a method to close all - // tabs and synchronize with the UI. - [[GREYUIThreadExecutor sharedInstance] drainUntilIdle]; - + [ChromeEarlGrey closeAllTabsInCurrentMode]; GURL URL = web::test::HttpServer::MakeUrl(kTestUrl1); NewMainTabWithURL(URL, kURL1FirstWord); OpenNewIncognitoTabUsingUIAndEvictMainTabs();
diff --git a/ios/chrome/browser/metrics/ukm_egtest.mm b/ios/chrome/browser/metrics/ukm_egtest.mm index 04b9067..94b7a60 100644 --- a/ios/chrome/browser/metrics/ukm_egtest.mm +++ b/ios/chrome/browser/metrics/ukm_egtest.mm
@@ -151,12 +151,12 @@ void CloseCurrentIncognitoTab() { NSUInteger incognito_tab_count = GetIncognitoTabCount(); - chrome_test_util::CloseCurrentTab(); + [ChromeEarlGrey closeCurrentTab]; [ChromeEarlGrey waitForIncognitoTabCount:(incognito_tab_count - 1)]; } void CloseAllIncognitoTabs() { - GREYAssert(chrome_test_util::CloseAllIncognitoTabs(), @"Tabs did not close"); + [ChromeEarlGrey closeAllIncognitoTabs]; [ChromeEarlGrey waitForIncognitoTabCount:0]; // The user is dropped into the tab grid after closing the last incognito tab. @@ -302,7 +302,7 @@ OpenNewRegularTab(); AssertUKMEnabled(false); - GREYAssert(chrome_test_util::CloseAllIncognitoTabs(), @"Tabs did not close"); + [ChromeEarlGrey closeAllIncognitoTabs]; [ChromeEarlGrey waitForIncognitoTabCount:0]; AssertUKMEnabled(true);
diff --git a/ios/chrome/browser/net/cookie_util.mm b/ios/chrome/browser/net/cookie_util.mm index 65130370..7582d21 100644 --- a/ios/chrome/browser/net/cookie_util.mm +++ b/ios/chrome/browser/net/cookie_util.mm
@@ -97,13 +97,11 @@ // On iOS 11, there is no need to use PersistentCookieStore or CookieMonster // because there is a way to access cookies in WKHTTPCookieStore. This will - // allow URLFetcher and anyother users of net:CookieStore to in iOS to set + // allow URLFetcher and any other users of net:CookieStore to in iOS to set // and get cookies directly in WKHTTPCookieStore. - if (@available(iOS 11, *)) { - if (base::FeatureList::IsEnabled(web::features::kWKHTTPSystemCookieStore)) { - return std::make_unique<net::CookieStoreIOS>( - std::move(system_cookie_store), net_log); - } + if (base::FeatureList::IsEnabled(web::features::kWKHTTPSystemCookieStore)) { + return std::make_unique<net::CookieStoreIOS>(std::move(system_cookie_store), + net_log); } scoped_refptr<net::SQLitePersistentCookieStore> persistent_store = nullptr;
diff --git a/ios/chrome/browser/net/cookie_util_unittest.mm b/ios/chrome/browser/net/cookie_util_unittest.mm index d28fdd6f..6e95565 100644 --- a/ios/chrome/browser/net/cookie_util_unittest.mm +++ b/ios/chrome/browser/net/cookie_util_unittest.mm
@@ -116,17 +116,10 @@ return callback_called; })); - if (@available(iOS 11, *)) { - // When WKHTTPSystemCookieStore feature is enabled and the iOS version is - // 11+ the cookie should be set directly in the backing SystemCookieStore. - EXPECT_EQ(1U, result_cookies.count); - EXPECT_NSEQ(cookie_name, result_cookies[0].name); - EXPECT_NSEQ(cookie_value, result_cookies[0].value); - } else { - // Before iOS 11, cookies are not set in the backing SystemCookieStore - // instead they are found on CookieMonster. - EXPECT_EQ(0U, result_cookies.count); - } + // The cookie should be set directly in the backing SystemCookieStore. + EXPECT_EQ(1U, result_cookies.count); + EXPECT_NSEQ(cookie_name, result_cookies[0].name); + EXPECT_NSEQ(cookie_value, result_cookies[0].value); // Clear cookies that was set in the test. __block bool cookies_cleared = false;
diff --git a/ios/chrome/browser/net/cookies_egtest.mm b/ios/chrome/browser/net/cookies_egtest.mm index d7fb763..ebbf929 100644 --- a/ios/chrome/browser/net/cookies_egtest.mm +++ b/ios/chrome/browser/net/cookies_egtest.mm
@@ -133,11 +133,7 @@ // Finally, closes all incognito tabs while still in normal tab. // Checks that incognito cookie is gone. - GREYAssert(chrome_test_util::CloseAllIncognitoTabs(), @"Tabs did not close"); - // TODO(crbug.com/783192): ChromeEarlGrey should have a method to close all - // incognito tabs and synchronize with the UI. - [[GREYUIThreadExecutor sharedInstance] drainUntilIdle]; - + [ChromeEarlGrey closeAllIncognitoTabs]; [ChromeEarlGrey openNewTab]; [ChromeEarlGrey loadURL:web::test::HttpServer::MakeUrl(kTestUrlIncognitoBrowsing)]; @@ -165,11 +161,7 @@ @"Only one cookie should be found in incognito mode."); // Closes all incognito tabs and switch back to a normal tab. - GREYAssert(chrome_test_util::CloseAllIncognitoTabs(), @"Tabs did not close"); - // TODO(crbug.com/783192): ChromeEarlGrey should have a method to close all - // incognito tabs and synchronize with the UI. - [[GREYUIThreadExecutor sharedInstance] drainUntilIdle]; - + [ChromeEarlGrey closeAllIncognitoTabs]; [ChromeEarlGrey openNewTab]; [ChromeEarlGrey loadURL:web::test::HttpServer::MakeUrl(kTestUrlNormalBrowsing)]; @@ -214,11 +206,7 @@ // Closes all incognito tabs and then switching back to a normal tab. Verifies // that the cookie set earlier is still there. - GREYAssert(chrome_test_util::CloseAllIncognitoTabs(), @"Tabs did not close"); - // TODO(crbug.com/783192): ChromeEarlGrey should have a method to close all - // incognito tabs and synchronize with the UI. - [[GREYUIThreadExecutor sharedInstance] drainUntilIdle]; - + [ChromeEarlGrey closeAllIncognitoTabs]; [ChromeEarlGrey openNewTab]; [ChromeEarlGrey loadURL:web::test::HttpServer::MakeUrl(kTestUrlNormalBrowsing)];
diff --git a/ios/chrome/browser/passwords/save_passwords_consumer.mm b/ios/chrome/browser/passwords/save_passwords_consumer.mm index bd472f3..904c0c7 100644 --- a/ios/chrome/browser/passwords/save_passwords_consumer.mm +++ b/ios/chrome/browser/passwords/save_passwords_consumer.mm
@@ -18,8 +18,7 @@ void SavePasswordsConsumer::OnGetPasswordStoreResults( std::vector<std::unique_ptr<autofill::PasswordForm>> results) { - if (!results.empty()) - [delegate_ onGetPasswordStoreResults:results]; + [delegate_ onGetPasswordStoreResults:results]; } } // namespace ios
diff --git a/ios/chrome/browser/prerender/prerender_egtest.mm b/ios/chrome/browser/prerender/prerender_egtest.mm index 04c3892..91ab237 100644 --- a/ios/chrome/browser/prerender/prerender_egtest.mm +++ b/ios/chrome/browser/prerender/prerender_egtest.mm
@@ -53,13 +53,11 @@ // Test that tapping the prerendered suggestions opens it. - (void)testTapPrerenderSuggestions { - // TODO(crbug.com/793306): Re-enable the test on iOS 11 iPad once the - // alternate letters problem is fixed. + // TODO(crbug.com/793306): Re-enable the test on iPad once the alternate + // letters problem is fixed. if (IsIPadIdiom()) { - if (@available(iOS 11, *)) { - EARL_GREY_TEST_DISABLED( - @"Disabled for iPad due to alternate letters educational screen."); - } + EARL_GREY_TEST_DISABLED( + @"Disabled for iPad due to alternate letters educational screen."); } GREYAssertTrue(chrome_test_util::ClearBrowsingHistory(),
diff --git a/ios/chrome/browser/signin/gaia_auth_fetcher_ios.mm b/ios/chrome/browser/signin/gaia_auth_fetcher_ios.mm index 1a081c4..e2e7b30 100644 --- a/ios/chrome/browser/signin/gaia_auth_fetcher_ios.mm +++ b/ios/chrome/browser/signin/gaia_auth_fetcher_ios.mm
@@ -362,8 +362,7 @@ // a network request with cookies sent and saved is by making it through a // WKWebView. SetPendingFetch(true); - bool shouldUseXmlHTTPRequest = - IsMultiloginUrl(gaia_gurl) || !base::ios::IsRunningOnIOS11OrLater(); + bool shouldUseXmlHTTPRequest = IsMultiloginUrl(gaia_gurl); bridge_->Fetch(gaia_gurl, headers, body, shouldUseXmlHTTPRequest); }
diff --git a/ios/chrome/browser/signin/gaia_auth_fetcher_ios_unittest.mm b/ios/chrome/browser/signin/gaia_auth_fetcher_ios_unittest.mm index 5f3d687..00e2413 100644 --- a/ios/chrome/browser/signin/gaia_auth_fetcher_ios_unittest.mm +++ b/ios/chrome/browser/signin/gaia_auth_fetcher_ios_unittest.mm
@@ -106,15 +106,8 @@ GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED); EXPECT_CALL(consumer_, OnClientLoginFailure(expected_error)).Times(1); - if (base::ios::IsRunningOnIOS11OrLater()) { - [static_cast<WKWebView*>([GetMockWKWebView() expect]) - loadRequest:[OCMArg any]]; - } else { - // TODO(crbug.com/740987): Remove this code once iOS 10 is dropped. - [static_cast<WKWebView*>([GetMockWKWebView() expect]) - loadHTMLString:[OCMArg any] - baseURL:[OCMArg any]]; - } + [static_cast<WKWebView*>([GetMockWKWebView() expect]) + loadRequest:[OCMArg any]]; [[GetMockWKWebView() expect] stopLoading]; gaia_auth_fetcher_->StartOAuthLogin("fake_token", "gaia");
diff --git a/ios/chrome/browser/snapshots/snapshot_tab_helper.mm b/ios/chrome/browser/snapshots/snapshot_tab_helper.mm index 560d6ae..7af220e 100644 --- a/ios/chrome/browser/snapshots/snapshot_tab_helper.mm +++ b/ios/chrome/browser/snapshots/snapshot_tab_helper.mm
@@ -129,13 +129,10 @@ void SnapshotTabHelper::UpdateSnapshotWithCallback(void (^callback)(UIImage*)) { if (IsWKWebViewSnapshotsEnabled() && web_state_->ContentIsHTML()) { - if (@available(iOS 11, *)) { - [snapshot_generator_ updateWebViewSnapshotWithCompletion:callback]; - return; - } + [snapshot_generator_ updateWebViewSnapshotWithCompletion:callback]; + return; } - // Pre-iOS 11 and native content cannot utilize the WKWebView snapshotting - // API. + // Native content cannot utilize the WKWebView snapshotting API. UIImage* image = UpdateSnapshot(/*with_overlays=*/true, /*visible_frame_only=*/true); dispatch_async(dispatch_get_main_queue(), ^{ @@ -209,17 +206,14 @@ if (!ignore_next_load_ && !pause_snapshotting_ && load_completion_status == web::PageLoadCompletionStatus::SUCCESS) { if (IsWKWebViewSnapshotsEnabled() && web_state->ContentIsHTML()) { - if (@available(iOS 11, *)) { - base::PostDelayedTaskWithTraits( - FROM_HERE, {web::WebThread::UI}, - base::BindOnce(&SnapshotTabHelper::UpdateSnapshotWithCallback, - weak_ptr_factory_.GetWeakPtr(), /*callback=*/nil), - base::TimeDelta::FromSeconds(1)); - return; - } + base::PostDelayedTaskWithTraits( + FROM_HERE, {web::WebThread::UI}, + base::BindOnce(&SnapshotTabHelper::UpdateSnapshotWithCallback, + weak_ptr_factory_.GetWeakPtr(), /*callback=*/nil), + base::TimeDelta::FromSeconds(1)); + return; } - // Pre-iOS 11 and native content cannot utilize the WKWebView snapshotting - // API. + // Native content cannot utilize the WKWebView snapshotting API. UpdateSnapshot(/*with_overlays=*/true, /*visible_frame_only=*/true); } ignore_next_load_ = false;
diff --git a/ios/chrome/browser/tabs/tab.h b/ios/chrome/browser/tabs/tab.h index bba48a32..c3fd137 100644 --- a/ios/chrome/browser/tabs/tab.h +++ b/ios/chrome/browser/tabs/tab.h
@@ -108,10 +108,6 @@ // TODO(crbug.com/228575): Create a delegate interface and remove this. - (void)setParentTabModel:(TabModel*)model; -// The view to display in the view hierarchy based on the current URL. Won't be -// nil. It is up to the caller to size the view and confirm |webUsageEnabled|. -- (UIView*)view; - // The view that generates print data when printing. It can be nil when printing // is not supported with this tab. It can be different from |Tab view|. - (UIView*)viewForPrinting;
diff --git a/ios/chrome/browser/tabs/tab.mm b/ios/chrome/browser/tabs/tab.mm index b8a8cb9..abfc628 100644 --- a/ios/chrome/browser/tabs/tab.mm +++ b/ios/chrome/browser/tabs/tab.mm
@@ -267,22 +267,6 @@ _parentTabModel = model; } -- (UIView*)view { - if (!self.webState) - return nil; - - // Record reload of previously-evicted tab. - if (self.webState->IsEvicted() && [_parentTabModel tabUsageRecorder]) - [_parentTabModel tabUsageRecorder]->RecordPageLoadStart(self.webState); - - // Do not trigger the load if the tab has crashed. SadTabTabHelper is - // responsible for handing reload logic for crashed tabs. - if (!self.webState->IsCrashed()) { - self.webState->GetNavigationManager()->LoadIfNecessary(); - } - return self.webState->GetView(); -} - - (UIView*)viewForPrinting { return self.webController.viewForPrinting; } @@ -420,8 +404,7 @@ _openInController = [[OpenInController alloc] initWithURLLoaderFactory:_browserState->GetSharedURLLoaderFactory() webController:self.webController]; - // If the tab was evicted before, It should have been loaded already before - // starting the open-in controller. + // Previously evicted tabs should be reloaded before this method is called. DCHECK(!self.webState->IsEvicted()); self.webState->GetNavigationManager()->LoadIfNecessary(); _openInController.baseView = self.webState->GetView();
diff --git a/ios/chrome/browser/ui/activity_services/activity_service_controller_egtest.mm b/ios/chrome/browser/ui/activity_services/activity_service_controller_egtest.mm index 2cf907b..a33c485 100644 --- a/ios/chrome/browser/ui/activity_services/activity_service_controller_egtest.mm +++ b/ios/chrome/browser/ui/activity_services/activity_service_controller_egtest.mm
@@ -77,11 +77,9 @@ @implementation ActivityServiceControllerTestCase - (void)testActivityServiceControllerCantPrintUnprintablePages { - // TODO(crbug.com/747622): re-enable this test on iOS 11 once earl grey can - // interact with the share menu. - if (base::ios::IsRunningOnIOS11OrLater()) { - EARL_GREY_TEST_DISABLED(@"Disabled on iOS 11."); - } + // TODO(crbug.com/747622): re-enable this test on once earl grey can interact + // with the share menu. + EARL_GREY_TEST_DISABLED(@"Disabled until EG can use share menu."); // TODO(crbug.com/864597): Reenable this test. EARL_GREY_TEST_DISABLED(@"Test should be rewritten to use Offline Version."); @@ -127,11 +125,9 @@ } - (void)testOpenActivityServiceControllerAndCopy { - // TODO(crbug.com/747622): re-enable this test on iOS 11 once earl grey can - // interact with the share menu. - if (base::ios::IsRunningOnIOS11OrLater()) { - EARL_GREY_TEST_DISABLED(@"Disabled on iOS 11."); - } + // TODO(crbug.com/747622): re-enable this test once earl grey can interact + // with the share menu. + EARL_GREY_TEST_DISABLED(@"Disabled until EG can use share menu."); // Set up mock http server. std::map<GURL, std::string> responses;
diff --git a/ios/chrome/browser/ui/app_launcher/open_mail_handler_view_controller.mm b/ios/chrome/browser/ui/app_launcher/open_mail_handler_view_controller.mm index 6ebb3db..80f6c264 100644 --- a/ios/chrome/browser/ui/app_launcher/open_mail_handler_view_controller.mm +++ b/ios/chrome/browser/ui/app_launcher/open_mail_handler_view_controller.mm
@@ -86,16 +86,6 @@ - (void)viewDidLoad { [super viewDidLoad]; - - // TODO(crbug.com/765146): This is needed here because crrev/c/660257 is not - // intended for M62 branch but this change to mailto:// handling is. This - // change is redundant but can co-exist with crrev/c/660257. - // This will be reverted after cherrypick to M62. - if (@available(iOS 11, *)) { - self.collectionView.contentInsetAdjustmentBehavior = - UIScrollViewContentInsetAdjustmentNever; - } - [self loadModel]; }
diff --git a/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_option_button.mm b/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_option_button.mm index 631f9b2..337e1ff 100644 --- a/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_option_button.mm +++ b/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_option_button.mm
@@ -68,7 +68,7 @@ checkMarkImageView.tintColor = UIColorFromRGB(kAuthenticationCheckmarkColor); [option addSubview:checkMarkImageView]; - id<LayoutGuideProvider> safeArea = SafeAreaLayoutGuideForView(option); + id<LayoutGuideProvider> safeArea = option.safeAreaLayoutGuide; if (text) { // There is text to be displayed. Make sure it is taken into account.
diff --git a/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_personalization_view_controller.mm b/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_personalization_view_controller.mm index ba783b9..442b6b4 100644 --- a/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_personalization_view_controller.mm +++ b/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_personalization_view_controller.mm
@@ -51,13 +51,11 @@ self.scrollView = [[UIScrollView alloc] init]; self.scrollView.translatesAutoresizingMaskIntoConstraints = NO; - if (@available(iOS 11, *)) { - // The observed behavior was buggy. When the view appears on the screen, - // the scrollview was not scrolled all the way to the top. Adjusting the - // safe area manually fixes the issue. - self.scrollView.contentInsetAdjustmentBehavior = - UIScrollViewContentInsetAdjustmentNever; - } + // The observed behavior was buggy. When the view appears on the screen, + // the scrollview was not scrolled all the way to the top. Adjusting the + // safe area manually fixes the issue. + self.scrollView.contentInsetAdjustmentBehavior = + UIScrollViewContentInsetAdjustmentNever; [self.view addSubview:self.scrollView]; // Scroll view container. @@ -129,7 +127,7 @@ self.options = @[ noChangeOption, reviewOption, turnOnOption ]; - id<LayoutGuideProvider> safeArea = SafeAreaLayoutGuideForView(self.view); + id<LayoutGuideProvider> safeArea = self.view.safeAreaLayoutGuide; AddSameConstraints(self.view, self.scrollView); AddSameConstraints(container, self.scrollView); AddSameCenterXConstraint(container, headerImageView); @@ -226,17 +224,9 @@ // Updates constraints and content insets for the |scrollView| and // |imageBackgroundView| related to non-safe area. - (void)updateScrollViewAndImageBackgroundView { - if (@available(iOS 11, *)) { - self.scrollView.contentInset = self.view.safeAreaInsets; - self.imageBackgroundViewHeightConstraint.constant = - self.view.safeAreaInsets.top; - } else { - CGFloat statusBarHeight = - [UIApplication sharedApplication].isStatusBarHidden ? 0. - : StatusBarHeight(); - self.scrollView.contentInset = UIEdgeInsetsMake(statusBarHeight, 0, 0, 0); - self.imageBackgroundViewHeightConstraint.constant = statusBarHeight; - } + self.scrollView.contentInset = self.view.safeAreaInsets; + self.imageBackgroundViewHeightConstraint.constant = + self.view.safeAreaInsets.top; } @end
diff --git a/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_view_controller.mm b/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_view_controller.mm index b87933f..f0480900 100644 --- a/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_view_controller.mm +++ b/ios/chrome/browser/ui/authentication/consent_bump/consent_bump_view_controller.mm
@@ -230,7 +230,7 @@ self.secondaryMoreButtonMarginConstraint = [self.moreButton.leadingAnchor constraintGreaterThanOrEqualToAnchor:self.moreOptionsButton.trailingAnchor constant:kMargin]; - id<LayoutGuideProvider> safeArea = SafeAreaLayoutGuideForView(self.view); + id<LayoutGuideProvider> safeArea = self.view.safeAreaLayoutGuide; AddSameConstraintsToSides(self.view, self.gradientView, LayoutSides::kLeading | LayoutSides::kTrailing); AddSameConstraintsToSides(
diff --git a/ios/chrome/browser/ui/authentication/unified_consent/identity_chooser/identity_chooser_cell.mm b/ios/chrome/browser/ui/authentication/unified_consent/identity_chooser/identity_chooser_cell.mm index 81f7af62..e8083f9 100644 --- a/ios/chrome/browser/ui/authentication/unified_consent/identity_chooser/identity_chooser_cell.mm +++ b/ios/chrome/browser/ui/authentication/unified_consent/identity_chooser/identity_chooser_cell.mm
@@ -55,21 +55,11 @@ [self.identityView setAvatar:image]; self.accessoryType = checked ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone; - if (@available(iOS 11, *)) { - if (checked) { - self.directionalLayoutMargins = - NSDirectionalEdgeInsetsMake(0, 0, 0, kCheckmarkMagin); - } else { - self.directionalLayoutMargins = NSDirectionalEdgeInsetsZero; - } + if (checked) { + self.directionalLayoutMargins = + NSDirectionalEdgeInsetsMake(0, 0, 0, kCheckmarkMagin); } else { - if (!checked) { - self.layoutMargins = UIEdgeInsetsZero; - } else if (base::i18n::IsRTL()) { - self.layoutMargins = UIEdgeInsetsMake(0, kCheckmarkMagin, 0, 0); - } else { - self.layoutMargins = UIEdgeInsetsMake(0, 0, 0, kCheckmarkMagin); - } + self.directionalLayoutMargins = NSDirectionalEdgeInsetsZero; } }
diff --git a/ios/chrome/browser/ui/authentication/unified_consent/identity_chooser/identity_chooser_presentation_controller.mm b/ios/chrome/browser/ui/authentication/unified_consent/identity_chooser/identity_chooser_presentation_controller.mm index 6322515c..9fb92c8 100644 --- a/ios/chrome/browser/ui/authentication/unified_consent/identity_chooser/identity_chooser_presentation_controller.mm +++ b/ios/chrome/browser/ui/authentication/unified_consent/identity_chooser/identity_chooser_presentation_controller.mm
@@ -37,7 +37,7 @@ - (CGRect)frameOfPresentedViewInContainerView { CGRect safeAreaFrame = UIEdgeInsetsInsetRect( - self.containerView.bounds, SafeAreaInsetsForView(self.containerView)); + self.containerView.bounds, self.containerView.safeAreaInsets); CGFloat availableWidth = CGRectGetWidth(safeAreaFrame); CGFloat availableHeight = CGRectGetHeight(safeAreaFrame);
diff --git a/ios/chrome/browser/ui/authentication/unified_consent/unified_consent_view_controller.mm b/ios/chrome/browser/ui/authentication/unified_consent/unified_consent_view_controller.mm index 8d9b5a3..949de45c 100644 --- a/ios/chrome/browser/ui/authentication/unified_consent/unified_consent_view_controller.mm +++ b/ios/chrome/browser/ui/authentication/unified_consent/unified_consent_view_controller.mm
@@ -161,13 +161,11 @@ self.scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds]; self.scrollView.translatesAutoresizingMaskIntoConstraints = NO; self.scrollView.accessibilityIdentifier = kUnifiedConsentScrollViewIdentifier; - if (@available(iOS 11, *)) { - // The observed behavior was buggy. When the view appears on the screen, - // the scrollview was not scrolled all the way to the top. Adjusting the - // safe area manually fixes the issue. - self.scrollView.contentInsetAdjustmentBehavior = - UIScrollViewContentInsetAdjustmentNever; - } + // The observed behavior was buggy. When the view appears on the screen, + // the scrollview was not scrolled all the way to the top. Adjusting the + // safe area manually fixes the issue. + self.scrollView.contentInsetAdjustmentBehavior = + UIScrollViewContentInsetAdjustmentNever; [self.view addSubview:self.scrollView]; // Scroll view container. @@ -299,7 +297,7 @@ constraintEqualToAnchor:self.identityPickerView.bottomAnchor constant:kVerticalTextMargin]; // Adding constraints for the container. - id<LayoutGuideProvider> safeArea = SafeAreaLayoutGuideForView(self.view); + id<LayoutGuideProvider> safeArea = self.view.safeAreaLayoutGuide; [container.widthAnchor constraintEqualToAnchor:safeArea.widthAnchor].active = YES; // Adding constraints for |imageBackgroundView|. @@ -454,17 +452,9 @@ // Updates constraints and content insets for the |scrollView| and // |imageBackgroundView| related to non-safe area. - (void)updateScrollViewAndImageBackgroundView { - if (@available(iOS 11, *)) { - self.scrollView.contentInset = self.view.safeAreaInsets; - self.imageBackgroundViewHeightConstraint.constant = - self.view.safeAreaInsets.top; - } else { - CGFloat statusBarHeight = - [UIApplication sharedApplication].isStatusBarHidden ? 0. - : StatusBarHeight(); - self.scrollView.contentInset = UIEdgeInsetsMake(statusBarHeight, 0, 0, 0); - self.imageBackgroundViewHeightConstraint.constant = statusBarHeight; - } + self.scrollView.contentInset = self.view.safeAreaInsets; + self.imageBackgroundViewHeightConstraint.constant = + self.view.safeAreaInsets.top; if (self.scrollView.delegate == self) { // Don't send the notification if the delegate is not configured yet. [self sendDidReachBottomIfReached];
diff --git a/ios/chrome/browser/ui/autofill/BUILD.gn b/ios/chrome/browser/ui/autofill/BUILD.gn index c9a66d9..5bc0e4a 100644 --- a/ios/chrome/browser/ui/autofill/BUILD.gn +++ b/ios/chrome/browser/ui/autofill/BUILD.gn
@@ -33,9 +33,11 @@ "//ios/chrome/browser", "//ios/chrome/browser/autofill", "//ios/chrome/browser/autofill:autofill_shared", + "//ios/chrome/browser/autofill/manual_fill", "//ios/chrome/browser/browser_state", "//ios/chrome/browser/infobars", "//ios/chrome/browser/metrics", + "//ios/chrome/browser/passwords", "//ios/chrome/browser/passwords:passwords_generation_utils", "//ios/chrome/browser/signin", "//ios/chrome/browser/ssl",
diff --git a/ios/chrome/browser/ui/autofill/form_input_accessory_coordinator.mm b/ios/chrome/browser/ui/autofill/form_input_accessory_coordinator.mm index debfe39..1509da2 100644 --- a/ios/chrome/browser/ui/autofill/form_input_accessory_coordinator.mm +++ b/ios/chrome/browser/ui/autofill/form_input_accessory_coordinator.mm
@@ -7,7 +7,11 @@ #include "base/mac/foundation_util.h" #include "components/autofill/core/common/autofill_features.h" #import "components/autofill/ios/browser/js_suggestion_manager.h" +#include "components/keyed_service/core/service_access_type.h" +#include "components/password_manager/core/browser/password_store.h" #import "ios/chrome/browser/autofill/form_input_accessory_view_controller.h" +#import "ios/chrome/browser/autofill/manual_fill/passwords_fetcher.h" +#include "ios/chrome/browser/passwords/ios_chrome_password_store_factory.h" #import "ios/chrome/browser/ui/autofill/form_input_accessory_mediator.h" #import "ios/chrome/browser/ui/autofill/manual_fill/address_coordinator.h" #import "ios/chrome/browser/ui/autofill/manual_fill/card_coordinator.h" @@ -24,7 +28,8 @@ ManualFillAccessoryViewControllerDelegate, AddressCoordinatorDelegate, CardCoordinatorDelegate, - PasswordCoordinatorDelegate> + PasswordCoordinatorDelegate, + PasswordFetcherDelegate> // The Mediator for the input accessory view controller. @property(nonatomic, strong) @@ -43,6 +48,9 @@ @property(nonatomic, strong) ManualFillInjectionHandler* manualFillInjectionHandler; +// The password fetcher used to inform if passwords are available. +@property(nonatomic, strong) PasswordFetcher* passwordFetcher; + // The WebStateList for this instance. Used to instantiate the child // coordinators lazily. @property(nonatomic, assign) WebStateList* webStateList; @@ -78,6 +86,17 @@ _formInputAccessoryMediator = [[FormInputAccessoryMediator alloc] initWithConsumer:self.formInputAccessoryViewController webStateList:webStateList]; + + auto passwordStore = IOSChromePasswordStoreFactory::GetForBrowserState( + browserState, ServiceAccessType::EXPLICIT_ACCESS); + // In BVC unit tests the password store doesn't exist. Skip creating the + // fetcher. + // TODO:(crbug.com/878388) Remove this workaround. + if (passwordStore) { + _passwordFetcher = + [[PasswordFetcher alloc] initWithPasswordStore:passwordStore + delegate:self]; + } } return self; } @@ -195,4 +214,13 @@ [self.delegate openAddressSettings]; } +#pragma mark - PasswordFetcherDelegate + +- (void)passwordFetcher:(PasswordFetcher*)passwordFetcher + didFetchPasswords: + (std::vector<std::unique_ptr<autofill::PasswordForm>>&)passwords { + self.manualFillAccessoryViewController.passwordButtonHidden = + passwords.empty(); +} + @end
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/action_cell.mm b/ios/chrome/browser/ui/autofill/manual_fill/action_cell.mm index 144da80..194bfb0 100644 --- a/ios/chrome/browser/ui/autofill/manual_fill/action_cell.mm +++ b/ios/chrome/browser/ui/autofill/manual_fill/action_cell.mm
@@ -15,16 +15,6 @@ namespace { // Left and right margins of the cell contents. static const CGFloat sideMargins = 16; -// The base multiplier for the top and bottom margins. This number multiplied -// by the font size plus the base margins will give similar results to -// |constraintEqualToSystemSpacingBelowAnchor:|. -static const CGFloat iOS10MarginFontMultiplier = 1.18; -// The base top margin, only used in iOS 10. Refer to -// |iOS10MarginFontMultiplier| for how it is used. -static const CGFloat iOS10BaseTopMargin = 4; -// The base bottom margin, only used in iOS 10. Refer to -// |iOS10MarginFontMultiplier| for how it is used. -static const CGFloat iOS10BaseBottomMargin = 4; // The multiplier for the base system spacing at the top margin. static const CGFloat TopBaseSystemSpacingMultiplier = 1.1; // The multiplier for the base system spacing at the bottom margin. @@ -110,44 +100,23 @@ forControlEvents:UIControlEventTouchUpInside]; self.titleButton.titleLabel.lineBreakMode = NSLineBreakByTruncatingTail; [self.contentView addSubview:self.titleButton]; - id<LayoutGuideProvider> safeArea = - SafeAreaLayoutGuideForView(self.contentView); + id<LayoutGuideProvider> safeArea = self.contentView.safeAreaLayoutGuide; NSArray* verticalConstraints; - if (@available(iOS 11, *)) { - // Multipliers of these constraints are calculated based on a 24 base - // system spacing. - verticalConstraints = @[ - // Vertical constraints. - [self.titleButton.firstBaselineAnchor - constraintEqualToSystemSpacingBelowAnchor:self.contentView.topAnchor - multiplier: - TopBaseSystemSpacingMultiplier], - [self.contentView.bottomAnchor - constraintEqualToSystemSpacingBelowAnchor:self.titleButton - .lastBaselineAnchor - multiplier: - BottomBaseSystemSpacingMultiplier], - ]; - } else { - CGFloat pointSize = self.titleButton.titleLabel.font.pointSize; - // These margins are based on the design size and the current point size. - // The multipliers were selected by manually testing the different system - // font sizes. - CGFloat marginTop = - iOS10BaseTopMargin + pointSize * iOS10MarginFontMultiplier; - CGFloat marginBottom = - iOS10BaseBottomMargin + pointSize * iOS10MarginFontMultiplier; - - verticalConstraints = @[ - [self.titleButton.firstBaselineAnchor - constraintEqualToAnchor:self.contentView.topAnchor - constant:marginTop], - [self.contentView.bottomAnchor - constraintEqualToAnchor:self.titleButton.lastBaselineAnchor - constant:marginBottom], - ]; - } + // Multipliers of these constraints are calculated based on a 24 base + // system spacing. + verticalConstraints = @[ + // Vertical constraints. + [self.titleButton.firstBaselineAnchor + constraintEqualToSystemSpacingBelowAnchor:self.contentView.topAnchor + multiplier: + TopBaseSystemSpacingMultiplier], + [self.contentView.bottomAnchor + constraintEqualToSystemSpacingBelowAnchor:self.titleButton + .lastBaselineAnchor + multiplier: + BottomBaseSystemSpacingMultiplier], + ]; [NSLayoutConstraint activateConstraints:verticalConstraints]; // Horizontal constraints. [NSLayoutConstraint activateConstraints:@[
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/fallback_view_controller.mm b/ios/chrome/browser/ui/autofill/manual_fill/fallback_view_controller.mm index e1a208b..72d1b4e 100644 --- a/ios/chrome/browser/ui/autofill/manual_fill/fallback_view_controller.mm +++ b/ios/chrome/browser/ui/autofill/manual_fill/fallback_view_controller.mm
@@ -103,7 +103,7 @@ if (self.contentInsetsAlwaysEqualToSafeArea && !IsIPadIdiom()) { // Resets the table view content inssets to be equal to the safe area // insets. - self.tableView.contentInset = SafeAreaInsetsForView(self.view); + self.tableView.contentInset = self.view.safeAreaInsets; } } @@ -115,7 +115,7 @@ CGRect keyboardFrame = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue]; CGFloat keyboardHeight = keyboardFrame.size.height; - UIEdgeInsets safeInsets = SafeAreaInsetsForView(self.view); + UIEdgeInsets safeInsets = self.view.safeAreaInsets; self.tableView.contentInset = UIEdgeInsetsMake(safeInsets.top, safeInsets.left, safeInsets.bottom - keyboardHeight, safeInsets.right);
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_accessory_view_controller.h b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_accessory_view_controller.h index e6025639..0dd39ff6 100644 --- a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_accessory_view_controller.h +++ b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_accessory_view_controller.h
@@ -41,6 +41,10 @@ // shown above the keyboard on iPhone and above the manual fill view. @interface ManualFillAccessoryViewController : UIViewController +// Changing this property hides and shows the password button. +@property(nonatomic, assign, getter=isPasswordButtonHidden) + BOOL passwordButtonHidden; + // Instances an object with the desired delegate. // // @param delegate The delegate for this object.
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_accessory_view_controller.mm b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_accessory_view_controller.mm index e0cc3b8..6632248 100644 --- a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_accessory_view_controller.mm +++ b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_accessory_view_controller.mm
@@ -41,24 +41,28 @@ @interface ManualFillAccessoryViewController () +// Delegate to handle interactions. @property(nonatomic, readonly, weak) id<ManualFillAccessoryViewControllerDelegate> delegate; +// The button to close manual fallback. @property(nonatomic, strong) UIButton* keyboardButton; + +// The button to open the passwords section. @property(nonatomic, strong) UIButton* passwordButton; + +// The button to open the credit cards section. @property(nonatomic, strong) UIButton* cardsButton; + +// The button to open the profiles section. @property(nonatomic, strong) UIButton* accountButton; @end @implementation ManualFillAccessoryViewController -@synthesize delegate = _delegate; -@synthesize keyboardButton = _keyboardButton; -@synthesize passwordButton = _passwordButton; -@synthesize cardsButton = _cardsButton; -@synthesize accountButton = _accountButton; +#pragma mark - Public - (instancetype)initWithDelegate: (id<ManualFillAccessoryViewControllerDelegate>)delegate { @@ -69,6 +73,24 @@ return self; } +- (void)reset { + [self resetTintColors]; + self.keyboardButton.hidden = YES; + self.keyboardButton.alpha = 0.0; +} + +#pragma mark - Setters + +- (void)setPasswordButtonHidden:(BOOL)passwordButtonHidden { + if (passwordButtonHidden == _passwordButtonHidden) { + return; + } + _passwordButton.hidden = passwordButtonHidden; + _passwordButtonHidden = passwordButtonHidden; +} + +#pragma mark - Private + - (void)loadView { self.view = [[UIView alloc] init]; self.view.translatesAutoresizingMaskIntoConstraints = NO; @@ -100,6 +122,7 @@ forControlEvents:UIControlEventTouchUpInside]; self.passwordButton.accessibilityIdentifier = manual_fill::AccessoryPasswordAccessibilityIdentifier; + self.passwordButton.hidden = self.isPasswordButtonHidden; [icons addObject:self.passwordButton]; if (autofill::features::IsAutofillManualFallbackEnabled()) { @@ -133,8 +156,7 @@ stackView.translatesAutoresizingMaskIntoConstraints = NO; [self.view addSubview:stackView]; - id<LayoutGuideProvider> safeAreaLayoutGuide = - SafeAreaLayoutGuideForView(self.view); + id<LayoutGuideProvider> safeAreaLayoutGuide = self.view.safeAreaLayoutGuide; [NSLayoutConstraint activateConstraints:@[ // Vertical constraints. [stackView.heightAnchor constraintEqualToAnchor:self.view.heightAnchor], @@ -152,12 +174,6 @@ self.keyboardButton.alpha = 0.0; } -- (void)reset { - [self resetTintColors]; - self.keyboardButton.hidden = YES; - self.keyboardButton.alpha = 0.0; -} - // Resets the colors of all the icons to the active color. - (void)resetTintColors { UIColor* activeTintColor = [self activeTintColor];
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_address_cell.mm b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_address_cell.mm index dd43ea0c..24d32ff9 100644 --- a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_address_cell.mm +++ b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_address_cell.mm
@@ -453,8 +453,7 @@ self.stateCountryLineConstraints = @[]; self.verticalConstraints = @[]; - id<LayoutGuideProvider> safeArea = - SafeAreaLayoutGuideForView(self.contentView); + id<LayoutGuideProvider> safeArea = self.contentView.safeAreaLayoutGuide; [NSLayoutConstraint activateConstraints:@[ // Common vertical constraints.
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_card_cell.mm b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_card_cell.mm index 040ccc8..66e6e68 100644 --- a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_card_cell.mm +++ b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_card_cell.mm
@@ -69,24 +69,6 @@ // Left and right margins of the cell content. static const CGFloat sideMargins = 16; -// The base multiplier for the top and bottom margins. This number multiplied by -// the font size plus the base margins will give similar results to -// |constraintEqualToSystemSpacingBelowAnchor:| which is not available on iOS -// 10. -static const CGFloat iOS10MarginFontMultiplier = 1.18; - -// The base top margin, only used in iOS 10. Refer to -// |iOS10MarginFontMultiplier| for how it is used. -static const CGFloat iOS10BaseTopMargin = 28; - -// The base middle margin, only used in iOS 10. Refer to -// |iOS10MarginFontMultiplier| for how it is used. -static const CGFloat iOS10BaseMiddleMargin = 24; - -// The base bottom margin, only used in iOS 10. Refer to -// |iOS10MarginFontMultiplier| for how it is used. -static const CGFloat iOS10BaseBottomMargin = 18; - // The multiplier for the base system spacing at the top margin. static const CGFloat TopSystemSpacingMultiplier = 1.58; @@ -268,8 +250,7 @@ ] container:self.contentView]; - id<LayoutGuideProvider> safeArea = - SafeAreaLayoutGuideForView(self.contentView); + id<LayoutGuideProvider> safeArea = self.contentView.safeAreaLayoutGuide; [NSLayoutConstraint activateConstraints:@[ // Common vertical constraints. @@ -336,50 +317,23 @@ - (void)setVerticalSpacingConstraintsForViews:(NSArray<UIView*>*)views container:(UIView*)container { NSMutableArray* verticalConstraints = [[NSMutableArray alloc] init]; - if (@available(iOS 11, *)) { - // Multipliers of these constraints are calculated based on a 24 base - // system spacing. - NSLayoutYAxisAnchor* previousAnchor = container.topAnchor; - CGFloat multiplier = TopSystemSpacingMultiplier; - for (UIView* view in views) { - [verticalConstraints - addObject:[view.firstBaselineAnchor - constraintEqualToSystemSpacingBelowAnchor:previousAnchor - multiplier:multiplier]]; - multiplier = MiddleSystemSpacingMultiplier; - previousAnchor = view.lastBaselineAnchor; - } - multiplier = BottomSystemSpacingMultiplier; + // Multipliers of these constraints are calculated based on a 24 base + // system spacing. + NSLayoutYAxisAnchor* previousAnchor = container.topAnchor; + CGFloat multiplier = TopSystemSpacingMultiplier; + for (UIView* view in views) { [verticalConstraints - addObject:[container.bottomAnchor + addObject:[view.firstBaselineAnchor constraintEqualToSystemSpacingBelowAnchor:previousAnchor multiplier:multiplier]]; - } else { - CGFloat pointSize = self.cardNumberButton.titleLabel.font.pointSize; - // These margins are based on the design size and the current point size. - // The multipliers were selected by manually testing the different system - // font sizes. - CGFloat marginBetweenButtons = - iOS10BaseMiddleMargin + pointSize * iOS10MarginFontMultiplier; - CGFloat marginBottom = - iOS10BaseBottomMargin + pointSize * iOS10MarginFontMultiplier / 2; - CGFloat marginTop = - iOS10BaseTopMargin + pointSize * iOS10MarginFontMultiplier / 2; - - NSLayoutYAxisAnchor* previousAnchor = container.topAnchor; - CGFloat constant = marginTop; - for (UIView* view in views) { - [verticalConstraints addObject:[view.firstBaselineAnchor - constraintEqualToAnchor:previousAnchor - constant:constant]]; - constant = marginBetweenButtons; - previousAnchor = view.lastBaselineAnchor; - } - [verticalConstraints addObject:[container.bottomAnchor - constraintEqualToAnchor:previousAnchor - constant:marginBottom]]; + multiplier = MiddleSystemSpacingMultiplier; + previousAnchor = view.lastBaselineAnchor; } - + multiplier = BottomSystemSpacingMultiplier; + [verticalConstraints + addObject:[container.bottomAnchor + constraintEqualToSystemSpacingBelowAnchor:previousAnchor + multiplier:multiplier]]; [NSLayoutConstraint activateConstraints:verticalConstraints]; }
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_password_cell.mm b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_password_cell.mm index a86b551..7e0bb2fa 100644 --- a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_password_cell.mm +++ b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_password_cell.mm
@@ -50,20 +50,6 @@ namespace { // Left and right margins of the cell content. static const CGFloat sideMargins = 16; -// The base multiplier for the top and bottom margins. This number multiplied by -// the font size plus the base margins will give similar results to -// |constraintEqualToSystemSpacingBelowAnchor:| which is not available on iOS -// 10. -static const CGFloat iOS10MarginFontMultiplier = 1.18; -// The base top margin, only used in iOS 10. Refer to -// |iOS10MarginFontMultiplier| for how it is used. -static const CGFloat iOS10BaseTopMargin = 28; -// The base middle margin, only used in iOS 10. Refer to -// |iOS10MarginFontMultiplier| for how it is used. -static const CGFloat iOS10BaseMiddleMargin = 24; -// The base bottom margin, only used in iOS 10. Refer to -// |iOS10MarginFontMultiplier| for how it is used. -static const CGFloat iOS10BaseBottomMargin = 18; // The multiplier for the base system spacing at the top margin. static const CGFloat TopSystemSpacingMultiplier = 1.58; // The multiplier for the base system spacing between elements (vertical). @@ -190,61 +176,31 @@ forControlEvents:UIControlEventTouchUpInside]; [self.contentView addSubview:self.passwordButton]; - id<LayoutGuideProvider> safeArea = - SafeAreaLayoutGuideForView(self.contentView); + id<LayoutGuideProvider> safeArea = self.contentView.safeAreaLayoutGuide; NSArray* verticalConstraints; - if (@available(iOS 11, *)) { - // Multipliers of these constraints are calculated based on a 24 base - // system spacing. - verticalConstraints = @[ - [self.siteNameLabel.firstBaselineAnchor - constraintEqualToSystemSpacingBelowAnchor:self.contentView.topAnchor - multiplier:TopSystemSpacingMultiplier], - [self.usernameButton.firstBaselineAnchor - constraintEqualToSystemSpacingBelowAnchor:self.siteNameLabel - .lastBaselineAnchor - multiplier: - MiddleSystemSpacingMultiplier], - [self.passwordButton.firstBaselineAnchor - constraintEqualToSystemSpacingBelowAnchor:self.usernameButton - .lastBaselineAnchor - multiplier: - MiddleSystemSpacingMultiplier], - [self.contentView.bottomAnchor - constraintEqualToSystemSpacingBelowAnchor:self.passwordButton - .lastBaselineAnchor - multiplier: - BottomSystemSpacingMultiplier], - ]; - } else { - CGFloat pointSize = self.usernameButton.titleLabel.font.pointSize; - // These margins are based on the design size and the current point size. - // The multipliers were selected by manually testing the different system - // font sizes. - CGFloat marginBetweenButtons = - iOS10BaseMiddleMargin + pointSize * iOS10MarginFontMultiplier; - CGFloat marginBottom = - iOS10BaseBottomMargin + pointSize * iOS10MarginFontMultiplier / 2; - CGFloat marginTop = - iOS10BaseTopMargin + pointSize * iOS10MarginFontMultiplier / 2; - - verticalConstraints = @[ - // This doesn't make sense when the label is to big. - [self.siteNameLabel.firstBaselineAnchor - constraintEqualToAnchor:self.contentView.topAnchor - constant:marginTop], - [self.usernameButton.firstBaselineAnchor - constraintEqualToAnchor:self.siteNameLabel.lastBaselineAnchor - constant:marginBetweenButtons], - [self.passwordButton.firstBaselineAnchor - constraintEqualToAnchor:self.usernameButton.lastBaselineAnchor - constant:marginBetweenButtons], - [self.contentView.bottomAnchor - constraintEqualToAnchor:self.passwordButton.lastBaselineAnchor - constant:marginBottom], - ]; - } + // Multipliers of these constraints are calculated based on a 24 base + // system spacing. + verticalConstraints = @[ + [self.siteNameLabel.firstBaselineAnchor + constraintEqualToSystemSpacingBelowAnchor:self.contentView.topAnchor + multiplier:TopSystemSpacingMultiplier], + [self.usernameButton.firstBaselineAnchor + constraintEqualToSystemSpacingBelowAnchor:self.siteNameLabel + .lastBaselineAnchor + multiplier: + MiddleSystemSpacingMultiplier], + [self.passwordButton.firstBaselineAnchor + constraintEqualToSystemSpacingBelowAnchor:self.usernameButton + .lastBaselineAnchor + multiplier: + MiddleSystemSpacingMultiplier], + [self.contentView.bottomAnchor + constraintEqualToSystemSpacingBelowAnchor:self.passwordButton + .lastBaselineAnchor + multiplier: + BottomSystemSpacingMultiplier], + ]; [NSLayoutConstraint activateConstraints:verticalConstraints]; [NSLayoutConstraint activateConstraints:@[
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/password_view_controller.mm b/ios/chrome/browser/ui/autofill/manual_fill/password_view_controller.mm index 1498c90..1f46d75 100644 --- a/ios/chrome/browser/ui/autofill/manual_fill/password_view_controller.mm +++ b/ios/chrome/browser/ui/autofill/manual_fill/password_view_controller.mm
@@ -91,27 +91,13 @@ self.definesPresentationContext = YES; self.searchController.searchBar.backgroundColor = [UIColor clearColor]; self.searchController.obscuresBackgroundDuringPresentation = NO; - if (@available(iOS 11, *)) { - self.navigationItem.searchController = self.searchController; - self.navigationItem.hidesSearchBarWhenScrolling = NO; - } else { - self.tableView.tableHeaderView = self.searchController.searchBar; - } + self.navigationItem.searchController = self.searchController; + self.navigationItem.hidesSearchBarWhenScrolling = NO; self.searchController.searchBar.accessibilityIdentifier = manual_fill::PasswordSearchBarAccessibilityIdentifier; NSString* titleString = l10n_util::GetNSString(IDS_IOS_MANUAL_FALLBACK_USE_OTHER_PASSWORD); self.title = titleString; - - if (!base::ios::IsRunningOnIOS11OrLater()) { - // On iOS 11 this is not needed since the cell constrains are updated by the - // system. - [[NSNotificationCenter defaultCenter] - addObserver:self.tableView - selector:@selector(reloadData) - name:UIContentSizeCategoryDidChangeNotification - object:nil]; - } } #pragma mark - ManualFillPasswordConsumer @@ -137,7 +123,7 @@ if (self.contentInsetsAlwaysEqualToSafeArea && !IsIPadIdiom()) { // Resets the table view content inssets to be equal to the safe area // insets. - self.tableView.contentInset = SafeAreaInsetsForView(self.view); + self.tableView.contentInset = self.view.safeAreaInsets; } } @@ -149,7 +135,7 @@ CGRect keyboardFrame = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue]; CGFloat keyboardHeight = keyboardFrame.size.height; - UIEdgeInsets safeInsets = SafeAreaInsetsForView(self.view); + UIEdgeInsets safeInsets = self.view.safeAreaInsets; self.tableView.contentInset = UIEdgeInsetsMake(safeInsets.top, safeInsets.left, safeInsets.bottom - keyboardHeight, safeInsets.right);
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/password_view_controller_egtest.mm b/ios/chrome/browser/ui/autofill/manual_fill/password_view_controller_egtest.mm index 7fa6064..025f1bf 100644 --- a/ios/chrome/browser/ui/autofill/manual_fill/password_view_controller_egtest.mm +++ b/ios/chrome/browser/ui/autofill/manual_fill/password_view_controller_egtest.mm
@@ -249,6 +249,7 @@ const GURL URL = self.testServer->GetURL(kFormHTMLFile); [ChromeEarlGrey loadURL:URL]; [ChromeEarlGrey waitForWebViewContainingText:"hello!"]; + SaveExamplePasswordForm(); } - (void)tearDown { @@ -260,10 +261,6 @@ // Tests that the passwords view controller appears on screen. - (void)testPasswordsViewControllerIsPresented { - // TODO(crbug.com/904885): re-enable this test. - if (base::FeatureList::IsEnabled(web::features::kSlimNavigationManager)) - EARL_GREY_TEST_DISABLED(@"Test disabled on SlimNavigationManager."); - // Bring up the keyboard. [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()] performAction:chrome_test_util::TapWebElement(kFormElementUsername)]; @@ -280,10 +277,6 @@ // Tests that the passwords view controller contains the "Manage Passwords..." // action. - (void)testPasswordsViewControllerContainsManagePasswordsAction { - // TODO(crbug.com/904885): re-enable this test. - if (base::FeatureList::IsEnabled(web::features::kSlimNavigationManager)) - EARL_GREY_TEST_DISABLED(@"Test disabled on SlimNavigationManager."); - // Bring up the keyboard. [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()] performAction:chrome_test_util::TapWebElement(kFormElementUsername)]; @@ -299,10 +292,6 @@ // Tests that the "Manage Passwords..." action works. - (void)testManagePasswordsActionOpensPasswordSettings { - // TODO(crbug.com/904885): re-enable this test. - if (base::FeatureList::IsEnabled(web::features::kSlimNavigationManager)) - EARL_GREY_TEST_DISABLED(@"Test disabled on SlimNavigationManager."); - // Bring up the keyboard. [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()] performAction:chrome_test_util::TapWebElement(kFormElementUsername)]; @@ -322,10 +311,6 @@ // Tests that the Password View Controller is not present when presenting UI. - (void)testPasswordControllerPauses { - // TODO(crbug.com/904885): re-enable this test. - if (base::FeatureList::IsEnabled(web::features::kSlimNavigationManager)) - EARL_GREY_TEST_DISABLED(@"Test disabled on SlimNavigationManager."); - // For the search bar to appear in password settings at least one password is // needed. SaveExamplePasswordForm(); @@ -355,10 +340,6 @@ // Tests that the Password View Controller is resumed after selecting other // password. - (void)testPasswordControllerResumes { - // TODO(crbug.com/904885): re-enable this test. - if (base::FeatureList::IsEnabled(web::features::kSlimNavigationManager)) - EARL_GREY_TEST_DISABLED(@"Test disabled on SlimNavigationManager."); - // For this test one password is needed. SaveExamplePasswordForm(); @@ -401,10 +382,6 @@ // Tests that the Password View Controller is resumed after dismissing "Other // Passwords". - (void)testPasswordControllerResumesWhenOtherPasswordsDismiss { - // TODO(crbug.com/904885): re-enable this test. - if (base::FeatureList::IsEnabled(web::features::kSlimNavigationManager)) - EARL_GREY_TEST_DISABLED(@"Test disabled on SlimNavigationManager."); - // Bring up the keyboard. [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()] performAction:chrome_test_util::TapWebElement(kFormElementUsername)]; @@ -439,10 +416,6 @@ // Tests that the Password View Controller is dismissed when tapping the // keyboard icon. - (void)testKeyboardIconDismissPasswordController { - // TODO(crbug.com/904885): re-enable this test. - if (base::FeatureList::IsEnabled(web::features::kSlimNavigationManager)) - EARL_GREY_TEST_DISABLED(@"Test disabled on SlimNavigationManager."); - if (IsIPadIdiom()) { // The keyboard icon is never present in iPads. return; @@ -474,10 +447,6 @@ // Tests that the Password View Controller is dismissed when tapping the outside // the popover on iPad. - (void)testIPadTappingOutsidePopOverDismissPasswordController { - // TODO(crbug.com/904885): re-enable this test. - if (base::FeatureList::IsEnabled(web::features::kSlimNavigationManager)) - EARL_GREY_TEST_DISABLED(@"Test disabled on SlimNavigationManager."); - if (!IsIPadIdiom()) { return; } @@ -510,10 +479,6 @@ // Tests that the Password View Controller is dismissed when tapping the // keyboard. - (void)testTappingKeyboardDismissPasswordControllerPopOver { - // TODO(crbug.com/904885): re-enable this test. - if (base::FeatureList::IsEnabled(web::features::kSlimNavigationManager)) - EARL_GREY_TEST_DISABLED(@"Test disabled on SlimNavigationManager."); - if (!IsIPadIdiom()) { return; } @@ -543,10 +508,6 @@ // Tests that after switching fields the content size of the table view didn't // grow. - (void)testPasswordControllerKeepsRightSize { - // TODO(crbug.com/904885): re-enable this test. - if (base::FeatureList::IsEnabled(web::features::kSlimNavigationManager)) - EARL_GREY_TEST_DISABLED(@"Test disabled on SlimNavigationManager."); - // Bring up the keyboard. [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()] performAction:chrome_test_util::TapWebElement(kFormElementUsername)]; @@ -574,10 +535,6 @@ // Tests that the Password View Controller stays on rotation. - (void)testPasswordControllerSupportsRotation { - // TODO(crbug.com/904885): re-enable this test. - if (base::FeatureList::IsEnabled(web::features::kSlimNavigationManager)) - EARL_GREY_TEST_DISABLED(@"Test disabled on SlimNavigationManager."); - // Bring up the keyboard. [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()] performAction:chrome_test_util::TapWebElement(kFormElementUsername)]; @@ -600,10 +557,6 @@ // Tests that content is injected in iframe messaging. - (void)testPasswordControllerSupportsIFrameMessaging { - // TODO(crbug.com/904885): re-enable this test. - if (base::FeatureList::IsEnabled(web::features::kSlimNavigationManager)) - EARL_GREY_TEST_DISABLED(@"Test disabled on SlimNavigationManager."); - // Iframe messaging is not supported on iOS < 11.3. if (!base::ios::IsRunningOnOrLater(11, 3, 0)) { EARL_GREY_TEST_SKIPPED(@"Skipped for iOS < 11.3"); @@ -645,4 +598,31 @@ XCTAssertTrue(WaitForJavaScriptCondition(javaScriptCondition)); } +// Tests that the password icon is hidden when no passwords are available. +- (void)testPasswordIconIsNotVisibleWhenPasswordStoreEmpty { + ClearPasswordStore(); + + // Bring up the keyboard. + [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()] + performAction:chrome_test_util::TapWebElement(kFormElementUsername)]; + + // Wait for the keyboard to appear. + [GREYKeyboard waitForKeyboardToAppear]; + + // Assert the password icon is not visible. + [[EarlGrey selectElementWithMatcher:PasswordIconMatcher()] + assertWithMatcher:grey_notVisible()]; + + // Store one password. + SaveExamplePasswordForm(); + + // Tap another field to trigger form activity. + [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()] + performAction:chrome_test_util::TapWebElement(kFormElementPassword)]; + + // Assert the password icon is visible now. + [[EarlGrey selectElementWithMatcher:PasswordIconMatcher()] + assertWithMatcher:grey_sufficientlyVisible()]; +} + @end
diff --git a/ios/chrome/browser/ui/autofill/save_card_infobar_view.mm b/ios/chrome/browser/ui/autofill/save_card_infobar_view.mm index 0b958ab1..c80d03fe 100644 --- a/ios/chrome/browser/ui/autofill/save_card_infobar_view.mm +++ b/ios/chrome/browser/ui/autofill/save_card_infobar_view.mm
@@ -200,7 +200,7 @@ // Calculate the safe area and current Toolbar height. Set the // bottomAnchorConstraint constant to this height to create the bottom // padding. - CGFloat bottomSafeAreaInset = SafeAreaInsetsForView(self).bottom; + CGFloat bottomSafeAreaInset = self.safeAreaInsets.bottom; CGFloat toolbarHeight = 0; UILayoutGuide* guide = [NamedGuide guideWithName:kSecondaryToolbarGuide view:self]; @@ -231,8 +231,7 @@ } else { self.backgroundColor = [UIColor whiteColor]; } - id<LayoutGuideProvider> safeAreaLayoutGuide = - SafeAreaLayoutGuideForView(self); + id<LayoutGuideProvider> safeAreaLayoutGuide = self.safeAreaLayoutGuide; // Add the icon. The icon is fixed to the top leading corner of the infobar. // |iconContainerView| is used here because the AutoLayout constraints for
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_edit_view_controller.mm b/ios/chrome/browser/ui/bookmarks/bookmark_edit_view_controller.mm index 078588d..37fcfac 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmark_edit_view_controller.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmark_edit_view_controller.mm
@@ -444,11 +444,8 @@ selectedFolder:self.folder]; folderViewController.delegate = self; self.folderViewController = folderViewController; - if (@available(iOS 11, *)) { - self.folderViewController.navigationItem.largeTitleDisplayMode = - UINavigationItemLargeTitleDisplayModeNever; - } - + self.folderViewController.navigationItem.largeTitleDisplayMode = + UINavigationItemLargeTitleDisplayModeNever; [self.navigationController pushViewController:self.folderViewController animated:YES]; }
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 db64447..5aeaacec 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm
@@ -356,22 +356,17 @@ action:@selector(dismissSearchController:) forControlEvents:UIControlEventAllTouchEvents]; - // For iOS 11 and later, place the search bar in the navigation bar. - // Otherwise place the search bar in the table view's header. - if (@available(iOS 11, *)) { - self.navigationItem.searchController = self.searchController; - self.navigationItem.hidesSearchBarWhenScrolling = NO; + // Place the search bar in the navigation bar. + self.navigationItem.searchController = self.searchController; + self.navigationItem.hidesSearchBarWhenScrolling = NO; - // Center search bar vertically so it looks centered in the header when - // searching. The cancel button is centered / decentered on - // viewWillAppear and viewDidDisappear. - UIOffset offset = - UIOffsetMake(0.0f, kTableViewNavigationVerticalOffsetForSearchHeader); - self.searchController.searchBar.searchFieldBackgroundPositionAdjustment = - offset; - } else { - self.tableView.tableHeaderView = self.searchController.searchBar; - } + // Center search bar vertically so it looks centered in the header when + // searching. The cancel button is centered / decentered on + // viewWillAppear and viewDidDisappear. + UIOffset offset = + UIOffsetMake(0.0f, kTableViewNavigationVerticalOffsetForSearchHeader); + self.searchController.searchBar.searchFieldBackgroundPositionAdjustment = + offset; self.searchTerm = @""; @@ -398,29 +393,25 @@ self.navigationController.toolbarHidden = YES; } - if (@available(iOS 11, *)) { - // Center search bar's cancel button vertically so it looks centered. - // We change the cancel button proxy styles, so we will return it to - // default in viewDidDisappear. - UIOffset offset = - UIOffsetMake(0.0f, kTableViewNavigationVerticalOffsetForSearchHeader); - UIBarButtonItem* cancelButton = [UIBarButtonItem - appearanceWhenContainedInInstancesOfClasses:@[ [UISearchBar class] ]]; - [cancelButton setTitlePositionAdjustment:offset - forBarMetrics:UIBarMetricsDefault]; - } + // Center search bar's cancel button vertically so it looks centered. + // We change the cancel button proxy styles, so we will return it to + // default in viewDidDisappear. + UIOffset offset = + UIOffsetMake(0.0f, kTableViewNavigationVerticalOffsetForSearchHeader); + UIBarButtonItem* cancelButton = [UIBarButtonItem + appearanceWhenContainedInInstancesOfClasses:@[ [UISearchBar class] ]]; + [cancelButton setTitlePositionAdjustment:offset + forBarMetrics:UIBarMetricsDefault]; } - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; - if (@available(iOS 11, *)) { - // Restore to default origin offset for cancel button proxy style. - UIBarButtonItem* cancelButton = [UIBarButtonItem - appearanceWhenContainedInInstancesOfClasses:@[ [UISearchBar class] ]]; - [cancelButton setTitlePositionAdjustment:UIOffsetZero - forBarMetrics:UIBarMetricsDefault]; - } + // Restore to default origin offset for cancel button proxy style. + UIBarButtonItem* cancelButton = [UIBarButtonItem + appearanceWhenContainedInInstancesOfClasses:@[ [UISearchBar class] ]]; + [cancelButton setTitlePositionAdjustment:UIOffsetZero + forBarMetrics:UIBarMetricsDefault]; } - (void)viewDidLayoutSubviews { @@ -749,17 +740,15 @@ [self navigateAway]; - if (@available(iOS 11, *)) { - // At root, since there's a large title, the search bar is lower than on - // whatever destination folder it is transitioning to (root is never - // reachable through search). To avoid a kink in the animation, the title - // is set to regular size, which means the search bar is at same level at - // beginning and end of animation. This controller will be replaced in - // |stack| so there's no need to care about restoring this. - if (_rootNode == self.bookmarks->root_node()) { - self.navigationItem.largeTitleDisplayMode = - UINavigationItemLargeTitleDisplayModeNever; - } + // At root, since there's a large title, the search bar is lower than on + // whatever destination folder it is transitioning to (root is never + // reachable through search). To avoid a kink in the animation, the title + // is set to regular size, which means the search bar is at same level at + // beginning and end of animation. This controller will be replaced in + // |stack| so there's no need to care about restoring this. + if (_rootNode == self.bookmarks->root_node()) { + self.navigationItem.largeTitleDisplayMode = + UINavigationItemLargeTitleDisplayModeNever; } auto completion = ^{ @@ -1027,11 +1016,9 @@ (const bookmarks::BookmarkNode*)node { viewController.navigationItem.leftBarButtonItem.action = @selector(back); // Disable large titles on every VC but the root controller. - if (@available(iOS 11, *)) { - if (node != self.bookmarks->root_node()) { - viewController.navigationItem.largeTitleDisplayMode = - UINavigationItemLargeTitleDisplayModeNever; - } + if (node != self.bookmarks->root_node()) { + viewController.navigationItem.largeTitleDisplayMode = + UINavigationItemLargeTitleDisplayModeNever; } // Add custom title.
diff --git a/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm b/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm index 9bfcd34..f034c9fa 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm
@@ -105,15 +105,9 @@ grey_anyOf(grey_accessibilityLabel(previousViewControllerLabel), grey_accessibilityLabel(@"Back"), nil); - if (@available(iOS 11, *)) { - return grey_allOf(grey_kindOfClass([UIButton class]), - grey_ancestor(grey_kindOfClass([UINavigationBar class])), - buttonLabelMatcher, nil); - } else { - return grey_allOf(grey_accessibilityTrait(UIAccessibilityTraitButton), - grey_ancestor(grey_kindOfClass([UINavigationBar class])), - buttonLabelMatcher, nil); - } + return grey_allOf(grey_kindOfClass([UIButton class]), + grey_ancestor(grey_kindOfClass([UINavigationBar class])), + buttonLabelMatcher, nil); } // Matcher for the DONE button on the bookmarks UI. @@ -1723,15 +1717,13 @@ #pragma mark - BookmarksEntriesTestCase Tests - (void)testUndoDeleteBookmarkFromSwipe { - // TODO(crbug.com/851227): On Compact Width on iOS11, the - // bookmark cell is being deleted by grey_swipeFastInDirection. + // TODO(crbug.com/851227): On Compact Width, the bookmark cell is being + // deleted by grey_swipeFastInDirection. // grey_swipeFastInDirectionWithStartPoint doesn't work either and it might // fail on devices. Disabling this test under these conditions on the // meantime. - if (@available(iOS 11, *)) { - if (!IsCompactWidth()) { - EARL_GREY_TEST_SKIPPED(@"Test disabled on iPad on iOS11."); - } + if (!IsCompactWidth()) { + EARL_GREY_TEST_SKIPPED(@"Test disabled on iPad."); } [BookmarksTestCase setupStandardBookmarks]; @@ -1775,15 +1767,13 @@ FLAKY_testSwipeToDeleteDisabledInEditMode #endif - (void)testSwipeToDeleteDisabledInEditMode { - // TODO(crbug.com/851227): On non Compact Width on iOS11, the - // bookmark cell is being deleted by grey_swipeFastInDirection. + // TODO(crbug.com/851227): On non Compact Width the bookmark cell is being + // deleted by grey_swipeFastInDirection. // grey_swipeFastInDirectionWithStartPoint doesn't work either and it might // fail on devices. Disabling this test under these conditions on the // meantime. - if (@available(iOS 11, *)) { - if (!IsCompactWidth()) { - EARL_GREY_TEST_SKIPPED(@"Test disabled on iPad on iOS11."); - } + if (!IsCompactWidth()) { + EARL_GREY_TEST_SKIPPED(@"Test disabled on iPad on iOS11."); } [BookmarksTestCase setupStandardBookmarks]; @@ -2129,7 +2119,7 @@ @"Incognito tab count should be 1"); // Close the incognito tab to go back to normal mode. - GREYAssert(chrome_test_util::CloseAllIncognitoTabs(), @"Tabs did not close"); + [ChromeEarlGrey closeAllIncognitoTabs]; // The following verifies the selected bookmarks are open in the same order as // in folder. @@ -4392,15 +4382,13 @@ // Tests that you can swipe URL items in search mode. - (void)testSearchUrlCanBeSwipedToDelete { - // TODO(crbug.com/851227): On non Compact Width on iOS11, the - // bookmark cell is being deleted by grey_swipeFastInDirection. + // TODO(crbug.com/851227): On non Compact Width, the bookmark cell is being + // deleted by grey_swipeFastInDirection. // grey_swipeFastInDirectionWithStartPoint doesn't work either and it might // fail on devices. Disabling this test under these conditions on the // meantime. - if (@available(iOS 11, *)) { - if (!IsCompactWidth()) { - EARL_GREY_TEST_SKIPPED(@"Test disabled on iPad on iOS11."); - } + if (!IsCompactWidth()) { + EARL_GREY_TEST_SKIPPED(@"Test disabled on iPad on iOS11."); } [BookmarksTestCase setupStandardBookmarks]; @@ -4422,15 +4410,13 @@ // Tests that you can swipe folders in search mode. - (void)testSearchFolderCanBeSwipedToDelete { - // TODO(crbug.com/851227): On non Compact Width on iOS11, the - // bookmark cell is being deleted by grey_swipeFastInDirection. + // TODO(crbug.com/851227): On non Compact Width, the bookmark cell is being + // deleted by grey_swipeFastInDirection. // grey_swipeFastInDirectionWithStartPoint doesn't work either and it might // fail on devices. Disabling this test under these conditions on the // meantime. - if (@available(iOS 11, *)) { - if (!IsCompactWidth()) { - EARL_GREY_TEST_SKIPPED(@"Test disabled on iPad on iOS11."); - } + if (!IsCompactWidth()) { + EARL_GREY_TEST_SKIPPED(@"Test disabled on iPad on iOS11."); } [BookmarksTestCase setupStandardBookmarks];
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm index f7f554f..1abad5c 100644 --- a/ios/chrome/browser/ui/browser_view_controller.mm +++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -1302,11 +1302,7 @@ - (CGFloat)headerOffset { CGFloat headerOffset = 0; - if (@available(iOS 11, *)) { - headerOffset = self.view.safeAreaInsets.top; - } else { - headerOffset = StatusBarHeight(); - } + headerOffset = self.view.safeAreaInsets.top; return [self canShowTabStrip] ? headerOffset : 0.0; } @@ -1325,16 +1321,12 @@ } - (BOOL)usesSafeInsetsForViewportAdjustments { - // The WKWebView viewport is only updatable via the safe area in iOS 11. - if (@available(iOS 11, *)) { - fullscreen::features::ViewportAdjustmentExperiment viewportExperiment = - fullscreen::features::GetActiveViewportExperiment(); - return viewportExperiment == - fullscreen::features::ViewportAdjustmentExperiment::SAFE_AREA || - viewportExperiment == - fullscreen::features::ViewportAdjustmentExperiment::HYBRID; - } - return NO; + fullscreen::features::ViewportAdjustmentExperiment viewportExperiment = + fullscreen::features::GetActiveViewportExperiment(); + return viewportExperiment == + fullscreen::features::ViewportAdjustmentExperiment::SAFE_AREA || + viewportExperiment == + fullscreen::features::ViewportAdjustmentExperiment::HYBRID; } - (BubblePresenter*)bubblePresenter { @@ -1874,12 +1866,6 @@ [self addConstraintsToPrimaryToolbar]; } - // Normally this happens in -viewSafeAreaInsetsDidChange, but added here to - // support iOS10. - if (!base::ios::IsRunningOnIOS11OrLater()) { - [self setUpViewLayout:NO]; - } - [self setNeedsStatusBarAppearanceUpdate]; } @@ -1896,21 +1882,6 @@ [_toolbarUIUpdater updateState]; } completion:nil]; - - if (!self.view.window.keyWindow && !base::ios::IsRunningOnIOS11OrLater()) { - // When a UIViewController in a background window is rotated, its top layout - // guide's length is not updated before |-viewDidLayoutSubviews| is called. - // In order to correctly capture the status bar height in the toolbar frame, - // start observing the key window notification here so that the updated top - // layout guide length can be used to resize the primary toolbar. This is - // only necessary on iOS10, as the safe area insets used in iOS11 are - // correctly updated for background window rotations. - [[NSNotificationCenter defaultCenter] - addObserver:self - selector:@selector(updateToolbarHeightForKeyWindow) - name:UIWindowDidBecomeKeyNotification - object:self.view.window]; - } } - (void)dismissViewControllerAnimated:(BOOL)flag @@ -2226,15 +2197,7 @@ return intrinsicHeight; // If the primary toolbar is topmost, subtract the height of the portion of // the unsafe area. - CGFloat unsafeHeight = 0.0; - if (@available(iOS 11, *)) { - unsafeHeight = self.view.safeAreaInsets.top; - } -#if !defined(__IPHONE_11_0) || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_11_0 - else { - unsafeHeight = self.topLayoutGuide.length; - } -#endif + CGFloat unsafeHeight = self.view.safeAreaInsets.top; // The topmost header is laid out |headerOffset| from the top of |view|, so // subtract that from the unsafe height. @@ -2251,10 +2214,7 @@ UIView* secondaryToolbar = self.secondaryToolbarCoordinator.viewController.view; // Add the safe area inset to the toolbar height. - CGFloat unsafeHeight = 0.0; - if (@available(iOS 11, *)) { - unsafeHeight = self.view.safeAreaInsets.bottom; - } + CGFloat unsafeHeight = self.view.safeAreaInsets.bottom; return secondaryToolbar.intrinsicContentSize.height + unsafeHeight; } @@ -2457,12 +2417,7 @@ - (void)setUpViewLayout:(BOOL)initialLayout { DCHECK([self isViewLoaded]); - CGFloat topInset = 0.0; - if (@available(iOS 11, *)) { - topInset = self.view.safeAreaInsets.top; - } else { - topInset = StatusBarHeight(); - } + CGFloat topInset = self.view.safeAreaInsets.top; // Update the fake toolbar background height. CGRect fakeStatusBarFrame = _fakeStatusBarView.frame; @@ -2609,7 +2564,8 @@ _browserContainerCoordinator.viewController.contentViewController = viewController; } else { - _browserContainerCoordinator.viewController.contentView = tab.view; + _browserContainerCoordinator.viewController.contentView = + [self viewForTab:tab]; } } [self updateToolbar]; @@ -2758,14 +2714,22 @@ - (UIView*)viewForTab:(Tab*)tab { DCHECK(tab); - if (tab.webState) { - NewTabPageTabHelper* NTPHelper = - NewTabPageTabHelper::FromWebState(tab.webState); - if (NTPHelper && NTPHelper->IsActive()) { - return _ntpCoordinatorsForWebStates[tab.webState].viewController.view; - } + if (!tab.webState) + return nil; + web::WebState* webState = tab.webState; + NewTabPageTabHelper* NTPHelper = NewTabPageTabHelper::FromWebState(webState); + if (NTPHelper && NTPHelper->IsActive()) { + return _ntpCoordinatorsForWebStates[webState].viewController.view; } - return tab.view; + // TODO(crbug.com/904588): Move |RecordPageLoadStart| to TabUsageRecorder. + if (webState->IsEvicted() && [tab.parentTabModel tabUsageRecorder]) { + [tab.parentTabModel tabUsageRecorder]->RecordPageLoadStart(webState); + } + if (!webState->IsCrashed()) { + // Load the page if it was evicted by browsing data clearing logic. + webState->GetNavigationManager()->LoadIfNecessary(); + } + return webState->GetView(); } #pragma mark - Private Methods: Find Bar UI @@ -3903,14 +3867,7 @@ return 0; // Also subtract the top safe area so the view will appear as full screen. // TODO(crbug.com/826369) Remove this once NTP is out of native content. - if (@available(iOS 11, *)) { - return -self.view.safeAreaInsets.top; - } -#if !defined(__IPHONE_11_0) || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_11_0 - else { - return -self.topLayoutGuide.length; - } -#endif + return -self.view.safeAreaInsets.top; } return [self headerHeightForTab:tab]; } @@ -3940,11 +3897,7 @@ // the browser container view is laid out using the full screen, it extends // past the status bar, so that additional overlap is added here. if (self.usesFullscreenContainer) { - if (@available(iOS 11, *)) { - collapsedToolbarHeight += self.view.safeAreaInsets.top; - } else { - collapsedToolbarHeight += StatusBarHeight(); - } + collapsedToolbarHeight += self.view.safeAreaInsets.top; } return collapsedToolbarHeight; } @@ -4120,12 +4073,10 @@ bottomToolbarHeight:(CGFloat)bottomToolbarHeight { UIViewController* containerViewController = _browserContainerCoordinator.viewController; - if (@available(iOS 11, *)) { - containerViewController.additionalSafeAreaInsets = UIEdgeInsetsMake( - topToolbarHeight - self.view.safeAreaInsets.top - - self.currentWebState->GetWebViewProxy().contentOffset.y, - 0, 0, 0); - } + containerViewController.additionalSafeAreaInsets = UIEdgeInsetsMake( + topToolbarHeight - self.view.safeAreaInsets.top - + self.currentWebState->GetWebViewProxy().contentOffset.y, + 0, 0, 0); } // Updates the padding of the web view proxy. This either resets the frame of @@ -5171,10 +5122,6 @@ return self.contentArea; } -- (BOOL)isParentViewVisible { - return self.visible; -} - #pragma mark - SadTabCoordinatorDelegate - (void)sadTabCoordinatorDidStart:(SadTabCoordinator*)sadTabCoordinator {
diff --git a/ios/chrome/browser/ui/browser_view_controller_unittest.mm b/ios/chrome/browser/ui/browser_view_controller_unittest.mm index d4aa52a..48c4a21d 100644 --- a/ios/chrome/browser/ui/browser_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/browser_view_controller_unittest.mm
@@ -194,10 +194,6 @@ [[tabModel stub] setCurrentTab:[OCMArg any]]; [[tabModel stub] closeAllTabs]; - // Stub methods for Tab. - UIView* dummyView = [[UIView alloc] initWithFrame:CGRectZero]; - [[[currentTab stub] andReturn:dummyView] view]; - web::WebState::CreateParams params(chrome_browser_state_.get()); std::unique_ptr<web::WebState> webState = web::WebState::Create(params); webStateImpl_.reset(static_cast<web::WebStateImpl*>(webState.release())); @@ -302,7 +298,7 @@ TEST_F(BrowserViewControllerTest, TestTabSelected) { [bvc_ tabSelected:tab_ notifyToolbar:YES]; - EXPECT_EQ([[tab_ view] superview], [bvc_ contentArea]); + EXPECT_EQ([tab_.webState->GetView() superview], [bvc_ contentArea]); EXPECT_TRUE(webStateImpl_->IsVisible()); } @@ -313,7 +309,7 @@ id tabMock = (id)tab_; [tabMock onSelector:@selector(url) callBlockExpectation:block]; [bvc_ tabSelected:tab_ notifyToolbar:YES]; - EXPECT_EQ([[tab_ view] superview], [bvc_ contentArea]); + EXPECT_EQ([tab_.webState->GetView() superview], [bvc_ contentArea]); EXPECT_TRUE(webStateImpl_->IsVisible()); }
diff --git a/ios/chrome/browser/ui/bubble/bubble_view_unittest.mm b/ios/chrome/browser/ui/bubble/bubble_view_unittest.mm index ca62299..cd47a0bb 100644 --- a/ios/chrome/browser/ui/bubble/bubble_view_unittest.mm +++ b/ios/chrome/browser/ui/bubble/bubble_view_unittest.mm
@@ -60,11 +60,7 @@ CGSize bubbleSize = [bubble sizeThatFits:maxSize_]; // The bubble should fit the label, which contains two lines of text. - if (base::ios::IsRunningOnIOS11OrLater()) { - EXPECT_NEAR(329.0f, bubbleSize.width, 1.0f); - } else { - EXPECT_NEAR(402.0f, bubbleSize.width, 1.0f); - } + EXPECT_NEAR(329.0f, bubbleSize.width, 1.0f); EXPECT_NEAR(83.0f, bubbleSize.height, 2.0f); }
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm index 64f4dcd..cbe6bf4 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm
@@ -257,14 +257,7 @@ - (CGFloat)overscrollHeaderHeight { CGFloat height = [self.headerController toolBarView].bounds.size.height; - CGFloat topInset = 0.0; - if (@available(iOS 11, *)) { - topInset = self.suggestionsViewController.view.safeAreaInsets.top; - } else { - // TODO(crbug.com/826369) Replace this when the NTP is contained by the - // BVC with |self.suggestionsViewController.topLayoutGuide.length|. - topInset = StatusBarHeight(); - } + CGFloat topInset = self.suggestionsViewController.view.safeAreaInsets.top; return height + topInset; }
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 b246bbc..0c257e5 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_egtest.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_egtest.mm
@@ -305,12 +305,7 @@ if (!IsRegularXRegularSizeClass()) { // Test that the omnibox is still pinned to the top of the screen and // under the safe area. - CGFloat safeAreaTop = 0; - if (@available(iOS 11, *)) { - safeAreaTop = ntp_home::CollectionView().safeAreaInsets.top; - } else { - safeAreaTop = StatusBarHeight(); - } + CGFloat safeAreaTop = ntp_home::CollectionView().safeAreaInsets.top; CGFloat contentOffset = ntp_home::CollectionView().contentOffset.y; CGFloat fakeOmniboxOrigin = ntp_home::FakeOmnibox().frame.origin.y;
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_synchronizer.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_synchronizer.mm index 834c317..7affd02 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_synchronizer.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_synchronizer.mm
@@ -22,17 +22,6 @@ namespace { const CGFloat kShiftTilesDownAnimationDuration = 0.2; const CGFloat kShiftTilesUpAnimationDuration = 0.25; - -UIEdgeInsets SafeAreaInsetsForViewWithinNTP(UIView* view) { - UIEdgeInsets insets = SafeAreaInsetsForView(view); - if (!base::ios::IsRunningOnIOS11OrLater()) { - // TODO(crbug.com/826369) Replace this when the NTP is contained by the - // BVC with |self.collectionController.topLayoutGuide.length|. - insets = UIEdgeInsetsMake(StatusBarHeight(), 0, 0, 0); - } - return insets; -} - } // namespace @interface ContentSuggestionsHeaderSynchronizer ()<UIGestureRecognizerDelegate> @@ -177,7 +166,7 @@ } if (self.shouldAnimateHeader) { - UIEdgeInsets insets = SafeAreaInsetsForViewWithinNTP(self.collectionView); + UIEdgeInsets insets = self.collectionView.safeAreaInsets; [self.headerController updateFakeOmniboxForOffset:self.collectionView.contentOffset.y screenWidth:self.collectionView.frame.size.width @@ -193,8 +182,7 @@ // updated safeAreaInsets, but VC.collectionView does not until a layer // -viewDidLayoutSubviews. Since self.collectionView and it's superview // should always have the same safeArea, this should be safe. - UIEdgeInsets insets = - SafeAreaInsetsForViewWithinNTP(self.collectionView.superview); + UIEdgeInsets insets = self.collectionView.superview.safeAreaInsets; [self.headerController updateFakeOmniboxForOffset:self.collectionView.contentOffset.y screenWidth:width
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view.mm index 53c6cfc..3089565 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view.mm
@@ -95,7 +95,7 @@ - (void)addToolbarView:(UIView*)toolbarView { _toolBarView = toolbarView; [self addSubview:toolbarView]; - id<LayoutGuideProvider> layoutGuide = SafeAreaLayoutGuideForView(self); + id<LayoutGuideProvider> layoutGuide = self.safeAreaLayoutGuide; [NSLayoutConstraint activateConstraints:@[ [toolbarView.leadingAnchor constraintEqualToAnchor:self.leadingAnchor], [toolbarView.topAnchor constraintEqualToAnchor:layoutGuide.topAnchor],
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller.mm index 920bfc0..b39d0f2 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller.mm
@@ -229,7 +229,7 @@ insetsView = [[UIApplication sharedApplication] keyWindow].rootViewController.view; } - UIEdgeInsets safeAreaInsets = SafeAreaInsetsForView(insetsView); + UIEdgeInsets safeAreaInsets = insetsView.safeAreaInsets; width = std::max<CGFloat>( 0, width - safeAreaInsets.left - safeAreaInsets.right);
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_layout.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_layout.mm index 44bdaca..53864838 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_layout.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_layout.mm
@@ -26,12 +26,7 @@ // top of the screen. CGFloat minimumHeight = collectionViewHeight + headerHeight - ntp_header::kScrolledToTopOmniboxBottomMargin; - CGFloat topSafeArea = 0; - if (@available(iOS 11, *)) { - topSafeArea = self.collectionView.safeAreaInsets.top; - } else { - topSafeArea = StatusBarHeight(); - } + CGFloat topSafeArea = self.collectionView.safeAreaInsets.top; if (!IsRegularXRegularSizeClass(self.collectionView)) minimumHeight -= ToolbarExpandedHeight( @@ -102,12 +97,7 @@ attributes.zIndex = NSIntegerMax; // Prevent the fake omnibox from scrolling up off of the screen. - CGFloat topSafeArea = 0; - if (@available(iOS 11, *)) { - topSafeArea = self.collectionView.safeAreaInsets.top; - } else { - topSafeArea = StatusBarHeight(); - } + CGFloat topSafeArea = self.collectionView.safeAreaInsets.top; CGFloat minY = headerHeight - ntp_header::kFakeOmniboxScrolledToTopMargin - ToolbarExpandedHeight(
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_metrics_recording.h b/ios/chrome/browser/ui/content_suggestions/content_suggestions_metrics_recording.h index cd4e9f4..6931f1a 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_metrics_recording.h +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_metrics_recording.h
@@ -5,7 +5,7 @@ #ifndef IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_CONTENT_SUGGESTIONS_METRICS_RECORDING_H_ #define IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_CONTENT_SUGGESTIONS_METRICS_RECORDING_H_ -#import <UIKit/UIKIt.h> +#import <UIKit/UIKit.h> #include "ui/base/window_open_disposition.h"
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm index 97ee580..48defa6b 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm
@@ -208,17 +208,10 @@ [super viewDidLoad]; self.collectionView.prefetchingEnabled = NO; - if (@available(iOS 11, *)) { - // Overscroll action does not work well with content offset, so set this - // to never and internally offset the UI to account for safe area insets. - self.collectionView.contentInsetAdjustmentBehavior = - UIScrollViewContentInsetAdjustmentNever; - } -#if !defined(__IPHONE_11_0) || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_11_0 - else { - self.automaticallyAdjustsScrollViewInsets = NO; - } -#endif + // Overscroll action does not work well with content offset, so set this + // to never and internally offset the UI to account for safe area insets. + self.collectionView.contentInsetAdjustmentBehavior = + UIScrollViewContentInsetAdjustmentNever; self.collectionView.accessibilityIdentifier = [[self class] collectionAccessibilityIdentifier]; _collectionUpdater.collectionViewController = self; @@ -644,15 +637,13 @@ if (base::FeatureList::IsEnabled(web::features::kBrowserContainerFullscreen)) return; - if (@available(iOS 11, *)) { - UIEdgeInsets missingTop = UIEdgeInsetsZero; - // During the new tab animation the browser container view controller - // actually matches the browser view controller frame, so safe area does - // work, so be sure to check the parent view controller offset. - if (self.parentViewController.view.frame.origin.y == StatusBarHeight()) - missingTop = UIEdgeInsetsMake(StatusBarHeight(), 0, 0, 0); - self.additionalSafeAreaInsets = missingTop; - } + UIEdgeInsets missingTop = UIEdgeInsetsZero; + // During the new tab animation the browser container view controller + // actually matches the browser view controller frame, so safe area does + // work, so be sure to check the parent view controller offset. + if (self.parentViewController.view.frame.origin.y == StatusBarHeight()) + missingTop = UIEdgeInsetsMake(StatusBarHeight(), 0, 0, 0); + self.additionalSafeAreaInsets = missingTop; } - (void)handleLongPress:(UILongPressGestureRecognizer*)gestureRecognizer {
diff --git a/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm b/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm index e39a252..b7bec4e 100644 --- a/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm +++ b/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm
@@ -173,7 +173,7 @@ EARL_GREY_TEST_DISABLED(@"Disabled for iPad due to device rotation bug."); } [[GREYUIThreadExecutor sharedInstance] drainUntilIdle]; - UIEdgeInsets safeArea = SafeAreaInsetsForView(CollectionView()); + UIEdgeInsets safeArea = CollectionView().safeAreaInsets; CGFloat collectionWidth = CGRectGetWidth(UIEdgeInsetsInsetRect(CollectionView().bounds, safeArea)); GREYAssertTrue(collectionWidth > 0, @"The collection width is nil."); @@ -187,7 +187,7 @@ errorOrNil:nil]; [[GREYUIThreadExecutor sharedInstance] drainUntilIdle]; - safeArea = SafeAreaInsetsForView(CollectionView()); + safeArea = CollectionView().safeAreaInsets; CGFloat collectionWidthAfterRotation = CGRectGetWidth(UIEdgeInsetsInsetRect(CollectionView().bounds, safeArea)); GREYAssertNotEqual(collectionWidth, collectionWidthAfterRotation, @@ -208,7 +208,7 @@ EARL_GREY_TEST_DISABLED(@"Disabled for iPad due to device rotation bug."); } [[GREYUIThreadExecutor sharedInstance] drainUntilIdle]; - UIEdgeInsets safeArea = SafeAreaInsetsForView(CollectionView()); + UIEdgeInsets safeArea = CollectionView().safeAreaInsets; CGFloat collectionWidth = CGRectGetWidth(UIEdgeInsetsInsetRect(CollectionView().bounds, safeArea)); GREYAssertTrue(collectionWidth > 0, @"The collection width is nil."); @@ -227,7 +227,7 @@ [[EarlGrey selectElementWithMatcher:chrome_test_util::SettingsDoneButton()] performAction:grey_tap()]; - safeArea = SafeAreaInsetsForView(CollectionView()); + safeArea = CollectionView().safeAreaInsets; CGFloat collectionWidthAfterRotation = CGRectGetWidth(UIEdgeInsetsInsetRect(CollectionView().bounds, safeArea)); GREYAssertNotEqual(collectionWidth, collectionWidthAfterRotation, @@ -361,11 +361,7 @@ CGPoint previousPosition = omnibox.bounds.origin; // Tap the omnibox to focus it. - [[EarlGrey selectElementWithMatcher:grey_accessibilityID( - FakeOmniboxAccessibilityID())] - performAction:grey_tap()]; - [ChromeEarlGrey - waitForElementWithMatcherSufficientlyVisible:chrome_test_util::Omnibox()]; + [self focusFakebox]; // Navigate and come back. [[EarlGrey selectElementWithMatcher: @@ -383,10 +379,10 @@ // Tests that tapping the fake omnibox focuses the real omnibox. - (void)testTapFakeOmnibox { - // TODO(crbug.com/753098): Re-enable this test on iOS 11 iPad once - // grey_typeText works on iOS 11. - if (IsRegularXRegularSizeClass() && base::ios::IsRunningOnIOS11OrLater()) { - EARL_GREY_TEST_DISABLED(@"Test disabled on iOS 11."); + // TODO(crbug.com/753098): Re-enable this test on iPad once grey_typeText + // works. + if (IsRegularXRegularSizeClass()) { + EARL_GREY_TEST_DISABLED(@"Test disabled on iPad."); } // Setup the server. self.testServer->RegisterRequestHandler(base::Bind(&StandardResponse)); @@ -396,11 +392,8 @@ NSString* URL = base::SysUTF8ToNSString(pageURL.spec()); // Tap the fake omnibox, type the URL in the real omnibox and navigate to the // page. - [[EarlGrey selectElementWithMatcher:grey_accessibilityID( - FakeOmniboxAccessibilityID())] - performAction:grey_tap()]; - [ChromeEarlGrey - waitForElementWithMatcherSufficientlyVisible:chrome_test_util::Omnibox()]; + [self focusFakebox]; + [[EarlGrey selectElementWithMatcher:chrome_test_util::Omnibox()] performAction:grey_typeText([URL stringByAppendingString:@"\n"])]; @@ -458,11 +451,7 @@ CGPoint origin = collectionView.contentOffset; // Tap the omnibox to focus it. - [[EarlGrey selectElementWithMatcher:grey_accessibilityID( - FakeOmniboxAccessibilityID())] - performAction:grey_tap()]; - [ChromeEarlGrey - waitForElementWithMatcherSufficientlyVisible:chrome_test_util::Omnibox()]; + [self focusFakebox]; // Offset after the fake omnibox has been tapped. CGPoint offsetAfterTap = collectionView.contentOffset; @@ -471,16 +460,8 @@ [[EarlGrey selectElementWithMatcher:grey_accessibilityID( FakeOmniboxAccessibilityID())] assertWithMatcher:grey_not(grey_sufficientlyVisible())]; - // TODO(crbug.com/826369) This should use collectionView.safeAreaInsets.top - // instead of -StatusBarHeight once iOS10 is dropped and the NTP is out of - // native content. - CGFloat top = 0; - if (@available(iOS 11, *)) { - top = ntp_home::CollectionView().safeAreaInsets.top; - } else { - top = StatusBarHeight(); - } + CGFloat top = ntp_home::CollectionView().safeAreaInsets.top; GREYAssertTrue(offsetAfterTap.y >= origin.y + headerHeight - (60 + top), @"The collection has not moved."); @@ -517,11 +498,7 @@ CGPoint origin = collectionView.contentOffset; // Tap the omnibox to focus it. - [[EarlGrey selectElementWithMatcher:grey_accessibilityID( - FakeOmniboxAccessibilityID())] - performAction:grey_tap()]; - [ChromeEarlGrey - waitForElementWithMatcherSufficientlyVisible:chrome_test_util::Omnibox()]; + [self focusFakebox]; // Unfocus the omnibox. [[EarlGrey selectElementWithMatcher:chrome_test_util:: @@ -580,4 +557,13 @@ [ChromeEarlGrey openNewTab]; } +// Taps the fake omnibox and waits for the real omnibox to be visible. +- (void)focusFakebox { + [[EarlGrey selectElementWithMatcher:grey_accessibilityID( + FakeOmniboxAccessibilityID())] + performAction:grey_tap()]; + [ChromeEarlGrey + waitForElementWithMatcherSufficientlyVisible:chrome_test_util::Omnibox()]; +} + @end
diff --git a/ios/chrome/browser/ui/dialogs/javascript_dialog_egtest.mm b/ios/chrome/browser/ui/dialogs/javascript_dialog_egtest.mm index 0fbbe48..8987b1bd 100644 --- a/ios/chrome/browser/ui/dialogs/javascript_dialog_egtest.mm +++ b/ios/chrome/browser/ui/dialogs/javascript_dialog_egtest.mm
@@ -440,10 +440,10 @@ // Tests that a prompt dialog is shown, and that the completion block is called // with the correct value when the OK buton is tapped. - (void)testShowJavaScriptPromptOK { - // TODO(crbug.com/753098): Re-enable this test on iOS 11 iPad once - // grey_typeText works on iOS 11. - if (base::ios::IsRunningOnIOS11OrLater() && IsIPadIdiom()) { - EARL_GREY_TEST_DISABLED(@"Test disabled on iOS 11."); + // TODO(crbug.com/753098): Re-enable this test on iPad once grey_typeText + // works. + if (IsIPadIdiom()) { + EARL_GREY_TEST_DISABLED(@"Test disabled on iPad."); } // Load the blank test page and show a prompt dialog. @@ -462,10 +462,10 @@ // Tests that a prompt dialog is shown, and that the completion block is called // with the correct value when the Cancel buton is tapped. - (void)testShowJavaScriptPromptCancelled { - // TODO(crbug.com/753098): Re-enable this test on iOS 11 iPad once - // grey_typeText works on iOS 11. - if (base::ios::IsRunningOnIOS11OrLater() && IsIPadIdiom()) { - EARL_GREY_TEST_DISABLED(@"Test disabled on iOS 11."); + // TODO(crbug.com/753098): Re-enable this test on iPad once grey_typeText + // works. + if (IsIPadIdiom()) { + EARL_GREY_TEST_DISABLED(@"Test disabled on iPad."); } // Load the blank test page and show a prompt dialog. @@ -544,11 +544,9 @@ // Tests that an alert is presented after displaying the share menu. - (void)testShowJavaScriptAfterShareMenu { - // TODO(crbug.com/747622): re-enable this test on iOS 11 once earl grey can - // interact with the share menu. - if (base::ios::IsRunningOnIOS11OrLater()) { - EARL_GREY_TEST_DISABLED(@"Disabled on iOS 11."); - } + // TODO(crbug.com/747622): re-enable this test once earl grey can interact + // with the share menu. + EARL_GREY_TEST_DISABLED(@"Disabled until EG can use share menu."); // Load the blank test page. [self loadBlankTestPage];
diff --git a/ios/chrome/browser/ui/download/download_manager_egtest.mm b/ios/chrome/browser/ui/download/download_manager_egtest.mm index b31a414..043ee43 100644 --- a/ios/chrome/browser/ui/download/download_manager_egtest.mm +++ b/ios/chrome/browser/ui/download/download_manager_egtest.mm
@@ -169,9 +169,7 @@ [ChromeEarlGrey loadURL:GURL(kChromeUITermsURL)]; const char kTermsText[] = "Google Chrome Terms of Service"; [ChromeEarlGrey waitForWebViewContainingText:kTermsText]; - chrome_test_util::CloseCurrentTab(); - [[GREYUIThreadExecutor sharedInstance] drainUntilIdle]; - + [ChromeEarlGrey closeCurrentTab]; GREYAssert(WaitForOpenInButton(), @"Open in... button did not show up"); }
diff --git a/ios/chrome/browser/ui/find_bar/find_bar_view.mm b/ios/chrome/browser/ui/find_bar/find_bar_view.mm index 22cf4ee..28a8c82 100644 --- a/ios/chrome/browser/ui/find_bar/find_bar_view.mm +++ b/ios/chrome/browser/ui/find_bar/find_bar_view.mm
@@ -91,7 +91,7 @@ // The subviews layout is the following: // |-[inputField]-[previousButton][nextButton]-[closeButton]-| - (void)setupConstraints { - id<LayoutGuideProvider> safeArea = SafeAreaLayoutGuideForView(self); + id<LayoutGuideProvider> safeArea = self.safeAreaLayoutGuide; [self.closeButton setContentCompressionResistancePriority:UILayoutPriorityDefaultHigh + 1
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_egtest.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_egtest.mm index 51d3b34..bd7abab 100644 --- a/ios/chrome/browser/ui/fullscreen/fullscreen_egtest.mm +++ b/ios/chrome/browser/ui/fullscreen/fullscreen_egtest.mm
@@ -115,12 +115,8 @@ if (base::FeatureList::IsEnabled( web::features::kBrowserContainerFullscreen) && base::FeatureList::IsEnabled(web::features::kOutOfWebFullscreen)) { - if (@available(iOS 11, *)) { - yOffset -= - chrome_test_util::GetCurrentWebState()->GetView().safeAreaInsets.top; - } else { - yOffset -= StatusBarHeight(); - } + yOffset -= + chrome_test_util::GetCurrentWebState()->GetView().safeAreaInsets.top; } DCHECK_LT(yOffset, 0); [[EarlGrey
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_system_notification_observer.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_system_notification_observer.mm index c1061f7..e84faf6 100644 --- a/ios/chrome/browser/ui/fullscreen/fullscreen_system_notification_observer.mm +++ b/ios/chrome/browser/ui/fullscreen/fullscreen_system_notification_observer.mm
@@ -50,21 +50,12 @@ // Register for VoiceOVer status change notifications. The notification // name has been updated in iOS 11. NSNotificationCenter* defaultCenter = [NSNotificationCenter defaultCenter]; - if (@available(iOS 11, *)) { - [defaultCenter - addObserver:self - selector:@selector(voiceOverStatusChanged) - name:UIAccessibilityVoiceOverStatusDidChangeNotification - object:nil]; - } -#if !defined(__IPHONE_11_0) || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_11_0 - else { - [defaultCenter addObserver:self - selector:@selector(voiceOverStatusChanged) - name:UIAccessibilityVoiceOverStatusChanged - object:nil]; - } -#endif + [defaultCenter + addObserver:self + selector:@selector(voiceOverStatusChanged) + name:UIAccessibilityVoiceOverStatusDidChangeNotification + object:nil]; + // Create a disabler if VoiceOver is enabled. if (UIAccessibilityIsVoiceOverRunning()) { _voiceOverDisabler =
diff --git a/ios/chrome/browser/ui/history/history_table_view_controller.mm b/ios/chrome/browser/ui/history/history_table_view_controller.mm index efcbe37..d1db90c 100644 --- a/ios/chrome/browser/ui/history/history_table_view_controller.mm +++ b/ios/chrome/browser/ui/history/history_table_view_controller.mm
@@ -152,29 +152,25 @@ - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; - if (@available(iOS 11, *)) { - // Center search bar's cancel button vertically so it looks centered. - // We change the cancel button proxy styles, so we will return it to - // default in viewDidDisappear. - UIOffset offset = - UIOffsetMake(0.0f, kTableViewNavigationVerticalOffsetForSearchHeader); - UIBarButtonItem* cancelButton = [UIBarButtonItem - appearanceWhenContainedInInstancesOfClasses:@[ [UISearchBar class] ]]; - [cancelButton setTitlePositionAdjustment:offset - forBarMetrics:UIBarMetricsDefault]; - } + // Center search bar's cancel button vertically so it looks centered. + // We change the cancel button proxy styles, so we will return it to + // default in viewDidDisappear. + UIOffset offset = + UIOffsetMake(0.0f, kTableViewNavigationVerticalOffsetForSearchHeader); + UIBarButtonItem* cancelButton = [UIBarButtonItem + appearanceWhenContainedInInstancesOfClasses:@[ [UISearchBar class] ]]; + [cancelButton setTitlePositionAdjustment:offset + forBarMetrics:UIBarMetricsDefault]; } - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; - if (@available(iOS 11, *)) { - // Restore to default origin offset for cancel button proxy style. - UIBarButtonItem* cancelButton = [UIBarButtonItem - appearanceWhenContainedInInstancesOfClasses:@[ [UISearchBar class] ]]; - [cancelButton setTitlePositionAdjustment:UIOffsetZero - forBarMetrics:UIBarMetricsDefault]; - } + // Restore to default origin offset for cancel button proxy style. + UIBarButtonItem* cancelButton = [UIBarButtonItem + appearanceWhenContainedInInstancesOfClasses:@[ [UISearchBar class] ]]; + [cancelButton setTitlePositionAdjustment:UIOffsetZero + forBarMetrics:UIBarMetricsDefault]; } - (void)viewDidLoad { @@ -241,21 +237,16 @@ action:@selector(dismissSearchController:) forControlEvents:UIControlEventAllTouchEvents]; - // For iOS 11 and later, place the search bar in the navigation bar. Otherwise - // place the search bar in the table view's header. - if (@available(iOS 11, *)) { - self.navigationItem.searchController = self.searchController; - self.navigationItem.hidesSearchBarWhenScrolling = NO; + // Place the search bar in the navigation bar. + self.navigationItem.searchController = self.searchController; + self.navigationItem.hidesSearchBarWhenScrolling = NO; - // Center search bar and cancel button vertically so it looks centered - // in the header when searching. - UIOffset offset = - UIOffsetMake(0.0f, kTableViewNavigationVerticalOffsetForSearchHeader); - self.searchController.searchBar.searchFieldBackgroundPositionAdjustment = - offset; - } else { - self.tableView.tableHeaderView = self.searchController.searchBar; - } + // Center search bar and cancel button vertically so it looks centered + // in the header when searching. + UIOffset offset = + UIOffsetMake(0.0f, kTableViewNavigationVerticalOffsetForSearchHeader); + self.searchController.searchBar.searchFieldBackgroundPositionAdjustment = + offset; } #pragma mark - TableViewModel @@ -534,25 +525,15 @@ } self.historyService->RemoveVisits(entries); - // Delete items from |self.tableView|. - // If iOS11+ use performBatchUpdates: instead of beginUpdates/endUpdates. - if (@available(iOS 11, *)) { - [self.tableView performBatchUpdates:^{ - [self deleteItemsFromTableViewModelWithIndex:toDeleteIndexPaths - deleteItemsFromTableView:YES]; - } - completion:^(BOOL) { - [self updateTableViewAfterDeletingEntries]; - [self configureViewsForNonEditModeWithAnimation:YES]; - }]; - } else { - [self.tableView beginUpdates]; + // Delete items from |self.tableView| using performBatchUpdates. + [self.tableView performBatchUpdates:^{ [self deleteItemsFromTableViewModelWithIndex:toDeleteIndexPaths deleteItemsFromTableView:YES]; - [self updateTableViewAfterDeletingEntries]; - [self configureViewsForNonEditModeWithAnimation:YES]; - [self.tableView endUpdates]; } + completion:^(BOOL) { + [self updateTableViewAfterDeletingEntries]; + [self configureViewsForNonEditModeWithAnimation:YES]; + }]; base::RecordAction(base::UserMetricsAction("HistoryPage_RemoveSelected")); } @@ -815,14 +796,7 @@ // If there's any tableUpdates, run them. if (tableUpdates) { - // If iOS11+ use performBatchUpdates: instead of beginUpdates/endUpdates. - if (@available(iOS 11, *)) { - [self.tableView performBatchUpdates:tableUpdates completion:nil]; - } else { - [self.tableView beginUpdates]; - tableUpdates(); - [self.tableView endUpdates]; - } + [self.tableView performBatchUpdates:tableUpdates completion:nil]; } self.currentStatusMessage = newStatusMessage; }
diff --git a/ios/chrome/browser/ui/history/history_ui_egtest.mm b/ios/chrome/browser/ui/history/history_ui_egtest.mm index 40f8e8a..0198e25 100644 --- a/ios/chrome/browser/ui/history/history_ui_egtest.mm +++ b/ios/chrome/browser/ui/history/history_ui_egtest.mm
@@ -218,10 +218,10 @@ // Tests that searching history displays only entries matching the search term. - (void)testSearchHistory { - // TODO(crbug.com/753098): Re-enable this test on iOS 11 iPad once - // grey_typeText works on iOS 11. - if (base::ios::IsRunningOnIOS11OrLater() && IsIPadIdiom()) { - EARL_GREY_TEST_DISABLED(@"Test disabled on iOS 11."); + // TODO(crbug.com/753098): Re-enable this test on iPad once grey_typeText + // works on iOS 11. + if (IsIPadIdiom()) { + EARL_GREY_TEST_DISABLED(@"Test disabled on iPad."); } [self loadTestURLs];
diff --git a/ios/chrome/browser/ui/infobars/confirm_infobar_view.mm b/ios/chrome/browser/ui/infobars/confirm_infobar_view.mm index 94a7dd0..d8c6d167 100644 --- a/ios/chrome/browser/ui/infobars/confirm_infobar_view.mm +++ b/ios/chrome/browser/ui/infobars/confirm_infobar_view.mm
@@ -388,7 +388,7 @@ leftMargin += metrics_->horizontal_space_between_icon_and_text; } else { leftMargin += metrics_->left_margin_on_first_line_when_icon_absent; - leftMargin += SafeAreaInsetsForView(self).left; + leftMargin += self.safeAreaInsets.left; } return leftMargin; } @@ -396,8 +396,7 @@ // Returns the width reserved for the close button. - (CGFloat)rightMarginOnFirstLine { return [closeButton_ imageView].image.size.width + - metrics_->close_button_inner_padding * 2 + - SafeAreaInsetsForView(self).right; + metrics_->close_button_inner_padding * 2 + self.safeAreaInsets.right; } // Returns the horizontal space available between the icon and the close @@ -533,7 +532,7 @@ [self layoutWideButtonAlignRight:button1_ rightEdge:CGRectGetWidth(self.bounds) - metrics_->button_margin - - SafeAreaInsetsForView(self).right + self.safeAreaInsets.right y:heightOfFirstLine]; [self layoutWideButtonAlignRight:button2_ rightEdge:leftOfRightmostButton - @@ -562,7 +561,7 @@ [self layoutWideButtonAlignRight:button rightEdge:CGRectGetWidth(self.bounds) - metrics_->button_margin - - SafeAreaInsetsForView(self).right + self.safeAreaInsets.right y:heightOfFirstLine]; } return metrics_->button_height; @@ -734,7 +733,7 @@ // The top safe area is ignored because at rest (i.e. not during animations) // the infobar is aligned to the bottom of the screen, and thus should not // have its top intersect with any safe area. - CGFloat bottomSafeAreaInset = SafeAreaInsetsForView(self).bottom; + CGFloat bottomSafeAreaInset = self.safeAreaInsets.bottom; requiredHeight += bottomSafeAreaInset; UILayoutGuide* guide = @@ -1013,7 +1012,7 @@ closeButtonSize.width += metrics_->close_button_inner_padding * 2; closeButtonSize.height += metrics_->close_button_inner_padding * 2; CGFloat x = CGRectGetMaxX(self.frame) - closeButtonSize.width - - SafeAreaInsetsForView(self).right; + self.safeAreaInsets.right; // Aligns the close button at the top (height includes touch padding). CGFloat y = 0; if (singleLineMode) { @@ -1027,8 +1026,7 @@ - (CGRect)frameOfIcon { CGSize iconSize = [imageView_ image].size; CGFloat y = metrics_->buttons_margin_top; - CGFloat x = - metrics_->close_button_margin_left + SafeAreaInsetsForView(self).left; + CGFloat x = metrics_->close_button_margin_left + self.safeAreaInsets.left; return CGRectMake(AlignValueToPixel(x), AlignValueToPixel(y), iconSize.width, iconSize.height); }
diff --git a/ios/chrome/browser/ui/infobars/infobar_container_view_controller.mm b/ios/chrome/browser/ui/infobars/infobar_container_view_controller.mm index 70342d3..541728f 100644 --- a/ios/chrome/browser/ui/infobars/infobar_container_view_controller.mm +++ b/ios/chrome/browser/ui/infobars/infobar_container_view_controller.mm
@@ -17,6 +17,14 @@ const CGFloat kAlphaChangeAnimationDuration = 0.35; } // namespace +@interface InfobarContainerViewController () + +// Whether the controller's view is currently available. +// YES from viewDidAppear to viewDidDisappear. +@property(nonatomic, assign, getter=isVisible) BOOL visible; + +@end + @implementation InfobarContainerViewController // Whenever the container or contained views are re-drawn update the layout to @@ -26,6 +34,16 @@ [self updateLayoutAnimated:YES]; } +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + self.visible = YES; +} + +- (void)viewDidDisappear:(BOOL)animated { + self.visible = NO; + [super viewDidDisappear:animated]; +} + #pragma mark - InfobarConsumer - (void)addInfoBarView:(UIView*)infoBarView position:(NSInteger)position { @@ -53,9 +71,8 @@ CGRectGetMaxY([self.positioner parentView].frame) - height; containerFrame.size.height = height; - BOOL isViewVisible = [self.positioner isParentViewVisible]; auto completion = ^(BOOL finished) { - if (!isViewVisible) + if (!self.visible) return; UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, self.view);
diff --git a/ios/chrome/browser/ui/infobars/infobar_egtest.mm b/ios/chrome/browser/ui/infobars/infobar_egtest.mm index 0227d2e7..f8ef228 100644 --- a/ios/chrome/browser/ui/infobars/infobar_egtest.mm +++ b/ios/chrome/browser/ui/infobars/infobar_egtest.mm
@@ -154,7 +154,7 @@ // Close the first tab. Verify that there is only one tab remaining and its // infobar is visible. - chrome_test_util::CloseCurrentTab(); + [ChromeEarlGrey closeCurrentTab]; [ChromeEarlGrey waitForMainTabCount:1]; VerifyTestInfoBarVisibleForCurrentTab(true, infoBarMessage); VerifyNumberOfInfobarsInManager(1);
diff --git a/ios/chrome/browser/ui/infobars/infobar_positioner.h b/ios/chrome/browser/ui/infobars/infobar_positioner.h index 5133d84..bc5e0ac 100644 --- a/ios/chrome/browser/ui/infobars/infobar_positioner.h +++ b/ios/chrome/browser/ui/infobars/infobar_positioner.h
@@ -14,9 +14,6 @@ // View to which the popup view should be added as subview. - (UIView*)parentView; -// YES if |parentView| is currently visible. -- (BOOL)isParentViewVisible; - @end #endif // IOS_CHROME_BROWSER_UI_INFOBARS_INFOBAR_POSITIONER_H_
diff --git a/ios/chrome/browser/ui/main/BUILD.gn b/ios/chrome/browser/ui/main/BUILD.gn index 24da136..14991e5 100644 --- a/ios/chrome/browser/ui/main/BUILD.gn +++ b/ios/chrome/browser/ui/main/BUILD.gn
@@ -5,6 +5,8 @@ source_set("main") { configs += [ "//build/config/compiler:enable_arc" ] sources = [ + "browser_coordinator.h", + "browser_coordinator.mm", "browser_view_information.h", "browser_view_wrangler.h", "browser_view_wrangler.mm", @@ -25,6 +27,7 @@ "//ios/chrome/browser/sessions:serialisation", "//ios/chrome/browser/tabs", "//ios/chrome/browser/tabs:tabs_internal", + "//ios/chrome/browser/ui/coordinators:chrome_coordinators", "//ios/public/provider/chrome/browser", ] public_deps = [
diff --git a/ios/chrome/browser/ui/main/browser_coordinator.h b/ios/chrome/browser/ui/main/browser_coordinator.h new file mode 100644 index 0000000..91df937 --- /dev/null +++ b/ios/chrome/browser/ui/main/browser_coordinator.h
@@ -0,0 +1,28 @@ +// 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_MAIN_BROWSER_COORDINATOR_H_ +#define IOS_CHROME_BROWSER_UI_MAIN_BROWSER_COORDINATOR_H_ + +#import "ios/chrome/browser/ui/coordinators/chrome_coordinator.h" + +@protocol ApplicationCommands; +@class BrowserViewController; +@class TabModel; + +// Coordinator for BrowserViewController. +@interface BrowserCoordinator : ChromeCoordinator + +// The main view controller. +@property(nonatomic, strong, readonly) BrowserViewController* viewController; + +// Command handler for ApplicationCommands. +@property(nonatomic, weak) id<ApplicationCommands> applicationCommandHandler; + +// The model. +@property(nonatomic, weak) TabModel* tabModel; + +@end + +#endif // IOS_CHROME_BROWSER_UI_MAIN_BROWSER_COORDINATOR_H_
diff --git a/ios/chrome/browser/ui/main/browser_coordinator.mm b/ios/chrome/browser/ui/main/browser_coordinator.mm new file mode 100644 index 0000000..0db3718 --- /dev/null +++ b/ios/chrome/browser/ui/main/browser_coordinator.mm
@@ -0,0 +1,50 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/main/browser_coordinator.h" + +#import "ios/chrome/browser/ui/browser_view_controller.h" +#import "ios/chrome/browser/ui/browser_view_controller_dependency_factory.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +@implementation BrowserCoordinator +@synthesize viewController = _viewController; +@synthesize applicationCommandHandler = _applicationCommandHandler; +@synthesize tabModel = _tabModel; + +#pragma mark - ChromeCoordinator + +- (void)start { + DCHECK(self.browserState); + DCHECK(!self.viewController); + _viewController = [self createViewController]; + [super start]; +} + +- (void)stop { + [_viewController browserStateDestroyed]; + [_viewController shutdown]; + _viewController = nil; + [super stop]; +} + +#pragma mark - Private + +// Instantiate a BrowserViewController. +- (BrowserViewController*)createViewController { + BrowserViewControllerDependencyFactory* factory = + [[BrowserViewControllerDependencyFactory alloc] + initWithBrowserState:self.browserState + webStateList:[self.tabModel webStateList]]; + return [[BrowserViewController alloc] + initWithTabModel:self.tabModel + browserState:self.browserState + dependencyFactory:factory + applicationCommandEndpoint:self.applicationCommandHandler]; +} + +@end
diff --git a/ios/chrome/browser/ui/main/browser_view_information.h b/ios/chrome/browser/ui/main/browser_view_information.h index b8b295d..a784a59 100644 --- a/ios/chrome/browser/ui/main/browser_view_information.h +++ b/ios/chrome/browser/ui/main/browser_view_information.h
@@ -18,16 +18,16 @@ @protocol BrowserViewInformation<NSObject> // The normal (non-OTR) BrowserViewController -@property(nonatomic, retain) BrowserViewController* mainBVC; +@property(nonatomic, readonly) BrowserViewController* mainBVC; // The normal (non-OTR) TabModel corresponding to mainBVC. @property(nonatomic, retain) TabModel* mainTabModel; // The OTR BrowserViewController. -@property(nonatomic, retain) BrowserViewController* otrBVC; +@property(nonatomic, readonly) BrowserViewController* otrBVC; // The OTR TabModel corresponding to otrBVC. @property(nonatomic, retain) TabModel* otrTabModel; // The BrowserViewController that is currently being used (one of mainBVC or // otrBVC). The other, if present, is in suspended mode. -@property(nonatomic, assign) BrowserViewController* currentBVC; +@property(nonatomic, weak) BrowserViewController* currentBVC; // Halts all tabs from all TabModels. - (void)haltAllTabs;
diff --git a/ios/chrome/browser/ui/main/browser_view_wrangler.mm b/ios/chrome/browser/ui/main/browser_view_wrangler.mm index 462dab5..85bb055 100644 --- a/ios/chrome/browser/ui/main/browser_view_wrangler.mm +++ b/ios/chrome/browser/ui/main/browser_view_wrangler.mm
@@ -18,6 +18,7 @@ #import "ios/chrome/browser/tabs/tab_model_observer.h" #import "ios/chrome/browser/ui/browser_view_controller.h" #import "ios/chrome/browser/ui/browser_view_controller_dependency_factory.h" +#import "ios/chrome/browser/ui/main/browser_coordinator.h" #include "ios/public/provider/chrome/browser/chrome_browser_provider.h" #import "ios/web/public/web_state/web_state.h" @@ -32,6 +33,12 @@ BOOL _isShutdown; } +// Coordinator for non-incognito BVC. +@property(nonatomic, strong) BrowserCoordinator* mainCoordinator; + +// Coordinator for incognito BVC. +@property(nonatomic, strong) BrowserCoordinator* incognitoCoordinator; + // Responsible for maintaining all state related to sharing to other devices. // Redeclared readwrite from the readonly declaration in the Testing interface. @property(nonatomic, strong, readwrite) @@ -48,22 +55,22 @@ // result. - (TabModel*)buildOtrTabModel:(BOOL)empty; -// Creates the correct BrowserViewController for the corresponding browser state +// Creates the correct BrowserCoordinator for the corresponding browser state // and tab model. -- (BrowserViewController*)bvcForBrowserState: - (ios::ChromeBrowserState*)browserState - tabModel:(TabModel*)tabModel; +- (BrowserCoordinator*)coordinatorForBrowserState: + (ios::ChromeBrowserState*)browserState + tabModel:(TabModel*)tabModel; @end @implementation BrowserViewWrangler // Properties defined in the BrowserViewInformation protocol. -@synthesize mainBVC = _mainBVC; @synthesize mainTabModel = _mainTabModel; -@synthesize otrBVC = _otrBVC; @synthesize otrTabModel = _otrTabModel; @synthesize currentBVC = _currentBVC; // Private properies. +@synthesize mainCoordinator = _mainCoordinator; +@synthesize incognitoCoordinator = _incognitoCoordinator; @synthesize deviceSharingManager = _deviceSharingManager; - (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState @@ -85,27 +92,16 @@ #pragma mark - BrowserViewInformation property implementations - (BrowserViewController*)mainBVC { - if (!_mainBVC) { + if (!self.mainCoordinator.viewController) { // |_browserState| should always be set before trying to create - // |_mainBVC|. + // |mainBVC|. DCHECK(_browserState); - self.mainBVC = - [self bvcForBrowserState:_browserState tabModel:self.mainTabModel]; - DCHECK(_mainBVC); + self.mainCoordinator = [self coordinatorForBrowserState:_browserState + tabModel:self.mainTabModel]; + [self.mainCoordinator start]; + DCHECK(self.mainCoordinator.viewController); } - return _mainBVC; -} - -- (void)setMainBVC:(BrowserViewController*)mainBVC { - if (_mainBVC == mainBVC) - return; - - if (_mainBVC) { - [_mainBVC browserStateDestroyed]; - [_mainBVC shutdown]; - } - - _mainBVC = mainBVC; + return self.mainCoordinator.viewController; } - (TabModel*)mainTabModel { @@ -137,30 +133,20 @@ } - (BrowserViewController*)otrBVC { - if (!_otrBVC) { + if (!self.incognitoCoordinator.viewController) { // |_browserState| should always be set before trying to create - // |_otrBVC|. + // |otrBVC|. DCHECK(_browserState); ios::ChromeBrowserState* otrBrowserState = _browserState->GetOffTheRecordChromeBrowserState(); DCHECK(otrBrowserState); - self.otrBVC = - [self bvcForBrowserState:otrBrowserState tabModel:self.otrTabModel]; - DCHECK(_otrBVC); + self.incognitoCoordinator = + [self coordinatorForBrowserState:otrBrowserState + tabModel:self.otrTabModel]; + [self.incognitoCoordinator start]; + DCHECK(self.incognitoCoordinator.viewController); } - return _otrBVC; -} - -- (void)setOtrBVC:(BrowserViewController*)otrBVC { - if (_otrBVC == otrBVC) - return; - - if (_otrBVC) { - [_otrBVC browserStateDestroyed]; - [_otrBVC shutdown]; - } - - _otrBVC = otrBVC; + return self.incognitoCoordinator.viewController; } - (TabModel*)otrTabModel { @@ -190,7 +176,7 @@ storageSwitcher:(id<BrowserStateStorageSwitching>)storageSwitcher { DCHECK(bvc != nil); // |bvc| should be one of the BrowserViewControllers this class already owns. - DCHECK(_mainBVC == bvc || _otrBVC == bvc); + DCHECK(self.mainBVC == bvc || self.otrBVC == bvc); if (self.currentBVC == bvc) { return; } @@ -271,11 +257,13 @@ breakpad::StopMonitoringTabStateForTabModel(self.otrTabModel); // At this stage, a new OTR BVC shouldn't be lazily constructed by calling the - // .otrBVC property getter. Instead, the ivar is accessed directly through the - // following code. - BOOL otrBVCIsCurrent = self.currentBVC == _otrBVC; + // .otrBVC property getter. + BOOL otrBVCIsCurrent = + self.currentBVC == self.incognitoCoordinator.viewController; @autoreleasepool { - self.otrBVC = nil; + [self.incognitoCoordinator stop]; + self.incognitoCoordinator = nil; + // There's no guarantee the tab model was ever added to the BVC (or even // that the BVC was created), so ensure the tab model gets notified. self.otrTabModel = nil; @@ -327,8 +315,10 @@ [_mainTabModel browserStateDestroyed]; [_otrTabModel browserStateDestroyed]; - self.mainBVC = nil; - self.otrBVC = nil; + [self.mainCoordinator stop]; + self.mainCoordinator = nil; + [self.incognitoCoordinator stop]; + self.incognitoCoordinator = nil; _browserState = nullptr; } @@ -374,18 +364,15 @@ return tabModel; } -- (BrowserViewController*)bvcForBrowserState: - (ios::ChromeBrowserState*)browserState - tabModel:(TabModel*)tabModel { - BrowserViewControllerDependencyFactory* factory = - [[BrowserViewControllerDependencyFactory alloc] - initWithBrowserState:browserState - webStateList:[tabModel webStateList]]; - return [[BrowserViewController alloc] - initWithTabModel:tabModel - browserState:browserState - dependencyFactory:factory - applicationCommandEndpoint:_applicationCommandEndpoint]; +- (BrowserCoordinator*)coordinatorForBrowserState: + (ios::ChromeBrowserState*)browserState + tabModel:(TabModel*)tabModel { + BrowserCoordinator* coordinator = + [[BrowserCoordinator alloc] initWithBaseViewController:nil + browserState:browserState]; + coordinator.tabModel = tabModel; + coordinator.applicationCommandHandler = _applicationCommandEndpoint; + return coordinator; } @end
diff --git a/ios/chrome/browser/ui/main_content/web_scroll_view_main_content_ui_forwarder.mm b/ios/chrome/browser/ui/main_content/web_scroll_view_main_content_ui_forwarder.mm index 93e3268..1f2b35e 100644 --- a/ios/chrome/browser/ui/main_content/web_scroll_view_main_content_ui_forwarder.mm +++ b/ios/chrome/browser/ui/main_content/web_scroll_view_main_content_ui_forwarder.mm
@@ -201,9 +201,7 @@ // any changes. - (void)checkForContentInsetAdjustment { UIEdgeInsets inset = self.proxy.contentInset; - if (@available(iOS 11, *)) { - inset = self.proxy.adjustedContentInset; - } + inset = self.proxy.adjustedContentInset; if (!UIEdgeInsetsEqualToEdgeInsets(inset, self.updater.state.contentInset)) [self.updater scrollViewDidResetContentInset:inset]; }
diff --git a/ios/chrome/browser/ui/ntp/incognito_view.mm b/ios/chrome/browser/ui/ntp/incognito_view.mm index 5f65456b..e256836 100644 --- a/ios/chrome/browser/ui/ntp/incognito_view.mm +++ b/ios/chrome/browser/ui/ntp/incognito_view.mm
@@ -285,8 +285,7 @@ if (!self.superview) return; - id<LayoutGuideProvider> safeAreaGuide = - SafeAreaLayoutGuideForView(self.superview); + id<LayoutGuideProvider> safeAreaGuide = self.superview.safeAreaLayoutGuide; _bottomUnsafeAreaGuideInSuperview = [[UILayoutGuide alloc] init]; [self.superview addLayoutGuide:_bottomUnsafeAreaGuideInSuperview]; @@ -345,12 +344,7 @@ if (IsRegularXRegularSizeClass(self)) { _topToolbarMarginHeight.constant = 0; } else { - CGFloat topInset = 0; - if (@available(iOS 11, *)) { - topInset = self.safeAreaInsets.top; - } else { - topInset = StatusBarHeight(); - } + CGFloat topInset = self.safeAreaInsets.top; _topToolbarMarginHeight.constant = topInset + ToolbarExpandedHeight( self.traitCollection.preferredContentSizeCategory);
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_egtest.mm b/ios/chrome/browser/ui/ntp/new_tab_page_egtest.mm index 305dcd8..815a36b 100644 --- a/ios/chrome/browser/ui/ntp/new_tab_page_egtest.mm +++ b/ios/chrome/browser/ui/ntp/new_tab_page_egtest.mm
@@ -65,7 +65,7 @@ [ChromeEarlGrey openNewIncognitoTab]; WaitForHistoryToDisappear(); chrome_test_util::VerifyAccessibilityForCurrentScreen(); - GREYAssert(chrome_test_util::CloseAllIncognitoTabs(), @"Tabs did not close"); + [ChromeEarlGrey closeAllIncognitoTabs]; } @end
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 f7bacefb..a763b979 100644 --- a/ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.mm +++ b/ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.mm
@@ -50,7 +50,6 @@ // When rendering the same string in a UITextField and a UILabel with the same // frame and the same font, the text is slightly offset. const CGFloat kUILabelUITextfieldBaselineDeltaInPoints = 1.0; -const CGFloat kUILabelUITextfieldBaselineDeltaIpadIOS10InPixels = 1.0; // The default omnibox text color (used while editing). UIColor* TextColor() { @@ -248,19 +247,6 @@ NSTextAlignment alignment = [self bestTextAlignment]; [self setTextAlignment:alignment]; - if (!base::ios::IsRunningOnIOS11OrLater()) { - // TODO(crbug.com/730461): Remove this entire block once it's been tested - // on trunk. - UITextWritingDirection writingDirection = - alignment == NSTextAlignmentLeft ? UITextWritingDirectionLeftToRight - : UITextWritingDirectionRightToLeft; - [self - setBaseWritingDirection:writingDirection - forRange: - [self - textRangeFromPosition:[self beginningOfDocument] - toPosition:[self endOfDocument]]]; - } } - (UIColor*)displayedTextColor { @@ -1118,19 +1104,12 @@ - (void)layoutSelectionViewWithNewEditingRectBounds:(CGRect)newBounds { // The goal is to visually align the _selection label and the |self| textfield // to avoid text jumping when inline autocomplete is shown or hidden. - CGFloat baselineDifference = kUILabelUITextfieldBaselineDeltaInPoints; - if (IsIPadIdiom() && !base::ios::IsRunningOnIOS11OrLater()) { - // On iOS 10, there is a difference between iPad and iPhone rendering. - baselineDifference = kUILabelUITextfieldBaselineDeltaIpadIOS10InPixels / - UIScreen.mainScreen.scale; - } - - newBounds.origin.y -= baselineDifference; + newBounds.origin.y -= kUILabelUITextfieldBaselineDeltaInPoints; // Position the selection view appropriately. [_selection setFrame:newBounds]; - newBounds.origin.y += baselineDifference; + newBounds.origin.y += kUILabelUITextfieldBaselineDeltaInPoints; } @end
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_controller.mm b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_controller.mm index 5208e9e..e84c028 100644 --- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_controller.mm +++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_controller.mm
@@ -127,10 +127,7 @@ - (void)viewDidLoad { [super viewDidLoad]; - // Respect the safe area on iOS 11 to support iPhone X. - if (@available(iOS 11, *)) { - self.tableView.insetsContentViewsToSafeArea = YES; - } + self.tableView.insetsContentViewsToSafeArea = YES; // Initialize the same size as the parent view, autoresize will correct this. [self.view setFrame:CGRectZero]; @@ -168,15 +165,8 @@ if ([self.tableView respondsToSelector:@selector(setLayoutMargins:)]) { [self.tableView setLayoutMargins:UIEdgeInsetsZero]; } - if (@available(iOS 11, *)) { - self.tableView.contentInsetAdjustmentBehavior = - UIScrollViewContentInsetAdjustmentNever; - } -#if !defined(__IPHONE_11_0) || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_11_0 - else { - self.automaticallyAdjustsScrollViewInsets = NO; - } -#endif + self.tableView.contentInsetAdjustmentBehavior = + UIScrollViewContentInsetAdjustmentNever; [self.tableView setContentInset:UIEdgeInsetsMake(kTopAndBottomPadding, 0, kTopAndBottomPadding, 0)]; self.tableView.estimatedRowHeight = 0; @@ -347,7 +337,7 @@ [detailTextLabel setTextAlignment:_alignment]; // The width must be positive for CGContextRef to be valid. - UIEdgeInsets safeAreaInsets = SafeAreaInsetsForView(self.view); + UIEdgeInsets safeAreaInsets = self.view.safeAreaInsets; CGRect rowBounds = UIEdgeInsetsInsetRect(self.view.bounds, safeAreaInsets); CGFloat labelWidth = MAX(40, floorf(rowBounds.size.width) - kTextCellLeadingPadding); @@ -547,16 +537,8 @@ - (void)scrollViewDidScroll:(UIScrollView*)scrollView { // TODO(crbug.com/733650): Default to the dragging check once it's been tested // on trunk. - if (base::ios::IsRunningOnIOS11OrLater()) { - if (!scrollView.dragging) - return; - } else { - // Setting the top inset of the scrollView to |kTopAndBottomPadding| causes - // a one time scrollViewDidScroll to |-kTopAndBottomPadding|. It's easier - // to just ignore this one scroll tick. - if (scrollView.contentOffset.y == 0 - kTopAndBottomPadding) - return; - } + if (!scrollView.dragging) + return; if (self.forwardsScrollEvents) [self.delegate autocompleteResultConsumerDidScroll:self];
diff --git a/ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.mm b/ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.mm index 704ac5e..5d0ac33 100644 --- a/ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.mm +++ b/ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.mm
@@ -386,12 +386,7 @@ CGFloat topMargin = 0; if (!_webViewProxy && base::FeatureList::IsEnabled( web::features::kBrowserContainerFullscreen)) { - CGFloat topMargin = 0.0; - if (@available(iOS 11, *)) { - topMargin = self.scrollView.safeAreaInsets.top; - } else { - topMargin = StatusBarHeight(); - } + topMargin = self.scrollView.safeAreaInsets.top; } if (contentOffsetFromExpandedHeader >= 0) { // Record initial content offset and dispatch delegate on state change.
diff --git a/ios/chrome/browser/ui/payments/cells/page_info_item.mm b/ios/chrome/browser/ui/payments/cells/page_info_item.mm index 56c0a366..690e2c4 100644 --- a/ios/chrome/browser/ui/payments/cells/page_info_item.mm +++ b/ios/chrome/browser/ui/payments/cells/page_info_item.mm
@@ -68,15 +68,13 @@ [text addAttribute:NSForegroundColorAttributeName value:[[MDCPalette cr_greenPalette] tint700] range:NSMakeRange(0, strlen(url::kHttpsScheme))]; - if (@available(iOS 11, *)) { - // We need to set the font to the attributed portion, or the field doesn't - // asjust with dynamic types. - [text addAttribute:NSFontAttributeName - value:[[UIFontMetrics defaultMetrics] - scaledFontForFont:[[MDCTypography fontLoader] - regularFontOfSize:12]] - range:NSMakeRange(0, strlen(url::kHttpsScheme))]; - } + // We need to set the font to the attributed portion, or the field doesn't + // asjust with dynamic types. + [text addAttribute:NSFontAttributeName + value:[[UIFontMetrics defaultMetrics] + scaledFontForFont:[[MDCTypography fontLoader] + regularFontOfSize:12]] + range:NSMakeRange(0, strlen(url::kHttpsScheme))]; [cell.pageHostLabel setAttributedText:text]; // Set lock image. UIImageRenderingModeAlwaysTemplate is used so that
diff --git a/ios/chrome/browser/ui/payments/cells/payments_selector_edit_item.mm b/ios/chrome/browser/ui/payments/cells/payments_selector_edit_item.mm index 16801d23..3c01c660 100644 --- a/ios/chrome/browser/ui/payments/cells/payments_selector_edit_item.mm +++ b/ios/chrome/browser/ui/payments/cells/payments_selector_edit_item.mm
@@ -36,12 +36,8 @@ - (UIFont*)nameFont { if (!_nameFont) { - if (@available(iOS 11, *)) { - _nameFont = [[UIFontMetrics defaultMetrics] - scaledFontForFont:[MDCTypography body2Font]]; - } else { - _nameFont = [MDCTypography body2Font]; - } + _nameFont = [[UIFontMetrics defaultMetrics] + scaledFontForFont:[MDCTypography body2Font]]; } return _nameFont; } @@ -55,12 +51,8 @@ - (UIFont*)valueFont { if (!_valueFont) { - if (@available(iOS 11, *)) { - _valueFont = [[UIFontMetrics defaultMetrics] - scaledFontForFont:[MDCTypography body1Font]]; - } else { - _valueFont = [MDCTypography body1Font]; - } + _valueFont = [[UIFontMetrics defaultMetrics] + scaledFontForFont:[MDCTypography body1Font]]; } return _valueFont; } @@ -86,10 +78,8 @@ cell.textLabel.textColor = self.nameColor; cell.detailTextLabel.font = self.valueFont; cell.detailTextLabel.textColor = self.valueColor; - if (@available(iOS 11, *)) { - cell.textLabel.adjustsFontForContentSizeCategory = YES; - cell.detailTextLabel.adjustsFontForContentSizeCategory = YES; - } + cell.textLabel.adjustsFontForContentSizeCategory = YES; + cell.detailTextLabel.adjustsFontForContentSizeCategory = YES; [cell updateConstraintsIfNeeded]; }
diff --git a/ios/chrome/browser/ui/payments/payment_request_picker_view_controller.mm b/ios/chrome/browser/ui/payments/payment_request_picker_view_controller.mm index 69ab08d..1605620 100644 --- a/ios/chrome/browser/ui/payments/payment_request_picker_view_controller.mm +++ b/ios/chrome/browser/ui/payments/payment_request_picker_view_controller.mm
@@ -286,12 +286,7 @@ // content by the same amount, to ensure they line up properly. Also insets // by one more pixel to hide the one pixel gap left in between the // navigation bar and the UITableView. - CGFloat topInset = 0; - if (@available(iOS 11, *)) { - topInset = self.view.safeAreaInsets.top; - } else { - topInset = StatusBarHeight(); - } + CGFloat topInset = self.view.safeAreaInsets.top; const UIEdgeInsets statusBarInset = UIEdgeInsetsMake(-1 - topInset, 0, 0, 0); self.tableView.contentInset = statusBarInset;
diff --git a/ios/chrome/browser/ui/popup_menu/popup_menu_presenter.mm b/ios/chrome/browser/ui/popup_menu/popup_menu_presenter.mm index 1814f21..cf98023 100644 --- a/ios/chrome/browser/ui/popup_menu/popup_menu_presenter.mm +++ b/ios/chrome/browser/ui/popup_menu/popup_menu_presenter.mm
@@ -211,7 +211,7 @@ constraintEqualToAnchor:namedGuide.centerXAnchor]; center.priority = UILayoutPriorityDefaultHigh; - id<LayoutGuideProvider> safeArea = SafeAreaLayoutGuideForView(parentView); + id<LayoutGuideProvider> safeArea = parentView.safeAreaLayoutGuide; self.presentedConstraints = @[ center, verticalPositioning,
diff --git a/ios/chrome/browser/ui/popup_menu/popup_menu_table_view_controller.mm b/ios/chrome/browser/ui/popup_menu/popup_menu_table_view_controller.mm index 6b2843a20..42b4a4f 100644 --- a/ios/chrome/browser/ui/popup_menu/popup_menu_table_view_controller.mm +++ b/ios/chrome/browser/ui/popup_menu/popup_menu_table_view_controller.mm
@@ -139,15 +139,6 @@ initWithFrame:CGRectMake(0.0f, 0.0f, self.tableView.bounds.size.width, 0.01f)]; - if (!base::ios::IsRunningOnIOS11OrLater()) { - // On iOS 10, a footer with a height of 0 is also needed to prevent inset at - // the bottom. - self.tableView.tableFooterView = [[UIView alloc] - initWithFrame:CGRectMake(0.0f, 0.0f, self.tableView.bounds.size.width, - 0.01f)]; - self.tableView.sectionFooterHeight = 0.0; - } - self.view.layer.cornerRadius = kPopupMenuCornerRadius; self.view.layer.masksToBounds = YES; }
diff --git a/ios/chrome/browser/ui/print/print_controller.mm b/ios/chrome/browser/ui/print/print_controller.mm index 186c3ff..0e8cbc1 100644 --- a/ios/chrome/browser/ui/print/print_controller.mm +++ b/ios/chrome/browser/ui/print/print_controller.mm
@@ -5,7 +5,7 @@ #import "ios/chrome/browser/ui/print/print_controller.h" #import <MobileCoreServices/UTType.h> -#import <Webkit/Webkit.h> +#import <WebKit/WebKit.h> #include <memory>
diff --git a/ios/chrome/browser/ui/print/print_controller_egtest.mm b/ios/chrome/browser/ui/print/print_controller_egtest.mm index 07fc678..1a7e9eb9 100644 --- a/ios/chrome/browser/ui/print/print_controller_egtest.mm +++ b/ios/chrome/browser/ui/print/print_controller_egtest.mm
@@ -31,21 +31,6 @@ // A test HTML URL. const char kHTMLURL[] = "http://test"; - -// Returns the collection view for the activity services menu. Since this is a -// system widget, it does not have an a11y id. Instead, search for a -// UICollectionView that is the superview of the "Copy" menu item. There are -// two nested UICollectionViews in the activity services menu, so choose the -// innermost one. -id<GREYMatcher> ShareMenuCollectionView() { - id<GREYMatcher> copyButton = - chrome_test_util::ButtonWithAccessibilityLabel(@"Copy"); - return grey_allOf( - grey_kindOfClass([UICollectionView class]), grey_descendant(copyButton), - // Looking for a nested UICollectionView. - grey_descendant(grey_kindOfClass([UICollectionView class])), nil); -} - } // namespace // Print test cases. These are Earl Grey integration tests. @@ -64,27 +49,7 @@ // loaded. // TODO(crbug.com/683280): Does this test serve any purpose on iOS11? - (void)testPrintNormalPage { - if (base::ios::IsRunningOnIOS11OrLater() && IsUIRefreshPhase1Enabled()) { - EARL_GREY_TEST_SKIPPED( - @"Dispatcher-based printing does not work on iOS11 when the " - @"UIRefresh flag is enabled."); - } - -#if !TARGET_IPHONE_SIMULATOR - if (!base::ios::IsRunningOnIOS11OrLater()) { - // TODO(crbug.com/869477): Re-enable this test on device. - EARL_GREY_TEST_DISABLED(@"Fails on iOS 10.0 devices."); - } -#endif - -#if TARGET_IPHONE_SIMULATOR - if (IsIPadIdiom() && !base::ios::IsRunningOnIOS11OrLater()) { - // TODO(crbug.com/871685): Re-enable this test. - EARL_GREY_TEST_DISABLED( - @"Failing on iOS 10 iPad simulator, for " - @"ios_chrome_multitasking_egtests"); - } -#endif // TARGET_IPHONE_SIMULATOR + EARL_GREY_TEST_SKIPPED(@"Dispatcher-based printing does not work."); GURL url = web::test::HttpServer::MakeUrl(kHTMLURL); std::map<GURL, std::string> responses; @@ -101,17 +66,7 @@ // Tests that the AirPrint menu successfully loads when a PDF is loaded. // TODO(crbug.com/683280): Does this test serve any purpose on iOS11? - (void)testPrintPDF { - if (base::ios::IsRunningOnIOS11OrLater() && IsUIRefreshPhase1Enabled()) { - EARL_GREY_TEST_SKIPPED( - @"Dispatcher-based printing does not work on iOS11 when the " - @"UIRefresh flag is enabled."); - } -#if !TARGET_IPHONE_SIMULATOR - if (!base::ios::IsRunningOnIOS11OrLater()) { - // TODO(crbug.com/869477): Re-enable this test on device. - EARL_GREY_TEST_DISABLED(@"Fails on iOS 10.0 devices."); - } -#endif + EARL_GREY_TEST_SKIPPED(@"Dispatcher-based printing does not work."); web::test::SetUpFileBasedHttpServer(); GURL url = web::test::HttpServer::MakeUrl(kPDFURL); @@ -121,18 +76,6 @@ } - (void)printCurrentPage { - // EarlGrey does not have the ability to interact with the share menu in - // iOS11, so use the dispatcher to trigger the print view controller instead. - if (!base::ios::IsRunningOnIOS11OrLater()) { - [ChromeEarlGreyUI openShareMenu]; - id<GREYMatcher> printButton = - chrome_test_util::ButtonWithAccessibilityLabel(@"Print"); - [[[EarlGrey selectElementWithMatcher:printButton] - usingSearchAction:grey_scrollInDirection(kGREYDirectionRight, 100) - onElementWithMatcher:ShareMenuCollectionView()] - performAction:grey_tap()]; - } - id<GREYMatcher> printerOptionButton = grey_allOf( grey_accessibilityID(@"Printer Options"), grey_not(grey_accessibilityTrait(UIAccessibilityTraitHeader)), nil);
diff --git a/ios/chrome/browser/ui/qr_scanner/qr_scanner_view_controller_egtest.mm b/ios/chrome/browser/ui/qr_scanner/qr_scanner_view_controller_egtest.mm index 67ec84f..83a56ea 100644 --- a/ios/chrome/browser/ui/qr_scanner/qr_scanner_view_controller_egtest.mm +++ b/ios/chrome/browser/ui/qr_scanner/qr_scanner_view_controller_egtest.mm
@@ -563,13 +563,6 @@ // switched off and the correct button indicating that the torch is off is shown // when the scanner is opened again. - (void)testTorchButtonIsResetWhenQRScannerIsReopened { -// TODO(crbug.com/869176): Re-enable this test on iOS 10 iPad device. -#if !TARGET_IPHONE_SIMULATOR - if (!base::ios::IsRunningOnIOS11OrLater() && IsIPadIdiom()) { - EARL_GREY_TEST_DISABLED(@"Test disabled on iOS 10 iPad device."); - } -#endif - id cameraControllerMock = [self getCameraControllerMockWithAuthorizationStatus: AVAuthorizationStatusAuthorized]; @@ -603,12 +596,6 @@ // Tests that the torch button is disabled when the camera reports that torch // became unavailable. - (void)testTorchButtonIsDisabledWhenTorchBecomesUnavailable { -// TODO(crbug.com/869176): Re-enable this test on iOS 10 iPad device. -#if !TARGET_IPHONE_SIMULATOR - if (!base::ios::IsRunningOnIOS11OrLater() && IsIPadIdiom()) { - EARL_GREY_TEST_DISABLED(@"Test disabled on iOS 10 iPad device."); - } -#endif id cameraControllerMock = [self getCameraControllerMockWithAuthorizationStatus: AVAuthorizationStatusAuthorized]; @@ -656,12 +643,6 @@ // Tests that a UIAlertController is presented by the QRScannerViewController if // the camera state changes after the QRScannerViewController is presented. - (void)testDialogIsDisplayedIfCameraStateChanges { -// TODO(crbug.com/869176): Re-enable this test on iOS 10 iPad device. -#if !TARGET_IPHONE_SIMULATOR - if (!base::ios::IsRunningOnIOS11OrLater() && IsIPadIdiom()) { - EARL_GREY_TEST_DISABLED(@"Test disabled on iOS 10 iPad device."); - } -#endif id cameraControllerMock = [self getCameraControllerMockWithAuthorizationStatus: AVAuthorizationStatusAuthorized]; @@ -725,13 +706,6 @@ // Tests that an error dialog is dismissed if the camera becomes available. - (void)testDialogDismissedIfCameraBecomesAvailable { -// TODO(crbug.com/869176): Re-enable this test on iOS 10 iPad device. -#if !TARGET_IPHONE_SIMULATOR - if (!base::ios::IsRunningOnIOS11OrLater() && IsIPadIdiom()) { - EARL_GREY_TEST_DISABLED(@"Test disabled on iOS 10 iPad device."); - } -#endif - id cameraControllerMock = [self getCameraControllerMockWithAuthorizationStatus: AVAuthorizationStatusAuthorized]; @@ -802,12 +776,6 @@ // Test that the correct page is loaded if the scanner result is a URL. - (void)testReceivingQRScannerURLResult { -// TODO(crbug.com/869176): Re-enable this test on iOS 10 iPad device. -#if !TARGET_IPHONE_SIMULATOR - if (!base::ios::IsRunningOnIOS11OrLater() && IsIPadIdiom()) { - EARL_GREY_TEST_DISABLED(@"Test disabled on iOS 10 iPad device."); - } -#endif [self doTestReceivingResult:_testURL.GetContent() response:kTestURLResponse edit:nil]; @@ -816,16 +784,10 @@ // Test that the correct page is loaded if the scanner result is a URL which is // then manually edited. - (void)testReceivingQRScannerURLResultAndEditingTheURL { -// TODO(crbug.com/869176): Re-enable this test on iOS 10 iPad device. -#if !TARGET_IPHONE_SIMULATOR - if (!base::ios::IsRunningOnIOS11OrLater() && IsIPadIdiom()) { - EARL_GREY_TEST_DISABLED(@"Test disabled on iOS 10 iPad device."); - } -#endif - // TODO(crbug.com/753098): Re-enable this test on iOS 11 iPad once - // grey_typeText works on iOS 11. - if (base::ios::IsRunningOnIOS11OrLater() && IsIPadIdiom()) { - EARL_GREY_TEST_DISABLED(@"Test disabled on iOS 11."); + // TODO(crbug.com/753098): Re-enable this test on iPad once grey_typeText + // works. + if (IsIPadIdiom()) { + EARL_GREY_TEST_DISABLED(@"Test disabled on iPad."); } [self doTestReceivingResult:_testURL.GetContent() @@ -842,16 +804,10 @@ // Test that the correct page is loaded if the scanner result is a search query // which is then manually edited. - (void)testReceivingQRScannerSearchQueryResultAndEditingTheQuery { -// TODO(crbug.com/869176): Re-enable this test on iOS 10 iPad device. -#if !TARGET_IPHONE_SIMULATOR - if (!base::ios::IsRunningOnIOS11OrLater() && IsIPadIdiom()) { - EARL_GREY_TEST_DISABLED(@"Test disabled on iOS 10 iPad device."); - } -#endif - // TODO(crbug.com/753098): Re-enable this test on iOS 11 iPad once - // grey_typeText works on iOS 11. - if (base::ios::IsRunningOnIOS11OrLater() && IsIPadIdiom()) { - EARL_GREY_TEST_DISABLED(@"Test disabled on iOS 11."); + // TODO(crbug.com/753098): Re-enable this test on iPad once grey_typeText + // works. + if (IsIPadIdiom()) { + EARL_GREY_TEST_DISABLED(@"Test disabled on iPad."); } [self swizzleLocationBarCoordinatorLoadGURLFromLocationBar:_testQueryEdited];
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_egtest.mm b/ios/chrome/browser/ui/reading_list/reading_list_egtest.mm index d2f60c4..d243d3c 100644 --- a/ios/chrome/browser/ui/reading_list/reading_list_egtest.mm +++ b/ios/chrome/browser/ui/reading_list/reading_list_egtest.mm
@@ -788,12 +788,7 @@ TapContextMenuButtonWithA11yLabelID( IDS_IOS_READING_LIST_MARK_ALL_READ_ACTION); - if (@available(iOS 11, *)) { - // On iOS10, removing UITableView sections don't remove their header text - // from the hierarchy. - AssertHeaderNotVisible(kUnreadHeader); - } - + AssertHeaderNotVisible(kUnreadHeader); AssertAllEntriesVisible(); XCTAssertEqual(kNumberUnreadEntries + kNumberReadEntries, ModelReadSize(GetReadingListModel()));
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_table_view_controller.mm b/ios/chrome/browser/ui/reading_list/reading_list_table_view_controller.mm index 0180c8ec5..f0753dba 100644 --- a/ios/chrome/browser/ui/reading_list/reading_list_table_view_controller.mm +++ b/ios/chrome/browser/ui/reading_list/reading_list_table_view_controller.mm
@@ -138,21 +138,6 @@ if (!editing) { self.editingWithToolbarButtons = NO; if (self.needsSectionCleanupAfterEditing) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunused-variable" - // |removedSectionCount| is only used in iOS10, so unused variable - // warnings should be ignored in order to allow compilation until the - // iOS10 fix is removed. - NSUInteger removedSectionCount = [self removeEmptySections]; -#pragma clang diagnostic pop -#if !defined(__IPHONE_11_0) || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_11_0 - // The swipe-to-delete gesture on iOS 10 erroneously attempts to reload - // deleted row's section upon completion of its animation, regardless of - // whether the row was the last in the section. If the section was - // removed force a full table reload so that the updated model is used. - if (removedSectionCount && !base::ios::IsRunningOnIOS11OrLater()) - [self.tableView reloadData]; -#endif self.needsSectionCleanupAfterEditing = NO; } }
diff --git a/ios/chrome/browser/ui/recent_tabs/recent_tabs_egtest.mm b/ios/chrome/browser/ui/recent_tabs/recent_tabs_egtest.mm index e2fe73e..2dc4e83 100644 --- a/ios/chrome/browser/ui/recent_tabs/recent_tabs_egtest.mm +++ b/ios/chrome/browser/ui/recent_tabs/recent_tabs_egtest.mm
@@ -105,10 +105,7 @@ // Close the tab containing the test page and wait for the stack view to // appear. - chrome_test_util::CloseCurrentTab(); - // TODO(crbug.com/783192): ChromeEarlGrey should have a method to close the - // current tab and synchronize with the UI. - [[GREYUIThreadExecutor sharedInstance] drainUntilIdle]; + [ChromeEarlGrey closeCurrentTab]; // Open the Recent Tabs panel and check that the test page is present. OpenRecentTabsPanel(); @@ -151,7 +148,7 @@ [[EarlGrey selectElementWithMatcher:exitMatcher] performAction:grey_tap()]; // Close tab. - chrome_test_util::CloseCurrentTab(); + [ChromeEarlGrey closeCurrentTab]; } // Tests that the sign-in promo can be reloaded correctly.
diff --git a/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm b/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm index b22cecd..6175cb1 100644 --- a/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm +++ b/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm
@@ -560,29 +560,17 @@ // sessionState. // Turn Off animations since UITableViewRowAnimationNone still animates. [UIView setAnimationsEnabled:NO]; - // If iOS11+ use performBatchUpdates: instead of begin/endUpdates. - if (@available(iOS 11, *)) { - if (newSessionState == - SessionsSyncUserState::USER_SIGNED_IN_SYNC_ON_WITH_SESSIONS) { - [self.tableView performBatchUpdates:^{ - [self updateSessionSections]; - } - completion:nil]; - } else { - [self.tableView performBatchUpdates:^{ - [self updateOtherDevicesSectionForState:newSessionState]; - } - completion:nil]; - } - } else { - [self.tableView beginUpdates]; - if (newSessionState == - SessionsSyncUserState::USER_SIGNED_IN_SYNC_ON_WITH_SESSIONS) { + if (newSessionState == + SessionsSyncUserState::USER_SIGNED_IN_SYNC_ON_WITH_SESSIONS) { + [self.tableView performBatchUpdates:^{ [self updateSessionSections]; - } else { + } + completion:nil]; + } else { + [self.tableView performBatchUpdates:^{ [self updateOtherDevicesSectionForState:newSessionState]; } - [self.tableView endUpdates]; + completion:nil]; } [UIView setAnimationsEnabled:YES]; } @@ -601,16 +589,10 @@ if (!self.updatesTableView) return; - if (@available(iOS 11, *)) { - [self.tableView performBatchUpdates:^{ - [self updateRecentlyClosedSection]; - } - completion:nil]; - } else { - [self.tableView beginUpdates]; + [self.tableView performBatchUpdates:^{ [self updateRecentlyClosedSection]; - [self.tableView endUpdates]; } + completion:nil]; } - (void)setTabRestoreService:(sessions::TabRestoreService*)tabRestoreService { @@ -651,18 +633,10 @@ } } -// TODO(crbug.com/850814): Use only dynamic sizing once we stop supporting -// iOS10. - (CGFloat)tableView:(UITableView*)tableView heightForHeaderInSection:(NSInteger)section { DCHECK_EQ(tableView, self.tableView); - if (@available(iOS 11, *)) { - return UITableViewAutomaticDimension; - } else { - TableViewHeaderFooterItem* header = - [self.tableViewModel headerForSection:section]; - return [header headerHeightForWidth:self.view.bounds.size.width]; - } + return UITableViewAutomaticDimension; } - (CGFloat)tableView:(UITableView*)tableView @@ -972,14 +946,7 @@ } }; - // If iOS11+ use performBatchUpdates: instead of beginUpdates/endUpdates. - if (@available(iOS 11, *)) { - [self.tableView performBatchUpdates:tableUpdates completion:nil]; - } else { - [self.tableView beginUpdates]; - tableUpdates(); - [self.tableView endUpdates]; - } + [self.tableView performBatchUpdates:tableUpdates completion:nil]; } #pragma mark - Long press and context menus @@ -1085,21 +1052,10 @@ withRowAnimation:UITableViewRowAnimationLeft]; }; - // If iOS11+ use performBatchUpdates: instead of beginUpdates/endUpdates. - if (@available(iOS 11, *)) { - [self.tableView performBatchUpdates:tableUpdates - completion:^(BOOL) { - openTabs->DeleteForeignSession(sessionTagCopy); - }]; - } else { - [self.tableView beginUpdates]; - tableUpdates(); - // DeleteForeignSession will cause |self refreshUserState:| to be called, - // thus refreshing the TableView, running this inside the updates block will - // make sure that the tableView animations are performed in order. - openTabs->DeleteForeignSession(sessionTagCopy); - [self.tableView endUpdates]; - } + [self.tableView performBatchUpdates:tableUpdates + completion:^(BOOL) { + openTabs->DeleteForeignSession(sessionTagCopy); + }]; } #pragma mark - SigninPromoViewConsumer
diff --git a/ios/chrome/browser/ui/settings/save_passwords_collection_view_controller.mm b/ios/chrome/browser/ui/settings/save_passwords_collection_view_controller.mm index d78bc90..e022112 100644 --- a/ios/chrome/browser/ui/settings/save_passwords_collection_view_controller.mm +++ b/ios/chrome/browser/ui/settings/save_passwords_collection_view_controller.mm
@@ -508,6 +508,9 @@ - (void)onGetPasswordStoreResults: (std::vector<std::unique_ptr<autofill::PasswordForm>>&)result { + if (result.empty()) { + return; + } for (auto it = result.begin(); it != result.end(); ++it) { // PasswordForm is needed when user wants to delete the site/password. auto form = std::make_unique<autofill::PasswordForm>(**it);
diff --git a/ios/chrome/browser/ui/settings/settings_egtest.mm b/ios/chrome/browser/ui/settings/settings_egtest.mm index 2f59237..56663449 100644 --- a/ios/chrome/browser/ui/settings/settings_egtest.mm +++ b/ios/chrome/browser/ui/settings/settings_egtest.mm
@@ -614,7 +614,7 @@ [[EarlGrey selectElementWithMatcher:SettingsDoneButton()] performAction:grey_tap()]; - GREYAssert(chrome_test_util::CloseAllIncognitoTabs(), @"Tabs did not close"); + [ChromeEarlGrey closeAllIncognitoTabs]; } // Verifies the UI elements are accessible on the Settings page.
diff --git a/ios/chrome/browser/ui/settings/settings_navigation_controller.mm b/ios/chrome/browser/ui/settings/settings_navigation_controller.mm index 2e161977..1273533 100644 --- a/ios/chrome/browser/ui/settings/settings_navigation_controller.mm +++ b/ios/chrome/browser/ui/settings/settings_navigation_controller.mm
@@ -52,8 +52,7 @@ - (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; - id<LayoutGuideProvider> safeAreaLayoutGuide = - SafeAreaLayoutGuideForView(self.view); + id<LayoutGuideProvider> safeAreaLayoutGuide = self.view.safeAreaLayoutGuide; UIView* contentView = self.contentViewController.view; UIView* headerView = self.appBarViewController.headerView; contentView.translatesAutoresizingMaskIntoConstraints = NO; @@ -440,15 +439,10 @@ viewController.navigationItem.leftBarButtonItems.count == 0) { viewController.navigationItem.leftBarButtonItem = [self backButton]; } - // TODO(crbug.com/875528): This is a workaround for iOS 10.x. - if (@available(iOS 11, *)) { - // Wrap the view controller in an MDCAppBarContainerViewController if - // needed. - [super pushViewController:[self wrappedControllerIfNeeded:viewController] - animated:animated]; - } else { - [super pushViewController:viewController animated:animated]; - } + // Wrap the view controller in an MDCAppBarContainerViewController if + // needed. + [super pushViewController:[self wrappedControllerIfNeeded:viewController] + animated:animated]; } - (UIViewController*)popViewControllerAnimated:(BOOL)animated {
diff --git a/ios/chrome/browser/ui/side_swipe/card_side_swipe_view.mm b/ios/chrome/browser/ui/side_swipe/card_side_swipe_view.mm index d4fb9bf..b88881b 100644 --- a/ios/chrome/browser/ui/side_swipe/card_side_swipe_view.mm +++ b/ios/chrome/browser/ui/side_swipe/card_side_swipe_view.mm
@@ -96,12 +96,7 @@ [self addSubview:background]; [background setTranslatesAutoresizingMaskIntoConstraints:NO]; - CGFloat topInset = 0; - if (@available(iOS 11, *)) { - topInset = self.safeAreaInsets.top; - } else { - topInset = StatusBarHeight(); - } + CGFloat topInset = self.safeAreaInsets.top; self.backgroundTopConstraint = [[background topAnchor] constraintEqualToAnchor:self.topAnchor constant:-topInset]; @@ -136,12 +131,7 @@ - (void)updateConstraints { [super updateConstraints]; - CGFloat topInset = 0; - if (@available(iOS 11, *)) { - topInset = self.safeAreaInsets.top; - } else { - topInset = StatusBarHeight(); - } + CGFloat topInset = self.safeAreaInsets.top; self.backgroundTopConstraint.constant = -topInset; }
diff --git a/ios/chrome/browser/ui/tab_grid/grid/grid_view_controller.mm b/ios/chrome/browser/ui/tab_grid/grid/grid_view_controller.mm index 1f45746..fa917284 100644 --- a/ios/chrome/browser/ui/tab_grid/grid/grid_view_controller.mm +++ b/ios/chrome/browser/ui/tab_grid/grid/grid_view_controller.mm
@@ -178,7 +178,7 @@ emptyStateView.translatesAutoresizingMaskIntoConstraints = NO; [self.collectionView.backgroundView addSubview:emptyStateView]; id<LayoutGuideProvider> safeAreaGuide = - SafeAreaLayoutGuideForView(self.collectionView.backgroundView); + self.collectionView.backgroundView.safeAreaLayoutGuide; [NSLayoutConstraint activateConstraints:@[ [self.collectionView.backgroundView.centerXAnchor constraintEqualToAnchor:emptyStateView.centerXAnchor],
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_bottom_toolbar.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_bottom_toolbar.mm index f974bbc..3bd0e3fd 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_bottom_toolbar.mm +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_bottom_toolbar.mm
@@ -51,22 +51,10 @@ UIButton* trailingButton = [UIButton buttonWithType:UIButtonTypeSystem]; trailingButton.translatesAutoresizingMaskIntoConstraints = NO; - if (@available(iOS 11, *)) { - leadingButton.contentHorizontalAlignment = - UIControlContentHorizontalAlignmentLeading; - trailingButton.contentHorizontalAlignment = - UIControlContentHorizontalAlignmentTrailing; - } else if (base::i18n::IsRTL()) { - leadingButton.contentHorizontalAlignment = - UIControlContentHorizontalAlignmentRight; - trailingButton.contentHorizontalAlignment = - UIControlContentHorizontalAlignmentLeft; - } else { - leadingButton.contentHorizontalAlignment = - UIControlContentHorizontalAlignmentLeft; - trailingButton.contentHorizontalAlignment = - UIControlContentHorizontalAlignmentRight; - } + leadingButton.contentHorizontalAlignment = + UIControlContentHorizontalAlignmentLeading; + trailingButton.contentHorizontalAlignment = + UIControlContentHorizontalAlignmentTrailing; trailingButton.tintColor = UIColorFromRGB(kTabGridToolbarTextButtonColor); TabGridNewTabButton* centerButton = [TabGridNewTabButton
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_top_toolbar.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_top_toolbar.mm index 5f119f4..7bdff40 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_top_toolbar.mm +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_top_toolbar.mm
@@ -57,22 +57,10 @@ trailingButton.translatesAutoresizingMaskIntoConstraints = NO; trailingButton.tintColor = UIColorFromRGB(kTabGridToolbarTextButtonColor); - if (@available(iOS 11, *)) { - leadingButton.contentHorizontalAlignment = - UIControlContentHorizontalAlignmentLeading; - trailingButton.contentHorizontalAlignment = - UIControlContentHorizontalAlignmentTrailing; - } else if (base::i18n::IsRTL()) { - leadingButton.contentHorizontalAlignment = - UIControlContentHorizontalAlignmentRight; - trailingButton.contentHorizontalAlignment = - UIControlContentHorizontalAlignmentLeft; - } else { - leadingButton.contentHorizontalAlignment = - UIControlContentHorizontalAlignmentLeft; - trailingButton.contentHorizontalAlignment = - UIControlContentHorizontalAlignmentRight; - } + leadingButton.contentHorizontalAlignment = + UIControlContentHorizontalAlignmentLeading; + trailingButton.contentHorizontalAlignment = + UIControlContentHorizontalAlignmentTrailing; [toolbar.contentView addSubview:leadingButton]; [toolbar.contentView addSubview:trailingButton];
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_transition_egtest.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_transition_egtest.mm index f4a5a7fd..acecb42 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_transition_egtest.mm +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_transition_egtest.mm
@@ -177,15 +177,14 @@ // Tests entering the tab switcher by closing the last normal tab. - (void)testEnterSwitcherByClosingLastNormalTab { - chrome_test_util::CloseAllTabsInCurrentMode(); + [ChromeEarlGrey closeAllTabsInCurrentMode]; } // Tests entering the tab switcher by closing the last incognito tab. - (void)testEnterSwitcherByClosingLastIncognitoTab { [ChromeEarlGreyUI openNewIncognitoTab]; [GetNormalTabModel() closeAllTabs]; - - chrome_test_util::CloseAllTabsInCurrentMode(); + [ChromeEarlGrey closeAllTabsInCurrentMode]; } // Tests exiting the switcher by tapping the switcher button.
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_transition_handler.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_transition_handler.mm index 0e58ba49..8a2bc5c9 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_transition_handler.mm +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_transition_handler.mm
@@ -23,12 +23,10 @@ animationControllerForPresentedController:(UIViewController*)presented presentingController:(UIViewController*)presenting sourceController:(UIViewController*)source { - if (@available(iOS 11, *)) { - if (!UIAccessibilityIsReduceMotionEnabled() && - self.provider.selectedCellVisible) { - return [[GridToVisibleTabAnimator alloc] - initWithStateProvider:self.provider]; - } + if (!UIAccessibilityIsReduceMotionEnabled() && + self.provider.selectedCellVisible) { + return + [[GridToVisibleTabAnimator alloc] initWithStateProvider:self.provider]; } ReducedMotionAnimator* simpleAnimator = [[ReducedMotionAnimator alloc] init]; simpleAnimator.presenting = YES; @@ -37,10 +35,8 @@ - (id<UIViewControllerAnimatedTransitioning>) animationControllerForDismissedController:(UIViewController*)dismissed { - if (@available(iOS 11, *)) { - if (!UIAccessibilityIsReduceMotionEnabled()) { - return [[TabToGridAnimator alloc] initWithStateProvider:self.provider]; - } + if (!UIAccessibilityIsReduceMotionEnabled()) { + return [[TabToGridAnimator alloc] initWithStateProvider:self.provider]; } ReducedMotionAnimator* simpleAnimator = [[ReducedMotionAnimator alloc] init]; simpleAnimator.presenting = NO;
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm index 36b1a08..258fbd7 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
@@ -459,33 +459,24 @@ : 0; UIEdgeInsets inset = UIEdgeInsetsMake( self.topToolbar.intrinsicContentSize.height, 0, bottomInset, 0); - if (@available(iOS 11, *)) { - // Left and right side could be missing correct safe area - // inset upon rotation. Manually correct it. - self.remoteTabsViewController.additionalSafeAreaInsets = UIEdgeInsetsZero; - UIEdgeInsets additionalSafeArea = inset; - UIEdgeInsets safeArea = self.scrollView.safeAreaInsets; - // If Remote Tabs isn't on the screen, it will not have the right safe area - // insets. Pass down the safe area insets of the scroll view. - if (self.currentPage != TabGridPageRemoteTabs) { - additionalSafeArea.right = safeArea.right; - additionalSafeArea.left = safeArea.left; - } + // Left and right side could be missing correct safe area + // inset upon rotation. Manually correct it. + self.remoteTabsViewController.additionalSafeAreaInsets = UIEdgeInsetsZero; + UIEdgeInsets additionalSafeArea = inset; + UIEdgeInsets safeArea = self.scrollView.safeAreaInsets; + // If Remote Tabs isn't on the screen, it will not have the right safe area + // insets. Pass down the safe area insets of the scroll view. + if (self.currentPage != TabGridPageRemoteTabs) { + additionalSafeArea.right = safeArea.right; + additionalSafeArea.left = safeArea.left; + } - // Ensure that the View Controller doesn't have safe area inset that already - // covers the view's bounds. - DCHECK(!CGRectIsEmpty(UIEdgeInsetsInsetRect( - self.remoteTabsViewController.tableView.bounds, - self.remoteTabsViewController.tableView.safeAreaInsets))); - self.remoteTabsViewController.additionalSafeAreaInsets = additionalSafeArea; - } -#if !defined(__IPHONE_11_0) || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_11_0 - else { - // Must manually account for status bar in pre-iOS 11. - inset.top += self.topLayoutGuide.length; - self.remoteTabsViewController.tableView.contentInset = inset; - } -#endif + // Ensure that the View Controller doesn't have safe area inset that already + // covers the view's bounds. + DCHECK(!CGRectIsEmpty(UIEdgeInsetsInsetRect( + self.remoteTabsViewController.tableView.bounds, + self.remoteTabsViewController.tableView.safeAreaInsets))); + self.remoteTabsViewController.additionalSafeAreaInsets = additionalSafeArea; } // Sets the proper insets for the Grid ViewControllers to accomodate for the @@ -503,18 +494,10 @@ : 0; UIEdgeInsets inset = UIEdgeInsetsMake( self.topToolbar.intrinsicContentSize.height, 0, bottomInset, 0); - if (@available(iOS 11, *)) { - inset.left = self.scrollView.safeAreaInsets.left; - inset.right = self.scrollView.safeAreaInsets.right; - inset.top += self.scrollView.safeAreaInsets.top; - inset.bottom += self.scrollView.safeAreaInsets.bottom; - } -#if !defined(__IPHONE_11_0) || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_11_0 - else { - // Must manually account for status bar in pre-iOS 11. - inset.top += self.topLayoutGuide.length; - } -#endif + inset.left = self.scrollView.safeAreaInsets.left; + inset.right = self.scrollView.safeAreaInsets.right; + inset.top += self.scrollView.safeAreaInsets.top; + inset.bottom += self.scrollView.safeAreaInsets.bottom; self.incognitoTabsViewController.gridView.contentInset = inset; self.regularTabsViewController.gridView.contentInset = inset; } @@ -615,12 +598,10 @@ scrollView.scrollEnabled = YES; scrollView.pagingEnabled = YES; scrollView.delegate = self; - if (@available(iOS 11, *)) { - // Ensures that scroll view does not add additional margins based on safe - // areas. - scrollView.contentInsetAdjustmentBehavior = - UIScrollViewContentInsetAdjustmentNever; - } + // Ensures that scroll view does not add additional margins based on safe + // areas. + scrollView.contentInsetAdjustmentBehavior = + UIScrollViewContentInsetAdjustmentNever; UIView* contentView = [[UIView alloc] init]; contentView.translatesAutoresizingMaskIntoConstraints = NO; [scrollView addSubview:contentView]; @@ -761,22 +742,10 @@ ]; [NSLayoutConstraint activateConstraints:constraints]; // Set the height of the toolbar, including unsafe areas. - if (@available(iOS 11, *)) { - // SafeArea is only available in iOS 11+. - [topToolbar.bottomAnchor - constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor - constant:topToolbar.intrinsicContentSize.height] - .active = YES; - } -#if !defined(__IPHONE_11_0) || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_11_0 - else { - // Top and bottom layout guides are deprecated starting in iOS 11. - [topToolbar.bottomAnchor - constraintEqualToAnchor:self.topLayoutGuide.bottomAnchor - constant:topToolbar.intrinsicContentSize.height] - .active = YES; - } -#endif + [topToolbar.bottomAnchor + constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor + constant:topToolbar.intrinsicContentSize.height] + .active = YES; } // Adds the bottom toolbar and sets constraints. @@ -794,22 +763,10 @@ ]; [NSLayoutConstraint activateConstraints:constraints]; // Adds the height of the toolbar above the bottom safe area. - if (@available(iOS 11, *)) { - // SafeArea is only available in iOS 11+. - [self.view.safeAreaLayoutGuide.bottomAnchor - constraintEqualToAnchor:bottomToolbar.topAnchor - constant:bottomToolbar.intrinsicContentSize.height] - .active = YES; - } -#if !defined(__IPHONE_11_0) || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_11_0 - else { - // Top and bottom layout guides are deprecated starting in iOS 11. - [bottomToolbar.topAnchor - constraintEqualToAnchor:self.bottomLayoutGuide.topAnchor - constant:-bottomToolbar.intrinsicContentSize.height] - .active = YES; - } -#endif + [self.view.safeAreaLayoutGuide.bottomAnchor + constraintEqualToAnchor:bottomToolbar.topAnchor + constant:bottomToolbar.intrinsicContentSize.height] + .active = YES; } // Adds floating button and constraints. @@ -828,7 +785,7 @@ UIUserInterfaceSizeClassRegular) { verticalInset = kTabGridFloatingButtonVerticalInsetLarge; } - id<LayoutGuideProvider> safeAreaGuide = SafeAreaLayoutGuideForView(self.view); + id<LayoutGuideProvider> safeAreaGuide = self.view.safeAreaLayoutGuide; [NSLayoutConstraint activateConstraints:@[ [button.trailingAnchor constraintEqualToAnchor:safeAreaGuide.trailingAnchor
diff --git a/ios/chrome/browser/ui/table_view/chrome_table_view_controller.mm b/ios/chrome/browser/ui/table_view/chrome_table_view_controller.mm index d91b29a..608ccd89 100644 --- a/ios/chrome/browser/ui/table_view/chrome_table_view_controller.mm +++ b/ios/chrome/browser/ui/table_view/chrome_table_view_controller.mm
@@ -153,16 +153,7 @@ - (void)performBatchTableViewUpdates:(void (^)(void))updates completion:(void (^)(BOOL finished))completion { - if (@available(iOS 11, *)) { - [self.tableView performBatchUpdates:updates completion:completion]; - } else { - [self.tableView beginUpdates]; - if (updates) - updates(); - [self.tableView endUpdates]; - if (completion) - completion(YES); - } + [self.tableView performBatchUpdates:updates completion:completion]; } - (void)removeFromModelItemAtIndexPaths:(NSArray<NSIndexPath*>*)indexPaths {
diff --git a/ios/chrome/browser/ui/table_view/table_view_presentation_controller.mm b/ios/chrome/browser/ui/table_view/table_view_presentation_controller.mm index 4eadca8..8eb5b47 100644 --- a/ios/chrome/browser/ui/table_view/table_view_presentation_controller.mm +++ b/ios/chrome/browser/ui/table_view/table_view_presentation_controller.mm
@@ -65,12 +65,8 @@ @synthesize tableViewContainer = _tableViewContainer; - (CGRect)frameOfPresentedViewInContainerView { - CGRect safeAreaBounds = self.containerView.bounds; - UIEdgeInsets safeAreaInsets = UIEdgeInsetsZero; - if (@available(iOS 11, *)) { - safeAreaBounds = self.containerView.safeAreaLayoutGuide.layoutFrame; - safeAreaInsets = self.containerView.safeAreaInsets; - } + CGRect safeAreaBounds = self.containerView.safeAreaLayoutGuide.layoutFrame; + UIEdgeInsets safeAreaInsets = self.containerView.safeAreaInsets; CGFloat safeAreaWidth = CGRectGetWidth(safeAreaBounds); CGFloat safeAreaHeight = CGRectGetHeight(safeAreaBounds);
diff --git a/ios/chrome/browser/ui/tabs/tab_view.mm b/ios/chrome/browser/ui/tabs/tab_view.mm index 54c0647..3ae798b 100644 --- a/ios/chrome/browser/ui/tabs/tab_view.mm +++ b/ios/chrome/browser/ui/tabs/tab_view.mm
@@ -144,11 +144,9 @@ forControlEvents:UIControlEventTouchUpInside]; if (DragAndDropIsEnabled()) { - if (@available(iOS 11, *)) { - _dropInteraction = - [[DropAndNavigateInteraction alloc] initWithDelegate:self]; - [self addInteraction:_dropInteraction]; - } + _dropInteraction = + [[DropAndNavigateInteraction alloc] initWithDelegate:self]; + [self addInteraction:_dropInteraction]; } } return self;
diff --git a/ios/chrome/browser/ui/toolbar/adaptive_toolbar_egtest.mm b/ios/chrome/browser/ui/toolbar/adaptive_toolbar_egtest.mm index 4ebbe7b8..462424bd 100644 --- a/ios/chrome/browser/ui/toolbar/adaptive_toolbar_egtest.mm +++ b/ios/chrome/browser/ui/toolbar/adaptive_toolbar_egtest.mm
@@ -604,10 +604,7 @@ [window convertRect:element.frame fromView:element.superview]); CGFloat bottomSafeArea = CGFLOAT_MAX; - if (@available(iOS 11, *)) { - bottomSafeArea = - CGRectGetMaxY(window.safeAreaLayoutGuide.layoutFrame); - } + bottomSafeArea = CGRectGetMaxY(window.safeAreaLayoutGuide.layoutFrame); CGFloat infobarContentBottomPoint = MIN(bottomSafeArea, toolbarTopPoint); BOOL buttonIsAbove = buttonBottomPoint < infobarContentBottomPoint - 10;
diff --git a/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_delegate.h b/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_delegate.h index a6068f5..beb3d56 100644 --- a/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_delegate.h +++ b/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_delegate.h
@@ -5,7 +5,7 @@ #ifndef IOS_CHROME_BROWSER_UI_TOOLBAR_KEYBOARD_ASSIST_TOOLBAR_ASSISTIVE_KEYBOARD_DELEGATE_H_ #define IOS_CHROME_BROWSER_UI_TOOLBAR_KEYBOARD_ASSIST_TOOLBAR_ASSISTIVE_KEYBOARD_DELEGATE_H_ -#import <UIKit/UIKIt.h> +#import <UIKit/UIKit.h> @protocol ApplicationCommands; @protocol BrowserCommands;
diff --git a/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_views.h b/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_views.h index dddf1f85..c4874de 100644 --- a/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_views.h +++ b/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_views.h
@@ -5,7 +5,7 @@ #ifndef IOS_CHROME_BROWSER_UI_TOOLBAR_KEYBOARD_ASSIST_TOOLBAR_ASSISTIVE_KEYBOARD_VIEWS_H_ #define IOS_CHROME_BROWSER_UI_TOOLBAR_KEYBOARD_ASSIST_TOOLBAR_ASSISTIVE_KEYBOARD_VIEWS_H_ -#import <UIKit/UIKIt.h> +#import <UIKit/UIKit.h> @protocol ToolbarAssistiveKeyboardDelegate;
diff --git a/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_views_utils.h b/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_views_utils.h index c24dbe4..311bc508 100644 --- a/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_views_utils.h +++ b/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_views_utils.h
@@ -5,7 +5,7 @@ #ifndef IOS_CHROME_BROWSER_UI_TOOLBAR_KEYBOARD_ASSIST_TOOLBAR_ASSISTIVE_KEYBOARD_VIEWS_UTILS_H_ #define IOS_CHROME_BROWSER_UI_TOOLBAR_KEYBOARD_ASSIST_TOOLBAR_ASSISTIVE_KEYBOARD_VIEWS_UTILS_H_ -#import <UIKit/UIKIt.h> +#import <UIKit/UIKit.h> @protocol ToolbarAssistiveKeyboardDelegate;
diff --git a/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_input_assistant_items.h b/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_input_assistant_items.h index 6bc31c4..2ed3671 100644 --- a/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_input_assistant_items.h +++ b/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_input_assistant_items.h
@@ -5,7 +5,7 @@ #ifndef IOS_CHROME_BROWSER_UI_TOOLBAR_KEYBOARD_ASSIST_TOOLBAR_INPUT_ASSISTANT_ITEMS_H_ #define IOS_CHROME_BROWSER_UI_TOOLBAR_KEYBOARD_ASSIST_TOOLBAR_INPUT_ASSISTANT_ITEMS_H_ -#import <UIKit/UIKIt.h> +#import <UIKit/UIKit.h> @protocol ToolbarAssistiveKeyboardDelegate;
diff --git a/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_keyboard_accessory_view.h b/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_keyboard_accessory_view.h index 6af5def..2cff181 100644 --- a/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_keyboard_accessory_view.h +++ b/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_keyboard_accessory_view.h
@@ -5,7 +5,7 @@ #ifndef IOS_CHROME_BROWSER_UI_TOOLBAR_KEYBOARD_ASSIST_TOOLBAR_KEYBOARD_ACCESSORY_VIEW_H_ #define IOS_CHROME_BROWSER_UI_TOOLBAR_KEYBOARD_ASSIST_TOOLBAR_KEYBOARD_ACCESSORY_VIEW_H_ -#import <UIKit/UIKIt.h> +#import <UIKit/UIKit.h> #import "ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_assistive_keyboard_delegate.h"
diff --git a/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_keyboard_accessory_view.mm b/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_keyboard_accessory_view.mm index 9c68bb8..e007b79 100644 --- a/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_keyboard_accessory_view.mm +++ b/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_keyboard_accessory_view.mm
@@ -86,7 +86,7 @@ [self addSubview:searchStackView]; // Position the stack views. - id<LayoutGuideProvider> layoutGuide = SafeAreaLayoutGuideForView(self); + id<LayoutGuideProvider> layoutGuide = self.safeAreaLayoutGuide; [NSLayoutConstraint activateConstraints:@[ [searchStackView.leadingAnchor constraintEqualToAnchor:layoutGuide.leadingAnchor
diff --git a/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_ui_bar_button_item.h b/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_ui_bar_button_item.h index fbcfcb61..3658ed1 100644 --- a/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_ui_bar_button_item.h +++ b/ios/chrome/browser/ui/toolbar/keyboard_assist/toolbar_ui_bar_button_item.h
@@ -5,7 +5,7 @@ #ifndef IOS_CHROME_BROWSER_UI_TOOLBAR_KEYBOARD_ASSIST_TOOLBAR_UI_BAR_BUTTON_ITEM_H_ #define IOS_CHROME_BROWSER_UI_TOOLBAR_KEYBOARD_ASSIST_TOOLBAR_UI_BAR_BUTTON_ITEM_H_ -#import <UIKit/UIKIt.h> +#import <UIKit/UIKit.h> @protocol ToolbarAssistiveKeyboardDelegate;
diff --git a/ios/chrome/browser/ui/toolbar/primary_toolbar_view.mm b/ios/chrome/browser/ui/toolbar/primary_toolbar_view.mm index b726e650..c89d0ca 100644 --- a/ios/chrome/browser/ui/toolbar/primary_toolbar_view.mm +++ b/ios/chrome/browser/ui/toolbar/primary_toolbar_view.mm
@@ -308,7 +308,7 @@ // Sets the constraints up. - (void)setUpConstraints { - id<LayoutGuideProvider> safeArea = SafeAreaLayoutGuideForView(self); + id<LayoutGuideProvider> safeArea = self.safeAreaLayoutGuide; self.expandedConstraints = [NSMutableArray array]; self.contractedConstraints = [NSMutableArray array]; self.contractedNoMarginConstraints = [NSMutableArray array]; @@ -324,18 +324,6 @@ constraintEqualToConstant:kAdaptiveToolbarButtonHeight], ]]; - // When switching between incognito and non-incognito BVCs, it is possible for - // all of the toolbar's buttons to be temporarily hidden, which results in the - // stack view having zero width. This seems to permanently break autolayout - // on iOS 10. Adding an optional width constraint seems to work around this - // issue. See https://crbug.com/851954. - if (!base::ios::IsRunningOnIOS11OrLater()) { - NSLayoutConstraint* minWidthConstraint = - [self.leadingStackView.widthAnchor constraintEqualToConstant:1.0]; - minWidthConstraint.priority = UILayoutPriorityDefaultLow; - minWidthConstraint.active = YES; - } - // LocationBar constraints. The constant value is set by the VC. self.locationBarHeight = [self.locationBarContainer.heightAnchor constraintEqualToConstant:0];
diff --git a/ios/chrome/browser/ui/toolbar/secondary_toolbar_view.mm b/ios/chrome/browser/ui/toolbar/secondary_toolbar_view.mm index b6ad656..a5660c05 100644 --- a/ios/chrome/browser/ui/toolbar/secondary_toolbar_view.mm +++ b/ios/chrome/browser/ui/toolbar/secondary_toolbar_view.mm
@@ -140,7 +140,7 @@ self.stackView.translatesAutoresizingMaskIntoConstraints = NO; [contentView addSubview:self.stackView]; - id<LayoutGuideProvider> safeArea = SafeAreaLayoutGuideForView(self); + id<LayoutGuideProvider> safeArea = self.safeAreaLayoutGuide; [NSLayoutConstraint activateConstraints:@[ [self.stackView.leadingAnchor
diff --git a/ios/chrome/browser/ui/toolbar/toolbar_egtest.mm b/ios/chrome/browser/ui/toolbar/toolbar_egtest.mm index a55d4ca..a9d2824 100644 --- a/ios/chrome/browser/ui/toolbar/toolbar_egtest.mm +++ b/ios/chrome/browser/ui/toolbar/toolbar_egtest.mm
@@ -150,11 +150,9 @@ EARL_GREY_TEST_SKIPPED(@"Test not support on iPhone"); } - // TODO(crbug.com/753098): Re-enable this test on iOS 11 iPad once - // grey_typeText works on iOS 11. - if (base::ios::IsRunningOnIOS11OrLater()) { - EARL_GREY_TEST_DISABLED(@"Test disabled on iOS 11."); - } + // TODO(crbug.com/753098): Re-enable this test on iPad once grey_typeText + // works on iOS 11. + EARL_GREY_TEST_DISABLED(@"Test disabled on iPad."); const GURL URL = web::test::HttpServer::MakeUrl("http://origin"); @@ -249,46 +247,37 @@ [[EarlGrey selectElementWithMatcher:chrome_test_util::Omnibox()] assertWithMatcher:chrome_test_util::OmniboxText(URL.GetContent())]; - if (base::ios::IsRunningOnIOS11OrLater()) { - // Can't access share menu from xctest on iOS 11+, so use the text field - // callout bar instead. - if (IsRefreshLocationBarEnabled()) { - [[EarlGrey - selectElementWithMatcher:chrome_test_util::DefocusedLocationView()] - performAction:grey_tap()]; - } else { - [[EarlGrey selectElementWithMatcher:chrome_test_util::Omnibox()] - performAction:grey_tap()]; - } - // Tap twice to get the pre-edit label callout bar copy button. + // Can't access share menu from xctest on iOS 11+, so use the text field + // callout bar instead. + if (IsRefreshLocationBarEnabled()) { [[EarlGrey - selectElementWithMatcher:grey_allOf( - grey_ancestor(chrome_test_util::Omnibox()), - grey_kindOfClass([UILabel class]), nil)] + selectElementWithMatcher:chrome_test_util::DefocusedLocationView()] + performAction:grey_tap()]; + } else { + [[EarlGrey selectElementWithMatcher:chrome_test_util::Omnibox()] + performAction:grey_tap()]; + } + // Tap twice to get the pre-edit label callout bar copy button. + [[EarlGrey + selectElementWithMatcher:grey_allOf( + grey_ancestor(chrome_test_util::Omnibox()), + grey_kindOfClass([UILabel class]), nil)] + performAction:grey_tap()]; + + [[[EarlGrey selectElementWithMatcher:SystemSelectionCalloutCopyButton()] + inRoot:SystemSelectionCallout()] performAction:grey_tap()]; + + if (IsIPadIdiom()) { + [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Typing Shield")] performAction:grey_tap()]; - [[[EarlGrey selectElementWithMatcher:SystemSelectionCalloutCopyButton()] - inRoot:SystemSelectionCallout()] performAction:grey_tap()]; - - if (IsIPadIdiom()) { - [[EarlGrey - selectElementWithMatcher:grey_accessibilityID(@"Typing Shield")] - performAction:grey_tap()]; - - } else { - // Typing shield might be unavailable if there are any suggestions - // displayed in the popup. - [[EarlGrey - selectElementWithMatcher: - grey_accessibilityID(kToolbarCancelOmniboxEditButtonIdentifier)] - performAction:grey_tap()]; - } - } else { - [ChromeEarlGreyUI openShareMenu]; + // Typing shield might be unavailable if there are any suggestions + // displayed in the popup. [[EarlGrey - selectElementWithMatcher:chrome_test_util::ButtonWithAccessibilityLabel( - @"Copy")] performAction:grey_tap()]; + selectElementWithMatcher:grey_accessibilityID( + kToolbarCancelOmniboxEditButtonIdentifier)] + performAction:grey_tap()]; } [ChromeEarlGrey loadURL:secondURL]; @@ -307,10 +296,10 @@ // Verifies that the clear text button clears any text in the omnibox. - (void)testOmniboxClearTextButton { - // TODO(crbug.com/753098): Re-enable this test on iOS 11 iPad once - // grey_typeText works on iOS 11. - if (base::ios::IsRunningOnIOS11OrLater() && IsIPadIdiom()) { - EARL_GREY_TEST_DISABLED(@"Test disabled on iOS 11."); + // TODO(crbug.com/753098): Re-enable this test on iPad once grey_typeText + // works. + if (IsIPadIdiom()) { + EARL_GREY_TEST_DISABLED(@"Test disabled on iPad."); } const GURL URL = web::test::HttpServer::MakeUrl("http://origin");
diff --git a/ios/chrome/browser/ui/toolbar_container/toolbar_container_view_controller.mm b/ios/chrome/browser/ui/toolbar_container/toolbar_container_view_controller.mm index 2e44a37..cad0e31 100644 --- a/ios/chrome/browser/ui/toolbar_container/toolbar_container_view_controller.mm +++ b/ios/chrome/browser/ui/toolbar_container/toolbar_container_view_controller.mm
@@ -342,22 +342,11 @@ // Adds additional height to the first toolbar to account for the safe area. - (void)updateForSafeArea { - if (@available(iOS 11, *)) { - if (self.orientation == ToolbarContainerOrientation::kTopToBottom) { - self.additionalStackHeight = self.view.safeAreaInsets.top; - } else { - self.additionalStackHeight = self.view.safeAreaInsets.bottom; - } + if (self.orientation == ToolbarContainerOrientation::kTopToBottom) { + self.additionalStackHeight = self.view.safeAreaInsets.top; + } else { + self.additionalStackHeight = self.view.safeAreaInsets.bottom; } -#if !defined(__IPHONE_11_0) || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_11_0 - else { - if (self.orientation == ToolbarContainerOrientation::kTopToBottom) { - self.additionalStackHeight = self.topLayoutGuide.length; - } else { - self.additionalStackHeight = self.bottomLayoutGuide.length; - } - } -#endif } @end
diff --git a/ios/chrome/browser/ui/toolbar_container/toolbar_container_view_controller_unittest.mm b/ios/chrome/browser/ui/toolbar_container/toolbar_container_view_controller_unittest.mm index 2ac5f2e..80871a41 100644 --- a/ios/chrome/browser/ui/toolbar_container/toolbar_container_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/toolbar_container/toolbar_container_view_controller_unittest.mm
@@ -129,32 +129,12 @@ view_controller_.orientation = IsTopToBottom() ? ToolbarContainerOrientation::kTopToBottom : ToolbarContainerOrientation::kBottomToTop; - if (@available(iOS 11, *)) { - UIEdgeInsets safe_insets = container_view().safeAreaInsets; - if (IsTopToBottom()) - safe_insets.top = kSafeAreaStackInset - safe_insets.top; - else - safe_insets.bottom = kSafeAreaStackInset - safe_insets.bottom; - view_controller_.additionalSafeAreaInsets = safe_insets; - } -#if !defined(__IPHONE_11_0) || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_11_0 - else { - // Deactivate all pre-existing constraints for the |guide|'s height. - // They are added by UIKit at the maximum priority, so must be removed to - // update |guide|'s length. - id<UILayoutSupport> guide = IsTopToBottom() - ? view_controller_.topLayoutGuide - : view_controller_.bottomLayoutGuide; - for (NSLayoutConstraint* constraint in container_view().constraints) { - if (constraint.firstItem == guide && - constraint.firstAttribute == NSLayoutAttributeHeight) { - constraint.active = NO; - } - } - [guide.heightAnchor constraintEqualToConstant:kSafeAreaStackInset] - .active = YES; - } -#endif + UIEdgeInsets safe_insets = container_view().safeAreaInsets; + if (IsTopToBottom()) + safe_insets.top = kSafeAreaStackInset - safe_insets.top; + else + safe_insets.bottom = kSafeAreaStackInset - safe_insets.bottom; + view_controller_.additionalSafeAreaInsets = safe_insets; } // Adds collapsible or non-collapsible toolbars to the container, depending on
diff --git a/ios/chrome/browser/ui/util/uikit_ui_util.h b/ios/chrome/browser/ui/util/uikit_ui_util.h index 570f5e2f..1ba54b1 100644 --- a/ios/chrome/browser/ui/util/uikit_ui_util.h +++ b/ios/chrome/browser/ui/util/uikit_ui_util.h
@@ -250,9 +250,6 @@ // |type| represent the type of notification associated with this feedback. void TriggerHapticFeedbackForNotification(UINotificationFeedbackType type); -// Returns the safeAreaInsets for a given view. -UIEdgeInsets SafeAreaInsetsForView(UIView* view); - // Returns the text for tabs count to be displayed in toolbar and tab_grid. // As an easter egg, show a smiley face instead of the count if the user has // more than 99 tabs open.
diff --git a/ios/chrome/browser/ui/util/uikit_ui_util.mm b/ios/chrome/browser/ui/util/uikit_ui_util.mm index 33f0553..bb969d8 100644 --- a/ios/chrome/browser/ui/util/uikit_ui_util.mm +++ b/ios/chrome/browser/ui/util/uikit_ui_util.mm
@@ -131,12 +131,8 @@ } void SetUILabelScaledFont(UILabel* label, UIFont* font) { - if (@available(iOS 11, *)) { - label.font = [[UIFontMetrics defaultMetrics] scaledFontForFont:font]; - label.adjustsFontForContentSizeCategory = YES; - } else { - label.font = font; - } + label.font = [[UIFontMetrics defaultMetrics] scaledFontForFont:font]; + label.adjustsFontForContentSizeCategory = YES; } void MaybeSetUILabelScaledFont(BOOL maybe, UILabel* label, UIFont* font) { @@ -148,12 +144,8 @@ } void SetUITextFieldScaledFont(UITextField* textField, UIFont* font) { - if (@available(iOS 11, *)) { - textField.font = [[UIFontMetrics defaultMetrics] scaledFontForFont:font]; - textField.adjustsFontForContentSizeCategory = YES; - } else { - textField.font = font; - } + textField.font = [[UIFontMetrics defaultMetrics] scaledFontForFont:font]; + textField.adjustsFontForContentSizeCategory = YES; } void MaybeSetUITextFieldScaledFont(BOOL maybe, @@ -649,13 +641,12 @@ } UIResponder* GetFirstResponder() { + DCHECK_CURRENTLY_ON(web::WebThread::UI); UIApplication* application = [UIApplication sharedApplication]; - if (base::ios::IsRunningOnIOS11OrLater() && - base::FeatureList::IsEnabled(kFirstResponderKeyWindow)) { + if (base::FeatureList::IsEnabled(kFirstResponderKeyWindow)) { return GetFirstResponderSubview(application.keyWindow); } - DCHECK_CURRENTLY_ON(web::WebThread::UI); DCHECK(!gFirstResponder); [application sendAction:@selector(cr_markSelfCurrentFirstResponder) to:nil @@ -715,14 +706,6 @@ } } -UIEdgeInsets SafeAreaInsetsForView(UIView* view) { - if (@available(iOS 11, *)) { - return view.safeAreaInsets; - } else { - return UIEdgeInsetsZero; - } -} - NSString* TextForTabCount(long count) { if (count <= 0) return @"";
diff --git a/ios/chrome/browser/web/cache_egtest.mm b/ios/chrome/browser/web/cache_egtest.mm index 8e8b64d..94a3626 100644 --- a/ios/chrome/browser/web/cache_egtest.mm +++ b/ios/chrome/browser/web/cache_egtest.mm
@@ -190,10 +190,10 @@ // Tests that cache is not used when selecting omnibox suggested website, even // though cache for that website exists. - (void)testCachingBehaviorOnSelectOmniboxSuggestion { - // TODO(crbug.com/753098): Re-enable this test on iOS 11 iPad once - // grey_typeText works on iOS 11. - if (base::ios::IsRunningOnIOS11OrLater() && IsIPadIdiom()) { - EARL_GREY_TEST_DISABLED(@"Test disabled on iOS 11."); + // TODO(crbug.com/753098): Re-enable this test on iPad once grey_typeText + // works. + if (IsIPadIdiom()) { + EARL_GREY_TEST_DISABLED(@"Test disabled on iPad."); } web::test::SetUpHttpServer(std::make_unique<CacheTestResponseProvider>());
diff --git a/ios/chrome/browser/web/window_open_by_dom_egtest.mm b/ios/chrome/browser/web/window_open_by_dom_egtest.mm index 9124030..2c5c2d84 100644 --- a/ios/chrome/browser/web/window_open_by_dom_egtest.mm +++ b/ios/chrome/browser/web/window_open_by_dom_egtest.mm
@@ -266,7 +266,7 @@ [ChromeEarlGrey waitForMainTabCount:2]; // Ensure that the starting tab hasn't navigated. - chrome_test_util::CloseCurrentTab(); + [ChromeEarlGrey closeCurrentTab]; const GURL URL = HttpServer::MakeUrl(kTestURL); [[EarlGrey selectElementWithMatcher:OmniboxText(URL.GetContent())] assertWithMatcher:grey_notNil()];
diff --git a/ios/chrome/common/ui_util/BUILD.gn b/ios/chrome/common/ui_util/BUILD.gn index a2aba112..07f5302 100644 --- a/ios/chrome/common/ui_util/BUILD.gn +++ b/ios/chrome/common/ui_util/BUILD.gn
@@ -12,19 +12,3 @@ ] configs += [ "//build/config/compiler:enable_arc" ] } - -source_set("unit_tests") { - configs += [ "//build/config/compiler:enable_arc" ] - testonly = true - sources = [ - "constraints_ui_util_unittest.mm", - ] - deps = [ - ":ui_util", - "//base", - "//ios/third_party/material_components_ios", - "//ios/third_party/material_roboto_font_loader_ios", - "//testing/gtest", - "//url", - ] -}
diff --git a/ios/chrome/common/ui_util/constraints_ui_util.h b/ios/chrome/common/ui_util/constraints_ui_util.h index e7a8616..9069c88 100644 --- a/ios/chrome/common/ui_util/constraints_ui_util.h +++ b/ios/chrome/common/ui_util/constraints_ui_util.h
@@ -176,7 +176,4 @@ #pragma mark - Safe Area. -// Returns a safeAreaLayoutGuide for a given view. -id<LayoutGuideProvider> SafeAreaLayoutGuideForView(UIView* view); - #endif // IOS_CHROME_COMMON_UI_UTIL_CONSTRAINTS_UI_UTIL_H_
diff --git a/ios/chrome/common/ui_util/constraints_ui_util.mm b/ios/chrome/common/ui_util/constraints_ui_util.mm index 3d81c3c..fc110529 100644 --- a/ios/chrome/common/ui_util/constraints_ui_util.mm +++ b/ios/chrome/common/ui_util/constraints_ui_util.mm
@@ -101,17 +101,7 @@ } void PinToSafeArea(id<LayoutGuideProvider> innerView, UIView* outerView) { - id<LayoutGuideProvider> outerSafeAreaGuide = - SafeAreaLayoutGuideForView(outerView); - AddSameConstraints(innerView, outerSafeAreaGuide); -} - -id<LayoutGuideProvider> SafeAreaLayoutGuideForView(UIView* view) { - if (@available(iOS 11, *)) { - return view.safeAreaLayoutGuide; - } else { - return view; - } + AddSameConstraints(innerView, outerView.safeAreaLayoutGuide); } void AddSameConstraintsToSides(id<LayoutGuideProvider> view1,
diff --git a/ios/chrome/common/ui_util/constraints_ui_util_unittest.mm b/ios/chrome/common/ui_util/constraints_ui_util_unittest.mm deleted file mode 100644 index 8267e83..0000000 --- a/ios/chrome/common/ui_util/constraints_ui_util_unittest.mm +++ /dev/null
@@ -1,28 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/common/ui_util/constraints_ui_util.h" - -#include "testing/gtest/include/gtest/gtest.h" -#include "testing/gtest_mac.h" -#include "testing/platform_test.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -namespace { - -using ConstraintsUIUtilTest = PlatformTest; - -// Tests that SafeAreaLayoutGuideForView returns self on iOS 10. -TEST_F(ConstraintsUIUtilTest, SafeAreaLayoutGuideForView) { - if (@available(iOS 11, *)) { - } else { - UIView* view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; - EXPECT_EQ(view, SafeAreaLayoutGuideForView(view)); - } -} - -} // namespace
diff --git a/ios/chrome/test/earl_grey/chrome_earl_grey.h b/ios/chrome/test/earl_grey/chrome_earl_grey.h index caae9d15..1c3e4235 100644 --- a/ios/chrome/test/earl_grey/chrome_earl_grey.h +++ b/ios/chrome/test/earl_grey/chrome_earl_grey.h
@@ -64,6 +64,17 @@ // Opens a new incognito tab and waits for the new tab animation to complete. + (void)openNewIncognitoTab; +// Closes all tabs in the current mode (incognito or normal), and waits for the +// UI to complete. If current mode is Incognito, mode will be switched to +// normal after closing all tabs. ++ (void)closeAllTabsInCurrentMode; + +// Closes all incognito tabs and waits for the UI to complete. ++ (void)closeAllIncognitoTabs; + +// Closes the current tab and waits for the UI to complete. ++ (void)closeCurrentTab; + // Waits for the page to finish loading within a timeout, or a GREYAssert is // induced. + (void)waitForPageToFinishLoading;
diff --git a/ios/chrome/test/earl_grey/chrome_earl_grey.mm b/ios/chrome/test/earl_grey/chrome_earl_grey.mm index b5712fe..3f4d15d 100644 --- a/ios/chrome/test/earl_grey/chrome_earl_grey.mm +++ b/ios/chrome/test/earl_grey/chrome_earl_grey.mm
@@ -143,6 +143,21 @@ [[GREYUIThreadExecutor sharedInstance] drainUntilIdle]; } ++ (void)closeAllTabsInCurrentMode { + chrome_test_util::CloseAllTabsInCurrentMode(); + [[GREYUIThreadExecutor sharedInstance] drainUntilIdle]; +} + ++ (void)closeAllIncognitoTabs { + GREYAssert(chrome_test_util::CloseAllIncognitoTabs(), @"Tabs did not close"); + [[GREYUIThreadExecutor sharedInstance] drainUntilIdle]; +} + ++ (void)closeCurrentTab { + chrome_test_util::CloseCurrentTab(); + [[GREYUIThreadExecutor sharedInstance] drainUntilIdle]; +} + + (void)waitForPageToFinishLoading { GREYAssert(chrome_test_util::WaitForPageToFinishLoading(), @"Page did not complete loading.");
diff --git a/ios/showcase/payments/sc_payments_picker_egtest.mm b/ios/showcase/payments/sc_payments_picker_egtest.mm index 801a639..1741bdf 100644 --- a/ios/showcase/payments/sc_payments_picker_egtest.mm +++ b/ios/showcase/payments/sc_payments_picker_egtest.mm
@@ -136,10 +136,10 @@ // Tests if filtering works. - (void)testVerifyFiltering { - // TODO(crbug.com/753098): Re-enable this test on iOS 11 iPad once - // grey_typeText works on iOS 11. - if (base::ios::IsRunningOnIOS11OrLater() && IsIPadIdiom()) { - EARL_GREY_TEST_DISABLED(@"Test disabled on iOS 11."); + // TODO(crbug.com/753098): Re-enable this test on iPad once grey_typeText + // works. + if (IsIPadIdiom()) { + EARL_GREY_TEST_DISABLED(@"Test disabled on iPad."); } [self scrollToTop];
diff --git a/ios/showcase/test/showcase_eg_utils.mm b/ios/showcase/test/showcase_eg_utils.mm index d86ec76..6b44ab5 100644 --- a/ios/showcase/test/showcase_eg_utils.mm +++ b/ios/showcase/test/showcase_eg_utils.mm
@@ -16,17 +16,9 @@ // Matcher for the back button on screens presented from the Showcase home // screen. id<GREYMatcher> BackButton() { - // TODO(crbug.com/750185): The original matcher fails on IOS 11 because the - // private class is not used anymore. Find a more robust solution that is - // consistent across different iOS versions. - if (base::ios::IsRunningOnIOS11OrLater()) { - return grey_allOf(grey_accessibilityLabel(@"SC"), - grey_accessibilityTrait(UIAccessibilityTraitButton), - grey_userInteractionEnabled(), nil); - } - - return grey_kindOfClass( - NSClassFromString(@"_UINavigationBarBackIndicatorView")); + return grey_allOf(grey_accessibilityLabel(@"SC"), + grey_accessibilityTrait(UIAccessibilityTraitButton), + grey_userInteractionEnabled(), nil); } // Matcher for the Showcase home screen view.
diff --git a/ios/web/net/cookies/wk_http_system_cookie_store.h b/ios/web/net/cookies/wk_http_system_cookie_store.h index 664e8bc..bd98c54 100644 --- a/ios/web/net/cookies/wk_http_system_cookie_store.h +++ b/ios/web/net/cookies/wk_http_system_cookie_store.h
@@ -6,7 +6,7 @@ #define IOS_WEB_NET_COOKIES_WK_HTTP_SYSTEM_COOKIE_STORE_H_ #import <Foundation/Foundation.h> -#import <WebKit/Webkit.h> +#import <WebKit/WebKit.h> #import "ios/net/cookies/system_cookie_store.h"
diff --git a/ios/web/net/cookies/wk_http_system_cookie_store_unittest.mm b/ios/web/net/cookies/wk_http_system_cookie_store_unittest.mm index 0f25ec1..ad1c1da2 100644 --- a/ios/web/net/cookies/wk_http_system_cookie_store_unittest.mm +++ b/ios/web/net/cookies/wk_http_system_cookie_store_unittest.mm
@@ -5,7 +5,7 @@ #import "ios/web/net/cookies/wk_http_system_cookie_store.h" #import <Foundation/Foundation.h> -#import <WebKit/Webkit.h> +#import <WebKit/WebKit.h> #include <memory>
diff --git a/media/gpu/jpeg_encode_accelerator_unittest.cc b/media/gpu/jpeg_encode_accelerator_unittest.cc index bcdd1fea..893d3644d 100644 --- a/media/gpu/jpeg_encode_accelerator_unittest.cc +++ b/media/gpu/jpeg_encode_accelerator_unittest.cc
@@ -1,11 +1,6 @@ // 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. - -// This has to be included first. -// See http://code.google.com/p/googletest/issues/detail?id=371 -#include "testing/gtest/include/gtest/gtest.h" - #include <stddef.h> #include <stdint.h> #include <string.h> @@ -34,6 +29,7 @@ #include "media/gpu/test/video_accelerator_unittest_helpers.h" #include "media/video/jpeg_encode_accelerator.h" #include "mojo/core/embedder/embedder.h" +#include "testing/gtest/include/gtest/gtest.h" #include "third_party/libyuv/include/libyuv.h" #include "ui/gfx/codec/jpeg_codec.h" @@ -47,9 +43,10 @@ // Default test image file. const base::FilePath::CharType kDefaultYuvFilename[] = FILE_PATH_LITERAL("bali_640x360_P420.yuv:640x360"); -// Whether to save encode results to files. Output files will be saved -// in the same directory with unittest. File name is like input file but -// changing the extension to "jpg". +// Whether to save encode results to files. Output files will be saved in the +// same directory as the input files, with the '.jpg' extension appended to +// their names. The encode result of generated images is written to the current +// folder using HxW_[black|white].jpg as output file name. bool g_save_to_file = false; const double kMeanDiffThreshold = 10.0; @@ -59,18 +56,21 @@ class JpegEncodeAcceleratorTestEnvironment; JpegEncodeAcceleratorTestEnvironment* g_env; -struct TestImageFile { - TestImageFile(const base::FilePath::StringType& filename, - gfx::Size visible_size) - : filename(filename), visible_size(visible_size) {} +struct TestImage { + TestImage(std::vector<uint8_t> image_data, + const gfx::Size& visible_size, + const base::FilePath output_filename) + : image_data(std::move(image_data)), + visible_size(visible_size), + output_filename(output_filename) {} - base::FilePath::StringType filename; - - // The input content of |filename|. - std::string data_str; - + // Test image data. + std::vector<uint8_t> image_data; gfx::Size visible_size; - size_t output_size; + + // Output filename, only used when '--save_to_file' is specified. + base::FilePath output_filename; + size_t output_size = 0; }; enum class ClientState { @@ -95,50 +95,41 @@ void LogToFile(const std::string& key, const std::string& value); // Read image from |filename| to |image_data|. - void ReadTestYuvImage(base::FilePath& filename, TestImageFile* image_data); + std::unique_ptr<TestImage> ReadTestYuvImage(const base::FilePath& filename, + const gfx::Size& image_size); // Returns a file path for a file in what name specified or media/test/data // directory. If the original file path is existed, returns it first. base::FilePath GetOriginalOrTestDataFilePath(const std::string& name); // Parsed data from command line. - std::vector<std::unique_ptr<TestImageFile>> image_data_user_; + std::vector<std::unique_ptr<TestImage>> image_data_user_; - // Parsed data of |test_4160x3120_yuv_file_|. - std::unique_ptr<TestImageFile> image_data_4160x3120_white_; - // Parsed data of |test_2560x1920_yuv_file_|. - std::unique_ptr<TestImageFile> image_data_2560x1920_white_; + // Generated 4160x3120 white I420 image. + std::unique_ptr<TestImage> image_data_4160x3120_white_; + // Generated 2560x1920 white I420 image. + std::unique_ptr<TestImage> image_data_2560x1920_white_; // Scarlet doesn't support 1080 width, it only suports 1088 width. - // Parsed data of |test_1280x720_yuv_file_|. - std::unique_ptr<TestImageFile> image_data_1280x720_white_; - // Parsed data of |test_640x480_yuv_file_|. - std::unique_ptr<TestImageFile> image_data_640x480_black_; - // Parsed data of |test_640x368_yuv_file_|. - std::unique_ptr<TestImageFile> image_data_640x368_black_; - // Parsed data of |test_640x360_yuv_file_|. - std::unique_ptr<TestImageFile> image_data_640x360_black_; + // Generated 1280x720 white I420 image. + std::unique_ptr<TestImage> image_data_1280x720_white_; + // Generated 640x480 black I420 image. + std::unique_ptr<TestImage> image_data_640x480_black_; + // Generated 640x368 black I420 image. + std::unique_ptr<TestImage> image_data_640x368_black_; + // Generated 640x360 black I420 image. + std::unique_ptr<TestImage> image_data_640x360_black_; // Number of times SimpleEncodeTest should repeat for an image. const size_t repeat_; private: - // Create black or white test image with |width| and |height| size. - void CreateTestYuvImage(int width, - int height, - bool is_black, - base::FilePath* filename); + // Create black or white test image with specified |size|. + std::unique_ptr<TestImage> CreateTestYuvImage(const gfx::Size& image_size, + bool is_black); const base::FilePath::CharType* user_yuv_files_; const base::FilePath log_path_; std::unique_ptr<base::File> log_file_; - - // Programatically generated YUV files. - base::FilePath test_4160x3120_yuv_file_; - base::FilePath test_2560x1920_yuv_file_; - base::FilePath test_1280x720_yuv_file_; - base::FilePath test_640x480_yuv_file_; - base::FilePath test_640x360_yuv_file_; - base::FilePath test_640x368_yuv_file_; }; void JpegEncodeAcceleratorTestEnvironment::SetUp() { @@ -148,42 +139,14 @@ LOG_ASSERT(log_file_->IsValid()); } - CreateTestYuvImage(4160, 3120, false, &test_4160x3120_yuv_file_); - CreateTestYuvImage(2560, 1920, false, &test_2560x1920_yuv_file_); - CreateTestYuvImage(1280, 720, false, &test_1280x720_yuv_file_); - CreateTestYuvImage(640, 480, true, &test_640x480_yuv_file_); - CreateTestYuvImage(640, 360, true, &test_640x360_yuv_file_); - CreateTestYuvImage(640, 368, true, &test_640x368_yuv_file_); - - image_data_4160x3120_white_.reset(new TestImageFile( - test_4160x3120_yuv_file_.value(), gfx::Size(4160, 3120))); - ASSERT_NO_FATAL_FAILURE(ReadTestYuvImage(test_4160x3120_yuv_file_, - image_data_4160x3120_white_.get())); - - image_data_2560x1920_white_.reset(new TestImageFile( - test_2560x1920_yuv_file_.value(), gfx::Size(2560, 1920))); - ASSERT_NO_FATAL_FAILURE(ReadTestYuvImage(test_2560x1920_yuv_file_, - image_data_2560x1920_white_.get())); - - image_data_1280x720_white_.reset( - new TestImageFile(test_1280x720_yuv_file_.value(), gfx::Size(1280, 720))); - ASSERT_NO_FATAL_FAILURE(ReadTestYuvImage(test_1280x720_yuv_file_, - image_data_1280x720_white_.get())); - - image_data_640x480_black_.reset( - new TestImageFile(test_640x480_yuv_file_.value(), gfx::Size(640, 480))); - ASSERT_NO_FATAL_FAILURE(ReadTestYuvImage(test_640x480_yuv_file_, - image_data_640x480_black_.get())); - - image_data_640x368_black_.reset( - new TestImageFile(test_640x368_yuv_file_.value(), gfx::Size(640, 368))); - ASSERT_NO_FATAL_FAILURE(ReadTestYuvImage(test_640x368_yuv_file_, - image_data_640x368_black_.get())); - - image_data_640x360_black_.reset( - new TestImageFile(test_640x360_yuv_file_.value(), gfx::Size(640, 360))); - ASSERT_NO_FATAL_FAILURE(ReadTestYuvImage(test_640x360_yuv_file_, - image_data_640x360_black_.get())); + image_data_4160x3120_white_ = + CreateTestYuvImage(gfx::Size(4160, 3120), false); + image_data_2560x1920_white_ = + CreateTestYuvImage(gfx::Size(2560, 1920), false); + image_data_1280x720_white_ = CreateTestYuvImage(gfx::Size(1280, 720), false); + image_data_640x480_black_ = CreateTestYuvImage(gfx::Size(640, 480), true); + image_data_640x368_black_ = CreateTestYuvImage(gfx::Size(640, 368), true); + image_data_640x360_black_ = CreateTestYuvImage(gfx::Size(640, 360), true); // |user_yuv_files_| may include many files and use ';' as delimiter. std::vector<base::FilePath::StringType> files = @@ -209,21 +172,13 @@ ASSERT_TRUE(!image_size.IsEmpty()); base::FilePath input_file = GetOriginalOrTestDataFilePath(filename); - auto image_data = std::make_unique<TestImageFile>(filename, image_size); - ASSERT_NO_FATAL_FAILURE(ReadTestYuvImage(input_file, image_data.get())); + auto image_data = ReadTestYuvImage(input_file, image_size); image_data_user_.push_back(std::move(image_data)); } } void JpegEncodeAcceleratorTestEnvironment::TearDown() { log_file_.reset(); - - base::DeleteFile(test_4160x3120_yuv_file_, false); - base::DeleteFile(test_2560x1920_yuv_file_, false); - base::DeleteFile(test_1280x720_yuv_file_, false); - base::DeleteFile(test_640x480_yuv_file_, false); - base::DeleteFile(test_640x368_yuv_file_, false); - base::DeleteFile(test_640x360_yuv_file_, false); } void JpegEncodeAcceleratorTestEnvironment::LogToFile(const std::string& key, @@ -235,51 +190,56 @@ } } -void JpegEncodeAcceleratorTestEnvironment::CreateTestYuvImage( - int width, - int height, - bool is_black, - base::FilePath* filename) { - std::vector<uint8_t> buffer(width * height * 3 / 2); +std::unique_ptr<TestImage> +JpegEncodeAcceleratorTestEnvironment::CreateTestYuvImage( + const gfx::Size& image_size, + bool is_black) { + const size_t num_pixels = image_size.width() * image_size.height(); + std::vector<uint8_t> image_data(num_pixels * 3 / 2); - size_t size = width * height; // Fill in Y values. - memset(buffer.data(), is_black ? 0 : 255, size); - // FIll in U and V values. - memset(buffer.data() + size, 128, size / 2); - LOG_ASSERT(base::CreateTemporaryFile(filename)); - EXPECT_TRUE(base::AppendToFile( - *filename, reinterpret_cast<char*>(buffer.data()), buffer.size())); + std::fill(image_data.begin(), image_data.begin() + num_pixels, + is_black ? 0 : 255); + // Fill in U and V values. + std::fill(image_data.begin() + num_pixels, image_data.end(), 128); + + base::FilePath output_filename(std::to_string(image_size.width()) + "x" + + std::to_string(image_size.height()) + + (is_black ? "_black.jpg" : "_white.jpg")); + return std::make_unique<TestImage>(std::move(image_data), image_size, + output_filename); } -void JpegEncodeAcceleratorTestEnvironment::ReadTestYuvImage( - base::FilePath& input_file, - TestImageFile* image_data) { - ASSERT_TRUE(base::ReadFileToString(input_file, &image_data->data_str)); +std::unique_ptr<TestImage> +JpegEncodeAcceleratorTestEnvironment::ReadTestYuvImage( + const base::FilePath& input_file, + const gfx::Size& image_size) { + int64_t file_size = 0; + LOG_ASSERT(GetFileSize(input_file, &file_size)); + std::vector<uint8_t> image_data(file_size); + LOG_ASSERT(ReadFile(input_file, reinterpret_cast<char*>(image_data.data()), + file_size) == file_size); - // This is just a placeholder. We will compute the real output size when we - // have encoder instance. - image_data->output_size = - VideoFrame::AllocationSize(PIXEL_FORMAT_I420, image_data->visible_size); + base::FilePath output_filename = input_file.AddExtension(".jpg"); + return std::make_unique<TestImage>(std::move(image_data), image_size, + output_filename); } base::FilePath JpegEncodeAcceleratorTestEnvironment::GetOriginalOrTestDataFilePath( const std::string& name) { - base::FilePath original_file_path = base::FilePath(name); - base::FilePath return_file_path = GetTestDataFilePath(name); - - if (PathExists(original_file_path)) - return_file_path = original_file_path; - - VLOG(3) << "Use file path " << return_file_path.value(); - return return_file_path; + base::FilePath file_path = base::FilePath(name); + if (!PathExists(file_path)) { + file_path = GetTestDataFilePath(name); + } + VLOG(3) << "Using file path " << file_path.value(); + return file_path; } class JpegClient : public JpegEncodeAccelerator::Client { public: - JpegClient(const std::vector<TestImageFile*>& test_aligned_image_files, - const std::vector<TestImageFile*>& test_image_files, + JpegClient(const std::vector<TestImage*>& test_aligned_images, + const std::vector<TestImage*>& test_images, ClientStateNotification<ClientState>* note); ~JpegClient() override; void CreateJpegEncoder(); @@ -293,10 +253,10 @@ private: // Get the related test image file. - TestImageFile* GetTestImageFile(int32_t bitstream_buffer_id); + TestImage* GetTestImage(int32_t bitstream_buffer_id); void PrepareMemory(int32_t bitstream_buffer_id); void SetState(ClientState new_state); - void SaveToFile(TestImageFile* image_file, size_t hw_size, size_t sw_size); + void SaveToFile(TestImage* test_image, size_t hw_size, size_t sw_size); bool CompareHardwareAndSoftwareResults(int width, int height, size_t hw_encoded_size, @@ -314,14 +274,14 @@ size_t* sw_encoded_size, base::TimeDelta* sw_encode_time); - // JpegClient doesn't own |test_aligned_image_files_|. + // JpegClient doesn't own |test_aligned_images_|. // The resolutions of these images are all aligned. HW Accelerator must // support them. - const std::vector<TestImageFile*>& test_aligned_image_files_; + const std::vector<TestImage*>& test_aligned_images_; - // JpegClient doesn't own |test_image_files_|. + // JpegClient doesn't own |test_images_|. // The resolutions of these images may be unaligned. - const std::vector<TestImageFile*>& test_image_files_; + const std::vector<TestImage*>& test_images_; // A map that stores HW encoding start timestamp for each output buffer id. std::map<int, base::TimeTicks> buffer_id_to_start_time_; @@ -346,12 +306,11 @@ DISALLOW_COPY_AND_ASSIGN(JpegClient); }; -JpegClient::JpegClient( - const std::vector<TestImageFile*>& test_aligned_image_files, - const std::vector<TestImageFile*>& test_image_files, - ClientStateNotification<ClientState>* note) - : test_aligned_image_files_(test_aligned_image_files), - test_image_files_(test_image_files), +JpegClient::JpegClient(const std::vector<TestImage*>& test_aligned_images, + const std::vector<TestImage*>& test_images, + ClientStateNotification<ClientState>* note) + : test_aligned_images_(test_aligned_images), + test_images_(test_images), state_(ClientState::CREATED), note_(note) {} @@ -396,12 +355,11 @@ base::TimeDelta elapsed_hw = hw_encode_end - buffer_id_to_start_time_[buffer_id]; - TestImageFile* test_image; - if (buffer_id < static_cast<int32_t>(test_aligned_image_files_.size())) { - test_image = test_aligned_image_files_[buffer_id]; + TestImage* test_image; + if (buffer_id < static_cast<int32_t>(test_aligned_images_.size())) { + test_image = test_aligned_images_[buffer_id]; } else { - test_image = - test_image_files_[buffer_id - test_aligned_image_files_.size()]; + test_image = test_images_[buffer_id - test_aligned_images_.size()]; } size_t sw_encoded_size = 0; @@ -519,44 +477,43 @@ encoded_buffer_.reset(nullptr); } -TestImageFile* JpegClient::GetTestImageFile(int32_t bitstream_buffer_id) { +TestImage* JpegClient::GetTestImage(int32_t bitstream_buffer_id) { DCHECK_LT(static_cast<size_t>(bitstream_buffer_id), - test_aligned_image_files_.size() + test_image_files_.size()); - TestImageFile* image_file; - if (bitstream_buffer_id < - static_cast<int32_t>(test_aligned_image_files_.size())) { - image_file = test_aligned_image_files_[bitstream_buffer_id]; + test_aligned_images_.size() + test_images_.size()); + TestImage* image_file; + if (bitstream_buffer_id < static_cast<int32_t>(test_aligned_images_.size())) { + image_file = test_aligned_images_[bitstream_buffer_id]; } else { - image_file = test_image_files_[bitstream_buffer_id - - test_aligned_image_files_.size()]; + image_file = + test_images_[bitstream_buffer_id - test_aligned_images_.size()]; } return image_file; } void JpegClient::PrepareMemory(int32_t bitstream_buffer_id) { - TestImageFile* image_file = GetTestImageFile(bitstream_buffer_id); + TestImage* test_image = GetTestImage(bitstream_buffer_id); - size_t input_size = image_file->data_str.size(); + size_t input_size = test_image->image_data.size(); if (!in_shm_.get() || input_size > in_shm_->mapped_size()) { in_shm_.reset(new base::SharedMemory); LOG_ASSERT(in_shm_->CreateAndMapAnonymous(input_size)); } - memcpy(in_shm_->memory(), image_file->data_str.data(), input_size); + memcpy(in_shm_->memory(), test_image->image_data.data(), input_size); if (!hw_out_shm_.get() || - image_file->output_size > hw_out_shm_->mapped_size()) { + test_image->output_size > hw_out_shm_->mapped_size()) { hw_out_shm_.reset(new base::SharedMemory); - LOG_ASSERT(hw_out_shm_->CreateAndMapAnonymous(image_file->output_size)); + LOG_ASSERT(hw_out_shm_->CreateAndMapAnonymous(test_image->output_size)); } - memset(hw_out_shm_->memory(), 0, image_file->output_size); + memset(hw_out_shm_->memory(), 0, test_image->output_size); if (!sw_out_shm_.get() || - image_file->output_size > sw_out_shm_->mapped_size()) { + test_image->output_size > sw_out_shm_->mapped_size()) { sw_out_shm_.reset(new base::SharedMemory); - LOG_ASSERT(sw_out_shm_->CreateAndMapAnonymous(image_file->output_size)); + LOG_ASSERT(sw_out_shm_->CreateAndMapAnonymous(test_image->output_size)); } - memset(sw_out_shm_->memory(), 0, image_file->output_size); + memset(sw_out_shm_->memory(), 0, test_image->output_size); } void JpegClient::SetState(ClientState new_state) { @@ -568,39 +525,43 @@ state_ = new_state; } -void JpegClient::SaveToFile(TestImageFile* image_file, +void JpegClient::SaveToFile(TestImage* test_image, size_t hw_size, size_t sw_size) { - DCHECK_NE(nullptr, image_file); + DCHECK_NE(nullptr, test_image); - base::FilePath in_filename(image_file->filename); - base::FilePath out_filename = in_filename.ReplaceExtension(".jpg"); + base::FilePath out_filename_hw = test_image->output_filename; + LOG(INFO) << "Writing HW encode results to " + << out_filename_hw.MaybeAsASCII(); ASSERT_EQ( static_cast<int>(hw_size), - base::WriteFile(out_filename, static_cast<char*>(hw_out_shm_->memory()), - hw_size)); + base::WriteFile(out_filename_hw, + static_cast<char*>(hw_out_shm_->memory()), hw_size)); + base::FilePath out_filename_sw = out_filename_hw.InsertBeforeExtension("_sw"); + LOG(INFO) << "Writing SW encode results to " + << out_filename_sw.MaybeAsASCII(); ASSERT_EQ( static_cast<int>(sw_size), - base::WriteFile(out_filename.InsertBeforeExtension("_sw"), + base::WriteFile(out_filename_sw, static_cast<char*>(sw_out_shm_->memory()), sw_size)); } void JpegClient::StartEncode(int32_t bitstream_buffer_id) { - TestImageFile* image_file = GetTestImageFile(bitstream_buffer_id); + TestImage* test_image = GetTestImage(bitstream_buffer_id); - image_file->output_size = - encoder_->GetMaxCodedBufferSize(image_file->visible_size); + test_image->output_size = + encoder_->GetMaxCodedBufferSize(test_image->visible_size); PrepareMemory(bitstream_buffer_id); base::SharedMemoryHandle dup_handle; dup_handle = base::SharedMemory::DuplicateHandle(hw_out_shm_->handle()); encoded_buffer_ = std::make_unique<BitstreamBuffer>( - bitstream_buffer_id, dup_handle, image_file->output_size); + bitstream_buffer_id, dup_handle, test_image->output_size); scoped_refptr<VideoFrame> input_frame_ = VideoFrame::WrapExternalSharedMemory( - PIXEL_FORMAT_I420, image_file->visible_size, - gfx::Rect(image_file->visible_size), image_file->visible_size, - static_cast<uint8_t*>(in_shm_->memory()), image_file->data_str.size(), + PIXEL_FORMAT_I420, test_image->visible_size, + gfx::Rect(test_image->visible_size), test_image->visible_size, + static_cast<uint8_t*>(in_shm_->memory()), test_image->image_data.size(), in_shm_->handle(), 0, base::TimeDelta()); LOG_ASSERT(input_frame_.get()); @@ -620,10 +581,10 @@ // JpegEncodeAccelerator implementations. base::test::ScopedTaskEnvironment scoped_task_environment_; - // The elements of |test_aligned_image_files_| and |test_image_files_| are + // The elements of |test_aligned_images_| and |test_images_| are // owned by JpegEncodeAcceleratorTestEnvironment. - std::vector<TestImageFile*> test_aligned_image_files_; - std::vector<TestImageFile*> test_image_files_; + std::vector<TestImage*> test_aligned_images_; + std::vector<TestImage*> test_images_; protected: DISALLOW_COPY_AND_ASSIGN(JpegEncodeAcceleratorTest); @@ -639,18 +600,18 @@ for (size_t i = 0; i < num_concurrent_encoders; i++) { notes.push_back(std::make_unique<ClientStateNotification<ClientState>>()); clients.push_back(std::make_unique<JpegClient>( - test_aligned_image_files_, test_image_files_, notes.back().get())); + test_aligned_images_, test_images_, notes.back().get())); encoder_thread.task_runner()->PostTask( FROM_HERE, base::BindOnce(&JpegClient::CreateJpegEncoder, base::Unretained(clients.back().get()))); ASSERT_EQ(notes[i]->Wait(), ClientState::INITIALIZED); } - for (size_t index = 0; index < test_aligned_image_files_.size(); index++) { - VLOG(3) << index << ",width:" - << test_aligned_image_files_[index]->visible_size.width(); - VLOG(3) << index << ",height:" - << test_aligned_image_files_[index]->visible_size.height(); + for (size_t index = 0; index < test_aligned_images_.size(); index++) { + VLOG(3) << index + << ",width:" << test_aligned_images_[index]->visible_size.width(); + VLOG(3) << index + << ",height:" << test_aligned_images_[index]->visible_size.height(); for (size_t i = 0; i < num_concurrent_encoders; i++) { encoder_thread.task_runner()->PostTask( FROM_HERE, base::BindOnce(&JpegClient::StartEncode, @@ -661,12 +622,12 @@ } } - for (size_t index = 0; index < test_image_files_.size(); index++) { - int buffer_id = index + test_aligned_image_files_.size(); + for (size_t index = 0; index < test_images_.size(); index++) { + int buffer_id = index + test_aligned_images_.size(); VLOG(3) << buffer_id - << ",width:" << test_image_files_[index]->visible_size.width(); + << ",width:" << test_images_[index]->visible_size.width(); VLOG(3) << buffer_id - << ",height:" << test_image_files_[index]->visible_size.height(); + << ",height:" << test_images_[index]->visible_size.height(); for (size_t i = 0; i < num_concurrent_encoders; i++) { encoder_thread.task_runner()->PostTask( FROM_HERE, @@ -698,7 +659,7 @@ TEST_F(JpegEncodeAcceleratorTest, SimpleEncode) { for (size_t i = 0; i < g_env->repeat_; i++) { for (auto& image : g_env->image_data_user_) { - test_image_files_.push_back(image.get()); + test_images_.push_back(image.get()); } } TestEncode(1); @@ -706,29 +667,28 @@ TEST_F(JpegEncodeAcceleratorTest, MultipleEncoders) { for (auto& image : g_env->image_data_user_) { - test_image_files_.push_back(image.get()); + test_images_.push_back(image.get()); } TestEncode(3); } TEST_F(JpegEncodeAcceleratorTest, ResolutionChange) { - test_image_files_.push_back(g_env->image_data_640x368_black_.get()); - test_image_files_.push_back(g_env->image_data_640x360_black_.get()); - test_aligned_image_files_.push_back(g_env->image_data_1280x720_white_.get()); + test_images_.push_back(g_env->image_data_640x368_black_.get()); + test_images_.push_back(g_env->image_data_640x360_black_.get()); + test_aligned_images_.push_back(g_env->image_data_1280x720_white_.get()); TestEncode(1); } TEST_F(JpegEncodeAcceleratorTest, AlignedSizes) { - test_aligned_image_files_.push_back(g_env->image_data_4160x3120_white_.get()); - test_aligned_image_files_.push_back(g_env->image_data_2560x1920_white_.get()); - test_aligned_image_files_.push_back(g_env->image_data_1280x720_white_.get()); - test_aligned_image_files_.push_back(g_env->image_data_640x480_black_.get()); - + test_aligned_images_.push_back(g_env->image_data_4160x3120_white_.get()); + test_aligned_images_.push_back(g_env->image_data_2560x1920_white_.get()); + test_aligned_images_.push_back(g_env->image_data_1280x720_white_.get()); + test_aligned_images_.push_back(g_env->image_data_640x480_black_.get()); TestEncode(1); } TEST_F(JpegEncodeAcceleratorTest, CodedSizeAlignment) { - test_image_files_.push_back(g_env->image_data_640x360_black_.get()); + test_images_.push_back(g_env->image_data_640x360_black_.get()); TestEncode(1); }
diff --git a/media/gpu/vt_video_decode_accelerator_mac.cc b/media/gpu/vt_video_decode_accelerator_mac.cc index bb650ed..95f1703 100644 --- a/media/gpu/vt_video_decode_accelerator_mac.cc +++ b/media/gpu/vt_video_decode_accelerator_mac.cc
@@ -190,7 +190,7 @@ &callback, // output_callback session.InitializeInto()); if (status) { - OSSTATUS_DLOG(WARNING, status) << "Failed to create VTDecompressionSession"; + OSSTATUS_DVLOG(1, status) << "Failed to create VTDecompressionSession"; return false; } @@ -212,7 +212,7 @@ const uint8_t pps_normal[] = {0x68, 0xe9, 0x7b, 0xcb}; if (!CreateVideoToolboxSession(sps_normal, arraysize(sps_normal), pps_normal, arraysize(pps_normal), true)) { - DLOG(WARNING) << "Hardware decoding with VideoToolbox is not supported"; + DVLOG(1) << "Hardware decoding with VideoToolbox is not supported"; return false; }
diff --git a/media/mojo/services/mojo_video_decoder_service.cc b/media/mojo/services/mojo_video_decoder_service.cc index 0c7d2ab..e7a1159 100644 --- a/media/mojo/services/mojo_video_decoder_service.cc +++ b/media/mojo/services/mojo_video_decoder_service.cc
@@ -269,7 +269,7 @@ void MojoVideoDecoderService::OnDecoderInitialized(bool success) { DVLOG(1) << __func__; - DCHECK(decoder_); + DCHECK(!success || decoder_); DCHECK(init_cb_); TRACE_EVENT_ASYNC_END1("media", kInitializeTraceName, this, "success", success);
diff --git a/media/mojo/test/mojo_video_decoder_integration_test.cc b/media/mojo/test/mojo_video_decoder_integration_test.cc index a88979c..c9507b0 100644 --- a/media/mojo/test/mojo_video_decoder_integration_test.cc +++ b/media/mojo/test/mojo_video_decoder_integration_test.cc
@@ -325,6 +325,32 @@ EXPECT_EQ(client_->GetMaxDecodeRequests(), kMaxDecodeRequests); } +TEST_F(MojoVideoDecoderIntegrationTest, InitializeFailNoDecoder) { + CreateClient(); + + StrictMock<base::MockCallback<VideoDecoder::InitCB>> init_cb; + EXPECT_CALL(init_cb, Run(false)); + + // Clear |decoder_| so that Initialize() should fail. + decoder_.reset(); + client_->Initialize(TestVideoConfig::NormalH264(), false, nullptr, + init_cb.Get(), output_cb_.Get(), base::NullCallback()); + RunUntilIdle(); +} + +TEST_F(MojoVideoDecoderIntegrationTest, InitializeFailNoCdm) { + CreateClient(); + + StrictMock<base::MockCallback<VideoDecoder::InitCB>> init_cb; + EXPECT_CALL(init_cb, Run(false)); + + // CdmContext* (3rd parameter) is not provided but the VideoDecoderConfig + // specifies encrypted video, so Initialize() should fail. + client_->Initialize(TestVideoConfig::NormalEncrypted(), false, nullptr, + init_cb.Get(), output_cb_.Get(), base::NullCallback()); + RunUntilIdle(); +} + TEST_F(MojoVideoDecoderIntegrationTest, MediaLogIsProxied) { ASSERT_TRUE(Initialize()); EXPECT_MEDIA_LOG_ON(client_media_log_, HasSubstr("\"test\""));
diff --git a/net/dns/BUILD.gn b/net/dns/BUILD.gn index 571d0cd..cd872e9 100644 --- a/net/dns/BUILD.gn +++ b/net/dns/BUILD.gn
@@ -188,6 +188,7 @@ deps = [ "//net:net_deps", + "//net/dns/public", ] public_deps = [ "//net:net_public_deps", @@ -236,6 +237,7 @@ deps = [ ":host_resolver", "//net:net_deps", + "//net/dns/public", ] public_deps = [ "//net:net_public_deps",
diff --git a/net/dns/dns_util.cc b/net/dns/dns_util.cc index 6230aab1..9b3b5d0 100644 --- a/net/dns/dns_util.cc +++ b/net/dns/dns_util.cc
@@ -99,7 +99,7 @@ if (namelen + 1 > sizeof name) return false; - if (namelen == 0) // Empty names e.g. "", "." are not valid. + if (namelen == 0) // Empty names e.g. "", "." are not valid. return false; name[namelen++] = 0; // This is the root label (of length 0). @@ -222,4 +222,30 @@ return std::string(buf, sizeof(buf)); } +uint16_t DnsQueryTypeToQtype(DnsQueryType dns_query_type) { + switch (dns_query_type) { + case DnsQueryType::UNSPECIFIED: + NOTREACHED(); + return 0; + case DnsQueryType::A: + return dns_protocol::kTypeA; + case DnsQueryType::AAAA: + return dns_protocol::kTypeAAAA; + } +} + +DnsQueryType AddressFamilyToDnsQueryType(AddressFamily address_family) { + switch (address_family) { + case ADDRESS_FAMILY_UNSPECIFIED: + return DnsQueryType::UNSPECIFIED; + case ADDRESS_FAMILY_IPV4: + return DnsQueryType::A; + case ADDRESS_FAMILY_IPV6: + return DnsQueryType::AAAA; + default: + NOTREACHED(); + return DnsQueryType::UNSPECIFIED; + } +} + } // namespace net
diff --git a/net/dns/dns_util.h b/net/dns/dns_util.h index 6694407..6e29748 100644 --- a/net/dns/dns_util.h +++ b/net/dns/dns_util.h
@@ -9,8 +9,10 @@ #include "base/strings/string_piece.h" #include "base/time/time.h" +#include "net/base/address_family.h" #include "net/base/net_export.h" #include "net/base/network_change_notifier.h" +#include "net/dns/public/dns_query_type.h" namespace net { @@ -85,6 +87,12 @@ // Note that |offset| must be less than 2^14 - 1 by definition. NET_EXPORT std::string CreateNamePointer(uint16_t offset); +// Convert a DnsQueryType enum to the wire format integer representation. +uint16_t DnsQueryTypeToQtype(DnsQueryType dns_query_type); + +NET_EXPORT DnsQueryType +AddressFamilyToDnsQueryType(AddressFamily address_family); + } // namespace net #endif // NET_DNS_DNS_UTIL_H_
diff --git a/net/dns/host_cache.cc b/net/dns/host_cache.cc index 6807320..dc348add 100644 --- a/net/dns/host_cache.cc +++ b/net/dns/host_cache.cc
@@ -16,6 +16,7 @@ #include "net/base/net_errors.h" #include "net/base/trace_constants.h" #include "net/dns/dns_util.h" +#include "net/dns/host_resolver.h" #include "net/log/net_log.h" namespace net { @@ -34,7 +35,9 @@ // String constants for dictionary keys. const char kHostnameKey[] = "hostname"; const char kAddressFamilyKey[] = "address_family"; +const char kDnsQueryTypeKey[] = "dns_query_type"; const char kFlagsKey[] = "flags"; +const char kHostResolverSourceKey[] = "host_resolver_source"; const char kExpirationKey[] = "expiration"; const char kTtlKey[] = "ttl"; const char kNetworkChangesKey[] = "network_changes"; @@ -82,6 +85,26 @@ MAX_ERASE_REASON }; +HostCache::Key::Key(const std::string& hostname, + DnsQueryType dns_query_type, + HostResolverFlags host_resolver_flags, + HostResolverSource host_resolver_source) + : hostname(hostname), + dns_query_type(dns_query_type), + host_resolver_flags(host_resolver_flags), + host_resolver_source(host_resolver_source) {} + +HostCache::Key::Key(const std::string& hostname, + AddressFamily address_family, + HostResolverFlags host_resolver_flags) + : Key(hostname, + AddressFamilyToDnsQueryType(address_family), + host_resolver_flags, + HostResolverSource::ANY) {} + +HostCache::Key::Key() + : Key("", DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY) {} + HostCache::Entry::Entry(int error, const AddressList& addresses, Source source, @@ -162,8 +185,7 @@ RecordEraseAll(ERASE_DESTRUCT, tick_clock_->NowTicks()); } -const HostCache::Entry* HostCache::Lookup(const Key& key, - base::TimeTicks now) { +const HostCache::Entry* HostCache::Lookup(const Key& key, base::TimeTicks now) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); if (caching_is_disabled()) return nullptr; @@ -318,9 +340,11 @@ new base::DictionaryValue()); entry_dict->SetString(kHostnameKey, key.hostname); - entry_dict->SetInteger(kAddressFamilyKey, - static_cast<int>(key.address_family)); + entry_dict->SetInteger(kDnsQueryTypeKey, + static_cast<int>(key.dns_query_type)); entry_dict->SetInteger(kFlagsKey, key.host_resolver_flags); + entry_dict->SetInteger(kHostResolverSourceKey, + static_cast<int>(key.host_resolver_source)); if (include_staleness) { // The kExpirationKey value is using TimeTicks instead of Time used if @@ -362,8 +386,9 @@ return false; std::string hostname; - int address_family; + int dns_query_type; HostResolverFlags flags; + int host_resolver_source; int error = OK; std::string expiration; base::ListValue empty_list; @@ -372,11 +397,30 @@ if (!entry_dict->GetString(kHostnameKey, &hostname) || !entry_dict->GetInteger(kFlagsKey, &flags) || - !entry_dict->GetInteger(kAddressFamilyKey, &address_family) || !entry_dict->GetString(kExpirationKey, &expiration)) { return false; } + // If there is no DnsQueryType, look for an AddressFamily. + // + // TODO(crbug.com/846423): Remove kAddressFamilyKey support after a enough + // time has passed to minimize loss-of-persistence impact from backwards + // incompatibility. + if (!entry_dict->GetInteger(kDnsQueryTypeKey, &dns_query_type)) { + int address_family; + if (!entry_dict->GetInteger(kAddressFamilyKey, &address_family)) { + return false; + } + dns_query_type = static_cast<int>(AddressFamilyToDnsQueryType( + static_cast<AddressFamily>(address_family))); + } + + // HostResolverSource is optional. + if (!entry_dict->GetInteger(kHostResolverSourceKey, + &host_resolver_source)) { + host_resolver_source = static_cast<int>(HostResolverSource::ANY); + } + // Only one of these fields should be in the dictionary. if (!entry_dict->GetInteger(kErrorKey, &error) && !entry_dict->GetList(kAddressesKey, &addresses_value)) { @@ -391,7 +435,8 @@ tick_clock_->NowTicks() - (base::Time::Now() - base::Time::FromInternalValue(time_internal)); - Key key(hostname, static_cast<AddressFamily>(address_family), flags); + Key key(hostname, static_cast<DnsQueryType>(dns_query_type), flags, + static_cast<HostResolverSource>(host_resolver_source)); if (error == OK && !AddressListFromListValue(addresses_value, &address_list)) { return false; @@ -554,12 +599,12 @@ const HostCache::Entry* entry = LookupStale(cache_key, tick_clock_->NowTicks(), stale_out); - if (!entry) { + if (!entry && IsAddressType(cache_key.dns_query_type)) { // Might not have found the cache entry because the address_family or // host_resolver_flags in cache_key do not match those used for the // original DNS lookup. Try another common combination of address_family // and host_resolver_flags in an attempt to find a matching cache entry. - cache_key.address_family = net::ADDRESS_FAMILY_IPV4; + cache_key.dns_query_type = DnsQueryType::A; cache_key.host_resolver_flags = net::HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6; entry = LookupStale(cache_key, tick_clock_->NowTicks(), stale_out);
diff --git a/net/dns/host_cache.h b/net/dns/host_cache.h index 45a3ee2e..ffd63c14 100644 --- a/net/dns/host_cache.h +++ b/net/dns/host_cache.h
@@ -23,6 +23,7 @@ #include "net/base/net_export.h" #include "net/dns/dns_util.h" #include "net/dns/host_resolver_source.h" +#include "net/dns/public/dns_query_type.h" namespace base { class ListValue; @@ -34,34 +35,29 @@ // Cache used by HostResolver to map hostnames to their resolved result. class NET_EXPORT HostCache { public: - struct Key { + struct NET_EXPORT Key { + Key(const std::string& hostname, + DnsQueryType dns_query_type, + HostResolverFlags host_resolver_flags, + HostResolverSource host_resolver_source); Key(const std::string& hostname, AddressFamily address_family, - HostResolverFlags host_resolver_flags, - HostResolverSource host_resolver_source = HostResolverSource::ANY) - : hostname(hostname), - address_family(address_family), - host_resolver_flags(host_resolver_flags), - host_resolver_source(host_resolver_source) {} - - Key() - : address_family(ADDRESS_FAMILY_UNSPECIFIED), - host_resolver_flags(0), - host_resolver_source(HostResolverSource::ANY) {} + HostResolverFlags host_resolver_flags); + Key(); bool operator<(const Key& other) const { // The order of comparisons of |Key| fields is arbitrary, thus - // |address_family| and |host_resolver_flags| are compared before + // |dns_query_type| and |host_resolver_flags| are compared before // |hostname| under assumption that integer comparisons are faster than // string comparisons. - return std::tie(address_family, host_resolver_flags, hostname, + return std::tie(dns_query_type, host_resolver_flags, hostname, host_resolver_source) < - std::tie(other.address_family, other.host_resolver_flags, + std::tie(other.dns_query_type, other.host_resolver_flags, other.hostname, other.host_resolver_source); } std::string hostname; - AddressFamily address_family; + DnsQueryType dns_query_type; HostResolverFlags host_resolver_flags; HostResolverSource host_resolver_source; };
diff --git a/net/dns/host_cache_unittest.cc b/net/dns/host_cache_unittest.cc index 7f6e569..b75becc 100644 --- a/net/dns/host_cache_unittest.cc +++ b/net/dns/host_cache_unittest.cc
@@ -23,9 +23,10 @@ const int kMaxCacheEntries = 10; -// Builds a key for |hostname|, defaulting the address family to unspecified. +// Builds a key for |hostname|, defaulting the query type to unspecified. HostCache::Key Key(const std::string& hostname) { - return HostCache::Key(hostname, ADDRESS_FAMILY_UNSPECIFIED, 0); + return HostCache::Key(hostname, DnsQueryType::UNSPECIFIED, 0, + HostResolverSource::ANY); } bool FoobarIndexIsOdd(const std::string& foobarx_com) { @@ -199,8 +200,8 @@ } // Tests that the same hostname can be duplicated in the cache, so long as -// the address family differs. -TEST(HostCacheTest, AddressFamilyIsPartOfKey) { +// the query type differs. +TEST(HostCacheTest, DnsQueryTypeIsPartOfKey) { const base::TimeDelta kSuccessEntryTTL = base::TimeDelta::FromSeconds(10); HostCache cache(kMaxCacheEntries); @@ -208,8 +209,10 @@ // t=0. base::TimeTicks now; - HostCache::Key key1("foobar.com", ADDRESS_FAMILY_UNSPECIFIED, 0); - HostCache::Key key2("foobar.com", ADDRESS_FAMILY_IPV4, 0); + HostCache::Key key1("foobar.com", DnsQueryType::UNSPECIFIED, 0, + HostResolverSource::ANY); + HostCache::Key key2("foobar.com", DnsQueryType::A, 0, + HostResolverSource::ANY); HostCache::Entry entry = HostCache::Entry(OK, AddressList(), HostCache::Entry::SOURCE_UNKNOWN); @@ -242,11 +245,12 @@ // t=0. base::TimeTicks now; - HostCache::Key key1("foobar.com", ADDRESS_FAMILY_IPV4, 0); - HostCache::Key key2("foobar.com", ADDRESS_FAMILY_IPV4, - HOST_RESOLVER_CANONNAME); - HostCache::Key key3("foobar.com", ADDRESS_FAMILY_IPV4, - HOST_RESOLVER_LOOPBACK_ONLY); + HostCache::Key key1("foobar.com", DnsQueryType::A, 0, + HostResolverSource::ANY); + HostCache::Key key2("foobar.com", DnsQueryType::A, HOST_RESOLVER_CANONNAME, + HostResolverSource::ANY); + HostCache::Key key3("foobar.com", DnsQueryType::A, + HOST_RESOLVER_LOOPBACK_ONLY, HostResolverSource::ANY); HostCache::Entry entry = HostCache::Entry(OK, AddressList(), HostCache::Entry::SOURCE_UNKNOWN); @@ -536,55 +540,47 @@ // 1 means key1 is greater than key2 int expected_comparison; } tests[] = { - { - HostCache::Key("host1", ADDRESS_FAMILY_UNSPECIFIED, 0), - HostCache::Key("host1", ADDRESS_FAMILY_UNSPECIFIED, 0), - 0 - }, - { - HostCache::Key("host1", ADDRESS_FAMILY_IPV4, 0), - HostCache::Key("host1", ADDRESS_FAMILY_UNSPECIFIED, 0), - 1 - }, - { - HostCache::Key("host1", ADDRESS_FAMILY_UNSPECIFIED, 0), - HostCache::Key("host1", ADDRESS_FAMILY_IPV4, 0), - -1 - }, - { - HostCache::Key("host1", ADDRESS_FAMILY_UNSPECIFIED, 0), - HostCache::Key("host2", ADDRESS_FAMILY_UNSPECIFIED, 0), - -1 - }, - { - HostCache::Key("host1", ADDRESS_FAMILY_IPV4, 0), - HostCache::Key("host2", ADDRESS_FAMILY_UNSPECIFIED, 0), - 1 - }, - { - HostCache::Key("host1", ADDRESS_FAMILY_UNSPECIFIED, 0), - HostCache::Key("host2", ADDRESS_FAMILY_IPV4, 0), - -1 - }, - { - HostCache::Key("host1", ADDRESS_FAMILY_UNSPECIFIED, 0), - HostCache::Key("host1", ADDRESS_FAMILY_UNSPECIFIED, - HOST_RESOLVER_CANONNAME), - -1 - }, - { - HostCache::Key("host1", ADDRESS_FAMILY_UNSPECIFIED, - HOST_RESOLVER_CANONNAME), - HostCache::Key("host1", ADDRESS_FAMILY_UNSPECIFIED, 0), - 1 - }, - { - HostCache::Key("host1", ADDRESS_FAMILY_UNSPECIFIED, - HOST_RESOLVER_CANONNAME), - HostCache::Key("host2", ADDRESS_FAMILY_UNSPECIFIED, - HOST_RESOLVER_CANONNAME), - -1 - }, + {HostCache::Key("host1", DnsQueryType::UNSPECIFIED, 0, + HostResolverSource::ANY), + HostCache::Key("host1", DnsQueryType::UNSPECIFIED, 0, + HostResolverSource::ANY), + 0}, + {HostCache::Key("host1", DnsQueryType::A, 0, HostResolverSource::ANY), + HostCache::Key("host1", DnsQueryType::UNSPECIFIED, 0, + HostResolverSource::ANY), + 1}, + {HostCache::Key("host1", DnsQueryType::UNSPECIFIED, 0, + HostResolverSource::ANY), + HostCache::Key("host1", DnsQueryType::A, 0, HostResolverSource::ANY), + -1}, + {HostCache::Key("host1", DnsQueryType::UNSPECIFIED, 0, + HostResolverSource::ANY), + HostCache::Key("host2", DnsQueryType::UNSPECIFIED, 0, + HostResolverSource::ANY), + -1}, + {HostCache::Key("host1", DnsQueryType::A, 0, HostResolverSource::ANY), + HostCache::Key("host2", DnsQueryType::UNSPECIFIED, 0, + HostResolverSource::ANY), + 1}, + {HostCache::Key("host1", DnsQueryType::UNSPECIFIED, 0, + HostResolverSource::ANY), + HostCache::Key("host2", DnsQueryType::A, 0, HostResolverSource::ANY), + -1}, + {HostCache::Key("host1", DnsQueryType::UNSPECIFIED, 0, + HostResolverSource::ANY), + HostCache::Key("host1", DnsQueryType::UNSPECIFIED, + HOST_RESOLVER_CANONNAME, HostResolverSource::ANY), + -1}, + {HostCache::Key("host1", DnsQueryType::UNSPECIFIED, + HOST_RESOLVER_CANONNAME, HostResolverSource::ANY), + HostCache::Key("host1", DnsQueryType::UNSPECIFIED, 0, + HostResolverSource::ANY), + 1}, + {HostCache::Key("host1", DnsQueryType::UNSPECIFIED, + HOST_RESOLVER_CANONNAME, HostResolverSource::ANY), + HostCache::Key("host2", DnsQueryType::UNSPECIFIED, + HOST_RESOLVER_CANONNAME, HostResolverSource::ANY), + -1}, }; for (size_t i = 0; i < arraysize(tests); ++i) {
diff --git a/net/dns/host_resolver.cc b/net/dns/host_resolver.cc index 46afc19..9b8daa3 100644 --- a/net/dns/host_resolver.cc +++ b/net/dns/host_resolver.cc
@@ -11,6 +11,7 @@ #include "base/values.h" #include "net/base/net_errors.h" #include "net/dns/dns_client.h" +#include "net/dns/dns_util.h" #include "net/dns/host_cache.h" #include "net/dns/host_resolver_impl.h" @@ -39,8 +40,8 @@ limits.total_jobs = kDefaultMaxProcTasks; // Parallelism is determined by the field trial. - std::string group = base::FieldTrialList::FindFullName( - "HostResolverDispatch"); + std::string group = + base::FieldTrialList::FindFullName("HostResolverDispatch"); if (group.empty()) return limits; @@ -86,8 +87,7 @@ HostResolver::Options::Options() : max_concurrent_resolves(kDefaultParallelism), max_retry_attempts(kDefaultRetryAttempts), - enable_caching(true) { -} + enable_caching(true) {} std::unique_ptr<HostResolver> HostResolver::Factory::CreateResolver( const Options& options, @@ -114,8 +114,7 @@ HostResolver::~HostResolver() = default; -void HostResolver::SetDnsClientEnabled(bool enabled) { -} +void HostResolver::SetDnsClientEnabled(bool enabled) {} HostCache* HostResolver::GetHostCache() { return nullptr; @@ -189,22 +188,6 @@ } // static -HostResolver::DnsQueryType HostResolver::AddressFamilyToDnsQueryType( - AddressFamily address_family) { - switch (address_family) { - case ADDRESS_FAMILY_UNSPECIFIED: - return DnsQueryType::UNSPECIFIED; - case ADDRESS_FAMILY_IPV4: - return DnsQueryType::A; - case ADDRESS_FAMILY_IPV6: - return DnsQueryType::AAAA; - default: - NOTREACHED(); - return DnsQueryType::UNSPECIFIED; - } -} - -// static HostResolver::ResolveHostParameters HostResolver::RequestInfoToResolveHostParameters( const HostResolver::RequestInfo& request_info,
diff --git a/net/dns/host_resolver.h b/net/dns/host_resolver.h index 27d2967..157d757 100644 --- a/net/dns/host_resolver.h +++ b/net/dns/host_resolver.h
@@ -21,6 +21,7 @@ #include "net/dns/dns_config.h" #include "net/dns/host_cache.h" #include "net/dns/host_resolver_source.h" +#include "net/dns/public/dns_query_type.h" namespace base { class Value; @@ -88,9 +89,9 @@ // If cancelled before |callback| is invoked, it will never be invoked. virtual int Start(CompletionOnceCallback callback) = 0; - // Result of the request. Should only be called after Start() signals - // completion, either by invoking the callback or by returning a result - // other than |ERR_IO_PENDING|. + // Address record (A or AAAA) results of the request. Should only be called + // after Start() signals completion, either by invoking the callback or by + // returning a result other than |ERR_IO_PENDING|. // // TODO(crbug.com/821021): Implement other GetResults() methods for requests // that return other data (eg DNS TXT requests). @@ -188,17 +189,6 @@ bool is_my_ip_address_; }; - // DNS query type for a ResolveHostRequest. - // See: - // https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4 - // - // TODO(crbug.com/846423): Add support for non-address types. - enum class DnsQueryType { - UNSPECIFIED, - A, - AAAA, - }; - // Parameter-grouping struct for additional optional parameters for // CreateRequest() calls. All fields are optional and have a reasonable // default. @@ -379,7 +369,6 @@ // // TODO(crbug.com/821021): Delete these methods once all usage has been // converted to the new CreateRequest() API. - static DnsQueryType AddressFamilyToDnsQueryType(AddressFamily address_family); static ResolveHostParameters RequestInfoToResolveHostParameters( const RequestInfo& request_info, RequestPriority priority);
diff --git a/net/dns/host_resolver_impl.cc b/net/dns/host_resolver_impl.cc index 818c55f..47cf9efd 100644 --- a/net/dns/host_resolver_impl.cc +++ b/net/dns/host_resolver_impl.cc
@@ -21,6 +21,7 @@ #include <cmath> #include <limits> #include <memory> +#include <unordered_set> #include <utility> #include <vector> @@ -513,7 +514,7 @@ // Is |dns_server| within the list of known DNS servers that also support // DNS-over-HTTPS? bool DnsServerSupportsDoh(const IPAddress& dns_server) { - const static base::NoDestructor<std::unordered_set<std::string>> + static const base::NoDestructor<std::unordered_set<std::string>> upgradable_servers({ // Google Public DNS "8.8.8.8", "8.8.4.4", "2001:4860:4860::8888", "2001:4860:4860::8844", @@ -805,6 +806,9 @@ net_log_(job_net_log), tick_clock_(tick_clock), weak_ptr_factory_(this) { + // ProcTask only supports resolving addresses. + DCHECK(IsAddressType(key_.dns_query_type)); + DCHECK(callback_); if (!params_.resolver_proc.get()) params_.resolver_proc = HostResolverProc::GetDefault(); @@ -884,9 +888,9 @@ AttemptCompletionCallback completion_callback) { AddressList results; int os_error = 0; - int error = - resolver_proc->Resolve(key.hostname, key.address_family, - key.host_resolver_flags, &results, &os_error); + int error = resolver_proc->Resolve( + key.hostname, DnsQueryTypeToAddressFamily(key.dns_query_type), + key.host_resolver_flags, &results, &os_error); network_task_runner->PostTask( FROM_HERE, base::BindOnce(std::move(completion_callback), results, @@ -1039,52 +1043,41 @@ bool allow_fallback_resolution() const { return allow_fallback_resolution_; } bool needs_two_transactions() const { - return key_.address_family == ADDRESS_FAMILY_UNSPECIFIED; + return key_.dns_query_type == DnsQueryType::UNSPECIFIED; } bool needs_another_transaction() const { - return needs_two_transactions() && !transaction_aaaa_; + return needs_two_transactions() && !transaction2_; } void StartFirstTransaction() { DCHECK_EQ(0u, num_completed_transactions_); + DCHECK(!transaction1_); + net_log_.BeginEvent(NetLogEventType::HOST_RESOLVER_IMPL_DNS_TASK); - if (key_.address_family == ADDRESS_FAMILY_IPV6) { - StartAAAA(); + if (key_.dns_query_type == DnsQueryType::UNSPECIFIED) { + transaction1_ = CreateTransaction(DnsQueryType::A); } else { - StartA(); + transaction1_ = CreateTransaction(key_.dns_query_type); } + transaction1_->Start(); } void StartSecondTransaction() { - DCHECK(needs_two_transactions()); - StartAAAA(); + DCHECK(needs_another_transaction()); + transaction2_ = CreateTransaction(DnsQueryType::AAAA); + transaction2_->Start(); } base::TimeDelta ttl() { return ttl_; } private: - void StartA() { - DCHECK(!transaction_a_); - DCHECK_NE(ADDRESS_FAMILY_IPV6, key_.address_family); - transaction_a_ = CreateTransaction(ADDRESS_FAMILY_IPV4); - transaction_a_->Start(); - } - - void StartAAAA() { - DCHECK(!transaction_aaaa_); - DCHECK_NE(ADDRESS_FAMILY_IPV4, key_.address_family); - transaction_aaaa_ = CreateTransaction(ADDRESS_FAMILY_IPV6); - transaction_aaaa_->Start(); - } - - std::unique_ptr<DnsTransaction> CreateTransaction(AddressFamily family) { - DCHECK_NE(ADDRESS_FAMILY_UNSPECIFIED, family); + std::unique_ptr<DnsTransaction> CreateTransaction( + DnsQueryType dns_query_type) { + DCHECK_NE(DnsQueryType::UNSPECIFIED, dns_query_type); std::unique_ptr<DnsTransaction> trans = client_->GetTransactionFactory()->CreateTransaction( - key_.hostname, - family == ADDRESS_FAMILY_IPV6 ? dns_protocol::kTypeAAAA - : dns_protocol::kTypeA, + key_.hostname, DnsQueryTypeToQtype(dns_query_type), base::BindOnce(&DnsTask::OnTransactionComplete, base::Unretained(this), tick_clock_->NowTicks()), net_log_); @@ -1137,13 +1130,15 @@ } if (transaction->GetType() == dns_protocol::kTypeA) { - DCHECK_EQ(transaction_a_.get(), transaction); + DCHECK_EQ(transaction1_.get(), transaction); // Place IPv4 addresses after IPv6. addr_list_.insert(addr_list_.end(), addr_list.begin(), addr_list.end()); - } else { - DCHECK_EQ(transaction_aaaa_.get(), transaction); + } else if (transaction->GetType() == dns_protocol::kTypeAAAA) { // Place IPv6 addresses before IPv4. addr_list_.insert(addr_list_.begin(), addr_list.begin(), addr_list.end()); + } else { + // TODO(crbug.com/846423): Add result parsing for non-address types. + NOTIMPLEMENTED(); } // If requested via HOST_RESOLVER_CANONNAME, store the canonical name from @@ -1237,8 +1232,8 @@ Delegate* delegate_; const NetLogWithSource net_log_; - std::unique_ptr<DnsTransaction> transaction_a_; - std::unique_ptr<DnsTransaction> transaction_aaaa_; + std::unique_ptr<DnsTransaction> transaction1_; + std::unique_ptr<DnsTransaction> transaction2_; unsigned num_completed_transactions_; @@ -1756,18 +1751,12 @@ DCHECK_EQ(0, key_.host_resolver_flags & ~HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6); - std::vector<HostResolver::DnsQueryType> query_types; - switch (key_.address_family) { - case ADDRESS_FAMILY_UNSPECIFIED: - query_types.push_back(HostResolver::DnsQueryType::A); - query_types.push_back(HostResolver::DnsQueryType::AAAA); - break; - case ADDRESS_FAMILY_IPV4: - query_types.push_back(HostResolver::DnsQueryType::A); - break; - case ADDRESS_FAMILY_IPV6: - query_types.push_back(HostResolver::DnsQueryType::AAAA); - break; + std::vector<DnsQueryType> query_types; + if (key_.dns_query_type == DnsQueryType::UNSPECIFIED) { + query_types.push_back(DnsQueryType::A); + query_types.push_back(DnsQueryType::AAAA); + } else { + query_types.push_back(key_.dns_query_type); } mdns_task_ = std::make_unique<HostResolverMdnsTask>( @@ -1814,19 +1803,22 @@ if (had_non_speculative_request_) { category = RESOLVE_SUCCESS; UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ResolveSuccessTime", duration); - switch (key_.address_family) { - case ADDRESS_FAMILY_IPV4: + switch (key_.dns_query_type) { + case DnsQueryType::A: UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ResolveSuccessTime.IPV4", duration); break; - case ADDRESS_FAMILY_IPV6: + case DnsQueryType::AAAA: UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ResolveSuccessTime.IPV6", duration); break; - case ADDRESS_FAMILY_UNSPECIFIED: + case DnsQueryType::UNSPECIFIED: UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ResolveSuccessTime.UNSPEC", duration); break; + default: + // No histogram for other query types. + break; } } else { category = RESOLVE_SPECULATIVE_SUCCESS; @@ -1839,19 +1831,22 @@ if (had_non_speculative_request_) { category = RESOLVE_FAIL; UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ResolveFailureTime", duration); - switch (key_.address_family) { - case ADDRESS_FAMILY_IPV4: + switch (key_.dns_query_type) { + case DnsQueryType::A: UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ResolveFailureTime.IPV4", duration); break; - case ADDRESS_FAMILY_IPV6: + case DnsQueryType::AAAA: UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ResolveFailureTime.IPV6", duration); break; - case ADDRESS_FAMILY_UNSPECIFIED: + case DnsQueryType::UNSPECIFIED: UMA_HISTOGRAM_LONG_TIMES_100("Net.DNS.ResolveFailureTime.UNSPEC", duration); break; + default: + // No histogram for other query types. + break; } } else { category = RESOLVE_SPECULATIVE_FAIL; @@ -2483,13 +2478,13 @@ AddressList* addresses) { DCHECK(addresses); DCHECK(net_error); - if (ip_address == nullptr) + if (ip_address == nullptr || !IsAddressType(key.dns_query_type)) return false; *net_error = OK; AddressFamily family = GetAddressFamily(*ip_address); - if (key.address_family != ADDRESS_FAMILY_UNSPECIFIED && - key.address_family != family) { + if (key.dns_query_type != DnsQueryType::UNSPECIFIED && + key.dns_query_type != AddressFamilyToDnsQueryType(family)) { // Don't return IPv6 addresses for IPv4 queries, and vice versa. *net_error = ERR_NAME_NOT_RESOLVED; } else { @@ -2547,15 +2542,15 @@ // flexibility, but lose implicit ordering. // We prefer IPv6 because "happy eyeballs" will fall back to IPv4 if // necessary. - if (key.address_family == ADDRESS_FAMILY_IPV6 || - key.address_family == ADDRESS_FAMILY_UNSPECIFIED) { + if (key.dns_query_type == DnsQueryType::AAAA || + key.dns_query_type == DnsQueryType::UNSPECIFIED) { auto it = hosts.find(DnsHostsKey(hostname, ADDRESS_FAMILY_IPV6)); if (it != hosts.end()) addresses->push_back(IPEndPoint(it->second, host_port)); } - if (key.address_family == ADDRESS_FAMILY_IPV4 || - key.address_family == ADDRESS_FAMILY_UNSPECIFIED) { + if (key.dns_query_type == DnsQueryType::A || + key.dns_query_type == DnsQueryType::UNSPECIFIED) { auto it = hosts.find(DnsHostsKey(hostname, ADDRESS_FAMILY_IPV4)); if (it != hosts.end()) addresses->push_back(IPEndPoint(it->second, host_port)); @@ -2567,7 +2562,7 @@ HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6) && IsAllIPv4Loopback(*addresses)) { Key new_key(key); - new_key.address_family = ADDRESS_FAMILY_UNSPECIFIED; + new_key.dns_query_type = DnsQueryType::UNSPECIFIED; new_key.host_resolver_flags &= ~HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6; return ServeFromHosts(new_key, host_port, addresses); @@ -2584,20 +2579,23 @@ addresses->clear(); - for (const auto& address : resolved_addresses) { - // Include the address if: - // - caller didn't specify an address family, or - // - caller specifically asked for the address family of this address, or - // - this is an IPv6 address and caller specifically asked for IPv4 due - // to lack of detected IPv6 support. (See SystemHostResolverCall for - // rationale). - if (key.address_family == ADDRESS_FAMILY_UNSPECIFIED || - key.address_family == address.GetFamily() || - (address.GetFamily() == ADDRESS_FAMILY_IPV6 && - key.address_family == ADDRESS_FAMILY_IPV4 && - (key.host_resolver_flags & - HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6))) { - addresses->push_back(address); + if (IsAddressType(key.dns_query_type)) { + for (const auto& address : resolved_addresses) { + // Include the address if: + // - caller didn't specify an address family, or + // - caller specifically asked for the address family of this address, or + // - this is an IPv6 address and caller specifically asked for IPv4 due + // to lack of detected IPv6 support. (See SystemHostResolverCall for + // rationale). + if (key.dns_query_type == DnsQueryType::UNSPECIFIED || + DnsQueryTypeToAddressFamily(key.dns_query_type) == + address.GetFamily() || + (address.GetFamily() == ADDRESS_FAMILY_IPV6 && + key.dns_query_type == DnsQueryType::A && + (key.host_resolver_flags & + HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6))) { + addresses->push_back(address); + } } } @@ -2665,22 +2663,21 @@ const NetLogWithSource& net_log) { HostResolverFlags effective_flags = flags | additional_resolver_flags_; - AddressFamily effective_address_family = - DnsQueryTypeToAddressFamily(dns_query_type); + DnsQueryType effective_query_type = dns_query_type; - if (effective_address_family == ADDRESS_FAMILY_UNSPECIFIED && + if (effective_query_type == DnsQueryType::UNSPECIFIED && // When resolving IPv4 literals, there's no need to probe for IPv6. // When resolving IPv6 literals, there's no benefit to artificially // limiting our resolution based on a probe. Prior logic ensures - // that this query is UNSPECIFIED (see effective_address_family - // check above) so the code requesting the resolution should be amenable - // to receiving a IPv6 resolution. + // that this query is UNSPECIFIED (see effective_query_type check above) + // so the code requesting the resolution should be amenable to receiving a + // IPv6 resolution. !use_local_ipv6_ && ip_address == nullptr && !IsIPv6Reachable(net_log)) { - effective_address_family = ADDRESS_FAMILY_IPV4; + effective_query_type = DnsQueryType::A; effective_flags |= HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6; } - return Key(hostname, effective_address_family, effective_flags, source); + return Key(hostname, effective_query_type, effective_flags, source); } bool HostResolverImpl::IsIPv6Reachable(const NetLogWithSource& net_log) {
diff --git a/net/dns/host_resolver_impl.h b/net/dns/host_resolver_impl.h index c527504..ff2c0a2 100644 --- a/net/dns/host_resolver_impl.h +++ b/net/dns/host_resolver_impl.h
@@ -24,6 +24,7 @@ #include "net/dns/host_cache.h" #include "net/dns/host_resolver.h" #include "net/dns/host_resolver_proc.h" +#include "net/dns/public/dns_query_type.h" #include "net/url_request/url_request_context.h" #include "url/gurl.h"
diff --git a/net/dns/host_resolver_impl_unittest.cc b/net/dns/host_resolver_impl_unittest.cc index 82f17cf..1c65e37d 100644 --- a/net/dns/host_resolver_impl_unittest.cc +++ b/net/dns/host_resolver_impl_unittest.cc
@@ -36,6 +36,7 @@ #include "net/dns/dns_client.h" #include "net/dns/dns_config.h" #include "net/dns/dns_test_util.h" +#include "net/dns/dns_util.h" #include "net/dns/mock_host_resolver.h" #include "net/dns/mock_mdns_client.h" #include "net/dns/mock_mdns_socket_factory.h" @@ -725,8 +726,10 @@ const HostCache::Entry* GetCacheEntry(const Request& req) { DCHECK(resolver_.get() && resolver_->GetHostCache()); - const HostCache::Key key(req.info().hostname(), req.info().address_family(), - req.info().host_resolver_flags()); + const HostCache::Key key( + req.info().hostname(), + AddressFamilyToDnsQueryType(req.info().address_family()), + req.info().host_resolver_flags(), HostResolverSource::ANY); return resolver_->GetHostCache()->LookupStale(key, base::TimeTicks(), nullptr); } @@ -782,11 +785,11 @@ HostResolver::ResolveHostParameters parameters; - parameters.dns_query_type = HostResolver::DnsQueryType::A; + parameters.dns_query_type = DnsQueryType::A; ResolveHostResponseHelper v4_response(resolver_->CreateRequest( HostPortPair("host", 80), NetLogWithSource(), parameters)); - parameters.dns_query_type = HostResolver::DnsQueryType::AAAA; + parameters.dns_query_type = DnsQueryType::AAAA; ResolveHostResponseHelper v6_response(resolver_->CreateRequest( HostPortPair("host", 80), NetLogWithSource(), parameters)); @@ -827,14 +830,14 @@ TEST_F(HostResolverImplTest, LocalhostIPV4IPV6Lookup_ResolveHost) { HostResolver::ResolveHostParameters parameters; - parameters.dns_query_type = HostResolver::DnsQueryType::A; + parameters.dns_query_type = DnsQueryType::A; ResolveHostResponseHelper v6_v4_response(resolver_->CreateRequest( HostPortPair("localhost6", 80), NetLogWithSource(), parameters)); EXPECT_THAT(v6_v4_response.result_error(), IsOk()); EXPECT_THAT(v6_v4_response.request()->GetAddressResults().value().endpoints(), testing::IsEmpty()); - parameters.dns_query_type = HostResolver::DnsQueryType::AAAA; + parameters.dns_query_type = DnsQueryType::AAAA; ResolveHostResponseHelper v6_v6_response(resolver_->CreateRequest( HostPortPair("localhost6", 80), NetLogWithSource(), parameters)); EXPECT_THAT(v6_v6_response.result_error(), IsOk()); @@ -848,14 +851,14 @@ v6_unsp_response.request()->GetAddressResults().value().endpoints(), testing::ElementsAre(CreateExpected("::1", 80))); - parameters.dns_query_type = HostResolver::DnsQueryType::A; + parameters.dns_query_type = DnsQueryType::A; ResolveHostResponseHelper v4_v4_response(resolver_->CreateRequest( HostPortPair("localhost", 80), NetLogWithSource(), parameters)); EXPECT_THAT(v4_v4_response.result_error(), IsOk()); EXPECT_THAT(v4_v4_response.request()->GetAddressResults().value().endpoints(), testing::ElementsAre(CreateExpected("127.0.0.1", 80))); - parameters.dns_query_type = HostResolver::DnsQueryType::AAAA; + parameters.dns_query_type = DnsQueryType::AAAA; ResolveHostResponseHelper v4_v6_response(resolver_->CreateRequest( HostPortPair("localhost", 80), NetLogWithSource(), parameters)); EXPECT_THAT(v4_v6_response.result_error(), IsOk()); @@ -2440,10 +2443,10 @@ // passed in. TEST_F(HostResolverImplTest, AddressFamilyWithRawIPs_ResolveHost) { HostResolver::ResolveHostParameters v4_parameters; - v4_parameters.dns_query_type = HostResolver::DnsQueryType::A; + v4_parameters.dns_query_type = DnsQueryType::A; HostResolver::ResolveHostParameters v6_parameters; - v6_parameters.dns_query_type = HostResolver::DnsQueryType::AAAA; + v6_parameters.dns_query_type = DnsQueryType::AAAA; ResolveHostResponseHelper v4_v4_request(resolver_->CreateRequest( HostPortPair("127.0.0.1", 80), NetLogWithSource(), v4_parameters)); @@ -3125,7 +3128,7 @@ EXPECT_CALL(*socket_factory_ptr, OnSendTo(_)).Times(2); HostResolver::ResolveHostParameters parameters; - parameters.dns_query_type = HostResolver::DnsQueryType::AAAA; + parameters.dns_query_type = DnsQueryType::AAAA; parameters.source = HostResolverSource::MULTICAST_DNS; ResolveHostResponseHelper response(resolver_->CreateRequest( @@ -3150,7 +3153,7 @@ EXPECT_CALL(*socket_factory_ptr, OnSendTo(_)).Times(2); HostResolver::ResolveHostParameters parameters; - parameters.dns_query_type = HostResolver::DnsQueryType::AAAA; + parameters.dns_query_type = DnsQueryType::AAAA; parameters.source = HostResolverSource::MULTICAST_DNS; ResolveHostResponseHelper response(resolver_->CreateRequest( @@ -4093,7 +4096,7 @@ // Requests with specified DNS query type. HostResolver::ResolveHostParameters parameters; - parameters.dns_query_type = HostResolver::DnsQueryType::A; + parameters.dns_query_type = DnsQueryType::A; ResolveHostResponseHelper response_specified_ipv4(resolver_->CreateRequest( HostPortPair("nx_ipv4", 80), NetLogWithSource(), parameters)); EXPECT_THAT(response_specified_ipv4.result_error(), IsOk()); @@ -4103,7 +4106,7 @@ .endpoints(), testing::ElementsAre(CreateExpected("127.0.0.1", 80))); - parameters.dns_query_type = HostResolver::DnsQueryType::AAAA; + parameters.dns_query_type = DnsQueryType::AAAA; ResolveHostResponseHelper response_specified_ipv6(resolver_->CreateRequest( HostPortPair("nx_ipv6", 80), NetLogWithSource(), parameters)); EXPECT_THAT(response_specified_ipv6.result_error(), IsOk()); @@ -5491,10 +5494,10 @@ ResolveHostResponseHelper response(resolver_->CreateRequest( HostPortPair("h1", 80), NetLogWithSource(), base::nullopt)); HostResolver::ResolveHostParameters parameters; - parameters.dns_query_type = HostResolver::DnsQueryType::A; + parameters.dns_query_type = DnsQueryType::A; ResolveHostResponseHelper v4_response(resolver_->CreateRequest( HostPortPair("h1", 80), NetLogWithSource(), parameters)); - parameters.dns_query_type = HostResolver::DnsQueryType::AAAA; + parameters.dns_query_type = DnsQueryType::AAAA; ResolveHostResponseHelper v6_response(resolver_->CreateRequest( HostPortPair("h1", 80), NetLogWithSource(), parameters)); @@ -5520,10 +5523,10 @@ ResolveHostResponseHelper no_wifi_response(resolver_->CreateRequest( HostPortPair("h1", 80), NetLogWithSource(), base::nullopt)); - parameters.dns_query_type = HostResolver::DnsQueryType::A; + parameters.dns_query_type = DnsQueryType::A; ResolveHostResponseHelper no_wifi_v4_response(resolver_->CreateRequest( HostPortPair("h1", 80), NetLogWithSource(), parameters)); - parameters.dns_query_type = HostResolver::DnsQueryType::AAAA; + parameters.dns_query_type = DnsQueryType::AAAA; ResolveHostResponseHelper no_wifi_v6_response(resolver_->CreateRequest( HostPortPair("h1", 80), NetLogWithSource(), parameters)); @@ -5554,7 +5557,8 @@ EXPECT_THAT(request->Resolve(), IsError(ERR_IO_PENDING)); EXPECT_THAT(request->WaitForResult(), IsError(ERR_NAME_NOT_RESOLVED)); EXPECT_THAT(request->NumberOfAddresses(), 0); - HostCache::Key key(request->info().hostname(), ADDRESS_FAMILY_UNSPECIFIED, 0); + HostCache::Key key(request->info().hostname(), DnsQueryType::UNSPECIFIED, 0, + HostResolverSource::ANY); HostCache::EntryStaleness staleness; const HostCache::Entry* cache_entry = resolver_->GetHostCache()->Lookup(key, base::TimeTicks::Now()); @@ -5567,8 +5571,8 @@ EXPECT_THAT(request->Resolve(), IsError(ERR_IO_PENDING)); EXPECT_THAT(request->WaitForResult(), IsError(ERR_NAME_NOT_RESOLVED)); EXPECT_THAT(request->NumberOfAddresses(), 0); - HostCache::Key nxkey(request->info().hostname(), ADDRESS_FAMILY_UNSPECIFIED, - 0); + HostCache::Key nxkey(request->info().hostname(), DnsQueryType::UNSPECIFIED, 0, + HostResolverSource::ANY); cache_entry = resolver_->GetHostCache()->Lookup(nxkey, base::TimeTicks::Now()); EXPECT_TRUE(!!cache_entry); @@ -5586,7 +5590,8 @@ HostPortPair("empty", 80), NetLogWithSource(), base::nullopt)); EXPECT_THAT(no_data_response.result_error(), IsError(ERR_NAME_NOT_RESOLVED)); EXPECT_FALSE(no_data_response.request()->GetAddressResults()); - HostCache::Key key("empty", ADDRESS_FAMILY_UNSPECIFIED, 0); + HostCache::Key key("empty", DnsQueryType::UNSPECIFIED, 0, + HostResolverSource::ANY); HostCache::EntryStaleness staleness; const HostCache::Entry* cache_entry = resolver_->GetHostCache()->Lookup(key, base::TimeTicks::Now()); @@ -5600,7 +5605,8 @@ EXPECT_THAT(no_domain_response.result_error(), IsError(ERR_NAME_NOT_RESOLVED)); EXPECT_FALSE(no_domain_response.request()->GetAddressResults()); - HostCache::Key nxkey("nodomain", ADDRESS_FAMILY_UNSPECIFIED, 0); + HostCache::Key nxkey("nodomain", DnsQueryType::UNSPECIFIED, 0, + HostResolverSource::ANY); cache_entry = resolver_->GetHostCache()->Lookup(nxkey, base::TimeTicks::Now()); EXPECT_TRUE(!!cache_entry); @@ -5693,7 +5699,7 @@ ChangeDnsConfig(CreateValidDnsConfig()); set_allow_fallback_to_proctask(false); HostResolver::ResolveHostParameters params; - params.dns_query_type = HostResolver::DnsQueryType::A; + params.dns_query_type = DnsQueryType::A; params.include_canonical_name = true; ResolveHostResponseHelper response(resolver_->CreateRequest( HostPortPair("alias", 80), NetLogWithSource(), params)); @@ -6187,7 +6193,7 @@ HostResolverImpl::MODE_FOR_HISTOGRAM_ASYNC_DNS); // Test upgradability is detected for async DNS. - const static std::vector<const char*> upgradable_servers( + static const std::vector<const char*> upgradable_servers( {// Google Public DNS "8.8.8.8", "8.8.4.4", "2001:4860:4860::8888", "2001:4860:4860::8844", // Cloudflare DNS
diff --git a/net/dns/host_resolver_mdns_task.cc b/net/dns/host_resolver_mdns_task.cc index 4ca031d..5f7d82f 100644 --- a/net/dns/host_resolver_mdns_task.cc +++ b/net/dns/host_resolver_mdns_task.cc
@@ -18,7 +18,7 @@ class HostResolverMdnsTask::Transaction { public: - Transaction(HostResolver::DnsQueryType query_type, HostResolverMdnsTask* task) + Transaction(DnsQueryType query_type, HostResolverMdnsTask* task) : query_type_(query_type), result_(ERR_IO_PENDING), task_(task) {} void Start() { @@ -28,20 +28,6 @@ DCHECK_EQ(ERR_IO_PENDING, result_); DCHECK(!async_transaction_); - uint16_t rrtype; - switch (query_type_) { - case net::HostResolver::DnsQueryType::A: - rrtype = net::dns_protocol::kTypeA; - break; - case net::HostResolver::DnsQueryType::AAAA: - rrtype = net::dns_protocol::kTypeAAAA; - break; - default: - // Type not supported for MDNS. - NOTREACHED(); - return; - } - // TODO(crbug.com/846423): Use |allow_cached_response| to set the // QUERY_CACHE flag or not. int flags = MDnsTransaction::SINGLE_RESULT | MDnsTransaction::QUERY_CACHE | @@ -50,7 +36,7 @@ // cancel and prevent invocation of OnComplete. std::unique_ptr<MDnsTransaction> inner_transaction = task_->mdns_client_->CreateTransaction( - rrtype, task_->hostname_, flags, + DnsQueryTypeToQtype(query_type_), task_->hostname_, flags, base::BindRepeating(&HostResolverMdnsTask::Transaction::OnComplete, base::Unretained(this))); @@ -97,16 +83,17 @@ if (result_ == net::OK) { switch (query_type_) { - case net::HostResolver::DnsQueryType::A: + case DnsQueryType::A: task_->result_addresses_.push_back( IPEndPoint(parsed->rdata<net::ARecordRdata>()->address(), 0)); break; - case net::HostResolver::DnsQueryType::AAAA: + case DnsQueryType::AAAA: task_->result_addresses_.push_back( IPEndPoint(parsed->rdata<net::AAAARecordRdata>()->address(), 0)); break; default: - NOTREACHED(); + // TODO(crbug.com/846423): Add result parsing for non-address types. + NOTIMPLEMENTED(); } } @@ -116,7 +103,7 @@ task_->CheckCompletion(!async_transaction_); } - const HostResolver::DnsQueryType query_type_; + const DnsQueryType query_type_; // ERR_IO_PENDING until transaction completes (or is cancelled). int result_; @@ -132,10 +119,10 @@ HostResolverMdnsTask::HostResolverMdnsTask( MDnsClient* mdns_client, const std::string& hostname, - const std::vector<HostResolver::DnsQueryType>& query_types) + const std::vector<DnsQueryType>& query_types) : mdns_client_(mdns_client), hostname_(hostname), weak_ptr_factory_(this) { DCHECK(!query_types.empty()); - for (HostResolver::DnsQueryType query_type : query_types) { + for (DnsQueryType query_type : query_types) { transactions_.emplace_back(query_type, this); } }
diff --git a/net/dns/host_resolver_mdns_task.h b/net/dns/host_resolver_mdns_task.h index eebf5ffc..90d3a7c 100644 --- a/net/dns/host_resolver_mdns_task.h +++ b/net/dns/host_resolver_mdns_task.h
@@ -16,6 +16,7 @@ #include "net/base/completion_once_callback.h" #include "net/dns/host_resolver.h" #include "net/dns/mdns_client.h" +#include "net/dns/public/dns_query_type.h" namespace net { @@ -25,10 +26,9 @@ class HostResolverMdnsTask { public: // |mdns_client| must outlive |this|. - HostResolverMdnsTask( - MDnsClient* mdns_client, - const std::string& hostname, - const std::vector<HostResolver::DnsQueryType>& query_types); + HostResolverMdnsTask(MDnsClient* mdns_client, + const std::string& hostname, + const std::vector<DnsQueryType>& query_types); ~HostResolverMdnsTask(); // Starts the task. |completion_callback| will be called asynchronously with
diff --git a/net/dns/mock_host_resolver.cc b/net/dns/mock_host_resolver.cc index b5382ab1..6a03108 100644 --- a/net/dns/mock_host_resolver.cc +++ b/net/dns/mock_host_resolver.cc
@@ -269,8 +269,9 @@ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); next_request_id_++; int rv = ResolveFromIPLiteralOrCache( - info.host_port_pair(), info.address_family(), info.host_resolver_flags(), - HostResolverSource::ANY, info.allow_cached_response(), addresses); + info.host_port_pair(), AddressFamilyToDnsQueryType(info.address_family()), + info.host_resolver_flags(), HostResolverSource::ANY, + info.allow_cached_response(), addresses); return rv; } @@ -283,9 +284,9 @@ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); next_request_id_++; int rv = ResolveFromIPLiteralOrCache( - info.host_port_pair(), info.address_family(), info.host_resolver_flags(), - HostResolverSource::ANY, info.allow_cached_response(), addresses, - stale_info); + info.host_port_pair(), AddressFamilyToDnsQueryType(info.address_family()), + info.host_resolver_flags(), HostResolverSource::ANY, + info.allow_cached_response(), addresses, stale_info); return rv; } @@ -346,8 +347,7 @@ num_resolve_++; AddressList addresses; int rv = ResolveFromIPLiteralOrCache( - request->request_host(), - DnsQueryTypeToAddressFamily(request->parameters().dns_query_type), + request->request_host(), request->parameters().dns_query_type, request->host_resolver_flags(), request->parameters().source, request->parameters().allow_cached_response, &addresses); if (rv == OK && !request->parameters().is_speculative) @@ -387,7 +387,7 @@ int MockHostResolverBase::ResolveFromIPLiteralOrCache( const HostPortPair& host, - AddressFamily requested_address_family, + DnsQueryType dns_query_type, HostResolverFlags flags, HostResolverSource source, bool allow_cache, @@ -396,8 +396,9 @@ IPAddress ip_address; if (ip_address.AssignFromIPLiteral(host.host())) { // This matches the behavior HostResolverImpl. - if (requested_address_family != ADDRESS_FAMILY_UNSPECIFIED && - requested_address_family != GetAddressFamily(ip_address)) { + if (dns_query_type != DnsQueryType::UNSPECIFIED && + dns_query_type != + AddressFamilyToDnsQueryType(GetAddressFamily(ip_address))) { return ERR_NAME_NOT_RESOLVED; } @@ -408,7 +409,7 @@ } int rv = ERR_DNS_CACHE_MISS; if (cache_.get() && allow_cache) { - HostCache::Key key(host.host(), requested_address_family, flags, source); + HostCache::Key key(host.host(), dns_query_type, flags, source); const HostCache::Entry* entry; if (stale_info) entry = cache_->LookupStale(key, tick_clock_->NowTicks(), stale_info); @@ -434,7 +435,9 @@ int rv = rules_map_[source]->Resolve(host.host(), requested_address_family, flags, &addr, nullptr); if (cache_.get()) { - HostCache::Key key(host.host(), requested_address_family, flags, source); + HostCache::Key key(host.host(), + AddressFamilyToDnsQueryType(requested_address_family), + flags, source); // Storing a failure with TTL 0 so that it overwrites previous value. base::TimeDelta ttl; if (rv == OK)
diff --git a/net/dns/mock_host_resolver.h b/net/dns/mock_host_resolver.h index 9cabbb4..694a6859 100644 --- a/net/dns/mock_host_resolver.h +++ b/net/dns/mock_host_resolver.h
@@ -21,6 +21,7 @@ #include "net/dns/host_resolver.h" #include "net/dns/host_resolver_proc.h" #include "net/dns/host_resolver_source.h" +#include "net/dns/public/dns_query_type.h" namespace base { class TickClock; @@ -176,7 +177,7 @@ // DNS_CACHE_MISS if failed. int ResolveFromIPLiteralOrCache( const HostPortPair& host, - AddressFamily requested_address_family, + DnsQueryType dns_query_type, HostResolverFlags flags, HostResolverSource source, bool allow_cache,
diff --git a/net/dns/public/BUILD.gn b/net/dns/public/BUILD.gn index 6f4b9a73..afe91da 100644 --- a/net/dns/public/BUILD.gn +++ b/net/dns/public/BUILD.gn
@@ -9,10 +9,14 @@ visibility = [ "//net", "//net/dns:dns_client", + "//net/dns:host_resolver", + "//net/dns:host_resolver_impl", ] sources = [ "dns_protocol.h", + "dns_query_type.cc", + "dns_query_type.h", "util.cc", "util.h", ]
diff --git a/net/dns/public/dns_query_type.cc b/net/dns/public/dns_query_type.cc new file mode 100644 index 0000000..ce8f149 --- /dev/null +++ b/net/dns/public/dns_query_type.cc
@@ -0,0 +1,17 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/dns/public/dns_query_type.h" + +namespace net { + +bool IsAddressType(DnsQueryType dns_query_type) { + // HostResolver treats UNSPECIFIED as A and/or AAAA depending on IPv4/IPv6 + // settings, so it is here considered an address type. + return dns_query_type == DnsQueryType::UNSPECIFIED || + dns_query_type == DnsQueryType::A || + dns_query_type == DnsQueryType::AAAA; +} + +} // namespace net
diff --git a/net/dns/public/dns_query_type.h b/net/dns/public/dns_query_type.h new file mode 100644 index 0000000..87abca31 --- /dev/null +++ b/net/dns/public/dns_query_type.h
@@ -0,0 +1,29 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_DNS_PUBLIC_DNS_QUERY_TYPE_H_ +#define NET_DNS_PUBLIC_DNS_QUERY_TYPE_H_ + +#include "net/base/net_export.h" + +namespace net { + +// DNS query type for HostResolver requests. +// See: +// https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4 +// +// TODO(crbug.com/846423): Add support for non-address types. +enum class DnsQueryType { + UNSPECIFIED, + A, + AAAA, +}; + +// |true| iff |dns_query_type| is an address-resulting type, convertable to and +// from net::AddressFamily. +bool NET_EXPORT IsAddressType(DnsQueryType dns_query_type); + +} // namespace net + +#endif // NET_DNS_PUBLIC_DNS_QUERY_TYPE_H_
diff --git a/net/socket/ssl_client_socket_impl.cc b/net/socket/ssl_client_socket_impl.cc index fe71b688..dc7f6cd0 100644 --- a/net/socket/ssl_client_socket_impl.cc +++ b/net/socket/ssl_client_socket_impl.cc
@@ -845,7 +845,9 @@ break; } - if (!base::FeatureList::IsEnabled(features::kEnforceTLS13Downgrade)) { + if (!base::FeatureList::IsEnabled(features::kEnforceTLS13Downgrade) || + base::GetFieldTrialParamByFeatureAsBool(features::kEnforceTLS13Downgrade, + "known_roots_only", false)) { SSL_set_ignore_tls13_downgrade(ssl_.get(), 1); } @@ -1141,17 +1143,21 @@ } } - if (!base::FeatureList::IsEnabled(features::kEnforceTLS13Downgrade)) { + bool enforce_tls13_downgrade_known_roots_only = + base::GetFieldTrialParamByFeatureAsBool( + features::kEnforceTLS13Downgrade, "known_roots_only", false); + if (!base::FeatureList::IsEnabled(features::kEnforceTLS13Downgrade) || + enforce_tls13_downgrade_known_roots_only) { // Record metrics on the TLS 1.3 anti-downgrade mechanism. This is only // recorded when enforcement is disabled. (When enforcement is enabled, // the connection will fail with ERR_TLS13_DOWNGRADE_DETECTED.) See // https://crbug.com/boringssl/226. // // Record metrics for both servers overall and the TLS 1.3 experiment - // set. These metrics are only useful on TLS 1.3 servers, so the latter is - // more precise, but there is a large enough TLS 1.3 deployment that the - // overall numbers may be more robust. In particular, the DowngradeType - // metrics do not need to be filtered. + // set. These metrics are only useful on TLS 1.3 servers, so the latter + // is more precise, but there is a large enough TLS 1.3 deployment that + // the overall numbers may be more robust. In particular, the + // DowngradeType metrics do not need to be filtered. bool is_downgrade = !!SSL_is_tls13_downgrade(ssl_.get()); UMA_HISTOGRAM_BOOLEAN("Net.SSLTLS13Downgrade", is_downgrade); bool is_tls13_experiment_host = @@ -1165,7 +1171,8 @@ // Record whether connections which hit the downgrade used known vs // unknown roots and which key exchange type. - // This enum is persisted into histograms. Values may not be renumbered. + // This enum is persisted into histograms. Values may not be + // renumbered. enum class DowngradeType { kKnownRootRSA = 0, kKnownRootECDHE = 1, @@ -1190,6 +1197,14 @@ type); } } + + if (enforce_tls13_downgrade_known_roots_only && + server_cert_verify_result_.is_issued_by_known_root) { + // Exit DoHandshakeLoop and return the result to the caller to + // Connect. + DCHECK_EQ(STATE_NONE, next_handshake_state_); + return ERR_TLS13_DOWNGRADE_DETECTED; + } } }
diff --git a/net/socket/ssl_client_socket_unittest.cc b/net/socket/ssl_client_socket_unittest.cc index 7f06dd4..bb68f2e4 100644 --- a/net/socket/ssl_client_socket_unittest.cc +++ b/net/socket/ssl_client_socket_unittest.cc
@@ -4846,6 +4846,64 @@ SSLConnectionStatusToVersion(info.connection_status)); } +// Test downgrade enforcement enforces known roots when configured to. +TEST_F(SSLClientSocketTest, TLS13DowngradeEnforcedKnownKnown) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeatureWithParameters( + features::kEnforceTLS13Downgrade, {{"known_roots_only", "true"}}); + + SpawnedTestServer::SSLOptions ssl_options; + ssl_options.simulate_tls13_downgrade = true; + ssl_options.tls_max_version = + SpawnedTestServer::SSLOptions::TLS_MAX_VERSION_TLS1_2; + ASSERT_TRUE(StartTestServer(ssl_options)); + + scoped_refptr<X509Certificate> server_cert = + spawned_test_server()->GetCertificate(); + + // Certificate is trusted and chains to a public root. + CertVerifyResult verify_result; + verify_result.is_issued_by_known_root = true; + verify_result.verified_cert = server_cert; + cert_verifier_->AddResultForCert(server_cert.get(), verify_result, OK); + + SSLConfig config; + config.version_max = SSL_PROTOCOL_VERSION_TLS1_3; + int rv; + ASSERT_TRUE(CreateAndConnectSSLClientSocket(config, &rv)); + EXPECT_THAT(rv, IsError(ERR_TLS13_DOWNGRADE_DETECTED)); + EXPECT_FALSE(sock_->IsConnected()); +} + +// Test downgrade enforcement ignores unknown roots when configured to. +TEST_F(SSLClientSocketTest, TLS13DowngradeEnforcedKnownUnknown) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeatureWithParameters( + features::kEnforceTLS13Downgrade, {{"known_roots_only", "true"}}); + + SpawnedTestServer::SSLOptions ssl_options; + ssl_options.simulate_tls13_downgrade = true; + ssl_options.tls_max_version = + SpawnedTestServer::SSLOptions::TLS_MAX_VERSION_TLS1_2; + ASSERT_TRUE(StartTestServer(ssl_options)); + + scoped_refptr<X509Certificate> server_cert = + spawned_test_server()->GetCertificate(); + + // Certificate is trusted and chains to a public root. + CertVerifyResult verify_result; + verify_result.is_issued_by_known_root = false; + verify_result.verified_cert = server_cert; + cert_verifier_->AddResultForCert(server_cert.get(), verify_result, OK); + + SSLConfig config; + config.version_max = SSL_PROTOCOL_VERSION_TLS1_3; + int rv; + ASSERT_TRUE(CreateAndConnectSSLClientSocket(config, &rv)); + EXPECT_THAT(rv, IsOk()); + EXPECT_TRUE(sock_->IsConnected()); +} + struct TLS13DowngradeMetricsParams { bool downgrade; bool known_root;
diff --git a/services/media_session/audio_focus_manager.cc b/services/media_session/audio_focus_manager.cc index 63a6fa2..f91f0f2 100644 --- a/services/media_session/audio_focus_manager.cc +++ b/services/media_session/audio_focus_manager.cc
@@ -106,6 +106,15 @@ const std::string& source_name() const { return source_name_; } + mojom::AudioFocusRequestStatePtr ToAudioFocusRequestState() const { + auto request = mojom::AudioFocusRequestState::New(); + request->session_info = session_info_.Clone(); + request->audio_focus_type = audio_focus_type_; + request->request_id = id_; + request->source_name = source_name_; + return request; + } + private: void OnConnectionError() { // Since we have multiple pathways that can call |OnConnectionError| we @@ -158,14 +167,8 @@ void AudioFocusManager::GetFocusRequests(GetFocusRequestsCallback callback) { std::vector<mojom::AudioFocusRequestStatePtr> requests; - for (const auto& row : audio_focus_stack_) { - auto request = mojom::AudioFocusRequestState::New(); - request->session_info = row->info().Clone(); - request->audio_focus_type = row->audio_focus_type(); - request->request_id = row->id(); - request->source_name = row->source_name(); - requests.push_back(std::move(request)); - } + for (const auto& row : audio_focus_stack_) + requests.push_back(row->ToAudioFocusRequestState()); std::move(callback).Run(std::move(requests)); } @@ -190,7 +193,7 @@ if (audio_focus_stack_.back()->id() != id) { RemoveFocusEntryIfPresent(id); - active_media_controller_.SetMediaSession(GetActiveGainSession()); + MaybeUpdateActiveSession(); return; } @@ -203,14 +206,14 @@ observer->OnFocusLost(row->info().Clone()); }); - active_media_controller_.SetMediaSession(GetActiveGainSession()); + MaybeUpdateActiveSession(); return; } if (IsAudioFocusEnforcementEnabled()) EnforceAudioFocusAbandon(row->audio_focus_type()); - active_media_controller_.SetMediaSession(GetActiveGainSession()); + MaybeUpdateActiveSession(); // Notify observers that we lost audio focus. observers_.ForAllPtrs([&row](mojom::AudioFocusObserver* observer) { @@ -268,7 +271,7 @@ row->SetAudioFocusType(type); audio_focus_stack_.push_back(std::move(row)); - active_media_controller_.SetMediaSession(GetActiveGainSession()); + MaybeUpdateActiveSession(); // Notify observers that we were gained audio focus. mojom::MediaSessionInfoPtr session_info = @@ -353,14 +356,29 @@ } } -mojom::MediaSession* AudioFocusManager::GetActiveGainSession() const { +void AudioFocusManager::MaybeUpdateActiveSession() { + StackRow* active = nullptr; + for (auto& row : base::Reversed(audio_focus_stack_)) { if (row->audio_focus_type() != mojom::AudioFocusType::kGain) continue; - return row->session(); + + active = row.get(); + break; } - return nullptr; + if (!active_media_controller_.SetMediaSession(active ? active->session() + : nullptr)) { + return; + } + + mojom::AudioFocusRequestStatePtr state = + active ? active->ToAudioFocusRequestState() : nullptr; + + // Notify observers that the active media session changed. + observers_.ForAllPtrs([&state](mojom::AudioFocusObserver* observer) { + observer->OnActiveSessionChanged(state.Clone()); + }); } AudioFocusManager::AudioFocusManager() {
diff --git a/services/media_session/audio_focus_manager.h b/services/media_session/audio_focus_manager.h index 2218913..17a2184 100644 --- a/services/media_session/audio_focus_manager.h +++ b/services/media_session/audio_focus_manager.h
@@ -88,8 +88,7 @@ void AbandonAudioFocusInternal(RequestId); void EnforceAudioFocusAbandon(mojom::AudioFocusType); - // Get the top most media session with the gain audio focus type. - mojom::MediaSession* GetActiveGainSession() const; + void MaybeUpdateActiveSession(); std::unique_ptr<StackRow> RemoveFocusEntryIfPresent(RequestId id);
diff --git a/services/media_session/audio_focus_manager_unittest.cc b/services/media_session/audio_focus_manager_unittest.cc index 9262093..d9f9a76 100644 --- a/services/media_session/audio_focus_manager_unittest.cc +++ b/services/media_session/audio_focus_manager_unittest.cc
@@ -985,4 +985,53 @@ } } +TEST_P(AudioFocusManagerTest, ObserverActiveSessionChanged) { + test::MockMediaSession media_session_1; + test::MockMediaSession media_session_2; + + { + std::unique_ptr<test::TestAudioFocusObserver> observer = CreateObserver(); + + RequestAudioFocus(&media_session_1, mojom::AudioFocusType::kGain); + EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive, + GetState(&media_session_1)); + + EXPECT_EQ(media_session_1.GetRequestIdFromClient(), + observer->active_session_->request_id); + } + + { + std::unique_ptr<test::TestAudioFocusObserver> observer = CreateObserver(); + + RequestAudioFocus(&media_session_2, mojom::AudioFocusType::kGainTransient); + EXPECT_EQ(mojom::MediaSessionInfo::SessionState::kActive, + GetState(&media_session_2)); + + EXPECT_NE( + test::TestAudioFocusObserver::NotificationType::kActiveSessionChanged, + observer->notifications().back()); + EXPECT_TRUE(observer->active_session_.is_null()); + } + + { + std::unique_ptr<test::TestAudioFocusObserver> observer = CreateObserver(); + media_session_2.AbandonAudioFocusFromClient(); + + EXPECT_NE( + test::TestAudioFocusObserver::NotificationType::kActiveSessionChanged, + observer->notifications().back()); + EXPECT_TRUE(observer->active_session_.is_null()); + } + + { + std::unique_ptr<test::TestAudioFocusObserver> observer = CreateObserver(); + media_session_1.AbandonAudioFocusFromClient(); + + EXPECT_EQ( + test::TestAudioFocusObserver::NotificationType::kActiveSessionChanged, + observer->notifications().back()); + EXPECT_TRUE(observer->active_session_.is_null()); + } +} + } // namespace media_session
diff --git a/services/media_session/media_controller.cc b/services/media_session/media_controller.cc index 754f9c91..0482595 100644 --- a/services/media_session/media_controller.cc +++ b/services/media_session/media_controller.cc
@@ -77,20 +77,24 @@ session_->NextTrack(); } -void MediaController::SetMediaSession(mojom::MediaSession* session) { +bool MediaController::SetMediaSession(mojom::MediaSession* session) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (session == nullptr) { + bool changed = session != session_; + + if (changed) { session_binding_.Close(); - } else if (session_ != session) { - // Add |this| as an observer for |session|. - session_binding_.Close(); - mojom::MediaSessionObserverPtr observer; - session_binding_.Bind(mojo::MakeRequest(&observer)); - session->AddObserver(std::move(observer)); + + if (session) { + // Add |this| as an observer for |session|. + mojom::MediaSessionObserverPtr observer; + session_binding_.Bind(mojo::MakeRequest(&observer)); + session->AddObserver(std::move(observer)); + } } session_ = session; + return changed; } void MediaController::BindToInterface(mojom::MediaControllerRequest request) {
diff --git a/services/media_session/media_controller.h b/services/media_session/media_controller.h index 517bb33..4c0d5ef 100644 --- a/services/media_session/media_controller.h +++ b/services/media_session/media_controller.h
@@ -30,16 +30,19 @@ void Suspend() override; void Resume() override; void ToggleSuspendResume() override; - void AddObserver(mojom::MediaSessionObserverPtr) override; + void AddObserver(mojom::MediaSessionObserverPtr observer) override; void PreviousTrack() override; void NextTrack() override; // mojom::MediaSessionObserver overrides. - void MediaSessionInfoChanged(mojom::MediaSessionInfoPtr) override; + void MediaSessionInfoChanged( + mojom::MediaSessionInfoPtr session_info) override; - void SetMediaSession(mojom::MediaSession*); + // Sets the media session that the controller should be bound to. If the + // session is already bound to the same session then we will return false. + bool SetMediaSession(mojom::MediaSession* session); - void BindToInterface(mojom::MediaControllerRequest); + void BindToInterface(mojom::MediaControllerRequest request); void FlushForTesting(); private:
diff --git a/services/media_session/public/cpp/test/audio_focus_test_util.cc b/services/media_session/public/cpp/test/audio_focus_test_util.cc index 9d356eb..ba349332 100644 --- a/services/media_session/public/cpp/test/audio_focus_test_util.cc +++ b/services/media_session/public/cpp/test/audio_focus_test_util.cc
@@ -42,6 +42,12 @@ run_loop_.Quit(); } +void TestAudioFocusObserver::OnActiveSessionChanged( + media_session::mojom::AudioFocusRequestStatePtr session) { + active_session_ = std::move(session); + notifications_.push_back(NotificationType::kActiveSessionChanged); +} + void TestAudioFocusObserver::WaitForGainedEvent() { if (!focus_gained_session_.is_null()) return;
diff --git a/services/media_session/public/cpp/test/audio_focus_test_util.h b/services/media_session/public/cpp/test/audio_focus_test_util.h index 05cd87a..55ec4ce8 100644 --- a/services/media_session/public/cpp/test/audio_focus_test_util.h +++ b/services/media_session/public/cpp/test/audio_focus_test_util.h
@@ -22,10 +22,11 @@ TestAudioFocusObserver(); ~TestAudioFocusObserver() override; - void OnFocusGained(media_session::mojom::MediaSessionInfoPtr, - media_session::mojom::AudioFocusType) override; - - void OnFocusLost(media_session::mojom::MediaSessionInfoPtr) override; + void OnFocusGained(media_session::mojom::MediaSessionInfoPtr session, + media_session::mojom::AudioFocusType type) override; + void OnFocusLost(media_session::mojom::MediaSessionInfoPtr session) override; + void OnActiveSessionChanged( + media_session::mojom::AudioFocusRequestStatePtr session) override; void WaitForGainedEvent(); void WaitForLostEvent(); @@ -40,11 +41,13 @@ // These store the values we received. media_session::mojom::MediaSessionInfoPtr focus_gained_session_; media_session::mojom::MediaSessionInfoPtr focus_lost_session_; + media_session::mojom::AudioFocusRequestStatePtr active_session_; // These store the order of notifications that were received by the observer. enum class NotificationType { kFocusGained, kFocusLost, + kActiveSessionChanged, }; const std::vector<NotificationType>& notifications() const { return notifications_;
diff --git a/services/media_session/public/mojom/audio_focus.mojom b/services/media_session/public/mojom/audio_focus.mojom index 9ad4b27a..2e6d647 100644 --- a/services/media_session/public/mojom/audio_focus.mojom +++ b/services/media_session/public/mojom/audio_focus.mojom
@@ -38,13 +38,18 @@ }; // The observer for audio focus events. -// Next Method ID: 2 interface AudioFocusObserver { // The given |session| gained audio focus with the specified |type|. - OnFocusGained@0(MediaSessionInfo session, AudioFocusType type); + OnFocusGained(MediaSessionInfo session, AudioFocusType type); // The given |session| lost audio focus. - OnFocusLost@1(MediaSessionInfo session); + OnFocusLost(MediaSessionInfo session); + + // The currently active session changed. The active session is the top most + // session that is not temporary. This is the session that will be associated + // with the MediaController interface. If all the media sessions have ended + // then |session| will be null. + OnActiveSessionChanged(AudioFocusRequestState? session); }; // Controls audio focus for an associated request.
diff --git a/services/network/host_resolver_unittest.cc b/services/network/host_resolver_unittest.cc index 501a042..a402ccbc 100644 --- a/services/network/host_resolver_unittest.cc +++ b/services/network/host_resolver_unittest.cc
@@ -19,6 +19,7 @@ #include "net/base/ip_address.h" #include "net/base/net_errors.h" #include "net/dns/mock_host_resolver.h" +#include "net/dns/public/dns_query_type.h" #include "net/log/net_log.h" #include "services/network/host_resolver.h" #include "services/network/public/mojom/host_resolver.mojom.h" @@ -158,7 +159,7 @@ mojom::ResolveHostParametersPtr optional_parameters = mojom::ResolveHostParameters::New(); - optional_parameters->dns_query_type = net::HostResolver::DnsQueryType::AAAA; + optional_parameters->dns_query_type = net::DnsQueryType::AAAA; base::RunLoop run_loop; mojom::ResolveHostClientPtr response_client_ptr;
diff --git a/services/network/network_context_unittest.cc b/services/network/network_context_unittest.cc index c3f2cea..6f2838a 100644 --- a/services/network/network_context_unittest.cc +++ b/services/network/network_context_unittest.cc
@@ -59,6 +59,7 @@ #include "net/dns/host_resolver_impl.h" #include "net/dns/host_resolver_source.h" #include "net/dns/mock_host_resolver.h" +#include "net/dns/public/dns_query_type.h" #include "net/http/http_auth.h" #include "net/http/http_cache.h" #include "net/http/http_network_session.h" @@ -3183,7 +3184,7 @@ base::RunLoop run_loop; mojom::ResolveHostParametersPtr optional_parameters = mojom::ResolveHostParameters::New(); - optional_parameters->dns_query_type = net::HostResolver::DnsQueryType::A; + optional_parameters->dns_query_type = net::DnsQueryType::A; optional_parameters->source = net::HostResolverSource::DNS; mojom::ResolveHostClientPtr response_client_ptr; TestResolveHostClient response_client(&response_client_ptr, &run_loop);
diff --git a/services/network/public/cpp/host_resolver.typemap b/services/network/public/cpp/host_resolver.typemap index 8348c54..8921967 100644 --- a/services/network/public/cpp/host_resolver.typemap +++ b/services/network/public/cpp/host_resolver.typemap
@@ -5,7 +5,8 @@ mojom = "//services/network/public/mojom/host_resolver.mojom" public_headers = [ "//net/dns/dns_config_overrides.h", - "//net/dns/host_resolver.h", + "//net/dns/host_resolver_source.h", + "//net/dns/public/dns_query_type.h", ] traits_headers = [ "//services/network/public/cpp/host_resolver_mojom_traits.h" ] @@ -17,6 +18,6 @@ ] type_mappings = [ "network.mojom.DnsConfigOverrides=net::DnsConfigOverrides", - "network.mojom.ResolveHostParameters.DnsQueryType=net::HostResolver::DnsQueryType", + "network.mojom.ResolveHostParameters.DnsQueryType=net::DnsQueryType", "network.mojom.ResolveHostParameters.Source=net::HostResolverSource", ]
diff --git a/services/network/public/cpp/host_resolver_mojom_traits.cc b/services/network/public/cpp/host_resolver_mojom_traits.cc index 87051db..d545770 100644 --- a/services/network/public/cpp/host_resolver_mojom_traits.cc +++ b/services/network/public/cpp/host_resolver_mojom_traits.cc
@@ -215,34 +215,32 @@ } // static -ResolveHostParameters::DnsQueryType EnumTraits< - ResolveHostParameters::DnsQueryType, - net::HostResolver::DnsQueryType>::ToMojom(net::HostResolver::DnsQueryType - input) { +ResolveHostParameters::DnsQueryType +EnumTraits<ResolveHostParameters::DnsQueryType, net::DnsQueryType>::ToMojom( + net::DnsQueryType input) { switch (input) { - case net::HostResolver::DnsQueryType::UNSPECIFIED: + case net::DnsQueryType::UNSPECIFIED: return ResolveHostParameters::DnsQueryType::UNSPECIFIED; - case net::HostResolver::DnsQueryType::A: + case net::DnsQueryType::A: return ResolveHostParameters::DnsQueryType::A; - case net::HostResolver::DnsQueryType::AAAA: + case net::DnsQueryType::AAAA: return ResolveHostParameters::DnsQueryType::AAAA; } } // static -bool EnumTraits<ResolveHostParameters::DnsQueryType, - net::HostResolver::DnsQueryType>:: +bool EnumTraits<ResolveHostParameters::DnsQueryType, net::DnsQueryType>:: FromMojom(ResolveHostParameters::DnsQueryType input, - net::HostResolver::DnsQueryType* output) { + net::DnsQueryType* output) { switch (input) { case ResolveHostParameters::DnsQueryType::UNSPECIFIED: - *output = net::HostResolver::DnsQueryType::UNSPECIFIED; + *output = net::DnsQueryType::UNSPECIFIED; return true; case ResolveHostParameters::DnsQueryType::A: - *output = net::HostResolver::DnsQueryType::A; + *output = net::DnsQueryType::A; return true; case ResolveHostParameters::DnsQueryType::AAAA: - *output = net::HostResolver::DnsQueryType::AAAA; + *output = net::DnsQueryType::AAAA; return true; } }
diff --git a/services/network/public/cpp/host_resolver_mojom_traits.h b/services/network/public/cpp/host_resolver_mojom_traits.h index 33e09d4..3d18769a 100644 --- a/services/network/public/cpp/host_resolver_mojom_traits.h +++ b/services/network/public/cpp/host_resolver_mojom_traits.h
@@ -20,6 +20,7 @@ #include "net/dns/dns_config_overrides.h" #include "net/dns/dns_hosts.h" #include "net/dns/host_resolver.h" +#include "net/dns/public/dns_query_type.h" #include "services/network/public/mojom/host_resolver.mojom.h" namespace mojo { @@ -72,12 +73,12 @@ template <> struct EnumTraits<network::mojom::ResolveHostParameters::DnsQueryType, - net::HostResolver::DnsQueryType> { + net::DnsQueryType> { static network::mojom::ResolveHostParameters::DnsQueryType ToMojom( - net::HostResolver::DnsQueryType input); + net::DnsQueryType input); static bool FromMojom( network::mojom::ResolveHostParameters::DnsQueryType input, - net::HostResolver::DnsQueryType* output); + net::DnsQueryType* output); }; template <>
diff --git a/services/tracing/perfetto/perfetto_tracing_coordinator.cc b/services/tracing/perfetto/perfetto_tracing_coordinator.cc index 06b301b..109ee11 100644 --- a/services/tracing/perfetto/perfetto_tracing_coordinator.cc +++ b/services/tracing/perfetto/perfetto_tracing_coordinator.cc
@@ -54,8 +54,8 @@ base::ResetAndReturn(&stop_and_flush_callback_) .Run(/*metadata=*/std::move(*metadata)); - base::SequencedTaskRunnerHandle::Get()->PostTask( - FROM_HERE, std::move(tracing_over_callback_)); + std::move(tracing_over_callback_).Run(); + // |this| is now destroyed. } }
diff --git a/testing/libfuzzer/fuzzers/generate_javascript_parser_proto.py b/testing/libfuzzer/fuzzers/generate_javascript_parser_proto.py index 4b82042..a2bac4f 100755 --- a/testing/libfuzzer/fuzzers/generate_javascript_parser_proto.py +++ b/testing/libfuzzer/fuzzers/generate_javascript_parser_proto.py
@@ -117,7 +117,7 @@ '\n' '// Bound calls to token_to_string to prevent memory usage from growing\n' '// too much.\n' - 'const int kMaxRecursiveDepth = 10;\n' + 'const int kMaxRecursiveDepth = 9;\n' '\n' 'std::string token_to_string(\n' ' const javascript_parser_proto_fuzzer::Token& token, int depth)'
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 9646d69..b95abe6 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -2160,6 +2160,30 @@ ] } ], + "HTMLParsingYieldTime": [ + { + "platforms": [ + "android", + "android_webview", + "chromeos", + "ios", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "Enabled_50ms", + "params": { + "limit": "0.05" + }, + "enable_features": [ + "HTMLParsingYieldTime" + ] + } + ] + } + ], "HTTPBadPhase3": [ { "platforms": [
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index e9cd1634..b462fbf 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -4767,13 +4767,6 @@ # WebRTC: In "Plan B", remote tracks are unmuted by default, so tests time out # waiting for "unmute". crbug.com/889487 external/wpt/webrtc/RTCPeerConnection-remote-track-mute.https.html [ Timeout ] -# WebRTC: In "Unified Plan", remote tracks are correctly muted by default, but -# they unmute whether or not RTP packets arrive which is incorrect, this causes -# a timeout in the "checkMute" test because the "unmute" listeners are hooked up -# after we've already unmuted. The "checkMute" test likely contain bugs that -# would cause a timeout anyway, but our implementation times out even before -# that part due to incorrect behavior. -crbug.com/889487 virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/RTCRtpTransceiver.https.html [ Timeout ] # Sheriff 2018-04-11 crbug.com/831796 fast/events/autoscroll-in-textfield.html [ Failure Pass ]
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST_5.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST_5.json index 72f366e..b1036086 100644 --- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST_5.json +++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST_5.json
@@ -154228,31 +154228,66 @@ {} ] ], + "feature-policy/reporting/camera-report-only.https.html.headers": [ + [ + {} + ] + ], "feature-policy/reporting/camera-reporting.https.html.headers": [ [ {} ] ], + "feature-policy/reporting/document-write-report-only.html.headers": [ + [ + {} + ] + ], "feature-policy/reporting/document-write-reporting.html.headers": [ [ {} ] ], + "feature-policy/reporting/encrypted-media-report-only.https.html.headers": [ + [ + {} + ] + ], "feature-policy/reporting/encrypted-media-reporting.https.html.headers": [ [ {} ] ], + "feature-policy/reporting/fullscreen-report-only.html.headers": [ + [ + {} + ] + ], "feature-policy/reporting/fullscreen-reporting.html.headers": [ [ {} ] ], + "feature-policy/reporting/generic-sensor-report-only.https.html.headers": [ + [ + {} + ] + ], "feature-policy/reporting/generic-sensor-reporting.https.html.headers": [ [ {} ] ], + "feature-policy/reporting/geolocation-report-only.https-expected.txt": [ + [ + {} + ] + ], + "feature-policy/reporting/geolocation-report-only.https.html.headers": [ + [ + {} + ] + ], "feature-policy/reporting/geolocation-reporting.https.html.headers": [ [ {} @@ -154263,26 +154298,61 @@ {} ] ], + "feature-policy/reporting/microphone-report-only.https.html.headers": [ + [ + {} + ] + ], "feature-policy/reporting/microphone-reporting.https.html.headers": [ [ {} ] ], + "feature-policy/reporting/midi-report-only-expected.txt": [ + [ + {} + ] + ], + "feature-policy/reporting/midi-report-only.html.headers": [ + [ + {} + ] + ], "feature-policy/reporting/midi-reporting.html.headers": [ [ {} ] ], + "feature-policy/reporting/payment-report-only.https-expected.txt": [ + [ + {} + ] + ], + "feature-policy/reporting/payment-report-only.https.html.headers": [ + [ + {} + ] + ], "feature-policy/reporting/payment-reporting.https.html.headers": [ [ {} ] ], + "feature-policy/reporting/picture-in-picture-report-only.html.headers": [ + [ + {} + ] + ], "feature-policy/reporting/picture-in-picture-reporting.html.headers": [ [ {} ] ], + "feature-policy/reporting/sync-xhr-report-only.html.headers": [ + [ + {} + ] + ], "feature-policy/reporting/sync-xhr-reporting.html.headers": [ [ {} @@ -154293,16 +154363,31 @@ {} ] ], + "feature-policy/reporting/usb-report-only.https.html.headers": [ + [ + {} + ] + ], "feature-policy/reporting/usb-reporting.https.html.headers": [ [ {} ] ], + "feature-policy/reporting/vr-report-only.https.html.headers": [ + [ + {} + ] + ], "feature-policy/reporting/vr-reporting.https.html.headers": [ [ {} ] ], + "feature-policy/reporting/xr-report-only.https.html.headers": [ + [ + {} + ] + ], "feature-policy/reporting/xr-reporting.https.html.headers": [ [ {} @@ -225319,60 +225404,128 @@ } ] ], + "feature-policy/reporting/camera-report-only.https.html": [ + [ + "/feature-policy/reporting/camera-report-only.https.html", + { + "testdriver": true + } + ] + ], "feature-policy/reporting/camera-reporting.https.html": [ [ "/feature-policy/reporting/camera-reporting.https.html", {} ] ], + "feature-policy/reporting/document-write-report-only.html": [ + [ + "/feature-policy/reporting/document-write-report-only.html", + {} + ] + ], "feature-policy/reporting/document-write-reporting.html": [ [ "/feature-policy/reporting/document-write-reporting.html", {} ] ], + "feature-policy/reporting/encrypted-media-report-only.https.html": [ + [ + "/feature-policy/reporting/encrypted-media-report-only.https.html", + {} + ] + ], "feature-policy/reporting/encrypted-media-reporting.https.html": [ [ "/feature-policy/reporting/encrypted-media-reporting.https.html", {} ] ], + "feature-policy/reporting/fullscreen-report-only.html": [ + [ + "/feature-policy/reporting/fullscreen-report-only.html", + { + "testdriver": true + } + ] + ], "feature-policy/reporting/fullscreen-reporting.html": [ [ "/feature-policy/reporting/fullscreen-reporting.html", {} ] ], + "feature-policy/reporting/generic-sensor-report-only.https.html": [ + [ + "/feature-policy/reporting/generic-sensor-report-only.https.html", + {} + ] + ], "feature-policy/reporting/generic-sensor-reporting.https.html": [ [ "/feature-policy/reporting/generic-sensor-reporting.https.html", {} ] ], + "feature-policy/reporting/geolocation-report-only.https.html": [ + [ + "/feature-policy/reporting/geolocation-report-only.https.html", + {} + ] + ], "feature-policy/reporting/geolocation-reporting.https.html": [ [ "/feature-policy/reporting/geolocation-reporting.https.html", {} ] ], + "feature-policy/reporting/microphone-report-only.https.html": [ + [ + "/feature-policy/reporting/microphone-report-only.https.html", + { + "testdriver": true + } + ] + ], "feature-policy/reporting/microphone-reporting.https.html": [ [ "/feature-policy/reporting/microphone-reporting.https.html", {} ] ], + "feature-policy/reporting/midi-report-only.html": [ + [ + "/feature-policy/reporting/midi-report-only.html", + {} + ] + ], "feature-policy/reporting/midi-reporting.html": [ [ "/feature-policy/reporting/midi-reporting.html", {} ] ], + "feature-policy/reporting/payment-report-only.https.html": [ + [ + "/feature-policy/reporting/payment-report-only.https.html", + {} + ] + ], "feature-policy/reporting/payment-reporting.https.html": [ [ "/feature-policy/reporting/payment-reporting.https.html", {} ] ], + "feature-policy/reporting/picture-in-picture-report-only.html": [ + [ + "/feature-policy/reporting/picture-in-picture-report-only.html", + { + "testdriver": true + } + ] + ], "feature-policy/reporting/picture-in-picture-reporting.html": [ [ "/feature-policy/reporting/picture-in-picture-reporting.html", @@ -225381,6 +225534,12 @@ } ] ], + "feature-policy/reporting/sync-xhr-report-only.html": [ + [ + "/feature-policy/reporting/sync-xhr-report-only.html", + {} + ] + ], "feature-policy/reporting/sync-xhr-reporting.html": [ [ "/feature-policy/reporting/sync-xhr-reporting.html", @@ -225393,18 +225552,38 @@ {} ] ], + "feature-policy/reporting/usb-report-only.https.html": [ + [ + "/feature-policy/reporting/usb-report-only.https.html", + { + "testdriver": true + } + ] + ], "feature-policy/reporting/usb-reporting.https.html": [ [ "/feature-policy/reporting/usb-reporting.https.html", {} ] ], + "feature-policy/reporting/vr-report-only.https.html": [ + [ + "/feature-policy/reporting/vr-report-only.https.html", + {} + ] + ], "feature-policy/reporting/vr-reporting.https.html": [ [ "/feature-policy/reporting/vr-reporting.https.html", {} ] ], + "feature-policy/reporting/xr-report-only.https.html": [ + [ + "/feature-policy/reporting/xr-report-only.https.html", + {} + ] + ], "feature-policy/reporting/xr-reporting.https.html": [ [ "/feature-policy/reporting/xr-reporting.https.html", @@ -341213,7 +341392,7 @@ "testharness" ], "css/css-properties-values-api/var-reference-registered-properties-cycles.html": [ - "58d6c846ae3a4a1c62f239786dfe8827eb921d05", + "65d11697355c17fca39b4e9fa0dcf0db404e22eb", "testharness" ], "css/css-properties-values-api/var-reference-registered-properties.html": [ @@ -381308,48 +381487,100 @@ "1759381fdc4141302f1b95868550ead76d9f5ca7", "support" ], + "feature-policy/reporting/camera-report-only.https.html": [ + "26488687e6fc75247356d716fa32134dc695fadf", + "testharness" + ], + "feature-policy/reporting/camera-report-only.https.html.headers": [ + "46b84811f55556b8dc4cbc87c174e1175b73e47b", + "support" + ], "feature-policy/reporting/camera-reporting.https.html": [ - "14b2ed1d37c6d79c9e011a35b9fece0cddc0ac76", + "1d08700d3c834692d99dee98fc3f6ebfc0245277", "testharness" ], "feature-policy/reporting/camera-reporting.https.html.headers": [ "2adc5e237fcec874767ff8f5ab38e3456c02cbf0", "support" ], + "feature-policy/reporting/document-write-report-only.html": [ + "ab0bb827166327228e825f9f9c5a0447666d17e1", + "testharness" + ], + "feature-policy/reporting/document-write-report-only.html.headers": [ + "63e43f1d719302760ccdd902439c32913bda375c", + "support" + ], "feature-policy/reporting/document-write-reporting.html": [ - "cb08b8d72d1851ca02c51abf5713519d52f1ecf4", + "d113f2e4a4cc95189044fb46fff8c487f2e8fb68", "testharness" ], "feature-policy/reporting/document-write-reporting.html.headers": [ "57102d5ee7c072e433fa44c0c13521573b32f469", "support" ], + "feature-policy/reporting/encrypted-media-report-only.https.html": [ + "20e44b2fd5db2ac6f54b67c909f6d31099edfaa3", + "testharness" + ], + "feature-policy/reporting/encrypted-media-report-only.https.html.headers": [ + "a2c8fbb44259448cadc9290aad6853051a28aba6", + "support" + ], "feature-policy/reporting/encrypted-media-reporting.https.html": [ - "d309d5390f1ec5f6f3edd00327e9a36b54926499", + "c3b63936b3a8310f873c748947f0fc0633928a9b", "testharness" ], "feature-policy/reporting/encrypted-media-reporting.https.html.headers": [ "73753a2e41d10b0a0398831350b1f17e586ab847", "support" ], + "feature-policy/reporting/fullscreen-report-only.html": [ + "a6b3d5adeed5654942aba43dc65d627fa7c35ae0", + "testharness" + ], + "feature-policy/reporting/fullscreen-report-only.html.headers": [ + "33defa88f6ef9842e4b388dc853ff88c2947e81d", + "support" + ], "feature-policy/reporting/fullscreen-reporting.html": [ - "83d97c91fab60e593cf3bf0cceff4db80552ef02", + "9a7fb8785594a09e862539e671eb6562043263cb", "testharness" ], "feature-policy/reporting/fullscreen-reporting.html.headers": [ "d35e48ba40dc65a3b043a3e41a11332c42bfdba9", "support" ], + "feature-policy/reporting/generic-sensor-report-only.https.html": [ + "deb6adeb73679e3e456787c23ee1a9acad1b8901", + "testharness" + ], + "feature-policy/reporting/generic-sensor-report-only.https.html.headers": [ + "26605eb0fa6c46f9991071f32f9ca35adf00acb2", + "support" + ], "feature-policy/reporting/generic-sensor-reporting.https.html": [ - "c60e3e81a1dddbdc000d799c19719c48ad55376c", + "517c7f6872146a66b02982c0d9e895b60f6d89af", "testharness" ], "feature-policy/reporting/generic-sensor-reporting.https.html.headers": [ "80cc02753044a3730695bce65bc2b4c22d7a8a6b", "support" ], + "feature-policy/reporting/geolocation-report-only.https-expected.txt": [ + "93220611ee3618ea05ef73671e21cc39227bf024", + "support" + ], + "feature-policy/reporting/geolocation-report-only.https.html": [ + "cf2a75b766c3e60b988a0e6e70f65d13b2b79fcf", + "testharness" + ], + "feature-policy/reporting/geolocation-report-only.https.html.headers": [ + "fc9859000f566801a83d89f1b1371017847c9eb6", + "support" + ], "feature-policy/reporting/geolocation-reporting.https.html": [ - "22e258563b799c7d48db2452f15eb6124d1f2d0e", + "ce069023228bdd8294026e1663325b75b3a97265", "testharness" ], "feature-policy/reporting/geolocation-reporting.https.html.headers": [ @@ -381360,40 +381591,88 @@ "c059b96d97fc3701ce4325165b79948f69189135", "support" ], + "feature-policy/reporting/microphone-report-only.https.html": [ + "2d7b4d960d8b5f1c16be272f39c22947370a2611", + "testharness" + ], + "feature-policy/reporting/microphone-report-only.https.html.headers": [ + "7673d05b9485d7d2aba2e1d952b65797fdbb0827", + "support" + ], "feature-policy/reporting/microphone-reporting.https.html": [ - "7347a2332bc8184b2437a965e95b54ff5fcac22f", + "4a0e0b5e98506667b07f02368f962418da818e09", "testharness" ], "feature-policy/reporting/microphone-reporting.https.html.headers": [ "a86e0a077851a84f704e2aa4df1d526ecd9a55b2", "support" ], + "feature-policy/reporting/midi-report-only-expected.txt": [ + "bba8e2aa4e6bcfcd26d918c967e6b0f4d14078ae", + "support" + ], + "feature-policy/reporting/midi-report-only.html": [ + "e466ce0dc412e14296755c2608dc9b4ac1bdc4f6", + "testharness" + ], + "feature-policy/reporting/midi-report-only.html.headers": [ + "3c6a2d4fbb320425b3850eaea2eceaf038b0ba62", + "support" + ], "feature-policy/reporting/midi-reporting.html": [ - "8303b7adce4de654e3a846bbbe1cba035ac9a284", + "fc6d8b1abac7b7a280c32aabea78cbfe51a405b1", "testharness" ], "feature-policy/reporting/midi-reporting.html.headers": [ "0e145978a014f08fb5faff42750e9338da0f9ede", "support" ], + "feature-policy/reporting/payment-report-only.https-expected.txt": [ + "19f3d28fba84148a0470a45d5d4feaa359badb3a", + "support" + ], + "feature-policy/reporting/payment-report-only.https.html": [ + "6a7678b51e759eef7c90e924a596bbf5c1364e15", + "testharness" + ], + "feature-policy/reporting/payment-report-only.https.html.headers": [ + "6411478e4ca37bd2eab26a35b5ae0e6e39ddf066", + "support" + ], "feature-policy/reporting/payment-reporting.https.html": [ - "03eaebea58fb603f5121f6836c85c2c6773c3a5d", + "2c1189d5b46d614fc94038ca282b494613601377", "testharness" ], "feature-policy/reporting/payment-reporting.https.html.headers": [ "a2836778bc5389fdb65e9f6d5f83c7967200866f", "support" ], + "feature-policy/reporting/picture-in-picture-report-only.html": [ + "157670f2cab802bf3f07343eab6649152b08c126", + "testharness" + ], + "feature-policy/reporting/picture-in-picture-report-only.html.headers": [ + "0df90a3e94a3f4997b97dccac3b18aa2830045e8", + "support" + ], "feature-policy/reporting/picture-in-picture-reporting.html": [ - "e3cbf1036871a40163a67aab22930fb7dcde8338", + "f15f47c549d9f03c6b2c49d4e00112900491174d", "testharness" ], "feature-policy/reporting/picture-in-picture-reporting.html.headers": [ "1759381fdc4141302f1b95868550ead76d9f5ca7", "support" ], + "feature-policy/reporting/sync-xhr-report-only.html": [ + "f841f63d6ed3503e7370d11a5305cd95588b1ff9", + "testharness" + ], + "feature-policy/reporting/sync-xhr-report-only.html.headers": [ + "79a82cfb6351efe60fca8945e11d8ec58719dc8d", + "support" + ], "feature-policy/reporting/sync-xhr-reporting.html": [ - "2c76390847be29c5bb2f3ec8605d1cb746c33e00", + "f16e335dd482b30613472c857d2eb24b584b600e", "testharness" ], "feature-policy/reporting/sync-xhr-reporting.html.headers": [ @@ -381408,24 +381687,48 @@ "db2dcbc1929b9e1264855e9b80f77dfbda5d4f38", "support" ], + "feature-policy/reporting/usb-report-only.https.html": [ + "e44c6c528fd4fc9b1d7d96ea65d68a922748bc47", + "testharness" + ], + "feature-policy/reporting/usb-report-only.https.html.headers": [ + "bd2e3c6fe5085b0faa97c2439920d39175497acb", + "support" + ], "feature-policy/reporting/usb-reporting.https.html": [ - "f90c602e449bd00e1d773edbce01e4fab63341e2", + "bc4bffdd98a81d96d3337bd0fee905abec14feda", "testharness" ], "feature-policy/reporting/usb-reporting.https.html.headers": [ "4fd1e269362c43d282ca8e3c5c35a5d648f0666b", "support" ], + "feature-policy/reporting/vr-report-only.https.html": [ + "91016d388532c5528f02e31b308178573191e2ef", + "testharness" + ], + "feature-policy/reporting/vr-report-only.https.html.headers": [ + "b54cad2af941d68b2d395e7d0b9f0af3931bbd01", + "support" + ], "feature-policy/reporting/vr-reporting.https.html": [ - "12cae052a167b47d020dcb8ec7887e5578ce48c5", + "927851989718724d2ea089112d156ab1db9bd7c7", "testharness" ], "feature-policy/reporting/vr-reporting.https.html.headers": [ "d021af75636de273c868412cd98dfff50576151d", "support" ], + "feature-policy/reporting/xr-report-only.https.html": [ + "5d4fb062c1ea2b49fff4068f33926f5afdf8c446", + "testharness" + ], + "feature-policy/reporting/xr-report-only.https.html.headers": [ + "b54cad2af941d68b2d395e7d0b9f0af3931bbd01", + "support" + ], "feature-policy/reporting/xr-reporting.https.html": [ - "a7a122237bb0bdef6d35954697c5a80dbebb8b0f", + "0c793d5b4890d4858018d9f9659adfc717728381", "testharness" ], "feature-policy/reporting/xr-reporting.https.html.headers": [ @@ -383189,7 +383492,7 @@ "support" ], "fetch/sec-metadata/resources/record-header.py": [ - "4c30d1e52ac8bfb24c890f790df154ea17947043", + "b81e93ec3c09a4bbfae7190e39508b31b68edfd7", "support" ], "fetch/sec-metadata/resources/sharedWorker.js": [ @@ -438693,11 +438996,11 @@ "support" ], "webrtc/RTCRtpTransceiver.https-expected.txt": [ - "4807af0735ee68ed4971525fe6d37079b3ae8a50", + "3941d3d372d904c093f42f4f85786b63057f5962", "support" ], "webrtc/RTCRtpTransceiver.https.html": [ - "7d16deaa8c7633928b39e1ed638f26e820e1e8d8", + "1614a11c1a1d6f6de8660117a47753d2c4154726", "testharness" ], "webrtc/RTCSctpTransport-constructor-expected.txt": [
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-model/grid-container-scrollbar-001-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-model/grid-container-scrollbar-001-ref.html new file mode 100644 index 0000000..31a9ef3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-model/grid-container-scrollbar-001-ref.html
@@ -0,0 +1,95 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS container Layout Test Reference</title> +<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com"> +<style> + .container { + margin: 10px; + background: grey; + } + + .scrollX { + overflow-x: scroll; + } + + .scrollY { + overflow-y: scroll; + } + + .fixedSize { + width: 200px; + height: 50px; + } + + .container > div { + background: cyan; + width: 100%; + height: 100%; + } + + .directionRTL { + direction: rtl; + } +</style> + +<p>The test passes if it has the same output than the reference.</p> + +<div style="float: left; width: 350px;"> + + <h2>direction: ltr;</h2> + + <div class="container scrollX"> + <div>item</div> + </div> + + <div class="container scrollY"> + <div>item</div> + </div> + + <div class="container scrollX scrollY"> + <div>item</div> + </div> + + <div class="container fixedSize scrollX"> + <div>item</div> + </div> + + <div class="container fixedSize scrollY"> + <div>item</div> + </div> + + <div class="container fixedSize scrollX scrollY"> + <div>item</div> + </div> + +</div> + +<div style="float: left; width: 350px;"> + + <h2>direction: rtl;</h2> + + <div class="directionRTL container scrollX"> + <div>item</div> + </div> + + <div class="directionRTL container scrollY"> + <div>item</div> + </div> + + <div class="directionRTL container scrollX scrollY"> + <div>item</div> + </div> + + <div class="directionRTL container fixedSize scrollX"> + <div>item</div> + </div> + + <div class="directionRTL container fixedSize scrollY"> + <div>item</div> + </div> + + <div class="directionRTL container fixedSize scrollX scrollY"> + <div>item</div> + </div> + +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-model/grid-container-scrollbar-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-model/grid-container-scrollbar-001.html new file mode 100644 index 0000000..1b3c6ee --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-model/grid-container-scrollbar-001.html
@@ -0,0 +1,92 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Grid container with scrollbars</title> +<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-grid/#grid-model"> +<link rel="match" href="grid-container-scrollbar-001-ref.html"> +<meta name="assert" content="This test verifes that scrollbars are properly painted on grid containers, and are shown in the expected position depending on the direction."> +<link href="support/grid.css" rel="stylesheet"> +<style> + .grid { + margin: 10px; + } + + .scrollX { + overflow-x: scroll; + } + + .scrollY { + overflow-y: scroll; + } + + .fixedSize { + width: 200px; + height: 50px; + } + + .grid > div { + background: cyan; + } +</style> + +<p>The test passes if it has the same output than the reference.</p> + +<div style="float: left; width: 350px;"> + + <h2>direction: ltr;</h2> + + <div class="grid scrollX"> + <div>item</div> + </div> + + <div class="grid scrollY"> + <div>item</div> + </div> + + <div class="grid scrollX scrollY"> + <div>item</div> + </div> + + <div class="grid fixedSize scrollX"> + <div>item</div> + </div> + + <div class="grid fixedSize scrollY"> + <div>item</div> + </div> + + <div class="grid fixedSize scrollX scrollY"> + <div>item</div> + </div> + +</div> + +<div style="float: left; width: 350px;"> + + <h2>direction: rtl;</h2> + + <div class="directionRTL grid scrollX"> + <div>item</div> + </div> + + <div class="directionRTL grid scrollY"> + <div>item</div> + </div> + + <div class="directionRTL grid scrollX scrollY"> + <div>item</div> + </div> + + <div class="directionRTL grid fixedSize scrollX"> + <div>item</div> + </div> + + <div class="directionRTL grid fixedSize scrollY"> + <div>item</div> + </div> + + <div class="directionRTL grid fixedSize scrollX scrollY"> + <div>item</div> + </div> + +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-model/grid-container-scrollbar-vertical-lr-001-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-model/grid-container-scrollbar-vertical-lr-001-ref.html new file mode 100644 index 0000000..512fb8a8 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-model/grid-container-scrollbar-vertical-lr-001-ref.html
@@ -0,0 +1,96 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS container Layout Test Reference</title> +<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com"> +<style> + .container { + margin: 10px; + background: grey; + writing-mode: vertical-lr; + } + + .scrollX { + overflow-x: scroll; + } + + .scrollY { + overflow-y: scroll; + } + + .fixedSize { + width: 200px; + height: 50px; + } + + .container > div { + background: cyan; + width: 100%; + height: 100%; + } + + .directionRTL { + direction: rtl; + } +</style> + +<p>The test passes if it has the same output than the reference.</p> + +<div style="float: left; width: 350px;"> + + <h2>direction: ltr;</h2> + + <div class="container scrollX"> + <div>item</div> + </div> + + <div class="container scrollY"> + <div>item</div> + </div> + + <div class="container scrollX scrollY"> + <div>item</div> + </div> + + <div class="container fixedSize scrollX"> + <div>item</div> + </div> + + <div class="container fixedSize scrollY"> + <div>item</div> + </div> + + <div class="container fixedSize scrollX scrollY"> + <div>item</div> + </div> + +</div> + +<div style="float: left; width: 350px;"> + + <h2>direction: rtl;</h2> + + <div class="directionRTL container scrollX"> + <div>item</div> + </div> + + <div class="directionRTL container scrollY"> + <div>item</div> + </div> + + <div class="directionRTL container scrollX scrollY"> + <div>item</div> + </div> + + <div class="directionRTL container fixedSize scrollX"> + <div>item</div> + </div> + + <div class="directionRTL container fixedSize scrollY"> + <div>item</div> + </div> + + <div class="directionRTL container fixedSize scrollX scrollY"> + <div>item</div> + </div> + +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-model/grid-container-scrollbar-vertical-lr-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-model/grid-container-scrollbar-vertical-lr-001.html new file mode 100644 index 0000000..ecdc7b7 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-model/grid-container-scrollbar-vertical-lr-001.html
@@ -0,0 +1,93 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Grid container with scrollbars</title> +<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-grid/#grid-model"> +<link rel="match" href="grid-container-scrollbar-vertical-lr-001-ref.html"> +<meta name="assert" content="This test verifes that scrollbars are properly painted on grid containers, and are shown in the expected position depending on the direction."> +<link href="support/grid.css" rel="stylesheet"> +<style> + .grid { + margin: 10px; + writing-mode: vertical-lr; + } + + .scrollX { + overflow-x: scroll; + } + + .scrollY { + overflow-y: scroll; + } + + .fixedSize { + width: 200px; + height: 50px; + } + + .grid > div { + background: cyan; + } +</style> + +<p>The test passes if it has the same output than the reference.</p> + +<div style="float: left; width: 350px;"> + + <h2>direction: ltr;</h2> + + <div class="grid scrollX"> + <div>item</div> + </div> + + <div class="grid scrollY"> + <div>item</div> + </div> + + <div class="grid scrollX scrollY"> + <div>item</div> + </div> + + <div class="grid fixedSize scrollX"> + <div>item</div> + </div> + + <div class="grid fixedSize scrollY"> + <div>item</div> + </div> + + <div class="grid fixedSize scrollX scrollY"> + <div>item</div> + </div> + +</div> + +<div style="float: left; width: 350px;"> + + <h2>direction: rtl;</h2> + + <div class="directionRTL grid scrollX"> + <div>item</div> + </div> + + <div class="directionRTL grid scrollY"> + <div>item</div> + </div> + + <div class="directionRTL grid scrollX scrollY"> + <div>item</div> + </div> + + <div class="directionRTL grid fixedSize scrollX"> + <div>item</div> + </div> + + <div class="directionRTL grid fixedSize scrollY"> + <div>item</div> + </div> + + <div class="directionRTL grid fixedSize scrollX scrollY"> + <div>item</div> + </div> + +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-model/grid-container-scrollbar-vertical-rl-001-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-model/grid-container-scrollbar-vertical-rl-001-ref.html new file mode 100644 index 0000000..d8eeedfa --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-model/grid-container-scrollbar-vertical-rl-001-ref.html
@@ -0,0 +1,96 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS container Layout Test Reference</title> +<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com"> +<style> + .container { + margin: 10px; + background: grey; + writing-mode: vertical-rl; + } + + .scrollX { + overflow-x: scroll; + } + + .scrollY { + overflow-y: scroll; + } + + .fixedSize { + width: 200px; + height: 50px; + } + + .container > div { + background: cyan; + width: 100%; + height: 100%; + } + + .directionRTL { + direction: rtl; + } +</style> + +<p>The test passes if it has the same output than the reference.</p> + +<div style="float: left; width: 350px;"> + + <h2>direction: ltr;</h2> + + <div class="container scrollX"> + <div>item</div> + </div> + + <div class="container scrollY"> + <div>item</div> + </div> + + <div class="container scrollX scrollY"> + <div>item</div> + </div> + + <div class="container fixedSize scrollX"> + <div>item</div> + </div> + + <div class="container fixedSize scrollY"> + <div>item</div> + </div> + + <div class="container fixedSize scrollX scrollY"> + <div>item</div> + </div> + +</div> + +<div style="float: left; width: 350px;"> + + <h2>direction: rtl;</h2> + + <div class="directionRTL container scrollX"> + <div>item</div> + </div> + + <div class="directionRTL container scrollY"> + <div>item</div> + </div> + + <div class="directionRTL container scrollX scrollY"> + <div>item</div> + </div> + + <div class="directionRTL container fixedSize scrollX"> + <div>item</div> + </div> + + <div class="directionRTL container fixedSize scrollY"> + <div>item</div> + </div> + + <div class="directionRTL container fixedSize scrollX scrollY"> + <div>item</div> + </div> + +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-model/grid-container-scrollbar-vertical-rl-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-model/grid-container-scrollbar-vertical-rl-001.html new file mode 100644 index 0000000..f2ab39ff5 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-model/grid-container-scrollbar-vertical-rl-001.html
@@ -0,0 +1,93 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Grid container with scrollbars</title> +<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-grid/#grid-model"> +<link rel="match" href="grid-container-scrollbar-vertical-rl-001-ref.html"> +<meta name="assert" content="This test verifes that scrollbars are properly painted on grid containers, and are shown in the expected position depending on the direction."> +<link href="support/grid.css" rel="stylesheet"> +<style> + .grid { + margin: 10px; + writing-mode: vertical-rl; + } + + .scrollX { + overflow-x: scroll; + } + + .scrollY { + overflow-y: scroll; + } + + .fixedSize { + width: 200px; + height: 50px; + } + + .grid > div { + background: cyan; + } +</style> + +<p>The test passes if it has the same output than the reference.</p> + +<div style="float: left; width: 350px;"> + + <h2>direction: ltr;</h2> + + <div class="grid scrollX"> + <div>item</div> + </div> + + <div class="grid scrollY"> + <div>item</div> + </div> + + <div class="grid scrollX scrollY"> + <div>item</div> + </div> + + <div class="grid fixedSize scrollX"> + <div>item</div> + </div> + + <div class="grid fixedSize scrollY"> + <div>item</div> + </div> + + <div class="grid fixedSize scrollX scrollY"> + <div>item</div> + </div> + +</div> + +<div style="float: left; width: 350px;"> + + <h2>direction: rtl;</h2> + + <div class="directionRTL grid scrollX"> + <div>item</div> + </div> + + <div class="directionRTL grid scrollY"> + <div>item</div> + </div> + + <div class="directionRTL grid scrollX scrollY"> + <div>item</div> + </div> + + <div class="directionRTL grid fixedSize scrollX"> + <div>item</div> + </div> + + <div class="directionRTL grid fixedSize scrollY"> + <div>item</div> + </div> + + <div class="directionRTL grid fixedSize scrollX scrollY"> + <div>item</div> + </div> + +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/fetch/sec-metadata/resources/record-header.py b/third_party/WebKit/LayoutTests/external/wpt/fetch/sec-metadata/resources/record-header.py index 4c30d1e..b81e93e 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/fetch/sec-metadata/resources/record-header.py +++ b/third_party/WebKit/LayoutTests/external/wpt/fetch/sec-metadata/resources/record-header.py
@@ -3,10 +3,7 @@ import hashlib import time -resourcePath = os.getcwd() + "/fetch/sec-metadata/resources/" - def main(request, response): - ## Get the query parameter (key) from URL ## ## Tests will record POST requests (CSP Report) and GET (rest) ## if request.GET: @@ -57,7 +54,8 @@ ## Return a valid SharedWorker ## if key.startswith("sharedworker"): response.headers.set("Content-Type", "application/javascript") - file = open(resourcePath + "sharedWorker.js", "r") + file = open(os.path.join(request.doc_root, "fetch", "sec-metadata", + "resources", "sharedWorker.js"), "r") shared_worker = file.read() file.close() return shared_worker
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/navigation-redirect.https.html b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/navigation-redirect.https.html index 6f03fd8..e8b8e9a 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/navigation-redirect.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/navigation-redirect.https.html
@@ -97,7 +97,7 @@ Object.keys(clients).forEach(key => { const info = clients[key]; if (info.found) { - assert_true(expected_final_client_tag, + assert_true(!!expected_final_client_tag, `${worker_name} client tag exists`); assert_equals(key, expected_final_client_tag, `${worker_name} client tag matches`); @@ -120,10 +120,10 @@ assert_equals(typeof(actual_id), 'string', `resultingClientId for ${url} request to ${worker}`); if (expected_id) { - assert_equals(requestInfos[0], expected_id, + assert_equals(actual_id, expected_id, `resultingClientId for ${url} request to ${worker}`); } else { - actual_ids[key] = actual_id; + actual_ids[tag] = actual_id; } } } @@ -489,7 +489,7 @@ url1, url2, [[{url: url1, resultingClientIdTag: 'a'}], [], []], - 'x', + null, 'SW-fallbacked redirect to other-origin out-scope.'); url1 = SCOPE1 + 'url=' + encodeURIComponent(OTHER_ORIGIN_SCOPE); @@ -530,8 +530,8 @@ redirect_test( url1, url2, - [[{url: url1, resultingClientIdTag: 'a'}], [], []], - null, + [[{url: url1, resultingClientIdTag: 'x'}], [], []], + 'x', 'SW-generated redirect to same-origin out-scope.'); url1 = SCOPE1 + 'sw=gen&url=' + encodeURIComponent(OUT_SCOPE) + '#ref';
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/redirect-worker.js b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/redirect-worker.js index 0c5bc3bd..ddcc2cf 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/redirect-worker.js +++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/redirect-worker.js
@@ -114,7 +114,7 @@ return; } - event.respondWith(waitUntilPromise.then(function() { + event.respondWith(waitUntilPromise.then(async () => { if (params['sw'] == 'gen') { return Response.redirect(params['url']); } else if (params['sw'] == 'fetch') { @@ -126,18 +126,13 @@ } else if (params['sw'] == 'manual') { return fetch(new Request(event.request.url, {redirect: 'manual'})); } else if (params['sw'] == 'manualThroughCache') { - var url = event.request.url; - var cache; - return caches.delete(url) - .then(function() { return self.caches.open(url); }) - .then(function(c) { - cache = c; - return fetch(new Request(url, {redirect: 'manual'})); - }) - .then(function(res) { return cache.put(event.request, res); }) - .then(function() { return cache.match(url); }); + const url = event.request.url; + await caches.delete(url) + const cache = await self.caches.open(url); + const response = await fetch(new Request(url, {redirect: 'manual'})); + await cache.put(event.request, response); + return cache.match(url); } - // unexpected... trigger an interception failure })); });
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCRtpTransceiver.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCRtpTransceiver.https-expected.txt index 4807af0..3941d3d 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCRtpTransceiver.https-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCRtpTransceiver.https-expected.txt
@@ -1,37 +1,4 @@ This is a testharness.js-based test. -Harness Error. harness_status.status = 1 , harness_status.message = Cannot read property 'receiver' of undefined -FAIL checkAddTransceiverNoTrack promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'. 'unified-plan' will become the default behavior in the future, but it is currently experimental. To try it out, construct the RTCPeerConnection with sdpSemantics:'unified-plan' present in the RTCConfiguration argument." -FAIL checkAddTransceiverWithTrack promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'. 'unified-plan' will become the default behavior in the future, but it is currently experimental. To try it out, construct the RTCPeerConnection with sdpSemantics:'unified-plan' present in the RTCConfiguration argument." -FAIL checkAddTransceiverWithAddTrack assert_equals: expected "[{currentDirection:null,direction:\"sendrecv\",mid:null,receiver:{track:{kind:\"audio\"}},sender:{track:{}},stopped:false},{currentDirection:null,direction:\"sendrecv\",mid:null,receiver:{track:{kind:\"video\"}},sender:{track:{}},stopped:false}]" but got "[]" -FAIL checkAddTransceiverWithDirection promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'. 'unified-plan' will become the default behavior in the future, but it is currently experimental. To try it out, construct the RTCPeerConnection with sdpSemantics:'unified-plan' present in the RTCConfiguration argument." -FAIL checkAddTransceiverWithSetRemoteOfferSending promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'. 'unified-plan' will become the default behavior in the future, but it is currently experimental. To try it out, construct the RTCPeerConnection with sdpSemantics:'unified-plan' present in the RTCConfiguration argument." -FAIL checkAddTransceiverWithSetRemoteOfferNoSend promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'. 'unified-plan' will become the default behavior in the future, but it is currently experimental. To try it out, construct the RTCPeerConnection with sdpSemantics:'unified-plan' present in the RTCConfiguration argument." -FAIL checkAddTransceiverBadKind assert_true: addTransceiver("foo") throws a TypeError expected true got false -FAIL checkNoMidOffer assert_equals: expected "[{currentDirection:null,direction:\"recvonly\",receiver:{track:{kind:\"audio\"}},sender:{track:null},stopped:false}]" but got "[]" -FAIL checkSetDirection promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'. 'unified-plan' will become the default behavior in the future, but it is currently experimental. To try it out, construct the RTCPeerConnection with sdpSemantics:'unified-plan' present in the RTCConfiguration argument." -FAIL checkCurrentDirection assert_equals: expected "[{currentDirection:null}]" but got "[]" -FAIL checkSendrecvWithNoSendTrack promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'. 'unified-plan' will become the default behavior in the future, but it is currently experimental. To try it out, construct the RTCPeerConnection with sdpSemantics:'unified-plan' present in the RTCConfiguration argument." -FAIL checkSendrecvWithTracklessStream promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'. 'unified-plan' will become the default behavior in the future, but it is currently experimental. To try it out, construct the RTCPeerConnection with sdpSemantics:'unified-plan' present in the RTCConfiguration argument." -FAIL checkAddTransceiverNoTrackDoesntPair promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'. 'unified-plan' will become the default behavior in the future, but it is currently experimental. To try it out, construct the RTCPeerConnection with sdpSemantics:'unified-plan' present in the RTCConfiguration argument." -FAIL checkAddTransceiverWithTrackDoesntPair promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'. 'unified-plan' will become the default behavior in the future, but it is currently experimental. To try it out, construct the RTCPeerConnection with sdpSemantics:'unified-plan' present in the RTCConfiguration argument." -FAIL checkAddTransceiverThenReplaceTrackDoesntPair promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'. 'unified-plan' will become the default behavior in the future, but it is currently experimental. To try it out, construct the RTCPeerConnection with sdpSemantics:'unified-plan' present in the RTCConfiguration argument." -FAIL checkAddTransceiverThenAddTrackPairs promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'. 'unified-plan' will become the default behavior in the future, but it is currently experimental. To try it out, construct the RTCPeerConnection with sdpSemantics:'unified-plan' present in the RTCConfiguration argument." -FAIL checkAddTrackPairs promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'. 'unified-plan' will become the default behavior in the future, but it is currently experimental. To try it out, construct the RTCPeerConnection with sdpSemantics:'unified-plan' present in the RTCConfiguration argument." -FAIL checkReplaceTrackNullDoesntPreventPairing promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'. 'unified-plan' will become the default behavior in the future, but it is currently experimental. To try it out, construct the RTCPeerConnection with sdpSemantics:'unified-plan' present in the RTCConfiguration argument." -FAIL checkRemoveAndReadd assert_equals: expected "[{direction:\"recvonly\",sender:{track:null}},{direction:\"sendrecv\",sender:{track:{}}}]" but got "[]" -FAIL checkAddTrackExistingTransceiverThenRemove promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'. 'unified-plan' will become the default behavior in the future, but it is currently experimental. To try it out, construct the RTCPeerConnection with sdpSemantics:'unified-plan' present in the RTCConfiguration argument." -FAIL checkRemoveTrackNegotiation promise_test: Unhandled rejection with value: object "TypeError: Cannot set property 'direction' of undefined" -FAIL checkMute promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'receiver' of undefined" -FAIL checkStop promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'stop' of undefined" -FAIL checkStopAfterCreateOffer promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'stop' of undefined" -FAIL checkStopAfterSetLocalOffer promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'stop' of undefined" -FAIL checkStopAfterSetRemoteOffer promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'stop' of undefined" -FAIL checkStopAfterCreateAnswer promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'stop' of undefined" -FAIL checkStopAfterSetLocalAnswer promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'receiver' of undefined" -FAIL checkStopAfterClose assert_equals: Stopping a transceiver on a closed PC should throw. throws InvalidStateError expected "InvalidStateError" but got "TypeError" -FAIL checkLocalRollback assert_equals: expected "[{currentDirection:null,direction:\"sendrecv\",receiver:{track:{kind:\"audio\"}},sender:{track:{}},stopped:false}]" but got "[]" -FAIL checkRollbackAndSetRemoteOfferWithDifferentType promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'setLocalDescription' on 'RTCPeerConnection': The provided value 'rollback' is not a valid enum value of type RTCSdpType." -FAIL checkRemoteRollback promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'setRemoteDescription' on 'RTCPeerConnection': The provided value 'rollback' is not a valid enum value of type RTCSdpType." -FAIL checkMsectionReuse promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'mid' of undefined" +FAIL RTCRtpTransceiver Uncaught ReferenceError: checkMsidNoTrackId is not defined Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCRtpTransceiver.https.html b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCRtpTransceiver.https.html index 7d16dea..1614a11 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCRtpTransceiver.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCRtpTransceiver.https.html
@@ -2129,6 +2129,7 @@ checkAddTransceiverWithTrack, checkAddTransceiverWithAddTrack, checkAddTransceiverWithDirection, + checkMsidNoTrackId, checkAddTransceiverWithSetRemoteOfferSending, checkAddTransceiverWithSetRemoteOfferNoSend, checkAddTransceiverBadKind,
diff --git a/third_party/WebKit/LayoutTests/virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/RTCRtpTransceiver.https-expected.txt b/third_party/WebKit/LayoutTests/virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/RTCRtpTransceiver.https-expected.txt deleted file mode 100644 index 7a9017a..0000000 --- a/third_party/WebKit/LayoutTests/virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/RTCRtpTransceiver.https-expected.txt +++ /dev/null
@@ -1,39 +0,0 @@ -This is a testharness.js-based test. -FAIL checkAddTransceiverNoTrack assert_equals: expected "[{currentDirection:null,direction:\"sendrecv\",mid:null,receiver:{track:{kind:\"audio\",muted:true,readyState:\"live\"}},sender:{track:null},stopped:false},{currentDirection:null,direction:\"sendrecv\",mid:null,receiver:{track:{kind:\"video\",muted:true,readyState:\"live\"}},sender:{track:null},stopped:false}]" but got "[{currentDirection:null,direction:\"sendrecv\",mid:null,receiver:{track:{kind:\"audio\",muted:false,readyState:\"live\"}},sender:{track:null},stopped:false},{currentDirection:null,direction:\"sendrecv\",mid:null,receiver:{track:{kind:\"video\",muted:false,readyState:\"live\"}},sender:{track:null},stopped:false}]" -PASS checkAddTransceiverWithTrack -PASS checkAddTransceiverWithAddTrack -PASS checkAddTransceiverWithDirection -PASS checkAddTransceiverWithStream -FAIL checkAddTransceiverWithOfferToReceiveAudio assert_equals: expected "[{currentDirection:null,direction:\"recvonly\",mid:null,receiver:{track:{kind:\"audio\"}},sender:{track:null},stopped:false}]" but got "[]" -FAIL checkAddTransceiverWithOfferToReceiveVideo assert_equals: expected "[{currentDirection:null,direction:\"recvonly\",mid:null,receiver:{track:{kind:\"video\"}},sender:{track:null},stopped:false}]" but got "[]" -FAIL checkAddTransceiverWithOfferToReceiveBoth assert_equals: expected "[{currentDirection:null,direction:\"recvonly\",mid:null,receiver:{track:{kind:\"audio\"}},sender:{track:null},stopped:false},{currentDirection:null,direction:\"recvonly\",mid:null,receiver:{track:{kind:\"video\"}},sender:{track:null},stopped:false}]" but got "[]" -PASS checkAddTransceiverWithSetRemoteOfferSending -PASS checkAddTransceiverWithSetRemoteOfferNoSend -PASS checkAddTransceiverBadKind -PASS checkSetDirection -PASS checkCurrentDirection -PASS checkSendrecvWithNoSendTrack -PASS checkSendrecvWithTracklessStream -PASS checkAddTransceiverNoTrackDoesntPair -PASS checkAddTransceiverWithTrackDoesntPair -PASS checkAddTransceiverThenReplaceTrackDoesntPair -FAIL checkAddTransceiverThenAddTrackPairs assert_equals: expected "[{sender:{track:{}}}]" but got "[{sender:{track:{}}},{}]" -PASS checkAddTrackPairs -PASS checkReplaceTrackNullDoesntPreventPairing -PASS checkRemoveAndReadd -PASS checkAddTrackExistingTransceiverThenRemove -FAIL checkRemoveTrackNegotiation promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'setRemoteDescription' on 'RTCPeerConnection': The provided value 'rollback' is not a valid enum value of type RTCSdpType." -FAIL checkMute assert_equals: expected "[{receiver:{track:{kind:\"audio\",muted:true}}},{receiver:{track:{kind:\"video\",muted:true}}}]" but got "[{receiver:{track:{kind:\"audio\",muted:false}}},{receiver:{track:{kind:\"video\",muted:false}}}]" -FAIL checkOnAddStream assert_equals: Should have 1 addstream event expected 1 but got 0 -FAIL checkStop promise_test: Unhandled rejection with value: object "TypeError: stoppedTransceiver.stop is not a function" -FAIL checkStopAfterCreateOffer promise_test: Unhandled rejection with value: object "TypeError: pc1.getTransceivers(...)[0].stop is not a function" -FAIL checkStopAfterSetLocalOffer promise_test: Unhandled rejection with value: object "TypeError: pc1.getTransceivers(...)[0].stop is not a function" -FAIL checkStopAfterSetRemoteOffer promise_test: Unhandled rejection with value: object "TypeError: pc2.getTransceivers(...)[0].stop is not a function" -FAIL checkStopAfterCreateAnswer promise_test: Unhandled rejection with value: object "TypeError: pc2.getTransceivers(...)[0].stop is not a function" -FAIL checkStopAfterSetLocalAnswer promise_test: Unhandled rejection with value: object "TypeError: pc2.getTransceivers(...)[0].stop is not a function" -FAIL checkStopAfterClose assert_equals: Stopping a transceiver on a closed PC should throw. throws InvalidStateError expected "InvalidStateError" but got "TypeError" -FAIL checkLocalRollback promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'setLocalDescription' on 'RTCPeerConnection': The provided value 'rollback' is not a valid enum value of type RTCSdpType." -FAIL checkRemoteRollback promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'setRemoteDescription' on 'RTCPeerConnection': The provided value 'rollback' is not a valid enum value of type RTCSdpType." -FAIL checkMsectionReuse promise_test: Unhandled rejection with value: object "TypeError: pc2.getTransceivers(...)[0].stop is not a function" -Harness: the test ran to completion. -
diff --git a/third_party/blink/renderer/core/editing/frame_selection.cc b/third_party/blink/renderer/core/editing/frame_selection.cc index 5b6244d8..3638301a 100644 --- a/third_party/blink/renderer/core/editing/frame_selection.cc +++ b/third_party/blink/renderer/core/editing/frame_selection.cc
@@ -1085,33 +1085,34 @@ // http://crbug.com/657237 for more details. if (!selection.IsCaret()) return false; - const VisiblePosition& position = selection.VisibleStart(); + const Position position = selection.Start(); static const EWordSide kWordSideList[2] = {kNextWordIfOnBoundary, kPreviousWordIfOnBoundary}; for (EWordSide word_side : kWordSideList) { - // TODO(yoichio): We should have Position version of |start/endOfWord| - // for avoiding unnecessary canonicalization. - VisiblePosition start = StartOfWord(position, word_side); - VisiblePosition end = EndOfWord(position, word_side); + Position start = StartOfWordPosition(position, word_side); + Position end = EndOfWordPosition(position, word_side); // TODO(editing-dev): |StartOfWord()| and |EndOfWord()| should not make null // for non-null parameter. // See http://crbug.com/872443 - if (start.DeepEquivalent().IsNull() || end.DeepEquivalent().IsNull()) + if (start.IsNull() || end.IsNull()) continue; - String text = - PlainText(EphemeralRange(start.DeepEquivalent(), end.DeepEquivalent())); + if (start > end) { + // Since word boundaries are computed on flat tree, they can be reversed + // when mapped back to DOM. + std::swap(start, end); + } + + String text = PlainText(EphemeralRange(start, end)); if (!text.IsEmpty() && !IsSeparator(text.CharacterStartingAt(0))) { - SetSelection(SelectionInDOMTree::Builder() - .Collapse(start.ToPositionWithAffinity()) - .Extend(end.DeepEquivalent()) - .Build(), - SetSelectionOptions::Builder() - .SetShouldCloseTyping(true) - .SetShouldClearTypingStyle(true) - .SetGranularity(TextGranularity::kWord) - .Build()); + SetSelection( + SelectionInDOMTree::Builder().Collapse(start).Extend(end).Build(), + SetSelectionOptions::Builder() + .SetShouldCloseTyping(true) + .SetShouldClearTypingStyle(true) + .SetGranularity(TextGranularity::kWord) + .Build()); return true; } }
diff --git a/third_party/blink/renderer/core/html/anchor_element_metrics.cc b/third_party/blink/renderer/core/html/anchor_element_metrics.cc index 78f00d2..9666026 100644 --- a/third_party/blink/renderer/core/html/anchor_element_metrics.cc +++ b/third_party/blink/renderer/core/html/anchor_element_metrics.cc
@@ -141,8 +141,7 @@ // static base::Optional<AnchorElementMetrics> AnchorElementMetrics::Create( - const HTMLAnchorElement* anchor_element, - bool is_url_incremented_by_one) { + const HTMLAnchorElement* anchor_element) { LocalFrame* local_frame = anchor_element->GetDocument().GetFrame(); LayoutObject* layout_object = anchor_element->GetLayoutObject(); if (!local_frame || !layout_object) @@ -154,11 +153,7 @@ return base::nullopt; IntRect viewport = root_frame_view->LayoutViewport()->VisibleContentRect(); - - // Do not ignore anchor elements for which |is_url_incremented_by_one| is - // true since there is typically high click probability for such anchor - // elements. - if (viewport.Size().IsEmpty() && !is_url_incremented_by_one) + if (viewport.Size().IsEmpty()) return base::nullopt; // Use the viewport size to normalize anchor element metrics. @@ -210,7 +205,7 @@ ratio_distance_top_to_visible_top, ratio_distance_center_to_visible_top, ratio_distance_root_top, ratio_distance_root_bottom, ratio_root_height, IsInIFrame(*anchor_element), ContainsImage(*anchor_element), - IsSameHost(*anchor_element), is_url_incremented_by_one); + IsSameHost(*anchor_element), IsUrlIncrementedByOne(*anchor_element)); } // static @@ -224,8 +219,7 @@ return base::nullopt; } - bool is_url_incremented_by_one = IsUrlIncrementedByOne(*anchor_element); - auto anchor_metrics = Create(anchor_element, is_url_incremented_by_one); + auto anchor_metrics = Create(anchor_element); if (anchor_metrics.has_value()) { anchor_metrics.value().RecordMetricsOnClick(); @@ -255,22 +249,14 @@ for (const auto& member_element : sender->GetAnchorElements()) { const HTMLAnchorElement& anchor_element = *member_element; - if (!anchor_element.Href().ProtocolIsInHTTPFamily()) - continue; - - bool is_url_incremented_by_one = IsUrlIncrementedByOne(anchor_element); - // We ignore anchor elements that are not in the visual viewport. - // Do not ignore anchor elements for which |is_url_incremented_by_one| is - // true since there is typically high click probability for such anchor - // elements. - if (anchor_element.VisibleBoundsInVisualViewport().IsEmpty() && - !is_url_incremented_by_one) { + if (!anchor_element.Href().ProtocolIsInHTTPFamily() || + anchor_element.VisibleBoundsInVisualViewport().IsEmpty()) { continue; } base::Optional<AnchorElementMetrics> anchor_metric = - Create(&anchor_element, is_url_incremented_by_one); + Create(&anchor_element); if (!anchor_metric.has_value()) continue;
diff --git a/third_party/blink/renderer/core/html/anchor_element_metrics.h b/third_party/blink/renderer/core/html/anchor_element_metrics.h index 3ecf9cf..da5949eb 100644 --- a/third_party/blink/renderer/core/html/anchor_element_metrics.h +++ b/third_party/blink/renderer/core/html/anchor_element_metrics.h
@@ -55,16 +55,8 @@ // browser on page load. static const int kMaxAnchorElementMetricsSize; - // Extract features of the anchor element. |is_url_incremented_by_one| is - // true if |anchor_element| links to a URL which is one number different - // from the document's URL. Based on the value of the anchor element URL, - // and document URL, |is_url_incremented_by_one| may be true or false. - // Examples for different values of |is_url_incremented_by_one|: - // example.com/page9/cat5, example.com/page10/cat5 => true - // example.com/page9/cat5, example.com/page10/cat10 => false - static base::Optional<AnchorElementMetrics> Create( - const HTMLAnchorElement* anchor_element, - bool is_url_incremented_by_one); + // Extract features of the anchor element. + static base::Optional<AnchorElementMetrics> Create(const HTMLAnchorElement*); // Returns the mojom struct used to send metrics to the browser process. mojom::blink::AnchorElementMetricsPtr CreateMetricsPtr() const;
diff --git a/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.cc b/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.cc index 9ffbb971..ff6bf15 100644 --- a/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.cc +++ b/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.cc
@@ -31,7 +31,6 @@ #include "third_party/blink/renderer/core/origin_trials/origin_trials.h" #include "third_party/blink/renderer/core/workers/worker_animation_frame_provider.h" #include "third_party/blink/renderer/core/workers/worker_global_scope.h" -#include "third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h" #include "third_party/blink/renderer/platform/weborigin/security_origin.h" @@ -48,16 +47,14 @@ // For wide gamut color spaces, user must explicitly request half float // storage. Otherwise, we fall back to sRGB in uint8. Invalid requests fall // back to sRGB in uint8 too. - if (SharedGpuContext::IsGpuCompositingEnabled()) { - if (creation_attributes_.pixel_format == kF16CanvasPixelFormatName) { - color_params_.SetCanvasPixelFormat(kF16CanvasPixelFormat); - if (creation_attributes_.color_space == kLinearRGBCanvasColorSpaceName) - color_params_.SetCanvasColorSpace(kLinearRGBCanvasColorSpace); - if (creation_attributes_.color_space == kRec2020CanvasColorSpaceName) - color_params_.SetCanvasColorSpace(kRec2020CanvasColorSpace); - else if (creation_attributes_.color_space == kP3CanvasColorSpaceName) - color_params_.SetCanvasColorSpace(kP3CanvasColorSpace); - } + if (creation_attributes_.pixel_format == kF16CanvasPixelFormatName) { + color_params_.SetCanvasPixelFormat(kF16CanvasPixelFormat); + if (creation_attributes_.color_space == kLinearRGBCanvasColorSpaceName) + color_params_.SetCanvasColorSpace(kLinearRGBCanvasColorSpace); + if (creation_attributes_.color_space == kRec2020CanvasColorSpaceName) + color_params_.SetCanvasColorSpace(kRec2020CanvasColorSpace); + else if (creation_attributes_.color_space == kP3CanvasColorSpaceName) + color_params_.SetCanvasColorSpace(kP3CanvasColorSpace); } if (!creation_attributes_.alpha)
diff --git a/third_party/blink/renderer/core/html/parser/html_document_parser.cc b/third_party/blink/renderer/core/html/parser/html_document_parser.cc index 1a2ab68..6624165f 100644 --- a/third_party/blink/renderer/core/html/parser/html_document_parser.cc +++ b/third_party/blink/renderer/core/html/parser/html_document_parser.cc
@@ -1211,8 +1211,9 @@ } void HTMLDocumentParser::ScanAndPreload(HTMLPreloadScanner* scanner) { - PreloadRequestStream requests = - scanner->Scan(GetDocument()->ValidBaseElementURL(), nullptr); + bool seen_csp_meta_tag = false; + PreloadRequestStream requests = scanner->Scan( + GetDocument()->ValidBaseElementURL(), nullptr, seen_csp_meta_tag); preloader_->TakeAndPreload(requests); }
diff --git a/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc b/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc index 9f3fb193..787fdda 100644 --- a/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc +++ b/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc
@@ -949,7 +949,8 @@ PreloadRequestStream HTMLPreloadScanner::Scan( const KURL& starting_base_element_url, - ViewportDescriptionWrapper* viewport) { + ViewportDescriptionWrapper* viewport, + bool& has_csp_meta_tag) { // HTMLTokenizer::updateStateFor only works on the main thread. DCHECK(IsMainThread()); @@ -967,13 +968,14 @@ if (token_.GetType() == HTMLToken::kStartTag) tokenizer_->UpdateStateFor( AttemptStaticStringCreation(token_.GetName(), kLikely8Bit)); - bool is_csp_meta_tag = false; - scanner_.Scan(token_, source_, requests, viewport, &is_csp_meta_tag); + bool seen_csp_meta_tag = false; + scanner_.Scan(token_, source_, requests, viewport, &seen_csp_meta_tag); + has_csp_meta_tag |= seen_csp_meta_tag; token_.Clear(); // Don't preload anything if a CSP meta tag is found. We should rarely find // them here because the HTMLPreloadScanner is only used for the synchronous // parsing path. - if (is_csp_meta_tag) { + if (seen_csp_meta_tag) { // Reset the tokenizer, to avoid re-scanning tokens that we are about to // start parsing. source_.Clear();
diff --git a/third_party/blink/renderer/core/html/parser/html_preload_scanner.h b/third_party/blink/renderer/core/html/parser/html_preload_scanner.h index 4905f0c..56bbeab 100644 --- a/third_party/blink/renderer/core/html/parser/html_preload_scanner.h +++ b/third_party/blink/renderer/core/html/parser/html_preload_scanner.h
@@ -189,7 +189,8 @@ void AppendToEnd(const SegmentedString&); PreloadRequestStream Scan(const KURL& document_base_element_url, - ViewportDescriptionWrapper*); + ViewportDescriptionWrapper*, + bool& has_csp_meta_tag); private: HTMLPreloadScanner(const HTMLParserOptions&,
diff --git a/third_party/blink/renderer/core/html/parser/html_preload_scanner_fuzzer.cc b/third_party/blink/renderer/core/html/parser/html_preload_scanner_fuzzer.cc index 0e934a41..4d20f391 100644 --- a/third_party/blink/renderer/core/html/parser/html_preload_scanner_fuzzer.cc +++ b/third_party/blink/renderer/core/html/parser/html_preload_scanner_fuzzer.cc
@@ -75,7 +75,9 @@ CString bytes = fuzzed_data.ConsumeRemainingBytes(); String decoded_bytes = decoder.Decode(bytes.data(), bytes.length()); scanner->AppendToEnd(decoded_bytes); - PreloadRequestStream requests = scanner->Scan(document_url, nullptr); + bool has_csp_meta_tag_unused = false; + PreloadRequestStream requests = + scanner->Scan(document_url, nullptr, has_csp_meta_tag_unused); preloader.TakeAndPreload(requests); return 0; }
diff --git a/third_party/blink/renderer/core/html/parser/html_preload_scanner_test.cc b/third_party/blink/renderer/core/html/parser/html_preload_scanner_test.cc index 4e189a85..87cc5c4 100644 --- a/third_party/blink/renderer/core/html/parser/html_preload_scanner_test.cc +++ b/third_party/blink/renderer/core/html/parser/html_preload_scanner_test.cc
@@ -61,6 +61,12 @@ network::mojom::FetchCredentialsMode credentials_mode; }; +struct CSPTestCase { + const char* base_url; + const char* input_html; + bool should_see_csp_tag; +}; + struct NonceTestCase { const char* base_url; const char* input_html; @@ -253,7 +259,8 @@ HTMLMockHTMLResourcePreloader preloader; KURL base_url(test_case.base_url); scanner_->AppendToEnd(String(test_case.input_html)); - PreloadRequestStream requests = scanner_->Scan(base_url, nullptr); + PreloadRequestStream requests = + scanner_->Scan(base_url, nullptr, seen_csp_meta_tag_); preloader.TakeAndPreload(requests); preloader.PreloadRequestVerification( @@ -265,7 +272,8 @@ HTMLMockHTMLResourcePreloader preloader; KURL base_url(test_case.base_url); scanner_->AppendToEnd(String(test_case.input_html)); - PreloadRequestStream requests = scanner_->Scan(base_url, nullptr); + PreloadRequestStream requests = + scanner_->Scan(base_url, nullptr, seen_csp_meta_tag_); preloader.TakeAndPreload(requests); preloader.PreconnectRequestVerification(test_case.preconnected_host, test_case.cross_origin); @@ -275,7 +283,8 @@ HTMLMockHTMLResourcePreloader preloader; KURL base_url(test_case.base_url); scanner_->AppendToEnd(String(test_case.input_html)); - PreloadRequestStream requests = scanner_->Scan(base_url, nullptr); + PreloadRequestStream requests = + scanner_->Scan(base_url, nullptr, seen_csp_meta_tag_); preloader.TakeAndPreload(requests); if (test_case.expected_referrer) { @@ -294,20 +303,29 @@ HTMLMockHTMLResourcePreloader preloader; KURL base_url(test_case.base_url); scanner_->AppendToEnd(String(test_case.input_html)); - PreloadRequestStream requests = scanner_->Scan(base_url, nullptr); + PreloadRequestStream requests = + scanner_->Scan(base_url, nullptr, seen_csp_meta_tag_); preloader.TakeAndPreload(requests); - preloader.CORSRequestVerification(&GetDocument(), test_case.request_mode, test_case.credentials_mode); } + void Test(CSPTestCase test_case) { + HTMLMockHTMLResourcePreloader preloader; + KURL base_url(test_case.base_url); + seen_csp_meta_tag_ = false; + scanner_->AppendToEnd(String(test_case.input_html)); + scanner_->Scan(base_url, nullptr, seen_csp_meta_tag_); + EXPECT_EQ(test_case.should_see_csp_tag, seen_csp_meta_tag_); + } + void Test(NonceTestCase test_case) { HTMLMockHTMLResourcePreloader preloader; KURL base_url(test_case.base_url); scanner_->AppendToEnd(String(test_case.input_html)); - PreloadRequestStream requests = scanner_->Scan(base_url, nullptr); + PreloadRequestStream requests = + scanner_->Scan(base_url, nullptr, seen_csp_meta_tag_); preloader.TakeAndPreload(requests); - preloader.NonceRequestVerification(test_case.nonce); } @@ -315,7 +333,8 @@ HTMLMockHTMLResourcePreloader preloader; KURL base_url(test_case.base_url); scanner_->AppendToEnd(String(test_case.input_html)); - PreloadRequestStream requests = scanner_->Scan(base_url, nullptr); + PreloadRequestStream requests = + scanner_->Scan(base_url, nullptr, seen_csp_meta_tag_); preloader.TakeAndPreload(requests); preloader.ContextVerification(test_case.is_image_set); @@ -326,7 +345,8 @@ HTMLMockHTMLResourcePreloader preloader; KURL base_url("http://example.test/"); scanner_->AppendToEnd(String(test_case.input_html)); - PreloadRequestStream requests = scanner_->Scan(base_url, nullptr); + PreloadRequestStream requests = + scanner_->Scan(base_url, nullptr, seen_csp_meta_tag_); preloader.TakeAndPreload(requests); preloader.CheckNumberOfIntegrityConstraints( @@ -335,6 +355,7 @@ private: std::unique_ptr<HTMLPreloadScanner> scanner_; + bool seen_csp_meta_tag_ = false; }; TEST_F(HTMLPreloadScannerTest, testImages) { @@ -889,6 +910,22 @@ } } +TEST_F(HTMLPreloadScannerTest, testCSP) { + CSPTestCase test_cases[] = { + {"http://example.test", + "<meta http-equiv=\"Content-Security-Policy\" content=\"default-src " + "https:\">", + true}, + {"http://example.test", + "<meta name=\"viewport\" content=\"width=device-width\">", false}, + {"http://example.test", "<img src=\"example.gif\">", false}}; + + for (const auto& test_case : test_cases) { + SCOPED_TRACE(test_case.input_html); + Test(test_case); + } +} + TEST_F(HTMLPreloadScannerTest, testNonce) { NonceTestCase test_cases[] = { {"http://example.test", "<script src='/script'></script>", ""},
diff --git a/third_party/blink/renderer/core/layout/layout_block_flow.h b/third_party/blink/renderer/core/layout/layout_block_flow.h index 2a7cbc5..9a000f4c 100644 --- a/third_party/blink/renderer/core/layout/layout_block_flow.h +++ b/third_party/blink/renderer/core/layout/layout_block_flow.h
@@ -821,6 +821,9 @@ int GetLayoutPassCountForTesting(); + // This is public only for use by LayoutNG, so that NGBlockNode can call it. + void IncrementLayoutPassCount(); + protected: LayoutUnit MaxPositiveMarginBefore() const { return rare_data_ @@ -1054,7 +1057,6 @@ // Positions new floats and also adjust all floats encountered on the line if // any of them have to move to the next page/column. void PositionDialog(); - void IncrementLayoutPassCount(); // END METHODS DEFINED IN LayoutBlockFlowLine };
diff --git a/third_party/blink/renderer/core/layout/layout_grid.cc b/third_party/blink/renderer/core/layout/layout_grid.cc index e8882aa..2df38ce 100644 --- a/third_party/blink/renderer/core/layout/layout_grid.cc +++ b/third_party/blink/renderer/core/layout/layout_grid.cc
@@ -1403,8 +1403,18 @@ direction == kForColumns ? offset_between_columns_ : offset_between_rows_; auto& positions = is_row_axis ? column_positions_ : row_positions_; positions.resize(number_of_lines); + auto border_and_padding = is_row_axis ? BorderAndPaddingLogicalLeft() : BorderAndPaddingBefore(); + if (is_row_axis) { + if (StyleRef().IsHorizontalWritingMode() && + !StyleRef().IsLeftToRightDirection()) + border_and_padding += ScrollbarLogicalWidth(); + } else { + if (StyleRef().GetWritingMode() == WritingMode::kVerticalRl) + border_and_padding += ScrollbarLogicalHeight(); + } + positions[0] = border_and_padding + offset.position_offset; if (number_of_lines > 1) { // If we have collapsed tracks we just ignore gaps here and add them later
diff --git a/third_party/blink/renderer/core/layout/layout_object_test.cc b/third_party/blink/renderer/core/layout/layout_object_test.cc index caa674e..bc840f270 100644 --- a/third_party/blink/renderer/core/layout/layout_object_test.cc +++ b/third_party/blink/renderer/core/layout/layout_object_test.cc
@@ -893,13 +893,13 @@ Document* iframe_doc = frame_owner_element->contentDocument(); Element* target = iframe_doc->getElementById("target"); HitTestResult result = target->GetLayoutObject()->HitTestForOcclusion(); - EXPECT_TRUE(result.InnerNode() == target); + EXPECT_EQ(result.InnerNode(), target); Element* occluder = GetDocument().getElementById("occluder"); occluder->SetInlineStyleProperty(CSSPropertyMarginTop, "-150px"); GetDocument().View()->UpdateAllLifecyclePhases(); result = target->GetLayoutObject()->HitTestForOcclusion(); - EXPECT_TRUE(result.InnerNode() == occluder); + EXPECT_EQ(result.InnerNode(), occluder); } } // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_node.cc b/third_party/blink/renderer/core/layout/ng/ng_block_node.cc index 4cd42c0..246e300 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_block_node.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
@@ -181,6 +181,9 @@ LayoutBlockFlow* block_flow = box_->IsLayoutNGMixin() ? ToLayoutBlockFlow(box_) : nullptr; + if (RuntimeEnabledFeatures::TrackLayoutPassesPerBlockEnabled() && block_flow) + block_flow->IncrementLayoutPassCount(); + NGLayoutInputNode first_child = FirstChild(); scoped_refptr<NGLayoutResult> layout_result; if (block_flow) {
diff --git a/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc b/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc index 60d94a5..a5f9add 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc
@@ -2660,10 +2660,7 @@ void AXLayoutObject::HandleAutofillStateChanged(bool is_available) { if (is_autofill_available_ != is_available) { is_autofill_available_ = is_available; - // Reusing the value change event in order to invalidate, even though the - // value did not necessarily change. - // TODO(dmazzoni) change to using a MarkDirty() API. - AXObjectCache().PostNotification(this, ax::mojom::Event::kValueChanged); + AXObjectCache().MarkAXObjectDirty(this, false); } }
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc index b40fd27e..f43a06c 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc
@@ -693,11 +693,7 @@ ChildrenChanged(element->parentNode()); } else { // Refresh the focusable state on the exposed object. - // Reusing the value change event in order to invalidate, even though the - // value did not necessarily change. - // TODO(accessibility) find out why using MarkAXObjectDirty(obj, false) does - // not cause a state change event to be emitted. - PostNotification(obj, ax::mojom::Event::kValueChanged); + MarkAXObjectDirty(obj, false); } }
diff --git a/third_party/blink/renderer/modules/webaudio/audio_node.cc b/third_party/blink/renderer/modules/webaudio/audio_node.cc index 9fa74340..bc76efec 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_node.cc +++ b/third_party/blink/renderer/modules/webaudio/audio_node.cc
@@ -450,10 +450,9 @@ // the outputs so that the tail for the node can be output. // Otherwise, we can disable the outputs right away. if (RequiresTailProcessing()) { - if (Context()->ContextState() != - BaseAudioContext::AudioContextState::kClosed) { - Context()->GetDeferredTaskHandler().AddTailProcessingHandler(this); - } + auto& deferred_task_handler = Context()->GetDeferredTaskHandler(); + if (deferred_task_handler.AcceptsTailProcessing()) + deferred_task_handler.AddTailProcessingHandler(this); } else { DisableOutputs(); }
diff --git a/third_party/blink/renderer/modules/webaudio/base_audio_context.cc b/third_party/blink/renderer/modules/webaudio/base_audio_context.cc index f97328b..eb0c9d7 100644 --- a/third_party/blink/renderer/modules/webaudio/base_audio_context.cc +++ b/third_party/blink/renderer/modules/webaudio/base_audio_context.cc
@@ -612,6 +612,9 @@ WrapPersistent(this))); } + if (new_state == kClosed) + GetDeferredTaskHandler().StopAcceptingTailProcessing(); + // Notify context that state changed if (GetExecutionContext()) { GetExecutionContext()
diff --git a/third_party/blink/renderer/modules/webaudio/deferred_task_handler.cc b/third_party/blink/renderer/modules/webaudio/deferred_task_handler.cc index 0e27a15..5174ef59 100644 --- a/third_party/blink/renderer/modules/webaudio/deferred_task_handler.cc +++ b/third_party/blink/renderer/modules/webaudio/deferred_task_handler.cc
@@ -167,6 +167,7 @@ void DeferredTaskHandler::AddTailProcessingHandler( scoped_refptr<AudioHandler> handler) { + DCHECK(accepts_tail_processing_); AssertGraphOwner(); if (!tail_processing_handlers_.Contains(handler)) {
diff --git a/third_party/blink/renderer/modules/webaudio/deferred_task_handler.h b/third_party/blink/renderer/modules/webaudio/deferred_task_handler.h index 4282936..0bc00da3 100644 --- a/third_party/blink/renderer/modules/webaudio/deferred_task_handler.h +++ b/third_party/blink/renderer/modules/webaudio/deferred_task_handler.h
@@ -109,6 +109,9 @@ void RequestToDeleteHandlersOnMainThread(); void ClearHandlersToBeDeleted(); + bool AcceptsTailProcessing() const { return accepts_tail_processing_; } + void StopAcceptingTailProcessing() { accepts_tail_processing_ = false; } + // If |node| requires tail processing, add it to the list of tail // nodes so the tail is processed. void AddTailProcessingHandler(scoped_refptr<AudioHandler>); @@ -228,11 +231,16 @@ // Nodes that are processing its tail. Vector<scoped_refptr<AudioHandler>> tail_processing_handlers_; + // Tail processing nodes that are now finished and want the output to be // disabled. This is updated in the audio thread (with the graph lock). The // main thread will disable the outputs. Vector<scoped_refptr<AudioHandler>> finished_tail_processing_handlers_; + // Once the associated context closes, new tail processing handlers are not + // accepted. + bool accepts_tail_processing_ = true; + scoped_refptr<base::SingleThreadTaskRunner> task_runner_; // Graph locking.
diff --git a/third_party/minizip/README.chromium b/third_party/minizip/README.chromium index e6602fe..85a56c2 100644 --- a/third_party/minizip/README.chromium +++ b/third_party/minizip/README.chromium
@@ -1,8 +1,8 @@ Name: nmoinvaz/minizip Short name: minizip URL: https://github.com/nmoinvaz/minizip -Version: 2.7.4 -Revision: c47090678d687742eddc60d07c5430279af416d8 +Version: 0 +Revision: 4d4c9db5b019e71b4a40fb41ab21fb47de12ae69 Security critical: yes License: Custom license License File: src/LICENSE
diff --git a/third_party/zlib/arm_features.c b/third_party/zlib/arm_features.c index 60acbac..a91030d 100644 --- a/third_party/zlib/arm_features.c +++ b/third_party/zlib/arm_features.c
@@ -7,6 +7,11 @@ #include "arm_features.h" #include "zutil.h" + +int ZLIB_INTERNAL arm_cpu_enable_crc32 = 0; +int ZLIB_INTERNAL arm_cpu_enable_pmull = 0; + +#if !defined(_MSC_VER) #include <pthread.h> #include <stdint.h> @@ -19,9 +24,6 @@ #error ### No ARM CPU features detection in your platform/OS #endif -int ZLIB_INTERNAL arm_cpu_enable_crc32 = 0; -int ZLIB_INTERNAL arm_cpu_enable_pmull = 0; - static pthread_once_t cpu_check_inited_once = PTHREAD_ONCE_INIT; static void init_arm_features(void) @@ -58,3 +60,31 @@ { pthread_once(&cpu_check_inited_once, init_arm_features); } +#else +#include <windows.h> + +static BOOL CALLBACK _arm_check_features(PINIT_ONCE once, + PVOID param, + PVOID *context); +static INIT_ONCE cpu_check_inited_once = INIT_ONCE_STATIC_INIT; + + +void ZLIB_INTERNAL arm_check_features(void) +{ + InitOnceExecuteOnce(&cpu_check_inited_once, _arm_check_features, + NULL, NULL); +} + +static BOOL CALLBACK _arm_check_features(PINIT_ONCE once, + PVOID param, + PVOID *context) +{ + if (IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE)) + arm_cpu_enable_crc32 = 1; + + if (IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE)) + arm_cpu_enable_pmull = 1; + + return TRUE; +} +#endif /* _MSC_VER */
diff --git a/tools/binary_size/libsupersize/archive.py b/tools/binary_size/libsupersize/archive.py index 0b879f4..95a440b372 100644 --- a/tools/binary_size/libsupersize/archive.py +++ b/tools/binary_size/libsupersize/archive.py
@@ -601,7 +601,7 @@ SRC_ROOT. cache: Dict of OWNERS paths. Used instead of filesystem if paths are present in the dict. - knobs: Instance of SectionSizeKnobs. Tunable knobs and options. + knobs: Instance of SectionSizeKnobs with tunable knobs and options. Returns: COMPONENT belonging to |start_path|, or empty string if not found. @@ -736,7 +736,7 @@ apk_path: Path to the .apk file to measure. tool_prefix: Prefix for c++filt & nm. output_directory: Build output directory. - linker_name: 'gold', 'lld_v#' (# is a number), 'lld-lto_v#', or None. + linker_name: A coded linker name (see linker_map_parser.py). Returns: None if |elf_path| is not supplied. Otherwise returns dict mapping string @@ -1194,13 +1194,20 @@ Args: map_path: Path to the linker .map(.gz) file to parse. - elf_path: Path to the corresponding unstripped ELF file. Used to find symbol - aliases and inlined functions. Can be None. tool_prefix: Prefix for c++filt & nm (required). output_directory: Build output directory. If None, source_paths and symbol alias information will not be recorded. + elf_path: Path to the corresponding unstripped ELF file. Used to find symbol + aliases and inlined functions. Can be None. + apk_path: Path to the .apk file to measure. track_string_literals: Whether to break down "** merge string" sections into smaller symbols (requires output_directory). + metadata: Metadata dict from CreateMetadata(). + apk_so_path: Path to an .so file within an APK file. + pak_files: List of paths to .pak files. + pak_info_file: Path to a .pak.info file. + linker_name: A coded linker name (see linker_map_parser.py). + knobs: Instance of SectionSizeKnobs with tunable knobs and options. Returns: A tuple of (section_sizes, raw_symbols).
diff --git a/tools/binary_size/libsupersize/linker_map_parser.py b/tools/binary_size/libsupersize/linker_map_parser.py index 7111e5c..9ba20f0 100755 --- a/tools/binary_size/libsupersize/linker_map_parser.py +++ b/tools/binary_size/libsupersize/linker_map_parser.py
@@ -3,7 +3,20 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""Parser for linker map files.""" +"""Parser for linker map files. + +The format of a linker map file depends on the linker that generates it. This +file uses "coded linker name" to identify formats and variants: + + 'gold': The gold linker (usage is being deprecated by Chrome). + 'lld_v0': LLD linker (no LTO), old format. + 'lld-lto_v0': LLD linker with ThinLTO, old format. + 'lld_v1': LLD linker (no LTO), new format. + 'lld-lto_v1': LLD linker with ThinLTO, new format. + +The |linker_name| parameter in various functions must take one of the above +coded linker name values. +""" from __future__ import print_function @@ -469,7 +482,7 @@ lines: Iterable of lines from the linker map. Returns: - A coded linker name: 'gold', 'lld_v#' (# is a number), or 'lld-lto_v#'. + A coded linker name. """ first_line = next(lines)
diff --git a/tools/grit/grit/format/chrome_messages_json.py b/tools/grit/grit/format/chrome_messages_json.py index 27a9da1..43853547 100644 --- a/tools/grit/grit/format/chrome_messages_json.py +++ b/tools/grit/grit/format/chrome_messages_json.py
@@ -15,15 +15,11 @@ def Format(root, lang='en', output_dir='.'): """Format the messages as JSON.""" - yield '{\n' + yield '{' encoder = JSONEncoder(ensure_ascii=False) - format = (' "%s": {\n' - ' "message": %s%s\n' - ' }') - placeholder_format = (' "%i": {\n' - ' "content": "$%i"\n' - ' }') + format = '"%s":{"message":%s%s}' + placeholder_format = '"%i":{"content":"$%i"}' first = True for child in root.ActiveDescendants(): if isinstance(child, message.MessageNode): @@ -50,15 +46,15 @@ break loc_message = loc_message.replace('$%d' % i, '$%d$' % i) if placeholders: - placeholders += ',\n' + placeholders += ',' placeholders += placeholder_format % (i, i) if not first: - yield ',\n' + yield ',' first = False if placeholders: - placeholders = ',\n "placeholders": {\n%s\n }' % placeholders + placeholders = ',"placeholders":{%s}' % placeholders yield format % (id, loc_message, placeholders) - yield '\n}\n' + yield '}'
diff --git a/tools/grit/grit/format/chrome_messages_json_unittest.py b/tools/grit/grit/format/chrome_messages_json_unittest.py index cf6de6c7..ae9c7a6 100755 --- a/tools/grit/grit/format/chrome_messages_json_unittest.py +++ b/tools/grit/grit/format/chrome_messages_json_unittest.py
@@ -6,6 +6,7 @@ """Unittest for chrome_messages_json.py. """ +import json import os import sys if __name__ == '__main__': @@ -20,6 +21,10 @@ class ChromeMessagesJsonFormatUnittest(unittest.TestCase): + # The default unittest diff limit is too low for our unittests. + # Allow the framework to show the full diff output all the time. + maxDiff = None + def testMessages(self): root = util.ParseGrdForUnittest(u""" <messages> @@ -96,7 +101,7 @@ } } """ - self.assertEqual(test.strip(), output.strip()) + self.assertEqual(json.loads(test), json.loads(output)) def testTranslations(self): root = util.ParseGrdForUnittest(""" @@ -121,7 +126,7 @@ } } """ - self.assertEqual(test.strip(), output.strip()) + self.assertEqual(json.loads(test), json.loads(output)) def testSkipMissingTranslations(self): grd = """<?xml version="1.0" encoding="UTF-8"?> @@ -141,12 +146,25 @@ build.RcBuilder.ProcessNode(root, DummyOutput('chrome_messages_json', 'fr'), buf) output = buf.getvalue() - test = u""" -{ + test = u'{}' + self.assertEqual(test, output) -} -""" - self.assertEqual(test.strip(), output.strip()) + def testVerifyMinification(self): + root = util.ParseGrdForUnittest(u""" + <messages> + <message name="IDS"> + <ph name="BEGIN">$1<ex>a</ex></ph>test<ph name="END">$2<ex>b</ex></ph> + </message> + </messages> + """) + + buf = StringIO.StringIO() + build.RcBuilder.ProcessNode(root, DummyOutput('chrome_messages_json', 'en'), + buf) + output = buf.getvalue() + test = (u'{"IDS":{"message":"$1$test$2$","placeholders":' + u'{"1":{"content":"$1"},"2":{"content":"$2"}}}}') + self.assertEqual(test, output) class DummyOutput(object):
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml index 74da157..c852ada 100644 --- a/tools/metrics/actions/actions.xml +++ b/tools/metrics/actions/actions.xml
@@ -17216,6 +17216,7 @@ </action> <action name="Signin_Signin_FromForceSigninWarning"> + <obsolete>Deprecated as the warning dialog is no longer used.</obsolete> <owner>zmin@chromium.org</owner> <description> Record when a user signs in again from the force sign in auth error warning
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 0c48007..aa6152b79 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -17263,6 +17263,7 @@ <int value="1290" label="TABS_GOBACK"/> <int value="1291" label="BRAILLEDISPLAYPRIVATE_UPDATEBLUETOOTHBRAILLEDISPLAYADDRESS"/> + <int value="1292" label="AUTOTESTPRIVATE_SETASSISTANTENABLED"/> </enum> <enum name="ExtensionIconState">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 495a3571..796e8d8d 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -24922,6 +24922,9 @@ </histogram> <histogram name="EasyUnlock.AuthProximity.TimeSinceLastZeroRssi" units="ms"> + <obsolete> + Deprecated as of 11/2018. + </obsolete> <owner>tengs@chromium.org</owner> <owner>xiaowenx@chromium.org</owner> <summary> @@ -24939,6 +24942,9 @@ </histogram> <histogram name="EasyUnlock.AuthProximity.TransmitPowerDelta" units="dBm"> + <obsolete> + Deprecated as of 11/2018. + </obsolete> <owner>tengs@chromium.org</owner> <owner>xiaowenx@chromium.org</owner> <summary> @@ -32105,6 +32111,17 @@ </summary> </histogram> +<histogram name="Extensions.IsRenderedIconSufficientlyVisibleTime" + units="microseconds" expires_after="2019-12-01"> + <owner>dbertoni@chromium.org</owner> + <owner>extensions-core@chromium.org</owner> + <summary> + The amount of elapsed time taken to render an icon against a specified + background color and determine whether it would be visible to the user. + Recorded every time the analysis code is called. + </summary> +</histogram> + <histogram name="Extensions.LoadAll"> <owner>rdevlin.cronin@chromium.org</owner> <summary>The number of extensions and themes loaded at profile open.</summary> @@ -51139,7 +51156,7 @@ </histogram> <histogram name="MobileStartup.LoadedHomepageOnColdStart" enum="BooleanIsNtp" - expires_after="M72"> + expires_after="M75"> <owner>tedchoc@chromium.org</owner> <owner>danielpark@chromium.org</owner> <owner>twellington@chromium.org</owner>
diff --git a/tools/perf/benchmarks/system_health_smoke_test.py b/tools/perf/benchmarks/system_health_smoke_test.py index 73afc74..0fe5aa7 100644 --- a/tools/perf/benchmarks/system_health_smoke_test.py +++ b/tools/perf/benchmarks/system_health_smoke_test.py
@@ -91,6 +91,7 @@ 'system_health.memory_desktop/load:news:cnn', 'system_health.memory_desktop/load:news:wikipedia', 'system_health.memory_desktop/load:search:baidu', + 'system_health.memory_desktop/load:search:google', 'system_health.memory_desktop/load:search:yahoo', 'system_health.memory_desktop/load:search:yandex', 'system_health.memory_desktop/load:tools:stackoverflow', @@ -99,6 +100,7 @@ 'system_health.memory_mobile/load:media:google_images', 'system_health.memory_mobile/load:news:wikipedia', 'system_health.memory_mobile/load:search:baidu', + 'system_health.memory_mobile/load:search:google', 'system_health.memory_mobile/load:search:yahoo', 'system_health.memory_mobile/load:search:yandex',
diff --git a/tools/perf/page_sets/data/system_health_desktop.json b/tools/perf/page_sets/data/system_health_desktop.json index ccf2069..c8b43a7 100644 --- a/tools/perf/page_sets/data/system_health_desktop.json +++ b/tools/perf/page_sets/data/system_health_desktop.json
@@ -234,6 +234,9 @@ "load:search:google": { "DEFAULT": "system_health_desktop_022.wprgo" }, + "load:search:google:2018": { + "DEFAULT": "system_health_desktop_b11350f30f.wprgo" + }, "load:search:taobao": { "DEFAULT": "system_health_desktop_000.wprgo" },
diff --git a/tools/perf/page_sets/data/system_health_desktop_b11350f30f.wprgo.sha1 b/tools/perf/page_sets/data/system_health_desktop_b11350f30f.wprgo.sha1 new file mode 100644 index 0000000..397240a --- /dev/null +++ b/tools/perf/page_sets/data/system_health_desktop_b11350f30f.wprgo.sha1
@@ -0,0 +1 @@ +b11350f30fff944eff752f84e498b364be782643 \ No newline at end of file
diff --git a/tools/perf/page_sets/data/system_health_mobile.json b/tools/perf/page_sets/data/system_health_mobile.json index 3f83fe99..29b1b99 100644 --- a/tools/perf/page_sets/data/system_health_mobile.json +++ b/tools/perf/page_sets/data/system_health_mobile.json
@@ -201,6 +201,9 @@ "load:search:google": { "DEFAULT": "system_health_mobile_029.wprgo" }, + "load:search:google:2018": { + "DEFAULT": "system_health_mobile_09493f5937.wprgo" + }, "load:search:taobao": { "DEFAULT": "system_health_mobile_000.wprgo" },
diff --git a/tools/perf/page_sets/data/system_health_mobile_09493f5937.wprgo.sha1 b/tools/perf/page_sets/data/system_health_mobile_09493f5937.wprgo.sha1 new file mode 100644 index 0000000..1ac13cac --- /dev/null +++ b/tools/perf/page_sets/data/system_health_mobile_09493f5937.wprgo.sha1
@@ -0,0 +1 @@ +09493f5937a66e59fc9bd561e160293b17ddec52 \ No newline at end of file
diff --git a/tools/perf/page_sets/system_health/loading_stories.py b/tools/perf/page_sets/system_health/loading_stories.py index c865e94..68bac45 100644 --- a/tools/perf/page_sets/system_health/loading_stories.py +++ b/tools/perf/page_sets/system_health/loading_stories.py
@@ -31,6 +31,12 @@ TAGS = [story_tags.YEAR_2016] +class LoadGoogleStory2018(_LoadingStory): + NAME = 'load:search:google:2018' + URL = 'https://www.google.co.uk/search?q=pepper' + TAGS = [story_tags.YEAR_2018] + + class LoadBaiduStory(_LoadingStory): NAME = 'load:search:baidu' URL = 'https://www.baidu.com/s?word=google'
diff --git a/ui/accessibility/BUILD.gn b/ui/accessibility/BUILD.gn index 3d33dd9..4dc34fd 100644 --- a/ui/accessibility/BUILD.gn +++ b/ui/accessibility/BUILD.gn
@@ -147,16 +147,6 @@ if (use_glib) { configs += [ "//build/config/linux:glib" ] } - - if (use_x11) { - sources += [ "platform/atk_util_auralinux_x11.cc" ] - - configs += [ "//build/config/linux:x11" ] - public_deps += [ - "//ui/events/x", - "//ui/gfx/x", - ] - } } if (use_aura) { @@ -252,10 +242,7 @@ libs = [ "oleacc.lib" ] } if (use_atk) { - sources += [ - "platform/atk_util_auralinux_unittest.cc", - "platform/ax_platform_node_auralinux_unittest.cc", - ] + sources += [ "platform/ax_platform_node_auralinux_unittest.cc" ] configs += [ "//build/config/linux/atk" ] } }
diff --git a/ui/accessibility/platform/DEPS b/ui/accessibility/platform/DEPS deleted file mode 100644 index d457dd7d..0000000 --- a/ui/accessibility/platform/DEPS +++ /dev/null
@@ -1,5 +0,0 @@ -specific_include_rules = { - "atk_util_auralinux_x11.cc": [ - "+ui/events/x", - ] -}
diff --git a/ui/accessibility/platform/atk_util_auralinux.cc b/ui/accessibility/platform/atk_util_auralinux.cc index 85895d8..eab53e1 100644 --- a/ui/accessibility/platform/atk_util_auralinux.cc +++ b/ui/accessibility/platform/atk_util_auralinux.cc
@@ -3,8 +3,6 @@ // found in the LICENSE file. #include <atk/atk.h> -#include <map> -#include <utility> #include "base/environment.h" #include "base/memory/singleton.h" @@ -77,25 +75,6 @@ return "1.0"; } -static std::map<guint, std::pair<AtkKeySnoopFunc, gpointer>> - g_key_snoop_function_map; - -static guint atk_util_add_key_event_listener(AtkKeySnoopFunc key_snoop_function, - gpointer data) { - static guint current_key_event_listener_id = 0; - - current_key_event_listener_id++; - g_key_snoop_function_map[current_key_event_listener_id] = - std::make_pair(key_snoop_function, data); - return current_key_event_listener_id; -} - -static void atk_util_remove_key_event_listener(guint listener_id) { - auto it = g_key_snoop_function_map.find(listener_id); - if (it != g_key_snoop_function_map.end()) - g_key_snoop_function_map.erase(it); -} - static void atk_util_auralinux_class_init(AtkUtilAuraLinuxClass *klass) { AtkUtilClass *atk_class; gpointer data; @@ -106,8 +85,6 @@ atk_class->get_root = atk_util_auralinux_get_root; atk_class->get_toolkit_name = atk_util_auralinux_get_toolkit_name; atk_class->get_toolkit_version = atk_util_auralinux_get_toolkit_version; - atk_class->add_key_event_listener = atk_util_add_key_event_listener; - atk_class->remove_key_event_listener = atk_util_remove_key_event_listener; } G_END_DECLS @@ -153,32 +130,4 @@ InitializeAsync(); } -// static -DiscardAtkKeyEvent AtkUtilAuraLinux::HandleAtkKeyEvent( - AtkKeyEventStruct* key_event) { - DCHECK(key_event); - - if (!GetInstance()->ShouldEnableAccessibility()) - return DiscardAtkKeyEvent::Retain; - - GetInstance()->InitializeAsync(); - - bool discard = false; - for (auto it = g_key_snoop_function_map.begin(); - it != g_key_snoop_function_map.end(); it++) { - AtkKeySnoopFunc key_snoop_function = it->second.first; - gpointer data = it->second.second; - if (key_snoop_function(key_event, data) != 0) - discard = true; - } - return discard ? DiscardAtkKeyEvent::Discard : DiscardAtkKeyEvent::Retain; -} - -#if !defined(USE_X11) -DiscardAtkKeyEvent AtkUtilAuraLinux::HandleKeyEvent( - const ui::KeyEvent& ui_key_event) { - NOTREACHED(); -} -#endif - } // namespace ui
diff --git a/ui/accessibility/platform/atk_util_auralinux.h b/ui/accessibility/platform/atk_util_auralinux.h index b846d5f..286d49a 100644 --- a/ui/accessibility/platform/atk_util_auralinux.h +++ b/ui/accessibility/platform/atk_util_auralinux.h
@@ -5,34 +5,12 @@ #ifndef UI_ACCESSIBILITY_AX_UTIL_AURALINUX_H_ #define UI_ACCESSIBILITY_AX_UTIL_AURALINUX_H_ -#include <atk/atk.h> - #include "base/macros.h" #include "base/memory/singleton.h" #include "ui/accessibility/ax_export.h" -#if defined(USE_X11) -#include "ui/gfx/x/x11.h" -#endif - namespace ui { -// These values are duplicates of the GDK values that can be found in -// <gdk/gdktypes.h>. ATK expects the GDK values, but we don't want to depend on -// GDK here. -typedef enum { - kAtkShiftMask = 1 << 0, - kAtkLockMask = 1 << 1, - kAtkControlMask = 1 << 2, - kAtkMod1Mask = 1 << 3, - kAtkMod2Mask = 1 << 4, - kAtkMod3Mask = 1 << 5, - kAtkMod4Mask = 1 << 6, - KAtkMod5Mask = 1 << 7, -} AtkKeyModifierMask; - -enum DiscardAtkKeyEvent { Discard, Retain }; - // This singleton class initializes ATK (accessibility toolkit) and // registers an implementation of the AtkUtil class, a global class that // every accessible application needs to register once. @@ -46,12 +24,6 @@ void InitializeAsync(); void InitializeForTesting(); - static DiscardAtkKeyEvent HandleAtkKeyEvent(AtkKeyEventStruct* key_event); - -#if defined(USE_X11) - static DiscardAtkKeyEvent HandleKeyEvent(XEvent* xevent); -#endif - private: friend struct base::DefaultSingletonTraits<AtkUtilAuraLinux>;
diff --git a/ui/accessibility/platform/atk_util_auralinux_unittest.cc b/ui/accessibility/platform/atk_util_auralinux_unittest.cc deleted file mode 100644 index 85d88e2..0000000 --- a/ui/accessibility/platform/atk_util_auralinux_unittest.cc +++ /dev/null
@@ -1,77 +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. - -// Chromium cannot upgrade to ATK 2.12 API as it still needs to run -// valid builds for Ubuntu Trusty. -#define ATK_DISABLE_DEPRECATION_WARNINGS - -#include <atk/atk.h> - -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/accessibility/platform/atk_util_auralinux.h" -#include "ui/accessibility/platform/ax_platform_node_auralinux.h" -#include "ui/accessibility/platform/ax_platform_node_unittest.h" -#include "ui/accessibility/platform/test_ax_node_wrapper.h" - -namespace ui { - -class AtkUtilAuraLinuxTest : public AXPlatformNodeTest { - public: - AtkUtilAuraLinuxTest() { - // We need to create a platform node in order to install it as the root - // ATK node. The ATK bridge will complain if we try to use it without a - // root node installed. - AXNodeData root; - root.id = 1; - Init(root); - - TestAXNodeWrapper* wrapper = - TestAXNodeWrapper::GetOrCreate(tree_.get(), GetRootNode()); - if (!wrapper) - NOTREACHED(); - AXPlatformNodeAuraLinux::SetApplication(wrapper->ax_platform_node()); - - AtkUtilAuraLinux::GetInstance()->InitializeForTesting(); - } - - ~AtkUtilAuraLinuxTest() override { - TestAXNodeWrapper* wrapper = - TestAXNodeWrapper::GetOrCreate(tree_.get(), GetRootNode()); - if (!wrapper) - NOTREACHED(); - g_object_unref(wrapper->ax_platform_node()->GetNativeViewAccessible()); - } -}; - -TEST_F(AtkUtilAuraLinuxTest, KeySnooping) { - AtkKeySnoopFunc key_snoop_func = reinterpret_cast<AtkKeySnoopFunc>( - +[](AtkKeyEventStruct* key_event, int* keyval_seen) { - *keyval_seen = key_event->keyval; - }); - - int keyval_seen = 0; - guint listener_id = atk_add_key_event_listener(key_snoop_func, &keyval_seen); - - AtkKeyEventStruct atk_key_event; - atk_key_event.type = ATK_KEY_EVENT_PRESS; - atk_key_event.state = 0; - atk_key_event.keyval = 55; - atk_key_event.keycode = 10; - atk_key_event.timestamp = 10; - atk_key_event.string = nullptr; - atk_key_event.length = 0; - - AtkUtilAuraLinux* atk_util = AtkUtilAuraLinux::GetInstance(); - atk_util->HandleAtkKeyEvent(&atk_key_event); - EXPECT_EQ(keyval_seen, 55); - - atk_remove_key_event_listener(listener_id); - - keyval_seen = 0; - atk_util->HandleAtkKeyEvent(&atk_key_event); - - EXPECT_EQ(keyval_seen, 0); -} - -} // namespace ui
diff --git a/ui/accessibility/platform/atk_util_auralinux_x11.cc b/ui/accessibility/platform/atk_util_auralinux_x11.cc deleted file mode 100644 index 143d9ca..0000000 --- a/ui/accessibility/platform/atk_util_auralinux_x11.cc +++ /dev/null
@@ -1,60 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <atk/atk.h> - -#include "ui/accessibility/platform/atk_util_auralinux.h" -#include "ui/events/x/events_x_utils.h" - -namespace ui { - -// static -DiscardAtkKeyEvent AtkUtilAuraLinux::HandleKeyEvent(XEvent* xevent) { - if (!GetInstance()->ShouldEnableAccessibility()) - return DiscardAtkKeyEvent::Retain; - - AtkKeyEventStruct atk_key_event; - if (xevent->type == KeyPress) - atk_key_event.type = ATK_KEY_EVENT_PRESS; - else if (xevent->type == KeyRelease) - atk_key_event.type = ATK_KEY_EVENT_RELEASE; - else - NOTREACHED() << xevent->type; - - XKeyEvent& xkey = xevent->xkey; - KeySym keysym = NoSymbol; - XLookupString(&xkey, nullptr, 0, &keysym, nullptr); - - atk_key_event.state = xkey.state; - atk_key_event.keyval = keysym; - atk_key_event.keycode = xkey.keycode; - atk_key_event.timestamp = xkey.time; - - // This string property matches the one that was removed from GdkEventKey. In - // the future, ATK clients should no longer rely on it, so we set it to null. - atk_key_event.string = nullptr; - atk_key_event.length = 0; - - int flags = ui::EventFlagsFromXEvent(*xevent); - if (flags & ui::EF_SHIFT_DOWN) - atk_key_event.state |= AtkKeyModifierMask::kAtkShiftMask; - if (flags & ui::EF_CAPS_LOCK_ON) - atk_key_event.state |= AtkKeyModifierMask::kAtkLockMask; - if (flags & ui::EF_CONTROL_DOWN) - atk_key_event.state |= AtkKeyModifierMask::kAtkControlMask; - if (flags & ui::EF_ALT_DOWN) - atk_key_event.state |= AtkKeyModifierMask::kAtkMod1Mask; - if (flags & ui::EF_NUM_LOCK_ON) - atk_key_event.state |= AtkKeyModifierMask::kAtkMod2Mask; - if (flags & ui::EF_MOD3_DOWN) - atk_key_event.state |= AtkKeyModifierMask::kAtkMod3Mask; - if (flags & ui::EF_COMMAND_DOWN) - atk_key_event.state |= AtkKeyModifierMask::kAtkMod4Mask; - if (flags & ui::EF_ALTGR_DOWN) - atk_key_event.state |= AtkKeyModifierMask::KAtkMod5Mask; - - return HandleAtkKeyEvent(&atk_key_event); -} - -} // namespace ui
diff --git a/ui/aura/window_occlusion_tracker.cc b/ui/aura/window_occlusion_tracker.cc index 810a5d3..4e6cb1b 100644 --- a/ui/aura/window_occlusion_tracker.cc +++ b/ui/aura/window_occlusion_tracker.cc
@@ -96,6 +96,30 @@ env_->UnpauseWindowOcclusionTracking(); } +WindowOcclusionTracker::ScopedExclude::ScopedExclude(Window* window) + : window_(window) { + window->AddObserver(this); + window->env()->GetWindowOcclusionTracker()->Exclude(window_); +} + +WindowOcclusionTracker::ScopedExclude::~ScopedExclude() { + Shutdown(); +} + +void WindowOcclusionTracker::ScopedExclude::OnWindowDestroying( + aura::Window* window) { + DCHECK_EQ(window_, window); + Shutdown(); +} + +void WindowOcclusionTracker::ScopedExclude::Shutdown() { + if (window_) { + window_->RemoveObserver(this); + window_->env()->GetWindowOcclusionTracker()->Unexclude(window_); + window_ = nullptr; + } +} + void WindowOcclusionTracker::Track(Window* window) { DCHECK(window); DCHECK(window != window->GetRootWindow()); @@ -214,7 +238,7 @@ return false; } - if (WindowIsAnimated(window)) { + if (WindowIsAnimated(window) || WindowIsExcluded(window)) { SetWindowAndDescendantsAreOccluded(window, false); return true; } @@ -282,9 +306,7 @@ if (animator->IsAnimatingOnePropertyOf(kSkipWindowWhenPropertiesAnimated)) return false; animator->RemoveObserver(this); - auto root_window_state_it = root_windows_.find(window->GetRootWindow()); - if (root_window_state_it != root_windows_.end()) - MarkRootWindowAsDirty(&root_window_state_it->second); + MarkRootWindowAsDirty(window->GetRootWindow()); return true; }); } @@ -345,6 +367,10 @@ return base::ContainsKey(animated_windows_, window); } +bool WindowOcclusionTracker::WindowIsExcluded(Window* window) const { + return base::ContainsKey(excluded_windows_, window); +} + template <typename Predicate> void WindowOcclusionTracker::MarkRootWindowAsDirtyAndMaybeComputeOcclusionIf( Window* window, @@ -366,12 +392,12 @@ if (root_window_state_it->second.dirty) return; if (predicate()) { - MarkRootWindowAsDirty(&root_window_state_it->second); + MarkRootWindowStateAsDirty(&root_window_state_it->second); MaybeComputeOcclusion(); } } -void WindowOcclusionTracker::MarkRootWindowAsDirty( +void WindowOcclusionTracker::MarkRootWindowStateAsDirty( RootWindowState* root_window_state) { // If a root window is marked as dirty and occlusion states have already been // recomputed |kMaxRecomputeOcclusion| times, it means that they are not @@ -382,6 +408,14 @@ root_window_state->dirty = true; } +bool WindowOcclusionTracker::MarkRootWindowAsDirty(aura::Window* root_window) { + auto root_window_state_it = root_windows_.find(root_window); + if (root_window_state_it == root_windows_.end()) + return false; + MarkRootWindowStateAsDirty(&root_window_state_it->second); + return true; +} + bool WindowOcclusionTracker::WindowOrParentIsAnimated(Window* window) const { while (window && !WindowIsAnimated(window)) window = window->parent(); @@ -430,13 +464,15 @@ // Changing the opacity of a window has no effect on the occlusion state of // the window or its children. It can however affect the occlusion state of // other windows in the tree if it is visible and not animated (animated - // windows aren't considered in occlusion computations). - return window->IsVisible() && !WindowOrParentIsAnimated(window); + // windows aren't considered in occlusion computations), unless it is + // excluded. + return window->IsVisible() && !WindowOrParentIsAnimated(window) && + !WindowIsExcluded(window); } bool WindowOcclusionTracker::WindowMoveMayAffectOcclusionStates( Window* window) const { - return !WindowOrParentIsAnimated(window) && + return !WindowOrParentIsAnimated(window) && !WindowIsExcluded(window) && (WindowOrDescendantIsOpaque(window) || WindowOrDescendantIsTrackedAndVisible(window)); } @@ -446,7 +482,7 @@ DCHECK(root_window); RootWindowState& root_window_state = root_windows_[root_window]; ++root_window_state.num_tracked_windows; - MarkRootWindowAsDirty(&root_window_state); + MarkRootWindowStateAsDirty(&root_window_state); // It's only useful to track the host if |window| is the first tracked window // under |root_window|. All windows under the same root have the same host. @@ -510,6 +546,27 @@ MaybeComputeOcclusion(); } +void WindowOcclusionTracker::Exclude(Window* window) { + // If threre is a valid use case to exclude the same window twice + // (e.g. independent clients may try to exclude the same window), + // introduce the count. + DCHECK(!WindowIsExcluded(window)); + excluded_windows_.insert(window); + if (window->IsVisible()) { + if (MarkRootWindowAsDirty(window->GetRootWindow())) + MaybeComputeOcclusion(); + } +} + +void WindowOcclusionTracker::Unexclude(Window* window) { + DCHECK(WindowIsExcluded(window)); + excluded_windows_.erase(window); + if (window->IsVisible()) { + if (MarkRootWindowAsDirty(window->GetRootWindow())) + MaybeComputeOcclusion(); + } +} + void WindowOcclusionTracker::OnLayerAnimationEnded( ui::LayerAnimationSequence* sequence) { CleanupAnimatedWindows(); @@ -651,11 +708,8 @@ return; animator->RemoveObserver(this); - auto root_window_state_it = root_windows_.find(window->GetRootWindow()); - if (root_window_state_it != root_windows_.end()) { - MarkRootWindowAsDirty(&root_window_state_it->second); + if (MarkRootWindowAsDirty(window->GetRootWindow())) MaybeComputeOcclusion(); - } } void WindowOcclusionTracker::OnOcclusionStateChanged(
diff --git a/ui/aura/window_occlusion_tracker.h b/ui/aura/window_occlusion_tracker.h index eb73dd4f..6258792 100644 --- a/ui/aura/window_occlusion_tracker.h +++ b/ui/aura/window_occlusion_tracker.h
@@ -65,6 +65,31 @@ DISALLOW_COPY_AND_ASSIGN(ScopedPause); }; + // Exclude the window from occlusion tracking so that a window behind the + // given window is still considered visible. The excluded window itself and + // its descendant windows, if tracked, are considered visible. This is useful + // for a window being dragged or resized to avoid unnecessary occlusion state + // change triggered by these operation, because the window bounds are + // temporary until it is finished. + // Note that this is intended to be used by window manager and not by mus + // client process. + class AURA_EXPORT ScopedExclude : public aura::WindowObserver { + public: + explicit ScopedExclude(Window* window); + ~ScopedExclude() override; + + Window* window() { return window_; } + + private: + // aura::WindowObserver: + void OnWindowDestroying(aura::Window* window) override; + + void Shutdown(); + + Window* window_; + DISALLOW_COPY_AND_ASSIGN(ScopedExclude); + }; + // Start tracking the occlusion state of |window|. void Track(Window* window); @@ -154,6 +179,9 @@ // Returns true if |window| is in |animated_windows_|. bool WindowIsAnimated(Window* window) const; + // Returns true if |window| is in |excluded_windows_|. + bool WindowIsExcluded(Window* window) const; + // If the root of |window| is not dirty and |predicate| is true, marks the // root of |window| as dirty. Then, calls MaybeComputeOcclusion(). // |predicate| is not evaluated if the root of |window| is already dirty when @@ -162,8 +190,12 @@ void MarkRootWindowAsDirtyAndMaybeComputeOcclusionIf(Window* window, Predicate predicate); - // Marks |root_window| as dirty. - void MarkRootWindowAsDirty(RootWindowState* root_window_state); + // Marks |root_window_state| as dirty. + void MarkRootWindowStateAsDirty(RootWindowState* root_window_state); + + // Marks |root_window| as dirty. Returns false if none of the descendent + // windows in |root_window| are tracked. + bool MarkRootWindowAsDirty(aura::Window* root_window); // Returns true if |window| or one of its parents is in |animated_windows_|. bool WindowOrParentIsAnimated(Window* window) const; @@ -206,6 +238,11 @@ void Pause(); void Unpause(); + // Exclucde/Unexclude a window from occlusion tracking. See comment on + // ScopedExclude. + void Exclude(Window* window); + void Unexclude(Window* window); + // ui::LayerAnimationObserver: void OnLayerAnimationEnded(ui::LayerAnimationSequence* sequence) override; void OnLayerAnimationAborted(ui::LayerAnimationSequence* sequence) override; @@ -247,6 +284,10 @@ // aborted. base::flat_set<Window*> animated_windows_; + // Windows that are excluded from occlustion tracking. See comment on + // ScopedExclude. + base::flat_set<Window*> excluded_windows_; + // Root Windows of Windows in |tracked_windows_|. base::flat_map<Window*, RootWindowState> root_windows_;
diff --git a/ui/aura/window_occlusion_tracker_unittest.cc b/ui/aura/window_occlusion_tracker_unittest.cc index e46ddcd..2910be9 100644 --- a/ui/aura/window_occlusion_tracker_unittest.cc +++ b/ui/aura/window_occlusion_tracker_unittest.cc
@@ -37,6 +37,8 @@ void set_window(Window* window) { window_ = window; } + void SetName(const std::string& name) { window_->SetName(name); } + void set_expectation(Window::OcclusionState occlusion_state, const SkRegion& occluded_region) { expected_occlusion_state_ = occlusion_state; @@ -49,6 +51,7 @@ void OnWindowOcclusionChanged(Window::OcclusionState occlusion_state, const SkRegion& occluded_region) override { + SCOPED_TRACE(window_->GetName()); ASSERT_TRUE(window_); EXPECT_NE(occlusion_state, Window::OcclusionState::UNKNOWN); EXPECT_EQ(occlusion_state, expected_occlusion_state_); @@ -2017,4 +2020,135 @@ EXPECT_FALSE(delegate_a->is_expecting_call()); } +// Verify that the excluded window is indeed ignored by occlusion tracking. +TEST_F(WindowOcclusionTrackerTest, ExcludeWindow) { + MockWindowDelegate* delegate_a = new MockWindowDelegate(); + delegate_a->set_expectation(Window::OcclusionState::VISIBLE, SkRegion()); + CreateTrackedWindow(delegate_a, gfx::Rect(0, 0, 10, 10)); + EXPECT_FALSE(delegate_a->is_expecting_call()); + + delegate_a->SetName("WindowA"); + + delegate_a->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion()); + Window* window_b = CreateUntrackedWindow(gfx::Rect(0, 0, 100, 100), nullptr); + EXPECT_FALSE(delegate_a->is_expecting_call()); + + MockWindowDelegate* delegate_bb = new MockWindowDelegate(); + delegate_bb->set_expectation(Window::OcclusionState::VISIBLE, SkRegion()); + CreateTrackedWindow(delegate_bb, gfx::Rect(0, 0, 10, 10), window_b); + EXPECT_FALSE(delegate_bb->is_expecting_call()); + + delegate_bb->SetName("WindowBB"); + + delegate_bb->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion()); + Window* window_c = CreateUntrackedWindow(gfx::Rect(0, 0, 100, 100), nullptr); + EXPECT_FALSE(delegate_bb->is_expecting_call()); + + { + // |window_b| is excluded, so its child's occlusion state becomes VISIBlE. + delegate_bb->set_expectation(Window::OcclusionState::VISIBLE, SkRegion()); + EXPECT_TRUE(delegate_bb->is_expecting_call()); + WindowOcclusionTracker::ScopedExclude scoped(window_b); + EXPECT_FALSE(delegate_bb->is_expecting_call()); + + // Moving |window_c| out from |window_a| will make |window_a| visible + // because |window_b| is ignored. + SkRegion window_a_occlusion(SkIRect::MakeXYWH(100, 100, 100, 100)); + delegate_a->set_expectation(Window::OcclusionState::VISIBLE, + window_a_occlusion); + SkRegion window_bb_occlusion; + window_bb_occlusion.op(SkIRect::MakeXYWH(100, 100, 100, 100), + SkRegion::kUnion_Op); + delegate_bb->set_expectation(Window::OcclusionState::VISIBLE, + window_bb_occlusion); + window_c->SetBounds(gfx::Rect(100, 100, 100, 100)); + + // Un-excluding wil make |window_bb| OCCLUDED. + delegate_a->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion()); + delegate_bb->set_expectation(Window::OcclusionState::VISIBLE, + window_bb_occlusion); + } + EXPECT_FALSE(delegate_a->is_expecting_call()); + EXPECT_FALSE(delegate_bb->is_expecting_call()); + + { + delegate_bb->set_expectation(Window::OcclusionState::VISIBLE, SkRegion()); + SkRegion window_a_occlusion(SkIRect::MakeXYWH(100, 100, 100, 100)); + delegate_a->set_expectation(Window::OcclusionState::VISIBLE, + window_a_occlusion); + EXPECT_TRUE(delegate_bb->is_expecting_call()); + WindowOcclusionTracker::ScopedExclude scoped(window_b); + EXPECT_FALSE(delegate_bb->is_expecting_call()); + EXPECT_FALSE(delegate_a->is_expecting_call()); + + // Moving |window_b| will not affect the occlusion status. + window_b->SetBounds(gfx::Rect(5, 5, 100, 100)); + + // Un-excluding will update the occlustion status. + // A's occlustion status includes all windows above a. + window_a_occlusion.setEmpty(); + window_a_occlusion.op(SkIRect::MakeXYWH(5, 5, 100, 100), + SkRegion::kUnion_Op); + window_a_occlusion.op(SkIRect::MakeXYWH(100, 100, 100, 100), + SkRegion::kUnion_Op); + delegate_a->set_expectation(Window::OcclusionState::VISIBLE, + window_a_occlusion); + + SkRegion window_bb_occlusion(SkIRect::MakeXYWH(100, 100, 100, 100)); + delegate_bb->set_expectation(Window::OcclusionState::VISIBLE, + window_bb_occlusion); + } + + EXPECT_FALSE(delegate_a->is_expecting_call()); + EXPECT_FALSE(delegate_bb->is_expecting_call()); + + { + delegate_bb->set_expectation(Window::OcclusionState::VISIBLE, SkRegion()); + SkRegion window_a_occlusion(SkIRect::MakeXYWH(100, 100, 100, 100)); + delegate_a->set_expectation(Window::OcclusionState::VISIBLE, + window_a_occlusion); + EXPECT_TRUE(delegate_bb->is_expecting_call()); + WindowOcclusionTracker::ScopedExclude scoped(window_b); + EXPECT_FALSE(delegate_bb->is_expecting_call()); + EXPECT_FALSE(delegate_a->is_expecting_call()); + + // Deleting the excluded window will un-exclude itself and recomputes the + // occlustion state, but should not affect the state on existing windows + // because it's already excluded. + delete window_b; + EXPECT_FALSE(scoped.window()); + } + + MockWindowDelegate* delegate_d = new MockWindowDelegate(); + delegate_d->set_expectation(Window::OcclusionState::VISIBLE, SkRegion()); + delegate_a->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion()); + + auto* window_d = CreateTrackedWindow(delegate_d, gfx::Rect(0, 0, 10, 10)); + window_d->SetName("WindowD"); + + EXPECT_FALSE(delegate_a->is_expecting_call()); + EXPECT_FALSE(delegate_d->is_expecting_call()); + + { + // Make sure excluding the tracked window also works. + SkRegion window_a_occlusion(SkIRect::MakeXYWH(100, 100, 100, 100)); + delegate_a->set_expectation(Window::OcclusionState::VISIBLE, + window_a_occlusion); + WindowOcclusionTracker::ScopedExclude scoped(window_d); + EXPECT_FALSE(delegate_a->is_expecting_call()); + + // Changing opacity/bounds shouldn't change the occlusion state. + window_d->layer()->SetOpacity(0.5f); + window_d->SetBounds(gfx::Rect(0, 0, 20, 20)); + + // A is now visible even if |window_d| is un-excluded becaues + // window_d is not fully opaque. + } + + EXPECT_FALSE(delegate_a->is_expecting_call()); + delegate_a->set_expectation(Window::OcclusionState::OCCLUDED, SkRegion()); + window_d->layer()->SetOpacity(1.f); + EXPECT_FALSE(delegate_a->is_expecting_call()); +} + } // namespace aura
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc index 9fd46f65..2c378f14 100644 --- a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc +++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
@@ -17,7 +17,6 @@ #include "base/threading/thread_task_runner_handle.h" #include "base/trace_event/trace_event.h" #include "third_party/skia/include/core/SkPath.h" -#include "ui/accessibility/platform/atk_util_auralinux.h" #include "ui/aura/client/aura_constants.h" #include "ui/aura/client/cursor_client.h" #include "ui/aura/client/focus_client.h" @@ -2046,11 +2045,8 @@ break; } case KeyPress: { - if (ui::AtkUtilAuraLinux::HandleKeyEvent(xev) != - ui::DiscardAtkKeyEvent::Discard) { - ui::KeyEvent keydown_event(xev); - DispatchKeyEvent(&keydown_event); - } + ui::KeyEvent keydown_event(xev); + DispatchKeyEvent(&keydown_event); break; } case KeyRelease: { @@ -2059,11 +2055,8 @@ if (!IsActive() && !HasCapture()) break; - if (ui::AtkUtilAuraLinux::HandleKeyEvent(xev) != - ui::DiscardAtkKeyEvent::Discard) { - ui::KeyEvent key_event(xev); - DispatchKeyEvent(&key_event); - } + ui::KeyEvent key_event(xev); + DispatchKeyEvent(&key_event); break; } case ButtonPress:
diff --git a/ui/views/widget/native_widget_mac_unittest.mm b/ui/views/widget/native_widget_mac_unittest.mm index bad9e86..74b583c 100644 --- a/ui/views/widget/native_widget_mac_unittest.mm +++ b/ui/views/widget/native_widget_mac_unittest.mm
@@ -2206,11 +2206,8 @@ widget_ = CreateTopLevelPlatformWidget(); - // It's not a bug if the native view has a different number of subviews, - // but the rest of this test assumes it. It may or may not be worth - // removing that assumption at some point. - ASSERT_EQ(0u, - [[widget_->GetNativeView().GetNativeNSView() subviews] count]); + starting_subviews_.reset( + [[widget_->GetNativeView().GetNativeNSView() subviews] copy]); native_host_parent_ = new View(); widget_->GetContentsView()->AddChildView(native_host_parent_); @@ -2224,7 +2221,9 @@ } EXPECT_EQ(kNativeViewCount, native_host_parent_->child_count()); EXPECT_NSEQ([widget_->GetNativeView().GetNativeNSView() subviews], - (@[ hosts_[0]->view(), hosts_[1]->view(), hosts_[2]->view() ])); + ([GetStartingSubviews() arrayByAddingObjectsFromArray:@[ + hosts_[0]->view(), hosts_[1]->view(), hosts_[2]->view() + ]])); } void TearDown() override { @@ -2236,9 +2235,12 @@ return widget_->GetNativeView().GetNativeNSView(); } + NSArray<NSView*>* GetStartingSubviews() { return starting_subviews_; } + Widget* widget_ = nullptr; View* native_host_parent_ = nullptr; std::vector<std::unique_ptr<NativeHostHolder>> hosts_; + base::scoped_nsobject<NSArray<NSView*>> starting_subviews_; private: DISALLOW_COPY_AND_ASSIGN(NativeWidgetMacViewsOrderTest); @@ -2249,22 +2251,30 @@ TEST_F(NativeWidgetMacViewsOrderTest, NativeViewAttached) { hosts_[1]->Detach(); EXPECT_NSEQ([GetContentNativeView() subviews], - (@[ hosts_[0]->view(), hosts_[2]->view() ])); + ([GetStartingSubviews() arrayByAddingObjectsFromArray:@[ + hosts_[0]->view(), hosts_[2]->view() + ]])); hosts_[1]->AttachNativeView(); EXPECT_NSEQ([GetContentNativeView() subviews], - (@[ hosts_[0]->view(), hosts_[1]->view(), hosts_[2]->view() ])); + ([GetStartingSubviews() arrayByAddingObjectsFromArray:@[ + hosts_[0]->view(), hosts_[1]->view(), hosts_[2]->view() + ]])); } // Tests that NativeViews order changes according to views::View hierarchy. TEST_F(NativeWidgetMacViewsOrderTest, ReorderViews) { native_host_parent_->ReorderChildView(hosts_[2]->host(), 1); EXPECT_NSEQ([GetContentNativeView() subviews], - (@[ hosts_[0]->view(), hosts_[2]->view(), hosts_[1]->view() ])); + ([GetStartingSubviews() arrayByAddingObjectsFromArray:@[ + hosts_[0]->view(), hosts_[2]->view(), hosts_[1]->view() + ]])); native_host_parent_->RemoveChildView(hosts_[2]->host()); EXPECT_NSEQ([GetContentNativeView() subviews], - (@[ hosts_[0]->view(), hosts_[1]->view() ])); + ([GetStartingSubviews() arrayByAddingObjectsFromArray:@[ + hosts_[0]->view(), hosts_[1]->view() + ]])); View* new_parent = new View(); native_host_parent_->RemoveChildView(hosts_[1]->host()); @@ -2272,11 +2282,15 @@ new_parent->AddChildView(hosts_[1]->host()); new_parent->AddChildView(hosts_[2]->host()); EXPECT_NSEQ([GetContentNativeView() subviews], - (@[ hosts_[0]->view(), hosts_[1]->view(), hosts_[2]->view() ])); + ([GetStartingSubviews() arrayByAddingObjectsFromArray:@[ + hosts_[0]->view(), hosts_[1]->view(), hosts_[2]->view() + ]])); native_host_parent_->ReorderChildView(new_parent, 0); EXPECT_NSEQ([GetContentNativeView() subviews], - (@[ hosts_[1]->view(), hosts_[2]->view(), hosts_[0]->view() ])); + ([GetStartingSubviews() arrayByAddingObjectsFromArray:@[ + hosts_[1]->view(), hosts_[2]->view(), hosts_[0]->view() + ]])); } // Test that unassociated native views stay on top after reordering. @@ -2284,15 +2298,17 @@ base::scoped_nsobject<NSView> child_view([[NSView alloc] init]); [GetContentNativeView() addSubview:child_view]; EXPECT_NSEQ( - [GetContentNativeView() subviews], (@[ + [GetContentNativeView() subviews], + ([GetStartingSubviews() arrayByAddingObjectsFromArray:@[ hosts_[0]->view(), hosts_[1]->view(), hosts_[2]->view(), child_view - ])); + ]])); native_host_parent_->ReorderChildView(hosts_[2]->host(), 1); EXPECT_NSEQ( - [GetContentNativeView() subviews], (@[ + [GetContentNativeView() subviews], + ([GetStartingSubviews() arrayByAddingObjectsFromArray:@[ hosts_[0]->view(), hosts_[2]->view(), hosts_[1]->view(), child_view - ])); + ]])); } // Test -[NSWindowDelegate windowShouldClose:].
diff --git a/ui/views/win/hwnd_message_handler.cc b/ui/views/win/hwnd_message_handler.cc index 0207ba2..45ef586d 100644 --- a/ui/views/win/hwnd_message_handler.cc +++ b/ui/views/win/hwnd_message_handler.cc
@@ -2950,7 +2950,7 @@ // Increment |touch_down_contexts_| on a pointer down. This variable // is used to debounce the WM_MOUSEACTIVATE events. - if (message == WM_POINTERDOWN) { + if (message == WM_POINTERDOWN || message == WM_NCPOINTERDOWN) { touch_down_contexts_++; base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( FROM_HERE, @@ -3004,10 +3004,24 @@ if (event_type == ui::ET_TOUCH_RELEASED) id_generator_.ReleaseNumber(pointer_id); - // Mark all touch released events handled. These will usually turn into tap + // Mark touch released events handled. These will usually turn into tap // gestures, and doing this avoids propagating the event to other windows. - const bool always_mark_handled = event_type == ui::ET_TOUCH_RELEASED; - SetMsgHandled(always_mark_handled || event.handled()); + if (delegate_->GetFrameMode() == FrameMode::SYSTEM_DRAWN) { + // WM_NCPOINTERUP must be DefWindowProc'ed in order for the system caption + // buttons to work correctly. + if (message == WM_POINTERUP) + event.SetHandled(); + } else { + // Messages on HTCAPTION should be DefWindowProc'ed, as we let Windows + // take care of dragging the window and double-tapping to maximize. + const bool on_titlebar = + SendMessage(hwnd(), WM_NCHITTEST, 0, l_param) == HTCAPTION; + // Unlike above, we must mark both WM_POINTERUP and WM_NCPOINTERUP as + // handled, in order for the custom caption buttons to work correctly. + if (event_type == ui::ET_TOUCH_RELEASED && !on_titlebar) + event.SetHandled(); + } + SetMsgHandled(event.handled()); } return 0; }
diff --git a/ui/views/win/hwnd_message_handler.h b/ui/views/win/hwnd_message_handler.h index d76b006..8f28cdd 100644 --- a/ui/views/win/hwnd_message_handler.h +++ b/ui/views/win/hwnd_message_handler.h
@@ -355,6 +355,9 @@ CR_MESSAGE_HANDLER_EX(WM_POINTERUPDATE, OnPointerEvent) CR_MESSAGE_HANDLER_EX(WM_POINTERENTER, OnPointerEvent) CR_MESSAGE_HANDLER_EX(WM_POINTERLEAVE, OnPointerEvent) + CR_MESSAGE_HANDLER_EX(WM_NCPOINTERDOWN, OnPointerEvent) + CR_MESSAGE_HANDLER_EX(WM_NCPOINTERUP, OnPointerEvent) + CR_MESSAGE_HANDLER_EX(WM_NCPOINTERUPDATE, OnPointerEvent) // Key events. CR_MESSAGE_HANDLER_EX(WM_KEYDOWN, OnKeyEvent)
diff --git a/ui/views/win/pen_event_processor.cc b/ui/views/win/pen_event_processor.cc index e142993..67ee69fc 100644 --- a/ui/views/win/pen_event_processor.cc +++ b/ui/views/win/pen_event_processor.cc
@@ -48,7 +48,7 @@ DCHECK(!eraser_pointer_id_ || *eraser_pointer_id_ == mapped_pointer_id); eraser_pointer_id_ = mapped_pointer_id; } else if (eraser_pointer_id_ && *eraser_pointer_id_ == mapped_pointer_id && - message == WM_POINTERUP) { + (message == WM_POINTERUP || message == WM_NCPOINTERUP)) { input_type = ui::EventPointerType::POINTER_TYPE_ERASER; eraser_pointer_id_.reset(); } @@ -113,6 +113,7 @@ int click_count = 0; switch (message) { case WM_POINTERDOWN: + case WM_NCPOINTERDOWN: event_type = ui::ET_MOUSE_PRESSED; if (pointer_info.ButtonChangeType == POINTER_CHANGE_FIRSTBUTTON_DOWN) changed_flag = ui::EF_LEFT_MOUSE_BUTTON; @@ -122,6 +123,7 @@ sent_mouse_down_ = true; break; case WM_POINTERUP: + case WM_NCPOINTERUP: event_type = ui::ET_MOUSE_RELEASED; if (pointer_info.ButtonChangeType == POINTER_CHANGE_FIRSTBUTTON_UP) { flag |= ui::EF_LEFT_MOUSE_BUTTON; @@ -137,6 +139,7 @@ sent_mouse_down_ = false; break; case WM_POINTERUPDATE: + case WM_NCPOINTERUPDATE: event_type = ui::ET_MOUSE_DRAGGED; if (flag == ui::EF_NONE) event_type = ui::ET_MOUSE_MOVED; @@ -169,10 +172,12 @@ ui::EventType event_type = ui::ET_TOUCH_MOVED; switch (message) { case WM_POINTERDOWN: + case WM_NCPOINTERDOWN: event_type = ui::ET_TOUCH_PRESSED; sent_touch_start_ = true; break; case WM_POINTERUP: + case WM_NCPOINTERUP: event_type = ui::ET_TOUCH_RELEASED; id_generator_->ReleaseNumber(pointer_id); if (!sent_touch_start_) @@ -180,6 +185,7 @@ sent_touch_start_ = false; break; case WM_POINTERUPDATE: + case WM_NCPOINTERUPDATE: event_type = ui::ET_TOUCH_MOVED; break; default:
diff --git a/ui/views_bridge_mac/bridged_native_widget_impl.mm b/ui/views_bridge_mac/bridged_native_widget_impl.mm index 0777853..1f368c2 100644 --- a/ui/views_bridge_mac/bridged_native_widget_impl.mm +++ b/ui/views_bridge_mac/bridged_native_widget_impl.mm
@@ -44,6 +44,18 @@ constexpr auto kUIPaintTimeout = base::TimeDelta::FromSeconds(5); } // namespace +// The NSView that hosts the composited CALayer drawing the UI. It fills the +// window but is not hittable so that accessibility hit tests always go to the +// BridgedContentView. +@interface ViewsCompositorSuperview : NSView +@end + +@implementation ViewsCompositorSuperview +- (NSView*)hitTest:(NSPoint)aPoint { + return nil; +} +@end + // Self-owning animation delegate that starts a hide animation, then calls // -[NSWindow close] when the animation ends, releasing itself. @interface ViewsNSWindowCloseAnimator : NSObject<NSAnimationDelegate> { @@ -172,6 +184,9 @@ void* rank_as_void) { DCHECK_NE(lhs, rhs); + if ([lhs isKindOfClass:[ViewsCompositorSuperview class]]) + return NSOrderedAscending; + const RankMap* rank = static_cast<const RankMap*>(rank_as_void); auto left_rank = rank->find(lhs); auto right_rank = rank->find(rhs); @@ -486,13 +501,20 @@ // this should be treated as an error and caught early. CHECK(bridged_view_); - // Set the layer first to create a layer-hosting view (not layer-backed), and - // set the compositor output to go to that layer. - base::scoped_nsobject<CALayer> background_layer([[CALayer alloc] init]); + // Beware: This view was briefly removed (in favor of a bare CALayer) in + // crrev/c/1236675. The ordering of unassociated layers relative to NSView + // layers is undefined on macOS 10.12 and earlier, so the compositor layer + // ended up covering up subviews (see crbug/899499). + base::scoped_nsobject<NSView> compositor_view( + [[ViewsCompositorSuperview alloc] initWithFrame:[bridged_view_ bounds]]); + [compositor_view + setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; + auto* background_layer = [CALayer layer]; display_ca_layer_tree_ = - std::make_unique<ui::DisplayCALayerTree>(background_layer.get()); - [bridged_view_ setLayer:background_layer]; - [bridged_view_ setWantsLayer:YES]; + std::make_unique<ui::DisplayCALayerTree>(background_layer); + [compositor_view setLayer:background_layer]; + [compositor_view setWantsLayer:YES]; + [bridged_view_ addSubview:compositor_view]; [window_ setContentView:bridged_view_]; }
diff --git a/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.html b/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.html index 1714455..f4e00640 100644 --- a/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.html +++ b/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.html
@@ -160,7 +160,7 @@ --cr-input-error-display: none; --cr-input-input: { font-size: 28px; - letter-spacing: 28px; + letter-spacing: 18px; }; --cr-input-padding-bottom: 1px; --cr-input-padding-end: 0;