diff --git a/AUTHORS b/AUTHORS index fe18810..93e9f00 100644 --- a/AUTHORS +++ b/AUTHORS
@@ -599,7 +599,7 @@ Miran Karic <miran.karic@imgtec.com> Mirela Budaes <mbudaes@adobe.com> Mirela Budaes <mbudaes@gmail.com> -Miyoung Shin <myid.shin@samsung.com> +Miyoung Shin <myid.shin@navercorp.com> Mohamed I. Hammad <ibraaaa@gmail.com> Mohamed Mansour <m0.interactive@gmail.com> Mohammad Azam <m.azam@samsung.com>
diff --git a/DEPS b/DEPS index fb00c6d3..82ea8a7 100644 --- a/DEPS +++ b/DEPS
@@ -105,7 +105,7 @@ # 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': '76c775f48decb142549215319ae9868a769d9902', + 'skia_revision': 'be8193c9313a7192947b10b7ba6f192245b4f704', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. @@ -129,7 +129,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': '7f47c50227fb4af93b58c6687786130c42b76333', + 'pdfium_revision': 'a1c846c4cf3f8c08edfffa1cc6b60860c011000b', # 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. @@ -165,7 +165,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': 'cb192dee19d43e5a17bdfa8b7397122aad312bc3', + 'catapult_revision': '2dd914402ebcc44ecb60034e5c7b9bfa3d0c9d89', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -620,7 +620,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '0daedf7758e157ee22a64e9dabcb089c0da5ef4c', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '22300e1fb562291b55eb702fe73b164cb1a2317d', 'src/third_party/devtools-node-modules': Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'), @@ -954,7 +954,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + 'a80f9bc11bcbea9fc552654281354fb696ac7b6b', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '2cbceb0be548f4d58fadf95381220e13aaf55a73', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + 'ac0d98b5cee6c024b0cffeb4f8f45b6fc5ccdb78', @@ -1106,7 +1106,7 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '6d2f3f4cb8bac1f7c4a945c73d07a33df74f22f9', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + 'd2650d1a2851ab4fb14b86f04ccc4c2c09c237f5', + Var('webrtc_git') + '/src.git' + '@' + '086cac5c439cf9f820b11b52859c03279c750989', 'src/third_party/xdg-utils': { 'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d', @@ -1137,7 +1137,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@64ba5a302bf0da7647c98f2aabccc42c072e1364', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@4b969b6f368a5a46a06b2e79aea50494eb1bb3e3', 'condition': 'checkout_src_internal', },
diff --git a/PRESUBMIT.py b/PRESUBMIT.py index 351e1f6..96358824 100644 --- a/PRESUBMIT.py +++ b/PRESUBMIT.py
@@ -2750,7 +2750,7 @@ Use of => (arrow) operator detected in: %s Please ensure your code does not run on iOS9 (=> (arrow) does not work there). -https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#Arrow-Functions +https://chromium.googlesource.com/chromium/src/+/master/styleguide/web/es6.md#Arrow-Functions """ % f.LocalPath() ]))) @@ -2764,8 +2764,8 @@ %s Please ensure your code does not run on iOS9 because const/let is not fully supported. -https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#let-Block_Scoped-Variables -https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#const-Block_Scoped-Constants +https://chromium.googlesource.com/chromium/src/+/master/styleguide/web/es6.md#let-Block_Scoped-Variables +https://chromium.googlesource.com/chromium/src/+/master/styleguide/web/es6.md#const-Block_Scoped-Constants """ % f.LocalPath() ])))
diff --git a/WATCHLISTS b/WATCHLISTS index 49fb774..ed829fd2 100644 --- a/WATCHLISTS +++ b/WATCHLISTS
@@ -1787,7 +1787,6 @@ 'tfarina@chromium.org'], 'arc': ['elijahtaylor+arcwatch@chromium.org', 'hidehiko+watch@chromium.org', - 'lhchavez+watch@chromium.org', 'victorhsieh+watch@chromium.org', 'yusukes+watch@chromium.org', 'arc-reviews+chromium@google.com'],
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index b493d5b..bd69a39f 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -731,10 +731,16 @@ "system/message_center/fullscreen_notification_blocker.h", "system/message_center/inactive_user_notification_blocker.cc", "system/message_center/inactive_user_notification_blocker.h", + "system/message_center/new_unified_message_center_view.cc", + "system/message_center/new_unified_message_center_view.h", "system/message_center/notification_tray.cc", "system/message_center/notification_tray.h", "system/message_center/session_state_notification_blocker.cc", "system/message_center/session_state_notification_blocker.h", + "system/message_center/unified_message_center_view.cc", + "system/message_center/unified_message_center_view.h", + "system/message_center/unified_message_list_view.cc", + "system/message_center/unified_message_list_view.h", "system/model/clock_model.cc", "system/model/clock_model.h", "system/model/enterprise_domain_model.cc", @@ -747,6 +753,8 @@ "system/model/tracing_model.h", "system/model/update_model.cc", "system/model/update_model.h", + "system/model/virtual_keyboard_model.cc", + "system/model/virtual_keyboard_model.h", "system/network/auto_connect_notifier.cc", "system/network/auto_connect_notifier.h", "system/network/network_feature_pod_button.cc", @@ -1013,8 +1021,6 @@ "system/unified/top_shortcuts_view.h", "system/unified/unified_detailed_view_delegate.cc", "system/unified/unified_detailed_view_delegate.h", - "system/unified/unified_message_center_view.cc", - "system/unified/unified_message_center_view.h", "system/unified/unified_notifier_settings_controller.cc", "system/unified/unified_notifier_settings_controller.h", "system/unified/unified_slider_bubble_controller.cc", @@ -1848,6 +1854,7 @@ "system/message_center/inactive_user_notification_blocker_unittest.cc", "system/message_center/notification_tray_unittest.cc", "system/message_center/session_state_notification_blocker_unittest.cc", + "system/message_center/unified_message_list_view_unittest.cc", "system/network/auto_connect_notifier_unittest.cc", "system/network/network_icon_unittest.cc", "system/network/sms_observer_unittest.cc",
diff --git a/ash/assistant/assistant_ui_controller.cc b/ash/assistant/assistant_ui_controller.cc index a021d9a..a899cff 100644 --- a/ash/assistant/assistant_ui_controller.cc +++ b/ash/assistant/assistant_ui_controller.cc
@@ -73,13 +73,8 @@ void AssistantUiController::OnWidgetActivationChanged(views::Widget* widget, bool active) { - if (active) { + if (active) container_view_->RequestFocus(); - } else { - // When the widget is deactivated the UI should hide. Interacting with - // the metalayer does not cause widget deactivation. - HideUi(AssistantSource::kUnspecified); - } } void AssistantUiController::OnWidgetVisibilityChanged(views::Widget* widget, @@ -227,16 +222,39 @@ ? mojom::VoiceInteractionState::RUNNING : mojom::VoiceInteractionState::STOPPED); - if (new_visibility == AssistantVisibility::kHidden) { - // When hiding the UI, start a timer to automatically close ourselves after - // |kAutoCloseThreshold|. This is to give the user an opportunity to resume - // their previous session before it is automatically finished. - auto_close_timer_.Start(FROM_HERE, kAutoCloseThreshold, - base::BindRepeating(&AssistantUiController::CloseUi, - weak_factory_.GetWeakPtr(), - AssistantSource::kUnspecified)); - } else { - auto_close_timer_.Stop(); + switch (new_visibility) { + case AssistantVisibility::kClosed: + // When the UI is closed, we stop the auto close timer as it may be + // running and also stop monitoring events. + auto_close_timer_.Stop(); + event_monitor_.reset(); + break; + case AssistantVisibility::kHidden: + // When hiding the UI, we start a timer to automatically close ourselves + // after |kAutoCloseThreshold|. This is to give the user an opportunity to + // resume their previous session before it is automatically finished. + auto_close_timer_.Start( + FROM_HERE, kAutoCloseThreshold, + base::BindRepeating(&AssistantUiController::CloseUi, + weak_factory_.GetWeakPtr(), + AssistantSource::kUnspecified)); + + // Because the UI is not visible we needn't monitor events. + event_monitor_.reset(); + break; + case AssistantVisibility::kVisible: + // Upon becoming visible, we stop the auto close timer. + auto_close_timer_.Stop(); + + // We need to monitor events for the root window while we're visible to + // give us an opportunity to dismiss Assistant UI when the user starts an + // interaction outside of our bounds. TODO(dmblack): Investigate how this + // behaves in a multi-display environment. + gfx::NativeWindow root_window = + container_view_->GetWidget()->GetNativeWindow()->GetRootWindow(); + event_monitor_ = + views::EventMonitor::CreateWindowMonitor(this, root_window); + break; } // Metalayer should not be sticky. Disable when the UI is no longer visible. @@ -381,6 +399,34 @@ } } +void AssistantUiController::OnMouseEvent(ui::MouseEvent* event) { + if (event->type() == ui::ET_MOUSE_PRESSED) + OnPressedEvent(*event); +} + +void AssistantUiController::OnTouchEvent(ui::TouchEvent* event) { + if (event->type() == ui::ET_TOUCH_PRESSED) + OnPressedEvent(*event); +} + +void AssistantUiController::OnPressedEvent(const ui::LocatedEvent& event) { + DCHECK(event.type() == ui::ET_MOUSE_PRESSED || + event.type() == ui::ET_TOUCH_PRESSED); + + const gfx::Point screen_location = + event.target() ? event.target()->GetScreenLocation(event) + : event.root_location(); + + const gfx::Rect screen_bounds = + container_view_->GetWidget()->GetWindowBoundsInScreen(); + + // Pressed events outside our widget bounds should result in hiding of + // Assistant UI. This event does not fire during a Metalayer session so we + // needn't enforce logic to prevent hiding when using the stylus. + if (!screen_bounds.Contains(screen_location)) + HideUi(AssistantSource::kUnspecified); +} + void AssistantUiController::UpdateUsableWorkArea(aura::Window* root_window) { gfx::Rect usable_work_area; gfx::Rect screen_bounds = root_window->GetBoundsInScreen();
diff --git a/ash/assistant/assistant_ui_controller.h b/ash/assistant/assistant_ui_controller.h index 9e23fe4..48b092a 100644 --- a/ash/assistant/assistant_ui_controller.h +++ b/ash/assistant/assistant_ui_controller.h
@@ -21,8 +21,10 @@ #include "base/macros.h" #include "base/timer/timer.h" #include "ui/display/display_observer.h" +#include "ui/events/event_handler.h" #include "ui/gfx/geometry/rect.h" #include "ui/keyboard/keyboard_controller_observer.h" +#include "ui/views/event_monitor.h" #include "ui/views/widget/widget_observer.h" namespace chromeos { @@ -53,7 +55,8 @@ public DialogPlateObserver, public HighlighterController::Observer, public keyboard::KeyboardControllerObserver, - public display::DisplayObserver { + public display::DisplayObserver, + public ui::EventHandler { public: explicit AssistantUiController(AssistantController* assistant_controller); ~AssistantUiController() override; @@ -115,6 +118,10 @@ void OnDisplayMetricsChanged(const display::Display& display, uint32_t changed_metrics) override; + // ui::EventHandler: + void OnMouseEvent(ui::MouseEvent* event) override; + void OnTouchEvent(ui::TouchEvent* event) override; + void ShowUi(AssistantSource source); void HideUi(AssistantSource source); void CloseUi(AssistantSource source); @@ -123,6 +130,9 @@ AssistantContainerView* GetViewForTest(); private: + // Invoked on either a mouse or touch pressed event. + void OnPressedEvent(const ui::LocatedEvent& event); + // Updates UI mode to |ui_mode| if specified. Otherwise UI mode is updated on // the basis of interaction/widget visibility state. void UpdateUiMode(base::Optional<AssistantUiMode> ui_mode = base::nullopt); @@ -146,6 +156,8 @@ AssistantContainerView* container_view_ = nullptr; // Owned by view hierarchy. + std::unique_ptr<views::EventMonitor> event_monitor_; + gfx::Rect keyboard_workspace_occluded_bounds_; // When hidden, Assistant automatically closes itself to finish the previous
diff --git a/ash/multi_device_setup/multi_device_notification_presenter.cc b/ash/multi_device_setup/multi_device_notification_presenter.cc index 17ef63f5..33fe6991 100644 --- a/ash/multi_device_setup/multi_device_notification_presenter.cc +++ b/ash/multi_device_setup/multi_device_notification_presenter.cc
@@ -121,16 +121,18 @@ const std::string& new_host_device_name) { base::string16 title = l10n_util::GetStringFUTF16( IDS_ASH_MULTI_DEVICE_SETUP_EXISTING_USER_HOST_SWITCHED_TITLE, - base::UTF8ToUTF16(new_host_device_name)); + base::ASCIIToUTF16(new_host_device_name)); base::string16 message = l10n_util::GetStringUTF16( IDS_ASH_MULTI_DEVICE_SETUP_EXISTING_USER_HOST_SWITCHED_MESSAGE); ShowNotification(Status::kExistingUserHostSwitchedNotificationVisible, title, message); } -void MultiDeviceNotificationPresenter::OnNewChromebookAddedForExistingUser() { - base::string16 title = l10n_util::GetStringUTF16( - IDS_ASH_MULTI_DEVICE_SETUP_EXISTING_USER_NEW_CHROMEBOOK_ADDED_TITLE); +void MultiDeviceNotificationPresenter::OnNewChromebookAddedForExistingUser( + const std::string& new_host_device_name) { + base::string16 title = l10n_util::GetStringFUTF16( + IDS_ASH_MULTI_DEVICE_SETUP_EXISTING_USER_NEW_CHROMEBOOK_ADDED_TITLE, + base::ASCIIToUTF16(new_host_device_name)); base::string16 message = l10n_util::GetStringUTF16( IDS_ASH_MULTI_DEVICE_SETUP_EXISTING_USER_NEW_CHROMEBOOK_ADDED_MESSAGE); ShowNotification(Status::kExistingUserNewChromebookNotificationVisible, title,
diff --git a/ash/multi_device_setup/multi_device_notification_presenter.h b/ash/multi_device_setup/multi_device_notification_presenter.h index 3a001650..2e4f158 100644 --- a/ash/multi_device_setup/multi_device_notification_presenter.h +++ b/ash/multi_device_setup/multi_device_notification_presenter.h
@@ -61,7 +61,8 @@ void OnPotentialHostExistsForNewUser() override; void OnConnectedHostSwitchedForExistingUser( const std::string& new_host_device_name) override; - void OnNewChromebookAddedForExistingUser() override; + void OnNewChromebookAddedForExistingUser( + const std::string& new_host_device_name) override; // SessionObserver: void OnUserSessionAdded(const AccountId& account_id) override;
diff --git a/ash/multi_device_setup/multi_device_notification_presenter_unittest.cc b/ash/multi_device_setup/multi_device_notification_presenter_unittest.cc index 987d252..65bf5b6 100644 --- a/ash/multi_device_setup/multi_device_notification_presenter_unittest.cc +++ b/ash/multi_device_setup/multi_device_notification_presenter_unittest.cc
@@ -184,7 +184,8 @@ void ShowExistingUserNewChromebookNotification() { EXPECT_TRUE(fake_multidevice_setup_->delegate().is_bound()); - fake_multidevice_setup_->delegate()->OnNewChromebookAddedForExistingUser(); + fake_multidevice_setup_->delegate()->OnNewChromebookAddedForExistingUser( + kTestHostDeviceName); InvokePendingMojoCalls(); } @@ -285,8 +286,9 @@ break; case MultiDeviceNotificationPresenter::Status:: kExistingUserNewChromebookNotificationVisible: - title = l10n_util::GetStringUTF16( - IDS_ASH_MULTI_DEVICE_SETUP_EXISTING_USER_NEW_CHROMEBOOK_ADDED_TITLE); + title = l10n_util::GetStringFUTF16( + IDS_ASH_MULTI_DEVICE_SETUP_EXISTING_USER_NEW_CHROMEBOOK_ADDED_TITLE, + base::ASCIIToUTF16(kTestHostDeviceName)); message = l10n_util::GetStringUTF16( IDS_ASH_MULTI_DEVICE_SETUP_EXISTING_USER_NEW_CHROMEBOOK_ADDED_MESSAGE); break;
diff --git a/ash/public/cpp/ash_features.cc b/ash/public/cpp/ash_features.cc index 78dff3c..91b56e8 100644 --- a/ash/public/cpp/ash_features.cc +++ b/ash/public/cpp/ash_features.cc
@@ -35,6 +35,9 @@ "LockScreenHideSensitiveNotificationsSupport", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kNewMessageListView{"NewMessageListView", + base::FEATURE_DISABLED_BY_DEFAULT}; + const base::Feature kNewWallpaperPicker{"NewWallpaperPicker", base::FEATURE_ENABLED_BY_DEFAULT}; @@ -85,6 +88,10 @@ kLockScreenHideSensitiveNotificationsSupport); } +bool IsNewMessageListViewEnabled() { + return base::FeatureList::IsEnabled(kNewMessageListView); +} + bool IsNewWallpaperPickerEnabled() { static bool use_new_wallpaper_picker = base::FeatureList::IsEnabled(kNewWallpaperPicker);
diff --git a/ash/public/cpp/ash_features.h b/ash/public/cpp/ash_features.h index a290c07..8d8891d 100644 --- a/ash/public/cpp/ash_features.h +++ b/ash/public/cpp/ash_features.h
@@ -48,6 +48,9 @@ ASH_PUBLIC_EXPORT extern const base::Feature kLockScreenHideSensitiveNotificationsSupport; +// Enables new message list view. https://crbug.com/769219 +ASH_PUBLIC_EXPORT extern const base::Feature kNewMessageListView; + // Enables the new wallpaper picker. // TODO(wzang): Remove this after the feature is fully launched. // https://crbug.com/777293. @@ -91,6 +94,8 @@ ASH_PUBLIC_EXPORT bool IsLockScreenHideSensitiveNotificationsSupported(); +ASH_PUBLIC_EXPORT bool IsNewMessageListViewEnabled(); + ASH_PUBLIC_EXPORT bool IsNewWallpaperPickerEnabled(); ASH_PUBLIC_EXPORT bool IsNightLightEnabled();
diff --git a/ash/shelf/shelf_view.cc b/ash/shelf/shelf_view.cc index 0f91ddd..55ac89de 100644 --- a/ash/shelf/shelf_view.cc +++ b/ash/shelf/shelf_view.cc
@@ -31,6 +31,8 @@ #include "ash/shell.h" #include "ash/shell_delegate.h" #include "ash/strings/grit/ash_strings.h" +#include "ash/system/model/system_tray_model.h" +#include "ash/system/model/virtual_keyboard_model.h" #include "ash/system/status_area_widget.h" #include "ash/wm/mru_window_tracker.h" #include "ash/wm/root_window_finder.h" @@ -351,6 +353,7 @@ DCHECK(shelf_); DCHECK(shelf_widget_); Shell::Get()->tablet_mode_controller()->AddObserver(this); + Shell::Get()->system_tray_model()->virtual_keyboard()->AddObserver(this); bounds_animator_->AddObserver(this); set_context_menu_controller(this); } @@ -359,6 +362,7 @@ // Shell destroys the TabletModeController before destroying all root windows. if (Shell::Get()->tablet_mode_controller()) Shell::Get()->tablet_mode_controller()->RemoveObserver(this); + Shell::Get()->system_tray_model()->virtual_keyboard()->RemoveObserver(this); bounds_animator_->RemoveObserver(this); model_->RemoveObserver(this); } @@ -651,6 +655,10 @@ shelf_menu_model_adapter_->Cancel(); } +void ShelfView::OnVirtualKeyboardVisibilityChanged() { + LayoutToIdealBounds(); +} + void ShelfView::CreateDragIconProxyByLocationWithNoAnimation( const gfx::Point& origin_in_screen_coordinates, const gfx::ImageSkia& icon, @@ -990,10 +998,13 @@ const int available_size = shelf_->PrimaryAxisValue(width(), height()); const int separator_index = GetSeparatorIndex(); + const bool virtual_keyboard_visible = + Shell::Get()->system_tray_model()->virtual_keyboard()->visible(); // Don't show the separator if it isn't needed, or would appear after all // visible items. separator_->SetVisible(separator_index != -1 && - separator_index < last_visible_index_); + separator_index < last_visible_index_ && + !virtual_keyboard_visible); int app_list_button_position; int x = 0; @@ -1097,7 +1108,13 @@ // FinalizeRipOffDrag(). if (dragged_off_shelf_ && view_model_->view_at(i) == drag_view_) continue; - view_model_->view_at(i)->SetVisible(i <= last_visible_index_); + // If virtual keyboard is visible, only back button and app list button are + // shown. + const bool is_visible_item = !virtual_keyboard_visible || + i == kBackButtonIndex || + i == kAppListButtonIndex; + view_model_->view_at(i)->SetVisible(i <= last_visible_index_ && + is_visible_item); } overflow_button_->SetVisible(show_overflow);
diff --git a/ash/shelf/shelf_view.h b/ash/shelf/shelf_view.h index 81febaa..ee22859 100644 --- a/ash/shelf/shelf_view.h +++ b/ash/shelf/shelf_view.h
@@ -16,6 +16,7 @@ #include "ash/shelf/ink_drop_button_listener.h" #include "ash/shelf/shelf_button_pressed_metric_tracker.h" #include "ash/shelf/shelf_tooltip_manager.h" +#include "ash/system/model/virtual_keyboard_model.h" #include "ash/wm/tablet_mode/tablet_mode_observer.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" @@ -112,7 +113,8 @@ public views::FocusTraversable, public views::BoundsAnimatorObserver, public app_list::ApplicationDragAndDropHost, - public ash::TabletModeObserver { + public ash::TabletModeObserver, + public VirtualKeyboardModel::Observer { public: ShelfView(ShelfModel* model, Shelf* shelf, ShelfWidget* shelf_widget); ~ShelfView() override; @@ -189,6 +191,9 @@ void OnTabletModeStarted() override; void OnTabletModeEnded() override; + // Overridden from VirtualKeyboardModel::Observer: + void OnVirtualKeyboardVisibilityChanged() override; + void CreateDragIconProxyByLocationWithNoAnimation( const gfx::Point& origin_in_screen_coordinates, const gfx::ImageSkia& icon,
diff --git a/ash/shell.cc b/ash/shell.cc index ba19a96..113f7a4b 100644 --- a/ash/shell.cc +++ b/ash/shell.cc
@@ -423,9 +423,21 @@ void Shell::InitWaylandServer(std::unique_ptr<exo::FileHelper> file_helper) { wayland_server_controller_ = WaylandServerController::CreateIfNecessary( std::move(file_helper), aura_env_); + if (wayland_server_controller_) { + system_tray_model() + ->virtual_keyboard() + ->SetInputMethodSurfaceManagerObserver( + wayland_server_controller_->arc_input_method_surface_manager()); + } } void Shell::DestroyWaylandServer() { + if (wayland_server_controller_) { + system_tray_model() + ->virtual_keyboard() + ->RemoveInputMethodSurfaceManagerObserver( + wayland_server_controller_->arc_input_method_surface_manager()); + } wayland_server_controller_.reset(); }
diff --git a/ash/system/ime_menu/ime_menu_tray.cc b/ash/system/ime_menu/ime_menu_tray.cc index 2ec45ce..be674e9d 100644 --- a/ash/system/ime_menu/ime_menu_tray.cc +++ b/ash/system/ime_menu/ime_menu_tray.cc
@@ -343,6 +343,10 @@ SystemTrayNotifier* tray_notifier = Shell::Get()->system_tray_notifier(); tray_notifier->AddIMEObserver(this); tray_notifier->AddVirtualKeyboardObserver(this); + + // Show the tray even if virtual keyboard is shown. (Other tray buttons will + // be hidden). + set_show_with_virtual_keyboard(true); } ImeMenuTray::~ImeMenuTray() {
diff --git a/ash/system/message_center/arc/arc_notification_content_view.cc b/ash/system/message_center/arc/arc_notification_content_view.cc index fe064d7..fa3a1b52d 100644 --- a/ash/system/message_center/arc/arc_notification_content_view.cc +++ b/ash/system/message_center/arc/arc_notification_content_view.cc
@@ -683,7 +683,7 @@ canvas->DrawImageInt( item_->GetSnapshot(), 0, 0, item_->GetSnapshot().width(), item_->GetSnapshot().height(), contents_bounds.x(), contents_bounds.y(), - contents_bounds.width(), contents_bounds.height(), false); + contents_bounds.width(), contents_bounds.height(), true /* filter */); } else { // Draw a blank background otherwise. The height of the view and surface are // not exactly synced and user may see the blank area out of the surface.
diff --git a/ash/system/message_center/new_unified_message_center_view.cc b/ash/system/message_center/new_unified_message_center_view.cc new file mode 100644 index 0000000..24089f5f --- /dev/null +++ b/ash/system/message_center/new_unified_message_center_view.cc
@@ -0,0 +1,51 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/system/message_center/new_unified_message_center_view.h" + +#include "ash/message_center/message_center_scroll_bar.h" +#include "ash/system/message_center/unified_message_list_view.h" +#include "ui/message_center/views/message_view.h" +#include "ui/views/controls/scroll_view.h" +#include "ui/views/layout/fill_layout.h" +#include "ui/views/widget/widget.h" + +namespace ash { + +NewUnifiedMessageCenterView::NewUnifiedMessageCenterView() + : scroller_(new views::ScrollView()), + message_list_view_(new UnifiedMessageListView(this)) { + SetLayoutManager(std::make_unique<views::FillLayout>()); + + // Need to set the transparent background explicitly, since ScrollView has + // set the default opaque background color. + scroller_->SetContents(message_list_view_); + scroller_->SetBackgroundColor(SK_ColorTRANSPARENT); + scroller_->SetVerticalScrollBar(new MessageCenterScrollBar(this)); + scroller_->set_draw_overflow_indicator(false); + AddChildView(scroller_); +} + +NewUnifiedMessageCenterView::~NewUnifiedMessageCenterView() = default; + +void NewUnifiedMessageCenterView::SetMaxHeight(int max_height) { + scroller_->ClipHeightTo(0, max_height); +} + +void NewUnifiedMessageCenterView::ListPreferredSizeChanged() { + SetVisible(message_list_view_->child_count() > 0); + PreferredSizeChanged(); + + if (GetWidget()) + GetWidget()->SynthesizeMouseMoveEvent(); +} + +void NewUnifiedMessageCenterView::ConfigureMessageView( + message_center::MessageView* message_view) { + message_view->set_scroller(scroller_); +} + +void NewUnifiedMessageCenterView::OnMessageCenterScrolled() {} + +} // namespace ash
diff --git a/ash/system/message_center/new_unified_message_center_view.h b/ash/system/message_center/new_unified_message_center_view.h new file mode 100644 index 0000000..284b6343 --- /dev/null +++ b/ash/system/message_center/new_unified_message_center_view.h
@@ -0,0 +1,54 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_SYSTEM_MESSAGE_CENTER_NEW_UNIFIED_MESSAGE_CENTER_VIEW_H_ +#define ASH_SYSTEM_MESSAGE_CENTER_NEW_UNIFIED_MESSAGE_CENTER_VIEW_H_ + +#include "ash/ash_export.h" +#include "ash/message_center/message_center_scroll_bar.h" +#include "ash/system/message_center/unified_message_list_view.h" +#include "ui/views/controls/button/button.h" +#include "ui/views/focus/focus_manager.h" +#include "ui/views/view.h" + +namespace views { + +class ScrollView; + +} // namespace views + +namespace ash { + +// Manages scrolling of notification list. +// TODO(tetsui): Rename to UnifiedMessageCenterView after old code is removed. +class ASH_EXPORT NewUnifiedMessageCenterView + : public views::View, + public MessageCenterScrollBar::Observer { + public: + NewUnifiedMessageCenterView(); + ~NewUnifiedMessageCenterView() override; + + // Sets the maximum height that the view can take. + void SetMaxHeight(int max_height); + + // Called from UnifiedMessageListView when the preferred size is changed. + void ListPreferredSizeChanged(); + + // Configures MessageView to forward scroll events. Called from + // UnifiedMessageListView. + void ConfigureMessageView(message_center::MessageView* message_view); + + // MessageCenterScrollBar::Observer: + void OnMessageCenterScrolled() override; + + private: + views::ScrollView* const scroller_; + UnifiedMessageListView* const message_list_view_; + + DISALLOW_COPY_AND_ASSIGN(NewUnifiedMessageCenterView); +}; + +} // namespace ash + +#endif // ASH_SYSTEM_MESSAGE_CENTER_NEW_UNIFIED_MESSAGE_CENTER_VIEW_H_
diff --git a/ash/system/unified/unified_message_center_view.cc b/ash/system/message_center/unified_message_center_view.cc similarity index 99% rename from ash/system/unified/unified_message_center_view.cc rename to ash/system/message_center/unified_message_center_view.cc index 02fd7fc..53ba0746 100644 --- a/ash/system/unified/unified_message_center_view.cc +++ b/ash/system/message_center/unified_message_center_view.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/system/unified/unified_message_center_view.h" +#include "ash/system/message_center/unified_message_center_view.h" #include "ash/message_center/message_center_scroll_bar.h" #include "ash/strings/grit/ash_strings.h"
diff --git a/ash/system/unified/unified_message_center_view.h b/ash/system/message_center/unified_message_center_view.h similarity index 95% rename from ash/system/unified/unified_message_center_view.h rename to ash/system/message_center/unified_message_center_view.h index b6ca272..433992c 100644 --- a/ash/system/unified/unified_message_center_view.h +++ b/ash/system/message_center/unified_message_center_view.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 ASH_SYSTEM_UNIFIED_UNIFIED_MESSAGE_CENTER_VIEW_H_ -#define ASH_SYSTEM_UNIFIED_UNIFIED_MESSAGE_CENTER_VIEW_H_ +#ifndef ASH_SYSTEM_MESSAGE_CENTER_UNIFIED_MESSAGE_CENTER_VIEW_H_ +#define ASH_SYSTEM_MESSAGE_CENTER_UNIFIED_MESSAGE_CENTER_VIEW_H_ #include <stddef.h> @@ -137,4 +137,4 @@ } // namespace ash -#endif // ASH_SYSTEM_UNIFIED_UNIFIED_MESSAGE_CENTER_VIEW_H_ +#endif // ASH_SYSTEM_MESSAGE_CENTER_UNIFIED_MESSAGE_CENTER_VIEW_H_
diff --git a/ash/system/message_center/unified_message_list_view.cc b/ash/system/message_center/unified_message_list_view.cc new file mode 100644 index 0000000..c3d85df --- /dev/null +++ b/ash/system/message_center/unified_message_list_view.cc
@@ -0,0 +1,121 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/system/message_center/unified_message_list_view.h" + +#include "ash/system/message_center/new_unified_message_center_view.h" +#include "base/auto_reset.h" +#include "ui/message_center/message_center.h" +#include "ui/message_center/views/message_view.h" +#include "ui/message_center/views/message_view_factory.h" +#include "ui/views/border.h" +#include "ui/views/layout/box_layout.h" + +using message_center::Notification; +using message_center::MessageCenter; +using message_center::MessageView; + +namespace ash { + +UnifiedMessageListView::UnifiedMessageListView( + NewUnifiedMessageCenterView* message_center_view) + : message_center_view_(message_center_view) { + MessageCenter::Get()->AddObserver(this); + + SetLayoutManager( + std::make_unique<views::BoxLayout>(views::BoxLayout::kVertical)); + + bool is_latest = true; + for (auto* notification : MessageCenter::Get()->GetVisibleNotifications()) { + auto* view = CreateMessageView(*notification); + // Expand the latest notification, and collapse all other notifications. + view->SetExpanded(is_latest && view->IsAutoExpandingAllowed()); + is_latest = false; + AddChildViewAt(view, 0); + MessageCenter::Get()->DisplayedNotification( + notification->id(), message_center::DISPLAY_SOURCE_MESSAGE_CENTER); + } +} + +UnifiedMessageListView::~UnifiedMessageListView() { + MessageCenter::Get()->RemoveObserver(this); +} + +void UnifiedMessageListView::ChildPreferredSizeChanged(views::View* child) { + if (ignore_size_change_) + return; + PreferredSizeChanged(); +} + +void UnifiedMessageListView::PreferredSizeChanged() { + views::View::PreferredSizeChanged(); + if (message_center_view_) + message_center_view_->ListPreferredSizeChanged(); +} + +void UnifiedMessageListView::OnNotificationAdded(const std::string& id) { + auto* notification = MessageCenter::Get()->FindVisibleNotificationById(id); + if (!notification) + return; + + // Collapse all notifications before adding new one. + CollapseAllNotifications(); + + auto* view = CreateMessageView(*notification); + // Expand the latest notification. + view->SetExpanded(view->IsAutoExpandingAllowed()); + AddChildView(view); + PreferredSizeChanged(); +} + +void UnifiedMessageListView::OnNotificationRemoved(const std::string& id, + bool by_user) { + for (int i = 0; i < child_count(); ++i) { + auto* view = static_cast<message_center::MessageView*>(child_at(i)); + if (view->notification_id() == id) { + delete view; + break; + } + } + + PreferredSizeChanged(); +} + +void UnifiedMessageListView::OnNotificationUpdated(const std::string& id) { + auto* notification = MessageCenter::Get()->FindVisibleNotificationById(id); + if (!notification) + return; + + for (int i = 0; i < child_count(); ++i) { + auto* view = static_cast<message_center::MessageView*>(child_at(i)); + if (view->notification_id() == id) { + view->UpdateWithNotification(*notification); + break; + } + } + + PreferredSizeChanged(); +} + +message_center::MessageView* UnifiedMessageListView::CreateMessageView( + const Notification& notification) const { + auto* view = message_center::MessageViewFactory::Create(notification); + view->SetIsNested(); + view->UpdateCornerRadius(0, 0); + view->SetBorder(views::NullBorder()); + if (message_center_view_) + message_center_view_->ConfigureMessageView(view); + return view; +} + +void UnifiedMessageListView::CollapseAllNotifications() { + base::AutoReset<bool> auto_reset(&ignore_size_change_, true); + for (int i = 0; i < child_count(); ++i) { + auto* view = static_cast<message_center::MessageView*>(child_at(i)); + if (!view->IsManuallyExpandedOrCollapsed()) + view->SetExpanded(false); + } +} + +} // namespace ash
diff --git a/ash/system/message_center/unified_message_list_view.h b/ash/system/message_center/unified_message_list_view.h new file mode 100644 index 0000000..3b4a0d1 --- /dev/null +++ b/ash/system/message_center/unified_message_list_view.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 ASH_SYSTEM_MESSAGE_CENTER_UNIFIED_MESSAGE_LIST_VIEW_H_ +#define ASH_SYSTEM_MESSAGE_CENTER_UNIFIED_MESSAGE_LIST_VIEW_H_ + +#include "ash/ash_export.h" +#include "ui/message_center/message_center_observer.h" +#include "ui/views/view.h" + +namespace message_center { +class MessageView; +class Notification; +} // namespace message_center + +namespace ash { + +class NewUnifiedMessageCenterView; + +// Manages list of notifications. The class doesn't know about the ScrollView +// it's enclosed. This class is used only from NewUnifiedMessageCenterView. +class ASH_EXPORT UnifiedMessageListView + : public views::View, + public message_center::MessageCenterObserver { + public: + // |message_center_view| can be null in unit tests. + explicit UnifiedMessageListView( + NewUnifiedMessageCenterView* message_center_view); + ~UnifiedMessageListView() override; + + // views::View: + void ChildPreferredSizeChanged(views::View* child) override; + void PreferredSizeChanged() override; + + // message_center::MessageCenterObserver: + void OnNotificationAdded(const std::string& id) override; + void OnNotificationRemoved(const std::string& id, bool by_user) override; + void OnNotificationUpdated(const std::string& id) override; + + private: + message_center::MessageView* CreateMessageView( + const message_center::Notification& notification) const; + void CollapseAllNotifications(); + + NewUnifiedMessageCenterView* const message_center_view_; + + // If true, ChildPreferredSizeChanged() will be ignored. This is used in + // CollapseAllNotifications() to prevent PreferredSizeChanged() triggered + // multiple times because of sequential SetExpanded() calls. + bool ignore_size_change_ = false; + + DISALLOW_COPY_AND_ASSIGN(UnifiedMessageListView); +}; + +} // namespace ash + +#endif // ASH_SYSTEM_MESSAGE_CENTER_UNIFIED_MESSAGE_LIST_VIEW_H_
diff --git a/ash/system/message_center/unified_message_list_view_unittest.cc b/ash/system/message_center/unified_message_list_view_unittest.cc new file mode 100644 index 0000000..25e4185 --- /dev/null +++ b/ash/system/message_center/unified_message_list_view_unittest.cc
@@ -0,0 +1,166 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/system/message_center/unified_message_list_view.h" + +#include "ash/test/ash_test_base.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/utf_string_conversions.h" +#include "ui/message_center/message_center.h" +#include "ui/message_center/views/message_view.h" + +using message_center::MessageCenter; +using message_center::MessageView; +using message_center::Notification; + +namespace ash { + +class UnifiedMessageListViewTest : public AshTestBase, + public views::ViewObserver { + public: + UnifiedMessageListViewTest() = default; + ~UnifiedMessageListViewTest() override = default; + + void TearDown() override { + message_list_view_.reset(); + AshTestBase::TearDown(); + } + + // views::ViewObserver: + void OnViewPreferredSizeChanged(views::View* view) override { + view->SetBoundsRect(gfx::Rect(view->GetPreferredSize())); + view->Layout(); + ++size_changed_count_; + } + + protected: + std::string AddNotification() { + std::string id = base::IntToString(id_++); + MessageCenter::Get()->AddNotification(std::make_unique<Notification>( + message_center::NOTIFICATION_TYPE_BASE_FORMAT, id, + base::UTF8ToUTF16("test title"), base::UTF8ToUTF16("test message"), + gfx::Image(), base::string16() /* display_source */, GURL(), + message_center::NotifierId(), message_center::RichNotificationData(), + new message_center::NotificationDelegate())); + return id; + } + + void CreateMessageListView() { + message_list_view_ = std::make_unique<UnifiedMessageListView>(nullptr); + message_list_view_->AddObserver(this); + OnViewPreferredSizeChanged(message_list_view_.get()); + size_changed_count_ = 0; + } + + MessageView* GetMessageViewAt(int index) const { + return static_cast<MessageView*>(message_list_view()->child_at(index)); + } + + UnifiedMessageListView* message_list_view() const { + return message_list_view_.get(); + } + + int size_changed_count() const { return size_changed_count_; } + + private: + int id_ = 0; + int size_changed_count_ = 0; + + std::unique_ptr<UnifiedMessageListView> message_list_view_; + + DISALLOW_COPY_AND_ASSIGN(UnifiedMessageListViewTest); +}; + +TEST_F(UnifiedMessageListViewTest, Open) { + auto id0 = AddNotification(); + auto id1 = AddNotification(); + auto id2 = AddNotification(); + CreateMessageListView(); + + EXPECT_EQ(3, message_list_view()->child_count()); + EXPECT_EQ(id0, GetMessageViewAt(0)->notification_id()); + EXPECT_EQ(id1, GetMessageViewAt(1)->notification_id()); + EXPECT_EQ(id2, GetMessageViewAt(2)->notification_id()); + + EXPECT_FALSE(GetMessageViewAt(0)->IsExpanded()); + EXPECT_FALSE(GetMessageViewAt(1)->IsExpanded()); + EXPECT_TRUE(GetMessageViewAt(2)->IsExpanded()); + + EXPECT_EQ(GetMessageViewAt(0)->bounds().bottom(), + GetMessageViewAt(1)->bounds().y()); + EXPECT_EQ(GetMessageViewAt(1)->bounds().bottom(), + GetMessageViewAt(2)->bounds().y()); + + EXPECT_LT(0, message_list_view()->GetPreferredSize().height()); +} + +TEST_F(UnifiedMessageListViewTest, AddNotifications) { + CreateMessageListView(); + EXPECT_EQ(0, message_list_view()->GetPreferredSize().height()); + + auto id0 = AddNotification(); + EXPECT_EQ(1, size_changed_count()); + EXPECT_EQ(1, message_list_view()->child_count()); + EXPECT_EQ(id0, GetMessageViewAt(0)->notification_id()); + + int previous_height = message_list_view()->GetPreferredSize().height(); + EXPECT_LT(0, previous_height); + + gfx::Rect previous_bounds = GetMessageViewAt(0)->bounds(); + + auto id1 = AddNotification(); + EXPECT_EQ(2, size_changed_count()); + EXPECT_EQ(2, message_list_view()->child_count()); + EXPECT_EQ(id1, GetMessageViewAt(1)->notification_id()); + + EXPECT_LT(previous_height, message_list_view()->GetPreferredSize().height()); + EXPECT_EQ(previous_bounds, GetMessageViewAt(0)->bounds()); + EXPECT_EQ(GetMessageViewAt(0)->bounds().bottom(), + GetMessageViewAt(1)->bounds().y()); +} + +TEST_F(UnifiedMessageListViewTest, RemoveNotification) { + auto id0 = AddNotification(); + auto id1 = AddNotification(); + + CreateMessageListView(); + int previous_height = message_list_view()->GetPreferredSize().height(); + + gfx::Rect previous_bounds = GetMessageViewAt(0)->bounds(); + MessageCenter::Get()->RemoveNotification(id0, true /* by_user */); + EXPECT_EQ(1, size_changed_count()); + EXPECT_EQ(previous_bounds.y(), GetMessageViewAt(0)->bounds().y()); + EXPECT_LT(0, message_list_view()->GetPreferredSize().height()); + EXPECT_GT(previous_height, message_list_view()->GetPreferredSize().height()); + + MessageCenter::Get()->RemoveNotification(id1, true /* by_user */); + EXPECT_EQ(2, size_changed_count()); + EXPECT_EQ(0, message_list_view()->GetPreferredSize().height()); +} + +TEST_F(UnifiedMessageListViewTest, CollapseOlderNotifications) { + AddNotification(); + CreateMessageListView(); + EXPECT_TRUE(GetMessageViewAt(0)->IsExpanded()); + + AddNotification(); + EXPECT_FALSE(GetMessageViewAt(0)->IsExpanded()); + EXPECT_TRUE(GetMessageViewAt(1)->IsExpanded()); + + AddNotification(); + EXPECT_FALSE(GetMessageViewAt(0)->IsExpanded()); + EXPECT_FALSE(GetMessageViewAt(1)->IsExpanded()); + EXPECT_TRUE(GetMessageViewAt(2)->IsExpanded()); + + GetMessageViewAt(1)->SetExpanded(true); + GetMessageViewAt(1)->SetManuallyExpandedOrCollapsed(true); + + AddNotification(); + EXPECT_FALSE(GetMessageViewAt(0)->IsExpanded()); + EXPECT_TRUE(GetMessageViewAt(1)->IsExpanded()); + EXPECT_FALSE(GetMessageViewAt(2)->IsExpanded()); + EXPECT_TRUE(GetMessageViewAt(3)->IsExpanded()); +} + +} // namespace ash
diff --git a/ash/system/model/system_tray_model.cc b/ash/system/model/system_tray_model.cc index 48feced0..66b4b4fc 100644 --- a/ash/system/model/system_tray_model.cc +++ b/ash/system/model/system_tray_model.cc
@@ -13,6 +13,7 @@ #include "ash/system/model/session_length_limit_model.h" #include "ash/system/model/tracing_model.h" #include "ash/system/model/update_model.h" +#include "ash/system/model/virtual_keyboard_model.h" #include "ash/system/status_area_widget.h" #include "ash/system/tray/system_tray.h" #include "ash/system/unified/unified_system_tray.h" @@ -25,7 +26,8 @@ enterprise_domain_(std::make_unique<EnterpriseDomainModel>()), session_length_limit_(std::make_unique<SessionLengthLimitModel>()), tracing_(std::make_unique<TracingModel>()), - update_model_(std::make_unique<UpdateModel>()) {} + update_model_(std::make_unique<UpdateModel>()), + virtual_keyboard_(std::make_unique<VirtualKeyboardModel>()) {} SystemTrayModel::~SystemTrayModel() = default;
diff --git a/ash/system/model/system_tray_model.h b/ash/system/model/system_tray_model.h index 32509bd4..de9525433 100644 --- a/ash/system/model/system_tray_model.h +++ b/ash/system/model/system_tray_model.h
@@ -18,6 +18,7 @@ class SessionLengthLimitModel; class TracingModel; class UpdateModel; +class VirtualKeyboardModel; // Top level model of SystemTray. class SystemTrayModel : public mojom::SystemTray { @@ -56,6 +57,7 @@ } TracingModel* tracing() { return tracing_.get(); } UpdateModel* update_model() { return update_model_.get(); } + VirtualKeyboardModel* virtual_keyboard() { return virtual_keyboard_.get(); } const mojom::SystemTrayClientPtr& client_ptr() { return client_ptr_; } @@ -65,6 +67,7 @@ std::unique_ptr<SessionLengthLimitModel> session_length_limit_; std::unique_ptr<TracingModel> tracing_; std::unique_ptr<UpdateModel> update_model_; + std::unique_ptr<VirtualKeyboardModel> virtual_keyboard_; // TODO(tetsui): Add following as a sub-model of SystemTrayModel: // * BluetoothModel
diff --git a/ash/system/model/virtual_keyboard_model.cc b/ash/system/model/virtual_keyboard_model.cc new file mode 100644 index 0000000..084aa5e --- /dev/null +++ b/ash/system/model/virtual_keyboard_model.cc
@@ -0,0 +1,48 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/system/model/virtual_keyboard_model.h" + +namespace ash { + +VirtualKeyboardModel::VirtualKeyboardModel() = default; +VirtualKeyboardModel::~VirtualKeyboardModel() = default; + +void VirtualKeyboardModel::AddObserver( + VirtualKeyboardModel::Observer* observer) { + observers_.AddObserver(observer); +} + +void VirtualKeyboardModel::RemoveObserver( + VirtualKeyboardModel::Observer* observer) { + observers_.RemoveObserver(observer); +} + +void VirtualKeyboardModel::SetInputMethodSurfaceManagerObserver( + ArcInputMethodSurfaceManager* input_method_surface_manager) { + DCHECK(input_method_surface_manager); + input_method_surface_manager->AddObserver(this); +} + +void VirtualKeyboardModel::RemoveInputMethodSurfaceManagerObserver( + ArcInputMethodSurfaceManager* input_method_surface_manager) { + DCHECK(input_method_surface_manager); + input_method_surface_manager->RemoveObserver(this); +} + +void VirtualKeyboardModel::OnArcInputMethodSurfaceBoundsChanged( + const gfx::Rect& bounds) { + const bool new_visible = !bounds.IsEmpty(); + if (visible_ == new_visible) + return; + visible_ = new_visible; + NotifyChanged(); +} + +void VirtualKeyboardModel::NotifyChanged() { + for (auto& observer : observers_) + observer.OnVirtualKeyboardVisibilityChanged(); +} + +} // namespace ash
diff --git a/ash/system/model/virtual_keyboard_model.h b/ash/system/model/virtual_keyboard_model.h new file mode 100644 index 0000000..91a7f82 --- /dev/null +++ b/ash/system/model/virtual_keyboard_model.h
@@ -0,0 +1,60 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_SYSTEM_MODEL_VIRTUAL_KEYBOARD_MODEL_H_ +#define ASH_SYSTEM_MODEL_VIRTUAL_KEYBOARD_MODEL_H_ + +#include <memory> + +#include "ash/ash_export.h" +#include "ash/keyboard/arc/arc_input_method_surface_manager.h" +#include "base/macros.h" +#include "base/observer_list.h" + +namespace ash { + +class ArcInputMethodSurfaceManager; + +// Model to store virtual keyboard visibility state. +class ASH_EXPORT VirtualKeyboardModel + : public ArcInputMethodSurfaceManager::Observer { + public: + class Observer { + public: + virtual ~Observer() {} + + virtual void OnVirtualKeyboardVisibilityChanged() = 0; + }; + + VirtualKeyboardModel(); + ~VirtualKeyboardModel() override; + + void AddObserver(Observer* observer); + void RemoveObserver(Observer* observer); + + // Start/stop observing ArcInputMethodSurfaceManager. + void SetInputMethodSurfaceManagerObserver( + ArcInputMethodSurfaceManager* input_method_surface_manager); + void RemoveInputMethodSurfaceManagerObserver( + ArcInputMethodSurfaceManager* input_method_surface_manager); + + // ArcInputMethodSurfaceManager::Observer: + void OnArcInputMethodSurfaceBoundsChanged(const gfx::Rect& bounds) override; + + bool visible() const { return visible_; } + + private: + void NotifyChanged(); + + // The visibility of virtual keyboard. + bool visible_ = false; + + base::ObserverList<Observer>::Unchecked observers_; + + DISALLOW_COPY_AND_ASSIGN(VirtualKeyboardModel); +}; + +} // namespace ash + +#endif // ASH_SYSTEM_MODEL_VIRTUAL_KEYBOARD_MODEL_H_
diff --git a/ash/system/status_area_widget.cc b/ash/system/status_area_widget.cc index bb18d0b..ec4ca5c 100644 --- a/ash/system/status_area_widget.cc +++ b/ash/system/status_area_widget.cc
@@ -96,6 +96,8 @@ if (notification_tray_) { system_tray_->InitializeTrayItems(notification_tray_.get()); notification_tray_->Initialize(); + } else { + unified_system_tray_->Initialize(); } palette_tray_->Initialize(); virtual_keyboard_tray_->Initialize();
diff --git a/ash/system/tray/tray_background_view.cc b/ash/system/tray/tray_background_view.cc index 343ea0b..1e1cf35 100644 --- a/ash/system/tray/tray_background_view.cc +++ b/ash/system/tray/tray_background_view.cc
@@ -17,6 +17,7 @@ #include "ash/shelf/shelf_layout_manager.h" #include "ash/shelf/shelf_widget.h" #include "ash/shell.h" +#include "ash/system/model/system_tray_model.h" #include "ash/system/status_area_widget.h" #include "ash/system/status_area_widget_delegate.h" #include "ash/system/tray/system_tray_notifier.h" @@ -177,6 +178,8 @@ background_(new TrayBackground(this)), is_active_(false), separator_visible_(true), + visible_preferred_(false), + show_with_virtual_keyboard_(false), widget_observer_(new TrayWidgetObserver(this)) { DCHECK(shelf_); set_notify_enter_exit_on_child(true); @@ -197,6 +200,7 @@ } TrayBackgroundView::~TrayBackgroundView() { + Shell::Get()->system_tray_model()->virtual_keyboard()->RemoveObserver(this); if (GetWidget()) GetWidget()->RemoveObserver(widget_observer_.get()); StopObservingImplicitAnimations(); @@ -204,6 +208,7 @@ void TrayBackgroundView::Initialize() { GetWidget()->AddObserver(widget_observer_.get()); + Shell::Get()->system_tray_model()->virtual_keyboard()->AddObserver(this); } // static @@ -218,6 +223,16 @@ } void TrayBackgroundView::SetVisible(bool visible) { + visible_preferred_ = visible; + + // If virtual keyboard is visible and TrayBackgroundView is hidden because of + // that, ignore SetVisible() call. |visible_preferred_| will be restored + // in OnVirtualKeyboardVisibilityChanged() when virtual keyboard is hidden. + if (!show_with_virtual_keyboard_ && + Shell::Get()->system_tray_model()->virtual_keyboard()->visible()) { + return; + } + if (visible == layer()->GetTargetVisibility()) return; @@ -393,6 +408,18 @@ drag_controller_->ProcessGestureEvent(event, this); } +void TrayBackgroundView::OnVirtualKeyboardVisibilityChanged() { + if (show_with_virtual_keyboard_) + return; + + // If virtual keyboard is hidden and current preferred visibility is true, + // set the visibility to true. We call base class' SetVisible because we don't + // want |visible_preferred_| to be updated here. + views::View::SetVisible( + !Shell::Get()->system_tray_model()->virtual_keyboard()->visible() && + visible_preferred_); +} + TrayBubbleView* TrayBackgroundView::GetBubbleView() { return nullptr; }
diff --git a/ash/system/tray/tray_background_view.h b/ash/system/tray/tray_background_view.h index 7b26151..8827124 100644 --- a/ash/system/tray/tray_background_view.h +++ b/ash/system/tray/tray_background_view.h
@@ -9,6 +9,7 @@ #include "ash/ash_export.h" #include "ash/shelf/shelf_background_animator_observer.h" +#include "ash/system/model/virtual_keyboard_model.h" #include "ash/system/tray/actionable_view.h" #include "ash/system/tray/tray_bubble_view.h" #include "ash/system/tray_drag_controller.h" @@ -29,7 +30,8 @@ class ASH_EXPORT TrayBackgroundView : public ActionableView, public ui::ImplicitAnimationObserver, public ShelfBackgroundAnimatorObserver, - public TrayBubbleView::Delegate { + public TrayBubbleView::Delegate, + public VirtualKeyboardModel::Observer { public: static const char kViewClassName[]; @@ -60,6 +62,9 @@ // TrayBubbleView::Delegate: void ProcessGestureEventForBubble(ui::GestureEvent* event) override; + // VirtualKeyboardModel::Observer: + void OnVirtualKeyboardVisibilityChanged() override; + // Returns the associated tray bubble view, if one exists. Otherwise returns // nullptr. virtual TrayBubbleView* GetBubbleView(); @@ -156,6 +161,10 @@ drag_controller_ = std::move(drag_controller); } + void set_show_with_virtual_keyboard(bool show_with_virtual_keyboard) { + show_with_virtual_keyboard_ = show_with_virtual_keyboard; + } + private: class TrayWidgetObserver; @@ -188,6 +197,14 @@ // right of tray. bool separator_visible_; + // During virtual keyboard is shown, visibility changes to TrayBackgroundView + // are ignored. In such case, preferred visibility is reflected after the + // virtual keyboard is hidden. + bool visible_preferred_; + + // If true, ignores virtual keyboard visibility changes. + bool show_with_virtual_keyboard_; + // Handles touch drag gestures on the tray area and its associated bubble. std::unique_ptr<TrayDragController> drag_controller_;
diff --git a/ash/system/unified/unified_system_tray_view.cc b/ash/system/unified/unified_system_tray_view.cc index 7f6d63f9..c25f867 100644 --- a/ash/system/unified/unified_system_tray_view.cc +++ b/ash/system/unified/unified_system_tray_view.cc
@@ -9,13 +9,14 @@ #include "ash/public/cpp/ash_features.h" #include "ash/session/session_controller.h" #include "ash/shell.h" +#include "ash/system/message_center/new_unified_message_center_view.h" +#include "ash/system/message_center/unified_message_center_view.h" #include "ash/system/tray/interacted_by_tap_recorder.h" #include "ash/system/tray/tray_constants.h" #include "ash/system/unified/feature_pod_button.h" #include "ash/system/unified/feature_pods_container_view.h" #include "ash/system/unified/notification_hidden_view.h" #include "ash/system/unified/top_shortcuts_view.h" -#include "ash/system/unified/unified_message_center_view.h" #include "ash/system/unified/unified_system_info_view.h" #include "ash/system/unified/unified_system_tray_controller.h" #include "ash/system/unified/unified_system_tray_model.h" @@ -220,10 +221,15 @@ system_info_view_(new UnifiedSystemInfoView(controller_)), system_tray_container_(new SystemTrayContainer()), detailed_view_container_(new DetailedViewContainer()), - message_center_view_( - new UnifiedMessageCenterView(controller, - this, - message_center::MessageCenter::Get())), + message_center_view_(features::IsNewMessageListViewEnabled() + ? nullptr + : new UnifiedMessageCenterView( + controller, + this, + message_center::MessageCenter::Get())), + new_message_center_view_(features::IsNewMessageListViewEnabled() + ? new NewUnifiedMessageCenterView() + : nullptr), focus_search_(std::make_unique<FocusSearch>(this)), interacted_by_tap_recorder_( std::make_unique<InteractedByTapRecorder>(this)) { @@ -238,11 +244,17 @@ SessionController* session_controller = Shell::Get()->session_controller(); - message_center_view_->SetVisible( + views::View* message_center_view; + if (features::IsNewMessageListViewEnabled()) + message_center_view = new_message_center_view_; + else + message_center_view = message_center_view_; + + message_center_view->SetVisible( session_controller->ShouldShowNotificationTray() && !session_controller->IsScreenLocked()); - AddChildView(message_center_view_); - layout->SetFlexForView(message_center_view_, 1); + AddChildView(message_center_view); + layout->SetFlexForView(message_center_view, 1); notification_hidden_view_->SetVisible( session_controller->GetUserSession(0) && @@ -265,8 +277,8 @@ // |message_center_view_| next to |detailed_view_container_|. // Also, SetNextFocusableView does not support loop as mentioned in the doc, // we have to set null to |message_center_view_|. - message_center_view_->SetNextFocusableView(nullptr); - detailed_view_container_->SetNextFocusableView(message_center_view_); + message_center_view->SetNextFocusableView(nullptr); + detailed_view_container_->SetNextFocusableView(message_center_view); top_shortcuts_view_->SetExpandedAmount(expanded_amount_); } @@ -274,7 +286,10 @@ UnifiedSystemTrayView::~UnifiedSystemTrayView() = default; void UnifiedSystemTrayView::SetMaxHeight(int max_height) { - message_center_view_->SetMaxHeight(max_height); + if (message_center_view_) + message_center_view_->SetMaxHeight(max_height); + else if (new_message_center_view_) + new_message_center_view_->SetMaxHeight(max_height); } void UnifiedSystemTrayView::AddFeaturePodButton(FeaturePodButton* button) { @@ -355,11 +370,13 @@ // TODO(tetsui): Support animation by transform even when // UnifiedMessageCenterview is visible. return expanded_amount_ != 0.0 && expanded_amount_ != 1.0 && - !message_center_view_->visible(); + (message_center_view_ ? !message_center_view_->visible() + : !new_message_center_view_->visible()); } void UnifiedSystemTrayView::ShowClearAllAnimation() { - message_center_view_->ShowClearAllAnimation(); + if (message_center_view_) + message_center_view_->ShowClearAllAnimation(); } void UnifiedSystemTrayView::SetNotificationHeightBelowScroll(
diff --git a/ash/system/unified/unified_system_tray_view.h b/ash/system/unified/unified_system_tray_view.h index 33a8311..a3ac488 100644 --- a/ash/system/unified/unified_system_tray_view.h +++ b/ash/system/unified/unified_system_tray_view.h
@@ -15,6 +15,7 @@ class FeaturePodsContainerView; class TopShortcutsView; class UnifiedMessageCenterView; +class NewUnifiedMessageCenterView; class UnifiedSystemInfoView; class UnifiedSystemTrayController; @@ -127,6 +128,7 @@ views::View* const system_tray_container_; views::View* const detailed_view_container_; UnifiedMessageCenterView* const message_center_view_; + NewUnifiedMessageCenterView* const new_message_center_view_; const std::unique_ptr<FocusSearch> focus_search_; const std::unique_ptr<ui::EventHandler> interacted_by_tap_recorder_;
diff --git a/ash/wayland/wayland_server_controller.h b/ash/wayland/wayland_server_controller.h index 75509fd..b14851eb 100644 --- a/ash/wayland/wayland_server_controller.h +++ b/ash/wayland/wayland_server_controller.h
@@ -37,6 +37,10 @@ ~WaylandServerController(); + ArcInputMethodSurfaceManager* arc_input_method_surface_manager() { + return arc_input_method_surface_manager_.get(); + } + private: WaylandServerController(std::unique_ptr<exo::FileHelper> file_helper, aura::Env* env);
diff --git a/base/command_line.cc b/base/command_line.cc index aec89f5..7825952 100644 --- a/base/command_line.cc +++ b/base/command_line.cc
@@ -371,7 +371,7 @@ // Gather all arguments after the last switch (may include kSwitchTerminator). StringVector args(argv_.begin() + begin_args_, argv_.end()); // Erase only the first kSwitchTerminator (maybe "--" is a legitimate page?) - StringVector::iterator switch_terminator = + auto switch_terminator = std::find(args.begin(), args.end(), kSwitchTerminator); if (switch_terminator != args.end()) args.erase(switch_terminator);
diff --git a/base/command_line_unittest.cc b/base/command_line_unittest.cc index 3718cd9..93ccd7c 100644 --- a/base/command_line_unittest.cc +++ b/base/command_line_unittest.cc
@@ -84,7 +84,7 @@ const CommandLine::StringVector& args = cl.GetArgs(); ASSERT_EQ(8U, args.size()); - std::vector<CommandLine::StringType>::const_iterator iter = args.begin(); + auto iter = args.begin(); EXPECT_EQ(FILE_PATH_LITERAL("flim"), *iter); ++iter; EXPECT_EQ(FILE_PATH_LITERAL("-"), *iter);
diff --git a/base/containers/flat_tree_unittest.cc b/base/containers/flat_tree_unittest.cc index 5b788d5..6482684a 100644 --- a/base/containers/flat_tree_unittest.cc +++ b/base/containers/flat_tree_unittest.cc
@@ -613,8 +613,8 @@ EXPECT_EQ(size, std::distance(cont.crbegin(), cont.crend())); { - IntTree::iterator it = cont.begin(); - IntTree::const_iterator c_it = cont.cbegin(); + auto it = cont.begin(); + auto c_it = cont.cbegin(); EXPECT_EQ(it, c_it); for (int j = 1; it != cont.end(); ++it, ++c_it, ++j) { EXPECT_EQ(j, *it); @@ -622,8 +622,8 @@ } } { - IntTree::reverse_iterator rit = cont.rbegin(); - IntTree::const_reverse_iterator c_rit = cont.crbegin(); + auto rit = cont.rbegin(); + auto c_rit = cont.crbegin(); EXPECT_EQ(rit, c_rit); for (int j = static_cast<int>(size); rit != cont.rend(); ++rit, ++c_rit, --j) { @@ -705,7 +705,7 @@ TEST(FlatTree, InsertPositionLValue) { IntTree cont; - IntTree::iterator result = cont.insert(cont.cend(), 2); + auto result = cont.insert(cont.cend(), 2); EXPECT_EQ(cont.begin(), result); EXPECT_EQ(1U, cont.size()); EXPECT_EQ(2, *result); @@ -731,7 +731,7 @@ TEST(FlatTree, InsertPositionRValue) { MoveOnlyTree cont; - MoveOnlyTree::iterator result = cont.insert(cont.cend(), MoveOnlyInt(2)); + auto result = cont.insert(cont.cend(), MoveOnlyInt(2)); EXPECT_EQ(cont.begin(), result); EXPECT_EQ(1U, cont.size()); EXPECT_EQ(2, result->data()); @@ -893,7 +893,7 @@ { EmplaceableTree cont; - EmplaceableTree::iterator result = cont.emplace_hint(cont.cend()); + auto result = cont.emplace_hint(cont.cend()); EXPECT_EQ(cont.begin(), result); EXPECT_EQ(1U, cont.size()); EXPECT_EQ(Emplaceable(), *cont.begin()); @@ -911,7 +911,7 @@ { IntTree cont; - IntTree::iterator result = cont.emplace_hint(cont.cend(), 2); + auto result = cont.emplace_hint(cont.cend(), 2); EXPECT_EQ(cont.begin(), result); EXPECT_EQ(1U, cont.size()); EXPECT_EQ(2, *result); @@ -927,7 +927,7 @@ { IntTree cont({1, 2, 3, 4, 5, 6, 7, 8}); - IntTree::iterator it = cont.erase(std::next(cont.cbegin(), 3)); + auto it = cont.erase(std::next(cont.cbegin(), 3)); EXPECT_EQ(std::next(cont.begin(), 3), it); EXPECT_THAT(cont, ElementsAre(1, 2, 3, 5, 6, 7, 8)); @@ -979,7 +979,7 @@ TEST(FlatTree, EraseRange) { IntTree cont({1, 2, 3, 4, 5, 6, 7, 8}); - IntTree::iterator it = + auto it = cont.erase(std::next(cont.cbegin(), 5), std::next(cont.cbegin(), 5)); EXPECT_EQ(std::next(cont.begin(), 5), it); EXPECT_THAT(cont, ElementsAre(1, 2, 3, 4, 5, 6, 7, 8));
diff --git a/base/containers/mru_cache_unittest.cc b/base/containers/mru_cache_unittest.cc index 28e6f0d..07b0144 100644 --- a/base/containers/mru_cache_unittest.cc +++ b/base/containers/mru_cache_unittest.cc
@@ -52,12 +52,12 @@ static const int kItem1Key = 5; CachedItem item1(10); - Cache::iterator inserted_item = cache.Put(kItem1Key, item1); + auto inserted_item = cache.Put(kItem1Key, item1); EXPECT_EQ(1U, cache.size()); // Check that item1 was properly inserted. { - Cache::iterator found = cache.Get(kItem1Key); + auto found = cache.Get(kItem1Key); EXPECT_TRUE(inserted_item == cache.begin()); EXPECT_TRUE(found != cache.end()); @@ -75,7 +75,7 @@ // Check that item1 is the oldest since item2 was added afterwards. { - Cache::reverse_iterator oldest = cache.rbegin(); + auto oldest = cache.rbegin(); ASSERT_TRUE(oldest != cache.rend()); EXPECT_EQ(kItem1Key, oldest->first); EXPECT_EQ(item1.value, oldest->second.value); @@ -83,7 +83,7 @@ // Check that item1 is still accessible by key. { - Cache::iterator test_item = cache.Get(kItem1Key); + auto test_item = cache.Get(kItem1Key); ASSERT_TRUE(test_item != cache.end()); EXPECT_EQ(kItem1Key, test_item->first); EXPECT_EQ(item1.value, test_item->second.value); @@ -91,7 +91,7 @@ // Check that retrieving item1 pushed item2 to oldest. { - Cache::reverse_iterator oldest = cache.rbegin(); + auto oldest = cache.rbegin(); ASSERT_TRUE(oldest != cache.rend()); EXPECT_EQ(kItem2Key, oldest->first); EXPECT_EQ(item2.value, oldest->second.value); @@ -99,7 +99,7 @@ // Remove the oldest item and check that item1 is now the only member. { - Cache::reverse_iterator next = cache.Erase(cache.rbegin()); + auto next = cache.Erase(cache.rbegin()); EXPECT_EQ(1U, cache.size()); @@ -136,7 +136,7 @@ // Check that item1 starts out as oldest { - Cache::reverse_iterator iter = cache.rbegin(); + auto iter = cache.rbegin(); ASSERT_TRUE(iter != cache.rend()); EXPECT_EQ(kItem1Key, iter->first); EXPECT_EQ(item1.value, iter->second.value); @@ -144,10 +144,10 @@ // Check that Peek doesn't change ordering { - Cache::iterator peekiter = cache.Peek(kItem1Key); + auto peekiter = cache.Peek(kItem1Key); ASSERT_TRUE(peekiter != cache.end()); - Cache::reverse_iterator iter = cache.rbegin(); + auto iter = cache.rbegin(); ASSERT_TRUE(iter != cache.rend()); EXPECT_EQ(kItem1Key, iter->first); EXPECT_EQ(item1.value, iter->second.value); @@ -179,14 +179,14 @@ EXPECT_EQ(4U, cache.size()); for (int i = 0; i < 3; ++i) { - Cache::reverse_iterator iter = cache.rbegin(); + auto iter = cache.rbegin(); ASSERT_TRUE(iter != cache.rend()); } // Make it so only the most important element is there. cache.ShrinkToSize(1); - Cache::iterator iter = cache.begin(); + auto iter = cache.begin(); EXPECT_EQ(kItem3Key, iter->first); EXPECT_EQ(item5.value, iter->second.value); } @@ -204,7 +204,7 @@ cache.Put(kItem1Key, WrapUnique(new CachedItem(22))); // There should still be one item, and one extra live item. - Cache::iterator iter = cache.Get(kItem1Key); + auto iter = cache.Get(kItem1Key); EXPECT_EQ(1U, cache.size()); EXPECT_TRUE(iter != cache.end()); EXPECT_EQ(initial_count + 1, cached_item_live_count); @@ -284,7 +284,7 @@ // Insert two items into cache1. static const int kItem1Key = 1; CachedItem item1(2); - Cache::iterator inserted_item = cache1.Put(kItem1Key, item1); + auto inserted_item = cache1.Put(kItem1Key, item1); EXPECT_EQ(1U, cache1.size()); static const int kItem2Key = 3; @@ -294,7 +294,7 @@ // Verify cache1's elements. { - Cache::iterator iter = cache1.begin(); + auto iter = cache1.begin(); ASSERT_TRUE(iter != cache1.end()); EXPECT_EQ(kItem2Key, iter->first); EXPECT_EQ(item2.value, iter->second.value); @@ -326,7 +326,7 @@ // Verify cache2's elements. { - Cache::iterator iter = cache2.begin(); + auto iter = cache2.begin(); ASSERT_TRUE(iter != cache2.end()); EXPECT_EQ(kItem5Key, iter->first); EXPECT_EQ(item5.value, iter->second.value); @@ -351,7 +351,7 @@ // Verify cache1's elements. { - Cache::iterator iter = cache1.begin(); + auto iter = cache1.begin(); ASSERT_TRUE(iter != cache1.end()); EXPECT_EQ(kItem5Key, iter->first); EXPECT_EQ(item5.value, iter->second.value); @@ -369,7 +369,7 @@ // Verify cache2's elements. { - Cache::iterator iter = cache2.begin(); + auto iter = cache2.begin(); ASSERT_TRUE(iter != cache2.end()); EXPECT_EQ(kItem2Key, iter->first); EXPECT_EQ(item2.value, iter->second.value);
diff --git a/base/containers/stack_container_unittest.cc b/base/containers/stack_container_unittest.cc index b6bb9b6..e652cf9 100644 --- a/base/containers/stack_container_unittest.cc +++ b/base/containers/stack_container_unittest.cc
@@ -79,7 +79,6 @@ TEST(StackContainer, VectorDoubleDelete) { // Regression testing for double-delete. typedef StackVector<scoped_refptr<Dummy>, 2> Vector; - typedef Vector::ContainerType Container; Vector vect; int alive = 0; @@ -93,7 +92,7 @@ dummy = nullptr; EXPECT_EQ(alive, 1); - Container::iterator itr = std::find(vect->begin(), vect->end(), dummy_unref); + auto itr = std::find(vect->begin(), vect->end(), dummy_unref); EXPECT_EQ(itr->get(), dummy_unref); vect->erase(itr); EXPECT_EQ(alive, 0);
diff --git a/base/deferred_sequenced_task_runner.cc b/base/deferred_sequenced_task_runner.cc index f88170c..156369a 100644 --- a/base/deferred_sequenced_task_runner.cc +++ b/base/deferred_sequenced_task_runner.cc
@@ -111,9 +111,8 @@ DCHECK(!started_); started_ = true; DCHECK(target_task_runner_); - for (std::vector<DeferredTask>::iterator i = deferred_tasks_queue_.begin(); - i != deferred_tasks_queue_.end(); - ++i) { + for (auto i = deferred_tasks_queue_.begin(); i != deferred_tasks_queue_.end(); + ++i) { DeferredTask& task = *i; if (task.is_non_nestable) { target_task_runner_->PostNonNestableDelayedTask(
diff --git a/base/environment.cc b/base/environment.cc index cdea53c8..9eccc78 100644 --- a/base/environment.cc +++ b/base/environment.cc
@@ -195,7 +195,7 @@ size_t line_length = ParseEnvLine(env[i], &key); // Keep only values not specified in the change vector. - EnvironmentMap::const_iterator found_change = changes.find(key); + auto found_change = changes.find(key); if (found_change == changes.end()) { result_indices.push_back(value_storage.size()); value_storage.append(env[i], line_length); @@ -203,8 +203,7 @@ } // Now append all modified and new values. - for (EnvironmentMap::const_iterator i = changes.begin(); - i != changes.end(); ++i) { + for (auto i = changes.begin(); i != changes.end(); ++i) { if (!i->second.empty()) { result_indices.push_back(value_storage.size()); value_storage.append(i->first);
diff --git a/base/files/file_path_watcher_linux.cc b/base/files/file_path_watcher_linux.cc index 182a762..b22421d 100644 --- a/base/files/file_path_watcher_linux.cc +++ b/base/files/file_path_watcher_linux.cc
@@ -551,9 +551,8 @@ recursive_paths_by_watch_[fired_watch] : target_; - std::map<FilePath, InotifyReader::Watch>::iterator start_it = - recursive_watches_by_path_.lower_bound(changed_dir); - std::map<FilePath, InotifyReader::Watch>::iterator end_it = start_it; + auto start_it = recursive_watches_by_path_.lower_bound(changed_dir); + auto end_it = start_it; for (; end_it != recursive_watches_by_path_.end(); ++end_it) { const FilePath& cur_path = end_it->first; if (!changed_dir.IsParent(cur_path))
diff --git a/base/files/file_util_posix.cc b/base/files/file_util_posix.cc index d0af7f3..53cc974 100644 --- a/base/files/file_util_posix.cc +++ b/base/files/file_util_posix.cc
@@ -715,8 +715,7 @@ } // Iterate through the parents and create the missing ones. - for (std::vector<FilePath>::reverse_iterator i = subpaths.rbegin(); - i != subpaths.rend(); ++i) { + for (auto i = subpaths.rbegin(); i != subpaths.rend(); ++i) { if (DirectoryExists(*i)) continue; if (mkdir(i->value().c_str(), 0700) == 0)
diff --git a/base/i18n/build_utf8_validator_tables.cc b/base/i18n/build_utf8_validator_tables.cc index 0cdcc35..b349c5f 100644 --- a/base/i18n/build_utf8_validator_tables.cc +++ b/base/i18n/build_utf8_validator_tables.cc
@@ -263,12 +263,9 @@ // algorithm is working. Use the command-line option // --vmodule=build_utf8_validator_tables=1 to see this output. void LogStringSets(const PairVector& pairs) { - for (PairVector::const_iterator pair_it = pairs.begin(); - pair_it != pairs.end(); - ++pair_it) { + for (auto pair_it = pairs.begin(); pair_it != pairs.end(); ++pair_it) { std::string set_as_string; - for (StringSet::const_iterator set_it = pair_it->set.begin(); - set_it != pair_it->set.end(); + for (auto set_it = pair_it->set.begin(); set_it != pair_it->set.end(); ++set_it) { set_as_string += base::StringPrintf("[\\x%02x-\\x%02x]", static_cast<int>(set_it->from()), @@ -333,7 +330,7 @@ std::vector<State> states(2, GenerateInvalidState()); StateMap state_map; state_map.insert(std::make_pair(StringSet(), 0)); - for (PairVector::const_iterator it = pairs.begin(); it != pairs.end(); ++it) { + for (auto it = pairs.begin(); it != pairs.end(); ++it) { DCHECK(it->character.empty()); DCHECK(!it->set.empty()); const Range& range = it->set.front(); @@ -376,16 +373,13 @@ std::vector<uint8_t> shifts; uint8_t pos = 0; - for (std::vector<State>::const_iterator state_it = states.begin(); - state_it != states.end(); - ++state_it) { + for (auto state_it = states.begin(); state_it != states.end(); ++state_it) { // We want to set |shift| to the (0-based) index of the least-significant // set bit in any of the ranges for this state, since this tells us how many // bits we can discard and still determine what range a byte lies in. Sadly // it appears that ffs() is not portable, so we do it clumsily. uint8_t shift = 7; - for (State::const_iterator range_it = state_it->begin(); - range_it != state_it->end(); + for (auto range_it = state_it->begin(); range_it != state_it->end(); ++range_it) { while (shift > 0 && range_it->from % (1 << shift) != 0) { --shift;
diff --git a/base/metrics/field_trial.cc b/base/metrics/field_trial.cc index b0e7a1d..ffb4744 100644 --- a/base/metrics/field_trial.cc +++ b/base/metrics/field_trial.cc
@@ -510,7 +510,7 @@ FieldTrialList::~FieldTrialList() { AutoLock auto_lock(lock_); while (!registered_.empty()) { - RegistrationMap::iterator it = registered_.begin(); + auto it = registered_.begin(); it->second->Release(); registered_.erase(it->first); } @@ -728,8 +728,8 @@ return; AutoLock auto_lock(global_->lock_); - for (RegistrationMap::iterator it = global_->registered_.begin(); - it != global_->registered_.end(); ++it) { + for (auto it = global_->registered_.begin(); it != global_->registered_.end(); + ++it) { FieldTrial::ActiveGroup active_group; if (it->second->GetActiveGroup(&active_group)) active_groups->push_back(active_group); @@ -1497,7 +1497,7 @@ } FieldTrial* FieldTrialList::PreLockedFind(const std::string& name) { - RegistrationMap::iterator it = registered_.find(name); + auto it = registered_.find(name); if (registered_.end() == it) return nullptr; return it->second;
diff --git a/base/metrics/field_trial_params.cc b/base/metrics/field_trial_params.cc index 7195f4a..f01db0f 100644 --- a/base/metrics/field_trial_params.cc +++ b/base/metrics/field_trial_params.cc
@@ -41,7 +41,7 @@ const std::string& param_name) { std::map<std::string, std::string> params; if (GetFieldTrialParams(trial_name, ¶ms)) { - std::map<std::string, std::string>::iterator it = params.find(param_name); + auto it = params.find(param_name); if (it != params.end()) return it->second; }
diff --git a/base/metrics/histogram.cc b/base/metrics/histogram.cc index 4166adf..bf7d7c9e 100644 --- a/base/metrics/histogram.cc +++ b/base/metrics/histogram.cc
@@ -1094,7 +1094,7 @@ const std::string LinearHistogram::GetAsciiBucketRange(uint32_t i) const { int range = ranges(i); - BucketDescriptionMap::const_iterator it = bucket_description_.find(range); + auto it = bucket_description_.find(range); if (it == bucket_description_.end()) return Histogram::GetAsciiBucketRange(i); return it->second;
diff --git a/base/metrics/histogram_delta_serialization.cc b/base/metrics/histogram_delta_serialization.cc index a74b87f..7214c9af 100644 --- a/base/metrics/histogram_delta_serialization.cc +++ b/base/metrics/histogram_delta_serialization.cc
@@ -57,8 +57,8 @@ // static void HistogramDeltaSerialization::DeserializeAndAddSamples( const std::vector<std::string>& serialized_deltas) { - for (std::vector<std::string>::const_iterator it = serialized_deltas.begin(); - it != serialized_deltas.end(); ++it) { + for (auto it = serialized_deltas.begin(); it != serialized_deltas.end(); + ++it) { Pickle pickle(it->data(), checked_cast<int>(it->size())); PickleIterator iter(pickle); DeserializeHistogramAndAddSamples(&iter);
diff --git a/base/metrics/sample_map.cc b/base/metrics/sample_map.cc index c6dce293..b441afa 100644 --- a/base/metrics/sample_map.cc +++ b/base/metrics/sample_map.cc
@@ -91,7 +91,7 @@ } Count SampleMap::GetCount(Sample value) const { - std::map<Sample, Count>::const_iterator it = sample_counts_.find(value); + auto it = sample_counts_.find(value); if (it == sample_counts_.end()) return 0; return it->second;
diff --git a/base/observer_list_threadsafe_unittest.cc b/base/observer_list_threadsafe_unittest.cc index 9920aab..4983d7c 100644 --- a/base/observer_list_threadsafe_unittest.cc +++ b/base/observer_list_threadsafe_unittest.cc
@@ -286,7 +286,7 @@ void Observe(int x) override { std::vector<Foo*> tmp; tmp.swap(foos_); - for (std::vector<Foo*>::iterator it = tmp.begin(); it != tmp.end(); ++it) { + for (auto it = tmp.begin(); it != tmp.end(); ++it) { list_->RemoveObserver(*it); } }
diff --git a/base/path_service.cc b/base/path_service.cc index 6ac501eaf..cc29cab 100644 --- a/base/path_service.cc +++ b/base/path_service.cc
@@ -148,7 +148,7 @@ if (path_data->cache_disabled) return false; // check for a cached version - PathMap::const_iterator it = path_data->cache.find(key); + auto it = path_data->cache.find(key); if (it != path_data->cache.end()) { *result = it->second; return true;
diff --git a/base/posix/global_descriptors.cc b/base/posix/global_descriptors.cc index 738d14e3..c198899 100644 --- a/base/posix/global_descriptors.cc +++ b/base/posix/global_descriptors.cc
@@ -38,8 +38,7 @@ } int GlobalDescriptors::MaybeGet(Key key) const { - for (Mapping::const_iterator - i = descriptors_.begin(); i != descriptors_.end(); ++i) { + for (auto i = descriptors_.begin(); i != descriptors_.end(); ++i) { if (i->key == key) return i->fd; } @@ -51,8 +50,7 @@ Key key, base::MemoryMappedFile::Region* region) { base::ScopedFD fd; - for (Mapping::iterator i = descriptors_.begin(); i != descriptors_.end(); - ++i) { + for (auto i = descriptors_.begin(); i != descriptors_.end(); ++i) { if (i->key == key) { *region = i->region; fd.reset(i->fd);
diff --git a/base/profiler/stack_sampling_profiler_unittest.cc b/base/profiler/stack_sampling_profiler_unittest.cc index 2bace768ec..793241d 100644 --- a/base/profiler/stack_sampling_profiler_unittest.cc +++ b/base/profiler/stack_sampling_profiler_unittest.cc
@@ -651,7 +651,7 @@ // Check that the stack contains a frame for // TargetThread::SignalAndWaitUntilSignaled(). - Frames::const_iterator end_frame = FindFirstFrameWithinFunction( + auto end_frame = FindFirstFrameWithinFunction( frames, &TargetThread::SignalAndWaitUntilSignaled); ASSERT_TRUE(end_frame != frames.end()) << "Function at " @@ -684,7 +684,7 @@ // Check that the stack contains a frame for // TargetThread::CallThroughOtherLibrary(). - Frames::const_iterator other_library_frame = FindFirstFrameWithinFunction( + auto other_library_frame = FindFirstFrameWithinFunction( frames, &TargetThread::CallThroughOtherLibrary); ASSERT_TRUE(other_library_frame != frames.end()) << "Function at " @@ -753,7 +753,7 @@ // Check that the stack contains a frame for // TargetThread::SignalAndWaitUntilSignaled(). - Frames::const_iterator loc = FindFirstFrameWithinFunction( + auto loc = FindFirstFrameWithinFunction( frames, &TargetThread::SignalAndWaitUntilSignaled); ASSERT_TRUE(loc != frames.end()) << "Function at " @@ -800,7 +800,7 @@ // Check that the stack contains a frame for // TargetThread::SignalAndWaitUntilSignaled(). - Frames::const_iterator end_frame = FindFirstFrameWithinFunction( + auto end_frame = FindFirstFrameWithinFunction( frames, &TargetThread::SignalAndWaitUntilSignaled); ASSERT_TRUE(end_frame != frames.end()) << "Function at " @@ -810,7 +810,7 @@ << FormatSampleForDiagnosticOutput(frames); // Check that the stack contains a frame for TargetThread::CallWithAlloca(). - Frames::const_iterator alloca_frame = + auto alloca_frame = FindFirstFrameWithinFunction(frames, &TargetThread::CallWithAlloca); ASSERT_TRUE(alloca_frame != frames.end()) << "Function at " @@ -1314,7 +1314,7 @@ // Check that the stack contains a frame for // TargetThread::CallThroughOtherLibrary(). - Frames::const_iterator other_library_frame = FindFirstFrameWithinFunction( + auto other_library_frame = FindFirstFrameWithinFunction( frames, &TargetThread::CallThroughOtherLibrary); ASSERT_TRUE(other_library_frame != frames.end()) << "Function at " @@ -1325,7 +1325,7 @@ // Check that the stack contains a frame for // TargetThread::SignalAndWaitUntilSignaled(). - Frames::const_iterator end_frame = FindFirstFrameWithinFunction( + auto end_frame = FindFirstFrameWithinFunction( frames, &TargetThread::SignalAndWaitUntilSignaled); ASSERT_TRUE(end_frame != frames.end()) << "Function at "
diff --git a/base/strings/utf_offset_string_conversions.cc b/base/strings/utf_offset_string_conversions.cc index b91ee03..2875663 100644 --- a/base/strings/utf_offset_string_conversions.cc +++ b/base/strings/utf_offset_string_conversions.cc
@@ -28,7 +28,7 @@ std::vector<size_t>* offsets_for_adjustment, size_t limit) { DCHECK(offsets_for_adjustment); - for (std::vector<size_t>::iterator i(offsets_for_adjustment->begin()); + for (auto i(offsets_for_adjustment->begin()); i != offsets_for_adjustment->end(); ++i) AdjustOffset(adjustments, &(*i), limit); } @@ -41,8 +41,7 @@ if (*offset == string16::npos) return; int adjustment = 0; - for (Adjustments::const_iterator i = adjustments.begin(); - i != adjustments.end(); ++i) { + for (auto i = adjustments.begin(); i != adjustments.end(); ++i) { if (*offset <= i->original_offset) break; if (*offset < (i->original_offset + i->original_length)) { @@ -63,7 +62,7 @@ std::vector<size_t>* offsets_for_unadjustment) { if (!offsets_for_unadjustment || adjustments.empty()) return; - for (std::vector<size_t>::iterator i(offsets_for_unadjustment->begin()); + for (auto i(offsets_for_unadjustment->begin()); i != offsets_for_unadjustment->end(); ++i) UnadjustOffset(adjustments, &(*i)); } @@ -74,8 +73,7 @@ if (*offset == string16::npos) return; int adjustment = 0; - for (Adjustments::const_iterator i = adjustments.begin(); - i != adjustments.end(); ++i) { + for (auto i = adjustments.begin(); i != adjustments.end(); ++i) { if (*offset + adjustment <= i->original_offset) break; adjustment += static_cast<int>(i->original_length - i->output_length); @@ -92,8 +90,8 @@ void OffsetAdjuster::MergeSequentialAdjustments( const Adjustments& first_adjustments, Adjustments* adjustments_on_adjusted_string) { - Adjustments::iterator adjusted_iter = adjustments_on_adjusted_string->begin(); - Adjustments::const_iterator first_iter = first_adjustments.begin(); + auto adjusted_iter = adjustments_on_adjusted_string->begin(); + auto first_iter = first_adjustments.begin(); // Simultaneously iterate over all |adjustments_on_adjusted_string| and // |first_adjustments|, adding adjustments to or correcting the adjustments // in |adjustments_on_adjusted_string| as we go. |shift| keeps track of the
diff --git a/base/strings/utf_offset_string_conversions_unittest.cc b/base/strings/utf_offset_string_conversions_unittest.cc index c5ce647..ed43348 100644 --- a/base/strings/utf_offset_string_conversions_unittest.cc +++ b/base/strings/utf_offset_string_conversions_unittest.cc
@@ -86,8 +86,7 @@ OffsetAdjuster::AdjustOffset(kNoAdjustments, &size_ts.back(), kLimit); } size_t unlimited_count = 0; - for (std::vector<size_t>::iterator ti = size_ts.begin(); ti != size_ts.end(); - ++ti) { + for (auto ti = size_ts.begin(); ti != size_ts.end(); ++ti) { if (*ti != kNpos) ++unlimited_count; } @@ -100,8 +99,7 @@ OffsetAdjuster::AdjustOffset(kNoAdjustments, &size_ts.back(), kLimit); } unlimited_count = 0; - for (std::vector<size_t>::iterator ti = size_ts.begin(); ti != size_ts.end(); - ++ti) { + for (auto ti = size_ts.begin(); ti != size_ts.end(); ++ti) { if (*ti != kNpos) ++unlimited_count; }
diff --git a/base/supports_user_data.cc b/base/supports_user_data.cc index 43ab21a..2eb93f4 100644 --- a/base/supports_user_data.cc +++ b/base/supports_user_data.cc
@@ -16,7 +16,7 @@ DCHECK(sequence_checker_.CalledOnValidSequence()); // Avoid null keys; they are too vulnerable to collision. DCHECK(key); - DataMap::const_iterator found = user_data_.find(key); + auto found = user_data_.find(key); if (found != user_data_.end()) return found->second.get(); return nullptr;
diff --git a/base/synchronization/waitable_event_posix.cc b/base/synchronization/waitable_event_posix.cc index fc382c0..e5d58034 100644 --- a/base/synchronization/waitable_event_posix.cc +++ b/base/synchronization/waitable_event_posix.cc
@@ -382,8 +382,7 @@ bool WaitableEvent::SignalAll() { bool signaled_at_least_one = false; - for (std::list<Waiter*>::iterator - i = kernel_->waiters_.begin(); i != kernel_->waiters_.end(); ++i) { + for (auto i = kernel_->waiters_.begin(); i != kernel_->waiters_.end(); ++i) { if ((*i)->Fire(this)) signaled_at_least_one = true; } @@ -420,8 +419,7 @@ // actually removed. Called with lock held. // ----------------------------------------------------------------------------- bool WaitableEvent::WaitableEventKernel::Dequeue(Waiter* waiter, void* tag) { - for (std::list<Waiter*>::iterator - i = waiters_.begin(); i != waiters_.end(); ++i) { + for (auto i = waiters_.begin(); i != waiters_.end(); ++i) { if (*i == waiter && (*i)->Compare(tag)) { waiters_.erase(i); return true;
diff --git a/base/test/gtest_util.cc b/base/test/gtest_util.cc index e5d38f4..4905e566 100644 --- a/base/test/gtest_util.cc +++ b/base/test/gtest_util.cc
@@ -82,7 +82,7 @@ return false; std::vector<base::TestIdentifier> result; - for (base::ListValue::iterator i = tests->begin(); i != tests->end(); ++i) { + for (auto i = tests->begin(); i != tests->end(); ++i) { base::DictionaryValue* test = nullptr; if (!i->GetAsDictionary(&test)) return false;
diff --git a/base/test/launcher/test_results_tracker.cc b/base/test/launcher/test_results_tracker.cc index a7e590c..94343a4 100644 --- a/base/test/launcher/test_results_tracker.cc +++ b/base/test/launcher/test_results_tracker.cc
@@ -337,10 +337,8 @@ std::unique_ptr<DictionaryValue> current_iteration_data( new DictionaryValue); - for (PerIterationData::ResultsMap::const_iterator j = - per_iteration_data_[i].results.begin(); - j != per_iteration_data_[i].results.end(); - ++j) { + for (auto j = per_iteration_data_[i].results.begin(); + j != per_iteration_data_[i].results.end(); ++j) { std::unique_ptr<ListValue> test_results(new ListValue); for (size_t k = 0; k < j->second.test_results.size(); k++) { @@ -488,10 +486,8 @@ void TestResultsTracker::GetTestStatusForIteration( int iteration, TestStatusMap* map) const { - for (PerIterationData::ResultsMap::const_iterator j = - per_iteration_data_[iteration].results.begin(); - j != per_iteration_data_[iteration].results.end(); - ++j) { + for (auto j = per_iteration_data_[iteration].results.begin(); + j != per_iteration_data_[iteration].results.end(); ++j) { // Use the last test result as the final one. const TestResult& result = j->second.test_results.back(); (*map)[result.status].insert(result.full_name);
diff --git a/base/test/metrics/user_action_tester.cc b/base/test/metrics/user_action_tester.cc index a845bca7..29fee46 100644 --- a/base/test/metrics/user_action_tester.cc +++ b/base/test/metrics/user_action_tester.cc
@@ -23,7 +23,7 @@ } int UserActionTester::GetActionCount(const std::string& user_action) const { - UserActionCountMap::const_iterator iter = count_map_.find(user_action); + auto iter = count_map_.find(user_action); return iter == count_map_.end() ? 0 : iter->second; }
diff --git a/base/test/scoped_feature_list.cc b/base/test/scoped_feature_list.cc index 5b3b2f65..94ec16a3 100644 --- a/base/test/scoped_feature_list.cc +++ b/base/test/scoped_feature_list.cc
@@ -182,8 +182,7 @@ // Add the field trial overrides. This assumes that |enabled_features| are at // the begining of |merged_features.enabled_feature_list|, in the same order. - std::vector<FieldTrial*>::const_iterator trial_it = - trials_for_enabled_features.begin(); + auto trial_it = trials_for_enabled_features.begin(); auto feature_it = merged_features.enabled_feature_list.begin(); std::vector<std::unique_ptr<std::string>> features_with_trial; features_with_trial.reserve(trials_for_enabled_features.size());
diff --git a/base/test/trace_event_analyzer.cc b/base/test/trace_event_analyzer.cc index 4eafa0d2..5ff93b4 100644 --- a/base/test/trace_event_analyzer.cc +++ b/base/test/trace_event_analyzer.cc
@@ -531,8 +531,7 @@ case OTHER_ARG: case PREV_ARG: { // Search for the argument name and return its value if found. - std::map<std::string, double>::const_iterator num_i = - the_event->arg_numbers.find(string_); + auto num_i = the_event->arg_numbers.find(string_); if (num_i == the_event->arg_numbers.end()) return false; *num = num_i->second; @@ -582,8 +581,7 @@ case OTHER_ARG: case PREV_ARG: { // Search for the argument name and return its value if found. - std::map<std::string, std::string>::const_iterator str_i = - the_event->arg_strings.find(string_); + auto str_i = the_event->arg_strings.find(string_); if (str_i == the_event->arg_strings.end()) return false; *str = str_i->second;
diff --git a/base/threading/thread_id_name_manager.cc b/base/threading/thread_id_name_manager.cc index ca1979d..a0ced2c5 100644 --- a/base/threading/thread_id_name_manager.cc +++ b/base/threading/thread_id_name_manager.cc
@@ -63,7 +63,7 @@ std::string* leaked_str = nullptr; { AutoLock locked(lock_); - NameToInternedNameMap::iterator iter = name_to_interned_name_.find(name); + auto iter = name_to_interned_name_.find(name); if (iter != name_to_interned_name_.end()) { leaked_str = iter->second; } else { @@ -71,8 +71,7 @@ name_to_interned_name_[name] = leaked_str; } - ThreadIdToHandleMap::iterator id_to_handle_iter = - thread_id_to_handle_.find(id); + auto id_to_handle_iter = thread_id_to_handle_.find(id); GetThreadNameTLS().Set(const_cast<char*>(leaked_str->c_str())); if (set_name_callback_) { @@ -104,12 +103,11 @@ if (id == main_process_id_) return main_process_name_->c_str(); - ThreadIdToHandleMap::iterator id_to_handle_iter = - thread_id_to_handle_.find(id); + auto id_to_handle_iter = thread_id_to_handle_.find(id); if (id_to_handle_iter == thread_id_to_handle_.end()) return name_to_interned_name_[kDefaultName]->c_str(); - ThreadHandleToInternedNameMap::iterator handle_to_name_iter = + auto handle_to_name_iter = thread_handle_to_interned_name_.find(id_to_handle_iter->second); return handle_to_name_iter->second->c_str(); } @@ -122,14 +120,12 @@ void ThreadIdNameManager::RemoveName(PlatformThreadHandle::Handle handle, PlatformThreadId id) { AutoLock locked(lock_); - ThreadHandleToInternedNameMap::iterator handle_to_name_iter = - thread_handle_to_interned_name_.find(handle); + auto handle_to_name_iter = thread_handle_to_interned_name_.find(handle); DCHECK(handle_to_name_iter != thread_handle_to_interned_name_.end()); thread_handle_to_interned_name_.erase(handle_to_name_iter); - ThreadIdToHandleMap::iterator id_to_handle_iter = - thread_id_to_handle_.find(id); + auto id_to_handle_iter = thread_id_to_handle_.find(id); DCHECK((id_to_handle_iter!= thread_id_to_handle_.end())); // The given |id| may have been re-used by the system. Make sure the // mapping points to the provided |handle| before removal.
diff --git a/base/trace_event/trace_log.cc b/base/trace_event/trace_log.cc index f3d42a2e..071a145 100644 --- a/base/trace_event/trace_log.cc +++ b/base/trace_event/trace_log.cc
@@ -1052,8 +1052,7 @@ "If this happens stably for some thread, please call " "TraceLog::GetInstance()->SetCurrentThreadBlocksMessageLoop() from " "the thread to avoid its trace events from being lost."; - for (hash_set<MessageLoop*>::const_iterator it = - thread_message_loops_.begin(); + for (auto it = thread_message_loops_.begin(); it != thread_message_loops_.end(); ++it) { LOG(WARNING) << "Thread: " << (*it)->GetThreadName(); }
diff --git a/base/vlog.cc b/base/vlog.cc index fbe1897..9100d4ff 100644 --- a/base/vlog.cc +++ b/base/vlog.cc
@@ -105,8 +105,7 @@ int VlogInfo::GetVlogLevel(const base::StringPiece& file) const { if (!vmodule_levels_.empty()) { base::StringPiece module(GetModule(file)); - for (std::vector<VmodulePattern>::const_iterator it = - vmodule_levels_.begin(); it != vmodule_levels_.end(); ++it) { + for (auto it = vmodule_levels_.begin(); it != vmodule_levels_.end(); ++it) { base::StringPiece target( (it->match_target == VmodulePattern::MATCH_FILE) ? file : module); if (MatchVlogPattern(target, it->pattern))
diff --git a/blink/tools/run_layout_tests.py b/blink/tools/run_layout_tests.py index 1d216fb..33cc6965 100755 --- a/blink/tools/run_layout_tests.py +++ b/blink/tools/run_layout_tests.py
@@ -5,18 +5,10 @@ """Wrapper around third_party/blink/tools/run_web_tests.py""" -import os -import subprocess + import sys -def main(): +if __name__ == '__main__': print '\n Please use third_party/blink/tools/run_web_tests.*. ' \ 'This command will be removed.\n' - src_dir = os.path.abspath(os.path.join(sys.path[0], '..', '..')) - script_dir=os.path.join(src_dir, "third_party", "blink", "tools") - script = os.path.join(script_dir, 'run_web_tests.py') - cmd = [sys.executable, script] + sys.argv[1:] - return subprocess.call(cmd) - -if __name__ == '__main__': - sys.exit(main()) + sys.exit(1)
diff --git a/build/check_gn_headers_whitelist.txt b/build/check_gn_headers_whitelist.txt index b31f96d..38e6257 100644 --- a/build/check_gn_headers_whitelist.txt +++ b/build/check_gn_headers_whitelist.txt
@@ -157,7 +157,6 @@ gpu/command_buffer/service/gl_stream_texture_image.h gpu/command_buffer/service/gles2_cmd_decoder_unittest_extensions_autogen.h gpu/command_buffer/service/memory_tracking.h -gpu/command_buffer/service/progress_reporter.h gpu/config/gpu_lists_version.h gpu/gles2_conform_support/gtf/gtf_stubs.h gpu/gpu_export.h @@ -360,5 +359,6 @@ ui/gl/gl_bindings_api_autogen_glx.h ui/gl/gpu_preference.h ui/gl/gpu_switching_observer.h +ui/gl/progress_reporter.h ui/ozone/ozone_base_export.h ui/ozone/public/ozone_switches.h
diff --git a/cc/base/list_container_unittest.cc b/cc/base/list_container_unittest.cc index c58597b..e1da298 100644 --- a/cc/base/list_container_unittest.cc +++ b/cc/base/list_container_unittest.cc
@@ -572,9 +572,8 @@ { ListContainer<NonDerivedElement>::ReverseIterator iter = list.rbegin(); - for (std::vector<NonDerivedElement*>::reverse_iterator nde_iter = - nde_list.rbegin(); - nde_iter != nde_list.rend(); ++nde_iter) { + for (auto nde_iter = nde_list.rbegin(); nde_iter != nde_list.rend(); + ++nde_iter) { EXPECT_EQ(*nde_iter, *iter); ++iter; }
diff --git a/cc/base/rolling_time_delta_history.cc b/cc/base/rolling_time_delta_history.cc index a79722cc..dde20a7 100644 --- a/cc/base/rolling_time_delta_history.cc +++ b/cc/base/rolling_time_delta_history.cc
@@ -24,7 +24,7 @@ chronological_sample_deque_.pop_front(); } - TimeDeltaMultiset::iterator it = sample_set_.insert(time); + auto it = sample_set_.insert(time); chronological_sample_deque_.push_back(it); percentile_cache_.clear(); } @@ -63,13 +63,13 @@ if (num_smaller_samples > sample_set_.size() / 2) { size_t num_larger_samples = sample_set_.size() - num_smaller_samples - 1; - TimeDeltaMultiset::const_reverse_iterator it = sample_set_.rbegin(); + auto it = sample_set_.rbegin(); for (size_t i = 0; i < num_larger_samples; i++) it++; return *it; } - TimeDeltaMultiset::const_iterator it = sample_set_.begin(); + auto it = sample_set_.begin(); for (size_t i = 0; i < num_smaller_samples; i++) it++; return *it;
diff --git a/cc/layers/layer.cc b/cc/layers/layer.cc index 01c693ac..5019dff 100644 --- a/cc/layers/layer.cc +++ b/cc/layers/layer.cc
@@ -245,8 +245,8 @@ return; } - for (LayerList::iterator iter = inputs_.children.begin(); - iter != inputs_.children.end(); ++iter) { + for (auto iter = inputs_.children.begin(); iter != inputs_.children.end(); + ++iter) { if (iter->get() != child) continue; @@ -1469,7 +1469,7 @@ void Layer::RemoveFromClipTree() { if (clip_children_.get()) { std::set<Layer*> copy = *clip_children_; - for (std::set<Layer*>::iterator it = copy.begin(); it != copy.end(); ++it) + for (auto it = copy.begin(); it != copy.end(); ++it) (*it)->SetClipParent(nullptr); }
diff --git a/cc/layers/picture_layer_impl_unittest.cc b/cc/layers/picture_layer_impl_unittest.cc index 542fefaa..00674d1 100644 --- a/cc/layers/picture_layer_impl_unittest.cc +++ b/cc/layers/picture_layer_impl_unittest.cc
@@ -3095,8 +3095,7 @@ std::vector<Tile*> high_res_tiles = pending_layer()->HighResTiling()->AllTilesForTesting(); - for (std::vector<Tile*>::iterator tile_it = high_res_tiles.begin(); - tile_it != high_res_tiles.end(); + for (auto tile_it = high_res_tiles.begin(); tile_it != high_res_tiles.end(); ++tile_it) { Tile* tile = *tile_it; TileDrawInfo& draw_info = tile->draw_info();
diff --git a/cc/layers/scrollbar_layer_unittest.cc b/cc/layers/scrollbar_layer_unittest.cc index 63ffe595..031d23cf 100644 --- a/cc/layers/scrollbar_layer_unittest.cc +++ b/cc/layers/scrollbar_layer_unittest.cc
@@ -62,7 +62,7 @@ // Deletes a UI resource. May safely be called more than once. void DeleteUIResource(UIResourceId id) override { - UIResourceBitmapMap::iterator iter = ui_resource_bitmap_map_.find(id); + auto iter = ui_resource_bitmap_map_.find(id); if (iter != ui_resource_bitmap_map_.end()) { ui_resource_bitmap_map_.erase(iter); total_ui_resource_deleted_++; @@ -74,14 +74,14 @@ int TotalUIResourceCreated() { return total_ui_resource_created_; } gfx::Size ui_resource_size(UIResourceId id) { - UIResourceBitmapMap::iterator iter = ui_resource_bitmap_map_.find(id); + auto iter = ui_resource_bitmap_map_.find(id); if (iter != ui_resource_bitmap_map_.end()) return iter->second.GetSize(); return gfx::Size(); } UIResourceBitmap* ui_resource_bitmap(UIResourceId id) { - UIResourceBitmapMap::iterator iter = ui_resource_bitmap_map_.find(id); + auto iter = ui_resource_bitmap_map_.find(id); if (iter != ui_resource_bitmap_map_.end()) return &iter->second; return nullptr;
diff --git a/cc/raster/raster_buffer_provider_perftest.cc b/cc/raster/raster_buffer_provider_perftest.cc index 69a2d47..bbdd6f5 100644 --- a/cc/raster/raster_buffer_provider_perftest.cc +++ b/cc/raster/raster_buffer_provider_perftest.cc
@@ -311,7 +311,7 @@ for (auto& decode_task : raster_task->dependencies()) { // Add decode task if it doesn't already exist in graph. - TaskGraph::Node::Vector::iterator decode_it = + auto decode_it = std::find_if(graph->nodes.begin(), graph->nodes.end(), [decode_task](const TaskGraph::Node& node) { return node.task == decode_task;
diff --git a/cc/raster/task_graph_work_queue.cc b/cc/raster/task_graph_work_queue.cc index 06b1f54..2d04f52 100644 --- a/cc/raster/task_graph_work_queue.cc +++ b/cc/raster/task_graph_work_queue.cc
@@ -80,11 +80,11 @@ } while (graph_->edges[current_index_].task != task_); // Now find the node for the dependent of this edge. - TaskGraph::Node::Vector::iterator it = std::find_if( - graph_->nodes.begin(), graph_->nodes.end(), - [this](const TaskGraph::Node& node) { - return node.task == graph_->edges[current_index_].dependent; - }); + auto it = std::find_if(graph_->nodes.begin(), graph_->nodes.end(), + [this](const TaskGraph::Node& node) { + return node.task == + graph_->edges[current_index_].dependent; + }); DCHECK(it != graph_->nodes.end()); current_node_ = &(*it); @@ -152,11 +152,11 @@ // Remove any old nodes that are associated with this task. The result is // that the old graph is left with all nodes not present in this graph, // which we use below to determine what tasks need to be canceled. - TaskGraph::Node::Vector::iterator old_it = std::find_if( - task_namespace.graph.nodes.begin(), task_namespace.graph.nodes.end(), - [&node](const TaskGraph::Node& other) { - return node.task == other.task; - }); + auto old_it = std::find_if(task_namespace.graph.nodes.begin(), + task_namespace.graph.nodes.end(), + [&node](const TaskGraph::Node& other) { + return node.task == other.task; + }); if (old_it != task_namespace.graph.nodes.end()) { std::swap(*old_it, task_namespace.graph.nodes.back()); // If old task is scheduled to run again and not yet started running, @@ -200,8 +200,7 @@ task_namespace.graph.Swap(graph); // Determine what tasks in old graph need to be canceled. - for (TaskGraph::Node::Vector::iterator it = graph->nodes.begin(); - it != graph->nodes.end(); ++it) { + for (auto it = graph->nodes.begin(); it != graph->nodes.end(); ++it) { TaskGraph::Node& node = *it; // Skip if already finished running task. @@ -353,7 +352,7 @@ void TaskGraphWorkQueue::CollectCompletedTasks(NamespaceToken token, Task::Vector* completed_tasks) { - TaskNamespaceMap::iterator it = namespaces_.find(token); + auto it = namespaces_.find(token); if (it == namespaces_.end()) return;
diff --git a/cc/test/task_graph_runner_test_template.cc b/cc/test/task_graph_runner_test_template.cc index f201e932..2825c0e 100644 --- a/cc/test/task_graph_runner_test_template.cc +++ b/cc/test/task_graph_runner_test_template.cc
@@ -60,8 +60,7 @@ Task::Vector new_dependents; TaskGraph new_graph; - for (std::vector<TaskInfo>::const_iterator it = tasks.begin(); - it != tasks.end(); ++it) { + for (auto it = tasks.begin(); it != tasks.end(); ++it) { scoped_refptr<FakeTaskImpl> new_task( new FakeTaskImpl(this, it->namespace_index, it->id)); new_graph.nodes.push_back(
diff --git a/cc/tiles/picture_layer_tiling.cc b/cc/tiles/picture_layer_tiling.cc index 4901cdbf..13b5f93 100644 --- a/cc/tiles/picture_layer_tiling.cc +++ b/cc/tiles/picture_layer_tiling.cc
@@ -94,7 +94,7 @@ include_borders); iter; ++iter) { TileMapKey key(iter.index()); - TileMap::iterator find = tiles_.find(key); + auto find = tiles_.find(key); if (find != tiles_.end()) continue; @@ -552,7 +552,7 @@ } std::unique_ptr<Tile> PictureLayerTiling::TakeTileAt(int i, int j) { - TileMap::iterator found = tiles_.find(TileMapKey(i, j)); + auto found = tiles_.find(TileMapKey(i, j)); if (found == tiles_.end()) return nullptr; std::unique_ptr<Tile> result = std::move(found->second); @@ -976,7 +976,7 @@ size_t PictureLayerTiling::GPUMemoryUsageInBytes() const { size_t amount = 0; - for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) { + for (auto it = tiles_.begin(); it != tiles_.end(); ++it) { const Tile* tile = it->second.get(); amount += tile->GPUMemoryUsageInBytes(); }
diff --git a/cc/tiles/picture_layer_tiling_unittest.cc b/cc/tiles/picture_layer_tiling_unittest.cc index 7f46861a..7931cbb 100644 --- a/cc/tiles/picture_layer_tiling_unittest.cc +++ b/cc/tiles/picture_layer_tiling_unittest.cc
@@ -129,9 +129,7 @@ tiling_->SetLiveTilesRect(live_tiles_rect); std::vector<Tile*> tiles = tiling_->AllTilesForTesting(); - for (std::vector<Tile*>::iterator iter = tiles.begin(); - iter != tiles.end(); - ++iter) { + for (auto iter = tiles.begin(); iter != tiles.end(); ++iter) { EXPECT_TRUE(live_tiles_rect.Intersects((*iter)->content_rect())); } }
diff --git a/cc/tiles/tile_manager.cc b/cc/tiles/tile_manager.cc index 6761f8d6..7dc254a 100644 --- a/cc/tiles/tile_manager.cc +++ b/cc/tiles/tile_manager.cc
@@ -253,8 +253,7 @@ size_t dependencies = 0u; // Insert image decode tasks. - for (TileTask::Vector::const_iterator it = decode_tasks.begin(); - it != decode_tasks.end(); ++it) { + for (auto it = decode_tasks.begin(); it != decode_tasks.end(); ++it) { TileTask* decode_task = it->get(); // Skip if already decoded. @@ -264,11 +263,10 @@ dependencies++; // Add decode task if it doesn't already exist in graph. - TaskGraph::Node::Vector::iterator decode_it = - std::find_if(graph->nodes.begin(), graph->nodes.end(), - [decode_task](const TaskGraph::Node& node) { - return node.task == decode_task; - }); + auto decode_it = std::find_if(graph->nodes.begin(), graph->nodes.end(), + [decode_task](const TaskGraph::Node& node) { + return node.task == decode_task; + }); // In rare circumstances, a background category task may come in before a // foreground category task. In these cases, upgrade any background category
diff --git a/cc/trees/damage_tracker.cc b/cc/trees/damage_tracker.cc index 56f03bf..925069e0 100644 --- a/cc/trees/damage_tracker.cc +++ b/cc/trees/damage_tracker.cc
@@ -213,8 +213,8 @@ bool* layer_is_new) { LayerRectMapData data(layer_id); - SortedRectMapForLayers::iterator it = std::lower_bound( - rect_history_for_layers_.begin(), rect_history_for_layers_.end(), data); + auto it = std::lower_bound(rect_history_for_layers_.begin(), + rect_history_for_layers_.end(), data); if (it == rect_history_for_layers_.end() || it->layer_id_ != layer_id) { *layer_is_new = true; @@ -229,9 +229,8 @@ bool* surface_is_new) { SurfaceRectMapData data(surface_id); - SortedRectMapForSurfaces::iterator it = - std::lower_bound(rect_history_for_surfaces_.begin(), - rect_history_for_surfaces_.end(), data); + auto it = std::lower_bound(rect_history_for_surfaces_.begin(), + rect_history_for_surfaces_.end(), data); if (it == rect_history_for_surfaces_.end() || it->surface_id_ != surface_id) { *surface_is_new = true; @@ -271,12 +270,10 @@ // So, these regions are now exposed on the target surface. DamageAccumulator damage; - SortedRectMapForLayers::iterator layer_cur_pos = - rect_history_for_layers_.begin(); - SortedRectMapForLayers::iterator layer_copy_pos = layer_cur_pos; - SortedRectMapForSurfaces::iterator surface_cur_pos = - rect_history_for_surfaces_.begin(); - SortedRectMapForSurfaces::iterator surface_copy_pos = surface_cur_pos; + auto layer_cur_pos = rect_history_for_layers_.begin(); + auto layer_copy_pos = layer_cur_pos; + auto surface_cur_pos = rect_history_for_surfaces_.begin(); + auto surface_copy_pos = surface_cur_pos; // Loop below basically implements std::remove_if loop with and extra // processing (adding deleted rect to damage) for deleted items.
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index d5d6073..9952d74 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc
@@ -5397,8 +5397,7 @@ } void LayerTreeHostImpl::MarkUIResourceNotEvicted(UIResourceId uid) { - std::set<UIResourceId>::iterator found_in_evicted = - evicted_ui_resources_.find(uid); + auto found_in_evicted = evicted_ui_resources_.find(uid); if (found_in_evicted == evicted_ui_resources_.end()) return; evicted_ui_resources_.erase(found_in_evicted); @@ -5420,13 +5419,13 @@ } void LayerTreeHostImpl::NotifySwapPromiseMonitorsOfSetNeedsRedraw() { - std::set<SwapPromiseMonitor*>::iterator it = swap_promise_monitor_.begin(); + auto it = swap_promise_monitor_.begin(); for (; it != swap_promise_monitor_.end(); it++) (*it)->OnSetNeedsRedrawOnImpl(); } void LayerTreeHostImpl::NotifySwapPromiseMonitorsOfForwardingToMainThread() { - std::set<SwapPromiseMonitor*>::iterator it = swap_promise_monitor_.begin(); + auto it = swap_promise_monitor_.begin(); for (; it != swap_promise_monitor_.end(); it++) (*it)->OnForwardScrollUpdateToMainThreadOnImpl(); }
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc index 018455c..6054dd3 100644 --- a/cc/trees/layer_tree_impl.cc +++ b/cc/trees/layer_tree_impl.cc
@@ -1402,7 +1402,7 @@ } LayerImpl* LayerTreeImpl::LayerById(int id) const { - LayerImplMap::const_iterator iter = layer_id_map_.find(id); + auto iter = layer_id_map_.find(id); return iter != layer_id_map_.end() ? iter->second : nullptr; } @@ -1834,8 +1834,7 @@ } void LayerTreeImpl::UnregisterPictureLayerImpl(PictureLayerImpl* layer) { - std::vector<PictureLayerImpl*>::iterator it = - std::find(picture_layers_.begin(), picture_layers_.end(), layer); + auto it = std::find(picture_layers_.begin(), picture_layers_.end(), layer); DCHECK(it != picture_layers_.end()); picture_layers_.erase(it); }
diff --git a/cc/trees/property_tree.cc b/cc/trees/property_tree.cc index 99b15dd..c4fa5bc 100644 --- a/cc/trees/property_tree.cc +++ b/cc/trees/property_tree.cc
@@ -1436,7 +1436,7 @@ const gfx::ScrollOffset ScrollTree::current_scroll_offset(ElementId id) const { if (property_trees()->is_main_thread) { - ScrollOffsetMap::const_iterator it = scroll_offset_map_.find(id); + auto it = scroll_offset_map_.find(id); return it != scroll_offset_map_.end() ? it->second : gfx::ScrollOffset(); } return GetSyncedScrollOffset(id)
diff --git a/cc/trees/property_tree_builder.cc b/cc/trees/property_tree_builder.cc index 29f43d30..b55d165 100644 --- a/cc/trees/property_tree_builder.cc +++ b/cc/trees/property_tree_builder.cc
@@ -1404,7 +1404,7 @@ return; if (layer->clip_children()) { - for (std::set<Layer*>::iterator it = layer->clip_children()->begin(); + for (auto it = layer->clip_children()->begin(); it != layer->clip_children()->end(); ++it) { DCHECK_EQ((*it)->clip_parent(), layer); }
diff --git a/chrome/VERSION b/chrome/VERSION index 86eb119..dd8690c 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=71 MINOR=0 -BUILD=3569 +BUILD=3570 PATCH=0
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedJournalBridge.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedJournalBridge.java index 38e8b98..ed3d8d4 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedJournalBridge.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedJournalBridge.java
@@ -47,7 +47,7 @@ } /** Loads the journal and asynchronously returns the contents. */ - public void loadJournal(String journalName, Callback<String[]> successCallback, + public void loadJournal(String journalName, Callback<byte[][]> successCallback, Callback<Void> failureCallback) { assert mNativeFeedJournalBridge != 0; nativeLoadJournal(mNativeFeedJournalBridge, journalName, successCallback, failureCallback); @@ -67,8 +67,7 @@ switch (operation.getType()) { case Type.APPEND: Append append = (Append) operation; - nativeAddAppendOperation( - mNativeFeedJournalBridge, new String(append.getValue())); + nativeAddAppendOperation(mNativeFeedJournalBridge, append.getValue()); break; case Type.COPY: Copy copy = (Copy) operation; @@ -112,13 +111,13 @@ private native long nativeInit(Profile profile); private native void nativeDestroy(long nativeFeedJournalBridge); private native void nativeLoadJournal(long nativeFeedJournalBridge, String journalName, - Callback<String[]> successCallback, Callback<Void> failureCallback); + Callback<byte[][]> successCallback, Callback<Void> failureCallback); private native void nativeCommitJournalMutation( long nativeFeedJournalBridge, Callback<Boolean> callback); private native void nativeStartJournalMutation( long nativeFeedJournalBridge, String journalName); private native void nativeDeleteJournalMutation(long nativeFeedJournalBridge); - private native void nativeAddAppendOperation(long nativeFeedJournalBridge, String value); + private native void nativeAddAppendOperation(long nativeFeedJournalBridge, byte[] value); private native void nativeAddCopyOperation(long nativeFeedJournalBridge, String toJournalName); private native void nativeAddDeleteOperation(long nativeFeedJournalBridge); private native void nativeDoesJournalExist(long nativeFeedJournalBridge, String journalName,
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedJournalStorage.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedJournalStorage.java index ca2ab65..90bdd47 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedJournalStorage.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedJournalStorage.java
@@ -13,7 +13,6 @@ import org.chromium.base.VisibleForTesting; import org.chromium.chrome.browser.profiles.Profile; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -52,11 +51,8 @@ @Override public void read(String journalName, Consumer < Result < List<byte[]>>> consumer) { assert mFeedJournalBridge != null; - mFeedJournalBridge.loadJournal(journalName, (String[] entries) -> { - List<byte[]> journal = new ArrayList<byte[]>(); - for (String entry : entries) { - journal.add(entry.getBytes()); - } + mFeedJournalBridge.loadJournal(journalName, (byte[][] entries) -> { + List<byte[]> journal = Arrays.asList(entries); consumer.accept(Result.success(journal)); }, (Void ignored) -> consumer.accept(Result.failure())); }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/feed/FeedJournalStorageTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/feed/FeedJournalStorageTest.java index 2abbcc3..0a48b503 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/feed/FeedJournalStorageTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/feed/FeedJournalStorageTest.java
@@ -47,9 +47,9 @@ public static final String JOURNAL_KEY1 = "JOURNAL_KEY_1"; public static final String JOURNAL_KEY2 = "JOURNAL_KEY_2"; public static final String JOURNAL_KEY3 = "JOURNAL_KEY_3"; - public static final String JOURNAL_DATA1 = "JOURNAL_DATA_1"; - public static final String JOURNAL_DATA2 = "JOURNAL_DATA_2"; - public static final String JOURNAL_DATA3 = "JOURNAL_DATA_3"; + public static final byte[] JOURNAL_DATA1 = {24, -119, -10, -71, -35, 5}; + public static final byte[] JOURNAL_DATA2 = {8, 3, 18, 53, 70, 69, 65, 84, 85, 82, 69}; + public static final byte[] JOURNAL_DATA3 = {54, 55, 56, 48, 51, 57, 24, -119, -10}; @Mock private FeedJournalBridge mBridge; @@ -76,6 +76,8 @@ @Captor private ArgumentCaptor<Callback<Boolean>> mBooleanSuccessCallbackArgument; @Captor + private ArgumentCaptor<Callback<byte[][]>> mArrayOfByteArraySuccessCallbackArgument; + @Captor private ArgumentCaptor<Callback<String[]>> mStringArraySuccessCallbackArgument; @Captor private ArgumentCaptor<Callback<Void>> mFailureCallbackArgument; @@ -84,6 +86,16 @@ private FeedJournalStorage mJournalStorage; + private Answer<Void> createArrayOfByteArraySuccessAnswer(byte[][] arrayOfByteArray) { + return new Answer<Void>() { + @Override + public Void answer(InvocationOnMock invocation) { + mArrayOfByteArraySuccessCallbackArgument.getValue().onResult(arrayOfByteArray); + return null; + } + }; + } + private Answer<Void> createStringArraySuccessAnswer(String[] stringArray) { return new Answer<Void>() { @Override @@ -115,23 +127,21 @@ } private void verifyListOfBytesResult( - List<String> expectedList, boolean expectedSuccess, Result<List<byte[]>> actualResult) { - assertEquals(expectedSuccess, actualResult.isSuccessful()); - if (!expectedSuccess) return; - + List<byte[]> expectedList, Result<List<byte[]>> actualResult) { List<byte[]> actualList = actualResult.getValue(); assertEquals(expectedList.size(), actualList.size()); for (byte[] actualString : actualList) { - assertTrue(expectedList.contains(new String(actualString))); + boolean foundSame = false; + for (byte[] expectedBytes : expectedList) { + if (Arrays.equals(expectedBytes, actualString)) { + foundSame = true; + break; + } + } + assertTrue(foundSame); } } - private void verifyListOfBytesResult( - String[] expectedString, boolean expectedSuccess, Result<List<byte[]>> actualResult) { - List<String> expectedList = Arrays.asList(expectedString); - verifyListOfBytesResult(expectedList, expectedSuccess, actualResult); - } - private void verifyListOfStringResult( String[] expectedStrings, boolean expectedSuccess, Result<List<String>> actualResult) { assertEquals(expectedSuccess, actualResult.isSuccessful()); @@ -153,33 +163,40 @@ @Test @SmallTest public void readTest() { - String[] answerStrings = {JOURNAL_DATA1, JOURNAL_DATA2, JOURNAL_DATA3}; - Answer<Void> answer = createStringArraySuccessAnswer(answerStrings); + byte[][] answerStrings = {JOURNAL_DATA1, JOURNAL_DATA2, JOURNAL_DATA3}; + Answer<Void> answer = createArrayOfByteArraySuccessAnswer(answerStrings); doAnswer(answer).when(mBridge).loadJournal(mStringArgument.capture(), - mStringArraySuccessCallbackArgument.capture(), mFailureCallbackArgument.capture()); + mArrayOfByteArraySuccessCallbackArgument.capture(), + mFailureCallbackArgument.capture()); mJournalStorage.read(JOURNAL_KEY1, mListOfByteArrayConsumer); verify(mBridge, times(1)) - .loadJournal(eq(JOURNAL_KEY1), mStringArraySuccessCallbackArgument.capture(), + .loadJournal(eq(JOURNAL_KEY1), mArrayOfByteArraySuccessCallbackArgument.capture(), mFailureCallbackArgument.capture()); verify(mListOfByteArrayConsumer, times(1)).accept(mListOfByteArrayCaptor.capture()); - verifyListOfBytesResult(answerStrings, true, mListOfByteArrayCaptor.getValue()); + assertEquals(true, mListOfByteArrayCaptor.getValue().isSuccessful()); + List<byte[]> expectedStrings = new ArrayList<byte[]>(); + expectedStrings.add(JOURNAL_DATA1); + expectedStrings.add(JOURNAL_DATA2); + expectedStrings.add(JOURNAL_DATA3); + verifyListOfBytesResult(expectedStrings, mListOfByteArrayCaptor.getValue()); } @Test @SmallTest public void readFailureTest() { - String[] answerStrings = {}; + byte[][] answerStrings = {}; Answer<Void> answer = createFailureAnswer(); doAnswer(answer).when(mBridge).loadJournal(mStringArgument.capture(), - mStringArraySuccessCallbackArgument.capture(), mFailureCallbackArgument.capture()); + mArrayOfByteArraySuccessCallbackArgument.capture(), + mFailureCallbackArgument.capture()); mJournalStorage.read(JOURNAL_KEY1, mListOfByteArrayConsumer); verify(mBridge, times(1)) - .loadJournal(eq(JOURNAL_KEY1), mStringArraySuccessCallbackArgument.capture(), + .loadJournal(eq(JOURNAL_KEY1), mArrayOfByteArraySuccessCallbackArgument.capture(), mFailureCallbackArgument.capture()); verify(mListOfByteArrayConsumer, times(1)).accept(mListOfByteArrayCaptor.capture()); - verifyListOfBytesResult(answerStrings, false, mListOfByteArrayCaptor.getValue()); + assertEquals(false, mListOfByteArrayCaptor.getValue().isSuccessful()); } @Test @@ -267,7 +284,7 @@ mBooleanSuccessCallbackArgument.capture()); mJournalStorage.commit(new JournalMutation.Builder(JOURNAL_KEY1) - .append(JOURNAL_DATA1.getBytes()) + .append(JOURNAL_DATA1) .copy(JOURNAL_KEY2) .delete() .build(),
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt index 7ebaa62..7185093 100644 --- a/chrome/android/profiles/newest.txt +++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@ -chromeos-chrome-amd64-71.0.3568.0_rc-r1.afdo.bz2 \ No newline at end of file +chromeos-chrome-amd64-71.0.3569.0_rc-r1.afdo.bz2 \ No newline at end of file
diff --git a/chrome/android/webapk/shell_apk/AndroidManifest.xml b/chrome/android/webapk/shell_apk/AndroidManifest.xml index bcf9882..80109c4 100644 --- a/chrome/android/webapk/shell_apk/AndroidManifest.xml +++ b/chrome/android/webapk/shell_apk/AndroidManifest.xml
@@ -14,7 +14,7 @@ <uses-sdk android:minSdkVersion="16" - android:targetSdkVersion="26" /> + android:targetSdkVersion="28" /> <application android:icon="@mipmap/ic_launcher"
diff --git a/chrome/android/webapk/shell_apk/current_version/current_version.gni b/chrome/android/webapk/shell_apk/current_version/current_version.gni index a8d3cc18..2a9c781 100644 --- a/chrome/android/webapk/shell_apk/current_version/current_version.gni +++ b/chrome/android/webapk/shell_apk/current_version/current_version.gni
@@ -12,4 +12,4 @@ # //chrome/android/webapk/shell_apk:webapk is changed. This includes # Java files, Android resource files and AndroidManifest.xml. Does not affect # Chrome.apk -current_shell_apk_version = 59 +current_shell_apk_version = 60
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp index 25edda30..d3c12a2 100644 --- a/chrome/app/chromeos_strings.grdp +++ b/chrome/app/chromeos_strings.grdp
@@ -3559,16 +3559,16 @@ Google assistant logo </message> <message name="IDS_ASSISTANT_HOTWORD_TITLE" desc="Title for assistant hotword optin."> - Ok Google + "Ok Google" </message> <message name="IDS_ASSISTANT_HOTWORD_DESC" desc="Description for assistant hotword optin."> - Access your Assistant anytime you say "Ok Google" when your device is awake and unlocked. + Access your Assistant any time you say "Ok Google" when your screen is on </message> <message name="IDS_ASSISTANT_SCREEN_CONTEXT_TITLE" desc="Title for assistant screen context optin."> - Get info for what's on screen + Related info </message> <message name="IDS_ASSISTANT_SCREEN_CONTEXT_DESC" desc="Description for assistant screen context optin."> - See relevant suggestions from your Assistant related to what's on your screen. + Let the Assistant give suggestions based on what's on your screen </message> <message name="IDS_ASSISTANT_GET_MORE_SCREEN_TITLE" desc="Title for assistant get more screen."> Get the most out of your Assistant
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 7b7ace0f..5119aa2d 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -4428,6 +4428,11 @@ Stop using data on this page </message> + <!-- HTTPS Server Previews InfoBar --> + <message name="IDS_LITE_PAGE_PREVIEWS_MESSAGE" desc="The text of the infobar notifying the user that Chrome's Lite mode will now also apply to HTTPS pages."> + Lite Mode now makes browsing faster on all pages, including HTTPS. + </message> + <!-- WebRTC logs --> <message name="IDS_WEBRTC_LOGS_TITLE" desc="Title for the chrome://webrtc-logs page."> WebRTC logs
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp index 0528f78..a044b41 100644 --- a/chrome/app/settings_strings.grdp +++ b/chrome/app/settings_strings.grdp
@@ -2660,28 +2660,28 @@ Google Assistant </message> <message name="IDS_SETTINGS_GOOGLE_ASSISTANT_ENABLE_CONTEXT" desc="Title for a toggle that lets the assistant use whats on the screen."> - Let Assistant use what's on your screen + Related info </message> <message name="IDS_SETTINGS_GOOGLE_ASSISTANT_ENABLE_CONTEXT_DESCRIPTION" desc="Sub label for context-enable toggle."> - Enables the Assistant to show you related info, apps, and actions. + Let the Assistant give suggestions based on what's on your screen </message> <message name="IDS_SETTINGS_GOOGLE_ASSISTANT_ENABLE_HOTWORD" desc="Title for a toggle that lets the assistant detect hotword."> - "Ok Google" detection + "Ok Google" </message> <message name="IDS_SETTINGS_GOOGLE_ASSISTANT_ENABLE_HOTWORD_DESCRIPTION" desc="Sub label for hotword-enable toggle."> - Access your Assistant any time you say "Ok Google" when your screen is on. + Access your Assistant any time you say "Ok Google" when your screen is on </message> <message name="IDS_SETTINGS_GOOGLE_ASSISTANT_ENABLE_NOTIFICATION" desc="Title for a toggle that lets the assistant show you notifications."> - Let Assistant show you notifications + Notifications </message> <message name="IDS_SETTINGS_GOOGLE_ASSISTANT_ENABLE_NOTIFICATION_DESCRIPTION" desc="Sub label for notification-enable toggle."> - Enables the Assistant to show you notifications. + Allow the Assistant to show you notifications </message> <message name="IDS_SETTINGS_GOOGLE_ASSISTANT_LAUNCH_WITH_MIC_OPEN" desc="Title for a toggle that determines whether to open the microphone when launching the Assistant."> - Launch Assistant with microphone open + Voice activation </message> <message name="IDS_SETTINGS_GOOGLE_ASSISTANT_LAUNCH_WITH_MIC_OPEN_DESCRIPTION" desc="Sub label for launch-with-microphone-open toggle."> - Always launch the Assistant with microphone open. + Use speech instead of keyboard when you start your Assistant </message> <message name="IDS_SETTINGS_GOOGLE_ASSISTANT_SETTINGS" desc="Title for a button that opens the Google Assistant app settings."> Google Assistant settings
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index b9295e96..02f71b8 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -1209,6 +1209,8 @@ "previews/previews_infobar_delegate.h", "previews/previews_lite_page_decider.cc", "previews/previews_lite_page_decider.h", + "previews/previews_lite_page_infobar_delegate.cc", + "previews/previews_lite_page_infobar_delegate.h", "previews/previews_lite_page_navigation_throttle.cc", "previews/previews_lite_page_navigation_throttle.h", "previews/previews_lite_page_navigation_throttle_manager.h",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index ded4115..c4df5a7 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -1567,9 +1567,6 @@ {"enable-javascript-harmony", flag_descriptions::kJavascriptHarmonyName, flag_descriptions::kJavascriptHarmonyDescription, kOsAll, SINGLE_VALUE_TYPE(switches::kJavaScriptHarmony)}, - {"enable-asm-webassembly", flag_descriptions::kEnableAsmWasmName, - flag_descriptions::kEnableAsmWasmDescription, kOsAll, - FEATURE_VALUE_TYPE(features::kAsmJsToWebAssembly)}, {"enable-webassembly", flag_descriptions::kEnableWasmName, flag_descriptions::kEnableWasmDescription, kOsAll, FEATURE_VALUE_TYPE(features::kWebAssembly)}, @@ -1687,6 +1684,10 @@ flag_descriptions::kEnableNotificationScrollBarName, flag_descriptions::kEnableNotificationScrollBarDescription, kOsCrOS, FEATURE_VALUE_TYPE(ash::features::kNotificationScrollBar)}, + {"ash-enable-new-message-list-view", + flag_descriptions::kEnableNewMessageListViewName, + flag_descriptions::kEnableNewMessageListViewDescription, kOsCrOS, + FEATURE_VALUE_TYPE(ash::features::kNewMessageListView)}, {"allow-touchpad-three-finger-click", flag_descriptions::kAllowTouchpadThreeFingerClickName, flag_descriptions::kAllowTouchpadThreeFingerClickDescription, kOsCrOS,
diff --git a/chrome/browser/android/chrome_feature_list.cc b/chrome/browser/android/chrome_feature_list.cc index ff87f10..d077e77 100644 --- a/chrome/browser/android/chrome_feature_list.cc +++ b/chrome/browser/android/chrome_feature_list.cc
@@ -75,6 +75,7 @@ &kAndroidPayIntegrationV2, &kAndroidPaymentApps, &kAutofillAssistant, + &kCastDeviceFilter, &kCCTBackgroundTab, &kCCTExternalLinkHandling, &kCCTModule, @@ -201,6 +202,10 @@ const base::Feature kBackgroundTaskComponentUpdate{ "BackgroundTaskComponentUpdate", base::FEATURE_DISABLED_BY_DEFAULT}; +// Used in downstream code. +const base::Feature kCastDeviceFilter{"CastDeviceFilter", + base::FEATURE_DISABLED_BY_DEFAULT}; + const base::Feature kCCTBackgroundTab{"CCTBackgroundTab", base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/chrome/browser/android/chrome_feature_list.h b/chrome/browser/android/chrome_feature_list.h index 0d72c510..52d953c7 100644 --- a/chrome/browser/android/chrome_feature_list.h +++ b/chrome/browser/android/chrome_feature_list.h
@@ -18,6 +18,7 @@ extern const base::Feature kAndroidPaymentApps; extern const base::Feature kAutofillAssistant; extern const base::Feature kBackgroundTaskComponentUpdate; +extern const base::Feature kCastDeviceFilter; extern const base::Feature kCCTBackgroundTab; extern const base::Feature kCCTExternalLinkHandling; extern const base::Feature kCCTModule;
diff --git a/chrome/browser/android/download/download_media_parser.cc b/chrome/browser/android/download/download_media_parser.cc index 9bbbed9..78e6cd6 100644 --- a/chrome/browser/android/download/download_media_parser.cc +++ b/chrome/browser/android/download/download_media_parser.cc
@@ -229,8 +229,15 @@ void DownloadMediaParser::RenderVideoFrame( scoped_refptr<media::VideoFrame> video_frame) { + media::Context3D context; + gpu::ContextSupport* context_support = nullptr; auto context_provider = gpu_factories_ ? gpu_factories_->GetMediaContextProvider() : nullptr; + if (context_provider) { + context = media::Context3D(context_provider->ContextGL(), + context_provider->GrContext()); + context_support = context_provider->ContextSupport(); + } media::PaintCanvasVideoRenderer renderer; SkBitmap bitmap; @@ -239,11 +246,7 @@ // Draw the video frame to |bitmap|. cc::SkiaPaintCanvas canvas(bitmap); - media::Context3D context = - context_provider ? media::Context3D(context_provider->ContextGL(), - context_provider->GrContext()) - : media::Context3D(); - renderer.Copy(video_frame, &canvas, context); + renderer.Copy(video_frame, &canvas, context, context_support); NotifyComplete(std::move(bitmap)); }
diff --git a/chrome/browser/android/feed/feed_journal_bridge.cc b/chrome/browser/android/feed/feed_journal_bridge.cc index 5fc8d67..1c32417d 100644 --- a/chrome/browser/android/feed/feed_journal_bridge.cc +++ b/chrome/browser/android/feed/feed_journal_bridge.cc
@@ -26,10 +26,12 @@ namespace feed { using base::android::AttachCurrentThread; +using base::android::JavaByteArrayToByteVector; using base::android::JavaRef; using base::android::JavaParamRef; using base::android::ScopedJavaGlobalRef; using base::android::ScopedJavaLocalRef; +using base::android::ToJavaArrayOfByteArray; using base::android::ToJavaArrayOfStrings; namespace { @@ -40,14 +42,29 @@ bool success, std::vector<std::string> entries) { JNIEnv* env = AttachCurrentThread(); + + if (success) { + RunObjectCallbackAndroid(success_callback, + ToJavaArrayOfByteArray(env, entries)); + } else { + RunObjectCallbackAndroid(failure_callback, nullptr); + } +} + +void OnLoadJournalKeyDone( + base::android::ScopedJavaGlobalRef<jobject> success_callback, + base::android::ScopedJavaGlobalRef<jobject> failure_callback, + bool success, + std::vector<std::string> entries) { + JNIEnv* env = AttachCurrentThread(); ScopedJavaLocalRef<jobjectArray> j_entries = ToJavaArrayOfStrings(env, entries); - if (!success) { + if (success) { + RunObjectCallbackAndroid(success_callback, j_entries); + } else { RunObjectCallbackAndroid(failure_callback, nullptr); - return; } - RunObjectCallbackAndroid(success_callback, j_entries); } void OnStorageCheckExistingCallbackDone( @@ -55,11 +72,11 @@ ScopedJavaGlobalRef<jobject> failure_callback, bool success, bool exists) { - if (!success) { + if (success) { + RunBooleanCallbackAndroid(success_callback, exists); + } else { RunObjectCallbackAndroid(failure_callback, nullptr); - return; } - RunBooleanCallbackAndroid(success_callback, exists); } void OnStorageBooleanCallbackDone(ScopedJavaGlobalRef<jobject> callback, @@ -146,8 +163,8 @@ ScopedJavaGlobalRef<jobject> success_callback(j_success_callback); ScopedJavaGlobalRef<jobject> failure_callback(j_failure_callback); - feed_journal_database_->LoadAllJournalKeys( - base::BindOnce(&OnLoadJournalDone, success_callback, failure_callback)); + feed_journal_database_->LoadAllJournalKeys(base::BindOnce( + &OnLoadJournalKeyDone, success_callback, failure_callback)); } void FeedJournalBridge::DeleteAllJournals( @@ -180,10 +197,12 @@ void FeedJournalBridge::AddAppendOperation( JNIEnv* j_env, const base::android::JavaRef<jobject>& j_this, - const base::android::JavaRef<jstring>& j_value) { + const base::android::JavaRef<jbyteArray>& j_value) { DCHECK(journal_mutation_); - std::string value = ConvertJavaStringToUTF8(j_env, j_value); - journal_mutation_->AddAppendOperation(std::move(value)); + std::vector<uint8_t> bytes_vector; + JavaByteArrayToByteVector(j_env, j_value.obj(), &bytes_vector); + journal_mutation_->AddAppendOperation( + std::string(bytes_vector.begin(), bytes_vector.end())); } void FeedJournalBridge::AddCopyOperation(
diff --git a/chrome/browser/android/feed/feed_journal_bridge.h b/chrome/browser/android/feed/feed_journal_bridge.h index c7f4a26..e84fb40 100644 --- a/chrome/browser/android/feed/feed_journal_bridge.h +++ b/chrome/browser/android/feed/feed_journal_bridge.h
@@ -64,7 +64,7 @@ const base::android::JavaRef<jobject>& j_this); void AddAppendOperation(JNIEnv* j_env, const base::android::JavaRef<jobject>& j_this, - const base::android::JavaRef<jstring>& j_value); + const base::android::JavaRef<jbyteArray>& j_value); void AddCopyOperation( JNIEnv* j_env, const base::android::JavaRef<jobject>& j_this,
diff --git a/chrome/browser/android/vr/arcore_device/arcore_impl.cc b/chrome/browser/android/vr/arcore_device/arcore_impl.cc index cf9ba11..f645070fa 100644 --- a/chrome/browser/android/vr/arcore_device/arcore_impl.cc +++ b/chrome/browser/android/vr/arcore_device/arcore_impl.cc
@@ -251,8 +251,16 @@ ArHitResultList_getSize(arcore_session_.get(), arcore_hit_result_list.get(), &arcore_hit_result_list_size); - for (int i = 0; i < arcore_hit_result_list_size; i++) { + // Go through the list in reverse order so the first hit we encounter is the + // furthest. + // We will accept the furthest hit and then for the rest require that the hit + // be within the actual polygon detected by ArCore. This heuristic allows us + // to get better results on floors w/o overestimating the size of tables etc. + // See https://crbug.com/872855. + + for (int i = arcore_hit_result_list_size - 1; i >= 0; i--) { internal::ScopedArCoreObject<ArHitResult*> arcore_hit; + ArHitResult_create(arcore_session_.get(), arcore_hit.receive()); if (!arcore_hit.is_valid()) { DLOG(ERROR) << "ArHitResult_create failed!"; @@ -262,11 +270,48 @@ ArHitResultList_getItem(arcore_session_.get(), arcore_hit_result_list.get(), i, arcore_hit.get()); - mojom::XRHitResultPtr mojo_hit = mojom::XRHitResult::New(); - if (!ArHitResultToXRHitResult(arcore_hit.get(), mojo_hit.get())) { + internal::ScopedArCoreObject<ArTrackable*> ar_trackable; + + ArHitResult_acquireTrackable(arcore_session_.get(), arcore_hit.get(), + ar_trackable.receive()); + ArTrackableType ar_trackable_type = AR_TRACKABLE_NOT_VALID; + ArTrackable_getType(arcore_session_.get(), ar_trackable.get(), + &ar_trackable_type); + + // Only consider hits with plane trackables + // TODO(874985): make this configurable or re-evaluate this decision + if (AR_TRACKABLE_PLANE != ar_trackable_type) { + continue; + } + + internal::ScopedArCoreObject<ArPose*> arcore_pose; + ArPose_create(arcore_session_.get(), nullptr, arcore_pose.receive()); + if (!arcore_pose.is_valid()) { + DLOG(ERROR) << "ArPose_create failed!"; return false; } - hit_results->push_back(std::move(mojo_hit)); + + ArHitResult_getHitPose(arcore_session_.get(), arcore_hit.get(), + arcore_pose.get()); + + // After the first (furthest) hit, only return hits that are within the + // actual detected polygon and not just within than the larger plane. + if (!hit_results->empty()) { + int32_t in_polygon = 0; + ArPlane* ar_plane = ArAsPlane(ar_trackable.get()); + ArPlane_isPoseInPolygon(arcore_session_.get(), ar_plane, + arcore_pose.get(), &in_polygon); + if (!in_polygon) + continue; + } + + mojom::XRHitResultPtr mojo_hit = mojom::XRHitResult::New(); + mojo_hit.get()->hit_matrix.resize(16); + ArPose_getMatrix(arcore_session_.get(), arcore_pose.get(), + mojo_hit.get()->hit_matrix.data()); + + // Insert new results at head to preserver order from ArCore + hit_results->insert(hit_results->begin(), std::move(mojo_hit)); } return true; } @@ -325,26 +370,6 @@ return true; } -bool ARCoreImpl::ArHitResultToXRHitResult(ArHitResult* arcore_hit, - mojom::XRHitResult* hit_result) { - DCHECK(IsOnGlThread()); - DCHECK(arcore_session_.is_valid()); - DCHECK(arcore_frame_.is_valid()); - - internal::ScopedArCoreObject<ArPose*> arcore_pose; - ArPose_create(arcore_session_.get(), nullptr, arcore_pose.receive()); - if (!arcore_pose.is_valid()) { - DLOG(ERROR) << "ArPose_create failed!"; - return false; - } - ArHitResult_getHitPose(arcore_session_.get(), arcore_hit, arcore_pose.get()); - hit_result->hit_matrix.resize(16); - ArPose_getMatrix(arcore_session_.get(), arcore_pose.get(), - hit_result->hit_matrix.data()); - - return true; -} - bool ARCoreImpl::IsOnGlThread() { return gl_thread_task_runner_->BelongsToCurrentThread(); }
diff --git a/chrome/browser/android/vr/arcore_device/arcore_impl.h b/chrome/browser/android/vr/arcore_device/arcore_impl.h index 3aff1a7..e1ccc63 100644 --- a/chrome/browser/android/vr/arcore_device/arcore_impl.h +++ b/chrome/browser/android/vr/arcore_device/arcore_impl.h
@@ -89,9 +89,6 @@ const gfx::Size& image_size, gfx::PointF* screen_point); - bool ArHitResultToXRHitResult(ArHitResult* ar_hit, - mojom::XRHitResult* hit_result); - bool IsOnGlThread(); base::WeakPtr<ARCoreImpl> GetWeakPtr() { return weak_ptr_factory_.GetWeakPtr();
diff --git a/chrome/browser/android/vr/arcore_device/arcore_shim.cc b/chrome/browser/android/vr/arcore_device/arcore_shim.cc index 4dccc1e..38ab264 100644 --- a/chrome/browser/android/vr/arcore_device/arcore_shim.cc +++ b/chrome/browser/android/vr/arcore_device/arcore_shim.cc
@@ -42,6 +42,10 @@ CALL(ArSession_resume) \ CALL(ArSession_setCameraTextureName) \ CALL(ArSession_setDisplayGeometry) \ + CALL(ArHitResult_acquireTrackable) \ + CALL(ArTrackable_getType) \ + CALL(ArTrackable_release) \ + CALL(ArPlane_isPoseInPolygon) \ CALL(ArSession_update) #define CALL(fn) decltype(&fn) impl_##fn = nullptr; @@ -176,6 +180,31 @@ arcore_api->impl_ArHitResult_getHitPose(session, hit_result, out_pose); } +void ArHitResult_acquireTrackable(const ArSession* session, + const ArHitResult* hit_result, + ArTrackable** out_trackable) { + arcore_api->impl_ArHitResult_acquireTrackable(session, hit_result, + out_trackable); +} + +void ArTrackable_getType(const ArSession* session, + const ArTrackable* trackable, + ArTrackableType* out_trackable_type) { + arcore_api->impl_ArTrackable_getType(session, trackable, out_trackable_type); +} + +void ArPlane_isPoseInPolygon(const ArSession* session, + const ArPlane* plane, + const ArPose* pose, + int32_t* out_pose_in_polygon) { + arcore_api->impl_ArPlane_isPoseInPolygon(session, plane, pose, + out_pose_in_polygon); +} + +void ArTrackable_release(ArTrackable* trackable) { + arcore_api->impl_ArTrackable_release(trackable); +} + void ArHitResultList_create(const ArSession* session, ArHitResultList** out_hit_result_list) { arcore_api->impl_ArHitResultList_create(session, out_hit_result_list);
diff --git a/chrome/browser/app_controller_mac.mm b/chrome/browser/app_controller_mac.mm index 6c9658f..9564293 100644 --- a/chrome/browser/app_controller_mac.mm +++ b/chrome/browser/app_controller_mac.mm
@@ -1229,7 +1229,8 @@ SessionServiceFactory::GetForProfileForSessionRestore( [self lastProfile]); if (sessionService && - sessionService->RestoreIfNecessary(std::vector<GURL>())) + sessionService->RestoreIfNecessary( + *base::CommandLine::ForCurrentProcess(), std::vector<GURL>())) return NO; } }
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd index 1b84a87..858136db 100644 --- a/chrome/browser/browser_resources.grd +++ b/chrome/browser/browser_resources.grd
@@ -88,6 +88,7 @@ <structure name="IDR_NUX_SET_AS_DEFAULT_JS" file="resources\welcome\onboarding_welcome\set_as_default\nux_set_as_default.js" type="chrome_html" /> <structure name="IDR_NUX_SET_AS_DEFAULT_PROXY_HTML" file="resources\welcome\onboarding_welcome\set_as_default\nux_set_as_default_proxy.html" type="chrome_html" /> <structure name="IDR_NUX_SET_AS_DEFAULT_PROXY_JS" file="resources\welcome\onboarding_welcome\set_as_default\nux_set_as_default_proxy.js" type="chrome_html" /> + <structure name="IDR_NUX_CHOOSER_SHARED_CSS" file="resources\welcome\onboarding_welcome\shared\chooser_shared_css.html" type="chrome_html" /> </if> <if expr="is_win"> <structure name="IDR_WELCOME_WIN10_CSS" file="resources\welcome\welcome_win10.css" type="chrome_html" />
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc index 93496353..2fcd8a2 100644 --- a/chrome/browser/chrome_browser_main.cc +++ b/chrome/browser/chrome_browser_main.cc
@@ -346,8 +346,7 @@ #if !defined(OS_ANDROID) && !defined(OS_CHROMEOS) void AddFirstRunNewTabs(StartupBrowserCreator* browser_creator, const std::vector<GURL>& new_tabs) { - for (std::vector<GURL>::const_iterator it = new_tabs.begin(); - it != new_tabs.end(); ++it) { + for (auto it = new_tabs.begin(); it != new_tabs.end(); ++it) { if (it->is_valid()) browser_creator->AddFirstRunTab(*it); }
diff --git a/chrome/browser/chromeos/arc/input_method_manager/DEPS b/chrome/browser/chromeos/arc/input_method_manager/DEPS new file mode 100644 index 0000000..ec55aaa --- /dev/null +++ b/chrome/browser/chromeos/arc/input_method_manager/DEPS
@@ -0,0 +1,6 @@ +specific_include_rules = { + # TODO(mash): Fix this. https://crbug.com/890677 + "arc_input_method_manager_service\.cc": [ + "+ash/shell.h", + ], +}
diff --git a/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service.cc b/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service.cc index 98a450d..6fc830b 100644 --- a/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service.cc +++ b/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service.cc
@@ -7,6 +7,7 @@ #include <algorithm> #include <utility> +#include "ash/shell.h" #include "base/logging.h" #include "base/memory/singleton.h" #include "base/stl_util.h" @@ -97,7 +98,17 @@ ~ArcProxyInputMethodObserver() override = default; // input_method::InputMethodEngineBase::Observer overrides: - void OnActivate(const std::string& engine_id) override {} + void OnActivate(const std::string& engine_id) override { + // ash::Shell is not created in the unit tests. + if (!ash::Shell::HasInstance()) + return; + const bool was_enabled = keyboard::IsKeyboardEnabled(); + // Disable fallback virtual keyboard while Android IME is activated. + keyboard::SetKeyboardShowOverride( + keyboard::KEYBOARD_SHOW_OVERRIDE_DISABLED); + if (was_enabled) + ash::Shell::Get()->DisableKeyboard(); + } void OnFocus( const ui::IMEEngineHandlerInterface::InputContext& context) override { owner_->Focus(context.id); @@ -108,7 +119,18 @@ const input_method::InputMethodEngineBase::KeyboardEvent& event, ui::IMEEngineHandlerInterface::KeyEventDoneCallback key_data) override {} void OnReset(const std::string& engine_id) override {} - void OnDeactivated(const std::string& engine_id) override {} + void OnDeactivated(const std::string& engine_id) override { + // ash::Shell is not created in the unit tests. + if (!ash::Shell::HasInstance()) + return; + const bool was_enabled = keyboard::IsKeyboardEnabled(); + // Stop overriding virtual keyboard availability. + keyboard::SetKeyboardShowOverride(keyboard::KEYBOARD_SHOW_OVERRIDE_NONE); + // If the device is still in tablet mode, virtual keyboard may be enabled. + const bool is_enabled = keyboard::IsKeyboardEnabled(); + if (!was_enabled && is_enabled) + ash::Shell::Get()->EnableKeyboard(); + } void OnCompositionBoundsChanged( const std::vector<gfx::Rect>& bounds) override { owner_->UpdateTextInputState();
diff --git a/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service_unittest.cc b/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service_unittest.cc index 77907e18..7dd2fb9b 100644 --- a/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service_unittest.cc +++ b/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service_unittest.cc
@@ -9,6 +9,7 @@ #include <utility> #include <vector> +#include "ash/test/ash_test_base.h" #include "base/macros.h" #include "base/memory/scoped_refptr.h" #include "base/stl_util.h" @@ -31,6 +32,7 @@ #include "ui/base/ime/mock_ime_input_context_handler.h" #include "ui/base/ime/mock_input_method.h" #include "ui/keyboard/keyboard_controller.h" +#include "ui/keyboard/keyboard_util.h" namespace arc { namespace { @@ -200,7 +202,9 @@ DISALLOW_COPY_AND_ASSIGN(TestInputMethodManagerBridge); }; -class ArcInputMethodManagerServiceTest : public testing::Test { +// TODO(crbug.com/890677): Stop inheriting ash::AshTestBase once ash::Shell +// dependency is removed from ArcInputMethodManagerService. +class ArcInputMethodManagerServiceTest : public ash::AshTestBase { protected: ArcInputMethodManagerServiceTest() : arc_service_manager_(std::make_unique<ArcServiceManager>()) {} @@ -219,12 +223,13 @@ } void SetUp() override { + ash::AshTestBase::SetUp(); + SetRunningOutsideAsh(); ui::IMEBridge::Initialize(); input_method_manager_ = new TestInputMethodManager(); chromeos::input_method::InputMethodManager::Initialize( input_method_manager_); tablet_mode_client_ = std::make_unique<TabletModeClient>(); - keyboard_controller_ = std::make_unique<keyboard::KeyboardController>(); profile_ = std::make_unique<TestingProfile>(); service_ = ArcInputMethodManagerService::GetForBrowserContextForTesting( profile_.get()); @@ -237,18 +242,16 @@ test_bridge_ = nullptr; service_->Shutdown(); profile_.reset(nullptr); - keyboard_controller_.reset(nullptr); tablet_mode_client_.reset(nullptr); chromeos::input_method::InputMethodManager::Shutdown(); ui::IMEBridge::Shutdown(); + ash::AshTestBase::TearDown(); } private: - content::TestBrowserThreadBundle thread_bundle_; std::unique_ptr<ArcServiceManager> arc_service_manager_; std::unique_ptr<TestingProfile> profile_; std::unique_ptr<TabletModeClient> tablet_mode_client_; - std::unique_ptr<keyboard::KeyboardController> keyboard_controller_; TestInputMethodManager* input_method_manager_ = nullptr; TestInputMethodManagerBridge* test_bridge_ = nullptr; // Owned by |service_| @@ -783,4 +786,59 @@ ui::IMEBridge::Get()->SetInputContextHandler(nullptr); } +TEST_F(ArcInputMethodManagerServiceTest, DisableFallbackVirtualKeyboard) { + namespace ceiu = chromeos::extension_ime_util; + using crx_file::id_util::GenerateId; + + base::test::ScopedFeatureList feature; + feature.InitAndEnableFeature(kEnableInputMethodFeature); + ToggleTabletMode(true); + + // Adding one ARC IME. + { + const std::string android_ime_id = "test.arc.ime"; + const std::string display_name = "DisplayName"; + const std::string settings_url = "url_to_settings"; + mojom::ImeInfoPtr info = mojom::ImeInfo::New(); + info->ime_id = android_ime_id; + info->display_name = display_name; + info->enabled = false; + info->settings_url = settings_url; + + std::vector<mojom::ImeInfoPtr> info_array; + info_array.emplace_back(std::move(info)); + service()->OnImeInfoChanged(std::move(info_array)); + } + // The proxy IME engine should be added. + ASSERT_EQ(1u, imm()->state()->added_input_method_extensions_.size()); + ui::IMEEngineHandlerInterface* engine_handler = + std::get<2>(imm()->state()->added_input_method_extensions_.at(0)); + // Enable it + ui::IMEBridge::Get()->SetCurrentEngineHandler(engine_handler); + + const std::string extension_ime_id = + ceiu::GetInputMethodID(GenerateId("test.extension.ime"), "us"); + const std::string component_extension_ime_id = + ceiu::GetComponentInputMethodID( + GenerateId("test.component.extension.ime"), "us"); + + // Enable Chrome OS virtual keyboard + keyboard::SetTouchKeyboardEnabled(true); + keyboard::SetKeyboardShowOverride(keyboard::KEYBOARD_SHOW_OVERRIDE_NONE); + ASSERT_TRUE(keyboard::IsKeyboardEnabled()); + + // It's disabled when the ARC IME is activated. + ui::IMEBridge::Get()->SetCurrentEngineHandler(engine_handler); + engine_handler->Enable( + chromeos::extension_ime_util::GetComponentIDByInputMethodID( + std::get<1>(imm()->state()->added_input_method_extensions_.at(0)) + .at(0) + .id())); + EXPECT_FALSE(keyboard::IsKeyboardEnabled()); + + // It's re-enabled when the ARC IME is deactivated. + engine_handler->Disable(); + EXPECT_TRUE(keyboard::IsKeyboardEnabled()); +} + } // namespace arc
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_drive.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_drive.cc index f54eb7b..dffbd60 100644 --- a/chrome/browser/chromeos/extensions/file_manager/private_api_drive.cc +++ b/chrome/browser/chromeos/extensions/file_manager/private_api_drive.cc
@@ -707,6 +707,8 @@ if (metadata->type != drivefs::mojom::FileMetadata::Type::kDirectory) { properties_->thumbnail_url = std::make_unique<std::string>( base::StrCat({"drivefs:", file_system_url_.ToGURL().spec()})); + properties_->cropped_thumbnail_url = + std::make_unique<std::string>(*properties_->thumbnail_url); } CompleteGetEntryProperties(drive::FILE_ERROR_OK);
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc index 4e6d07a..57fecfd 100644 --- a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc +++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
@@ -180,6 +180,7 @@ TestCase("fileDisplayDrive"), TestCase("fileDisplayDrive").TabletMode(), TestCase("fileDisplayDrive").EnableDriveFs(), + TestCase("fileDisplayDrive").TabletMode().EnableDriveFs(), TestCase("fileDisplayDriveOffline").Offline().EnableDriveFs(), TestCase("fileDisplayDriveOnline").EnableDriveFs(), TestCase("fileDisplayDriveOnline"), @@ -323,6 +324,48 @@ TestCase("checkContextMenuForTeamDriveRoot"))); WRAPPED_INSTANTIATE_TEST_CASE_P( + ContextMenu2, /* context_menu.js */ + FilesAppBrowserTest, + ::testing::Values( + TestCase("checkDeleteEnabledForReadWriteFile").EnableDriveFs(), + TestCase("checkDeleteDisabledForReadOnlyDocument").EnableDriveFs(), + TestCase("checkDeleteDisabledForReadOnlyFile").EnableDriveFs(), + TestCase("checkDeleteDisabledForReadOnlyFolder").EnableDriveFs(), + TestCase("checkRenameEnabledForReadWriteFile").EnableDriveFs(), + TestCase("checkRenameDisabledForReadOnlyDocument").EnableDriveFs(), + TestCase("checkRenameDisabledForReadOnlyFile").EnableDriveFs(), + TestCase("checkRenameDisabledForReadOnlyFolder").EnableDriveFs(), + TestCase("checkShareEnabledForReadWriteFile").EnableDriveFs(), + TestCase("checkShareEnabledForReadOnlyDocument").EnableDriveFs(), + TestCase("checkShareDisabledForStrictReadOnlyDocument").EnableDriveFs(), + TestCase("checkShareEnabledForReadOnlyFile").EnableDriveFs(), + TestCase("checkShareEnabledForReadOnlyFolder").EnableDriveFs(), + TestCase("checkCopyEnabledForReadWriteFile").EnableDriveFs(), + TestCase("checkCopyEnabledForReadOnlyDocument").EnableDriveFs(), + TestCase("checkCopyDisabledForStrictReadOnlyDocument").EnableDriveFs(), + TestCase("checkCopyEnabledForReadOnlyFile").EnableDriveFs(), + TestCase("checkCopyEnabledForReadOnlyFolder").EnableDriveFs(), + TestCase("checkCutEnabledForReadWriteFile").EnableDriveFs(), + TestCase("checkCutDisabledForReadOnlyDocument").EnableDriveFs(), + TestCase("checkCutDisabledForReadOnlyFile").EnableDriveFs(), + TestCase("checkCutDisabledForReadOnlyFolder").EnableDriveFs(), + TestCase("checkPasteIntoFolderEnabledForReadWriteFolder") + .EnableDriveFs(), + TestCase("checkPasteIntoFolderDisabledForReadOnlyFolder") + .EnableDriveFs(), + TestCase("checkNewFolderEnabledInsideReadWriteFolder").EnableDriveFs(), + TestCase("checkNewFolderDisabledInsideReadOnlyFolder").EnableDriveFs(), + TestCase("checkPasteEnabledInsideReadWriteFolder").EnableDriveFs(), + TestCase("checkPasteDisabledInsideReadOnlyFolder").EnableDriveFs(), + TestCase("checkCopyEnabledForReadWriteFolderInTree").EnableDriveFs(), + TestCase("checkCopyEnabledForReadOnlyFolderInTree").EnableDriveFs(), + TestCase("checkCutEnabledForReadWriteFolderInTree").EnableDriveFs(), + TestCase("checkCutDisabledForReadOnlyFolderInTree").EnableDriveFs(), + TestCase("checkPasteEnabledForReadWriteFolderInTree").EnableDriveFs(), + TestCase("checkPasteDisabledForReadOnlyFolderInTree").EnableDriveFs(), + TestCase("checkContextMenuForTeamDriveRoot").EnableDriveFs())); + +WRAPPED_INSTANTIATE_TEST_CASE_P( Delete, /* delete.js */ FilesAppBrowserTest, ::testing::Values(TestCase("deleteMenuItemNoEntrySelected"), @@ -481,7 +524,9 @@ FolderShortcuts, /* folder_shortcuts.js */ FilesAppBrowserTest, ::testing::Values(TestCase("traverseFolderShortcuts"), - TestCase("addRemoveFolderShortcuts"))); + TestCase("traverseFolderShortcuts").EnableDriveFs(), + TestCase("addRemoveFolderShortcuts"), + TestCase("addRemoveFolderShortcuts").EnableDriveFs())); WRAPPED_INSTANTIATE_TEST_CASE_P( SortColumns, /* sort_columns.js */ @@ -627,8 +672,11 @@ FilesAppBrowserTest, ::testing::Values(TestCase("metadataDownloads"), TestCase("metadataDrive"), + TestCase("metadataDrive").EnableDriveFs(), TestCase("metadataTeamDrives"), - TestCase("metadataLargeDrive"))); + TestCase("metadataTeamDrives").EnableDriveFs(), + TestCase("metadataLargeDrive"), + TestCase("metadataLargeDrive").EnableDriveFs())); // Structure to describe an account info. struct TestAccountInfo {
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc index b3a7a0ef..995f237 100644 --- a/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc +++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc
@@ -856,7 +856,10 @@ base::FilePath(entry.target_path).BaseName().value(), entry.pinned, entry.shared_option == AddEntriesMessage::SharedOption::SHARED || entry.shared_option == - AddEntriesMessage::SharedOption::SHARED_WITH_ME); + AddEntriesMessage::SharedOption::SHARED_WITH_ME, + {entry.capabilities.can_share, entry.capabilities.can_copy, + entry.capabilities.can_delete, entry.capabilities.can_rename, + entry.capabilities.can_add_children}); switch (entry.type) { case AddEntriesMessage::FILE: { @@ -1401,7 +1404,8 @@ kPredefinedProfileSalt); drive_volumes_[profile->GetOriginalProfile()] = std::make_unique<DriveFsTestVolume>(profile->GetOriginalProfile()); - if (!IsIncognitoModeTest()) { + if (!IsIncognitoModeTest() && + profile->GetPath().BaseName().value() == "user") { base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(base::IgnoreResult(&LocalTestVolume::Mount),
diff --git a/chrome/browser/chromeos/policy/device_status_collector_browsertest.cc b/chrome/browser/chromeos/policy/device_status_collector_browsertest.cc index 772d2e6..e7ee855 100644 --- a/chrome/browser/chromeos/policy/device_status_collector_browsertest.cc +++ b/chrome/browser/chromeos/policy/device_status_collector_browsertest.cc
@@ -2418,8 +2418,9 @@ base::test::ScopedFeatureList scoped_feature_list_; }; +// Fails on all chromeos builders https://crbug.com/891573 TEST_F(ConsumerDeviceStatusCollectorTimeLimitEnabledTest, - ReportingActivityTimesSessionTransistions) { + DISABLED_ReportingActivityTimesSessionTransistions) { DeviceStateTransitions test_states[] = { DeviceStateTransitions::kEnterSessionActive, DeviceStateTransitions::kPeriodicCheckTriggered, @@ -2444,8 +2445,9 @@ device_status_.active_period(0).user_email()); } +// Fails on all chromeos builders https://crbug.com/891573 TEST_F(ConsumerDeviceStatusCollectorTimeLimitEnabledTest, - ReportingActivityTimesSleepTransistions) { + DISABLED_ReportingActivityTimesSleepTransistions) { DeviceStateTransitions test_states[] = { DeviceStateTransitions::kEnterSessionActive, DeviceStateTransitions::kPeriodicCheckTriggered, @@ -2469,8 +2471,9 @@ device_status_.active_period(0).user_email()); } +// Fails on all chromeos builders https://crbug.com/891573 TEST_F(ConsumerDeviceStatusCollectorTimeLimitEnabledTest, - ReportingActivityTimesIdleTransitions) { + DISABLED_ReportingActivityTimesIdleTransitions) { DeviceStateTransitions test_states[] = { DeviceStateTransitions::kEnterSessionActive, DeviceStateTransitions::kPeriodicCheckTriggered, @@ -2496,7 +2499,9 @@ device_status_.active_period(0).user_email()); } -TEST_F(ConsumerDeviceStatusCollectorTimeLimitEnabledTest, ActivityKeptInPref) { +// Fails on all chromeos builders https://crbug.com/891573 +TEST_F(ConsumerDeviceStatusCollectorTimeLimitEnabledTest, + DISABLED_ActivityKeptInPref) { EXPECT_TRUE( profile_pref_service_.GetDictionary(prefs::kUserActivityTimes)->empty()); @@ -2534,8 +2539,9 @@ profile_pref_service_.GetInteger(prefs::kChildScreenTimeMilliseconds)); } +// Fails on all chromeos builders https://crbug.com/891573 TEST_F(ConsumerDeviceStatusCollectorTimeLimitEnabledTest, - ActivityNotWrittenToLocalState) { + DISABLED_ActivityNotWrittenToLocalState) { EXPECT_TRUE(local_state_.GetDictionary(prefs::kDeviceActivityTimes)->empty()); DeviceStateTransitions test_states[] = {
diff --git a/chrome/browser/devtools/devtools_eye_dropper.h b/chrome/browser/devtools/devtools_eye_dropper.h index aaa87d2..5c0c293 100644 --- a/chrome/browser/devtools/devtools_eye_dropper.h +++ b/chrome/browser/devtools/devtools_eye_dropper.h
@@ -12,7 +12,6 @@ #include "components/viz/host/client_frame_sink_video_capturer.h" #include "content/public/browser/render_widget_host.h" #include "content/public/browser/web_contents_observer.h" -#include "media/renderers/paint_canvas_video_renderer.h" #include "third_party/skia/include/core/SkBitmap.h" namespace blink { @@ -59,7 +58,6 @@ content::RenderWidgetHost::MouseEventCallback mouse_event_callback_; content::RenderWidgetHost* host_; std::unique_ptr<viz::ClientFrameSinkVideoCapturer> video_capturer_; - media::PaintCanvasVideoRenderer video_renderer_; base::WeakPtrFactory<DevToolsEyeDropper> weak_factory_; DISALLOW_COPY_AND_ASSIGN(DevToolsEyeDropper);
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 52c173c..d3e0fe37 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -346,12 +346,6 @@ "Enables experimental support for Accessibility Object Model APIs " "that are in development."; -const char kEnableAsmWasmName[] = - "Experimental Validate Asm.js and convert to WebAssembly when valid."; -const char kEnableAsmWasmDescription[] = - R"*(Validate Asm.js when "use asm" is present and then convert to )*" - R"*(WebAssembly.)*"; - const char kEnableWebPaymentsSingleAppUiSkipName[] = "Enable Web Payments single app UI skip"; const char kEnableWebPaymentsSingleAppUiSkipDescription[] = @@ -643,6 +637,10 @@ const char kEnableNotificationScrollBarDescription[] = "Enable the scroll bar of the notification list in Unified System Tray."; +const char kEnableNewMessageListViewName[] = "Enable new message list view"; +const char kEnableNewMessageListViewDescription[] = + "Enable new implementation of message list view."; + const char kEnableNupPrintingName[] = "Enable N-up printing"; const char kEnableNupPrintingDescription[] = "Enable N-up printing in the print preview panel.";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 1cd3b69..5695b5f 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -243,9 +243,6 @@ extern const char kEnableAccessibilityObjectModelName[]; extern const char kEnableAccessibilityObjectModelDescription[]; -extern const char kEnableAsmWasmName[]; -extern const char kEnableAsmWasmDescription[]; - extern const char kEnableAutofillAccountWalletStorageName[]; extern const char kEnableAutofillAccountWalletStorageDescription[]; @@ -414,6 +411,9 @@ extern const char kEnableNotificationScrollBarName[]; extern const char kEnableNotificationScrollBarDescription[]; +extern const char kEnableNewMessageListViewName[]; +extern const char kEnableNewMessageListViewDescription[]; + extern const char kEnableNupPrintingName[]; extern const char kEnableNupPrintingDescription[];
diff --git a/chrome/browser/font_family_cache.cc b/chrome/browser/font_family_cache.cc index e273b0e..8002ffa 100644 --- a/chrome/browser/font_family_cache.cc +++ b/chrome/browser/font_family_cache.cc
@@ -78,7 +78,7 @@ const char* map_name) { FontFamilyMap::const_iterator it = font_family_map_.find(map_name); if (it != font_family_map_.end()) { - ScriptFontMap::const_iterator it2 = it->second.find(script); + auto it2 = it->second.find(script); if (it2 != it->second.end()) return it2->second; } @@ -100,7 +100,7 @@ continue; ScriptFontMap& map = it.second; - for (ScriptFontMap::iterator it2 = map.begin(); it2 != map.end(); ++it2) { + for (auto it2 = map.begin(); it2 != map.end(); ++it2) { const char* script = it2->first; size_t script_length = strlen(script);
diff --git a/chrome/browser/infobars/infobars_browsertest.cc b/chrome/browser/infobars/infobars_browsertest.cc index ac8c8b7..bcbf0e43 100644 --- a/chrome/browser/infobars/infobars_browsertest.cc +++ b/chrome/browser/infobars/infobars_browsertest.cc
@@ -29,6 +29,7 @@ #include "chrome/browser/plugins/plugin_observer.h" #include "chrome/browser/plugins/reload_plugin_infobar_delegate.h" #include "chrome/browser/previews/previews_infobar_delegate.h" +#include "chrome/browser/previews/previews_lite_page_infobar_delegate.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/themes/theme_service.h" #include "chrome/browser/themes/theme_service_factory.h" @@ -230,6 +231,7 @@ {"automation", IBD::AUTOMATION_INFOBAR_DELEGATE}, {"page_load_capping", IBD::PAGE_LOAD_CAPPING_INFOBAR_DELEGATE}, {"bloated_renderer", IBD::BLOATED_RENDERER_INFOBAR_DELEGATE}, + {"previews_lite_page", IBD::LITE_PAGE_PREVIEWS_INFOBAR}, }; auto id = kIdentifiers.find(name); expected_identifiers_.push_back((id == kIdentifiers.end()) ? IBD::INVALID @@ -416,6 +418,10 @@ BloatedRendererTabHelper::ShowInfoBar(GetInfoBarService()); break; + case IBD::LITE_PAGE_PREVIEWS_INFOBAR: + PreviewsLitePageInfoBarDelegate::Create(GetWebContents()); + break; + default: break; } @@ -584,6 +590,10 @@ ShowAndVerifyUi(); } +IN_PROC_BROWSER_TEST_F(InfoBarUiTest, InvokeUi_previews_lite_page) { + ShowAndVerifyUi(); +} + IN_PROC_BROWSER_TEST_F(InfoBarUiTest, InvokeUi_multiple_infobars) { ShowAndVerifyUi(); }
diff --git a/chrome/browser/internal_auth.cc b/chrome/browser/internal_auth.cc index 35552a5..cdbff42f7c 100644 --- a/chrome/browser/internal_auth.cc +++ b/chrome/browser/internal_auth.cc
@@ -128,7 +128,7 @@ bool IsVarValueMapSane(const VarValueMap& map) { if (map.size() > kVarsLimit) return false; - for (VarValueMap::const_iterator it = map.begin(); it != map.end(); ++it) { + for (auto it = map.begin(); it != map.end(); ++it) { const std::string& var = it->first; const std::string& value = it->second; if (!IsVarSane(var) || !IsValueSane(value)) @@ -140,7 +140,7 @@ void ConvertVarValueMapToBlob(const VarValueMap& map, std::string* out) { out->clear(); DCHECK(IsVarValueMapSane(map)); - for (VarValueMap::const_iterator it = map.begin(); it != map.end(); ++it) + for (auto it = map.begin(); it != map.end(); ++it) *out += it->first + kVarValueSeparator + it->second + kItemSeparator; }
diff --git a/chrome/browser/media/cast_remoting_connector.cc b/chrome/browser/media/cast_remoting_connector.cc index a632376..ba39f521 100644 --- a/chrome/browser/media/cast_remoting_connector.cc +++ b/chrome/browser/media/cast_remoting_connector.cc
@@ -25,8 +25,7 @@ #include "content/public/browser/web_contents.h" #include "mojo/public/cpp/bindings/strong_binding.h" -#if defined(TOOLKIT_VIEWS) && \ - (!defined(OS_MACOSX) || defined(MAC_VIEWS_BROWSER)) +#if defined(TOOLKIT_VIEWS) #include "chrome/browser/ui/views/media_router/media_remoting_dialog_view.h" #endif @@ -139,8 +138,7 @@ media_router::MediaRouterFactory::GetApiForBrowserContext( contents->GetBrowserContext()), SessionTabHelper::IdForTab(contents), -#if defined(TOOLKIT_VIEWS) && \ - (!defined(OS_MACOSX) || defined(MAC_VIEWS_BROWSER)) +#if defined(TOOLKIT_VIEWS) base::BindRepeating( [](content::WebContents* contents, PermissionResultCallback result_callback) {
diff --git a/chrome/browser/memory_details.cc b/chrome/browser/memory_details.cc index 3280b5e..8594ab1 100644 --- a/chrome/browser/memory_details.cc +++ b/chrome/browser/memory_details.cc
@@ -162,10 +162,7 @@ // Sort by memory consumption, low to high. std::sort(processes.begin(), processes.end()); // Print from high to low. - for (ProcessMemoryInformationList::reverse_iterator iter1 = - processes.rbegin(); - iter1 != processes.rend(); - ++iter1) { + for (auto iter1 = processes.rbegin(); iter1 != processes.rend(); ++iter1) { log += ProcessMemoryInformation::GetFullTypeNameInEnglish( iter1->process_type, iter1->renderer_type); if (!iter1->titles.empty()) {
diff --git a/chrome/browser/memory_details_linux.cc b/chrome/browser/memory_details_linux.cc index e8c1ddf6bf..b001dab 100644 --- a/chrome/browser/memory_details_linux.cc +++ b/chrome/browser/memory_details_linux.cc
@@ -124,8 +124,7 @@ current_browser.name = l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME); current_browser.process_name = base::ASCIIToUTF16("chrome"); - for (std::vector<ProcessMemoryInformation>::iterator - i = current_browser.processes.begin(); + for (auto i = current_browser.processes.begin(); i != current_browser.processes.end(); ++i) { // Check if this is one of the child processes whose data we collected // on the IO thread, and if so copy over that data.
diff --git a/chrome/browser/pepper_flash_settings_manager.cc b/chrome/browser/pepper_flash_settings_manager.cc index 0862dc88..ae29694 100644 --- a/chrome/browser/pepper_flash_settings_manager.cc +++ b/chrome/browser/pepper_flash_settings_manager.cc
@@ -365,8 +365,7 @@ std::vector<PendingRequest> temp_pending_requests; temp_pending_requests.swap(pending_requests_); - for (std::vector<PendingRequest>::iterator iter = - temp_pending_requests.begin(); + for (auto iter = temp_pending_requests.begin(); iter != temp_pending_requests.end(); ++iter) { switch (iter->type) { case INVALID_REQUEST_TYPE: @@ -664,8 +663,8 @@ state_ = STATE_ERROR; std::vector<std::pair<uint32_t, RequestType>> notifications; - for (std::vector<PendingRequest>::iterator iter = pending_requests_.begin(); - iter != pending_requests_.end(); ++iter) { + for (auto iter = pending_requests_.begin(); iter != pending_requests_.end(); + ++iter) { notifications.push_back(std::make_pair(iter->id, iter->type)); } pending_requests_.clear(); @@ -749,9 +748,7 @@ DCHECK_CURRENTLY_ON(BrowserThread::UI); scoped_refptr<Core> protector(this); - for (std::vector<std::pair<uint32_t, RequestType>>::const_iterator iter = - notifications.begin(); - iter != notifications.end(); ++iter) { + for (auto iter = notifications.begin(); iter != notifications.end(); ++iter) { // Check |manager_| for each iteration in case it is destroyed in one of // the callbacks. if (!manager_.get()) @@ -800,8 +797,7 @@ DLOG_IF(ERROR, !success) << "DeauthorizeContentLicenses returned error"; - std::map<uint32_t, RequestType>::iterator iter = - pending_responses_.find(request_id); + auto iter = pending_responses_.find(request_id); if (iter == pending_responses_.end()) return; @@ -825,8 +821,7 @@ DLOG_IF(ERROR, !success) << "GetPermissionSettings returned error"; - std::map<uint32_t, RequestType>::iterator iter = - pending_responses_.find(request_id); + auto iter = pending_responses_.find(request_id); if (iter == pending_responses_.end()) return; @@ -848,8 +843,7 @@ DLOG_IF(ERROR, !success) << "SetDefaultPermission returned error"; - std::map<uint32_t, RequestType>::iterator iter = - pending_responses_.find(request_id); + auto iter = pending_responses_.find(request_id); if (iter == pending_responses_.end()) return; @@ -871,8 +865,7 @@ DLOG_IF(ERROR, !success) << "SetSitePermission returned error"; - std::map<uint32_t, RequestType>::iterator iter = - pending_responses_.find(request_id); + auto iter = pending_responses_.find(request_id); if (iter == pending_responses_.end()) return; @@ -892,8 +885,7 @@ if (state_ == STATE_DETACHED) return; - std::map<uint32_t, RequestType>::iterator iter = - pending_responses_.find(request_id); + auto iter = pending_responses_.find(request_id); if (iter == pending_responses_.end()) return; @@ -915,8 +907,7 @@ DLOG_IF(ERROR, !success) << "ClearSiteData returned error"; - std::map<uint32_t, RequestType>::iterator iter = - pending_responses_.find(request_id); + auto iter = pending_responses_.find(request_id); if (iter == pending_responses_.end()) return; @@ -957,8 +948,7 @@ plugin_service->GetPluginInfoArray( GURL(), content::kFlashPluginSwfMimeType, false, &plugins, NULL); - for (std::vector<content::WebPluginInfo>::iterator iter = plugins.begin(); - iter != plugins.end(); ++iter) { + for (auto iter = plugins.begin(); iter != plugins.end(); ++iter) { if (iter->is_pepper_plugin() && plugin_prefs->IsPluginEnabled(*iter)) { if (plugin_info) *plugin_info = *iter;
diff --git a/chrome/browser/previews/previews_lite_page_browsertest.cc b/chrome/browser/previews/previews_lite_page_browsertest.cc index 0c8febd9..cd51c6c 100644 --- a/chrome/browser/previews/previews_lite_page_browsertest.cc +++ b/chrome/browser/previews/previews_lite_page_browsertest.cc
@@ -18,6 +18,9 @@ #include "base/test/simple_test_tick_clock.h" #include "build/build_config.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/infobars/mock_infobar_service.h" +#include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings.h" +#include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings_factory.h" #include "chrome/browser/previews/previews_lite_page_decider.h" #include "chrome/browser/previews/previews_lite_page_navigation_throttle.h" #include "chrome/browser/previews/previews_service.h" @@ -27,6 +30,7 @@ #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_test_utils.h" +#include "components/infobars/core/infobar.h" #include "components/previews/core/previews_features.h" #include "content/public/browser/navigation_entry.h" #include "content/public/browser/web_contents.h" @@ -58,7 +62,7 @@ } void SetUp() override { - SetUpLitePageTest(false); + SetUpLitePageTest(false /* use_timeout */); InProcessBrowserTest::SetUp(); } @@ -152,12 +156,24 @@ g_browser_process->network_quality_tracker() ->ReportEffectiveConnectionTypeForTesting( net::EFFECTIVE_CONNECTION_TYPE_2G); + + // Some tests shouldn't bother with the notification InfoBar. Just set the + // state on the decider so it isn't required. + PreviewsService* previews_service = + PreviewsServiceFactory::GetForProfile(browser()->profile()); + PreviewsLitePageDecider* decider = + previews_service->previews_lite_page_decider(); + decider->SetUserHasSeenUINotification(); } content::WebContents* GetWebContents() const { return browser()->tab_strip_model()->GetActiveWebContents(); } + InfoBarService* GetInfoBarService() { + return InfoBarService::FromWebContents(GetWebContents()); + } + void ExecuteScript(const std::string& script) const { EXPECT_TRUE(content::ExecuteScript(GetWebContents(), script)); } @@ -650,7 +666,7 @@ ~PreviewsLitePageServerTimeoutBrowserTest() override = default; void SetUp() override { - SetUpLitePageTest(true); + SetUpLitePageTest(true /* use_timeout */); InProcessBrowserTest::SetUp(); } @@ -799,3 +815,102 @@ ui_test_utils::NavigateToURL(browser(), HttpsLitePageURL(200)); VerifyPreviewNotLoaded(); } + +class PreviewsLitePageNotificationDSEnabledBrowserTest + : public PreviewsLitePageServerBrowserTest { + public: + PreviewsLitePageNotificationDSEnabledBrowserTest() = default; + + ~PreviewsLitePageNotificationDSEnabledBrowserTest() override = default; + + void SetUp() override { + SetUpLitePageTest(false /* use_timeout */); + + InProcessBrowserTest::SetUp(); + } + + void SetUpOnMainThread() override { + InProcessBrowserTest::SetUpOnMainThread(); + + g_browser_process->network_quality_tracker() + ->ReportEffectiveConnectionTypeForTesting( + net::EFFECTIVE_CONNECTION_TYPE_2G); + } +}; + +// Previews InfoBar (which these tests trigger) does not work on Mac. +// See https://crbug.com/782322 for detail. +// Also occasional flakes on win7 (https://crbug.com/789542). +#if defined(OS_ANDROID) || defined(OS_LINUX) +#define MAYBE_LitePagePreviewsInfoBarDataSaverUser \ + LitePagePreviewsInfoBarDataSaverUser +#else +#define MAYBE_LitePagePreviewsInfoBarDataSaverUser \ + DISABLED_LitePagePreviewsInfoBarDataSaverUser +#endif +IN_PROC_BROWSER_TEST_F(PreviewsLitePageNotificationDSEnabledBrowserTest, + MAYBE_LitePagePreviewsInfoBarDataSaverUser) { + // Ensure the preview is not shown the first time before the infobar is shown + // for users who have DRP enabled. + base::HistogramTester histogram_tester; + ui_test_utils::NavigateToURL(browser(), HttpsLitePageURL(200)); + + VerifyPreviewNotLoaded(); + EXPECT_EQ(1U, GetInfoBarService()->infobar_count()); + histogram_tester.ExpectBucketCount( + "Previews.ServerLitePage.IneligibleReasons", + PreviewsLitePageNavigationThrottle::IneligibleReason::kInfoBarNotSeen, 1); + + ui_test_utils::NavigateToURL(browser(), HttpsLitePageURL(200)); + EXPECT_EQ(0U, GetInfoBarService()->infobar_count()); + VerifyPreviewLoaded(); +} + +class PreviewsLitePageNotificationDSDisabledBrowserTest + : public PreviewsLitePageServerBrowserTest { + public: + PreviewsLitePageNotificationDSDisabledBrowserTest() = default; + + ~PreviewsLitePageNotificationDSDisabledBrowserTest() override = default; + + void SetUp() override { + SetUpLitePageTest(false /* use_timeout */); + + InProcessBrowserTest::SetUp(); + } + + void SetUpOnMainThread() override { + InProcessBrowserTest::SetUpOnMainThread(); + + g_browser_process->network_quality_tracker() + ->ReportEffectiveConnectionTypeForTesting( + net::EFFECTIVE_CONNECTION_TYPE_2G); + } + + // Overrides the cmd line in PreviewsLitePageServerBrowserTest and leave out + // the flag to enable DataSaver. + void SetUpCommandLine(base::CommandLine* cmd) override { + cmd->AppendSwitchASCII("force-effective-connection-type", "Slow-2G"); + // Resolve all localhost subdomains to plain localhost so that Chrome's Test + // DNS resolver doesn't get upset. + cmd->AppendSwitchASCII( + "host-rules", "MAP *.localhost 127.0.0.1, MAP *.127.0.0.1 127.0.0.1"); + } +}; + +// Previews InfoBar (which these tests trigger) does not work on Mac. +// See https://crbug.com/782322 for detail. +// Also occasional flakes on win7 (https://crbug.com/789542). +#if defined(OS_ANDROID) || defined(OS_LINUX) +#define MAYBE_LitePagePreviewsInfoBarNonDataSaverUser \ + LitePagePreviewsInfoBarNonDataSaverUser +#else +#define MAYBE_LitePagePreviewsInfoBarNonDataSaverUser \ + DISABLED_LitePagePreviewsInfoBarNonDataSaverUser +#endif +IN_PROC_BROWSER_TEST_F(PreviewsLitePageNotificationDSDisabledBrowserTest, + MAYBE_LitePagePreviewsInfoBarNonDataSaverUser) { + ui_test_utils::NavigateToURL(browser(), HttpsLitePageURL(200)); + VerifyPreviewNotLoaded(); + EXPECT_EQ(0U, GetInfoBarService()->infobar_count()); +}
diff --git a/chrome/browser/previews/previews_lite_page_decider.cc b/chrome/browser/previews/previews_lite_page_decider.cc index 784f863..3a02baeb 100644 --- a/chrome/browser/previews/previews_lite_page_decider.cc +++ b/chrome/browser/previews/previews_lite_page_decider.cc
@@ -10,6 +10,7 @@ #include "base/time/default_tick_clock.h" #include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings.h" #include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings_factory.h" +#include "chrome/browser/previews/previews_lite_page_infobar_delegate.h" #include "chrome/browser/previews/previews_lite_page_navigation_throttle.h" #include "chrome/browser/previews/previews_service.h" #include "chrome/browser/previews/previews_service_factory.h" @@ -66,8 +67,7 @@ void DidFinishNavigation(content::NavigationHandle* handle) override { if (ui_shown_callback_ && handle->GetNetErrorCode() == net::OK) { - // TODO(robertogden): Call PreviewsLitePageInfobarDelegate::Create and - // pass it the callback instead. + PreviewsLitePageInfoBarDelegate::Create(web_contents()); std::move(ui_shown_callback_).Run(); } DestroySelf();
diff --git a/chrome/browser/previews/previews_lite_page_decider_unittest.cc b/chrome/browser/previews/previews_lite_page_decider_unittest.cc index a6779d9f..54e6fda 100644 --- a/chrome/browser/previews/previews_lite_page_decider_unittest.cc +++ b/chrome/browser/previews/previews_lite_page_decider_unittest.cc
@@ -141,6 +141,8 @@ return decider_.get(); } + PreviewsLitePageDecider* decider() { return decider_.get(); } + private: std::unique_ptr<data_reduction_proxy::DataReductionProxyTestContext> drp_test_context_; @@ -176,7 +178,8 @@ GetManagerWithDRPEnabled(true); EXPECT_TRUE(manager->NeedsToNotifyUser()); - manager->NotifyUser(web_contents()); + // Simulate the callback being run. + decider()->SetUserHasSeenUINotification(); content::WebContentsTester::For(web_contents()) ->NavigateAndCommit(GURL(kTestUrl));
diff --git a/chrome/browser/previews/previews_lite_page_infobar_delegate.cc b/chrome/browser/previews/previews_lite_page_infobar_delegate.cc new file mode 100644 index 0000000..e24cb2c5 --- /dev/null +++ b/chrome/browser/previews/previews_lite_page_infobar_delegate.cc
@@ -0,0 +1,70 @@ +// 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/previews/previews_lite_page_infobar_delegate.h" + +#include <memory> + +#include "base/metrics/histogram_macros.h" +#include "base/time/default_tick_clock.h" +#include "chrome/browser/infobars/infobar_service.h" +#include "chrome/grit/generated_resources.h" +#include "components/infobars/core/infobar.h" +#include "components/previews/core/previews_experiments.h" +#include "content/public/browser/web_contents.h" +#include "ui/base/l10n/l10n_util.h" + +namespace { + +void RecordInfoBarAction( + PreviewsLitePageInfoBarDelegate::PreviewsLitePageInfoBarAction action) { + UMA_HISTOGRAM_ENUMERATION("Previews.LitePageNotificationInfoBar", action); +} + +} // namespace + +// static +void PreviewsLitePageInfoBarDelegate::Create( + content::WebContents* web_contents) { + InfoBarService* infobar_service = + InfoBarService::FromWebContents(web_contents); + if (!infobar_service) + return; + + std::unique_ptr<PreviewsLitePageInfoBarDelegate> delegate( + new PreviewsLitePageInfoBarDelegate()); + + std::unique_ptr<infobars::InfoBar> infobar_ptr( + infobar_service->CreateConfirmInfoBar(std::move(delegate))); + + RecordInfoBarAction(kInfoBarShown); + infobar_service->AddInfoBar(std::move(infobar_ptr)); +} + +PreviewsLitePageInfoBarDelegate::PreviewsLitePageInfoBarDelegate() {} +PreviewsLitePageInfoBarDelegate::~PreviewsLitePageInfoBarDelegate() {} + +infobars::InfoBarDelegate::InfoBarIdentifier +PreviewsLitePageInfoBarDelegate::GetIdentifier() const { + return LITE_PAGE_PREVIEWS_INFOBAR; +} + +// TODO(robertogden): Add link on Android. + +int PreviewsLitePageInfoBarDelegate::GetIconId() const { + // TODO(robertogden): Add an Android icon. + return kNoIconID; +} + +void PreviewsLitePageInfoBarDelegate::InfoBarDismissed() { + RecordInfoBarAction(kInfoBarDismissed); +} + +base::string16 PreviewsLitePageInfoBarDelegate::GetMessageText() const { + return l10n_util::GetStringUTF16(IDS_LITE_PAGE_PREVIEWS_MESSAGE); +} + +int PreviewsLitePageInfoBarDelegate::GetButtons() const { + return BUTTON_NONE; +}
diff --git a/chrome/browser/previews/previews_lite_page_infobar_delegate.h b/chrome/browser/previews/previews_lite_page_infobar_delegate.h new file mode 100644 index 0000000..1a361db --- /dev/null +++ b/chrome/browser/previews/previews_lite_page_infobar_delegate.h
@@ -0,0 +1,48 @@ +// 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_PREVIEWS_PREVIEWS_LITE_PAGE_INFOBAR_DELEGATE_H_ +#define CHROME_BROWSER_PREVIEWS_PREVIEWS_LITE_PAGE_INFOBAR_DELEGATE_H_ + +#include "base/callback.h" +#include "base/strings/string16.h" +#include "base/time/tick_clock.h" +#include "base/time/time.h" +#include "components/infobars/core/confirm_infobar_delegate.h" + +namespace content { +class WebContents; +} + +// This InfoBar notifies the user that Data Saver now also applies to HTTPS +// pages. +class PreviewsLitePageInfoBarDelegate : public ConfirmInfoBarDelegate { + public: + ~PreviewsLitePageInfoBarDelegate() override; + + // Actions taken on the infobar. This enum must remain synchronized with the + // enum of the same name in metrics/histograms/enums.xml. + enum PreviewsLitePageInfoBarAction { + kInfoBarShown = 0, + kInfoBarDismissed = 1, + kMaxValue = kInfoBarDismissed, + }; + + // Shows the InfoBar. + static void Create(content::WebContents* web_contents); + + private: + PreviewsLitePageInfoBarDelegate(); + + // ConfirmInfoBarDelegate: + infobars::InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override; + void InfoBarDismissed() override; + int GetButtons() const override; + int GetIconId() const override; + base::string16 GetMessageText() const override; + + DISALLOW_COPY_AND_ASSIGN(PreviewsLitePageInfoBarDelegate); +}; + +#endif // CHROME_BROWSER_PREVIEWS_PREVIEWS_LITE_PAGE_INFOBAR_DELEGATE_H_
diff --git a/chrome/browser/previews/previews_lite_page_infobar_delegate_unittest.cc b/chrome/browser/previews/previews_lite_page_infobar_delegate_unittest.cc new file mode 100644 index 0000000..09a5815 --- /dev/null +++ b/chrome/browser/previews/previews_lite_page_infobar_delegate_unittest.cc
@@ -0,0 +1,78 @@ +// 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/previews/previews_lite_page_infobar_delegate.h" + +#include "base/bind_helpers.h" +#include "base/strings/string16.h" +#include "base/test/metrics/histogram_tester.h" +#include "base/test/simple_test_tick_clock.h" +#include "build/build_config.h" +#include "chrome/browser/infobars/mock_infobar_service.h" +#include "chrome/grit/generated_resources.h" +#include "chrome/test/base/chrome_render_view_host_test_harness.h" +#include "components/infobars/core/confirm_infobar_delegate.h" +#include "components/infobars/core/infobar.h" +#include "components/previews/core/previews_features.h" +#include "ui/base/l10n/l10n_util.h" + +class PreviewsLitePageInfoBarDelegateUnitTest + : public ChromeRenderViewHostTestHarness { + protected: + PreviewsLitePageInfoBarDelegateUnitTest() = default; + + void SetUp() override { + ChromeRenderViewHostTestHarness::SetUp(); + MockInfoBarService::CreateForWebContents(web_contents()); + } + + PreviewsLitePageInfoBarDelegate* CreateInfoBar() { + PreviewsLitePageInfoBarDelegate::Create(web_contents()); + EXPECT_EQ(1U, infobar_service()->infobar_count()); + return static_cast<PreviewsLitePageInfoBarDelegate*>( + infobar_service()->infobar_at(0)->delegate()); + } + + InfoBarService* infobar_service() { + return InfoBarService::FromWebContents(web_contents()); + } +}; + +// TODO(crbug/782740): Test temporarily disabled on Windows because it crashes +// on trybots. +#if defined(OS_WIN) +#define DISABLE_ON_WINDOWS(x) DISABLED_##x +#else +#define DISABLE_ON_WINDOWS(x) x +#endif +TEST_F(PreviewsLitePageInfoBarDelegateUnitTest, + DISABLE_ON_WINDOWS(InfoBarUserDismissal)) { + base::HistogramTester tester; + ConfirmInfoBarDelegate* infobar = CreateInfoBar(); + + // Simulate dismissing the infobar. + infobar->InfoBarDismissed(); + infobar_service()->infobar_at(0)->RemoveSelf(); + EXPECT_EQ(0U, infobar_service()->infobar_count()); + + tester.ExpectBucketCount("Previews.LitePageNotificationInfoBar", + PreviewsLitePageInfoBarDelegate::kInfoBarDismissed, + 1); +} + +TEST_F(PreviewsLitePageInfoBarDelegateUnitTest, + DISABLE_ON_WINDOWS(LitePagePreviewInfoBarTest)) { + base::HistogramTester tester; + ConfirmInfoBarDelegate* infobar = CreateInfoBar(); + + tester.ExpectUniqueSample("Previews.LitePageNotificationInfoBar", + PreviewsLitePageInfoBarDelegate::kInfoBarShown, 1); + + // Check the strings. + ASSERT_TRUE(infobar); + ASSERT_EQ(l10n_util::GetStringUTF16(IDS_LITE_PAGE_PREVIEWS_MESSAGE), + infobar->GetMessageText()); + ASSERT_EQ(base::string16(), infobar->GetLinkText()); + ASSERT_EQ(PreviewsLitePageInfoBarDelegate::kNoIconID, infobar->GetIconId()); +}
diff --git a/chrome/browser/previews/previews_lite_page_navigation_throttle.cc b/chrome/browser/previews/previews_lite_page_navigation_throttle.cc index 76bae81..4992c3e 100644 --- a/chrome/browser/previews/previews_lite_page_navigation_throttle.cc +++ b/chrome/browser/previews/previews_lite_page_navigation_throttle.cc
@@ -213,7 +213,16 @@ reason); } - return blacklist_reasons.empty(); + if (!blacklist_reasons.empty()) + return false; + + if (manager_->NeedsToNotifyUser()) { + manager_->NotifyUser(navigation_handle()->GetWebContents()); + UMA_HISTOGRAM_ENUMERATION("Previews.ServerLitePage.IneligibleReasons", + IneligibleReason::kInfoBarNotSeen); + return false; + } + return true; } // static
diff --git a/chrome/browser/previews/previews_lite_page_navigation_throttle.h b/chrome/browser/previews/previews_lite_page_navigation_throttle.h index 1501fa1..7162747 100644 --- a/chrome/browser/previews/previews_lite_page_navigation_throttle.h +++ b/chrome/browser/previews/previews_lite_page_navigation_throttle.h
@@ -37,7 +37,8 @@ kHttpPost = 1, kSubframeNavigation = 2, kServerUnavailable = 3, - kMaxValue = kServerUnavailable, + kInfoBarNotSeen = 4, + kMaxValue = kInfoBarNotSeen, }; // The response type from the previews server. This enum must
diff --git a/chrome/browser/previews/previews_lite_page_navigation_throttle_manager.h b/chrome/browser/previews/previews_lite_page_navigation_throttle_manager.h index d36687e..7ea111f 100644 --- a/chrome/browser/previews/previews_lite_page_navigation_throttle_manager.h +++ b/chrome/browser/previews/previews_lite_page_navigation_throttle_manager.h
@@ -41,7 +41,6 @@ // Note: |NeedsToToNotify| is intentionally separate from |NotifyUser| for // ease of testing and metrics collection without changing the notification // state. - // Returns true if the UI notification needs to be shown to the user before // this preview can be shown. virtual bool NeedsToNotifyUser() = 0;
diff --git a/chrome/browser/process_singleton_posix.cc b/chrome/browser/process_singleton_posix.cc index 23da92f..3b6c0b6 100644 --- a/chrome/browser/process_singleton_posix.cc +++ b/chrome/browser/process_singleton_posix.cc
@@ -868,8 +868,7 @@ to_send.append(current_dir.value()); const std::vector<std::string>& argv = cmd_line.argv(); - for (std::vector<std::string>::const_iterator it = argv.begin(); - it != argv.end(); ++it) { + for (auto it = argv.begin(); it != argv.end(); ++it) { to_send.push_back(kTokenDelimiter); to_send.append(*it); }
diff --git a/chrome/browser/resource_coordinator/tab_manager_delegate_chromeos.cc b/chrome/browser/resource_coordinator/tab_manager_delegate_chromeos.cc index 30bc448..133c387 100644 --- a/chrome/browser/resource_coordinator/tab_manager_delegate_chromeos.cc +++ b/chrome/browser/resource_coordinator/tab_manager_delegate_chromeos.cc
@@ -536,9 +536,6 @@ bool TabManagerDelegate::KillTab(LifecycleUnit* lifecycle_unit, ::mojom::LifecycleUnitDiscardReason reason) { - DecisionDetails decision_details; - if (!lifecycle_unit->CanDiscard(reason, &decision_details)) - return false; bool did_discard = lifecycle_unit->Discard(reason); return did_discard; }
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/output_test.extjs b/chrome/browser/resources/chromeos/chromevox/cvox2/background/output_test.extjs index 079d7af2..a676b7f 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/output_test.extjs +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/output_test.extjs
@@ -229,19 +229,18 @@ .withoutHints() .withSpeechAndBraille(range, null, 'navigate'); - checkSpeechOutput('play|Button|begin playback|audio|Tool bar', + checkSpeechOutput('play|Button|audio|Tool bar', [ {value: new Output.EarconAction('BUTTON'), start: 0, end: 4}, - {value: 'description', start: 12, end: 26}, - {value: 'name', start: 27, end: 32}, - {value: 'role', start: 33, end: 41} + {value: 'name', start: 12, end: 17}, + {value: 'role', start: 18, end: 26} ], o); checkBrailleOutput( - 'play btn begin playback audio tlbar', - [{value: new Output.NodeSpan(el), start: 0, end: 23}, - {value: new Output.NodeSpan(el.parent), start: 24, end: 35}], + 'play btn audio tlbar', + [{value: new Output.NodeSpan(el), start: 0, end: 8}, + {value: new Output.NodeSpan(el.parent), start: 9, end: 20}], o); // TODO(dmazzoni/dtseng): Replace with a query.
diff --git a/chrome/browser/resources/print_preview/new/pages_settings.html b/chrome/browser/resources/print_preview/new/pages_settings.html index 9d59c9e..1903cc45 100644 --- a/chrome/browser/resources/print_preview/new/pages_settings.html +++ b/chrome/browser/resources/print_preview/new/pages_settings.html
@@ -18,11 +18,13 @@ --paper-radio-group-item-padding: 0; } - :host([error-state_='0']) #pageSettingsCustomInput { + :host([error-state_='0']) #pageSettingsCustomInput, + :host([error-state_='3']) #pageSettingsCustomInput { --cr-input-error-display: none; } - :host(:not([error-state_='0'])) #customRadioButton { + :host([error-state_='1']) #customRadioButton, + :host([error-state_='2']) #customRadioButton { /* Margin = -1 * error height = -1 * (16px + 2 lines * line-height) */ --cr-radio-button-disc: { margin-top: calc(-16px - 2 * .75rem);
diff --git a/chrome/browser/resources/print_preview/new/pages_settings.js b/chrome/browser/resources/print_preview/new/pages_settings.js index 5bc0f1a..07c2d9b 100644 --- a/chrome/browser/resources/print_preview/new/pages_settings.js +++ b/chrome/browser/resources/print_preview/new/pages_settings.js
@@ -10,6 +10,7 @@ NO_ERROR: 0, INVALID_SYNTAX: 1, OUT_OF_BOUNDS: 2, + EMPTY: 3, }; /** @enum {string} */ @@ -152,9 +153,13 @@ * @private */ computePagesToPrint_: function() { - if (this.optionSelected_ === PagesValue.ALL || this.inputString_ === '') { + if (this.optionSelected_ === PagesValue.ALL) { this.errorState_ = PagesInputErrorState.NO_ERROR; return this.allPagesArray_; + } else if (this.inputString_ === '') { + if (this.errorState_ !== PagesInputErrorState.NO_ERROR) + this.errorState_ = PagesInputErrorState.EMPTY; + return this.pagesToPrint_; } const pages = []; @@ -283,11 +288,18 @@ if (this.settings === undefined || this.pagesToPrint_ === undefined) return; - if (this.errorState_ != PagesInputErrorState.NO_ERROR) { + if (this.errorState_ === PagesInputErrorState.EMPTY) { + this.setSettingValid('pages', false); + this.$.pageSettingsCustomInput.invalid = false; + return; + } + + if (this.errorState_ !== PagesInputErrorState.NO_ERROR) { this.setSettingValid('pages', false); this.$.pageSettingsCustomInput.invalid = true; return; } + this.$.pageSettingsCustomInput.invalid = false; this.setSettingValid('pages', true); const nupPages = this.getNupPages_(); @@ -312,8 +324,14 @@ /** @private */ resetIfEmpty_: function() { - if (this.inputString_ === '') - this.optionSelected_ = PagesValue.ALL; + if (this.inputString_ !== '') + return; + + this.optionSelected_ = PagesValue.ALL; + + // Manually set tab index to -1, so that this is not identified as the + // target for the radio group if the user navigates back. + this.$.customRadioButton.tabIndex = -1; }, /** @@ -337,9 +355,10 @@ * @private */ onCustomRadioBlur_: function(event) { - if (event.relatedTarget != - /** @type {!CrInputElement} */ - (this.$.pageSettingsCustomInput).inputElement) { + if (event.relatedTarget != this.$.pageSettingsCustomInput && + event.relatedTarget != + /** @type {!CrInputElement} */ + (this.$.pageSettingsCustomInput).inputElement) { this.resetIfEmpty_(); } }, @@ -353,10 +372,6 @@ if (event.relatedTarget != this.$.customRadioButton) { this.resetIfEmpty_(); - - // Manually set tab index to -1, so that this is not identified as the - // target for the radio group if the user navigates back. - this.$.customRadioButton.tabIndex = -1; } }, @@ -390,8 +405,10 @@ * @private */ getHintMessage_: function() { - if (this.errorState_ == PagesInputErrorState.NO_ERROR) + if (this.errorState_ == PagesInputErrorState.NO_ERROR || + this.errorState_ == PagesInputErrorState.EMPTY) { return ''; + } let formattedMessage = ''; if (this.errorState_ == PagesInputErrorState.INVALID_SYNTAX) { @@ -413,7 +430,8 @@ * @private */ hintHidden_: function() { - return this.errorState_ == PagesInputErrorState.NO_ERROR; + return this.errorState_ == PagesInputErrorState.NO_ERROR || + this.errorState_ == PagesInputErrorState.EMPTY; } }); })();
diff --git a/chrome/browser/resources/settings/basic_page/basic_page.html b/chrome/browser/resources/settings/basic_page/basic_page.html index ec867412..216ff5d5 100644 --- a/chrome/browser/resources/settings/basic_page/basic_page.html +++ b/chrome/browser/resources/settings/basic_page/basic_page.html
@@ -21,7 +21,7 @@ <link rel="import" href="../crostini_page/crostini_page.html"> <link rel="import" href="../device_page/device_page.html"> <link rel="import" href="../internet_page/internet_page.html"> -<link rel="import" href="../multidevice_page/multidevice_page_container.html"> +<link rel="import" href="../multidevice_page/multidevice_page.html"> </if> <if expr="not chromeos"> @@ -122,12 +122,8 @@ if="[[canShowMultideviceSection_(showMultidevice, pageVisibility)]]" restamp> <settings-section page-title="$i18n{multidevicePageTitle}" - section="multidevice" - hidden$="[[!doesChromebookSupportMultiDeviceSection_]]"> - <settings-multidevice-page-container - does-chromebook-support-multi-device-features= - "{{doesChromebookSupportMultiDeviceSection_}}"> - </settings-multidevice-page-container> + section="multidevice"> + <settings-multidevice-page></settings-multidevice-page> </settings-section> </template> </if>
diff --git a/chrome/browser/resources/settings/basic_page/basic_page.js b/chrome/browser/resources/settings/basic_page/basic_page.js index b875e7f8..d1cfd958 100644 --- a/chrome/browser/resources/settings/basic_page/basic_page.js +++ b/chrome/browser/resources/settings/basic_page/basic_page.js
@@ -89,16 +89,6 @@ type: Boolean, computed: 'computeShowSecondaryUserBanner_(hasExpandedSection_)', }, - - /** - * Whether the account supports the features controlled in the multidevice - * section. - * @private {boolean} - */ - doesChromebookSupportMultiDeviceSection_: { - type: Boolean, - value: false, - }, // </if> /** @private {!settings.Route|undefined} */
diff --git a/chrome/browser/resources/settings/multidevice_page/BUILD.gn b/chrome/browser/resources/settings/multidevice_page/BUILD.gn index 46e84a10..30149cc 100644 --- a/chrome/browser/resources/settings/multidevice_page/BUILD.gn +++ b/chrome/browser/resources/settings/multidevice_page/BUILD.gn
@@ -12,7 +12,6 @@ ":multidevice_feature_item", ":multidevice_feature_toggle", ":multidevice_page", - ":multidevice_page_container", ":multidevice_subpage", ":multidevice_tether_item", ] @@ -62,15 +61,6 @@ ":multidevice_feature_behavior", "../controls:password_prompt_dialog", "//ui/webui/resources/js:cr", - ] -} - -js_library("multidevice_page_container") { - deps = [ - ":multidevice_browser_proxy", - ":multidevice_constants", - ":multidevice_feature_behavior", - "//ui/webui/resources/js:cr", "//ui/webui/resources/js:web_ui_listener_behavior", ] }
diff --git a/chrome/browser/resources/settings/multidevice_page/multidevice_page.html b/chrome/browser/resources/settings/multidevice_page/multidevice_page.html index 4dc80bd..5001f6bc 100644 --- a/chrome/browser/resources/settings/multidevice_page/multidevice_page.html +++ b/chrome/browser/resources/settings/multidevice_page/multidevice_page.html
@@ -3,6 +3,7 @@ <link rel="import" href="chrome://resources/cr_elements/cr_toggle/cr_toggle.html"> <link rel="import" href="chrome://resources/html/cr.html"> <link rel="import" href="chrome://resources/html/i18n_behavior.html"> +<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> <link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
diff --git a/chrome/browser/resources/settings/multidevice_page/multidevice_page.js b/chrome/browser/resources/settings/multidevice_page/multidevice_page.js index 4c5c871c..f722db6 100644 --- a/chrome/browser/resources/settings/multidevice_page/multidevice_page.js +++ b/chrome/browser/resources/settings/multidevice_page/multidevice_page.js
@@ -11,7 +11,7 @@ Polymer({ is: 'settings-multidevice-page', - behaviors: [MultiDeviceFeatureBehavior], + behaviors: [MultiDeviceFeatureBehavior, WebUIListenerBehavior], properties: { /** @@ -72,8 +72,15 @@ browserProxy_: null, /** @override */ - created: function() { + ready: function() { this.browserProxy_ = settings.MultiDeviceBrowserProxyImpl.getInstance(); + + this.addWebUIListener( + 'settings.updateMultidevicePageContentData', + this.onPageContentDataChanged_.bind(this)); + + this.browserProxy_.getPageContentData().then( + this.onPageContentDataChanged_.bind(this)); }, /** @@ -307,4 +314,12 @@ this.browserProxy_.removeHostDevice(); settings.navigateTo(settings.routes.MULTIDEVICE); }, + + /** + * @param {!MultiDevicePageContentData} newData + * @private + */ + onPageContentDataChanged_: function(newData) { + this.pageContentData = newData; + }, });
diff --git a/chrome/browser/resources/settings/multidevice_page/multidevice_page_container.html b/chrome/browser/resources/settings/multidevice_page/multidevice_page_container.html deleted file mode 100644 index c804083..0000000 --- a/chrome/browser/resources/settings/multidevice_page/multidevice_page_container.html +++ /dev/null
@@ -1,20 +0,0 @@ -<link rel="import" href="chrome://resources/html/polymer.html"> - -<link rel="import" href="chrome://resources/html/cr.html"> -<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html"> -<link rel="import" href="multidevice_browser_proxy.html"> -<link rel="import" href="multidevice_constants.html"> -<link rel="import" href="multidevice_feature_behavior.html"> -<link rel="import" href="multidevice_page.html"> - -<dom-module id="settings-multidevice-page-container"> - <template> - <template is="dom-if" - if="[[doesChromebookSupportMultiDeviceFeatures]]" - restamp> - <settings-multidevice-page page-content-data="[[pageContentData]]"> - </settings-multidevice-page> - </template> - </template> - <script src="multidevice_page_container.js"></script> -</dom-module>
diff --git a/chrome/browser/resources/settings/multidevice_page/multidevice_page_container.js b/chrome/browser/resources/settings/multidevice_page/multidevice_page_container.js deleted file mode 100644 index dd74a92..0000000 --- a/chrome/browser/resources/settings/multidevice_page/multidevice_page_container.js +++ /dev/null
@@ -1,87 +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. - -/** - * @fileoverview Container element that interfaces with the - * MultiDeviceBrowserProxy to ensure that if there is not a host device or - * potential host device - * (a) the entire multidevice settings-section is hidden and - * (b) the settings-multidevice-page is not attched to the DOM. - * It also provides the settings-multidevice-page with the data it needs to - * provide the user with the correct infomation and call(s) to action based on - * the data retrieved from the browser proxy (i.e. the mode_ property). - */ - -cr.exportPath('settings'); - -Polymer({ - is: 'settings-multidevice-page-container', - - behaviors: [MultiDeviceFeatureBehavior, WebUIListenerBehavior], - - properties: { - /** - * Whether the Chromebook is capable of enabling Better Together features. - * @type {boolean} - */ - doesChromebookSupportMultiDeviceFeatures: { - type: Boolean, - computed: - 'computeDoesChromebookSupportMultiDeviceFeatures(pageContentData)', - notify: true, - }, - }, - - /** @private {?settings.MultiDeviceBrowserProxy} */ - browserProxy_: null, - - /** @override */ - ready: function() { - this.browserProxy_ = settings.MultiDeviceBrowserProxyImpl.getInstance(); - - this.addWebUIListener( - 'settings.updateMultidevicePageContentData', - this.onPageContentDataChanged_.bind(this)); - - this.browserProxy_.getPageContentData().then( - this.onPageContentDataChanged_.bind(this)); - }, - - /** - * @param {!MultiDevicePageContentData} newData - * @private - */ - onPageContentDataChanged_: function(newData) { - if (!this.isStatusChangeValid_(newData)) { - console.error('Invalid status change'); - return; - } - this.pageContentData = newData; - }, - - /** - * If the new mode corresponds to no eligible host or unset potential hosts - * (i.e. NO_ELIGIBLE_HOSTS or NO_HOST_SET), then newHostDeviceName should be - * falsy. Otherwise it should be truthy. - * @param {!MultiDevicePageContentData} newData - * @private - */ - isStatusChangeValid_: function(newData) { - const noHostModes = [ - settings.MultiDeviceSettingsMode.NO_ELIGIBLE_HOSTS, - settings.MultiDeviceSettingsMode.NO_HOST_SET, - ]; - return !newData.hostDeviceName === noHostModes.includes(newData.mode); - }, - - /** - * @return {boolean} - * @private - */ - computeDoesChromebookSupportMultiDeviceFeatures: function() { - return !!this.pageContentData && - this.isFeatureSupported( - settings.MultiDeviceFeature.BETTER_TOGETHER_SUITE); - }, -});
diff --git a/chrome/browser/resources/settings/multidevice_page/multidevice_subpage.html b/chrome/browser/resources/settings/multidevice_page/multidevice_subpage.html index 383a1b23..5b45963 100644 --- a/chrome/browser/resources/settings/multidevice_page/multidevice_subpage.html +++ b/chrome/browser/resources/settings/multidevice_page/multidevice_subpage.html
@@ -115,7 +115,7 @@ <cr-dialog id="forgetDeviceDialog"> <div slot="title">$i18n{multideviceForgetDevice}</div> <div slot="body"> - <div class="settings-box first"> + <div class="first"> $i18n{multideviceForgetDeviceDialogMessage} </div> </div>
diff --git a/chrome/browser/resources/settings/settings_resources.grd b/chrome/browser/resources/settings/settings_resources.grd index 98b783f..3b2676828 100644 --- a/chrome/browser/resources/settings/settings_resources.grd +++ b/chrome/browser/resources/settings/settings_resources.grd
@@ -1357,12 +1357,6 @@ <structure name="IDR_SETTINGS_MULTIDEVICE_PAGE_JS" file="multidevice_page/multidevice_page.js" type="chrome_html" /> - <structure name="IDR_SETTINGS_MULTIDEVICE_PAGE_CONTAINER_HTML" - file="multidevice_page/multidevice_page_container.html" - type="chrome_html" /> - <structure name="IDR_SETTINGS_MULTIDEVICE_PAGE_CONTAINER_JS" - file="multidevice_page/multidevice_page_container.js" - type="chrome_html" /> <structure name="IDR_SETTINGS_MULTIDEVICE_SUBPAGE_HTML" file="multidevice_page/multidevice_subpage.html" type="chrome_html" />
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/email/email_chooser.html b/chrome/browser/resources/welcome/onboarding_welcome/email/email_chooser.html index 189078697..25d80fd 100644 --- a/chrome/browser/resources/welcome/onboarding_welcome/email/email_chooser.html +++ b/chrome/browser/resources/welcome/onboarding_welcome/email/email_chooser.html
@@ -8,94 +8,11 @@ <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> <link rel="import" href="chrome://welcome/email/nux_email_proxy.html"> +<link rel="import" href="chrome://welcome/shared/chooser_shared_css.html"> <dom-module id="email-chooser"> <template> - <style include="paper-button-style"> - :host { - display: block; - white-space: nowrap; - } - - .option { - align-items: center; - background: white; - border-radius: 8px; - border: 1px solid transparent; - box-sizing: border-box; - box-shadow: 0 1px 2px 0 rgba(0,36,100,0.30), - 0 2px 6px 2px rgba(0,36,100,0.15); - display: inline-flex; - flex-direction: column; - height: 96px; - justify-content: center; - position: relative; - vertical-align: bottom; - -webkit-appearance: none; - width: 120px; - outline: 0; - } - - .option:not(:first-of-type) { - margin-inline-start: 24px; - } - - .option.keyboard-focused:focus { - outline: -webkit-focus-ring-color auto 5px; - } - - .option .email-name { - flex-grow: 0; - font-size: 0.875rem; - line-height: 1.25rem; - text-align: center; - white-space: normal; - } - - .option .email-icon { - background-position: center; - background-repeat: no-repeat; - background-size: contain; - height: 40px; - margin: 0; - margin-bottom: 4px; - width: 40px; - } - - .option iron-icon { - --iron-icon-fill-color: white; - background: lightgrey; - border-radius: 50%; - display: none; - height: 12px; - margin: 0; - position: absolute; - right: 10px; - top: 10px; - width: 12px; - } - - .option.keyboard-focused:focus iron-icon[icon="cr:check"], - .option:hover iron-icon[icon="cr:check"], - .option[active] iron-icon[icon="cr:check"] { - display: block; - } - - .option[active] { - border: 1px solid var(--google-blue-600); - color: var(--google-blue-600); - } - - .option[active] iron-icon[icon="cr:check"] { - background: var(--google-blue-600); - } - - .button-bar { - display: flex; - margin-top: 64px; - justify-content: space-between; - } - + <style include="chooser-shared-css paper-button-style"> .gmail { background-image: -webkit-image-set( url(chrome://welcome/email/gmail_1x.png) 1x, @@ -131,8 +48,8 @@ <button active$="[[getSelected_(item, selectedEmailProvider_)]]" on-click="onEmailClick_" on-pointerdown="onEmailPointerDown_" on-keyup="onEmailKeyUp_" class="option"> - <div class$="[[item.icon]] email-icon"></div> - <div class="email-name">[[item.name]]</div> + <div class$="[[item.icon]] option-icon"></div> + <div class="option-name">[[item.name]]</div> <iron-icon icon="cr:check"></iron-icon> </button> </template>
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/google_apps/apps_chooser.html b/chrome/browser/resources/welcome/onboarding_welcome/google_apps/apps_chooser.html index b5a96d44..f92ff424 100644 --- a/chrome/browser/resources/welcome/onboarding_welcome/google_apps/apps_chooser.html +++ b/chrome/browser/resources/welcome/onboarding_welcome/google_apps/apps_chooser.html
@@ -4,33 +4,11 @@ <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> +<link rel="import" href="chrome://welcome/shared/chooser_shared_css.html"> <dom-module id="apps-chooser"> <template> - <style> - :host { - display: flex; - flex-direction: column; - } - - .app-icon { - margin-inline-end: 16px; - margin-inline-start: 4px; - } - - iron-icon { - margin-inline-end: 48px; - } - - [active] iron-icon[icon="cr:check"] { - --iron-icon-fill-color: var(--google-blue-600); - opacity: unset; - } - - iron-icon[icon="cr:check"] { - opacity: 0; - } - + <style include="chooser-shared-css"> .gmail { content: -webkit-image-set( url(chrome://welcome/apps/gmail_1x.png) 1x, @@ -61,43 +39,22 @@ url(chrome://welcome/apps/news_2x.png) 2x); } - .chrome_store { + .chrome-store { content: -webkit-image-set( url(chrome://welcome/apps/chrome_store_1x.png) 1x, url(chrome://welcome/apps/chrome_store_2x.png) 2x); } - - paper-button:first-of-type { - border-top: unset; - } - - paper-button { - border-radius: 0; - border-top: var(--cr-section_-_border-top); - display: flex; - margin: 0; - padding: 12px 0; - text-transform: unset; - } - - paper-button:not([raised]).keyboard-focus { - outline-width: unset; - font-weight: unset; - } - - .app-name { - flex: 1; - } </style> <template is="dom-repeat" items="[[appList]]"> - <paper-button toggles noink - active$="[[item.selected]]" on-click="onAppClick_"> - <div class$="[[item.icon]] app-icon"></div> - <div class="app-name">[[item.name]]</div> - <iron-icon icon="cr:check"></iron-icon> - </paper-button> + <button active$="[[item.selected]]" + on-click="onAppClick_" on-pointerdown="onAppPointerDown_" + on-keyup="onAppKeyUp_" class="option"> + <div class$="[[item.icon]] option-icon"></div> + <div class="option-name">[[item.name]]</div> + <iron-icon icon="cr:check"></iron-icon> + </button> + </template> </template> - </template> <script src="apps_chooser.js"></script> -</dom-module> +</dom-module> \ No newline at end of file
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/google_apps/apps_chooser.js b/chrome/browser/resources/welcome/onboarding_welcome/google_apps/apps_chooser.js index 5cec1de..4cdeb18 100644 --- a/chrome/browser/resources/welcome/onboarding_welcome/google_apps/apps_chooser.js +++ b/chrome/browser/resources/welcome/onboarding_welcome/google_apps/apps_chooser.js
@@ -53,8 +53,8 @@ selected: true, }, { - name: 'Chrome Web Store', - icon: 'chrome_store', + name: 'Web Store', + icon: 'chrome-store', selected: true, }, ]; @@ -87,6 +87,22 @@ }, /** + * @param {!Event} e + * @private + */ + onAppPointerDown_: function(e) { + e.currentTarget.classList.remove('keyboard-focused'); + }, + + /** + * @param {!Event} e + * @private + */ + onAppKeyUp_: function(e) { + e.currentTarget.classList.add('keyboard-focused'); + }, + + /** * @return {boolean} * @private */
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps.html b/chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps.html index 56f427a..41b5c58 100644 --- a/chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps.html +++ b/chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps.html
@@ -6,6 +6,7 @@ <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html"> +<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> <link rel="import" href="chrome://welcome/apps/apps_chooser.html"> <link rel="import" href="chrome://welcome/apps/nux_google_apps_proxy.html"> @@ -21,33 +22,33 @@ margin-left: auto; margin-right: auto; margin-top: 116px; - max-width: 568px; + width: fit-content; } .chrome-logo { content: -webkit-image-set( - url('chrome://welcome/logo.png') 1x, - url('chrome://welcome/logo2x.png') 2x); + url(chrome://welcome/logo.png) 1x, + url(chrome://welcome/logo2x.png) 2x); height: 40px; margin-bottom: 36px; width: 40px; } h1 { - color: #202124; + color: var(--cr-primary-text-color); font-size: 28px; - opacity: .8; margin-bottom: 16px; + opacity: .8; } .description { - color: #5f6368; + color: var(--cr-secondary-text-color); font-size: 16px; margin-bottom: 24px; } apps-chooser { - color: #202124; + color: var(--cr-primary-text-color); font-size: 14px; margin-bottom: 48px; }
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/shared/chooser_shared_css.html b/chrome/browser/resources/welcome/onboarding_welcome/shared/chooser_shared_css.html new file mode 100644 index 0000000..6c64c2a8 --- /dev/null +++ b/chrome/browser/resources/welcome/onboarding_welcome/shared/chooser_shared_css.html
@@ -0,0 +1,93 @@ +<link rel="import" href="chrome://resources/html/polymer.html"> + +<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html"> + +<dom-module id="chooser-shared-css"> + <template> + <style> + :host { + display: block; + white-space: nowrap; + } + + .option { + -webkit-appearance: none; + align-items: center; + background: white; + border: 1px solid transparent; + border-radius: 8px; + box-shadow: 0 1px 2px 0 rgba(0,36,100,0.30), + 0 2px 6px 2px rgba(0,36,100,0.15); + box-sizing: border-box; + display: inline-flex; + flex-direction: column; + height: 96px; + justify-content: center; + outline: 0; + position: relative; + vertical-align: bottom; + width: 120px; + } + + .option:not(:first-of-type) { + margin-inline-start: 24px; + } + + .option.keyboard-focused:focus { + outline: -webkit-focus-ring-color auto 5px; + } + + .option .option-name { + flex-grow: 0; + font-size: 0.875rem; + line-height: 1.25rem; + text-align: center; + white-space: normal; + } + + .option .option-icon { + background-position: center; + background-repeat: no-repeat; + background-size: contain; + height: 40px; + margin: 0; + margin-bottom: 4px; + width: 40px; + } + + .option iron-icon { + --iron-icon-fill-color: white; + background: lightgrey; + border-radius: 50%; + display: none; + height: 12px; + margin: 0; + position: absolute; + right: 10px; + top: 10px; + width: 12px; + } + + .option.keyboard-focused:focus iron-icon[icon='cr:check'], + .option:hover iron-icon[icon='cr:check'], + .option[active] iron-icon[icon='cr:check'] { + display: block; + } + + .option[active] { + border: 1px solid var(--google-blue-600); + color: var(--google-blue-600); + } + + .option[active] iron-icon[icon='cr:check'] { + background: var(--google-blue-600); + } + + .button-bar { + display: flex; + justify-content: space-between; + margin-top: 64px; + } + </style> + </template> +</dom-module> \ No newline at end of file
diff --git a/chrome/browser/sessions/session_service.cc b/chrome/browser/sessions/session_service.cc index 0cdcf11..84bdcf8 100644 --- a/chrome/browser/sessions/session_service.cc +++ b/chrome/browser/sessions/session_service.cc
@@ -124,8 +124,9 @@ return false; } -bool SessionService::RestoreIfNecessary(const std::vector<GURL>& urls_to_open) { - return RestoreIfNecessary(urls_to_open, NULL); +bool SessionService::RestoreIfNecessary(const base::CommandLine& command_line, + const std::vector<GURL>& urls_to_open) { + return RestoreIfNecessary(command_line, urls_to_open, NULL); } void SessionService::ResetFromCurrentBrowsers() { @@ -230,7 +231,8 @@ if (!ShouldTrackBrowser(browser)) return; - RestoreIfNecessary(std::vector<GURL>(), browser); + RestoreIfNecessary(*base::CommandLine::ForCurrentProcess(), + std::vector<GURL>(), browser); SetWindowType(browser->session_id(), browser->type(), browser->is_app() ? TYPE_APP : TYPE_NORMAL); @@ -566,7 +568,8 @@ } } -bool SessionService::RestoreIfNecessary(const std::vector<GURL>& urls_to_open, +bool SessionService::RestoreIfNecessary(const base::CommandLine& command_line, + const std::vector<GURL>& urls_to_open, Browser* browser) { if (ShouldNewWindowStartSession()) { // We're going from no tabbed browsers to a tabbed browser (and not in @@ -576,8 +579,8 @@ MoveCurrentSessionToLastSession(); move_on_new_browser_ = false; } - SessionStartupPref pref = StartupBrowserCreator::GetSessionStartupPref( - *base::CommandLine::ForCurrentProcess(), profile()); + SessionStartupPref pref = + StartupBrowserCreator::GetSessionStartupPref(command_line, profile()); sessions::TabRestoreService* tab_restore_service = TabRestoreServiceFactory::GetForProfileIfExisting(profile()); if (pref.type == SessionStartupPref::LAST &&
diff --git a/chrome/browser/sessions/session_service.h b/chrome/browser/sessions/session_service.h index 3c42ba4e..02a8676 100644 --- a/chrome/browser/sessions/session_service.h +++ b/chrome/browser/sessions/session_service.h
@@ -28,6 +28,10 @@ class Profile; +namespace base { +class CommandLine; +} // namespace base + namespace content { class WebContents; } // namespace content @@ -89,8 +93,11 @@ // during startup and window creation this is invoked to see if a session // needs to be restored. If a session needs to be restored it is done so // asynchronously and true is returned. If false is returned the session was - // not restored and the caller needs to create a new window. - bool RestoreIfNecessary(const std::vector<GURL>& urls_to_open); + // not restored and the caller needs to create a new window. The command_line + // should be the one of the original process that lead to opening the window + // and deciding whether the session needs to be restored. + bool RestoreIfNecessary(const base::CommandLine& command_line, + const std::vector<GURL>& urls_to_open); // Resets the contents of the file from the current state of all open // browsers whose profile matches our profile. @@ -247,7 +254,8 @@ // Implementation of RestoreIfNecessary. If |browser| is non-null and we need // to restore, the tabs are added to it, otherwise a new browser is created. - bool RestoreIfNecessary(const std::vector<GURL>& urls_to_open, + bool RestoreIfNecessary(const base::CommandLine& command_line, + const std::vector<GURL>& urls_to_open, Browser* browser); // BrowserListObserver
diff --git a/chrome/browser/ui/bookmarks/recently_used_folders_combo_model.cc b/chrome/browser/ui/bookmarks/recently_used_folders_combo_model.cc index d5f4bb0..5d25f8e0 100644 --- a/chrome/browser/ui/bookmarks/recently_used_folders_combo_model.cc +++ b/chrome/browser/ui/bookmarks/recently_used_folders_combo_model.cc
@@ -88,10 +88,8 @@ items_.push_back(Item(NULL, Item::TYPE_SEPARATOR)); items_.push_back(Item(NULL, Item::TYPE_CHOOSE_ANOTHER_FOLDER)); - std::vector<Item>::iterator it = std::find(items_.begin(), - items_.end(), - Item(node->parent(), - Item::TYPE_NODE)); + auto it = std::find(items_.begin(), items_.end(), + Item(node->parent(), Item::TYPE_NODE)); node_parent_index_ = static_cast<int>(it - items_.begin()); } @@ -166,8 +164,7 @@ // Changing is rare enough that we don't attempt to readjust the contents. // Update |items_| so we aren't left pointing to a deleted node. bool changed = false; - for (std::vector<Item>::iterator i = items_.begin(); - i != items_.end();) { + for (auto i = items_.begin(); i != items_.end();) { if (i->type == Item::TYPE_NODE && i->node->HasAncestor(node)) { i = items_.erase(i); changed = true; @@ -209,8 +206,7 @@ // Changing is rare enough that we don't attempt to readjust the contents. // Update |items_| so we aren't left pointing to a deleted node. bool changed = false; - for (std::vector<Item>::iterator i = items_.begin(); - i != items_.end();) { + for (auto i = items_.begin(); i != items_.end();) { if (i->type == Item::TYPE_NODE && !bookmark_model_->is_permanent_node(i->node)) { i = items_.erase(i); @@ -245,9 +241,8 @@ } void RecentlyUsedFoldersComboModel::RemoveNode(const BookmarkNode* node) { - std::vector<Item>::iterator it = std::find(items_.begin(), - items_.end(), - Item(node, Item::TYPE_NODE)); + auto it = + std::find(items_.begin(), items_.end(), Item(node, Item::TYPE_NODE)); if (it != items_.end()) items_.erase(it); }
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc index 15a93429..0879266 100644 --- a/chrome/browser/ui/browser.cc +++ b/chrome/browser/ui/browser.cc
@@ -2392,7 +2392,7 @@ if (!contents) return; - UpdateMap::iterator i = scheduled_updates_.find(contents); + auto i = scheduled_updates_.find(contents); if (i != scheduled_updates_.end()) scheduled_updates_.erase(i); }
diff --git a/chrome/browser/ui/browser_commands.cc b/chrome/browser/ui/browser_commands.cc index 1b80948..2b03134 100644 --- a/chrome/browser/ui/browser_commands.cc +++ b/chrome/browser/ui/browser_commands.cc
@@ -403,7 +403,8 @@ SessionServiceFactory::GetForProfileForSessionRestore( profile->GetOriginalProfile()); if (!session_service || - !session_service->RestoreIfNecessary(std::vector<GURL>())) { + !session_service->RestoreIfNecessary( + *base::CommandLine::ForCurrentProcess(), std::vector<GURL>())) { OpenEmptyWindow(profile->GetOriginalProfile()); } }
diff --git a/chrome/browser/ui/browser_finder.cc b/chrome/browser/ui/browser_finder.cc index 5853b30..d11d741 100644 --- a/chrome/browser/ui/browser_finder.cc +++ b/chrome/browser/ui/browser_finder.cc
@@ -152,8 +152,8 @@ BrowserList* browser_list_impl = BrowserList::GetInstance(); size_t count = 0; if (browser_list_impl) { - for (BrowserList::const_iterator i = browser_list_impl->begin(); - i != browser_list_impl->end(); ++i) { + for (auto i = browser_list_impl->begin(); i != browser_list_impl->end(); + ++i) { if (BrowserMatches(*i, profile, Browser::FEATURE_NONE, match_types, display_id)) count++;
diff --git a/chrome/browser/ui/browser_list.cc b/chrome/browser/ui/browser_list.cc index 244c5c21..e00c780 100644 --- a/chrome/browser/ui/browser_list.cc +++ b/chrome/browser/ui/browser_list.cc
@@ -180,8 +180,8 @@ const CloseCallback& on_close_aborted, const base::FilePath& profile_path, const bool skip_beforeunload) { - for (BrowserVector::const_iterator it = browsers_to_close.begin(); - it != browsers_to_close.end(); ++it) { + for (auto it = browsers_to_close.begin(); it != browsers_to_close.end(); + ++it) { if ((*it)->TryToCloseWindow( skip_beforeunload, base::Bind(&BrowserList::PostTryToCloseBrowserWindow, @@ -220,8 +220,8 @@ profile_path, skip_beforeunload); } else if (!resetting_handlers) { base::AutoReset<bool> resetting_handlers_scoper(&resetting_handlers, true); - for (BrowserVector::const_iterator it = browsers_to_close.begin(); - it != browsers_to_close.end(); ++it) { + for (auto it = browsers_to_close.begin(); it != browsers_to_close.end(); + ++it) { (*it)->ResetTryToCloseWindow(); } if (on_close_aborted) @@ -333,7 +333,7 @@ // static void BrowserList::RemoveBrowserFrom(Browser* browser, BrowserVector* browser_list) { - BrowserVector::iterator remove_browser = + auto remove_browser = std::find(browser_list->begin(), browser_list->end(), browser); if (remove_browser != browser_list->end()) browser_list->erase(remove_browser);
diff --git a/chrome/browser/ui/fast_unload_controller.cc b/chrome/browser/ui/fast_unload_controller.cc index 7fa178a..7c259975 100644 --- a/chrome/browser/ui/fast_unload_controller.cc +++ b/chrome/browser/ui/fast_unload_controller.cc
@@ -243,8 +243,8 @@ DCHECK(is_attempting_to_close_browser_); tabs_needing_before_unload_.clear(); CancelTabNeedingBeforeUnloadAck(); - for (WebContentsSet::iterator it = tabs_needing_unload_.begin(); - it != tabs_needing_unload_.end(); it++) { + for (auto it = tabs_needing_unload_.begin(); it != tabs_needing_unload_.end(); + it++) { content::WebContents* contents = *it; CoreTabHelper* core_tab_helper = CoreTabHelper::FromWebContents(contents); @@ -403,7 +403,7 @@ tabs_needing_before_unload_.end()); tabs_needing_before_unload_.clear(); } else { - WebContentsSet::iterator it = tabs_needing_before_unload_.begin(); + auto it = tabs_needing_before_unload_.begin(); content::WebContents* contents = *it; tabs_needing_before_unload_.erase(it); // Null check render_view_host here as this gets called on a PostTask and @@ -445,9 +445,9 @@ browser_->OnWindowClosing(); // Run unload handlers detached since no more interaction is possible. - WebContentsSet::iterator it = tabs_needing_unload_.begin(); + auto it = tabs_needing_unload_.begin(); while (it != tabs_needing_unload_.end()) { - WebContentsSet::iterator current = it++; + auto current = it++; content::WebContents* contents = *current; tabs_needing_unload_.erase(current); // Null check render_view_host here as this gets called on a PostTask
diff --git a/chrome/browser/ui/hung_plugin_tab_helper.cc b/chrome/browser/ui/hung_plugin_tab_helper.cc index 47c5827..cb4ec669 100644 --- a/chrome/browser/ui/hung_plugin_tab_helper.cc +++ b/chrome/browser/ui/hung_plugin_tab_helper.cc
@@ -122,8 +122,7 @@ // For now, just do a brute-force search to see if we have this plugin. Since // we'll normally have 0 or 1, this is fast. - for (PluginStateMap::iterator i = hung_plugins_.begin(); - i != hung_plugins_.end(); ++i) { + for (auto i = hung_plugins_.begin(); i != hung_plugins_.end(); ++i) { if (i->second->path == plugin_path) { if (i->second->infobar) infobar_service->RemoveInfoBar(i->second->infobar); @@ -144,7 +143,7 @@ if (!infobar_observer_.IsObserving(infobar_service)) infobar_observer_.Add(infobar_service); - PluginStateMap::iterator found = hung_plugins_.find(plugin_child_id); + auto found = hung_plugins_.find(plugin_child_id); if (found != hung_plugins_.end()) { if (!is_hung) { // Hung plugin became un-hung, close the infobar and delete our info. @@ -191,7 +190,7 @@ } void HungPluginTabHelper::KillPlugin(int child_id) { - PluginStateMap::iterator found = hung_plugins_.find(child_id); + auto found = hung_plugins_.find(child_id); DCHECK(found != hung_plugins_.end()); base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO}, @@ -202,7 +201,7 @@ void HungPluginTabHelper::OnReshowTimer(int child_id) { // The timer should have been cancelled if the record isn't in our map // anymore. - PluginStateMap::iterator found = hung_plugins_.find(child_id); + auto found = hung_plugins_.find(child_id); DCHECK(found != hung_plugins_.end()); DCHECK(!found->second->infobar); ShowBar(child_id, found->second.get());
diff --git a/chrome/browser/ui/input_method/input_method_engine_base.cc b/chrome/browser/ui/input_method/input_method_engine_base.cc index 91de5a4..1265386 100644 --- a/chrome/browser/ui/input_method/input_method_engine_base.cc +++ b/chrome/browser/ui/input_method/input_method_engine_base.cc
@@ -204,8 +204,7 @@ composition_text_->selection.set_end(selection_end); // TODO: Add support for displaying selected text in the composition string. - for (std::vector<SegmentInfo>::const_iterator segment = segments.begin(); - segment != segments.end(); ++segment) { + for (auto segment = segments.begin(); segment != segments.end(); ++segment) { ui::ImeTextSpan ime_text_span; ime_text_span.underline_color = SK_ColorTRANSPARENT; @@ -410,7 +409,7 @@ composition_changed_ = false; } - RequestMap::iterator request = request_map_.find(request_id); + auto request = request_map_.find(request_id); if (request == request_map_.end()) { LOG(ERROR) << "Request ID not found: " << request_id; return;
diff --git a/chrome/browser/ui/libgtkui/gtk_ui.cc b/chrome/browser/ui/libgtkui/gtk_ui.cc index e1dffee8..1fa492ec 100644 --- a/chrome/browser/ui/libgtkui/gtk_ui.cc +++ b/chrome/browser/ui/libgtkui/gtk_ui.cc
@@ -476,7 +476,7 @@ {colors_, pref_service->GetBoolean(prefs::kUseCustomChromeFrame) ? custom_frame_colors_ : native_frame_colors_}) { - ColorMap::const_iterator it = color_map.find(id); + auto it = color_map.find(id); if (it != color_map.end()) { *color = it->second; return true;
diff --git a/chrome/browser/ui/libgtkui/menu_util.cc b/chrome/browser/ui/libgtkui/menu_util.cc index f61b49ce..1c11cb6 100644 --- a/chrome/browser/ui/libgtkui/menu_util.cc +++ b/chrome/browser/ui/libgtkui/menu_util.cc
@@ -125,8 +125,7 @@ break; case ui::MenuModel::TYPE_RADIO: { - std::map<int, GtkWidget*>::iterator iter = - radio_groups.find(model->GetGroupIdAt(i)); + auto iter = radio_groups.find(model->GetGroupIdAt(i)); if (iter == radio_groups.end()) { menu_item =
diff --git a/chrome/browser/ui/login/login_handler_browsertest.cc b/chrome/browser/ui/login/login_handler_browsertest.cc index db69dfd..51be03f 100644 --- a/chrome/browser/ui/login/login_handler_browsertest.cc +++ b/chrome/browser/ui/login/login_handler_browsertest.cc
@@ -97,7 +97,7 @@ const net::AuthChallengeInfo* challenge = handler->auth_info(); ASSERT_TRUE(challenge); - AuthMap::iterator i = auth_map_.find(challenge->realm); + auto i = auth_map_.find(challenge->realm); EXPECT_TRUE(auth_map_.end() != i); if (i != auth_map_.end()) { const AuthInfo& info = i->second;
diff --git a/chrome/browser/ui/login/login_handler_test_utils.cc b/chrome/browser/ui/login/login_handler_test_utils.cc index 0191348..b7b6bd01 100644 --- a/chrome/browser/ui/login/login_handler_test_utils.cc +++ b/chrome/browser/ui/login/login_handler_test_utils.cc
@@ -38,8 +38,7 @@ } void LoginPromptBrowserTestObserver::RemoveHandler(LoginHandler* handler) { - std::list<LoginHandler*>::iterator i = - std::find(handlers_.begin(), handlers_.end(), handler); + auto i = std::find(handlers_.begin(), handlers_.end(), handler); // Cannot use ASSERT_NE, because gTest on Android confuses iterators with // containers. ASSERT_TRUE(i != handlers_.end());
diff --git a/chrome/browser/ui/passwords/password_manager_presenter.cc b/chrome/browser/ui/passwords/password_manager_presenter.cc index cbd01dda..5b65052 100644 --- a/chrome/browser/ui/passwords/password_manager_presenter.cc +++ b/chrome/browser/ui/passwords/password_manager_presenter.cc
@@ -55,8 +55,7 @@ std::pair<password_manager::DuplicatesMap::iterator, password_manager::DuplicatesMap::iterator> dups = duplicates->equal_range(key); - for (password_manager::DuplicatesMap::iterator it = dups.first; - it != dups.second; ++it) + for (auto it = dups.first; it != dups.second; ++it) store->RemoveLogin(*it->second); duplicates->erase(key); }
diff --git a/chrome/browser/ui/startup/startup_browser_creator.cc b/chrome/browser/ui/startup/startup_browser_creator.cc index 7ace08e..fd89147b9 100644 --- a/chrome/browser/ui/startup/startup_browser_creator.cc +++ b/chrome/browser/ui/startup/startup_browser_creator.cc
@@ -176,7 +176,7 @@ // Check that browsers have been opened for all the launched profiles. // Note that browsers opened for profiles that were not added as launched // profiles are simply ignored. - std::set<const Profile*>::const_iterator i = launched_profiles_.begin(); + auto i = launched_profiles_.begin(); for (; i != launched_profiles_.end(); ++i) { if (opened_profiles_.find(*i) == opened_profiles_.end()) return; @@ -807,14 +807,14 @@ size_t DEBUG_num_profiles_at_loop_start = std::numeric_limits<size_t>::max(); base::debug::Alias(&DEBUG_num_profiles_at_loop_start); - Profiles::const_iterator DEBUG_it_begin = last_opened_profiles.begin(); + auto DEBUG_it_begin = last_opened_profiles.begin(); base::debug::Alias(&DEBUG_it_begin); - Profiles::const_iterator DEBUG_it_end = last_opened_profiles.end(); + auto DEBUG_it_end = last_opened_profiles.end(); base::debug::Alias(&DEBUG_it_end); // Launch the profiles in the order they became active. - for (Profiles::const_iterator it = last_opened_profiles.begin(); - it != last_opened_profiles.end(); ++it, ++DEBUG_loop_counter) { + for (auto it = last_opened_profiles.begin(); it != last_opened_profiles.end(); + ++it, ++DEBUG_loop_counter) { DEBUG_num_profiles_at_loop_start = last_opened_profiles.size(); DCHECK(!(*it)->IsGuestSession());
diff --git a/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc b/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc index 6a3cf24..1f39df30 100644 --- a/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc +++ b/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
@@ -1361,6 +1361,45 @@ tab_strip->GetWebContentsAt(0)->GetURL().ExtractFileName()); } +class StartupIncognitoBrowserCreatorTest : public InProcessBrowserTest { + protected: + StartupIncognitoBrowserCreatorTest() = default; + + void SetUpCommandLine(base::CommandLine* command_line) override { + command_line->AppendSwitch(switches::kIncognito); + } + + private: + DISALLOW_COPY_AND_ASSIGN(StartupIncognitoBrowserCreatorTest); +}; + +IN_PROC_BROWSER_TEST_F(StartupIncognitoBrowserCreatorTest, + IncognitoStartupThenNormalStartup) { + ProfileManager* profile_manager = g_browser_process->profile_manager(); + base::FilePath dest_path = profile_manager->user_data_dir(); + Profile* profile = nullptr; + { + base::ScopedAllowBlockingForTesting allow_blocking; + profile = Profile::CreateProfile( + dest_path.Append(FILE_PATH_LITERAL("New Profile 1")), nullptr, + Profile::CreateMode::CREATE_MODE_SYNCHRONOUS); + } + ASSERT_TRUE(profile); + profile_manager->RegisterTestingProfile(profile, true, false); + SessionStartupPref::SetStartupPref( + profile, SessionStartupPref(SessionStartupPref::LAST)); + + EXPECT_FALSE(profile->restored_last_session()); + + base::CommandLine dummy(base::CommandLine::NO_PROGRAM); + StartupBrowserCreatorImpl creator(base::FilePath(), dummy, + chrome::startup::IS_NOT_FIRST_RUN); + + EXPECT_TRUE(creator.Launch(profile, {}, false)); + + EXPECT_TRUE(profile->restored_last_session()); +} + #endif // !defined(OS_CHROMEOS) class StartupBrowserCreatorWelcomeBackTest : public InProcessBrowserTest {
diff --git a/chrome/browser/ui/startup/startup_browser_creator_impl.cc b/chrome/browser/ui/startup/startup_browser_creator_impl.cc index 5da96407..3202d12 100644 --- a/chrome/browser/ui/startup/startup_browser_creator_impl.cc +++ b/chrome/browser/ui/startup/startup_browser_creator_impl.cc
@@ -719,7 +719,8 @@ SessionService* service = SessionServiceFactory::GetForProfileForSessionRestore(profile_); - return service && service->RestoreIfNecessary(TabsToUrls(tabs)); + return service && + service->RestoreIfNecessary(command_line_, TabsToUrls(tabs)); } Browser* StartupBrowserCreatorImpl::RestoreOrCreateBrowser(
diff --git a/chrome/browser/ui/tabs/pinned_tab_codec.cc b/chrome/browser/ui/tabs/pinned_tab_codec.cc index d801d94..a012aedd 100644 --- a/chrome/browser/ui/tabs/pinned_tab_codec.cc +++ b/chrome/browser/ui/tabs/pinned_tab_codec.cc
@@ -111,7 +111,7 @@ ListPrefUpdate update(prefs, prefs::kPinnedTabs); base::ListValue* values = update.Get(); values->Clear(); - for (StartupTabs::const_iterator i = tabs.begin(); i != tabs.end(); ++i) + for (auto i = tabs.begin(); i != tabs.end(); ++i) EncodeTab(*i, values); }
diff --git a/chrome/browser/ui/tabs/tab_strip_model.cc b/chrome/browser/ui/tabs/tab_strip_model.cc index 4f73de0..bd6d83a6 100644 --- a/chrome/browser/ui/tabs/tab_strip_model.cc +++ b/chrome/browser/ui/tabs/tab_strip_model.cc
@@ -1106,8 +1106,7 @@ base::RecordAction(UserMetricsAction("TabContextMenu_MuteTabs")); else base::RecordAction(UserMetricsAction("TabContextMenu_UnmuteTabs")); - for (std::vector<int>::const_iterator i = indices.begin(); - i != indices.end(); ++i) { + for (auto i = indices.begin(); i != indices.end(); ++i) { chrome::SetTabAudioMuted(GetWebContentsAt(*i), mute, TabMutedReason::CONTEXT_MENU, std::string()); }
diff --git a/chrome/browser/ui/tabs/tab_utils.cc b/chrome/browser/ui/tabs/tab_utils.cc index 1111dc6..fa5e2ba 100644 --- a/chrome/browser/ui/tabs/tab_utils.cc +++ b/chrome/browser/ui/tabs/tab_utils.cc
@@ -135,8 +135,7 @@ bool AreAllTabsMuted(const TabStripModel& tab_strip, const std::vector<int>& indices) { - for (std::vector<int>::const_iterator i = indices.begin(); i != indices.end(); - ++i) { + for (auto i = indices.begin(); i != indices.end(); ++i) { if (!tab_strip.GetWebContentsAt(*i)->IsAudioMuted()) return false; }
diff --git a/chrome/browser/ui/toolbar/app_menu_model.cc b/chrome/browser/ui/toolbar/app_menu_model.cc index 5c2342b5..5db023f3 100644 --- a/chrome/browser/ui/toolbar/app_menu_model.cc +++ b/chrome/browser/ui/toolbar/app_menu_model.cc
@@ -877,8 +877,7 @@ const GlobalErrorService::GlobalErrorList& errors = GlobalErrorServiceFactory::GetForProfile(browser_->profile())->errors(); bool menu_items_added = false; - for (GlobalErrorService::GlobalErrorList::const_iterator it = errors.begin(); - it != errors.end(); ++it) { + for (auto it = errors.begin(); it != errors.end(); ++it) { GlobalError* error = *it; DCHECK(error); if (error->HasMenuItem()) {
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_bar.cc b/chrome/browser/ui/toolbar/toolbar_actions_bar.cc index d65c2ba..23ab254 100644 --- a/chrome/browser/ui/toolbar/toolbar_actions_bar.cc +++ b/chrome/browser/ui/toolbar/toolbar_actions_bar.cc
@@ -636,7 +636,7 @@ } void ToolbarActionsBar::OnToolbarActionRemoved(const std::string& action_id) { - ToolbarActions::iterator iter = toolbar_actions_.begin(); + auto iter = toolbar_actions_.begin(); while (iter != toolbar_actions_.end() && (*iter)->GetId() != action_id) ++iter;
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_model.cc b/chrome/browser/ui/toolbar/toolbar_actions_model.cc index 11f6d77..92f29161 100644 --- a/chrome/browser/ui/toolbar/toolbar_actions_model.cc +++ b/chrome/browser/ui/toolbar/toolbar_actions_model.cc
@@ -92,7 +92,7 @@ } void ToolbarActionsModel::MoveActionIcon(const std::string& id, size_t index) { - std::vector<ToolbarItem>::iterator pos = toolbar_items_.begin(); + auto pos = toolbar_items_.begin(); while (pos != toolbar_items_.end() && (*pos).id != id) ++pos; if (pos == toolbar_items_.end()) { @@ -103,7 +103,7 @@ ToolbarItem action = *pos; toolbar_items_.erase(pos); - std::vector<std::string>::iterator pos_id = + auto pos_id = std::find(last_known_positions_.begin(), last_known_positions_.end(), id); if (pos_id != last_known_positions_.end()) last_known_positions_.erase(pos_id); @@ -112,7 +112,7 @@ // If the index is not at the end, find the item currently at |index|, and // insert |action| before it in |toolbar_items_| and |action|'s id in // |last_known_positions_|. - std::vector<ToolbarItem>::iterator iter = toolbar_items_.begin() + index; + auto iter = toolbar_items_.begin() + index; last_known_positions_.insert( std::find(last_known_positions_.begin(), last_known_positions_.end(), iter->id), @@ -245,8 +245,8 @@ } void ToolbarActionsModel::RemovePref(const ToolbarItem& item) { - std::vector<std::string>::iterator pos = std::find( - last_known_positions_.begin(), last_known_positions_.end(), item.id); + auto pos = std::find(last_known_positions_.begin(), + last_known_positions_.end(), item.id); if (pos != last_known_positions_.end()) { last_known_positions_.erase(pos); @@ -387,8 +387,7 @@ } void ToolbarActionsModel::RemoveItem(const ToolbarItem& item) { - std::vector<ToolbarItem>::iterator pos = - std::find(toolbar_items_.begin(), toolbar_items_.end(), item); + auto pos = std::find(toolbar_items_.begin(), toolbar_items_.end(), item); if (pos == toolbar_items_.end()) return; @@ -654,8 +653,7 @@ std::set<std::string> component_ids = component_actions_factory_->GetInitialComponentIds(); - for (std::vector<ToolbarItem>::const_iterator iter = - original_model->toolbar_items_.begin(); + for (auto iter = original_model->toolbar_items_.begin(); iter != original_model->toolbar_items_.end(); ++iter) { // The extension might not be shown in incognito mode. // We may also disable certain component actions in incognito mode.
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_model_unittest.cc b/chrome/browser/ui/toolbar/toolbar_actions_model_unittest.cc index a086bce..8060033 100644 --- a/chrome/browser/ui/toolbar/toolbar_actions_model_unittest.cc +++ b/chrome/browser/ui/toolbar/toolbar_actions_model_unittest.cc
@@ -348,8 +348,7 @@ testing::AssertionResult ToolbarActionsModelUnitTest::AddAndVerifyExtensions( const extensions::ExtensionList& extensions) { - for (extensions::ExtensionList::const_iterator iter = extensions.begin(); - iter != extensions.end(); ++iter) { + for (auto iter = extensions.begin(); iter != extensions.end(); ++iter) { if (!AddExtension(*iter)) { return testing::AssertionFailure() << "Failed to install extension: " << (*iter)->name();
diff --git a/chrome/browser/ui/unload_controller.cc b/chrome/browser/ui/unload_controller.cc index c963f06a..07fab9b 100644 --- a/chrome/browser/ui/unload_controller.cc +++ b/chrome/browser/ui/unload_controller.cc
@@ -208,8 +208,8 @@ // Closing of window can be canceled from a beforeunload handler. DCHECK(is_attempting_to_close_browser_); tabs_needing_before_unload_fired_.clear(); - for (UnloadListenerSet::iterator it = tabs_needing_unload_fired_.begin(); - it != tabs_needing_unload_fired_.end(); ++it) { + for (auto it = tabs_needing_unload_fired_.begin(); + it != tabs_needing_unload_fired_.end(); ++it) { DevToolsWindow::OnPageCloseCanceled(*it); } tabs_needing_unload_fired_.clear(); @@ -372,8 +372,7 @@ content::WebContents* web_contents) { DCHECK(is_attempting_to_close_browser_); - UnloadListenerSet::iterator iter = - std::find(set->begin(), set->end(), web_contents); + auto iter = std::find(set->begin(), set->end(), web_contents); if (iter != set->end()) { set->erase(iter); return true;
diff --git a/chrome/browser/ui/views/accelerator_table_unittest.cc b/chrome/browser/ui/views/accelerator_table_unittest.cc index 167d72a6d..7862e6d 100644 --- a/chrome/browser/ui/views/accelerator_table_unittest.cc +++ b/chrome/browser/ui/views/accelerator_table_unittest.cc
@@ -34,8 +34,7 @@ TEST(AcceleratorTableTest, CheckDuplicatedAccelerators) { std::set<AcceleratorMapping, Cmp> accelerators; const std::vector<AcceleratorMapping> accelerator_list(GetAcceleratorList()); - for (std::vector<AcceleratorMapping>::const_iterator it = - accelerator_list.begin(); it != accelerator_list.end(); ++it) { + for (auto it = accelerator_list.begin(); it != accelerator_list.end(); ++it) { const AcceleratorMapping& entry = *it; EXPECT_TRUE(accelerators.insert(entry).second) << "Duplicated accelerator: " << entry.keycode << ", "
diff --git a/chrome/browser/ui/views/apps/chrome_native_app_window_views.cc b/chrome/browser/ui/views/apps/chrome_native_app_window_views.cc index aeb2507..2872ac7 100644 --- a/chrome/browser/ui/views/apps/chrome_native_app_window_views.cc +++ b/chrome/browser/ui/views/apps/chrome_native_app_window_views.cc
@@ -172,9 +172,8 @@ CHECK(!is_kiosk_app_mode || zoom::ZoomController::FromWebContents(web_view()->GetWebContents())); - for (std::map<ui::Accelerator, int>::const_iterator iter = - accelerator_table.begin(); - iter != accelerator_table.end(); ++iter) { + for (auto iter = accelerator_table.begin(); iter != accelerator_table.end(); + ++iter) { if (is_kiosk_app_mode && !chrome::IsCommandAllowedInAppMode(iter->second)) continue; @@ -277,8 +276,7 @@ const ui::Accelerator& accelerator) { const std::map<ui::Accelerator, int>& accelerator_table = GetAcceleratorTable(); - std::map<ui::Accelerator, int>::const_iterator iter = - accelerator_table.find(accelerator); + auto iter = accelerator_table.find(accelerator); DCHECK(iter != accelerator_table.end()); int command_id = iter->second; switch (command_id) {
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_editor_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_editor_view.cc index ddaf3da..972e9edb 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_editor_view.cc +++ b/chrome/browser/ui/views/bookmarks/bookmark_editor_view.cc
@@ -475,8 +475,7 @@ void BookmarkEditorView::ExpandAndSelect() { BookmarkExpandedStateTracker::Nodes expanded_nodes = bb_model_->expanded_state_tracker()->GetExpandedNodes(); - for (BookmarkExpandedStateTracker::Nodes::const_iterator i( - expanded_nodes.begin()); i != expanded_nodes.end(); ++i) { + for (auto i(expanded_nodes.begin()); i != expanded_nodes.end(); ++i) { EditorNode* editor_node = FindNodeWithID(tree_model_->GetRoot(), (*i)->id()); if (editor_node)
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.cc b/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.cc index 558107a6..865946e8 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.cc +++ b/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.cc
@@ -145,7 +145,7 @@ base::string16 BookmarkMenuDelegate::GetTooltipText( int id, const gfx::Point& screen_loc) const { - MenuIDToNodeMap::const_iterator i = menu_id_to_node_map_.find(id); + auto i = menu_id_to_node_map_.find(id); // When removing bookmarks it may be possible to end up here without a node. if (i == menu_id_to_node_map_.end()) { DCHECK(is_mutating_model_); @@ -372,7 +372,7 @@ void BookmarkMenuDelegate::BookmarkNodeFaviconChanged( BookmarkModel* model, const BookmarkNode* node) { - NodeToMenuMap::iterator menu_pair = node_to_menu_map_.find(node); + auto menu_pair = node_to_menu_map_.find(node); if (menu_pair == node_to_menu_map_.end()) return; // We're not showing a menu item for the node. @@ -396,9 +396,8 @@ // Remove the menu items. std::set<MenuItemView*> changed_parent_menus; - for (std::vector<const BookmarkNode*>::const_iterator i(bookmarks.begin()); - i != bookmarks.end(); ++i) { - NodeToMenuMap::iterator node_to_menu = node_to_menu_map_.find(*i); + for (auto i(bookmarks.begin()); i != bookmarks.end(); ++i) { + auto node_to_menu = node_to_menu_map_.find(*i); if (node_to_menu != node_to_menu_map_.end()) { MenuItemView* menu = node_to_menu->second; MenuItemView* parent = menu->GetParentMenuItem(); @@ -420,11 +419,9 @@ DCHECK_LE(changed_parent_menus.size(), 1U); // Remove any descendants of the removed nodes in |node_to_menu_map_|. - for (NodeToMenuMap::iterator i(node_to_menu_map_.begin()); - i != node_to_menu_map_.end(); ) { + for (auto i(node_to_menu_map_.begin()); i != node_to_menu_map_.end();) { bool ancestor_removed = false; - for (std::vector<const BookmarkNode*>::const_iterator j(bookmarks.begin()); - j != bookmarks.end(); ++j) { + for (auto j(bookmarks.begin()); j != bookmarks.end(); ++j) { if (i->first->HasAncestor(*j)) { ancestor_removed = true; break; @@ -438,8 +435,8 @@ } } - for (std::set<MenuItemView*>::const_iterator i(changed_parent_menus.begin()); - i != changed_parent_menus.end(); ++i) + for (auto i(changed_parent_menus.begin()); i != changed_parent_menus.end(); + ++i) (*i)->ChildrenChanged(); }
diff --git a/chrome/browser/ui/views/content_setting_bubble_contents.cc b/chrome/browser/ui/views/content_setting_bubble_contents.cc index 25e4fc4..064bb43 100644 --- a/chrome/browser/ui/views/content_setting_bubble_contents.cc +++ b/chrome/browser/ui/views/content_setting_bubble_contents.cc
@@ -466,8 +466,7 @@ const ContentSettingBubbleModel::RadioGroup& radio_group = bubble_content.radio_group; if (!radio_group.radio_items.empty()) { - for (ContentSettingBubbleModel::RadioItems::const_iterator i( - radio_group.radio_items.begin()); + for (auto i(radio_group.radio_items.begin()); i != radio_group.radio_items.end(); ++i) { auto radio = std::make_unique<views::RadioButton>(*i, 0); radio->SetEnabled(bubble_content.radio_group_enabled); @@ -488,8 +487,7 @@ LayoutRowType::INDENTED}); } - for (std::vector<ContentSettingBubbleModel::DomainList>::const_iterator i( - bubble_content.domain_lists.begin()); + for (auto i(bubble_content.domain_lists.begin()); i != bubble_content.domain_lists.end(); ++i) { auto list_view = std::make_unique<ContentSettingDomainListView>(i->title, i->hosts);
diff --git a/chrome/browser/ui/views/desktop_capture/desktop_media_source_view.cc b/chrome/browser/ui/views/desktop_capture/desktop_media_source_view.cc index 705715f3..7af8468c 100644 --- a/chrome/browser/ui/views/desktop_capture/desktop_media_source_view.cc +++ b/chrome/browser/ui/views/desktop_capture/desktop_media_source_view.cc
@@ -83,7 +83,7 @@ // Unselect all other sources. Views neighbours; parent()->GetViewsInGroup(GetGroup(), &neighbours); - for (Views::iterator i(neighbours.begin()); i != neighbours.end(); ++i) { + for (auto i(neighbours.begin()); i != neighbours.end(); ++i) { if (*i != this) { DCHECK_EQ((*i)->GetClassName(), DesktopMediaSourceView::kDesktopMediaSourceViewClassName); @@ -134,7 +134,7 @@ if (neighbours.empty()) return nullptr; - for (Views::iterator i(neighbours.begin()); i != neighbours.end(); ++i) { + for (auto i(neighbours.begin()); i != neighbours.end(); ++i) { DCHECK_EQ((*i)->GetClassName(), DesktopMediaSourceView::kDesktopMediaSourceViewClassName); DesktopMediaSourceView* source_view =
diff --git a/chrome/browser/ui/views/extensions/media_galleries_dialog_views.cc b/chrome/browser/ui/views/extensions/media_galleries_dialog_views.cc index fad9f3d..251aec72 100644 --- a/chrome/browser/ui/views/extensions/media_galleries_dialog_views.cc +++ b/chrome/browser/ui/views/extensions/media_galleries_dialog_views.cc
@@ -189,7 +189,7 @@ const MediaGalleriesDialogController::Entry& gallery, views::View* container, int trailing_vertical_space) { - CheckboxMap::iterator iter = checkbox_map_.find(gallery.pref_info.pref_id); + auto iter = checkbox_map_.find(gallery.pref_info.pref_id); if (iter != checkbox_map_.end()) { views::Checkbox* checkbox = iter->second->checkbox(); checkbox->SetChecked(gallery.selected);
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc index fa5eb90..8f629a37 100644 --- a/chrome/browser/ui/views/frame/browser_view.cc +++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -621,8 +621,8 @@ return true; #endif // Else, we retrieve the accelerator information from the accelerator table. - for (std::map<ui::Accelerator, int>::const_iterator it = - accelerator_table_.begin(); it != accelerator_table_.end(); ++it) { + for (auto it = accelerator_table_.begin(); it != accelerator_table_.end(); + ++it) { if (it->second == cmd_id) { *accelerator = it->first; return true; @@ -2984,8 +2984,7 @@ bool BrowserView::FindCommandIdForAccelerator( const ui::Accelerator& accelerator, int* command_id) const { - std::map<ui::Accelerator, int>::const_iterator iter = - accelerator_table_.find(accelerator); + auto iter = accelerator_table_.find(accelerator); if (iter == accelerator_table_.end()) return false;
diff --git a/chrome/browser/ui/views/frame/global_menu_bar_registrar_x11.cc b/chrome/browser/ui/views/frame/global_menu_bar_registrar_x11.cc index b112b0f..f6254b5 100644 --- a/chrome/browser/ui/views/frame/global_menu_bar_registrar_x11.cc +++ b/chrome/browser/ui/views/frame/global_menu_bar_registrar_x11.cc
@@ -135,8 +135,7 @@ GParamSpec* /* ignored */) { // If the name owner changed, we need to reregister all the live xids with // the system. - for (std::set<unsigned long>::const_iterator it = live_xids_.begin(); - it != live_xids_.end(); ++it) { + for (auto it = live_xids_.begin(); it != live_xids_.end(); ++it) { RegisterXID(*it); } }
diff --git a/chrome/browser/ui/views/frame/global_menu_bar_x11.cc b/chrome/browser/ui/views/frame/global_menu_bar_x11.cc index 0cddbcb..0f3e3885 100644 --- a/chrome/browser/ui/views/frame/global_menu_bar_x11.cc +++ b/chrome/browser/ui/views/frame/global_menu_bar_x11.cc
@@ -597,8 +597,7 @@ } void GlobalMenuBarX11::OnBookmarkBarVisibilityChanged() { - CommandIDMenuItemMap::iterator it = - id_to_menu_item_.find(IDC_SHOW_BOOKMARK_BAR); + auto it = id_to_menu_item_.find(IDC_SHOW_BOOKMARK_BAR); if (it != id_to_menu_item_.end()) { PrefService* prefs = browser_->profile()->GetPrefs(); // Note: Unlike the GTK version, we don't appear to need to do tricks where @@ -723,7 +722,7 @@ } void GlobalMenuBarX11::EnabledStateChangedForCommand(int id, bool enabled) { - CommandIDMenuItemMap::iterator it = id_to_menu_item_.find(id); + auto it = id_to_menu_item_.find(id); if (it != id_to_menu_item_.end()) menuitem_property_set_bool(it->second, kPropertyEnabled, enabled); } @@ -748,8 +747,7 @@ TAG_RECENTLY_CLOSED_HEADER) + 1; unsigned int added_count = 0; - for (sessions::TabRestoreService::Entries::const_iterator it = - entries.begin(); + for (auto it = entries.begin(); it != entries.end() && added_count < kRecentlyClosedCount; ++it) { sessions::TabRestoreService::Entry* entry = it->get();
diff --git a/chrome/browser/ui/views/infobars/alternate_nav_infobar_view.cc b/chrome/browser/ui/views/infobars/alternate_nav_infobar_view.cc index 347ef22..883a89c3 100644 --- a/chrome/browser/ui/views/infobars/alternate_nav_infobar_view.cc +++ b/chrome/browser/ui/views/infobars/alternate_nav_infobar_view.cc
@@ -57,7 +57,7 @@ views::Label* last_label = labels->back(); labels->pop_back(); int used_width = 0; - for (Labels::iterator i(labels->begin()); i != labels->end(); ++i) + for (auto i(labels->begin()); i != labels->end(); ++i) used_width += (*i)->GetPreferredSize().width(); int last_label_width = std::min(last_label->GetPreferredSize().width(), available_width - used_width);
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc index 2610875..c083a87a 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.cc +++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -1917,7 +1917,7 @@ TabStrip::FindClosingTabResult TabStrip::FindClosingTab(const Tab* tab) { DCHECK(tab->closing()); for (auto i = tabs_closing_map_.begin(); i != tabs_closing_map_.end(); ++i) { - Tabs::iterator j = std::find(i->second.begin(), i->second.end(), tab); + auto j = std::find(i->second.begin(), i->second.end(), tab); if (j != i->second.end()) return FindClosingTabResult(i, j); }
diff --git a/chrome/browser/ui/views/toolbar/app_menu.cc b/chrome/browser/ui/views/toolbar/app_menu.cc index 3ede94a..ef4d8ea 100644 --- a/chrome/browser/ui/views/toolbar/app_menu.cc +++ b/chrome/browser/ui/views/toolbar/app_menu.cc
@@ -762,8 +762,7 @@ // Remove all elements in |AppMenu::command_id_to_entry_| that map to // |model_|. - AppMenu::CommandIDToEntry::iterator iter = - app_menu_->command_id_to_entry_.begin(); + auto iter = app_menu_->command_id_to_entry_.begin(); while (iter != app_menu_->command_id_to_entry_.end()) { if (iter->second.first == model_) app_menu_->command_id_to_entry_.erase(iter++); @@ -1014,7 +1013,7 @@ return false; } - CommandIDToEntry::const_iterator ix = command_id_to_entry_.find(command_id); + auto ix = command_id_to_entry_.find(command_id); const Entry& entry = ix->second; ui::Accelerator menu_accelerator; if (!entry.first->GetAcceleratorAt(entry.second, &menu_accelerator)) @@ -1254,7 +1253,7 @@ } int AppMenu::ModelIndexFromCommandId(int command_id) const { - CommandIDToEntry::const_iterator ix = command_id_to_entry_.find(command_id); + auto ix = command_id_to_entry_.find(command_id); DCHECK(ix != command_id_to_entry_.end()); return ix->second.second; }
diff --git a/chrome/browser/ui/views/toolbar/browser_actions_container.cc b/chrome/browser/ui/views/toolbar/browser_actions_container.cc index b1f6bbf..404023b 100644 --- a/chrome/browser/ui/views/toolbar/browser_actions_container.cc +++ b/chrome/browser/ui/views/toolbar/browser_actions_container.cc
@@ -167,7 +167,7 @@ void BrowserActionsContainer::RemoveViewForAction( ToolbarActionViewController* action) { std::unique_ptr<ToolbarActionView> view; - for (ToolbarActionViews::iterator iter = toolbar_action_views_.begin(); + for (auto iter = toolbar_action_views_.begin(); iter != toolbar_action_views_.end(); ++iter) { if ((*iter)->view_controller() == action) { std::swap(view, *iter);
diff --git a/chrome/browser/ui/webui/welcome/welcome_ui.cc b/chrome/browser/ui/webui/welcome/welcome_ui.cc index 2c7a134..53ae802 100644 --- a/chrome/browser/ui/webui/welcome/welcome_ui.cc +++ b/chrome/browser/ui/webui/welcome/welcome_ui.cc
@@ -144,6 +144,11 @@ } #if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD) + // TODO(hcarmona): Move this behind nux::kNuxOnboardingFeature when email and + // apps experiments end. + html_source->AddResourcePath("shared/chooser_shared_css.html", + IDR_NUX_CHOOSER_SHARED_CSS); + if (base::FeatureList::IsEnabled(nux::kNuxOnboardingFeature)) { web_ui->AddMessageHandler(std::make_unique<nux::SetAsDefaultHandler>()); nux::SetAsDefaultHandler::AddSources(html_source);
diff --git a/chrome/browser/ui/window_sizer/window_sizer.cc b/chrome/browser/ui/window_sizer/window_sizer.cc index 66cebbb..22c00880 100644 --- a/chrome/browser/ui/window_sizer/window_sizer.cc +++ b/chrome/browser/ui/window_sizer/window_sizer.cc
@@ -98,8 +98,7 @@ window = browser_->window(); } else { const BrowserList* browser_list = BrowserList::GetInstance(); - for (BrowserList::const_reverse_iterator it = - browser_list->begin_last_active(); + for (auto it = browser_list->begin_last_active(); it != browser_list->end_last_active(); ++it) { Browser* last_active = *it; if (last_active && last_active->is_type_tabbed()) {
diff --git a/chrome/common/crash_keys.cc b/chrome/common/crash_keys.cc index 887e137..c54f40f 100644 --- a/chrome/common/crash_keys.cc +++ b/chrome/common/crash_keys.cc
@@ -98,7 +98,7 @@ {"extension-10", ExtensionIDKey::Tag::kArray}, }; - std::set<std::string>::const_iterator it = extensions.begin(); + auto it = extensions.begin(); for (size_t i = 0; i < arraysize(extension_ids); ++i) { if (it == extensions.end()) { extension_ids[i].Clear();
diff --git a/chrome/common/extensions/api/commands/commands_manifest_unittest.cc b/chrome/common/extensions/api/commands/commands_manifest_unittest.cc index c5f156d..12fde8b 100644 --- a/chrome/common/extensions/api/commands/commands_manifest_unittest.cc +++ b/chrome/common/extensions/api/commands/commands_manifest_unittest.cc
@@ -41,7 +41,7 @@ const CommandMap* commands = CommandsInfo::GetNamedCommands(extension.get()); ASSERT_TRUE(commands); ASSERT_EQ(1u, commands->size()); - CommandMap::const_iterator iter = commands->begin(); + auto iter = commands->begin(); ASSERT_TRUE(commands->end() != iter); const Command* named_command = &(*iter).second; ASSERT_STREQ("feature1", named_command->command_name().c_str());
diff --git a/chrome/common/extensions/api/common_extension_api_unittest.cc b/chrome/common/extensions/api/common_extension_api_unittest.cc index a37895e..4f5cce0 100644 --- a/chrome/common/extensions/api/common_extension_api_unittest.cc +++ b/chrome/common/extensions/api/common_extension_api_unittest.cc
@@ -429,8 +429,7 @@ manifest.SetInteger("manifest_version", 2); { std::unique_ptr<base::ListValue> permissions_list(new base::ListValue()); - for (std::set<std::string>::const_iterator i = permissions.begin(); - i != permissions.end(); ++i) { + for (auto i = permissions.begin(); i != permissions.end(); ++i) { permissions_list->AppendString(*i); } manifest.Set("permissions", std::move(permissions_list)); @@ -542,8 +541,7 @@ values.Set(manifest_keys::kApp, std::move(app)); { auto permissions_list = std::make_unique<base::ListValue>(); - for (std::set<std::string>::const_iterator i = permissions.begin(); - i != permissions.end(); ++i) { + for (auto i = permissions.begin(); i != permissions.end(); ++i) { permissions_list->AppendString(*i); } values.Set("permissions", std::move(permissions_list));
diff --git a/chrome/common/extensions/api/url_handlers/url_handlers_parser.cc b/chrome/common/extensions/api/url_handlers/url_handlers_parser.cc index d28fc9c9..701ec1b8 100644 --- a/chrome/common/extensions/api/url_handlers/url_handlers_parser.cc +++ b/chrome/common/extensions/api/url_handlers/url_handlers_parser.cc
@@ -128,8 +128,7 @@ return false; } - for (base::ListValue::const_iterator it = manif_patterns->begin(); - it != manif_patterns->end(); ++it) { + for (auto it = manif_patterns->begin(); it != manif_patterns->end(); ++it) { std::string str_pattern; it->GetAsString(&str_pattern); // TODO(sergeygs): Limit this to non-top-level domains.
diff --git a/chrome/common/extensions/chrome_extensions_client.cc b/chrome/common/extensions/chrome_extensions_client.cc index c38ad97..299f60c 100644 --- a/chrome/common/extensions/chrome_extensions_client.cc +++ b/chrome/common/extensions/chrome_extensions_client.cc
@@ -129,7 +129,7 @@ PermissionIDSet* permissions) const { // When editing this function, be sure to add the same functionality to // FilterHostPermissions() above. - for (URLPatternSet::const_iterator i = hosts.begin(); i != hosts.end(); ++i) { + for (auto i = hosts.begin(); i != hosts.end(); ++i) { // Filters out every URL pattern that matches chrome:// scheme. if (i->scheme() == content::kChromeUIScheme) { // chrome://favicon is the only URL for chrome:// scheme that we
diff --git a/chrome/common/extensions/command.cc b/chrome/common/extensions/command.cc index 1bc2d4a..a22cf55 100644 --- a/chrome/common/extensions/command.cc +++ b/chrome/common/extensions/command.cc
@@ -495,8 +495,7 @@ command->GetBoolean(keys::kGlobal, &global); // Normalize the suggestions. - for (SuggestionMap::iterator iter = suggestions.begin(); - iter != suggestions.end(); ++iter) { + for (auto iter = suggestions.begin(); iter != suggestions.end(); ++iter) { // Before we normalize Ctrl to Command we must detect when the developer // specified Command in the Default section, which will work on Mac after // normalization but only fail on other platforms when they try it out on
diff --git a/chrome/common/pepper_permission_util.cc b/chrome/common/pepper_permission_util.cc index 1d632ed..35bf998 100644 --- a/chrome/common/pepper_permission_util.cc +++ b/chrome/common/pepper_permission_util.cc
@@ -53,9 +53,7 @@ typedef std::vector<SharedModuleInfo::ImportInfo> ImportInfoVector; const ImportInfoVector& imports = SharedModuleInfo::GetImports(extension); - for (ImportInfoVector::const_iterator it = imports.begin(); - it != imports.end(); - ++it) { + for (auto it = imports.begin(); it != imports.end(); ++it) { const Extension* imported_extension = extension_set->GetByID(it->extension_id); if (imported_extension &&
diff --git a/chrome/renderer/chrome_render_frame_observer.cc b/chrome/renderer/chrome_render_frame_observer.cc index b1c6a400..6c45e54 100644 --- a/chrome/renderer/chrome_render_frame_observer.cc +++ b/chrome/renderer/chrome_render_frame_observer.cc
@@ -296,9 +296,7 @@ // any icon with a data URL to have originated from a favicon. We don't want // to decode arbitrary data URLs in the browser process. See // http://b/issue?id=1162972 - for (std::vector<WebApplicationInfo::IconInfo>::iterator it = - web_app_info.icons.begin(); - it != web_app_info.icons.end();) { + for (auto it = web_app_info.icons.begin(); it != web_app_info.icons.end();) { if (it->url.SchemeIs(url::kDataScheme)) it = web_app_info.icons.erase(it); else
diff --git a/chrome/renderer/extensions/cast_streaming_native_handler.cc b/chrome/renderer/extensions/cast_streaming_native_handler.cc index eb57fda..07f10e12 100644 --- a/chrome/renderer/extensions/cast_streaming_native_handler.cc +++ b/chrome/renderer/extensions/cast_streaming_native_handler.cc
@@ -741,8 +741,7 @@ v8::HandleScope handle_scope(isolate); v8::Context::Scope context_scope(context()->v8_context()); - RtpStreamCallbackMap::iterator it = - get_raw_events_callbacks_.find(transport_id); + auto it = get_raw_events_callbacks_.find(transport_id); if (it == get_raw_events_callbacks_.end()) return; v8::Local<v8::Value> callback_args[] = {V8ValueConverter::Create()->ToV8Value( @@ -759,7 +758,7 @@ v8::HandleScope handle_scope(isolate); v8::Context::Scope context_scope(context()->v8_context()); - RtpStreamCallbackMap::iterator it = get_stats_callbacks_.find(transport_id); + auto it = get_stats_callbacks_.find(transport_id); if (it == get_stats_callbacks_.end()) return; @@ -772,8 +771,7 @@ CastRtpStream* CastStreamingNativeHandler::GetRtpStreamOrThrow( int transport_id) const { - RtpStreamMap::const_iterator iter = rtp_stream_map_.find( - transport_id); + auto iter = rtp_stream_map_.find(transport_id); if (iter != rtp_stream_map_.end()) return iter->second.get(); v8::Isolate* isolate = context()->v8_context()->GetIsolate(); @@ -786,8 +784,7 @@ CastUdpTransport* CastStreamingNativeHandler::GetUdpTransportOrThrow( int transport_id) const { - UdpTransportMap::const_iterator iter = udp_transport_map_.find( - transport_id); + auto iter = udp_transport_map_.find(transport_id); if (iter != udp_transport_map_.end()) return iter->second.get(); v8::Isolate* isolate = context()->v8_context()->GetIsolate();
diff --git a/chrome/renderer/media/cast_transport_ipc.cc b/chrome/renderer/media/cast_transport_ipc.cc index 0a5cd51..7d9d41d 100644 --- a/chrome/renderer/media/cast_transport_ipc.cc +++ b/chrome/renderer/media/cast_transport_ipc.cc
@@ -137,7 +137,7 @@ } void CastTransportIPC::OnRtt(uint32_t rtp_sender_ssrc, base::TimeDelta rtt) { - ClientMap::iterator it = clients_.find(rtp_sender_ssrc); + auto it = clients_.find(rtp_sender_ssrc); if (it == clients_.end()) { LOG(ERROR) << "Received RTT report for unknown SSRC: " << rtp_sender_ssrc; return; @@ -148,7 +148,7 @@ void CastTransportIPC::OnRtcpCastMessage( uint32_t rtp_sender_ssrc, const media::cast::RtcpCastMessage& cast_message) { - ClientMap::iterator it = clients_.find(rtp_sender_ssrc); + auto it = clients_.find(rtp_sender_ssrc); if (it == clients_.end()) { LOG(ERROR) << "Received cast message for unknown SSRC: " << rtp_sender_ssrc; return; @@ -157,7 +157,7 @@ } void CastTransportIPC::OnReceivedPli(uint32_t rtp_sender_ssrc) { - ClientMap::iterator it = clients_.find(rtp_sender_ssrc); + auto it = clients_.find(rtp_sender_ssrc); if (it == clients_.end()) { LOG(ERROR) << "Received picture loss indicator for unknown SSRC: " << rtp_sender_ssrc;
diff --git a/chrome/renderer/net/net_error_helper.cc b/chrome/renderer/net/net_error_helper.cc index 13c4ad8..8bcc00b 100644 --- a/chrome/renderer/net/net_error_helper.cc +++ b/chrome/renderer/net/net_error_helper.cc
@@ -55,6 +55,7 @@ #include "third_party/blink/public/web/web_document.h" #include "third_party/blink/public/web/web_document_loader.h" #include "third_party/blink/public/web/web_frame.h" +#include "third_party/blink/public/web/web_history_item.h" #include "third_party/blink/public/web/web_local_frame.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/webui/jstemplate_builder.h" @@ -388,8 +389,12 @@ void NetErrorHelper::LoadErrorPage(const std::string& html, const GURL& failed_url) { - render_frame()->GetWebFrame()->LoadHTMLString( - html, GURL(kUnreachableWebDataURL), failed_url, true); + render_frame()->GetWebFrame()->CommitDataNavigation( + blink::WebURLRequest(GURL(kUnreachableWebDataURL)), blink::WebData(html), + blink::WebString::FromUTF8("text/html"), + blink::WebString::FromUTF8("UTF-8"), failed_url, + blink::WebFrameLoadType::kReplaceCurrentItem, blink::WebHistoryItem(), + false /* is_client_redirect */, nullptr, nullptr); } void NetErrorHelper::EnablePageHelperFunctions(net::Error net_error) {
diff --git a/chrome/renderer/prerender/prerender_dispatcher.cc b/chrome/renderer/prerender/prerender_dispatcher.cc index cad6cd7..b7c3a3a4 100644 --- a/chrome/renderer/prerender/prerender_dispatcher.cc +++ b/chrome/renderer/prerender/prerender_dispatcher.cc
@@ -54,7 +54,7 @@ } void PrerenderDispatcher::PrerenderStart(int prerender_id) { - std::map<int, WebPrerender>::iterator it = prerenders_.find(prerender_id); + auto it = prerenders_.find(prerender_id); if (it == prerenders_.end()) return; @@ -68,7 +68,7 @@ } void PrerenderDispatcher::PrerenderStopLoading(int prerender_id) { - std::map<int, WebPrerender>::iterator it = prerenders_.find(prerender_id); + auto it = prerenders_.find(prerender_id); if (it == prerenders_.end()) return; @@ -81,7 +81,7 @@ } void PrerenderDispatcher::PrerenderDomContentLoaded(int prerender_id) { - std::map<int, WebPrerender>::iterator it = prerenders_.find(prerender_id); + auto it = prerenders_.find(prerender_id); if (it == prerenders_.end()) return; @@ -101,7 +101,7 @@ void PrerenderDispatcher::PrerenderRemoveAliases( const std::vector<GURL>& aliases) { for (size_t i = 0; i < aliases.size(); ++i) { - std::multiset<GURL>::iterator it = running_prerender_urls_.find(aliases[i]); + auto it = running_prerender_urls_.find(aliases[i]); if (it != running_prerender_urls_.end()) { running_prerender_urls_.erase(it); } @@ -109,7 +109,7 @@ } void PrerenderDispatcher::PrerenderStop(int prerender_id) { - std::map<int, WebPrerender>::iterator it = prerenders_.find(prerender_id); + auto it = prerenders_.find(prerender_id); if (it == prerenders_.end()) return; WebPrerender& prerender = it->second;
diff --git a/chrome/renderer/safe_browsing/phishing_term_feature_extractor.cc b/chrome/renderer/safe_browsing/phishing_term_feature_extractor.cc index a55b877..c570c33c 100644 --- a/chrome/renderer/safe_browsing/phishing_term_feature_extractor.cc +++ b/chrome/renderer/safe_browsing/phishing_term_feature_extractor.cc
@@ -207,7 +207,7 @@ // Check if the size of shingle hashes is over the limit. if (shingle_hashes_->size() > max_shingles_per_page_) { // Pop the largest one. - std::set<uint32_t>::iterator it = shingle_hashes_->end(); + auto it = shingle_hashes_->end(); shingle_hashes_->erase(--it); } @@ -234,16 +234,14 @@ // state_->previous_words.append(word_lower); std::string current_term = state_->previous_words; - for (std::list<size_t>::iterator it = state_->previous_word_sizes.begin(); + for (auto it = state_->previous_word_sizes.begin(); it != state_->previous_word_sizes.end(); ++it) { hashes_to_check[crypto::SHA256HashString(current_term)] = current_term; current_term.erase(0, *it); } // Add features for any hashes that match page_term_hashes_. - for (std::map<std::string, std::string>::iterator it = - hashes_to_check.begin(); - it != hashes_to_check.end(); ++it) { + for (auto it = hashes_to_check.begin(); it != hashes_to_check.end(); ++it) { if (page_term_hashes_->find(it->first) != page_term_hashes_->end()) { features_->AddBooleanFeature(features::kPageTerm + it->second); }
diff --git a/chrome/renderer/safe_browsing/phishing_term_feature_extractor_unittest.cc b/chrome/renderer/safe_browsing/phishing_term_feature_extractor_unittest.cc index 4089c02d..9ced887 100644 --- a/chrome/renderer/safe_browsing/phishing_term_feature_extractor_unittest.cc +++ b/chrome/renderer/safe_browsing/phishing_term_feature_extractor_unittest.cc
@@ -54,8 +54,7 @@ // Chinese (translation of "goodbye") terms.insert("\xe5\x86\x8d\xe8\xa7\x81"); - for (base::hash_set<std::string>::iterator it = terms.begin(); - it != terms.end(); ++it) { + for (auto it = terms.begin(); it != terms.end(); ++it) { term_hashes_.insert(crypto::SHA256HashString(*it)); } @@ -72,8 +71,7 @@ words.insert("\xe4\xbd\xa0\xe5\xa5\xbd"); words.insert("\xe5\x86\x8d\xe8\xa7\x81"); - for (base::hash_set<std::string>::iterator it = words.begin(); - it != words.end(); ++it) { + for (auto it = words.begin(); it != words.end(); ++it) { word_hashes_.insert(MurmurHash3String(*it, kMurmurHash3Seed)); } @@ -247,7 +245,7 @@ kMurmurHash3Seed)); expected_shingle_hashes.insert(MurmurHash3String("way too many words ", kMurmurHash3Seed)); - std::set<uint32_t>::iterator it = expected_shingle_hashes.end(); + auto it = expected_shingle_hashes.end(); expected_shingle_hashes.erase(--it); features.Clear();
diff --git a/chrome/renderer/safe_browsing/phishing_url_feature_extractor.cc b/chrome/renderer/safe_browsing/phishing_url_feature_extractor.cc index 1b416f2..931c520 100644 --- a/chrome/renderer/safe_browsing/phishing_url_feature_extractor.cc +++ b/chrome/renderer/safe_browsing/phishing_url_feature_extractor.cc
@@ -69,8 +69,7 @@ host_tokens.pop_back(); // Now we're just left with the "other" host tokens. - for (std::vector<std::string>::iterator it = host_tokens.begin(); - it != host_tokens.end(); ++it) { + for (auto it = host_tokens.begin(); it != host_tokens.end(); ++it) { if (!features->AddBooleanFeature(features::kUrlOtherHostToken + *it)) return false; }
diff --git a/chrome/service/cloud_print/cloud_print_connector.cc b/chrome/service/cloud_print/cloud_print_connector.cc index daccf7fb..2e071b2 100644 --- a/chrome/service/cloud_print/cloud_print_connector.cc +++ b/chrome/service/cloud_print/cloud_print_connector.cc
@@ -137,7 +137,7 @@ return; } - JobHandlerMap::iterator printer_it = job_handler_map_.find(printer_id); + auto printer_it = job_handler_map_.find(printer_id); if (printer_it == job_handler_map_.end()) { std::string status_message = l10n_util::GetStringUTF8(IDS_CLOUD_PRINT_ZOMBIE_PRINTER); @@ -381,8 +381,7 @@ bool CloudPrintConnector::RemovePrinterFromList( const std::string& printer_name, printing::PrinterList* printer_list) { - for (printing::PrinterList::iterator it = printer_list->begin(); - it != printer_list->end(); ++it) { + for (auto it = printer_list->begin(); it != printer_list->end(); ++it) { if (IsSamePrinter(it->printer_name, printer_name)) { printer_list->erase(it); return true; @@ -566,7 +565,7 @@ void CloudPrintConnector::OnPrinterDelete(const std::string& printer_id) { // Remove corresponding printer job handler. - JobHandlerMap::iterator it = job_handler_map_.find(printer_id); + auto it = job_handler_map_.find(printer_id); if (it != job_handler_map_.end()) { it->second->Shutdown(); job_handler_map_.erase(it);
diff --git a/chrome/service/cloud_print/connector_settings.cc b/chrome/service/cloud_print/connector_settings.cc index 83a4617..f80ecc7 100644 --- a/chrome/service/cloud_print/connector_settings.cc +++ b/chrome/service/cloud_print/connector_settings.cc
@@ -94,7 +94,7 @@ } bool ConnectorSettings::ShouldConnect(const std::string& printer_name) const { - Printers::const_iterator printer = printers_.find(printer_name); + auto printer = printers_.find(printer_name); if (printer != printers_.end()) return !connect_new_printers_; return connect_new_printers_;
diff --git a/chrome/service/cloud_print/printer_job_handler.cc b/chrome/service/cloud_print/printer_job_handler.cc index d526e93..e672f06 100644 --- a/chrome/service/cloud_print/printer_job_handler.cc +++ b/chrome/service/cloud_print/printer_job_handler.cc
@@ -217,7 +217,7 @@ base::subtle::NoBarrier_AtomicIncrement(&g_total_jobs_done, 1); job_queue_handler_.JobDone(job_details_.job_id_); - for (JobStatusUpdaterList::iterator it = job_status_updater_list_.begin(); + for (auto it = job_status_updater_list_.begin(); it != job_status_updater_list_.end(); ++it) { if (it->get() == updater) { job_status_updater_list_.erase(it);
diff --git a/chrome/services/media_gallery_util/media_metadata_parser.cc b/chrome/services/media_gallery_util/media_metadata_parser.cc index ae99a20..9c9de4b 100644 --- a/chrome/services/media_gallery_util/media_metadata_parser.cc +++ b/chrome/services/media_gallery_util/media_metadata_parser.cc
@@ -57,15 +57,12 @@ metadata->title = extractor.title(); metadata->track = extractor.track(); - for (media::AudioVideoMetadataExtractor::StreamInfoVector::const_iterator it = - extractor.stream_infos().begin(); + for (auto it = extractor.stream_infos().begin(); it != extractor.stream_infos().end(); ++it) { chrome::mojom::MediaStreamInfoPtr stream_info = chrome::mojom::MediaStreamInfo::New( it->type, base::Value(base::Value::Type::DICTIONARY)); - for (std::map<std::string, std::string>::const_iterator tag_it = - it->tags.begin(); - tag_it != it->tags.end(); ++tag_it) { + for (auto tag_it = it->tags.begin(); tag_it != it->tags.end(); ++tag_it) { stream_info->additional_properties.SetKey(tag_it->first, base::Value(tag_it->second)); } @@ -73,8 +70,7 @@ } if (get_attached_images) { - for (std::vector<std::string>::const_iterator it = - extractor.attached_images_bytes().begin(); + for (auto it = extractor.attached_images_bytes().begin(); it != extractor.attached_images_bytes().end(); ++it) { attached_images->push_back(metadata::AttachedImage()); attached_images->back().data = *it;
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 27048fd..8bb7bcc 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -2611,6 +2611,7 @@ "../browser/prerender/prerender_util_unittest.cc", "../browser/previews/previews_infobar_delegate_unittest.cc", "../browser/previews/previews_lite_page_decider_unittest.cc", + "../browser/previews/previews_lite_page_infobar_delegate_unittest.cc", "../browser/previews/previews_lite_page_navigation_throttle_unittest.cc", "../browser/previews/previews_service_unittest.cc", "../browser/previews/previews_ui_tab_helper_unittest.cc",
diff --git a/chrome/test/base/test_chrome_web_ui_controller_factory.cc b/chrome/test/base/test_chrome_web_ui_controller_factory.cc index f599baea..09cdf54b 100644 --- a/chrome/test/base/test_chrome_web_ui_controller_factory.cc +++ b/chrome/test/base/test_chrome_web_ui_controller_factory.cc
@@ -55,7 +55,6 @@ TestChromeWebUIControllerFactory::WebUIProvider* TestChromeWebUIControllerFactory::GetWebUIProvider( Profile* profile, const GURL& url) const { - FactoryOverridesMap::const_iterator found = - factory_overrides_.find(url.host()); + auto found = factory_overrides_.find(url.host()); return found != factory_overrides_.end() ? found->second : nullptr; }
diff --git a/chrome/test/base/test_launcher_utils.cc b/chrome/test/base/test_launcher_utils.cc index 177ea0cc..22a199b 100644 --- a/chrome/test/base/test_launcher_utils.cc +++ b/chrome/test/base/test_launcher_utils.cc
@@ -73,8 +73,7 @@ base::CommandLine* out_command_line) { const base::CommandLine::SwitchMap& switch_map = in_command_line.GetSwitches(); - for (base::CommandLine::SwitchMap::const_iterator i = switch_map.begin(); - i != switch_map.end(); ++i) { + for (auto i = switch_map.begin(); i != switch_map.end(); ++i) { const std::string& switch_name = i->first; if (switch_name == switch_to_remove) continue;
diff --git a/chrome/test/base/testing_profile_manager.cc b/chrome/test/base/testing_profile_manager.cc index c122355..43f0f0ff 100644 --- a/chrome/test/base/testing_profile_manager.cc +++ b/chrome/test/base/testing_profile_manager.cc
@@ -175,7 +175,7 @@ void TestingProfileManager::DeleteTestingProfile(const std::string& name) { DCHECK(called_set_up_); - TestingProfilesMap::iterator it = testing_profiles_.find(name); + auto it = testing_profiles_.find(name); DCHECK(it != testing_profiles_.end()); TestingProfile* profile = it->second; @@ -191,8 +191,8 @@ void TestingProfileManager::DeleteAllTestingProfiles() { ProfileAttributesStorage& storage = profile_manager_->GetProfileAttributesStorage(); - for (TestingProfilesMap::iterator it = testing_profiles_.begin(); - it != testing_profiles_.end(); ++it) { + for (auto it = testing_profiles_.begin(); it != testing_profiles_.end(); + ++it) { TestingProfile* profile = it->second; storage.RemoveProfile(profile->GetPath()); } @@ -203,7 +203,7 @@ void TestingProfileManager::DeleteGuestProfile() { DCHECK(called_set_up_); - TestingProfilesMap::iterator it = testing_profiles_.find(kGuestProfileName); + auto it = testing_profiles_.find(kGuestProfileName); DCHECK(it != testing_profiles_.end()); profile_manager_->profiles_info_.erase(ProfileManager::GetGuestProfilePath()); @@ -212,7 +212,7 @@ void TestingProfileManager::DeleteSystemProfile() { DCHECK(called_set_up_); - TestingProfilesMap::iterator it = testing_profiles_.find(kSystemProfileName); + auto it = testing_profiles_.find(kSystemProfileName); DCHECK(it != testing_profiles_.end()); profile_manager_->profiles_info_.erase(
diff --git a/chrome/test/base/v8_unit_test.cc b/chrome/test/base/v8_unit_test.cc index 7f8ed5b..0243c81 100644 --- a/chrome/test/base/v8_unit_test.cc +++ b/chrome/test/base/v8_unit_test.cc
@@ -59,8 +59,7 @@ bool V8UnitTest::ExecuteJavascriptLibraries() { std::string utf8_content; - for (std::vector<base::FilePath>::iterator user_libraries_iterator = - user_libraries_.begin(); + for (auto user_libraries_iterator = user_libraries_.begin(); user_libraries_iterator != user_libraries_.end(); ++user_libraries_iterator) { std::string library_content;
diff --git a/chrome/test/chromedriver/capabilities.cc b/chrome/test/chromedriver/capabilities.cc index bb93d11f..450c5560 100644 --- a/chrome/test/chromedriver/capabilities.cc +++ b/chrome/test/chromedriver/capabilities.cc
@@ -610,9 +610,8 @@ } void Switches::SetFromSwitches(const Switches& switches) { - for (SwitchMap::const_iterator iter = switches.switch_map_.begin(); - iter != switches.switch_map_.end(); - ++iter) { + for (auto iter = switches.switch_map_.begin(); + iter != switches.switch_map_.end(); ++iter) { switch_map_[iter->first] = iter->second; } } @@ -651,7 +650,7 @@ Switches::NativeString Switches::GetSwitchValueNative( const std::string& name) const { - SwitchMap::const_iterator iter = switch_map_.find(name); + auto iter = switch_map_.find(name); if (iter == switch_map_.end()) return NativeString(); return iter->second; @@ -662,16 +661,14 @@ } void Switches::AppendToCommandLine(base::CommandLine* command) const { - for (SwitchMap::const_iterator iter = switch_map_.begin(); - iter != switch_map_.end(); - ++iter) { + for (auto iter = switch_map_.begin(); iter != switch_map_.end(); ++iter) { command->AppendSwitchNative(iter->first, iter->second); } } std::string Switches::ToString() const { std::string str; - SwitchMap::const_iterator iter = switch_map_.begin(); + auto iter = switch_map_.begin(); while (iter != switch_map_.end()) { str += "--" + iter->first; std::string value = GetSwitchValue(iter->first); @@ -756,8 +753,7 @@ base::BindRepeating(&ParseBoolean, &network_emulation_enabled); } - for (std::map<std::string, Parser>::iterator it = parser_map.begin(); - it != parser_map.end(); ++it) { + for (auto it = parser_map.begin(); it != parser_map.end(); ++it) { const base::Value* capability = NULL; if (desired_caps.Get(it->first, &capability)) { Status status = it->second.Run(*capability, this);
diff --git a/chrome/test/chromedriver/chrome/chrome_impl.cc b/chrome/test/chromedriver/chrome/chrome_impl.cc index 52cd0af..a2f76dd 100644 --- a/chrome/test/chromedriver/chrome/chrome_impl.cc +++ b/chrome/test/chromedriver/chrome/chrome_impl.cc
@@ -27,8 +27,7 @@ } bool ChromeImpl::HasCrashedWebView() { - for (WebViewList::iterator it = web_views_.begin(); - it != web_views_.end(); ++it) { + for (auto it = web_views_.begin(); it != web_views_.end(); ++it) { if ((*it)->WasCrashed()) return true; } @@ -72,7 +71,7 @@ bool w3c_compliant) { // Check if some web views are closed (or in the case of background pages, // become inactive). - WebViewList::iterator it = web_views_.begin(); + auto it = web_views_.begin(); while (it != web_views_.end()) { const WebViewInfo* view = views_info.GetForId((*it)->GetId()); if (!view || view->IsInactiveBackgroundPage()) { @@ -112,8 +111,7 @@ } Status ChromeImpl::GetWebViewById(const std::string& id, WebView** web_view) { - for (WebViewList::iterator it = web_views_.begin(); - it != web_views_.end(); ++it) { + for (auto it = web_views_.begin(); it != web_views_.end(); ++it) { if ((*it)->GetId() == id) { *web_view = (*it).get(); return Status(kOk); @@ -199,8 +197,7 @@ Status status = devtools_http_client_->CloseWebView(id); if (status.IsError()) return status; - for (WebViewList::iterator iter = web_views_.begin(); - iter != web_views_.end(); ++iter) { + for (auto iter = web_views_.begin(); iter != web_views_.end(); ++iter) { if ((*iter)->GetId() == id) { web_views_.erase(iter); break;
diff --git a/chrome/test/chromedriver/chrome/devtools_client_impl.cc b/chrome/test/chromedriver/chrome/devtools_client_impl.cc index 8f333eb3..d651608 100644 --- a/chrome/test/chromedriver/chrome/devtools_client_impl.cc +++ b/chrome/test/chromedriver/chrome/devtools_client_impl.cc
@@ -385,7 +385,7 @@ // have been deleted from |response_info_map_|) or blocked while notifying // listeners. if (expected_id != -1) { - ResponseInfoMap::iterator iter = response_info_map_.find(expected_id); + auto iter = response_info_map_.find(expected_id); if (iter == response_info_map_.end() || iter->second->state != kWaiting) return Status(kOk); } @@ -508,7 +508,7 @@ Status DevToolsClientImpl::ProcessCommandResponse( const internal::InspectorCommandResponse& response) { - ResponseInfoMap::iterator iter = response_info_map_.find(response.id); + auto iter = response_info_map_.find(response.id); if (IsVLogOn(1)) { std::string method, result; if (iter != response_info_map_.end())
diff --git a/chrome/test/chromedriver/chrome/network_conditions.cc b/chrome/test/chromedriver/chrome/network_conditions.cc index bc28c9e..62270bf3 100644 --- a/chrome/test/chromedriver/chrome/network_conditions.cc +++ b/chrome/test/chromedriver/chrome/network_conditions.cc
@@ -35,9 +35,7 @@ if (!networks_value->GetAsList(&networks)) return Status(kUnknownError, "malformed networks list"); - for (base::ListValue::iterator it = networks->begin(); - it != networks->end(); - ++it) { + for (auto it = networks->begin(); it != networks->end(); ++it) { base::DictionaryValue* network = NULL; if (!it->GetAsDictionary(&network)) { return Status(kUnknownError,
diff --git a/chrome/test/chromedriver/chrome/web_view_impl.cc b/chrome/test/chromedriver/chrome/web_view_impl.cc index 1cee354..5ea1c85 100644 --- a/chrome/test/chromedriver/chrome/web_view_impl.cc +++ b/chrome/test/chromedriver/chrome/web_view_impl.cc
@@ -412,8 +412,7 @@ "new Promise(x => setTimeout(() => setTimeout(x, 20), 20)"); params.SetBoolean("awaitPromise", true); client_->SendCommand("Runtime.evaluate", params); - for (std::list<MouseEvent>::const_iterator it = events.begin(); - it != events.end(); ++it) { + for (auto it = events.begin(); it != events.end(); ++it) { base::DictionaryValue params; switch (it->type) { @@ -453,8 +452,7 @@ return DispatchTouchEventsForMouseEvents(events, frame); double page_scale_factor = 1.0; - for (std::list<MouseEvent>::const_iterator it = events.begin(); - it != events.end(); ++it) { + for (auto it = events.begin(); it != events.end(); ++it) { base::DictionaryValue params; params.SetString("type", GetAsString(it->type)); params.SetInteger("x", it->x * page_scale_factor); @@ -479,8 +477,7 @@ } Status WebViewImpl::DispatchTouchEvents(const std::list<TouchEvent>& events) { - for (std::list<TouchEvent>::const_iterator it = events.begin(); - it != events.end(); ++it) { + for (auto it = events.begin(); it != events.end(); ++it) { Status status = DispatchTouchEvent(*it); if (status.IsError()) return status; @@ -489,8 +486,7 @@ } Status WebViewImpl::DispatchKeyEvents(const std::list<KeyEvent>& events) { - for (std::list<KeyEvent>::const_iterator it = events.begin(); - it != events.end(); ++it) { + for (auto it = events.begin(); it != events.end(); ++it) { base::DictionaryValue params; params.SetString("type", GetAsString(it->type)); if (it->modifiers & kNumLockKeyModifierMask) {
diff --git a/chrome/test/chromedriver/commands.cc b/chrome/test/chromedriver/commands.cc index 9a26a2f..8a0371e 100644 --- a/chrome/test/chromedriver/commands.cc +++ b/chrome/test/chromedriver/commands.cc
@@ -316,7 +316,7 @@ const base::DictionaryValue& params, const std::string& session_id, const CommandCallback& callback) { - SessionThreadMap::iterator iter = session_thread_map->find(session_id); + auto iter = session_thread_map->find(session_id); if (iter == session_thread_map->end()) { Status status(return_ok_without_session ? kOk : kInvalidSessionId); callback.Run(status, std::unique_ptr<base::Value>(), session_id,
diff --git a/chrome/test/chromedriver/devtools_events_logger.cc b/chrome/test/chromedriver/devtools_events_logger.cc index 9796887..94d60d0 100644 --- a/chrome/test/chromedriver/devtools_events_logger.cc +++ b/chrome/test/chromedriver/devtools_events_logger.cc
@@ -17,9 +17,7 @@ inline DevToolsEventsLogger::~DevToolsEventsLogger() {} Status DevToolsEventsLogger::OnConnected(DevToolsClient* client) { - for (base::ListValue::const_iterator it = prefs_->begin(); - it != prefs_->end(); - ++it) { + for (auto it = prefs_->begin(); it != prefs_->end(); ++it) { std::string event; it->GetAsString(&event); events_.insert(event); @@ -30,7 +28,7 @@ Status DevToolsEventsLogger::OnEvent(DevToolsClient* client, const std::string& method, const base::DictionaryValue& params) { - std::unordered_set<std::string>::iterator it = events_.find(method); + auto it = events_.find(method); if (it != events_.end()) { base::DictionaryValue log_message_dict; log_message_dict.SetString("method", method);
diff --git a/chrome/test/chromedriver/element_util.cc b/chrome/test/chromedriver/element_util.cc index 472dad3..a5e0fe5d 100644 --- a/chrome/test/chromedriver/element_util.cc +++ b/chrome/test/chromedriver/element_util.cc
@@ -669,8 +669,8 @@ " return document.evaluate(xpath, document, null," " XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;" "}"; - for (std::list<FrameInfo>::reverse_iterator rit = session->frames.rbegin(); - rit != session->frames.rend(); ++rit) { + for (auto rit = session->frames.rbegin(); rit != session->frames.rend(); + ++rit) { base::ListValue args; args.AppendString( base::StringPrintf("//*[@cd_frame_id_ = '%s']",
diff --git a/chrome/test/chromedriver/key_converter_unittest.cc b/chrome/test/chromedriver/key_converter_unittest.cc index 2b9da34..b88a7af 100644 --- a/chrome/test/chromedriver/key_converter_unittest.cc +++ b/chrome/test/chromedriver/key_converter_unittest.cc
@@ -28,7 +28,7 @@ EXPECT_EQ(kOk, ConvertKeysToKeyEvents(keys, release_modifiers, &modifiers, &events).code()); EXPECT_EQ(expected_events.size(), events.size()); - std::list<KeyEvent>::const_iterator expected = expected_events.begin(); + auto expected = expected_events.begin(); std::list<KeyEvent>::const_iterator actual = events.begin(); while (expected != expected_events.end() && actual != events.end()) { EXPECT_EQ(expected->type, actual->type);
diff --git a/chrome/test/chromedriver/logging.cc b/chrome/test/chromedriver/logging.cc index 8e3beaf..e3712cd 100644 --- a/chrome/test/chromedriver/logging.cc +++ b/chrome/test/chromedriver/logging.cc
@@ -169,9 +169,7 @@ bool GetFirstErrorMessageFromList(const base::ListValue* list, std::string* message) { - for (base::ListValue::const_iterator it = list->begin(); - it != list->end(); - ++it) { + for (auto it = list->begin(); it != list->end(); ++it) { const base::DictionaryValue* log_entry = NULL; it->GetAsDictionary(&log_entry); if (log_entry != NULL) { @@ -314,9 +312,7 @@ Log::Level browser_log_level = Log::kWarning; const LoggingPrefs& prefs = capabilities.logging_prefs; - for (LoggingPrefs::const_iterator iter = prefs.begin(); - iter != prefs.end(); - ++iter) { + for (auto iter = prefs.begin(); iter != prefs.end(); ++iter) { std::string type = iter->first; Log::Level level = iter->second; if (type == WebDriverLog::kPerformanceType) {
diff --git a/chrome/test/data/nacl/exit_status/pm_exit_status_test.cc b/chrome/test/data/nacl/exit_status/pm_exit_status_test.cc index 0254f382..ecb09c3 100644 --- a/chrome/test/data/nacl/exit_status/pm_exit_status_test.cc +++ b/chrome/test/data/nacl/exit_status/pm_exit_status_test.cc
@@ -18,6 +18,7 @@ #include <sys/fcntl.h> #include <unistd.h> +#include "base/format_macros.h" #include "ppapi/cpp/instance.h" #include "ppapi/cpp/module.h" #include "ppapi/cpp/var.h" @@ -93,14 +94,14 @@ for (size_t ix = 0; kMsgHandlers[ix].request != NULL; ++ix) { if (op_name == kMsgHandlers[ix].request) { - fprintf(stderr, "found at index %u\n", ix); + fprintf(stderr, "found at index %" PRIuS "\n", ix); kMsgHandlers[ix].handler(message_data, &sb); break; } } len = strlen(sb.c_str()); - fprintf(stderr, "posting reply len %d\n", len); + fprintf(stderr, "posting reply len %" PRIuS "\n", len); fprintf(stderr, "posting reply \"%s\".\n", sb.c_str()); fflush(stderr);
diff --git a/chrome/test/data/nacl/sysconf_nprocessors_onln/sysconf_nprocessors_onln_test.cc b/chrome/test/data/nacl/sysconf_nprocessors_onln/sysconf_nprocessors_onln_test.cc index 4c7355da..82e83c8 100644 --- a/chrome/test/data/nacl/sysconf_nprocessors_onln/sysconf_nprocessors_onln_test.cc +++ b/chrome/test/data/nacl/sysconf_nprocessors_onln/sysconf_nprocessors_onln_test.cc
@@ -76,14 +76,14 @@ for (size_t ix = 0; kMsgHandlers[ix].request != NULL; ++ix) { if (op_name == kMsgHandlers[ix].request) { - fprintf(stderr, "found at index %u\n", ix); + fprintf(stderr, "found at index %zu\n", ix); kMsgHandlers[ix].handler(message_data, &sb); break; } } len = strlen(sb.c_str()); - fprintf(stderr, "posting reply len %d\n", len); + fprintf(stderr, "posting reply len %zu\n", len); fprintf(stderr, "posting reply \"%s\".\n", sb.c_str()); PostMessage(pp::Var(sb));
diff --git a/chrome/test/data/perf/tough_compositor_cases/infinite_scroll_root_fixed_n_layers.html b/chrome/test/data/perf/tough_compositor_cases/infinite_scroll_root_fixed_n_layers.html new file mode 100644 index 0000000..e5e82a7 --- /dev/null +++ b/chrome/test/data/perf/tough_compositor_cases/infinite_scroll_root_fixed_n_layers.html
@@ -0,0 +1,252 @@ +<!doctype html> +<!-- +Copyright (c) 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. +--> +<html> + <head> + <title>infinite-scroll</title> + <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes"> + <style> + html { + height: 100%; + } + body { + display: block; + height: 100%; + margin: 0; + } + #container { + overflow-y: scroll; + height: 100%; + margin: 0; + contain: layout; + } + #runway { + height: 100000px; + contain: layout; + } + .item { + -webkit-transform: translate3d(0,0,0); + box-sizing: border-box; + overflow: hidden; + contain: layout; + } + + .conversation { + font-family: sans-serif; + height: 70px; + display: flex; + border-bottom: 1px solid lightgray; + } + .avatar { + display: flex; + flex-shrink: 0; + color: white; + align-items: center; + justify-content: center; + font-size: 40px; + width: 50px; + height: 50px; + margin: 10px; + background-color: lightblue; + } + .summary { + flex: 1; + flex-shrink: 0; + display: flex; + flex-direction: column; + padding: 10px 10px 10px 0px; + } + .topline { + display: flex; + flex-shrink: 0; + } + .participants { + flex: 1; + flex-shrink: 0; + font-weight: bold; + } + .time { + flex-shrink: 0; + font-size: 12px; + color: #444; + } + .bottomline { + flex-shrink: 0; + display: flex; + } + .preview { + flex: 1; + flex-shrink: 0; + font-size: 12px; + height: 2em; + text-overflow: ellipsis; + } + .subject { + font-weight: bold; + } + .snippet { + color: #444; + } + .trinkets { + flex-shrink: 0; + font-size: 20px; + } + .fixed { + position: fixed; + top: 0; + left: 50%; + transform: translate(-50%, 0); + border: 3px solid #73AD21; + } + </style> + </head> + <body > + <div id="runway"> + <template> + <div class="item conversation"> + <div class="avatar">A</div> + <div class="summary"> + <div class="topline"> + <div class="participants">{{ participants }}</div> + <div class="time">{{ time }}</div> + </div> + <div class="bottomline"> + <div class="preview"><span class="subject">{{ subject }}</span> — + <span class="snippet">{{ snippet }}</span></div> + <div class="trinkets">☆</div> + </div> + </div> + </div> + </template> + </div> + <div class="fixed">This div element has position: fixed</div> + <script> + var qs = (function(a) { + if (a == "") return {}; + var b = {}; + for (var i = 0; i < a.length; ++i) + { + var p=a[i].split('=', 2); + if (p.length == 1) + b[p[0]] = ""; + else + b[p[0]] = decodeURIComponent(p[1].replace(/\+/g, " ")); + } + return b; + })(window.location.search.substr(1).split('&')); + + function getRandomItem(array) { + return array[Math.floor(Math.random() * array.length)]; + } + function generateFakeData() { + var kNumberOfItems = 500; + var possibleParticipants = [ + 'Adam', 'Ojan', 'Elliot', 'Chris', + ]; + var possibleTimes = [ + 'Now', 'Yesterday', 'Last week', + ]; + var possibleSubjects = [ + 'Do you even bench?', + 'I like to scroll forever', + 'Lunch', + 'What if my subject is really long? Longer than that. Like really, really, long?', + ]; + var possibleSnippets = [ + 'Four score and seven years ago our fathers brought forth on this continent, a new nation, conceived in Liberty, and dedicated to the proposition that all men are created equal.', + 'When, in disgrace with fortune and men\'s eyes, I all alone beweep my outcast state,', + 'We the People of the United States, in Order to form a more perfect Union, establish Justice, insure domestic Tranquility', + ]; + var data = new Array(kNumberOfItems); + for (var i = 0; i < kNumberOfItems; ++i) { + data[i] = { + participants: getRandomItem(possibleParticipants), + time: getRandomItem(possibleTimes), + subject: getRandomItem(possibleSubjects), + snippet: getRandomItem(possibleSnippets), + } + console.log(data[i]); + } + return data; + } + + var data = generateFakeData(); + + "use strict"; + (function(exports) { + var kHeight = 70; + var kPhysicalCount = qs['layer_count']; + + var container = window; + var runway = document.getElementById('runway'); + + + var template = runway.querySelector('template'); + var items = new Array(kPhysicalCount); + for (var i = 0; i < kPhysicalCount; ++i) { + var fragment = template.content.cloneNode(true); + runway.appendChild(fragment); + var item = runway.lastElementChild; + items[i] = item; + item.transformValue_ = 0; + item.participants_ = item.querySelector('.participants').firstChild; + item.time_ = item.querySelector('.time').firstChild; + item.subject_ = item.querySelector('.subject').firstChild; + item.snippet_ = item.querySelector('.snippet').firstChild; + + updateText(item, i); + } + + var physicalHeight = kHeight * kPhysicalCount; + + function updateText(item, index) { + var datum = data[index % data.length]; + item.participants_.nodeValue = datum.participants; + item.time_.nodeValue = datum.time; + item.subject_.nodeValue = datum.subject; + item.snippet_.nodeValue = datum.snippet; + } + + container.addEventListener('scroll', function(e) { + var scrollTop = container.scrollY; + + var firstVirtualIndex = Math.floor(scrollTop / kHeight); + var firstPhysicalIndex = firstVirtualIndex % kPhysicalCount; + + var baseVirtualIndex = firstVirtualIndex - firstPhysicalIndex; + + var baseTransformValue = kHeight * baseVirtualIndex; + var nextTransformValue = baseTransformValue + physicalHeight; + + var baseTransformString = 'translate3d(0,' + baseTransformValue + 'px,0)'; + var nextTransformString = 'translate3d(0,' + nextTransformValue + 'px,0)'; + + window.requestAnimationFrame(function() { + for (var i = 0; i < firstPhysicalIndex; ++i) { + var item = items[i]; + if (item.transformValue_ != nextTransformValue) { + // NOTE(vmiura): Removed updateText to remove layout changes from the benchmark. + //updateText(item, baseVirtualIndex + kPhysicalCount + i); + item.style.WebkitTransform = nextTransformString; + item.transformValue_ = nextTransformValue; + } + + } + for (var i = firstPhysicalIndex; i < kPhysicalCount; ++i) { + var item = items[i]; + if (item.transformValue_ != baseTransformValue) { + // NOTE(vmiura): Removed updateText to remove layout changes from the benchmark. + //updateText(item, baseVirtualIndex + i); + item.style.WebkitTransform = baseTransformString; + item.transformValue_ = baseTransformValue; + } + } + }); + }); + })(window); + </script> + </body> +</html>
diff --git a/chrome/test/data/webui/print_preview/pages_settings_test.js b/chrome/test/data/webui/print_preview/pages_settings_test.js index 29f7ed15..2435e011 100644 --- a/chrome/test/data/webui/print_preview/pages_settings_test.js +++ b/chrome/test/data/webui/print_preview/pages_settings_test.js
@@ -8,6 +8,8 @@ ValidPageRanges: 'valid page ranges', InvalidPageRanges: 'invalid page ranges', NupChangesPages: 'nup changes pages', + ClearInput: 'clear input', + TabOrder: 'tab order', }; const suiteName = 'PagesSettingsTest'; @@ -18,6 +20,12 @@ /** @type {?print_preview.DocumentInfo} */ let documentInfo = null; + /** @type {!Array<number>} */ + const oneToHundred = Array.from({length: 100}, (x, i) => i + 1); + + /** @type {string} */ + const limitError = 'Out of bounds page reference, limit is '; + /** @override */ setup(function() { documentInfo = new print_preview.DocumentInfo(); @@ -89,99 +97,97 @@ }); } - /** @param {!Array<number>} expectedPages The expected pages value. */ - function validateState(expectedPages) { + /** + * @param {!Array<number>} expectedPages The expected pages value. + * @param {string} expectedError The expected error message. + * @param {boolean} invalid Whether the pages setting should be invalid. + */ + function validateState(expectedPages, expectedError, invalid) { const pagesValue = pagesSection.getSettingValue('pages'); assertEquals(expectedPages.length, pagesValue.length); expectedPages.forEach((page, index) => { assertEquals(page, pagesValue[index]); }); - assertTrue(pagesSection.$$('cr-input').errorMessage.length === 0); + assertEquals(!invalid, pagesSection.getSetting('pages').valid); + assertEquals(expectedError !== '', pagesSection.$$('cr-input').invalid); + assertEquals(expectedError, pagesSection.$$('cr-input').errorMessage); } // Tests that the page ranges set are valid for different user inputs. test(assert(TestNames.ValidPageRanges), function() { - const oneToHundred = Array.from({length: 100}, (x, i) => i + 1); const tenToHundred = Array.from({length: 91}, (x, i) => i + 10); return setupInput('1, 2, 3, 1, 56', 100) .then(function() { - validateState([1, 2, 3, 56]); + validateState([1, 2, 3, 56], '', false); return setupInput('1-3, 6-9, 6-10', 100); }) .then(function() { - validateState([1, 2, 3, 6, 7, 8, 9, 10]); + validateState([1, 2, 3, 6, 7, 8, 9, 10], '', false); return setupInput('10-', 100); }) .then(function() { - validateState(tenToHundred); + validateState(tenToHundred, '', false); return setupInput('10-100', 100); }) .then(function() { - validateState(tenToHundred); + validateState(tenToHundred, '', false); return setupInput('-', 100); }) .then(function() { - validateState(oneToHundred); + validateState(oneToHundred, '', false); // https://crbug.com/806165 return setupInput('1\u30012\u30013\u30011\u300156', 100); }) .then(function() { - validateState([1, 2, 3, 56]); + validateState([1, 2, 3, 56], '', false); return setupInput('1,2,3\u30011\u300156', 100); }) .then(function() { - validateState([1, 2, 3, 56]); + validateState([1, 2, 3, 56], '', false); }); }); // Tests that the correct error messages are shown for different user // inputs. test(assert(TestNames.InvalidPageRanges), function() { - const limitError = 'Out of bounds page reference, limit is '; const syntaxError = 'Invalid page range, use e.g. 1-5, 8, 11-13'; - /** @param {string} expectedMessage The expected error message. */ - const validateErrorState = function(expectedMessage) { - assertFalse(pagesSection.$$('cr-input').errorMessage.length === 0); - assertEquals(expectedMessage, pagesSection.$$('cr-input').errorMessage); - }; - return setupInput('10-100000', 100) .then(function() { - validateErrorState(limitError + '100'); + validateState(oneToHundred, limitError + '100', true); return setupInput('1, 100000', 100); }) .then(function() { - validateErrorState(limitError + '100'); + validateState(oneToHundred, limitError + '100', true); return setupInput('1, 2, 0, 56', 100); }) .then(function() { - validateErrorState(syntaxError); + validateState(oneToHundred, syntaxError, true); return setupInput('-1, 1, 2,, 56', 100); }) .then(function() { - validateErrorState(syntaxError); + validateState(oneToHundred, syntaxError, true); return setupInput('1,2,56-40', 100); }) .then(function() { - validateErrorState(syntaxError); + validateState(oneToHundred, syntaxError, true); return setupInput('101-110', 100); }) .then(function() { - validateErrorState(limitError + '100'); + validateState(oneToHundred, limitError + '100', true); return setupInput('1\u30012\u30010\u300156', 100); }) .then(function() { - validateErrorState(syntaxError); + validateState(oneToHundred, syntaxError, true); return setupInput('-1,1,2\u3001\u300156', 100); }) .then(function() { - validateErrorState(syntaxError); + validateState(oneToHundred, syntaxError, true); return setupInput('--', 100); }) .then(function() { - validateErrorState(syntaxError); + validateState(oneToHundred, syntaxError, true); }); }); @@ -202,35 +208,179 @@ .then(function() { const rangesValue = JSON.stringify(pagesSection.getSettingValue('ranges')); - validateState([1, 2, 3, 56]); + validateState([1, 2, 3, 56], '', false); pagesSection.setSetting('pagesPerSheet', 2); validateRanges(rangesValue); - validateState([1, 2]); + validateState([1, 2], '', false); pagesSection.setSetting('pagesPerSheet', 4); validateRanges(rangesValue); - validateState([1]); + validateState([1], '', false); pagesSection.setSetting('pagesPerSheet', 1); return setupInput('1-3, 6-9, 6-10', 100); }) .then(function() { const rangesValue = JSON.stringify(pagesSection.getSettingValue('ranges')); - validateState([1, 2, 3, 6, 7, 8, 9, 10]); + validateState([1, 2, 3, 6, 7, 8, 9, 10], '', false); pagesSection.setSetting('pagesPerSheet', 2); validateRanges(rangesValue); - validateState([1, 2, 3, 4]); + validateState([1, 2, 3, 4], '', false); pagesSection.setSetting('pagesPerSheet', 3); validateRanges(rangesValue); - validateState([1, 2, 3]); + validateState([1, 2, 3], '', false); return setupInput('1-3', 100); }) .then(function() { const rangesValue = JSON.stringify(pagesSection.getSettingValue('ranges')); - validateState([1]); + validateState([1], '', false); pagesSection.setSetting('pagesPerSheet', 1); validateRanges(rangesValue); - validateState([1, 2, 3]); + validateState([1, 2, 3], '', false); + }); + }); + + // Tests that the clearing a valid input has no effect, clearing an invalid + // input does not show an error message but does not reset the preview, and + // changing focus from an empty input in either case automatically reselects + // the "all" radio button. + test(assert(TestNames.ClearInput), function() { + const input = pagesSection.$.pageSettingsCustomInput.inputElement; + const radioGroup = pagesSection.$$('paper-radio-group'); + assertEquals(pagesSection.pagesValueEnum_.ALL, radioGroup.selected); + return setupInput('1-2', 3) + .then(function() { + assertEquals( + pagesSection.pagesValueEnum_.CUSTOM, radioGroup.selected); + validateState([1, 2], '', false); + return setupInput('', 3); + }) + .then(function() { + assertEquals( + pagesSection.pagesValueEnum_.CUSTOM, radioGroup.selected); + validateState([1, 2], '', false); + const whenBlurred = test_util.eventToPromise('blur', input); + input.blur(); + return whenBlurred; + }) + .then(function() { + assertEquals(pagesSection.pagesValueEnum_.ALL, radioGroup.selected); + validateState([1, 2, 3], '', false); + return setupInput('5', 3); + }) + .then(function() { + assertEquals( + pagesSection.pagesValueEnum_.CUSTOM, radioGroup.selected); + validateState([1, 2, 3], limitError + '3', true); + return setupInput('', 3); + }) + .then(function() { + assertEquals( + pagesSection.pagesValueEnum_.CUSTOM, radioGroup.selected); + validateState([1, 2, 3], '', true); + const whenBlurred = test_util.eventToPromise('blur', input); + input.blur(); + return whenBlurred; + }) + .then(function() { + assertEquals(pagesSection.pagesValueEnum_.ALL, radioGroup.selected); + validateState([1, 2, 3], '', false); + }); + }); + + // Tests that the radio buttons and custom input are appropriately + // inside/outside the tab order. + test(assert(TestNames.TabOrder), function() { + documentInfo.updatePageCount(3); + + const radioGroup = pagesSection.$$('paper-radio-group'); + const customRadio = pagesSection.$.customRadioButton; + const allRadio = pagesSection.$.allRadioButton; + const input = pagesSection.$.pageSettingsCustomInput; + + /** @param {boolean} allSelected Whether all radio button is selected. */ + const validateTabOrder = function(allSelected) { + const expectedSelection = allSelected ? + pagesSection.pagesValueEnum_.ALL : + pagesSection.pagesValueEnum_.CUSTOM; + assertEquals(expectedSelection, radioGroup.selected); + assertEquals(allSelected, customRadio.tabIndex === -1); + assertEquals(allSelected, input.tabIndex === -1); + assertEquals(!allSelected, allRadio.tabIndex === -1); + }; + + let whenFocused = test_util.eventToPromise('focus', radioGroup); + // Focus the radio group. + radioGroup.focus(); + return whenFocused + .then(() => { + // Start out with all selected. + validateTabOrder(true); + + // Down arrow, to switch to custom. + whenFocused = test_util.eventToPromise('focus', input.inputElement); + MockInteractions.keyEventOn( + allRadio, 'keydown', 40, [], 'ArrowDown'); + return whenFocused; + }) + .then(() => { + // Custom selected + validateTabOrder(false); + + // Set a custom page range. + input.inputElement.value = '1, 2'; + input.inputElement.dispatchEvent( + new CustomEvent('input', {composed: true, bubbles: true})); + return test_util.eventToPromise('input-change', pagesSection); + }) + .then(() => { + validateTabOrder(false); + + // Shift + tab should focus the custom radio button, not skip it. + const whenCustomRadioFocused = + test_util.eventToPromise('focus', customRadio); + MockInteractions.keyEventOn( + input.inputElement, 'keydown', 9, ['shift'], 'Tab'); + return whenCustomRadioFocused; + }) + .then(function() { + validateTabOrder(false); + + // Clear the input. + input.inputElement.value = ''; + input.inputElement.dispatchEvent( + new CustomEvent('input', {composed: true, bubbles: true})); + return test_util.eventToPromise('input-change', pagesSection); + }) + .then(function() { + validateTabOrder(false); + + // Focusing custom radio button does not reselect all. + const whenCustomRadioFocused = + test_util.eventToPromise('focus', customRadio); + MockInteractions.keyEventOn( + input.inputElement, 'keydown', 9, ['shift'], 'Tab'); + return whenCustomRadioFocused; + }) + .then(function() { + validateTabOrder(false); + + // Blurring the radio button reselects all + const whenCustomRadioBlurred = + test_util.eventToPromise('blur', customRadio); + customRadio.blur(); + Polymer.dom.flush(); + return whenCustomRadioBlurred; + }) + .then(function() { + // Send focus back to the radio group. It should now send focus to + // all, since it is selected. + const whenAllFocused = test_util.eventToPromise('focus', allRadio); + radioGroup.focus(); + return whenAllFocused; + }) + .then(function() { + validateTabOrder(true); }); }); });
diff --git a/chrome/test/data/webui/print_preview/print_preview_interactive_ui_tests.js b/chrome/test/data/webui/print_preview/print_preview_interactive_ui_tests.js index e82fee6..7136481 100644 --- a/chrome/test/data/webui/print_preview/print_preview_interactive_ui_tests.js +++ b/chrome/test/data/webui/print_preview/print_preview_interactive_ui_tests.js
@@ -132,3 +132,11 @@ TEST_F('PrintPreviewPagesSettingsTest', 'NupChangesPages', function() { this.runMochaTest(pages_settings_test.TestNames.NupChangesPages); }); + +TEST_F('PrintPreviewPagesSettingsTest', 'ClearInput', function() { + this.runMochaTest(pages_settings_test.TestNames.ClearInput); +}); + +TEST_F('PrintPreviewPagesSettingsTest', 'TabOrder', function() { + this.runMochaTest(pages_settings_test.TestNames.TabOrder); +});
diff --git a/chrome/test/data/webui/settings/cr_settings_browsertest.js b/chrome/test/data/webui/settings/cr_settings_browsertest.js index e2d6ec1..8d252bd 100644 --- a/chrome/test/data/webui/settings/cr_settings_browsertest.js +++ b/chrome/test/data/webui/settings/cr_settings_browsertest.js
@@ -1936,31 +1936,6 @@ }); /** - * Test fixture for the multidevice settings page container. - * @constructor - * @extends {CrSettingsBrowserTest} - */ -function CrSettingsMultidevicePageContainerTest() {} - -CrSettingsMultidevicePageContainerTest.prototype = { - __proto__: CrSettingsBrowserTest.prototype, - - /** @override */ - browsePreload: - 'chrome://settings/multidevice_page/multidevice_page_container.html', - - /** @override */ - extraLibraries: CrSettingsBrowserTest.prototype.extraLibraries.concat([ - '../test_browser_proxy.js', - 'multidevice_page_container_tests.js', - ]), -}; - -TEST_F('CrSettingsMultidevicePageContainerTest', 'All', function() { - mocha.run(); -}); - -/** * Test fixture for the multidevice settings page. * @constructor * @extends {CrSettingsBrowserTest}
diff --git a/chrome/test/data/webui/settings/multidevice_page_container_tests.js b/chrome/test/data/webui/settings/multidevice_page_container_tests.js deleted file mode 100644 index 705885f..0000000 --- a/chrome/test/data/webui/settings/multidevice_page_container_tests.js +++ /dev/null
@@ -1,125 +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. - -/** - * @implements {settings.MultideviceBrowserProxy} - * Note: showMultiDeviceSetupDialog is not used by the - * multidevice-page-container element. - */ -class TestMultideviceBrowserProxy extends TestBrowserProxy { - constructor(initialPageContentData) { - super([ - 'showMultiDeviceSetupDialog', - 'getPageContentData', - ]); - this.data = initialPageContentData; - } - - /** @override */ - getPageContentData() { - this.methodCalled('getPageContentData'); - return Promise.resolve(this.data); - } -} - -suite('Multidevice', function() { - let multidevicePageContainer = null; - let browserProxy = null; - let ALL_MODES; - - /** - * @param {!settings.MultiDeviceSettingsMode} mode - * @param {boolean} isSuiteSupported - * @return {!MultiDevicePageContentData} - */ - function getFakePageContentData(mode, isSuiteSupported) { - return { - mode: mode, - hostDeviceName: [ - settings.MultiDeviceSettingsMode.HOST_SET_WAITING_FOR_SERVER, - settings.MultiDeviceSettingsMode.HOST_SET_WAITING_FOR_VERIFICATION, - settings.MultiDeviceSettingsMode.HOST_SET_VERIFIED, - ].includes(mode) ? - 'Pixel XL' : - undefined, - betterTogetherState: isSuiteSupported ? - settings.MultiDeviceFeatureState.ENABLED_BY_USER : - settings.MultiDeviceFeatureState.NOT_SUPPORTED_BY_CHROMEBOOK, - }; - } - - /** - * @param {!settings.MultiDeviceSettingsMode} newMode - * @param {boolean} isSuiteSupported - */ - function changePageContent(newMode, isSuiteSupported) { - cr.webUIListenerCallback( - 'settings.updateMultidevicePageContentData', - getFakePageContentData(newMode, isSuiteSupported)); - Polymer.dom.flush(); - } - - suiteSetup(function() { - ALL_MODES = Object.values(settings.MultiDeviceSettingsMode); - }); - - /** @return {?HTMLElement} */ - const getMultidevicePage = () => - multidevicePageContainer.$$('settings-multidevice-page'); - - // Initializes page container with provided mode and sets the Better Together - // suite's feature state based on provided boolean. It returns a promise that - // only resolves when the multidevice-page has changed its pageContentData and - // the ensuing callbacks back been flushed. - /** - * @param {!settings.MultiDeviceSettingsMode} mode - * @param {boolean} isSuiteSupported - * @return {!Promise} - */ - function setInitialPageContent(mode, isSuiteSupported) { - if (multidevicePageContainer) - multidevicePageContainer.remove(); - browserProxy = new TestMultideviceBrowserProxy( - getFakePageContentData(mode, isSuiteSupported)); - settings.MultiDeviceBrowserProxyImpl.instance_ = browserProxy; - - PolymerTest.clearBody(); - multidevicePageContainer = - document.createElement('settings-multidevice-page-container'); - document.body.appendChild(multidevicePageContainer); - - return browserProxy.whenCalled('getPageContentData') - .then(Polymer.dom.flush()); - } - - test( - 'WebUIListener toggles multidevice page based suite support in all modes', - function() { - return setInitialPageContent( - settings.MultiDeviceSettingsMode.NO_HOST_SET, - /* isSuiteSupported */ true) - .then(() => { - for (const mode of ALL_MODES) { - // Check that the settings-page is visible iff the suite is - // supported. - changePageContent(mode, /* isSuiteSupported */ true); - assertTrue(!!getMultidevicePage()); - - changePageContent(mode, /* isSuiteSupported */ false); - assertFalse(!!getMultidevicePage()); - - changePageContent(mode, /* isSuiteSupported */ true); - assertTrue(!!getMultidevicePage()); - } - }); - }); - - test( - 'multidevice-page is not attached if suite is not supported', function() { - return setInitialPageContent( - settings.MultiDeviceSettingsMode.NO_HOST_SET, - /* isSuiteSupported */ false) - .then(() => assertFalse(!!getMultidevicePage())); - }); -});
diff --git a/chrome/test/data/webui/settings/multidevice_page_tests.js b/chrome/test/data/webui/settings/multidevice_page_tests.js index db762afb..1e03e972 100644 --- a/chrome/test/data/webui/settings/multidevice_page_tests.js +++ b/chrome/test/data/webui/settings/multidevice_page_tests.js
@@ -2,69 +2,98 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -/** - * @implements {settings.MultideviceBrowserProxy} - * Note: Only showMultiDeviceSetupDialog is used by the multidevice-page - * element. - */ -class TestMultideviceBrowserProxy extends TestBrowserProxy { - constructor() { - super([ - 'showMultiDeviceSetupDialog', - 'getPageContentData', - 'setFeatureEnabledState', - ]); - } - - /** @override */ - showMultiDeviceSetupDialog() { - this.methodCalled('showMultiDeviceSetupDialog'); - } - - /** @override */ - setFeatureEnabledState(feature, enabled, opt_authToken) { - this.methodCalled( - 'setFeatureEnabledState', [feature, enabled, opt_authToken]); - } -} - suite('Multidevice', function() { + /** + * Builds fake pageContentData for the specified mode. If it is a mode + * corresponding to a set host, it will set the hostDeviceName to the provided + * name or else default to HOST_DEVICE. + * @param {settings.MultiDeviceSettingsMode} mode + * @param {string=} opt_hostDeviceName Overrides default if |mode| corresponds + * to a set host. + * @return {!MultiDevicePageContentData} + */ + function createFakePageContentData(mode, opt_hostDeviceName) { + let pageContentData = {mode: mode}; + if ([ + settings.MultiDeviceSettingsMode.HOST_SET_WAITING_FOR_SERVER, + settings.MultiDeviceSettingsMode.HOST_SET_WAITING_FOR_VERIFICATION, + settings.MultiDeviceSettingsMode.HOST_SET_VERIFIED, + ].includes(mode)) { + pageContentData.hostDeviceName = opt_hostDeviceName || HOST_DEVICE; + } + return pageContentData; + } + + /** + * @implements {settings.MultideviceBrowserProxy} + * Note: Only showMultiDeviceSetupDialog is used by the multidevice-page + * element. + */ + class TestMultideviceBrowserProxy extends TestBrowserProxy { + constructor() { + super([ + 'showMultiDeviceSetupDialog', + 'getPageContentData', + 'setFeatureEnabledState', + ]); + this.data = createFakePageContentData( + settings.MultiDeviceSettingsMode.NO_HOST_SET); + } + + /** @override */ + getPageContentData() { + this.methodCalled('getPageContentData'); + return Promise.resolve(this.data); + } + + /** @override */ + showMultiDeviceSetupDialog() { + this.methodCalled('showMultiDeviceSetupDialog'); + } + + /** @override */ + setFeatureEnabledState(feature, enabled, opt_authToken) { + this.methodCalled( + 'setFeatureEnabledState', [feature, enabled, opt_authToken]); + } + } + let multidevicePage = null; let browserProxy = null; let ALL_MODES; const HOST_DEVICE = 'Pixel XL'; /** + * Sets pageContentData via WebUI Listener and flushes. + * @param {!MultiDevicePageContentData} + */ + function setPageContentData(newPageContentData) { + cr.webUIListenerCallback( + 'settings.updateMultidevicePageContentData', newPageContentData); + Polymer.dom.flush(); + } + + /** * Sets pageContentData to the specified mode. If it is a mode corresponding * to a set host, it will set the hostDeviceName to the provided name or else * default to HOST_DEVICE. * @param {settings.MultiDeviceSettingsMode} newMode - * @param {string|undefined} newHostDeviceName Overrides default if there - * newMode corresponds to a set host. + * @param {string=} opt_newHostDeviceName Overrides default if |newMode| + * corresponds to a set host. */ - function setPageContentData(newMode, newHostDeviceName) { - let newPageContentData = {mode: newMode}; - if ([ - settings.MultiDeviceSettingsMode.HOST_SET_WAITING_FOR_SERVER, - settings.MultiDeviceSettingsMode.HOST_SET_WAITING_FOR_VERIFICATION, - settings.MultiDeviceSettingsMode.HOST_SET_VERIFIED, - ].includes(newMode)) { - newPageContentData.hostDeviceName = newHostDeviceName || HOST_DEVICE; - } - multidevicePage.pageContentData = newPageContentData; - Polymer.dom.flush(); + function setHostData(newMode, opt_newHostDeviceName) { + setPageContentData( + createFakePageContentData(newMode, opt_newHostDeviceName)); } function setSuiteState(newState) { - multidevicePage.pageContentData = Object.assign( - {}, multidevicePage.pageContentData, {betterTogetherState: newState}); - Polymer.dom.flush(); + setPageContentData(Object.assign( + {}, multidevicePage.pageContentData, {betterTogetherState: newState})); } function setSmartLockState(newState) { - multidevicePage.pageContentData = Object.assign( - {}, multidevicePage.pageContentData, {smartLockState: newState}); - Polymer.dom.flush(); + setPageContentData(Object.assign( + {}, multidevicePage.pageContentData, {smartLockState: newState})); } /** @@ -129,7 +158,7 @@ const getSubpage = () => multidevicePage.$$('settings-multidevice-subpage'); test('clicking setup shows multidevice setup dialog', function() { - setPageContentData(settings.MultiDeviceSettingsMode.NO_HOST_SET); + setHostData(settings.MultiDeviceSettingsMode.NO_HOST_SET); const button = multidevicePage.$$('paper-button'); assertTrue(!!button); button.click(); @@ -138,23 +167,23 @@ test('headings render based on mode and host', function() { for (const mode of ALL_MODES) { - setPageContentData(mode); + setHostData(mode); assertEquals(multidevicePage.isHostSet(), getLabel() === HOST_DEVICE); } }); test('changing host device changes header', function() { - setPageContentData(settings.MultiDeviceSettingsMode.HOST_SET_VERIFIED); + setHostData(settings.MultiDeviceSettingsMode.HOST_SET_VERIFIED); assertEquals(getLabel(), HOST_DEVICE); const anotherHost = 'Super Duper ' + HOST_DEVICE; - setPageContentData( + setHostData( settings.MultiDeviceSettingsMode.HOST_SET_VERIFIED, anotherHost); assertEquals(getLabel(), anotherHost); }); test('item is actionable if and only if a host is set', function() { for (const mode of ALL_MODES) { - setPageContentData(mode); + setHostData(mode); assertEquals( multidevicePage.isHostSet(), !!multidevicePage.$$('#multidevice-item').hasAttribute('actionable')); @@ -164,7 +193,7 @@ test( 'clicking item with verified host opens subpage with features', function() { - setPageContentData(settings.MultiDeviceSettingsMode.HOST_SET_VERIFIED); + setHostData(settings.MultiDeviceSettingsMode.HOST_SET_VERIFIED); assertFalse(!!getSubpage()); multidevicePage.$$('#multidevice-item').click(); assertTrue(!!getSubpage()); @@ -174,7 +203,7 @@ test( 'clicking item with unverified set host opens subpage without features', function() { - setPageContentData( + setHostData( settings.MultiDeviceSettingsMode.HOST_SET_WAITING_FOR_VERIFICATION, HOST_DEVICE); assertFalse(!!getSubpage()); @@ -184,7 +213,7 @@ }); test('policy prohibited suite shows policy indicator', function() { - setPageContentData(settings.MultiDeviceSettingsMode.NO_ELIGIBLE_HOSTS); + setHostData(settings.MultiDeviceSettingsMode.NO_ELIGIBLE_HOSTS); assertFalse(!!multidevicePage.$$('cr-policy-indicator')); // Prohibit suite by policy. setSuiteState(settings.MultiDeviceFeatureState.PROHIBITED_BY_POLICY);
diff --git a/chrome/tools/convert_dict/aff_reader.cc b/chrome/tools/convert_dict/aff_reader.cc index 4185a6a..51a13d0 100644 --- a/chrome/tools/convert_dict/aff_reader.cc +++ b/chrome/tools/convert_dict/aff_reader.cc
@@ -155,7 +155,7 @@ } int AffReader::GetAFIndexForAFString(const std::string& af_string) { - std::map<std::string, int>::iterator found = affix_groups_.find(af_string); + auto found = affix_groups_.find(af_string); if (found != affix_groups_.end()) return found->second; std::string my_string(af_string); @@ -166,8 +166,7 @@ // line with "AF" for the parser to read later. std::vector<std::string> AffReader::GetAffixGroups() const { int max_id = 0; - for (std::map<std::string, int>::const_iterator i = affix_groups_.begin(); - i != affix_groups_.end(); ++i) { + for (auto i = affix_groups_.begin(); i != affix_groups_.end(); ++i) { if (i->second > max_id) max_id = i->second; } @@ -175,8 +174,7 @@ std::vector<std::string> ret; ret.resize(max_id); - for (std::map<std::string, int>::const_iterator i = affix_groups_.begin(); - i != affix_groups_.end(); ++i) { + for (auto i = affix_groups_.begin(); i != affix_groups_.end(); ++i) { // Convert the indices into 1-based. ret[i->second - 1] = std::string("AF ") + i->first; }
diff --git a/chrome/tools/convert_dict/convert_dict_unittest.cc b/chrome/tools/convert_dict/convert_dict_unittest.cc index 338b048..a12752c 100644 --- a/chrome/tools/convert_dict/convert_dict_unittest.cc +++ b/chrome/tools/convert_dict/convert_dict_unittest.cc
@@ -70,8 +70,7 @@ std::string aff_data(base::StringPrintf("SET %s\n", codepage)); std::string dic_data(base::StringPrintf("%" PRIuS "\n", word_list.size())); - for (std::map<base::string16, bool>::const_iterator it = word_list.begin(); - it != word_list.end(); ++it) { + for (auto it = word_list.begin(); it != word_list.end(); ++it) { std::string encoded_word; EXPECT_TRUE(UTF16ToCodepage(it->first, codepage,
diff --git a/chrome/tools/convert_dict/dic_reader.cc b/chrome/tools/convert_dict/dic_reader.cc index 07382ac..3eb8ca10 100644 --- a/chrome/tools/convert_dict/dic_reader.cc +++ b/chrome/tools/convert_dict/dic_reader.cc
@@ -115,7 +115,7 @@ if (word_tab_offset != std::string::npos) utf8word = utf8word.substr(0, word_tab_offset); - WordSet::iterator found = word_set->find(utf8word); + auto found = word_set->find(utf8word); std::set<int> affix_vector; affix_vector.insert(affix_index); @@ -170,11 +170,9 @@ "UTF-8", false); } // Make sure the words are sorted, they may be unsorted in the input. - for (WordSet::iterator word = word_set.begin(); word != word_set.end(); - ++word) { + for (auto word = word_set.begin(); word != word_set.end(); ++word) { std::vector<int> affixes; - for (std::set<int>::iterator aff = word->second.begin(); - aff != word->second.end(); ++aff) + for (auto aff = word->second.begin(); aff != word->second.end(); ++aff) affixes.push_back(*aff); // Double check that the affixes are sorted. This isn't strictly necessary
diff --git a/chrome/utility/importer/external_process_importer_bridge.cc b/chrome/utility/importer/external_process_importer_bridge.cc index 2119346..9c9c671 100644 --- a/chrome/utility/importer/external_process_importer_bridge.cc +++ b/chrome/utility/importer/external_process_importer_bridge.cc
@@ -45,11 +45,9 @@ // Debug bounds-check which prevents pushing an iterator beyond its end() // (i.e., |it + 2 < s.end()| crashes in debug mode if |i + 1 == s.end()|). int bookmarks_left = bookmarks.end() - bookmarks.begin(); - for (std::vector<ImportedBookmarkEntry>::const_iterator it = - bookmarks.begin(); it < bookmarks.end();) { + for (auto it = bookmarks.begin(); it < bookmarks.end();) { std::vector<ImportedBookmarkEntry> bookmark_group; - std::vector<ImportedBookmarkEntry>::const_iterator end_group = - it + std::min(bookmarks_left, kNumBookmarksToSend); + auto end_group = it + std::min(bookmarks_left, kNumBookmarksToSend); bookmark_group.assign(it, end_group); (*observer_)->OnBookmarksImportGroup(bookmark_group); @@ -71,11 +69,9 @@ // Debug bounds-check which prevents pushing an iterator beyond its end() // (i.e., |it + 2 < s.end()| crashes in debug mode if |i + 1 == s.end()|). int favicons_left = favicons.end() - favicons.begin(); - for (favicon_base::FaviconUsageDataList::const_iterator it = favicons.begin(); - it < favicons.end();) { + for (auto it = favicons.begin(); it < favicons.end();) { favicon_base::FaviconUsageDataList favicons_group; - favicon_base::FaviconUsageDataList::const_iterator end_group = - it + std::min(favicons_left, kNumFaviconsToSend); + auto end_group = it + std::min(favicons_left, kNumFaviconsToSend); favicons_group.assign(it, end_group); (*observer_)->OnFaviconsImportGroup(favicons_group); @@ -94,11 +90,9 @@ // Debug bounds-check which prevents pushing an iterator beyond its end() // (i.e., |it + 2 < s.end()| crashes in debug mode if |i + 1 == s.end()|). int rows_left = rows.end() - rows.begin(); - for (std::vector<ImporterURLRow>::const_iterator it = rows.begin(); - it < rows.end();) { + for (auto it = rows.begin(); it < rows.end();) { std::vector<ImporterURLRow> row_group; - std::vector<ImporterURLRow>::const_iterator end_group = - it + std::min(rows_left, kNumHistoryRowsToSend); + auto end_group = it + std::min(rows_left, kNumHistoryRowsToSend); row_group.assign(it, end_group); (*observer_)->OnHistoryImportGroup(row_group, visit_source); @@ -133,13 +127,10 @@ // its end() (i.e., |it + 2 < s.end()| crashes in debug mode if |i + 1 == // s.end()|). int autofill_form_data_entries_left = entries.end() - entries.begin(); - for (std::vector<ImporterAutofillFormDataEntry>::const_iterator it = - entries.begin(); - it < entries.end();) { + for (auto it = entries.begin(); it < entries.end();) { std::vector<ImporterAutofillFormDataEntry> autofill_form_data_entry_group; - std::vector<ImporterAutofillFormDataEntry>::const_iterator end_group = - it + - std::min(autofill_form_data_entries_left, kNumAutofillFormDataToSend); + auto end_group = it + std::min(autofill_form_data_entries_left, + kNumAutofillFormDataToSend); autofill_form_data_entry_group.assign(it, end_group); (*observer_)->OnAutofillFormDataImportGroup(autofill_form_data_entry_group);
diff --git a/chrome/utility/importer/firefox_importer.cc b/chrome/utility/importer/firefox_importer.cc index da84b878..f7ed312 100644 --- a/chrome/utility/importer/firefox_importer.cc +++ b/chrome/utility/importer/firefox_importer.cc
@@ -796,8 +796,7 @@ if (!s.is_valid()) return; - for (FaviconMap::const_iterator i = favicon_map.begin(); - i != favicon_map.end(); ++i) { + for (auto i = favicon_map.begin(); i != favicon_map.end(); ++i) { s.BindInt64(0, i->first); if (s.Step()) { std::vector<unsigned char> data;
diff --git a/chromecast/base/device_capabilities.h b/chromecast/base/device_capabilities.h index 8ee06e16..2a09a9fe 100644 --- a/chromecast/base/device_capabilities.h +++ b/chromecast/base/device_capabilities.h
@@ -120,7 +120,7 @@ } // Accessor for complete capabilities string in JSON format. - const std::string& json_string() const { return *json_string_.get(); } + const std::string& json_string() const { return json_string_; } private: friend class base::RefCountedThreadSafe<Data>; @@ -135,7 +135,7 @@ ~Data(); const std::unique_ptr<const base::DictionaryValue> dictionary_; - const std::unique_ptr<const std::string> json_string_; + const std::string json_string_; DISALLOW_COPY_AND_ASSIGN(Data); };
diff --git a/chromecast/base/device_capabilities_impl.cc b/chromecast/base/device_capabilities_impl.cc index 398d221..936ca2e 100644 --- a/chromecast/base/device_capabilities_impl.cc +++ b/chromecast/base/device_capabilities_impl.cc
@@ -103,16 +103,13 @@ DeviceCapabilities::Data::Data() : dictionary_(new base::DictionaryValue), - json_string_(SerializeToJson(*dictionary_)) { - DCHECK(json_string_.get()); -} + json_string_(*SerializeToJson(*dictionary_)) {} DeviceCapabilities::Data::Data( std::unique_ptr<const base::DictionaryValue> dictionary) : dictionary_(std::move(dictionary)), - json_string_(SerializeToJson(*dictionary_)) { + json_string_(*SerializeToJson(*dictionary_)) { DCHECK(dictionary_.get()); - DCHECK(json_string_.get()); } DeviceCapabilitiesImpl::Data::~Data() {}
diff --git a/chromecast/base/device_capabilities_impl_unittest.cc b/chromecast/base/device_capabilities_impl_unittest.cc index d819975..692f5ed 100644 --- a/chromecast/base/device_capabilities_impl_unittest.cc +++ b/chromecast/base/device_capabilities_impl_unittest.cc
@@ -187,8 +187,8 @@ const base::Value& value) { base::DictionaryValue dict_value; dict_value.Set(key, value.CreateDeepCopy()); - std::unique_ptr<const std::string> dict_json(SerializeToJson(dict_value)); - return dict_json.get() && *dict_json == json; + base::Optional<std::string> dict_json = SerializeToJson(dict_value); + return dict_json && *dict_json == json; } // The function runs through the set of basic operations of DeviceCapabilities. @@ -273,9 +273,8 @@ // Tests that class is in correct state after Create(). TEST_F(DeviceCapabilitiesImplTest, Create) { - std::unique_ptr<const std::string> empty_dict_string( - SerializeToJson(base::DictionaryValue())); - EXPECT_EQ(capabilities()->GetAllData()->json_string(), *empty_dict_string); + std::string empty_dict_string = *SerializeToJson(base::DictionaryValue()); + EXPECT_EQ(capabilities()->GetAllData()->json_string(), empty_dict_string); EXPECT_TRUE(capabilities()->GetAllData()->dictionary().empty()); } @@ -290,9 +289,8 @@ false); EXPECT_EQ(capabilities()->GetValidator(key), &manager); - std::unique_ptr<const std::string> empty_dict_string( - SerializeToJson(base::DictionaryValue())); - EXPECT_EQ(capabilities()->GetAllData()->json_string(), *empty_dict_string); + std::string empty_dict_string = *SerializeToJson(base::DictionaryValue()); + EXPECT_EQ(capabilities()->GetAllData()->json_string(), empty_dict_string); EXPECT_FALSE(capabilities()->GetCapability(key)); } @@ -309,9 +307,8 @@ delete manager; EXPECT_FALSE(capabilities()->GetValidator(key)); - std::unique_ptr<const std::string> empty_dict_string( - SerializeToJson(base::DictionaryValue())); - EXPECT_EQ(capabilities()->GetAllData()->json_string(), *empty_dict_string); + std::string empty_dict_string = *SerializeToJson(base::DictionaryValue()); + EXPECT_EQ(capabilities()->GetAllData()->json_string(), empty_dict_string); EXPECT_FALSE(capabilities()->GetCapability(key)); }
diff --git a/chromecast/base/serializers.cc b/chromecast/base/serializers.cc index 7041a961..1c38636 100644 --- a/chromecast/base/serializers.cc +++ b/chromecast/base/serializers.cc
@@ -23,12 +23,12 @@ return value; } -std::unique_ptr<std::string> SerializeToJson(const base::Value& value) { - std::unique_ptr<std::string> json_str(new std::string()); - JSONStringValueSerializer serializer(json_str.get()); - if (!serializer.Serialize(value)) - json_str.reset(nullptr); - return json_str; +base::Optional<std::string> SerializeToJson(const base::Value& value) { + std::string json_str; + JSONStringValueSerializer serializer(&json_str); + if (serializer.Serialize(value)) + return json_str; + return base::nullopt; } std::unique_ptr<base::Value> DeserializeJsonFromFile(
diff --git a/chromecast/base/serializers.h b/chromecast/base/serializers.h index df648fee..110ccc92 100644 --- a/chromecast/base/serializers.h +++ b/chromecast/base/serializers.h
@@ -8,6 +8,7 @@ #include <memory> #include <string> +#include "base/optional.h" namespace base { class Value; @@ -22,8 +23,10 @@ std::unique_ptr<base::Value> DeserializeFromJson(const std::string& text); // Helper function which serializes |value| into a JSON string. If a -// serialization error occurs,the return value will hold the NULL pointer. -std::unique_ptr<std::string> SerializeToJson(const base::Value& value); +// serialization error occurs,the return value will be base::nullopt. +// Dereferencing the result is equivalent to DCHECK()-ing that serialization +// succeeded and retrieving the serialized string. +base::Optional<std::string> SerializeToJson(const base::Value& value); // Helper function which deserializes JSON file at |path| into a base::Value. // If file in |path| is empty, is not valid JSON, or if some other
diff --git a/chromecast/base/serializers_unittest.cc b/chromecast/base/serializers_unittest.cc index 5e3d751..750e237 100644 --- a/chromecast/base/serializers_unittest.cc +++ b/chromecast/base/serializers_unittest.cc
@@ -56,22 +56,22 @@ TEST(SerializeToJson, BadValue) { base::Value value(std::vector<char>(12)); - std::unique_ptr<std::string> str = SerializeToJson(value); - EXPECT_EQ(nullptr, str.get()); + base::Optional<std::string> str = SerializeToJson(value); + EXPECT_EQ(base::nullopt, str); } TEST(SerializeToJson, EmptyValue) { base::DictionaryValue value; - std::unique_ptr<std::string> str = SerializeToJson(value); - ASSERT_NE(nullptr, str.get()); + base::Optional<std::string> str = SerializeToJson(value); + ASSERT_NE(base::nullopt, str); EXPECT_EQ(kEmptyJsonString, *str); } TEST(SerializeToJson, PopulatedValue) { base::DictionaryValue orig_value; orig_value.SetString(kTestKey, kTestValue); - std::unique_ptr<std::string> str = SerializeToJson(orig_value); - ASSERT_NE(nullptr, str.get()); + base::Optional<std::string> str = SerializeToJson(orig_value); + ASSERT_NE(nullptr, str); std::unique_ptr<base::Value> new_value = DeserializeFromJson(*str); ASSERT_NE(nullptr, new_value.get());
diff --git a/chromecast/crash/linux/crash_testing_utils.cc b/chromecast/crash/linux/crash_testing_utils.cc index aa7cea8..f81e548 100644 --- a/chromecast/crash/linux/crash_testing_utils.cc +++ b/chromecast/crash/linux/crash_testing_utils.cc
@@ -62,7 +62,7 @@ std::string lockfile; for (const auto& elem : *contents) { - std::unique_ptr<std::string> dump_info = SerializeToJson(elem); + base::Optional<std::string> dump_info = SerializeToJson(elem); RCHECK(dump_info, -1, "Failed to serialize DumpInfo"); lockfile += *dump_info; lockfile += "\n"; // Add line seperatators
diff --git a/chromecast/crash/linux/synchronized_minidump_manager.cc b/chromecast/crash/linux/synchronized_minidump_manager.cc index 62149fb2..459bc3e 100644 --- a/chromecast/crash/linux/synchronized_minidump_manager.cc +++ b/chromecast/crash/linux/synchronized_minidump_manager.cc
@@ -302,7 +302,7 @@ std::string lockfile; for (const auto& elem : *dumps) { - std::unique_ptr<std::string> dump_info = SerializeToJson(elem); + base::Optional<std::string> dump_info = SerializeToJson(elem); RCHECK(dump_info, false); lockfile += *dump_info; lockfile += "\n"; // Add line seperatators
diff --git a/chromeos/components/drivefs/fake_drivefs.cc b/chromeos/components/drivefs/fake_drivefs.cc index 9e73ccb8..df1ffe2 100644 --- a/chromeos/components/drivefs/fake_drivefs.cc +++ b/chromeos/components/drivefs/fake_drivefs.cc
@@ -89,6 +89,7 @@ bool hosted = false; bool shared = false; std::string original_name; + mojom::Capabilities capabilities; }; class FakeDriveFs::SearchQuery : public mojom::SearchQuery { @@ -235,11 +236,13 @@ const std::string& mime_type, const std::string& original_name, bool pinned, - bool shared) { + bool shared, + const mojom::Capabilities& capabilities) { auto& stored_metadata = metadata_[path]; stored_metadata.mime_type = mime_type; stored_metadata.original_name = original_name; stored_metadata.hosted = (original_name != path.BaseName().value()); + stored_metadata.capabilities = capabilities; if (pinned) { stored_metadata.pinned = true; } @@ -294,7 +297,7 @@ ? path.BaseName().value() : stored_metadata.original_name; metadata->alternate_url = GURL(base::StrCat({prefix, suffix})).spec(); - metadata->capabilities = mojom::Capabilities::New(); + metadata->capabilities = stored_metadata.capabilities.Clone(); std::move(callback).Run(drive::FILE_ERROR_OK, std::move(metadata)); }
diff --git a/chromeos/components/drivefs/fake_drivefs.h b/chromeos/components/drivefs/fake_drivefs.h index 853aca9d..403771c0 100644 --- a/chromeos/components/drivefs/fake_drivefs.h +++ b/chromeos/components/drivefs/fake_drivefs.h
@@ -34,7 +34,8 @@ const std::string& mime_type, const std::string& original_name, bool pinned, - bool shared); + bool shared, + const mojom::Capabilities& capabilities); const base::FilePath& mount_path() { return mount_path_; }
diff --git a/chromeos/services/multidevice_setup/account_status_change_delegate_notifier_impl.cc b/chromeos/services/multidevice_setup/account_status_change_delegate_notifier_impl.cc index 51e2b2f..18e88d3c 100644 --- a/chromeos/services/multidevice_setup/account_status_change_delegate_notifier_impl.cc +++ b/chromeos/services/multidevice_setup/account_status_change_delegate_notifier_impl.cc
@@ -156,7 +156,8 @@ CheckForNewUserPotentialHostExistsEvent(host_status_with_device); CheckForExistingUserHostSwitchedEvent(host_status_with_device, host_device_id_before_update); - CheckForExistingUserChromebookAddedEvent(host_device_id_before_update); + CheckForExistingUserChromebookAddedEvent(host_status_with_device, + host_device_id_before_update); } void AccountStatusChangeDelegateNotifierImpl:: @@ -207,6 +208,7 @@ void AccountStatusChangeDelegateNotifierImpl:: CheckForExistingUserChromebookAddedEvent( + const HostStatusProvider::HostStatusWithDevice& host_status_with_device, const base::Optional<std::string>& host_device_id_before_update) { // The Chromebook added event requires that a set host was found by the // update, i.e. there was no host before the host status update but afterward @@ -214,7 +216,8 @@ if (!host_device_id_from_most_recent_update_ || host_device_id_before_update) return; - delegate()->OnNewChromebookAddedForExistingUser(); + delegate()->OnNewChromebookAddedForExistingUser( + host_status_with_device.host_device()->name()); pref_service_->SetInt64(kExistingUserChromebookAddedPrefName, clock_->Now().ToJavaTime()); }
diff --git a/chromeos/services/multidevice_setup/account_status_change_delegate_notifier_impl.h b/chromeos/services/multidevice_setup/account_status_change_delegate_notifier_impl.h index 150d2246..66950f8 100644 --- a/chromeos/services/multidevice_setup/account_status_change_delegate_notifier_impl.h +++ b/chromeos/services/multidevice_setup/account_status_change_delegate_notifier_impl.h
@@ -86,6 +86,7 @@ const HostStatusProvider::HostStatusWithDevice& host_status_with_device, const base::Optional<std::string>& host_device_id_before_update); void CheckForExistingUserChromebookAddedEvent( + const HostStatusProvider::HostStatusWithDevice& host_status_with_device, const base::Optional<std::string>& host_device_id_before_update); // Loads data from previous session using PrefService.
diff --git a/chromeos/services/multidevice_setup/fake_account_status_change_delegate.cc b/chromeos/services/multidevice_setup/fake_account_status_change_delegate.cc index cb340b5..d06af56 100644 --- a/chromeos/services/multidevice_setup/fake_account_status_change_delegate.cc +++ b/chromeos/services/multidevice_setup/fake_account_status_change_delegate.cc
@@ -28,7 +28,8 @@ ++num_existing_user_host_switched_events_handled_; } -void FakeAccountStatusChangeDelegate::OnNewChromebookAddedForExistingUser() { +void FakeAccountStatusChangeDelegate::OnNewChromebookAddedForExistingUser( + const std::string& new_host_device_name) { ++num_existing_user_chromebook_added_events_handled_; }
diff --git a/chromeos/services/multidevice_setup/fake_account_status_change_delegate.h b/chromeos/services/multidevice_setup/fake_account_status_change_delegate.h index 7c6b4a4..8f65e2a5 100644 --- a/chromeos/services/multidevice_setup/fake_account_status_change_delegate.h +++ b/chromeos/services/multidevice_setup/fake_account_status_change_delegate.h
@@ -36,7 +36,8 @@ void OnPotentialHostExistsForNewUser() override; void OnConnectedHostSwitchedForExistingUser( const std::string& new_host_device_name) override; - void OnNewChromebookAddedForExistingUser() override; + void OnNewChromebookAddedForExistingUser( + const std::string& new_host_device_name) override; private: size_t num_new_user_events_handled_ = 0u;
diff --git a/chromeos/services/multidevice_setup/multidevice_setup_impl.cc b/chromeos/services/multidevice_setup/multidevice_setup_impl.cc index 5ae1536..6cea743 100644 --- a/chromeos/services/multidevice_setup/multidevice_setup_impl.cc +++ b/chromeos/services/multidevice_setup/multidevice_setup_impl.cc
@@ -251,7 +251,8 @@ kTestDeviceNameForDebugNotification); break; case mojom::EventTypeForDebugging::kExistingUserNewChromebookAdded: - delegate->OnNewChromebookAddedForExistingUser(); + delegate->OnNewChromebookAddedForExistingUser( + kTestDeviceNameForDebugNotification); break; default: NOTREACHED();
diff --git a/chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom b/chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom index a5f5c517..85209c3 100644 --- a/chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom +++ b/chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom
@@ -94,14 +94,13 @@ // Callback which indicates that the currently-connected MultiDevice host has // changed. This likely means that the user has changed MultiDevice settings // on another device. This function is only called if the current user has - // already set up MultiDevice features. Note: |new_host_device_name| is - // expected to be a UTF-8 string. + // already set up MultiDevice features. OnConnectedHostSwitchedForExistingUser(string new_host_device_name); // Callback which indicates that a new Chromebook was added to the account of // the current user. This function is only called if the current user has // already set up MultiDevice features. - OnNewChromebookAddedForExistingUser(); + OnNewChromebookAddedForExistingUser(string new_host_device_name); }; interface HostStatusObserver {
diff --git a/components/autofill/ios/browser/autofill_agent.mm b/components/autofill/ios/browser/autofill_agent.mm index bf1c03ee..13b03d91 100644 --- a/components/autofill/ios/browser/autofill_agent.mm +++ b/components/autofill/ios/browser/autofill_agent.mm
@@ -371,8 +371,7 @@ webState:(web::WebState*)webState completionHandler:(SuggestionsAvailableCompletion)completion { web::WebFrame* frame = - web::WebFramesManager::FromWebState(webState)->GetFrameWithId( - base::SysNSStringToUTF8(frameID)); + GetWebFrameWithId(webState, base::SysNSStringToUTF8(frameID)); autofill::AutofillManager* autofillManager = [self autofillManagerFromWebState:webState webFrame:frame]; if (!autofillManager) @@ -574,6 +573,7 @@ - (void)processPage:(web::WebState*)webState { web::WebFramesManager* framesManager = web::WebFramesManager::FromWebState(webState); + DCHECK(framesManager); if (!autofill::switches::IsAutofillIFrameMessagingEnabled()) { [self processFrame:framesManager->GetMainWebFrame() inWebState:webState]; } else {
diff --git a/components/autofill_assistant/browser/protocol_utils.cc b/components/autofill_assistant/browser/protocol_utils.cc index c44b2ff..5184f25 100644 --- a/components/autofill_assistant/browser/protocol_utils.cc +++ b/components/autofill_assistant/browser/protocol_utils.cc
@@ -77,8 +77,8 @@ const auto& presentation = script_proto.presentation(); script->handle.name = presentation.name(); script->handle.autostart = presentation.autostart(); - script->precondition = - ScriptPrecondition::FromProto(presentation.precondition()); + script->precondition = ScriptPrecondition::FromProto( + script_proto.path(), presentation.precondition()); script->priority = presentation.priority(); if (script->handle.name.empty() || script->handle.path.empty() ||
diff --git a/components/autofill_assistant/browser/script_precondition.cc b/components/autofill_assistant/browser/script_precondition.cc index b843b15e..c81793d51 100644 --- a/components/autofill_assistant/browser/script_precondition.cc +++ b/components/autofill_assistant/browser/script_precondition.cc
@@ -7,6 +7,7 @@ #include <utility> #include "base/bind.h" +#include "base/strings/strcat.h" #include "base/threading/thread_task_runner_handle.h" #include "components/autofill_assistant/browser/service.pb.h" #include "third_party/re2/src/re2/re2.h" @@ -15,6 +16,7 @@ namespace autofill_assistant { // Static std::unique_ptr<ScriptPrecondition> ScriptPrecondition::FromProto( + const std::string& script_path, const ScriptPreconditionProto& script_precondition_proto) { std::vector<std::vector<std::string>> elements_exist; for (const auto& element : script_precondition_proto.elements_exist()) { @@ -22,6 +24,12 @@ for (const auto& selector : element.selectors()) { selectors.emplace_back(selector); } + if (selectors.empty()) { + DLOG(WARNING) + << "Empty selectors in script precondition for script path: " + << script_path << "."; + continue; + } elements_exist.emplace_back(selectors); } @@ -34,7 +42,8 @@ for (const auto& pattern : script_precondition_proto.path_pattern()) { auto re = std::make_unique<re2::RE2>(pattern); if (re->error_code() != re2::RE2::NoError) { - LOG(ERROR) << "Invalid regexp in script precondition '" << pattern; + DLOG(ERROR) << "Invalid regexp in script precondition '" << pattern + << "' for script path: " << script_path << "."; return nullptr; } path_pattern.emplace_back(std::move(re)); @@ -140,7 +149,10 @@ if (domain_match_.empty()) return true; - return domain_match_.find(url.host()) != domain_match_.end(); + // We require the scheme and host parts to match. + // TODO(crbug.com/806868): Consider using Origin::IsSameOriginWith here. + std::string scheme_domain = base::StrCat({url.scheme(), "://", url.host()}); + return domain_match_.find(scheme_domain) != domain_match_.end(); } bool ScriptPrecondition::MatchPath(const GURL& url) const {
diff --git a/components/autofill_assistant/browser/script_precondition.h b/components/autofill_assistant/browser/script_precondition.h index 5455c49..11a8247b 100644 --- a/components/autofill_assistant/browser/script_precondition.h +++ b/components/autofill_assistant/browser/script_precondition.h
@@ -28,7 +28,11 @@ public: // Builds a precondition from its proto representation. Returns nullptr if the // preconditions are invalid. + // + // Note: The |script_path| paramter is used to allow logging misconfigured + // scripts. static std::unique_ptr<ScriptPrecondition> FromProto( + const std::string& script_path, const ScriptPreconditionProto& script_precondition_proto); ScriptPrecondition(
diff --git a/components/autofill_assistant/browser/script_precondition_unittest.cc b/components/autofill_assistant/browser/script_precondition_unittest.cc index 0d498dd5..44c37d6 100644 --- a/components/autofill_assistant/browser/script_precondition_unittest.cc +++ b/components/autofill_assistant/browser/script_precondition_unittest.cc
@@ -77,7 +77,7 @@ // Runs the preconditions and returns the result. bool Check(const ScriptPreconditionProto& proto) { - auto precondition = ScriptPrecondition::FromProto(proto); + auto precondition = ScriptPrecondition::FromProto("unused", proto); if (!precondition) return false; @@ -99,17 +99,36 @@ TEST_F(ScriptPreconditionTest, DomainMatch) { ScriptPreconditionProto proto; - proto.add_domain("match.example.com"); - proto.add_domain("alsomatch.example.com"); + proto.add_domain("http://match.example.com"); + proto.add_domain("http://alsomatch.example.com"); SetUrl("http://match.example.com/path"); EXPECT_TRUE(Check(proto)); + // Scheme must match. + SetUrl("https://match.example.com/path"); + EXPECT_FALSE(Check(proto)) << "Scheme must match."; + + // Port is ignored. + SetUrl("http://match.example.com:8080"); + EXPECT_TRUE(Check(proto)) << "Port should be ignored"; + SetUrl("http://nomatch.example.com/path"); - EXPECT_FALSE(Check(proto)); + EXPECT_FALSE(Check(proto)) << "nomatch"; SetUrl("http://alsomatch.example.com/path"); - EXPECT_TRUE(Check(proto)); + EXPECT_TRUE(Check(proto)) << "Path should be ignored"; + + SetUrl("http://alsomatch.example.com/path?a=b"); + EXPECT_TRUE(Check(proto)) << "Query should be ignored."; +} + +TEST_F(ScriptPreconditionTest, TrailingSlash) { + ScriptPreconditionProto proto; + proto.add_domain("http://example.com/"); + + SetUrl("http://example.com/path"); + EXPECT_FALSE(Check(proto)); } TEST_F(ScriptPreconditionTest, PathFullMatch) { @@ -142,7 +161,18 @@ ScriptPreconditionProto proto; proto.add_path_pattern("invalid["); - EXPECT_EQ(nullptr, ScriptPrecondition::FromProto(proto)); + EXPECT_EQ(nullptr, ScriptPrecondition::FromProto("unused", proto)); +} + +TEST_F(ScriptPreconditionTest, IgnoreEmptyElementsExist) { + EXPECT_CALL(mock_web_controller_, OnElementExists(ElementsAre("exists"), _)) + .WillOnce(RunOnceCallback<1>(true)); + + ScriptPreconditionProto proto; + proto.add_elements_exist()->add_selectors("exists"); + proto.add_elements_exist(); + + EXPECT_TRUE(Check(proto)); } TEST_F(ScriptPreconditionTest, WrongScriptStatusEqualComparator) { @@ -237,20 +267,18 @@ TEST_F(ScriptPreconditionTest, MultipleConditions) { ScriptPreconditionProto proto; - proto.add_domain("match.example.com"); + proto.add_domain("http://match.example.com"); proto.add_path_pattern("/path"); proto.add_elements_exist()->add_selectors("exists"); // Domain and path don't match. EXPECT_FALSE(Check(proto)); - // Domain, path and selector match. SetUrl("http://match.example.com/path"); - EXPECT_TRUE(Check(proto)); + EXPECT_TRUE(Check(proto)) << "Domain, path and selector must match."; - // Selector doesn't match. proto.mutable_elements_exist(0)->set_selectors(0, "does_not_exist"); - EXPECT_FALSE(Check(proto)); + EXPECT_FALSE(Check(proto)) << "Element can not match."; } TEST_F(ScriptPreconditionTest, FormValueMatch) {
diff --git a/components/discardable_memory/service/discardable_shared_memory_manager.cc b/components/discardable_memory/service/discardable_shared_memory_manager.cc index 748e0a0..99fcdfe 100644 --- a/components/discardable_memory/service/discardable_shared_memory_manager.cc +++ b/components/discardable_memory/service/discardable_shared_memory_manager.cc
@@ -14,7 +14,6 @@ #include "base/command_line.h" #include "base/macros.h" #include "base/memory/discardable_memory.h" -#include "base/memory/memory_coordinator_client_registry.h" #include "base/memory/shared_memory_tracker.h" #include "base/numerics/safe_math.h" #include "base/process/memory.h" @@ -235,11 +234,9 @@ base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( this, "DiscardableSharedMemoryManager", base::ThreadTaskRunnerHandle::Get()); - base::MemoryCoordinatorClientRegistry::GetInstance()->Register(this); } DiscardableSharedMemoryManager::~DiscardableSharedMemoryManager() { - base::MemoryCoordinatorClientRegistry::GetInstance()->Unregister(this); base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider( this); @@ -405,32 +402,6 @@ return bytes_allocated_; } -void DiscardableSharedMemoryManager::OnMemoryStateChange( - base::MemoryState state) { - // Don't use SetMemoryLimit() as it frees up existing allocations. - // OnPurgeMemory() is called to actually free up memory. - base::AutoLock lock(lock_); - switch (state) { - case base::MemoryState::NORMAL: - memory_limit_ = default_memory_limit_; - break; - case base::MemoryState::THROTTLED: - memory_limit_ = 0; - break; - case base::MemoryState::SUSPENDED: - // Note that SUSPENDED never occurs in the main browser process so far. - // Fall through. - case base::MemoryState::UNKNOWN: - NOTREACHED(); - break; - } -} - -void DiscardableSharedMemoryManager::OnPurgeMemory() { - base::AutoLock lock(lock_); - ReduceMemoryUsageUntilWithinLimit(0); -} - void DiscardableSharedMemoryManager::WillDestroyCurrentMessageLoop() { // The mojo thead is going to be destroyed. We should invalidate all related // weak ptrs and remove the destrunction observer.
diff --git a/components/discardable_memory/service/discardable_shared_memory_manager.h b/components/discardable_memory/service/discardable_shared_memory_manager.h index 354cf393..6005fd1 100644 --- a/components/discardable_memory/service/discardable_shared_memory_manager.h +++ b/components/discardable_memory/service/discardable_shared_memory_manager.h
@@ -17,7 +17,6 @@ #include "base/macros.h" #include "base/memory/discardable_memory_allocator.h" #include "base/memory/discardable_shared_memory.h" -#include "base/memory/memory_coordinator_client.h" #include "base/memory/memory_pressure_listener.h" #include "base/memory/ref_counted.h" #include "base/memory/unsafe_shared_memory_region.h" @@ -49,7 +48,6 @@ class DISCARDABLE_MEMORY_EXPORT DiscardableSharedMemoryManager : public base::DiscardableMemoryAllocator, public base::trace_event::MemoryDumpProvider, - public base::MemoryCoordinatorClient, public base::MessageLoopCurrent::DestructionObserver { public: DiscardableSharedMemoryManager(); @@ -117,10 +115,6 @@ return a->memory()->last_known_usage() > b->memory()->last_known_usage(); } - // base::MemoryCoordinatorClient implementation: - void OnMemoryStateChange(base::MemoryState state) override; - void OnPurgeMemory() override; - // base::MessageLoopCurrent::DestructionObserver implementation: void WillDestroyCurrentMessageLoop() override;
diff --git a/components/domain_reliability/quic_error_mapping.cc b/components/domain_reliability/quic_error_mapping.cc index 767ca15..ccf9748 100644 --- a/components/domain_reliability/quic_error_mapping.cc +++ b/components/domain_reliability/quic_error_mapping.cc
@@ -291,6 +291,7 @@ {quic::QUIC_INVALID_PATH_RESPONSE_DATA, "quic.invalid.path_response_data"}, {quic::QUIC_INVALID_MESSAGE_DATA, "quic.invalid.message_data"}, {quic::IETF_QUIC_PROTOCOL_VIOLATION, "quic.ietf.protocol_violation"}, + {quic::QUIC_INVALID_NEW_TOKEN, "quic.invalid_new_token"}, // No error. Used as bound while iterating. {quic::QUIC_LAST_ERROR, "quic.last_error"}};
diff --git a/components/feed/core/feed_journal_mutation_unittest.cc b/components/feed/core/feed_journal_mutation_unittest.cc index f6c8346..b220a5d6 100644 --- a/components/feed/core/feed_journal_mutation_unittest.cc +++ b/components/feed/core/feed_journal_mutation_unittest.cc
@@ -13,7 +13,11 @@ const char kJournalName1[] = "Journal1"; const char kJournalName2[] = "Journal2"; -const char kJournalValue[] = "value"; +const uint8_t kJournalValue[] = { + 8, 1, 18, 40, 70, 69, 65, 84, 85, 82, 69, 58, 58, + 115, 116, 111, 114, 105, 101, 115, 46, 102, 58, 58, 45, 56, + 57, 48, 56, 51, 51, 54, 49, 56, 52, 53, 48, 48, 54, + 55, 56, 48, 51, 57, 24, -119, -10, -71, -35, 5}; } // namespace @@ -30,13 +34,19 @@ EXPECT_EQ(mutation.journal_name(), kJournalName1); EXPECT_TRUE(mutation.Empty()); - mutation.AddAppendOperation(kJournalValue); + std::vector<uint8_t> bytes_vector( + kJournalValue, + kJournalValue + sizeof(kJournalValue) / sizeof(kJournalValue[0])); + + mutation.AddAppendOperation( + std::string(bytes_vector.begin(), bytes_vector.end())); EXPECT_FALSE(mutation.Empty()); JournalOperation operation = mutation.TakeFristOperation(); EXPECT_TRUE(mutation.Empty()); EXPECT_EQ(operation.type(), JournalOperation::JOURNAL_APPEND); - EXPECT_EQ(operation.value(), kJournalValue); + EXPECT_EQ(operation.value(), + std::string(bytes_vector.begin(), bytes_vector.end())); } TEST_F(FeedJournalMutationTest, AddCopyOperation) {
diff --git a/components/infobars/core/infobar_delegate.h b/components/infobars/core/infobar_delegate.h index 3100501..51f3fb6 100644 --- a/components/infobars/core/infobar_delegate.h +++ b/components/infobars/core/infobar_delegate.h
@@ -155,6 +155,7 @@ BLOATED_RENDERER_INFOBAR_DELEGATE = 84, SUPERVISED_USERS_DEPRECATED_INFOBAR_DELEGATE = 85, NEAR_OOM_REDUCTION_INFOBAR_ANDROID = 86, + LITE_PAGE_PREVIEWS_INFOBAR = 87, }; // Describes navigation events, used to decide whether infobars should be
diff --git a/components/neterror/resources/neterror.html b/components/neterror/resources/neterror.html index 96f398c..be2f4bcd 100644 --- a/components/neterror/resources/neterror.html +++ b/components/neterror/resources/neterror.html
@@ -63,16 +63,14 @@ </div> </div> <div id="offline-content-list" hidden> - <webview> - <div class="offline-content-list-title" jsselect="offlineContentList" - jscontent="title"></div> - <div id="offline-content-suggestions"></div> - <div class="offline-content-list-action"> - <a class="link-button" onclick="launchDownloadsPage()" - jsselect="offlineContentList" jscontent="actionText"> - </a> - </div> - </webview> + <div class="offline-content-list-title" jsselect="offlineContentList" + jscontent="title"></div> + <div id="offline-content-suggestions"></div> + <div class="offline-content-list-action"> + <a class="link-button" onclick="launchDownloadsPage()" + jsselect="offlineContentList" jscontent="actionText"> + </a> + </div> </div> <div id="offline-content-summary" onclick="launchDownloadsPage()" hidden> <div class="offline-content-summary-images">
diff --git a/components/viz/service/display_embedder/gl_output_surface_buffer_queue_android.cc b/components/viz/service/display_embedder/gl_output_surface_buffer_queue_android.cc index 7739592..c938519a 100644 --- a/components/viz/service/display_embedder/gl_output_surface_buffer_queue_android.cc +++ b/components/viz/service/display_embedder/gl_output_surface_buffer_queue_android.cc
@@ -5,7 +5,7 @@ #include "components/viz/service/display_embedder/gl_output_surface_buffer_queue_android.h" #include "components/viz/service/display_embedder/compositor_overlay_candidate_validator_android.h" -#include "ui/gl/gl_bindings.h" +#include "third_party/khronos/GLES2/gl2.h" namespace viz {
diff --git a/content/app/strings/content_strings.grd b/content/app/strings/content_strings.grd index eacdf8f..8017be1 100644 --- a/content/app/strings/content_strings.grd +++ b/content/app/strings/content_strings.grd
@@ -704,22 +704,6 @@ video </message> - <message name="IDS_AX_MEDIA_MUTE_BUTTON_HELP" desc="Accessibility help description for mute button"> - mute audio track - </message> - - <message name="IDS_AX_MEDIA_UNMUTE_BUTTON_HELP" desc="Accessibility help description for turn mute off button"> - unmute audio track - </message> - - <message name="IDS_AX_MEDIA_PLAY_BUTTON_HELP" desc="Accessibility help description for play button"> - begin playback - </message> - - <message name="IDS_AX_MEDIA_PAUSE_BUTTON_HELP" desc="Accessibility help description for pause button"> - pause playback - </message> - <message name="IDS_AX_MEDIA_AUDIO_SLIDER_HELP" desc="Accessibility help description for audio timeline slider"> audio time scrubber </message> @@ -740,42 +724,6 @@ number of seconds of movie remaining </message> - <message name="IDS_AX_MEDIA_ENTER_FULL_SCREEN_BUTTON_HELP" desc="Accessibility help description for enter fullscreen button"> - play movie in full screen mode - </message> - - <message name="IDS_AX_MEDIA_EXIT_FULL_SCREEN_BUTTON_HELP" desc="Accessibility help description for exit fullscreen button"> - exit full screen - </message> - - <message name="IDS_AX_MEDIA_DISPLAY_CUT_OUT_FULL_SCREEN_BUTTON_HELP" desc="Accessibility help description for display cutout fullscreen button"> - toggle fullscreen into display cutout area - </message> - - <message name="IDS_AX_MEDIA_ENTER_PICTURE_IN_PICTURE_BUTTON_HELP" desc="Accessibility help description for enter Picture-in-Picture button"> - play video in picture-in-picture mode - </message> - - <message name="IDS_AX_MEDIA_EXIT_PICTURE_IN_PICTURE_BUTTON_HELP" desc="Accessibility help description for exit Picture-in-Picture button"> - exit picture-in-picture - </message> - - <message name="IDS_AX_MEDIA_SHOW_CLOSED_CAPTIONS_BUTTON_HELP" desc="Accessibility help description for show closed captions button"> - start displaying closed captions - </message> - - <message name="IDS_AX_MEDIA_HIDE_CLOSED_CAPTIONS_BUTTON_HELP" desc="Accessibility help description for hide closed captions button"> - stop displaying closed captions - </message> - - <message name="IDS_AX_MEDIA_CAST_OFF_BUTTON_HELP" desc="Accessibility help description for remote playback button"> - play on remote device - </message> - - <message name="IDS_AX_MEDIA_CAST_ON_BUTTON_HELP" desc="Accessibility help description for remote playback control button"> - control remote playback - </message> - <message name="IDS_AX_MEDIA_OVERFLOW_BUTTON_HELP" desc="Accessibility help description for overflow button."> more options </message>
diff --git a/content/browser/appcache/appcache_request_handler.cc b/content/browser/appcache/appcache_request_handler.cc index 459c79a..53eb77c 100644 --- a/content/browser/appcache/appcache_request_handler.cc +++ b/content/browser/appcache/appcache_request_handler.cc
@@ -600,6 +600,8 @@ return false; } DCHECK(was_called); + if (IsMainResourceType(resource_type_)) + should_create_subresource_loader_ = true; return true; }
diff --git a/content/browser/devtools/devtools_video_consumer.cc b/content/browser/devtools/devtools_video_consumer.cc index f06866c3..1dd814c 100644 --- a/content/browser/devtools/devtools_video_consumer.cc +++ b/content/browser/devtools/devtools_video_consumer.cc
@@ -57,7 +57,7 @@ skbitmap.allocN32Pixels(frame->visible_rect().width(), frame->visible_rect().height()); cc::SkiaPaintCanvas canvas(skbitmap); - renderer.Copy(frame, &canvas, media::Context3D()); + renderer.Copy(frame, &canvas, media::Context3D(), nullptr); return skbitmap; }
diff --git a/content/browser/frame_host/cross_process_frame_connector.cc b/content/browser/frame_host/cross_process_frame_connector.cc index 004cbb10..2ed248d 100644 --- a/content/browser/frame_host/cross_process_frame_connector.cc +++ b/content/browser/frame_host/cross_process_frame_connector.cc
@@ -556,16 +556,6 @@ // Actually log the UMA. UMA_HISTOGRAM_ENUMERATION("Stability.ChildFrameCrash.Visibility", visibility); - - if (visibility == CrashVisibility::kShownAfterCrashing) { - auto* rfh = frame_proxy_in_parent_renderer_->frame_tree_node() - ->current_frame_host(); - if (rfh->GetParent() && rfh->is_local_root()) { - UMA_HISTOGRAM_BOOLEAN( - "RenderFrameHostImpl.ReceivedPostMessageFromNonDescendant", - rfh->received_post_message_from_non_descendant()); - } - } } bool CrossProcessFrameConnector::IsVisible() {
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h index 1dc020f..2af671e 100644 --- a/content/browser/frame_host/render_frame_host_impl.h +++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -766,14 +766,6 @@ // for unload handler processing. void SetSubframeUnloadTimeoutForTesting(const base::TimeDelta& timeout); - bool received_post_message_from_non_descendant() const { - return received_post_message_from_non_descendant_; - } - - void did_receive_post_message_from_non_descendant() { - received_post_message_from_non_descendant_ = true; - } - // Returns the list of NavigationEntry ids corresponding to NavigationRequests // waiting to commit in this RenderFrameHost. std::set<int> GetNavigationEntryIdsPendingCommit(); @@ -1437,12 +1429,6 @@ // relevant NavigationEntry. int nav_entry_id_; - // Tracks if a frame has been influenced by post message from - // non-descendant frames. Useful for determining if silently reloading a - // crashed frame is safe. Post messages from descendants to not matter for - // this decision since they will be reloaded as well. - bool received_post_message_from_non_descendant_ = false; - // Used to swap out or shut down this RFH when the unload event is taking too // long to execute, depending on the number of active frames in the // SiteInstance. May be null in tests.
diff --git a/content/browser/frame_host/render_frame_proxy_host.cc b/content/browser/frame_host/render_frame_proxy_host.cc index bad4c9f..c357287 100644 --- a/content/browser/frame_host/render_frame_proxy_host.cc +++ b/content/browser/frame_host/render_frame_proxy_host.cc
@@ -381,11 +381,6 @@ ->SynchronizeVisualPropertiesIgnoringPendingAck(); } - if (!source_rfh->frame_tree_node()->IsDescendantOf( - target_rfh->frame_tree_node())) { - target_rfh->did_receive_post_message_from_non_descendant(); - } - // Ensure that we have a swapped-out RVH and proxy for the source frame // in the target SiteInstance. If it doesn't exist, create it on demand // and also create its opener chain, since that will also be accessible
diff --git a/content/browser/ppapi_plugin_process_host.cc b/content/browser/ppapi_plugin_process_host.cc index 1df1149..3c2cf89 100644 --- a/content/browser/ppapi_plugin_process_host.cc +++ b/content/browser/ppapi_plugin_process_host.cc
@@ -23,14 +23,15 @@ #include "content/common/child_process_host_impl.h" #include "content/common/content_switches_internal.h" #include "content/public/browser/content_browser_client.h" +#include "content/public/browser/network_service_instance.h" #include "content/public/common/content_constants.h" #include "content/public/common/content_switches.h" #include "content/public/common/pepper_plugin_info.h" #include "content/public/common/process_type.h" #include "content/public/common/sandboxed_process_launcher_delegate.h" #include "content/public/common/service_names.mojom.h" -#include "net/base/network_change_notifier.h" #include "ppapi/proxy/ppapi_messages.h" +#include "services/network/public/cpp/network_connection_tracker.h" #include "services/service_manager/sandbox/sandbox_type.h" #include "services/service_manager/sandbox/switches.h" #include "services/service_manager/zygote/common/zygote_buildflags.h" @@ -129,25 +130,38 @@ }; class PpapiPluginProcessHost::PluginNetworkObserver - : public net::NetworkChangeNotifier::NetworkChangeObserver { + : public network::NetworkConnectionTracker::NetworkConnectionObserver { public: explicit PluginNetworkObserver(PpapiPluginProcessHost* process_host) - : process_host_(process_host) { - net::NetworkChangeNotifier::AddNetworkChangeObserver(this); + : process_host_(process_host), + network_connection_tracker_(nullptr), + weak_factory_(this) { + GetNetworkConnectionTrackerFromUIThread( + base::BindOnce(&PluginNetworkObserver::SetNetworkConnectionTracker, + weak_factory_.GetWeakPtr())); + } + + void SetNetworkConnectionTracker( + network::NetworkConnectionTracker* network_connection_tracker) { + DCHECK(network_connection_tracker); + network_connection_tracker_ = network_connection_tracker; + network_connection_tracker_->AddNetworkConnectionObserver(this); } ~PluginNetworkObserver() override { - net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this); + if (network_connection_tracker_) + network_connection_tracker_->RemoveNetworkConnectionObserver(this); } - void OnNetworkChanged( - net::NetworkChangeNotifier::ConnectionType type) override { + void OnConnectionChanged(network::mojom::ConnectionType type) override { process_host_->Send(new PpapiMsg_SetNetworkState( - type != net::NetworkChangeNotifier::CONNECTION_NONE)); + type != network::mojom::ConnectionType::CONNECTION_NONE)); } private: PpapiPluginProcessHost* const process_host_; + network::NetworkConnectionTracker* network_connection_tracker_; + base::WeakPtrFactory<PluginNetworkObserver> weak_factory_; }; PpapiPluginProcessHost::~PpapiPluginProcessHost() {
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc index d9faa8a4..c120832 100644 --- a/content/browser/renderer_host/compositor_impl_android.cc +++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -80,9 +80,11 @@ #include "gpu/ipc/client/gpu_channel_host.h" #include "gpu/ipc/common/gpu_surface_tracker.h" #include "gpu/vulkan/buildflags.h" +#if BUILDFLAG(ENABLE_VULKAN) #include "gpu/vulkan/init/vulkan_factory.h" #include "gpu/vulkan/vulkan_implementation.h" #include "gpu/vulkan/vulkan_surface.h" +#endif #include "services/viz/privileged/interfaces/compositing/frame_sink_manager.mojom.h" #include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h" #include "services/ws/public/cpp/gpu/context_provider_command_buffer.h"
diff --git a/content/browser/renderer_host/render_widget_targeter.cc b/content/browser/renderer_host/render_widget_targeter.cc index 815bdf0..c55163a 100644 --- a/content/browser/renderer_host/render_widget_targeter.cc +++ b/content/browser/renderer_host/render_widget_targeter.cc
@@ -60,7 +60,6 @@ } ~TracingUmaTracker() = default; TracingUmaTracker(TracingUmaTracker&& tracker) = default; - TracingUmaTracker& operator=(TracingUmaTracker&& tracker) = default; void Stop() { TRACE_EVENT_ASYNC_END0(
diff --git a/content/browser/service_worker/service_worker_provider_host.cc b/content/browser/service_worker/service_worker_provider_host.cc index 8e80b67a..7159d70 100644 --- a/content/browser/service_worker/service_worker_provider_host.cc +++ b/content/browser/service_worker/service_worker_provider_host.cc
@@ -1218,11 +1218,10 @@ AsWeakPtr(), std::move(controller_request))); } -void ServiceWorkerProviderHost::CloneForWorker( +void ServiceWorkerProviderHost::CloneContainerHost( mojom::ServiceWorkerContainerHostRequest container_host_request) { DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled()); - bindings_for_worker_threads_.AddBinding(this, - std::move(container_host_request)); + additional_bindings_.AddBinding(this, std::move(container_host_request)); } void ServiceWorkerProviderHost::Ping(PingCallback callback) {
diff --git a/content/browser/service_worker/service_worker_provider_host.h b/content/browser/service_worker/service_worker_provider_host.h index 9a950be..801a78dc 100644 --- a/content/browser/service_worker/service_worker_provider_host.h +++ b/content/browser/service_worker/service_worker_provider_host.h
@@ -541,7 +541,7 @@ void EnsureControllerServiceWorker( mojom::ControllerServiceWorkerRequest controller_request, mojom::ControllerServiceWorkerPurpose purpose) override; - void CloneForWorker( + void CloneContainerHost( mojom::ServiceWorkerContainerHostRequest container_host_request) override; void Ping(PingCallback callback) override; void HintToUpdateServiceWorker() override; @@ -673,17 +673,10 @@ // content::ServiceWorkerProviderHost will be destroyed. mojo::AssociatedBinding<mojom::ServiceWorkerContainerHost> binding_; - // Mojo bindings for provider host pointers which are used from (dedicated or - // shared) worker threads. - // When this is hosting a shared worker, |bindings_for_worker_threads_| - // contains exactly one element for the shared worker thread. This binding is - // needed because the host pointer which is bound to |binding_| can only be - // used from the main thread. - // When this is hosting a document, |bindings_for_worker_threads_| contains - // all dedicated workers associated with the document. This binding is needed - // for the host pointers which are used from the dedicated worker threads. - mojo::BindingSet<mojom::ServiceWorkerContainerHost> - bindings_for_worker_threads_; + // Container host bindings other than the original |binding_|. These include + // bindings for container host pointers used from (dedicated or shared) worker + // threads, or from ServiceWorkerSubresourceLoaderFactory. + mojo::BindingSet<mojom::ServiceWorkerContainerHost> additional_bindings_; // For service worker execution contexts. mojo::Binding<service_manager::mojom::InterfaceProvider>
diff --git a/content/browser/shared_worker/shared_worker_script_fetcher.cc b/content/browser/shared_worker/shared_worker_script_fetcher.cc index b3d3180bf..6c50fba1 100644 --- a/content/browser/shared_worker/shared_worker_script_fetcher.cc +++ b/content/browser/shared_worker/shared_worker_script_fetcher.cc
@@ -7,7 +7,6 @@ #include "base/feature_list.h" #include "content/browser/shared_worker/shared_worker_script_loader.h" #include "content/browser/shared_worker/shared_worker_script_loader_factory.h" -#include "content/common/navigation_subresource_loader_params.h" #include "content/common/throttling_url_loader.h" #include "content/public/browser/browser_thread.h" #include "content/public/common/url_loader_throttle.h" @@ -71,7 +70,8 @@ CreateAndStartCallback callback) : script_loader_factory_(std::move(script_loader_factory)), resource_request_(std::move(resource_request)), - callback_(std::move(callback)) { + callback_(std::move(callback)), + response_url_loader_binding_(this) { DCHECK_CURRENTLY_ON(BrowserThread::IO); } @@ -104,14 +104,49 @@ const network::ResourceResponseHead& head) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - // TODO(nhiroki): Support AppCache's fallback case. See - // NavigationLoaderInterceptor::MaybeCreateLoaderForResponse() for - // reference (https://crbug.com/715632). + base::WeakPtr<SharedWorkerScriptLoader> script_loader = + script_loader_factory_->GetScriptLoader(); + if (script_loader && script_loader->default_loader_used_) { + // If the default network loader was used to handle the URL load request we + // need to see if the request interceptors want to potentially create a new + // loader for the response, e.g. AppCache's fallback. + DCHECK(!response_url_loader_); + network::mojom::URLLoaderClientRequest response_client_request; + if (script_loader->MaybeCreateLoaderForResponse(head, &response_url_loader_, + &response_client_request, + url_loader_.get())) { + DCHECK(response_url_loader_); + response_url_loader_binding_.Bind(std::move(response_client_request)); + subresource_loader_params_ = script_loader->TakeSubresourceLoaderParams(); + url_loader_.reset(); + // OnReceiveResponse() will be called again. + return; + } + } blink::mojom::SharedWorkerMainScriptLoadParamsPtr main_script_load_params = blink::mojom::SharedWorkerMainScriptLoadParams::New(); + + // Fill in params for loading shared worker's main script and subresources. main_script_load_params->response_head = head; - main_script_load_params->url_loader_client_endpoints = url_loader_->Unbind(); + if (url_loader_) { + // The main script was served by a request interceptor or the default + // network loader. + DCHECK(!response_url_loader_); + main_script_load_params->url_loader_client_endpoints = + url_loader_->Unbind(); + subresource_loader_params_ = script_loader->TakeSubresourceLoaderParams(); + } else { + // The main script was served by the default network loader first, and then + // a request interceptor created another loader |response_url_loader_| for + // serving an alternative response. + DCHECK(response_url_loader_); + DCHECK(response_url_loader_binding_.is_bound()); + main_script_load_params->url_loader_client_endpoints = + network::mojom::URLLoaderClientEndpoints::New( + response_url_loader_.PassInterface(), + response_url_loader_binding_.Unbind()); + } for (size_t i = 0; i < redirect_infos_.size(); ++i) { main_script_load_params->redirect_infos.emplace_back(redirect_infos_[i]); @@ -119,11 +154,8 @@ redirect_response_heads_[i]); } - base::Optional<SubresourceLoaderParams> subresource_loader_params = - script_loader_factory_->TakeSubresourceLoaderParams(); - std::move(callback_).Run(std::move(main_script_load_params), - std::move(subresource_loader_params), + std::move(subresource_loader_params_), true /* success */); delete this; }
diff --git a/content/browser/shared_worker/shared_worker_script_fetcher.h b/content/browser/shared_worker/shared_worker_script_fetcher.h index af7e55a..4117d0d 100644 --- a/content/browser/shared_worker/shared_worker_script_fetcher.h +++ b/content/browser/shared_worker/shared_worker_script_fetcher.h
@@ -7,6 +7,8 @@ #include "base/callback.h" #include "base/optional.h" +#include "content/common/navigation_subresource_loader_params.h" +#include "mojo/public/cpp/bindings/binding.h" #include "net/url_request/redirect_info.h" #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" #include "services/network/public/mojom/url_loader.mojom.h" @@ -22,7 +24,6 @@ class SharedWorkerScriptLoaderFactory; class ThrottlingURLLoader; class URLLoaderThrottle; -struct SubresourceLoaderParams; // NetworkService (PlzWorker): // This is an implementation of the URLLoaderClient for shared worker's main @@ -71,10 +72,22 @@ void OnComplete(const network::URLLoaderCompletionStatus& status) override; std::unique_ptr<SharedWorkerScriptLoaderFactory> script_loader_factory_; + std::unique_ptr<network::ResourceRequest> resource_request_; CreateAndStartCallback callback_; + + // URLLoader instance backed by a request interceptor (e.g., + // AppCacheRequestHandler) or the network service. std::unique_ptr<ThrottlingURLLoader> url_loader_; + // URLLoader instance for handling a response received from the default + // network loader. This can be provided by an interceptor. For example, + // AppCache's interceptor creates this for AppCache's fallback case. + network::mojom::URLLoaderPtr response_url_loader_; + mojo::Binding<network::mojom::URLLoaderClient> response_url_loader_binding_; + + base::Optional<SubresourceLoaderParams> subresource_loader_params_; + std::vector<net::RedirectInfo> redirect_infos_; std::vector<network::ResourceResponseHead> redirect_response_heads_; };
diff --git a/content/browser/shared_worker/shared_worker_script_loader.cc b/content/browser/shared_worker/shared_worker_script_loader.cc index 4854a89..11c292b 100644 --- a/content/browser/shared_worker/shared_worker_script_loader.cc +++ b/content/browser/shared_worker/shared_worker_script_loader.cc
@@ -117,6 +117,7 @@ void SharedWorkerScriptLoader::LoadFromNetwork( bool reset_subresource_loader_params) { + default_loader_used_ = true; network::mojom::URLLoaderClientPtr client; if (url_loader_client_binding_) url_loader_client_binding_.Unbind(); @@ -245,4 +246,22 @@ client_->OnComplete(status); } +bool SharedWorkerScriptLoader::MaybeCreateLoaderForResponse( + const network::ResourceResponseHead& response, + network::mojom::URLLoaderPtr* response_url_loader, + network::mojom::URLLoaderClientRequest* response_client_request, + ThrottlingURLLoader* url_loader) { + DCHECK(default_loader_used_); + for (auto& interceptor : interceptors_) { + if (interceptor->MaybeCreateLoaderForResponse(response, response_url_loader, + response_client_request, + url_loader)) { + subresource_loader_params_ = + interceptor->MaybeCreateSubresourceLoaderParams(); + return true; + } + } + return false; +} + } // namespace content
diff --git a/content/browser/shared_worker/shared_worker_script_loader.h b/content/browser/shared_worker/shared_worker_script_loader.h index 93b7140..017ca7f 100644 --- a/content/browser/shared_worker/shared_worker_script_loader.h +++ b/content/browser/shared_worker/shared_worker_script_loader.h
@@ -20,6 +20,7 @@ namespace content { class AppCacheHost; +class ThrottlingURLLoader; class NavigationLoaderInterceptor; class ResourceContext; class ServiceWorkerProviderHost; @@ -83,12 +84,25 @@ mojo::ScopedDataPipeConsumerHandle body) override; void OnComplete(const network::URLLoaderCompletionStatus& status) override; + // Returns a URLLoader client endpoint if an interceptor wants to handle the + // response, i.e. return a different response. For e.g. AppCache may have + // fallback content. + bool MaybeCreateLoaderForResponse( + const network::ResourceResponseHead& response, + network::mojom::URLLoaderPtr* response_url_loader, + network::mojom::URLLoaderClientRequest* response_client_request, + ThrottlingURLLoader* url_loader); + base::Optional<SubresourceLoaderParams> TakeSubresourceLoaderParams() { return std::move(subresource_loader_params_); } base::WeakPtr<SharedWorkerScriptLoader> GetWeakPtr(); + // Set to true if the default URLLoader (network service) was used for the + // current request. + bool default_loader_used_ = false; + private: void Start(); void MaybeStartLoader(
diff --git a/content/browser/shared_worker/shared_worker_script_loader_factory.cc b/content/browser/shared_worker/shared_worker_script_loader_factory.cc index eae7545..bdbec0c 100644 --- a/content/browser/shared_worker/shared_worker_script_loader_factory.cc +++ b/content/browser/shared_worker/shared_worker_script_loader_factory.cc
@@ -89,10 +89,4 @@ NOTREACHED(); } -base::Optional<SubresourceLoaderParams> -SharedWorkerScriptLoaderFactory::TakeSubresourceLoaderParams() { - DCHECK(script_loader_); - return script_loader_->TakeSubresourceLoaderParams(); -} - } // namespace content
diff --git a/content/browser/shared_worker/shared_worker_script_loader_factory.h b/content/browser/shared_worker/shared_worker_script_loader_factory.h index 4eedffb8..58072e3 100644 --- a/content/browser/shared_worker/shared_worker_script_loader_factory.h +++ b/content/browser/shared_worker/shared_worker_script_loader_factory.h
@@ -59,7 +59,9 @@ traffic_annotation) override; void Clone(network::mojom::URLLoaderFactoryRequest request) override; - base::Optional<SubresourceLoaderParams> TakeSubresourceLoaderParams(); + base::WeakPtr<SharedWorkerScriptLoader> GetScriptLoader() { + return script_loader_; + } private: const int process_id_;
diff --git a/content/browser/web_package/signed_exchange_handler.cc b/content/browser/web_package/signed_exchange_handler.cc index f927098..cca3568d 100644 --- a/content/browser/web_package/signed_exchange_handler.cc +++ b/content/browser/web_package/signed_exchange_handler.cc
@@ -391,6 +391,7 @@ const bool force_fetch = load_flags_ & net::LOAD_BYPASS_CACHE; + cert_fetch_start_time_ = base::TimeTicks::Now(); cert_fetcher_ = std::move(cert_fetcher_factory_) ->CreateFetcherAndStart( cert_url, force_fetch, *version_, @@ -423,8 +424,13 @@ std::unique_ptr<SignedExchangeCertificateChain> cert_chain) { TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"), "SignedExchangeHandler::OnCertReceived"); + base::TimeDelta cert_fetch_duration = + base::TimeTicks::Now() - cert_fetch_start_time_; DCHECK_EQ(state_, State::kFetchingCertificate); if (result != SignedExchangeLoadResult::kSuccess) { + UMA_HISTOGRAM_MEDIUM_TIMES("SignedExchange.Time.CertificateFetch.Failure", + cert_fetch_duration); + signed_exchange_utils::ReportErrorAndTraceEvent( devtools_proxy_.get(), "Failed to fetch the certificate.", std::make_pair(0 /* signature_index */, @@ -433,6 +439,8 @@ return; } + UMA_HISTOGRAM_MEDIUM_TIMES("SignedExchange.Time.CertificateFetch.Success", + cert_fetch_duration); unverified_cert_chain_ = std::move(cert_chain); const SignedExchangeSignatureVerifier::Result verify_result =
diff --git a/content/browser/web_package/signed_exchange_handler.h b/content/browser/web_package/signed_exchange_handler.h index 2e94169..0465a06 100644 --- a/content/browser/web_package/signed_exchange_handler.h +++ b/content/browser/web_package/signed_exchange_handler.h
@@ -152,6 +152,8 @@ base::RepeatingCallback<int(void)> frame_tree_node_id_getter_; + base::TimeTicks cert_fetch_start_time_; + base::WeakPtrFactory<SignedExchangeHandler> weak_factory_; DISALLOW_COPY_AND_ASSIGN(SignedExchangeHandler);
diff --git a/content/browser/web_package/signed_exchange_request_handler_browsertest.cc b/content/browser/web_package/signed_exchange_request_handler_browsertest.cc index 0da4cb7..3599afc 100644 --- a/content/browser/web_package/signed_exchange_request_handler_browsertest.cc +++ b/content/browser/web_package/signed_exchange_request_handler_browsertest.cc
@@ -222,6 +222,8 @@ EXPECT_EQ(original_fingerprint, fingerprint); histogram_tester_.ExpectUniqueSample("SignedExchange.LoadResult", SignedExchangeLoadResult::kSuccess, 1); + histogram_tester_.ExpectTotalCount( + "SignedExchange.Time.CertificateFetch.Success", 1); } IN_PROC_BROWSER_TEST_F(SignedExchangeRequestHandlerBrowserTest, @@ -310,6 +312,8 @@ histogram_tester_.ExpectUniqueSample( "SignedExchange.LoadResult", SignedExchangeLoadResult::kCertFetchError, 1); + histogram_tester_.ExpectTotalCount( + "SignedExchange.Time.CertificateFetch.Failure", 1); } class SignedExchangeRequestHandlerRealCertVerifierBrowserTest
diff --git a/content/child/blink_platform_impl.cc b/content/child/blink_platform_impl.cc index 1e794d78..1f0bfd3c 100644 --- a/content/child/blink_platform_impl.cc +++ b/content/child/blink_platform_impl.cc
@@ -126,14 +126,6 @@ return IDS_AX_MEDIA_AUDIO_ELEMENT_HELP; case WebLocalizedString::kAXMediaVideoElementHelp: return IDS_AX_MEDIA_VIDEO_ELEMENT_HELP; - case WebLocalizedString::kAXMediaMuteButtonHelp: - return IDS_AX_MEDIA_MUTE_BUTTON_HELP; - case WebLocalizedString::kAXMediaUnMuteButtonHelp: - return IDS_AX_MEDIA_UNMUTE_BUTTON_HELP; - case WebLocalizedString::kAXMediaPlayButtonHelp: - return IDS_AX_MEDIA_PLAY_BUTTON_HELP; - case WebLocalizedString::kAXMediaPauseButtonHelp: - return IDS_AX_MEDIA_PAUSE_BUTTON_HELP; case WebLocalizedString::kAXMediaAudioSliderHelp: return IDS_AX_MEDIA_AUDIO_SLIDER_HELP; case WebLocalizedString::kAXMediaVideoSliderHelp: @@ -144,24 +136,6 @@ return IDS_AX_MEDIA_CURRENT_TIME_DISPLAY_HELP; case WebLocalizedString::kAXMediaTimeRemainingDisplayHelp: return IDS_AX_MEDIA_TIME_REMAINING_DISPLAY_HELP; - case WebLocalizedString::kAXMediaEnterFullscreenButtonHelp: - return IDS_AX_MEDIA_ENTER_FULL_SCREEN_BUTTON_HELP; - case WebLocalizedString::kAXMediaExitFullscreenButtonHelp: - return IDS_AX_MEDIA_EXIT_FULL_SCREEN_BUTTON_HELP; - case WebLocalizedString::kAXMediaDisplayCutoutFullscreenButtonHelp: - return IDS_AX_MEDIA_DISPLAY_CUT_OUT_FULL_SCREEN_BUTTON_HELP; - case WebLocalizedString::kAXMediaEnterPictureInPictureButtonHelp: - return IDS_AX_MEDIA_ENTER_PICTURE_IN_PICTURE_BUTTON_HELP; - case WebLocalizedString::kAXMediaExitPictureInPictureButtonHelp: - return IDS_AX_MEDIA_EXIT_PICTURE_IN_PICTURE_BUTTON_HELP; - case WebLocalizedString::kAXMediaShowClosedCaptionsButtonHelp: - return IDS_AX_MEDIA_SHOW_CLOSED_CAPTIONS_BUTTON_HELP; - case WebLocalizedString::kAXMediaHideClosedCaptionsButtonHelp: - return IDS_AX_MEDIA_HIDE_CLOSED_CAPTIONS_BUTTON_HELP; - case WebLocalizedString::kAXMediaCastOffButtonHelp: - return IDS_AX_MEDIA_CAST_OFF_BUTTON_HELP; - case WebLocalizedString::kAXMediaCastOnButtonHelp: - return IDS_AX_MEDIA_CAST_ON_BUTTON_HELP; case WebLocalizedString::kAXMediaOverflowButtonHelp: return IDS_AX_MEDIA_OVERFLOW_BUTTON_HELP; case WebLocalizedString::kAXMillisecondFieldText:
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc index 72fe98a..4cb11d61 100644 --- a/content/child/runtime_features.cc +++ b/content/child/runtime_features.cc
@@ -499,6 +499,9 @@ WebRuntimeFeatures::EnableNoHoverAfterLayoutChange( base::FeatureList::IsEnabled(features::kNoHoverAfterLayoutChange)); + + WebRuntimeFeatures::EnableNoHoverDuringScroll( + base::FeatureList::IsEnabled(features::kNoHoverDuringScroll)); } } // namespace content
diff --git a/content/common/service_worker/service_worker_container.mojom b/content/common/service_worker/service_worker_container.mojom index c6a7e1e..fd67fc7a 100644 --- a/content/common/service_worker/service_worker_container.mojom +++ b/content/common/service_worker/service_worker_container.mojom
@@ -34,7 +34,6 @@ // - For shared workers (non-S13nSW): // Associated with ServiceWorkerDispatcherHost, which is on the // channel-associated interface to the renderer process. -// IPC channel. // - For documents: // Associated with ServiceWorkerDispatcherHost, which is on the // channel-associated interface to the renderer process. @@ -91,9 +90,8 @@ ControllerServiceWorkerPurpose purpose); // S13nServiceWorker: - // Clones the Mojo end point to the ServiceWorker container host. This is - // used to communicate with the host from dedicated and shared workers. - CloneForWorker(ServiceWorkerContainerHost& container_host_for_worker); + // Makes a new endpoint to this ServiceWorkerContainerHost. + CloneContainerHost(ServiceWorkerContainerHost& container_host); // Does nothing but calls the callback. Useful for pumping the message pipe // for this interface and associated interfaces: when the callback is called,
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index 0dff056..3672df015 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -33,11 +33,6 @@ "AllowSignedHTTPExchangeCertsWithoutExtension", base::FEATURE_DISABLED_BY_DEFAULT}; -// Enables asm.js to WebAssembly V8 backend. -// http://asmjs.org/spec/latest/ -const base::Feature kAsmJsToWebAssembly{"AsmJsToWebAssembly", - base::FEATURE_ENABLED_BY_DEFAULT}; - // Creates audio output and input streams using the audio service. const base::Feature kAudioServiceAudioStreams{ "AudioServiceAudioStreams", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h index 00fd287..874fc98f 100644 --- a/content/public/common/content_features.h +++ b/content/public/common/content_features.h
@@ -21,7 +21,6 @@ kAllowContentInitiatedDataUrlNavigations; CONTENT_EXPORT extern const base::Feature kAllowSignedHTTPExchangeCertsWithoutExtension; -CONTENT_EXPORT extern const base::Feature kAsmJsToWebAssembly; CONTENT_EXPORT extern const base::Feature kAudioServiceAudioStreams; CONTENT_EXPORT extern const base::Feature kAudioServiceLaunchOnStartup; CONTENT_EXPORT extern const base::Feature kAudioServiceOutOfProcess;
diff --git a/content/renderer/appcache/appcache_frontend_impl.cc b/content/renderer/appcache/appcache_frontend_impl.cc index 20afc6b..75e398f8 100644 --- a/content/renderer/appcache/appcache_frontend_impl.cc +++ b/content/renderer/appcache/appcache_frontend_impl.cc
@@ -27,8 +27,7 @@ void AppCacheFrontendImpl::OnStatusChanged(const std::vector<int>& host_ids, AppCacheStatus status) { - for (std::vector<int>::const_iterator i = host_ids.begin(); - i != host_ids.end(); ++i) { + for (auto i = host_ids.begin(); i != host_ids.end(); ++i) { WebApplicationCacheHostImpl* host = GetHost(*i); if (host) host->OnStatusChanged(status); @@ -42,8 +41,7 @@ AppCacheEventID::APPCACHE_PROGRESS_EVENT); // See OnProgressEventRaised. DCHECK_NE(event_id, AppCacheEventID::APPCACHE_ERROR_EVENT); // See OnErrorEventRaised. - for (std::vector<int>::const_iterator i = host_ids.begin(); - i != host_ids.end(); ++i) { + for (auto i = host_ids.begin(); i != host_ids.end(); ++i) { WebApplicationCacheHostImpl* host = GetHost(*i); if (host) host->OnEventRaised(event_id); @@ -55,8 +53,7 @@ const GURL& url, int num_total, int num_complete) { - for (std::vector<int>::const_iterator i = host_ids.begin(); - i != host_ids.end(); ++i) { + for (auto i = host_ids.begin(); i != host_ids.end(); ++i) { WebApplicationCacheHostImpl* host = GetHost(*i); if (host) host->OnProgressEventRaised(url, num_total, num_complete); @@ -66,8 +63,7 @@ void AppCacheFrontendImpl::OnErrorEventRaised( const std::vector<int>& host_ids, const AppCacheErrorDetails& details) { - for (std::vector<int>::const_iterator i = host_ids.begin(); - i != host_ids.end(); ++i) { + for (auto i = host_ids.begin(); i != host_ids.end(); ++i) { WebApplicationCacheHostImpl* host = GetHost(*i); if (host) host->OnErrorEventRaised(details);
diff --git a/content/renderer/browser_plugin/browser_plugin.cc b/content/renderer/browser_plugin/browser_plugin.cc index 5252ab6b..9c5002e1 100644 --- a/content/renderer/browser_plugin/browser_plugin.cc +++ b/content/renderer/browser_plugin/browser_plugin.cc
@@ -78,7 +78,7 @@ return nullptr; PluginContainerMap* browser_plugins = g_plugin_container_map.Pointer(); - PluginContainerMap::iterator it = browser_plugins->find(container); + auto it = browser_plugins->find(container); return it == browser_plugins->end() ? nullptr : it->second; }
diff --git a/content/renderer/categorized_worker_pool.cc b/content/renderer/categorized_worker_pool.cc index 0235547..30a1737a 100644 --- a/content/renderer/categorized_worker_pool.cc +++ b/content/renderer/categorized_worker_pool.cc
@@ -221,7 +221,7 @@ DCHECK(completed_tasks_.empty()); CollectCompletedTasksWithLockAcquired(namespace_token_, &completed_tasks_); - cc::Task::Vector::iterator end = std::remove_if( + auto end = std::remove_if( tasks_.begin(), tasks_.end(), [this](const scoped_refptr<cc::Task>& e) { return std::find(this->completed_tasks_.begin(), this->completed_tasks_.end(),
diff --git a/content/renderer/dom_serializer_browsertest.cc b/content/renderer/dom_serializer_browsertest.cc index 50347bd..14e32bb5 100644 --- a/content/renderer/dom_serializer_browsertest.cc +++ b/content/renderer/dom_serializer_browsertest.cc
@@ -140,9 +140,9 @@ WebData data(contents.data(), contents.length()); GetMainFrame()->CommitDataNavigation( blink::WebURLRequest(base_url), data, "text/html", encoding_info, - WebURL(), false /* replace */, blink::WebFrameLoadType::kStandard, - blink::WebHistoryItem(), false /* is_client_redirect */, - nullptr /* navigation_params */, nullptr /* navigation_data */); + WebURL(), blink::WebFrameLoadType::kStandard, blink::WebHistoryItem(), + false /* is_client_redirect */, nullptr /* navigation_params */, + nullptr /* navigation_data */); } base::MessageLoopCurrent::ScopedNestableTaskAllower allow; waiter.Wait();
diff --git a/content/renderer/dom_storage/dom_storage_cached_area.cc b/content/renderer/dom_storage/dom_storage_cached_area.cc index 402c2772..a7cdf90 100644 --- a/content/renderer/dom_storage/dom_storage_cached_area.cc +++ b/content/renderer/dom_storage/dom_storage_cached_area.cc
@@ -144,8 +144,7 @@ // We have to retain local additions which happened after this // clear operation from another process. - std::map<base::string16, int>::iterator iter = - ignore_key_mutations_.begin(); + auto iter = ignore_key_mutations_.begin(); while (iter != ignore_key_mutations_.end()) { base::NullableString16 value = old->GetItem(iter->first); if (!value.is_null()) { @@ -240,8 +239,7 @@ Reset(); return; } - std::map<base::string16, int>::iterator found = - ignore_key_mutations_.find(key); + auto found = ignore_key_mutations_.find(key); DCHECK(found != ignore_key_mutations_.end()); if (--found->second == 0) ignore_key_mutations_.erase(found); @@ -252,8 +250,7 @@ blink::WebScopedVirtualTimePauser, bool success) { DCHECK(success); - std::map<base::string16, int>::iterator found = - ignore_key_mutations_.find(key); + auto found = ignore_key_mutations_.find(key); DCHECK(found != ignore_key_mutations_.end()); if (--found->second == 0) ignore_key_mutations_.erase(found);
diff --git a/content/renderer/dom_storage/dom_storage_dispatcher.cc b/content/renderer/dom_storage/dom_storage_dispatcher.cc index 0a8b4be..f7fcb66 100644 --- a/content/renderer/dom_storage/dom_storage_dispatcher.cc +++ b/content/renderer/dom_storage/dom_storage_dispatcher.cc
@@ -171,7 +171,7 @@ } CachedAreaHolder* GetAreaHolder(const std::string& key) { - CachedAreaMap::iterator found = cached_areas_.find(key); + auto found = cached_areas_.find(key); if (found == cached_areas_.end()) return nullptr; return &(found->second);
diff --git a/content/renderer/image_downloader/image_downloader_impl.cc b/content/renderer/image_downloader/image_downloader_impl.cc index f20ad65..164406a 100644 --- a/content/renderer/image_downloader/image_downloader_impl.cc +++ b/content/renderer/image_downloader/image_downloader_impl.cc
@@ -54,8 +54,7 @@ uint32_t min_image_size = std::numeric_limits<uint32_t>::max(); // Filter the images by |max_image_size|, and also identify the smallest image // in case all the images are bigger than |max_image_size|. - for (std::vector<SkBitmap>::const_iterator it = unfiltered.begin(); - it != unfiltered.end(); ++it) { + for (auto it = unfiltered.begin(); it != unfiltered.end(); ++it) { const SkBitmap& image = *it; uint32_t current_size = std::max(it->width(), it->height()); if (current_size < min_image_size) {
diff --git a/content/renderer/loader/resource_dispatcher.cc b/content/renderer/loader/resource_dispatcher.cc index f8b7704..4fc82f3 100644 --- a/content/renderer/loader/resource_dispatcher.cc +++ b/content/renderer/loader/resource_dispatcher.cc
@@ -281,7 +281,7 @@ ResourceDispatcher::PendingRequestInfo* ResourceDispatcher::GetPendingRequestInfo(int request_id) { - PendingRequestMap::iterator it = pending_requests_.find(request_id); + auto it = pending_requests_.find(request_id); if (it == pending_requests_.end()) return nullptr; return it->second.get(); @@ -548,7 +548,7 @@ bool ResourceDispatcher::RemovePendingRequest( int request_id, scoped_refptr<base::SingleThreadTaskRunner> task_runner) { - PendingRequestMap::iterator it = pending_requests_.find(request_id); + auto it = pending_requests_.find(request_id); if (it == pending_requests_.end()) return false; @@ -579,7 +579,7 @@ void ResourceDispatcher::Cancel( int request_id, scoped_refptr<base::SingleThreadTaskRunner> task_runner) { - PendingRequestMap::iterator it = pending_requests_.find(request_id); + auto it = pending_requests_.find(request_id); if (it == pending_requests_.end()) { DLOG(ERROR) << "unknown request"; return;
diff --git a/content/renderer/loader/web_url_loader_impl.cc b/content/renderer/loader/web_url_loader_impl.cc index 576cfdf4..e6e299b 100644 --- a/content/renderer/loader/web_url_loader_impl.cc +++ b/content/renderer/loader/web_url_loader_impl.cc
@@ -1250,15 +1250,14 @@ info.raw_request_response_info->response_headers_text)); const HeadersVector& request_headers = info.raw_request_response_info->request_headers; - for (HeadersVector::const_iterator it = request_headers.begin(); - it != request_headers.end(); ++it) { + for (auto it = request_headers.begin(); it != request_headers.end(); ++it) { load_info.AddRequestHeader(WebString::FromLatin1(it->first), WebString::FromLatin1(it->second)); } const HeadersVector& response_headers = info.raw_request_response_info->response_headers; - for (HeadersVector::const_iterator it = response_headers.begin(); - it != response_headers.end(); ++it) { + for (auto it = response_headers.begin(); it != response_headers.end(); + ++it) { load_info.AddResponseHeader(WebString::FromLatin1(it->first), WebString::FromLatin1(it->second)); }
diff --git a/content/renderer/loader/web_worker_fetch_context_impl.cc b/content/renderer/loader/web_worker_fetch_context_impl.cc index dd6409b..fc03ca1 100644 --- a/content/renderer/loader/web_worker_fetch_context_impl.cc +++ b/content/renderer/loader/web_worker_fetch_context_impl.cc
@@ -201,7 +201,7 @@ mojom::ServiceWorkerContainerHostPtrInfo host_ptr_info; if (blink::ServiceWorkerUtils::IsServicificationEnabled()) { - service_worker_container_host_->CloneForWorker( + service_worker_container_host_->CloneContainerHost( mojo::MakeRequest(&host_ptr_info)); } @@ -449,7 +449,7 @@ network::mojom::URLLoaderFactoryPtr service_worker_url_loader_factory; mojom::ServiceWorkerContainerHostPtrInfo host_ptr_info; - service_worker_container_host_->CloneForWorker( + service_worker_container_host_->CloneContainerHost( mojo::MakeRequest(&host_ptr_info)); // To avoid potential dead-lock while synchronous loading, create the // SubresourceLoaderFactory on a background thread.
diff --git a/content/renderer/media/audio/audio_renderer_mixer_manager.cc b/content/renderer/media/audio/audio_renderer_mixer_manager.cc index b457f7c..a3211106 100644 --- a/content/renderer/media/audio/audio_renderer_mixer_manager.cc +++ b/content/renderer/media/audio/audio_renderer_mixer_manager.cc
@@ -187,7 +187,7 @@ latency_map_.to_ulong()); } - AudioRendererMixerMap::iterator it = mixers_.find(key); + auto it = mixers_.find(key); if (it != mixers_.end()) { if (device_status) *device_status = media::OUTPUT_DEVICE_STATUS_OK; @@ -223,7 +223,7 @@ void AudioRendererMixerManager::ReturnMixer(media::AudioRendererMixer* mixer) { base::AutoLock auto_lock(mixers_lock_); - AudioRendererMixerMap::iterator it = std::find_if( + auto it = std::find_if( mixers_.begin(), mixers_.end(), [mixer](const std::pair<MixerKey, AudioRendererMixerReference>& val) { return val.second.mixer == mixer;
diff --git a/content/renderer/media/media_permission_dispatcher.cc b/content/renderer/media/media_permission_dispatcher.cc index 64203183..96f057c 100644 --- a/content/renderer/media/media_permission_dispatcher.cc +++ b/content/renderer/media/media_permission_dispatcher.cc
@@ -144,7 +144,7 @@ DVLOG(2) << __func__ << ": (" << request_id << ", " << status << ")"; DCHECK(task_runner_->RunsTasksInCurrentSequence()); - RequestMap::iterator iter = requests_.find(request_id); + auto iter = requests_.find(request_id); DCHECK(iter != requests_.end()) << "Request not found."; PermissionStatusCB permission_status_cb = iter->second;
diff --git a/content/renderer/media/midi/midi_message_filter.cc b/content/renderer/media/midi/midi_message_filter.cc index b96e36e8..bb485d6 100644 --- a/content/renderer/media/midi/midi_message_filter.cc +++ b/content/renderer/media/midi/midi_message_filter.cc
@@ -57,9 +57,8 @@ << "RemoveClient call was not ballanced with AddClient call"; DCHECK(main_task_runner_->BelongsToCurrentThread()); clients_.erase(client); - ClientsQueue::iterator it = std::find(clients_waiting_session_queue_.begin(), - clients_waiting_session_queue_.end(), - client); + auto it = std::find(clients_waiting_session_queue_.begin(), + clients_waiting_session_queue_.end(), client); if (it != clients_waiting_session_queue_.end()) clients_waiting_session_queue_.erase(it); if (clients_.empty() && clients_waiting_session_queue_.empty()) {
diff --git a/content/renderer/media/stream/aec_dump_message_filter.cc b/content/renderer/media/stream/aec_dump_message_filter.cc index 5c1312e..bb1f429 100644 --- a/content/renderer/media/stream/aec_dump_message_filter.cc +++ b/content/renderer/media/stream/aec_dump_message_filter.cc
@@ -148,7 +148,7 @@ int id, IPC::PlatformFileForTransit file_handle) { DCHECK(main_task_runner_->BelongsToCurrentThread()); - DelegateMap::iterator it = delegates_.find(id); + auto it = delegates_.find(id); if (it != delegates_.end()) { it->second->OnAecDumpFile(file_handle); } else { @@ -161,16 +161,14 @@ void AecDumpMessageFilter::DoDisableAecDump() { DCHECK(main_task_runner_->BelongsToCurrentThread()); - for (DelegateMap::iterator it = delegates_.begin(); - it != delegates_.end(); ++it) { + for (auto it = delegates_.begin(); it != delegates_.end(); ++it) { it->second->OnDisableAecDump(); } } void AecDumpMessageFilter::DoChannelClosingOnDelegates() { DCHECK(main_task_runner_->BelongsToCurrentThread()); - for (DelegateMap::iterator it = delegates_.begin(); - it != delegates_.end(); ++it) { + for (auto it = delegates_.begin(); it != delegates_.end(); ++it) { it->second->OnIpcClosing(); } delegates_.clear(); @@ -179,8 +177,7 @@ int AecDumpMessageFilter::GetIdForDelegate( AecDumpMessageFilter::AecDumpDelegate* delegate) { DCHECK(main_task_runner_->BelongsToCurrentThread()); - for (DelegateMap::iterator it = delegates_.begin(); - it != delegates_.end(); ++it) { + for (auto it = delegates_.begin(); it != delegates_.end(); ++it) { if (it->second == delegate) return it->first; }
diff --git a/content/renderer/media/stream/media_stream_device_observer.cc b/content/renderer/media/stream/media_stream_device_observer.cc index 80a3e5df96..df23fbe6 100644 --- a/content/renderer/media/stream/media_stream_device_observer.cc +++ b/content/renderer/media/stream/media_stream_device_observer.cc
@@ -22,8 +22,8 @@ bool RemoveStreamDeviceFromArray(const MediaStreamDevice& device, MediaStreamDevices* devices) { - for (MediaStreamDevices::iterator device_it = devices->begin(); - device_it != devices->end(); ++device_it) { + for (auto device_it = devices->begin(); device_it != devices->end(); + ++device_it) { if (device_it->IsSameDevice(device)) { devices->erase(device_it); return true;
diff --git a/content/renderer/media/stream/media_stream_video_source.cc b/content/renderer/media/stream/media_stream_video_source.cc index 74ba3b0..b3a4ddf7 100644 --- a/content/renderer/media/stream/media_stream_video_source.cc +++ b/content/renderer/media/stream/media_stream_video_source.cc
@@ -85,8 +85,7 @@ base::OnceClosure callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); { - std::vector<MediaStreamVideoTrack*>::iterator it = - std::find(tracks_.begin(), tracks_.end(), video_track); + auto it = std::find(tracks_.begin(), tracks_.end(), video_track); DCHECK(it != tracks_.end()); tracks_.erase(it); }
diff --git a/content/renderer/media/stream/media_stream_video_track.cc b/content/renderer/media/stream/media_stream_video_track.cc index 38a3319..fcfd43bd 100644 --- a/content/renderer/media/stream/media_stream_video_track.cc +++ b/content/renderer/media/stream/media_stream_video_track.cc
@@ -128,7 +128,7 @@ VideoSinkId id, const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) { DCHECK(io_task_runner_->BelongsToCurrentThread()); - std::vector<VideoIdCallbackPair>::iterator it = callbacks_.begin(); + auto it = callbacks_.begin(); for (; it != callbacks_.end(); ++it) { if (it->first == id) { // Callback is copied to heap and then deleted on the target thread. @@ -318,8 +318,7 @@ void MediaStreamVideoTrack::RemoveSink(MediaStreamVideoSink* sink) { DCHECK(main_render_thread_checker_.CalledOnValidThread()); - std::vector<MediaStreamVideoSink*>::iterator it = - std::find(sinks_.begin(), sinks_.end(), sink); + auto it = std::find(sinks_.begin(), sinks_.end(), sink); DCHECK(it != sinks_.end()); sinks_.erase(it); frame_deliverer_->RemoveCallback(sink);
diff --git a/content/renderer/media/stream/user_media_processor.cc b/content/renderer/media/stream/user_media_processor.cc index 36d2961a..86c723b0 100644 --- a/content/renderer/media/stream/user_media_processor.cc +++ b/content/renderer/media/stream/user_media_processor.cc
@@ -1252,7 +1252,7 @@ const blink::WebMediaStreamSource& source) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - for (LocalStreamSources::iterator device_it = local_sources_.begin(); + for (auto device_it = local_sources_.begin(); device_it != local_sources_.end(); ++device_it) { if (IsSameSource(*device_it, source)) { local_sources_.erase(device_it); @@ -1261,7 +1261,7 @@ } // Check if the source was pending. - for (LocalStreamSources::iterator device_it = pending_local_sources_.begin(); + for (auto device_it = pending_local_sources_.begin(); device_it != pending_local_sources_.end(); ++device_it) { if (IsSameSource(*device_it, source)) { MediaStreamSource* const source_extra_data =
diff --git a/content/renderer/media/stream/video_track_adapter.cc b/content/renderer/media/stream/video_track_adapter.cc index 28727ef..cbe15d6 100644 --- a/content/renderer/media/stream/video_track_adapter.cc +++ b/content/renderer/media/stream/video_track_adapter.cc
@@ -179,7 +179,7 @@ void VideoTrackAdapter::VideoFrameResolutionAdapter::RemoveAndReleaseCallback( const MediaStreamVideoTrack* track) { DCHECK(io_thread_checker_.CalledOnValidThread()); - std::vector<VideoIdCallbackPair>::iterator it = callbacks_.begin(); + auto it = callbacks_.begin(); for (; it != callbacks_.end(); ++it) { if (it->first == track) { // Make sure the VideoCaptureDeliverFrameCB is released on the main
diff --git a/content/renderer/media/stream/webmediaplayer_ms.cc b/content/renderer/media/stream/webmediaplayer_ms.cc index d2b6ef2..8d5a6ab 100644 --- a/content/renderer/media/stream/webmediaplayer_ms.cc +++ b/content/renderer/media/stream/webmediaplayer_ms.cc
@@ -829,6 +829,7 @@ compositor_->GetCurrentFrameWithoutUpdatingStatistics(); media::Context3D context_3d; + gpu::ContextSupport* context_support = nullptr; if (frame && frame->HasTextures()) { auto* provider = RenderThreadImpl::current()->SharedMainThreadContextProvider().get(); @@ -836,11 +837,11 @@ if (!provider) return; context_3d = media::Context3D(provider->ContextGL(), provider->GrContext()); - DCHECK(context_3d.gl); + context_support = provider->ContextSupport(); } const gfx::RectF dest_rect(rect.x, rect.y, rect.width, rect.height); video_renderer_.Paint(frame, canvas, dest_rect, flags, video_rotation_, - context_3d); + context_3d, context_support); } bool WebMediaPlayerMS::DidGetOpaqueResponseFromServiceWorker() const { @@ -1016,8 +1017,8 @@ DCHECK(context_3d.gl); return video_renderer_.CopyVideoFrameTexturesToGLTexture( - context_3d, gl, video_frame.get(), target, texture, internal_format, - format, type, level, premultiply_alpha, flip_y); + context_3d, provider->ContextSupport(), gl, video_frame.get(), target, + texture, internal_format, format, type, level, premultiply_alpha, flip_y); } bool WebMediaPlayerMS::CopyVideoYUVDataToPlatformTexture(
diff --git a/content/renderer/media/stream/webmediaplayer_ms_compositor.cc b/content/renderer/media/stream/webmediaplayer_ms_compositor.cc index c53c0be2..92b6b60 100644 --- a/content/renderer/media/stream/webmediaplayer_ms_compositor.cc +++ b/content/renderer/media/stream/webmediaplayer_ms_compositor.cc
@@ -68,7 +68,8 @@ DCHECK(provider->ContextGL()); video_renderer->Copy( frame.get(), &paint_canvas, - media::Context3D(provider->ContextGL(), provider->GrContext())); + media::Context3D(provider->ContextGL(), provider->GrContext()), + provider->ContextSupport()); SkPixmap pixmap; const bool result = bitmap.peekPixels(&pixmap);
diff --git a/content/renderer/media/webrtc/mock_peer_connection_dependency_factory.cc b/content/renderer/media/webrtc/mock_peer_connection_dependency_factory.cc index 8a895d2c..2a48dee4 100644 --- a/content/renderer/media/webrtc/mock_peer_connection_dependency_factory.cc +++ b/content/renderer/media/webrtc/mock_peer_connection_dependency_factory.cc
@@ -31,7 +31,7 @@ template <class V> static typename V::iterator FindTrack(V* vector, const std::string& track_id) { - typename V::iterator it = vector->begin(); + auto it = vector->begin(); for (; it != vector->end(); ++it) { if ((*it)->id() == track_id) { break; @@ -68,8 +68,7 @@ } bool MockMediaStream::RemoveTrack(AudioTrackInterface* track) { - AudioTrackVector::iterator it = FindTrack(&audio_track_vector_, - track->id()); + auto it = FindTrack(&audio_track_vector_, track->id()); if (it == audio_track_vector_.end()) return false; audio_track_vector_.erase(it); @@ -78,8 +77,7 @@ } bool MockMediaStream::RemoveTrack(VideoTrackInterface* track) { - VideoTrackVector::iterator it = FindTrack(&video_track_vector_, - track->id()); + auto it = FindTrack(&video_track_vector_, track->id()); if (it == video_track_vector_.end()) return false; video_track_vector_.erase(it); @@ -101,13 +99,13 @@ rtc::scoped_refptr<AudioTrackInterface> MockMediaStream::FindAudioTrack( const std::string& track_id) { - AudioTrackVector::iterator it = FindTrack(&audio_track_vector_, track_id); + auto it = FindTrack(&audio_track_vector_, track_id); return it == audio_track_vector_.end() ? nullptr : *it; } rtc::scoped_refptr<VideoTrackInterface> MockMediaStream::FindVideoTrack( const std::string& track_id) { - VideoTrackVector::iterator it = FindTrack(&video_track_vector_, track_id); + auto it = FindTrack(&video_track_vector_, track_id); return it == video_track_vector_.end() ? nullptr : *it; } @@ -117,14 +115,13 @@ } void MockMediaStream::UnregisterObserver(ObserverInterface* observer) { - ObserverSet::iterator it = observers_.find(observer); + auto it = observers_.find(observer); DCHECK(it != observers_.end()); observers_.erase(it); } void MockMediaStream::NotifyObservers() { - for (ObserverSet::iterator it = observers_.begin(); it != observers_.end(); - ++it) { + for (auto it = observers_.begin(); it != observers_.end(); ++it) { (*it)->OnChanged(); } }
diff --git a/content/renderer/media/webrtc/mock_peer_connection_impl.cc b/content/renderer/media/webrtc/mock_peer_connection_impl.cc index efed2e4..e27341c 100644 --- a/content/renderer/media/webrtc/mock_peer_connection_impl.cc +++ b/content/renderer/media/webrtc/mock_peer_connection_impl.cc
@@ -64,7 +64,7 @@ streams_.push_back(stream); } void RemoveStream(MediaStreamInterface* stream) { - StreamVector::iterator it = streams_.begin(); + auto it = streams_.begin(); for (; it != streams_.end(); ++it) { if (it->get() == stream) { streams_.erase(it);
diff --git a/content/renderer/media/webrtc/peer_connection_tracker.cc b/content/renderer/media/webrtc/peer_connection_tracker.cc index 76bffec..4af9ed3 100644 --- a/content/renderer/media/webrtc/peer_connection_tracker.cc +++ b/content/renderer/media/webrtc/peer_connection_tracker.cc
@@ -511,7 +511,7 @@ DCHECK(main_thread_.CalledOnValidThread()); const std::string empty_track_id; - for (PeerConnectionIdMap::iterator it = peer_connection_id_map_.begin(); + for (auto it = peer_connection_id_map_.begin(); it != peer_connection_id_map_.end(); ++it) { rtc::scoped_refptr<InternalStatsObserver> observer( new rtc::RefCountedObject<InternalStatsObserver>( @@ -532,7 +532,7 @@ void PeerConnectionTracker::OnSuspend() { DCHECK(main_thread_.CalledOnValidThread()); - for (PeerConnectionIdMap::iterator it = peer_connection_id_map_.begin(); + for (auto it = peer_connection_id_map_.begin(); it != peer_connection_id_map_.end(); ++it) { it->first->CloseClientPeerConnection(); } @@ -611,8 +611,7 @@ DCHECK(main_thread_.CalledOnValidThread()); DVLOG(1) << "PeerConnectionTracker::UnregisterPeerConnection()"; - std::map<RTCPeerConnectionHandler*, int>::iterator it = - peer_connection_id_map_.find(pc_handler); + auto it = peer_connection_id_map_.find(pc_handler); if (it == peer_connection_id_map_.end()) { // The PeerConnection might not have been registered if its initilization
diff --git a/content/renderer/media/webrtc/rtc_video_decoder.cc b/content/renderer/media/webrtc/rtc_video_decoder.cc index c42e15b2..cc7016e 100644 --- a/content/renderer/media/webrtc/rtc_video_decoder.cc +++ b/content/renderer/media/webrtc/rtc_video_decoder.cc
@@ -361,8 +361,7 @@ DVLOG(3) << "DismissPictureBuffer. id=" << id; DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); - std::map<int32_t, media::PictureBuffer>::iterator it = - assigned_picture_buffers_.find(id); + auto it = assigned_picture_buffers_.find(id); if (it == assigned_picture_buffers_.end()) { NOTREACHED() << "Missing picture buffer: " << id; return; @@ -385,8 +384,7 @@ DVLOG(3) << "PictureReady"; DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); - std::map<int32_t, media::PictureBuffer>::iterator it = - assigned_picture_buffers_.find(picture.picture_buffer_id()); + auto it = assigned_picture_buffers_.find(picture.picture_buffer_id()); if (it == assigned_picture_buffers_.end()) { NOTREACHED() << "Missing picture buffer: " << picture.picture_buffer_id(); NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE);
diff --git a/content/renderer/media/webrtc/webrtc_audio_renderer.cc b/content/renderer/media/webrtc/webrtc_audio_renderer.cc index ef2de1d..c50c9ad6 100644 --- a/content/renderer/media/webrtc/webrtc_audio_renderer.cc +++ b/content/renderer/media/webrtc/webrtc_audio_renderer.cc
@@ -515,7 +515,7 @@ // set to 0.0. float volume = 0.0f; - SourcePlayingStates::iterator entry = source_playing_states_.find(source); + auto entry = source_playing_states_.find(source); if (entry != source_playing_states_.end()) { PlayingStates& states = entry->second; for (PlayingStates::const_iterator it = states.begin(); @@ -566,13 +566,12 @@ PlayingState* state) { DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(!state->playing()); - SourcePlayingStates::iterator found = source_playing_states_.find(source); + auto found = source_playing_states_.find(source); if (found == source_playing_states_.end()) return false; PlayingStates& array = found->second; - PlayingStates::iterator state_it = - std::find(array.begin(), array.end(), state); + auto state_it = std::find(array.begin(), array.end(), state); if (state_it == array.end()) return false;
diff --git a/content/renderer/media_recorder/video_track_recorder.cc b/content/renderer/media_recorder/video_track_recorder.cc index c7fb3465..ef28d3170 100644 --- a/content/renderer/media_recorder/video_track_recorder.cc +++ b/content/renderer/media_recorder/video_track_recorder.cc
@@ -313,7 +313,8 @@ DCHECK(context_provider->ContextGL()); video_renderer_->Copy(video_frame.get(), canvas_.get(), media::Context3D(context_provider->ContextGL(), - context_provider->GrContext())); + context_provider->GrContext()), + context_provider->ContextSupport()); SkPixmap pixmap; if (!bitmap_.peekPixels(&pixmap)) {
diff --git a/content/renderer/p2p/ipc_network_manager.cc b/content/renderer/p2p/ipc_network_manager.cc index 430f61d..169c27a0 100644 --- a/content/renderer/p2p/ipc_network_manager.cc +++ b/content/renderer/p2p/ipc_network_manager.cc
@@ -93,8 +93,7 @@ // rtc::Network uses these prefix_length to compare network // interfaces discovered. std::vector<rtc::Network*> networks; - for (net::NetworkInterfaceList::const_iterator it = list.begin(); - it != list.end(); it++) { + for (auto it = list.begin(); it != list.end(); it++) { rtc::IPAddress ip_address = jingle_glue::NetIPAddressToRtcIPAddress(it->address); DCHECK(!ip_address.IsNil());
diff --git a/content/renderer/pepper/host_globals.cc b/content/renderer/pepper/host_globals.cc index 5ef70b5..4a43be09f 100644 --- a/content/renderer/pepper/host_globals.cc +++ b/content/renderer/pepper/host_globals.cc
@@ -43,9 +43,7 @@ // Adds all WebPluginContainers associated with the given module to the set. void GetAllContainersForModule(PluginModule* module, ContainerSet* containers) { const PluginModule::PluginInstanceSet& instances = module->GetAllInstances(); - for (PluginModule::PluginInstanceSet::const_iterator i = instances.begin(); - i != instances.end(); - ++i) { + for (auto i = instances.begin(); i != instances.end(); ++i) { WebPluginContainer* container = (*i)->container(); // If "Delete" is called on an instance, the instance sets its container to // NULL, but the instance may actually outlive its container. Callers of @@ -107,7 +105,7 @@ ppapi::CallbackTracker* HostGlobals::GetCallbackTrackerForInstance( PP_Instance instance) { - InstanceMap::iterator found = instance_map_.find(instance); + auto found = instance_map_.find(instance); if (found == instance_map_.end()) return nullptr; return found->second->module()->GetCallbackTracker().get(); @@ -182,8 +180,7 @@ } WebConsoleMessage message = MakeLogMessage(level, source, value); - for (ContainerSet::iterator i = containers.begin(); i != containers.end(); - ++i) { + for (auto i = containers.begin(); i != containers.end(); ++i) { WebLocalFrame* frame = (*i)->GetDocument().GetFrame(); if (frame) frame->AddMessageToConsole(message); @@ -222,7 +219,7 @@ void HostGlobals::ModuleDeleted(PP_Module module) { DLOG_IF(ERROR, !CheckIdType(module, ppapi::PP_ID_TYPE_MODULE)) << module << " is not a PP_Module."; - ModuleMap::iterator found = module_map_.find(module); + auto found = module_map_.find(module); if (found == module_map_.end()) { NOTREACHED(); return; @@ -233,7 +230,7 @@ PluginModule* HostGlobals::GetModule(PP_Module module) { DLOG_IF(ERROR, !CheckIdType(module, ppapi::PP_ID_TYPE_MODULE)) << module << " is not a PP_Module."; - ModuleMap::iterator found = module_map_.find(module); + auto found = module_map_.find(module); if (found == module_map_.end()) return nullptr; return found->second; @@ -274,7 +271,7 @@ PepperPluginInstanceImpl* HostGlobals::GetInstance(PP_Instance instance) { DLOG_IF(ERROR, !CheckIdType(instance, ppapi::PP_ID_TYPE_INSTANCE)) << instance << " is not a PP_Instance."; - InstanceMap::iterator found = instance_map_.find(instance); + auto found = instance_map_.find(instance); if (found == instance_map_.end()) return nullptr; return found->second;
diff --git a/content/renderer/pepper/host_var_tracker.cc b/content/renderer/pepper/host_var_tracker.cc index b058576d..0424b3d 100644 --- a/content/renderer/pepper/host_var_tracker.cc +++ b/content/renderer/pepper/host_var_tracker.cc
@@ -63,8 +63,8 @@ void HostVarTracker::RemoveV8ObjectVar(V8ObjectVar* object_var) { CheckThreadingPreconditions(); v8::HandleScope handle_scope(object_var->instance()->GetIsolate()); - ObjectMap::iterator it = GetForV8Object( - object_var->instance()->pp_instance(), object_var->GetHandle()); + auto it = GetForV8Object(object_var->instance()->pp_instance(), + object_var->GetHandle()); DCHECK(it != object_map_.end()); object_map_.erase(it); } @@ -120,7 +120,7 @@ // Use a key with an empty handle to find the v8 object var in the map with // the given instance and the lowest hash. V8ObjectVarKey key(pp_instance, v8::Local<v8::Object>()); - ObjectMap::iterator it = object_map_.lower_bound(key); + auto it = object_map_.lower_bound(key); while (it != object_map_.end() && it->first.instance == pp_instance) { ForceReleaseV8Object(it->second); object_map_.erase(it++); @@ -129,7 +129,7 @@ void HostVarTracker::ForceReleaseV8Object(ppapi::V8ObjectVar* object_var) { object_var->InstanceDeleted(); - VarMap::iterator iter = live_vars_.find(object_var->GetExistingVarID()); + auto iter = live_vars_.find(object_var->GetExistingVarID()); if (iter == live_vars_.end()) { NOTREACHED(); return; @@ -145,7 +145,7 @@ std::pair<ObjectMap::iterator, ObjectMap::iterator> range = object_map_.equal_range(V8ObjectVarKey(instance, object)); - for (ObjectMap::iterator it = range.first; it != range.second; ++it) { + for (auto it = range.first; it != range.second; ++it) { if (object == it->second->GetHandle()) return it; } @@ -174,7 +174,7 @@ PP_Instance instance, base::SharedMemoryHandle* handle, uint32_t* size_in_bytes) { - SharedMemoryMap::iterator it = shared_memory_map_.find(id); + auto it = shared_memory_map_.find(id); if (it == shared_memory_map_.end()) return false; if (it->second.instance != instance)
diff --git a/content/renderer/pepper/pepper_broker.cc b/content/renderer/pepper/pepper_broker.cc index 1f5cd9f..4d75b47 100644 --- a/content/renderer/pepper/pepper_broker.cc +++ b/content/renderer/pepper/pepper_broker.cc
@@ -156,8 +156,7 @@ dispatcher_.reset(dispatcher.release()); // Process all pending channel requests from the plugins. - for (ClientMap::iterator i = pending_connects_.begin(); - i != pending_connects_.end();) { + for (auto i = pending_connects_.begin(); i != pending_connects_.end();) { base::WeakPtr<PPB_Broker_Impl>& weak_ptr = i->second.client; if (!i->second.is_authorized) { ++i; @@ -173,7 +172,7 @@ void PepperBroker::OnBrokerPermissionResult(PPB_Broker_Impl* client, bool result) { - ClientMap::iterator entry = pending_connects_.find(client); + auto entry = pending_connects_.find(client); if (entry == pending_connects_.end()) return; @@ -213,9 +212,7 @@ void PepperBroker::ReportFailureToClients(int error_code) { DCHECK_NE(PP_OK, error_code); - for (ClientMap::iterator i = pending_connects_.begin(); - i != pending_connects_.end(); - ++i) { + for (auto i = pending_connects_.begin(); i != pending_connects_.end(); ++i) { base::WeakPtr<PPB_Broker_Impl>& weak_ptr = i->second.client; if (weak_ptr.get()) { weak_ptr->BrokerConnected(
diff --git a/content/renderer/pepper/pepper_browser_connection.cc b/content/renderer/pepper/pepper_browser_connection.cc index 19ba1cc..71b3e6c 100644 --- a/content/renderer/pepper/pepper_browser_connection.cc +++ b/content/renderer/pepper/pepper_browser_connection.cc
@@ -74,8 +74,7 @@ const std::vector<int>& pending_resource_host_ids) { // Check that the message is destined for the plugin this object is associated // with. - std::map<int32_t, PendingResourceIDCallback>::iterator it = - pending_create_map_.find(sequence_number); + auto it = pending_create_map_.find(sequence_number); if (it != pending_create_map_.end()) { it->second.Run(pending_resource_host_ids); pending_create_map_.erase(it);
diff --git a/content/renderer/pepper/pepper_media_device_manager.cc b/content/renderer/pepper/pepper_media_device_manager.cc index 606cec3..7e09fcc 100644 --- a/content/renderer/pepper/pepper_media_device_manager.cc +++ b/content/renderer/pepper/pepper_media_device_manager.cc
@@ -232,7 +232,7 @@ bool success, const std::string& label, const MediaStreamDevice& device) { - OpenCallbackMap::iterator iter = open_callbacks_.find(request_id); + auto iter = open_callbacks_.find(request_id); if (iter == open_callbacks_.end()) { // The callback may have been unregistered. return;
diff --git a/content/renderer/pepper/pepper_plugin_instance_impl.cc b/content/renderer/pepper/pepper_plugin_instance_impl.cc index 5babe8a6..1ed2844 100644 --- a/content/renderer/pepper/pepper_plugin_instance_impl.cc +++ b/content/renderer/pepper/pepper_plugin_instance_impl.cc
@@ -438,8 +438,7 @@ void PepperPluginInstanceImpl::ExternalDocumentLoader::ReplayReceivedData( WebAssociatedURLLoaderClient* document_loader) { - for (std::list<std::string>::iterator it = data_.begin(); it != data_.end(); - ++it) { + for (auto it = data_.begin(); it != data_.end(); ++it) { document_loader->DidReceiveData(it->c_str(), it->length()); } if (finished_loading_) { @@ -591,8 +590,7 @@ // unregister themselves inside the delete call). PluginObjectSet plugin_object_copy; live_plugin_objects_.swap(plugin_object_copy); - for (PluginObjectSet::iterator i = plugin_object_copy.begin(); - i != plugin_object_copy.end(); + for (auto i = plugin_object_copy.begin(); i != plugin_object_copy.end(); ++i) { (*i)->InstanceDeleted(); } @@ -1020,10 +1018,9 @@ for (size_t i = 0; i < ime_text_spans.size(); ++i) { if (ime_text_spans[i].thickness == ws::mojom::ImeTextSpanThickness::kThick) { - std::vector<uint32_t>::iterator it = - std::find(event.composition_segment_offsets.begin(), - event.composition_segment_offsets.end(), - utf8_offsets[2 * i + 2]); + auto it = std::find(event.composition_segment_offsets.begin(), + event.composition_segment_offsets.end(), + utf8_offsets[2 * i + 2]); if (it != event.composition_segment_offsets.end()) { event.composition_target_segment = it - event.composition_segment_offsets.begin(); @@ -2370,9 +2367,7 @@ CreateSimulatedWebInputEvents( input_event, view_data_.rect.point.x + view_data_.rect.size.width / 2, view_data_.rect.point.y + view_data_.rect.size.height / 2); - for (std::vector<std::unique_ptr<WebInputEvent>>::iterator it = - events.begin(); - it != events.end(); ++it) { + for (auto it = events.begin(); it != events.end(); ++it) { widget->HandleInputEvent(blink::WebCoalescedInputEvent(*it->get())); } if (input_event.event_type == PP_INPUTEVENT_TYPE_TOUCHSTART ||
diff --git a/content/renderer/pepper/pepper_plugin_registry.cc b/content/renderer/pepper/pepper_plugin_registry.cc index 73ddbac..0f87597 100644 --- a/content/renderer/pepper/pepper_plugin_registry.cc +++ b/content/renderer/pepper/pepper_plugin_registry.cc
@@ -48,8 +48,7 @@ PluginModule* PepperPluginRegistry::GetLiveModule( const base::FilePath& path, const base::Optional<url::Origin>& origin_lock) { - NonOwningModuleMap::iterator module_iter = - live_modules_.find({path, origin_lock}); + auto module_iter = live_modules_.find({path, origin_lock}); if (module_iter == live_modules_.end()) return nullptr; @@ -64,8 +63,7 @@ if (instance_set.empty()) return module_iter->second; - PluginModule::PluginInstanceSet::const_iterator instance_iter = - instance_set.begin(); + auto instance_iter = instance_set.begin(); while (instance_iter != instance_set.end()) { if (!(*instance_iter)->is_deleted()) return module_iter->second; @@ -88,9 +86,7 @@ // Modules aren't destroyed very often and there are normally at most a // couple of them. So for now we just do a brute-force search. - for (NonOwningModuleMap::iterator i = live_modules_.begin(); - i != live_modules_.end(); - ++i) { + for (auto i = live_modules_.begin(); i != live_modules_.end(); ++i) { if (i->second == dead_module) { live_modules_.erase(i); return;
diff --git a/content/renderer/pepper/pepper_video_decoder_host.cc b/content/renderer/pepper/pepper_video_decoder_host.cc index 5201b8d..ae99e928 100644 --- a/content/renderer/pepper/pepper_video_decoder_host.cc +++ b/content/renderer/pepper/pepper_video_decoder_host.cc
@@ -319,7 +319,7 @@ return PP_ERROR_FAILED; DCHECK(decoder_); - PictureBufferMap::iterator it = picture_buffer_map_.find(texture_id); + auto it = picture_buffer_map_.find(texture_id); if (it == picture_buffer_map_.end()) return PP_ERROR_BADARGUMENT; @@ -388,8 +388,7 @@ } void PepperVideoDecoderHost::PictureReady(const media::Picture& picture) { - PictureBufferMap::iterator it = - picture_buffer_map_.find(picture.picture_buffer_id()); + auto it = picture_buffer_map_.find(picture.picture_buffer_id()); DCHECK(it != picture_buffer_map_.end()); DCHECK(it->second == PictureBufferState::ASSIGNED); it->second = PictureBufferState::IN_USE; @@ -404,7 +403,7 @@ } void PepperVideoDecoderHost::DismissPictureBuffer(int32_t picture_buffer_id) { - PictureBufferMap::iterator it = picture_buffer_map_.find(picture_buffer_id); + auto it = picture_buffer_map_.find(picture_buffer_id); DCHECK(it != picture_buffer_map_.end()); // If the texture is still used by the plugin keep it until the plugin @@ -423,7 +422,7 @@ void PepperVideoDecoderHost::NotifyEndOfBitstreamBuffer( int32_t bitstream_buffer_id) { - PendingDecodeList::iterator it = GetPendingDecodeById(bitstream_buffer_id); + auto it = GetPendingDecodeById(bitstream_buffer_id); if (it == pending_decodes_.end()) { NOTREACHED(); return;
diff --git a/content/renderer/pepper/pepper_websocket_host.cc b/content/renderer/pepper/pepper_websocket_host.cc index 0a8e50a..0a6e752 100644 --- a/content/renderer/pepper/pepper_websocket_host.cc +++ b/content/renderer/pepper/pepper_websocket_host.cc
@@ -216,10 +216,8 @@ // Validate protocols. std::string protocol_string; - for (std::vector<std::string>::const_iterator vector_it = protocols.begin(); - vector_it != protocols.end(); + for (auto vector_it = protocols.begin(); vector_it != protocols.end(); ++vector_it) { - // Check containing characters. for (std::string::const_iterator string_it = vector_it->begin(); string_it != vector_it->end();
diff --git a/content/renderer/pepper/plugin_module.cc b/content/renderer/pepper/plugin_module.cc index c0e6fb2..cf6e7d16 100644 --- a/content/renderer/pepper/plugin_module.cc +++ b/content/renderer/pepper/plugin_module.cc
@@ -679,9 +679,7 @@ is_crashed_ = true; // Notify all instances that they crashed. - for (PluginInstanceSet::iterator i = instances_.begin(); - i != instances_.end(); - ++i) + for (auto i = instances_.begin(); i != instances_.end(); ++i) (*i)->InstanceCrashed(); PepperPluginRegistry::GetInstance()->PluginModuleDead(this);
diff --git a/content/renderer/pepper/v8_var_converter.cc b/content/renderer/pepper/v8_var_converter.cc index 93cdbdc..ca81eb01 100644 --- a/content/renderer/pepper/v8_var_converter.cc +++ b/content/renderer/pepper/v8_var_converter.cc
@@ -94,7 +94,7 @@ if (ppapi::VarTracker::IsVarTypeRefcounted(var.type)) { if (parent_ids->count(var.value.as_id) != 0) return false; - VarHandleMap::iterator it = visited_ids->find(var.value.as_id); + auto it = visited_ids->find(var.value.as_id); if (it != visited_ids->end()) { *result = it->second; return true; @@ -401,10 +401,8 @@ DCHECK(current_v8->IsObject()); v8::Local<v8::Object> v8_object = current_v8.As<v8::Object>(); - for (DictionaryVar::KeyValueMap::const_iterator iter = - dict_var->key_value_map().begin(); - iter != dict_var->key_value_map().end(); - ++iter) { + for (auto iter = dict_var->key_value_map().begin(); + iter != dict_var->key_value_map().end(); ++iter) { const std::string& key = iter->first; const PP_Var& child_var = iter->second.get(); v8::Local<v8::Value> child_v8;
diff --git a/content/renderer/pepper/v8_var_converter_unittest.cc b/content/renderer/pepper/v8_var_converter_unittest.cc index 6c4bfd95..3de4b45 100644 --- a/content/renderer/pepper/v8_var_converter_unittest.cc +++ b/content/renderer/pepper/v8_var_converter_unittest.cc
@@ -80,7 +80,7 @@ v8::Local<v8::Value> val, VarHandleMap* visited_ids) { if (ppapi::VarTracker::IsVarTypeRefcounted(var.type)) { - VarHandleMap::iterator it = visited_ids->find(var.value.as_id); + auto it = visited_ids->find(var.value.as_id); if (it != visited_ids->end()) return it->second == val; (*visited_ids)[var.value.as_id] = val;
diff --git a/content/renderer/pepper/video_decoder_shim.cc b/content/renderer/pepper/video_decoder_shim.cc index ac45730..b7ea303d 100644 --- a/content/renderer/pepper/video_decoder_shim.cc +++ b/content/renderer/pepper/video_decoder_shim.cc
@@ -848,7 +848,7 @@ VideoDecoderShim::~VideoDecoderShim() { DCHECK(RenderThreadImpl::current()); // Delete any remaining textures. - TextureIdMap::iterator it = texture_id_map_.begin(); + auto it = texture_id_map_.begin(); for (; it != texture_id_map_.end(); ++it) DeleteTexture(it->second); texture_id_map_.clear(); @@ -1024,9 +1024,8 @@ ++it) { textures_to_dismiss_.insert(it->first); } - for (TextureIdSet::const_iterator it = available_textures_.begin(); - it != available_textures_.end(); - ++it) { + for (auto it = available_textures_.begin(); + it != available_textures_.end(); ++it) { DismissTexture(*it); } available_textures_.clear(); @@ -1049,7 +1048,7 @@ while (!pending_frames_.empty() && !available_textures_.empty()) { const std::unique_ptr<PendingFrame>& frame = pending_frames_.front(); - TextureIdSet::iterator it = available_textures_.begin(); + auto it = available_textures_.begin(); uint32_t texture_id = *it; available_textures_.erase(it);
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index 9619fcf..0549df6b 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -1250,8 +1250,7 @@ // static RenderFrameImpl* RenderFrameImpl::FromRoutingID(int routing_id) { - RoutingIDFrameMap::iterator iter = - g_routing_id_frame_map.Get().find(routing_id); + auto iter = g_routing_id_frame_map.Get().find(routing_id); if (iter != g_routing_id_frame_map.Get().end()) return iter->second; return nullptr; @@ -1528,7 +1527,7 @@ // static void RenderFrame::ForEach(RenderFrameVisitor* visitor) { FrameMap* frames = g_frame_map.Pointer(); - for (FrameMap::iterator it = frames->begin(); it != frames->end(); ++it) { + for (auto it = frames->begin(); it != frames->end(); ++it) { if (!visitor->Visit(it->second)) return; } @@ -1547,7 +1546,7 @@ // static RenderFrameImpl* RenderFrameImpl::FromWebFrame(blink::WebFrame* web_frame) { - FrameMap::iterator iter = g_frame_map.Get().find(web_frame); + auto iter = g_frame_map.Get().find(web_frame); if (iter != g_frame_map.Get().end()) return iter->second; return nullptr; @@ -2848,6 +2847,8 @@ : blink::WebFrameLoadType::kStandard; const blink::WebHistoryItem& history_item = history_entry ? history_entry->root() : blink::WebHistoryItem(); + if (replace && frame_load_type == WebFrameLoadType::kStandard) + frame_load_type = WebFrameLoadType::kReplaceCurrentItem; // Failed navigations will always provide a |failed_request|. Error induced // by the client/renderer side after a commit won't have a |failed_request|. @@ -2862,10 +2863,10 @@ // should not inherit the cache mode from |failed_request|). new_request.SetCacheMode(blink::mojom::FetchCacheMode::kNoStore); - frame_->CommitDataNavigation( - new_request, error_html, "text/html", "UTF-8", error_url, replace, - frame_load_type, history_item, is_client_redirect, - std::move(navigation_params), std::move(navigation_data)); + frame_->CommitDataNavigation(new_request, error_html, "text/html", "UTF-8", + error_url, frame_load_type, history_item, + is_client_redirect, std::move(navigation_params), + std::move(navigation_data)); } void RenderFrameImpl::DidMeaningfulLayout( @@ -3743,11 +3744,6 @@ service_worker_client_request = mojo::MakeRequest(&worker_client_ptr); provider_context->RegisterWorkerClient(std::move(worker_client_ptr)); - // TODO(horo): Use this host pointer also when S13nServiceWorker is not - // enabled once we support navigator.serviceWorker on dedicated workers: - // crbug.com/371690. Currently we use this only to call - // GetControllerServiceWorker() from the worker thread if S13nServiceWorker - // is enabled. if (blink::ServiceWorkerUtils::IsServicificationEnabled()) container_host_ptr_info = provider_context->CloneContainerHostPtrInfo(); } @@ -4009,7 +4005,7 @@ // the RenderFrameImpl. In contrast, the main frame is owned by its // containing RenderViewHost (so that they have the same lifetime), so only // removal from the map is needed and no deletion. - FrameMap::iterator it = g_frame_map.Get().find(frame_); + auto it = g_frame_map.Get().find(frame_); CHECK(it != g_frame_map.Get().end()); CHECK_EQ(it->second, this); g_frame_map.Get().erase(it); @@ -5687,8 +5683,7 @@ // Set zoom level, but don't do it for full-page plugin since they don't use // the same zoom settings. - HostZoomLevels::iterator host_zoom = - host_zoom_levels_.find(GetLoadingUrl()); + auto host_zoom = host_zoom_levels_.find(GetLoadingUrl()); if (render_view_->webview()->MainFrame()->IsWebLocalFrame() && render_view_->webview() ->MainFrame() @@ -6891,14 +6886,12 @@ const GURL base_url = common_params.base_url_for_data_url.is_empty() ? common_params.url : common_params.base_url_for_data_url; - bool replace = load_type == WebFrameLoadType::kReloadBypassingCache || - load_type == WebFrameLoadType::kReload; frame_->CommitDataNavigation( WebURLRequest(base_url), WebData(data.c_str(), data.length()), WebString::FromUTF8(mime_type), WebString::FromUTF8(charset), // Needed so that history-url-only changes don't become reloads. - common_params.history_url_for_data_url, replace, load_type, + common_params.history_url_for_data_url, load_type, item_for_history_navigation, is_client_redirect, BuildNavigationParams( common_params, request_params,
diff --git a/content/renderer/render_frame_proxy.cc b/content/renderer/render_frame_proxy.cc index e1df1b76..ade104d 100644 --- a/content/renderer/render_frame_proxy.cc +++ b/content/renderer/render_frame_proxy.cc
@@ -179,7 +179,7 @@ // static RenderFrameProxy* RenderFrameProxy::FromRoutingID(int32_t routing_id) { RoutingIDProxyMap* proxies = g_routing_id_proxy_map.Pointer(); - RoutingIDProxyMap::iterator it = proxies->find(routing_id); + auto it = proxies->find(routing_id); return it == proxies->end() ? NULL : it->second; } @@ -188,7 +188,7 @@ blink::WebRemoteFrame* web_frame) { // TODO(dcheng): Turn this into a DCHECK() if it doesn't crash on canary. CHECK(web_frame); - FrameProxyMap::iterator iter = g_frame_proxy_map.Get().find(web_frame); + auto iter = g_frame_proxy_map.Get().find(web_frame); if (iter != g_frame_proxy_map.Get().end()) { RenderFrameProxy* proxy = iter->second; DCHECK_EQ(web_frame, proxy->web_frame()); @@ -730,7 +730,7 @@ // Remove the entry in the WebFrame->RenderFrameProxy map, as the |web_frame_| // is no longer valid. - FrameProxyMap::iterator it = g_frame_proxy_map.Get().find(web_frame_); + auto it = g_frame_proxy_map.Get().find(web_frame_); CHECK(it != g_frame_proxy_map.Get().end()); CHECK_EQ(it->second, this); g_frame_proxy_map.Get().erase(it);
diff --git a/content/renderer/render_process_impl.cc b/content/renderer/render_process_impl.cc index f641614f..b9f38b0 100644 --- a/content/renderer/render_process_impl.cc +++ b/content/renderer/render_process_impl.cc
@@ -136,9 +136,6 @@ "--harmony-dynamic-import --harmony-import-meta"; v8::V8::SetFlagsFromString(kModuleFlags, sizeof(kModuleFlags)); - SetV8FlagIfFeature(features::kAsmJsToWebAssembly, "--validate-asm"); - SetV8FlagIfNotFeature(features::kAsmJsToWebAssembly, "--no-validate-asm"); - SetV8FlagIfFeature(features::kV8Orinoco, "--no-single-threaded-gc"); SetV8FlagIfNotFeature(features::kV8Orinoco, "--single-threaded-gc");
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc index 6d60eae..a6bdb66 100644 --- a/content/renderer/render_view_impl.cc +++ b/content/renderer/render_view_impl.cc
@@ -380,8 +380,7 @@ void ApplyFontsFromMap(const ScriptFontFamilyMap& map, SetFontFamilyWrapper setter, WebSettings* settings) { - for (ScriptFontFamilyMap::const_iterator it = map.begin(); it != map.end(); - ++it) { + for (auto it = map.begin(); it != map.end(); ++it) { int32_t script = u_getPropertyValueEnum(UCHAR_SCRIPT, (it->first).c_str()); if (script >= 0 && script < USCRIPT_CODE_LIMIT) { UScriptCode code = static_cast<UScriptCode>(script); @@ -612,7 +611,7 @@ /*static*/ RenderViewImpl* RenderViewImpl::FromWebView(WebView* webview) { ViewMap* views = g_view_map.Pointer(); - ViewMap::iterator it = views->find(webview); + auto it = views->find(webview); return it == views->end() ? NULL : it->second; } @@ -624,7 +623,7 @@ /*static*/ RenderViewImpl* RenderViewImpl::FromRoutingID(int32_t routing_id) { RoutingIDViewMap* views = g_routing_id_view_map.Pointer(); - RoutingIDViewMap::iterator it = views->find(routing_id); + auto it = views->find(routing_id); return it == views->end() ? NULL : it->second; } @@ -641,7 +640,7 @@ /*static*/ void RenderView::ForEach(RenderViewVisitor* visitor) { ViewMap* views = g_view_map.Pointer(); - for (ViewMap::iterator it = views->begin(); it != views->end(); ++it) { + for (auto it = views->begin(); it != views->end(); ++it) { if (!visitor->Visit(it->second)) return; }
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc index 055afd0..2d10e5b 100644 --- a/content/renderer/render_widget.cc +++ b/content/renderer/render_widget.cc
@@ -297,9 +297,7 @@ item_list.push_back(item); } - for (std::vector<ui::FileInfo>::const_iterator it = - drop_data.filenames.begin(); - it != drop_data.filenames.end(); + for (auto it = drop_data.filenames.begin(); it != drop_data.filenames.end(); ++it) { WebDragData::Item item; item.storage_type = WebDragData::Item::kStorageTypeFilename; @@ -309,10 +307,8 @@ item_list.push_back(item); } - for (std::vector<DropData::FileSystemFileInfo>::const_iterator it = - drop_data.file_system_files.begin(); - it != drop_data.file_system_files.end(); - ++it) { + for (auto it = drop_data.file_system_files.begin(); + it != drop_data.file_system_files.end(); ++it) { WebDragData::Item item; item.storage_type = WebDragData::Item::kStorageTypeFileSystemFile; item.file_system_url = it->url; @@ -470,7 +466,7 @@ // static RenderWidget* RenderWidget::FromRoutingID(int32_t routing_id) { RoutingIDWidgetMap* widgets = g_routing_id_widget_map.Pointer(); - RoutingIDWidgetMap::iterator it = widgets->find(routing_id); + auto it = widgets->find(routing_id); return it == widgets->end() ? NULL : it->second; }
diff --git a/content/renderer/service_worker/controller_service_worker_connector.h b/content/renderer/service_worker/controller_service_worker_connector.h index 066a87c7..49a66ad 100644 --- a/content/renderer/service_worker/controller_service_worker_connector.h +++ b/content/renderer/service_worker/controller_service_worker_connector.h
@@ -5,6 +5,8 @@ #ifndef CONTENT_RENDERER_SERVICE_WORKER_CONTROLLER_SERVICE_WORKER_CONNECTOR_H_ #define CONTENT_RENDERER_SERVICE_WORKER_CONTROLLER_SERVICE_WORKER_CONNECTOR_H_ +#include <string> + #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/observer_list.h" @@ -97,16 +99,11 @@ mojo::BindingSet<mojom::ControllerServiceWorkerConnector> bindings_; - // Keeps the mojo end to the browser process on its own. - // Non-null only for the service worker clients that are workers (i.e., only - // when created for dedicated workers or shared workers). + // Connection to the container host in the browser process. mojom::ServiceWorkerContainerHostPtr container_host_ptr_; - // Connection to the ControllerServiceWorker. The consumer of this connection - // should not need to know which process this is connected to. - // (Currently this is connected to BrowserSideControllerServiceWorker, - // but will eventually be directly connected to the controller service worker - // in the renderer process) + // Connection to the controller service worker, which lives in a renderer + // process that's not necessarily the same as this connector. mojom::ControllerServiceWorkerPtr controller_service_worker_; base::ObserverList<Observer>::Unchecked observer_list_;
diff --git a/content/renderer/service_worker/service_worker_provider_context.cc b/content/renderer/service_worker/service_worker_provider_context.cc index 697f3e3..7ee9e0f2 100644 --- a/content/renderer/service_worker/service_worker_provider_context.cc +++ b/content/renderer/service_worker/service_worker_provider_context.cc
@@ -204,8 +204,8 @@ DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence()); DCHECK(state_for_client_); mojom::ServiceWorkerContainerHostPtrInfo container_host_ptr_info; - // TODO(kinuko): rename this, now this can be used for non-worker clients. - container_host_->CloneForWorker(mojo::MakeRequest(&container_host_ptr_info)); + container_host_->CloneContainerHost( + mojo::MakeRequest(&container_host_ptr_info)); return container_host_ptr_info; }
diff --git a/content/renderer/service_worker/service_worker_provider_context.h b/content/renderer/service_worker/service_worker_provider_context.h index 197858b..f6773f10 100644 --- a/content/renderer/service_worker/service_worker_provider_context.h +++ b/content/renderer/service_worker/service_worker_provider_context.h
@@ -139,11 +139,8 @@ mojom::ServiceWorkerWorkerClientRegistryRequest request) override; // S13nServiceWorker: - // For service worker clients. Creates a ServiceWorkerContainerHostPtrInfo - // which can be bound to a ServiceWorkerContainerHostPtr in a (dedicated or - // shared) worker thread. WebWorkerFetchContextImpl will use the host pointer - // to get the controller service worker by GetControllerServiceWorker() and - // send FetchEvents to the service worker. + // For service worker clients. Returns a ServiceWorkerContainerHostPtrInfo + // to this client's container host. mojom::ServiceWorkerContainerHostPtrInfo CloneContainerHostPtrInfo(); // For service worker clients. Returns the registration object described by
diff --git a/content/renderer/service_worker/service_worker_provider_context_unittest.cc b/content/renderer/service_worker/service_worker_provider_context_unittest.cc index 7274953c..94925ba2 100644 --- a/content/renderer/service_worker/service_worker_provider_context_unittest.cc +++ b/content/renderer/service_worker/service_worker_provider_context_unittest.cc
@@ -318,7 +318,7 @@ mojom::ControllerServiceWorkerPurpose purpose) override { NOTIMPLEMENTED(); } - void CloneForWorker( + void CloneContainerHost( mojom::ServiceWorkerContainerHostRequest request) override { bindings_.AddBinding(this, std::move(request)); }
diff --git a/content/renderer/service_worker/service_worker_subresource_loader.h b/content/renderer/service_worker/service_worker_subresource_loader.h index 28359d5..9cb935a0 100644 --- a/content/renderer/service_worker/service_worker_subresource_loader.h +++ b/content/renderer/service_worker/service_worker_subresource_loader.h
@@ -182,9 +182,8 @@ // default URLLoaderFactory for network fallback. This should be the // URLLoaderFactory that directly goes to network without going through // any custom URLLoader factories. - // |task_runner| is the runner where this loader runs. (We need to pass - // this around because calling base::SequencedTaskRunnerHandle is - // prohibited in the renderer :() + // |task_runner| is the runner where this loader runs. In production it runs, + // on a background thread. static void Create( scoped_refptr<ControllerServiceWorkerConnector> controller_connector, scoped_refptr<network::SharedURLLoaderFactory> fallback_factory,
diff --git a/content/renderer/service_worker/service_worker_subresource_loader_unittest.cc b/content/renderer/service_worker/service_worker_subresource_loader_unittest.cc index 46abdd0..2b98b15 100644 --- a/content/renderer/service_worker/service_worker_subresource_loader_unittest.cc +++ b/content/renderer/service_worker/service_worker_subresource_loader_unittest.cc
@@ -4,6 +4,11 @@ #include "content/renderer/service_worker/service_worker_subresource_loader.h" +#include <memory> +#include <string> +#include <utility> +#include <vector> + #include "base/run_loop.h" #include "base/strings/string_number_conversions.h" #include "base/test/metrics/histogram_tester.h" @@ -377,7 +382,7 @@ return; fake_controller_->Clone(std::move(request)); } - void CloneForWorker( + void CloneContainerHost( mojom::ServiceWorkerContainerHostRequest request) override { bindings_.AddBinding(this, std::move(request)); } @@ -432,7 +437,8 @@ network::mojom::URLLoaderFactoryPtr CreateSubresourceLoaderFactory() { if (!connector_) { mojom::ServiceWorkerContainerHostPtrInfo host_ptr_info; - fake_container_host_.CloneForWorker(mojo::MakeRequest(&host_ptr_info)); + fake_container_host_.CloneContainerHost( + mojo::MakeRequest(&host_ptr_info)); connector_ = base::MakeRefCounted<ControllerServiceWorkerConnector>( std::move(host_ptr_info), nullptr /*controller_ptr*/, "" /*client_id*/);
diff --git a/content/renderer/v8_value_converter_impl.cc b/content/renderer/v8_value_converter_impl.cc index 1afe31ed3..730b660 100644 --- a/content/renderer/v8_value_converter_impl.cc +++ b/content/renderer/v8_value_converter_impl.cc
@@ -95,7 +95,7 @@ // hash (key) in the map, because two objects can have the same hash. bool AddToUniquenessCheck(v8::Local<v8::Object> handle) { int hash; - Iterator iter = GetIteratorInMap(handle, &hash); + auto iter = GetIteratorInMap(handle, &hash); if (iter != unique_map_.end()) return false; @@ -105,7 +105,7 @@ bool RemoveFromUniquenessCheck(v8::Local<v8::Object> handle) { int unused_hash; - Iterator iter = GetIteratorInMap(handle, &unused_hash); + auto iter = GetIteratorInMap(handle, &unused_hash); if (iter == unique_map_.end()) return false; unique_map_.erase(iter); @@ -126,7 +126,7 @@ // hash. Different hash obviously means different objects, but two objects // in a couple of thousands could have the same identity hash. std::pair<Iterator, Iterator> range = unique_map_.equal_range(*hash); - for (Iterator it = range.first; it != range.second; ++it) { + for (auto it = range.first; it != range.second; ++it) { // Operator == for handles actually compares the underlying objects. if (it->second == handle) return it;
diff --git a/content/renderer/web_ui_extension_data.cc b/content/renderer/web_ui_extension_data.cc index 43cf15e..9d8c5ed 100644 --- a/content/renderer/web_ui_extension_data.cc +++ b/content/renderer/web_ui_extension_data.cc
@@ -18,8 +18,7 @@ } std::string WebUIExtensionData::GetValue(const std::string& key) const { - std::map<std::string, std::string>::const_iterator it = - variable_map_.find(key); + auto it = variable_map_.find(key); if (it == variable_map_.end()) return std::string(); return it->second;
diff --git a/content/renderer/worker_thread_registry.cc b/content/renderer/worker_thread_registry.cc index e5204cd..1984cd2 100644 --- a/content/renderer/worker_thread_registry.cc +++ b/content/renderer/worker_thread_registry.cc
@@ -129,7 +129,7 @@ bool WorkerThreadRegistry::PostTask(int id, base::OnceClosure closure) { DCHECK(id > 0); base::AutoLock locker(task_runner_map_lock_); - IDToTaskRunnerMap::iterator found = task_runner_map_.find(id); + auto found = task_runner_map_.find(id); if (found == task_runner_map_.end()) return false; return found->second->PostTask(FROM_HERE, std::move(closure));
diff --git a/content/test/data/accessibility/html/audio-expected-auralinux.txt b/content/test/data/accessibility/html/audio-expected-auralinux.txt index a0d4367..1c70d30e 100644 --- a/content/test/data/accessibility/html/audio-expected-auralinux.txt +++ b/content/test/data/accessibility/html/audio-expected-auralinux.txt
@@ -4,8 +4,8 @@ ++++++[section] ++++++++[tool bar] name='audio' description='audio' horizontal ++++++++++[tool bar] name='audio' description='audio' horizontal -++++++++++++[push button] name='play' description='begin playback' xml-roles:button +++++++++++++[push button] name='play' xml-roles:button ++++++++++++[text] name='0:00' ++++++++++++[text] name='/ 0:00' ++++++++++++[slider] description='audio time scrubber' horizontal xml-roles:slider -++++++++++++[push button] name='mute' description='mute audio track' xml-roles:button +++++++++++++[push button] name='mute' xml-roles:button
diff --git a/content/test/data/accessibility/html/source-expected-auralinux.txt b/content/test/data/accessibility/html/source-expected-auralinux.txt index da6f0cd..ab0b222 100644 --- a/content/test/data/accessibility/html/source-expected-auralinux.txt +++ b/content/test/data/accessibility/html/source-expected-auralinux.txt
@@ -4,8 +4,8 @@ ++++++[section] ++++++++[tool bar] name='audio' description='audio' horizontal ++++++++++[tool bar] name='audio' description='audio' horizontal -++++++++++++[push button] name='play' description='begin playback' focusable +++++++++++++[push button] name='play' focusable ++++++++++++[text] name='0:00' ++++++++++++[text] name='/ 0:00' ++++++++++++[slider] description='audio time scrubber' focusable horizontal -++++++++++++[push button] name='mute' description='mute audio track' +++++++++++++[push button] name='mute'
diff --git a/content/test/gpu/gpu_tests/power_measurement_integration_test.py b/content/test/gpu/gpu_tests/power_measurement_integration_test.py index 64452ff8..14d8ad0 100644 --- a/content/test/gpu/gpu_tests/power_measurement_integration_test.py +++ b/content/test/gpu/gpu_tests/power_measurement_integration_test.py
@@ -47,13 +47,34 @@ return rt; } - // Return true if video has started playing. - function setupVideoElement() { + /** + * Set up the video element for testing. + * @param {boolean} force_underlay - Whether to add a layer on top so + * the video layer becomes an underlay. + * @returns {boolean} true if video has started playing. + */ + function setupVideoElement(force_underlay) { var video = locateElement("video"); if (video) { video.muted = true; video.loop = true; video.autoplay = true; + if (force_underlay) { + var layer = document.createElement("div"); + layer.style.border = "thick solid rgb(0,0,255)"; + layer.style.backgroundColor = "red"; + layer.style.width = "100px"; + layer.style.height = "50px"; + layer.style.position = "absolute"; + layer.style.zIndex = "1000"; + var vid_rect = video.getBoundingClientRect(); + var parent_rect = video.parentNode.getBoundingClientRect(); + var top = vid_rect.top - parent_rect.top; + var left = vid_rect.left - parent_rect.left; + layer.style.top = top.toString() + "px"; + layer.style.left = left.toString() + "px"; + video.parentNode.appendChild(layer); + } return video.currentTime > 0; } return false; @@ -125,6 +146,9 @@ help="specify if the browser goes to fullscreen mode " "automatically, specifically if there is a single video " "element in the page, switch it to fullsrceen mode.") + parser.add_option("--underlay", action="store_true", default=False, + help="add a layer on top so the video layer becomes an " + "underlay.") parser.add_option("--logdir", help="Speficy where the Intel Power Gadget log file " "should be stored. If specified, the log file name will " @@ -145,6 +169,7 @@ yield ('url', options.url, (options.repeat, options.outliers, options.fullscreen, + options.underlay, options.logdir, options.duration, options.delay, @@ -166,10 +191,11 @@ repeat = args[0] outliers = args[1] fullscreen = args[2] - ipg_logdir = args[3] - ipg_duration = args[4] - ipg_delay = args[5] - ipg_resolution = args[6] + underlay = args[3] + ipg_logdir = args[4] + ipg_duration = args[5] + ipg_delay = args[6] + ipg_resolution = args[7] print "" print "Total iterations: ", repeat @@ -180,7 +206,8 @@ if test_path: self.tab.action_runner.Navigate(test_path, fullscreen_script) self.tab.WaitForDocumentReadyStateToBeComplete() - if not self.tab.action_runner.EvaluateJavaScript('setupVideoElement()'): + code = "setupVideoElement(%s)" % ("true" if underlay else "false") + if not self.tab.action_runner.EvaluateJavaScript(code): # autoplay doesn't work for vimeo. # action_runner.PlayMedia doesn't work for vimeo. self.tab.action_runner.TapElement(element_function=(
diff --git a/docs/README.md b/docs/README.md index ffe325ae..f9e5b0f 100644 --- a/docs/README.md +++ b/docs/README.md
@@ -134,8 +134,6 @@ the window system and low level input and graphics. * [Optimizing Chrome Web UIs](optimizing_web_uis.md) - Notes on making webuis more performant -* [ES6 Support in Chromium](es6_chromium.md) - Implementation of ECMAScript6 - features in Chromium * [Adding a new feature flag in chrome://flags](how_to_add_your_feature_flag.md) - Quick guide to add a new feature flag to experiment your feature. * [Guidelines for considering branch dates in project planning](release_branch_guidance.md) -
diff --git a/extensions/browser/service_worker_task_queue.cc b/extensions/browser/service_worker_task_queue.cc index 9cefafca..7508092b 100644 --- a/extensions/browser/service_worker_task_queue.cc +++ b/extensions/browser/service_worker_task_queue.cc
@@ -70,8 +70,6 @@ thread_id(thread_id) {} WaitingDidStartWorkerTask(WaitingDidStartWorkerTask&& other) = default; - WaitingDidStartWorkerTask& operator=(WaitingDidStartWorkerTask&& other) = - default; LazyContextTaskQueue::PendingTask task; const ExtensionId extension_id;
diff --git a/gpu/command_buffer/service/context_group.cc b/gpu/command_buffer/service/context_group.cc index 3200bd1..321f3ec 100644 --- a/gpu/command_buffer/service/context_group.cc +++ b/gpu/command_buffer/service/context_group.cc
@@ -17,7 +17,6 @@ #include "gpu/command_buffer/service/gles2_cmd_decoder_passthrough.h" #include "gpu/command_buffer/service/path_manager.h" #include "gpu/command_buffer/service/program_manager.h" -#include "gpu/command_buffer/service/progress_reporter.h" #include "gpu/command_buffer/service/renderbuffer_manager.h" #include "gpu/command_buffer/service/sampler_manager.h" #include "gpu/command_buffer/service/service_discardable_manager.h" @@ -27,6 +26,7 @@ #include "gpu/config/gpu_preferences.h" #include "ui/gl/gl_bindings.h" #include "ui/gl/gl_version_info.h" +#include "ui/gl/progress_reporter.h" namespace gpu { namespace gles2 { @@ -70,7 +70,7 @@ bool bind_generates_resource, ImageManager* image_manager, gpu::ImageFactory* image_factory, - ProgressReporter* progress_reporter, + gl::ProgressReporter* progress_reporter, const GpuFeatureInfo& gpu_feature_info, ServiceDiscardableManager* discardable_manager) : gpu_preferences_(gpu_preferences),
diff --git a/gpu/command_buffer/service/context_group.h b/gpu/command_buffer/service/context_group.h index 5e47d38f..c119b43f 100644 --- a/gpu/command_buffer/service/context_group.h +++ b/gpu/command_buffer/service/context_group.h
@@ -24,6 +24,10 @@ #include "gpu/config/gpu_preferences.h" #include "gpu/gpu_gles2_export.h" +namespace gl { +class ProgressReporter; +} + namespace gpu { class ImageFactory; @@ -41,7 +45,6 @@ class RenderbufferManager; class PathManager; class ProgramManager; -class ProgressReporter; class SamplerManager; class ShaderManager; class TextureManager; @@ -67,7 +70,7 @@ bool bind_generates_resource, ImageManager* image_manager, gpu::ImageFactory* image_factory, - ProgressReporter* progress_reporter, + gl::ProgressReporter* progress_reporter, const GpuFeatureInfo& gpu_feature_info, ServiceDiscardableManager* discardable_manager); @@ -313,7 +316,7 @@ // Used to notify the watchdog thread of progress during destruction, // preventing time-outs when destruction takes a long time. May be null when // using in-process command buffer. - ProgressReporter* progress_reporter_; + gl::ProgressReporter* progress_reporter_; GpuFeatureInfo gpu_feature_info_;
diff --git a/gpu/command_buffer/service/program_manager.cc b/gpu/command_buffer/service/program_manager.cc index 5fc3e24..2947d0c 100644 --- a/gpu/command_buffer/service/program_manager.cc +++ b/gpu/command_buffer/service/program_manager.cc
@@ -28,11 +28,11 @@ #include "gpu/command_buffer/service/decoder_context.h" #include "gpu/command_buffer/service/feature_info.h" #include "gpu/command_buffer/service/program_cache.h" -#include "gpu/command_buffer/service/progress_reporter.h" #include "gpu/command_buffer/service/shader_manager.h" #include "gpu/config/gpu_preferences.h" #include "third_party/re2/src/re2/re2.h" #include "ui/gl/gl_version_info.h" +#include "ui/gl/progress_reporter.h" using base::TimeDelta; using base::TimeTicks; @@ -2597,7 +2597,7 @@ uint32_t max_vertex_attribs, const GpuPreferences& gpu_preferences, FeatureInfo* feature_info, - ProgressReporter* progress_reporter) + gl::ProgressReporter* progress_reporter) : program_count_(0), have_context_(true), program_cache_(program_cache),
diff --git a/gpu/command_buffer/service/program_manager.h b/gpu/command_buffer/service/program_manager.h index 77f79eb..7bc019fa 100644 --- a/gpu/command_buffer/service/program_manager.h +++ b/gpu/command_buffer/service/program_manager.h
@@ -652,7 +652,7 @@ uint32_t max_vertex_attribs, const GpuPreferences& gpu_preferences, FeatureInfo* feature_info, - ProgressReporter* progress_reporter); + gl::ProgressReporter* progress_reporter); ~ProgramManager(); // Must call before destruction. @@ -737,7 +737,7 @@ // Used to notify the watchdog thread of progress during destruction, // preventing time-outs when destruction takes a long time. May be null when // using in-process command buffer. - ProgressReporter* progress_reporter_; + gl::ProgressReporter* progress_reporter_; DISALLOW_COPY_AND_ASSIGN(ProgramManager); };
diff --git a/gpu/command_buffer/service/progress_reporter.h b/gpu/command_buffer/service/progress_reporter.h deleted file mode 100644 index 926e4f8..0000000 --- a/gpu/command_buffer/service/progress_reporter.h +++ /dev/null
@@ -1,25 +0,0 @@ -// Copyright (c) 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef GPU_COMMAND_BUFFER_SERVICE_PROGRESS_REPORTER_H_ -#define GPU_COMMAND_BUFFER_SERVICE_PROGRESS_REPORTER_H_ - -#include "gpu/gpu_gles2_export.h" - -namespace gpu { -namespace gles2 { - -// ProgressReporter is used by ContextGroup to report when it is making forward -// progress in execution, delaying activation of the watchdog timeout. -class GPU_GLES2_EXPORT ProgressReporter { - public: - virtual ~ProgressReporter() = default; - - virtual void ReportProgress() = 0; -}; - -} // namespace gles2 -} // namespace gpu - -#endif // GPU_COMMAND_BUFFER_SERVICE_PROGRESS_REPORTER_H_
diff --git a/gpu/command_buffer/service/raster_decoder_context_state.cc b/gpu/command_buffer/service/raster_decoder_context_state.cc index ef4ada86..9b12cb99 100644 --- a/gpu/command_buffer/service/raster_decoder_context_state.cc +++ b/gpu/command_buffer/service/raster_decoder_context_state.cc
@@ -43,11 +43,13 @@ void RasterDecoderContextState::InitializeGrContext( const GpuDriverBugWorkarounds& workarounds, GrContextOptions::PersistentCache* cache, - GpuProcessActivityFlags* activity_flags) { + GpuProcessActivityFlags* activity_flags, + gl::ProgressReporter* progress_reporter) { DCHECK(context->IsCurrent(surface.get())); sk_sp<GrGLInterface> interface(gl::init::CreateGrGLInterface( - *context->GetVersionInfo(), workarounds.use_es2_for_oopr)); + *context->GetVersionInfo(), workarounds.use_es2_for_oopr, + progress_reporter)); if (!interface) { LOG(ERROR) << "OOP raster support disabled: GrGLInterface creation " "failed.";
diff --git a/gpu/command_buffer/service/raster_decoder_context_state.h b/gpu/command_buffer/service/raster_decoder_context_state.h index f6bb7d5..28321e47 100644 --- a/gpu/command_buffer/service/raster_decoder_context_state.h +++ b/gpu/command_buffer/service/raster_decoder_context_state.h
@@ -11,6 +11,7 @@ #include "gpu/command_buffer/common/skia_utils.h" #include "gpu/gpu_gles2_export.h" #include "third_party/skia/include/gpu/GrContext.h" +#include "ui/gl/progress_reporter.h" namespace gl { class GLContext; @@ -35,7 +36,8 @@ bool use_virtualized_gl_contexts); void InitializeGrContext(const GpuDriverBugWorkarounds& workarounds, GrContextOptions::PersistentCache* cache, - GpuProcessActivityFlags* activity_flags = nullptr); + GpuProcessActivityFlags* activity_flags = nullptr, + gl::ProgressReporter* progress_reporter = nullptr); void PurgeMemory( base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level);
diff --git a/gpu/command_buffer/service/shader_manager.cc b/gpu/command_buffer/service/shader_manager.cc index 4889a7f..44f5b2d 100644 --- a/gpu/command_buffer/service/shader_manager.cc +++ b/gpu/command_buffer/service/shader_manager.cc
@@ -10,7 +10,7 @@ #include "base/logging.h" #include "base/strings/string_util.h" -#include "gpu/command_buffer/service/progress_reporter.h" +#include "ui/gl/progress_reporter.h" namespace gpu { namespace gles2 { @@ -277,7 +277,7 @@ return nullptr; } -ShaderManager::ShaderManager(ProgressReporter* progress_reporter) +ShaderManager::ShaderManager(gl::ProgressReporter* progress_reporter) : progress_reporter_(progress_reporter) {} ShaderManager::~ShaderManager() {
diff --git a/gpu/command_buffer/service/shader_manager.h b/gpu/command_buffer/service/shader_manager.h index f36aa32..579dddd 100644 --- a/gpu/command_buffer/service/shader_manager.h +++ b/gpu/command_buffer/service/shader_manager.h
@@ -15,11 +15,13 @@ #include "gpu/command_buffer/service/shader_translator.h" #include "gpu/gpu_gles2_export.h" +namespace gl { +class ProgressReporter; +} + namespace gpu { namespace gles2 { -class ProgressReporter; - enum ShaderVariableBaseType { SHADER_VARIABLE_INT = 0x01, SHADER_VARIABLE_UINT = 0x02, @@ -279,7 +281,7 @@ // need to be shared by multiple GLES2Decoders. class GPU_GLES2_EXPORT ShaderManager { public: - ShaderManager(ProgressReporter* progress_reporter); + ShaderManager(gl::ProgressReporter* progress_reporter); ~ShaderManager(); // Must call before destruction. @@ -322,7 +324,7 @@ // Used to notify the watchdog thread of progress during destruction, // preventing time-outs when destruction takes a long time. May be null when // using in-process command buffer. - ProgressReporter* progress_reporter_; + gl::ProgressReporter* progress_reporter_; DISALLOW_COPY_AND_ASSIGN(ShaderManager); };
diff --git a/gpu/command_buffer/service/texture_manager.cc b/gpu/command_buffer/service/texture_manager.cc index 0556e350..9bb41247 100644 --- a/gpu/command_buffer/service/texture_manager.cc +++ b/gpu/command_buffer/service/texture_manager.cc
@@ -28,12 +28,12 @@ #include "gpu/command_buffer/service/gl_stream_texture_image.h" #include "gpu/command_buffer/service/mailbox_manager.h" #include "gpu/command_buffer/service/memory_tracking.h" -#include "gpu/command_buffer/service/progress_reporter.h" #include "gpu/command_buffer/service/service_discardable_manager.h" #include "ui/gl/gl_context.h" #include "ui/gl/gl_implementation.h" #include "ui/gl/gl_state_restorer.h" #include "ui/gl/gl_version_info.h" +#include "ui/gl/progress_reporter.h" #include "ui/gl/trace_util.h" using base::trace_event::MemoryAllocatorDump; @@ -1957,7 +1957,7 @@ GLint max_3d_texture_size, GLint max_array_texture_layers, bool use_default_textures, - ProgressReporter* progress_reporter, + gl::ProgressReporter* progress_reporter, ServiceDiscardableManager* discardable_manager) : memory_type_tracker_(new MemoryTypeTracker(memory_tracker)), memory_tracker_(memory_tracker),
diff --git a/gpu/command_buffer/service/texture_manager.h b/gpu/command_buffer/service/texture_manager.h index 92777837..99fe91a 100644 --- a/gpu/command_buffer/service/texture_manager.h +++ b/gpu/command_buffer/service/texture_manager.h
@@ -28,6 +28,10 @@ #include "ui/gfx/geometry/rect.h" #include "ui/gl/gl_image.h" +namespace gl { +class ProgressReporter; +} + namespace gpu { class DecoderContext; class ServiceDiscardableManager; @@ -40,7 +44,6 @@ class ErrorState; class FeatureInfo; class FramebufferManager; -class ProgressReporter; class Texture; class TextureManager; class TextureRef; @@ -754,7 +757,7 @@ GLsizei max_3d_texture_size, GLsizei max_array_texture_layers, bool use_default_textures, - ProgressReporter* progress_reporter, + gl::ProgressReporter* progress_reporter, ServiceDiscardableManager* discardable_manager); ~TextureManager() override; @@ -1247,7 +1250,7 @@ // Used to notify the watchdog thread of progress during destruction, // preventing time-outs when destruction takes a long time. May be null when // using in-process command buffer. - ProgressReporter* progress_reporter_; + gl::ProgressReporter* progress_reporter_; ServiceDiscardableManager* discardable_manager_;
diff --git a/gpu/ipc/service/direct_composition_surface_win.cc b/gpu/ipc/service/direct_composition_surface_win.cc index b5afb09..1eb57c4 100644 --- a/gpu/ipc/service/direct_composition_surface_win.cc +++ b/gpu/ipc/service/direct_composition_surface_win.cc
@@ -236,8 +236,10 @@ OverlayFormatToString(info.overlay_format), info.flags); } - UMA_HISTOGRAM_ENUMERATION("GPU.DirectComposition.OverlayFormatUsed", - g_overlay_format_used); + if (g_supports_overlays) { + UMA_HISTOGRAM_ENUMERATION("GPU.DirectComposition.OverlayFormatUsed2", + g_overlay_format_used); + } UMA_HISTOGRAM_BOOLEAN("GPU.DirectComposition.OverlaysSupported", g_supports_overlays); } @@ -735,8 +737,10 @@ return false; } - UMA_HISTOGRAM_BOOLEAN("GPU.DirectComposition.SwapchainFormat", - is_yuv_swapchain_); + UMA_HISTOGRAM_ENUMERATION( + "GPU.DirectComposition.SwapChainFormat2", + is_yuv_swapchain_ ? g_overlay_format_used : OverlayFormat::kBGRA); + frames_since_color_space_change_++; Microsoft::WRL::ComPtr<IDXGISwapChainMedia> swap_chain_media; @@ -943,6 +947,8 @@ frames_since_color_space_change_ = 0; + const std::string kSwapChainCreationResultUmaPrefix = + "GPU.DirectComposition.SwapChainCreationResult."; is_yuv_swapchain_ = false; // The composition surface handle isn't actually used, but // CreateSwapChainForComposition can't create YUV swapchains. @@ -952,6 +958,9 @@ swap_chain_.GetAddressOf()); is_yuv_swapchain_ = SUCCEEDED(hr); failed_to_create_yuv_swapchain_ = !is_yuv_swapchain_; + base::UmaHistogramBoolean(kSwapChainCreationResultUmaPrefix + + OverlayFormatToString(g_overlay_format_used), + SUCCEEDED(hr)); if (FAILED(hr)) { DLOG(ERROR) << "Failed to create " << OverlayFormatToString(g_overlay_format_used) @@ -970,6 +979,9 @@ HRESULT hr = media_factory->CreateSwapChainForCompositionSurfaceHandle( d3d11_device_.Get(), swap_chain_handle_.Get(), &desc, nullptr, swap_chain_.GetAddressOf()); + base::UmaHistogramBoolean(kSwapChainCreationResultUmaPrefix + + OverlayFormatToString(OverlayFormat::kBGRA), + SUCCEEDED(hr)); if (FAILED(hr)) { DLOG(ERROR) << "Failed to create BGRA swap chain with error " << std::hex << hr;
diff --git a/gpu/ipc/service/gpu_channel_manager.cc b/gpu/ipc/service/gpu_channel_manager.cc index 9237b226..1ed58cf 100644 --- a/gpu/ipc/service/gpu_channel_manager.cc +++ b/gpu/ipc/service/gpu_channel_manager.cc
@@ -31,6 +31,7 @@ #include "gpu/ipc/service/gpu_channel.h" #include "gpu/ipc/service/gpu_channel_manager_delegate.h" #include "gpu/ipc/service/gpu_memory_buffer_factory.h" +#include "gpu/ipc/service/gpu_watchdog_thread.h" #include "third_party/skia/include/core/SkGraphics.h" #include "ui/gl/gl_bindings.h" #include "ui/gl/gl_share_group.h" @@ -422,7 +423,8 @@ gpu::kGpuFeatureStatusEnabled; if (enable_raster_transport) { raster_decoder_context_state_->InitializeGrContext( - gpu_driver_bug_workarounds_, gr_shader_cache(), &activity_flags_); + gpu_driver_bug_workarounds_, gr_shader_cache(), &activity_flags_, + watchdog_); } gr_cache_controller_.emplace(raster_decoder_context_state_.get(),
diff --git a/gpu/ipc/service/gpu_watchdog_thread.h b/gpu/ipc/service/gpu_watchdog_thread.h index 1d2e14a..a7896770 100644 --- a/gpu/ipc/service/gpu_watchdog_thread.h +++ b/gpu/ipc/service/gpu_watchdog_thread.h
@@ -14,9 +14,9 @@ #include "base/threading/thread.h" #include "base/time/time.h" #include "build/build_config.h" -#include "gpu/command_buffer/service/progress_reporter.h" #include "gpu/ipc/service/gpu_ipc_service_export.h" #include "ui/gfx/native_widget_types.h" +#include "ui/gl/progress_reporter.h" #if defined(USE_X11) #include <sys/poll.h> @@ -28,10 +28,9 @@ // A thread that intermitently sends tasks to a group of watched message loops // and deliberately crashes if one of them does not respond after a timeout. -class GPU_IPC_SERVICE_EXPORT GpuWatchdogThread - : public base::Thread, - public base::PowerObserver, - public gles2::ProgressReporter { +class GPU_IPC_SERVICE_EXPORT GpuWatchdogThread : public base::Thread, + public base::PowerObserver, + public gl::ProgressReporter { public: ~GpuWatchdogThread() override; @@ -43,7 +42,7 @@ // any thread. void AddPowerObserver(); - // gles2::ProgressReporter implementation: + // gl::ProgressReporter implementation: void ReportProgress() override; // Notifies the watchdog when Chrome is backgrounded / foregrounded. Should
diff --git a/headless/app/headless_shell.cc b/headless/app/headless_shell.cc index 4159f2d..f0e0c9d 100644 --- a/headless/app/headless_shell.cc +++ b/headless/app/headless_shell.cc
@@ -721,11 +721,6 @@ builder.SetProxyConfig(std::move(proxy_config)); } - if (command_line.HasSwitch(::network::switches::kHostResolverRules)) { - builder.SetHostResolverRules(command_line.GetSwitchValueASCII( - ::network::switches::kHostResolverRules)); - } - if (command_line.HasSwitch(switches::kUseGL)) { builder.SetGLImplementation( command_line.GetSwitchValueASCII(switches::kUseGL));
diff --git a/headless/lib/browser/headless_browser_context_impl.cc b/headless/lib/browser/headless_browser_context_impl.cc index d90b6a6..6cc1e61 100644 --- a/headless/lib/browser/headless_browser_context_impl.cc +++ b/headless/lib/browser/headless_browser_context_impl.cc
@@ -405,13 +405,6 @@ return *this; } -HeadlessBrowserContext::Builder& -HeadlessBrowserContext::Builder::SetHostResolverRules( - const std::string& host_resolver_rules) { - options_->host_resolver_rules_ = host_resolver_rules; - return *this; -} - HeadlessBrowserContext::Builder& HeadlessBrowserContext::Builder::SetWindowSize( const gfx::Size& window_size) { options_->window_size_ = window_size;
diff --git a/headless/lib/browser/headless_browser_context_options.cc b/headless/lib/browser/headless_browser_context_options.cc index aedbb0a..e3ab688 100644 --- a/headless/lib/browser/headless_browser_context_options.cc +++ b/headless/lib/browser/headless_browser_context_options.cc
@@ -52,11 +52,6 @@ return browser_options_->proxy_config.get(); } -const std::string& HeadlessBrowserContextOptions::host_resolver_rules() const { - return ReturnOverriddenValue(host_resolver_rules_, - browser_options_->host_resolver_rules); -} - const gfx::Size& HeadlessBrowserContextOptions::window_size() const { return ReturnOverriddenValue(window_size_, browser_options_->window_size); }
diff --git a/headless/lib/browser/headless_browser_context_options.h b/headless/lib/browser/headless_browser_context_options.h index a8f3b098..441f884 100644 --- a/headless/lib/browser/headless_browser_context_options.h +++ b/headless/lib/browser/headless_browser_context_options.h
@@ -34,9 +34,6 @@ // See HeadlessBrowser::Options::proxy_config. const net::ProxyConfig* proxy_config() const; - // See HeadlessBrowser::Options::host_resolver_rules. - const std::string& host_resolver_rules() const; - const gfx::Size& window_size() const; // See HeadlessBrowser::Options::user_data_dir.
diff --git a/headless/lib/browser/headless_url_request_context_getter.cc b/headless/lib/browser/headless_url_request_context_getter.cc index 689a154c..efd07c5 100644 --- a/headless/lib/browser/headless_url_request_context_getter.cc +++ b/headless/lib/browser/headless_url_request_context_getter.cc
@@ -32,6 +32,7 @@ #include "net/traffic_annotation/network_traffic_annotation.h" #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_context_builder.h" +#include "services/network/public/cpp/network_switches.h" #if defined(OS_LINUX) && !defined(OS_CHROMEOS) #include "base/command_line.h" @@ -71,7 +72,6 @@ : io_task_runner_(std::move(io_task_runner)), accept_language_(options->accept_language()), user_agent_(options->user_agent()), - host_resolver_rules_(options->host_resolver_rules()), proxy_config_(options->proxy_config()), request_interceptors_(std::move(request_interceptors)), user_data_path_(std::move(user_data_path)) { @@ -87,6 +87,9 @@ prefs_.SetServerWhitelist( command_line->GetSwitchValueASCII(switches::kAuthServerWhitelist)); + host_resolver_rules_ = command_line->GetSwitchValueASCII( + ::network::switches::kHostResolverRules); + // We must create the proxy config service on the UI loop on Linux because it // must synchronously run on the glib message loop. This will be passed to // the URLRequestContextStorage on the IO thread in GetURLRequestContext(). @@ -228,10 +231,6 @@ return io_task_runner_; } -net::HostResolver* HeadlessURLRequestContextGetter::host_resolver() const { - return url_request_context_->host_resolver(); -} - void HeadlessURLRequestContextGetter::NotifyContextShuttingDown() { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); shut_down_ = true;
diff --git a/headless/lib/browser/headless_url_request_context_getter.h b/headless/lib/browser/headless_url_request_context_getter.h index 4ea266ad..05aac08d 100644 --- a/headless/lib/browser/headless_url_request_context_getter.h +++ b/headless/lib/browser/headless_url_request_context_getter.h
@@ -22,7 +22,6 @@ #include "net/url_request/url_request_job_factory.h" namespace net { -class HostResolver; class ProxyConfigService; } @@ -44,8 +43,6 @@ scoped_refptr<base::SingleThreadTaskRunner> GetNetworkTaskRunner() const override; - net::HostResolver* host_resolver() const; - void NotifyContextShuttingDown(); protected:
diff --git a/headless/lib/headless_browser_browsertest.cc b/headless/lib/headless_browser_browsertest.cc index 491f2dc..4cd0459 100644 --- a/headless/lib/headless_browser_browsertest.cc +++ b/headless/lib/headless_browser_browsertest.cc
@@ -231,30 +231,6 @@ EXPECT_TRUE(browser_context->GetAllWebContents().empty()); } -IN_PROC_BROWSER_TEST_F(HeadlessBrowserTest, SetHostResolverRules) { - EXPECT_TRUE(embedded_test_server()->Start()); - - std::string host_resolver_rules = - base::StringPrintf("MAP not-an-actual-domain.tld 127.0.0.1:%d", - embedded_test_server()->host_port_pair().port()); - - HeadlessBrowserContext* browser_context = - browser() - ->CreateBrowserContextBuilder() - .SetHostResolverRules(host_resolver_rules) - .Build(); - - // Load a page which doesn't actually exist, but which is turned into a valid - // address by our host resolver rules. - HeadlessWebContents* web_contents = - browser_context->CreateWebContentsBuilder() - .SetInitialURL(GURL("http://not-an-actual-domain.tld/hello.html")) - .Build(); - EXPECT_TRUE(web_contents); - - EXPECT_TRUE(WaitForLoad(web_contents)); -} - IN_PROC_BROWSER_TEST_F(HeadlessBrowserTest, WebGLSupported) { HeadlessBrowserContext* browser_context = browser()->CreateBrowserContextBuilder().Build();
diff --git a/headless/public/headless_browser.cc b/headless/public/headless_browser.cc index 22d2dc95..9ad4199 100644 --- a/headless/public/headless_browser.cc +++ b/headless/public/headless_browser.cc
@@ -99,11 +99,6 @@ return *this; } -Builder& Builder::SetHostResolverRules(const std::string& host_resolver_rules) { - options_.host_resolver_rules = host_resolver_rules; - return *this; -} - Builder& Builder::SetSingleProcessMode(bool single_process_mode) { options_.single_process_mode = single_process_mode; return *this;
diff --git a/headless/public/headless_browser.h b/headless/public/headless_browser.h index 7b0e30c..130c2ee 100644 --- a/headless/public/headless_browser.h +++ b/headless/public/headless_browser.h
@@ -161,10 +161,6 @@ // The ProxyConfig to use. The system proxy settings are used by default. std::unique_ptr<net::ProxyConfig> proxy_config = nullptr; - // Comma-separated list of rules that control how hostnames are mapped. See - // chrome::switches::kHostRules for a description for the format. - std::string host_resolver_rules; - // Default window size. This is also used to create the window tree host and // as initial screen size. Defaults to 800x600. gfx::Size window_size; @@ -257,7 +253,6 @@ Builder& SetEnableBeginFrameControl(bool enable_begin_frame_control); Builder& SetUserAgent(const std::string& user_agent); Builder& SetProxyConfig(std::unique_ptr<net::ProxyConfig> proxy_config); - Builder& SetHostResolverRules(const std::string& host_resolver_rules); Builder& SetWindowSize(const gfx::Size& window_size); Builder& SetUserDataDir(const base::FilePath& user_data_dir); Builder& SetIncognitoMode(bool incognito_mode);
diff --git a/headless/public/headless_browser_context.h b/headless/public/headless_browser_context.h index 0a21c55..886e2bb 100644 --- a/headless/public/headless_browser_context.h +++ b/headless/public/headless_browser_context.h
@@ -102,7 +102,6 @@ Builder& SetAcceptLanguage(const std::string& accept_language); Builder& SetUserAgent(const std::string& user_agent); Builder& SetProxyConfig(std::unique_ptr<net::ProxyConfig> proxy_config); - Builder& SetHostResolverRules(const std::string& host_resolver_rules); Builder& SetWindowSize(const gfx::Size& window_size); Builder& SetUserDataDir(const base::FilePath& user_data_dir); Builder& SetIncognitoMode(bool incognito_mode);
diff --git a/headless/test/headless_protocol_browsertest.cc b/headless/test/headless_protocol_browsertest.cc index fc46e13..5a25a6047 100644 --- a/headless/test/headless_protocol_browsertest.cc +++ b/headless/test/headless_protocol_browsertest.cc
@@ -26,6 +26,7 @@ #include "headless/public/headless_web_contents.h" #include "headless/test/headless_browser_test.h" #include "net/test/spawned_test_server/spawned_test_server.h" +#include "services/network/public/cpp/network_switches.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/url_util.h" @@ -47,6 +48,13 @@ EXPECT_TRUE(embedded_test_server()->Start()); } + protected: + void SetUpCommandLine(base::CommandLine* command_line) override { + command_line->AppendSwitchASCII(::network::switches::kHostResolverRules, + "MAP *.test 127.0.0.1"); + HeadlessAsyncDevTooledBrowserTest::SetUpCommandLine(command_line); + } + private: // HeadlessWebContentsObserver implementation. void DevToolsTargetReady() override { @@ -173,7 +181,6 @@ // Make sure the navigations spawn new processes. We run test harness // in one process (harness.test) and tests in another. builder.SetSitePerProcess(true); - builder.SetHostResolverRules("MAP *.test 127.0.0.1"); } protected:
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_home_mediator.mm b/ios/chrome/browser/ui/bookmarks/bookmark_home_mediator.mm index c30a780..513dd55 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmark_home_mediator.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmark_home_mediator.mm
@@ -199,9 +199,6 @@ int count = 0; for (const BookmarkNode* node : nodes) { - if (!node->is_url()) - continue; - BookmarkHomeNodeItem* nodeItem = [[BookmarkHomeNodeItem alloc] initWithType:BookmarkHomeItemTypeBookmark bookmarkNode:node];
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 070684d..450abda 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm
@@ -200,7 +200,7 @@ @property(nonatomic, readonly, weak) id<ApplicationCommands> dispatcher; // The current search term. Set to the empty string when no search is active. -@property(nonatomic, assign) NSString* searchTerm; +@property(nonatomic, copy) NSString* searchTerm; // This ViewController's searchController; @property(nonatomic, strong) UISearchController* searchController; @@ -772,6 +772,53 @@ } - (void)handleSelectFolderForNavigation:(const bookmarks::BookmarkNode*)folder { + if (self.sharedState.currentlyShowingSearchResults) { + // Clear bookmark path cache. + int64_t unusedFolderId; + int unusedIndexPathRow; + while ([BookmarkPathCache + getBookmarkTopMostRowCacheWithPrefService:self.browserState->GetPrefs() + model:self.bookmarks + folderId:&unusedFolderId + topMostRow:&unusedIndexPathRow]) { + [BookmarkPathCache + clearBookmarkTopMostRowCacheWithPrefService:self.browserState + ->GetPrefs()]; + } + + // Rebuild folder controller list, going back up the tree. + NSMutableArray<BookmarkHomeViewController*>* stack = [NSMutableArray array]; + std::vector<const bookmarks::BookmarkNode*> nodes; + const bookmarks::BookmarkNode* cursor = folder; + while (cursor) { + // Build reversed list of nodes to restore bookmark path below. + nodes.insert(nodes.begin(), cursor); + + // Build reversed list of controllers. + BookmarkHomeViewController* controller = + [self createControllerWithRootFolder:cursor]; + [stack insertObject:controller atIndex:0]; + + // Setup now, so that the back button labels shows parent folder + // title and that we don't show large title everywhere. + [self setupNavigationForBookmarkHomeViewController:controller + usingBookmarkNode:cursor]; + + cursor = cursor->parent(); + } + + // Reconstruct bookmark path cache. + for (const bookmarks::BookmarkNode* node : nodes) { + [BookmarkPathCache + cacheBookmarkTopMostRowWithPrefService:self.browserState->GetPrefs() + folderId:node->id() + topMostRow:0]; + } + + [self navigateAway]; + [self.navigationController setViewControllers:stack animated:YES]; + return; + } BookmarkHomeViewController* controller = [self createControllerWithRootFolder:folder]; [self.navigationController pushViewController:controller animated:YES];
diff --git a/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm b/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm index 957e6af..488e0aa8 100644 --- a/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm +++ b/ios/chrome/browser/ui/bookmarks/bookmarks_egtest.mm
@@ -1729,7 +1729,7 @@ #pragma mark - BookmarksTestCaseEntries Tests - (void)testUndoDeleteBookmarkFromSwipe { - // TODO(crbug.com/851227): On UIRefresh non Compact Width on iOS11, the + // TODO(crbug.com/851227): On Compact Width on iOS11, 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 @@ -1781,7 +1781,7 @@ FLAKY_testSwipeToDeleteDisabledInEditMode #endif - (void)testSwipeToDeleteDisabledInEditMode { - // TODO(crbug.com/851227): On UIRefresh non Compact Width on iOS11, the + // TODO(crbug.com/851227): On non Compact Width on iOS11, 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 @@ -4115,10 +4115,10 @@ [[EarlGrey selectElementWithMatcher:SearchIconButton()] performAction:grey_typeText(@"o")]; - // Verify that folders are filtered out. + // Verify that folders are not filtered out. [[EarlGrey selectElementWithMatcher:TappableBookmarkNodeWithLabel(@"Folder 1")] - assertWithMatcher:grey_nil()]; + assertWithMatcher:grey_notNil()]; // Search 'on'. [[EarlGrey selectElementWithMatcher:SearchIconButton()] @@ -4135,6 +4135,10 @@ [[EarlGrey selectElementWithMatcher:TappableBookmarkNodeWithLabel(@"French URL")] assertWithMatcher:grey_nil()]; + // Verify that folders are not filtered out. + [[EarlGrey + selectElementWithMatcher:TappableBookmarkNodeWithLabel(@"Folder 1")] + assertWithMatcher:grey_nil()]; // Search again for 'ony'. [[EarlGrey selectElementWithMatcher:SearchIconButton()] @@ -4338,9 +4342,57 @@ assertWithMatcher:grey_notNil()]; } -// Tests that you can swipe items in search mode. -- (void)testSearchItemsCanBeSwipedToDelete { - // TODO(crbug.com/851227): On UIRefresh non Compact Width on iOS11, the +// Tests that you can long press and edit a bookmark folder and see edits +// when going back to search. +- (void)testSearchLongPressEditOnFolder { + [BookmarksTestCase setupStandardBookmarks]; + [BookmarksTestCase openBookmarks]; + [BookmarksTestCase openMobileBookmarks]; + + NSString* existingFolderTitle = @"Folder 1.1"; + + // Search. + [[EarlGrey selectElementWithMatcher:SearchIconButton()] + performAction:grey_typeText(existingFolderTitle)]; + + // Invoke Edit through long press. + [[EarlGrey selectElementWithMatcher:TappableBookmarkNodeWithLabel( + existingFolderTitle)] + performAction:grey_longPress()]; + + [[EarlGrey + selectElementWithMatcher:ButtonWithAccessibilityLabelId( + IDS_IOS_BOOKMARK_CONTEXT_MENU_EDIT_FOLDER)] + performAction:grey_tap()]; + + // Verify that the editor is present. + [[EarlGrey + selectElementWithMatcher:grey_accessibilityID( + kBookmarkFolderEditViewContainerIdentifier)] + assertWithMatcher:grey_notNil()]; + + NSString* newFolderTitle = @"n7"; + [BookmarksTestCase renameBookmarkFolderWithFolderTitle:newFolderTitle]; + + [[EarlGrey selectElementWithMatcher:BookmarksSaveEditFolderButton()] + performAction:grey_tap()]; + + // Verify that the change has been made. + [[EarlGrey selectElementWithMatcher:TappableBookmarkNodeWithLabel( + existingFolderTitle)] + assertWithMatcher:grey_nil()]; + + [[EarlGrey selectElementWithMatcher:SearchIconButton()] + performAction:grey_replaceText(newFolderTitle)]; + + [[EarlGrey + selectElementWithMatcher:TappableBookmarkNodeWithLabel(newFolderTitle)] + assertWithMatcher:grey_notNil()]; +} + +// 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. // grey_swipeFastInDirectionWithStartPoint doesn't work either and it might // fail on devices. Disabling this test under these conditions on the @@ -4357,7 +4409,7 @@ // Search. [[EarlGrey selectElementWithMatcher:SearchIconButton()] - performAction:grey_typeText(@"F")]; + performAction:grey_typeText(@"First URL")]; [[EarlGrey selectElementWithMatcher:TappableBookmarkNodeWithLabel(@"First URL")] @@ -4368,6 +4420,36 @@ assertWithMatcher:grey_notNil()]; } +// 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. + // 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."); + } + } + + [BookmarksTestCase setupStandardBookmarks]; + [BookmarksTestCase openBookmarks]; + [BookmarksTestCase openMobileBookmarks]; + + // Search. + [[EarlGrey selectElementWithMatcher:SearchIconButton()] + performAction:grey_typeText(@"Folder 1")]; + + [[EarlGrey + selectElementWithMatcher:TappableBookmarkNodeWithLabel(@"Folder 1")] + performAction:grey_swipeFastInDirection(kGREYDirectionLeft)]; + + // Verify we have a delete button. + [[EarlGrey selectElementWithMatcher:BookmarksDeleteSwipeButton()] + assertWithMatcher:grey_notNil()]; +} + // Tests that you can't search while in edit mode. - (void)testDisablesSearchOnEditMode { [BookmarksTestCase setupStandardBookmarks]; @@ -4633,4 +4715,44 @@ assertWithMatcher:grey_nil()]; } +// Tests that you can search folders. +- (void)testSearchFolders { + [BookmarksTestCase setupStandardBookmarks]; + [BookmarksTestCase openBookmarks]; + [BookmarksTestCase openMobileBookmarks]; + + // Go down Folder 1 / Folder 2 / Folder 3. + [[EarlGrey + selectElementWithMatcher:TappableBookmarkNodeWithLabel(@"Folder 1")] + performAction:grey_tap()]; + [[EarlGrey + selectElementWithMatcher:TappableBookmarkNodeWithLabel(@"Folder 2")] + performAction:grey_tap()]; + [[EarlGrey + selectElementWithMatcher:TappableBookmarkNodeWithLabel(@"Folder 3")] + performAction:grey_tap()]; + + // Search and go to folder 1.1. + [[EarlGrey selectElementWithMatcher:SearchIconButton()] + performAction:grey_typeText(@"Folder 1.1")]; + [[EarlGrey + selectElementWithMatcher:TappableBookmarkNodeWithLabel(@"Folder 1.1")] + performAction:grey_tap()]; + + // Go back and verify we are in MobileBooknarks. (i.e. not back to Folder 2) + [[EarlGrey selectElementWithMatcher:NavigateBackButtonTo(@"Mobile Bookmarks")] + performAction:grey_tap()]; + + // Search and go to Folder 2. + [[EarlGrey selectElementWithMatcher:SearchIconButton()] + performAction:grey_typeText(@"Folder 2")]; + [[EarlGrey + selectElementWithMatcher:TappableBookmarkNodeWithLabel(@"Folder 2")] + performAction:grey_tap()]; + + // Go back and verify we are in Folder 1. (i.e. not back to Mobile Bookmarks) + [[EarlGrey selectElementWithMatcher:NavigateBackButtonTo(@"Folder 1")] + performAction:grey_tap()]; +} + @end
diff --git a/media/blink/webmediaplayer_impl.cc b/media/blink/webmediaplayer_impl.cc index 253f3fd..c6d0d94 100644 --- a/media/blink/webmediaplayer_impl.cc +++ b/media/blink/webmediaplayer_impl.cc
@@ -1131,10 +1131,12 @@ gfx::Rect gfx_rect(rect); Context3D context_3d; + gpu::ContextSupport* context_support = nullptr; if (video_frame.get() && video_frame->HasTextures()) { if (context_provider_) { context_3d = Context3D(context_provider_->ContextGL(), context_provider_->GrContext()); + context_support = context_provider_->ContextSupport(); } if (!context_3d.gl) return; // Unable to get/create a shared main thread context. @@ -1152,7 +1154,8 @@ } video_renderer_.Paint( video_frame, canvas, gfx::RectF(gfx_rect), flags, - pipeline_metadata_.video_decoder_config.video_rotation(), context_3d); + pipeline_metadata_.video_decoder_config.video_rotation(), context_3d, + context_support); } bool WebMediaPlayerImpl::DidGetOpaqueResponseFromServiceWorker() const { @@ -1238,13 +1241,15 @@ } Context3D context_3d; + gpu::ContextSupport* context_support = nullptr; if (context_provider_) { context_3d = Context3D(context_provider_->ContextGL(), context_provider_->GrContext()); + context_support = context_provider_->ContextSupport(); } return video_renderer_.CopyVideoFrameTexturesToGLTexture( - context_3d, gl, video_frame.get(), target, texture, internal_format, - format, type, level, premultiply_alpha, flip_y); + context_3d, context_support, gl, video_frame.get(), target, texture, + internal_format, format, type, level, premultiply_alpha, flip_y); } // static
diff --git a/media/gpu/windows/d3d11_video_decoder.cc b/media/gpu/windows/d3d11_video_decoder.cc index 1894ca4..8c3d681 100644 --- a/media/gpu/windows/d3d11_video_decoder.cc +++ b/media/gpu/windows/d3d11_video_decoder.cc
@@ -106,7 +106,9 @@ Microsoft::WRL::ComPtr<ID3D11VideoDecoder> video_decoder) { if (isVP9(config)) { accelerated_video_decoder_ = - std::make_unique<VP9Decoder>(std::make_unique<D3D11VP9Accelerator>()); + std::make_unique<VP9Decoder>(std::make_unique<D3D11VP9Accelerator>( + this, media_log_.get(), video_decoder, video_device_, + video_context_)); return; }
diff --git a/media/gpu/windows/d3d11_vp9_accelerator.cc b/media/gpu/windows/d3d11_vp9_accelerator.cc index e910c50..52ee2a1 100644 --- a/media/gpu/windows/d3d11_vp9_accelerator.cc +++ b/media/gpu/windows/d3d11_vp9_accelerator.cc
@@ -4,18 +4,303 @@ #include "media/gpu/windows/d3d11_vp9_accelerator.h" +#include <windows.h> +#include <string> +#include <utility> + +#include "base/memory/ptr_util.h" +#include "media/gpu/windows/d3d11_vp9_picture.h" + namespace media { -D3D11VP9Accelerator::D3D11VP9Accelerator() { - // Pass -} +#define RECORD_FAILURE(expr_name, expr_value) \ + do { \ + media_log_->AddEvent(media_log_->CreateStringEvent( \ + MediaLogEvent::MEDIA_ERROR_LOG_ENTRY, "error", \ + std::string("DX11VP9Failure(") + expr_name + \ + ")=" + std::to_string(expr_value))); \ + } while (0) -D3D11VP9Accelerator::~D3D11VP9Accelerator() { - // Pass -} +#define RETURN_ON_HR_FAILURE(expr_name, expr) \ + do { \ + HRESULT expr_value = (expr); \ + if (FAILED(expr_value)) { \ + RECORD_FAILURE(#expr_name, expr_value); \ + return false; \ + } \ + } while (0) + +D3D11VP9Accelerator::D3D11VP9Accelerator( + D3D11VideoDecoderClient* client, + MediaLog* media_log, + Microsoft::WRL::ComPtr<ID3D11VideoDecoder> video_decoder, + Microsoft::WRL::ComPtr<ID3D11VideoDevice> video_device, + Microsoft::WRL::ComPtr<ID3D11VideoContext> video_context) + : client_(client), + media_log_(media_log), + status_feedback_(0), + video_decoder_(std::move(video_decoder)), + video_device_(std::move(video_device)), + video_context_(std::move(video_context)) {} + +D3D11VP9Accelerator::~D3D11VP9Accelerator() {} scoped_refptr<VP9Picture> D3D11VP9Accelerator::CreateVP9Picture() { - return nullptr; + D3D11PictureBuffer* picture_buffer = client_->GetPicture(); + if (!picture_buffer) + return nullptr; + return base::MakeRefCounted<D3D11VP9Picture>(picture_buffer); +} + +bool D3D11VP9Accelerator::BeginFrame(D3D11VP9Picture* pic) { + Microsoft::WRL::ComPtr<ID3D11VideoDecoderOutputView> output_view; + D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC view_desc = { + .DecodeProfile = D3D11_DECODER_PROFILE_VP9_VLD_PROFILE0, + .ViewDimension = D3D11_VDOV_DIMENSION_TEXTURE2D, + .Texture2D = {.ArraySlice = (UINT)pic->level()}}; + + RETURN_ON_HR_FAILURE(CreateVideoDecoderOutputView, + video_device_->CreateVideoDecoderOutputView( + pic->picture_buffer()->texture().Get(), &view_desc, + output_view.GetAddressOf())); + + HRESULT hr; + do { + hr = video_context_->DecoderBeginFrame(video_decoder_.Get(), + output_view.Get(), 0, nullptr); + } while (hr == E_PENDING || hr == D3DERR_WASSTILLDRAWING); + + if (FAILED(hr)) { + RECORD_FAILURE("DecoderBeginFrame", hr); + return false; + } + + return true; +} + +void D3D11VP9Accelerator::CopyFrameParams( + const scoped_refptr<D3D11VP9Picture>& pic, + DXVA_PicParams_VP9* pic_params) { +#define SET_PARAM(a, b) pic_params->a = pic->frame_hdr->b +#define COPY_PARAM(a) SET_PARAM(a, a) + + COPY_PARAM(profile); + COPY_PARAM(show_frame); + COPY_PARAM(error_resilient_mode); + COPY_PARAM(refresh_frame_context); + COPY_PARAM(frame_parallel_decoding_mode); + COPY_PARAM(intra_only); + COPY_PARAM(frame_context_idx); + COPY_PARAM(allow_high_precision_mv); + COPY_PARAM(refresh_frame_context); + COPY_PARAM(frame_parallel_decoding_mode); + COPY_PARAM(intra_only); + COPY_PARAM(frame_context_idx); + COPY_PARAM(allow_high_precision_mv); + + // extra_plane, BitDepthMinus8Luma, and BitDepthMinus8Chroma are initialized + // at 0 already. + + pic_params->CurrPic.Index7Bits = pic->level(); + pic_params->frame_type = !pic->frame_hdr->IsKeyframe(); + pic_params->subsampling_x = pic->frame_hdr->subsampling_x == 1; + pic_params->subsampling_y = pic->frame_hdr->subsampling_y == 1; + + SET_PARAM(width, frame_width); + SET_PARAM(height, frame_height); + SET_PARAM(interp_filter, interpolation_filter); + SET_PARAM(log2_tile_cols, tile_cols_log2); + SET_PARAM(log2_tile_rows, tile_rows_log2); +#undef COPY_PARAM +#undef SET_PARAM +} + +void D3D11VP9Accelerator::CopyReferenceFrames( + const scoped_refptr<D3D11VP9Picture>& pic, + DXVA_PicParams_VP9* pic_params, + const std::vector<scoped_refptr<VP9Picture>>& reference_pictures) { + D3D11_TEXTURE2D_DESC texture_descriptor; + pic->picture_buffer()->texture()->GetDesc(&texture_descriptor); + + for (size_t i = 0; i < base::size(pic_params->ref_frame_map); i++) { + if (i < reference_pictures.size() && reference_pictures[i].get()) { + scoped_refptr<D3D11VP9Picture> our_ref_pic( + static_cast<D3D11VP9Picture*>(reference_pictures[i].get())); + pic_params->ref_frame_map[i].Index7Bits = our_ref_pic->level(); + pic_params->ref_frame_coded_width[i] = texture_descriptor.Width; + pic_params->ref_frame_coded_height[i] = texture_descriptor.Height; + } else { + pic_params->ref_frame_map[i].bPicEntry = 0xff; + pic_params->ref_frame_coded_width[i] = 0; + pic_params->ref_frame_coded_height[i] = 0; + } + } +} + +void D3D11VP9Accelerator::CopyFrameRefs( + DXVA_PicParams_VP9* pic_params, + const scoped_refptr<D3D11VP9Picture>& pic) { + for (size_t i = 0; i < base::size(pic_params->frame_refs); i++) { + pic_params->frame_refs[i] = + pic_params->ref_frame_map[pic->frame_hdr->ref_frame_idx[i]]; + } + + for (size_t i = 0; i < base::size(pic_params->ref_frame_sign_bias); i++) { + pic_params->ref_frame_sign_bias[i] = pic->frame_hdr->ref_frame_sign_bias[i]; + } +} + +void D3D11VP9Accelerator::CopyLoopFilterParams( + DXVA_PicParams_VP9* pic_params, + const Vp9LoopFilterParams& loop_filter_params) { +#define SET_PARAM(a, b) pic_params->a = loop_filter_params.b + SET_PARAM(filter_level, level); + SET_PARAM(sharpness_level, sharpness); + SET_PARAM(mode_ref_delta_enabled, delta_enabled); + SET_PARAM(mode_ref_delta_update, delta_update); +#undef SET_PARAM + + // base::size(...) doesn't work well in an array initializer. + DCHECK_EQ(4lu, base::size(pic_params->ref_deltas)); + int ref_deltas[4] = {0}; + for (size_t i = 0; i < base::size(pic_params->ref_deltas); i++) { + if (loop_filter_params.update_ref_deltas[i]) + ref_deltas[i] = loop_filter_params.ref_deltas[i]; + pic_params->ref_deltas[i] = ref_deltas[i]; + } + + int mode_deltas[2] = {0}; + DCHECK_EQ(2lu, base::size(pic_params->mode_deltas)); + for (size_t i = 0; i < base::size(pic_params->mode_deltas); i++) { + if (loop_filter_params.update_mode_deltas[i]) + mode_deltas[i] = loop_filter_params.mode_deltas[i]; + pic_params->mode_deltas[i] = mode_deltas[i]; + } +} + +void D3D11VP9Accelerator::CopyQuantParams( + DXVA_PicParams_VP9* pic_params, + const scoped_refptr<D3D11VP9Picture>& pic) { +#define SET_PARAM(a, b) pic_params->a = pic->frame_hdr->quant_params.b + SET_PARAM(base_qindex, base_q_idx); + SET_PARAM(y_dc_delta_q, delta_q_y_dc); + SET_PARAM(uv_dc_delta_q, delta_q_uv_dc); + SET_PARAM(uv_ac_delta_q, delta_q_uv_ac); +#undef SET_PARAM +} + +void D3D11VP9Accelerator::CopySegmentationParams( + DXVA_PicParams_VP9* pic_params, + const Vp9SegmentationParams& segmentation_params) { +#define SET_PARAM(a, b) pic_params->stVP9Segments.a = segmentation_params.b +#define COPY_PARAM(a) SET_PARAM(a, a) + COPY_PARAM(enabled); + COPY_PARAM(update_map); + COPY_PARAM(temporal_update); + SET_PARAM(abs_delta, abs_or_delta_update); + + for (size_t i = 0; i < base::size(segmentation_params.tree_probs); i++) { + COPY_PARAM(tree_probs[i]); + } + + for (size_t i = 0; i < base::size(segmentation_params.pred_probs); i++) { + COPY_PARAM(pred_probs[i]); + } + + for (size_t i = 0; i < 8; i++) { + for (size_t j = 0; j < 4; j++) { + COPY_PARAM(feature_data[i][j]); + if (segmentation_params.feature_enabled[i][j]) + pic_params->stVP9Segments.feature_mask[i] |= (1 << j); + } + } +#undef COPY_PARAM +#undef SET_PARAM +} + +void D3D11VP9Accelerator::CopyHeaderSizeAndID( + DXVA_PicParams_VP9* pic_params, + const scoped_refptr<D3D11VP9Picture>& pic) { + pic_params->uncompressed_header_size_byte_aligned = + static_cast<USHORT>(pic->frame_hdr->uncompressed_header_size); + pic_params->first_partition_size = + static_cast<USHORT>(pic->frame_hdr->header_size_in_bytes); + + pic_params->StatusReportFeedbackNumber = status_feedback_++; +} + +bool D3D11VP9Accelerator::SubmitDecoderBuffer( + const DXVA_PicParams_VP9& pic_params, + const scoped_refptr<D3D11VP9Picture>& pic) { +#define GET_BUFFER(type) \ + RETURN_ON_HR_FAILURE(GetDecoderBuffer, \ + video_context_->GetDecoderBuffer( \ + video_decoder_.Get(), type, &buffer_size, &buffer)) +#define RELEASE_BUFFER(type) \ + RETURN_ON_HR_FAILURE( \ + ReleaseDecoderBuffer, \ + video_context_->ReleaseDecoderBuffer(video_decoder_.Get(), type)) + + UINT buffer_size; + void* buffer; + + GET_BUFFER(D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS); + memcpy(buffer, &pic_params, sizeof(pic_params)); + RELEASE_BUFFER(D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS); + + size_t buffer_offset = 0; + while (buffer_offset < pic->frame_hdr->frame_size) { + GET_BUFFER(D3D11_VIDEO_DECODER_BUFFER_BITSTREAM); + size_t copy_size = pic->frame_hdr->frame_size - buffer_offset; + bool contains_end = true; + if (copy_size > buffer_size) { + copy_size = buffer_size; + contains_end = false; + } + memcpy(buffer, pic->frame_hdr->data + buffer_offset, copy_size); + RELEASE_BUFFER(D3D11_VIDEO_DECODER_BUFFER_BITSTREAM); + + DXVA_Slice_VPx_Short slice_info; + + GET_BUFFER(D3D11_VIDEO_DECODER_BUFFER_SLICE_CONTROL); + slice_info.BSNALunitDataLocation = 0; + slice_info.SliceBytesInBuffer = (UINT)copy_size; + + // See the DXVA header specification for values of wBadSliceChopping: + // https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/dxva/ns-dxva-_dxva_sliceinfo#wBadSliceChopping + if (buffer_offset == 0 && contains_end) + slice_info.wBadSliceChopping = 0; + else if (buffer_offset == 0 && !contains_end) + slice_info.wBadSliceChopping = 1; + else if (buffer_offset != 0 && contains_end) + slice_info.wBadSliceChopping = 2; + else if (buffer_offset != 0 && !contains_end) + slice_info.wBadSliceChopping = 3; + + memcpy(buffer, &slice_info, sizeof(slice_info)); + RELEASE_BUFFER(D3D11_VIDEO_DECODER_BUFFER_SLICE_CONTROL); + + constexpr int buffers_count = 3; + D3D11_VIDEO_DECODER_BUFFER_DESC buffers[buffers_count] = {}; + buffers[0].BufferType = D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS; + buffers[0].DataOffset = 0; + buffers[0].DataSize = sizeof(pic_params); + buffers[1].BufferType = D3D11_VIDEO_DECODER_BUFFER_SLICE_CONTROL; + buffers[1].DataOffset = 0; + buffers[1].DataSize = sizeof(slice_info); + buffers[2].BufferType = D3D11_VIDEO_DECODER_BUFFER_BITSTREAM; + buffers[2].DataOffset = 0; + buffers[2].DataSize = copy_size; + + RETURN_ON_HR_FAILURE(SubmitDecoderBuffers, + video_context_->SubmitDecoderBuffers( + video_decoder_.Get(), buffers_count, buffers)); + buffer_offset += copy_size; + } + + return true; +#undef GET_BUFFER +#undef RELEASE_BUFFER } bool D3D11VP9Accelerator::SubmitDecode( @@ -24,12 +309,36 @@ const Vp9LoopFilterParams& loop_filter_params, const std::vector<scoped_refptr<VP9Picture>>& reference_pictures, const base::Closure& on_finished_cb) { - return false; + scoped_refptr<D3D11VP9Picture> pic( + static_cast<D3D11VP9Picture*>(picture.get())); + + if (!BeginFrame(pic.get())) + return false; + + DXVA_PicParams_VP9 pic_params = {}; + CopyFrameParams(pic, &pic_params); + CopyReferenceFrames(pic, &pic_params, reference_pictures); + CopyFrameRefs(&pic_params, pic); + CopyLoopFilterParams(&pic_params, loop_filter_params); + CopyQuantParams(&pic_params, pic); + CopySegmentationParams(&pic_params, segmentation_params); + CopyHeaderSizeAndID(&pic_params, pic); + + if (!SubmitDecoderBuffer(pic_params, pic)) + return false; + + RETURN_ON_HR_FAILURE(DecoderEndFrame, + video_context_->DecoderEndFrame(video_decoder_.Get())); + if (on_finished_cb) + on_finished_cb.Run(); + return true; } bool D3D11VP9Accelerator::OutputPicture( const scoped_refptr<VP9Picture>& picture) { - return false; + D3D11VP9Picture* pic = static_cast<D3D11VP9Picture*>(picture.get()); + client_->OutputResult(picture.get(), pic->picture_buffer()); + return true; } bool D3D11VP9Accelerator::IsFrameContextRequired() const {
diff --git a/media/gpu/windows/d3d11_vp9_accelerator.h b/media/gpu/windows/d3d11_vp9_accelerator.h index c6e4bda..d3bf967 100644 --- a/media/gpu/windows/d3d11_vp9_accelerator.h +++ b/media/gpu/windows/d3d11_vp9_accelerator.h
@@ -5,17 +5,30 @@ #ifndef MEDIA_GPU_WINDOWS_D3D11_VP9_ACCELERATOR_H_ #define MEDIA_GPU_WINDOWS_D3D11_VP9_ACCELERATOR_H_ +#include <d3d11_1.h> +#include <d3d9.h> +#include <windows.h> +#include <wrl/client.h> + +#include "media/base/media_log.h" #include "media/gpu/vp9_decoder.h" +#include "media/gpu/windows/d3d11_video_decoder_client.h" +#include "media/gpu/windows/d3d11_vp9_picture.h" namespace media { class D3D11VP9Accelerator : public VP9Decoder::VP9Accelerator { public: - D3D11VP9Accelerator(); + D3D11VP9Accelerator(D3D11VideoDecoderClient* client, + MediaLog* media_log, + Microsoft::WRL::ComPtr<ID3D11VideoDecoder> video_decoder, + Microsoft::WRL::ComPtr<ID3D11VideoDevice> video_device, + Microsoft::WRL::ComPtr<ID3D11VideoContext> video_context); ~D3D11VP9Accelerator() override; scoped_refptr<VP9Picture> CreateVP9Picture() override; + // TODO(crbug/890054): Use constref instead of scoped_refptr. bool SubmitDecode( const scoped_refptr<VP9Picture>& picture, const Vp9SegmentationParams& segmentation_params, @@ -31,6 +44,36 @@ Vp9FrameContext* frame_context) override; private: + // Helper methods for SubmitDecode + bool BeginFrame(D3D11VP9Picture* pic); + + // TODO(crbug/890054): Use constref instead of scoped_refptr. + void CopyFrameParams(const scoped_refptr<D3D11VP9Picture>& pic, + DXVA_PicParams_VP9* pic_params); + void CopyReferenceFrames( + const scoped_refptr<D3D11VP9Picture>& pic, + DXVA_PicParams_VP9* pic_params, + const std::vector<scoped_refptr<VP9Picture>>& reference_pictures); + void CopyFrameRefs(DXVA_PicParams_VP9* pic_params, + const scoped_refptr<D3D11VP9Picture>& picture); + void CopyLoopFilterParams(DXVA_PicParams_VP9* pic_params, + const Vp9LoopFilterParams& loop_filter_params); + void CopyQuantParams(DXVA_PicParams_VP9* pic_params, + const scoped_refptr<D3D11VP9Picture>& pic); + void CopySegmentationParams(DXVA_PicParams_VP9* pic_params, + const Vp9SegmentationParams& segmentation_params); + void CopyHeaderSizeAndID(DXVA_PicParams_VP9* pic_params, + const scoped_refptr<D3D11VP9Picture>& pic); + bool SubmitDecoderBuffer(const DXVA_PicParams_VP9& pic_params, + const scoped_refptr<D3D11VP9Picture>& pic); + + D3D11VideoDecoderClient* client_; + MediaLog* const media_log_; + UINT status_feedback_; + Microsoft::WRL::ComPtr<ID3D11VideoDecoder> video_decoder_; + Microsoft::WRL::ComPtr<ID3D11VideoDevice> video_device_; + Microsoft::WRL::ComPtr<ID3D11VideoContext> video_context_; + DISALLOW_COPY_AND_ASSIGN(D3D11VP9Accelerator); };
diff --git a/media/gpu/windows/d3d11_vp9_picture.h b/media/gpu/windows/d3d11_vp9_picture.h index e4f3afc2..1d2f407 100644 --- a/media/gpu/windows/d3d11_vp9_picture.h +++ b/media/gpu/windows/d3d11_vp9_picture.h
@@ -17,6 +17,10 @@ public: explicit D3D11VP9Picture(D3D11PictureBuffer* picture_buffer); + D3D11PictureBuffer* picture_buffer() const { return picture_buffer_; }; + + size_t level() const { return level_; }; + protected: ~D3D11VP9Picture() override;
diff --git a/media/renderers/paint_canvas_video_renderer.cc b/media/renderers/paint_canvas_video_renderer.cc index 8d12b5f..cdaac96 100644 --- a/media/renderers/paint_canvas_video_renderer.cc +++ b/media/renderers/paint_canvas_video_renderer.cc
@@ -14,6 +14,7 @@ #include "cc/paint/paint_image.h" #include "cc/paint/paint_image_builder.h" #include "gpu/GLES2/gl2extchromium.h" +#include "gpu/command_buffer/client/context_support.h" #include "gpu/command_buffer/client/gles2_interface.h" #include "gpu/command_buffer/common/capabilities.h" #include "gpu/command_buffer/common/mailbox_holder.h" @@ -275,6 +276,34 @@ } } +void OnQueryDone(scoped_refptr<VideoFrame> video_frame, + gpu::gles2::GLES2Interface* gl, + unsigned query_id) { + gl->DeleteQueriesEXT(1, &query_id); + // |video_frame| is dropped here. +} + +void SynchronizeVideoFrameRead(scoped_refptr<VideoFrame> video_frame, + gpu::gles2::GLES2Interface* gl, + gpu::ContextSupport* context_support) { + DCHECK(gl); + SyncTokenClientImpl client(gl); + video_frame->UpdateReleaseSyncToken(&client); + + if (video_frame->metadata()->IsTrue( + VideoFrameMetadata::READ_LOCK_FENCES_ENABLED)) { + // |video_frame| must be kept alive during read operations. + DCHECK(context_support); + unsigned query_id = 0; + gl->GenQueriesEXT(1, &query_id); + DCHECK(query_id); + gl->BeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM, query_id); + gl->EndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM); + context_support->SignalQuery( + query_id, base::BindOnce(&OnQueryDone, video_frame, gl, query_id)); + } +} + } // anonymous namespace // Generates an RGB image from a VideoFrame. Convert YUV to RGB plain on GPU. @@ -416,7 +445,8 @@ const gfx::RectF& dest_rect, cc::PaintFlags& flags, VideoRotation video_rotation, - const Context3D& context_3d) { + const Context3D& context_3d, + gpu::ContextSupport* context_support) { DCHECK(thread_checker_.CalledOnValidThread()); if (flags.getAlpha() == 0) { return; @@ -509,22 +539,23 @@ canvas->flush(); if (video_frame->HasTextures()) { - DCHECK(gl); - SyncTokenClientImpl client(gl); - video_frame->UpdateReleaseSyncToken(&client); + // Synchronize |video_frame| with the read operations in UpdateLastImage(), + // which are triggered by canvas->flush(). + SynchronizeVideoFrameRead(video_frame, gl, context_support); } } void PaintCanvasVideoRenderer::Copy( const scoped_refptr<VideoFrame>& video_frame, cc::PaintCanvas* canvas, - const Context3D& context_3d) { + const Context3D& context_3d, + gpu::ContextSupport* context_support) { cc::PaintFlags flags; flags.setBlendMode(SkBlendMode::kSrc); flags.setFilterQuality(kLow_SkFilterQuality); Paint(video_frame, canvas, gfx::RectF(gfx::SizeF(video_frame->visible_rect().size())), flags, - media::VIDEO_ROTATION_0, context_3d); + media::VIDEO_ROTATION_0, context_3d, context_support); } namespace { @@ -901,14 +932,14 @@ target, texture, internal_format, format, type, level, premultiply_alpha, flip_y); gl->DeleteTextures(1, &source_texture); - gl->Flush(); - - SyncTokenClientImpl client(gl); - video_frame->UpdateReleaseSyncToken(&client); + gl->ShallowFlushCHROMIUM(); + // The caller must call SynchronizeVideoFrameRead() after this operation, but + // we can't do that because we don't have the ContextSupport. } bool PaintCanvasVideoRenderer::CopyVideoFrameTexturesToGLTexture( const Context3D& context_3d, + gpu::ContextSupport* context_support, gpu::gles2::GLES2Interface* destination_gl, const scoped_refptr<VideoFrame>& video_frame, unsigned int target, @@ -922,7 +953,9 @@ DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(video_frame); DCHECK(video_frame->HasTextures()); - if (video_frame->NumTextures() > 1) { + if (video_frame->NumTextures() > 1 || + video_frame->metadata()->IsTrue( + VideoFrameMetadata::READ_LOCK_FENCES_ENABLED)) { if (!context_3d.gr_context) return false; if (!UpdateLastImage(video_frame, context_3d)) @@ -936,7 +969,11 @@ if (!backend_texture.getGLTextureInfo(&texture_info)) return false; + // Synchronize |video_frame| with the read operations in UpdateLastImage(), + // which are triggered by getBackendTexture(). gpu::gles2::GLES2Interface* canvas_gl = context_3d.gl; + SynchronizeVideoFrameRead(video_frame, canvas_gl, context_support); + gpu::MailboxHolder mailbox_holder; mailbox_holder.texture_target = texture_info.fTarget; canvas_gl->ProduceTextureDirectCHROMIUM(texture_info.fID, @@ -964,13 +1001,11 @@ gpu::SyncToken dest_sync_token; destination_gl->GenUnverifiedSyncTokenCHROMIUM(dest_sync_token.GetData()); canvas_gl->WaitSyncTokenCHROMIUM(dest_sync_token.GetConstData()); - - SyncTokenClientImpl client(canvas_gl); - video_frame->UpdateReleaseSyncToken(&client); } else { CopyVideoFrameSingleTextureToGLTexture( destination_gl, video_frame.get(), target, texture, internal_format, format, type, level, premultiply_alpha, flip_y); + SynchronizeVideoFrameRead(video_frame, destination_gl, nullptr); } return true; @@ -1208,8 +1243,9 @@ return false; last_id_ = video_frame->unique_id(); } + + DCHECK(last_image_); last_image_deleting_timer_.Reset(); - DCHECK(!!last_image_); return true; }
diff --git a/media/renderers/paint_canvas_video_renderer.h b/media/renderers/paint_canvas_video_renderer.h index d732111..d4752f3 100644 --- a/media/renderers/paint_canvas_video_renderer.h +++ b/media/renderers/paint_canvas_video_renderer.h
@@ -29,6 +29,7 @@ namespace gpu { struct Capabilities; +class ContextSupport; } namespace media { @@ -39,25 +40,29 @@ PaintCanvasVideoRenderer(); ~PaintCanvasVideoRenderer(); - // Paints |video_frame| on |canvas|, scaling and rotating the result to fit - // dimensions specified by |dest_rect|. - // If the format of |video_frame| is PIXEL_FORMAT_NATIVE_TEXTURE, |context_3d| - // must be provided. + // Paints |video_frame| translated and scaled to |dest_rect| on |canvas|. // - // Black will be painted on |canvas| if |video_frame| is null. + // If the format of |video_frame| is PIXEL_FORMAT_NATIVE_TEXTURE, |context_3d| + // and |context_support| must be provided. + // + // If |video_frame| is nullptr or an unsupported format, |dest_rect| will be + // painted black. void Paint(const scoped_refptr<VideoFrame>& video_frame, cc::PaintCanvas* canvas, const gfx::RectF& dest_rect, cc::PaintFlags& flags, VideoRotation video_rotation, - const Context3D& context_3d); + const Context3D& context_3d, + gpu::ContextSupport* context_support); - // Copy |video_frame| on |canvas|. + // Paints |video_frame| scaled to its visible size on |canvas|. + // // If the format of |video_frame| is PIXEL_FORMAT_NATIVE_TEXTURE, |context_3d| - // must be provided. + // and |context_support| must be provided. void Copy(const scoped_refptr<VideoFrame>& video_frame, cc::PaintCanvas* canvas, - const Context3D& context_3d); + const Context3D& context_3d, + gpu::ContextSupport* context_support); // Convert the contents of |video_frame| to raw RGB pixels. |rgb_pixels| // should point into a buffer large enough to hold as many 32 bit RGBA pixels @@ -82,15 +87,12 @@ bool premultiply_alpha, bool flip_y); - // Copy the contents of texture of |video_frame| to texture |texture| in - // context |destination_gl|. - // |level|, |internal_format|, |type| specify target texture |texture|. + // Copy the contents of |video_frame| to |texture| of |destination_gl|. + // // The format of |video_frame| must be VideoFrame::NATIVE_TEXTURE. - // |context_3d| has a GrContext that may be used during the copy. - // CorrectLastImageDimensions() ensures that the source texture will be - // cropped to |visible_rect|. Returns true on success. bool CopyVideoFrameTexturesToGLTexture( const Context3D& context_3d, + gpu::ContextSupport* context_support, gpu::gles2::GLES2Interface* destination_gl, const scoped_refptr<VideoFrame>& video_frame, unsigned int target, @@ -168,8 +170,6 @@ // never be painted again, so we can release the resource. void ResetCache(); - void CorrectLastImageDimensions(const SkIRect& visible_rect); - // Used for unit test. SkISize LastImageDimensionsForTesting(); @@ -179,6 +179,8 @@ bool UpdateLastImage(const scoped_refptr<VideoFrame>& video_frame, const Context3D& context_3d); + void CorrectLastImageDimensions(const SkIRect& visible_rect); + // Last image used to draw to the canvas. cc::PaintImage last_image_;
diff --git a/media/renderers/paint_canvas_video_renderer_unittest.cc b/media/renderers/paint_canvas_video_renderer_unittest.cc index 3bca993..bd321305 100644 --- a/media/renderers/paint_canvas_video_renderer_unittest.cc +++ b/media/renderers/paint_canvas_video_renderer_unittest.cc
@@ -225,7 +225,7 @@ cc::PaintFlags flags; flags.setFilterQuality(kLow_SkFilterQuality); renderer_.Paint(nullptr, canvas, kNaturalRect, flags, VIDEO_ROTATION_0, - Context3D()); + Context3D(), nullptr); } void PaintCanvasVideoRendererTest::Paint( @@ -260,13 +260,13 @@ flags.setBlendMode(mode); flags.setFilterQuality(kLow_SkFilterQuality); renderer_.Paint(video_frame, canvas, dest_rect, flags, video_rotation, - Context3D()); + Context3D(), nullptr); } void PaintCanvasVideoRendererTest::Copy( const scoped_refptr<VideoFrame>& video_frame, cc::PaintCanvas* canvas) { - renderer_.Copy(video_frame, canvas, Context3D()); + renderer_.Copy(video_frame, canvas, Context3D(), nullptr); } TEST_F(PaintCanvasVideoRendererTest, NoFrame) { @@ -564,7 +564,7 @@ flags.setFilterQuality(kNone_SkFilterQuality); renderer_.Paint(video_frame, &canvas, gfx::RectF(bitmap.width(), bitmap.height()), flags, - VIDEO_ROTATION_0, Context3D()); + VIDEO_ROTATION_0, Context3D(), nullptr); for (int j = 0; j < bitmap.height(); j++) { for (int i = 0; i < bitmap.width(); i++) { const int value = i + j * bitmap.width(); @@ -657,43 +657,32 @@ cc::PaintFlags flags; flags.setFilterQuality(kLow_SkFilterQuality); renderer_.Paint(video_frame, &canvas, kNaturalRect, flags, VIDEO_ROTATION_90, - context_3d); + context_3d, nullptr); } void EmptyCallback(const gpu::SyncToken& sync_token) {} TEST_F(PaintCanvasVideoRendererTest, CorrectFrameSizeToVisibleRect) { - int fWidth{16}, fHeight{16}; + constexpr int fWidth{16}, fHeight{16}; SkImageInfo imInfo = SkImageInfo::MakeN32(fWidth, fHeight, kOpaque_SkAlphaType); - sk_sp<const GrGLInterface> glInterface(GrGLCreateNullInterface()); - sk_sp<GrContext> grContext = GrContext::MakeGL(std::move(glInterface)); + cc::SkiaPaintCanvas canvas(AllocBitmap(kWidth, kHeight)); - sk_sp<SkSurface> surface = - SkSurface::MakeRenderTarget(grContext.get(), SkBudgeted::kYes, imInfo); - cc::SkiaPaintCanvas canvas(surface->getCanvas()); - - TestGLES2Interface gles2; - Context3D context_3d(&gles2, grContext.get()); gfx::Size coded_size(fWidth, fHeight); gfx::Size visible_size(fWidth / 2, fHeight / 2); - gpu::MailboxHolder mailbox_holders[VideoFrame::kMaxPlanes]; - for (size_t i = 0; i < VideoFrame::kMaxPlanes; i++) { - mailbox_holders[i] = gpu::MailboxHolder( - gpu::Mailbox::Generate(), gpu::SyncToken(), GL_TEXTURE_RECTANGLE_ARB); - } + uint8_t memory[fWidth * fHeight * 2] = {0}; - auto video_frame = VideoFrame::WrapNativeTextures( - PIXEL_FORMAT_I420, mailbox_holders, base::Bind(EmptyCallback), coded_size, - gfx::Rect(visible_size), visible_size, + auto video_frame = media::VideoFrame::WrapExternalData( + media::PIXEL_FORMAT_Y16, coded_size, gfx::Rect(visible_size), + visible_size, &memory[0], fWidth * fHeight * 2, base::TimeDelta::FromMilliseconds(4)); gfx::RectF visible_rect(visible_size.width(), visible_size.height()); cc::PaintFlags flags; renderer_.Paint(video_frame, &canvas, visible_rect, flags, VIDEO_ROTATION_0, - context_3d); + Context3D(), nullptr); EXPECT_EQ(fWidth / 2, renderer_.LastImageDimensionsForTesting().width()); EXPECT_EQ(fWidth / 2, renderer_.LastImageDimensionsForTesting().height());
diff --git a/media/renderers/video_resource_updater.cc b/media/renderers/video_resource_updater.cc index 952c9a7..5b4abce 100644 --- a/media/renderers/video_resource_updater.cc +++ b/media/renderers/video_resource_updater.cc
@@ -866,7 +866,7 @@ // This is software path, so canvas and video_frame are always backed // by software. - video_renderer_->Copy(video_frame, &canvas, Context3D()); + video_renderer_->Copy(video_frame, &canvas, Context3D(), nullptr); } else { HardwarePlaneResource* hardware_resource = plane_resource->AsHardware(); size_t bytes_per_row = viz::ResourceSizes::CheckedWidthInBytes<size_t>(
diff --git a/mojo/public/cpp/system/data_pipe.h b/mojo/public/cpp/system/data_pipe.h index 30c7546..8e1e0b88 100644 --- a/mojo/public/cpp/system/data_pipe.h +++ b/mojo/public/cpp/system/data_pipe.h
@@ -150,7 +150,7 @@ MojoResult result = CreateDataPipe(nullptr, &producer_handle, &consumer_handle); ALLOW_UNUSED_LOCAL(result); - DCHECK_EQ(MOJO_RESULT_OK, result); + CHECK_EQ(MOJO_RESULT_OK, result); } inline DataPipe::DataPipe(uint32_t capacity_num_bytes) { @@ -163,14 +163,14 @@ MojoResult result = CreateDataPipe(&options, &producer_handle, &consumer_handle); ALLOW_UNUSED_LOCAL(result); - DCHECK_EQ(MOJO_RESULT_OK, result); + CHECK_EQ(MOJO_RESULT_OK, result); } inline DataPipe::DataPipe(const MojoCreateDataPipeOptions& options) { MojoResult result = CreateDataPipe(&options, &producer_handle, &consumer_handle); ALLOW_UNUSED_LOCAL(result); - DCHECK_EQ(MOJO_RESULT_OK, result); + CHECK_EQ(MOJO_RESULT_OK, result); } inline DataPipe::~DataPipe() {
diff --git a/net/BUILD.gn b/net/BUILD.gn index ea6c4c1..3991b98 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -1332,13 +1332,13 @@ "third_party/quic/core/frames/quic_blocked_frame.h", "third_party/quic/core/frames/quic_connection_close_frame.cc", "third_party/quic/core/frames/quic_connection_close_frame.h", - "third_party/quic/core/frames/quic_control_frame.h", "third_party/quic/core/frames/quic_crypto_frame.cc", "third_party/quic/core/frames/quic_crypto_frame.h", "third_party/quic/core/frames/quic_frame.cc", "third_party/quic/core/frames/quic_frame.h", "third_party/quic/core/frames/quic_goaway_frame.cc", "third_party/quic/core/frames/quic_goaway_frame.h", + "third_party/quic/core/frames/quic_inlined_frame.h", "third_party/quic/core/frames/quic_max_stream_id_frame.cc", "third_party/quic/core/frames/quic_max_stream_id_frame.h", "third_party/quic/core/frames/quic_message_frame.cc", @@ -1346,6 +1346,8 @@ "third_party/quic/core/frames/quic_mtu_discovery_frame.h", "third_party/quic/core/frames/quic_new_connection_id_frame.cc", "third_party/quic/core/frames/quic_new_connection_id_frame.h", + "third_party/quic/core/frames/quic_new_token_frame.cc", + "third_party/quic/core/frames/quic_new_token_frame.h", "third_party/quic/core/frames/quic_padding_frame.cc", "third_party/quic/core/frames/quic_padding_frame.h", "third_party/quic/core/frames/quic_path_challenge_frame.cc", @@ -1390,6 +1392,10 @@ "third_party/quic/core/qpack/qpack_decoder.h", "third_party/quic/core/qpack/qpack_encoder.cc", "third_party/quic/core/qpack/qpack_encoder.h", + "third_party/quic/core/qpack/qpack_encoder_stream_receiver.cc", + "third_party/quic/core/qpack/qpack_encoder_stream_receiver.h", + "third_party/quic/core/qpack/qpack_encoder_stream_sender.cc", + "third_party/quic/core/qpack/qpack_encoder_stream_sender.h", "third_party/quic/core/qpack/qpack_header_table.cc", "third_party/quic/core/qpack/qpack_header_table.h", "third_party/quic/core/quic_ack_listener_interface.cc", @@ -1534,8 +1540,6 @@ "third_party/quic/platform/api/quic_text_utils.h", "third_party/quic/platform/api/quic_url.cc", "third_party/quic/platform/api/quic_url.h", - "third_party/quic/platform/api/quic_url_utils.cc", - "third_party/quic/platform/api/quic_url_utils.h", "third_party/quic/platform/impl/quic_aligned_impl.h", "third_party/quic/platform/impl/quic_arraysize_impl.h", "third_party/quic/platform/impl/quic_bug_tracker_impl.h", @@ -1580,8 +1584,6 @@ "third_party/quic/platform/impl/quic_text_utils_impl.h", "third_party/quic/platform/impl/quic_url_impl.cc", "third_party/quic/platform/impl/quic_url_impl.h", - "third_party/quic/platform/impl/quic_url_utils_impl.cc", - "third_party/quic/platform/impl/quic_url_utils_impl.h", "third_party/quic/quartc/quartc_factory.cc", "third_party/quic/quartc/quartc_factory.h", "third_party/quic/quartc/quartc_packet_writer.cc", @@ -5010,6 +5012,8 @@ "third_party/quic/core/http/quic_headers_stream_test.cc", "third_party/quic/core/packet_number_indexed_queue_test.cc", "third_party/quic/core/qpack/qpack_decoder_test.cc", + "third_party/quic/core/qpack/qpack_encoder_stream_receiver_test.cc", + "third_party/quic/core/qpack/qpack_encoder_stream_sender_test.cc", "third_party/quic/core/qpack/qpack_encoder_test.cc", "third_party/quic/core/quic_alarm_test.cc", "third_party/quic/core/quic_arena_scoped_ptr_test.cc", @@ -5141,13 +5145,9 @@ "third_party/quic/platform/api/quic_reference_counted_test.cc", "third_party/quic/platform/api/quic_singleton_test.cc", "third_party/quic/platform/api/quic_str_cat_test.cc", - "third_party/quic/platform/api/quic_test_random.h", "third_party/quic/platform/api/quic_text_utils_test.cc", "third_party/quic/platform/api/quic_url_test.cc", "third_party/quic/platform/impl/quic_chromium_clock_test.cc", - "third_party/quic/platform/impl/quic_test_random_impl.cc", - "third_party/quic/platform/impl/quic_test_random_impl.h", - "third_party/quic/platform/impl/quic_url_utils_impl_test.cc", "third_party/quic/quartc/quartc_session_test.cc", "third_party/quic/quartc/quartc_stream_test.cc", "third_party/quic/quartc/simulated_packet_transport.cc",
diff --git a/net/quic/quic_chromium_client_session.cc b/net/quic/quic_chromium_client_session.cc index cafdd106..f4f63b5b 100644 --- a/net/quic/quic_chromium_client_session.cc +++ b/net/quic/quic_chromium_client_session.cc
@@ -1487,7 +1487,7 @@ if (GetNumOpenOutgoingStreams() > 0) { UMA_HISTOGRAM_BOOLEAN( "Net.QuicSession.TimedOutWithOpenStreams.HasUnackedPackets", - connection()->sent_packet_manager().HasUnackedPackets()); + connection()->sent_packet_manager().HasInFlightPackets()); UMA_HISTOGRAM_COUNTS_1M( "Net.QuicSession.TimedOutWithOpenStreams.ConsecutiveRTOCount", connection()->sent_packet_manager().GetConsecutiveRtoCount());
diff --git a/net/quic/quic_flags_list.h b/net/quic/quic_flags_list.h index 7e3dd62..fd34e51 100644 --- a/net/quic/quic_flags_list.h +++ b/net/quic/quic_flags_list.h
@@ -133,9 +133,6 @@ // If true, enable experiment for testing PCC congestion-control. QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_pcc3, false) -// If true, fix potential crashes in QuicSession::RetransmitLostData. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_fix_retransmit_lost_data, true) - // When true, ensure BBR allows at least one MSS to be sent in response to an // ACK in packet conservation. QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_bbr_one_mss_conservation, false) @@ -241,7 +238,7 @@ true) // This flag fixes a bug where a zombie stream cannot be correctly reset. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_fix_reset_zombie_streams, false) +QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_fix_reset_zombie_streams, true) // When true, fix initialization and updating of // |time_of_first_packet_sent_after_receiving_| in QuicConnection. @@ -266,3 +263,10 @@ // When the STMP connection option is sent by the client, timestamps in the QUIC // ACK frame are sent and processed. QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_send_timestamps, false) + +// If true, use a common stream ID limit checking method. +QUIC_FLAG(bool, FLAGS_quic_use_common_stream_check, false) + +// When true, don't arm the path degrading alarm on the server side and stop +// using HasUnackedPackets to decide when to arm it. +QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_fix_path_degrading_alarm, false)
diff --git a/net/spdy/spdy_http_stream.cc b/net/spdy/spdy_http_stream.cc index 263a9f0..decc783 100644 --- a/net/spdy/spdy_http_stream.cc +++ b/net/spdy/spdy_http_stream.cc
@@ -142,9 +142,8 @@ request_info_ = request_info; if (pushed_stream_id_ != kNoPushedStreamFound) { - int error = - spdy_session_->GetPushedStream(request_info_->url, pushed_stream_id_, - priority, &stream_, stream_net_log); + int error = spdy_session_->GetPushedStream( + request_info_->url, pushed_stream_id_, priority, &stream_); if (error != OK) return error;
diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc index 5f38d336..a656aae 100644 --- a/net/spdy/spdy_session.cc +++ b/net/spdy/spdy_session.cc
@@ -920,8 +920,7 @@ int SpdySession::GetPushedStream(const GURL& url, spdy::SpdyStreamId pushed_stream_id, RequestPriority priority, - SpdyStream** stream, - const NetLogWithSource& stream_net_log) { + SpdyStream** stream) { CHECK(!in_io_loop_); // |pushed_stream_id| must be valid. DCHECK_NE(pushed_stream_id, kNoPushedStreamFound); @@ -930,7 +929,6 @@ pool_->push_promise_index()->FindStream(url, this)); if (availability_state_ == STATE_DRAINING) { - *stream = nullptr; return ERR_CONNECTION_CLOSED; }
diff --git a/net/spdy/spdy_session.h b/net/spdy/spdy_session.h index 97f7f58..537f7b5 100644 --- a/net/spdy/spdy_session.h +++ b/net/spdy/spdy_session.h
@@ -317,31 +317,21 @@ const SpdySessionKey& spdy_session_key() const { return spdy_session_key_; } - // Get a pushed stream for a given |url|. If the server initiates a - // stream, it might already exist for a given path. The server - // might also not have initiated the stream yet, but indicated it - // will via X-Associated-Content. Returns OK if a stream was found - // and put into |spdy_stream|, or if one was not found but it is - // okay to create a new stream (in which case |spdy_stream| is - // reset). Returns an error (not ERR_IO_PENDING) otherwise, and - // resets |spdy_stream|. + + // Get a pushed stream for a given |url| with stream ID |pushed_stream_id|. + // The caller must have already claimed the stream from Http2PushPromiseIndex. + // |pushed_stream_id| must not be kNoPushedStreamFound. // - // If |pushed_stream_id != kNoPushedStreamFound|, then the pushed stream with - // pushed_stream_id is used. An error is returned if that stream is not - // available. - // - // If |pushed_stream_id == kNoPushedStreamFound|, then any matching pushed - // stream that has not been claimed by another request can be used. This can - // happen, for example, with http scheme pushed streams, or if the pushed - // stream was received from the server in the meanwhile. - // - // If a stream was found and the stream is still open, the priority - // of that stream is updated to match |priority|. + // Returns ERR_CONNECTION_CLOSED if the connection is being closed. + // Returns ERR_SPDY_PUSHED_STREAM_NOT_AVAILABLE if the pushed stream is not + // available any longer, for example, if the server has reset it. + // Returns OK if the stream is still available, and returns the stream in + // |*spdy_stream|. If the stream is still open, updates its priority to + // |priority|. int GetPushedStream(const GURL& url, spdy::SpdyStreamId pushed_stream_id, RequestPriority priority, - SpdyStream** spdy_stream, - const NetLogWithSource& stream_net_log); + SpdyStream** spdy_stream); // Called when the pushed stream should be cancelled. If the pushed stream is // not claimed and active, sends RST to the server to cancel the stream.
diff --git a/net/spdy/spdy_session_unittest.cc b/net/spdy/spdy_session_unittest.cc index 19d899b..d2ee430 100644 --- a/net/spdy/spdy_session_unittest.cc +++ b/net/spdy/spdy_session_unittest.cc
@@ -1650,7 +1650,7 @@ SpdyStream* spdy_stream2; int rv = session_->GetPushedStream(pushed_url, pushed_stream_id, MEDIUM, - &spdy_stream2, NetLogWithSource()); + &spdy_stream2); ASSERT_THAT(rv, IsOk()); ASSERT_TRUE(spdy_stream2); @@ -5603,7 +5603,7 @@ SpdyStream* pushed_stream; int rv = session_->GetPushedStream(pushed_url, pushed_stream_id, IDLE, - &pushed_stream, NetLogWithSource()); + &pushed_stream); ASSERT_THAT(rv, IsOk()); ASSERT_TRUE(pushed_stream); test::StreamDelegateCloseOnHeaders delegate2(pushed_stream->GetWeakPtr()); @@ -5687,7 +5687,7 @@ const GURL pushed_url(kPushedUrl); SpdyStream* pushed_stream; int rv = session_->GetPushedStream(pushed_url, 2 /* pushed_stream_id */, IDLE, - &pushed_stream, NetLogWithSource()); + &pushed_stream); EXPECT_THAT(rv, IsError(ERR_SPDY_PUSHED_STREAM_NOT_AVAILABLE)); // Read PUSH_PROMISE. @@ -5718,13 +5718,13 @@ // GetPushedStream() should return an error if there does not exist a pushed // stream with ID |pushed_stream_id|. rv = session_->GetPushedStream(pushed_url, 4 /* pushed_stream_id */, IDLE, - &pushed_stream, NetLogWithSource()); + &pushed_stream); EXPECT_THAT(rv, IsError(ERR_SPDY_PUSHED_STREAM_NOT_AVAILABLE)); // GetPushedStream() should return OK and return the pushed stream in // |pushed_stream| outparam if |pushed_stream_id| matches. rv = session_->GetPushedStream(pushed_url, 2 /* pushed_stream_id */, IDLE, - &pushed_stream, NetLogWithSource()); + &pushed_stream); EXPECT_THAT(rv, IsOk()); ASSERT_TRUE(pushed_stream); test::StreamDelegateCloseOnHeaders delegate2(pushed_stream->GetWeakPtr());
diff --git a/net/spdy/spdy_stream_unittest.cc b/net/spdy/spdy_stream_unittest.cc index 95f119d..69f2c44 100644 --- a/net/spdy/spdy_stream_unittest.cc +++ b/net/spdy/spdy_stream_unittest.cc
@@ -357,7 +357,7 @@ SpdyStream* push_stream; EXPECT_THAT(session->GetPushedStream(pushed_url, pushed_stream_id, IDLE, - &push_stream, NetLogWithSource()), + &push_stream), IsOk()); ASSERT_TRUE(push_stream); EXPECT_EQ(kPushUrl, push_stream->url().spec());
diff --git a/net/third_party/quic/core/chlo_extractor.cc b/net/third_party/quic/core/chlo_extractor.cc index f702b5c..d72158d 100644 --- a/net/third_party/quic/core/chlo_extractor.cc +++ b/net/third_party/quic/core/chlo_extractor.cc
@@ -51,6 +51,7 @@ bool OnConnectionCloseFrame(const QuicConnectionCloseFrame& frame) override; bool OnApplicationCloseFrame(const QuicApplicationCloseFrame& frame) override; bool OnNewConnectionIdFrame(const QuicNewConnectionIdFrame& frame) override; + bool OnNewTokenFrame(const QuicNewTokenFrame& frame) override; bool OnStopSendingFrame(const QuicStopSendingFrame& frame) override; bool OnPathChallengeFrame(const QuicPathChallengeFrame& frame) override; bool OnPathResponseFrame(const QuicPathResponseFrame& frame) override; @@ -220,6 +221,10 @@ return true; } +bool ChloFramerVisitor::OnNewTokenFrame(const QuicNewTokenFrame& frame) { + return true; +} + bool ChloFramerVisitor::OnPaddingFrame(const QuicPaddingFrame& frame) { return true; }
diff --git a/net/third_party/quic/core/frames/quic_blocked_frame.cc b/net/third_party/quic/core/frames/quic_blocked_frame.cc index 3ea12fb8..b4ba2c7 100644 --- a/net/third_party/quic/core/frames/quic_blocked_frame.cc +++ b/net/third_party/quic/core/frames/quic_blocked_frame.cc
@@ -3,19 +3,21 @@ // found in the LICENSE file. #include "net/third_party/quic/core/frames/quic_blocked_frame.h" +#include "net/third_party/quic/core/quic_constants.h" namespace quic { -QuicBlockedFrame::QuicBlockedFrame() : stream_id(0), offset(0) {} +QuicBlockedFrame::QuicBlockedFrame() + : control_frame_id(kInvalidControlFrameId), stream_id(0), offset(0) {} QuicBlockedFrame::QuicBlockedFrame(QuicControlFrameId control_frame_id, QuicStreamId stream_id) - : QuicControlFrame(control_frame_id), stream_id(stream_id), offset(0) {} + : control_frame_id(control_frame_id), stream_id(stream_id), offset(0) {} QuicBlockedFrame::QuicBlockedFrame(QuicControlFrameId control_frame_id, QuicStreamId stream_id, QuicStreamOffset offset) - : QuicControlFrame(control_frame_id), + : control_frame_id(control_frame_id), stream_id(stream_id), offset(offset) {}
diff --git a/net/third_party/quic/core/frames/quic_blocked_frame.h b/net/third_party/quic/core/frames/quic_blocked_frame.h index 70974be..d30dcb6e 100644 --- a/net/third_party/quic/core/frames/quic_blocked_frame.h +++ b/net/third_party/quic/core/frames/quic_blocked_frame.h
@@ -7,7 +7,7 @@ #include <ostream> -#include "net/third_party/quic/core/frames/quic_control_frame.h" +#include "net/third_party/quic/core/quic_types.h" namespace quic { @@ -15,7 +15,7 @@ // endpoint believes itself to be flow-control blocked but otherwise ready to // send data. The BLOCKED frame is purely advisory and optional. // Based on SPDY's BLOCKED frame (undocumented as of 2014-01-28). -struct QUIC_EXPORT_PRIVATE QuicBlockedFrame : public QuicControlFrame { +struct QUIC_EXPORT_PRIVATE QuicBlockedFrame { QuicBlockedFrame(); QuicBlockedFrame(QuicControlFrameId control_frame_id, QuicStreamId stream_id); QuicBlockedFrame(QuicControlFrameId control_frame_id, @@ -26,6 +26,10 @@ std::ostream& os, const QuicBlockedFrame& b); + // A unique identifier of this control frame. 0 when this frame is received, + // and non-zero when sent. + QuicControlFrameId control_frame_id; + // The stream this frame applies to. 0 is a special case meaning the overall // connection rather than a specific stream. //
diff --git a/net/third_party/quic/core/frames/quic_control_frame.h b/net/third_party/quic/core/frames/quic_control_frame.h deleted file mode 100644 index 41b3c14..0000000 --- a/net/third_party/quic/core/frames/quic_control_frame.h +++ /dev/null
@@ -1,25 +0,0 @@ -// Copyright (c) 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 NET_THIRD_PARTY_QUIC_CORE_FRAMES_QUIC_CONTROL_FRAME_H_ -#define NET_THIRD_PARTY_QUIC_CORE_FRAMES_QUIC_CONTROL_FRAME_H_ - -#include "net/third_party/quic/core/quic_constants.h" -#include "net/third_party/quic/platform/api/quic_export.h" - -namespace quic { - -struct QUIC_EXPORT_PRIVATE QuicControlFrame { - QuicControlFrame() : control_frame_id(kInvalidControlFrameId) {} - explicit QuicControlFrame(QuicControlFrameId control_frame_id) - : control_frame_id(control_frame_id) {} - - // A unique identifier of this control frame. 0 when this frame is received, - // and non-zero when sent. - QuicControlFrameId control_frame_id; -}; - -} // namespace quic - -#endif // NET_THIRD_PARTY_QUIC_CORE_FRAMES_QUIC_CONTROL_FRAME_H_
diff --git a/net/third_party/quic/core/frames/quic_frame.cc b/net/third_party/quic/core/frames/quic_frame.cc index 8ada26e..8d6b132 100644 --- a/net/third_party/quic/core/frames/quic_frame.cc +++ b/net/third_party/quic/core/frames/quic_frame.cc
@@ -14,7 +14,7 @@ QuicFrame::QuicFrame() {} QuicFrame::QuicFrame(QuicPaddingFrame padding_frame) - : type(PADDING_FRAME), padding_frame(padding_frame) {} + : padding_frame(padding_frame) {} QuicFrame::QuicFrame(QuicStreamFrame stream_frame) : stream_frame(stream_frame) {} @@ -25,13 +25,12 @@ QuicFrame::QuicFrame(QuicAckFrame* frame) : type(ACK_FRAME), ack_frame(frame) {} QuicFrame::QuicFrame(QuicMtuDiscoveryFrame frame) - : type(MTU_DISCOVERY_FRAME), mtu_discovery_frame(frame) {} + : mtu_discovery_frame(frame) {} QuicFrame::QuicFrame(QuicStopWaitingFrame* frame) : type(STOP_WAITING_FRAME), stop_waiting_frame(frame) {} -QuicFrame::QuicFrame(QuicPingFrame frame) - : type(PING_FRAME), ping_frame(frame) {} +QuicFrame::QuicFrame(QuicPingFrame frame) : ping_frame(frame) {} QuicFrame::QuicFrame(QuicRstStreamFrame* frame) : type(RST_STREAM_FRAME), rst_stream_frame(frame) {} @@ -54,11 +53,10 @@ QuicFrame::QuicFrame(QuicNewConnectionIdFrame* frame) : type(NEW_CONNECTION_ID_FRAME), new_connection_id_frame(frame) {} -QuicFrame::QuicFrame(QuicMaxStreamIdFrame frame) - : type(MAX_STREAM_ID_FRAME), max_stream_id_frame(frame) {} +QuicFrame::QuicFrame(QuicMaxStreamIdFrame frame) : max_stream_id_frame(frame) {} QuicFrame::QuicFrame(QuicStreamIdBlockedFrame frame) - : type(STREAM_ID_BLOCKED_FRAME), stream_id_blocked_frame(frame) {} + : stream_id_blocked_frame(frame) {} QuicFrame::QuicFrame(QuicPathResponseFrame* frame) : type(PATH_RESPONSE_FRAME), path_response_frame(frame) {} @@ -72,6 +70,9 @@ QuicFrame::QuicFrame(QuicMessageFrame* frame) : type(MESSAGE_FRAME), message_frame(frame) {} +QuicFrame::QuicFrame(QuicNewTokenFrame* frame) + : type(NEW_TOKEN_FRAME), new_token_frame(frame) {} + void DeleteFrames(QuicFrames* frames) { for (QuicFrame& frame : *frames) { DeleteFrame(&frame); @@ -131,6 +132,9 @@ case CRYPTO_FRAME: delete frame->crypto_frame; break; + case NEW_TOKEN_FRAME: + delete frame->new_token_frame; + break; case NUM_FRAME_TYPES: DCHECK(false) << "Cannot delete type: " << frame->type; @@ -310,6 +314,9 @@ case MESSAGE_FRAME: os << "type { MESSAGE_FRAME }" << *(frame.message_frame); break; + case NEW_TOKEN_FRAME: + os << "type { NEW_TOKEN_FRAME }" << *(frame.new_token_frame); + break; default: { QUIC_LOG(ERROR) << "Unknown frame type: " << frame.type; break;
diff --git a/net/third_party/quic/core/frames/quic_frame.h b/net/third_party/quic/core/frames/quic_frame.h index 5815eac..83d51d5b 100644 --- a/net/third_party/quic/core/frames/quic_frame.h +++ b/net/third_party/quic/core/frames/quic_frame.h
@@ -18,6 +18,7 @@ #include "net/third_party/quic/core/frames/quic_message_frame.h" #include "net/third_party/quic/core/frames/quic_mtu_discovery_frame.h" #include "net/third_party/quic/core/frames/quic_new_connection_id_frame.h" +#include "net/third_party/quic/core/frames/quic_new_token_frame.h" #include "net/third_party/quic/core/frames/quic_padding_frame.h" #include "net/third_party/quic/core/frames/quic_path_challenge_frame.h" #include "net/third_party/quic/core/frames/quic_path_response_frame.h" @@ -53,6 +54,7 @@ explicit QuicFrame(QuicBlockedFrame* frame); explicit QuicFrame(QuicApplicationCloseFrame* frame); explicit QuicFrame(QuicNewConnectionIdFrame* frame); + explicit QuicFrame(QuicNewTokenFrame* frame); explicit QuicFrame(QuicPathResponseFrame* frame); explicit QuicFrame(QuicPathChallengeFrame* frame); explicit QuicFrame(QuicStopSendingFrame* frame); @@ -63,10 +65,18 @@ const QuicFrame& frame); union { + // Inlined frames. // Overlapping inlined frames have a |type| field at the same 0 offset as - // QuicFrame does below, allowing use of the remaining 7 bytes after offset - // for frame-type specific fields. + // QuicFrame does for out of line frames below, allowing use of the + // remaining 7 bytes after offset for frame-type specific fields. + QuicPaddingFrame padding_frame; + QuicMtuDiscoveryFrame mtu_discovery_frame; + QuicPingFrame ping_frame; + QuicMaxStreamIdFrame max_stream_id_frame; + QuicStreamIdBlockedFrame stream_id_blocked_frame; QuicStreamFrame stream_frame; + + // Out of line frames. struct { QuicFrameType type; @@ -75,14 +85,6 @@ // QuicWindowUpdateFrame, QuicBlockedFrame, QuicPathResponseFrame, // QuicPathChallengeFrame and QuicStopSendingFrame. union { - // Inlined frames. - QuicPaddingFrame padding_frame; - QuicMtuDiscoveryFrame mtu_discovery_frame; - QuicPingFrame ping_frame; - QuicMaxStreamIdFrame max_stream_id_frame; - QuicStreamIdBlockedFrame stream_id_blocked_frame; - - // Out of line frames. QuicAckFrame* ack_frame; QuicStopWaitingFrame* stop_waiting_frame; QuicRstStreamFrame* rst_stream_frame; @@ -97,17 +99,16 @@ QuicStopSendingFrame* stop_sending_frame; QuicMessageFrame* message_frame; QuicCryptoFrame* crypto_frame; + QuicNewTokenFrame* new_token_frame; }; }; }; }; -// In QuicFrame, QuicFrameType consumes 8 bytes with padding. + static_assert(sizeof(QuicFrame) <= 24, - "Frames larger than 16 bytes should be referenced by pointer."); + "Frames larger than 24 bytes should be referenced by pointer."); static_assert(offsetof(QuicStreamFrame, type) == offsetof(QuicFrame, type), "Offset of |type| must match in QuicFrame and QuicStreamFrame"); -static_assert(offsetof(QuicStreamFrame, type) == 0, - "Illegal stream frame layout"); // A inline size of 1 is chosen to optimize the typical use case of // 1-stream-frame in QuicTransmissionInfo.retransmittable_frames.
diff --git a/net/third_party/quic/core/frames/quic_goaway_frame.cc b/net/third_party/quic/core/frames/quic_goaway_frame.cc index 814f311..e739c028 100644 --- a/net/third_party/quic/core/frames/quic_goaway_frame.cc +++ b/net/third_party/quic/core/frames/quic_goaway_frame.cc
@@ -3,18 +3,21 @@ // found in the LICENSE file. #include "net/third_party/quic/core/frames/quic_goaway_frame.h" +#include "net/third_party/quic/core/quic_constants.h" #include "net/third_party/quic/platform/api/quic_string.h" namespace quic { QuicGoAwayFrame::QuicGoAwayFrame() - : error_code(QUIC_NO_ERROR), last_good_stream_id(0) {} + : control_frame_id(kInvalidControlFrameId), + error_code(QUIC_NO_ERROR), + last_good_stream_id(0) {} QuicGoAwayFrame::QuicGoAwayFrame(QuicControlFrameId control_frame_id, QuicErrorCode error_code, QuicStreamId last_good_stream_id, const QuicString& reason) - : QuicControlFrame(control_frame_id), + : control_frame_id(control_frame_id), error_code(error_code), last_good_stream_id(last_good_stream_id), reason_phrase(reason) {}
diff --git a/net/third_party/quic/core/frames/quic_goaway_frame.h b/net/third_party/quic/core/frames/quic_goaway_frame.h index 62c9dd0..532692d 100644 --- a/net/third_party/quic/core/frames/quic_goaway_frame.h +++ b/net/third_party/quic/core/frames/quic_goaway_frame.h
@@ -7,13 +7,13 @@ #include <ostream> -#include "net/third_party/quic/core/frames/quic_control_frame.h" #include "net/third_party/quic/core/quic_error_codes.h" +#include "net/third_party/quic/core/quic_types.h" #include "net/third_party/quic/platform/api/quic_string.h" namespace quic { -struct QUIC_EXPORT_PRIVATE QuicGoAwayFrame : public QuicControlFrame { +struct QUIC_EXPORT_PRIVATE QuicGoAwayFrame { QuicGoAwayFrame(); QuicGoAwayFrame(QuicControlFrameId control_frame_id, QuicErrorCode error_code, @@ -23,6 +23,9 @@ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, const QuicGoAwayFrame& g); + // A unique identifier of this control frame. 0 when this frame is received, + // and non-zero when sent. + QuicControlFrameId control_frame_id; QuicErrorCode error_code; QuicStreamId last_good_stream_id; QuicString reason_phrase;
diff --git a/net/third_party/quic/core/frames/quic_inlined_frame.h b/net/third_party/quic/core/frames/quic_inlined_frame.h new file mode 100644 index 0000000..5c716eb --- /dev/null +++ b/net/third_party/quic/core/frames/quic_inlined_frame.h
@@ -0,0 +1,30 @@ +// Copyright (c) 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_THIRD_PARTY_QUIC_CORE_FRAMES_QUIC_INLINED_FRAME_H_ +#define NET_THIRD_PARTY_QUIC_CORE_FRAMES_QUIC_INLINED_FRAME_H_ + +#include "net/third_party/quic/core/quic_types.h" +#include "net/third_party/quic/platform/api/quic_export.h" + +namespace quic { + +// QuicInlinedFrame is the base class of all frame types that is inlined in the +// QuicFrame class. It gurantees all inlined frame types contain a 'type' field +// at offset 0, such that QuicFrame.type can get the correct frame type for both +// inline and out-of-line frame types. +template <typename DerivedT> +struct QUIC_EXPORT_PRIVATE QuicInlinedFrame { + QuicInlinedFrame(QuicFrameType type) : type(type) { + static_assert(offsetof(DerivedT, type) == 0, + "type must be the first field."); + static_assert(sizeof(DerivedT) <= 24, + "Frames larger than 24 bytes should not be inlined."); + } + QuicFrameType type; +}; + +} // namespace quic + +#endif // NET_THIRD_PARTY_QUIC_CORE_FRAMES_QUIC_INLINED_FRAME_H_
diff --git a/net/third_party/quic/core/frames/quic_max_stream_id_frame.cc b/net/third_party/quic/core/frames/quic_max_stream_id_frame.cc index 914a15f..0696f68b 100644 --- a/net/third_party/quic/core/frames/quic_max_stream_id_frame.cc +++ b/net/third_party/quic/core/frames/quic_max_stream_id_frame.cc
@@ -6,11 +6,15 @@ namespace quic { -QuicMaxStreamIdFrame::QuicMaxStreamIdFrame() {} +QuicMaxStreamIdFrame::QuicMaxStreamIdFrame() + : QuicInlinedFrame(MAX_STREAM_ID_FRAME), + control_frame_id(kInvalidControlFrameId) {} QuicMaxStreamIdFrame::QuicMaxStreamIdFrame(QuicControlFrameId control_frame_id, QuicStreamId max_stream_id) - : QuicControlFrame(control_frame_id), max_stream_id(max_stream_id) {} + : QuicInlinedFrame(MAX_STREAM_ID_FRAME), + control_frame_id(control_frame_id), + max_stream_id(max_stream_id) {} std::ostream& operator<<(std::ostream& os, const QuicMaxStreamIdFrame& frame) { os << "{ control_frame_id: " << frame.control_frame_id
diff --git a/net/third_party/quic/core/frames/quic_max_stream_id_frame.h b/net/third_party/quic/core/frames/quic_max_stream_id_frame.h index 6368afce..98c414a 100644 --- a/net/third_party/quic/core/frames/quic_max_stream_id_frame.h +++ b/net/third_party/quic/core/frames/quic_max_stream_id_frame.h
@@ -7,14 +7,18 @@ #include <ostream> -#include "net/third_party/quic/core/frames/quic_control_frame.h" +#include "net/third_party/quic/core/frames/quic_inlined_frame.h" +#include "net/third_party/quic/core/quic_constants.h" +#include "net/third_party/quic/core/quic_types.h" +#include "net/third_party/quic/platform/api/quic_export.h" namespace quic { // IETF format MAX_STREAM_ID frame. // This frame is used by the sender to inform the peer of the largest // stream id that the peer may open and that the sender will accept. -struct QUIC_EXPORT_PRIVATE QuicMaxStreamIdFrame : public QuicControlFrame { +struct QUIC_EXPORT_PRIVATE QuicMaxStreamIdFrame + : public QuicInlinedFrame<QuicMaxStreamIdFrame> { QuicMaxStreamIdFrame(); QuicMaxStreamIdFrame(QuicControlFrameId control_frame_id, QuicStreamId max_stream_id); @@ -23,6 +27,10 @@ std::ostream& os, const QuicMaxStreamIdFrame& frame); + // A unique identifier of this control frame. 0 when this frame is received, + // and non-zero when sent. + QuicControlFrameId control_frame_id; + // The maximum stream id to support. QuicStreamId max_stream_id; };
diff --git a/net/third_party/quic/core/frames/quic_mtu_discovery_frame.h b/net/third_party/quic/core/frames/quic_mtu_discovery_frame.h index 29c25a6..de1e461 100644 --- a/net/third_party/quic/core/frames/quic_mtu_discovery_frame.h +++ b/net/third_party/quic/core/frames/quic_mtu_discovery_frame.h
@@ -5,13 +5,18 @@ #ifndef NET_THIRD_PARTY_QUIC_CORE_FRAMES_QUIC_MTU_DISCOVERY_FRAME_H_ #define NET_THIRD_PARTY_QUIC_CORE_FRAMES_QUIC_MTU_DISCOVERY_FRAME_H_ +#include "net/third_party/quic/core/frames/quic_inlined_frame.h" +#include "net/third_party/quic/core/quic_types.h" #include "net/third_party/quic/platform/api/quic_export.h" namespace quic { // A path MTU discovery frame contains no payload and is serialized as a ping // frame. -struct QUIC_EXPORT_PRIVATE QuicMtuDiscoveryFrame {}; +struct QUIC_EXPORT_PRIVATE QuicMtuDiscoveryFrame + : public QuicInlinedFrame<QuicMtuDiscoveryFrame> { + QuicMtuDiscoveryFrame() : QuicInlinedFrame(MTU_DISCOVERY_FRAME) {} +}; } // namespace quic
diff --git a/net/third_party/quic/core/frames/quic_new_connection_id_frame.cc b/net/third_party/quic/core/frames/quic_new_connection_id_frame.cc index 6629620..82bbcfa7 100644 --- a/net/third_party/quic/core/frames/quic_new_connection_id_frame.cc +++ b/net/third_party/quic/core/frames/quic_new_connection_id_frame.cc
@@ -3,18 +3,21 @@ // found in the LICENSE file. #include "net/third_party/quic/core/frames/quic_new_connection_id_frame.h" +#include "net/third_party/quic/core/quic_constants.h" namespace quic { QuicNewConnectionIdFrame::QuicNewConnectionIdFrame() - : QuicControlFrame(0), connection_id(0), sequence_number(0) {} + : control_frame_id(kInvalidControlFrameId), + connection_id(0), + sequence_number(0) {} QuicNewConnectionIdFrame::QuicNewConnectionIdFrame( QuicControlFrameId control_frame_id, QuicConnectionId connection_id, QuicConnectionIdSequenceNumber sequence_number, const QuicUint128 stateless_reset_token) - : QuicControlFrame(control_frame_id), + : control_frame_id(control_frame_id), connection_id(connection_id), sequence_number(sequence_number), stateless_reset_token(stateless_reset_token) {}
diff --git a/net/third_party/quic/core/frames/quic_new_connection_id_frame.h b/net/third_party/quic/core/frames/quic_new_connection_id_frame.h index 81a6517..04a1336 100644 --- a/net/third_party/quic/core/frames/quic_new_connection_id_frame.h +++ b/net/third_party/quic/core/frames/quic_new_connection_id_frame.h
@@ -7,13 +7,13 @@ #include <ostream> -#include "net/third_party/quic/core/frames/quic_control_frame.h" #include "net/third_party/quic/core/quic_error_codes.h" +#include "net/third_party/quic/core/quic_types.h" #include "net/third_party/quic/platform/api/quic_uint128.h" namespace quic { -struct QUIC_EXPORT_PRIVATE QuicNewConnectionIdFrame : public QuicControlFrame { +struct QUIC_EXPORT_PRIVATE QuicNewConnectionIdFrame { QuicNewConnectionIdFrame(); QuicNewConnectionIdFrame(QuicControlFrameId control_frame_id, QuicConnectionId connection_id, @@ -24,6 +24,9 @@ std::ostream& os, const QuicNewConnectionIdFrame& frame); + // A unique identifier of this control frame. 0 when this frame is received, + // and non-zero when sent. + QuicControlFrameId control_frame_id; QuicConnectionId connection_id; QuicConnectionIdSequenceNumber sequence_number; QuicUint128 stateless_reset_token;
diff --git a/net/third_party/quic/core/frames/quic_new_token_frame.cc b/net/third_party/quic/core/frames/quic_new_token_frame.cc new file mode 100644 index 0000000..6100790 --- /dev/null +++ b/net/third_party/quic/core/frames/quic_new_token_frame.cc
@@ -0,0 +1,24 @@ +// Copyright (c) 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/third_party/quic/core/frames/quic_new_token_frame.h" +#include "net/third_party/quic/core/quic_constants.h" +#include "net/third_party/quic/platform/api/quic_logging.h" + +namespace quic { + +QuicNewTokenFrame::QuicNewTokenFrame() + : control_frame_id(kInvalidControlFrameId) {} + +QuicNewTokenFrame::QuicNewTokenFrame(QuicControlFrameId control_frame_id, + QuicString token) + : control_frame_id(control_frame_id), token(token) {} + +std::ostream& operator<<(std::ostream& os, const QuicNewTokenFrame& s) { + os << "{ control_frame_id: " << s.control_frame_id << ", token: " << s.token + << " }\n"; + return os; +} + +} // namespace quic
diff --git a/net/third_party/quic/core/frames/quic_new_token_frame.h b/net/third_party/quic/core/frames/quic_new_token_frame.h new file mode 100644 index 0000000..86a391e9 --- /dev/null +++ b/net/third_party/quic/core/frames/quic_new_token_frame.h
@@ -0,0 +1,37 @@ +// Copyright (c) 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_THIRD_PARTY_QUIC_CORE_FRAMES_QUIC_NEW_TOKEN_FRAME_H_ +#define NET_THIRD_PARTY_QUIC_CORE_FRAMES_QUIC_NEW_TOKEN_FRAME_H_ + +#include <memory> +#include <ostream> + +#include "net/third_party/quic/core/quic_buffer_allocator.h" +#include "net/third_party/quic/core/quic_types.h" +#include "net/third_party/quic/platform/api/quic_export.h" +#include "net/third_party/quic/platform/api/quic_string_piece.h" + +namespace quic { + +struct QUIC_EXPORT_PRIVATE QuicNewTokenFrame { + QuicNewTokenFrame(); + QuicNewTokenFrame(QuicControlFrameId control_frame_id, QuicString token); + + friend QUIC_EXPORT_PRIVATE std::ostream& operator<<( + std::ostream& os, + const QuicNewTokenFrame& s); + + // A unique identifier of this control frame. 0 when this frame is received, + // and non-zero when sent. + QuicControlFrameId control_frame_id; + + QuicString token; +}; +static_assert(sizeof(QuicNewTokenFrame) <= 64, + "Keep the QuicNewTokenFrame size to a cacheline."); + +} // namespace quic + +#endif // NET_THIRD_PARTY_QUIC_CORE_FRAMES_QUIC_NEW_TOKEN_FRAME_H_
diff --git a/net/third_party/quic/core/frames/quic_padding_frame.h b/net/third_party/quic/core/frames/quic_padding_frame.h index 366a160..4313f3e 100644 --- a/net/third_party/quic/core/frames/quic_padding_frame.h +++ b/net/third_party/quic/core/frames/quic_padding_frame.h
@@ -8,15 +8,18 @@ #include <cstdint> #include <ostream> +#include "net/third_party/quic/core/frames/quic_inlined_frame.h" +#include "net/third_party/quic/core/quic_types.h" #include "net/third_party/quic/platform/api/quic_export.h" namespace quic { // A padding frame contains no payload. -struct QUIC_EXPORT_PRIVATE QuicPaddingFrame { - QuicPaddingFrame() : num_padding_bytes(-1) {} +struct QUIC_EXPORT_PRIVATE QuicPaddingFrame + : public QuicInlinedFrame<QuicPaddingFrame> { + QuicPaddingFrame() : QuicInlinedFrame(PADDING_FRAME), num_padding_bytes(-1) {} explicit QuicPaddingFrame(int num_padding_bytes) - : num_padding_bytes(num_padding_bytes) {} + : QuicInlinedFrame(PADDING_FRAME), num_padding_bytes(num_padding_bytes) {} friend QUIC_EXPORT_PRIVATE std::ostream& operator<<( std::ostream& os,
diff --git a/net/third_party/quic/core/frames/quic_path_challenge_frame.cc b/net/third_party/quic/core/frames/quic_path_challenge_frame.cc index 4497411..c47458d1 100644 --- a/net/third_party/quic/core/frames/quic_path_challenge_frame.cc +++ b/net/third_party/quic/core/frames/quic_path_challenge_frame.cc
@@ -3,16 +3,18 @@ // found in the LICENSE file. #include "net/third_party/quic/core/frames/quic_path_challenge_frame.h" +#include "net/third_party/quic/core/quic_constants.h" #include "net/third_party/quic/platform/api/quic_bug_tracker.h" namespace quic { -QuicPathChallengeFrame::QuicPathChallengeFrame() : QuicControlFrame(0) {} +QuicPathChallengeFrame::QuicPathChallengeFrame() + : control_frame_id(kInvalidControlFrameId) {} QuicPathChallengeFrame::QuicPathChallengeFrame( QuicControlFrameId control_frame_id, const QuicPathFrameBuffer& data_buff) - : QuicControlFrame(control_frame_id) { + : control_frame_id(control_frame_id) { memcpy(data_buffer.data(), data_buff.data(), data_buffer.size()); }
diff --git a/net/third_party/quic/core/frames/quic_path_challenge_frame.h b/net/third_party/quic/core/frames/quic_path_challenge_frame.h index 513ea55..db0fd35 100644 --- a/net/third_party/quic/core/frames/quic_path_challenge_frame.h +++ b/net/third_party/quic/core/frames/quic_path_challenge_frame.h
@@ -8,7 +8,6 @@ #include <memory> #include <ostream> -#include "net/third_party/quic/core/frames/quic_control_frame.h" #include "net/third_party/quic/core/quic_types.h" namespace quic { @@ -16,7 +15,7 @@ // Size of the entire IETF Quic Path Challenge frame. const size_t kQuicPathChallengeFrameSize = kQuicPathFrameBufferSize; -struct QUIC_EXPORT_PRIVATE QuicPathChallengeFrame : public QuicControlFrame { +struct QUIC_EXPORT_PRIVATE QuicPathChallengeFrame { QuicPathChallengeFrame(); QuicPathChallengeFrame(QuicControlFrameId control_frame_id, const QuicPathFrameBuffer& data_buff); @@ -26,6 +25,10 @@ std::ostream& os, const QuicPathChallengeFrame& frame); + // A unique identifier of this control frame. 0 when this frame is received, + // and non-zero when sent. + QuicControlFrameId control_frame_id; + QuicPathFrameBuffer data_buffer; }; } // namespace quic
diff --git a/net/third_party/quic/core/frames/quic_path_response_frame.cc b/net/third_party/quic/core/frames/quic_path_response_frame.cc index 31c95768..d6cd3f4 100644 --- a/net/third_party/quic/core/frames/quic_path_response_frame.cc +++ b/net/third_party/quic/core/frames/quic_path_response_frame.cc
@@ -3,16 +3,18 @@ // found in the LICENSE file. #include "net/third_party/quic/core/frames/quic_path_response_frame.h" +#include "net/third_party/quic/core/quic_constants.h" #include "net/third_party/quic/platform/api/quic_bug_tracker.h" namespace quic { -QuicPathResponseFrame::QuicPathResponseFrame() : QuicControlFrame(0) {} +QuicPathResponseFrame::QuicPathResponseFrame() + : control_frame_id(kInvalidControlFrameId) {} QuicPathResponseFrame::QuicPathResponseFrame( QuicControlFrameId control_frame_id, const QuicPathFrameBuffer& data_buff) - : QuicControlFrame(control_frame_id) { + : control_frame_id(control_frame_id) { memcpy(data_buffer.data(), data_buff.data(), data_buffer.size()); }
diff --git a/net/third_party/quic/core/frames/quic_path_response_frame.h b/net/third_party/quic/core/frames/quic_path_response_frame.h index ebc624586..19368de1 100644 --- a/net/third_party/quic/core/frames/quic_path_response_frame.h +++ b/net/third_party/quic/core/frames/quic_path_response_frame.h
@@ -8,7 +8,6 @@ #include <memory> #include <ostream> -#include "net/third_party/quic/core/frames/quic_control_frame.h" #include "net/third_party/quic/core/quic_types.h" namespace quic { @@ -16,7 +15,7 @@ // Size of the entire IETF Quic Path Response frame. const size_t kQuicPathResponseFrameSize = kQuicPathFrameBufferSize; -struct QUIC_EXPORT_PRIVATE QuicPathResponseFrame : public QuicControlFrame { +struct QUIC_EXPORT_PRIVATE QuicPathResponseFrame { QuicPathResponseFrame(); QuicPathResponseFrame(QuicControlFrameId control_frame_id, const QuicPathFrameBuffer& data_buff); @@ -26,6 +25,10 @@ std::ostream& os, const QuicPathResponseFrame& frame); + // A unique identifier of this control frame. 0 when this frame is received, + // and non-zero when sent. + QuicControlFrameId control_frame_id; + QuicPathFrameBuffer data_buffer; }; } // namespace quic
diff --git a/net/third_party/quic/core/frames/quic_ping_frame.cc b/net/third_party/quic/core/frames/quic_ping_frame.cc index 3b64f18..4d18752 100644 --- a/net/third_party/quic/core/frames/quic_ping_frame.cc +++ b/net/third_party/quic/core/frames/quic_ping_frame.cc
@@ -6,10 +6,11 @@ namespace quic { -QuicPingFrame::QuicPingFrame() {} +QuicPingFrame::QuicPingFrame() + : QuicInlinedFrame(PING_FRAME), control_frame_id(kInvalidControlFrameId) {} QuicPingFrame::QuicPingFrame(QuicControlFrameId control_frame_id) - : QuicControlFrame(control_frame_id) {} + : QuicInlinedFrame(PING_FRAME), control_frame_id(control_frame_id) {} std::ostream& operator<<(std::ostream& os, const QuicPingFrame& ping_frame) { os << "{ control_frame_id: " << ping_frame.control_frame_id << " }\n";
diff --git a/net/third_party/quic/core/frames/quic_ping_frame.h b/net/third_party/quic/core/frames/quic_ping_frame.h index 0ee991e..216b88d 100644 --- a/net/third_party/quic/core/frames/quic_ping_frame.h +++ b/net/third_party/quic/core/frames/quic_ping_frame.h
@@ -5,19 +5,27 @@ #ifndef NET_THIRD_PARTY_QUIC_CORE_FRAMES_QUIC_PING_FRAME_H_ #define NET_THIRD_PARTY_QUIC_CORE_FRAMES_QUIC_PING_FRAME_H_ -#include "net/third_party/quic/core/frames/quic_control_frame.h" +#include "net/third_party/quic/core/frames/quic_inlined_frame.h" +#include "net/third_party/quic/core/quic_constants.h" +#include "net/third_party/quic/core/quic_types.h" +#include "net/third_party/quic/platform/api/quic_export.h" namespace quic { // A ping frame contains no payload, though it is retransmittable, // and ACK'd just like other normal frames. -struct QUIC_EXPORT_PRIVATE QuicPingFrame : public QuicControlFrame { +struct QUIC_EXPORT_PRIVATE QuicPingFrame + : public QuicInlinedFrame<QuicPingFrame> { QuicPingFrame(); explicit QuicPingFrame(QuicControlFrameId control_frame_id); friend QUIC_EXPORT_PRIVATE std::ostream& operator<<( std::ostream& os, const QuicPingFrame& ping_frame); + + // A unique identifier of this control frame. 0 when this frame is received, + // and non-zero when sent. + QuicControlFrameId control_frame_id; }; } // namespace quic
diff --git a/net/third_party/quic/core/frames/quic_rst_stream_frame.cc b/net/third_party/quic/core/frames/quic_rst_stream_frame.cc index fd8cc0bf..aa3563a 100644 --- a/net/third_party/quic/core/frames/quic_rst_stream_frame.cc +++ b/net/third_party/quic/core/frames/quic_rst_stream_frame.cc
@@ -3,17 +3,21 @@ // found in the LICENSE file. #include "net/third_party/quic/core/frames/quic_rst_stream_frame.h" +#include "net/third_party/quic/core/quic_constants.h" namespace quic { QuicRstStreamFrame::QuicRstStreamFrame() - : stream_id(0), error_code(QUIC_STREAM_NO_ERROR), byte_offset(0) {} + : control_frame_id(kInvalidControlFrameId), + stream_id(0), + error_code(QUIC_STREAM_NO_ERROR), + byte_offset(0) {} QuicRstStreamFrame::QuicRstStreamFrame(QuicControlFrameId control_frame_id, QuicStreamId stream_id, QuicRstStreamErrorCode error_code, QuicStreamOffset bytes_written) - : QuicControlFrame(control_frame_id), + : control_frame_id(control_frame_id), stream_id(stream_id), error_code(error_code), byte_offset(bytes_written) {} @@ -22,7 +26,7 @@ QuicStreamId stream_id, uint16_t ietf_error_code, QuicStreamOffset bytes_written) - : QuicControlFrame(control_frame_id), + : control_frame_id(control_frame_id), stream_id(stream_id), ietf_error_code(ietf_error_code), byte_offset(bytes_written) {}
diff --git a/net/third_party/quic/core/frames/quic_rst_stream_frame.h b/net/third_party/quic/core/frames/quic_rst_stream_frame.h index c21e83a..a03f5f7 100644 --- a/net/third_party/quic/core/frames/quic_rst_stream_frame.h +++ b/net/third_party/quic/core/frames/quic_rst_stream_frame.h
@@ -7,12 +7,12 @@ #include <ostream> -#include "net/third_party/quic/core/frames/quic_control_frame.h" #include "net/third_party/quic/core/quic_error_codes.h" +#include "net/third_party/quic/core/quic_types.h" namespace quic { -struct QUIC_EXPORT_PRIVATE QuicRstStreamFrame : public QuicControlFrame { +struct QUIC_EXPORT_PRIVATE QuicRstStreamFrame { QuicRstStreamFrame(); QuicRstStreamFrame(QuicControlFrameId control_frame_id, QuicStreamId stream_id, @@ -27,6 +27,10 @@ std::ostream& os, const QuicRstStreamFrame& r); + // A unique identifier of this control frame. 0 when this frame is received, + // and non-zero when sent. + QuicControlFrameId control_frame_id; + QuicStreamId stream_id; // Caller must know whether IETF- or Google- QUIC is in use and
diff --git a/net/third_party/quic/core/frames/quic_stop_sending_frame.cc b/net/third_party/quic/core/frames/quic_stop_sending_frame.cc index 00794f0..8f1a71ad 100644 --- a/net/third_party/quic/core/frames/quic_stop_sending_frame.cc +++ b/net/third_party/quic/core/frames/quic_stop_sending_frame.cc
@@ -3,17 +3,20 @@ // found in the LICENSE file. #include "net/third_party/quic/core/frames/quic_stop_sending_frame.h" +#include "net/third_party/quic/core/quic_constants.h" namespace quic { QuicStopSendingFrame::QuicStopSendingFrame() - : stream_id(0), application_error_code(0) {} + : control_frame_id(kInvalidControlFrameId), + stream_id(0), + application_error_code(0) {} QuicStopSendingFrame::QuicStopSendingFrame( QuicControlFrameId control_frame_id, QuicStreamId stream_id, QuicApplicationErrorCode application_error_code) - : QuicControlFrame(control_frame_id), + : control_frame_id(control_frame_id), stream_id(stream_id), application_error_code(application_error_code) {}
diff --git a/net/third_party/quic/core/frames/quic_stop_sending_frame.h b/net/third_party/quic/core/frames/quic_stop_sending_frame.h index 9ade111..52c1931b 100644 --- a/net/third_party/quic/core/frames/quic_stop_sending_frame.h +++ b/net/third_party/quic/core/frames/quic_stop_sending_frame.h
@@ -7,12 +7,12 @@ #include <ostream> -#include "net/third_party/quic/core/frames/quic_control_frame.h" #include "net/third_party/quic/core/quic_error_codes.h" +#include "net/third_party/quic/core/quic_types.h" namespace quic { -struct QUIC_EXPORT_PRIVATE QuicStopSendingFrame : public QuicControlFrame { +struct QUIC_EXPORT_PRIVATE QuicStopSendingFrame { QuicStopSendingFrame(); QuicStopSendingFrame(QuicControlFrameId control_frame_id, QuicStreamId stream_id, @@ -22,6 +22,9 @@ std::ostream& os, const QuicStopSendingFrame& frame); + // A unique identifier of this control frame. 0 when this frame is received, + // and non-zero when sent. + QuicControlFrameId control_frame_id; QuicStreamId stream_id; QuicApplicationErrorCode application_error_code; };
diff --git a/net/third_party/quic/core/frames/quic_stream_frame.cc b/net/third_party/quic/core/frames/quic_stream_frame.cc index d0dcbb8..8f9ca7a 100644 --- a/net/third_party/quic/core/frames/quic_stream_frame.cc +++ b/net/third_party/quic/core/frames/quic_stream_frame.cc
@@ -27,7 +27,7 @@ QuicStreamOffset offset, const char* data_buffer, QuicPacketLength data_length) - : type(STREAM_FRAME), + : QuicInlinedFrame(STREAM_FRAME), fin(fin), data_length(data_length), stream_id(stream_id),
diff --git a/net/third_party/quic/core/frames/quic_stream_frame.h b/net/third_party/quic/core/frames/quic_stream_frame.h index 71aa120..9e51db02 100644 --- a/net/third_party/quic/core/frames/quic_stream_frame.h +++ b/net/third_party/quic/core/frames/quic_stream_frame.h
@@ -8,6 +8,7 @@ #include <memory> #include <ostream> +#include "net/third_party/quic/core/frames/quic_inlined_frame.h" #include "net/third_party/quic/core/quic_buffer_allocator.h" #include "net/third_party/quic/core/quic_types.h" #include "net/third_party/quic/platform/api/quic_export.h" @@ -15,7 +16,8 @@ namespace quic { -struct QUIC_EXPORT_PRIVATE QuicStreamFrame { +struct QUIC_EXPORT_PRIVATE QuicStreamFrame + : public QuicInlinedFrame<QuicStreamFrame> { QuicStreamFrame(); QuicStreamFrame(QuicStreamId stream_id, bool fin, @@ -29,11 +31,6 @@ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, const QuicStreamFrame& s); - // The union in QuicFrame requires the QuicStreamFrame |type| field to be the - // first field in the frame. - QuicFrameType type; - - // QuicStreamFrame fields. bool fin; QuicPacketLength data_length; QuicStreamId stream_id;
diff --git a/net/third_party/quic/core/frames/quic_stream_id_blocked_frame.cc b/net/third_party/quic/core/frames/quic_stream_id_blocked_frame.cc index 07346a63..1cad68c 100644 --- a/net/third_party/quic/core/frames/quic_stream_id_blocked_frame.cc +++ b/net/third_party/quic/core/frames/quic_stream_id_blocked_frame.cc
@@ -6,12 +6,16 @@ namespace quic { -QuicStreamIdBlockedFrame::QuicStreamIdBlockedFrame() {} +QuicStreamIdBlockedFrame::QuicStreamIdBlockedFrame() + : QuicInlinedFrame(STREAM_ID_BLOCKED_FRAME), + control_frame_id(kInvalidControlFrameId) {} QuicStreamIdBlockedFrame::QuicStreamIdBlockedFrame( QuicControlFrameId control_frame_id, QuicStreamId stream_id) - : QuicControlFrame(control_frame_id), stream_id(stream_id) {} + : QuicInlinedFrame(STREAM_ID_BLOCKED_FRAME), + control_frame_id(control_frame_id), + stream_id(stream_id) {} std::ostream& operator<<(std::ostream& os, const QuicStreamIdBlockedFrame& frame) {
diff --git a/net/third_party/quic/core/frames/quic_stream_id_blocked_frame.h b/net/third_party/quic/core/frames/quic_stream_id_blocked_frame.h index 47d7a47..c3087450 100644 --- a/net/third_party/quic/core/frames/quic_stream_id_blocked_frame.h +++ b/net/third_party/quic/core/frames/quic_stream_id_blocked_frame.h
@@ -7,7 +7,10 @@ #include <ostream> -#include "net/third_party/quic/core/frames/quic_control_frame.h" +#include "net/third_party/quic/core/frames/quic_inlined_frame.h" +#include "net/third_party/quic/core/quic_constants.h" +#include "net/third_party/quic/core/quic_types.h" +#include "net/third_party/quic/platform/api/quic_export.h" namespace quic { @@ -15,7 +18,8 @@ // The sender uses this to inform the peer that the sender wished to // open a new stream but was blocked from doing so due due to the // maximum stream ID limit set by the peer (via a MAX_STREAM_ID frame) -struct QUIC_EXPORT_PRIVATE QuicStreamIdBlockedFrame : public QuicControlFrame { +struct QUIC_EXPORT_PRIVATE QuicStreamIdBlockedFrame + : public QuicInlinedFrame<QuicStreamIdBlockedFrame> { QuicStreamIdBlockedFrame(); QuicStreamIdBlockedFrame(QuicControlFrameId control_frame_id, QuicStreamId stream_id); @@ -24,6 +28,10 @@ std::ostream& os, const QuicStreamIdBlockedFrame& frame); + // A unique identifier of this control frame. 0 when this frame is received, + // and non-zero when sent. + QuicControlFrameId control_frame_id; + QuicStreamId stream_id; };
diff --git a/net/third_party/quic/core/frames/quic_window_update_frame.cc b/net/third_party/quic/core/frames/quic_window_update_frame.cc index cbd23442..2445ba8 100644 --- a/net/third_party/quic/core/frames/quic_window_update_frame.cc +++ b/net/third_party/quic/core/frames/quic_window_update_frame.cc
@@ -3,16 +3,18 @@ // found in the LICENSE file. #include "net/third_party/quic/core/frames/quic_window_update_frame.h" +#include "net/third_party/quic/core/quic_constants.h" namespace quic { -QuicWindowUpdateFrame::QuicWindowUpdateFrame() {} +QuicWindowUpdateFrame::QuicWindowUpdateFrame() + : control_frame_id(kInvalidControlFrameId) {} QuicWindowUpdateFrame::QuicWindowUpdateFrame( QuicControlFrameId control_frame_id, QuicStreamId stream_id, QuicStreamOffset byte_offset) - : QuicControlFrame(control_frame_id), + : control_frame_id(control_frame_id), stream_id(stream_id), byte_offset(byte_offset) {}
diff --git a/net/third_party/quic/core/frames/quic_window_update_frame.h b/net/third_party/quic/core/frames/quic_window_update_frame.h index 73b4448b..bc434f7 100644 --- a/net/third_party/quic/core/frames/quic_window_update_frame.h +++ b/net/third_party/quic/core/frames/quic_window_update_frame.h
@@ -7,7 +7,7 @@ #include <ostream> -#include "net/third_party/quic/core/frames/quic_control_frame.h" +#include "net/third_party/quic/core/quic_types.h" namespace quic { @@ -16,7 +16,7 @@ // than a window delta. // TODO(rjshade): A possible future optimization is to make stream_id and // byte_offset variable length, similar to stream frames. -struct QUIC_EXPORT_PRIVATE QuicWindowUpdateFrame : public QuicControlFrame { +struct QUIC_EXPORT_PRIVATE QuicWindowUpdateFrame { QuicWindowUpdateFrame(); QuicWindowUpdateFrame(QuicControlFrameId control_frame_id, QuicStreamId stream_id, @@ -26,6 +26,10 @@ std::ostream& os, const QuicWindowUpdateFrame& w); + // A unique identifier of this control frame. 0 when this frame is received, + // and non-zero when sent. + QuicControlFrameId control_frame_id; + // The stream this frame applies to. 0 is a special case meaning the overall // connection rather than a specific stream. QuicStreamId stream_id;
diff --git a/net/third_party/quic/core/http/quic_server_session_base.cc b/net/third_party/quic/core/http/quic_server_session_base.cc index 7778ab7..1326676 100644 --- a/net/third_party/quic/core/http/quic_server_session_base.cc +++ b/net/third_party/quic/core/http/quic_server_session_base.cc
@@ -8,6 +8,7 @@ #include "net/third_party/quic/core/quic_connection.h" #include "net/third_party/quic/core/quic_stream.h" #include "net/third_party/quic/platform/api/quic_bug_tracker.h" +#include "net/third_party/quic/platform/api/quic_flag_utils.h" #include "net/third_party/quic/platform/api/quic_flags.h" #include "net/third_party/quic/platform/api/quic_logging.h" #include "net/third_party/quic/platform/api/quic_string.h" @@ -216,12 +217,15 @@ QUIC_BUG << "Encryption not established so no outgoing stream created."; return false; } - if (GetNumOpenOutgoingStreams() >= max_open_outgoing_streams()) { - VLOG(1) << "No more streams should be created. " - << "Already " << GetNumOpenOutgoingStreams() << " open."; - return false; + if (!GetQuicFlag(FLAGS_quic_use_common_stream_check)) { + if (GetNumOpenOutgoingStreams() >= max_open_outgoing_streams()) { + VLOG(1) << "No more streams should be created. " + << "Already " << GetNumOpenOutgoingStreams() << " open."; + return false; + } } - return true; + QUIC_FLAG_COUNT_N(quic_use_common_stream_check, 2, 2); + return CanOpenNextOutgoingStream(); } QuicCryptoServerStreamBase* QuicServerSessionBase::GetMutableCryptoStream() {
diff --git a/net/third_party/quic/core/http/quic_spdy_client_session.cc b/net/third_party/quic/core/http/quic_spdy_client_session.cc index 042295c..68266ff 100644 --- a/net/third_party/quic/core/http/quic_spdy_client_session.cc +++ b/net/third_party/quic/core/http/quic_spdy_client_session.cc
@@ -9,6 +9,8 @@ #include "net/third_party/quic/core/http/spdy_utils.h" #include "net/third_party/quic/core/quic_server_id.h" #include "net/third_party/quic/platform/api/quic_bug_tracker.h" +#include "net/third_party/quic/platform/api/quic_flag_utils.h" +#include "net/third_party/quic/platform/api/quic_flags.h" #include "net/third_party/quic/platform/api/quic_logging.h" #include "net/third_party/quic/platform/api/quic_ptr_util.h" #include "net/third_party/quic/platform/api/quic_string.h" @@ -44,17 +46,26 @@ QUIC_DLOG(INFO) << "Encryption not active so no outgoing stream created."; return false; } - if (GetNumOpenOutgoingStreams() >= max_open_outgoing_streams()) { - QUIC_DLOG(INFO) << "Failed to create a new outgoing stream. " - << "Already " << GetNumOpenOutgoingStreams() << " open."; - return false; + if (!GetQuicFlag(FLAGS_quic_use_common_stream_check)) { + if (GetNumOpenOutgoingStreams() >= max_open_outgoing_streams()) { + QUIC_DLOG(INFO) << "Failed to create a new outgoing stream. " + << "Already " << GetNumOpenOutgoingStreams() << " open."; + return false; + } + if (goaway_received() && respect_goaway_) { + QUIC_DLOG(INFO) << "Failed to create a new outgoing stream. " + << "Already received goaway."; + return false; + } + return true; } if (goaway_received() && respect_goaway_) { QUIC_DLOG(INFO) << "Failed to create a new outgoing stream. " << "Already received goaway."; return false; } - return true; + QUIC_FLAG_COUNT_N(quic_use_common_stream_check, 1, 2); + return CanOpenNextOutgoingStream(); } QuicSpdyClientStream* QuicSpdyClientSession::CreateOutgoingDynamicStream() {
diff --git a/net/third_party/quic/core/http/spdy_utils.cc b/net/third_party/quic/core/http/spdy_utils.cc index 31e2d09..0477824 100644 --- a/net/third_party/quic/core/http/spdy_utils.cc +++ b/net/third_party/quic/core/http/spdy_utils.cc
@@ -14,10 +14,10 @@ #include "net/third_party/quic/platform/api/quic_string.h" #include "net/third_party/quic/platform/api/quic_string_piece.h" #include "net/third_party/quic/platform/api/quic_text_utils.h" -#include "net/third_party/quic/platform/api/quic_url_utils.h" #include "net/third_party/spdy/core/spdy_frame_builder.h" #include "net/third_party/spdy/core/spdy_framer.h" #include "net/third_party/spdy/core/spdy_protocol.h" +#include "url/gurl.h" using spdy::SpdyHeaderBlock; @@ -179,7 +179,7 @@ } QuicStringPiece path = it->second; - return QuicUrlUtils::GetPushPromiseUrl(scheme, authority, path); + return GetPushPromiseUrl(scheme, authority, path); } // static @@ -187,13 +187,13 @@ const SpdyHeaderBlock& headers) { // TODO(fayang): Consider just checking out the value of the ":authority" key // in headers. - return QuicUrlUtils::HostName(GetPromisedUrlFromHeaders(headers)); + return GURL(GetPromisedUrlFromHeaders(headers)).host(); } // static bool SpdyUtils::PromisedUrlIsValid(const SpdyHeaderBlock& headers) { QuicString url(GetPromisedUrlFromHeaders(headers)); - return !url.empty() && QuicUrlUtils::IsValidUrl(url); + return !url.empty() && GURL(url).is_valid(); } // static @@ -217,4 +217,137 @@ return true; } +// static +QuicString SpdyUtils::GetPushPromiseUrl(QuicStringPiece scheme, + QuicStringPiece authority, + QuicStringPiece path) { + // RFC 7540, Section 8.1.2.3: The ":path" pseudo-header field includes the + // path and query parts of the target URI (the "path-absolute" production + // and optionally a '?' character followed by the "query" production (see + // Sections 3.3 and 3.4 of RFC3986). A request in asterisk form includes the + // value '*' for the ":path" pseudo-header field. + // + // This pseudo-header field MUST NOT be empty for "http" or "https" URIs; + // "http" or "https" URIs that do not contain a path MUST include a value of + // '/'. The exception to this rule is an OPTIONS request for an "http" or + // "https" URI that does not include a path component; these MUST include a + // ":path" pseudo-header with a value of '*' (see RFC7230, Section 5.3.4). + // + // In addition to the above restriction from RFC 7540, note that RFC3986 + // defines the "path-absolute" construction as starting with "/" but not "//". + // + // RFC 7540, Section 8.2.1: The header fields in PUSH_PROMISE and any + // subsequent CONTINUATION frames MUST be a valid and complete set of request + // header fields (Section 8.1.2.3). The server MUST include a method in the + // ":method" pseudo-header field that is safe and cacheable. + // + // RFC 7231, Section 4.2.1: + // ... this specification defines GET, HEAD, and POST as cacheable, ... + // + // Since the OPTIONS method is not cacheable, it cannot be the method of a + // PUSH_PROMISE. Therefore, the exception mentioned in RFC 7540, Section + // 8.1.2.3 about OPTIONS requests does not apply here (i.e. ":path" cannot be + // "*"). + if (path.empty() || path[0] != '/' || (path.size() >= 2 && path[1] == '/')) { + return QuicString(); + } + + // Validate the scheme; this is to ensure a scheme of "foo://bar" is not + // parsed as a URL of "foo://bar://baz" when combined with a host of "baz". + std::string canonical_scheme; + url::StdStringCanonOutput canon_output(&canonical_scheme); + url::Component canon_component; + url::Component scheme_component(0, scheme.size()); + + if (!url::CanonicalizeScheme(scheme.data(), scheme_component, &canon_output, + &canon_component) || + !canon_component.is_nonempty() || canon_component.begin != 0) { + return QuicString(); + } + canonical_scheme.resize(canon_component.len + 1); + + // Validate the authority; this is to ensure an authority such as + // "host/path" is not accepted, as when combined with a scheme like + // "http://", could result in a URL of "http://host/path". + url::Component auth_component(0, authority.size()); + url::Component username_component; + url::Component password_component; + url::Component host_component; + url::Component port_component; + + url::ParseAuthority(authority.data(), auth_component, &username_component, + &password_component, &host_component, &port_component); + + // RFC 7540, Section 8.1.2.3: The authority MUST NOT include the deprecated + // "userinfo" subcomponent for "http" or "https" schemed URIs. + // + // Note: Although |canonical_scheme| has not yet been checked for that, as + // it is performed later in processing, only "http" and "https" schemed + // URIs are supported for PUSH. + if (username_component.is_valid() || password_component.is_valid()) { + return QuicString(); + } + + // Failed parsing or no host present. ParseAuthority() will ensure that + // host_component + port_component cover the entire string, if + // username_component and password_component are not present. + if (!host_component.is_nonempty()) { + return QuicString(); + } + + // Validate the port (if present; it's optional). + int parsed_port_number = url::PORT_INVALID; + if (port_component.is_nonempty()) { + parsed_port_number = url::ParsePort(authority.data(), port_component); + if (parsed_port_number < 0 && parsed_port_number != url::PORT_UNSPECIFIED) { + return QuicString(); + } + } + + // Validate the host by attempting to canoncalize it. Invalid characters + // will result in a canonicalization failure (e.g. '/') + std::string canon_host; + canon_output = url::StdStringCanonOutput(&canon_host); + canon_component.reset(); + if (!url::CanonicalizeHost(authority.data(), host_component, &canon_output, + &canon_component) || + !canon_component.is_nonempty() || canon_component.begin != 0) { + return QuicString(); + } + + // At this point, "authority" has been validated to either be of the form + // 'host:port' or 'host', with 'host' being a valid domain or IP address, + // and 'port' (if present), being a valid port. Attempt to construct a + // URL of just the (scheme, host, port), which should be safe and will not + // result in ambiguous parsing. + // + // This also enforces that all PUSHed URLs are either HTTP or HTTPS-schemed + // URIs, consistent with the other restrictions enforced above. + // + // Note: url::CanonicalizeScheme() will have added the ':' to + // |canonical_scheme|. + GURL origin_url(canonical_scheme + "//" + std::string(authority)); + if (!origin_url.is_valid() || !origin_url.SchemeIsHTTPOrHTTPS() || + // The following checks are merely defense in depth. + origin_url.has_username() || origin_url.has_password() || + (origin_url.has_path() && origin_url.path_piece() != "/") || + origin_url.has_query() || origin_url.has_ref()) { + return QuicString(); + } + + // Attempt to parse the path. + std::string spec = origin_url.GetWithEmptyPath().spec(); + spec.pop_back(); // Remove the '/', as ":path" must contain it. + spec.append(std::string(path)); + + // Attempt to parse the full URL, with the path as well. Ensure there is no + // fragment to the query. + GURL full_url(spec); + if (!full_url.is_valid() || full_url.has_ref()) { + return QuicString(); + } + + return full_url.spec(); +} + } // namespace quic
diff --git a/net/third_party/quic/core/http/spdy_utils.h b/net/third_party/quic/core/http/spdy_utils.h index ec1bf11..1a5881a5 100644 --- a/net/third_party/quic/core/http/spdy_utils.h +++ b/net/third_party/quic/core/http/spdy_utils.h
@@ -56,6 +56,13 @@ // which must be fully-qualified. static bool PopulateHeaderBlockFromUrl(const QuicString url, spdy::SpdyHeaderBlock* headers); + + // Returns a canonical, valid URL for a PUSH_PROMISE with the specified + // ":scheme", ":authority", and ":path" header fields, or an empty + // string if the resulting URL is not valid or supported. + static QuicString GetPushPromiseUrl(QuicStringPiece scheme, + QuicStringPiece authority, + QuicStringPiece path); }; } // namespace quic
diff --git a/net/third_party/quic/core/http/spdy_utils_test.cc b/net/third_party/quic/core/http/spdy_utils_test.cc index 3c6b618..b6bf144 100644 --- a/net/third_party/quic/core/http/spdy_utils_test.cc +++ b/net/third_party/quic/core/http/spdy_utils_test.cc
@@ -6,6 +6,7 @@ #include "base/macros.h" #include "net/third_party/quic/core/http/spdy_utils.h" +#include "net/third_party/quic/platform/api/quic_arraysize.h" #include "net/third_party/quic/platform/api/quic_string.h" #include "net/third_party/quic/platform/api/quic_string_piece.h" #include "net/third_party/quic/platform/api/quic_test.h" @@ -380,5 +381,121 @@ SpdyUtils::PopulateHeaderBlockFromUrl("www.google.com/", &headers)); } +using PushPromiseUrlTest = QuicTest; + +TEST_F(PushPromiseUrlTest, GetPushPromiseUrl) { + // Test rejection of various inputs. + EXPECT_EQ("", + SpdyUtils::GetPushPromiseUrl("file", "localhost", "/etc/password")); + EXPECT_EQ("", SpdyUtils::GetPushPromiseUrl("file", "", + "/C:/Windows/System32/Config/")); + EXPECT_EQ("", + SpdyUtils::GetPushPromiseUrl("", "https://www.google.com", "/")); + + EXPECT_EQ("", SpdyUtils::GetPushPromiseUrl("https://www.google.com", + "www.google.com", "/")); + EXPECT_EQ("", + SpdyUtils::GetPushPromiseUrl("https://", "www.google.com", "/")); + EXPECT_EQ("", SpdyUtils::GetPushPromiseUrl("https", "", "/")); + EXPECT_EQ("", SpdyUtils::GetPushPromiseUrl("https", "", "www.google.com/")); + EXPECT_EQ("", SpdyUtils::GetPushPromiseUrl("https", "www.google.com/", "/")); + EXPECT_EQ("", SpdyUtils::GetPushPromiseUrl("https", "www.google.com", "")); + EXPECT_EQ("", SpdyUtils::GetPushPromiseUrl("https", "www.google", ".com/")); + + // Test acception/rejection of various input combinations. + // |input_headers| is an array of pairs. The first value of each pair is a + // string that will be used as one of the inputs of GetPushPromiseUrl(). The + // second value of each pair is a bitfield where the lowest 3 bits indicate + // for which headers that string is valid (in a PUSH_PROMISE). For example, + // the string "http" would be valid for both the ":scheme" and ":authority" + // headers, so the bitfield paired with it is set to SCHEME | AUTH. + const unsigned char SCHEME = (1u << 0); + const unsigned char AUTH = (1u << 1); + const unsigned char PATH = (1u << 2); + const std::pair<const char*, unsigned char> input_headers[] = { + {"http", SCHEME | AUTH}, + {"https", SCHEME | AUTH}, + {"hTtP", SCHEME | AUTH}, + {"HTTPS", SCHEME | AUTH}, + {"www.google.com", AUTH}, + {"90af90e0", AUTH}, + {"12foo%20-bar:00001233", AUTH}, + {"GOO\u200b\u2060\ufeffgoo", AUTH}, + {"192.168.0.5", AUTH}, + {"[::ffff:192.168.0.1.]", AUTH}, + {"http:", AUTH}, + {"bife l", AUTH}, + {"/", PATH}, + {"/foo/bar/baz", PATH}, + {"/%20-2DVdkj.cie/foe_.iif/", PATH}, + {"http://", 0}, + {":443", 0}, + {":80/eddd", 0}, + {"google.com:-0", 0}, + {"google.com:65536", 0}, + {"http://google.com", 0}, + {"http://google.com:39", 0}, + {"//google.com/foo", 0}, + {".com/", 0}, + {"http://www.google.com/", 0}, + {"http://foo:439", 0}, + {"[::ffff:192.168", 0}, + {"]/", 0}, + {"//", 0}}; + for (size_t i = 0; i < QUIC_ARRAYSIZE(input_headers); ++i) { + bool should_accept = (input_headers[i].second & SCHEME); + for (size_t j = 0; j < QUIC_ARRAYSIZE(input_headers); ++j) { + bool should_accept_2 = should_accept && (input_headers[j].second & AUTH); + for (size_t k = 0; k < QUIC_ARRAYSIZE(input_headers); ++k) { + // |should_accept_3| indicates whether or not GetPushPromiseUrl() is + // expected to accept this input combination. + bool should_accept_3 = + should_accept_2 && (input_headers[k].second & PATH); + + std::string url = SpdyUtils::GetPushPromiseUrl(input_headers[i].first, + input_headers[j].first, + input_headers[k].first); + + ::testing::AssertionResult result = ::testing::AssertionSuccess(); + if (url.empty() == should_accept_3) { + result = ::testing::AssertionFailure() + << "GetPushPromiseUrl() accepted/rejected the inputs when " + "it shouldn't have." + << std::endl + << " scheme: " << input_headers[i].first << std::endl + << " authority: " << input_headers[j].first << std::endl + << " path: " << input_headers[k].first << std::endl + << "Output: " << url << std::endl; + } + ASSERT_TRUE(result); + } + } + } + + // Test canonicalization of various valid inputs. + EXPECT_EQ("http://www.google.com/", + SpdyUtils::GetPushPromiseUrl("http", "www.google.com", "/")); + EXPECT_EQ( + "https://www.goo-gle.com/fOOo/baRR", + SpdyUtils::GetPushPromiseUrl("hTtPs", "wWw.gOo-gLE.cOm", "/fOOo/baRR")); + EXPECT_EQ("https://www.goo-gle.com:3278/pAth/To/reSOurce", + SpdyUtils::GetPushPromiseUrl("hTtPs", "Www.gOo-Gle.Com:000003278", + "/pAth/To/reSOurce")); + EXPECT_EQ("https://foo%20bar/foo/bar/baz", + SpdyUtils::GetPushPromiseUrl("https", "foo bar", "/foo/bar/baz")); + EXPECT_EQ("http://foo.com:70/e/", + SpdyUtils::GetPushPromiseUrl("http", "foo.com:0000070", "/e/")); + EXPECT_EQ( + "http://192.168.0.1:70/e/", + SpdyUtils::GetPushPromiseUrl("http", "0300.0250.00.01:0070", "/e/")); + EXPECT_EQ("http://192.168.0.1/e/", + SpdyUtils::GetPushPromiseUrl("http", "0xC0a80001", "/e/")); + EXPECT_EQ("http://[::c0a8:1]/", + SpdyUtils::GetPushPromiseUrl("http", "[::192.168.0.1]", "/")); + EXPECT_EQ( + "https://[::ffff:c0a8:1]/", + SpdyUtils::GetPushPromiseUrl("https", "[::ffff:0xC0.0Xa8.0x0.0x1]", "/")); +} + } // namespace test } // namespace quic
diff --git a/net/third_party/quic/core/qpack/qpack_constants.h b/net/third_party/quic/core/qpack/qpack_constants.h index 6ae0c9f..585577d 100644 --- a/net/third_party/quic/core/qpack/qpack_constants.h +++ b/net/third_party/quic/core/qpack/qpack_constants.h
@@ -9,8 +9,39 @@ namespace quic { +// TODO(bnc): Move this into HpackVarintEncoder. +// The integer encoder can encode up to 2^64-1, which can take up to 10 bytes +// (each carrying 7 bits) after the prefix. +const uint8_t kMaxExtensionBytesForVarintEncoding = 10; + // Wire format defined in -// https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#rfc.section.5.4.2. +// https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#rfc.section.5 + +// Encoder stream + +// 5.2.1 Insert With Name Reference +const uint8_t kInsertWithNameReferenceOpcode = 0b10000000; +const uint8_t kInsertWithNameReferenceOpcodeMask = 0b10000000; +const uint8_t kInsertWithNameReferenceStaticBit = 0b01000000; +const uint8_t kInsertWithNameReferenceNameIndexPrefixLength = 6; + +// 5.2.2 Insert Without Name Reference +const uint8_t kInsertWithoutNameReferenceOpcode = 0b01000000; +const uint8_t kInsertWithoutNameReferenceOpcodeMask = 0b11000000; +const uint8_t kInsertWithoutNameReferenceNameHuffmanBit = 0b00100000; +const uint8_t kInsertWithoutNameReferenceNameLengthPrefixLength = 5; + +// 5.2.3 Duplicate +const uint8_t kDuplicateOpcode = 0b00000000; +const uint8_t kDuplicateOpcodeMask = 0b11100000; +const uint8_t kDuplicateIndexPrefixLength = 5; + +// 5.2.4 Dynamic Table Size Update +const uint8_t kDynamicTableSizeUpdateOpcode = 0b00100000; +const uint8_t kDynamicTableSizeUpdateOpcodeMask = 0b11100000; +const uint8_t kDynamicTableSizeUpdateMaxSizePrefixLength = 5; + +// Request and push streams // 5.4.2.1. Indexed Header Field const uint8_t kIndexedHeaderFieldOpcode = 0b10000000;
diff --git a/net/third_party/quic/core/qpack/qpack_decoder.cc b/net/third_party/quic/core/qpack/qpack_decoder.cc index e269855..13d1fc1 100644 --- a/net/third_party/quic/core/qpack/qpack_decoder.cc +++ b/net/third_party/quic/core/qpack/qpack_decoder.cc
@@ -45,8 +45,11 @@ case State::kVarintDone: DoVarintDone(); break; - case State::kNameString: - bytes_consumed = DoNameString(data); + case State::kReadName: + bytes_consumed = DoReadName(data); + break; + case State::kDecodeName: + DoDecodeName(); break; case State::kValueLengthStart: bytes_consumed = DoValueLengthStart(data); @@ -57,8 +60,11 @@ case State::kValueLengthDone: DoValueLengthDone(); break; - case State::kValueString: - bytes_consumed = DoValueString(data); + case State::kReadValue: + bytes_consumed = DoReadValue(data); + break; + case State::kDecodeValue: + DoDecodeValue(); break; case State::kDone: DoDone(); @@ -76,7 +82,8 @@ // Stop processing if no more data but next state would require it. if (data.empty() && (state_ != State::kVarintDone) && - (state_ != State::kValueLengthDone) && (state_ != State::kDone)) { + (state_ != State::kDecodeName) && (state_ != State::kValueLengthDone) && + (state_ != State::kDecodeValue) && (state_ != State::kDone)) { return; } } @@ -190,7 +197,12 @@ name_length_ = varint_decoder_.value(); name_.clear(); name_.reserve(name_length_); - state_ = State::kNameString; + // Do not handle empty names differently. (They are probably forbidden by + // higher layers, but it is not enforced in this class.) If there is no + // more data to read, then processing stalls, but the instruction is not + // complete without the value, so OnHeaderDecoded() could not be called yet + // anyway. + state_ = State::kReadName; return; } @@ -212,17 +224,23 @@ state_ = State::kStart; } -size_t QpackDecoder::ProgressiveDecoder::DoNameString(QuicStringPiece data) { +size_t QpackDecoder::ProgressiveDecoder::DoReadName(QuicStringPiece data) { DCHECK(!data.empty()); + // |name_length_| might be zero. DCHECK_LE(name_.size(), name_length_); size_t bytes_consumed = std::min(name_length_ - name_.size(), data.size()); name_.append(data.data(), bytes_consumed); - if (name_.size() < name_length_) { - return bytes_consumed; + DCHECK_LE(name_.size(), name_length_); + if (name_.size() == name_length_) { + state_ = State::kDecodeName; } + return bytes_consumed; +} + +void QpackDecoder::ProgressiveDecoder::DoDecodeName() { DCHECK_EQ(name_.size(), name_length_); if (is_huffman_) { @@ -232,13 +250,12 @@ huffman_decoder_.Decode(name_, &decoded_name); if (!huffman_decoder_.InputProperlyTerminated()) { OnError("Error in Huffman-encoded name."); - return bytes_consumed; + return; } name_ = decoded_name; } state_ = State::kValueLengthStart; - return bytes_consumed; } size_t QpackDecoder::ProgressiveDecoder::DoValueLengthStart( @@ -293,26 +310,34 @@ value_.clear(); value_length_ = varint_decoder_.value(); + // If value is empty, skip DoReadValue() and DoDecodeValue() and jump directly + // to DoDone(). This is so that OnHeaderDecoded() is called even if there is + // no more data. if (value_length_ == 0) { state_ = State::kDone; return; } value_.reserve(value_length_); - state_ = State::kValueString; + state_ = State::kReadValue; } -size_t QpackDecoder::ProgressiveDecoder::DoValueString(QuicStringPiece data) { +size_t QpackDecoder::ProgressiveDecoder::DoReadValue(QuicStringPiece data) { DCHECK(!data.empty()); + DCHECK_LT(0u, value_length_); DCHECK_LT(value_.size(), value_length_); size_t bytes_consumed = std::min(value_length_ - value_.size(), data.size()); value_.append(data.data(), bytes_consumed); - if (value_.size() < value_length_) { - return bytes_consumed; + DCHECK_LE(value_.size(), value_length_); + if (value_.size() == value_length_) { + state_ = State::kDecodeValue; } + return bytes_consumed; +} +void QpackDecoder::ProgressiveDecoder::DoDecodeValue() { DCHECK_EQ(value_.size(), value_length_); if (is_huffman_) { @@ -322,13 +347,12 @@ huffman_decoder_.Decode(value_, &decoded_value); if (!huffman_decoder_.InputProperlyTerminated()) { OnError("Error in Huffman-encoded value."); - return bytes_consumed; + return; } value_ = decoded_value; } state_ = State::kDone; - return bytes_consumed; } void QpackDecoder::ProgressiveDecoder::DoDone() {
diff --git a/net/third_party/quic/core/qpack/qpack_decoder.h b/net/third_party/quic/core/qpack/qpack_decoder.h index 1aa554a..3d8e0cb5 100644 --- a/net/third_party/quic/core/qpack/qpack_decoder.h +++ b/net/third_party/quic/core/qpack/qpack_decoder.h
@@ -70,14 +70,18 @@ kStart, kVarintResume, kVarintDone, - // This might be followed by the name as a string literal. - kNameString, + // This might be followed by the name as a string literal, + // optionally Huffman encoded. + kReadName, + kDecodeName, // This might be followed by the length of the value. kValueLengthStart, kValueLengthResume, kValueLengthDone, - // This might be followed by the value as a string literal. - kValueString, + // This might be followed by the value as a string literal, + // optionally Huffman encoded. + kReadValue, + kDecodeValue, kDone, }; @@ -86,11 +90,13 @@ size_t DoStart(QuicStringPiece data); size_t DoVarintResume(QuicStringPiece data); void DoVarintDone(); - size_t DoNameString(QuicStringPiece data); + size_t DoReadName(QuicStringPiece data); + void DoDecodeName(); size_t DoValueLengthStart(QuicStringPiece data); size_t DoValueLengthResume(QuicStringPiece data); void DoValueLengthDone(); - size_t DoValueString(QuicStringPiece data); + size_t DoReadValue(QuicStringPiece data); + void DoDecodeValue(); void DoDone(); void OnError(QuicStringPiece error_message);
diff --git a/net/third_party/quic/core/qpack/qpack_encoder.cc b/net/third_party/quic/core/qpack/qpack_encoder.cc index 0b5a77d..eee1f9d 100644 --- a/net/third_party/quic/core/qpack/qpack_encoder.cc +++ b/net/third_party/quic/core/qpack/qpack_encoder.cc
@@ -299,7 +299,7 @@ } // namespace std::unique_ptr<spdy::HpackEncoder::ProgressiveEncoder> -QpackEncoder::EncodeHeaderSet(const spdy::SpdyHeaderBlock* header_list) { +QpackEncoder::EncodeHeaderList(const spdy::SpdyHeaderBlock* header_list) { return std::make_unique<QpackProgressiveEncoder>(&header_table_, header_list); }
diff --git a/net/third_party/quic/core/qpack/qpack_encoder.h b/net/third_party/quic/core/qpack/qpack_encoder.h index 641753f..a8f4825 100644 --- a/net/third_party/quic/core/qpack/qpack_encoder.h +++ b/net/third_party/quic/core/qpack/qpack_encoder.h
@@ -22,10 +22,10 @@ // encoder stream, and receive data on the decoder stream. class QUIC_EXPORT_PRIVATE QpackEncoder { public: - // This factory method should be called to start encoding. + // This factory method should be called to start encoding a header list. // |*header_list| must remain valid and must not change // during the lifetime of the returned ProgressiveEncoder instance. - std::unique_ptr<spdy::HpackEncoder::ProgressiveEncoder> EncodeHeaderSet( + std::unique_ptr<spdy::HpackEncoder::ProgressiveEncoder> EncodeHeaderList( const spdy::SpdyHeaderBlock* header_list); private:
diff --git a/net/third_party/quic/core/qpack/qpack_encoder_stream_receiver.cc b/net/third_party/quic/core/qpack/qpack_encoder_stream_receiver.cc new file mode 100644 index 0000000..628a2e8 --- /dev/null +++ b/net/third_party/quic/core/qpack/qpack_encoder_stream_receiver.cc
@@ -0,0 +1,393 @@ +// Copyright (c) 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/third_party/quic/core/qpack/qpack_encoder_stream_receiver.h" + +#include "net/third_party/http2/decoder/decode_buffer.h" +#include "net/third_party/http2/decoder/decode_status.h" +#include "net/third_party/quic/core/qpack/qpack_constants.h" + +namespace quic { + +QpackEncoderStreamReceiver::QpackEncoderStreamReceiver(Delegate* delegate) + : delegate_(delegate), + state_(State::kStart), + is_huffman_(false), + is_static_(false), + literal_name_(false), + name_index_(0), + name_length_(0), + value_length_(0), + error_detected_(false) { + DCHECK(delegate_); +} + +void QpackEncoderStreamReceiver::Decode(QuicStringPiece data) { + while (!error_detected_) { + size_t bytes_consumed = 0; + + switch (state_) { + case State::kStart: + bytes_consumed = DoStart(data); + break; + case State::kNameIndexOrLengthResume: + bytes_consumed = DoNameIndexOrLengthResume(data); + break; + case State::kNameIndexOrLengthDone: + DoNameIndexOrLengthDone(); + break; + case State::kReadName: + bytes_consumed = DoReadName(data); + break; + case State::kDecodeName: + DoDecodeName(); + break; + case State::kValueLengthStart: + bytes_consumed = DoValueLengthStart(data); + break; + case State::kValueLengthResume: + bytes_consumed = DoValueLengthResume(data); + break; + case State::kValueLengthDone: + DoValueLengthDone(); + break; + case State::kReadValue: + bytes_consumed = DoReadValue(data); + break; + case State::kDecodeValue: + DoDecodeValue(); + break; + case State::kInsertDone: + DoInsertDone(); + break; + case State::kIndexResume: + bytes_consumed = DoIndexResume(data); + break; + case State::kIndexDone: + DoIndexDone(); + break; + case State::kMaxSizeResume: + bytes_consumed = DoMaxSizeResume(data); + break; + case State::kMaxSizeDone: + DoMaxSizeDone(); + break; + } + + DCHECK_LE(bytes_consumed, data.size()); + + data = QuicStringPiece(data.data() + bytes_consumed, + data.size() - bytes_consumed); + + // Stop processing if no more data but next state would require it. + if (data.empty() && (state_ != State::kNameIndexOrLengthDone) && + (state_ != State::kDecodeName) && (state_ != State::kValueLengthDone) && + (state_ != State::kDecodeValue) && (state_ != State::kInsertDone) && + (state_ != State::kIndexDone) && (state_ != State::kMaxSizeDone)) { + return; + } + } +} + +size_t QpackEncoderStreamReceiver::DoStart(QuicStringPiece data) { + DCHECK(!data.empty()); + + size_t prefix_length; + State state_varint_in_progress; + State state_varint_done; + if ((data[0] & kInsertWithNameReferenceOpcodeMask) == + kInsertWithNameReferenceOpcode) { + is_static_ = (data[0] & kInsertWithNameReferenceStaticBit) == + kInsertWithNameReferenceStaticBit; + + prefix_length = kInsertWithNameReferenceNameIndexPrefixLength; + literal_name_ = false; + state_varint_in_progress = State::kNameIndexOrLengthResume; + state_varint_done = State::kNameIndexOrLengthDone; + } else if ((data[0] & kInsertWithoutNameReferenceOpcodeMask) == + kInsertWithoutNameReferenceOpcode) { + is_huffman_ = (data[0] & kInsertWithoutNameReferenceNameHuffmanBit) == + kInsertWithoutNameReferenceNameHuffmanBit; + prefix_length = kInsertWithoutNameReferenceNameLengthPrefixLength; + literal_name_ = true; + state_varint_in_progress = State::kNameIndexOrLengthResume; + state_varint_done = State::kNameIndexOrLengthDone; + } else if ((data[0] & kDuplicateOpcodeMask) == kDuplicateOpcode) { + prefix_length = kDuplicateIndexPrefixLength; + state_varint_in_progress = State::kIndexResume; + state_varint_done = State::kIndexDone; + } else { + DCHECK_EQ(kDynamicTableSizeUpdateOpcode, + data[0] & kDynamicTableSizeUpdateOpcodeMask); + + prefix_length = kDynamicTableSizeUpdateMaxSizePrefixLength; + state_varint_in_progress = State::kMaxSizeResume; + state_varint_done = State::kMaxSizeDone; + } + + http2::DecodeBuffer buffer(data.data() + 1, data.size() - 1); + http2::DecodeStatus status = + varint_decoder_.Start(data[0], prefix_length, &buffer); + + switch (status) { + case http2::DecodeStatus::kDecodeDone: + state_ = state_varint_done; + break; + case http2::DecodeStatus::kDecodeInProgress: + DCHECK(buffer.Empty()); + state_ = state_varint_in_progress; + break; + case http2::DecodeStatus::kDecodeError: + OnError("Encoded integer too large."); + break; + } + return 1 + buffer.Offset(); +} + +size_t QpackEncoderStreamReceiver::DoNameIndexOrLengthResume( + QuicStringPiece data) { + DCHECK(!data.empty()); + + http2::DecodeBuffer buffer(data); + http2::DecodeStatus status = varint_decoder_.Resume(&buffer); + + switch (status) { + case http2::DecodeStatus::kDecodeDone: + state_ = State::kNameIndexOrLengthDone; + break; + case http2::DecodeStatus::kDecodeInProgress: + DCHECK(buffer.Empty()); + break; + case http2::DecodeStatus::kDecodeError: + OnError("Encoded integer too large."); + break; + } + return buffer.Offset(); +} + +void QpackEncoderStreamReceiver::DoNameIndexOrLengthDone() { + DCHECK(name_.empty()); + + if (literal_name_) { + name_length_ = varint_decoder_.value(); + name_.reserve(name_length_); + // Do not handle empty names differently. (They are probably forbidden by + // higher layers, but it is not enforced in this class.) If there is no + // more data to read, then processing stalls, but the instruction is not + // complete without the value, so OnInsertWithoutNameReference() could not + // be called yet anyway. + state_ = State::kReadName; + return; + } + + name_index_ = varint_decoder_.value(); + state_ = State::kValueLengthStart; +} + +size_t QpackEncoderStreamReceiver::DoReadName(QuicStringPiece data) { + DCHECK(!data.empty()); + // |name_length_| might be zero. + DCHECK_LE(name_.size(), name_length_); + + size_t bytes_consumed = std::min(name_length_ - name_.size(), data.size()); + name_.append(data.data(), bytes_consumed); + + DCHECK_LE(name_.size(), name_length_); + if (name_.size() == name_length_) { + state_ = State::kDecodeName; + } + + return bytes_consumed; +} + +void QpackEncoderStreamReceiver::DoDecodeName() { + DCHECK_EQ(name_.size(), name_length_); + + if (is_huffman_) { + huffman_decoder_.Reset(); + // HpackHuffmanDecoder::Decode() cannot perform in-place decoding. + QuicString decoded_name; + huffman_decoder_.Decode(name_, &decoded_name); + if (!huffman_decoder_.InputProperlyTerminated()) { + OnError("Error in Huffman-encoded name."); + return; + } + name_ = decoded_name; + } + + state_ = State::kValueLengthStart; +} + +size_t QpackEncoderStreamReceiver::DoValueLengthStart(QuicStringPiece data) { + DCHECK(!data.empty()); + + is_huffman_ = + (data[0] & kLiteralValueHuffmanMask) == kLiteralValueHuffmanMask; + + http2::DecodeBuffer buffer(data.data() + 1, data.size() - 1); + http2::DecodeStatus status = + varint_decoder_.Start(data[0], kLiteralValuePrefixLength, &buffer); + + switch (status) { + case http2::DecodeStatus::kDecodeDone: + state_ = State::kValueLengthDone; + break; + case http2::DecodeStatus::kDecodeInProgress: + DCHECK(buffer.Empty()); + state_ = State::kValueLengthResume; + break; + case http2::DecodeStatus::kDecodeError: + OnError("ValueLen too large."); + break; + } + return 1 + buffer.Offset(); +} + +size_t QpackEncoderStreamReceiver::DoValueLengthResume(QuicStringPiece data) { + DCHECK(!data.empty()); + + http2::DecodeBuffer buffer(data.data() + 1, data.size() - 1); + http2::DecodeStatus status = + varint_decoder_.Start(data[0], kLiteralValuePrefixLength, &buffer); + + switch (status) { + case http2::DecodeStatus::kDecodeDone: + state_ = State::kValueLengthDone; + break; + case http2::DecodeStatus::kDecodeInProgress: + DCHECK(buffer.Empty()); + break; + case http2::DecodeStatus::kDecodeError: + OnError("ValueLen too large."); + break; + } + return 1 + buffer.Offset(); +} + +void QpackEncoderStreamReceiver::DoValueLengthDone() { + DCHECK(value_.empty()); + + value_length_ = varint_decoder_.value(); + + // If value is empty, skip DoReadValue() and DoDecodeValue() and jump directly + // to DoInsertDone(). This is so that OnInsertName*() is called even if there + // is no more data. + if (value_length_ == 0) { + state_ = State::kInsertDone; + return; + } + + value_.reserve(value_length_); + state_ = State::kReadValue; +} + +size_t QpackEncoderStreamReceiver::DoReadValue(QuicStringPiece data) { + DCHECK(!data.empty()); + DCHECK_LT(0u, value_length_); + DCHECK_LT(value_.size(), value_length_); + + size_t bytes_consumed = std::min(value_length_ - value_.size(), data.size()); + value_.append(data.data(), bytes_consumed); + + DCHECK_LE(value_.size(), value_length_); + if (value_.size() == value_length_) { + state_ = State::kDecodeValue; + } + + return bytes_consumed; +} + +void QpackEncoderStreamReceiver::DoDecodeValue() { + DCHECK_EQ(value_.size(), value_length_); + + if (is_huffman_) { + huffman_decoder_.Reset(); + // HpackHuffmanDecoder::Decode() cannot perform in-place decoding. + QuicString decoded_value; + huffman_decoder_.Decode(value_, &decoded_value); + if (!huffman_decoder_.InputProperlyTerminated()) { + OnError("Error in Huffman-encoded value."); + return; + } + value_ = decoded_value; + } + + state_ = State::kInsertDone; +} + +void QpackEncoderStreamReceiver::DoInsertDone() { + if (literal_name_) { + delegate_->OnInsertWithoutNameReference(name_, value_); + name_.clear(); + value_.clear(); + } else { + delegate_->OnInsertWithNameReference(is_static_, name_index_, value_); + value_.clear(); + } + + state_ = State::kStart; +} + +size_t QpackEncoderStreamReceiver::DoIndexResume(QuicStringPiece data) { + DCHECK(!data.empty()); + + http2::DecodeBuffer buffer(data.data() + 1, data.size() - 1); + http2::DecodeStatus status = + varint_decoder_.Start(data[0], kLiteralValuePrefixLength, &buffer); + + switch (status) { + case http2::DecodeStatus::kDecodeDone: + state_ = State::kIndexDone; + break; + case http2::DecodeStatus::kDecodeInProgress: + DCHECK(buffer.Empty()); + break; + case http2::DecodeStatus::kDecodeError: + OnError("Index too large."); + break; + } + return 1 + buffer.Offset(); +} + +void QpackEncoderStreamReceiver::DoIndexDone() { + delegate_->OnDuplicate(varint_decoder_.value()); + + state_ = State::kStart; +} + +size_t QpackEncoderStreamReceiver::DoMaxSizeResume(QuicStringPiece data) { + DCHECK(!data.empty()); + + http2::DecodeBuffer buffer(data.data() + 1, data.size() - 1); + http2::DecodeStatus status = + varint_decoder_.Start(data[0], kLiteralValuePrefixLength, &buffer); + + switch (status) { + case http2::DecodeStatus::kDecodeDone: + state_ = State::kMaxSizeDone; + break; + case http2::DecodeStatus::kDecodeInProgress: + DCHECK(buffer.Empty()); + break; + case http2::DecodeStatus::kDecodeError: + OnError("Maximum table size too large."); + break; + } + return 1 + buffer.Offset(); +} + +void QpackEncoderStreamReceiver::DoMaxSizeDone() { + delegate_->OnDynamicTableSizeUpdate(varint_decoder_.value()); + + state_ = State::kStart; +} + +void QpackEncoderStreamReceiver::OnError(QuicStringPiece error_message) { + DCHECK(!error_detected_); + + error_detected_ = true; + delegate_->OnErrorDetected(error_message); +} + +} // namespace quic
diff --git a/net/third_party/quic/core/qpack/qpack_encoder_stream_receiver.h b/net/third_party/quic/core/qpack/qpack_encoder_stream_receiver.h new file mode 100644 index 0000000..55d47440 --- /dev/null +++ b/net/third_party/quic/core/qpack/qpack_encoder_stream_receiver.h
@@ -0,0 +1,138 @@ +// Copyright (c) 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_THIRD_PARTY_QUIC_CORE_QPACK_QPACK_ENCODER_STREAM_RECEIVER_H_ +#define NET_THIRD_PARTY_QUIC_CORE_QPACK_QPACK_ENCODER_STREAM_RECEIVER_H_ + +#include <cstddef> +#include <cstdint> + +#include "net/third_party/http2/hpack/huffman/hpack_huffman_decoder.h" +#include "net/third_party/http2/hpack/varint/hpack_varint_decoder.h" +#include "net/third_party/quic/platform/api/quic_export.h" +#include "net/third_party/quic/platform/api/quic_string.h" +#include "net/third_party/quic/platform/api/quic_string_piece.h" + +namespace quic { + +// This class decodes data received on the encoder stream. +class QUIC_EXPORT_PRIVATE QpackEncoderStreamReceiver { + public: + // An interface for handling instructions decoded from the encoder stream, see + // https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#rfc.section.5.2 + class Delegate { + public: + virtual ~Delegate() = default; + + // 5.2.1. Insert With Name Reference + virtual void OnInsertWithNameReference(bool is_static, + uint64_t name_index, + QuicStringPiece value) = 0; + // 5.2.2. Insert Without Name Reference + virtual void OnInsertWithoutNameReference(QuicStringPiece name, + QuicStringPiece value) = 0; + // 5.2.3. Duplicate + virtual void OnDuplicate(uint64_t index) = 0; + // 5.2.4. Dynamic Table Size Update + virtual void OnDynamicTableSizeUpdate(uint64_t max_size) = 0; + // Decoding error + virtual void OnErrorDetected(QuicStringPiece error_message) = 0; + }; + + explicit QpackEncoderStreamReceiver(Delegate* delegate); + QpackEncoderStreamReceiver() = delete; + QpackEncoderStreamReceiver(const QpackEncoderStreamReceiver&) = delete; + QpackEncoderStreamReceiver& operator=(const QpackEncoderStreamReceiver&) = + delete; + + // Decode data and call appropriate Delegate method after each decoded + // instruction. Once an error occurs, Delegate::OnErrorDetected() is called, + // and all further data is ignored. + void Decode(QuicStringPiece data); + + private: + enum class State { + // Identify the instruction and start decoding an integer. + kStart, + // Decode name index or name length. + kNameIndexOrLengthResume, + kNameIndexOrLengthDone, + // Read name string literal, which is optionally Huffman encoded. + kReadName, + // Optionally decode Huffman encoded name. + kDecodeName, + // Read value string length. + kValueLengthStart, + kValueLengthResume, + kValueLengthDone, + // Read value string literal, which is optionally Huffman encoded. + kReadValue, + // Optionally decode Huffman encoded value. + kDecodeValue, + // Done with insertion instruction. + kInsertDone, + // Read index to duplicate. + kIndexResume, + kIndexDone, + // Read maximum table size. + kMaxSizeResume, + kMaxSizeDone, + }; + + // One method for each state. Some take input data and return the number of + // octets processed. Some only change internal state. + size_t DoStart(QuicStringPiece data); + size_t DoNameIndexOrLengthResume(QuicStringPiece data); + void DoNameIndexOrLengthDone(); + size_t DoReadName(QuicStringPiece data); + void DoDecodeName(); + size_t DoValueLengthStart(QuicStringPiece data); + size_t DoValueLengthResume(QuicStringPiece data); + void DoValueLengthDone(); + size_t DoReadValue(QuicStringPiece data); + void DoDecodeValue(); + void DoInsertDone(); + size_t DoIndexResume(QuicStringPiece data); + void DoIndexDone(); + size_t DoMaxSizeResume(QuicStringPiece data); + void DoMaxSizeDone(); + + void OnError(QuicStringPiece error_message); + + Delegate* const delegate_; + http2::HpackVarintDecoder varint_decoder_; + http2::HpackHuffmanDecoder huffman_decoder_; + State state_; + + // True if the currently parsed string (name or value) is Huffman encoded. + bool is_huffman_; + + // True if the name index refers to the static table. + bool is_static_; + + // True if the header field value is encoded as a string literal. + bool literal_name_; + + // Decoded name index. + uint64_t name_index_; + + // Decoded length for header name. + size_t name_length_; + + // Decoded header name. + QuicString name_; + + // Decoded length for header value. + size_t value_length_; + + // Decoded header value. + QuicString value_; + + // True if a decoding error has been detected. + bool error_detected_; +}; + +} // namespace quic + +#endif // NET_THIRD_PARTY_QUIC_CORE_QPACK_QPACK_ENCODER_STREAM_RECEIVER_H_
diff --git a/net/third_party/quic/core/qpack/qpack_encoder_stream_receiver_test.cc b/net/third_party/quic/core/qpack/qpack_encoder_stream_receiver_test.cc new file mode 100644 index 0000000..16737f570 --- /dev/null +++ b/net/third_party/quic/core/qpack/qpack_encoder_stream_receiver_test.cc
@@ -0,0 +1,148 @@ +// Copyright (c) 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/third_party/quic/core/qpack/qpack_encoder_stream_receiver.h" + +#include "net/third_party/quic/platform/api/quic_test.h" +#include "net/third_party/quic/platform/api/quic_text_utils.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using testing::Eq; +using testing::StrictMock; + +namespace quic { +namespace test { +namespace { + +class MockDelegate : public QpackEncoderStreamReceiver::Delegate { + public: + ~MockDelegate() override = default; + + MOCK_METHOD3(OnInsertWithNameReference, + void(bool is_static, + uint64_t name_index, + QuicStringPiece value)); + MOCK_METHOD2(OnInsertWithoutNameReference, + void(QuicStringPiece name, QuicStringPiece value)); + MOCK_METHOD1(OnDuplicate, void(uint64_t index)); + MOCK_METHOD1(OnDynamicTableSizeUpdate, void(uint64_t max_size)); + MOCK_METHOD1(OnErrorDetected, void(QuicStringPiece error_message)); +}; + +class QpackEncoderStreamReceiverTest : public QuicTest { + protected: + QpackEncoderStreamReceiverTest() : stream_(&delegate_) {} + + void Decode(QuicStringPiece data) { stream_.Decode(data); } + StrictMock<MockDelegate>* delegate() { return &delegate_; } + + private: + QpackEncoderStreamReceiver stream_; + StrictMock<MockDelegate> delegate_; +}; + +TEST_F(QpackEncoderStreamReceiverTest, InsertWithNameReference) { + // Static, index fits in prefix, empty value. + EXPECT_CALL(*delegate(), OnInsertWithNameReference(true, 5, Eq(""))); + // Static, index fits in prefix, Huffman encoded value. + EXPECT_CALL(*delegate(), OnInsertWithNameReference(true, 2, Eq("foo"))); + // Not static, index does not fit in prefix, not Huffman encoded value. + EXPECT_CALL(*delegate(), OnInsertWithNameReference(false, 137, Eq("bar"))); + // Value length does not fit in prefix. + // 'Z' would be Huffman encoded to 8 bits, so no Huffman encoding is used. + EXPECT_CALL(*delegate(), + OnInsertWithNameReference(false, 42, Eq(QuicString(127, 'Z')))); + + Decode(QuicTextUtils::HexDecode( + "c500" + "c28294e7" + "bf4a03626172" + "aa7f005a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a" + "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a" + "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a" + "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a")); +} + +TEST_F(QpackEncoderStreamReceiverTest, InsertWithNameReferenceIndexTooLarge) { + EXPECT_CALL(*delegate(), OnErrorDetected(Eq("Encoded integer too large."))); + + Decode(QuicTextUtils::HexDecode("bfffffffffffffffffffffff")); +} + +TEST_F(QpackEncoderStreamReceiverTest, InsertWithNameReferenceValueTooLong) { + EXPECT_CALL(*delegate(), OnErrorDetected(Eq("ValueLen too large."))); + + Decode(QuicTextUtils::HexDecode("c57fffffffffffffffffffff")); +} + +TEST_F(QpackEncoderStreamReceiverTest, InsertWithoutNameReference) { + // Empty name and value. + EXPECT_CALL(*delegate(), OnInsertWithoutNameReference(Eq(""), Eq(""))); + // Huffman encoded short strings. + EXPECT_CALL(*delegate(), OnInsertWithoutNameReference(Eq("bar"), Eq("bar"))); + // Not Huffman encoded short strings. + EXPECT_CALL(*delegate(), OnInsertWithoutNameReference(Eq("foo"), Eq("foo"))); + // Not Huffman encoded long strings; length does not fit on prefix. + // 'Z' would be Huffman encoded to 8 bits, so no Huffman encoding is used. + EXPECT_CALL(*delegate(), + OnInsertWithoutNameReference(Eq(QuicString(31, 'Z')), + Eq(QuicString(127, 'Z')))); + + Decode(QuicTextUtils::HexDecode( + "4000" + "4362617203626172" + "6294e78294e7" + "5f005a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a7f005a" + "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a" + "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a" + "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a" + "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a")); +} + +TEST_F(QpackEncoderStreamReceiverTest, InsertWithoutNameReferenceNameTooLong) { + EXPECT_CALL(*delegate(), OnErrorDetected(Eq("Encoded integer too large."))); + + Decode(QuicTextUtils::HexDecode("5fffffffffffffffffffff")); +} + +TEST_F(QpackEncoderStreamReceiverTest, InsertWithoutNameReferenceValueTooLong) { + EXPECT_CALL(*delegate(), OnErrorDetected(Eq("ValueLen too large."))); + + Decode(QuicTextUtils::HexDecode("436261727fffffffffffffffffffff")); +} + +TEST_F(QpackEncoderStreamReceiverTest, Duplicate) { + // Small index fits in prefix. + EXPECT_CALL(*delegate(), OnDuplicate(17)); + // Large index requires two extension bytes. + EXPECT_CALL(*delegate(), OnDuplicate(500)); + + Decode(QuicTextUtils::HexDecode("111fd503")); +} + +TEST_F(QpackEncoderStreamReceiverTest, DuplicateIndexTooLarge) { + EXPECT_CALL(*delegate(), OnErrorDetected(Eq("Encoded integer too large."))); + + Decode(QuicTextUtils::HexDecode("1fffffffffffffffffffff")); +} + +TEST_F(QpackEncoderStreamReceiverTest, DynamicTableSizeUpdate) { + // Small max size fits in prefix. + EXPECT_CALL(*delegate(), OnDynamicTableSizeUpdate(17)); + // Large max size requires two extension bytes. + EXPECT_CALL(*delegate(), OnDynamicTableSizeUpdate(500)); + + Decode(QuicTextUtils::HexDecode("313fd503")); +} + +TEST_F(QpackEncoderStreamReceiverTest, DynamicTableSizeUpdateMaxSizeTooLarge) { + EXPECT_CALL(*delegate(), OnErrorDetected(Eq("Encoded integer too large."))); + + Decode(QuicTextUtils::HexDecode("3fffffffffffffffffffff")); +} + +} // namespace +} // namespace test +} // namespace quic
diff --git a/net/third_party/quic/core/qpack/qpack_encoder_stream_sender.cc b/net/third_party/quic/core/qpack/qpack_encoder_stream_sender.cc new file mode 100644 index 0000000..a688d94 --- /dev/null +++ b/net/third_party/quic/core/qpack/qpack_encoder_stream_sender.cc
@@ -0,0 +1,162 @@ +// Copyright (c) 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/third_party/quic/core/qpack/qpack_encoder_stream_sender.h" + +#include "net/third_party/http2/hpack/huffman/hpack_huffman_encoder.h" +#include "net/third_party/quic/core/qpack/qpack_constants.h" +#include "net/third_party/quic/platform/api/quic_logging.h" +#include "net/third_party/quic/platform/api/quic_string.h" + +namespace quic { + +QpackEncoderStreamSender::QpackEncoderStreamSender(Delegate* delegate) + : delegate_(delegate) { + DCHECK(delegate_); +} + +void QpackEncoderStreamSender::SendInsertWithNameReference( + bool is_static, + uint64_t name_index, + QuicStringPiece value) { + QuicString encoded_name_index_and_value_length; + + // Encode instruction code and name index. + uint8_t high_bits = kInsertWithNameReferenceOpcode; + if (is_static) { + high_bits |= kInsertWithNameReferenceStaticBit; + } + encoded_name_index_and_value_length.push_back(varint_encoder_.StartEncoding( + high_bits, kInsertWithNameReferenceNameIndexPrefixLength, name_index)); + if (varint_encoder_.IsEncodingInProgress()) { + varint_encoder_.ResumeEncoding(kMaxExtensionBytesForVarintEncoding, + &encoded_name_index_and_value_length); + } + DCHECK(!varint_encoder_.IsEncodingInProgress()); + + // Huffman encode value string. + QuicString huffman_encoded_value; + http2::HuffmanEncode(value, &huffman_encoded_value); + + // Only use Huffman compression if it makes the string shorter. + QuicStringPiece value_to_send; + if (huffman_encoded_value.size() < value.size()) { + value_to_send = huffman_encoded_value; + high_bits = kLiteralValueHuffmanMask; + } else { + value_to_send = value; + high_bits = kLiteralValueWithoutHuffmanEncoding; + } + + // Encode value length. + encoded_name_index_and_value_length.push_back(varint_encoder_.StartEncoding( + high_bits, kLiteralValuePrefixLength, value_to_send.size())); + if (varint_encoder_.IsEncodingInProgress()) { + varint_encoder_.ResumeEncoding(kMaxExtensionBytesForVarintEncoding, + &encoded_name_index_and_value_length); + } + DCHECK(!varint_encoder_.IsEncodingInProgress()); + + // Write everything. + DCHECK(!encoded_name_index_and_value_length.empty()); + delegate_->Write(encoded_name_index_and_value_length); + if (!value_to_send.empty()) { + delegate_->Write(value_to_send); + } +} + +void QpackEncoderStreamSender::SendInsertWithoutNameReference( + QuicStringPiece name, + QuicStringPiece value) { + QuicString huffman_encoded_name; + http2::HuffmanEncode(name, &huffman_encoded_name); + + // Only use Huffman compression if it makes the string shorter. + QuicStringPiece name_to_send; + uint8_t high_bits = kInsertWithoutNameReferenceOpcode; + if (huffman_encoded_name.size() < name.size()) { + name_to_send = huffman_encoded_name; + high_bits |= kInsertWithoutNameReferenceNameHuffmanBit; + } else { + name_to_send = name; + } + + // Encode instruction code and name length. + QuicString encoded_name_length; + encoded_name_length.push_back(varint_encoder_.StartEncoding( + high_bits, kInsertWithoutNameReferenceNameLengthPrefixLength, + name_to_send.size())); + if (varint_encoder_.IsEncodingInProgress()) { + varint_encoder_.ResumeEncoding(kMaxExtensionBytesForVarintEncoding, + &encoded_name_length); + } + DCHECK(!varint_encoder_.IsEncodingInProgress()); + + // Write instruction code, name length, and name. + DCHECK(!encoded_name_length.empty()); + delegate_->Write(encoded_name_length); + if (!name_to_send.empty()) { + delegate_->Write(name_to_send); + } + + // Huffman encode value string. + QuicString huffman_encoded_value; + http2::HuffmanEncode(value, &huffman_encoded_value); + + // Only use Huffman compression if it makes the string shorter. + QuicStringPiece value_to_send; + if (huffman_encoded_value.size() < value.size()) { + value_to_send = huffman_encoded_value; + high_bits = kLiteralValueHuffmanMask; + } else { + value_to_send = value; + high_bits = kLiteralValueWithoutHuffmanEncoding; + } + + // Encode value length. + QuicString encoded_value_length; + encoded_value_length.push_back(varint_encoder_.StartEncoding( + high_bits, kLiteralValuePrefixLength, value_to_send.size())); + if (varint_encoder_.IsEncodingInProgress()) { + varint_encoder_.ResumeEncoding(kMaxExtensionBytesForVarintEncoding, + &encoded_value_length); + } + DCHECK(!varint_encoder_.IsEncodingInProgress()); + + // Write value length and value. + DCHECK(!encoded_value_length.empty()); + delegate_->Write(encoded_value_length); + if (!value_to_send.empty()) { + delegate_->Write(value_to_send); + } +} + +void QpackEncoderStreamSender::SendDuplicate(uint64_t index) { + QuicString data; + data.push_back(varint_encoder_.StartEncoding( + kDuplicateOpcode, kDuplicateIndexPrefixLength, index)); + if (varint_encoder_.IsEncodingInProgress()) { + varint_encoder_.ResumeEncoding(kMaxExtensionBytesForVarintEncoding, &data); + } + DCHECK(!varint_encoder_.IsEncodingInProgress()); + + DCHECK(!data.empty()); + delegate_->Write(data); +} + +void QpackEncoderStreamSender::SendDynamicTableSizeUpdate(uint64_t max_size) { + QuicString data; + data.push_back(varint_encoder_.StartEncoding( + kDynamicTableSizeUpdateOpcode, kDynamicTableSizeUpdateMaxSizePrefixLength, + max_size)); + if (varint_encoder_.IsEncodingInProgress()) { + varint_encoder_.ResumeEncoding(kMaxExtensionBytesForVarintEncoding, &data); + } + DCHECK(!varint_encoder_.IsEncodingInProgress()); + + DCHECK(!data.empty()); + delegate_->Write(data); +} + +} // namespace quic
diff --git a/net/third_party/quic/core/qpack/qpack_encoder_stream_sender.h b/net/third_party/quic/core/qpack/qpack_encoder_stream_sender.h new file mode 100644 index 0000000..a12aef1 --- /dev/null +++ b/net/third_party/quic/core/qpack/qpack_encoder_stream_sender.h
@@ -0,0 +1,56 @@ +// Copyright (c) 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_THIRD_PARTY_QUIC_CORE_QPACK_QPACK_ENCODER_STREAM_SENDER_H_ +#define NET_THIRD_PARTY_QUIC_CORE_QPACK_QPACK_ENCODER_STREAM_SENDER_H_ + +#include <cstdint> + +#include "net/third_party/http2/hpack/varint/hpack_varint_encoder.h" +#include "net/third_party/quic/platform/api/quic_export.h" +#include "net/third_party/quic/platform/api/quic_string_piece.h" + +namespace quic { + +// This class serializes instructions for transmission on the encoder stream. +class QUIC_EXPORT_PRIVATE QpackEncoderStreamSender { + public: + // An interface for handling encoded data. + class Delegate { + public: + virtual ~Delegate() = default; + + // Encoded |data| is ready to be written on the encoder stream. + // |data| is guaranteed to be not empty. + virtual void Write(QuicStringPiece data) = 0; + }; + + explicit QpackEncoderStreamSender(Delegate* delegate); + QpackEncoderStreamSender() = delete; + QpackEncoderStreamSender(const QpackEncoderStreamSender&) = delete; + QpackEncoderStreamSender& operator=(const QpackEncoderStreamSender&) = delete; + + // Methods for sending instructions, see + // https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#rfc.section.5.2 + + // 5.2.1. Insert With Name Reference + void SendInsertWithNameReference(bool is_static, + uint64_t name_index, + QuicStringPiece value); + // 5.2.2. Insert Without Name Reference + void SendInsertWithoutNameReference(QuicStringPiece name, + QuicStringPiece value); + // 5.2.3. Duplicate + void SendDuplicate(uint64_t index); + // 5.2.4. Dynamic Table Size Update + void SendDynamicTableSizeUpdate(uint64_t max_size); + + private: + Delegate* const delegate_; + http2::HpackVarintEncoder varint_encoder_; +}; + +} // namespace quic + +#endif // NET_THIRD_PARTY_QUIC_CORE_QPACK_QPACK_ENCODER_STREAM_SENDER_H_
diff --git a/net/third_party/quic/core/qpack/qpack_encoder_stream_sender_test.cc b/net/third_party/quic/core/qpack/qpack_encoder_stream_sender_test.cc new file mode 100644 index 0000000..de30a4b --- /dev/null +++ b/net/third_party/quic/core/qpack/qpack_encoder_stream_sender_test.cc
@@ -0,0 +1,111 @@ +// Copyright (c) 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/third_party/quic/core/qpack/qpack_encoder_stream_sender.h" + +#include "net/third_party/quic/platform/api/quic_test.h" +#include "net/third_party/quic/platform/api/quic_text_utils.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace quic { +namespace test { +namespace { + +class TestSendingDelegate : public QpackEncoderStreamSender::Delegate { + public: + ~TestSendingDelegate() override = default; + + void Write(QuicStringPiece data) override { + EXPECT_FALSE(data.empty()); + buffer_.append(data.data(), data.size()); + } + + const QuicString& buffer() { return buffer_; } + + private: + QuicString buffer_; +}; + +class QpackEncoderStreamSenderTest : public QuicTest { + protected: + QpackEncoderStreamSenderTest() : stream_(&delegate_) {} + + QpackEncoderStreamSender* stream() { return &stream_; } + const QuicString& buffer() { return delegate_.buffer(); } + + private: + TestSendingDelegate delegate_; + QpackEncoderStreamSender stream_; +}; + +TEST_F(QpackEncoderStreamSenderTest, InsertWithNameReference) { + // Static, index fits in prefix, empty value. + stream()->SendInsertWithNameReference(true, 5, ""); + // Static, index fits in prefix, Huffman encoded value. + stream()->SendInsertWithNameReference(true, 2, "foo"); + // Not static, index does not fit in prefix, not Huffman encoded value. + stream()->SendInsertWithNameReference(false, 137, "bar"); + // Value length does not fit in prefix. + // 'Z' would be Huffman encoded to 8 bits, so no Huffman encoding is used. + stream()->SendInsertWithNameReference(false, 42, QuicString(127, 'Z')); + + EXPECT_EQ( + QuicTextUtils::HexDecode( + "c500" + "c28294e7" + "bf4a03626172" + "aa7f005a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a" + "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a" + "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a" + "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a"), + buffer()); +} + +TEST_F(QpackEncoderStreamSenderTest, InsertWithoutNameReference) { + // Empty name and value. + stream()->SendInsertWithoutNameReference("", ""); + // Huffman encoded short strings. + stream()->SendInsertWithoutNameReference("bar", "bar"); + // Not Huffman encoded short strings. + stream()->SendInsertWithoutNameReference("foo", "foo"); + // Not Huffman encoded long strings; length does not fit on prefix. + // 'Z' would be Huffman encoded to 8 bits, so no Huffman encoding is used. + stream()->SendInsertWithoutNameReference(QuicString(31, 'Z'), + QuicString(127, 'Z')); + + EXPECT_EQ( + QuicTextUtils::HexDecode( + "4000" + "4362617203626172" + "6294e78294e7" + "5f005a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a7f" + "005a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a" + "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a" + "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a" + "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a"), + buffer()); +} + +TEST_F(QpackEncoderStreamSenderTest, Duplicate) { + // Small index fits in prefix. + stream()->SendDuplicate(17); + // Large index requires two extension bytes. + stream()->SendDuplicate(500); + + EXPECT_EQ(QuicTextUtils::HexDecode("111fd503"), buffer()); +} + +TEST_F(QpackEncoderStreamSenderTest, DynamicTableSizeUpdate) { + // Small max size fits in prefix. + stream()->SendDynamicTableSizeUpdate(17); + // Large max size requires two extension bytes. + stream()->SendDynamicTableSizeUpdate(500); + + EXPECT_EQ(QuicTextUtils::HexDecode("313fd503"), buffer()); +} + +} // namespace +} // namespace test +} // namespace quic
diff --git a/net/third_party/quic/core/qpack/qpack_encoder_test.cc b/net/third_party/quic/core/qpack/qpack_encoder_test.cc index 1306dfe..2755665 100644 --- a/net/third_party/quic/core/qpack/qpack_encoder_test.cc +++ b/net/third_party/quic/core/qpack/qpack_encoder_test.cc
@@ -78,7 +78,7 @@ spdy::SpdyHeaderBlock header_list; header_list["foo"] = "bar"; // 'Z' would be Huffman encoded to 8 bits, so no Huffman encoding is used. - header_list["ZZZZZZZ"] = std::string(127, 'Z'); + header_list["ZZZZZZZ"] = QuicString(127, 'Z'); QuicString output = Encode(&header_list); EXPECT_EQ(
diff --git a/net/third_party/quic/core/qpack/qpack_encoder_test_utils.cc b/net/third_party/quic/core/qpack/qpack_encoder_test_utils.cc index 32700afa..3f38cff 100644 --- a/net/third_party/quic/core/qpack/qpack_encoder_test_utils.cc +++ b/net/third_party/quic/core/qpack/qpack_encoder_test_utils.cc
@@ -9,7 +9,7 @@ QuicString QpackEncode(const FragmentSizeGenerator& fragment_size_generator, const spdy::SpdyHeaderBlock* header_list) { QpackEncoder encoder; - auto progressive_encoder = encoder.EncodeHeaderSet(header_list); + auto progressive_encoder = encoder.EncodeHeaderList(header_list); QuicString output; while (progressive_encoder->HasNext()) {
diff --git a/net/third_party/quic/core/quic_connection.cc b/net/third_party/quic/core/quic_connection.cc index c03374a..2ce683d5 100644 --- a/net/third_party/quic/core/quic_connection.cc +++ b/net/third_party/quic/core/quic_connection.cc
@@ -1223,6 +1223,10 @@ return true; } +bool QuicConnection::OnNewTokenFrame(const QuicNewTokenFrame& frame) { + return true; +} + bool QuicConnection::OnMessageFrame(const QuicMessageFrame& frame) { DCHECK(connected_); @@ -2402,7 +2406,7 @@ } void QuicConnection::OnRetransmissionTimeout() { - DCHECK(sent_packet_manager_.HasUnackedPackets()); + DCHECK(!sent_packet_manager_.unacked_packets().empty()); if (close_connection_after_five_rtos_ && sent_packet_manager_.GetConsecutiveRtoCount() >= 4) { // Close on the 5th consecutive RTO, so after 4 previous RTOs have occurred. @@ -2740,6 +2744,11 @@ } void QuicConnection::SetPathDegradingAlarm() { + if (GetQuicReloadableFlag(quic_fix_path_degrading_alarm) && + perspective_ == Perspective::IS_SERVER) { + QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_fix_path_degrading_alarm, 1, 2); + return; + } const QuicTime::Delta delay = sent_packet_manager_.GetPathDegradingDelay(); path_degrading_alarm_->Update(clock_->ApproximateNow() + delay, QuicTime::Delta::FromMilliseconds(1)); @@ -3208,8 +3217,25 @@ // Always reset the retransmission alarm when an ack comes in, since we now // have a better estimate of the current rtt than when it was set. SetRetransmissionAlarm(); + MaybeSetPathDegradingAlarm(acked_new_packet); - if (!sent_packet_manager_.HasUnackedPackets()) { + // TODO(ianswett): Only increment stop_waiting_count_ if StopWaiting frames + // are sent. + if (send_stop_waiting) { + ++stop_waiting_count_; + } else { + stop_waiting_count_ = 0; + } +} + +void QuicConnection::MaybeSetPathDegradingAlarm(bool acked_new_packet) { + bool has_unacked_packets = !sent_packet_manager_.unacked_packets().empty(); + if (GetQuicReloadableFlag(quic_fix_path_degrading_alarm)) { + QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_fix_path_degrading_alarm, 2, 2); + // If there in flight packets, an ACK is expected in the future. + has_unacked_packets = sent_packet_manager_.HasInFlightPackets(); + } + if (!has_unacked_packets) { // There are no retransmittable packets on the wire, so it may be // necessary to send a PING to keep a retransmittable packet on the wire. if (!retransmittable_on_wire_alarm_->IsSet()) { @@ -3225,14 +3251,6 @@ is_path_degrading_ = false; SetPathDegradingAlarm(); } - - // TODO(ianswett): Only increment stop_waiting_count_ if StopWaiting frames - // are sent. - if (send_stop_waiting) { - ++stop_waiting_count_; - } else { - stop_waiting_count_ = 0; - } } void QuicConnection::SetSessionNotifier( @@ -3258,6 +3276,7 @@ } void QuicConnection::SetRetransmittableOnWireAlarm() { + // TODO(ianswett): Merge the RetransmittableOnWireAlarm and PingAlarm. if (perspective_ == Perspective::IS_SERVER) { // Only clients send pings. return;
diff --git a/net/third_party/quic/core/quic_connection.h b/net/third_party/quic/core/quic_connection.h index 97a6a8a..ae856a8 100644 --- a/net/third_party/quic/core/quic_connection.h +++ b/net/third_party/quic/core/quic_connection.h
@@ -489,6 +489,7 @@ bool OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) override; bool OnBlockedFrame(const QuicBlockedFrame& frame) override; bool OnNewConnectionIdFrame(const QuicNewConnectionIdFrame& frame) override; + bool OnNewTokenFrame(const QuicNewTokenFrame& frame) override; bool OnMessageFrame(const QuicMessageFrame& frame) override; void OnPacketComplete() override; bool IsValidStatelessResetToken(QuicUint128 token) const override; @@ -1006,6 +1007,10 @@ // |acked_new_packet| is true if a previously-unacked packet was acked. void PostProcessAfterAckFrame(bool send_stop_waiting, bool acked_new_packet); + // Called when an ACK is received to set the path degrading alarm or + // retransmittable on wire alarm. + void MaybeSetPathDegradingAlarm(bool acked_new_packet); + // Updates the release time into the future. void UpdateReleaseTimeIntoFuture();
diff --git a/net/third_party/quic/core/quic_connection_test.cc b/net/third_party/quic/core/quic_connection_test.cc index 36bc4ff..f6ffc51 100644 --- a/net/third_party/quic/core/quic_connection_test.cc +++ b/net/third_party/quic/core/quic_connection_test.cc
@@ -6696,6 +6696,40 @@ EXPECT_TRUE(connection_.GetPathDegradingAlarm()->IsSet()); } +TEST_P(QuicConnectionTest, NoPathDegradingOnServer) { + SetQuicReloadableFlag(quic_fix_path_degrading_alarm, true); + set_perspective(Perspective::IS_SERVER); + QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false); + + EXPECT_FALSE(connection_.IsPathDegrading()); + EXPECT_FALSE(connection_.GetPathDegradingAlarm()->IsSet()); + + // Send data. + const char data[] = "data"; + connection_.SendStreamDataWithString(1, data, 0, NO_FIN); + EXPECT_FALSE(connection_.IsPathDegrading()); + EXPECT_FALSE(connection_.GetPathDegradingAlarm()->IsSet()); + + // Ack data. + clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5)); + EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); + EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _)); + QuicAckFrame frame = InitAckFrame({{1u, 2u}}); + ProcessAckPacket(&frame); + EXPECT_FALSE(connection_.IsPathDegrading()); + EXPECT_FALSE(connection_.GetPathDegradingAlarm()->IsSet()); +} + +TEST_P(QuicConnectionTest, NoPathDegradingAfterSendingAck) { + SetQuicReloadableFlag(quic_fix_path_degrading_alarm, true); + + SendAckPacketToPeer(); + EXPECT_FALSE(connection_.sent_packet_manager().unacked_packets().empty()); + EXPECT_FALSE(connection_.sent_packet_manager().HasInFlightPackets()); + EXPECT_FALSE(connection_.IsPathDegrading()); + EXPECT_FALSE(connection_.GetPathDegradingAlarm()->IsSet()); +} + TEST_P(QuicConnectionTest, MultipleCallsToCloseConnection) { // Verifies that multiple calls to CloseConnection do not // result in multiple attempts to close the connection - it will be marked as @@ -6965,7 +6999,7 @@ // there are no outstanding packets. TEST_P(QuicConnectionTest, SendProbingRetransmissionsFailsWhenNothingToRetransmit) { - ASSERT_FALSE(connection_.sent_packet_manager().HasUnackedPackets()); + ASSERT_TRUE(connection_.sent_packet_manager().unacked_packets().empty()); MockQuicConnectionDebugVisitor debug_visitor; connection_.set_debug_visitor(&debug_visitor);
diff --git a/net/third_party/quic/core/quic_constants.h b/net/third_party/quic/core/quic_constants.h index 58f9d32..cbadc51 100644 --- a/net/third_party/quic/core/quic_constants.h +++ b/net/third_party/quic/core/quic_constants.h
@@ -226,6 +226,9 @@ // Minimum length of random bytes in IETF stateless reset packet. const size_t kMinRandomBytesLengthInStatelessReset = 20; +// Maximum length allowed for the token in a NEW_TOKEN frame. +const size_t kMaxNewTokenTokenLength = 0xffff; + } // namespace quic #endif // NET_THIRD_PARTY_QUIC_CORE_QUIC_CONSTANTS_H_
diff --git a/net/third_party/quic/core/quic_dispatcher.cc b/net/third_party/quic/core/quic_dispatcher.cc index d71f6a36..04873f3c 100644 --- a/net/third_party/quic/core/quic_dispatcher.cc +++ b/net/third_party/quic/core/quic_dispatcher.cc
@@ -817,6 +817,11 @@ return false; } +bool QuicDispatcher::OnNewTokenFrame(const QuicNewTokenFrame& frame) { + DCHECK(false); + return false; +} + bool QuicDispatcher::OnMessageFrame(const QuicMessageFrame& frame) { DCHECK(false); return false;
diff --git a/net/third_party/quic/core/quic_dispatcher.h b/net/third_party/quic/core/quic_dispatcher.h index 29a09b8..cd87edd9 100644 --- a/net/third_party/quic/core/quic_dispatcher.h +++ b/net/third_party/quic/core/quic_dispatcher.h
@@ -158,6 +158,7 @@ bool OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) override; bool OnBlockedFrame(const QuicBlockedFrame& frame) override; bool OnNewConnectionIdFrame(const QuicNewConnectionIdFrame& frame) override; + bool OnNewTokenFrame(const QuicNewTokenFrame& frame) override; bool OnMessageFrame(const QuicMessageFrame& frame) override; void OnPacketComplete() override; bool IsValidStatelessResetToken(QuicUint128 token) const override;
diff --git a/net/third_party/quic/core/quic_error_codes.cc b/net/third_party/quic/core/quic_error_codes.cc index aebc181..a77aa65e 100644 --- a/net/third_party/quic/core/quic_error_codes.cc +++ b/net/third_party/quic/core/quic_error_codes.cc
@@ -150,6 +150,7 @@ RETURN_STRING_LITERAL(QUIC_CONNECTION_MIGRATION_HANDSHAKE_UNCONFIRMED); RETURN_STRING_LITERAL(QUIC_INVALID_MESSAGE_DATA); RETURN_STRING_LITERAL(IETF_QUIC_PROTOCOL_VIOLATION); + RETURN_STRING_LITERAL(QUIC_INVALID_NEW_TOKEN); RETURN_STRING_LITERAL(QUIC_LAST_ERROR); // Intentionally have no default case, so we'll break the build // if we add errors and don't put them here.
diff --git a/net/third_party/quic/core/quic_error_codes.h b/net/third_party/quic/core/quic_error_codes.h index b0929cce..31c3e29 100644 --- a/net/third_party/quic/core/quic_error_codes.h +++ b/net/third_party/quic/core/quic_error_codes.h
@@ -304,12 +304,13 @@ // Error deframing PATH CHALLENGE or PATH RESPONSE frames. QUIC_INVALID_PATH_CHALLENGE_DATA = 109, QUIC_INVALID_PATH_RESPONSE_DATA = 110, - // This is used to indicate an IETF QUIC PROTOCOL VIOLATION // transport error within Google (pre-v99) QUIC. IETF_QUIC_PROTOCOL_VIOLATION = 113, + QUIC_INVALID_NEW_TOKEN = 114, + // No error. Used as bound while iterating. - QUIC_LAST_ERROR = 114, + QUIC_LAST_ERROR = 115, }; // QuicErrorCodes is encoded as a single octet on-the-wire. static_assert(static_cast<int>(QUIC_LAST_ERROR) <=
diff --git a/net/third_party/quic/core/quic_framer.cc b/net/third_party/quic/core/quic_framer.cc index b99e760..4cd48a5ee 100644 --- a/net/third_party/quic/core/quic_framer.cc +++ b/net/third_party/quic/core/quic_framer.cc
@@ -465,6 +465,8 @@ frame.application_close_frame->error_details); case NEW_CONNECTION_ID_FRAME: return GetNewConnectionIdFrameSize(*frame.new_connection_id_frame); + case NEW_TOKEN_FRAME: + return GetNewTokenFrameSize(*frame.new_token_frame); case MAX_STREAM_ID_FRAME: return GetMaxStreamIdFrameSize(version, frame.max_stream_id_frame); case STREAM_ID_BLOCKED_FRAME: @@ -536,6 +538,13 @@ } // static +size_t QuicFramer::GetNewTokenFrameSize(const QuicNewTokenFrame& frame) { + return kQuicFrameTypeSize + + QuicDataWriter::GetVarInt62Len(frame.token.length()) + + frame.token.length(); +} + +// static size_t QuicFramer::GetVersionNegotiationPacketSize(size_t number_versions) { return kPublicFlagsSize + PACKET_8BYTE_CONNECTION_ID + number_versions * kQuicVersionSize; @@ -718,6 +727,10 @@ set_detailed_error( "Attempt to append NEW_CONNECTION_ID frame and not in version 99."); return RaiseError(QUIC_INTERNAL_ERROR); + case NEW_TOKEN_FRAME: + set_detailed_error( + "Attempt to append NEW_TOKEN_ID frame and not in version 99."); + return RaiseError(QUIC_INTERNAL_ERROR); case MAX_STREAM_ID_FRAME: set_detailed_error( "Attempt to append MAX_STREAM_ID frame and not in version 99."); @@ -875,6 +888,12 @@ return 0; } break; + case NEW_TOKEN_FRAME: + if (!AppendNewTokenFrame(*frame.new_token_frame, &writer)) { + QUIC_BUG << "AppendNewTokenFrame failed"; + return 0; + } + break; case STOP_SENDING_FRAME: if (!AppendStopSendingFrame(*frame.stop_sending_frame, &writer)) { QUIC_BUG << "AppendStopSendingFrame failed"; @@ -2313,6 +2332,18 @@ } break; } + case IETF_NEW_TOKEN: { + QuicNewTokenFrame frame; + if (!ProcessNewTokenFrame(reader, &frame)) { + return RaiseError(QUIC_INVALID_NEW_TOKEN); + } + if (!visitor_->OnNewTokenFrame(frame)) { + QUIC_DVLOG(1) << "Visitor asked to stop further processing."; + // Returning true since there was no parsing error. + return true; + } + break; + } case IETF_STOP_SENDING: { QuicStopSendingFrame frame; if (!ProcessStopSendingFrame(reader, &frame)) { @@ -3407,6 +3438,10 @@ set_detailed_error( "Attempt to append NEW_CONNECTION_ID frame and not in version 99."); return RaiseError(QUIC_INTERNAL_ERROR); + case NEW_TOKEN_FRAME: + set_detailed_error( + "Attempt to append NEW_TOKEN frame and not in version 99."); + return RaiseError(QUIC_INTERNAL_ERROR); case MAX_STREAM_ID_FRAME: set_detailed_error( "Attempt to append MAX_STREAM_ID frame and not in version 99."); @@ -3497,6 +3532,9 @@ case NEW_CONNECTION_ID_FRAME: type_byte = IETF_NEW_CONNECTION_ID; break; + case NEW_TOKEN_FRAME: + type_byte = IETF_NEW_TOKEN; + break; case MAX_STREAM_ID_FRAME: type_byte = IETF_MAX_STREAM_ID; break; @@ -3642,6 +3680,40 @@ } return true; } +bool QuicFramer::AppendNewTokenFrame(const QuicNewTokenFrame& frame, + QuicDataWriter* writer) { + if (!writer->WriteVarInt62(static_cast<uint64_t>(frame.token.length()))) { + set_detailed_error("Writing token length failed."); + return false; + } + if (!writer->WriteBytes(frame.token.data(), frame.token.length())) { + set_detailed_error("Writing token buffer failed."); + return false; + } + return true; +} + +bool QuicFramer::ProcessNewTokenFrame(QuicDataReader* reader, + QuicNewTokenFrame* frame) { + uint64_t length; + if (!reader->ReadVarInt62(&length)) { + set_detailed_error("Unable to read new token length."); + return false; + } + if (length > kMaxNewTokenTokenLength) { + set_detailed_error("Token length larger than maximum."); + return false; + } + + // TODO(ianswett): Don't use QuicStringPiece as an intermediary. + QuicStringPiece data; + if (!reader->ReadStringPiece(&data, length)) { + set_detailed_error("Unable to read new token data."); + return false; + } + frame->token = QuicString(data); + return true; +} // Add a new ietf-format stream frame. // Bits controlling whether there is a frame-length and frame-offset
diff --git a/net/third_party/quic/core/quic_framer.h b/net/third_party/quic/core/quic_framer.h index d7ca1c1..09d1293 100644 --- a/net/third_party/quic/core/quic_framer.h +++ b/net/third_party/quic/core/quic_framer.h
@@ -174,6 +174,9 @@ virtual bool OnNewConnectionIdFrame( const QuicNewConnectionIdFrame& frame) = 0; + // Called when a NewTokenFrame has been parsed. + virtual bool OnNewTokenFrame(const QuicNewTokenFrame& frame) = 0; + // Called when a message frame has been parsed. virtual bool OnMessageFrame(const QuicMessageFrame& frame) = 0; @@ -315,6 +318,9 @@ static size_t GetNewConnectionIdFrameSize( const QuicNewConnectionIdFrame& frame); + // Size in bytes for a serialized new token frame + static size_t GetNewTokenFrameSize(const QuicNewTokenFrame& frame); + // Size in bytes required for a serialized version negotiation packet static size_t GetVersionNegotiationPacketSize(size_t number_versions); @@ -752,6 +758,10 @@ bool ProcessNewConnectionIdFrame(QuicDataReader* reader, QuicNewConnectionIdFrame* frame); + bool AppendNewTokenFrame(const QuicNewTokenFrame& frame, + QuicDataWriter* writer); + bool ProcessNewTokenFrame(QuicDataReader* reader, QuicNewTokenFrame* frame); + bool RaiseError(QuicErrorCode error); // Returns true if |header| indicates a version negotiation packet.
diff --git a/net/third_party/quic/core/quic_framer_test.cc b/net/third_party/quic/core/quic_framer_test.cc index 11a58f4..a1360f2 100644 --- a/net/third_party/quic/core/quic_framer_test.cc +++ b/net/third_party/quic/core/quic_framer_test.cc
@@ -329,6 +329,11 @@ return true; } + bool OnNewTokenFrame(const QuicNewTokenFrame& frame) override { + new_token_ = frame; + return true; + } + bool IsValidStatelessResetToken(QuicUint128 token) const override { return token == kTestStatelessResetToken; } @@ -370,6 +375,7 @@ QuicStreamIdBlockedFrame stream_id_blocked_frame_; QuicMaxStreamIdFrame max_stream_id_frame_; QuicNewConnectionIdFrame new_connection_id_; + QuicNewTokenFrame new_token_; std::vector<std::unique_ptr<QuicString>> stream_data_; }; @@ -9269,6 +9275,98 @@ QUIC_ARRAYSIZE(packet99)); } +TEST_P(QuicFramerTest, NewTokenFrame) { + if (framer_.transport_version() != QUIC_VERSION_99) { + // This frame is only for version 99. + return; + } + // clang-format off + PacketFragments packet = { + // type (short header, 4 byte packet number) + {"", + {0x32}}, + // connection_id + {"", + {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}}, + // packet number + {"", + {0x12, 0x34, 0x56, 0x78}}, + // frame type (new token frame) + {"", + {0x19}}, + // Length + {"Unable to read new token length.", + {kVarInt62OneByte + 0x08}}, + {"Unable to read new token data.", + {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}} + }; + // clang-format on + uint8_t expected_token_value[] = {0x00, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x07}; + + std::unique_ptr<QuicEncryptedPacket> encrypted( + AssemblePacketFromFragments(packet)); + EXPECT_TRUE(framer_.ProcessPacket(*encrypted)); + + EXPECT_EQ(QUIC_NO_ERROR, framer_.error()); + ASSERT_TRUE(visitor_.header_.get()); + EXPECT_TRUE(CheckDecryption( + *encrypted, !kIncludeVersion, !kIncludeDiversificationNonce, + PACKET_8BYTE_CONNECTION_ID, PACKET_0BYTE_CONNECTION_ID)); + + EXPECT_EQ(0u, visitor_.stream_frames_.size()); + + EXPECT_EQ(sizeof(expected_token_value), visitor_.new_token_.token.length()); + EXPECT_EQ(0, memcmp(expected_token_value, visitor_.new_token_.token.data(), + sizeof(expected_token_value))); + + CheckFramingBoundaries(packet, QUIC_INVALID_NEW_TOKEN); +} + +TEST_P(QuicFramerTest, BuildNewTokenFramePacket) { + if (framer_.transport_version() != QUIC_VERSION_99) { + // This frame is only for version 99. + return; + } + QuicPacketHeader header; + header.destination_connection_id = kConnectionId; + header.reset_flag = false; + header.version_flag = false; + header.packet_number = kPacketNumber; + + uint8_t expected_token_value[] = {0x00, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x07}; + + QuicNewTokenFrame frame(0, QuicString((const char*)(expected_token_value), + sizeof(expected_token_value))); + + QuicFrames frames = {QuicFrame(&frame)}; + + // clang-format off + unsigned char packet[] = { + // type (short header, 4 byte packet number) + 0x32, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + + // frame type (new token frame) + 0x19, + // Length and token + kVarInt62OneByte + 0x08, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 + }; + // clang-format on + + std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames)); + ASSERT_TRUE(data != nullptr); + + test::CompareCharArraysWithHexError("constructed packet", data->data(), + data->length(), AsChars(packet), + QUIC_ARRAYSIZE(packet)); +} + TEST_P(QuicFramerTest, IetfStopSendingFrame) { // This test is only for version 99. if (framer_.transport_version() != QUIC_VERSION_99) {
diff --git a/net/third_party/quic/core/quic_ietf_framer_test.cc b/net/third_party/quic/core/quic_ietf_framer_test.cc index b32cbab..e56b6a4 100644 --- a/net/third_party/quic/core/quic_ietf_framer_test.cc +++ b/net/third_party/quic/core/quic_ietf_framer_test.cc
@@ -172,6 +172,8 @@ return true; } + bool OnNewTokenFrame(const QuicNewTokenFrame& frame) override { return true; } + bool IsValidStatelessResetToken(QuicUint128 token) const override { return true; }
diff --git a/net/third_party/quic/core/quic_sent_packet_manager.h b/net/third_party/quic/core/quic_sent_packet_manager.h index 08c96ea..5caf222 100644 --- a/net/third_party/quic/core/quic_sent_packet_manager.h +++ b/net/third_party/quic/core/quic_sent_packet_manager.h
@@ -152,15 +152,16 @@ // there are pending retransmissions prior to calling this function. QuicPendingRetransmission NextPendingRetransmission(); - bool HasUnackedPackets() const { - return unacked_packets_.HasUnackedPackets(); - } - // Returns true if there's outstanding crypto data. bool HasUnackedCryptoPackets() const { return unacked_packets_.HasPendingCryptoPackets(); } + // Returns true if there are packets in flight expecting to be acknowledged. + bool HasInFlightPackets() const { + return unacked_packets_.HasInFlightPackets(); + } + // Returns the smallest packet number of a serialized packet which has not // been acked by the peer. QuicPacketNumber GetLeastUnacked() const {
diff --git a/net/third_party/quic/core/quic_sent_packet_manager_test.cc b/net/third_party/quic/core/quic_sent_packet_manager_test.cc index 10f6747..a8d9d17 100644 --- a/net/third_party/quic/core/quic_sent_packet_manager_test.cc +++ b/net/third_party/quic/core/quic_sent_packet_manager_test.cc
@@ -113,13 +113,13 @@ } void VerifyUnackedPackets(QuicPacketNumber* packets, size_t num_packets) { if (num_packets == 0) { - EXPECT_FALSE(manager_.HasUnackedPackets()); + EXPECT_TRUE(manager_.unacked_packets().empty()); EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetNumRetransmittablePackets( &manager_)); return; } - EXPECT_TRUE(manager_.HasUnackedPackets()); + EXPECT_FALSE(manager_.unacked_packets().empty()); EXPECT_EQ(packets[0], manager_.GetLeastUnacked()); for (size_t i = 0; i < num_packets; ++i) { EXPECT_TRUE(QuicSentPacketManagerPeer::IsUnacked(&manager_, packets[i])) @@ -1612,6 +1612,7 @@ if (manager_.session_decides_what_to_write()) { EXPECT_CALL(notifier_, RetransmitFrames(_, _)) .WillOnce(InvokeWithoutArgs([this]() { RetransmitCryptoPacket(2); })); + // When session decides what to write, crypto_packet_send_time gets updated. crypto_packet_send_time = clock_.Now(); } manager_.OnRetransmissionTimeout(); @@ -1622,6 +1623,23 @@ // The retransmission time should now be twice as far in the future. expected_time = crypto_packet_send_time + srtt * 2 * 1.5; EXPECT_EQ(expected_time, manager_.GetRetransmissionTime()); + + // Retransmit the packet for the 2nd time. + clock_.AdvanceTime(2 * 1.5 * srtt); + if (manager_.session_decides_what_to_write()) { + EXPECT_CALL(notifier_, RetransmitFrames(_, _)) + .WillOnce(InvokeWithoutArgs([this]() { RetransmitCryptoPacket(3); })); + // When session decides what to write, crypto_packet_send_time gets updated. + crypto_packet_send_time = clock_.Now(); + } + manager_.OnRetransmissionTimeout(); + if (!manager_.session_decides_what_to_write()) { + RetransmitNextPacket(3); + } + + // Verify exponential backoff of the retransmission timeout. + expected_time = crypto_packet_send_time + srtt * 4 * 1.5; + EXPECT_EQ(expected_time, manager_.GetRetransmissionTime()); } TEST_P(QuicSentPacketManagerTest,
diff --git a/net/third_party/quic/core/quic_session.cc b/net/third_party/quic/core/quic_session.cc index 06a4cd20..17fd031 100644 --- a/net/third_party/quic/core/quic_session.cc +++ b/net/third_party/quic/core/quic_session.cc
@@ -830,6 +830,15 @@ return id; } +bool QuicSession::CanOpenNextOutgoingStream() { + if (GetNumOpenOutgoingStreams() >= max_open_outgoing_streams()) { + QUIC_DLOG(INFO) << "Failed to create a new outgoing stream. " + << "Already " << GetNumOpenOutgoingStreams() << " open."; + return false; + } + return true; +} + QuicStream* QuicSession::GetOrCreateStream(const QuicStreamId stream_id) { StaticStreamMap::iterator it = static_stream_map_.find(stream_id); if (it != static_stream_map_.end()) { @@ -1280,19 +1289,12 @@ if (stream->HasPendingRetransmission()) { // Connection is write blocked. break; - } else { - if (GetQuicReloadableFlag(quic_fix_retransmit_lost_data)) { - QUIC_FLAG_COUNT(quic_reloadable_flag_quic_fix_retransmit_lost_data); - if (!streams_with_pending_retransmission_.empty() && - streams_with_pending_retransmission_.begin()->first == id) { - // Retransmit lost data may cause connection close. If this stream - // has not yet sent fin, a RST_STREAM will be sent and it will be - // removed from streams_with_pending_retransmission_. - streams_with_pending_retransmission_.pop_front(); - } - } else { - streams_with_pending_retransmission_.pop_front(); - } + } else if (!streams_with_pending_retransmission_.empty() && + streams_with_pending_retransmission_.begin()->first == id) { + // Retransmit lost data may cause connection close. If this stream + // has not yet sent fin, a RST_STREAM will be sent and it will be + // removed from streams_with_pending_retransmission_. + streams_with_pending_retransmission_.pop_front(); } } else { QUIC_BUG << "Try to retransmit data of a closed stream";
diff --git a/net/third_party/quic/core/quic_session.h b/net/third_party/quic/core/quic_session.h index 3b401b1..d102f6d 100644 --- a/net/third_party/quic/core/quic_session.h +++ b/net/third_party/quic/core/quic_session.h
@@ -377,6 +377,9 @@ // underlying counter. QuicStreamId GetNextOutgoingStreamId(); + // Indicates whether the next outgoing stream ID can be allocated or not. + bool CanOpenNextOutgoingStream(); + // Returns existing stream with id = |stream_id|. If no such stream exists, // and |stream_id| is a peer-created id, then a new stream is created and // returned. However if |stream_id| is a locally-created id and no such stream
diff --git a/net/third_party/quic/core/quic_stream_test.cc b/net/third_party/quic/core/quic_stream_test.cc index 6d1a6cb..670bd9b 100644 --- a/net/third_party/quic/core/quic_stream_test.cc +++ b/net/third_party/quic/core/quic_stream_test.cc
@@ -41,12 +41,10 @@ const char kData1[] = "FooAndBar"; const char kData2[] = "EepAndBaz"; const size_t kDataLen = 9; -const bool kShouldProcessData = true; -const bool kShouldNotProcessData = false; class TestStream : public QuicStream { public: - TestStream(QuicStreamId id, QuicSession* session, bool should_process_data) + TestStream(QuicStreamId id, QuicSession* session) : QuicStream(id, session, /*is_static=*/false) {} void OnDataAvailable() override {} @@ -74,7 +72,7 @@ supported_versions_(AllSupportedVersions()) { } - void Initialize(bool stream_should_process_data) { + void Initialize() { connection_ = new StrictMock<MockQuicConnection>( &helper_, &alarm_factory_, Perspective::IS_SERVER, supported_versions_); connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1)); @@ -85,8 +83,7 @@ QuicConfigPeer::SetReceivedInitialStreamFlowControlWindow( session_->config(), initial_flow_control_window_bytes_); - stream_ = new TestStream(kTestStreamId, session_.get(), - stream_should_process_data); + stream_ = new TestStream(kTestStreamId, session_.get()); // session_ now owns stream_. session_->ActivateStream(QuicWrapUnique(stream_)); // Ignore resetting when session_ is terminated. @@ -136,7 +133,7 @@ }; TEST_F(QuicStreamTest, WriteAllData) { - Initialize(kShouldProcessData); + Initialize(); size_t length = 1 + QuicPacketCreator::StreamFramePacketOverhead( @@ -152,7 +149,7 @@ } TEST_F(QuicStreamTest, NoBlockingIfNoDataOrFin) { - Initialize(kShouldProcessData); + Initialize(); // Write no data and no fin. If we consume nothing we should not be write // blocked. @@ -162,7 +159,7 @@ } TEST_F(QuicStreamTest, BlockIfOnlySomeDataConsumed) { - Initialize(kShouldProcessData); + Initialize(); // Write some data and no fin. If we consume some but not all of the data, // we should be write blocked a not all the data was consumed. @@ -177,7 +174,7 @@ } TEST_F(QuicStreamTest, BlockIfFinNotConsumedWithData) { - Initialize(kShouldProcessData); + Initialize(); // Write some data and no fin. If we consume all the data but not the fin, // we should be write blocked because the fin was not consumed. @@ -193,7 +190,7 @@ } TEST_F(QuicStreamTest, BlockIfSoloFinNotConsumed) { - Initialize(kShouldProcessData); + Initialize(); // Write no data and a fin. If we consume nothing we should be write blocked, // as the fin was not consumed. @@ -204,7 +201,7 @@ } TEST_F(QuicStreamTest, CloseOnPartialWrite) { - Initialize(kShouldProcessData); + Initialize(); // Write some data and no fin. However, while writing the data // close the stream and verify that MarkConnectionLevelWriteBlocked does not @@ -216,7 +213,7 @@ } TEST_F(QuicStreamTest, WriteOrBufferData) { - Initialize(kShouldProcessData); + Initialize(); EXPECT_FALSE(HasWriteBlockedStreams()); size_t length = @@ -258,7 +255,7 @@ TEST_F(QuicStreamTest, WriteOrBufferDataReachStreamLimit) { SetQuicReloadableFlag(quic_stream_too_long, true); - Initialize(kShouldProcessData); + Initialize(); QuicString data("aaaaa"); QuicStreamPeer::SetStreamBytesWritten(kMaxStreamLength - data.length(), stream_); @@ -271,7 +268,7 @@ } TEST_F(QuicStreamTest, ConnectionCloseAfterStreamClose) { - Initialize(kShouldProcessData); + Initialize(); QuicStreamPeer::CloseReadSide(stream_); stream_->CloseWriteSide(); @@ -288,7 +285,7 @@ // before termination. // Test that if no FIN has been sent, we send a RST. - Initialize(kShouldProcessData); + Initialize(); EXPECT_FALSE(fin_sent()); EXPECT_FALSE(rst_sent()); @@ -314,7 +311,7 @@ // before termination. // Test that if a FIN has been sent, we don't also send a RST. - Initialize(kShouldProcessData); + Initialize(); EXPECT_FALSE(fin_sent()); EXPECT_FALSE(rst_sent()); @@ -340,7 +337,7 @@ // Test that if a stream sends a RST, it doesn't send an additional RST during // OnClose() (this shouldn't be harmful, but we shouldn't do it anyway...) - Initialize(kShouldProcessData); + Initialize(); EXPECT_FALSE(fin_sent()); EXPECT_FALSE(rst_sent()); @@ -361,7 +358,7 @@ TEST_F(QuicStreamTest, StreamFlowControlMultipleWindowUpdates) { set_initial_flow_control_window_bytes(1000); - Initialize(kShouldProcessData); + Initialize(); // If we receive multiple WINDOW_UPDATES (potentially out of order), then we // want to make sure we latch the largest offset we see. @@ -396,7 +393,7 @@ } TEST_F(QuicStreamTest, FrameStats) { - Initialize(kShouldProcessData); + Initialize(); EXPECT_EQ(0, stream_->num_frames_received()); EXPECT_EQ(0, stream_->num_duplicate_frames_received()); @@ -413,7 +410,7 @@ // too much data on the stream) that the stream sequencer never sees this frame, // as we check for violation and close the connection early. TEST_F(QuicStreamTest, StreamSequencerNeverSeesPacketsViolatingFlowControl) { - Initialize(kShouldProcessData); + Initialize(); // Receive a stream frame that violates flow control: the byte offset is // higher than the receive window offset. @@ -432,7 +429,7 @@ // Verify that after the consumer calls StopReading(), the stream still sends // flow control updates. TEST_F(QuicStreamTest, StopReadingSendsFlowControl) { - Initialize(kShouldProcessData); + Initialize(); stream_->StopReading(); @@ -457,7 +454,7 @@ } TEST_F(QuicStreamTest, FinalByteOffsetFromFin) { - Initialize(kShouldProcessData); + Initialize(); EXPECT_FALSE(stream_->HasFinalReceivedByteOffset()); @@ -473,7 +470,7 @@ } TEST_F(QuicStreamTest, FinalByteOffsetFromRst) { - Initialize(kShouldProcessData); + Initialize(); EXPECT_FALSE(stream_->HasFinalReceivedByteOffset()); QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream_->id(), @@ -483,7 +480,7 @@ } TEST_F(QuicStreamTest, InvalidFinalByteOffsetFromRst) { - Initialize(kShouldProcessData); + Initialize(); EXPECT_FALSE(stream_->HasFinalReceivedByteOffset()); QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream_->id(), @@ -503,7 +500,7 @@ // current flow control limits. Flow control should only be concerned with // data that has actually been sent/received, so verify that flow control // ignores such a stream frame. - Initialize(kShouldProcessData); + Initialize(); EXPECT_FALSE(stream_->HasFinalReceivedByteOffset()); const QuicStreamOffset kByteOffsetExceedingFlowControlWindow = @@ -536,7 +533,7 @@ TEST_F(QuicStreamTest, OnStreamResetOffsetOverflow) { SetQuicReloadableFlag(quic_stream_too_long, true); - Initialize(kShouldProcessData); + Initialize(); QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream_->id(), QUIC_STREAM_CANCELLED, kMaxStreamLength + 1); EXPECT_CALL(*connection_, CloseConnection(QUIC_STREAM_LENGTH_OVERFLOW, _, _)); @@ -545,7 +542,7 @@ TEST_F(QuicStreamTest, OnStreamFrameUpperLimit) { SetQuicReloadableFlag(quic_stream_too_long, true); - Initialize(kShouldProcessData); + Initialize(); // Modify receive window offset and sequencer buffer total_bytes_read_ to // avoid flow control violation. @@ -568,7 +565,7 @@ TEST_F(QuicStreamTest, StreamTooLong) { SetQuicReloadableFlag(quic_stream_too_long, true); - Initialize(kShouldProcessData); + Initialize(); EXPECT_CALL(*connection_, CloseConnection(QUIC_STREAM_LENGTH_OVERFLOW, _, _)) .Times(1); QuicStreamFrame stream_frame(stream_->id(), false, kMaxStreamLength, @@ -579,7 +576,7 @@ TEST_F(QuicStreamTest, SetDrainingIncomingOutgoing) { // Don't have incoming data consumed. - Initialize(kShouldNotProcessData); + Initialize(); // Incoming data with FIN. QuicStreamFrame stream_frame_with_fin(stream_->id(), true, 1234, @@ -608,7 +605,7 @@ TEST_F(QuicStreamTest, SetDrainingOutgoingIncoming) { // Don't have incoming data consumed. - Initialize(kShouldNotProcessData); + Initialize(); // Outgoing data with FIN. EXPECT_CALL(*session_, WritevData(stream_, kTestStreamId, _, _, _)) @@ -639,7 +636,7 @@ // Verify that if the server completes the response before reading the end of // the request, the received FIN is recorded. - Initialize(kShouldProcessData); + Initialize(); EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0); EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) .WillRepeatedly(Invoke(MockQuicSession::ConsumeData)); @@ -661,7 +658,7 @@ } TEST_F(QuicStreamTest, StreamWaitsForAcks) { - Initialize(kShouldProcessData); + Initialize(); QuicReferenceCountedPointer<MockAckListener> mock_ack_listener( new StrictMock<MockAckListener>); stream_->set_ack_listener(mock_ack_listener); @@ -712,7 +709,7 @@ } TEST_F(QuicStreamTest, StreamDataGetAckedOutOfOrder) { - Initialize(kShouldProcessData); + Initialize(); EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) .WillRepeatedly(Invoke(MockQuicSession::ConsumeData)); // Send data. @@ -740,7 +737,7 @@ } TEST_F(QuicStreamTest, CancelStream) { - Initialize(kShouldProcessData); + Initialize(); EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) .WillRepeatedly(Invoke(MockQuicSession::ConsumeData)); EXPECT_FALSE(stream_->IsWaitingForAcks()); @@ -763,7 +760,7 @@ } TEST_F(QuicStreamTest, RstFrameReceivedStreamNotFinishSending) { - Initialize(kShouldProcessData); + Initialize(); EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) .WillRepeatedly(Invoke(MockQuicSession::ConsumeData)); EXPECT_FALSE(stream_->IsWaitingForAcks()); @@ -786,7 +783,7 @@ } TEST_F(QuicStreamTest, RstFrameReceivedStreamFinishSending) { - Initialize(kShouldProcessData); + Initialize(); EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) .WillRepeatedly(Invoke(MockQuicSession::ConsumeData)); EXPECT_FALSE(stream_->IsWaitingForAcks()); @@ -806,7 +803,7 @@ } TEST_F(QuicStreamTest, ConnectionClosed) { - Initialize(kShouldProcessData); + Initialize(); EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) .WillRepeatedly(Invoke(MockQuicSession::ConsumeData)); EXPECT_FALSE(stream_->IsWaitingForAcks()); @@ -830,7 +827,7 @@ // Do not stream level flow control block this stream. set_initial_flow_control_window_bytes(500000); - Initialize(kShouldProcessData); + Initialize(); QuicString data(1024, 'a'); EXPECT_TRUE(stream_->CanWriteNewData()); @@ -926,7 +923,7 @@ TEST_F(QuicStreamTest, WritevDataReachStreamLimit) { SetQuicReloadableFlag(quic_stream_too_long, true); - Initialize(kShouldProcessData); + Initialize(); QuicString data("aaaaa"); QuicStreamPeer::SetStreamBytesWritten(kMaxStreamLength - data.length(), stream_); @@ -947,7 +944,7 @@ // Do not flow control block this stream. set_initial_flow_control_window_bytes(500000); - Initialize(kShouldProcessData); + Initialize(); char data[1024]; std::vector<std::pair<char*, size_t>> buffers; buffers.push_back(std::make_pair(data, QUIC_ARRAYSIZE(data))); @@ -1009,7 +1006,7 @@ TEST_F(QuicStreamTest, WriteMemSlicesReachStreamLimit) { SetQuicReloadableFlag(quic_stream_too_long, true); - Initialize(kShouldProcessData); + Initialize(); QuicStreamPeer::SetStreamBytesWritten(kMaxStreamLength - 5u, stream_); char data[5]; std::vector<std::pair<char*, size_t>> buffers; @@ -1035,7 +1032,7 @@ } TEST_F(QuicStreamTest, StreamDataGetAckedMultipleTimes) { - Initialize(kShouldProcessData); + Initialize(); QuicReferenceCountedPointer<MockAckListener> mock_ack_listener( new StrictMock<MockAckListener>); stream_->set_ack_listener(mock_ack_listener); @@ -1091,7 +1088,7 @@ } TEST_F(QuicStreamTest, OnStreamFrameLost) { - Initialize(kShouldProcessData); + Initialize(); // Send [0, 9). EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) @@ -1156,7 +1153,7 @@ } TEST_F(QuicStreamTest, CannotBundleLostFin) { - Initialize(kShouldProcessData); + Initialize(); // Send [0, 18) and fin. EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) @@ -1184,7 +1181,7 @@ TEST_F(QuicStreamTest, MarkConnectionLevelWriteBlockedOnWindowUpdateFrame) { // Set a small initial control window size. set_initial_flow_control_window_bytes(100); - Initialize(kShouldProcessData); + Initialize(); EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) .WillRepeatedly(Invoke(MockQuicSession::ConsumeData)); @@ -1209,7 +1206,7 @@ // Set a small initial flow control window size. const uint32_t kSmallWindow = 100; set_initial_flow_control_window_bytes(kSmallWindow); - Initialize(kShouldProcessData); + Initialize(); QuicString data(kSmallWindow, '.'); EXPECT_CALL(*session_, WritevData(_, _, _, _, _)) @@ -1228,7 +1225,7 @@ } TEST_F(QuicStreamTest, RetransmitStreamData) { - Initialize(kShouldProcessData); + Initialize(); InSequence s; // Send [0, 18) with fin. @@ -1264,7 +1261,7 @@ } TEST_F(QuicStreamTest, ResetStreamOnTtlExpiresRetransmitLostData) { - Initialize(kShouldProcessData); + Initialize(); EXPECT_CALL(*session_, WritevData(_, stream_->id(), 200, 0, FIN)) .WillOnce(Invoke(MockQuicSession::ConsumeData)); @@ -1288,7 +1285,7 @@ } TEST_F(QuicStreamTest, ResetStreamOnTtlExpiresEarlyRetransmitData) { - Initialize(kShouldProcessData); + Initialize(); EXPECT_CALL(*session_, WritevData(_, stream_->id(), 200, 0, FIN)) .WillOnce(Invoke(MockQuicSession::ConsumeData));
diff --git a/net/third_party/quic/core/quic_trace_visitor.cc b/net/third_party/quic/core/quic_trace_visitor.cc index 4768bc9..a6951dd 100644 --- a/net/third_party/quic/core/quic_trace_visitor.cc +++ b/net/third_party/quic/core/quic_trace_visitor.cc
@@ -89,6 +89,7 @@ case STOP_SENDING_FRAME: case MESSAGE_FRAME: case CRYPTO_FRAME: + case NEW_TOKEN_FRAME: break; // Ignore gQUIC-specific frames. @@ -215,6 +216,7 @@ case STOP_SENDING_FRAME: case MESSAGE_FRAME: case CRYPTO_FRAME: + case NEW_TOKEN_FRAME: break; case NUM_FRAME_TYPES:
diff --git a/net/third_party/quic/core/quic_types.h b/net/third_party/quic/core/quic_types.h index 5776ed2..00b95e3 100644 --- a/net/third_party/quic/core/quic_types.h +++ b/net/third_party/quic/core/quic_types.h
@@ -185,6 +185,7 @@ STOP_SENDING_FRAME, MESSAGE_FRAME, CRYPTO_FRAME, + NEW_TOKEN_FRAME, NUM_FRAME_TYPES }; @@ -225,9 +226,8 @@ // bit specifically when/as needed. IETF_STREAM = 0x10, IETF_CRYPTO = 0x18, - // TODO(fkastenholz): When the NEW_TOKEN frame type value is added, need - // to update the test in ProcessIetfFrameData that checks to see if the frame - // type has not been minimally encoded. + IETF_NEW_TOKEN = 0x19, + // MESSAGE frame type is not yet determined, use 0x2x temporarily to give // stream frame some wiggle room. IETF_EXTENSION_MESSAGE_NO_LENGTH = 0x20,
diff --git a/net/third_party/quic/core/quic_unacked_packet_map.cc b/net/third_party/quic/core/quic_unacked_packet_map.cc index 0114fbbb..a7b509d7f 100644 --- a/net/third_party/quic/core/quic_unacked_packet_map.cc +++ b/net/third_party/quic/core/quic_unacked_packet_map.cc
@@ -299,10 +299,6 @@ } } -bool QuicUnackedPacketMap::HasUnackedPackets() const { - return !unacked_packets_.empty(); -} - bool QuicUnackedPacketMap::HasInFlightPackets() const { return bytes_in_flight_ > 0; }
diff --git a/net/third_party/quic/core/quic_unacked_packet_map.h b/net/third_party/quic/core/quic_unacked_packet_map.h index 7d4c5481..b1c4fbd 100644 --- a/net/third_party/quic/core/quic_unacked_packet_map.h +++ b/net/third_party/quic/core/quic_unacked_packet_map.h
@@ -81,13 +81,13 @@ // acked. bool HasRetransmittableFrames(const QuicTransmissionInfo& info) const; - // Returns true if there are any unacked packets. - bool HasUnackedPackets() const; - // Returns true if there are any unacked packets which have retransmittable // frames. bool HasUnackedRetransmittableFrames() const; + // Returns true if there are no packets present in the unacked packet map. + bool empty() const { return unacked_packets_.empty(); } + // Returns the largest packet number that has been sent. QuicPacketNumber largest_sent_packet() const { return largest_sent_packet_; }
diff --git a/net/third_party/quic/core/quic_unacked_packet_map_test.cc b/net/third_party/quic/core/quic_unacked_packet_map_test.cc index 0d8d325f..cdb7e6e7 100644 --- a/net/third_party/quic/core/quic_unacked_packet_map_test.cc +++ b/net/third_party/quic/core/quic_unacked_packet_map_test.cc
@@ -98,13 +98,13 @@ void VerifyUnackedPackets(QuicPacketNumber* packets, size_t num_packets) { unacked_packets_.RemoveObsoletePackets(); if (num_packets == 0) { - EXPECT_FALSE(unacked_packets_.HasUnackedPackets()); + EXPECT_TRUE(unacked_packets_.empty()); if (!GetQuicReloadableFlag(quic_optimize_inflight_check)) { EXPECT_FALSE(unacked_packets_.HasUnackedRetransmittableFrames()); } return; } - EXPECT_TRUE(unacked_packets_.HasUnackedPackets()); + EXPECT_FALSE(unacked_packets_.empty()); for (size_t i = 0; i < num_packets; ++i) { EXPECT_TRUE(unacked_packets_.IsUnacked(packets[i])) << packets[i]; }
diff --git a/net/third_party/quic/core/quic_write_blocked_list.h b/net/third_party/quic/core/quic_write_blocked_list.h index fc3e844..5e41d32 100644 --- a/net/third_party/quic/core/quic_write_blocked_list.h +++ b/net/third_party/quic/core/quic_write_blocked_list.h
@@ -10,6 +10,7 @@ #include "base/macros.h" #include "net/third_party/quic/core/quic_packets.h" +#include "net/third_party/quic/platform/api/quic_containers.h" #include "net/third_party/quic/platform/api/quic_export.h" #include "net/third_party/quic/platform/api/quic_map_util.h" #include "net/third_party/spdy/core/priority_write_scheduler.h" @@ -177,13 +178,12 @@ bool is_blocked; }; - std::vector<StreamIdBlockedPair>::const_iterator begin() const { - return streams_.cbegin(); - } + // Optimized for the typical case of 2 static streams per session. + typedef QuicInlinedVector<StreamIdBlockedPair, 2> StreamsVector; - std::vector<StreamIdBlockedPair>::const_iterator end() const { - return streams_.cend(); - } + StreamsVector::const_iterator begin() const { return streams_.cbegin(); } + + StreamsVector::const_iterator end() const { return streams_.cend(); } size_t num_blocked() const { return num_blocked_; } @@ -254,7 +254,7 @@ private: size_t num_blocked_ = 0; - std::vector<StreamIdBlockedPair> streams_; + StreamsVector streams_; }; StaticStreamCollection static_stream_collection_;
diff --git a/net/third_party/quic/platform/api/quic_test_random.h b/net/third_party/quic/platform/api/quic_test_random.h deleted file mode 100644 index abb65c96..0000000 --- a/net/third_party/quic/platform/api/quic_test_random.h +++ /dev/null
@@ -1,22 +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 NET_THIRD_PARTY_QUIC_PLATFORM_API_QUIC_TEST_RANDOM_H_ -#define NET_THIRD_PARTY_QUIC_PLATFORM_API_QUIC_TEST_RANDOM_H_ - -#include <stdint.h> -#include <limits> - -#include "net/third_party/quic/platform/api/quic_string.h" -#include "net/third_party/quic/platform/impl/quic_test_random_impl.h" - -namespace quic { -namespace test { - -using QuicTestRandom = QuicTestRandomImpl; - -} // namespace test -} // namespace quic - -#endif // NET_THIRD_PARTY_QUIC_PLATFORM_API_QUIC_TEST_RANDOM_H_
diff --git a/net/third_party/quic/platform/api/quic_url_utils.cc b/net/third_party/quic/platform/api/quic_url_utils.cc deleted file mode 100644 index 4cc8f74..0000000 --- a/net/third_party/quic/platform/api/quic_url_utils.cc +++ /dev/null
@@ -1,27 +0,0 @@ -// Copyright (c) 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 "net/third_party/quic/platform/api/quic_url_utils.h" -#include "net/third_party/quic/platform/api/quic_string.h" - -namespace quic { - -// static -QuicString QuicUrlUtils::HostName(QuicStringPiece url) { - return QuicUrlUtilsImpl::HostName(url); -} - -// static -bool QuicUrlUtils::IsValidUrl(QuicStringPiece url) { - return QuicUrlUtilsImpl::IsValidUrl(url); -} - -// static -QuicString QuicUrlUtils::GetPushPromiseUrl(QuicStringPiece scheme, - QuicStringPiece authority, - QuicStringPiece path) { - return QuicUrlUtilsImpl::GetPushPromiseUrl(scheme, authority, path); -} - -} // namespace quic
diff --git a/net/third_party/quic/platform/api/quic_url_utils.h b/net/third_party/quic/platform/api/quic_url_utils.h deleted file mode 100644 index 65a1467..0000000 --- a/net/third_party/quic/platform/api/quic_url_utils.h +++ /dev/null
@@ -1,38 +0,0 @@ -// Copyright (c) 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 NET_THIRD_PARTY_QUIC_PLATFORM_API_QUIC_URL_UTILS_H_ -#define NET_THIRD_PARTY_QUIC_PLATFORM_API_QUIC_URL_UTILS_H_ - -#include "base/macros.h" -#include "net/third_party/quic/platform/api/quic_export.h" -#include "net/third_party/quic/platform/api/quic_string.h" -#include "net/third_party/quic/platform/api/quic_string_piece.h" -#include "net/third_party/quic/platform/impl/quic_url_utils_impl.h" - -namespace quic { - -class QUIC_EXPORT_PRIVATE QuicUrlUtils { - public: - QuicUrlUtils() = delete; - - // Returns hostname, or empty std::string if missing. - static QuicString HostName(QuicStringPiece url); - - // Returns false if any of these conditions occur: (1) Host name too long; (2) - // Invalid characters in host name, path or params; (3) Invalid port number - // (e.g. greater than 65535). - static bool IsValidUrl(QuicStringPiece url); - - // Returns a canonical, valid URL for a PUSH_PROMISE with the specified - // ":scheme", ":authority", and ":path" header fields, or an empty - // string if the resulting URL is not valid or supported. - static QuicString GetPushPromiseUrl(QuicStringPiece scheme, - QuicStringPiece authority, - QuicStringPiece path); -}; - -} // namespace quic - -#endif // NET_THIRD_PARTY_QUIC_PLATFORM_API_QUIC_URL_UTILS_H_
diff --git a/net/third_party/quic/platform/impl/quic_test_random_impl.cc b/net/third_party/quic/platform/impl/quic_test_random_impl.cc deleted file mode 100644 index 0a0965cb..0000000 --- a/net/third_party/quic/platform/impl/quic_test_random_impl.cc +++ /dev/null
@@ -1,58 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/third_party/quic/platform/api/quic_test_random.h" - -#include <memory> - -#include "base/rand_util.h" - -namespace quic { -namespace test { - -bool QuicTestRandom::OneIn(int n) { - return base::RandGenerator(n) == 0; -} - -int32_t QuicTestRandom::Uniform(int32_t n) { - return base::RandGenerator(n); -} - -uint8_t QuicTestRandom::Rand8() { - return base::RandGenerator( - static_cast<uint64_t>(std::numeric_limits<uint8_t>::max()) + 1); -} - -uint16_t QuicTestRandom::Rand16() { - return base::RandGenerator( - static_cast<uint64_t>(std::numeric_limits<uint16_t>::max()) + 1); -} - -uint32_t QuicTestRandom::Rand32() { - return base::RandGenerator( - static_cast<uint64_t>(std::numeric_limits<uint32_t>::max()) + 1); -} - -uint64_t QuicTestRandom::Rand64() { - return base::RandUint64(); -} - -int32_t QuicTestRandom::Next() { - return Rand32(); -} - -int32_t QuicTestRandom::Skewed(int max_log) { - const uint32_t base = Rand32() % (max_log + 1); - const uint32_t mask = ((base < 32) ? (1u << base) : 0u) - 1u; - return Rand32() & mask; -} - -QuicString QuicTestRandom::RandString(int length) { - std::unique_ptr<char[]> buffer(new char[length]); - base::RandBytes(buffer.get(), length); - return QuicString(buffer.get(), length); -} - -} // namespace test -} // namespace quic
diff --git a/net/third_party/quic/platform/impl/quic_test_random_impl.h b/net/third_party/quic/platform/impl/quic_test_random_impl.h deleted file mode 100644 index e8112f3..0000000 --- a/net/third_party/quic/platform/impl/quic_test_random_impl.h +++ /dev/null
@@ -1,52 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_THIRD_PARTY_QUIC_PLATFORM_IMPL_QUIC_TEST_RANDOM_IMPL_H_ -#define NET_THIRD_PARTY_QUIC_PLATFORM_IMPL_QUIC_TEST_RANDOM_IMPL_H_ - -namespace quic { -namespace test { - -class QuicTestRandomBaseImpl { - public: - virtual ~QuicTestRandomBaseImpl() {} - virtual bool OneIn(int n) = 0; - virtual int32_t Uniform(int32_t n) = 0; - virtual uint8_t Rand8() = 0; - virtual uint16_t Rand16() = 0; - virtual uint32_t Rand32() = 0; - virtual uint64_t Rand64() = 0; - virtual int32_t Next() = 0; - virtual int32_t Skewed(int max_log) = 0; - virtual QuicString RandString(int length) = 0; - - // STL UniformRandomNumberGenerator implementation. - typedef uint32_t result_type; - static constexpr result_type min() { return 0; } - static constexpr result_type max() { - return std::numeric_limits<uint32_t>::max(); - } - result_type operator()() { return Rand32(); } -}; - -// QuicTestRandom holds no state: instances use the same base::RandGenerator -// with a global state. -class QuicTestRandomImpl : public QuicTestRandomBaseImpl { - public: - ~QuicTestRandomImpl() override {} - bool OneIn(int n) override; - int32_t Uniform(int32_t n) override; - uint8_t Rand8() override; - uint16_t Rand16() override; - uint32_t Rand32() override; - uint64_t Rand64() override; - int32_t Next() override; - int32_t Skewed(int max_log) override; - QuicString RandString(int length) override; -}; - -} // namespace test -} // namespace quic - -#endif // NET_THIRD_PARTY_QUIC_PLATFORM_IMPL_QUIC_TEST_RANDOM_IMPL_H_
diff --git a/net/third_party/quic/platform/impl/quic_url_utils_impl.cc b/net/third_party/quic/platform/impl/quic_url_utils_impl.cc deleted file mode 100644 index daf5792..0000000 --- a/net/third_party/quic/platform/impl/quic_url_utils_impl.cc +++ /dev/null
@@ -1,154 +0,0 @@ -// Copyright (c) 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. - -#include "net/third_party/quic/platform/impl/quic_url_utils_impl.h" - -#include "url/gurl.h" - -namespace quic { - -// static -std::string QuicUrlUtilsImpl::HostName(QuicStringPiece url) { - return GURL(url).host(); -} - -// static -bool QuicUrlUtilsImpl::IsValidUrl(QuicStringPiece url) { - return GURL(url).is_valid(); -} - -// static -std::string QuicUrlUtilsImpl::GetPushPromiseUrl(QuicStringPiece scheme, - QuicStringPiece authority, - QuicStringPiece path) { - // RFC 7540, Section 8.1.2.3: The ":path" pseudo-header field includes the - // path and query parts of the target URI (the "path-absolute" production - // and optionally a '?' character followed by the "query" production (see - // Sections 3.3 and 3.4 of RFC3986). A request in asterisk form includes the - // value '*' for the ":path" pseudo-header field. - // - // This pseudo-header field MUST NOT be empty for "http" or "https" URIs; - // "http" or "https" URIs that do not contain a path MUST include a value of - // '/'. The exception to this rule is an OPTIONS request for an "http" or - // "https" URI that does not include a path component; these MUST include a - // ":path" pseudo-header with a value of '*' (see RFC7230, Section 5.3.4). - // - // In addition to the above restriction from RFC 7540, note that RFC3986 - // defines the "path-absolute" construction as starting with "/" but not "//". - // - // RFC 7540, Section 8.2.1: The header fields in PUSH_PROMISE and any - // subsequent CONTINUATION frames MUST be a valid and complete set of request - // header fields (Section 8.1.2.3). The server MUST include a method in the - // ":method" pseudo-header field that is safe and cacheable. - // - // RFC 7231, Section 4.2.1: - // ... this specification defines GET, HEAD, and POST as cacheable, ... - // - // Since the OPTIONS method is not cacheable, it cannot be the method of a - // PUSH_PROMISE. Therefore, the exception mentioned in RFC 7540, Section - // 8.1.2.3 about OPTIONS requests does not apply here (i.e. ":path" cannot be - // "*"). - if (path.empty() || path[0] != '/' || (path.size() >= 2 && path[1] == '/')) { - return std::string(); - } - - // Validate the scheme; this is to ensure a scheme of "foo://bar" is not - // parsed as a URL of "foo://bar://baz" when combined with a host of "baz". - std::string canonical_scheme; - url::StdStringCanonOutput canon_output(&canonical_scheme); - url::Component canon_component; - url::Component scheme_component(0, scheme.size()); - - if (!url::CanonicalizeScheme(scheme.data(), scheme_component, &canon_output, - &canon_component) || - !canon_component.is_nonempty() || canon_component.begin != 0) { - return std::string(); - } - canonical_scheme.resize(canon_component.len + 1); - - // Validate the authority; this is to ensure an authority such as - // "host/path" is not accepted, as when combined with a scheme like - // "http://", could result in a URL of "http://host/path". - url::Component auth_component(0, authority.size()); - url::Component username_component; - url::Component password_component; - url::Component host_component; - url::Component port_component; - - url::ParseAuthority(authority.data(), auth_component, &username_component, - &password_component, &host_component, &port_component); - - // RFC 7540, Section 8.1.2.3: The authority MUST NOT include the deprecated - // "userinfo" subcomponent for "http" or "https" schemed URIs. - // - // Note: Although |canonical_scheme| has not yet been checked for that, as - // it is performed later in processing, only "http" and "https" schemed - // URIs are supported for PUSH. - if (username_component.is_valid() || password_component.is_valid()) { - return std::string(); - } - - // Failed parsing or no host present. ParseAuthority() will ensure that - // host_component + port_component cover the entire string, if - // username_component and password_component are not present. - if (!host_component.is_nonempty()) { - return std::string(); - } - - // Validate the port (if present; it's optional). - int parsed_port_number = url::PORT_INVALID; - if (port_component.is_nonempty()) { - parsed_port_number = url::ParsePort(authority.data(), port_component); - if (parsed_port_number < 0 && parsed_port_number != url::PORT_UNSPECIFIED) { - return std::string(); - } - } - - // Validate the host by attempting to canoncalize it. Invalid characters - // will result in a canonicalization failure (e.g. '/') - std::string canon_host; - canon_output = url::StdStringCanonOutput(&canon_host); - canon_component.reset(); - if (!url::CanonicalizeHost(authority.data(), host_component, &canon_output, - &canon_component) || - !canon_component.is_nonempty() || canon_component.begin != 0) { - return std::string(); - } - - // At this point, "authority" has been validated to either be of the form - // 'host:port' or 'host', with 'host' being a valid domain or IP address, - // and 'port' (if present), being a valid port. Attempt to construct a - // URL of just the (scheme, host, port), which should be safe and will not - // result in ambiguous parsing. - // - // This also enforces that all PUSHed URLs are either HTTP or HTTPS-schemed - // URIs, consistent with the other restrictions enforced above. - // - // Note: url::CanonicalizeScheme() will have added the ':' to - // |canonical_scheme|. - GURL origin_url(canonical_scheme + "//" + std::string(authority)); - if (!origin_url.is_valid() || !origin_url.SchemeIsHTTPOrHTTPS() || - // The following checks are merely defense in depth. - origin_url.has_username() || origin_url.has_password() || - (origin_url.has_path() && origin_url.path_piece() != "/") || - origin_url.has_query() || origin_url.has_ref()) { - return std::string(); - } - - // Attempt to parse the path. - std::string spec = origin_url.GetWithEmptyPath().spec(); - spec.pop_back(); // Remove the '/', as ":path" must contain it. - spec.append(std::string(path)); - - // Attempt to parse the full URL, with the path as well. Ensure there is no - // fragment to the query. - GURL full_url(spec); - if (!full_url.is_valid() || full_url.has_ref()) { - return std::string(); - } - - return full_url.spec(); -} - -} // namespace quic
diff --git a/net/third_party/quic/platform/impl/quic_url_utils_impl.h b/net/third_party/quic/platform/impl/quic_url_utils_impl.h deleted file mode 100644 index 84facd98..0000000 --- a/net/third_party/quic/platform/impl/quic_url_utils_impl.h +++ /dev/null
@@ -1,38 +0,0 @@ -// Copyright (c) 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. - -#ifndef NET_THIRD_PARTY_QUIC_PLATFORM_IMPL_QUIC_URL_UTILS_IMPL_H_ -#define NET_THIRD_PARTY_QUIC_PLATFORM_IMPL_QUIC_URL_UTILS_IMPL_H_ - -#include "base/macros.h" -#include "net/third_party/quic/core/quic_server_id.h" -#include "net/third_party/quic/platform/api/quic_export.h" -#include "net/third_party/quic/platform/api/quic_string_piece.h" - -namespace quic { - -class QUIC_EXPORT_PRIVATE QuicUrlUtilsImpl { - public: - // Returns hostname, or empty std::string if missing. - static std::string HostName(QuicStringPiece url); - - // Returns false if any of these conditions occur: (1) Host name too long; (2) - // Invalid characters in host name, path or params; (3) Invalid port number - // (e.g. greater than 65535). - static bool IsValidUrl(QuicStringPiece url); - - // Returns a canonical, valid URL for a PUSH_PROMISE with the specified - // ":scheme", ":authority", and ":path" header fields, or an empty - // string if the resulting URL is not valid or supported. - static std::string GetPushPromiseUrl(QuicStringPiece scheme, - QuicStringPiece authority, - QuicStringPiece path); - - private: - DISALLOW_COPY_AND_ASSIGN(QuicUrlUtilsImpl); -}; - -} // namespace quic - -#endif // NET_THIRD_PARTY_QUIC_PLATFORM_IMPL_QUIC_URL_UTILS_IMPL_H_
diff --git a/net/third_party/quic/platform/impl/quic_url_utils_impl_test.cc b/net/third_party/quic/platform/impl/quic_url_utils_impl_test.cc deleted file mode 100644 index d0e4b01..0000000 --- a/net/third_party/quic/platform/impl/quic_url_utils_impl_test.cc +++ /dev/null
@@ -1,141 +0,0 @@ -// Copyright (c) 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/third_party/quic/platform/impl/quic_url_utils_impl.h" - -#include <cstdint> - -#include "net/third_party/quic/platform/api/quic_arraysize.h" -#include "net/third_party/quic/platform/api/quic_test.h" - -using std::string; - -namespace quic { -namespace test { -namespace { - -using QuicUrlUtilsImplTest = QuicTest; - -TEST_F(QuicUrlUtilsImplTest, GetPushPromiseUrl) { - // Test rejection of various inputs. - EXPECT_EQ("", QuicUrlUtilsImpl::GetPushPromiseUrl("file", "localhost", - "/etc/password")); - EXPECT_EQ("", QuicUrlUtilsImpl::GetPushPromiseUrl( - "file", "", "/C:/Windows/System32/Config/")); - EXPECT_EQ("", QuicUrlUtilsImpl::GetPushPromiseUrl( - "", "https://www.google.com", "/")); - - EXPECT_EQ("", QuicUrlUtilsImpl::GetPushPromiseUrl("https://www.google.com", - "www.google.com", "/")); - EXPECT_EQ("", QuicUrlUtilsImpl::GetPushPromiseUrl("https://", - "www.google.com", "/")); - EXPECT_EQ("", QuicUrlUtilsImpl::GetPushPromiseUrl("https", "", "/")); - EXPECT_EQ( - "", QuicUrlUtilsImpl::GetPushPromiseUrl("https", "", "www.google.com/")); - EXPECT_EQ( - "", QuicUrlUtilsImpl::GetPushPromiseUrl("https", "www.google.com/", "/")); - EXPECT_EQ("", - QuicUrlUtilsImpl::GetPushPromiseUrl("https", "www.google.com", "")); - EXPECT_EQ( - "", QuicUrlUtilsImpl::GetPushPromiseUrl("https", "www.google", ".com/")); - - // Test acception/rejection of various input combinations. - // |input_headers| is an array of pairs. The first value of each pair is a - // string that will be used as one of the inputs of GetPushPromiseUrl(). The - // second value of each pair is a bitfield where the lowest 3 bits indicate - // for which headers that string is valid (in a PUSH_PROMISE). For example, - // the string "http" would be valid for both the ":scheme" and ":authority" - // headers, so the bitfield paired with it is set to SCHEME | AUTH. - const unsigned char SCHEME = (1u << 0); - const unsigned char AUTH = (1u << 1); - const unsigned char PATH = (1u << 2); - const std::pair<const char*, unsigned char> input_headers[] = { - {"http", SCHEME | AUTH}, - {"https", SCHEME | AUTH}, - {"hTtP", SCHEME | AUTH}, - {"HTTPS", SCHEME | AUTH}, - {"www.google.com", AUTH}, - {"90af90e0", AUTH}, - {"12foo%20-bar:00001233", AUTH}, - {"GOO\u200b\u2060\ufeffgoo", AUTH}, - {"192.168.0.5", AUTH}, - {"[::ffff:192.168.0.1.]", AUTH}, - {"http:", AUTH}, - {"bife l", AUTH}, - {"/", PATH}, - {"/foo/bar/baz", PATH}, - {"/%20-2DVdkj.cie/foe_.iif/", PATH}, - {"http://", 0}, - {":443", 0}, - {":80/eddd", 0}, - {"google.com:-0", 0}, - {"google.com:65536", 0}, - {"http://google.com", 0}, - {"http://google.com:39", 0}, - {"//google.com/foo", 0}, - {".com/", 0}, - {"http://www.google.com/", 0}, - {"http://foo:439", 0}, - {"[::ffff:192.168", 0}, - {"]/", 0}, - {"//", 0}}; - for (size_t i = 0; i < QUIC_ARRAYSIZE(input_headers); ++i) { - bool should_accept = (input_headers[i].second & SCHEME); - for (size_t j = 0; j < QUIC_ARRAYSIZE(input_headers); ++j) { - bool should_accept_2 = should_accept && (input_headers[j].second & AUTH); - for (size_t k = 0; k < QUIC_ARRAYSIZE(input_headers); ++k) { - // |should_accept_3| indicates whether or not GetPushPromiseUrl() is - // expected to accept this input combination. - bool should_accept_3 = - should_accept_2 && (input_headers[k].second & PATH); - - std::string url = QuicUrlUtilsImpl::GetPushPromiseUrl( - input_headers[i].first, input_headers[j].first, - input_headers[k].first); - - ::testing::AssertionResult result = ::testing::AssertionSuccess(); - if (url.empty() == should_accept_3) { - result = ::testing::AssertionFailure() - << "GetPushPromiseUrl() accepted/rejected the inputs when " - "it shouldn't have." - << std::endl - << " scheme: " << input_headers[i].first << std::endl - << " authority: " << input_headers[j].first << std::endl - << " path: " << input_headers[k].first << std::endl - << "Output: " << url << std::endl; - } - ASSERT_TRUE(result); - } - } - } - - // Test canonicalization of various valid inputs. - EXPECT_EQ("http://www.google.com/", - QuicUrlUtilsImpl::GetPushPromiseUrl("http", "www.google.com", "/")); - EXPECT_EQ("https://www.goo-gle.com/fOOo/baRR", - QuicUrlUtilsImpl::GetPushPromiseUrl("hTtPs", "wWw.gOo-gLE.cOm", - "/fOOo/baRR")); - EXPECT_EQ("https://www.goo-gle.com:3278/pAth/To/reSOurce", - QuicUrlUtilsImpl::GetPushPromiseUrl( - "hTtPs", "Www.gOo-Gle.Com:000003278", "/pAth/To/reSOurce")); - EXPECT_EQ( - "https://foo%20bar/foo/bar/baz", - QuicUrlUtilsImpl::GetPushPromiseUrl("https", "foo bar", "/foo/bar/baz")); - EXPECT_EQ("http://foo.com:70/e/", QuicUrlUtilsImpl::GetPushPromiseUrl( - "http", "foo.com:0000070", "/e/")); - EXPECT_EQ("http://192.168.0.1:70/e/", - QuicUrlUtilsImpl::GetPushPromiseUrl("http", "0300.0250.00.01:0070", - "/e/")); - EXPECT_EQ("http://192.168.0.1/e/", - QuicUrlUtilsImpl::GetPushPromiseUrl("http", "0xC0a80001", "/e/")); - EXPECT_EQ("http://[::c0a8:1]/", QuicUrlUtilsImpl::GetPushPromiseUrl( - "http", "[::192.168.0.1]", "/")); - EXPECT_EQ("https://[::ffff:c0a8:1]/", - QuicUrlUtilsImpl::GetPushPromiseUrl( - "https", "[::ffff:0xC0.0Xa8.0x0.0x1]", "/")); -} - -}; // namespace -}; // namespace test -}; // namespace quic \ No newline at end of file
diff --git a/net/third_party/quic/quartc/quartc_factory.cc b/net/third_party/quic/quartc/quartc_factory.cc index 66d3873..cdc04b2 100644 --- a/net/third_party/quic/quartc/quartc_factory.cc +++ b/net/third_party/quic/quartc/quartc_factory.cc
@@ -43,6 +43,10 @@ QuicTagVector copt; copt.push_back(kNSTP); + // Enable and request QUIC to include receive timestamps in ACK frames. + SetQuicReloadableFlag(quic_send_timestamps, true); + copt.push_back(kSTMP); + // Enable ACK_DECIMATION_WITH_REORDERING. It requires ack_decimation to be // false. SetQuicReloadableFlag(quic_enable_ack_decimation, false);
diff --git a/net/third_party/quic/test_tools/quic_test_utils.cc b/net/third_party/quic/test_tools/quic_test_utils.cc index 799c1e0..88f943ec 100644 --- a/net/third_party/quic/test_tools/quic_test_utils.cc +++ b/net/third_party/quic/test_tools/quic_test_utils.cc
@@ -245,6 +245,10 @@ return true; } +bool NoOpFramerVisitor::OnNewTokenFrame(const QuicNewTokenFrame& frame) { + return true; +} + bool NoOpFramerVisitor::OnStopSendingFrame(const QuicStopSendingFrame& frame) { return true; }
diff --git a/net/third_party/quic/test_tools/quic_test_utils.h b/net/third_party/quic/test_tools/quic_test_utils.h index b681914..bfad4855 100644 --- a/net/third_party/quic/test_tools/quic_test_utils.h +++ b/net/third_party/quic/test_tools/quic_test_utils.h
@@ -271,6 +271,7 @@ bool(const QuicApplicationCloseFrame& frame)); MOCK_METHOD1(OnNewConnectionIdFrame, bool(const QuicNewConnectionIdFrame& frame)); + MOCK_METHOD1(OnNewTokenFrame, bool(const QuicNewTokenFrame& frame)); MOCK_METHOD1(OnStopSendingFrame, bool(const QuicStopSendingFrame& frame)); MOCK_METHOD1(OnPathChallengeFrame, bool(const QuicPathChallengeFrame& frame)); MOCK_METHOD1(OnPathResponseFrame, bool(const QuicPathResponseFrame& frame)); @@ -318,6 +319,7 @@ bool OnConnectionCloseFrame(const QuicConnectionCloseFrame& frame) override; bool OnApplicationCloseFrame(const QuicApplicationCloseFrame& frame) override; bool OnNewConnectionIdFrame(const QuicNewConnectionIdFrame& frame) override; + bool OnNewTokenFrame(const QuicNewTokenFrame& frame) override; bool OnStopSendingFrame(const QuicStopSendingFrame& frame) override; bool OnPathChallengeFrame(const QuicPathChallengeFrame& frame) override; bool OnPathResponseFrame(const QuicPathResponseFrame& frame) override;
diff --git a/net/third_party/quic/test_tools/simple_quic_framer.cc b/net/third_party/quic/test_tools/simple_quic_framer.cc index e8dec44..f8ff820 100644 --- a/net/third_party/quic/test_tools/simple_quic_framer.cc +++ b/net/third_party/quic/test_tools/simple_quic_framer.cc
@@ -127,6 +127,11 @@ return true; } + bool OnNewTokenFrame(const QuicNewTokenFrame& frame) override { + new_token_frames_.push_back(frame); + return true; + } + bool OnStopSendingFrame(const QuicStopSendingFrame& frame) override { stop_sending_frames_.push_back(frame); return true; @@ -249,6 +254,7 @@ std::vector<QuicWindowUpdateFrame> window_update_frames_; std::vector<QuicBlockedFrame> blocked_frames_; std::vector<QuicNewConnectionIdFrame> new_connection_id_frames_; + std::vector<QuicNewTokenFrame> new_token_frames_; std::vector<QuicMessageFrame> message_frames_; std::vector<std::unique_ptr<QuicString>> stream_data_; };
diff --git a/net/third_party/quic/tools/quic_packet_printer_bin.cc b/net/third_party/quic/tools/quic_packet_printer_bin.cc index d07b6856..b9c3114 100644 --- a/net/third_party/quic/tools/quic_packet_printer_bin.cc +++ b/net/third_party/quic/tools/quic_packet_printer_bin.cc
@@ -160,6 +160,10 @@ std::cerr << "OnNewConnectionIdFrame: " << frame; return true; } + bool OnNewTokenFrame(const QuicNewTokenFrame& frame) override { + std::cerr << "OnNewTokenFrame: " << frame; + return true; + } bool OnStopSendingFrame(const QuicStopSendingFrame& frame) override { std::cerr << "OnStopSendingFrame: " << frame; return true;
diff --git a/remoting/host/input_monitor/local_mouse_input_monitor_win.cc b/remoting/host/input_monitor/local_mouse_input_monitor_win.cc index ea3605ec..64baa3c 100644 --- a/remoting/host/input_monitor/local_mouse_input_monitor_win.cc +++ b/remoting/host/input_monitor/local_mouse_input_monitor_win.cc
@@ -42,6 +42,8 @@ LocalInputMonitor::MouseMoveCallback on_mouse_move_; base::OnceClosure disconnect_callback_; + webrtc::DesktopVector mouse_position_; + // Tracks whether the instance is registered to receive raw input events. bool registered_ = false; @@ -99,18 +101,30 @@ // Notify the observer about mouse events generated locally. Remote (injected) // mouse events do not specify a device handle (based on observed behavior). - if (input->header.dwType == RIM_TYPEMOUSE && - input->header.hDevice != nullptr) { - POINT position; - if (!GetCursorPos(&position)) { - position.x = 0; - position.y = 0; - } - - caller_task_runner_->PostTask( - FROM_HERE, base::BindOnce(on_mouse_move_, webrtc::DesktopVector( - position.x, position.y))); + if (input->header.dwType != RIM_TYPEMOUSE || + input->header.hDevice == nullptr) { + return; } + + POINT position; + if (!GetCursorPos(&position)) { + position.x = 0; + position.y = 0; + } + webrtc::DesktopVector new_position(position.x, position.y); + + // Ignore the event if the cursor position or button states have not changed. + // Note: If GetCursorPos fails above, we err on the safe side and treat it + // like a movement. + if (mouse_position_.equals(new_position) && + !input->data.mouse.usButtonFlags && !new_position.is_zero()) { + return; + } + + mouse_position_ = new_position; + + caller_task_runner_->PostTask( + FROM_HERE, base::BindOnce(on_mouse_move_, std::move(new_position))); } void MouseRawInputHandlerWin::OnError() {
diff --git a/services/network/public/cpp/features.cc b/services/network/public/cpp/features.cc index ecda780..bd224a18 100644 --- a/services/network/public/cpp/features.cc +++ b/services/network/public/cpp/features.cc
@@ -40,7 +40,7 @@ // ResourceScheduler just as HTTP/1.1 resources are. However, requests from such // servers are not subject to kMaxNumDelayableRequestsPerHostPerClient limit. const base::Feature kDelayRequestsOnMultiplexedConnections{ - "DelayRequestsOnMultiplexedConnections", base::FEATURE_DISABLED_BY_DEFAULT}; + "DelayRequestsOnMultiplexedConnections", base::FEATURE_ENABLED_BY_DEFAULT}; } // namespace features } // namespace network
diff --git a/services/network/resource_scheduler_params_manager.cc b/services/network/resource_scheduler_params_manager.cc index 644d785..f363f2a 100644 --- a/services/network/resource_scheduler_params_manager.cc +++ b/services/network/resource_scheduler_params_manager.cc
@@ -87,8 +87,10 @@ features::kDelayRequestsOnMultiplexedConnections, "MaxEffectiveConnectionType")); - if (!max_effective_connection_type) - return result; + if (!max_effective_connection_type) { + // Use a default value if one is not set using field trial params. + max_effective_connection_type = net::EFFECTIVE_CONNECTION_TYPE_3G; + } for (int ect = net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G; ect <= max_effective_connection_type.value(); ++ect) {
diff --git a/services/network/resource_scheduler_params_manager_unittest.cc b/services/network/resource_scheduler_params_manager_unittest.cc index 60f71de..742767b 100644 --- a/services/network/resource_scheduler_params_manager_unittest.cc +++ b/services/network/resource_scheduler_params_manager_unittest.cc
@@ -87,7 +87,6 @@ switch (effective_connection_type) { case net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN: case net::EFFECTIVE_CONNECTION_TYPE_OFFLINE: - case net::EFFECTIVE_CONNECTION_TYPE_3G: case net::EFFECTIVE_CONNECTION_TYPE_4G: EXPECT_EQ(10u, resource_scheduler_params_manager .GetParamsForEffectiveConnectionType( @@ -102,7 +101,20 @@ .GetParamsForEffectiveConnectionType(effective_connection_type) .delay_requests_on_multiplexed_connections); return; - + case net::EFFECTIVE_CONNECTION_TYPE_3G: + EXPECT_EQ(10u, resource_scheduler_params_manager + .GetParamsForEffectiveConnectionType( + effective_connection_type) + .max_delayable_requests); + EXPECT_EQ(0.0, resource_scheduler_params_manager + .GetParamsForEffectiveConnectionType( + effective_connection_type) + .non_delayable_weight); + EXPECT_TRUE( + resource_scheduler_params_manager + .GetParamsForEffectiveConnectionType(effective_connection_type) + .delay_requests_on_multiplexed_connections); + return; case net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G: case net::EFFECTIVE_CONNECTION_TYPE_2G: EXPECT_EQ(8u, resource_scheduler_params_manager @@ -113,7 +125,7 @@ .GetParamsForEffectiveConnectionType( effective_connection_type) .non_delayable_weight); - EXPECT_FALSE( + EXPECT_TRUE( resource_scheduler_params_manager .GetParamsForEffectiveConnectionType(effective_connection_type) .delay_requests_on_multiplexed_connections); @@ -184,6 +196,17 @@ .GetParamsForEffectiveConnectionType(ect) .delay_requests_on_multiplexed_connections); + } else if (effective_connection_type == net::EFFECTIVE_CONNECTION_TYPE_3G) { + EXPECT_EQ(10u, resource_scheduler_params_manager + .GetParamsForEffectiveConnectionType(ect) + .max_delayable_requests); + EXPECT_EQ(0.0, resource_scheduler_params_manager + .GetParamsForEffectiveConnectionType(ect) + .non_delayable_weight); + EXPECT_FALSE(resource_scheduler_params_manager + .GetParamsForEffectiveConnectionType(ect) + .delay_requests_on_multiplexed_connections); + } else { VerifyDefaultParams( resource_scheduler_params_manager,
diff --git a/services/service_manager/public/cpp/service_keepalive.cc b/services/service_manager/public/cpp/service_keepalive.cc index 4eb0d60..d8f30aa 100644 --- a/services/service_manager/public/cpp/service_keepalive.cc +++ b/services/service_manager/public/cpp/service_keepalive.cc
@@ -11,7 +11,7 @@ namespace service_manager { ServiceKeepalive::ServiceKeepalive(ServiceContext* context, - base::TimeDelta idle_timeout, + base::Optional<base::TimeDelta> idle_timeout, TimeoutObserver* timeout_observer) : context_(context), idle_timeout_(idle_timeout), @@ -40,7 +40,9 @@ } void ServiceKeepalive::OnRefCountZero() { - idle_timer_.Start(FROM_HERE, idle_timeout_, + if (!idle_timeout_.has_value()) + return; + idle_timer_.Start(FROM_HERE, idle_timeout_.value(), base::BindRepeating(&ServiceKeepalive::OnTimerExpired, weak_ptr_factory_.GetWeakPtr())); }
diff --git a/services/service_manager/public/cpp/service_keepalive.h b/services/service_manager/public/cpp/service_keepalive.h index af5db0c7..9fb0b9df 100644 --- a/services/service_manager/public/cpp/service_keepalive.h +++ b/services/service_manager/public/cpp/service_keepalive.h
@@ -9,6 +9,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" +#include "base/optional.h" #include "base/timer/timer.h" #include "services/service_manager/public/cpp/service_context_ref.h" @@ -39,10 +40,12 @@ }; // Creates a keepalive which allows the service to be idle for |idle_timeout| - // before requesting termination. Both |context| and |timeout_observer| are - // not owned and must outlive the ServiceKeepalive instance. + // before requesting termination. If |idle_timeout| is not given, the + // ServiceKeepalive will never request termination, i.e. the service will + // stay alive indefinitely. Both |context| and |timeout_observer| are not + // owned and must outlive the ServiceKeepalive instance. ServiceKeepalive(ServiceContext* context, - base::TimeDelta idle_timeout, + base::Optional<base::TimeDelta> idle_timeout, TimeoutObserver* timeout_observer = nullptr); ~ServiceKeepalive(); @@ -55,7 +58,7 @@ void OnTimerExpired(); ServiceContext* const context_; - const base::TimeDelta idle_timeout_; + const base::Optional<base::TimeDelta> idle_timeout_; TimeoutObserver* const timeout_observer_; base::OneShotTimer idle_timer_; ServiceContextRefFactory ref_factory_;
diff --git a/services/video_capture/service_impl.cc b/services/video_capture/service_impl.cc index 9c981ae..0316e85 100644 --- a/services/video_capture/service_impl.cc +++ b/services/video_capture/service_impl.cc
@@ -4,6 +4,7 @@ #include "services/video_capture/service_impl.h" +#include "build/build_config.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "services/service_manager/public/cpp/service_context.h" #include "services/video_capture/device_factory_provider_impl.h" @@ -13,9 +14,8 @@ namespace video_capture { -ServiceImpl::ServiceImpl(float shutdown_delay_in_seconds) - : shutdown_delay_in_seconds_(shutdown_delay_in_seconds), - weak_factory_(this) {} +ServiceImpl::ServiceImpl(base::Optional<base::TimeDelta> shutdown_delay) + : shutdown_delay_(shutdown_delay), weak_factory_(this) {} ServiceImpl::~ServiceImpl() { DCHECK(thread_checker_.CalledOnValidThread()); @@ -25,7 +25,14 @@ // static std::unique_ptr<service_manager::Service> ServiceImpl::Create() { - return std::make_unique<ServiceImpl>(); +#if defined(OS_ANDROID) + // On Android, we do not use automatic service shutdown, because when shutting + // down the service, we lose caching of the supported formats, and re-querying + // these can take several seconds on certain Android devices. + return std::make_unique<ServiceImpl>(base::Optional<base::TimeDelta>()); +#else + return std::make_unique<ServiceImpl>(base::TimeDelta::FromSeconds(5)); +#endif } void ServiceImpl::SetDestructionObserver(base::OnceClosure observer_cb) { @@ -66,8 +73,7 @@ // SetServiceContextRefProviderForTesting(). if (!ref_factory_) { ref_factory_ = std::make_unique<service_manager::ServiceKeepalive>( - context(), base::TimeDelta::FromSecondsD(shutdown_delay_in_seconds_), - this); + context(), shutdown_delay_, this); } registry_.AddInterface<mojom::DeviceFactoryProvider>(
diff --git a/services/video_capture/service_impl.h b/services/video_capture/service_impl.h index 5fabb9a..e5b93d9 100644 --- a/services/video_capture/service_impl.h +++ b/services/video_capture/service_impl.h
@@ -25,7 +25,9 @@ class ServiceImpl : public service_manager::Service, public service_manager::ServiceKeepalive::TimeoutObserver { public: - ServiceImpl(float shutdown_delay_in_seconds = 5.0f); + // If |shutdown_delay| is provided, the service will shut itself down as soon + // as no client was connect for the corresponding duration. + explicit ServiceImpl(base::Optional<base::TimeDelta> shutdown_delay); ~ServiceImpl() override; static std::unique_ptr<service_manager::Service> Create(); @@ -58,7 +60,7 @@ void LazyInitializeDeviceFactoryProvider(); void OnProviderClientDisconnected(); - const float shutdown_delay_in_seconds_; + const base::Optional<base::TimeDelta> shutdown_delay_; #if defined(OS_WIN) // COM must be initialized in order to access the video capture devices. base::win::ScopedCOMInitializer com_initializer_;
diff --git a/services/video_capture/service_main.cc b/services/video_capture/service_main.cc index 52ae77d..52093729 100644 --- a/services/video_capture/service_main.cc +++ b/services/video_capture/service_main.cc
@@ -7,6 +7,7 @@ #include "services/video_capture/service_impl.h" MojoResult ServiceMain(MojoHandle service_request_handle) { - return service_manager::ServiceRunner(new video_capture::ServiceImpl()) + return service_manager::ServiceRunner( + video_capture::ServiceImpl::Create().release()) .Run(service_request_handle); }
diff --git a/services/video_capture/test/device_factory_provider_connectortest.cc b/services/video_capture/test/device_factory_provider_connectortest.cc index 30e2165..af211e1 100644 --- a/services/video_capture/test/device_factory_provider_connectortest.cc +++ b/services/video_capture/test/device_factory_provider_connectortest.cc
@@ -24,6 +24,7 @@ // Test fixture that creates a video_capture::ServiceImpl and sets up a // local service_manager::Connector through which client code can connect to // it. +template <class DeviceFactoryProviderConnectorTestTraits> class DeviceFactoryProviderConnectorTest : public ::testing::Test { public: DeviceFactoryProviderConnectorTest() {} @@ -32,13 +33,8 @@ void SetUp() override { base::CommandLine::ForCurrentProcess()->AppendSwitch( switches::kUseFakeDeviceForMediaStream); - // We need to set the shutdown delay to at least some epsilon > 0 in order - // to avoid the service shutting down synchronously which would prevent - // test case ServiceIncreasesRefCountOnNewConnectionAfterDisconnect from - // being able to reconnect before the timer expires. - static const float kShutdownDelayInSeconds = 0.0001f; - std::unique_ptr<ServiceImpl> service_impl = - std::make_unique<ServiceImpl>(kShutdownDelayInSeconds); + std::unique_ptr<ServiceImpl> service_impl = std::make_unique<ServiceImpl>( + DeviceFactoryProviderConnectorTestTraits::shutdown_delay()); service_impl->SetDestructionObserver(base::BindOnce( [](base::RunLoop* service_destroyed_wait_loop) { service_destroyed_wait_loop->Quit(); @@ -59,7 +55,9 @@ } void TearDown() override { - if (factory_provider_.is_bound()) { + if (factory_provider_.is_bound() && + DeviceFactoryProviderConnectorTestTraits::shutdown_delay() + .has_value()) { factory_provider_.reset(); service_destroyed_wait_loop_.Run(); } @@ -78,9 +76,22 @@ std::unique_ptr<service_manager::TestConnectorFactory> connector_factory_; }; +// We need to set the shutdown delay to at least some epsilon > 0 in order +// to avoid the service shutting down synchronously which would prevent +// test case ServiceIncreasesRefCountOnNewConnectionAfterDisconnect from +// being able to reconnect before the timer expires. +struct ShortShutdownDelayDeviceFactoryProviderConnectorTestTraits { + static base::Optional<base::TimeDelta> shutdown_delay() { + return base::TimeDelta::FromMicroseconds(100); + } +}; +using ShortShutdownDelayDeviceFactoryProviderConnectorTest = + DeviceFactoryProviderConnectorTest< + ShortShutdownDelayDeviceFactoryProviderConnectorTestTraits>; + // Tests that the service does not quit when a client connects // while a second client stays connected. -TEST_F(DeviceFactoryProviderConnectorTest, +TEST_F(ShortShutdownDelayDeviceFactoryProviderConnectorTest, ServiceDoesNotQuitWhenOneOfTwoClientsDisconnects) { // Establish second connection mojom::DeviceFactoryProviderPtr second_connection; @@ -109,7 +120,7 @@ // Tests that the service quits when the only client disconnects after not // having done anything other than obtaining a connection to the fake device // factory. -TEST_F(DeviceFactoryProviderConnectorTest, +TEST_F(ShortShutdownDelayDeviceFactoryProviderConnectorTest, ServiceQuitsWhenSingleClientDisconnected) { mojom::DeviceFactoryPtr factory; factory_provider_->ConnectToDeviceFactory(mojo::MakeRequest(&factory)); @@ -120,7 +131,7 @@ } // Tests that the service quits when both of two clients disconnect. -TEST_F(DeviceFactoryProviderConnectorTest, +TEST_F(ShortShutdownDelayDeviceFactoryProviderConnectorTest, ServiceQuitsWhenAllClientsDisconnected) { // Bind another client to the DeviceFactoryProvider interface. mojom::DeviceFactoryProviderPtr second_connection; @@ -137,7 +148,7 @@ // Tests that the service increase the context ref count when a new connection // comes in after all previous connections have been released. -TEST_F(DeviceFactoryProviderConnectorTest, +TEST_F(ShortShutdownDelayDeviceFactoryProviderConnectorTest, ServiceIncreasesRefCountOnNewConnectionAfterDisconnect) { base::RunLoop wait_loop; service_impl_->SetShutdownTimeoutCancelledObserver(base::BindRepeating( @@ -152,7 +163,7 @@ // Tests that the service quits when the last client disconnects while using a // device. -TEST_F(DeviceFactoryProviderConnectorTest, +TEST_F(ShortShutdownDelayDeviceFactoryProviderConnectorTest, ServiceQuitsWhenClientDisconnectsWhileUsingDevice) { mojom::DeviceFactoryPtr factory; factory_provider_->ConnectToDeviceFactory(mojo::MakeRequest(&factory)); @@ -201,4 +212,41 @@ service_destroyed_wait_loop_.Run(); } +struct NoAutomaticShutdownDeviceFactoryProviderConnectorTestTraits { + static base::Optional<base::TimeDelta> shutdown_delay() { + return base::Optional<base::TimeDelta>(); + } +}; +using NoAutomaticShutdownDeviceFactoryProviderConnectorTest = + DeviceFactoryProviderConnectorTest< + NoAutomaticShutdownDeviceFactoryProviderConnectorTestTraits>; + +// Tests that the service does not shut down after disconnecting. +TEST_F(NoAutomaticShutdownDeviceFactoryProviderConnectorTest, + ServiceDoesNotShutDownOnDisconnect) { + { + base::RunLoop wait_loop; + service_impl_->SetFactoryProviderClientDisconnectedObserver( + wait_loop.QuitClosure()); + factory_provider_.reset(); + wait_loop.Run(); + } + + base::MockCallback<base::OnceClosure> service_impl_destructor_cb; + service_impl_->SetDestructionObserver(service_impl_destructor_cb.Get()); + EXPECT_CALL(service_impl_destructor_cb, Run()).Times(0); + + // Wait for an arbitrary short extra time after which we are convinced that + // there is enough evidence that service is not going to shut down. + { + base::RunLoop wait_loop; + base::OneShotTimer wait_timer; + wait_timer.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(10), + wait_loop.QuitClosure()); + wait_loop.Run(); + } + + service_impl_->SetDestructionObserver(base::DoNothing()); +} + } // namespace video_capture
diff --git a/docs/es6_chromium.md b/styleguide/web/es6.md similarity index 100% rename from docs/es6_chromium.md rename to styleguide/web/es6.md
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 73e9992..9514f6d 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -4133,7 +4133,7 @@ ], "experiments": [ { - "name": "Enabled", + "name": "Enabled2", "enable_features": [ "ServiceWorkerServicification" ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG index 54ca084c2..47d8edb7 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -59,7 +59,6 @@ crbug.com/728378 compositing/culling/tile-occlusion-boundaries.html [ Failure ] crbug.com/591099 compositing/iframes/floating-self-painting-frame.html [ Failure ] crbug.com/591099 css3/filters/composited-layer-child-bounds-after-composited-to-sw-shadow-change.html [ Failure ] -crbug.com/714962 css3/masking/clip-path-reference-box-inline.html [ Failure ] crbug.com/591099 editing/selection/paint-hyphen.html [ Pass ] crbug.com/591099 external/wpt/css/CSS2/floats/float-nowrap-3.html [ Pass ] crbug.com/591099 external/wpt/css/CSS2/floats/floats-line-wrap-shifted-001.html [ Pass ] @@ -193,8 +192,6 @@ crbug.com/591099 external/wpt/css/selectors/selector-placeholder-shown-type-change-001.html [ Pass ] crbug.com/591099 external/wpt/css/selectors/selector-read-write-type-change-002.html [ Pass ] crbug.com/591099 external/wpt/css/selectors/selector-required-type-change-002.html [ Pass ] -crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/contain/contain-paint-clip-002.html [ Pass ] -crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/contain/contain-paint-clip-006.html [ Pass ] crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-self-horiz-002.xhtml [ Pass ] crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-writing-mode-011.html [ Pass ] crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-writing-mode-012.html [ Pass ] @@ -280,7 +277,7 @@ crbug.com/591099 external/wpt/svg/painting/reftests/paint-context-001.svg [ Failure ] crbug.com/591099 external/wpt/svg/painting/reftests/paint-context-002.svg [ Failure ] crbug.com/591099 external/wpt/svg/path/bearing/zero.svg [ Failure ] -crbug.com/591099 external/wpt/webrtc/RTCDTMFSender-ontonechange.https.html [ Pass ] +crbug.com/591099 external/wpt/webrtc/RTCDTMFSender-ontonechange.https.html [ Failure Pass ] crbug.com/591099 external/wpt/webrtc/RTCPeerConnection-setLocalDescription-answer.html [ Pass ] crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_partially_move_down.html [ Failure ] crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/2_tracks.html [ Failure ] @@ -328,7 +325,7 @@ crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_outline_shorthand.html [ Failure ] crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_normal_wrapped.html [ Failure ] crbug.com/591099 external/wpt/workers/Worker_ErrorEvent_error.htm [ Pass ] -crbug.com/591099 external/wpt/workers/Worker_terminate_event_queue.htm [ Crash Timeout ] +crbug.com/591099 external/wpt/workers/Worker_terminate_event_queue.htm [ Timeout ] crbug.com/591099 external/wpt/workers/baseurl/alpha/worker-in-worker.html [ Pass ] crbug.com/591099 external/wpt/workers/constructors/Worker/same-origin.html [ Timeout ] crbug.com/591099 external/wpt/workers/semantics/interface-objects/004.html [ Failure ] @@ -389,7 +386,6 @@ crbug.com/591099 fast/writing-mode/fieldsets.html [ Failure ] crbug.com/591099 fast/writing-mode/percentage-height-orthogonal-writing-modes.html [ Failure ] crbug.com/591099 fast/writing-mode/table-percent-width-quirk.html [ Pass ] -crbug.com/591099 hittesting/inline-with-clip-path.html [ Failure ] crbug.com/855039 html/details_summary/details-writing-mode-align-center.html [ Failure ] crbug.com/855039 html/details_summary/details-writing-mode-align-left.html [ Failure ] crbug.com/855039 html/details_summary/details-writing-mode-align-right.html [ Failure ] @@ -404,7 +400,7 @@ crbug.com/591099 http/tests/intersection-observer/v2/cross-origin-effects.html [ Failure ] crbug.com/591099 http/tests/intersection-observer/v2/cross-origin-occlusion.html [ Failure ] crbug.com/591099 http/tests/local/fileapi/select-dragged-file-input.html [ Skip ] -crbug.com/591099 http/tests/misc/object-embedding-svg-delayed-size-negotiation.xhtml [ Failure ] +crbug.com/591099 http/tests/misc/object-embedding-svg-delayed-size-negotiation.xhtml [ Failure Pass ] crbug.com/591099 http/tests/security/cors-rfc1918/addressspace-document-appcache.https.html [ Crash Failure ] crbug.com/591099 http/tests/security/cors-rfc1918/addressspace-document-csp-appcache.https.html [ Crash Failure Pass ] crbug.com/591099 http/tests/security/setDomainRelaxationForbiddenForURLScheme.html [ Crash ] @@ -462,7 +458,7 @@ crbug.com/591099 storage/indexeddb/objectstore-cursor.html [ Pass ] crbug.com/591099 svg/hixie/error/013.xml [ Failure ] crbug.com/591099 svg/transforms/svg-css-transforms.xhtml [ Failure ] -crbug.com/591099 svg/transforms/text-with-pattern-inside-transformed-html.xhtml [ Failure ] +crbug.com/591099 svg/transforms/text-with-pattern-inside-transformed-html.xhtml [ Failure Pass ] crbug.com/591099 svg/zoom/page/zoom-img-preserveAspectRatio-support-1.html [ Failure ] crbug.com/591099 svg/zoom/page/zoom-svg-float-border-padding.xml [ Failure ] crbug.com/591099 svg/zoom/page/zoom-svg-through-object-with-absolute-size-2.xhtml [ Failure ] @@ -475,7 +471,7 @@ crbug.com/591099 tables/mozilla/bugs/bug50695-2.html [ Failure ] crbug.com/591099 tables/mozilla/bugs/bug55527.html [ Failure ] crbug.com/591099 transforms/svg-vs-css.xhtml [ Failure ] -crbug.com/870008 virtual/android/rootscroller/position-fixed-in-unscrollable-document-iframe.html [ Failure ] +crbug.com/870008 virtual/android/rootscroller/position-fixed-in-unscrollable-document-iframe.html [ Failure Pass ] crbug.com/870008 virtual/android/rootscroller/position-fixed-in-unscrollable-document.html [ Failure ] crbug.com/591099 virtual/exotic-color-space/ [ Skip ] crbug.com/591099 virtual/feature-policy-vibrate/ [ Skip ] @@ -519,5 +515,5 @@ crbug.com/591099 virtual/threaded/ [ Skip ] crbug.com/591099 virtual/user-activation-v2/fast/events/mouse-cursor.html [ Failure ] crbug.com/591099 virtual/user-activation-v2/fast/events/touch/compositor-touch-hit-rects.html [ Failure ] -crbug.com/591099 virtual/video-surface-layer/media/video-layer-crash.html [ Crash Failure Pass ] -crbug.com/591099 virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/RTCDTMFSender-ontonechange.https.html [ Failure Pass ] +crbug.com/591099 virtual/video-surface-layer/media/video-layer-crash.html [ Crash Pass ] +crbug.com/591099 virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/RTCDTMFSender-ontonechange.https.html [ Pass ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-gen-property-trees b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-gen-property-trees index 2ea7da2..0d4ba7161 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-gen-property-trees +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-gen-property-trees
@@ -60,7 +60,6 @@ Bug(none) vibration/ [ Skip ] Bug(none) virtual/cors-rfc1918/ [ Skip ] Bug(none) virtual/custom-user-timing/ [ Skip ] -Bug(none) virtual/enable_asmjs/ [ Skip ] Bug(none) virtual/enable_wasm/ [ Skip ] Bug(none) virtual/exotic-color-space/ [ Skip ] Bug(none) virtual/feature-policy-permissions/ [ Skip ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService b/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService index b95ae80..60f6ebf 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService
@@ -1,8 +1,6 @@ # These tests currently fail when run with --enable-features=NetworkSerivce # See https://crbug.com/729849 -crbug.com/829417 external/wpt/html/browsers/offline/appcache/workers/appcache-worker.https.html [ Timeout ] - Bug(none) http/tests/security/cors-rfc1918 [ Crash Timeout ] Bug(none) http/tests/security/powerfulFeatureRestrictions/old-powerful-features-on-insecure-origin.html [ Pass Timeout ] Bug(none) virtual/outofblink-cors/http/tests/security/cors-rfc1918 [ Crash Timeout ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2 b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2 index 4766be0..6f821ef 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2 +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
@@ -68,7 +68,6 @@ Bug(none) virtual/android/ [ Skip ] Bug(none) virtual/blink-gen-property-trees/ [ Skip ] -Bug(none) virtual/enable_asmjs/ [ Skip ] Bug(none) virtual/enable_wasm/ [ Skip ] Bug(none) virtual/exotic-color-space/ [ Skip ] Bug(none) virtual/gpu/ [ Skip ]
diff --git a/third_party/WebKit/LayoutTests/LeakExpectations b/third_party/WebKit/LayoutTests/LeakExpectations index 3135bd4..09430a9 100644 --- a/third_party/WebKit/LayoutTests/LeakExpectations +++ b/third_party/WebKit/LayoutTests/LeakExpectations
@@ -15,6 +15,12 @@ crbug.com/410974 virtual/scroll_customization/fast/scroll-behavior/scroll-customization/touch-scroll-customization.html [ Leak ] crbug.com/410974 virtual/scroll_customization/fast/scroll-behavior/scroll-customization/scrollstate-distribute-to-scroll-chain-descendant.html [ Leak ] +# FIXME: rootscroller/set-root-scroller.html on WebKit Linux Trusty +crbug.com/891575 rootscroller/set-root-scroller.html [ Leak ] +crbug.com/891575 virtual/android/rootscroller/remove-rootscroller-crash.html [ Leak Pass ] +crbug.com/891575 virtual/android/rootscroller/set-root-scroller.html [ Leak ] +crbug.com/891575 virtual/android/fullscreen/video-overlay-scroll.html [ Leak Pass ] + # ----------------------------------------------------------------- # Untriaged but known leaks of PausableObject (fast). # -----------------------------------------------------------------
diff --git a/third_party/WebKit/LayoutTests/VirtualTestSuites b/third_party/WebKit/LayoutTests/VirtualTestSuites index 52ca328..bc5d0c1 100644 --- a/third_party/WebKit/LayoutTests/VirtualTestSuites +++ b/third_party/WebKit/LayoutTests/VirtualTestSuites
@@ -337,11 +337,6 @@ "args": ["--enable-features=WebAssembly"] }, { - "prefix": "enable_asmjs", - "base": "http/tests/asmjs", - "args": ["--enable-features=AsmJsToWebAssembly"] - }, - { "prefix": "layout_ng", "base": "fast/block/basic", "args": ["--enable-blink-features=LayoutNG"]
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-masking/clip-path/clip-path-inline-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-masking/clip-path/clip-path-inline-001.html new file mode 100644 index 0000000..3436464 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-masking/clip-path/clip-path-inline-001.html
@@ -0,0 +1,27 @@ +<!DOCTYPE html> +<title>clip-path on inline, horizontal-tb writing-mode</title> +<link rel="author" title="Morten Stenshorne" href="mstensho@chromium.org"> +<link rel="help" href="https://www.w3.org/TR/css-masking-1/#the-clip-path" title="5.1 Clipping Shape: the clip-path property"> +<link rel="match" href="../../reference/ref-filled-green-100px-square.xht"> +<meta content="ahem" name="flags"> +<style> + .container { + writing-mode: horizontal-tb; + font: 100px/1 Ahem; + line-height: 100px; + color: red; + } + .container::first-letter { + color:green; + } + .container > span { + clip-path: polygon(0% 0%, 50% 0%, 50% 100%, 0% 100%); + } +</style> +<p>Test passes if there is a filled green square and <strong>no red</strong>.</p> +<div class="container"> + <span> + XX<br> + XXX + </span> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-masking/clip-path/clip-path-inline-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-masking/clip-path/clip-path-inline-002.html new file mode 100644 index 0000000..d56117e --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-masking/clip-path/clip-path-inline-002.html
@@ -0,0 +1,28 @@ +<!DOCTYPE html> +<title>clip-path on inline, vertical-rl writing-mode</title> +<link rel="author" title="Morten Stenshorne" href="mstensho@chromium.org"> +<link rel="help" href="https://www.w3.org/TR/css-masking-1/#the-clip-path" title="5.1 Clipping Shape: the clip-path property"> +<link rel="match" href="../../reference/ref-filled-green-100px-square.xht"> +<meta content="ahem" name="flags"> +<style> + .container { + writing-mode: vertical-rl; + margin-left: -100px; + font: 100px/1 Ahem; + line-height: 100px; + color: red; + } + .container::first-letter { + color:green; + } + .container > span { + clip-path: polygon(0% 0%, 100% 0%, 100% 50%, 0% 50%); + } +</style> +<p>Test passes if there is a filled green square and <strong>no red</strong>.</p> +<div class="container"> + <span> + XX<br> + XXX + </span> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-masking/clip-path/clip-path-inline-003.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-masking/clip-path/clip-path-inline-003.html new file mode 100644 index 0000000..4c907a46 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-masking/clip-path/clip-path-inline-003.html
@@ -0,0 +1,27 @@ +<!DOCTYPE html> +<title>clip-path on inline, vertical-lr writing-mode</title> +<link rel="author" title="Morten Stenshorne" href="mstensho@chromium.org"> +<link rel="help" href="https://www.w3.org/TR/css-masking-1/#the-clip-path" title="5.1 Clipping Shape: the clip-path property"> +<link rel="match" href="../../reference/ref-filled-green-100px-square.xht"> +<meta content="ahem" name="flags"> +<style> + .container { + writing-mode: vertical-lr; + font: 100px/1 Ahem; + line-height: 100px; + color: red; + } + .container::first-letter { + color:green; + } + .container > span { + clip-path: polygon(0% 0%, 100% 0%, 100% 50%, 0% 50%); + } +</style> +<p>Test passes if there is a filled green square and <strong>no red</strong>.</p> +<div class="container"> + <span> + XX<br> + XXX + </span> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/offline/appcache/appcache-iframe.https.html b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/offline/appcache/appcache-iframe.https.html new file mode 100644 index 0000000..8e72664 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/offline/appcache/appcache-iframe.https.html
@@ -0,0 +1,37 @@ +<html manifest="resources/appcache-iframe.manifest"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +const initPromise = new Promise(resolve => { + applicationCache.addEventListener('cached', resolve, false); + applicationCache.addEventListener('noupdate', resolve, false); +}); + +function with_iframe(url) { + return new Promise(resolve => { + let frame = document.createElement('iframe'); + frame.src = url; + frame.onload = () => { resolve(frame); }; + document.body.appendChild(frame); + add_result_callback(() => frame.remove()); + }); +} + +promise_test(async t => { + await initPromise; + const frame = + await with_iframe('resources/appcache-iframe.py?type=cached'); + const msgEvent = await new Promise(r => window.onmessage = r); + assert_equals(msgEvent.data, 'Done: cached'); + }, 'iframe should be loaded from application caches.'); + +promise_test(async t => { + await initPromise; + const frame = + await with_iframe('resources/appcache-iframe.py?type=fallingback'); + const msgEvent = await new Promise(r => window.onmessage = r); + assert_equals(msgEvent.data, 'Done: fallbacked'); + }, 'iframe should be loaded from application caches for fallback.'); + +</script> +</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/offline/appcache/resources/appcache-data.py b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/offline/appcache/resources/appcache-data.py new file mode 100644 index 0000000..f92c511 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/offline/appcache/resources/appcache-data.py
@@ -0,0 +1,5 @@ +def main(request, response): + type = request.GET['type'] + if request.GET['type'] == 'fallingback': + return 404, [('Content-Type', 'text/plain')], "Page not found" + return [('Content-Type', 'text/plain')], type
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/offline/appcache/resources/appcache-iframe.manifest b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/offline/appcache/resources/appcache-iframe.manifest new file mode 100644 index 0000000..7221e90 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/offline/appcache/resources/appcache-iframe.manifest
@@ -0,0 +1,8 @@ +CACHE MANIFEST + +appcache-iframe.py?type=cached +appcache-data.py?type=cached + +FALLBACK: +appcache-iframe.py?type=fallingback appcache-iframe.py?type=fallbacked +appcache-data.py?type=fallingback appcache-data.py?type=fallbacked
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/offline/appcache/resources/appcache-iframe.py b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/offline/appcache/resources/appcache-iframe.py new file mode 100644 index 0000000..bc82788 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/offline/appcache/resources/appcache-iframe.py
@@ -0,0 +1,43 @@ +script = ''' +<script> +function fetchCachedFileTest() { + return fetch('appcache-data.py?type=cached') + .then(res => res.text(), + _ => { throw new Error('Failed to fetch cached file'); }) + .then(text => { + if (text != 'cached') { + throw new Error('cached file missmatch'); + } + }); +} + +function fetchNotInCacheFileTest() { + return fetch('appcache-data.py?type=not-in-cache') + .then(_ => { throw new Error('Fetching not-in-cache file must fail'); }, + _ => {}); +} + +function fetchFallbackFileTest() { + return fetch('appcache-data.py?type=fallingback') + .then(res => res.text(), + _ => { throw new Error('Failed to fetch fallingback file'); }) + .then(text => { + if (text != 'fallbacked') { + throw new Error('fallbacked file miss match'); + } + }); +} + +fetchCachedFileTest() + .then(fetchNotInCacheFileTest) + .then(fetchFallbackFileTest) + .then(_ => window.parent.postMessage('Done: %s'), + error => window.parent.postMessage(error.toString())); +</script> +''' + +def main(request, response): + type = request.GET['type'] + if request.GET['type'] == 'fallingback': + return 404, [('Content-Type', 'text/plain')], "Page not found" + return [('Content-Type', 'text/html')], script % type
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/offline/appcache/workers/resources/appcache-worker.py b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/offline/appcache/workers/resources/appcache-worker.py index 00281a2b..10643219 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/offline/appcache/workers/resources/appcache-worker.py +++ b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/offline/appcache/workers/resources/appcache-worker.py
@@ -91,6 +91,7 @@ .then(importFallbackScriptTest) .then(fetchCachedFileTest) .then(fetchNotInCacheFileTest) + .then(fetchFallbackFileTest) .then(_ => postMessage('Done: %s'), error => postMessage(error.toString())); '''
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCQuicStream.https.html b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCQuicStream.https.html index 33025451..68c88e27 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCQuicStream.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCQuicStream.https.html
@@ -13,13 +13,14 @@ // The following helper functions are called from RTCQuicTransport-helper.js: // makeStandaloneQuicTransport +// makeTwoConnectedQuicTransports promise_test(async t => { - const quicTransport = await makeStandaloneQuicTransport(t); + const [ quicTransport, ] = await makeTwoConnectedQuicTransports(t); const quicStream = quicTransport.createStream(); assert_equals(quicStream.transport, quicTransport, 'Expect transport to be set to the creating RTCQuicTransport.'); - assert_equals(quicStream.state, 'new', `Expect state to be 'new'.`); + assert_equals(quicStream.state, 'open', `Expect state to be 'open'.`); assert_equals(quicStream.readBufferedAmount, 0, 'Expect read buffered amount to be 0.'); assert_equals(quicStream.writeBufferedAmount, 0, @@ -28,17 +29,130 @@ promise_test(async t => { const quicTransport = await makeStandaloneQuicTransport(t); + assert_throws('InvalidStateError', () => quicTransport.createStream()); +}, 'createStream() throws if the transport is not connected.'); + +promise_test(async t => { + const quicTransport = await makeStandaloneQuicTransport(t); quicTransport.stop(); assert_throws('InvalidStateError', () => quicTransport.createStream()); }, 'createStream() throws if the transport is closed.'); promise_test(async t => { - const quicTransport = await makeStandaloneQuicTransport(t); + const [ quicTransport, ] = await makeTwoConnectedQuicTransports(t); const firstQuicStream = quicTransport.createStream(); const secondQuicStream = quicTransport.createStream(); quicTransport.stop(); assert_equals(firstQuicStream.state, 'closed'); assert_equals(secondQuicStream.state, 'closed'); -}, 'RTCQuicTransport.stop() closes all streams.'); +}, 'RTCQuicTransport.stop() closes all local streams.'); + +promise_test(async t => { + const [ localQuicTransport, remoteQuicTransport ] = + await makeTwoConnectedQuicTransports(t); + const firstLocalStream = localQuicTransport.createStream(); + firstLocalStream.finish(); + const secondLocalStream = localQuicTransport.createStream(); + secondLocalStream.finish(); + const remoteWatcher = + new EventWatcher(t, remoteQuicTransport, [ 'quicstream', 'statechange' ]); + const { stream: firstRemoteStream } = + await remoteWatcher.wait_for('quicstream'); + const { stream: secondRemoteStream } = + await remoteWatcher.wait_for('quicstream'); + localQuicTransport.stop(); + await remoteWatcher.wait_for('statechange'); + assert_equals(firstRemoteStream.state, 'closed'); + assert_equals(secondRemoteStream.state, 'closed'); +}, 'RTCQuicTransport.stop() closes all remote streams.'); + +promise_test(async t => { + const [ localQuicTransport, remoteQuicTransport ] = + await makeTwoConnectedQuicTransports(t); + const localStream = localQuicTransport.createStream(); + localStream.finish(); + assert_equals(localStream.state, 'closing'); +}, `finish() changes state to 'closing'.`); + +promise_test(async t => { + const [ localQuicTransport, remoteQuicTransport ] = + await makeTwoConnectedQuicTransports(t); + const localStream = localQuicTransport.createStream(); + localStream.finish(); + localStream.finish(); + assert_equals(localStream.state, 'closing'); +}, `finish() twice does not change state.`); + +promise_test(async t => { + const [ localQuicTransport, remoteQuicTransport ] = + await makeTwoConnectedQuicTransports(t); + const localStream = localQuicTransport.createStream(); + localStream.reset(); + assert_equals(localStream.state, 'closed'); +}, `reset() changes state to 'closed'.`); + +promise_test(async t => { + const [ localQuicTransport, remoteQuicTransport ] = + await makeTwoConnectedQuicTransports(t); + const localStream = localQuicTransport.createStream(); + localStream.finish(); + localStream.reset(); + assert_equals(localStream.state, 'closed'); +}, `reset() following finish() changes state to 'closed'.`); + +promise_test(async t => { + const [ localQuicTransport, remoteQuicTransport ] = + await makeTwoConnectedQuicTransports(t); + const localStream = localQuicTransport.createStream(); + localStream.finish(); + const remoteWatcher = new EventWatcher(t, remoteQuicTransport, 'quicstream'); + const { stream: remoteStream } = await remoteWatcher.wait_for('quicstream'); + assert_equals(remoteStream.state, 'open'); + const remoteStreamWatcher = new EventWatcher(t, remoteStream, 'statechange'); + await remoteStreamWatcher.wait_for('statechange'); + assert_equals(remoteStream.state, 'closing'); +}, 'createStream() followed by finish() fires a quicstream event followed by ' + + `a statechange event to 'closing' on the remote side.`); + +promise_test(async t => { + const [ localQuicTransport, remoteQuicTransport ] = + await makeTwoConnectedQuicTransports(t); + const localStream = localQuicTransport.createStream(); + localStream.reset(); + const remoteWatcher = new EventWatcher(t, remoteQuicTransport, 'quicstream'); + const { stream: remoteStream } = await remoteWatcher.wait_for('quicstream'); + assert_equals(remoteStream.state, 'open'); + const remoteStreamWatcher = new EventWatcher(t, remoteStream, 'statechange'); + await remoteStreamWatcher.wait_for('statechange'); + assert_equals(remoteStream.state, 'closed'); +}, 'createStream() followed by reset() fires a quicstream event followed ' + + `by a statechange event to 'closed' on the remote side.`); + +promise_test(async t => { + const [ localQuicTransport, remoteQuicTransport ] = + await makeTwoConnectedQuicTransports(t); + remoteQuicTransport.onquicstream = ({ stream }) => stream.reset(); + const localStream = localQuicTransport.createStream(); + localStream.finish(); + const localWatcher = new EventWatcher(t, localStream, 'statechange'); + await localWatcher.wait_for('statechange'); + assert_equals(localStream.state, 'closed'); +}, 'finish() on a remote stream that has already finished fires a ' + + `statechange event to 'closed' on the remote side.`); + +promise_test(async t => { + const [ localQuicTransport, remoteQuicTransport ] = + await makeTwoConnectedQuicTransports(t); + const localStream = localQuicTransport.createStream(); + localStream.finish(); + localStream.reset(); + const remoteWatcher = new EventWatcher(t, remoteQuicTransport, 'quicstream'); + const { stream: remoteStream } = await remoteWatcher.wait_for('quicstream'); + const remoteStreamWatcher = new EventWatcher(t, remoteStream, 'statechange'); + await remoteStreamWatcher.wait_for('statechange'); + assert_equals(remoteStream.state, 'closing'); + await remoteStreamWatcher.wait_for('statechange'); + assert_equals(remoteStream.state, 'closed'); +}, 'finish() then reset() fires two statechange events on the remote side.'); </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCQuicTransport-helper.js b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCQuicTransport-helper.js index 3ea19d7..7e28fea 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCQuicTransport-helper.js +++ b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCQuicTransport-helper.js
@@ -79,4 +79,3 @@ ]); return [ localQuicTransport, remoteQuicTransport ]; } -
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCQuicTransport.https.html b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCQuicTransport.https.html index ec79bc22..3bcc93d 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCQuicTransport.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/webrtc/RTCQuicTransport.https.html
@@ -17,6 +17,7 @@ // makeAndGatherTwoIceTransports // The following helper functions are called from RTCQuicTransport-helper.js: +// generateCertificate // makeQuicTransport // makeStandaloneQuicTransport // makeAndStartTwoQuicTransports
diff --git a/third_party/WebKit/LayoutTests/fast/scrolling/no-hover-during-scroll.html b/third_party/WebKit/LayoutTests/fast/scrolling/no-hover-during-scroll.html new file mode 100644 index 0000000..da0083a --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/scrolling/no-hover-during-scroll.html
@@ -0,0 +1,101 @@ +<!DOCTYPE html> +<script src='../../resources/testharness.js'></script> +<script src='../../resources/testharnessreport.js'></script> +<script src='../../resources/gesture-util.js'></script> + +<style> + body, html { + margin: 0; + } + div { + height: 50px; + width: 100%; + } + + .hoverme { + background-color: rgb(0, 0, 255); + } + + .hoverme:hover { + background-color: rgb(255, 255, 0); + } + + .message { + width: 100%; + text-align: left; + } +</style> + +<div class="message"> + First move your mouse cursor to the page, you will see the text under the mouse cursor changed to "currently hovered". <br> + Scroll mouse wheel slowly, you should not see any text under the mouse changed to "currently hovered" while the scrolling is in process and finishes. +</div> + +<script> + let array; + const numHoverElements = 30; + const elementHeight = 50; + const textWhenNotHovered = "hover over me"; + const textWhenHovered = "currently hovered"; + const textWhenWasHovered = "was hovered"; + const mouse = GestureSourceType.MOUSE_INPUT; + + function buildPage() { + for (let i = 0; i < numHoverElements; i++) { + let div = document.createElement('div'); + div.className = "hoverme"; + div.innerHTML = textWhenNotHovered; + document.body.appendChild(div); + } + + array = document.getElementsByClassName('hoverme'); + + for (let element of array) { + element.addEventListener('mouseover', function (e) { + this.innerHTML = textWhenHovered; + }); + element.addEventListener('mouseout', function (e) { + this.innerHTML = textWhenWasHovered; + }); + } + } + + window.onload = async () => { + if (window.internals) { + internals.settings.setScrollAnimatorEnabled(false); + internals.runtimeFlags.noHoverDuringScrollEnabled = true; + } + + buildPage(); + await waitForCompositorCommit(); + + promise_test(async () => { + let x = array[0].offsetLeft + 10; + let y = array[0].offsetTop + 10; + // Move cursor to 1st element. + await mouseMoveTo(x, y); + await waitFor( () => { return array[0].innerHTML == textWhenHovered;}, 'wait for moveto 1st element'); + assert_equals(array[0].innerHTML, textWhenHovered); + assert_equals(array[1].innerHTML, textWhenNotHovered); + assert_equals(getComputedStyle(array[0]).backgroundColor, 'rgb(255, 255, 0)'); + + // Scroll end up at 4th element. Hover state does not update during scrolling + // so that 2nd, 3rd and 4th elements do not see the mouseover and mouseout events. + assert_equals(document.scrollingElement.scrollTop, 0); + await smoothScroll(3 * elementHeight, x, y, mouse, 'down', SPEED_INSTANT); + // Wait enough time to see if we fire a fake mouse move event to update the hover state. + await waitForAnimationEnd(() => { return document.scrollingElement.scrollTop; }, 200, 100); + assert_approx_equals(document.scrollingElement.scrollTop, 3 * elementHeight, 10); + assert_equals(array[0].innerHTML, textWhenHovered); + assert_equals(array[1].innerHTML, textWhenNotHovered); + assert_equals(array[2].innerHTML, textWhenNotHovered); + assert_equals(array[3].innerHTML, textWhenNotHovered); + assert_equals(array[4].innerHTML, textWhenNotHovered); + assert_equals(getComputedStyle(array[0]).backgroundColor, 'rgb(255, 255, 0)'); + assert_equals(getComputedStyle(array[1]).backgroundColor, 'rgb(0, 0, 255)'); + assert_equals(getComputedStyle(array[2]).backgroundColor, 'rgb(0, 0, 255)'); + assert_equals(getComputedStyle(array[3]).backgroundColor, 'rgb(0, 0, 255)'); + }, 'Mouse wheel scroll on the page, no hover update during scrolling.'); + } + +</script> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/fast/xmlhttprequest/resources/xmlhttprequest-no-file-access-real.html b/third_party/WebKit/LayoutTests/fast/xmlhttprequest/resources/xmlhttprequest-no-file-access-real.html index 3cd09ab..48a9d80 100644 --- a/third_party/WebKit/LayoutTests/fast/xmlhttprequest/resources/xmlhttprequest-no-file-access-real.html +++ b/third_party/WebKit/LayoutTests/fast/xmlhttprequest/resources/xmlhttprequest-no-file-access-real.html
@@ -3,43 +3,37 @@ <html> <head> <script> - function log(message) - { - var console = document.getElementById('console'); - console.appendChild(document.createTextNode(message)); - console.appendChild(document.createElement('br')); + function logFailure(message) { + window.top.postMessage(message, "*"); } - + function done() { + window.top.postMessage("DONE", "*"); + } function testXHRDenied() { - log("Checking that same-origin iframes work."); var f = document.getElementById("f"); + // Check that access to an empty iframe allowed. f.contentDocument.body.innerHTML = "Successful write into iframe"; - log("Doing an XHR to an existing file."); xhr = new XMLHttpRequest(); - try { - xhr.open("GET", "../xmlhttprequest-no-file-access-expected.txt", false); - xhr.send(""); - log("Bad: XHR didn't throw exception"); - } catch(e) { - log("Exception: " + e.message); - try { - var results = window.top.document.getElementById('results'); - log("Bad: DOM access didn't throw exception"); - } catch (e) { - log("Exception: " + e.message); - if (window.testRunner) { - setTimeout("testRunner.notifyDone()", 0); - } - } - } + xhr.open("GET", "../xmlhttprequest-no-file-access-expected.txt"); + xhr.onload = () => { + logFailure("Bad: XHR didn't throw exception"); + done(); + }; + xhr.onerror = (e) => { + try { + window.top.document.body; + logFailure("Bad: DOM access didn't throw exception"); + } finally { + done(); + } + }; + xhr.send(""); } </script> </head> <body onload="testXHRDenied()"> <iframe id="f"></iframe> - <p> We're checking we can't read an arbitrary file when we set each file:// URI to have a unique domain. </p> - <div id="console"/> </body> </html>
diff --git a/third_party/WebKit/LayoutTests/fast/xmlhttprequest/xmlhttprequest-no-file-access-expected.txt b/third_party/WebKit/LayoutTests/fast/xmlhttprequest/xmlhttprequest-no-file-access-expected.txt deleted file mode 100644 index 8214650e..0000000 --- a/third_party/WebKit/LayoutTests/fast/xmlhttprequest/xmlhttprequest-no-file-access-expected.txt +++ /dev/null
@@ -1,4 +0,0 @@ -CONSOLE WARNING: line 22: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/. -CONSOLE ERROR: line 23: Access to XMLHttpRequest at 'xmlhttprequest-no-file-access-expected.txt' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, https. - -The child iframe cannot paste its textual results into this iframe because it is considered a different domain - that's the point of this test! Therefore, success is denoted by the child iframe calling notifyDone. The test will hang if something goes amiss with the access control checks.
diff --git a/third_party/WebKit/LayoutTests/fast/xmlhttprequest/xmlhttprequest-no-file-access.html b/third_party/WebKit/LayoutTests/fast/xmlhttprequest/xmlhttprequest-no-file-access.html index 2ef75dd..40a44e8 100644 --- a/third_party/WebKit/LayoutTests/fast/xmlhttprequest/xmlhttprequest-no-file-access.html +++ b/third_party/WebKit/LayoutTests/fast/xmlhttprequest/xmlhttprequest-no-file-access.html
@@ -1,20 +1,26 @@ <html> <head> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> <script> if (window.testRunner) { - testRunner.dumpAsText(); - testRunner.waitUntilDone(); testRunner.setAllowUniversalAccessFromFileURLs(false); testRunner.setAllowFileAccessFromFileURLs(false); } </script> </head> <body> +<script> +async_test((test) => { + window.onmessage = (e) => { + if (e.data === 'DONE') { + test.done(); + return; + } + assert_unreached(e.data); + }; +}, 'Test if file: origin is treate as (virtually) opaque.'); +</script> <iframe src="resources/xmlhttprequest-no-file-access-real.html"></iframe> -<div id="results"></div> -The child iframe cannot paste its textual results into this iframe because it -is considered a different domain - that's the point of this test! -Therefore, success is denoted by the child iframe calling notifyDone. -The test will hang if something goes amiss with the access control checks. </body> </html>
diff --git a/third_party/WebKit/LayoutTests/virtual/enable_asmjs/http/tests/asmjs/asm-warnings-expected.txt b/third_party/WebKit/LayoutTests/http/tests/asmjs/asm-warnings-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/virtual/enable_asmjs/http/tests/asmjs/asm-warnings-expected.txt rename to third_party/WebKit/LayoutTests/http/tests/asmjs/asm-warnings-expected.txt
diff --git a/third_party/WebKit/LayoutTests/virtual/enable_asmjs/http/tests/asmjs/asm-warnings.html b/third_party/WebKit/LayoutTests/http/tests/asmjs/asm-warnings.html similarity index 100% rename from third_party/WebKit/LayoutTests/virtual/enable_asmjs/http/tests/asmjs/asm-warnings.html rename to third_party/WebKit/LayoutTests/http/tests/asmjs/asm-warnings.html
diff --git a/third_party/WebKit/LayoutTests/virtual/enable_asmjs/http/tests/asmjs/worker.js b/third_party/WebKit/LayoutTests/http/tests/asmjs/worker.js similarity index 100% rename from third_party/WebKit/LayoutTests/virtual/enable_asmjs/http/tests/asmjs/worker.js rename to third_party/WebKit/LayoutTests/http/tests/asmjs/worker.js
diff --git a/third_party/WebKit/LayoutTests/virtual/enable_asmjs/http/tests/asmjs/README.txt b/third_party/WebKit/LayoutTests/virtual/enable_asmjs/http/tests/asmjs/README.txt deleted file mode 100644 index ea39d27d..0000000 --- a/third_party/WebKit/LayoutTests/virtual/enable_asmjs/http/tests/asmjs/README.txt +++ /dev/null
@@ -1 +0,0 @@ -Tests that depend on --enable-features=AsmJsToWebAssembly
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt index f19508d..d2d04ae 100644 --- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -5569,16 +5569,25 @@ attribute @@toStringTag getter candidate method constructor -interface RTCQuicStream +interface RTCQuicStream : EventTarget attribute @@toStringTag + getter onstatechange getter readBufferedAmount getter state getter transport getter writeBufferedAmount method constructor + method finish + method reset + setter onstatechange +interface RTCQuicStreamEvent : Event + attribute @@toStringTag + getter stream + method constructor interface RTCQuicTransport : EventTarget attribute @@toStringTag getter onerror + getter onquicstream getter onstatechange getter state getter transport @@ -5591,6 +5600,7 @@ method start method stop setter onerror + setter onquicstream setter onstatechange interface RTCRtpContributingSource attribute @@toStringTag
diff --git a/third_party/WebKit/Tools/Scripts/run-webkit-tests b/third_party/WebKit/Tools/Scripts/run-webkit-tests index 7da86061..112dc99 100755 --- a/third_party/WebKit/Tools/Scripts/run-webkit-tests +++ b/third_party/WebKit/Tools/Scripts/run-webkit-tests
@@ -29,8 +29,7 @@ """Wrapper around webkitpy/layout_tests/run_webkit_tests.py""" -from webkitpy.common import add_blinkpy # pylint: disable=unused-import -from blinkpy.common import multiprocessing_bootstrap +import sys print '\n Please use third_party/blink/tools/run_web_tests.*. This command will be removed.\n' -multiprocessing_bootstrap.run('blinkpy', 'web_tests', 'run_webkit_tests.py') +sys.exit(1)
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/__init__.py b/third_party/WebKit/Tools/Scripts/webkitpy/__init__.py deleted file mode 100644 index b376bf2b..0000000 --- a/third_party/WebKit/Tools/Scripts/webkitpy/__init__.py +++ /dev/null
@@ -1,13 +0,0 @@ -# Required for Python to search this directory for module files - -# Keep this file free of any code or import statements that could -# cause either an error to occur or a log message to be logged. -# This ensures that calling code can import initialization code from -# webkitpy before any errors or log messages due to code in this file. -# Initialization code can include things like version-checking code and -# logging configuration code. -# -# We do not execute any version-checking code or logging configuration -# code in this file so that callers can opt-in as they want. This also -# allows different callers to choose different initialization code, -# as necessary.
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/__init__.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/__init__.py deleted file mode 100644 index ef65bee5..0000000 --- a/third_party/WebKit/Tools/Scripts/webkitpy/common/__init__.py +++ /dev/null
@@ -1 +0,0 @@ -# Required for Python to search this directory for module files
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/add_blinkpy.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/add_blinkpy.py deleted file mode 100644 index f6615881..0000000 --- a/third_party/WebKit/Tools/Scripts/webkitpy/common/add_blinkpy.py +++ /dev/null
@@ -1,22 +0,0 @@ -# Copyright 2018 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Add the path of blinkpy to sys.path. - -You don't need to call a function to do it. You need just import this. e.g. - import webkitpy.common.add_blinkpy # pylint: disable=unused-import - or - from webkitpy.common import add_blinkpy # pylint: disable=unused-import - -This is a transitional solution to handle both of blinkpy and webkitpy. We'll -remove this file when we finish moving webkitpy to blinkpy. -""" - -import os -import sys - -# Without abspath(), PathFinder can't find chromium_base correctly. -sys.path.append(os.path.abspath( - os.path.join(os.path.dirname(__file__), '..', '..', '..', '..', '..', - 'blink', 'tools')))
diff --git a/third_party/blink/public/platform/web_localized_string.h b/third_party/blink/public/platform/web_localized_string.h index bd19f6f..8be42ff 100644 --- a/third_party/blink/public/platform/web_localized_string.h +++ b/third_party/blink/public/platform/web_localized_string.h
@@ -47,43 +47,30 @@ kAXMediaAudioElementHelp, kAXMediaAudioSliderHelp, kAXMediaCastOffButton, - kAXMediaCastOffButtonHelp, kAXMediaCastOnButton, - kAXMediaCastOnButtonHelp, kAXMediaCurrentTimeDisplay, kAXMediaCurrentTimeDisplayHelp, kAXMediaDefault, kAXMediaDownloadButton, kAXMediaEnterFullscreenButton, - kAXMediaEnterFullscreenButtonHelp, kAXMediaExitFullscreenButton, - kAXMediaExitFullscreenButtonHelp, kAXMediaHideClosedCaptionsButton, - kAXMediaHideClosedCaptionsButtonHelp, kAXMediaMuteButton, - kAXMediaMuteButtonHelp, kAXMediaDisplayCutoutFullscreenButton, - kAXMediaDisplayCutoutFullscreenButtonHelp, kAXMediaOverflowButton, kAXMediaOverflowButtonHelp, kAXMediaPauseButton, - kAXMediaPauseButtonHelp, kAXMediaPlayButton, - kAXMediaPlayButtonHelp, kAXMediaShowClosedCaptionsButton, - kAXMediaShowClosedCaptionsButtonHelp, kAXMediaTimeRemainingDisplay, kAXMediaTimeRemainingDisplayHelp, kAXMediaUnMuteButton, - kAXMediaUnMuteButtonHelp, kAXMediaVideoElement, kAXMediaVideoElementHelp, kAXMediaVideoSliderHelp, kAXMediaVolumeSliderHelp, kAXMediaEnterPictureInPictureButton, - kAXMediaEnterPictureInPictureButtonHelp, kAXMediaExitPictureInPictureButton, - kAXMediaExitPictureInPictureButtonHelp, kAXMillisecondFieldText, kAXMinuteFieldText, kAXMonthFieldText,
diff --git a/third_party/blink/public/platform/web_runtime_features.h b/third_party/blink/public/platform/web_runtime_features.h index c8499d1..ad7c5f2 100644 --- a/third_party/blink/public/platform/web_runtime_features.h +++ b/third_party/blink/public/platform/web_runtime_features.h
@@ -113,6 +113,7 @@ BLINK_PLATFORM_EXPORT static void EnableNetInfoDownlinkMax(bool); BLINK_PLATFORM_EXPORT static void EnableNetworkService(bool); BLINK_PLATFORM_EXPORT static void EnableNoHoverAfterLayoutChange(bool); + BLINK_PLATFORM_EXPORT static void EnableNoHoverDuringScroll(bool); BLINK_PLATFORM_EXPORT static void EnableNotificationConstructor(bool); BLINK_PLATFORM_EXPORT static void EnableNotificationContentImage(bool); BLINK_PLATFORM_EXPORT static void EnableNotifications(bool);
diff --git a/third_party/blink/public/web/web_local_frame.h b/third_party/blink/public/web/web_local_frame.h index 9d29ab05..79271999 100644 --- a/third_party/blink/public/web/web_local_frame.h +++ b/third_party/blink/public/web/web_local_frame.h
@@ -234,8 +234,7 @@ // TODO(dgozman): rename to CommitHTMLStringNavigation. virtual void LoadHTMLString(const WebData& html, const WebURL& base_url, - const WebURL& unreachable_url = WebURL(), - bool replace = false) = 0; + const WebURL& unreachable_url = WebURL()) = 0; // Navigates to the given |data| with specified |mime_type| and optional // |text_encoding|. @@ -254,7 +253,6 @@ const WebString& mime_type, const WebString& text_encoding, const WebURL& unreachable_url, - bool replace, WebFrameLoadType, const WebHistoryItem&, bool is_client_redirect,
diff --git a/third_party/blink/public/web/web_serialized_script_value_version.h b/third_party/blink/public/web/web_serialized_script_value_version.h index 08b2bd0..176ecef7 100644 --- a/third_party/blink/public/web/web_serialized_script_value_version.h +++ b/third_party/blink/public/web/web_serialized_script_value_version.h
@@ -38,7 +38,7 @@ // Embedders may serialize this as out-of-band metadata along with // collections of serialized data so that version skew can be detected // before deserializing individual values. -const unsigned kSerializedScriptValueVersion = 18; +const unsigned kSerializedScriptValueVersion = 19; } // namespace blink
diff --git a/third_party/blink/renderer/bindings/core/v8/serialization/serialization_tag.h b/third_party/blink/renderer/bindings/core/v8/serialization/serialization_tag.h index adb208c..33d2b21f 100644 --- a/third_party/blink/renderer/bindings/core/v8/serialization/serialization_tag.h +++ b/third_party/blink/renderer/bindings/core/v8/serialization/serialization_tag.h
@@ -93,7 +93,15 @@ // namedCurve:uint32_t kRTCCertificateTag = 'k', // length:uint32_t, pemPrivateKey:WebCoreString, // pemCertificate:WebCoreString - kVersionTag = 0xFF // version:uint32_t -> Uses this as the file version. + kDetectedBarcodeTag = + 'B', // raw_value:WebCoreString, bounding_box:DOMRectReadOnly, + // corner_points:Point2D[length] -> DetectedBarcode (ref) + kDetectedFaceTag = + 'F', // raw_value:WebCoreString, bounding_box:DOMRectReadOnly, + // corner_points:Point2D[length] -> DetectedText (ref) + kDetectedTextTag = 't', // bounding_box:DOMRectReadOnly, + // landmarks:Landmark[length] -> DetectedFace (ref) + kVersionTag = 0xFF // version:uint32_t -> Uses this as the file version. }; } // namespace blink
diff --git a/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h b/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h index 5dc7bbf..68ebafe5 100644 --- a/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h +++ b/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h
@@ -88,6 +88,7 @@ // Version 17: Remove unnecessary byte swapping. // Version 18: Add a list of key-value pairs for ImageBitmap and ImageData to // support color space information, compression, etc. + // Version 19: Add DetectedBarcode, DetectedFace, and DetectedText support. // // The following versions cannot be used, in order to be able to // deserialize version 0 SSVs. The class implementation has details. @@ -100,7 +101,7 @@ // // Recent changes are routinely reverted in preparation for branch, and this // has been the cause of at least one bug in the past. - static constexpr uint32_t kWireFormatVersion = 18; + static constexpr uint32_t kWireFormatVersion = 19; // This enumeration specifies whether we're serializing a value for storage; // e.g. when writing to IndexedDB. This corresponds to the forStorage flag of
diff --git a/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.cc b/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.cc index a7f18c5..298cc58e 100644 --- a/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.cc +++ b/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.cc
@@ -419,11 +419,7 @@ return DOMRect::Create(x, y, width, height); } case kDOMRectReadOnlyTag: { - double x = 0, y = 0, width = 0, height = 0; - if (!ReadDouble(&x) || !ReadDouble(&y) || !ReadDouble(&width) || - !ReadDouble(&height)) - return nullptr; - return DOMRectReadOnly::Create(x, y, width, height); + return ReadDOMRectReadOnly(); } case kDOMQuadTag: { DOMPointInit pointInits[4]; @@ -560,6 +556,14 @@ blob_handle); } +DOMRectReadOnly* V8ScriptValueDeserializer::ReadDOMRectReadOnly() { + double x = 0, y = 0, width = 0, height = 0; + if (!ReadDouble(&x) || !ReadDouble(&y) || !ReadDouble(&width) || + !ReadDouble(&height)) + return nullptr; + return DOMRectReadOnly::Create(x, y, width, height); +} + scoped_refptr<BlobDataHandle> V8ScriptValueDeserializer::GetOrCreateBlobDataHandle(const String& uuid, const String& type,
diff --git a/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.h b/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.h index 3582fcb..c020791 100644 --- a/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.h +++ b/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.h
@@ -17,6 +17,7 @@ namespace blink { +class DOMRectReadOnly; class File; class UnpackedSerializedScriptValue; @@ -65,6 +66,7 @@ return deserializer_.ReadRawBytes(size, data); } bool ReadUTF8String(String* string_out); + DOMRectReadOnly* ReadDOMRectReadOnly(); template <typename E> bool ReadUint32Enum(E* value) {
diff --git a/third_party/blink/renderer/bindings/modules/BUILD.gn b/third_party/blink/renderer/bindings/modules/BUILD.gn index b242546..e35eaba33 100644 --- a/third_party/blink/renderer/bindings/modules/BUILD.gn +++ b/third_party/blink/renderer/bindings/modules/BUILD.gn
@@ -41,6 +41,7 @@ "//third_party/blink/renderer/modules/peerconnection/rtc_data_channel_event.idl", "//third_party/blink/renderer/modules/peerconnection/rtc_dtmf_tone_change_event.idl", "//third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_ice_event.idl", + "//third_party/blink/renderer/modules/peerconnection/rtc_quic_stream_event.idl", "//third_party/blink/renderer/modules/picture_in_picture/enter_picture_in_picture_event.idl", "//third_party/blink/renderer/modules/presentation/presentation_connection_available_event.idl", "//third_party/blink/renderer/modules/presentation/presentation_connection_close_event.idl",
diff --git a/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.cc b/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.cc index 10e3e7af..1609823 100644 --- a/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.cc +++ b/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.cc
@@ -14,6 +14,9 @@ #include "third_party/blink/renderer/modules/crypto/crypto_key.h" #include "third_party/blink/renderer/modules/filesystem/dom_file_system.h" #include "third_party/blink/renderer/modules/peerconnection/rtc_certificate.h" +#include "third_party/blink/renderer/modules/shapedetection/detected_barcode.h" +#include "third_party/blink/renderer/modules/shapedetection/detected_face.h" +#include "third_party/blink/renderer/modules/shapedetection/detected_text.h" namespace blink { @@ -57,6 +60,60 @@ return nullptr; return new RTCCertificate(std::move(certificate)); } + case kDetectedBarcodeTag: { + String raw_value; + if (!ReadUTF8String(&raw_value)) + return nullptr; + DOMRectReadOnly* bounding_box = ReadDOMRectReadOnly(); + if (!bounding_box) + return nullptr; + uint32_t corner_points_length; + if (!ReadUint32(&corner_points_length)) + return nullptr; + HeapVector<Point2D> corner_points; + for (uint32_t i = 0; i < corner_points_length; i++) { + Point2D point; + if (!ReadPoint2D(&point)) + return nullptr; + corner_points.push_back(point); + } + return DetectedBarcode::Create(raw_value, bounding_box, corner_points); + } + case kDetectedFaceTag: { + DOMRectReadOnly* bounding_box = ReadDOMRectReadOnly(); + if (!bounding_box) + return nullptr; + uint32_t landmarks_length; + if (!ReadUint32(&landmarks_length)) + return nullptr; + HeapVector<Landmark> landmarks; + for (uint32_t i = 0; i < landmarks_length; i++) { + Landmark landmark; + if (!ReadLandmark(&landmark)) + return nullptr; + landmarks.push_back(landmark); + } + return DetectedFace::Create(bounding_box, landmarks); + } + case kDetectedTextTag: { + String raw_value; + if (!ReadUTF8String(&raw_value)) + return nullptr; + DOMRectReadOnly* bounding_box = ReadDOMRectReadOnly(); + if (!bounding_box) + return nullptr; + uint32_t corner_points_length; + if (!ReadUint32(&corner_points_length)) + return nullptr; + HeapVector<Point2D> corner_points; + for (uint32_t i = 0; i < corner_points_length; i++) { + Point2D point; + if (!ReadPoint2D(&point)) + return nullptr; + corner_points.push_back(point); + } + return DetectedText::Create(raw_value, bounding_box, corner_points); + } default: break; } @@ -291,4 +348,32 @@ return CryptoKey::Create(key); } +bool V8ScriptValueDeserializerForModules::ReadLandmark(Landmark* landmark) { + String type; + if (!ReadUTF8String(&type)) + return false; + uint32_t locations_length; + if (!ReadUint32(&locations_length)) + return false; + HeapVector<Point2D> locations; + for (uint32_t i = 0; i < locations_length; i++) { + Point2D location; + if (!ReadPoint2D(&location)) + return false; + locations.push_back(location); + } + landmark->setType(type); + landmark->setLocations(locations); + return true; +} + +bool V8ScriptValueDeserializerForModules::ReadPoint2D(Point2D* point) { + double x = 0, y = 0; + if (!ReadDouble(&x) || !ReadDouble(&y)) + return false; + point->setX(x); + point->setY(y); + return true; +} + } // namespace blink
diff --git a/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.h b/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.h index a120c08..eab1e1f 100644 --- a/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.h +++ b/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.h
@@ -11,6 +11,8 @@ namespace blink { class CryptoKey; +class Landmark; +class Point2D; // Extends V8ScriptValueSerializer with support for modules/ types. class MODULES_EXPORT V8ScriptValueDeserializerForModules final @@ -42,6 +44,8 @@ return true; } CryptoKey* ReadCryptoKey(); + bool ReadLandmark(Landmark* landmark); + bool ReadPoint2D(Point2D* point); }; } // namespace blink
diff --git a/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.cc b/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.cc index 49bf4c3..00efd23 100644 --- a/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.cc +++ b/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.cc
@@ -8,8 +8,12 @@ #include "third_party/blink/public/platform/web_crypto.h" #include "third_party/blink/public/platform/web_crypto_key.h" #include "third_party/blink/public/platform/web_crypto_key_algorithm.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_dom_rect_read_only.h" #include "third_party/blink/renderer/bindings/modules/v8/serialization/web_crypto_sub_tags.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_crypto_key.h" +#include "third_party/blink/renderer/bindings/modules/v8/v8_detected_barcode.h" +#include "third_party/blink/renderer/bindings/modules/v8/v8_detected_face.h" +#include "third_party/blink/renderer/bindings/modules/v8/v8_detected_text.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_dom_file_system.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_rtc_certificate.h" #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" @@ -54,6 +58,61 @@ WriteUTF8String(pem.certificate().c_str()); return true; } + if (wrapper_type_info == &V8DetectedBarcode::wrapperTypeInfo) { + DetectedBarcode* detected_barcode = wrappable->ToImpl<DetectedBarcode>(); + WriteTag(kDetectedBarcodeTag); + WriteUTF8String(detected_barcode->rawValue()); + DOMRectReadOnly* bounding_box = detected_barcode->boundingBox(); + WriteDouble(bounding_box->x()); + WriteDouble(bounding_box->y()); + WriteDouble(bounding_box->width()); + WriteDouble(bounding_box->height()); + const HeapVector<Point2D>& corner_points = detected_barcode->cornerPoints(); + WriteUint32(static_cast<uint32_t>(corner_points.size())); + for (const auto& corner_point : corner_points) { + WriteDouble(corner_point.x()); + WriteDouble(corner_point.y()); + } + return true; + } + if (wrapper_type_info == &V8DetectedFace::wrapperTypeInfo) { + DetectedFace* detected_face = wrappable->ToImpl<DetectedFace>(); + WriteTag(kDetectedFaceTag); + DOMRectReadOnly* bounding_box = detected_face->boundingBox(); + WriteDouble(bounding_box->x()); + WriteDouble(bounding_box->y()); + WriteDouble(bounding_box->width()); + WriteDouble(bounding_box->height()); + const HeapVector<Landmark>& landmarks = detected_face->landmarks(); + WriteUint32(static_cast<uint32_t>(landmarks.size())); + for (const auto& landmark : landmarks) { + WriteUTF8String(landmark.type()); + const HeapVector<Point2D>& locations = landmark.locations(); + WriteUint32(static_cast<uint32_t>(locations.size())); + for (const auto& location : locations) { + WriteDouble(location.x()); + WriteDouble(location.y()); + } + } + return true; + } + if (wrapper_type_info == &V8DetectedText::wrapperTypeInfo) { + DetectedText* detected_text = wrappable->ToImpl<DetectedText>(); + WriteTag(kDetectedTextTag); + WriteUTF8String(detected_text->rawValue()); + DOMRectReadOnly* bounding_box = detected_text->boundingBox(); + WriteDouble(bounding_box->x()); + WriteDouble(bounding_box->y()); + WriteDouble(bounding_box->width()); + WriteDouble(bounding_box->height()); + const HeapVector<Point2D>& corner_points = detected_text->cornerPoints(); + WriteUint32(static_cast<uint32_t>(corner_points.size())); + for (const auto& corner_point : corner_points) { + WriteDouble(corner_point.x()); + WriteDouble(corner_point.y()); + } + return true; + } return false; }
diff --git a/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules_test.cc b/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules_test.cc index 6fd7f32..8f5ffd39 100644 --- a/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules_test.cc +++ b/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules_test.cc
@@ -17,8 +17,12 @@ #include "third_party/blink/renderer/bindings/core/v8/v8_array_buffer.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h" #include "third_party/blink/renderer/bindings/core/v8/v8_dom_exception.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_dom_rect_read_only.h" #include "third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_crypto_key.h" +#include "third_party/blink/renderer/bindings/modules/v8/v8_detected_barcode.h" +#include "third_party/blink/renderer/bindings/modules/v8/v8_detected_face.h" +#include "third_party/blink/renderer/bindings/modules/v8/v8_detected_text.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_dom_file_system.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_rtc_certificate.h" #include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h" @@ -972,5 +976,83 @@ ->IsNull()); } +TEST(V8ScriptValueSerializerForModulesTest, DecodeDetectedBarcode) { + V8TestingScope scope; + ScriptState* script_state = scope.GetScriptState(); + scoped_refptr<SerializedScriptValue> input = SerializedValue( + {0xff, 0x13, 0xff, 0x0d, 0x5c, 'B', 0x04, 0x74, 0x65, 0x78, 0x74, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xf0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40}); + v8::Local<v8::Value> result = + V8ScriptValueDeserializerForModules(script_state, input).Deserialize(); + ASSERT_TRUE(V8DetectedBarcode::hasInstance(result, scope.GetIsolate())); + DetectedBarcode* detected_barcode = + V8DetectedBarcode::ToImpl(result.As<v8::Object>()); + EXPECT_EQ("text", detected_barcode->rawValue()); + DOMRectReadOnly* bounding_box = detected_barcode->boundingBox(); + EXPECT_EQ(1, bounding_box->x()); + EXPECT_EQ(2, bounding_box->y()); + EXPECT_EQ(3, bounding_box->width()); + EXPECT_EQ(4, bounding_box->height()); + const HeapVector<Point2D>& corner_points = detected_barcode->cornerPoints(); + EXPECT_EQ(1u, corner_points.size()); + EXPECT_EQ(1, corner_points[0].x()); + EXPECT_EQ(2, corner_points[0].y()); +} + +TEST(V8ScriptValueSerializerForModulesTest, DecodeDetectedFace) { + V8TestingScope scope; + ScriptState* script_state = scope.GetScriptState(); + scoped_refptr<SerializedScriptValue> input = SerializedValue( + {0xff, 0x13, 0xff, 0x0d, 0x5c, 'F', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xf0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x40, 0x01, 0x03, 0x65, 0x79, 0x65, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xf0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40}); + v8::Local<v8::Value> result = + V8ScriptValueDeserializerForModules(script_state, input).Deserialize(); + ASSERT_TRUE(V8DetectedFace::hasInstance(result, scope.GetIsolate())); + DetectedFace* detected_face = V8DetectedFace::ToImpl(result.As<v8::Object>()); + DOMRectReadOnly* bounding_box = detected_face->boundingBox(); + EXPECT_EQ(1, bounding_box->x()); + EXPECT_EQ(2, bounding_box->y()); + EXPECT_EQ(3, bounding_box->width()); + EXPECT_EQ(4, bounding_box->height()); + const HeapVector<Landmark>& landmarks = detected_face->landmarks(); + EXPECT_EQ(1u, landmarks.size()); + EXPECT_EQ("eye", landmarks[0].type()); + const HeapVector<Point2D>& locations = landmarks[0].locations(); + EXPECT_EQ(1u, locations.size()); + EXPECT_EQ(1, locations[0].x()); + EXPECT_EQ(2, locations[0].y()); +} + +TEST(V8ScriptValueSerializerForModulesTest, DecodeDetectedText) { + V8TestingScope scope; + ScriptState* script_state = scope.GetScriptState(); + scoped_refptr<SerializedScriptValue> input = SerializedValue( + {0xff, 0x13, 0xff, 0x0d, 0x5c, 't', 0x04, 0x74, 0x65, 0x78, 0x74, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xf0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40}); + v8::Local<v8::Value> result = + V8ScriptValueDeserializerForModules(script_state, input).Deserialize(); + ASSERT_TRUE(V8DetectedText::hasInstance(result, scope.GetIsolate())); + DetectedText* detected_text = V8DetectedText::ToImpl(result.As<v8::Object>()); + EXPECT_EQ("text", detected_text->rawValue()); + DOMRectReadOnly* bounding_box = detected_text->boundingBox(); + EXPECT_EQ(1, bounding_box->x()); + EXPECT_EQ(2, bounding_box->y()); + EXPECT_EQ(3, bounding_box->width()); + EXPECT_EQ(4, bounding_box->height()); + const HeapVector<Point2D>& corner_points = detected_text->cornerPoints(); + EXPECT_EQ(1u, corner_points.size()); + EXPECT_EQ(1, corner_points[0].x()); + EXPECT_EQ(2, corner_points[0].y()); +} + } // namespace } // namespace blink
diff --git a/third_party/blink/renderer/core/css/css_style_declaration.idl b/third_party/blink/renderer/core/css/css_style_declaration.idl index 7f5b13d..03e8b07 100644 --- a/third_party/blink/renderer/core/css/css_style_declaration.idl +++ b/third_party/blink/renderer/core/css/css_style_declaration.idl
@@ -39,7 +39,5 @@ // https://drafts.csswg.org/cssom/#dom-cssstyledeclaration-camel-cased-attribute // https://drafts.csswg.org/cssom/#dom-cssstyledeclaration-dashed-attribute [Affects=Nothing] getter DOMString (DOMString name); - // TODO(crbug.com/831544): [TreatNullAs=EmptyString] should be used instead - // of [TreatNullAs=NullString]. - [CEReactions, CallWith=ScriptState] setter void (DOMString property, [TreatNullAs=NullString] DOMString propertyValue); + [CEReactions, CallWith=ScriptState] setter void (DOMString property, [TreatNullAs=EmptyString] DOMString propertyValue); };
diff --git a/third_party/blink/renderer/core/css/media_values.cc b/third_party/blink/renderer/core/css/media_values.cc index 7325011..1a63d54 100644 --- a/third_party/blink/renderer/core/css/media_values.cc +++ b/third_party/blink/renderer/core/css/media_values.cc
@@ -172,7 +172,7 @@ ColorSpaceGamut MediaValues::CalculateColorGamut(LocalFrame* frame) { DCHECK(frame); DCHECK(frame->GetPage()); - return ColorSpaceUtilities::GetColorSpaceGamut( + return color_space_utilities::GetColorSpaceGamut( frame->GetPage()->GetChromeClient().GetScreenInfo()); }
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc index 978a1ff..574fb14 100644 --- a/third_party/blink/renderer/core/dom/document.cc +++ b/third_party/blink/renderer/core/dom/document.cc
@@ -7578,7 +7578,8 @@ if (child->IsLocalFrame()) { if (ToLocalFrame(child)->IsAdSubframe()) { ToLocalFrame(child)->Navigate( - FrameLoadRequest(this, ResourceRequest(BlankURL()))); + FrameLoadRequest(this, ResourceRequest(BlankURL())), + WebFrameLoadType::kStandard); } } // TODO(yuzus): Once AdsTracker for remote frames is implemented and OOPIF
diff --git a/third_party/blink/renderer/core/events/event_type_names.json5 b/third_party/blink/renderer/core/events/event_type_names.json5 index d922745..4e520a8c 100644 --- a/third_party/blink/renderer/core/events/event_type_names.json5 +++ b/third_party/blink/renderer/core/events/event_type_names.json5
@@ -216,6 +216,7 @@ "progress", "processorerror", "push", + "quicstream", "ratechange", "reading", "readystatechange",
diff --git a/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.cc b/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.cc index 368ce90..d1d9b39 100644 --- a/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.cc +++ b/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.cc
@@ -34,7 +34,6 @@ #include <memory> #include <utility> -#include "base/single_thread_task_runner.h" #include "mojo/public/cpp/bindings/binding.h" #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/public/platform/web_float_rect.h" @@ -55,6 +54,7 @@ #include "third_party/blink/renderer/core/frame/web_frame_widget_base.h" #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h" #include "third_party/blink/renderer/core/inspector/dev_tools_emulator.h" +#include "third_party/blink/renderer/core/inspector/devtools_agent.h" #include "third_party/blink/renderer/core/inspector/inspected_frames.h" #include "third_party/blink/renderer/core/inspector/inspector_animation_agent.h" #include "third_party/blink/renderer/core/inspector/inspector_application_cache_agent.h" @@ -185,295 +185,113 @@ ClientMessageLoopAdapter* ClientMessageLoopAdapter::instance_ = nullptr; -// --------- WebDevToolsAgentImpl::Session ------------- - -class WebDevToolsAgentImpl::Session : public GarbageCollectedFinalized<Session>, - public mojom::blink::DevToolsSession, - public InspectorSession::Client { - public: - Session(WebDevToolsAgentImpl*, - mojom::blink::DevToolsSessionHostAssociatedPtrInfo host_ptr_info, - mojom::blink::DevToolsSessionAssociatedRequest main_request, - mojom::blink::DevToolsSessionRequest io_request, - mojom::blink::DevToolsSessionStatePtr reattach_session_state); - ~Session() override; - - virtual void Trace(blink::Visitor*); - void Detach(); - - InspectorSession* inspector_session() { return inspector_session_.Get(); } - InspectorNetworkAgent* network_agent() { return network_agent_.Get(); } - InspectorPageAgent* page_agent() { return page_agent_.Get(); } - InspectorOverlayAgent* overlay_agent() { return overlay_agent_.Get(); } - - private: - class IOSession; - - // mojom::blink::DevToolsSession implementation. - void DispatchProtocolCommand(int call_id, - const String& method, - const String& message) override; - - // InspectorSession::Client implementation. - void SendProtocolResponse( - int session_id, - int call_id, - const String& response, - mojom::blink::DevToolsSessionStatePtr updates) override; - void SendProtocolNotification( - int session_id, - const String& message, - mojom::blink::DevToolsSessionStatePtr updates) override; - - void DispatchProtocolCommandInternal(int call_id, - const String& method, - const String& message); - void InitializeInspectorSession( - mojom::blink::DevToolsSessionStatePtr reattach_session_state); - - Member<WebDevToolsAgentImpl> agent_; - Member<WebLocalFrameImpl> frame_; - mojo::AssociatedBinding<mojom::blink::DevToolsSession> binding_; - mojom::blink::DevToolsSessionHostAssociatedPtr host_ptr_; - IOSession* io_session_; - Member<InspectorSession> inspector_session_; - Member<InspectorNetworkAgent> network_agent_; - Member<InspectorPageAgent> page_agent_; - Member<InspectorOverlayAgent> overlay_agent_; - bool detached_ = false; - - DISALLOW_COPY_AND_ASSIGN(Session); -}; - -// Created and stored in unique_ptr on UI. -// Binds request, receives messages and destroys on IO. -class WebDevToolsAgentImpl::Session::IOSession - : public mojom::blink::DevToolsSession { - public: - IOSession(scoped_refptr<base::SingleThreadTaskRunner> session_task_runner, - scoped_refptr<InspectorTaskRunner> inspector_task_runner, - CrossThreadWeakPersistent<WebDevToolsAgentImpl::Session> session, - mojom::blink::DevToolsSessionRequest request) - : session_task_runner_(session_task_runner), - inspector_task_runner_(inspector_task_runner), - session_(std::move(session)), - binding_(this) { - session_task_runner->PostTask( - FROM_HERE, ConvertToBaseCallback(CrossThreadBind( - &IOSession::BindInterface, CrossThreadUnretained(this), - WTF::Passed(std::move(request))))); - } - - ~IOSession() override {} - - void BindInterface(mojom::blink::DevToolsSessionRequest request) { - binding_.Bind(std::move(request)); - } - - void DeleteSoon() { session_task_runner_->DeleteSoon(FROM_HERE, this); } - - // mojom::blink::DevToolsSession implementation. - void DispatchProtocolCommand(int call_id, - const String& method, - const String& message) override { - DCHECK(InspectorSession::ShouldInterruptForMethod(method)); - // Crash renderer. - if (method == "Page.crash") - CHECK(false); - inspector_task_runner_->AppendTask( - CrossThreadBind(&WebDevToolsAgentImpl::Session::DispatchProtocolCommand, - session_, call_id, method, message)); - } - - private: - scoped_refptr<base::SingleThreadTaskRunner> session_task_runner_; - scoped_refptr<InspectorTaskRunner> inspector_task_runner_; - CrossThreadWeakPersistent<WebDevToolsAgentImpl::Session> session_; - mojo::Binding<mojom::blink::DevToolsSession> binding_; - - DISALLOW_COPY_AND_ASSIGN(IOSession); -}; - -WebDevToolsAgentImpl::Session::Session( - WebDevToolsAgentImpl* agent, - mojom::blink::DevToolsSessionHostAssociatedPtrInfo host_ptr_info, - mojom::blink::DevToolsSessionAssociatedRequest request, - mojom::blink::DevToolsSessionRequest io_request, - mojom::blink::DevToolsSessionStatePtr reattach_session_state) - : agent_(agent), - frame_(agent->web_local_frame_impl_), - binding_(this, std::move(request)) { - io_session_ = - new IOSession(Platform::Current()->GetIOTaskRunner(), - frame_->GetFrame()->GetInspectorTaskRunner(), - WrapCrossThreadWeakPersistent(this), std::move(io_request)); - - host_ptr_.Bind(std::move(host_ptr_info)); - host_ptr_.set_connection_error_handler(WTF::Bind( - &WebDevToolsAgentImpl::Session::Detach, WrapWeakPersistent(this))); - - InitializeInspectorSession(std::move(reattach_session_state)); -} - -WebDevToolsAgentImpl::Session::~Session() { - DCHECK(detached_); -} - -void WebDevToolsAgentImpl::Session::Trace(blink::Visitor* visitor) { - visitor->Trace(agent_); - visitor->Trace(frame_); - visitor->Trace(inspector_session_); - visitor->Trace(network_agent_); - visitor->Trace(page_agent_); - visitor->Trace(overlay_agent_); -} - -void WebDevToolsAgentImpl::Session::Detach() { - DCHECK(!detached_); - detached_ = true; - agent_->DetachSession(this); - binding_.Close(); - host_ptr_.reset(); - io_session_->DeleteSoon(); - io_session_ = nullptr; - inspector_session_->Dispose(); -} - -void WebDevToolsAgentImpl::Session::SendProtocolResponse( - int session_id, - int call_id, - const String& response, - mojom::blink::DevToolsSessionStatePtr updates) { - if (detached_) - return; - - // Make tests more predictable by flushing all sessions before sending - // protocol response in any of them. - if (LayoutTestSupport::IsRunningLayoutTest()) - agent_->FlushProtocolNotifications(); - host_ptr_->DispatchProtocolResponse(response, call_id, std::move(updates)); -} - -void WebDevToolsAgentImpl::Session::SendProtocolNotification( - int session_id, - const String& message, - mojom::blink::DevToolsSessionStatePtr updates) { - host_ptr_->DispatchProtocolNotification(message, std::move(updates)); -} - -void WebDevToolsAgentImpl::Session::DispatchProtocolCommand( - int call_id, - const String& method, - const String& message) { - // IOSession does not provide ordering guarantees relative to - // Session, so a command may come to IOSession after Session is detached, - // and get posted to main thread to this method. - // - // At the same time, Session may not be garbage collected yet - // (even though already detached), and CrossThreadWeakPersistent<Session> - // will still be valid. - // - // Both these factors combined may lead to this method being called after - // detach, so we have to check a flag here. - if (detached_) - return; - inspector_session_->DispatchProtocolMessage(call_id, method, message); -} - -void WebDevToolsAgentImpl::Session::InitializeInspectorSession( +InspectorSession* WebDevToolsAgentImpl::AttachSession( + InspectorSession::Client* session_client, mojom::blink::DevToolsSessionStatePtr reattach_session_state) { + if (!sessions_.size()) + Platform::Current()->CurrentThread()->AddTaskObserver(this); + ClientMessageLoopAdapter::EnsureMainThreadDebuggerCreated(); MainThreadDebugger* main_thread_debugger = MainThreadDebugger::Instance(); v8::Isolate* isolate = V8PerIsolateData::MainThreadIsolate(); - InspectedFrames* inspected_frames = agent_->inspected_frames_.Get(); + InspectedFrames* inspected_frames = inspected_frames_.Get(); bool should_reattach = !reattach_session_state.is_null(); - inspector_session_ = new InspectorSession( - this, agent_->probe_sink_.Get(), 0, + InspectorSession* inspector_session = new InspectorSession( + session_client, probe_sink_.Get(), 0, main_thread_debugger->GetV8Inspector(), main_thread_debugger->ContextGroupId(inspected_frames->Root()), std::move(reattach_session_state)); InspectorDOMAgent* dom_agent = new InspectorDOMAgent( - isolate, inspected_frames, inspector_session_->V8Session()); - inspector_session_->Append(dom_agent); + isolate, inspected_frames, inspector_session->V8Session()); + inspector_session->Append(dom_agent); InspectorLayerTreeAgent* layer_tree_agent = - InspectorLayerTreeAgent::Create(inspected_frames, agent_); - inspector_session_->Append(layer_tree_agent); + InspectorLayerTreeAgent::Create(inspected_frames, this); + inspector_session->Append(layer_tree_agent); - network_agent_ = new InspectorNetworkAgent(inspected_frames, nullptr, - inspector_session_->V8Session()); - inspector_session_->Append(network_agent_); + InspectorNetworkAgent* network_agent = new InspectorNetworkAgent( + inspected_frames, nullptr, inspector_session->V8Session()); + inspector_session->Append(network_agent); - InspectorCSSAgent* css_agent = - InspectorCSSAgent::Create(dom_agent, inspected_frames, network_agent_, - agent_->resource_content_loader_.Get(), - agent_->resource_container_.Get()); - inspector_session_->Append(css_agent); + InspectorCSSAgent* css_agent = InspectorCSSAgent::Create( + dom_agent, inspected_frames, network_agent, + resource_content_loader_.Get(), resource_container_.Get()); + inspector_session->Append(css_agent); InspectorDOMDebuggerAgent* dom_debugger_agent = new InspectorDOMDebuggerAgent( - isolate, dom_agent, inspector_session_->V8Session()); - inspector_session_->Append(dom_debugger_agent); + isolate, dom_agent, inspector_session->V8Session()); + inspector_session->Append(dom_debugger_agent); - inspector_session_->Append( + inspector_session->Append( InspectorDOMSnapshotAgent::Create(inspected_frames, dom_debugger_agent)); - inspector_session_->Append(new InspectorAnimationAgent( - inspected_frames, css_agent, inspector_session_->V8Session())); + inspector_session->Append(new InspectorAnimationAgent( + inspected_frames, css_agent, inspector_session->V8Session())); - inspector_session_->Append(InspectorMemoryAgent::Create(inspected_frames)); + inspector_session->Append(InspectorMemoryAgent::Create(inspected_frames)); - inspector_session_->Append( + inspector_session->Append( InspectorPerformanceAgent::Create(inspected_frames)); - inspector_session_->Append( + inspector_session->Append( InspectorApplicationCacheAgent::Create(inspected_frames)); - inspector_session_->Append( + inspector_session->Append( new InspectorWorkerAgent(inspected_frames, nullptr)); - page_agent_ = InspectorPageAgent::Create( - inspected_frames, agent_, agent_->resource_content_loader_.Get(), - inspector_session_->V8Session()); - inspector_session_->Append(page_agent_); + InspectorPageAgent* page_agent = InspectorPageAgent::Create( + inspected_frames, this, resource_content_loader_.Get(), + inspector_session->V8Session()); + inspector_session->Append(page_agent); - inspector_session_->Append(new InspectorLogAgent( + inspector_session->Append(new InspectorLogAgent( &inspected_frames->Root()->GetPage()->GetConsoleMessageStorage(), inspected_frames->Root()->GetPerformanceMonitor(), - inspector_session_->V8Session())); + inspector_session->V8Session())); - overlay_agent_ = - new InspectorOverlayAgent(frame_.Get(), inspected_frames, - inspector_session_->V8Session(), dom_agent); - inspector_session_->Append(overlay_agent_); + InspectorOverlayAgent* overlay_agent = + new InspectorOverlayAgent(web_local_frame_impl_.Get(), inspected_frames, + inspector_session->V8Session(), dom_agent); + inspector_session->Append(overlay_agent); - inspector_session_->Append( - new InspectorIOAgent(isolate, inspector_session_->V8Session())); + inspector_session->Append( + new InspectorIOAgent(isolate, inspector_session->V8Session())); - inspector_session_->Append(new InspectorAuditsAgent(network_agent_)); + inspector_session->Append(new InspectorAuditsAgent(network_agent)); // TODO(dgozman): we should actually pass the view instead of frame, but // during remote->local transition we cannot access mainFrameImpl() yet, so // we have to store the frame which will become the main frame later. - inspector_session_->Append(new InspectorEmulationAgent(frame_.Get())); + inspector_session->Append( + new InspectorEmulationAgent(web_local_frame_impl_.Get())); - inspector_session_->Append(new InspectorTestingAgent(inspected_frames)); + inspector_session->Append(new InspectorTestingAgent(inspected_frames)); // Call session init callbacks registered from higher layers CoreInitializer::GetInstance().InitInspectorAgentSession( - inspector_session_, agent_->include_view_agents_, dom_agent, - inspected_frames, frame_->ViewImpl()->GetPage()); + inspector_session, include_view_agents_, dom_agent, inspected_frames, + web_local_frame_impl_->ViewImpl()->GetPage()); if (should_reattach) { - inspector_session_->Restore(); - if (agent_->worker_client_) - agent_->worker_client_->ResumeStartup(); + inspector_session->Restore(); + if (worker_client_) + worker_client_->ResumeStartup(); } -} -// --------- WebDevToolsAgentImpl ------------- + if (node_to_inspect_) { + overlay_agent->Inspect(node_to_inspect_); + node_to_inspect_ = nullptr; + } + + sessions_.insert(inspector_session); + network_agents_.insert(inspector_session, network_agent); + page_agents_.insert(inspector_session, page_agent); + overlay_agents_.insert(inspector_session, overlay_agent); + return inspector_session; +} // static WebDevToolsAgentImpl* WebDevToolsAgentImpl::CreateForFrame( @@ -492,8 +310,7 @@ WebLocalFrameImpl* web_local_frame_impl, bool include_view_agents, WorkerClient* worker_client) - : binding_(this), - worker_client_(worker_client), + : worker_client_(worker_client), web_local_frame_impl_(web_local_frame_impl), probe_sink_(web_local_frame_impl_->GetFrame()->GetProbeSink()), resource_content_loader_(InspectorResourceContentLoader::Create( @@ -502,7 +319,9 @@ resource_container_(new InspectorResourceContainer(inspected_frames_)), include_view_agents_(include_view_agents) { DCHECK(IsMainThread()); - DCHECK(web_local_frame_impl_->GetFrame()); + agent_ = new DevToolsAgent( + this, web_local_frame_impl_->GetFrame()->GetInspectorTaskRunner(), + Platform::Current()->GetIOTaskRunner()); } WebDevToolsAgentImpl::~WebDevToolsAgentImpl() { @@ -510,7 +329,11 @@ } void WebDevToolsAgentImpl::Trace(blink::Visitor* visitor) { + visitor->Trace(agent_); visitor->Trace(sessions_); + visitor->Trace(network_agents_); + visitor->Trace(page_agents_); + visitor->Trace(overlay_agents_); visitor->Trace(web_local_frame_impl_); visitor->Trace(probe_sink_); visitor->Trace(resource_content_loader_); @@ -522,36 +345,23 @@ void WebDevToolsAgentImpl::WillBeDestroyed() { DCHECK(web_local_frame_impl_->GetFrame()); DCHECK(inspected_frames_->Root()->View()); - - HeapHashSet<Member<Session>> copy(sessions_); - for (auto& session : copy) - session->Detach(); - + agent_->WillBeDestroyed(); resource_content_loader_->Dispose(); worker_client_ = nullptr; - binding_.Close(); } void WebDevToolsAgentImpl::BindRequest( mojom::blink::DevToolsAgentAssociatedRequest request) { - binding_.Bind(std::move(request)); + agent_->BindRequest(std::move(request)); } -void WebDevToolsAgentImpl::AttachDevToolsSession( - mojom::blink::DevToolsSessionHostAssociatedPtrInfo host, - mojom::blink::DevToolsSessionAssociatedRequest session_request, - mojom::blink::DevToolsSessionRequest io_session_request, - mojom::blink::DevToolsSessionStatePtr reattach_session_state) { +void WebDevToolsAgentImpl::DetachSession(InspectorSession* session) { + network_agents_.erase(session); + page_agents_.erase(session); + overlay_agents_.erase(session); + sessions_.erase(session); if (!sessions_.size()) - Platform::Current()->CurrentThread()->AddTaskObserver(this); - Session* session = new Session( - this, std::move(host), std::move(session_request), - std::move(io_session_request), std::move(reattach_session_state)); - sessions_.insert(session); - if (node_to_inspect_) { - session->overlay_agent()->Inspect(node_to_inspect_); - node_to_inspect_ = nullptr; - } + Platform::Current()->CurrentThread()->RemoveTaskObserver(this); } void WebDevToolsAgentImpl::InspectElement(const WebPoint& point_in_local_root) { @@ -589,50 +399,44 @@ if (!node && web_local_frame_impl_->GetFrame()->GetDocument()) node = web_local_frame_impl_->GetFrame()->GetDocument()->documentElement(); - if (!sessions_.IsEmpty()) { - for (auto& session : sessions_) - session->overlay_agent()->Inspect(node); + if (!overlay_agents_.IsEmpty()) { + for (auto& it : overlay_agents_) + it.value->Inspect(node); } else { node_to_inspect_ = node; } } -void WebDevToolsAgentImpl::DetachSession(Session* session) { - sessions_.erase(session); - if (!sessions_.size()) - Platform::Current()->CurrentThread()->RemoveTaskObserver(this); -} - void WebDevToolsAgentImpl::DidCommitLoadForLocalFrame(LocalFrame* frame) { resource_container_->DidCommitLoadForLocalFrame(frame); resource_content_loader_->DidCommitLoadForLocalFrame(frame); for (auto& session : sessions_) - session->inspector_session()->DidCommitLoadForLocalFrame(frame); + session->DidCommitLoadForLocalFrame(frame); } void WebDevToolsAgentImpl::DidStartProvisionalLoad(LocalFrame* frame) { if (inspected_frames_->Root() == frame) { for (auto& session : sessions_) - session->inspector_session()->V8Session()->resume(); + session->V8Session()->resume(); } } bool WebDevToolsAgentImpl::ScreencastEnabled() { - for (auto& session : sessions_) { - if (session->page_agent()->ScreencastEnabled()) + for (auto& it : page_agents_) { + if (it.value->ScreencastEnabled()) return true; } return false; } void WebDevToolsAgentImpl::PageLayoutInvalidated(bool resized) { - for (auto& session : sessions_) - session->overlay_agent()->PageLayoutInvalidated(resized); + for (auto& it : overlay_agents_) + it.value->PageLayoutInvalidated(resized); } bool WebDevToolsAgentImpl::IsInspectorLayer(GraphicsLayer* layer) { - for (auto& session : sessions_) { - if (session->overlay_agent()->IsInspectorLayer(layer)) + for (auto& it : overlay_agents_) { + if (it.value->IsInspectorLayer(layer)) return true; } return false; @@ -640,32 +444,32 @@ String WebDevToolsAgentImpl::EvaluateInOverlayForTesting(const String& script) { String result; - for (auto& session : sessions_) - result = session->overlay_agent()->EvaluateInOverlayForTest(script); + for (auto& it : overlay_agents_) + result = it.value->EvaluateInOverlayForTest(script); return result; } void WebDevToolsAgentImpl::UpdateOverlays() { - for (auto& session : sessions_) - session->overlay_agent()->UpdateAllOverlayLifecyclePhases(); + for (auto& it : overlay_agents_) + it.value->UpdateAllOverlayLifecyclePhases(); } void WebDevToolsAgentImpl::DispatchBufferedTouchEvents() { - for (auto& session : sessions_) - session->overlay_agent()->DispatchBufferedTouchEvents(); + for (auto& it : overlay_agents_) + it.value->DispatchBufferedTouchEvents(); } bool WebDevToolsAgentImpl::HandleInputEvent(const WebInputEvent& event) { - for (auto& session : sessions_) { - if (session->overlay_agent()->HandleInputEvent(event)) + for (auto& it : overlay_agents_) { + if (it.value->HandleInputEvent(event)) return true; } return false; } String WebDevToolsAgentImpl::NavigationInitiatorInfo(LocalFrame* frame) { - for (auto& session : sessions_) { - String initiator = session->network_agent()->NavigationInitiatorInfo(frame); + for (auto& it : network_agents_) { + String initiator = it.value->NavigationInitiatorInfo(frame); if (!initiator.IsNull()) return initiator; } @@ -673,8 +477,7 @@ } void WebDevToolsAgentImpl::FlushProtocolNotifications() { - for (auto& session : sessions_) - session->inspector_session()->flushProtocolNotifications(); + agent_->FlushProtocolNotifications(); } void WebDevToolsAgentImpl::WillProcessTask() {
diff --git a/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.h b/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.h index 61d383f0..acc14e3 100644 --- a/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.h +++ b/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.h
@@ -33,11 +33,11 @@ #include <memory> -#include "mojo/public/cpp/bindings/associated_binding.h" #include "third_party/blink/public/platform/web_size.h" #include "third_party/blink/public/platform/web_thread.h" #include "third_party/blink/public/web/devtools_agent.mojom-blink.h" #include "third_party/blink/renderer/core/core_export.h" +#include "third_party/blink/renderer/core/inspector/devtools_agent.h" #include "third_party/blink/renderer/core/inspector/inspector_layer_tree_agent.h" #include "third_party/blink/renderer/core/inspector/inspector_page_agent.h" #include "third_party/blink/renderer/platform/heap/handle.h" @@ -48,6 +48,8 @@ class ClientMessageLoopAdapter; class GraphicsLayer; class InspectedFrames; +class InspectorNetworkAgent; +class InspectorOverlayAgent; class InspectorResourceContainer; class InspectorResourceContentLoader; class LocalFrame; @@ -55,7 +57,7 @@ class CORE_EXPORT WebDevToolsAgentImpl final : public GarbageCollectedFinalized<WebDevToolsAgentImpl>, - public mojom::blink::DevToolsAgent, + public DevToolsAgent::Client, public InspectorPageAgent::Client, public InspectorLayerTreeAgent::Client, private WebThread::TaskObserver { @@ -88,18 +90,16 @@ private: friend class ClientMessageLoopAdapter; - class Session; WebDevToolsAgentImpl(WebLocalFrameImpl*, bool include_view_agents, WorkerClient*); - // mojom::blink::DevToolsAgent implementation. - void AttachDevToolsSession( - mojom::blink::DevToolsSessionHostAssociatedPtrInfo, - mojom::blink::DevToolsSessionAssociatedRequest main_session, - mojom::blink::DevToolsSessionRequest io_session, + // DevToolsAgent::Client implementation. + InspectorSession* AttachSession( + InspectorSession::Client*, mojom::blink::DevToolsSessionStatePtr reattach_session_state) override; + void DetachSession(InspectorSession*) override; void InspectElement(const WebPoint& point_in_local_root) override; // InspectorPageAgent::Client implementation. @@ -112,10 +112,14 @@ void WillProcessTask() override; void DidProcessTask() override; - void DetachSession(Session*); - - mojo::AssociatedBinding<mojom::blink::DevToolsAgent> binding_; - HeapHashSet<Member<Session>> sessions_; + Member<DevToolsAgent> agent_; + HeapHashSet<Member<InspectorSession>> sessions_; + HeapHashMap<Member<InspectorSession>, Member<InspectorNetworkAgent>> + network_agents_; + HeapHashMap<Member<InspectorSession>, Member<InspectorPageAgent>> + page_agents_; + HeapHashMap<Member<InspectorSession>, Member<InspectorOverlayAgent>> + overlay_agents_; WorkerClient* worker_client_; Member<WebLocalFrameImpl> web_local_frame_impl_; Member<CoreProbeSink> probe_sink_;
diff --git a/third_party/blink/renderer/core/exported/web_frame_test.cc b/third_party/blink/renderer/core/exported/web_frame_test.cc index ab84e7e..cfaa334 100644 --- a/third_party/blink/renderer/core/exported/web_frame_test.cc +++ b/third_party/blink/renderer/core/exported/web_frame_test.cc
@@ -6550,9 +6550,12 @@ // FrameTestHelpers::TestWebFrameClient: void DidFailProvisionalLoad(const WebURLError& error, WebHistoryCommitType) override { - Frame()->LoadHTMLString("This should appear", - ToKURL("chrome-error://chromewebdata/"), - error.url(), true); + Frame()->CommitDataNavigation( + WebURLRequest(ToKURL("chrome-error://chromewebdata/")), + WebData("This should appear"), WebString::FromUTF8("text/html"), + WebString::FromUTF8("UTF-8"), error.url(), + WebFrameLoadType::kReplaceCurrentItem, WebHistoryItem(), + false /* is_client_redirect */, nullptr, nullptr); } void DidCommitProvisionalLoad(const WebHistoryItem&, WebHistoryCommitType,
diff --git a/third_party/blink/renderer/core/frame/frame.h b/third_party/blink/renderer/core/frame/frame.h index 036e509..5845feb 100644 --- a/third_party/blink/renderer/core/frame/frame.h +++ b/third_party/blink/renderer/core/frame/frame.h
@@ -99,10 +99,10 @@ // eventually fixed. virtual void ScheduleNavigation(Document& origin_document, const KURL&, - bool replace_current_item, + WebFrameLoadType, UserGestureStatus) = 0; // Synchronously begins a navigation. - virtual void Navigate(const FrameLoadRequest&) = 0; + virtual void Navigate(const FrameLoadRequest&, WebFrameLoadType) = 0; void Detach(FrameDetachType); void DisconnectOwnerElement();
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_party/blink/renderer/core/frame/local_dom_window.cc index 43bc62d2..1996ac95 100644 --- a/third_party/blink/renderer/core/frame/local_dom_window.cc +++ b/third_party/blink/renderer/core/frame/local_dom_window.cc
@@ -1602,7 +1602,8 @@ if (url_string.IsEmpty()) return target_frame->DomWindow(); - target_frame->ScheduleNavigation(*active_document, completed_url, false, + target_frame->ScheduleNavigation(*active_document, completed_url, + WebFrameLoadType::kStandard, UserGestureStatus::kNone); return target_frame->DomWindow(); }
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc index 3ca32dc..6e83b3a 100644 --- a/third_party/blink/renderer/core/frame/local_frame.cc +++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -272,14 +272,15 @@ void LocalFrame::ScheduleNavigation(Document& origin_document, const KURL& url, - bool replace_current_item, + WebFrameLoadType frame_load_type, UserGestureStatus user_gesture_status) { navigation_scheduler_->ScheduleFrameNavigation(&origin_document, url, - replace_current_item); + frame_load_type); } -void LocalFrame::Navigate(const FrameLoadRequest& request) { - loader_.StartNavigation(request); +void LocalFrame::Navigate(const FrameLoadRequest& request, + WebFrameLoadType frame_load_type) { + loader_.StartNavigation(request, frame_load_type); } void LocalFrame::DetachImpl(FrameDetachType type) {
diff --git a/third_party/blink/renderer/core/frame/local_frame.h b/third_party/blink/renderer/core/frame/local_frame.h index 4b52f9e..b0a066e 100644 --- a/third_party/blink/renderer/core/frame/local_frame.h +++ b/third_party/blink/renderer/core/frame/local_frame.h
@@ -127,9 +127,9 @@ void Trace(blink::Visitor*) override; void ScheduleNavigation(Document& origin_document, const KURL&, - bool replace_current_item, + WebFrameLoadType, UserGestureStatus) override; - void Navigate(const FrameLoadRequest&) override; + void Navigate(const FrameLoadRequest&, WebFrameLoadType) override; bool ShouldClose() override; SecurityContext* GetSecurityContext() const override; void PrintNavigationErrorMessage(const Frame&, const char* reason);
diff --git a/third_party/blink/renderer/core/frame/location.cc b/third_party/blink/renderer/core/frame/location.cc index 23d4b30..3306af7 100644 --- a/third_party/blink/renderer/core/frame/location.cc +++ b/third_party/blink/renderer/core/frame/location.cc
@@ -304,10 +304,12 @@ argv.push_back(completed_url); activity_logger->LogEvent("blinkSetAttribute", argv.size(), argv.data()); } - dom_window_->GetFrame()->ScheduleNavigation( - *current_window->document(), completed_url, - set_location_policy == SetLocationPolicy::kReplaceThisFrame, - UserGestureStatus::kNone); + WebFrameLoadType frame_load_type = WebFrameLoadType::kStandard; + if (set_location_policy == SetLocationPolicy::kReplaceThisFrame) + frame_load_type = WebFrameLoadType::kReplaceCurrentItem; + dom_window_->GetFrame()->ScheduleNavigation(*current_window->document(), + completed_url, frame_load_type, + UserGestureStatus::kNone); } Document* Location::GetDocument() const {
diff --git a/third_party/blink/renderer/core/frame/remote_frame.cc b/third_party/blink/renderer/core/frame/remote_frame.cc index bc54e83..e1358d8 100644 --- a/third_party/blink/renderer/core/frame/remote_frame.cc +++ b/third_party/blink/renderer/core/frame/remote_frame.cc
@@ -58,19 +58,19 @@ void RemoteFrame::ScheduleNavigation(Document& origin_document, const KURL& url, - bool replace_current_item, + WebFrameLoadType frame_load_type, UserGestureStatus user_gesture_status) { FrameLoadRequest frame_request(&origin_document, ResourceRequest(url)); - frame_request.SetReplacesCurrentItem(replace_current_item); frame_request.GetResourceRequest().SetHasUserGesture( user_gesture_status == UserGestureStatus::kActive); frame_request.GetResourceRequest().SetFrameType( IsMainFrame() ? network::mojom::RequestContextFrameType::kTopLevel : network::mojom::RequestContextFrameType::kNested); - Navigate(frame_request); + Navigate(frame_request, frame_load_type); } -void RemoteFrame::Navigate(const FrameLoadRequest& passed_request) { +void RemoteFrame::Navigate(const FrameLoadRequest& passed_request, + WebFrameLoadType frame_load_type) { FrameLoadRequest frame_request(passed_request); // The process where this frame actually lives won't have sufficient @@ -81,7 +81,7 @@ frame_request.OriginDocument()); Client()->Navigate(frame_request.GetResourceRequest(), - frame_request.ReplacesCurrentItem(), + frame_load_type == WebFrameLoadType::kReplaceCurrentItem, frame_request.GetBlobURLToken()); }
diff --git a/third_party/blink/renderer/core/frame/remote_frame.h b/third_party/blink/renderer/core/frame/remote_frame.h index afc7119..84173c0 100644 --- a/third_party/blink/renderer/core/frame/remote_frame.h +++ b/third_party/blink/renderer/core/frame/remote_frame.h
@@ -31,9 +31,9 @@ void Trace(blink::Visitor*) override; void ScheduleNavigation(Document& origin_document, const KURL&, - bool replace_current_item, + WebFrameLoadType, UserGestureStatus) override; - void Navigate(const FrameLoadRequest& passed_request) override; + void Navigate(const FrameLoadRequest&, WebFrameLoadType) override; RemoteSecurityContext* GetSecurityContext() const override; bool PrepareForCommit() override; void CheckCompleted() override;
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc index 76b761b0..7632df4 100644 --- a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc +++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
@@ -949,12 +949,11 @@ void WebLocalFrameImpl::LoadHTMLString(const WebData& data, const WebURL& base_url, - const WebURL& unreachable_url, - bool replace) { + const WebURL& unreachable_url) { DCHECK(GetFrame()); CommitDataNavigation( WebURLRequest(base_url), data, WebString::FromUTF8("text/html"), - WebString::FromUTF8("UTF-8"), unreachable_url, replace, + WebString::FromUTF8("UTF-8"), unreachable_url, WebFrameLoadType::kStandard, WebHistoryItem(), false, nullptr, nullptr); } @@ -2133,7 +2132,6 @@ const WebString& mime_type, const WebString& text_encoding, const WebURL& unreachable_url, - bool replace, WebFrameLoadType web_frame_load_type, const WebHistoryItem& history_item, bool is_client_redirect, @@ -2143,7 +2141,6 @@ nullptr, request.ToResourceRequest(), SubstituteData(data, mime_type, text_encoding, unreachable_url)); DCHECK(frame_request.GetSubstituteData().IsValid()); - frame_request.SetReplacesCurrentItem(replace); if (is_client_redirect) frame_request.SetClientRedirect(ClientRedirectPolicy::kClientRedirect);
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.h b/third_party/blink/renderer/core/frame/web_local_frame_impl.h index 383fd8c..48918c3c 100644 --- a/third_party/blink/renderer/core/frame/web_local_frame_impl.h +++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.h
@@ -156,8 +156,7 @@ void CheckCompleted() override; void LoadHTMLString(const WebData& html, const WebURL& base_url, - const WebURL& unreachable_url, - bool replace) override; + const WebURL& unreachable_url) override; void StopLoading() override; WebDocumentLoader* GetProvisionalDocumentLoader() const override; WebDocumentLoader* GetDocumentLoader() const override; @@ -282,7 +281,6 @@ const WebString& mime_type, const WebString& text_encoding, const WebURL& unreachable_url, - bool replace, WebFrameLoadType, const WebHistoryItem&, bool is_client_redirect,
diff --git a/third_party/blink/renderer/core/html/forms/html_form_element.cc b/third_party/blink/renderer/core/html/forms/html_form_element.cc index 06846322..3f10176 100644 --- a/third_party/blink/renderer/core/html/forms/html_form_element.cc +++ b/third_party/blink/renderer/core/html/forms/html_form_element.cc
@@ -490,7 +490,8 @@ LocalFrame::HasTransientUserActivation(GetDocument().GetFrame())); // TODO(dgozman): we lose information about triggering event and desired // navigation policy here. - ToRemoteFrame(target_frame)->Navigate(frame_load_request); + ToRemoteFrame(target_frame) + ->Navigate(frame_load_request, WebFrameLoadType::kStandard); } }
diff --git a/third_party/blink/renderer/core/html/html_frame_owner_element.cc b/third_party/blink/renderer/core/html/html_frame_owner_element.cc index 320afef..da2aaf4 100644 --- a/third_party/blink/renderer/core/html/html_frame_owner_element.cc +++ b/third_party/blink/renderer/core/html/html_frame_owner_element.cc
@@ -364,7 +364,10 @@ if (ContentFrame()) { // TODO(sclittle): Support lazily loading frame navigations. - ContentFrame()->ScheduleNavigation(GetDocument(), url, replace_current_item, + WebFrameLoadType frame_load_type = WebFrameLoadType::kStandard; + if (replace_current_item) + frame_load_type = WebFrameLoadType::kReplaceCurrentItem; + ContentFrame()->ScheduleNavigation(GetDocument(), url, frame_load_type, UserGestureStatus::kNone); return true; }
diff --git a/third_party/blink/renderer/core/input/mouse_event_manager.cc b/third_party/blink/renderer/core/input/mouse_event_manager.cc index 953ba5f..1077580 100644 --- a/third_party/blink/renderer/core/input/mouse_event_manager.cc +++ b/third_party/blink/renderer/core/input/mouse_event_manager.cc
@@ -620,8 +620,10 @@ if (update_hover_reason == MouseEventManager::UpdateHoverReason::kScrollOffsetChanged && - mouse_pressed_) + (RuntimeEnabledFeatures::NoHoverDuringScrollEnabled() || + mouse_pressed_)) { return; + } // TODO(lanwei): When the mouse position is unknown, we do not send the fake // mousemove event for now, so we cannot update the hover states and mouse
diff --git a/third_party/blink/renderer/core/inspector/BUILD.gn b/third_party/blink/renderer/core/inspector/BUILD.gn index 0c995cd..9d1daad 100644 --- a/third_party/blink/renderer/core/inspector/BUILD.gn +++ b/third_party/blink/renderer/core/inspector/BUILD.gn
@@ -23,6 +23,8 @@ "dev_tools_emulator.h", "dev_tools_host.cc", "dev_tools_host.h", + "devtools_agent.cc", + "devtools_agent.h", "dom_editor.cc", "dom_editor.h", "dom_patch_support.cc",
diff --git a/third_party/blink/renderer/core/inspector/devtools_agent.cc b/third_party/blink/renderer/core/inspector/devtools_agent.cc new file mode 100644 index 0000000..4400f14 --- /dev/null +++ b/third_party/blink/renderer/core/inspector/devtools_agent.cc
@@ -0,0 +1,246 @@ +// 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 "third_party/blink/renderer/core/inspector/devtools_agent.h" + +#include <v8-inspector.h> +#include <memory> + +#include "mojo/public/cpp/bindings/binding.h" +#include "third_party/blink/renderer/core/inspector/inspector_session.h" +#include "third_party/blink/renderer/core/inspector/inspector_task_runner.h" +#include "third_party/blink/renderer/platform/cross_thread_functional.h" +#include "third_party/blink/renderer/platform/heap/persistent.h" +#include "third_party/blink/renderer/platform/layout_test_support.h" +#include "third_party/blink/renderer/platform/web_task_runner.h" +#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" + +namespace blink { + +// --------- DevToolsAgent::Session ------------- + +class DevToolsAgent::Session : public GarbageCollectedFinalized<Session>, + public mojom::blink::DevToolsSession, + public InspectorSession::Client { + public: + Session(DevToolsAgent*, + mojom::blink::DevToolsSessionHostAssociatedPtrInfo host_ptr_info, + mojom::blink::DevToolsSessionAssociatedRequest main_request, + mojom::blink::DevToolsSessionRequest io_request, + mojom::blink::DevToolsSessionStatePtr reattach_session_state); + ~Session() override; + + virtual void Trace(blink::Visitor*); + void Detach(); + + InspectorSession* inspector_session() { return inspector_session_.Get(); } + + private: + class IOSession; + + // mojom::blink::DevToolsSession implementation. + void DispatchProtocolCommand(int call_id, + const String& method, + const String& message) override; + + // InspectorSession::Client implementation. + void SendProtocolResponse( + int session_id, + int call_id, + const String& response, + mojom::blink::DevToolsSessionStatePtr updates) override; + void SendProtocolNotification( + int session_id, + const String& message, + mojom::blink::DevToolsSessionStatePtr updates) override; + + void DispatchProtocolCommandInternal(int call_id, + const String& method, + const String& message); + + Member<DevToolsAgent> agent_; + mojo::AssociatedBinding<mojom::blink::DevToolsSession> binding_; + mojom::blink::DevToolsSessionHostAssociatedPtr host_ptr_; + IOSession* io_session_; + Member<InspectorSession> inspector_session_; + + DISALLOW_COPY_AND_ASSIGN(Session); +}; + +// Created and stored in unique_ptr on UI. +// Binds request, receives messages and destroys on IO. +class DevToolsAgent::Session::IOSession : public mojom::blink::DevToolsSession { + public: + IOSession(scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, + scoped_refptr<InspectorTaskRunner> inspector_task_runner, + CrossThreadWeakPersistent<DevToolsAgent::Session> session, + mojom::blink::DevToolsSessionRequest request) + : io_task_runner_(io_task_runner), + inspector_task_runner_(inspector_task_runner), + session_(std::move(session)), + binding_(this) { + io_task_runner->PostTask( + FROM_HERE, ConvertToBaseCallback(CrossThreadBind( + &IOSession::BindInterface, CrossThreadUnretained(this), + WTF::Passed(std::move(request))))); + } + + ~IOSession() override {} + + void BindInterface(mojom::blink::DevToolsSessionRequest request) { + binding_.Bind(std::move(request)); + } + + void DeleteSoon() { io_task_runner_->DeleteSoon(FROM_HERE, this); } + + // mojom::blink::DevToolsSession implementation. + void DispatchProtocolCommand(int call_id, + const String& method, + const String& message) override { + DCHECK(InspectorSession::ShouldInterruptForMethod(method)); + // Crash renderer. + if (method == "Page.crash") + CHECK(false); + inspector_task_runner_->AppendTask( + CrossThreadBind(&DevToolsAgent::Session::DispatchProtocolCommand, + session_, call_id, method, message)); + } + + private: + scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; + scoped_refptr<InspectorTaskRunner> inspector_task_runner_; + CrossThreadWeakPersistent<DevToolsAgent::Session> session_; + mojo::Binding<mojom::blink::DevToolsSession> binding_; + + DISALLOW_COPY_AND_ASSIGN(IOSession); +}; + +DevToolsAgent::Session::Session( + DevToolsAgent* agent, + mojom::blink::DevToolsSessionHostAssociatedPtrInfo host_ptr_info, + mojom::blink::DevToolsSessionAssociatedRequest request, + mojom::blink::DevToolsSessionRequest io_request, + mojom::blink::DevToolsSessionStatePtr reattach_session_state) + : agent_(agent), binding_(this, std::move(request)) { + io_session_ = + new IOSession(agent_->io_task_runner_, agent_->inspector_task_runner_, + WrapCrossThreadWeakPersistent(this), std::move(io_request)); + + host_ptr_.Bind(std::move(host_ptr_info)); + host_ptr_.set_connection_error_handler( + WTF::Bind(&DevToolsAgent::Session::Detach, WrapWeakPersistent(this))); + inspector_session_ = + agent_->client_->AttachSession(this, std::move(reattach_session_state)); +} + +DevToolsAgent::Session::~Session() { + DCHECK(!host_ptr_.is_bound()); +} + +void DevToolsAgent::Session::Trace(blink::Visitor* visitor) { + visitor->Trace(agent_); + visitor->Trace(inspector_session_); +} + +void DevToolsAgent::Session::Detach() { + agent_->client_->DetachSession(inspector_session_.Get()); + agent_->sessions_.erase(this); + binding_.Close(); + host_ptr_.reset(); + io_session_->DeleteSoon(); + io_session_ = nullptr; + inspector_session_->Dispose(); +} + +void DevToolsAgent::Session::SendProtocolResponse( + int session_id, + int call_id, + const String& response, + mojom::blink::DevToolsSessionStatePtr updates) { + if (!host_ptr_.is_bound()) + return; + // Make tests more predictable by flushing all sessions before sending + // protocol response in any of them. + if (LayoutTestSupport::IsRunningLayoutTest()) + agent_->FlushProtocolNotifications(); + host_ptr_->DispatchProtocolResponse(response, call_id, std::move(updates)); +} + +void DevToolsAgent::Session::SendProtocolNotification( + int session_id, + const String& message, + mojom::blink::DevToolsSessionStatePtr updates) { + if (!host_ptr_.is_bound()) + return; + host_ptr_->DispatchProtocolNotification(message, std::move(updates)); +} + +void DevToolsAgent::Session::DispatchProtocolCommand(int call_id, + const String& method, + const String& message) { + // IOSession does not provide ordering guarantees relative to + // Session, so a command may come to IOSession after Session is detached, + // and get posted to main thread to this method. + // + // At the same time, Session may not be garbage collected yet + // (even though already detached), and CrossThreadWeakPersistent<Session> + // will still be valid. + // + // Both these factors combined may lead to this method being called after + // detach, so we have to check it here. + if (!host_ptr_.is_bound()) + return; + inspector_session_->DispatchProtocolMessage(call_id, method, message); +} + +// --------- DevToolsAgent ------------- + +DevToolsAgent::DevToolsAgent( + Client* client, + scoped_refptr<InspectorTaskRunner> inspector_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> io_task_runner) + : client_(client), + binding_(this), + inspector_task_runner_(std::move(inspector_task_runner)), + io_task_runner_(std::move(io_task_runner)) {} + +DevToolsAgent::~DevToolsAgent() {} + +void DevToolsAgent::Trace(blink::Visitor* visitor) { + visitor->Trace(sessions_); +} + +void DevToolsAgent::WillBeDestroyed() { + HeapHashSet<Member<Session>> copy(sessions_); + for (auto& session : copy) + session->Detach(); + binding_.Close(); +} + +void DevToolsAgent::BindRequest( + mojom::blink::DevToolsAgentAssociatedRequest request) { + binding_.Bind(std::move(request)); +} + +void DevToolsAgent::AttachDevToolsSession( + mojom::blink::DevToolsSessionHostAssociatedPtrInfo host, + mojom::blink::DevToolsSessionAssociatedRequest session_request, + mojom::blink::DevToolsSessionRequest io_session_request, + mojom::blink::DevToolsSessionStatePtr reattach_session_state) { + Session* session = new Session( + this, std::move(host), std::move(session_request), + std::move(io_session_request), std::move(reattach_session_state)); + sessions_.insert(session); +} + +void DevToolsAgent::InspectElement(const WebPoint& point) { + client_->InspectElement(point); +} + +void DevToolsAgent::FlushProtocolNotifications() { + for (auto& session : sessions_) + session->inspector_session()->flushProtocolNotifications(); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/core/inspector/devtools_agent.h b/third_party/blink/renderer/core/inspector/devtools_agent.h new file mode 100644 index 0000000..2ce2cf3 --- /dev/null +++ b/third_party/blink/renderer/core/inspector/devtools_agent.h
@@ -0,0 +1,67 @@ +// 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 THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_DEVTOOLS_AGENT_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_DEVTOOLS_AGENT_H_ + +#include <memory> + +#include "base/single_thread_task_runner.h" +#include "mojo/public/cpp/bindings/associated_binding.h" +#include "third_party/blink/public/web/devtools_agent.mojom-blink.h" +#include "third_party/blink/renderer/core/core_export.h" +#include "third_party/blink/renderer/core/inspector/inspector_session.h" +#include "third_party/blink/renderer/platform/heap/handle.h" +#include "third_party/blink/renderer/platform/wtf/forward.h" +#include "third_party/blink/renderer/platform/wtf/ref_counted.h" + +namespace blink { + +class InspectorTaskRunner; + +class CORE_EXPORT DevToolsAgent + : public GarbageCollectedFinalized<DevToolsAgent>, + public mojom::blink::DevToolsAgent { + public: + class Client { + public: + virtual ~Client() {} + virtual InspectorSession* AttachSession( + InspectorSession::Client*, + mojom::blink::DevToolsSessionStatePtr reattach_session_state) = 0; + virtual void DetachSession(InspectorSession*) = 0; + virtual void InspectElement(const WebPoint&) = 0; + }; + + DevToolsAgent(Client*, + scoped_refptr<InspectorTaskRunner> inspector_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> io_task_runner); + ~DevToolsAgent() override; + + void WillBeDestroyed(); + void FlushProtocolNotifications(); + void BindRequest(mojom::blink::DevToolsAgentAssociatedRequest); + virtual void Trace(blink::Visitor*); + + private: + class Session; + + // mojom::blink::DevToolsAgent implementation. + void AttachDevToolsSession( + mojom::blink::DevToolsSessionHostAssociatedPtrInfo, + mojom::blink::DevToolsSessionAssociatedRequest main_session, + mojom::blink::DevToolsSessionRequest io_session, + mojom::blink::DevToolsSessionStatePtr reattach_session_state) override; + void InspectElement(const WebPoint& point) override; + + Client* client_; + mojo::AssociatedBinding<mojom::blink::DevToolsAgent> binding_; + HeapHashSet<Member<Session>> sessions_; + scoped_refptr<InspectorTaskRunner> inspector_task_runner_; + scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_DEVTOOLS_AGENT_H_
diff --git a/third_party/blink/renderer/core/layout/layout_inline.cc b/third_party/blink/renderer/core/layout/layout_inline.cc index ef0d9ce..aa7e9178 100644 --- a/third_party/blink/renderer/core/layout/layout_inline.cc +++ b/third_party/blink/renderer/core/layout/layout_inline.cc
@@ -1312,6 +1312,23 @@ return overflow_rect; } +LayoutRect LayoutInline::ReferenceBoxForClipPath() const { + // The spec just says to use the border box as clip-path reference box. It + // doesn't say what to do if there are multiple lines. Gecko uses the first + // fragment in that case. We'll do the same here (but correctly with respect + // to writing-mode - Gecko has some issues there). + // See crbug.com/641907 + LayoutRect bounding_box; + if (const NGPaintFragment* fragment = FirstInlineFragment()) { + bounding_box.SetLocation(fragment->Offset().ToLayoutPoint()); + bounding_box.SetSize(fragment->Size().ToLayoutSize()); + } else if (const InlineFlowBox* flow_box = FirstLineBox()) { + bounding_box = flow_box->FrameRect(); + } + ContainingBlock()->FlipForWritingMode(bounding_box); + return bounding_box; +} + bool LayoutInline::MapToVisualRectInAncestorSpaceInternal( const LayoutBoxModelObject* ancestor, TransformState& transform_state,
diff --git a/third_party/blink/renderer/core/layout/layout_inline.h b/third_party/blink/renderer/core/layout/layout_inline.h index 14c8dcd..b55cc5eb 100644 --- a/third_party/blink/renderer/core/layout/layout_inline.h +++ b/third_party/blink/renderer/core/layout/layout_inline.h
@@ -158,6 +158,7 @@ LayoutRect LinesBoundingBox() const; LayoutRect VisualOverflowRect() const final; + LayoutRect ReferenceBoxForClipPath() const; InlineFlowBox* CreateAndAppendInlineFlowBox();
diff --git a/third_party/blink/renderer/core/loader/appcache/application_cache_host.cc b/third_party/blink/renderer/core/loader/appcache/application_cache_host.cc index 4510299e..ec240a0 100644 --- a/third_party/blink/renderer/core/loader/appcache/application_cache_host.cc +++ b/third_party/blink/renderer/core/loader/appcache/application_cache_host.cc
@@ -165,7 +165,8 @@ // navigation algorithm. The navigation will not result in the same resource // being loaded, because "foreign" entries are never picked during // navigation. see ApplicationCacheGroup::selectCache() - frame->ScheduleNavigation(*document, document->Url(), true, + frame->ScheduleNavigation(*document, document->Url(), + WebFrameLoadType::kReplaceCurrentItem, UserGestureStatus::kNone); } }
diff --git a/third_party/blink/renderer/core/loader/frame_load_request.cc b/third_party/blink/renderer/core/loader/frame_load_request.cc index 0b30b8da..19de358 100644 --- a/third_party/blink/renderer/core/loader/frame_load_request.cc +++ b/third_party/blink/renderer/core/loader/frame_load_request.cc
@@ -76,7 +76,6 @@ resource_request_(resource_request), frame_name_(frame_name), substitute_data_(substitute_data), - replaces_current_item_(false), client_redirect_(ClientRedirectPolicy::kNotClientRedirect), should_send_referrer_(kMaybeSendReferrer), should_set_opener_(kMaybeSetOpener),
diff --git a/third_party/blink/renderer/core/loader/frame_load_request.h b/third_party/blink/renderer/core/loader/frame_load_request.h index 50379f81..13502501 100644 --- a/third_party/blink/renderer/core/loader/frame_load_request.h +++ b/third_party/blink/renderer/core/loader/frame_load_request.h
@@ -76,11 +76,6 @@ const SubstituteData& GetSubstituteData() const { return substitute_data_; } - bool ReplacesCurrentItem() const { return replaces_current_item_; } - void SetReplacesCurrentItem(bool replaces_current_item) { - replaces_current_item_ = replaces_current_item; - } - ClientRedirectPolicy ClientRedirect() const { return client_redirect_; } void SetClientRedirect(ClientRedirectPolicy client_redirect) { client_redirect_ = client_redirect; @@ -167,7 +162,6 @@ AtomicString frame_name_; AtomicString href_translate_; SubstituteData substitute_data_; - bool replaces_current_item_; ClientRedirectPolicy client_redirect_; WebTriggeringEventInfo triggering_event_info_ = WebTriggeringEventInfo::kNotFromEvent;
diff --git a/third_party/blink/renderer/core/loader/frame_loader.cc b/third_party/blink/renderer/core/loader/frame_loader.cc index d055dba..bfc32b4 100644 --- a/third_party/blink/renderer/core/loader/frame_loader.cc +++ b/third_party/blink/renderer/core/loader/frame_loader.cc
@@ -629,15 +629,27 @@ } WebFrameLoadType FrameLoader::DetermineFrameLoadType( - const FrameLoadRequest& request) { - if (frame_->Tree().Parent() && - !state_machine_.CommittedFirstRealDocumentLoad()) - return WebFrameLoadType::kReplaceCurrentItem; - if (!frame_->Tree().Parent() && !Client()->BackForwardLength()) { - if (Opener() && request.GetResourceRequest().Url().IsEmpty()) + const FrameLoadRequest& request, + WebFrameLoadType frame_load_type) { + // TODO(dgozman): this method is rewriting the load type, which makes it hard + // to reason about various navigations and their desired load type. We should + // untangle it and detect the load type at the proper place. See, for example, + // location.assign() block below. + // Achieving that is complicated due to similar conditions in many places + // both in the renderer and in the browser. + if (frame_load_type == WebFrameLoadType::kStandard || + frame_load_type == WebFrameLoadType::kReplaceCurrentItem) { + if (frame_->Tree().Parent() && + !state_machine_.CommittedFirstRealDocumentLoad()) return WebFrameLoadType::kReplaceCurrentItem; - return WebFrameLoadType::kStandard; + if (!frame_->Tree().Parent() && !Client()->BackForwardLength()) { + if (Opener() && request.GetResourceRequest().Url().IsEmpty()) + return WebFrameLoadType::kReplaceCurrentItem; + return WebFrameLoadType::kStandard; + } } + if (frame_load_type != WebFrameLoadType::kStandard) + return frame_load_type; CHECK_NE(mojom::FetchCacheMode::kValidateCache, request.GetResourceRequest().GetCacheMode()); CHECK_NE(mojom::FetchCacheMode::kBypassCache, @@ -646,8 +658,7 @@ // "If the browsing context's session history contains only one Document, // and that was the about:blank Document created when the browsing context // was created, then the navigation must be done with replacement enabled." - if (request.ReplacesCurrentItem() || - (!state_machine_.CommittedMultipleRealLoads() && + if ((!state_machine_.CommittedMultipleRealLoads() && DeprecatedEqualIgnoringCase(frame_->GetDocument()->Url(), BlankURL()))) return WebFrameLoadType::kReplaceCurrentItem; @@ -806,7 +817,7 @@ bool was_in_same_page = target_frame->GetPage() == frame_->GetPage(); request.SetFrameName("_self"); - target_frame->Navigate(request); + target_frame->Navigate(request, frame_load_type); Page* page = target_frame->GetPage(); if (!was_in_same_page && page) page->GetChromeClient().Focus(frame_); @@ -835,8 +846,7 @@ return; } - if (frame_load_type == WebFrameLoadType::kStandard) - frame_load_type = DetermineFrameLoadType(request); + frame_load_type = DetermineFrameLoadType(request, frame_load_type); bool same_document_navigation = policy == kNavigationPolicyCurrentTab && @@ -934,7 +944,6 @@ nullptr, resource_request, AtomicString(), request.ShouldCheckMainWorldContentSecurityPolicy(), request.GetDevToolsNavigationToken()); - new_request.SetReplacesCurrentItem(request.ReplacesCurrentItem()); new_request.SetClientRedirect(request.ClientRedirect()); CommitNavigation(new_request, frame_load_type, nullptr, nullptr, nullptr); return; @@ -1000,8 +1009,7 @@ resource_request.SetHasUserGesture( LocalFrame::HasTransientUserActivation(frame_)); - if (frame_load_type == WebFrameLoadType::kStandard) - frame_load_type = DetermineFrameLoadType(request); + frame_load_type = DetermineFrameLoadType(request, frame_load_type); // Note: we might actually classify this navigation as same document // right here in the following circumstances: @@ -1760,6 +1768,9 @@ bool replace_current_item = load_type == WebFrameLoadType::kReplaceCurrentItem && (!Opener() || !request.Url().IsEmpty()); + // TODO(dgozman): we should get rid of this boolean field, and make client + // responsible for it's own view of "replaces current item", based on the + // frame load type. loader->SetReplacesCurrentHistoryItem(replace_current_item); probe::lifecycleEvent(frame_, loader, "init", CurrentTimeTicksInSeconds());
diff --git a/third_party/blink/renderer/core/loader/frame_loader.h b/third_party/blink/renderer/core/loader/frame_loader.h index 11c3de10..2f113d6a 100644 --- a/third_party/blink/renderer/core/loader/frame_loader.h +++ b/third_party/blink/renderer/core/loader/frame_loader.h
@@ -229,7 +229,8 @@ private: bool PrepareRequestForThisFrame(FrameLoadRequest&); - WebFrameLoadType DetermineFrameLoadType(const FrameLoadRequest&); + WebFrameLoadType DetermineFrameLoadType(const FrameLoadRequest&, + WebFrameLoadType); SubstituteData DefaultSubstituteDataForURL(const KURL&);
diff --git a/third_party/blink/renderer/core/loader/navigation_scheduler.cc b/third_party/blink/renderer/core/loader/navigation_scheduler.cc index ba1dd26..7d5aba6 100644 --- a/third_party/blink/renderer/core/loader/navigation_scheduler.cc +++ b/third_party/blink/renderer/core/loader/navigation_scheduler.cc
@@ -70,18 +70,15 @@ double delay, Document* origin_document, const KURL& url, - bool replaces_current_item, + WebFrameLoadType frame_load_type, bool is_location_change, base::TimeTicks input_timestamp) - : ScheduledNavigation(reason, - delay, - origin_document, - replaces_current_item, - is_location_change), + : ScheduledNavigation(reason, delay, origin_document, is_location_change), url_(url), should_check_main_world_content_security_policy_( kCheckContentSecurityPolicy), - input_timestamp_(input_timestamp) { + input_timestamp_(input_timestamp), + frame_load_type_(frame_load_type) { if (ContentSecurityPolicy::ShouldBypassMainWorld(origin_document)) { should_check_main_world_content_security_policy_ = kDoNotCheckContentSecurityPolicy; @@ -99,7 +96,6 @@ CreateUserGestureIndicator(); FrameLoadRequest request(OriginDocument(), ResourceRequest(url_), "_self", should_check_main_world_content_security_policy_); - request.SetReplacesCurrentItem(ReplacesCurrentItem()); request.SetClientRedirect(ClientRedirectPolicy::kClientRedirect); if (!input_timestamp_.is_null()) { request.SetInputStartTime(input_timestamp_); @@ -111,17 +107,20 @@ request.SetBlobURLToken(std::move(token_clone)); } - frame->Loader().StartNavigation(request); + frame->Loader().StartNavigation(request, frame_load_type_); } KURL Url() const override { return url_; } + WebFrameLoadType LoadType() const { return frame_load_type_; } + private: KURL url_; mojom::blink::BlobURLTokenPtr blob_url_token_; ContentSecurityPolicyDisposition should_check_main_world_content_security_policy_; base::TimeTicks input_timestamp_; + WebFrameLoadType frame_load_type_; }; class ScheduledRedirect final : public ScheduledURLNavigation { @@ -130,9 +129,9 @@ Document* origin_document, const KURL& url, Document::HttpRefreshType http_refresh_type, - bool replaces_current_item) { + WebFrameLoadType frame_load_type) { return new ScheduledRedirect(delay, origin_document, url, http_refresh_type, - replaces_current_item); + frame_load_type); } bool ShouldStartTimer(LocalFrame* frame) override { @@ -143,8 +142,7 @@ std::unique_ptr<UserGestureIndicator> gesture_indicator = CreateUserGestureIndicator(); FrameLoadRequest request(OriginDocument(), ResourceRequest(Url()), "_self"); - WebFrameLoadType load_type = WebFrameLoadType::kStandard; - request.SetReplacesCurrentItem(ReplacesCurrentItem()); + WebFrameLoadType load_type = LoadType(); if (EqualIgnoringFragmentIdentifier(frame->GetDocument()->Url(), request.GetResourceRequest().Url())) { request.GetResourceRequest().SetCacheMode( @@ -173,12 +171,12 @@ Document* origin_document, const KURL& url, Document::HttpRefreshType http_refresh_type, - bool replaces_current_item) + WebFrameLoadType frame_load_type) : ScheduledURLNavigation(ToReason(http_refresh_type), delay, origin_document, url, - replaces_current_item, + frame_load_type, false, base::TimeTicks()) { ClearUserGesture(); @@ -189,22 +187,22 @@ public: static ScheduledFrameNavigation* Create(Document* origin_document, const KURL& url, - bool replaces_current_item, + WebFrameLoadType frame_load_type, base::TimeTicks input_timestamp) { - return new ScheduledFrameNavigation(origin_document, url, - replaces_current_item, input_timestamp); + return new ScheduledFrameNavigation(origin_document, url, frame_load_type, + input_timestamp); } private: ScheduledFrameNavigation(Document* origin_document, const KURL& url, - bool replaces_current_item, + WebFrameLoadType frame_load_type, base::TimeTicks input_timestamp) : ScheduledURLNavigation(Reason::kFrameNavigation, 0.0, origin_document, url, - replaces_current_item, + frame_load_type, !url.ProtocolIsJavaScript(), input_timestamp) {} }; @@ -239,7 +237,6 @@ : ScheduledNavigation(Reason::kReload, 0.0, nullptr /*origin_document */, - true, true), frame_(frame) { DCHECK(frame->GetDocument()); @@ -265,7 +262,6 @@ : ScheduledNavigation(Reason::kPageBlock, 0.0, origin_document, - true, true), reason_(reason) {} @@ -276,9 +272,8 @@ public: static ScheduledFormSubmission* Create(Document* document, FormSubmission* submission, - bool replaces_current_item) { - return new ScheduledFormSubmission(document, submission, - replaces_current_item); + WebFrameLoadType frame_load_type) { + return new ScheduledFormSubmission(document, submission, frame_load_type); } void Fire(LocalFrame* frame) override { @@ -286,8 +281,7 @@ CreateUserGestureIndicator(); FrameLoadRequest frame_request = submission_->CreateFrameLoadRequest(OriginDocument()); - frame_request.SetReplacesCurrentItem(ReplacesCurrentItem()); - frame->Loader().StartNavigation(frame_request, WebFrameLoadType::kStandard, + frame->Loader().StartNavigation(frame_request, frame_load_type_, submission_->GetNavigationPolicy()); } @@ -301,20 +295,21 @@ private: ScheduledFormSubmission(Document* document, FormSubmission* submission, - bool replaces_current_item) + WebFrameLoadType frame_load_type) : ScheduledNavigation(submission->Method() == FormSubmission::kGetMethod ? Reason::kFormSubmissionGet : Reason::kFormSubmissionPost, 0, document, - replaces_current_item, true), - submission_(submission) { + submission_(submission), + frame_load_type_(frame_load_type) { DCHECK_NE(submission->Method(), FormSubmission::kDialogMethod); DCHECK(submission_->Form()); } Member<FormSubmission> submission_; + WebFrameLoadType frame_load_type_; }; NavigationScheduler::NavigationScheduler(LocalFrame* frame) : frame_(frame) {} @@ -373,8 +368,11 @@ // We want a new back/forward list item if the refresh timeout is > 1 second. if (!redirect_ || delay <= redirect_->Delay()) { + WebFrameLoadType frame_load_type = WebFrameLoadType::kStandard; + if (delay <= 1) + frame_load_type = WebFrameLoadType::kReplaceCurrentItem; Schedule(ScheduledRedirect::Create(delay, frame_->GetDocument(), url, - http_refresh_type, delay <= 1)); + http_refresh_type, frame_load_type)); } } @@ -396,9 +394,10 @@ !ToLocalFrame(parent_frame)->Loader().AllAncestorsAreComplete(); } -void NavigationScheduler::ScheduleFrameNavigation(Document* origin_document, - const KURL& url, - bool replaces_current_item) { +void NavigationScheduler::ScheduleFrameNavigation( + Document* origin_document, + const KURL& url, + WebFrameLoadType frame_load_type) { if (!ShouldScheduleNavigation(url)) return; @@ -407,8 +406,8 @@ input_timestamp = input_event->TimeStamp(); } - replaces_current_item = - replaces_current_item || MustReplaceCurrentItem(frame_); + if (MustReplaceCurrentItem(frame_)) + frame_load_type = WebFrameLoadType::kReplaceCurrentItem; // If the URL we're going to navigate to is the same as the current one, // except for the fragment part, we don't need to schedule the location @@ -419,17 +418,16 @@ if (url.HasFragmentIdentifier() && EqualIgnoringFragmentIdentifier(frame_->GetDocument()->Url(), url)) { FrameLoadRequest request(origin_document, ResourceRequest(url), "_self"); - request.SetReplacesCurrentItem(replaces_current_item); request.SetInputStartTime(input_timestamp); - if (replaces_current_item) + if (frame_load_type == WebFrameLoadType::kReplaceCurrentItem) request.SetClientRedirect(ClientRedirectPolicy::kClientRedirect); - frame_->Loader().StartNavigation(request); + frame_->Loader().StartNavigation(request, frame_load_type); return; } } - Schedule(ScheduledFrameNavigation::Create( - origin_document, url, replaces_current_item, input_timestamp)); + Schedule(ScheduledFrameNavigation::Create(origin_document, url, + frame_load_type, input_timestamp)); } void NavigationScheduler::SchedulePageBlock(Document* origin_document, @@ -441,8 +439,11 @@ void NavigationScheduler::ScheduleFormSubmission(Document* document, FormSubmission* submission) { DCHECK(frame_->GetPage()); - Schedule(ScheduledFormSubmission::Create(document, submission, - MustReplaceCurrentItem(frame_))); + WebFrameLoadType frame_load_type = WebFrameLoadType::kStandard; + if (MustReplaceCurrentItem(frame_)) + frame_load_type = WebFrameLoadType::kReplaceCurrentItem; + Schedule( + ScheduledFormSubmission::Create(document, submission, frame_load_type)); } void NavigationScheduler::ScheduleReload() {
diff --git a/third_party/blink/renderer/core/loader/navigation_scheduler.h b/third_party/blink/renderer/core/loader/navigation_scheduler.h index 67cd23e4a..c270de2 100644 --- a/third_party/blink/renderer/core/loader/navigation_scheduler.h +++ b/third_party/blink/renderer/core/loader/navigation_scheduler.h
@@ -37,6 +37,7 @@ #include "base/macros.h" #include "base/memory/scoped_refptr.h" #include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h" +#include "third_party/blink/public/web/web_frame_load_type.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/platform/heap/handle.h" @@ -65,9 +66,7 @@ bool IsNavigationScheduledWithin(double interval_in_seconds) const; void ScheduleRedirect(double delay, const KURL&, Document::HttpRefreshType); - void ScheduleFrameNavigation(Document*, - const KURL&, - bool replaces_current_item = true); + void ScheduleFrameNavigation(Document*, const KURL&, WebFrameLoadType); void SchedulePageBlock(Document*, int reason); void ScheduleFormSubmission(Document*, FormSubmission*); void ScheduleReload();
diff --git a/third_party/blink/renderer/core/loader/scheduled_navigation.cc b/third_party/blink/renderer/core/loader/scheduled_navigation.cc index 6b2b9e5..fc8768da 100644 --- a/third_party/blink/renderer/core/loader/scheduled_navigation.cc +++ b/third_party/blink/renderer/core/loader/scheduled_navigation.cc
@@ -15,12 +15,10 @@ ScheduledNavigation::ScheduledNavigation(Reason reason, double delay, Document* origin_document, - bool replaces_current_item, bool is_location_change) : reason_(reason), delay_(delay), origin_document_(origin_document), - replaces_current_item_(replaces_current_item), is_location_change_(is_location_change) { if (LocalFrame::HasTransientUserActivation( origin_document ? origin_document->GetFrame() : nullptr))
diff --git a/third_party/blink/renderer/core/loader/scheduled_navigation.h b/third_party/blink/renderer/core/loader/scheduled_navigation.h index 82942e2..5d48eed 100644 --- a/third_party/blink/renderer/core/loader/scheduled_navigation.h +++ b/third_party/blink/renderer/core/loader/scheduled_navigation.h
@@ -31,7 +31,6 @@ ScheduledNavigation(Reason, double delay, Document* origin_document, - bool replaces_current_item, bool is_location_change); virtual ~ScheduledNavigation(); @@ -44,7 +43,6 @@ Reason GetReason() const { return reason_; } double Delay() const { return delay_; } Document* OriginDocument() const { return origin_document_.Get(); } - bool ReplacesCurrentItem() const { return replaces_current_item_; } bool IsLocationChange() const { return is_location_change_; } std::unique_ptr<UserGestureIndicator> CreateUserGestureIndicator(); @@ -59,7 +57,6 @@ Reason reason_; double delay_; Member<Document> origin_document_; - bool replaces_current_item_; bool is_location_change_; scoped_refptr<UserGestureToken> user_gesture_token_;
diff --git a/third_party/blink/renderer/core/page/create_window.cc b/third_party/blink/renderer/core/page/create_window.cc index f3ab620..3d3f5683 100644 --- a/third_party/blink/renderer/core/page/create_window.cc +++ b/third_party/blink/renderer/core/page/create_window.cc
@@ -451,10 +451,10 @@ if (const WebInputEvent* input_event = CurrentInputEvent::Get()) { request.SetInputStartTime(input_event->TimeStamp()); } - new_frame->Navigate(request); + new_frame->Navigate(request, WebFrameLoadType::kStandard); } else if (!url_string.IsEmpty()) { new_frame->ScheduleNavigation(*calling_window.document(), completed_url, - false, + WebFrameLoadType::kStandard, has_user_gesture ? UserGestureStatus::kActive : UserGestureStatus::kNone); }
diff --git a/third_party/blink/renderer/core/page/drag_controller.cc b/third_party/blink/renderer/core/page/drag_controller.cc index a7c06afc..7b0d5eb 100644 --- a/third_party/blink/renderer/core/page/drag_controller.cc +++ b/third_party/blink/renderer/core/page/drag_controller.cc
@@ -299,7 +299,8 @@ SecurityOrigin::Create(KURL(drag_data->AsURL()))); resource_request.SetHasUserGesture(LocalFrame::HasTransientUserActivation( document_under_mouse_ ? document_under_mouse_->GetFrame() : nullptr)); - page_->MainFrame()->Navigate(FrameLoadRequest(nullptr, resource_request)); + page_->MainFrame()->Navigate(FrameLoadRequest(nullptr, resource_request), + WebFrameLoadType::kStandard); } // TODO(bokan): This case happens when we end a URL drag inside a guest
diff --git a/third_party/blink/renderer/core/paint/clip_path_clipper.cc b/third_party/blink/renderer/core/paint/clip_path_clipper.cc index 54e5ce3..6816f59 100644 --- a/third_party/blink/renderer/core/paint/clip_path_clipper.cc +++ b/third_party/blink/renderer/core/paint/clip_path_clipper.cc
@@ -71,14 +71,7 @@ return FloatRect(ToLayoutBox(object).BorderBoxRect()); SECURITY_DCHECK(object.IsLayoutInline()); - const LayoutInline& layout_inline = ToLayoutInline(object); - // This somewhat convoluted computation matches what Gecko does. - // See crbug.com/641907. - LayoutRect inline_b_box = layout_inline.LinesBoundingBox(); - const InlineFlowBox* flow_box = layout_inline.FirstLineBox(); - inline_b_box.SetHeight(flow_box ? flow_box->FrameRect().Height() - : LayoutUnit(0)); - return FloatRect(inline_b_box); + return FloatRect(ToLayoutInline(object).ReferenceBoxForClipPath()); } base::Optional<FloatRect> ClipPathClipper::LocalClipPathBoundingBox(
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker.cc b/third_party/blink/renderer/core/workers/dedicated_worker.cc index 5d6f2c2..ad3a5a1c 100644 --- a/third_party/blink/renderer/core/workers/dedicated_worker.cc +++ b/third_party/blink/renderer/core/workers/dedicated_worker.cc
@@ -11,14 +11,14 @@ #include "third_party/blink/public/platform/dedicated_worker_factory.mojom-blink.h" #include "third_party/blink/public/platform/web_content_settings_client.h" #include "third_party/blink/public/platform/web_layer_tree_view.h" -#include "third_party/blink/public/web/web_local_frame_client.h" #include "third_party/blink/renderer/bindings/core/v8/serialization/post_message_helper.h" #include "third_party/blink/renderer/core/core_initializer.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/events/message_event.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h" +#include "third_party/blink/renderer/core/frame/local_frame.h" +#include "third_party/blink/renderer/core/frame/local_frame_client.h" #include "third_party/blink/renderer/core/frame/use_counter.h" -#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h" #include "third_party/blink/renderer/core/inspector/main_thread_debugger.h" #include "third_party/blink/renderer/core/messaging/post_message_options.h" #include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h" @@ -257,9 +257,8 @@ std::unique_ptr<WebContentSettingsClient> client; if (GetExecutionContext()->IsDocument()) { - WebLocalFrameImpl* web_frame = WebLocalFrameImpl::FromFrame( - ToDocument(GetExecutionContext())->GetFrame()); - client = web_frame->Client()->CreateWorkerContentSettingsClient(); + LocalFrame* frame = ToDocument(GetExecutionContext())->GetFrame(); + client = frame->Client()->CreateWorkerContentSettingsClient(); } else if (GetExecutionContext()->IsWorkerGlobalScope()) { WebContentSettingsClient* web_worker_content_settings_client = WorkerContentSettingsClient::From(*GetExecutionContext())
diff --git a/third_party/blink/renderer/core/workers/threaded_messaging_proxy_base.cc b/third_party/blink/renderer/core/workers/threaded_messaging_proxy_base.cc index 4dc16a5..920d9cf 100644 --- a/third_party/blink/renderer/core/workers/threaded_messaging_proxy_base.cc +++ b/third_party/blink/renderer/core/workers/threaded_messaging_proxy_base.cc
@@ -7,11 +7,11 @@ #include "base/synchronization/waitable_event.h" #include "third_party/blink/public/platform/task_type.h" #include "third_party/blink/public/platform/web_worker_fetch_context.h" -#include "third_party/blink/public/web/web_local_frame_client.h" #include "third_party/blink/renderer/bindings/core/v8/source_location.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/frame/deprecation.h" -#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h" +#include "third_party/blink/renderer/core/frame/local_frame.h" +#include "third_party/blink/renderer/core/frame/local_frame_client.h" #include "third_party/blink/renderer/core/loader/document_loader.h" #include "third_party/blink/renderer/core/loader/worker_fetch_context.h" #include "third_party/blink/renderer/core/workers/global_scope_creation_params.h" @@ -65,15 +65,13 @@ std::unique_ptr<WebWorkerFetchContext> web_worker_fetch_context; if (execution_context_->IsDocument()) { - // |web_frame| is null in some unit tests. - if (WebLocalFrameImpl* web_frame = WebLocalFrameImpl::FromFrame( - ToDocument(GetExecutionContext())->GetFrame())) { - web_worker_fetch_context = - web_frame->Client()->CreateWorkerFetchContext(); - DCHECK(web_worker_fetch_context); + LocalFrame* frame = ToDocument(GetExecutionContext())->GetFrame(); + web_worker_fetch_context = frame->Client()->CreateWorkerFetchContext(); + // |web_worker_fetch_context| is null in some unit tests. + if (web_worker_fetch_context) { web_worker_fetch_context->SetApplicationCacheHostID( GetExecutionContext()->Fetcher()->Context().ApplicationCacheHostID()); - web_worker_fetch_context->SetIsOnSubframe(web_frame != web_frame->Top()); + web_worker_fetch_context->SetIsOnSubframe(!frame->IsMainFrame()); } } else if (execution_context_->IsWorkerGlobalScope()) { web_worker_fetch_context =
diff --git a/third_party/blink/renderer/devtools/front_end/elements/StylesSidebarPane.js b/third_party/blink/renderer/devtools/front_end/elements/StylesSidebarPane.js index 55888d9e..36b0565 100644 --- a/third_party/blink/renderer/devtools/front_end/elements/StylesSidebarPane.js +++ b/third_party/blink/renderer/devtools/front_end/elements/StylesSidebarPane.js
@@ -2107,7 +2107,7 @@ case 'ArrowDown': case 'PageUp': case 'PageDown': - if (this._handleNameOrValueUpDown(event)) { + if (!this.isSuggestBoxVisible() && this._handleNameOrValueUpDown(event)) { event.preventDefault(); return; }
diff --git a/third_party/blink/renderer/devtools/front_end/ui/TextPrompt.js b/third_party/blink/renderer/devtools/front_end/ui/TextPrompt.js index 30f5e79a..f3305be 100644 --- a/third_party/blink/renderer/devtools/front_end/ui/TextPrompt.js +++ b/third_party/blink/renderer/devtools/front_end/ui/TextPrompt.js
@@ -274,7 +274,7 @@ */ onKeyDown(event) { let handled = false; - if (this._isSuggestBoxVisible() && this._suggestBox.keyPressed(event)) { + if (this.isSuggestBoxVisible() && this._suggestBox.keyPressed(event)) { event.consume(true); return; } @@ -299,7 +299,7 @@ this.clearAutocomplete(); break; case 'Escape': - if (this._isSuggestBoxVisible()) { + if (this.isSuggestBoxVisible()) { this.clearAutocomplete(); handled = true; } @@ -338,7 +338,7 @@ */ acceptAutoComplete() { let result = false; - if (this._isSuggestBoxVisible()) + if (this.isSuggestBoxVisible()) result = this._suggestBox.acceptSuggestion(); if (!result) result = this._acceptSuggestionInternal(); @@ -349,7 +349,7 @@ clearAutocomplete() { const beforeText = this.textWithCurrentSuggestion(); - if (this._isSuggestBoxVisible()) + if (this.isSuggestBoxVisible()) this._suggestBox.hide(); this._clearAutocompleteTimeout(); this._queryRange = null; @@ -382,7 +382,7 @@ * @param {boolean=} force */ autoCompleteSoon(force) { - const immediately = this._isSuggestBoxVisible() || force; + const immediately = this.isSuggestBoxVisible() || force; if (!this._completeTimeout) { this._completeTimeout = setTimeout(this.complete.bind(this, force), immediately ? 0 : this._autocompletionTimeout); @@ -401,7 +401,7 @@ let shouldExit; - if (!force && !this._isCaretAtEndOfPrompt() && !this._isSuggestBoxVisible()) + if (!force && !this._isCaretAtEndOfPrompt() && !this.isSuggestBoxVisible()) shouldExit = true; else if (!selection.isCollapsed) shouldExit = true; @@ -565,9 +565,10 @@ } /** + * @protected * @return {boolean} */ - _isSuggestBoxVisible() { + isSuggestBoxVisible() { return this._suggestBox && this._suggestBox.visible(); }
diff --git a/third_party/blink/renderer/modules/accessibility/ax_media_controls.cc b/third_party/blink/renderer/modules/accessibility/ax_media_controls.cc index 664ad27..4bc852f 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_media_controls.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_media_controls.cc
@@ -195,45 +195,31 @@ ax::mojom::DescriptionFrom& description_from, AXObjectVector* description_objects) const { switch (ControlType()) { - case kMediaEnterFullscreenButton: - return QueryString(WebLocalizedString::kAXMediaEnterFullscreenButtonHelp); - case kMediaExitFullscreenButton: - return QueryString(WebLocalizedString::kAXMediaExitFullscreenButtonHelp); - case kMediaMuteButton: - return QueryString(WebLocalizedString::kAXMediaMuteButtonHelp); - case kMediaPlayButton: - return QueryString(WebLocalizedString::kAXMediaPlayButtonHelp); - case kMediaUnMuteButton: - return QueryString(WebLocalizedString::kAXMediaUnMuteButtonHelp); - case kMediaPauseButton: - return QueryString(WebLocalizedString::kAXMediaPauseButtonHelp); case kMediaCurrentTimeDisplay: return QueryString(WebLocalizedString::kAXMediaCurrentTimeDisplayHelp); case kMediaTimeRemainingDisplay: return QueryString(WebLocalizedString::kAXMediaTimeRemainingDisplayHelp); - case kMediaShowClosedCaptionsButton: - return QueryString( - WebLocalizedString::kAXMediaShowClosedCaptionsButtonHelp); - case kMediaHideClosedCaptionsButton: - return QueryString( - WebLocalizedString::kAXMediaHideClosedCaptionsButtonHelp); - case kMediaCastOffButton: - case kMediaOverlayCastOffButton: - return QueryString(WebLocalizedString::kAXMediaCastOffButtonHelp); - case kMediaCastOnButton: - case kMediaOverlayCastOnButton: - return QueryString(WebLocalizedString::kAXMediaCastOnButtonHelp); case kMediaOverflowButton: return QueryString(WebLocalizedString::kAXMediaOverflowButtonHelp); - case kMediaEnterPictureInPictureButton: - return QueryString( - WebLocalizedString::kAXMediaEnterPictureInPictureButtonHelp); - case kMediaExitPictureInPictureButton: - return QueryString( - WebLocalizedString::kAXMediaExitPictureInPictureButtonHelp); + // The following descriptions are repeats of their respective titles. When + // read by accessibility, we get the same thing said twice, with no value + // added. So instead, we just return an empty string. + case kMediaEnterFullscreenButton: + case kMediaExitFullscreenButton: case kMediaDisplayCutoutFullscreenButton: - return QueryString( - WebLocalizedString::kAXMediaDisplayCutoutFullscreenButtonHelp); + case kMediaMuteButton: + case kMediaUnMuteButton: + case kMediaPlayButton: + case kMediaPauseButton: + case kMediaShowClosedCaptionsButton: + case kMediaHideClosedCaptionsButton: + case kMediaCastOffButton: + case kMediaOverlayCastOffButton: + case kMediaCastOnButton: + case kMediaOverlayCastOnButton: + case kMediaEnterPictureInPictureButton: + case kMediaExitPictureInPictureButton: + return ""; case kMediaSliderThumb: case kMediaTextTrackList: case kMediaTimelineContainer:
diff --git a/third_party/blink/renderer/modules/event_target_modules_names.json5 b/third_party/blink/renderer/modules/event_target_modules_names.json5 index b1b6e85..dc4b6094 100644 --- a/third_party/blink/renderer/modules/event_target_modules_names.json5 +++ b/third_party/blink/renderer/modules/event_target_modules_names.json5
@@ -31,6 +31,7 @@ "modules/notifications/Notification", "modules/payments/PaymentRequest", "modules/peerconnection/RTCIceTransport", + "modules/peerconnection/RTCQuicStream", "modules/peerconnection/RTCQuicTransport", "modules/permissions/PermissionStatus", "modules/picture_in_picture/HTMLVideoElementPictureInPicture",
diff --git a/third_party/blink/renderer/modules/modules_idl_files.gni b/third_party/blink/renderer/modules/modules_idl_files.gni index eb7effe..763c8494 100644 --- a/third_party/blink/renderer/modules/modules_idl_files.gni +++ b/third_party/blink/renderer/modules/modules_idl_files.gni
@@ -228,6 +228,7 @@ "peerconnection/rtc_peer_connection.idl", "peerconnection/rtc_peer_connection_ice_event.idl", "peerconnection/rtc_quic_stream.idl", + "peerconnection/rtc_quic_stream_event.idl", "peerconnection/rtc_quic_transport.idl", "peerconnection/rtc_rtp_contributing_source.idl", "peerconnection/rtc_rtp_receiver.idl", @@ -614,6 +615,7 @@ "peerconnection/rtc_offer_options.idl", "peerconnection/rtc_peer_connection_ice_event_init.idl", "peerconnection/rtc_quic_parameters.idl", + "peerconnection/rtc_quic_stream_event_init.idl", "peerconnection/rtc_rtcp_parameters.idl", "peerconnection/rtc_rtp_capabilities.idl", "peerconnection/rtc_rtp_codec_capability.idl",
diff --git a/third_party/blink/renderer/modules/payments/payment_request.cc b/third_party/blink/renderer/modules/payments/payment_request.cc index 25b1e5f..cbdac9c6 100644 --- a/third_party/blink/renderer/modules/payments/payment_request.cc +++ b/third_party/blink/renderer/modules/payments/payment_request.cc
@@ -1222,7 +1222,8 @@ if (retry_resolver_) { DCHECK(payment_response_); - payment_response_->Update(std::move(response), shipping_address_.Get()); + payment_response_->Update(retry_resolver_->GetScriptState(), + std::move(response), shipping_address_.Get()); retry_resolver_->Resolve(); // Do not close the mojo connection here. The merchant website should call @@ -1230,9 +1231,9 @@ // connection to display a success or failure message to the user. retry_resolver_.Clear(); } else if (accept_resolver_) { - payment_response_ = - new PaymentResponse(GetExecutionContext(), std::move(response), - shipping_address_.Get(), this, id_); + payment_response_ = new PaymentResponse(accept_resolver_->GetScriptState(), + std::move(response), + shipping_address_.Get(), this, id_); accept_resolver_->Resolve(payment_response_); // Do not close the mojo connection here. The merchant website should call
diff --git a/third_party/blink/renderer/modules/payments/payment_response.cc b/third_party/blink/renderer/modules/payments/payment_response.cc index 31811e8a..68f5ae9 100644 --- a/third_party/blink/renderer/modules/payments/payment_response.cc +++ b/third_party/blink/renderer/modules/payments/payment_response.cc
@@ -10,20 +10,20 @@ #include "third_party/blink/renderer/modules/payments/payment_state_resolver.h" #include "third_party/blink/renderer/modules/payments/payment_validation_errors.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" +#include "third_party/blink/renderer/platform/bindings/script_state.h" #include "third_party/blink/renderer/platform/wtf/assertions.h" namespace blink { PaymentResponse::PaymentResponse( - ExecutionContext* execution_context, + ScriptState* script_state, payments::mojom::blink::PaymentResponsePtr response, PaymentAddress* shipping_address, PaymentStateResolver* payment_state_resolver, - const String& requestId) - : ContextLifecycleObserver(execution_context), - requestId_(requestId), + const String& request_id) + : ContextLifecycleObserver(ExecutionContext::From(script_state)), + request_id_(request_id), method_name_(response->method_name), - stringified_details_(response->stringified_details), shipping_address_(shipping_address), shipping_option_(response->shipping_option), payer_name_(response->payer->name), @@ -31,22 +31,24 @@ payer_phone_(response->payer->phone), payment_state_resolver_(payment_state_resolver) { DCHECK(payment_state_resolver_); + UpdateDetailsFromJSON(script_state, response->stringified_details); } PaymentResponse::~PaymentResponse() = default; void PaymentResponse::Update( + ScriptState* script_state, payments::mojom::blink::PaymentResponsePtr response, PaymentAddress* shipping_address) { DCHECK(response); DCHECK(response->payer); method_name_ = response->method_name; - stringified_details_ = response->stringified_details; shipping_address_ = shipping_address; shipping_option_ = response->shipping_option; payer_name_ = response->payer->name; payer_email_ = response->payer->email; payer_phone_ = response->payer->phone; + UpdateDetailsFromJSON(script_state, response->stringified_details); } void PaymentResponse::UpdatePayerDetail( @@ -57,11 +59,33 @@ payer_phone_ = detail->phone; } +void PaymentResponse::UpdateDetailsFromJSON(ScriptState* script_state, + const String& json) { + ScriptState::Scope scope(script_state); + if (json.IsEmpty()) { + details_ = V8ObjectBuilder(script_state).GetScriptValue(); + return; + } + + ExceptionState exception_state(script_state->GetIsolate(), + ExceptionState::kConstructionContext, + "PaymentResponse"); + v8::Local<v8::Value> parsed_value = + FromJSONString(script_state->GetIsolate(), script_state->GetContext(), + json, exception_state); + if (exception_state.HadException()) { + exception_state.ClearException(); + details_ = V8ObjectBuilder(script_state).GetScriptValue(); + return; + } + details_ = ScriptValue(script_state, parsed_value); +} + ScriptValue PaymentResponse::toJSONForBinding(ScriptState* script_state) const { V8ObjectBuilder result(script_state); result.AddString("requestId", requestId()); result.AddString("methodName", methodName()); - result.Add("details", details(script_state, ASSERT_NO_EXCEPTION)); + result.Add("details", details(script_state)); if (shippingAddress()) result.Add("shippingAddress", @@ -77,12 +101,8 @@ return result.GetScriptValue(); } -ScriptValue PaymentResponse::details(ScriptState* script_state, - ExceptionState& exception_state) const { - return ScriptValue( - script_state, - FromJSONString(script_state->GetIsolate(), script_state->GetContext(), - stringified_details_, exception_state)); +ScriptValue PaymentResponse::details(ScriptState* script_state) const { + return ScriptValue(script_state, details_.V8ValueFor(script_state)); } ScriptPromise PaymentResponse::complete(ScriptState* script_state,
diff --git a/third_party/blink/renderer/modules/payments/payment_response.h b/third_party/blink/renderer/modules/payments/payment_response.h index 91fd235..f20071d 100644 --- a/third_party/blink/renderer/modules/payments/payment_response.h +++ b/third_party/blink/renderer/modules/payments/payment_response.h
@@ -20,7 +20,6 @@ namespace blink { -class ExceptionState; class PaymentAddress; class PaymentStateResolver; class PaymentValidationErrors; @@ -35,21 +34,24 @@ WTF_MAKE_NONCOPYABLE(PaymentResponse); public: - PaymentResponse(ExecutionContext*, - payments::mojom::blink::PaymentResponsePtr, - PaymentAddress* shipping_address_, - PaymentStateResolver*, - const String& requestId); + PaymentResponse(ScriptState* script_state, + payments::mojom::blink::PaymentResponsePtr response, + PaymentAddress* shipping_address, + PaymentStateResolver* payment_state_resolver, + const String& request_id); ~PaymentResponse() override; - void Update(payments::mojom::blink::PaymentResponsePtr, PaymentAddress*); + void Update(ScriptState* script_state, + payments::mojom::blink::PaymentResponsePtr response, + PaymentAddress* shipping_address); void UpdatePayerDetail(payments::mojom::blink::PayerDetailPtr); + void UpdateDetailsFromJSON(ScriptState* script_state, const String& json); ScriptValue toJSONForBinding(ScriptState*) const; - const String& requestId() const { return requestId_; } + const String& requestId() const { return request_id_; } const String& methodName() const { return method_name_; } - ScriptValue details(ScriptState*, ExceptionState&) const; + ScriptValue details(ScriptState* script_state) const; PaymentAddress* shippingAddress() const { return shipping_address_.Get(); } const String& shippingOption() const { return shipping_option_; } const String& payerName() const { return payer_name_; } @@ -69,9 +71,9 @@ void Trace(blink::Visitor*) override; private: - String requestId_; + String request_id_; String method_name_; - String stringified_details_; + ScriptValue details_; Member<PaymentAddress> shipping_address_; String shipping_option_; String payer_name_;
diff --git a/third_party/blink/renderer/modules/payments/payment_response.idl b/third_party/blink/renderer/modules/payments/payment_response.idl index 39ecfc0..31096ecec 100644 --- a/third_party/blink/renderer/modules/payments/payment_response.idl +++ b/third_party/blink/renderer/modules/payments/payment_response.idl
@@ -22,7 +22,7 @@ readonly attribute DOMString requestId; readonly attribute DOMString methodName; - [CallWith=ScriptState, RaisesException] readonly attribute object details; + [CallWith=ScriptState] readonly attribute object details; readonly attribute PaymentAddress? shippingAddress; readonly attribute DOMString? shippingOption; readonly attribute DOMString? payerName;
diff --git a/third_party/blink/renderer/modules/payments/payment_response_test.cc b/third_party/blink/renderer/modules/payments/payment_response_test.cc index 95c2a276..5f1b4d995 100644 --- a/third_party/blink/renderer/modules/payments/payment_response_test.cc +++ b/third_party/blink/renderer/modules/payments/payment_response_test.cc
@@ -11,6 +11,7 @@ #include "third_party/blink/renderer/bindings/core/v8/script_value.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_object_builder.h" #include "third_party/blink/renderer/modules/payments/payment_address.h" #include "third_party/blink/renderer/modules/payments/payment_state_resolver.h" #include "third_party/blink/renderer/modules/payments/payment_test_helper.h" @@ -59,8 +60,8 @@ MockPaymentStateResolver* complete_callback = new MockPaymentStateResolver; PaymentResponse* output = - new PaymentResponse(scope.GetExecutionContext(), std::move(input), - nullptr, complete_callback, "id"); + new PaymentResponse(scope.GetScriptState(), std::move(input), nullptr, + complete_callback, "id"); EXPECT_EQ("foo", output->methodName()); EXPECT_EQ("standardShippingOption", output->shippingOption()); @@ -69,8 +70,7 @@ EXPECT_EQ("0123", output->payerPhone()); EXPECT_EQ("id", output->requestId()); - ScriptValue details = - output->details(scope.GetScriptState(), scope.GetExceptionState()); + ScriptValue details = output->details(scope.GetScriptState()); ASSERT_FALSE(scope.GetExceptionState().HadException()); ASSERT_TRUE(details.V8Value()->IsObject()); @@ -84,20 +84,41 @@ EXPECT_EQ(123, transaction_id.V8Value().As<v8::Number>()->Value()); } -TEST(PaymentResponseTest, PaymentResponseDetailsJSONObject) { +TEST(PaymentResponseTest, + PaymentResponseDetailsWithUnexpectedJSONFormatString) { V8TestingScope scope; payments::mojom::blink::PaymentResponsePtr input = BuildPaymentResponseForTest(); input->stringified_details = "transactionId"; MockPaymentStateResolver* complete_callback = new MockPaymentStateResolver; PaymentResponse* output = - new PaymentResponse(scope.GetExecutionContext(), std::move(input), - nullptr, complete_callback, "id"); + new PaymentResponse(scope.GetScriptState(), std::move(input), nullptr, + complete_callback, "id"); - ScriptValue details = - output->details(scope.GetScriptState(), scope.GetExceptionState()); + ScriptValue details = output->details(scope.GetScriptState()); + ASSERT_TRUE(details.V8Value()->IsObject()); - ASSERT_TRUE(scope.GetExceptionState().HadException()); + String stringified_details = ToBlinkString<String>( + v8::JSON::Stringify(scope.GetContext(), + details.V8Value().As<v8::Object>()) + .ToLocalChecked(), + kDoNotExternalize); + + EXPECT_EQ("{}", stringified_details); +} + +TEST(PaymentResponseTest, PaymentResponseDetailsRetrunsTheSameObject) { + V8TestingScope scope; + payments::mojom::blink::PaymentResponsePtr input = + BuildPaymentResponseForTest(); + input->method_name = "foo"; + input->stringified_details = "{\"transactionId\": 123}"; + MockPaymentStateResolver* complete_callback = new MockPaymentStateResolver; + PaymentResponse* output = + new PaymentResponse(scope.GetScriptState(), std::move(input), nullptr, + complete_callback, "id"); + EXPECT_EQ(output->details(scope.GetScriptState()), + output->details(scope.GetScriptState())); } TEST(PaymentResponseTest, CompleteCalledWithSuccess) { @@ -108,8 +129,8 @@ input->stringified_details = "{\"transactionId\": 123}"; MockPaymentStateResolver* complete_callback = new MockPaymentStateResolver; PaymentResponse* output = - new PaymentResponse(scope.GetExecutionContext(), std::move(input), - nullptr, complete_callback, "id"); + new PaymentResponse(scope.GetScriptState(), std::move(input), nullptr, + complete_callback, "id"); EXPECT_CALL(*complete_callback, Complete(scope.GetScriptState(), PaymentStateResolver::kSuccess)); @@ -125,8 +146,8 @@ input->stringified_details = "{\"transactionId\": 123}"; MockPaymentStateResolver* complete_callback = new MockPaymentStateResolver; PaymentResponse* output = - new PaymentResponse(scope.GetExecutionContext(), std::move(input), - nullptr, complete_callback, "id"); + new PaymentResponse(scope.GetScriptState(), std::move(input), nullptr, + complete_callback, "id"); EXPECT_CALL(*complete_callback, Complete(scope.GetScriptState(), PaymentStateResolver::kFail)); @@ -155,8 +176,8 @@ new PaymentAddress(std::move(input->shipping_address)); PaymentResponse* output = - new PaymentResponse(scope.GetExecutionContext(), std::move(input), - address, new MockPaymentStateResolver, "id"); + new PaymentResponse(scope.GetScriptState(), std::move(input), address, + new MockPaymentStateResolver, "id"); ScriptValue json_object = output->toJSONForBinding(scope.GetScriptState()); EXPECT_TRUE(json_object.IsObject());
diff --git a/third_party/blink/renderer/modules/peerconnection/BUILD.gn b/third_party/blink/renderer/modules/peerconnection/BUILD.gn index 4f543a3..0592dce0 100644 --- a/third_party/blink/renderer/modules/peerconnection/BUILD.gn +++ b/third_party/blink/renderer/modules/peerconnection/BUILD.gn
@@ -24,6 +24,10 @@ "adapters/p2p_quic_transport_factory_impl.h", "adapters/p2p_quic_transport_impl.cc", "adapters/p2p_quic_transport_impl.h", + "adapters/quic_stream_host.cc", + "adapters/quic_stream_host.h", + "adapters/quic_stream_proxy.cc", + "adapters/quic_stream_proxy.h", "adapters/quic_transport_host.cc", "adapters/quic_transport_host.h", "adapters/quic_transport_proxy.cc", @@ -54,6 +58,8 @@ "rtc_peer_connection_ice_event.h", "rtc_quic_stream.cc", "rtc_quic_stream.h", + "rtc_quic_stream_event.cc", + "rtc_quic_stream_event.h", "rtc_quic_transport.cc", "rtc_quic_transport.h", "rtc_rtp_contributing_source.cc",
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_host.cc b/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_host.cc index 5db8163..495e9605 100644 --- a/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_host.cc +++ b/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_host.cc
@@ -14,10 +14,14 @@ IceTransportHost::IceTransportHost( scoped_refptr<base::SingleThreadTaskRunner> proxy_thread, + scoped_refptr<base::SingleThreadTaskRunner> host_thread, base::WeakPtr<IceTransportProxy> proxy) - : proxy_thread_(std::move(proxy_thread)), proxy_(std::move(proxy)) { + : proxy_thread_(std::move(proxy_thread)), + host_thread_(std::move(host_thread)), + proxy_(std::move(proxy)) { DETACH_FROM_THREAD(thread_checker_); DCHECK(proxy_thread_); + DCHECK(host_thread_); DCHECK(proxy_); } @@ -33,6 +37,18 @@ transport_ = adapter_factory->ConstructOnWorkerThread(this); } +scoped_refptr<base::SingleThreadTaskRunner> IceTransportHost::proxy_thread() + const { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + return proxy_thread_; +} + +scoped_refptr<base::SingleThreadTaskRunner> IceTransportHost::host_thread() + const { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + return host_thread_; +} + void IceTransportHost::StartGathering( const cricket::IceParameters& local_parameters, const cricket::ServerAddresses& stun_servers,
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_host.h b/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_host.h index 08ac5458..63fe3195 100644 --- a/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_host.h +++ b/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_host.h
@@ -42,12 +42,16 @@ class IceTransportHost final : public IceTransportAdapter::Delegate { public: IceTransportHost(scoped_refptr<base::SingleThreadTaskRunner> proxy_thread, + scoped_refptr<base::SingleThreadTaskRunner> host_thread, base::WeakPtr<IceTransportProxy> proxy); ~IceTransportHost() override; void Initialize( std::unique_ptr<IceTransportAdapterCrossThreadFactory> adapter_factory); + scoped_refptr<base::SingleThreadTaskRunner> proxy_thread() const; + scoped_refptr<base::SingleThreadTaskRunner> host_thread() const; + void StartGathering( const cricket::IceParameters& local_parameters, const cricket::ServerAddresses& stun_servers, @@ -75,6 +79,7 @@ void OnStateChanged(cricket::IceTransportState new_state) override; const scoped_refptr<base::SingleThreadTaskRunner> proxy_thread_; + const scoped_refptr<base::SingleThreadTaskRunner> host_thread_; std::unique_ptr<IceTransportAdapter> transport_; base::WeakPtr<IceTransportProxy> proxy_; QuicTransportHost* consumer_host_ = nullptr;
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_proxy.cc b/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_proxy.cc index 3ff6fd7..9a575b79 100644 --- a/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_proxy.cc +++ b/third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_proxy.cc
@@ -33,8 +33,8 @@ // The IceTransportHost is constructed on the proxy thread but should only be // interacted with via PostTask to the host thread. The OnTaskRunnerDeleter // (configured above) will ensure it gets deleted on the host thread. - host_.reset( - new IceTransportHost(proxy_thread_, weak_ptr_factory_.GetWeakPtr())); + host_.reset(new IceTransportHost(proxy_thread_, host_thread_, + weak_ptr_factory_.GetWeakPtr())); PostCrossThreadTask(*host_thread_, FROM_HERE, CrossThreadBind(&IceTransportHost::Initialize, CrossThreadUnretained(host_.get()),
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/quic_stream_host.cc b/third_party/blink/renderer/modules/peerconnection/adapters/quic_stream_host.cc new file mode 100644 index 0000000..71545c64 --- /dev/null +++ b/third_party/blink/renderer/modules/peerconnection/adapters/quic_stream_host.cc
@@ -0,0 +1,88 @@ +// 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 "third_party/blink/renderer/modules/peerconnection/adapters/quic_stream_host.h" + +#include "third_party/blink/renderer/modules/peerconnection/adapters/quic_stream_proxy.h" +#include "third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_host.h" +#include "third_party/blink/renderer/modules/peerconnection/adapters/web_rtc_cross_thread_copier.h" +#include "third_party/blink/renderer/platform/cross_thread_functional.h" +#include "third_party/blink/renderer/platform/web_task_runner.h" + +namespace blink { + +QuicStreamHost::QuicStreamHost() { + DETACH_FROM_THREAD(thread_checker_); +} + +QuicStreamHost::~QuicStreamHost() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); +} + +void QuicStreamHost::set_proxy(base::WeakPtr<QuicStreamProxy> stream_proxy) { + DETACH_FROM_THREAD(thread_checker_); + stream_proxy_ = stream_proxy; +} + +void QuicStreamHost::Initialize(QuicTransportHost* transport_host, + P2PQuicStream* p2p_stream) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK(transport_host); + DCHECK(p2p_stream); + transport_host_ = transport_host; + p2p_stream_ = p2p_stream; + p2p_stream_->SetDelegate(this); +} + +scoped_refptr<base::SingleThreadTaskRunner> QuicStreamHost::proxy_thread() + const { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK(transport_host_); + return transport_host_->proxy_thread(); +} + +void QuicStreamHost::Reset() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK(p2p_stream_); + p2p_stream_->Reset(); + Delete(); +} + +void QuicStreamHost::Finish() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK(p2p_stream_); + p2p_stream_->Finish(); + writeable_ = false; + if (!readable_ && !writeable_) { + Delete(); + } +} + +void QuicStreamHost::OnRemoteReset() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + PostCrossThreadTask( + *proxy_thread(), FROM_HERE, + CrossThreadBind(&QuicStreamProxy::OnRemoteReset, stream_proxy_)); + Delete(); +} + +void QuicStreamHost::OnRemoteFinish() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + PostCrossThreadTask( + *proxy_thread(), FROM_HERE, + CrossThreadBind(&QuicStreamProxy::OnRemoteFinish, stream_proxy_)); + readable_ = false; + if (!readable_ && !writeable_) { + Delete(); + } +} + +void QuicStreamHost::Delete() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK(transport_host_); + // OnRemoveStream will delete |this|. + transport_host_->OnRemoveStream(this); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/quic_stream_host.h b/third_party/blink/renderer/modules/peerconnection/adapters/quic_stream_host.h new file mode 100644 index 0000000..baab847 --- /dev/null +++ b/third_party/blink/renderer/modules/peerconnection/adapters/quic_stream_host.h
@@ -0,0 +1,86 @@ +// 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 THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_QUIC_STREAM_HOST_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_QUIC_STREAM_HOST_H_ + +#include "base/memory/scoped_refptr.h" +#include "base/memory/weak_ptr.h" +#include "base/single_thread_task_runner.h" +#include "base/threading/thread_checker.h" +#include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_stream.h" + +namespace blink { + +class QuicStreamProxy; +class QuicTransportHost; + +// This class is the host side correspondent to the QuicStreamProxy. See the +// QuicStreamProxy documentation for background. This class lives on the host +// thread and proxies calls between the QuicStreamProxy and the P2PQuicStream +// (which is single-threaded). +// +// The QuicStreamHost is owned by the QuicTransportHost and constructed when +// either a new local QUIC stream is created or when a remote QUIC stream has +// been created. The stream host will be deleted in the following circumstances: +// 1) Reset() is called. +// 2) OnRemoteReset() is indicated. +// 3) Finish() and OnRemoteFinish() have been called. +// The QuicStreamHost will instruct the QuicTransportHost to delete it when any +// condition has been met. +// +// Since the QuicStreamHost can be constructed from either the proxy or host +// thread, initialization happens in three steps: +// 1) QuicStreamHost is constructed. +// 2) set_proxy is called when a WeakPtr to the corresponding proxy-thread +// object. +// 3) Initialize is called on the host thread. +class QuicStreamHost final : public base::SupportsWeakPtr<QuicStreamHost>, + public P2PQuicStream::Delegate { + public: + QuicStreamHost(); + ~QuicStreamHost() override; + + // Sets a WeakPtr to the corresponding QuicStreamProxy. This is valid on + // either the proxy or host thread. Should happen right after construction. + void set_proxy(base::WeakPtr<QuicStreamProxy> stream_proxy); + + // Initializes the QuicStreamHost. Must be called on the host thread. + // |transport_host| must outlive this object. + void Initialize(QuicTransportHost* transport_host, P2PQuicStream* p2p_stream); + + // The remaining methods can only be called from the host thread and must be + // preceded by Initialize(). + + scoped_refptr<base::SingleThreadTaskRunner> proxy_thread() const; + + void Reset(); + void Finish(); + + private: + // Instruct the QuicTransportHost to remove and delete this stream host. + void Delete(); + + // P2PQuicStream::Delegate overrides. + void OnRemoteReset() override; + void OnRemoteFinish() override; + + // Up reference. Owned by QuicTransportProxy. + QuicTransportHost* transport_host_ = nullptr; + // Forward reference. Owned by P2PQuicTransport. + P2PQuicStream* p2p_stream_ = nullptr; + // Back reference. Owned by QuicTransportProxy. + base::WeakPtr<QuicStreamProxy> stream_proxy_; + + // |readable_| transitions to false when OnRemoteFinish() is called. + bool readable_ = true; + // |writeable_| transitions to false when Finish() is called. + bool writeable_ = true; + + THREAD_CHECKER(thread_checker_); +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_QUIC_STREAM_HOST_H_
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/quic_stream_proxy.cc b/third_party/blink/renderer/modules/peerconnection/adapters/quic_stream_proxy.cc new file mode 100644 index 0000000..e50ebf09 --- /dev/null +++ b/third_party/blink/renderer/modules/peerconnection/adapters/quic_stream_proxy.cc
@@ -0,0 +1,91 @@ +// 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 "third_party/blink/renderer/modules/peerconnection/adapters/quic_stream_proxy.h" + +#include "third_party/blink/renderer/modules/peerconnection/adapters/quic_stream_host.h" +#include "third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_proxy.h" +#include "third_party/blink/renderer/modules/peerconnection/adapters/web_rtc_cross_thread_copier.h" +#include "third_party/blink/renderer/platform/cross_thread_functional.h" +#include "third_party/blink/renderer/platform/web_task_runner.h" + +namespace blink { + +QuicStreamProxy::QuicStreamProxy() { + DETACH_FROM_THREAD(thread_checker_); +} + +QuicStreamProxy::~QuicStreamProxy() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); +} + +void QuicStreamProxy::set_host(base::WeakPtr<QuicStreamHost> stream_host) { + DETACH_FROM_THREAD(thread_checker_); + stream_host_ = stream_host; +} + +void QuicStreamProxy::Initialize(QuicTransportProxy* transport_proxy) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK(transport_proxy); + transport_proxy_ = transport_proxy; +} + +void QuicStreamProxy::set_delegate(Delegate* delegate) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK(delegate); + delegate_ = delegate; +} + +scoped_refptr<base::SingleThreadTaskRunner> QuicStreamProxy::host_thread() + const { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK(transport_proxy_); + return transport_proxy_->host_thread(); +} + +void QuicStreamProxy::Reset() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + PostCrossThreadTask(*host_thread(), FROM_HERE, + CrossThreadBind(&QuicStreamHost::Reset, stream_host_)); + Delete(); +} + +void QuicStreamProxy::Finish() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + PostCrossThreadTask(*host_thread(), FROM_HERE, + CrossThreadBind(&QuicStreamHost::Finish, stream_host_)); + writeable_ = false; + if (!readable_ && !writeable_) { + Delete(); + } +} + +void QuicStreamProxy::OnRemoteReset() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK(delegate_); + // Need to copy the |delegate_| member since Delete() will destroy |this|. + Delegate* delegate_copy = delegate_; + Delete(); + delegate_copy->OnRemoteReset(); +} + +void QuicStreamProxy::OnRemoteFinish() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK(delegate_); + // Need to copy the |delegate_| member since Delete() will destroy |this|. + Delegate* delegate_copy = delegate_; + readable_ = false; + if (!readable_ && !writeable_) { + Delete(); + } + delegate_copy->OnRemoteFinish(); +} + +void QuicStreamProxy::Delete() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + // OnRemoveStream will delete |this|. + transport_proxy_->OnRemoveStream(this); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/quic_stream_proxy.h b/third_party/blink/renderer/modules/peerconnection/adapters/quic_stream_proxy.h new file mode 100644 index 0000000..0d059f6 --- /dev/null +++ b/third_party/blink/renderer/modules/peerconnection/adapters/quic_stream_proxy.h
@@ -0,0 +1,98 @@ +// 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 THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_QUIC_STREAM_PROXY_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_QUIC_STREAM_PROXY_H_ + +#include "base/memory/scoped_refptr.h" +#include "base/memory/weak_ptr.h" +#include "base/single_thread_task_runner.h" +#include "base/threading/thread_checker.h" + +namespace blink { + +class QuicStreamHost; +class QuicTransportProxy; + +// This class allows interactions with a QUIC stream that runs on a thread +// different from which it is controlled. All interactions with the QUIC +// implementation happen asynchronously. +// +// The QuicStreamProxy is owned by the QuicTransportProxy and constructed when +// either a new local QUIC stream is created or when a remote QUIC stream has +// been created. The stream proxy will be deleted in the following +// circumstances: +// 1) Reset() is called. +// 2) OnRemoteReset() is indicated. +// 3) Finish() and OnRemoteFinish() have been called. +// The client is responsible for knowing when any of these conditions have been +// met and clearing its reference accordingly. +// +// Since the QuicStreamProxy can be constructed from either the proxy or host +// thread, initialization happens in four steps: +// 1) QuicStreamProxy is constructed. +// 2) set_host is called with a WeakPtr to the corresponding host-thread object. +// 3) Initialize is called on the proxy thread. +// 4) set_delegate is called on the proxy thread. +class QuicStreamProxy final : public base::SupportsWeakPtr<QuicStreamProxy> { + public: + class Delegate { + public: + virtual ~Delegate() = default; + + // Called when the remote side resets the stream. + virtual void OnRemoteReset() {} + // Called when the remote side finishes the stream. + virtual void OnRemoteFinish() {} + }; + + QuicStreamProxy(); + ~QuicStreamProxy(); + + // Sets a WeakPtr to the corresponding QuicStreamHost. This is valid on either + // the proxy or host thread. Should happen right after construction. + void set_host(base::WeakPtr<QuicStreamHost> stream_host); + + // Initializes the QuicStreamProxy. Must be called on the proxy thread. + // |transport_proxy| must outlive this object. + void Initialize(QuicTransportProxy* transport_proxy); + + // Sets the delegate for receiving remote callbacks. + void set_delegate(Delegate* delegate); + + // The remaining methods can only be called from the proxy thread and must + // be preceded by Initialize(). + + scoped_refptr<base::SingleThreadTaskRunner> host_thread() const; + + void Reset(); + void Finish(); + + private: + // Instruct the QuicTransportProxy to remove and delete this stream proxy. + void Delete(); + + // Callbacks from QuicStreamHost. + friend class QuicStreamHost; + void OnRemoteReset(); + void OnRemoteFinish(); + + // Up reference. Owned by the QuicTransportProxy client. + QuicTransportProxy* transport_proxy_ = nullptr; + // Forward reference. Owned by the QuicTransportHost. + base::WeakPtr<QuicStreamHost> stream_host_; + // Back reference. Owned by the RTCQuicTransport. + Delegate* delegate_ = nullptr; + + // |readable_| transitions to false when OnRemoteFinish() is called. + bool readable_ = true; + // |writeable_| transitions to false when Finish() is called. + bool writeable_ = true; + + THREAD_CHECKER(thread_checker_); +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_QUIC_STREAM_PROXY_H_
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_host.cc b/third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_host.cc index a875a85..3ba0c444 100644 --- a/third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_host.cc +++ b/third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_host.cc
@@ -4,10 +4,14 @@ #include "third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_host.h" +#include <utility> + #include "net/quic/quic_chromium_alarm_factory.h" #include "net/third_party/quic/platform/impl/quic_chromium_clock.h" #include "third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_host.h" #include "third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_factory_impl.h" +#include "third_party/blink/renderer/modules/peerconnection/adapters/quic_stream_host.h" +#include "third_party/blink/renderer/modules/peerconnection/adapters/quic_stream_proxy.h" #include "third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_proxy.h" #include "third_party/blink/renderer/modules/peerconnection/adapters/web_rtc_cross_thread_copier.h" #include "third_party/blink/renderer/platform/cross_thread_functional.h" @@ -15,12 +19,9 @@ namespace blink { -QuicTransportHost::QuicTransportHost( - scoped_refptr<base::SingleThreadTaskRunner> proxy_thread, - base::WeakPtr<QuicTransportProxy> proxy) - : proxy_thread_(std::move(proxy_thread)), proxy_(std::move(proxy)) { +QuicTransportHost::QuicTransportHost(base::WeakPtr<QuicTransportProxy> proxy) + : proxy_(std::move(proxy)) { DETACH_FROM_THREAD(thread_checker_); - DCHECK(proxy_thread_); DCHECK(proxy_); } @@ -35,7 +36,6 @@ void QuicTransportHost::Initialize( IceTransportHost* ice_transport_host, - scoped_refptr<base::SingleThreadTaskRunner> host_thread, quic::Perspective perspective, const std::vector<rtc::scoped_refptr<rtc::RTCCertificate>>& certificates) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); @@ -43,8 +43,8 @@ DCHECK(!ice_transport_host_); ice_transport_host_ = ice_transport_host; quic::QuicClock* clock = quic::QuicChromiumClock::GetInstance(); - auto alarm_factory = - std::make_unique<net::QuicChromiumAlarmFactory>(host_thread.get(), clock); + auto alarm_factory = std::make_unique<net::QuicChromiumAlarmFactory>( + host_thread().get(), clock); quic_transport_factory_.reset( new P2PQuicTransportFactoryImpl(clock, std::move(alarm_factory))); P2PQuicTransportConfig config( @@ -55,6 +55,18 @@ quic_transport_factory_->CreateQuicTransport(std::move(config)); } +scoped_refptr<base::SingleThreadTaskRunner> QuicTransportHost::proxy_thread() + const { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + return ice_transport_host_->proxy_thread(); +} + +scoped_refptr<base::SingleThreadTaskRunner> QuicTransportHost::host_thread() + const { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + return ice_transport_host_->host_thread(); +} + void QuicTransportHost::Start( std::vector<std::unique_ptr<rtc::SSLFingerprint>> remote_fingerprints) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); @@ -66,17 +78,37 @@ quic_transport_->Stop(); } +void QuicTransportHost::CreateStream( + std::unique_ptr<QuicStreamHost> stream_host) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + + P2PQuicStream* p2p_stream = quic_transport_->CreateStream(); + stream_host->Initialize(this, p2p_stream); + stream_hosts_.insert( + std::make_pair(stream_host.get(), std::move(stream_host))); +} + +void QuicTransportHost::OnRemoveStream(QuicStreamHost* stream_host_to_remove) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + + auto it = stream_hosts_.find(stream_host_to_remove); + DCHECK(it != stream_hosts_.end()); + stream_hosts_.erase(it); +} + void QuicTransportHost::OnRemoteStopped() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + stream_hosts_.clear(); PostCrossThreadTask( - *proxy_thread_, FROM_HERE, + *proxy_thread(), FROM_HERE, CrossThreadBind(&QuicTransportProxy::OnRemoteStopped, proxy_)); } void QuicTransportHost::OnConnectionFailed(const std::string& error_details, bool from_remote) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - PostCrossThreadTask(*proxy_thread_, FROM_HERE, + stream_hosts_.clear(); + PostCrossThreadTask(*proxy_thread(), FROM_HERE, CrossThreadBind(&QuicTransportProxy::OnConnectionFailed, proxy_, error_details, from_remote)); } @@ -84,8 +116,27 @@ void QuicTransportHost::OnConnected() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); PostCrossThreadTask( - *proxy_thread_, FROM_HERE, + *proxy_thread(), FROM_HERE, CrossThreadBind(&QuicTransportProxy::OnConnected, proxy_)); } +void QuicTransportHost::OnStream(P2PQuicStream* p2p_stream) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK(p2p_stream); + + auto stream_proxy = std::make_unique<QuicStreamProxy>(); + auto stream_host = std::make_unique<QuicStreamHost>(); + stream_proxy->set_host(stream_host->AsWeakPtr()); + stream_host->set_proxy(stream_proxy->AsWeakPtr()); + + stream_host->Initialize(this, p2p_stream); + + stream_hosts_.insert( + std::make_pair(stream_host.get(), std::move(stream_host))); + + PostCrossThreadTask(*proxy_thread(), FROM_HERE, + CrossThreadBind(&QuicTransportProxy::OnStream, proxy_, + WTF::Passed(std::move(stream_proxy)))); +} + } // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_host.h b/third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_host.h index 0558c95..98c4403 100644 --- a/third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_host.h +++ b/third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_host.h
@@ -5,6 +5,8 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_QUIC_TRANSPORT_HOST_H_ #define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_QUIC_TRANSPORT_HOST_H_ +#include <unordered_map> + #include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" #include "base/single_thread_task_runner.h" @@ -16,6 +18,7 @@ class IceTransportHost; class P2PQuicTransportFactory; +class QuicStreamHost; class QuicTransportProxy; // The host class is the host side correspondent to the QuicTransportProxy. See @@ -42,32 +45,40 @@ // must be called on the host thread. class QuicTransportHost final : public P2PQuicTransport::Delegate { public: - QuicTransportHost(scoped_refptr<base::SingleThreadTaskRunner> proxy_thread, - base::WeakPtr<QuicTransportProxy> transport_proxy); + QuicTransportHost(base::WeakPtr<QuicTransportProxy> transport_proxy); ~QuicTransportHost() override; void Initialize( IceTransportHost* ice_transport_host, - scoped_refptr<base::SingleThreadTaskRunner> host_thread, quic::Perspective perspective, const std::vector<rtc::scoped_refptr<rtc::RTCCertificate>>& certificates); + scoped_refptr<base::SingleThreadTaskRunner> proxy_thread() const; + scoped_refptr<base::SingleThreadTaskRunner> host_thread() const; + void Start( std::vector<std::unique_ptr<rtc::SSLFingerprint>> remote_fingerprints); void Stop(); + void CreateStream(std::unique_ptr<QuicStreamHost> stream_host); + + // QuicStreamHost callbacks. + void OnRemoveStream(QuicStreamHost* stream_host_to_remove); + private: // P2PQuicTransport::Delegate overrides. void OnRemoteStopped() override; void OnConnectionFailed(const std::string& error_details, bool from_remote) override; void OnConnected() override; + void OnStream(P2PQuicStream* stream) override; - const scoped_refptr<base::SingleThreadTaskRunner> proxy_thread_; std::unique_ptr<P2PQuicTransportFactory> quic_transport_factory_; std::unique_ptr<P2PQuicTransport> quic_transport_; base::WeakPtr<QuicTransportProxy> proxy_; IceTransportHost* ice_transport_host_ = nullptr; + std::unordered_map<QuicStreamHost*, std::unique_ptr<QuicStreamHost>> + stream_hosts_; THREAD_CHECKER(thread_checker_); };
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_proxy.cc b/third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_proxy.cc index 815129d..7299267 100644 --- a/third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_proxy.cc +++ b/third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_proxy.cc
@@ -6,6 +6,8 @@ #include "third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_host.h" #include "third_party/blink/renderer/modules/peerconnection/adapters/ice_transport_proxy.h" +#include "third_party/blink/renderer/modules/peerconnection/adapters/quic_stream_host.h" +#include "third_party/blink/renderer/modules/peerconnection/adapters/quic_stream_proxy.h" #include "third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_host.h" #include "third_party/blink/renderer/modules/peerconnection/adapters/web_rtc_cross_thread_copier.h" #include "third_party/blink/renderer/platform/cross_thread_functional.h" @@ -32,8 +34,7 @@ // The QuicTransportHost is constructed on the proxy thread but should only be // interacted with via PostTask to the host thread. The OnTaskRunnerDeleter // (configured above) will ensure it gets deleted on the host thread. - host_.reset( - new QuicTransportHost(proxy_thread, weak_ptr_factory_.GetWeakPtr())); + host_.reset(new QuicTransportHost(weak_ptr_factory_.GetWeakPtr())); // Connect to the IceTransportProxy. This gives us a reference to the // underlying IceTransportHost that should be connected by the // QuicTransportHost on the host thread. It is safe to post it unretained @@ -42,12 +43,11 @@ // object. IceTransportHost* ice_transport_host = ice_transport_proxy->ConnectConsumer(this); - PostCrossThreadTask( - *host_thread(), FROM_HERE, - CrossThreadBind(&QuicTransportHost::Initialize, - CrossThreadUnretained(host_.get()), - CrossThreadUnretained(ice_transport_host), host_thread(), - perspective, certificates)); + PostCrossThreadTask(*host_thread(), FROM_HERE, + CrossThreadBind(&QuicTransportHost::Initialize, + CrossThreadUnretained(host_.get()), + CrossThreadUnretained(ice_transport_host), + perspective, certificates)); } QuicTransportProxy::~QuicTransportProxy() { @@ -85,6 +85,36 @@ CrossThreadUnretained(host_.get()))); } +QuicStreamProxy* QuicTransportProxy::CreateStream() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + + auto stream_proxy = std::make_unique<QuicStreamProxy>(); + auto stream_host = std::make_unique<QuicStreamHost>(); + stream_proxy->set_host(stream_host->AsWeakPtr()); + stream_host->set_proxy(stream_proxy->AsWeakPtr()); + + stream_proxy->Initialize(this); + + PostCrossThreadTask(*host_thread(), FROM_HERE, + CrossThreadBind(&QuicTransportHost::CreateStream, + CrossThreadUnretained(host_.get()), + WTF::Passed(std::move(stream_host)))); + + QuicStreamProxy* stream_proxy_ptr = stream_proxy.get(); + stream_proxies_.insert( + std::make_pair(stream_proxy_ptr, std::move(stream_proxy))); + return stream_proxy_ptr; +} + +void QuicTransportProxy::OnRemoveStream( + QuicStreamProxy* stream_proxy_to_remove) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + + auto it = stream_proxies_.find(stream_proxy_to_remove); + DCHECK(it != stream_proxies_.end()); + stream_proxies_.erase(it); +} + void QuicTransportProxy::OnConnected() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); delegate_->OnConnected(); @@ -92,6 +122,7 @@ void QuicTransportProxy::OnRemoteStopped() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + stream_proxies_.clear(); delegate_->OnRemoteStopped(); } @@ -99,6 +130,19 @@ bool from_remote) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); delegate_->OnConnectionFailed(error_details, from_remote); + stream_proxies_.clear(); +} + +void QuicTransportProxy::OnStream( + std::unique_ptr<QuicStreamProxy> stream_proxy) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + + stream_proxy->Initialize(this); + + QuicStreamProxy* stream_proxy_ptr = stream_proxy.get(); + stream_proxies_.insert( + std::make_pair(stream_proxy_ptr, std::move(stream_proxy))); + delegate_->OnStream(stream_proxy_ptr); } } // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_proxy.h b/third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_proxy.h index 3e158944..e3e949f 100644 --- a/third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_proxy.h +++ b/third_party/blink/renderer/modules/peerconnection/adapters/quic_transport_proxy.h
@@ -5,6 +5,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_QUIC_TRANSPORT_PROXY_H_ #define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_ADAPTERS_QUIC_TRANSPORT_PROXY_H_ +#include <unordered_map> #include <vector> #include "base/memory/scoped_refptr.h" @@ -22,6 +23,7 @@ namespace blink { class IceTransportProxy; +class QuicStreamProxy; class QuicTransportHost; // This class allows the QUIC implementation (P2PQuicTransport) to run on a @@ -49,6 +51,8 @@ // locally by the framer or remotely by the peer. virtual void OnConnectionFailed(const std::string& error_details, bool from_remote) {} + // Called when the remote side has created a new stream. + virtual void OnStream(QuicStreamProxy* stream_proxy) {} }; // Construct a Proxy with the underlying QUIC implementation running on the @@ -72,18 +76,26 @@ std::vector<std::unique_ptr<rtc::SSLFingerprint>> remote_fingerprints); void Stop(); + QuicStreamProxy* CreateStream(); + + // QuicStreamProxy callbacks. + void OnRemoveStream(QuicStreamProxy* stream_proxy); + private: // Callbacks from QuicTransportHost. friend class QuicTransportHost; void OnConnected(); void OnRemoteStopped(); void OnConnectionFailed(const std::string& error_details, bool from_remote); + void OnStream(std::unique_ptr<QuicStreamProxy> stream_proxy); // Since the Host is deleted on the host thread (Via OnTaskRunnerDeleter), as // long as this is alive it is safe to post tasks to it (using unretained). std::unique_ptr<QuicTransportHost, base::OnTaskRunnerDeleter> host_; Delegate* const delegate_; IceTransportProxy* ice_transport_proxy_; + std::unordered_map<QuicStreamProxy*, std::unique_ptr<QuicStreamProxy>> + stream_proxies_; THREAD_CHECKER(thread_checker_);
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream.cc b/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream.cc index ef0cc25..66f32031 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream.cc
@@ -3,13 +3,20 @@ // found in the LICENSE file. #include "third_party/blink/renderer/modules/peerconnection/rtc_quic_stream.h" +#include "third_party/blink/renderer/core/dom/events/event.h" #include "third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.h" namespace blink { -RTCQuicStream::RTCQuicStream(RTCQuicTransport* transport) - : transport_(transport) { +RTCQuicStream::RTCQuicStream(ExecutionContext* context, + RTCQuicTransport* transport, + QuicStreamProxy* stream_proxy) + : EventTargetWithInlineData(), + ContextClient(context), + transport_(transport), + proxy_(stream_proxy) { DCHECK(transport_); + DCHECK(proxy_); } RTCQuicStream::~RTCQuicStream() = default; @@ -42,13 +49,75 @@ return write_buffered_amount_; } +void RTCQuicStream::finish() { + if (!writeable_) { + return; + } + proxy_->Finish(); + writeable_ = false; + if (readable_) { + DCHECK_EQ(state_, RTCQuicStreamState::kOpen); + state_ = RTCQuicStreamState::kClosing; + } else { + DCHECK_EQ(state_, RTCQuicStreamState::kClosing); + Close(); + } +} + +void RTCQuicStream::reset() { + if (IsClosed()) { + return; + } + proxy_->Reset(); + writeable_ = false; + readable_ = false; + Close(); +} + void RTCQuicStream::Stop() { + readable_ = false; + writeable_ = false; state_ = RTCQuicStreamState::kClosed; + proxy_ = nullptr; +} + +void RTCQuicStream::Close() { + Stop(); + transport_->RemoveStream(this); +} + +void RTCQuicStream::OnRemoteReset() { + DCHECK_NE(state_, RTCQuicStreamState::kClosed); + Close(); + DispatchEvent(*Event::Create(EventTypeNames::statechange)); +} + +void RTCQuicStream::OnRemoteFinish() { + DCHECK_NE(state_, RTCQuicStreamState::kClosed); + DCHECK(readable_); + readable_ = false; + if (writeable_) { + DCHECK_EQ(state_, RTCQuicStreamState::kOpen); + state_ = RTCQuicStreamState::kClosing; + } else { + DCHECK_EQ(state_, RTCQuicStreamState::kClosing); + Close(); + } + DispatchEvent(*Event::Create(EventTypeNames::statechange)); +} + +const AtomicString& RTCQuicStream::InterfaceName() const { + return EventTargetNames::RTCQuicStream; +} + +ExecutionContext* RTCQuicStream::GetExecutionContext() const { + return ContextClient::GetExecutionContext(); } void RTCQuicStream::Trace(blink::Visitor* visitor) { visitor->Trace(transport_); - ScriptWrappable::Trace(visitor); + EventTargetWithInlineData::Trace(visitor); + ContextClient::Trace(visitor); } } // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream.h b/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream.h index db56e123..b2952b2 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream.h +++ b/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream.h
@@ -5,8 +5,10 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_RTC_QUIC_STREAM_H_ #define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_RTC_QUIC_STREAM_H_ +#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h" +#include "third_party/blink/renderer/modules/event_target_modules.h" #include "third_party/blink/renderer/modules/modules_export.h" -#include "third_party/blink/renderer/platform/bindings/script_wrappable.h" +#include "third_party/blink/renderer/modules/peerconnection/adapters/quic_stream_proxy.h" namespace blink { @@ -14,29 +16,54 @@ enum class RTCQuicStreamState { kNew, kOpening, kOpen, kClosing, kClosed }; -class MODULES_EXPORT RTCQuicStream final : public ScriptWrappable { +class MODULES_EXPORT RTCQuicStream final : public EventTargetWithInlineData, + public ContextClient, + public QuicStreamProxy::Delegate { DEFINE_WRAPPERTYPEINFO(); public: - RTCQuicStream(RTCQuicTransport* transport); + RTCQuicStream(ExecutionContext* context, + RTCQuicTransport* transport, + QuicStreamProxy* stream_proxy); ~RTCQuicStream() override; + // Called from the RTCQuicTransport when it is being stopped. void Stop(); + bool IsClosed() const { return state_ == RTCQuicStreamState::kClosed; } // rtc_quic_stream.idl RTCQuicTransport* transport() const; String state() const; uint32_t readBufferedAmount() const; uint32_t writeBufferedAmount() const; + void finish(); + void reset(); + DEFINE_ATTRIBUTE_EVENT_LISTENER(statechange); + + // EventTarget overrides. + const AtomicString& InterfaceName() const override; + ExecutionContext* GetExecutionContext() const override; // For garbage collection. void Trace(blink::Visitor* visitor) override; private: + // Closes the stream. This will change the state to kClosed and deregister it + // from the RTCQuicTransport. The QuicStreamProxy can no longer be used after + // this point. + void Close(); + + // QuicStreamProxy::Delegate overrides. + void OnRemoteReset() override; + void OnRemoteFinish() override; + Member<RTCQuicTransport> transport_; - RTCQuicStreamState state_ = RTCQuicStreamState::kNew; + RTCQuicStreamState state_ = RTCQuicStreamState::kOpen; + bool readable_ = true; + bool writeable_ = true; uint32_t read_buffered_amount_ = 0; uint32_t write_buffered_amount_ = 0; + QuicStreamProxy* proxy_; }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream.idl b/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream.idl index edc3184..945d6b4 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream.idl +++ b/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream.idl
@@ -14,12 +14,15 @@ // https://w3c.github.io/webrtc-quic/#quicstream* [ Exposed=Window, - RuntimeEnabled=RTCQuicStream -] interface RTCQuicStream { + RuntimeEnabled=RTCQuicTransport +] interface RTCQuicStream : EventTarget { readonly attribute RTCQuicTransport transport; readonly attribute RTCQuicStreamState state; readonly attribute unsigned long readBufferedAmount; readonly attribute unsigned long writeBufferedAmount; + void finish(); + void reset(); + attribute EventHandler onstatechange; // TODO(crbug.com/868068): Implement remaining methods, attributes, and events. };
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream_event.cc b/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream_event.cc new file mode 100644 index 0000000..af4228d --- /dev/null +++ b/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream_event.cc
@@ -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. + +#include "third_party/blink/renderer/modules/peerconnection/rtc_quic_stream_event.h" +#include "third_party/blink/renderer/modules/peerconnection/rtc_quic_stream.h" +#include "third_party/blink/renderer/modules/peerconnection/rtc_quic_stream_event_init.h" + +namespace blink { + +RTCQuicStreamEvent* RTCQuicStreamEvent::Create(RTCQuicStream* stream) { + return new RTCQuicStreamEvent(stream); +} + +RTCQuicStreamEvent* RTCQuicStreamEvent::Create( + const AtomicString& type, + const RTCQuicStreamEventInit& initializer) { + return new RTCQuicStreamEvent(type, initializer); +} + +RTCQuicStreamEvent::RTCQuicStreamEvent(RTCQuicStream* stream) + : Event(EventTypeNames::quicstream, Bubbles::kNo, Cancelable::kNo), + stream_(stream) {} + +RTCQuicStreamEvent::RTCQuicStreamEvent( + const AtomicString& type, + const RTCQuicStreamEventInit& initializer) + : Event(type, initializer), stream_(initializer.stream()) {} + +RTCQuicStreamEvent::~RTCQuicStreamEvent() = default; + +RTCQuicStream* RTCQuicStreamEvent::stream() const { + return stream_.Get(); +} + +const AtomicString& RTCQuicStreamEvent::InterfaceName() const { + return EventNames::RTCQuicStreamEvent; +} + +void RTCQuicStreamEvent::Trace(blink::Visitor* visitor) { + visitor->Trace(stream_); + Event::Trace(visitor); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream_event.h b/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream_event.h new file mode 100644 index 0000000..6e60d9a --- /dev/null +++ b/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream_event.h
@@ -0,0 +1,44 @@ +// 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 THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_RTC_QUIC_STREAM_EVENT_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_RTC_QUIC_STREAM_EVENT_H_ + +#include "third_party/blink/renderer/modules/event_modules.h" + +namespace blink { + +class RTCQuicStream; +class RTCQuicStreamEventInit; + +class RTCQuicStreamEvent final : public Event { + DEFINE_WRAPPERTYPEINFO(); + + public: + static RTCQuicStreamEvent* Create(RTCQuicStream* stream); + static RTCQuicStreamEvent* Create(const AtomicString& type, + const RTCQuicStreamEventInit& init); + + ~RTCQuicStreamEvent() override; + + // rtc_quic_stream_event.idl + RTCQuicStream* stream() const; + + // Event overrides. + const AtomicString& InterfaceName() const override; + + // For garbage collection. + void Trace(blink::Visitor*) override; + + private: + RTCQuicStreamEvent(RTCQuicStream* stream); + RTCQuicStreamEvent(const AtomicString& type, + const RTCQuicStreamEventInit& init); + + Member<RTCQuicStream> stream_; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_RTC_QUIC_STREAM_EVENT_H_
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream_event.idl b/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream_event.idl new file mode 100644 index 0000000..ced237c --- /dev/null +++ b/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream_event.idl
@@ -0,0 +1,12 @@ +// 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. + +// https://w3c.github.io/webrtc-quic/#rtcquicstreamevent +[ + RuntimeEnabled=RTCQuicTransport, + Constructor(DOMString type, optional RTCQuicStreamEventInit eventInitDict), + Exposed=Window +] interface RTCQuicStreamEvent : Event { + readonly attribute RTCQuicStream stream; +};
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream_event_init.idl b/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream_event_init.idl new file mode 100644 index 0000000..53e3bcd --- /dev/null +++ b/third_party/blink/renderer/modules/peerconnection/rtc_quic_stream_event_init.idl
@@ -0,0 +1,8 @@ +// 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. + +// https://w3c.github.io/webrtc-quic/#dom-rtcquicstreameventinit +dictionary RTCQuicStreamEventInit : EventInit { + RTCQuicStream stream; +};
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.cc b/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.cc index 79d0957..17e2201 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.cc
@@ -12,6 +12,7 @@ #include "third_party/blink/renderer/modules/peerconnection/rtc_certificate.h" #include "third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.h" #include "third_party/blink/renderer/modules/peerconnection/rtc_quic_stream.h" +#include "third_party/blink/renderer/modules/peerconnection/rtc_quic_stream_event.h" namespace blink { @@ -199,14 +200,31 @@ } RTCQuicStream* RTCQuicTransport::createStream(ExceptionState& exception_state) { - if (RaiseExceptionIfClosed(exception_state)) { + // TODO(github.com/w3c/webrtc-quic/issues/50): Maybe support createStream in + // the 'new' or 'connecting' states. + if (state_ != RTCQuicTransportState::kConnected) { + exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError, + "RTCQuicTransport.createStream() is only " + "valid in the 'connected' state."); return nullptr; } - RTCQuicStream* stream = new RTCQuicStream(this); + return AddStream(proxy_->CreateStream()); +} + +RTCQuicStream* RTCQuicTransport::AddStream(QuicStreamProxy* stream_proxy) { + auto* stream = new RTCQuicStream(GetExecutionContext(), this, stream_proxy); + stream_proxy->set_delegate(stream); streams_.insert(stream); return stream; } +void RTCQuicTransport::RemoveStream(RTCQuicStream* stream) { + DCHECK(stream); + auto it = streams_.find(stream); + DCHECK(it != streams_.end()); + streams_.erase(it); +} + void RTCQuicTransport::OnConnected() { state_ = RTCQuicTransportState::kConnected; DispatchEvent(*Event::Create(EventTypeNames::statechange)); @@ -223,6 +241,11 @@ DispatchEvent(*Event::Create(EventTypeNames::statechange)); } +void RTCQuicTransport::OnStream(QuicStreamProxy* stream_proxy) { + RTCQuicStream* stream = AddStream(stream_proxy); + DispatchEvent(*RTCQuicStreamEvent::Create(stream)); +} + bool RTCQuicTransport::RaiseExceptionIfClosed( ExceptionState& exception_state) const { if (IsClosed()) {
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.h b/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.h index d734457..b66e191 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.h +++ b/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.h
@@ -44,6 +44,9 @@ ~RTCQuicTransport() override; + RTCQuicStream* AddStream(QuicStreamProxy* stream_proxy); + void RemoveStream(RTCQuicStream* stream); + // https://w3c.github.io/webrtc-quic/#quic-transport* RTCIceTransport* transport() const; String state() const; @@ -57,6 +60,7 @@ RTCQuicStream* createStream(ExceptionState& exception_state); DEFINE_ATTRIBUTE_EVENT_LISTENER(statechange); DEFINE_ATTRIBUTE_EVENT_LISTENER(error); + DEFINE_ATTRIBUTE_EVENT_LISTENER(quicstream); // Called by the RTCIceTransport when its start() method is called. void OnTransportStarted(); @@ -85,6 +89,7 @@ void OnConnectionFailed(const std::string& error_details, bool from_remote) override; void OnRemoteStopped() override; + void OnStream(QuicStreamProxy* stream_proxy) override; bool IsClosed() const { return state_ == RTCQuicTransportState::kClosed; } bool RaiseExceptionIfClosed(ExceptionState& exception_state) const;
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.idl b/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.idl index 6118b67..ab25d01 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.idl +++ b/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.idl
@@ -28,8 +28,8 @@ sequence<ArrayBuffer> getRemoteCertificates(); [RaisesException] void start(RTCQuicParameters remoteParameters); void stop(); - [RaisesException, RuntimeEnabled=RTCQuicStream] RTCQuicStream createStream(); + [RaisesException] RTCQuicStream createStream(); attribute EventHandler onstatechange; attribute EventHandler onerror; - // TODO(crbug.com/868068): Implement onstream. + attribute EventHandler onquicstream; };
diff --git a/third_party/blink/renderer/modules/shapedetection/detected_barcode.idl b/third_party/blink/renderer/modules/shapedetection/detected_barcode.idl index 6878cf7..7df4129 100644 --- a/third_party/blink/renderer/modules/shapedetection/detected_barcode.idl +++ b/third_party/blink/renderer/modules/shapedetection/detected_barcode.idl
@@ -6,6 +6,7 @@ [ Constructor, + Serializable, OriginTrialEnabled=ShapeDetection ] interface DetectedBarcode { // TODO(mcasas): Implement missing fields. https://crbug.com/646083
diff --git a/third_party/blink/renderer/modules/shapedetection/detected_face.idl b/third_party/blink/renderer/modules/shapedetection/detected_face.idl index e45b7c2..f367b6a 100644 --- a/third_party/blink/renderer/modules/shapedetection/detected_face.idl +++ b/third_party/blink/renderer/modules/shapedetection/detected_face.idl
@@ -6,6 +6,7 @@ [ Constructor, + Serializable, OriginTrialEnabled=ShapeDetection ] interface DetectedFace { // TODO(xianglu): Implement any other fields. https://crbug.com/646083
diff --git a/third_party/blink/renderer/modules/shapedetection/detected_text.idl b/third_party/blink/renderer/modules/shapedetection/detected_text.idl index 656b604a..7afa4c66 100644 --- a/third_party/blink/renderer/modules/shapedetection/detected_text.idl +++ b/third_party/blink/renderer/modules/shapedetection/detected_text.idl
@@ -6,6 +6,7 @@ [ Constructor, + Serializable, OriginTrialEnabled=ShapeDetection ] interface DetectedText { [SameObject] readonly attribute DOMString rawValue;
diff --git a/third_party/blink/renderer/platform/exported/web_runtime_features.cc b/third_party/blink/renderer/platform/exported/web_runtime_features.cc index 0412601..26b9b86 100644 --- a/third_party/blink/renderer/platform/exported/web_runtime_features.cc +++ b/third_party/blink/renderer/platform/exported/web_runtime_features.cc
@@ -216,6 +216,10 @@ RuntimeEnabledFeatures::SetNoHoverAfterLayoutChangeEnabled(enable); } +void WebRuntimeFeatures::EnableNoHoverDuringScroll(bool enable) { + RuntimeEnabledFeatures::SetNoHoverDuringScrollEnabled(enable); +} + void WebRuntimeFeatures::EnableNotificationConstructor(bool enable) { RuntimeEnabledFeatures::SetNotificationConstructorEnabled(enable); }
diff --git a/third_party/blink/renderer/platform/graphics/bitmap_image_metrics.cc b/third_party/blink/renderer/platform/graphics/bitmap_image_metrics.cc index 96c15bc..3158dc5 100644 --- a/third_party/blink/renderer/platform/graphics/bitmap_image_metrics.cc +++ b/third_party/blink/renderer/platform/graphics/bitmap_image_metrics.cc
@@ -78,8 +78,8 @@ DEFINE_THREAD_SAFE_STATIC_LOCAL( EnumerationHistogram, gamut_named_histogram, ("Blink.ColorGamut.Source", static_cast<int>(ColorSpaceGamut::kEnd))); - gamut_named_histogram.Count( - static_cast<int>(ColorSpaceUtilities::GetColorSpaceGamut(color_profile))); + gamut_named_histogram.Count(static_cast<int>( + color_space_utilities::GetColorSpaceGamut(color_profile))); } void BitmapImageMetrics::CountJpegArea(const IntSize& size) {
diff --git a/third_party/blink/renderer/platform/graphics/color_space_gamut.cc b/third_party/blink/renderer/platform/graphics/color_space_gamut.cc index 736049dc..1ca39ae 100644 --- a/third_party/blink/renderer/platform/graphics/color_space_gamut.cc +++ b/third_party/blink/renderer/platform/graphics/color_space_gamut.cc
@@ -9,7 +9,7 @@ namespace blink { -namespace ColorSpaceUtilities { +namespace color_space_utilities { ColorSpaceGamut GetColorSpaceGamut(const WebScreenInfo& screen_info) { const gfx::ColorSpace& color_space = screen_info.color_space; @@ -19,7 +19,7 @@ // wide gamut for HDR profiles). skcms_ICCProfile color_profile; color_space.GetRasterColorSpace().ToSkColorSpace()->toProfile(&color_profile); - return ColorSpaceUtilities::GetColorSpaceGamut(&color_profile); + return color_space_utilities::GetColorSpaceGamut(&color_profile); } ColorSpaceGamut GetColorSpaceGamut(const skcms_ICCProfile* color_profile) { @@ -62,6 +62,6 @@ return ColorSpaceGamut::kUltraWide; } -} // namespace ColorSpaceUtilities +} // namespace color_space_utilities } // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/color_space_gamut.h b/third_party/blink/renderer/platform/graphics/color_space_gamut.h index 20502a1a..fccb1e1 100644 --- a/third_party/blink/renderer/platform/graphics/color_space_gamut.h +++ b/third_party/blink/renderer/platform/graphics/color_space_gamut.h
@@ -29,12 +29,12 @@ kEnd }; -namespace ColorSpaceUtilities { +namespace color_space_utilities { PLATFORM_EXPORT ColorSpaceGamut GetColorSpaceGamut(const WebScreenInfo&); ColorSpaceGamut GetColorSpaceGamut(const skcms_ICCProfile*); -} // namespace ColorSpaceUtilities +} // namespace color_space_utilities } // namespace blink
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index 9092649..5e51f106 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -818,6 +818,10 @@ settable_from_internals: true, }, { + name: "NoHoverDuringScroll", + settable_from_internals: true, + }, + { name: "NoIdleEncodingForLayoutTests", status: "test", }, @@ -1072,11 +1076,6 @@ origin_trial_feature_name: "RtcPeerConnectionId", status: "experimental", }, - // Enables the use of the RTCQuicStream object. - { - name: "RTCQuicStream", - status: "test", - }, // Enables the use of the RTCQuicTransport object. { name: "RTCQuicTransport",
diff --git a/third_party/blink/tools/audit_non_blink_usage.py b/third_party/blink/tools/audit_non_blink_usage.py index 59c7a0dd..b870be5 100755 --- a/third_party/blink/tools/audit_non_blink_usage.py +++ b/third_party/blink/tools/audit_non_blink_usage.py
@@ -47,6 +47,7 @@ 'base::SequencedTaskRunner', 'base::SingleThreadTaskRunner', 'base::ScopedFD', + 'base::SupportsWeakPtr', 'base::SysInfo', 'base::ThreadChecker', 'base::Time', @@ -290,6 +291,12 @@ ], }, { + 'paths': ['third_party/blink/renderer/core/css/media_values.cc'], + 'allowed': [ + 'color_space_utilities::GetColorSpaceGamut', + ], + }, + { 'paths': ['third_party/blink/renderer/core/fetch/data_consumer_handle_test_util.cc'], 'allowed': [ # The existing code already contains gin::IsolateHolder.
diff --git a/third_party/crashpad/README.chromium b/third_party/crashpad/README.chromium index 141f86b..80b861d 100644 --- a/third_party/crashpad/README.chromium +++ b/third_party/crashpad/README.chromium
@@ -2,7 +2,7 @@ Short Name: crashpad URL: https://crashpad.chromium.org/ Version: unknown -Revision: 688dcfa22ee906f83d49b905b69c7c53347c92d9 +Revision: 91781418bc4eb79e357687094811bab6430b10b2 License: Apache 2.0 License File: crashpad/LICENSE Security Critical: yes
diff --git a/third_party/crashpad/crashpad/CONTRIBUTORS b/third_party/crashpad/crashpad/CONTRIBUTORS index 2080cc45..8724b7f 100644 --- a/third_party/crashpad/crashpad/CONTRIBUTORS +++ b/third_party/crashpad/crashpad/CONTRIBUTORS
@@ -12,3 +12,4 @@ Mark Mentovai <mark@chromium.org> Robert Sesek <rsesek@chromium.org> Scott Graham <scottmg@chromium.org> +Joshua Peraza <jperaza@chromium.org>
diff --git a/third_party/crashpad/crashpad/client/crashpad_client.h b/third_party/crashpad/crashpad/client/crashpad_client.h index 154d9ac..ea0e7b6 100644 --- a/third_party/crashpad/crashpad/client/crashpad_client.h +++ b/third_party/crashpad/crashpad/client/crashpad_client.h
@@ -266,6 +266,12 @@ //! CaptureContext() or similar. static void DumpWithoutCrash(NativeCPUContext* context); + //! \brief Disables any installed crash handler, including any + //! FirstChanceHandler and crashes the current process. + //! + //! \param[in] message A message to be logged before crashing. + static void CrashWithoutDump(const std::string& message); + //! \brief The type for custom handlers installed by clients. using FirstChanceHandler = bool (*)(int, siginfo_t*, ucontext_t*);
diff --git a/third_party/crashpad/crashpad/client/crashpad_client_linux.cc b/third_party/crashpad/crashpad/client/crashpad_client_linux.cc index 1e9d651..e8e7f46 100644 --- a/third_party/crashpad/crashpad/client/crashpad_client_linux.cc +++ b/third_party/crashpad/crashpad/client/crashpad_client_linux.cc
@@ -78,28 +78,8 @@ #endif // OS_ANDROID -class SignalHandler { - public: - virtual void HandleCrashFatal(int signo, - siginfo_t* siginfo, - void* context) = 0; - virtual bool HandleCrashNonFatal(int signo, - siginfo_t* siginfo, - void* context) = 0; - - void SetFirstChanceHandler(CrashpadClient::FirstChanceHandler handler) { - first_chance_handler_ = handler; - } - - protected: - SignalHandler() = default; - ~SignalHandler() = default; - - CrashpadClient::FirstChanceHandler first_chance_handler_ = nullptr; -}; - // Launches a single use handler to snapshot this process. -class LaunchAtCrashHandler : public SignalHandler { +class LaunchAtCrashHandler { public: static LaunchAtCrashHandler* Get() { static LaunchAtCrashHandler* instance = new LaunchAtCrashHandler(); @@ -123,9 +103,7 @@ return Signals::InstallCrashHandlers(HandleCrash, 0, nullptr); } - bool HandleCrashNonFatal(int signo, - siginfo_t* siginfo, - void* context) override { + bool HandleCrashNonFatal(int signo, siginfo_t* siginfo, void* context) { if (first_chance_handler_ && first_chance_handler_( signo, siginfo, static_cast<ucontext_t*>(context))) { @@ -162,13 +140,19 @@ return false; } - void HandleCrashFatal(int signo, siginfo_t* siginfo, void* context) override { - if (HandleCrashNonFatal(signo, siginfo, context)) { + void HandleCrashFatal(int signo, siginfo_t* siginfo, void* context) { + if (enabled_ && HandleCrashNonFatal(signo, siginfo, context)) { return; } Signals::RestoreHandlerAndReraiseSignalOnReturn(siginfo, nullptr); } + void SetFirstChanceHandler(CrashpadClient::FirstChanceHandler handler) { + first_chance_handler_ = handler; + } + + static void Disable() { enabled_ = false; } + private: LaunchAtCrashHandler() = default; @@ -183,16 +167,20 @@ std::vector<const char*> argv_; std::vector<std::string> envp_strings_; std::vector<const char*> envp_; - bool set_envp_ = false; ExceptionInformation exception_information_; + CrashpadClient::FirstChanceHandler first_chance_handler_ = nullptr; + bool set_envp_ = false; + + static thread_local bool enabled_; DISALLOW_COPY_AND_ASSIGN(LaunchAtCrashHandler); }; +thread_local bool LaunchAtCrashHandler::enabled_ = true; // A pointer to the currently installed crash signal handler. This allows // the static method CrashpadClient::DumpWithoutCrashing to simulate a crash // using the currently configured crash handling strategy. -static SignalHandler* g_crash_handler; +static LaunchAtCrashHandler* g_crash_handler; } // namespace @@ -319,6 +307,12 @@ } // static +void CrashpadClient::CrashWithoutDump(const std::string& message) { + LaunchAtCrashHandler::Disable(); + LOG(FATAL) << message; +} + +// static void CrashpadClient::SetFirstChanceExceptionHandler( FirstChanceHandler handler) { DCHECK(g_crash_handler);
diff --git a/third_party/crashpad/crashpad/minidump/BUILD.gn b/third_party/crashpad/crashpad/minidump/BUILD.gn index 88a1081..86966d82 100644 --- a/third_party/crashpad/crashpad/minidump/BUILD.gn +++ b/third_party/crashpad/crashpad/minidump/BUILD.gn
@@ -154,6 +154,10 @@ "minidump_writable_test.cc", ] + configs += [ + "../build:crashpad_is_in_fuchsia", + ] + deps = [ ":test_support", "../snapshot:test_support",
diff --git a/third_party/crashpad/crashpad/minidump/minidump_string_writer_test.cc b/third_party/crashpad/crashpad/minidump/minidump_string_writer_test.cc index 382baaf..1d65485 100644 --- a/third_party/crashpad/crashpad/minidump/minidump_string_writer_test.cc +++ b/third_party/crashpad/crashpad/minidump/minidump_string_writer_test.cc
@@ -100,6 +100,12 @@ } } +// Related tracking issues: +// https://fuchsia.atlassian.net/browse/DX-487 +// https://bugs.chromium.org/p/chromium/issues/detail?id=872892 +// https://bugs.chromium.org/p/chromium/issues/detail?id=889582 +// TODO: Re-enable test once LUCI supports invalid UTF8 characters in test logs. +#if !defined(CRASHPAD_IS_IN_FUCHSIA) TEST(MinidumpStringWriter, ConvertInvalidUTF8ToUTF16) { StringFile string_file; @@ -139,6 +145,7 @@ EXPECT_NE(output_string.find(0xfffd), base::string16::npos); } } +#endif // !defined(CRASHPAD_IS_IN_FUCHSIA) TEST(MinidumpStringWriter, MinidumpUTF8StringWriter) { StringFile string_file;
diff --git a/third_party/crashpad/crashpad/util/BUILD.gn b/third_party/crashpad/crashpad/util/BUILD.gn index 564587c5..3ad253e0 100644 --- a/third_party/crashpad/crashpad/util/BUILD.gn +++ b/third_party/crashpad/crashpad/util/BUILD.gn
@@ -642,11 +642,9 @@ "win/session_end_watcher_test.cc", ] - if (crashpad_is_in_chromium) { - if (is_asan && is_component_build) { - # TODO(crbug.com/856174): Re-enable these once Windows ASan is fixed. - sources -= [ "stdlib/string_number_conversion_test.cc" ] - } + if (crashpad_is_in_chromium && is_asan && is_component_build) { + # TODO(crbug.com/856174): Re-enable these once Windows ASan is fixed. + sources -= [ "stdlib/string_number_conversion_test.cc" ] } }
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index b7fb90d..2197e924 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -29694,6 +29694,7 @@ <int value="178337215" label="enable-md-history"/> <int value="180074362" label="memory-pressure-thresholds"/> <int value="185991204" label="enable-webrtc-srtp-encrypted-headers"/> + <int value="188610022" label="NewMessageListView:enabled"/> <int value="189728101" label="FasterLocationReload:disabled"/> <int value="191737931" label="enable-mark-http-as"/> <int value="194573877" label="MacViewsNativeDialogs:disabled"/> @@ -30244,6 +30245,7 @@ <int value="1269940659" label="EnumerateAudioDevices:enabled"/> <int value="1269952439" label="AndroidAIAFetching:disabled"/> <int value="1272699563" label="enable-hosted-mode"/> + <int value="1272923911" label="NewMessageListView:disabled"/> <int value="1275507565" label="OfflinePagesRenovations:enabled"/> <int value="1276209777" label="ntp-switch-to-existing-tab"/> <int value="1277386636" label="QueryInOmnibox:disabled"/> @@ -40565,6 +40567,11 @@ label="Timestamp shown indicating the page was just updated on reload"/> </enum> +<enum name="PreviewsLitePageInfoBarAction"> + <int value="0" label="Infobar shown"/> + <int value="1" label="Infobar dismissed by user"/> +</enum> + <enum name="PreviewsOptimizationFilterStatus"> <int value="0" label="Found a server blacklist configuration"> Found configuration data for a server blacklist. @@ -40608,6 +40615,7 @@ <int value="1" label="HTTP POST"/> <int value="2" label="Subframe navigation"/> <int value="3" label="Server Unavailable"/> + <int value="4" label="Infobar hasn't been seen by the user and needs to be"/> </enum> <enum name="PreviewsServerLitePageServerResponse">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index bda6b0d..1021101 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -34677,10 +34677,23 @@ </histogram> <histogram name="GPU.DirectComposition.OverlayFormatUsed" enum="OverlayFormat"> + <obsolete> + Deprecated 10/2018. Replaced by GPU.DirectComposition.OverlayFormatUsed2. + </obsolete> <owner>sunnyps@chromium.org</owner> <summary>Which overlay format was chosen for YUV overlays.</summary> </histogram> +<histogram name="GPU.DirectComposition.OverlayFormatUsed2" enum="OverlayFormat" + expires_after="M75"> + <owner>sunnyps@chromium.org</owner> + <owner>zmo@chromium.org</owner> + <summary> + Which overlay format was chosen for YUV overlays. Recorded once per GPU + process launch only if hardware overlays are supported. + </summary> +</histogram> + <histogram name="GPU.DirectComposition.OverlaysSupported" enum="BooleanOverlaySupported"> <owner>jbauman@chromium.org</owner> @@ -34740,11 +34753,35 @@ <summary>Whether or not swap buffers succeeded.</summary> </histogram> +<histogram base="true" name="GPU.DirectComposition.SwapChainCreationResult" + enum="BooleanSuccess" expires_after="M75"> +<!-- Name completed by histogram_suffixes name="GPU.DirectComposition.OverlayFormat" --> + + <owner>sunnyps@chromium.org</owner> + <owner>zmo@chromium.org</owner> + <summary> + Whether creating swap chain for overlay format succeeded. Recorded once per + swap chain creation. + </summary> +</histogram> + <histogram name="GPU.DirectComposition.SwapchainFormat" enum="SwapchainFormat"> + <obsolete> + Deprecated 10/2018. Replaced by GPU.DirectComposition.SwapChainFormatUsed. + </obsolete> <owner>jbauman@chromium.org</owner> <summary>What type of swapchain was actually created for an overlay.</summary> </histogram> +<histogram name="GPU.DirectComposition.SwapChainFormat2" enum="OverlayFormat" + expires_after="M75"> + <owner>sunnyps@chromium.org</owner> + <owner>zmo@chromium.org</owner> + <summary> + What format was used for each overlay swap chain on each swap buffers. + </summary> +</histogram> + <histogram name="GPU.DisplayCompositorLifetimeEvents" enum="GPUProcessLifetimeEvent"> <obsolete> @@ -81226,6 +81263,14 @@ </summary> </histogram> +<histogram name="Previews.LitePageNotificationInfoBar" + enum="PreviewsLitePageInfoBarAction"> + <owner>robertogden@chromium.org</owner> + <summary> + User interactions with the HTTPS Server Previews notification InfoBar. + </summary> +</histogram> + <histogram base="true" name="Previews.OptimizationFilterStatus" enum="PreviewsOptimizationFilterStatus"> <owner>dougarnett@chromium.org</owner> @@ -85451,6 +85496,9 @@ <histogram name="RenderFrameHostImpl.ReceivedPostMessageFromNonDescendant" enum="BooleanReceived" expires_after="2018-10-30"> + <obsolete> + Removed Oct 2018. + </obsolete> <owner>alexmos@chromium.org</owner> <owner>boliu@chromium.org</owner> <summary> @@ -97707,6 +97755,26 @@ </summary> </histogram> +<histogram name="SignedExchange.Time.CertificateFetch.Failure" units="ms" + expires_after="2019-10-01"> + <owner>kinuko@chromium.org</owner> + <owner>kouhei@chromium.org</owner> + <summary> + The amount of time elapsed to fetch certificate chain from certUrl, for + which the fetch has failed. + </summary> +</histogram> + +<histogram name="SignedExchange.Time.CertificateFetch.Success" units="ms" + expires_after="2019-10-01"> + <owner>kinuko@chromium.org</owner> + <owner>kouhei@chromium.org</owner> + <summary> + The amount of time elapsed to fetch certificate chain from certUrl, for + which the fetch has succeeded. + </summary> +</histogram> + <histogram name="SignedExchange.Time.SignatureVerify" units="ms" expires_after="2019-10-01"> <owner>kinuko@chromium.org</owner>
diff --git a/tools/perf/page_sets/rendering/tough_compositor_cases.py b/tools/perf/page_sets/rendering/tough_compositor_cases.py index 999c7ea4..c574760 100644 --- a/tools/perf/page_sets/rendering/tough_compositor_cases.py +++ b/tools/perf/page_sets/rendering/tough_compositor_cases.py
@@ -224,7 +224,7 @@ selector='#container', speed_in_pixels_per_second=1000) -# Why: Infinite root scroller with 1 layer baseline""" +# Why: Infinite non-root scroller with 1 layer baseline""" class InfiniteScrollElementNLayers0(InfiniteScrollElementNLayersPage): BASE_NAME = 'infinite_scroll_element_n_layers_0' SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY @@ -232,7 +232,7 @@ 'infinite_scroll_element_n_layers.html?layer_count=1') -# Why: Infinite root scroller with 50%-ile layer count""" +# Why: Infinite non-root scroller with 50%-ile layer count""" class InfiniteScrollElementNLayers50(InfiniteScrollElementNLayersPage): BASE_NAME = 'infinite_scroll_element_n_layers_50' SUPPORTED_PLATFORMS = platforms.NO_PLATFORMS @@ -240,7 +240,7 @@ 'infinite_scroll_element_n_layers.html?layer_count=31') -# Why: Infinite root scroller with 75%-ile layer count""" +# Why: Infinite non-root scroller with 75%-ile layer count""" class InfiniteScrollElementNLayers75(InfiniteScrollElementNLayersPage): BASE_NAME = 'infinite_scroll_element_n_layers_75' SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY @@ -248,7 +248,7 @@ 'infinite_scroll_element_n_layers.html?layer_count=53') -# Why: Infinite root scroller with 95%-ile layer count""" +# Why: Infinite non-root scroller with 95%-ile layer count""" class InfiniteScrollElementNLayers95(InfiniteScrollElementNLayersPage): BASE_NAME = 'infinite_scroll_element_n_layers_95' SUPPORTED_PLATFORMS = platforms.NO_PLATFORMS @@ -256,7 +256,7 @@ 'infinite_scroll_element_n_layers.html?layer_count=144') -# Why: Infinite root scroller with 99%-ile layer count""" +# Why: Infinite non-root scroller with 99%-ile layer count""" class InfiniteScrollElementNLayers99(InfiniteScrollElementNLayersPage): BASE_NAME = 'infinite_scroll_element_n_layers_99' SUPPORTED_PLATFORMS = platforms.ALL_PLATFORMS @@ -272,7 +272,7 @@ speed_in_pixels_per_second=1000) -# Why: Infinite non-root scroller with 1 layer baseline """ +# Why: Infinite root scroller with 1 layer baseline """ class InfiniteScrollRootNLayers0(InfiniteScrollRootNLayersPage): BASE_NAME = 'infinite_scroll_root_n_layers_0' SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY @@ -280,7 +280,7 @@ 'infinite_scroll_root_n_layers.html?layer_count=1') -# Why: Infinite non-root scroller with 50%-ile layer count""" +# Why: Infinite root scroller with 50%-ile layer count""" class InfiniteScrollRootNLayers50(InfiniteScrollRootNLayersPage): BASE_NAME = 'infinite_scroll_root_n_layers_50' SUPPORTED_PLATFORMS = platforms.NO_PLATFORMS @@ -288,7 +288,7 @@ 'infinite_scroll_root_n_layers.html?layer_count=31') -# Why: Infinite non-root scroller with 75%-ile layer count""" +# Why: Infinite root scroller with 75%-ile layer count""" class InfiniteScrollRootNLayers75(InfiniteScrollRootNLayersPage): BASE_NAME = 'infinite_scroll_root_n_layers_75' SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY @@ -296,7 +296,7 @@ 'infinite_scroll_root_n_layers.html?layer_count=53') -# Why: Infinite non-root scroller with 95%-ile layer count""" +# Why: Infinite root scroller with 95%-ile layer count""" class InfiniteScrollRootNLayers95(InfiniteScrollRootNLayersPage): BASE_NAME = 'infinite_scroll_root_n_layers_95' SUPPORTED_PLATFORMS = platforms.NO_PLATFORMS @@ -304,9 +304,49 @@ 'infinite_scroll_root_n_layers.html?layer_count=144') -# Why: Infinite non-root scroller with 99%-ile layer count""" +# Why: Infinite root scroller with 99%-ile layer count""" class InfiniteScrollRootNLayers99(InfiniteScrollRootNLayersPage): BASE_NAME = 'infinite_scroll_root_n_layers_99' SUPPORTED_PLATFORMS = platforms.ALL_PLATFORMS URL = ('file://../../../../chrome/test/data/perf/tough_compositor_cases/' 'infinite_scroll_root_n_layers.html?layer_count=306') + + +# Why: Infinite root scroller + fixed element, with 1 layer baseline """ +class InfiniteScrollRootFixedNLayers0(InfiniteScrollRootNLayersPage): + BASE_NAME = 'infinite_scroll_root_fixed_n_layers_0' + SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY + URL = ('file://../../../../chrome/test/data/perf/tough_compositor_cases/' + 'infinite_scroll_root_fixed_n_layers.html?layer_count=1') + + +# Why: Infinite root scroller + fixed element, with 50%-ile layer count""" +class InfiniteScrollRootFixedNLayers50(InfiniteScrollRootNLayersPage): + BASE_NAME = 'infinite_scroll_root_fixed_n_layers_50' + SUPPORTED_PLATFORMS = platforms.NO_PLATFORMS + URL = ('file://../../../../chrome/test/data/perf/tough_compositor_cases/' + 'infinite_scroll_root_fixed_n_layers.html?layer_count=31') + + +# Why: Infinite root scroller + fixed element, with 75%-ile layer count""" +class InfiniteScrollRootFixedNLayers75(InfiniteScrollRootNLayersPage): + BASE_NAME = 'infinite_scroll_root_fixed_n_layers_75' + SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY + URL = ('file://../../../../chrome/test/data/perf/tough_compositor_cases/' + 'infinite_scroll_root_fixed_n_layers.html?layer_count=53') + + +# Why: Infinite root scroller + fixed element, with 95%-ile layer count""" +class InfiniteScrollRootFixedNLayers95(InfiniteScrollRootNLayersPage): + BASE_NAME = 'infinite_scroll_root_fixed_n_layers_95' + SUPPORTED_PLATFORMS = platforms.NO_PLATFORMS + URL = ('file://../../../../chrome/test/data/perf/tough_compositor_cases/' + 'infinite_scroll_root_fixed_n_layers.html?layer_count=144') + + +# Why: Infinite root scroller + fixed element, with 99%-ile layer count""" +class InfiniteScrollRootFixedNLayers99(InfiniteScrollRootNLayersPage): + BASE_NAME = 'infinite_scroll_root_fixed_n_layers_99' + SUPPORTED_PLATFORMS = platforms.ALL_PLATFORMS + URL = ('file://../../../../chrome/test/data/perf/tough_compositor_cases/' + 'infinite_scroll_root_fixed_n_layers.html?layer_count=306')
diff --git a/ui/base/dragdrop/os_exchange_data_provider_mac.mm b/ui/base/dragdrop/os_exchange_data_provider_mac.mm index 334bc9c..ff55487 100644 --- a/ui/base/dragdrop/os_exchange_data_provider_mac.mm +++ b/ui/base/dragdrop/os_exchange_data_provider_mac.mm
@@ -15,6 +15,7 @@ #import "ui/base/clipboard/clipboard_util_mac.h" #include "ui/base/clipboard/custom_data_helper.h" #import "ui/base/dragdrop/cocoa_dnd_util.h" +#include "ui/base/dragdrop/file_info.h" #include "url/gurl.h" namespace ui { @@ -64,7 +65,16 @@ void OSExchangeDataProviderMac::SetFilenames( const std::vector<FileInfo>& filenames) { - NOTIMPLEMENTED(); + if (filenames.empty()) + return; + + NSMutableArray* paths = [NSMutableArray arrayWithCapacity:filenames.size()]; + + for (const auto& filename : filenames) { + NSString* path = base::SysUTF8ToNSString(filename.path.value()); + [paths addObject:path]; + } + [pasteboard_->get() setPropertyList:paths forType:NSFilenamesPboardType]; } void OSExchangeDataProviderMac::SetPickledData( @@ -137,8 +147,16 @@ bool OSExchangeDataProviderMac::GetFilenames( std::vector<FileInfo>* filenames) const { - NOTIMPLEMENTED(); - return false; + NSArray* paths = + [pasteboard_->get() propertyListForType:NSFilenamesPboardType]; + if ([paths count] == 0) + return false; + + for (NSString* path in paths) + filenames->push_back( + {base::FilePath(base::SysNSStringToUTF8(path)), base::FilePath()}); + + return true; } bool OSExchangeDataProviderMac::GetPickledData(
diff --git a/ui/base/dragdrop/os_exchange_data_unittest.cc b/ui/base/dragdrop/os_exchange_data_unittest.cc index 62d98d1..9291ca57 100644 --- a/ui/base/dragdrop/os_exchange_data_unittest.cc +++ b/ui/base/dragdrop/os_exchange_data_unittest.cc
@@ -12,6 +12,7 @@ #include "net/base/filename_util.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" +#include "ui/base/dragdrop/file_info.h" #include "ui/base/dragdrop/os_exchange_data.h" #include "ui/events/platform/platform_event_source.h" #include "url/gurl.h" @@ -164,6 +165,30 @@ EXPECT_EQ(2, value); } +TEST_F(OSExchangeDataTest, TestFilenames) { +#if defined(OS_WIN) + const std::vector<FileInfo> kTestFilenames = { + {base::FilePath(FILE_PATH_LITERAL("C:\\tmp\\test_file1")), + base::FilePath()}, + {base::FilePath(FILE_PATH_LITERAL("C:\\tmp\\test_file2")), + base::FilePath()}, + }; +#else + const std::vector<FileInfo> kTestFilenames = { + {base::FilePath(FILE_PATH_LITERAL("/tmp/test_file1")), base::FilePath()}, + {base::FilePath(FILE_PATH_LITERAL("/tmp/test_file2")), base::FilePath()}, + }; +#endif + OSExchangeData data; + data.SetFilenames(kTestFilenames); + + OSExchangeData copy(data.provider().Clone()); + std::vector<FileInfo> dropped_filenames; + + EXPECT_TRUE(copy.GetFilenames(&dropped_filenames)); + EXPECT_EQ(kTestFilenames, dropped_filenames); +} + #if defined(USE_AURA) TEST_F(OSExchangeDataTest, TestHTML) { OSExchangeData data;
diff --git a/ui/base/dragdrop/os_exchange_data_win_unittest.cc b/ui/base/dragdrop/os_exchange_data_win_unittest.cc index 3d6a92fd..09bf9b0d 100644 --- a/ui/base/dragdrop/os_exchange_data_win_unittest.cc +++ b/ui/base/dragdrop/os_exchange_data_win_unittest.cc
@@ -304,23 +304,6 @@ EXPECT_EQ(file_contents, read_contents); } -TEST(OSExchangeDataWinTest, Filenames) { - OSExchangeData data; - const std::vector<FileInfo> kTestFilenames = { - {base::FilePath(FILE_PATH_LITERAL("C:\\tmp\\test_file1")), - base::FilePath()}, - {base::FilePath(FILE_PATH_LITERAL("C:\\tmp\\test_file2")), - base::FilePath()}, - }; - data.SetFilenames(kTestFilenames); - - OSExchangeData copy(data.provider().Clone()); - std::vector<FileInfo> dropped_filenames; - - EXPECT_TRUE(copy.GetFilenames(&dropped_filenames)); - EXPECT_EQ(kTestFilenames, dropped_filenames); -} - TEST(OSExchangeDataWinTest, CFHtml) { OSExchangeData data; GURL url("http://www.google.com/");
diff --git a/ui/events/BUILD.gn b/ui/events/BUILD.gn index 65ded87..ee659a97 100644 --- a/ui/events/BUILD.gn +++ b/ui/events/BUILD.gn
@@ -155,55 +155,59 @@ } jumbo_component("events") { - sources = [ + public = [ "cocoa/cocoa_event_utils.h", - "cocoa/cocoa_event_utils.mm", - "cocoa/events_mac.mm", - "event.cc", "event.h", - "event_dispatcher.cc", "event_dispatcher.h", - "event_handler.cc", "event_handler.h", - "event_modifiers.cc", "event_modifiers.h", - "event_processor.cc", "event_processor.h", - "event_rewriter.cc", "event_rewriter.h", "event_sink.h", - "event_source.cc", "event_source.h", - "event_target.cc", "event_target.h", "event_target_iterator.h", "event_targeter.h", - "event_utils.cc", "event_utils.h", "events_export.h", - "events_stub.cc", - "gestures/gesture_recognizer_impl_mac.cc", "gestures/gesture_recognizer_impl_mac.h", - "gestures/gesture_types.cc", "gestures/gesture_types.h", "keyboard_hook.h", + "null_event_targeter.h", + "scoped_target_handler.h", + "system_input_injector.h", + "win/events_win_utils.h", + "win/system_event_state_lookup.h", + ] + + sources = [ + "cocoa/cocoa_event_utils.mm", + "cocoa/events_mac.mm", + "event.cc", + "event_dispatcher.cc", + "event_handler.cc", + "event_modifiers.cc", + "event_processor.cc", + "event_rewriter.cc", + "event_source.cc", + "event_target.cc", + "event_utils.cc", + "events_stub.cc", + "gestures/gesture_recognizer_impl_mac.cc", + "gestures/gesture_types.cc", "keyboard_hook_base.cc", "keyboard_hook_base.h", "keycodes/platform_key_map_win.cc", "keycodes/platform_key_map_win.h", "mac/keyboard_hook_mac.mm", "null_event_targeter.cc", - "null_event_targeter.h", "scoped_target_handler.cc", - "scoped_target_handler.h", "system_input_injector.cc", - "system_input_injector.h", "win/events_win.cc", "win/events_win_utils.cc", - "win/events_win_utils.h", "win/keyboard_hook_win.cc", + "win/keyboard_hook_win.h", "win/system_event_state_lookup.cc", - "win/system_event_state_lookup.h", ] defines = [ "EVENTS_IMPLEMENTATION" ] @@ -222,6 +226,12 @@ "//ui/gfx/geometry", ] + # Expose the internals of this target to other packages in this BUILD file + # so the unit tests can access the private header files. + # Note: Only 'events_unittests' needs access in this file, however it uses a + # template which generates different target names on different platforms. + friend = [ ":*" ] + if (use_x11) { sources += [ "x/events_x.cc", @@ -249,24 +259,26 @@ } if (use_ozone) { + public += [ "ozone/events_ozone.h" ] sources += [ "ozone/events_ozone.cc", - "ozone/events_ozone.h", "ozone/keyboard_hook_ozone.cc", ] deps += [ "//ui/events/ozone:events_ozone_layout" ] } if (use_aura) { - sources += [ - "gestures/gesture_provider_aura.cc", + public += [ "gestures/gesture_provider_aura.h", "gestures/gesture_recognizer.h", - "gestures/gesture_recognizer_impl.cc", "gestures/gesture_recognizer_impl.h", - "gestures/motion_event_aura.cc", "gestures/motion_event_aura.h", ] + sources += [ + "gestures/gesture_provider_aura.cc", + "gestures/gesture_recognizer_impl.cc", + "gestures/motion_event_aura.cc", + ] } if (is_win || is_mac || use_x11 || use_ozone) { @@ -274,21 +286,23 @@ } if (is_android) { - sources += [ - "android/drag_event_android.cc", + public += [ "android/drag_event_android.h", - "android/event_handler_android.cc", "android/event_handler_android.h", - "android/gesture_event_android.cc", "android/gesture_event_android.h", "android/gesture_event_type.h", - "android/key_event_android.cc", "android/key_event_android.h", - "android/key_event_utils.cc", "android/key_event_utils.h", + "android/motion_event_android.h", + ] + sources += [ + "android/drag_event_android.cc", + "android/event_handler_android.cc", + "android/gesture_event_android.cc", + "android/key_event_android.cc", + "android/key_event_utils.cc", "android/keyboard_hook_android.cc", "android/motion_event_android.cc", - "android/motion_event_android.h", ] deps += [ ":keyevent_jni_headers", @@ -301,11 +315,11 @@ } if (is_fuchsia) { - sources += [ - "fuchsia/input_event_dispatcher.cc", + public += [ "fuchsia/input_event_dispatcher.h", "fuchsia/input_event_dispatcher_delegate.h", ] + sources += [ "fuchsia/input_event_dispatcher.cc" ] public_deps += [ "//third_party/fuchsia-sdk/sdk:input" ] } } @@ -488,6 +502,7 @@ "platform/platform_event_source_unittest.cc", "scoped_target_handler_unittest.cc", "win/event_utils_win_unittest.cc", + "win/keyboard_hook_win_unittest.cc", ] deps = [
diff --git a/ui/events/blink/blink_features.cc b/ui/events/blink/blink_features.cc index 46384f2..a88686a 100644 --- a/ui/events/blink/blink_features.cc +++ b/ui/events/blink/blink_features.cc
@@ -19,4 +19,7 @@ const base::Feature kNoHoverAfterLayoutChange{ "NoHoverAfterLayoutChange", base::FEATURE_DISABLED_BY_DEFAULT}; + +const base::Feature kNoHoverDuringScroll{"NoHoverDuringScroll", + base::FEATURE_DISABLED_BY_DEFAULT}; }
diff --git a/ui/events/blink/blink_features.h b/ui/events/blink/blink_features.h index 7a82663..c7ee6ef 100644 --- a/ui/events/blink/blink_features.h +++ b/ui/events/blink/blink_features.h
@@ -20,8 +20,15 @@ // the native platforms. crbug.com/450631 extern const base::Feature kSendMouseLeaveEvents; -// Do not update hover after the layout is changed. +// When enabled, this feature prevents Blink from changing the hover state and +// dispatching mouse enter/exit events for elements under the mouse after the +// layout under the mouse cursor is changed. extern const base::Feature kNoHoverAfterLayoutChange; + +// When enabled, this feature prevents Blink from changing the hover state and +// dispatching mouse enter/exit events for elements under the mouse as the page +// is scrolled. +extern const base::Feature kNoHoverDuringScroll; } #endif // UI_EVENTS_BLINK_BLINK_FEATURES_H_
diff --git a/ui/events/keyboard_hook.h b/ui/events/keyboard_hook.h index accb805..36e9b88 100644 --- a/ui/events/keyboard_hook.h +++ b/ui/events/keyboard_hook.h
@@ -38,7 +38,7 @@ KeyEventCallback callback); // True if |dom_code| is reserved for an active KeyboardLock request. - virtual bool IsKeyLocked(DomCode dom_code) = 0; + virtual bool IsKeyLocked(DomCode dom_code) const = 0; }; } // namespace ui
diff --git a/ui/events/keyboard_hook_base.cc b/ui/events/keyboard_hook_base.cc index 6f971814..56381738 100644 --- a/ui/events/keyboard_hook_base.cc +++ b/ui/events/keyboard_hook_base.cc
@@ -23,7 +23,7 @@ KeyboardHookBase::~KeyboardHookBase() = default; -bool KeyboardHookBase::IsKeyLocked(DomCode dom_code) { +bool KeyboardHookBase::IsKeyLocked(DomCode dom_code) const { return ShouldCaptureKeyEvent(dom_code); }
diff --git a/ui/events/keyboard_hook_base.h b/ui/events/keyboard_hook_base.h index 8d18d942..81ffae2 100644 --- a/ui/events/keyboard_hook_base.h +++ b/ui/events/keyboard_hook_base.h
@@ -22,7 +22,7 @@ ~KeyboardHookBase() override; // KeyboardHook implementation. - bool IsKeyLocked(DomCode dom_code) override; + bool IsKeyLocked(DomCode dom_code) const override; protected: // Indicates whether |dom_code| should be intercepted by the keyboard hook.
diff --git a/ui/events/win/keyboard_hook_win.cc b/ui/events/win/keyboard_hook_win.cc index c5fa97e..042e2956 100644 --- a/ui/events/win/keyboard_hook_win.cc +++ b/ui/events/win/keyboard_hook_win.cc
@@ -2,12 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/events/keyboard_hook_base.h" +#include "ui/events/win/keyboard_hook_win.h" #include <utility> -#include <windows.h> - #include "base/logging.h" #include "base/macros.h" #include "base/optional.h" @@ -16,30 +14,112 @@ #include "ui/events/event_utils.h" #include "ui/events/keycodes/dom/dom_code.h" #include "ui/events/keycodes/dom/keycode_converter.h" +#include "ui/events/keycodes/keyboard_code_conversion.h" +#include "ui/events/win/events_win_utils.h" #include "ui/gfx/native_widget_types.h" namespace ui { namespace { -// These keys interfere with the return value of ::GetKeyState() as observing -// them directly in LowLevelKeyboardProc will cause their key combinations to be -// ignored. As an example, the KeyF event in an Alt + F combination will result -// in a missing alt-down flag. Since a regular application can successfully -// receive these keys without using LowLevelKeyboardProc, they can be ignored. -bool IsOSReservedKey(DWORD vk) { - return vk == VK_SHIFT || vk == VK_LSHIFT || vk == VK_RSHIFT || - vk == VK_CONTROL || vk == VK_LCONTROL || vk == VK_RCONTROL || - vk == VK_MENU || vk == VK_LMENU || vk == VK_RMENU || vk == VK_LWIN || - vk == VK_RWIN || vk == VK_CAPITAL || vk == VK_NUMLOCK || - vk == VK_SCROLL; +// The Windows KeyboardHook implementation uses a low-level hook in order to +// intercept system key combinations such as Alt + Tab. A standard hook or +// other window message filtering mechanisms will allow us to observe key events +// but we would be unable to block them or the corresponding system action. +// There are downsides to this approach as described in the following blurbs. + +// Low-level hooks are not given a repeat state for each key event. This is +// because the events are intercepted prior to the OS handling them and tracking +// their states the usual way. We solve this by tracking the last key seen and +// modifying the event manually to indicate it is a repeat. This works for +// every key except escape which is used to exit fullscreen and tear down the +// hook. The quirk is that after the hook is torn down, the first escape key +// event passed to the window will appear like an initial keydown. This is +// because it *is* an initial keydown from Windows' perspective as it was being +// intercepted before then. + +// Intercepting modifier keys (Ctrl, Shift, Win, Etc.) within a low-level +// keyboard hook will result in an incorrect modifier state reported by the OS +// for that key. This is because the hook intercepts the event before the OS +// has a chance to observe the event and update its internal state. This +// trade-off is necessary as we also want to intercept and prevent specific key +// combos from taking effect. + +// A related side-effect occurs when intercepting printable characters. Since +// the key event is intercepted before the OS handles it, no char events are +// produced. So if we intercept scan codes which should generate a printable +// character, the result is that the key up/down events are sent correctly but +// no WM_CHAR message is generated. This is unacceptable for some usages of the +// hook as the behavior is very different between locked and unlocked states. + +// This is a fair number of downsides however the ability to block system key +// combos is a hard requirement so we need to work around them. + +// The solution we have adopted is: +// - Only intercept modifiers and allow all other keys to pass through +// Note: Shift is not included as otherwise it is not applied by the OS and +// the printable characters generated by the key event will be wrong. +// - Track the repeat state ourselves +// - Update the per-thread key state for the tracked modifiers using +// SetKeyboardState(). + +// In practice this works well as intercepting the modifiers allows us to block +// system keyboard combos and all other keys generate the proper events and +// printable chars. + +// Using SetKeyboardState() allows us to tell Windows the current state for the +// modifiers we intercept. This state only works for the current thread, +// meaning that other applications / threads which check the key state for the +// modifiers will not receive an accurate value. One constraint for the +// KeyboardHook is that it is only engaged when our window is fullscreen and +// focused so we don't need to worry too much about other apps. + +// Represents a VK_LCONTROL scancode with the 0x02 flag in the high word. +// The 0x02 flag does not seem to be documented on MSDN or in the public Windows +// headers. I suspect it is related to the KF_ family of constants which skips +// from 0x0100 to 0x0800 with 0x0200 and 0x0400 undocumented (likely reserved). +constexpr DWORD kSynthesizedControlScanCodeForAltGr = 0x021D; + +// {Get|Set}KeyboardState() receives an array with 256 elements. This is +// described in MSDN but no constant exists for this value. Function reference: +// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getkeyboardstate +// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-setkeyboardstate +constexpr int kKeyboardStateArraySize = 256; + +// Used for setting and testing the bits in the KeyboardState array. +constexpr BYTE kKeyDown = 0x80; +constexpr BYTE kKeyUp = 0x00; + +bool IsAltKey(DWORD vk) { + return vk == VK_MENU || vk == VK_LMENU || vk == VK_RMENU; } -class KeyboardHookWin : public KeyboardHookBase { +bool IsControlKey(DWORD vk) { + return vk == VK_CONTROL || vk == VK_LCONTROL || vk == VK_RCONTROL; +} + +bool IsWindowsKey(DWORD vk) { + return vk == VK_LWIN || vk == VK_RWIN; +} + +bool IsModifierKey(DWORD vk) { + // We don't track the state of the shift key as we want to allow the OS to + // know about its state so it is correctly applied to printable characters. + return IsAltKey(vk) || IsControlKey(vk) || IsWindowsKey(vk); +} + +class KeyboardHookWinImpl : public KeyboardHookWin { public: - KeyboardHookWin(base::Optional<base::flat_set<DomCode>> dom_codes, - KeyEventCallback callback); - ~KeyboardHookWin() override; + KeyboardHookWinImpl(base::Optional<base::flat_set<DomCode>> dom_codes, + KeyEventCallback callback, + bool enable_hook_registration); + ~KeyboardHookWinImpl() override; + + // KeyboardHookWin implementation. + bool ProcessKeyEventMessage(WPARAM w_param, + DWORD vk, + DWORD scan_code, + DWORD time_stamp) override; bool Register(); @@ -47,30 +127,50 @@ static LRESULT CALLBACK ProcessKeyEvent(int code, WPARAM w_param, LPARAM l_param); - static KeyboardHookWin* instance_; + + void UpdateModifierState(DWORD vk, bool key_down); + + void ClearModifierStates(); + + static KeyboardHookWinImpl* instance_; THREAD_CHECKER(thread_checker_); HHOOK hook_ = nullptr; - // Tracks the last key down seen in order to determine if the current key - // event is a repeated key press. + // Tracks the last non-located key down seen in order to determine if the + // current key event should be marked as a repeated key press. DWORD last_key_down_ = 0; - DISALLOW_COPY_AND_ASSIGN(KeyboardHookWin); + // Tracks the number of AltGr key sequences seen since the start of the most + // recent AltGr key down. When the AltGr key is pressed, Windows injects a + // synthesized left control key event followed by the right alt key event. + // This sequence occurs on the initial keypress and every repeat. + int altgr_sequence_count_ = 0; + + const bool enable_hook_registration_ = true; + + DISALLOW_COPY_AND_ASSIGN(KeyboardHookWinImpl); }; // static -KeyboardHookWin* KeyboardHookWin::instance_ = nullptr; +KeyboardHookWinImpl* KeyboardHookWinImpl::instance_ = nullptr; -KeyboardHookWin::KeyboardHookWin( +KeyboardHookWinImpl::KeyboardHookWinImpl( base::Optional<base::flat_set<DomCode>> dom_codes, - KeyEventCallback callback) - : KeyboardHookBase(std::move(dom_codes), std::move(callback)) {} + KeyEventCallback callback, + bool enable_hook_registration) + : KeyboardHookWin(std::move(dom_codes), std::move(callback)), + enable_hook_registration_(enable_hook_registration) {} -KeyboardHookWin::~KeyboardHookWin() { +KeyboardHookWinImpl::~KeyboardHookWinImpl() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + ClearModifierStates(); + + if (!enable_hook_registration_) + return; + DCHECK_EQ(instance_, this); instance_ = nullptr; @@ -78,9 +178,12 @@ DPLOG(ERROR) << "UnhookWindowsHookEx failed"; } -bool KeyboardHookWin::Register() { +bool KeyboardHookWinImpl::Register() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + // If the hook was created for testing, |Register()| should not be called. + DCHECK(enable_hook_registration_); + // Only one instance of this class can be registered at a time. DCHECK(!instance_); instance_ = this; @@ -89,7 +192,7 @@ // which installed it. hook_ = SetWindowsHookEx( WH_KEYBOARD_LL, - reinterpret_cast<HOOKPROC>(&KeyboardHookWin::ProcessKeyEvent), + reinterpret_cast<HOOKPROC>(&KeyboardHookWinImpl::ProcessKeyEvent), /*hMod=*/nullptr, /*dwThreadId=*/0); DPLOG_IF(ERROR, !hook_) << "SetWindowsHookEx failed"; @@ -97,10 +200,127 @@ return hook_ != nullptr; } +void KeyboardHookWinImpl::ClearModifierStates() { + BYTE keyboard_state[kKeyboardStateArraySize] = {0}; + if (!GetKeyboardState(keyboard_state)) { + DPLOG(ERROR) << "GetKeyboardState() failed: "; + return; + } + + // Reset each modifier position. + keyboard_state[VK_CONTROL] = kKeyUp; + keyboard_state[VK_LCONTROL] = kKeyUp; + keyboard_state[VK_RCONTROL] = kKeyUp; + keyboard_state[VK_MENU] = kKeyUp; + keyboard_state[VK_LMENU] = kKeyUp; + keyboard_state[VK_RMENU] = kKeyUp; + keyboard_state[VK_LWIN] = kKeyUp; + keyboard_state[VK_RWIN] = kKeyUp; + + if (!SetKeyboardState(keyboard_state)) + DPLOG(ERROR) << "SetKeyboardState() failed: "; +} + +bool KeyboardHookWinImpl::ProcessKeyEventMessage(WPARAM w_param, + DWORD vk, + DWORD scan_code, + DWORD time_stamp) { + // The |vk| delivered to the low-level hook includes a location which is + // needed to track individual keystates such as when both left and right + // control keys are pressed. Make sure that location information was retained + // when the vkey was passed into this method. + DCHECK_NE(vk, static_cast<DWORD>(VK_CONTROL)); + DCHECK_NE(vk, static_cast<DWORD>(VK_MENU)); + + if (!IsModifierKey(vk)) + return false; + + // Windows synthesizes an additional key event when AltGr is pressed. The + // event has the left control scan code in the low word and a 0x02 flag set in + // the high word. The VK_RMENU event will be sent once this key is processed. + bool is_altgr_sequence = false; + if (scan_code == kSynthesizedControlScanCodeForAltGr) { + is_altgr_sequence = true; + scan_code = KeycodeConverter::DomCodeToNativeKeycode(DomCode::CONTROL_LEFT); + } + + // If the caller has only requested that Alt be captured, then we don't want + // to bail early on the injected control event. + DomCode dom_code = DomCode::NONE; + if (is_altgr_sequence) + dom_code = DomCode::ALT_RIGHT; + else + dom_code = KeycodeConverter::NativeKeycodeToDomCode(scan_code); + + if (!ShouldCaptureKeyEvent(dom_code)) + return false; + + if (is_altgr_sequence) + altgr_sequence_count_++; + else if (vk != VK_RMENU) + altgr_sequence_count_ = 0; + + // The Windows key is always located, the other modifiers are not. + DWORD non_located_vk = + IsWindowsKey(vk) + ? vk + : LocatedToNonLocatedKeyboardCode(static_cast<KeyboardCode>(vk)); + + bool is_repeat = false; + MSG msg = {nullptr, w_param, non_located_vk, GetLParamFromScanCode(scan_code), + time_stamp}; + EventType event_type = EventTypeFromMSG(msg); + if (event_type == ET_KEY_PRESSED) { + UpdateModifierState(vk, /*key_down=*/true); + // We use the non-located vkey to determine whether a key event is a repeat + // or not. The exception is for AltGr which has a two key sequence which + // alternates. + is_repeat = (last_key_down_ == non_located_vk) || altgr_sequence_count_ > 1; + last_key_down_ = non_located_vk; + } else { + DCHECK_EQ(event_type, ET_KEY_RELEASED); + UpdateModifierState(vk, /*key_down=*/false); + altgr_sequence_count_ = 0; + last_key_down_ = 0; + } + + std::unique_ptr<KeyEvent> key_event = + std::make_unique<KeyEvent>(KeyEventFromMSG(msg)); + if (is_repeat) + key_event->set_flags(key_event->flags() | EF_IS_REPEAT); + ForwardCapturedKeyEvent(std::move(key_event)); + + return true; +} + +void KeyboardHookWinImpl::UpdateModifierState(DWORD vk, bool is_key_down) { + BYTE keyboard_state[kKeyboardStateArraySize] = {0}; + if (!GetKeyboardState(keyboard_state)) { + DPLOG(ERROR) << "GetKeyboardState() failed: "; + return; + } + + // Update the located virtual key first. + keyboard_state[vk] = is_key_down ? kKeyDown : kKeyUp; + + // Now update the non-located virtual key. + keyboard_state[VK_CONTROL] = (keyboard_state[VK_LCONTROL] == kKeyDown || + keyboard_state[VK_RCONTROL] == kKeyDown) + ? kKeyDown + : kKeyUp; + keyboard_state[VK_MENU] = (keyboard_state[VK_LMENU] == kKeyDown || + keyboard_state[VK_RMENU] == kKeyDown) + ? kKeyDown + : kKeyUp; + + if (!SetKeyboardState(keyboard_state)) + PLOG(ERROR) << "SetKeyboardState() failed: "; +} + // static -LRESULT CALLBACK KeyboardHookWin::ProcessKeyEvent(int code, - WPARAM w_param, - LPARAM l_param) { +LRESULT CALLBACK KeyboardHookWinImpl::ProcessKeyEvent(int code, + WPARAM w_param, + LPARAM l_param) { // If there is an error unhooking, this method could be called with a null // |instance_|. Ensure we have a valid instance and that |code| is correct // before proceeding. @@ -110,33 +330,20 @@ DCHECK_CALLED_ON_VALID_THREAD(instance_->thread_checker_); KBDLLHOOKSTRUCT* ll_hooks = reinterpret_cast<KBDLLHOOKSTRUCT*>(l_param); - DomCode dom_code = - KeycodeConverter::NativeKeycodeToDomCode(ll_hooks->scanCode); - if (!IsOSReservedKey(ll_hooks->vkCode) && - instance_->ShouldCaptureKeyEvent(dom_code)) { - MSG msg = {nullptr, static_cast<UINT>(w_param), ll_hooks->vkCode, - (ll_hooks->scanCode << 16) | (ll_hooks->flags & 0xFFFF), - ll_hooks->time}; - KeyEvent key_event = KeyEventFromMSG(msg); - // Determine if this key event represents a repeated key event. - // A low level KB Hook is not passed a parameter or flag which indicates - // whether the key event is a repeat or not as it is called very early in - // input handling pipeline. That means we need to apply our own heuristic - // to determine if it should be treated as a repeated key press or not. - if (key_event.type() == ET_KEY_PRESSED) { - if (instance_->last_key_down_ != 0 && - instance_->last_key_down_ == ll_hooks->vkCode) { - key_event.set_flags(key_event.flags() | EF_IS_REPEAT); - } - instance_->last_key_down_ = ll_hooks->vkCode; - } else { - DCHECK_EQ(key_event.type(), ET_KEY_RELEASED); - instance_->last_key_down_ = 0; - } - instance_->ForwardCapturedKeyEvent(std::make_unique<KeyEvent>(key_event)); + // This vkey represents both a vkey and a location on the keyboard such as + // VK_LCONTROL or VK_RCONTROL. + DWORD vk = ll_hooks->vkCode; + + // Apply the extended flag prior to passing |scan_code| since |instance_| does + // not have access to the low-level hook flags. + DWORD scan_code = ll_hooks->scanCode; + if (ll_hooks->flags & LLKHF_EXTENDED) + scan_code |= 0xE000; + + if (instance_->ProcessKeyEventMessage(w_param, vk, scan_code, ll_hooks->time)) return 1; - } + return CallNextHookEx(nullptr, code, w_param, l_param); } @@ -147,9 +354,10 @@ base::Optional<base::flat_set<DomCode>> dom_codes, gfx::AcceleratedWidget accelerated_widget, KeyEventCallback callback) { - std::unique_ptr<KeyboardHookWin> keyboard_hook = - std::make_unique<KeyboardHookWin>(std::move(dom_codes), - std::move(callback)); + std::unique_ptr<KeyboardHookWinImpl> keyboard_hook = + std::make_unique<KeyboardHookWinImpl>(std::move(dom_codes), + std::move(callback), + /*enable_hook_registration=*/true); if (!keyboard_hook->Register()) return nullptr; @@ -157,4 +365,19 @@ return keyboard_hook; } +std::unique_ptr<KeyboardHookWin> KeyboardHookWin::CreateForTesting( + base::Optional<base::flat_set<DomCode>> dom_codes, + KeyEventCallback callback) { + return std::make_unique<KeyboardHookWinImpl>( + std::move(dom_codes), std::move(callback), + /*enable_hook_registration=*/false); +} + +KeyboardHookWin::KeyboardHookWin( + base::Optional<base::flat_set<DomCode>> dom_codes, + KeyEventCallback callback) + : KeyboardHookBase(std::move(dom_codes), std::move(callback)) {} + +KeyboardHookWin::~KeyboardHookWin() = default; + } // namespace ui
diff --git a/ui/events/win/keyboard_hook_win.h b/ui/events/win/keyboard_hook_win.h new file mode 100644 index 0000000..627ba313 --- /dev/null +++ b/ui/events/win/keyboard_hook_win.h
@@ -0,0 +1,52 @@ +// 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 UI_EVENTS_WIN_KEYBOARD_HOOK_WIN_H_ +#define UI_EVENTS_WIN_KEYBOARD_HOOK_WIN_H_ + +#include <memory> + +#include <windows.h> + +#include "base/containers/flat_set.h" +#include "base/logging.h" +#include "base/macros.h" +#include "base/optional.h" +#include "ui/events/event.h" +#include "ui/events/events_export.h" +#include "ui/events/keyboard_hook_base.h" +#include "ui/events/keycodes/dom/dom_code.h" + +namespace ui { + +// Exposes a method to drive the Windows KeyboardHook implementation by feeding +// it key event data. This method is used by both the low-level keyboard hook +// and by unit tests which simulate the hooked behavior w/o actually installing +// a hook (doing so would cause problems with test parallelization). +class EVENTS_EXPORT KeyboardHookWin : public KeyboardHookBase { + public: + KeyboardHookWin(base::Optional<base::flat_set<DomCode>> dom_codes, + KeyEventCallback callback); + ~KeyboardHookWin() override; + + // Create a KeyboardHookWin instance which does not register a low-level hook. + static std::unique_ptr<KeyboardHookWin> CreateForTesting( + base::Optional<base::flat_set<DomCode>> dom_codes, + KeyEventCallback callback); + + // Called when a key event message is delivered via the low-level hook. + // Exposed here to allow for testing w/o engaging the low-level hook. + // Returns true if the message was handled. + virtual bool ProcessKeyEventMessage(WPARAM w_param, + DWORD vk, + DWORD scan_code, + DWORD time_stamp) = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(KeyboardHookWin); +}; + +} // namespace ui + +#endif // UI_EVENTS_WIN_KEYBOARD_HOOK_WIN_H_
diff --git a/ui/events/win/keyboard_hook_win_unittest.cc b/ui/events/win/keyboard_hook_win_unittest.cc new file mode 100644 index 0000000..d8f3dea --- /dev/null +++ b/ui/events/win/keyboard_hook_win_unittest.cc
@@ -0,0 +1,1085 @@ +// 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 <vector> + +#include "base/bind.h" +#include "base/containers/flat_set.h" +#include "base/optional.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/events/event.h" +#include "ui/events/keyboard_hook.h" +#include "ui/events/keycodes/dom/dom_code.h" +#include "ui/events/keycodes/dom/keycode_converter.h" +#include "ui/events/keycodes/keyboard_codes.h" +#include "ui/events/test/keyboard_layout.h" +#include "ui/events/win/keyboard_hook_win.h" +#include "ui/events/win/system_event_state_lookup.h" + +namespace ui { + +class KeyboardHookWinTest : public testing::Test { + public: + KeyboardHookWinTest(); + ~KeyboardHookWinTest() override; + + // testing::Test overrides. + void SetUp() override; + + void HandleKeyPress(KeyEvent* key_event); + + protected: + KeyboardHookWin* keyboard_hook() { return keyboard_hook_.get(); } + + uint32_t next_time_stamp() { return time_stamp_++; } + + std::vector<KeyEvent>* key_events() { return &key_events_; } + + // Used for sending key events which are handled by the hook. + void SendModifierKeyDownEvent(KeyboardCode key_code, + DomCode dom_code, + int repeat_count = 1); + void SendModifierKeyUpEvent(KeyboardCode key_code, DomCode dom_code); + + void SetKeyboardLayoutForTest(KeyboardLayout new_layout); + + private: + uint32_t time_stamp_ = 0; + std::unique_ptr<KeyboardHookWin> keyboard_hook_; + std::vector<KeyEvent> key_events_; + std::unique_ptr<ScopedKeyboardLayout> keyboard_layout_; + + DISALLOW_COPY_AND_ASSIGN(KeyboardHookWinTest); +}; + +KeyboardHookWinTest::KeyboardHookWinTest() = default; + +KeyboardHookWinTest::~KeyboardHookWinTest() = default; + +void KeyboardHookWinTest::SetUp() { + keyboard_hook_ = KeyboardHookWin::CreateForTesting( + base::Optional<base::flat_set<DomCode>>(), + base::BindRepeating(&KeyboardHookWinTest::HandleKeyPress, + base::Unretained(this))); + + keyboard_layout_ = std::make_unique<ScopedKeyboardLayout>( + KeyboardLayout::KEYBOARD_LAYOUT_ENGLISH_US); +} + +void KeyboardHookWinTest::HandleKeyPress(KeyEvent* key_event) { + key_events_.push_back(*key_event); +} + +void KeyboardHookWinTest::SendModifierKeyDownEvent(KeyboardCode key_code, + DomCode dom_code, + int repeat_count /*=1*/) { + // Ensure we have a valid repeat count and the modifer passed in contains + // location information. + DCHECK_GT(repeat_count, 0); + DCHECK_NE(key_code, KeyboardCode::VKEY_CONTROL); + DCHECK_NE(key_code, KeyboardCode::VKEY_MENU); + + for (int i = 0; i < repeat_count; i++) { + ASSERT_TRUE(keyboard_hook()->ProcessKeyEventMessage( + WM_KEYDOWN, key_code, + KeycodeConverter::DomCodeToNativeKeycode(dom_code), next_time_stamp())); + } +} + +void KeyboardHookWinTest::SendModifierKeyUpEvent(KeyboardCode key_code, + DomCode dom_code) { + // Ensure we have a valid repeat count and the modifer passed in contains + // location information. + DCHECK_NE(key_code, KeyboardCode::VKEY_CONTROL); + DCHECK_NE(key_code, KeyboardCode::VKEY_MENU); + + ASSERT_TRUE(keyboard_hook()->ProcessKeyEventMessage( + WM_KEYUP, key_code, KeycodeConverter::DomCodeToNativeKeycode(dom_code), + next_time_stamp())); +} + +void VerifyKeyEvent(KeyEvent* key_event, + KeyboardCode non_located_key_code, + DomCode dom_code, + bool key_down, + bool is_repeat) { + if (key_down) { + ASSERT_EQ(key_event->type(), ET_KEY_PRESSED); + ASSERT_EQ(key_event->is_repeat(), is_repeat); + } else { + ASSERT_EQ(key_event->type(), ET_KEY_RELEASED); + ASSERT_FALSE(key_event->is_repeat()); + } + ASSERT_EQ(key_event->key_code(), non_located_key_code); + ASSERT_EQ(key_event->code(), dom_code); +} + +TEST_F(KeyboardHookWinTest, SimpleLeftControlKeypressTest) { + const KeyboardCode key_code = KeyboardCode::VKEY_LCONTROL; + const DomCode dom_code = DomCode::CONTROL_LEFT; + SendModifierKeyDownEvent(key_code, dom_code); + ASSERT_EQ(key_events()->size(), 1ULL); + SendModifierKeyUpEvent(key_code, dom_code); + ASSERT_EQ(key_events()->size(), 2ULL); + + KeyEvent down_event = key_events()->at(0); + VerifyKeyEvent(&down_event, KeyboardCode::VKEY_CONTROL, dom_code, true, + false); + ASSERT_TRUE(down_event.IsControlDown()); + ASSERT_FALSE(down_event.IsAltDown()); + ASSERT_FALSE(down_event.IsCommandDown()); + + KeyEvent up_event = key_events()->at(1); + VerifyKeyEvent(&up_event, KeyboardCode::VKEY_CONTROL, dom_code, false, false); + ASSERT_FALSE(up_event.IsControlDown()); +} + +TEST_F(KeyboardHookWinTest, RepeatingLeftControlKeypressTest) { + const int repeat_count = 10; + const KeyboardCode key_code = KeyboardCode::VKEY_LCONTROL; + const DomCode dom_code = DomCode::CONTROL_LEFT; + SendModifierKeyDownEvent(key_code, dom_code, repeat_count); + ASSERT_EQ(static_cast<int>(key_events()->size()), repeat_count); + SendModifierKeyUpEvent(key_code, dom_code); + ASSERT_EQ(static_cast<int>(key_events()->size()), repeat_count + 1); + + bool should_repeat = false; + for (int i = 0; i < repeat_count; i++) { + KeyEvent event = key_events()->at(i); + VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, dom_code, true, + should_repeat); + ASSERT_TRUE(event.IsControlDown()); + ASSERT_FALSE(event.IsAltDown()); + ASSERT_FALSE(event.IsCommandDown()); + should_repeat = true; + } + + KeyEvent up_event = key_events()->at(repeat_count); + VerifyKeyEvent(&up_event, KeyboardCode::VKEY_CONTROL, dom_code, false, false); + ASSERT_FALSE(up_event.IsControlDown()); +} + +TEST_F(KeyboardHookWinTest, SimpleRightControlKeypressTest) { + const KeyboardCode key_code = KeyboardCode::VKEY_RCONTROL; + const DomCode dom_code = DomCode::CONTROL_RIGHT; + SendModifierKeyDownEvent(key_code, dom_code); + ASSERT_EQ(key_events()->size(), 1ULL); + SendModifierKeyUpEvent(key_code, dom_code); + ASSERT_EQ(key_events()->size(), 2ULL); + + KeyEvent down_event = key_events()->at(0); + VerifyKeyEvent(&down_event, KeyboardCode::VKEY_CONTROL, dom_code, true, + false); + ASSERT_TRUE(down_event.IsControlDown()); + ASSERT_FALSE(down_event.IsAltDown()); + ASSERT_FALSE(down_event.IsCommandDown()); + + KeyEvent up_event = key_events()->at(1); + VerifyKeyEvent(&up_event, KeyboardCode::VKEY_CONTROL, dom_code, false, false); + ASSERT_FALSE(up_event.IsControlDown()); +} + +TEST_F(KeyboardHookWinTest, RepeatingRightControlKeypressTest) { + const int repeat_count = 10; + const KeyboardCode key_code = KeyboardCode::VKEY_RCONTROL; + const DomCode dom_code = DomCode::CONTROL_RIGHT; + SendModifierKeyDownEvent(key_code, dom_code, repeat_count); + ASSERT_EQ(static_cast<int>(key_events()->size()), repeat_count); + SendModifierKeyUpEvent(key_code, dom_code); + ASSERT_EQ(static_cast<int>(key_events()->size()), repeat_count + 1); + + bool should_repeat = false; + for (int i = 0; i < repeat_count; i++) { + KeyEvent event = key_events()->at(i); + VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, dom_code, true, + should_repeat); + ASSERT_TRUE(event.IsControlDown()); + ASSERT_FALSE(event.IsAltDown()); + ASSERT_FALSE(event.IsCommandDown()); + should_repeat = true; + } + + KeyEvent up_event = key_events()->at(repeat_count); + VerifyKeyEvent(&up_event, KeyboardCode::VKEY_CONTROL, dom_code, false, false); + ASSERT_FALSE(up_event.IsControlDown()); +} + +TEST_F(KeyboardHookWinTest, SimpleLifoControlSequenceTest) { + const KeyboardCode left_key_code = KeyboardCode::VKEY_LCONTROL; + const DomCode left_dom_code = DomCode::CONTROL_LEFT; + const KeyboardCode right_key_code = KeyboardCode::VKEY_RCONTROL; + const DomCode right_dom_code = DomCode::CONTROL_RIGHT; + SendModifierKeyDownEvent(left_key_code, left_dom_code, 2); + SendModifierKeyDownEvent(right_key_code, right_dom_code, 2); + SendModifierKeyUpEvent(right_key_code, right_dom_code); + SendModifierKeyUpEvent(left_key_code, left_dom_code); + ASSERT_EQ(key_events()->size(), 6ULL); + + // First key down, no repeat. + KeyEvent event = key_events()->at(0); + VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, left_dom_code, true, + false); + ASSERT_TRUE(event.IsControlDown()); + + // First key still down, repeat. + event = key_events()->at(1); + VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, left_dom_code, true, true); + ASSERT_TRUE(event.IsControlDown()); + + // Second key down, repeat. + event = key_events()->at(2); + VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, right_dom_code, true, + true); + ASSERT_TRUE(event.IsControlDown()); + + // Second key still down, repeat. + event = key_events()->at(3); + VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, right_dom_code, true, + true); + ASSERT_TRUE(event.IsControlDown()); + + // Second key up. + event = key_events()->at(4); + VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, right_dom_code, false, + false); + ASSERT_TRUE(event.IsControlDown()); + + // First key up. + event = key_events()->at(5); + VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, left_dom_code, false, + false); + ASSERT_FALSE(event.IsControlDown()); +} + +TEST_F(KeyboardHookWinTest, SimpleFifoControlSequenceTest) { + const KeyboardCode left_key_code = KeyboardCode::VKEY_LCONTROL; + const DomCode left_dom_code = DomCode::CONTROL_LEFT; + const KeyboardCode right_key_code = KeyboardCode::VKEY_RCONTROL; + const DomCode right_dom_code = DomCode::CONTROL_RIGHT; + SendModifierKeyDownEvent(right_key_code, right_dom_code, 2); + SendModifierKeyDownEvent(left_key_code, left_dom_code, 2); + SendModifierKeyUpEvent(right_key_code, right_dom_code); + SendModifierKeyUpEvent(left_key_code, left_dom_code); + ASSERT_EQ(key_events()->size(), 6ULL); + + // First key down, no repeat. + KeyEvent event = key_events()->at(0); + VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, right_dom_code, true, + false); + ASSERT_TRUE(event.IsControlDown()); + + // First key still down, repeat. + event = key_events()->at(1); + VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, right_dom_code, true, + true); + ASSERT_TRUE(event.IsControlDown()); + + // Second key down, repeat. + event = key_events()->at(2); + VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, left_dom_code, true, true); + ASSERT_TRUE(event.IsControlDown()); + + // Second key still down, repeat. + event = key_events()->at(3); + VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, left_dom_code, true, true); + ASSERT_TRUE(event.IsControlDown()); + + // First key up. + event = key_events()->at(4); + VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, right_dom_code, false, + false); + ASSERT_TRUE(event.IsControlDown()); + + // Second key up. + event = key_events()->at(5); + VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, left_dom_code, false, + false); + ASSERT_FALSE(event.IsControlDown()); +} + +TEST_F(KeyboardHookWinTest, SimpleLeftAltKeypressTest) { + const KeyboardCode key_code = KeyboardCode::VKEY_LMENU; + const DomCode dom_code = DomCode::ALT_LEFT; + SendModifierKeyDownEvent(key_code, dom_code); + ASSERT_EQ(key_events()->size(), 1ULL); + SendModifierKeyUpEvent(key_code, dom_code); + ASSERT_EQ(key_events()->size(), 2ULL); + + KeyEvent down_event = key_events()->at(0); + VerifyKeyEvent(&down_event, KeyboardCode::VKEY_MENU, dom_code, true, false); + ASSERT_FALSE(down_event.IsControlDown()); + ASSERT_TRUE(down_event.IsAltDown()); + ASSERT_FALSE(down_event.IsCommandDown()); + + KeyEvent up_event = key_events()->at(1); + VerifyKeyEvent(&up_event, KeyboardCode::VKEY_MENU, dom_code, false, false); + ASSERT_FALSE(up_event.IsAltDown()); +} + +TEST_F(KeyboardHookWinTest, RepeatingLeftAltKeypressTest) { + const int repeat_count = 10; + const KeyboardCode key_code = KeyboardCode::VKEY_LMENU; + const DomCode dom_code = DomCode::ALT_LEFT; + SendModifierKeyDownEvent(key_code, dom_code, repeat_count); + ASSERT_EQ(static_cast<int>(key_events()->size()), repeat_count); + SendModifierKeyUpEvent(key_code, dom_code); + ASSERT_EQ(static_cast<int>(key_events()->size()), repeat_count + 1); + + bool should_repeat = false; + for (int i = 0; i < repeat_count; i++) { + KeyEvent event = key_events()->at(i); + VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, dom_code, true, + should_repeat); + ASSERT_FALSE(event.IsControlDown()); + ASSERT_TRUE(event.IsAltDown()); + ASSERT_FALSE(event.IsCommandDown()); + should_repeat = true; + } + + KeyEvent up_event = key_events()->at(repeat_count); + VerifyKeyEvent(&up_event, KeyboardCode::VKEY_MENU, dom_code, false, false); + ASSERT_FALSE(up_event.IsAltDown()); +} + +TEST_F(KeyboardHookWinTest, SimpleRightAltKeypressTest) { + const KeyboardCode key_code = KeyboardCode::VKEY_RMENU; + const DomCode dom_code = DomCode::ALT_LEFT; + SendModifierKeyDownEvent(key_code, dom_code); + ASSERT_EQ(key_events()->size(), 1ULL); + SendModifierKeyUpEvent(key_code, dom_code); + ASSERT_EQ(key_events()->size(), 2ULL); + + KeyEvent down_event = key_events()->at(0); + VerifyKeyEvent(&down_event, KeyboardCode::VKEY_MENU, dom_code, true, false); + ASSERT_FALSE(down_event.IsControlDown()); + ASSERT_TRUE(down_event.IsAltDown()); + ASSERT_FALSE(down_event.IsCommandDown()); + + KeyEvent up_event = key_events()->at(1); + VerifyKeyEvent(&up_event, KeyboardCode::VKEY_MENU, dom_code, false, false); + ASSERT_FALSE(up_event.IsAltDown()); +} + +TEST_F(KeyboardHookWinTest, RepeatingRightAltKeypressTest) { + const int repeat_count = 10; + const KeyboardCode key_code = KeyboardCode::VKEY_RMENU; + const DomCode dom_code = DomCode::ALT_RIGHT; + SendModifierKeyDownEvent(key_code, dom_code, repeat_count); + ASSERT_EQ(static_cast<int>(key_events()->size()), repeat_count); + SendModifierKeyUpEvent(key_code, dom_code); + ASSERT_EQ(static_cast<int>(key_events()->size()), repeat_count + 1); + + bool should_repeat = false; + for (int i = 0; i < repeat_count; i++) { + KeyEvent event = key_events()->at(i); + VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, dom_code, true, + should_repeat); + ASSERT_FALSE(event.IsControlDown()); + ASSERT_TRUE(event.IsAltDown()); + ASSERT_FALSE(event.IsCommandDown()); + should_repeat = true; + } + + KeyEvent up_event = key_events()->at(repeat_count); + VerifyKeyEvent(&up_event, KeyboardCode::VKEY_MENU, dom_code, false, false); + ASSERT_FALSE(up_event.IsAltDown()); +} + +TEST_F(KeyboardHookWinTest, SimpleLifoAltSequenceTest) { + const KeyboardCode left_key_code = KeyboardCode::VKEY_LMENU; + const DomCode left_dom_code = DomCode::ALT_LEFT; + const KeyboardCode right_key_code = KeyboardCode::VKEY_RMENU; + const DomCode right_dom_code = DomCode::ALT_RIGHT; + SendModifierKeyDownEvent(left_key_code, left_dom_code, 2); + SendModifierKeyDownEvent(right_key_code, right_dom_code, 2); + SendModifierKeyUpEvent(right_key_code, right_dom_code); + SendModifierKeyUpEvent(left_key_code, left_dom_code); + ASSERT_EQ(key_events()->size(), 6ULL); + + // First key down, no repeat. + KeyEvent event = key_events()->at(0); + VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, left_dom_code, true, false); + ASSERT_TRUE(event.IsAltDown()); + + // First key still down, repeat. + event = key_events()->at(1); + VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, left_dom_code, true, true); + ASSERT_TRUE(event.IsAltDown()); + + // Second key down, repeat. + event = key_events()->at(2); + VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, right_dom_code, true, true); + ASSERT_TRUE(event.IsAltDown()); + + // Second key still down, repeat. + event = key_events()->at(3); + VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, right_dom_code, true, true); + ASSERT_TRUE(event.IsAltDown()); + + // Second key up. + event = key_events()->at(4); + VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, right_dom_code, false, false); + ASSERT_TRUE(event.IsAltDown()); + + // First key up. + event = key_events()->at(5); + VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, left_dom_code, false, false); + ASSERT_FALSE(event.IsAltDown()); +} + +TEST_F(KeyboardHookWinTest, SimpleFifoAltSequenceTest) { + const KeyboardCode left_key_code = KeyboardCode::VKEY_LMENU; + const DomCode left_dom_code = DomCode::ALT_LEFT; + const KeyboardCode right_key_code = KeyboardCode::VKEY_RMENU; + const DomCode right_dom_code = DomCode::ALT_RIGHT; + SendModifierKeyDownEvent(right_key_code, right_dom_code, 2); + SendModifierKeyDownEvent(left_key_code, left_dom_code, 2); + SendModifierKeyUpEvent(right_key_code, right_dom_code); + SendModifierKeyUpEvent(left_key_code, left_dom_code); + ASSERT_EQ(key_events()->size(), 6ULL); + + // First key down, no repeat. + KeyEvent event = key_events()->at(0); + VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, right_dom_code, true, false); + ASSERT_TRUE(event.IsAltDown()); + + // First key still down, repeat. + event = key_events()->at(1); + VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, right_dom_code, true, true); + ASSERT_TRUE(event.IsAltDown()); + + // Second key down, repeat. + event = key_events()->at(2); + VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, left_dom_code, true, true); + ASSERT_TRUE(event.IsAltDown()); + + // Second key still down, repeat. + event = key_events()->at(3); + VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, left_dom_code, true, true); + ASSERT_TRUE(event.IsAltDown()); + + // First key up. + event = key_events()->at(4); + VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, right_dom_code, false, false); + ASSERT_TRUE(event.IsAltDown()); + + // Second key up. + event = key_events()->at(5); + VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, left_dom_code, false, false); + ASSERT_FALSE(event.IsAltDown()); +} + +TEST_F(KeyboardHookWinTest, SimpleLeftWinKeypressTest) { + const KeyboardCode key_code = KeyboardCode::VKEY_LWIN; + const DomCode dom_code = DomCode::META_LEFT; + SendModifierKeyDownEvent(key_code, dom_code); + ASSERT_EQ(key_events()->size(), 1ULL); + SendModifierKeyUpEvent(key_code, dom_code); + ASSERT_EQ(key_events()->size(), 2ULL); + + KeyEvent down_event = key_events()->at(0); + // VKEY_LWIN is the 'non-located' version of the Windows key. + VerifyKeyEvent(&down_event, KeyboardCode::VKEY_LWIN, dom_code, true, false); + ASSERT_FALSE(down_event.IsControlDown()); + ASSERT_FALSE(down_event.IsAltDown()); + ASSERT_TRUE(down_event.IsCommandDown()); + + KeyEvent up_event = key_events()->at(1); + VerifyKeyEvent(&up_event, KeyboardCode::VKEY_LWIN, dom_code, false, false); + ASSERT_FALSE(up_event.IsCommandDown()); +} + +TEST_F(KeyboardHookWinTest, RepeatingLeftWinKeypressTest) { + const int repeat_count = 10; + const KeyboardCode key_code = KeyboardCode::VKEY_LWIN; + const DomCode dom_code = DomCode::META_LEFT; + SendModifierKeyDownEvent(key_code, dom_code, repeat_count); + ASSERT_EQ(static_cast<int>(key_events()->size()), repeat_count); + SendModifierKeyUpEvent(key_code, dom_code); + ASSERT_EQ(static_cast<int>(key_events()->size()), repeat_count + 1); + + bool should_repeat = false; + for (int i = 0; i < repeat_count; i++) { + KeyEvent event = key_events()->at(i); + // VKEY_LWIN is the 'non-located' version of the Windows key. + VerifyKeyEvent(&event, KeyboardCode::VKEY_LWIN, dom_code, true, + should_repeat); + ASSERT_FALSE(event.IsControlDown()); + ASSERT_FALSE(event.IsAltDown()); + ASSERT_TRUE(event.IsCommandDown()); + should_repeat = true; + } + + KeyEvent up_event = key_events()->at(repeat_count); + VerifyKeyEvent(&up_event, KeyboardCode::VKEY_LWIN, dom_code, false, false); + ASSERT_FALSE(up_event.IsCommandDown()); +} + +TEST_F(KeyboardHookWinTest, SimpleRightWinKeypressTest) { + const KeyboardCode key_code = KeyboardCode::VKEY_RWIN; + const DomCode dom_code = DomCode::META_RIGHT; + SendModifierKeyDownEvent(key_code, dom_code); + ASSERT_EQ(key_events()->size(), 1ULL); + SendModifierKeyUpEvent(key_code, dom_code); + ASSERT_EQ(key_events()->size(), 2ULL); + + KeyEvent down_event = key_events()->at(0); + // VKEY_LWIN is the 'non-located' version of the Windows key. + VerifyKeyEvent(&down_event, KeyboardCode::VKEY_RWIN, dom_code, true, false); + ASSERT_FALSE(down_event.IsControlDown()); + ASSERT_FALSE(down_event.IsAltDown()); + ASSERT_TRUE(down_event.IsCommandDown()); + + KeyEvent up_event = key_events()->at(1); + VerifyKeyEvent(&up_event, KeyboardCode::VKEY_RWIN, dom_code, false, false); + ASSERT_FALSE(up_event.IsCommandDown()); +} + +TEST_F(KeyboardHookWinTest, RepeatingRightWinKeypressTest) { + const int repeat_count = 10; + const KeyboardCode key_code = KeyboardCode::VKEY_RWIN; + const DomCode dom_code = DomCode::META_RIGHT; + SendModifierKeyDownEvent(key_code, dom_code, repeat_count); + ASSERT_EQ(static_cast<int>(key_events()->size()), repeat_count); + SendModifierKeyUpEvent(key_code, dom_code); + ASSERT_EQ(static_cast<int>(key_events()->size()), repeat_count + 1); + + bool should_repeat = false; + for (int i = 0; i < repeat_count; i++) { + KeyEvent event = key_events()->at(i); + // VKEY_LWIN is the 'non-located' version of the Windows key. + VerifyKeyEvent(&event, KeyboardCode::VKEY_RWIN, dom_code, true, + should_repeat); + ASSERT_FALSE(event.IsControlDown()); + ASSERT_FALSE(event.IsAltDown()); + ASSERT_TRUE(event.IsCommandDown()); + should_repeat = true; + } + + KeyEvent up_event = key_events()->at(repeat_count); + VerifyKeyEvent(&up_event, KeyboardCode::VKEY_RWIN, dom_code, false, false); + ASSERT_FALSE(up_event.IsCommandDown()); +} + +TEST_F(KeyboardHookWinTest, SimpleLifoWinSequenceTest) { + const KeyboardCode left_key_code = KeyboardCode::VKEY_LWIN; + const DomCode left_dom_code = DomCode::META_LEFT; + const KeyboardCode right_key_code = KeyboardCode::VKEY_RWIN; + const DomCode right_dom_code = DomCode::META_RIGHT; + SendModifierKeyDownEvent(left_key_code, left_dom_code, 2); + SendModifierKeyDownEvent(right_key_code, right_dom_code, 2); + SendModifierKeyUpEvent(right_key_code, right_dom_code); + SendModifierKeyUpEvent(left_key_code, left_dom_code); + ASSERT_EQ(key_events()->size(), 6ULL); + + // First key down, no repeat. + KeyEvent event = key_events()->at(0); + VerifyKeyEvent(&event, KeyboardCode::VKEY_LWIN, left_dom_code, true, false); + ASSERT_TRUE(event.IsCommandDown()); + + // First key still down, repeat. + event = key_events()->at(1); + VerifyKeyEvent(&event, KeyboardCode::VKEY_LWIN, left_dom_code, true, true); + ASSERT_TRUE(event.IsCommandDown()); + + // Second key down, no repeat. + event = key_events()->at(2); + VerifyKeyEvent(&event, KeyboardCode::VKEY_RWIN, right_dom_code, true, false); + ASSERT_TRUE(event.IsCommandDown()); + + // Second key still down, repeat. + event = key_events()->at(3); + VerifyKeyEvent(&event, KeyboardCode::VKEY_RWIN, right_dom_code, true, true); + ASSERT_TRUE(event.IsCommandDown()); + + // Second key up. + event = key_events()->at(4); + VerifyKeyEvent(&event, KeyboardCode::VKEY_RWIN, right_dom_code, false, false); + ASSERT_TRUE(event.IsCommandDown()); + + // First key up. + event = key_events()->at(5); + VerifyKeyEvent(&event, KeyboardCode::VKEY_LWIN, left_dom_code, false, false); + ASSERT_FALSE(event.IsCommandDown()); +} + +TEST_F(KeyboardHookWinTest, SimpleFifoWinSequenceTest) { + const KeyboardCode left_key_code = KeyboardCode::VKEY_LWIN; + const DomCode left_dom_code = DomCode::META_LEFT; + const KeyboardCode right_key_code = KeyboardCode::VKEY_RWIN; + const DomCode right_dom_code = DomCode::META_RIGHT; + SendModifierKeyDownEvent(right_key_code, right_dom_code, 2); + SendModifierKeyDownEvent(left_key_code, left_dom_code, 2); + SendModifierKeyUpEvent(right_key_code, right_dom_code); + SendModifierKeyUpEvent(left_key_code, left_dom_code); + ASSERT_EQ(key_events()->size(), 6ULL); + + // First key down, no repeat. + KeyEvent event = key_events()->at(0); + VerifyKeyEvent(&event, KeyboardCode::VKEY_RWIN, right_dom_code, true, false); + ASSERT_TRUE(event.IsCommandDown()); + + // First key still down, repeat. + event = key_events()->at(1); + VerifyKeyEvent(&event, KeyboardCode::VKEY_RWIN, right_dom_code, true, true); + ASSERT_TRUE(event.IsCommandDown()); + + // Second key down, no repeat. + event = key_events()->at(2); + VerifyKeyEvent(&event, KeyboardCode::VKEY_LWIN, left_dom_code, true, false); + ASSERT_TRUE(event.IsCommandDown()); + + // Second key still down, repeat. + event = key_events()->at(3); + VerifyKeyEvent(&event, KeyboardCode::VKEY_LWIN, left_dom_code, true, true); + ASSERT_TRUE(event.IsCommandDown()); + + // First key up. + event = key_events()->at(4); + VerifyKeyEvent(&event, KeyboardCode::VKEY_RWIN, right_dom_code, false, false); + ASSERT_TRUE(event.IsCommandDown()); + + // Second key up. + event = key_events()->at(5); + VerifyKeyEvent(&event, KeyboardCode::VKEY_LWIN, left_dom_code, false, false); + ASSERT_FALSE(event.IsCommandDown()); +} + +TEST_F(KeyboardHookWinTest, CombinedModifierLifoSequenceKeypressTest) { + const KeyboardCode first_key_code = KeyboardCode::VKEY_LCONTROL; + const DomCode first_dom_code = DomCode::CONTROL_LEFT; + const KeyboardCode second_key_code = KeyboardCode::VKEY_RWIN; + const DomCode second_dom_code = DomCode::META_RIGHT; + const KeyboardCode third_key_code = KeyboardCode::VKEY_LMENU; + const DomCode third_dom_code = DomCode::ALT_LEFT; + SendModifierKeyDownEvent(first_key_code, first_dom_code, 2); + SendModifierKeyDownEvent(second_key_code, second_dom_code, 2); + SendModifierKeyDownEvent(third_key_code, third_dom_code, 2); + SendModifierKeyUpEvent(third_key_code, third_dom_code); + SendModifierKeyUpEvent(second_key_code, second_dom_code); + SendModifierKeyUpEvent(first_key_code, first_dom_code); + ASSERT_EQ(key_events()->size(), 9ULL); + + // First key down, no repeat. + KeyEvent event = key_events()->at(0); + VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, first_dom_code, true, + false); + ASSERT_TRUE(event.IsControlDown()); + ASSERT_FALSE(event.IsAltDown()); + ASSERT_FALSE(event.IsCommandDown()); + + // First key still down, repeat. + event = key_events()->at(1); + VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, first_dom_code, true, + true); + ASSERT_TRUE(event.IsControlDown()); + ASSERT_FALSE(event.IsAltDown()); + ASSERT_FALSE(event.IsCommandDown()); + + // Second key down, no repeat. + event = key_events()->at(2); + VerifyKeyEvent(&event, KeyboardCode::VKEY_RWIN, second_dom_code, true, false); + ASSERT_TRUE(event.IsControlDown()); + ASSERT_FALSE(event.IsAltDown()); + ASSERT_TRUE(event.IsCommandDown()); + + // Second key still down, repeat. + event = key_events()->at(3); + VerifyKeyEvent(&event, KeyboardCode::VKEY_RWIN, second_dom_code, true, true); + ASSERT_TRUE(event.IsControlDown()); + ASSERT_FALSE(event.IsAltDown()); + ASSERT_TRUE(event.IsCommandDown()); + + // Third key down, no repeat. + event = key_events()->at(4); + VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, third_dom_code, true, false); + ASSERT_TRUE(event.IsControlDown()); + ASSERT_TRUE(event.IsAltDown()); + ASSERT_TRUE(event.IsCommandDown()); + + // Third key still down, repeat. + event = key_events()->at(5); + VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, third_dom_code, true, true); + ASSERT_TRUE(event.IsControlDown()); + ASSERT_TRUE(event.IsAltDown()); + ASSERT_TRUE(event.IsCommandDown()); + + // Third key up. + event = key_events()->at(6); + VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, third_dom_code, false, false); + ASSERT_TRUE(event.IsControlDown()); + ASSERT_FALSE(event.IsAltDown()); + ASSERT_TRUE(event.IsCommandDown()); + + // Second key up. + event = key_events()->at(7); + VerifyKeyEvent(&event, KeyboardCode::VKEY_RWIN, second_dom_code, false, + false); + ASSERT_TRUE(event.IsControlDown()); + ASSERT_FALSE(event.IsAltDown()); + ASSERT_FALSE(event.IsCommandDown()); + + // First key up. + event = key_events()->at(8); + VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, first_dom_code, false, + false); + ASSERT_FALSE(event.IsControlDown()); + ASSERT_FALSE(event.IsAltDown()); + ASSERT_FALSE(event.IsCommandDown()); +} + +TEST_F(KeyboardHookWinTest, CombinedModifierFifoSequenceKeypressTest) { + const KeyboardCode first_key_code = KeyboardCode::VKEY_RCONTROL; + const DomCode first_dom_code = DomCode::CONTROL_RIGHT; + const KeyboardCode second_key_code = KeyboardCode::VKEY_LWIN; + const DomCode second_dom_code = DomCode::META_LEFT; + const KeyboardCode third_key_code = KeyboardCode::VKEY_RMENU; + const DomCode third_dom_code = DomCode::ALT_RIGHT; + SendModifierKeyDownEvent(first_key_code, first_dom_code, 2); + SendModifierKeyDownEvent(second_key_code, second_dom_code, 2); + SendModifierKeyDownEvent(third_key_code, third_dom_code, 2); + SendModifierKeyUpEvent(first_key_code, first_dom_code); + SendModifierKeyUpEvent(second_key_code, second_dom_code); + SendModifierKeyUpEvent(third_key_code, third_dom_code); + ASSERT_EQ(key_events()->size(), 9ULL); + + // First key down, no repeat. + KeyEvent event = key_events()->at(0); + VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, first_dom_code, true, + false); + ASSERT_TRUE(event.IsControlDown()); + ASSERT_FALSE(event.IsAltDown()); + ASSERT_FALSE(event.IsCommandDown()); + + // First key still down, repeat. + event = key_events()->at(1); + VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, first_dom_code, true, + true); + ASSERT_TRUE(event.IsControlDown()); + ASSERT_FALSE(event.IsAltDown()); + ASSERT_FALSE(event.IsCommandDown()); + + // Second key down, no repeat. + event = key_events()->at(2); + VerifyKeyEvent(&event, KeyboardCode::VKEY_LWIN, second_dom_code, true, false); + ASSERT_TRUE(event.IsControlDown()); + ASSERT_FALSE(event.IsAltDown()); + ASSERT_TRUE(event.IsCommandDown()); + + // Second key still down, repeat. + event = key_events()->at(3); + VerifyKeyEvent(&event, KeyboardCode::VKEY_LWIN, second_dom_code, true, true); + ASSERT_TRUE(event.IsControlDown()); + ASSERT_FALSE(event.IsAltDown()); + ASSERT_TRUE(event.IsCommandDown()); + + // Third key down, no repeat. + event = key_events()->at(4); + VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, third_dom_code, true, false); + ASSERT_TRUE(event.IsControlDown()); + ASSERT_TRUE(event.IsAltDown()); + ASSERT_TRUE(event.IsCommandDown()); + + // Third key still down, repeat. + event = key_events()->at(5); + VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, third_dom_code, true, true); + ASSERT_TRUE(event.IsControlDown()); + ASSERT_TRUE(event.IsAltDown()); + ASSERT_TRUE(event.IsCommandDown()); + + // First key up. + event = key_events()->at(6); + VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, first_dom_code, false, + false); + ASSERT_FALSE(event.IsControlDown()); + ASSERT_TRUE(event.IsAltDown()); + ASSERT_TRUE(event.IsCommandDown()); + + // Second key up. + event = key_events()->at(7); + VerifyKeyEvent(&event, KeyboardCode::VKEY_LWIN, second_dom_code, false, + false); + ASSERT_FALSE(event.IsControlDown()); + ASSERT_TRUE(event.IsAltDown()); + ASSERT_FALSE(event.IsCommandDown()); + + // Third key up. + event = key_events()->at(8); + VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, third_dom_code, false, false); + ASSERT_FALSE(event.IsControlDown()); + ASSERT_FALSE(event.IsAltDown()); + ASSERT_FALSE(event.IsCommandDown()); +} + +TEST_F(KeyboardHookWinTest, VerifyPlatformModifierStateTest) { + SendModifierKeyDownEvent(KeyboardCode::VKEY_LCONTROL, DomCode::CONTROL_LEFT); + ASSERT_TRUE(win::IsCtrlPressed()); + ASSERT_FALSE(win::IsAltPressed()); + ASSERT_FALSE(win::IsWindowsKeyPressed()); + + SendModifierKeyDownEvent(KeyboardCode::VKEY_RWIN, DomCode::META_RIGHT); + ASSERT_TRUE(win::IsCtrlPressed()); + ASSERT_FALSE(win::IsAltPressed()); + ASSERT_TRUE(win::IsWindowsKeyPressed()); + + SendModifierKeyDownEvent(KeyboardCode::VKEY_LMENU, DomCode::ALT_LEFT); + ASSERT_TRUE(win::IsCtrlPressed()); + ASSERT_TRUE(win::IsAltPressed()); + ASSERT_FALSE(win::IsAltRightPressed()); + ASSERT_TRUE(win::IsWindowsKeyPressed()); + + SendModifierKeyUpEvent(KeyboardCode::VKEY_RWIN, DomCode::META_RIGHT); + ASSERT_TRUE(win::IsCtrlPressed()); + ASSERT_TRUE(win::IsAltPressed()); + ASSERT_FALSE(win::IsWindowsKeyPressed()); + + SendModifierKeyUpEvent(KeyboardCode::VKEY_LCONTROL, DomCode::CONTROL_LEFT); + ASSERT_FALSE(win::IsCtrlPressed()); + ASSERT_TRUE(win::IsAltPressed()); + ASSERT_FALSE(win::IsWindowsKeyPressed()); + + SendModifierKeyUpEvent(KeyboardCode::VKEY_LMENU, DomCode::ALT_LEFT); + ASSERT_FALSE(win::IsCtrlPressed()); + ASSERT_FALSE(win::IsAltPressed()); + ASSERT_FALSE(win::IsWindowsKeyPressed()); + + SendModifierKeyDownEvent(KeyboardCode::VKEY_RMENU, DomCode::ALT_RIGHT); + ASSERT_TRUE(win::IsAltPressed()); + ASSERT_TRUE(win::IsAltRightPressed()); +} + +TEST_F(KeyboardHookWinTest, SimpleAltGrKeyPressTest) { + ScopedKeyboardLayout keyboard_layout(KeyboardLayout::KEYBOARD_LAYOUT_GERMAN); + + // AltGr produces two events, an injected, modified scan code for VK_LCONTROL, + // and an event for VK_RMENU. We simulate that sequence here. + const KeyboardCode altgr_key_code = KeyboardCode::VKEY_RMENU; + const DomCode altgr_dom_code = DomCode::ALT_RIGHT; + const DomCode control_dom_code = DomCode::CONTROL_LEFT; + const DWORD control_scan_code = + KeycodeConverter::DomCodeToNativeKeycode(control_dom_code); + const DWORD injected_control_scan_code = control_scan_code | 0x0200; + + ASSERT_TRUE(keyboard_hook()->ProcessKeyEventMessage( + WM_KEYDOWN, KeyboardCode::VKEY_LCONTROL, injected_control_scan_code, + next_time_stamp())); + SendModifierKeyDownEvent(altgr_key_code, altgr_dom_code); + + ASSERT_TRUE(keyboard_hook()->ProcessKeyEventMessage( + WM_KEYUP, KeyboardCode::VKEY_LCONTROL, + KeycodeConverter::DomCodeToNativeKeycode(control_dom_code), + next_time_stamp())); + SendModifierKeyUpEvent(altgr_key_code, altgr_dom_code); + ASSERT_EQ(key_events()->size(), 4ULL); + + // Injected control key down, no repeat. + KeyEvent event = key_events()->at(0); + VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, control_dom_code, true, + false); + ASSERT_TRUE(event.IsControlDown()); + ASSERT_FALSE(event.IsAltDown()); + ASSERT_FALSE(event.IsAltGrDown()); + ASSERT_FALSE(event.IsCommandDown()); + + // Altgr key down. + event = key_events()->at(1); + VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, altgr_dom_code, true, false); + ASSERT_FALSE(event.IsControlDown()); + ASSERT_FALSE(event.IsAltDown()); + ASSERT_TRUE(event.IsAltGrDown()); + ASSERT_FALSE(event.IsCommandDown()); + + // Injected control key up. + event = key_events()->at(2); + VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, control_dom_code, false, + false); + ASSERT_FALSE(event.IsControlDown()); + ASSERT_FALSE(event.IsAltDown()); + ASSERT_TRUE(event.IsAltGrDown()); + ASSERT_FALSE(event.IsCommandDown()); + + // AltGr key up. + event = key_events()->at(3); + VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, altgr_dom_code, false, false); + ASSERT_FALSE(event.IsControlDown()); + ASSERT_FALSE(event.IsAltDown()); + ASSERT_FALSE(event.IsAltGrDown()); + ASSERT_FALSE(event.IsCommandDown()); +} + +TEST_F(KeyboardHookWinTest, RepeatingAltGrKeyPressTest) { + ScopedKeyboardLayout keyboard_layout(KeyboardLayout::KEYBOARD_LAYOUT_GERMAN); + + // AltGr produces two events, an injected, modified scan code for VK_LCONTROL, + // and an event for VK_RMENU. This sequence repeats for each repeated key + // press. We simulate that sequence here. + const KeyboardCode altgr_key_code = KeyboardCode::VKEY_RMENU; + const DomCode altgr_dom_code = DomCode::ALT_RIGHT; + const DomCode control_dom_code = DomCode::CONTROL_LEFT; + const DWORD control_scan_code = + KeycodeConverter::DomCodeToNativeKeycode(control_dom_code); + const DWORD injected_control_scan_code = control_scan_code | 0x0200; + + ASSERT_TRUE(keyboard_hook()->ProcessKeyEventMessage( + WM_KEYDOWN, KeyboardCode::VKEY_LCONTROL, injected_control_scan_code, + next_time_stamp())); + SendModifierKeyDownEvent(altgr_key_code, altgr_dom_code); + ASSERT_TRUE(keyboard_hook()->ProcessKeyEventMessage( + WM_KEYDOWN, KeyboardCode::VKEY_LCONTROL, injected_control_scan_code, + next_time_stamp())); + SendModifierKeyDownEvent(altgr_key_code, altgr_dom_code); + ASSERT_TRUE(keyboard_hook()->ProcessKeyEventMessage( + WM_KEYDOWN, KeyboardCode::VKEY_LCONTROL, injected_control_scan_code, + next_time_stamp())); + SendModifierKeyDownEvent(altgr_key_code, altgr_dom_code); + ASSERT_TRUE(keyboard_hook()->ProcessKeyEventMessage( + WM_KEYUP, KeyboardCode::VKEY_LCONTROL, + KeycodeConverter::DomCodeToNativeKeycode(control_dom_code), + next_time_stamp())); + SendModifierKeyUpEvent(altgr_key_code, altgr_dom_code); + ASSERT_EQ(key_events()->size(), 8ULL); + + // Injected control key down, no repeat. + KeyEvent event = key_events()->at(0); + VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, control_dom_code, true, + false); + ASSERT_TRUE(event.IsControlDown()); + ASSERT_FALSE(event.IsAltDown()); + ASSERT_FALSE(event.IsAltGrDown()); + ASSERT_FALSE(event.IsCommandDown()); + + // Altgr key down. + event = key_events()->at(1); + VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, altgr_dom_code, true, false); + ASSERT_FALSE(event.IsControlDown()); + ASSERT_FALSE(event.IsAltDown()); + ASSERT_TRUE(event.IsAltGrDown()); + ASSERT_FALSE(event.IsCommandDown()); + + // Injected control key down, repeat. + event = key_events()->at(2); + VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, control_dom_code, true, + true); + ASSERT_FALSE(event.IsControlDown()); + ASSERT_FALSE(event.IsAltDown()); + ASSERT_TRUE(event.IsAltGrDown()); + ASSERT_FALSE(event.IsCommandDown()); + + // Altgr key down, repeat. + event = key_events()->at(3); + VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, altgr_dom_code, true, true); + ASSERT_FALSE(event.IsControlDown()); + ASSERT_FALSE(event.IsAltDown()); + ASSERT_TRUE(event.IsAltGrDown()); + ASSERT_FALSE(event.IsCommandDown()); + + // Injected control key down, repeat. + event = key_events()->at(4); + VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, control_dom_code, true, + true); + ASSERT_FALSE(event.IsControlDown()); + ASSERT_FALSE(event.IsAltDown()); + ASSERT_TRUE(event.IsAltGrDown()); + ASSERT_FALSE(event.IsCommandDown()); + + // Altgr key down, repeat. + event = key_events()->at(5); + VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, altgr_dom_code, true, true); + ASSERT_FALSE(event.IsControlDown()); + ASSERT_FALSE(event.IsAltDown()); + ASSERT_TRUE(event.IsAltGrDown()); + ASSERT_FALSE(event.IsCommandDown()); + + // Injected control key up. + event = key_events()->at(6); + VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, control_dom_code, false, + false); + ASSERT_FALSE(event.IsControlDown()); + ASSERT_FALSE(event.IsAltDown()); + ASSERT_TRUE(event.IsAltGrDown()); + ASSERT_FALSE(event.IsCommandDown()); + + // AltGr key up. + event = key_events()->at(7); + VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, altgr_dom_code, false, false); + ASSERT_FALSE(event.IsControlDown()); + ASSERT_FALSE(event.IsAltDown()); + ASSERT_FALSE(event.IsAltGrDown()); + ASSERT_FALSE(event.IsCommandDown()); +} + +TEST_F(KeyboardHookWinTest, VerifyAltGrPlatformModifierStateTest) { + ScopedKeyboardLayout keyboard_layout(KeyboardLayout::KEYBOARD_LAYOUT_GERMAN); + + // AltGr produces two events, an injected, modified scan code for VK_LCONTROL, + // and an event for VK_RMENU. We simulate that sequence here. + const KeyboardCode altgr_key_code = KeyboardCode::VKEY_RMENU; + const DomCode altgr_dom_code = DomCode::ALT_RIGHT; + const DomCode control_dom_code = DomCode::CONTROL_LEFT; + const DWORD control_scan_code = + KeycodeConverter::DomCodeToNativeKeycode(control_dom_code); + const DWORD injected_control_scan_code = control_scan_code | 0x0200; + + ASSERT_TRUE(keyboard_hook()->ProcessKeyEventMessage( + WM_KEYDOWN, KeyboardCode::VKEY_LCONTROL, injected_control_scan_code, + next_time_stamp())); + ASSERT_TRUE(win::IsCtrlPressed()); + ASSERT_FALSE(win::IsAltPressed()); + ASSERT_FALSE(win::IsAltRightPressed()); + ASSERT_FALSE(win::IsWindowsKeyPressed()); + + SendModifierKeyDownEvent(altgr_key_code, altgr_dom_code); + ASSERT_TRUE(win::IsCtrlPressed()); + ASSERT_TRUE(win::IsAltPressed()); + ASSERT_TRUE(win::IsAltRightPressed()); + ASSERT_FALSE(win::IsWindowsKeyPressed()); + + ASSERT_TRUE(keyboard_hook()->ProcessKeyEventMessage( + WM_KEYUP, KeyboardCode::VKEY_LCONTROL, + KeycodeConverter::DomCodeToNativeKeycode(control_dom_code), + next_time_stamp())); + ASSERT_FALSE(win::IsCtrlPressed()); + ASSERT_TRUE(win::IsAltPressed()); + ASSERT_TRUE(win::IsAltRightPressed()); + ASSERT_FALSE(win::IsWindowsKeyPressed()); + + SendModifierKeyUpEvent(altgr_key_code, altgr_dom_code); + ASSERT_FALSE(win::IsCtrlPressed()); + ASSERT_FALSE(win::IsAltPressed()); + ASSERT_FALSE(win::IsAltRightPressed()); + ASSERT_FALSE(win::IsWindowsKeyPressed()); +} + +TEST_F(KeyboardHookWinTest, NonInterceptedKeysTest) { + // Here we try a few keys we do not expect to be intercepted / handled. + ASSERT_FALSE(keyboard_hook()->ProcessKeyEventMessage( + WM_KEYDOWN, KeyboardCode::VKEY_RSHIFT, + KeycodeConverter::DomCodeToNativeKeycode(DomCode::SHIFT_RIGHT), + next_time_stamp())); + ASSERT_FALSE(keyboard_hook()->ProcessKeyEventMessage( + WM_KEYUP, KeyboardCode::VKEY_RSHIFT, + KeycodeConverter::DomCodeToNativeKeycode(DomCode::SHIFT_RIGHT), + next_time_stamp())); + + ASSERT_FALSE(keyboard_hook()->ProcessKeyEventMessage( + WM_KEYDOWN, KeyboardCode::VKEY_MEDIA_PLAY_PAUSE, + KeycodeConverter::DomCodeToNativeKeycode(DomCode::MEDIA_PLAY_PAUSE), + next_time_stamp())); + ASSERT_FALSE(keyboard_hook()->ProcessKeyEventMessage( + WM_KEYUP, KeyboardCode::VKEY_MEDIA_PLAY_PAUSE, + KeycodeConverter::DomCodeToNativeKeycode(DomCode::MEDIA_PLAY_PAUSE), + next_time_stamp())); + + ASSERT_FALSE(keyboard_hook()->ProcessKeyEventMessage( + WM_KEYDOWN, KeyboardCode::VKEY_A, + KeycodeConverter::DomCodeToNativeKeycode(DomCode::US_A), + next_time_stamp())); + ASSERT_FALSE(keyboard_hook()->ProcessKeyEventMessage( + WM_KEYUP, KeyboardCode::VKEY_A, + KeycodeConverter::DomCodeToNativeKeycode(DomCode::US_A), + next_time_stamp())); +} + +} // namespace ui
diff --git a/ui/file_manager/file_manager/test/crostini.js b/ui/file_manager/file_manager/test/crostini.js index 1e94667..cde9238 100644 --- a/ui/file_manager/file_manager/test/crostini.js +++ b/ui/file_manager/file_manager/test/crostini.js
@@ -97,7 +97,7 @@ .then(() => { // Click OK button to close. assertTrue(test.fakeMouseClick('button.cr-dialog-ok')); - return test.waitForElementLost('.cr-dialog-container.shown'); + return test.waitForElementLost('.cr-dialog-container'); }) .then(() => { // Reset chrome.fileManagerPrivate.mountCrostini. @@ -215,7 +215,7 @@ 'Let Linux apps open <b>hello.txt</b>.', document.querySelector('.cr-dialog-text').innerHTML); assertTrue(test.fakeMouseClick('button.cr-dialog-ok')); - return test.waitForElementLost('.cr-dialog-container.shown'); + return test.waitForElementLost('.cr-dialog-container'); }) .then(() => { // Ensure fmp.sharePathWithCrostini, fmp.executeTask called. @@ -275,7 +275,7 @@ 'first copy to Linux files folder.', document.querySelector('.cr-dialog-text').innerText); assertTrue(test.fakeMouseClick('button.cr-dialog-ok')); - return test.waitForElementLost('.cr-dialog-container.shown'); + return test.waitForElementLost('.cr-dialog-container'); }) .then(() => { // Restore fmp.getFileTasks.
diff --git a/ui/file_manager/file_manager/test/js/chrome_file_manager_private_test_impl.js b/ui/file_manager/file_manager/test/js/chrome_file_manager_private_test_impl.js index 1e36a99..a83ec3e 100644 --- a/ui/file_manager/file_manager/test/js/chrome_file_manager_private_test_impl.js +++ b/ui/file_manager/file_manager/test/js/chrome_file_manager_private_test_impl.js
@@ -277,8 +277,9 @@ } } } - var error = - new Error('webkitResolveLocalFileSystemURL not found: [' + url + ']'); + const message = `webkitResolveLocalFileSystemURL not found: ${url}`; + console.warn(message); + const error = new DOMException(message, 'NotFoundError'); if (errorCallback) { setTimeout(errorCallback, 0, error); } else {
diff --git a/ui/file_manager/integration_tests/file_manager/context_menu.js b/ui/file_manager/integration_tests/file_manager/context_menu.js index f7364ca..9640afc 100644 --- a/ui/file_manager/integration_tests/file_manager/context_menu.js +++ b/ui/file_manager/integration_tests/file_manager/context_menu.js
@@ -276,22 +276,6 @@ }; /** - * Tests that the New Folder menu item is enabled if a read-write folder is - * selected. - */ -testcase.checkNewFolderEnabledForReadWriteFolder = function() { - checkContextMenu('new-folder', 'photos', true); -}; - -/** - * Tests that the New Folder menu item is disabled if a read-only folder is - * selected. - */ -testcase.checkNewFolderDisabledForReadOnlyFolder = function() { - checkContextMenu('new-folder', 'Read-Only Folder', false); -}; - -/** * Tests that text selection context menus are disabled in tablet mode. */ testcase.checkContextMenusForInputElements = function() {
diff --git a/ui/gfx/BUILD.gn b/ui/gfx/BUILD.gn index 10bfb43..9ae47c3 100644 --- a/ui/gfx/BUILD.gn +++ b/ui/gfx/BUILD.gn
@@ -224,6 +224,8 @@ "skia_vector_animation.cc", "skia_vector_animation.h", "skia_vector_animation_observer.h", + "skottie_wrapper.cc", + "skottie_wrapper.h", ] }
diff --git a/ui/gfx/skia_vector_animation.cc b/ui/gfx/skia_vector_animation.cc index 191e327..8e16dc9 100644 --- a/ui/gfx/skia_vector_animation.cc +++ b/ui/gfx/skia_vector_animation.cc
@@ -13,6 +13,7 @@ #include "ui/gfx/image/image_skia.h" #include "ui/gfx/skia_util.h" #include "ui/gfx/skia_vector_animation_observer.h" +#include "ui/gfx/skottie_wrapper.h" namespace gfx { @@ -68,15 +69,8 @@ return end_offset_.InMillisecondsF() * progress_per_millisecond_; } -SkiaVectorAnimation::SkiaVectorAnimation( - const scoped_refptr<base::RefCountedMemory>& data_stream) { - TRACE_EVENT0("ui", "SkiaVectorAnimation Parse"); - SkMemoryStream sk_stream(data_stream->front(), data_stream->size()); - animation_ = skottie::Animation::Make(&sk_stream); -} - -SkiaVectorAnimation::SkiaVectorAnimation(std::unique_ptr<SkMemoryStream> stream) - : animation_(skottie::Animation::Make(stream.get())) {} +SkiaVectorAnimation::SkiaVectorAnimation(scoped_refptr<SkottieWrapper> skottie) + : skottie_(skottie) {} SkiaVectorAnimation::~SkiaVectorAnimation() {} @@ -88,13 +82,13 @@ base::TimeDelta SkiaVectorAnimation::GetAnimationDuration() const { return base::TimeDelta::FromMilliseconds( - std::floor(SkScalarToFloat(animation_->duration()) * 1000.f)); + std::floor(SkScalarToFloat(skottie_->duration()) * 1000.f)); } gfx::Size SkiaVectorAnimation::GetOriginalSize() const { #if DCHECK_IS_ON() // The size should have no fractional component. - gfx::SizeF float_size = gfx::SkSizeToSizeF(animation_->size()); + gfx::SizeF float_size = gfx::SkSizeToSizeF(skottie_->size()); gfx::Size rounded_size = gfx::ToRoundedSize(float_size); float height_diff = std::abs(float_size.height() - rounded_size.height()); @@ -103,7 +97,7 @@ DCHECK_LE(height_diff, std::numeric_limits<float>::epsilon()); DCHECK_LE(width_diff, std::numeric_limits<float>::epsilon()); #endif - return gfx::ToRoundedSize(gfx::SkSizeToSizeF(animation_->size())); + return gfx::ToRoundedSize(gfx::SkSizeToSizeF(skottie_->size())); } void SkiaVectorAnimation::Start(Style style) { @@ -158,8 +152,7 @@ } else { // It may be that the timer hasn't been initialized which may happen if // the animation was paused while it was in |kScheculePlay| state. - return scheduled_start_offset_.InMillisecondsF() / - animation_->duration(); + return scheduled_start_offset_.InMillisecondsF() / skottie_->duration(); } case PlayState::kSchedulePlay: case PlayState::kPlaying: @@ -214,17 +207,16 @@ DCHECK_GE(t, 0.f); DCHECK_LE(t, 1.f); - animation_->seek(t); float scale = canvas->UndoDeviceScaleFactor(); + gfx::Size pixel_size = gfx::ScaleToRoundedSize(size, scale); SkBitmap bitmap; - bitmap.allocN32Pixels(std::round(size.width() * scale), - std::round(size.height() * scale), false); + bitmap.allocN32Pixels(std::round(pixel_size.width()), + std::round(pixel_size.height()), false); SkCanvas skcanvas(bitmap); skcanvas.clear(SK_ColorTRANSPARENT); - SkRect dst = SkRect::MakeXYWH(0, 0, std::round(size.width() * scale), - std::round(size.height() * scale)); - animation_->render(&skcanvas, &dst); + + skottie_->Draw(&skcanvas, t, pixel_size); canvas->DrawImageInt(gfx::ImageSkia::CreateFrom1xBitmap(bitmap), 0, 0); }
diff --git a/ui/gfx/skia_vector_animation.h b/ui/gfx/skia_vector_animation.h index f0c133f..14081bfd 100644 --- a/ui/gfx/skia_vector_animation.h +++ b/ui/gfx/skia_vector_animation.h
@@ -20,6 +20,7 @@ class Canvas; class SkiaVectorAnimationTest; class SkiaVectorAnimationObserver; +class SkottieWrapper; // This class is a wrapper over the Skia object for lottie vector graphic // animations. It has its own timeline manager for the animation controls. The @@ -80,9 +81,7 @@ kLoop // Same as LINEAR, except the animation repeats after it ends. }; - explicit SkiaVectorAnimation( - const scoped_refptr<base::RefCountedMemory>& data_stream); - explicit SkiaVectorAnimation(std::unique_ptr<SkMemoryStream> stream); + explicit SkiaVectorAnimation(scoped_refptr<SkottieWrapper> skottie); ~SkiaVectorAnimation(); void SetAnimationObserver(SkiaVectorAnimationObserver* Observer); @@ -138,6 +137,9 @@ // paint. void PaintFrame(gfx::Canvas* canvas, float t, const gfx::Size& size); + // Returns the skottie object that contins the animation data. + scoped_refptr<SkottieWrapper> skottie() const { return skottie_; } + private: friend class SkiaVectorAnimationTest; @@ -229,7 +231,7 @@ SkiaVectorAnimationObserver* observer_ = nullptr; - sk_sp<skottie::Animation> animation_; + scoped_refptr<SkottieWrapper> skottie_; DISALLOW_COPY_AND_ASSIGN(SkiaVectorAnimation); };
diff --git a/ui/gfx/skia_vector_animation_unittest.cc b/ui/gfx/skia_vector_animation_unittest.cc index f9d9737..e7394e2 100644 --- a/ui/gfx/skia_vector_animation_unittest.cc +++ b/ui/gfx/skia_vector_animation_unittest.cc
@@ -15,6 +15,7 @@ #include "third_party/skia/include/core/SkStream.h" #include "ui/gfx/canvas.h" #include "ui/gfx/skia_vector_animation_observer.h" +#include "ui/gfx/skottie_wrapper.h" namespace gfx { namespace { @@ -101,6 +102,9 @@ void SetUp() override { canvas_.reset(new gfx::Canvas(gfx::Size(kAnimationWidth, kAnimationHeight), 1.f, false)); + skottie_ = base::MakeRefCounted<SkottieWrapper>( + std::make_unique<SkMemoryStream>(kData, std::strlen(kData))); + animation_ = std::make_unique<SkiaVectorAnimation>(skottie_); } void TearDown() override { animation_.reset(nullptr); } @@ -186,6 +190,7 @@ protected: std::unique_ptr<SkiaVectorAnimation> animation_; + scoped_refptr<SkottieWrapper> skottie_; private: std::unique_ptr<gfx::Canvas> canvas_; @@ -197,15 +202,17 @@ TEST_F(SkiaVectorAnimationTest, InitializationAndLoadingData) { auto bytes = base::MakeRefCounted<base::RefCountedBytes>( std::vector<unsigned char>(kData, kData + std::strlen(kData))); - animation_ = std::make_unique<SkiaVectorAnimation>(bytes.get()); + skottie_ = base::MakeRefCounted<SkottieWrapper>(bytes.get()); + animation_ = std::make_unique<SkiaVectorAnimation>(skottie_); EXPECT_FLOAT_EQ(animation_->GetOriginalSize().width(), kAnimationWidth); EXPECT_FLOAT_EQ(animation_->GetOriginalSize().height(), kAnimationHeight); EXPECT_FLOAT_EQ(animation_->GetAnimationDuration().InSecondsF(), kAnimationDuration); EXPECT_TRUE(IsStopped()); - animation_ = std::make_unique<SkiaVectorAnimation>( + skottie_ = base::MakeRefCounted<SkottieWrapper>( std::make_unique<SkMemoryStream>(kData, std::strlen(kData))); + animation_ = std::make_unique<SkiaVectorAnimation>(skottie_); EXPECT_FLOAT_EQ(animation_->GetOriginalSize().width(), kAnimationWidth); EXPECT_FLOAT_EQ(animation_->GetOriginalSize().height(), kAnimationHeight); EXPECT_FLOAT_EQ(animation_->GetAnimationDuration().InSecondsF(), @@ -215,8 +222,6 @@ TEST_F(SkiaVectorAnimationTest, PlayLinearAnimation) { TestAnimationObserver observer; - animation_ = std::make_unique<SkiaVectorAnimation>( - std::make_unique<SkMemoryStream>(kData, std::strlen(kData))); animation_->SetAnimationObserver(&observer); // Advance clock by 300 milliseconds. @@ -256,8 +261,6 @@ TEST_F(SkiaVectorAnimationTest, StopLinearAnimation) { TestAnimationObserver observer; - animation_ = std::make_unique<SkiaVectorAnimation>( - std::make_unique<SkMemoryStream>(kData, std::strlen(kData))); animation_->SetAnimationObserver(&observer); // Advance clock by 300 milliseconds. @@ -285,8 +288,6 @@ TestAnimationObserver observer; - animation_ = std::make_unique<SkiaVectorAnimation>( - std::make_unique<SkMemoryStream>(kData, std::strlen(kData))); animation_->SetAnimationObserver(&observer); // Advance clock by 300 milliseconds. @@ -344,8 +345,6 @@ const int start_time_ms = 400; const int duration_ms = 1000; const float total_duration_ms = kAnimationDuration * 1000.f; - animation_ = std::make_unique<SkiaVectorAnimation>( - std::make_unique<SkMemoryStream>(kData, std::strlen(kData))); TestAnimationObserver observer; animation_->SetAnimationObserver(&observer); @@ -390,8 +389,6 @@ TEST_F(SkiaVectorAnimationTest, PlayLoopAnimation) { TestAnimationObserver observer; - animation_ = std::make_unique<SkiaVectorAnimation>( - std::make_unique<SkMemoryStream>(kData, std::strlen(kData))); animation_->SetAnimationObserver(&observer); // Advance clock by 300 milliseconds. @@ -436,8 +433,6 @@ const int duration_ms = 1000; const float total_duration_ms = kAnimationDuration * 1000.f; - animation_ = std::make_unique<SkiaVectorAnimation>( - std::make_unique<SkMemoryStream>(kData, std::strlen(kData))); TestAnimationObserver observer; animation_->SetAnimationObserver(&observer); @@ -498,8 +493,6 @@ const int start_time_ms = 400; const int duration_ms = 1000; const float total_duration_ms = kAnimationDuration * 1000.f; - animation_ = std::make_unique<SkiaVectorAnimation>( - std::make_unique<SkMemoryStream>(kData, std::strlen(kData))); TestAnimationObserver observer; animation_->SetAnimationObserver(&observer); @@ -550,8 +543,6 @@ } TEST_F(SkiaVectorAnimationTest, PlayThrobbingAnimation) { - animation_ = std::make_unique<SkiaVectorAnimation>( - std::make_unique<SkMemoryStream>(kData, std::strlen(kData))); TestAnimationObserver observer; animation_->SetAnimationObserver(&observer); @@ -607,8 +598,6 @@ const int duration_ms = 1000; const float total_duration_ms = kAnimationDuration * 1000.f; - animation_ = std::make_unique<SkiaVectorAnimation>( - std::make_unique<SkMemoryStream>(kData, std::strlen(kData))); TestAnimationObserver observer; animation_->SetAnimationObserver(&observer); @@ -688,8 +677,6 @@ const int start_time_ms = 400; const int duration_ms = 1000; const float total_duration_ms = kAnimationDuration * 1000.f; - animation_ = std::make_unique<SkiaVectorAnimation>( - std::make_unique<SkMemoryStream>(kData, std::strlen(kData))); AdvanceClock(200); @@ -782,8 +769,6 @@ // Test to see if the race condition is handled correctly. It may happen that // we pause the video before it even starts playing. - animation_ = std::make_unique<SkiaVectorAnimation>( - std::make_unique<SkMemoryStream>(kData, std::strlen(kData))); TestAnimationObserver observer; animation_->SetAnimationObserver(&observer); @@ -814,8 +799,6 @@ TEST_F(SkiaVectorAnimationTest, PaintTest) { std::unique_ptr<gfx::Canvas> canvas(new gfx::Canvas( gfx::Size(kAnimationWidth, kAnimationHeight), 1.f, false)); - animation_ = std::make_unique<SkiaVectorAnimation>( - std::make_unique<SkMemoryStream>(kData, std::strlen(kData))); // Advance clock by 300 milliseconds. AdvanceClock(300);
diff --git a/ui/gfx/skottie_wrapper.cc b/ui/gfx/skottie_wrapper.cc new file mode 100644 index 0000000..1cba085f --- /dev/null +++ b/ui/gfx/skottie_wrapper.cc
@@ -0,0 +1,36 @@ +// 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 "ui/gfx/skottie_wrapper.h" + +#include "base/memory/ref_counted_memory.h" +#include "base/trace_event/trace_event.h" +#include "third_party/skia/include/core/SkRect.h" +#include "third_party/skia/include/core/SkStream.h" +#include "ui/gfx/geometry/size.h" + +namespace gfx { + +SkottieWrapper::SkottieWrapper( + const scoped_refptr<base::RefCountedMemory>& data_stream) { + TRACE_EVENT0("ui", "SkottieWrapper Parse"); + SkMemoryStream sk_stream(data_stream->front(), data_stream->size()); + animation_ = skottie::Animation::Make(&sk_stream); +} + +SkottieWrapper::SkottieWrapper(std::unique_ptr<SkMemoryStream> stream) + : animation_(skottie::Animation::Make(stream.get())) {} + +SkottieWrapper::~SkottieWrapper() {} + +void SkottieWrapper::Draw(SkCanvas* canvas, float t, const gfx::Size& size) { + SkRect dst = SkRect::MakeXYWH(0, 0, size.width(), size.height()); + { + base::AutoLock lock(lock_); + animation_->seek(t); + animation_->render(canvas, &dst); + } +} + +} // namespace gfx
diff --git a/ui/gfx/skottie_wrapper.h b/ui/gfx/skottie_wrapper.h new file mode 100644 index 0000000..006d0cd2 --- /dev/null +++ b/ui/gfx/skottie_wrapper.h
@@ -0,0 +1,55 @@ +// 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 UI_GFX_SKOTTIE_WRAPPER_H_ +#define UI_GFX_SKOTTIE_WRAPPER_H_ + +#include <memory> + +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/synchronization/lock.h" +#include "third_party/skia/modules/skottie/include/Skottie.h" +#include "ui/gfx/gfx_export.h" + +class SkCanvas; +class SkMemoryStream; + +namespace base { +class RefCountedMemory; +} // namespace base + +namespace gfx { +class Size; + +// A wrapper over Skia's Skottie object that can be shared by multiple +// SkiaVectorAnimation objects. This class is thread safe when performing a draw +// on an SkCanvas. +class GFX_EXPORT SkottieWrapper + : public base::RefCountedThreadSafe<SkottieWrapper> { + public: + explicit SkottieWrapper( + const scoped_refptr<base::RefCountedMemory>& data_stream); + explicit SkottieWrapper(std::unique_ptr<SkMemoryStream> stream); + + // A thread safe call that will draw an image of size |size| for the frame at + // normalized time instant |t| onto the |canvas|. + void Draw(SkCanvas* canvas, float t, const Size& size); + + float duration() const { return animation_->duration(); } + SkSize size() const { return animation_->size(); } + + private: + friend class base::RefCountedThreadSafe<SkottieWrapper>; + ~SkottieWrapper(); + + base::Lock lock_; + sk_sp<skottie::Animation> animation_; + + DISALLOW_COPY_AND_ASSIGN(SkottieWrapper); +}; + +} // namespace gfx + +#endif // UI_GFX_SKOTTIE_WRAPPER_H_
diff --git a/ui/gl/BUILD.gn b/ui/gl/BUILD.gn index 77eae44..51b1afd 100644 --- a/ui/gl/BUILD.gn +++ b/ui/gl/BUILD.gn
@@ -128,6 +128,7 @@ "gpu_switching_manager.h", "gpu_timing.cc", "gpu_timing.h", + "progress_reporter.h", "scoped_binders.cc", "scoped_binders.h", "scoped_make_current.cc",
diff --git a/ui/gl/gl_surface_egl.cc b/ui/gl/gl_surface_egl.cc index 00cdf20..2c96347a 100644 --- a/ui/gl/gl_surface_egl.cc +++ b/ui/gl/gl_surface_egl.cc
@@ -16,6 +16,7 @@ #include "base/logging.h" #include "base/macros.h" #include "base/metrics/histogram_macros.h" +#include "base/stl_util.h" #include "base/strings/string_number_conversions.h" #include "base/sys_info.h" #include "base/trace_event/trace_event.h" @@ -492,10 +493,8 @@ void AddInitDisplay(std::vector<DisplayType>* init_displays, DisplayType display_type) { // Make sure to not add the same display type twice. - if (std::find(init_displays->begin(), init_displays->end(), display_type) == - init_displays->end()) { + if (!base::ContainsValue(*init_displays, display_type)) init_displays->push_back(display_type); - } } const char* GetDebugMessageTypeString(EGLint source) {
diff --git a/ui/gl/init/create_gr_gl_interface.cc b/ui/gl/init/create_gr_gl_interface.cc index b8634d2..598b98cdf 100644 --- a/ui/gl/init/create_gr_gl_interface.cc +++ b/ui/gl/init/create_gr_gl_interface.cc
@@ -5,6 +5,7 @@ #include "ui/gl/init/create_gr_gl_interface.h" #include "ui/gl/gl_bindings.h" #include "ui/gl/gl_version_info.h" +#include "ui/gl/progress_reporter.h" namespace gl { namespace init { @@ -17,6 +18,28 @@ return [func, api](Args... args) { return (api->*func)(args...); }; } +class ScopedProgressReporter { + public: + ScopedProgressReporter(gl::ProgressReporter* progress_reporter) + : progress_reporter_(progress_reporter) {} + ~ScopedProgressReporter() { progress_reporter_->ReportProgress(); } + + private: + gl::ProgressReporter* progress_reporter_; +}; + +template <typename R, typename... Args> +GrGLFunction<R GR_GL_FUNCTION_TYPE(Args...)> bind_slow( + R(GL_BINDING_CALL* func)(Args...), + gl::ProgressReporter* progress_reporter) { + if (!progress_reporter) + return func; + return [func, progress_reporter](Args... args) { + ScopedProgressReporter scoped_reporter(progress_reporter); + return func(args...); + }; +}; + const GLubyte* GetStringHook(const char* version_string, GLenum name) { switch (name) { case GL_VERSION: @@ -47,7 +70,8 @@ sk_sp<GrGLInterface> CreateGrGLInterface( const gl::GLVersionInfo& version_info, - bool use_version_es2) { + bool use_version_es2, + gl::ProgressReporter* progress_reporter) { // Can't fake ES with desktop GL. use_version_es2 &= version_info.is_es; @@ -119,17 +143,23 @@ // functions->fClearTexSubImage = nullptr; functions->fColorMask = gl->glColorMaskFn; - functions->fCompileShader = gl->glCompileShaderFn; - functions->fCompressedTexImage2D = gl->glCompressedTexImage2DFn; - functions->fCompressedTexSubImage2D = gl->glCompressedTexSubImage2DFn; - functions->fCopyTexSubImage2D = gl->glCopyTexSubImage2DFn; + functions->fCompileShader = + bind_slow(gl->glCompileShaderFn, progress_reporter); + functions->fCompressedTexImage2D = + bind_slow(gl->glCompressedTexImage2DFn, progress_reporter); + functions->fCompressedTexSubImage2D = + bind_slow(gl->glCompressedTexSubImage2DFn, progress_reporter); + functions->fCopyTexSubImage2D = + bind_slow(gl->glCopyTexSubImage2DFn, progress_reporter); functions->fCreateProgram = gl->glCreateProgramFn; functions->fCreateShader = gl->glCreateShaderFn; functions->fCullFace = gl->glCullFaceFn; - functions->fDeleteBuffers = gl->glDeleteBuffersARBFn; - functions->fDeleteProgram = gl->glDeleteProgramFn; + functions->fDeleteBuffers = + bind_slow(gl->glDeleteBuffersARBFn, progress_reporter); + functions->fDeleteProgram = + bind_slow(gl->glDeleteProgramFn, progress_reporter); functions->fDeleteQueries = gl->glDeleteQueriesFn; - functions->fDeleteShader = gl->glDeleteShaderFn; + functions->fDeleteShader = bind_slow(gl->glDeleteShaderFn, progress_reporter); functions->fDeleteTextures = gl->glDeleteTexturesFn; functions->fDepthMask = gl->glDepthMaskFn; functions->fDisable = gl->glDisableFn; @@ -151,8 +181,8 @@ functions->fEnable = gl->glEnableFn; functions->fEnableVertexAttribArray = gl->glEnableVertexAttribArrayFn; functions->fEndQuery = gl->glEndQueryFn; - functions->fFinish = gl->glFinishFn; - functions->fFlush = gl->glFlushFn; + functions->fFinish = bind_slow(gl->glFinishFn, progress_reporter); + functions->fFlush = bind_slow(gl->glFlushFn, progress_reporter); functions->fFrontFace = gl->glFrontFaceFn; functions->fGenBuffers = gl->glGenBuffersARBFn; functions->fGetBufferParameteriv = gl->glGetBufferParameterivFn; @@ -179,7 +209,7 @@ functions->fGetUniformLocation = gl->glGetUniformLocationFn; functions->fIsTexture = gl->glIsTextureFn; functions->fLineWidth = gl->glLineWidthFn; - functions->fLinkProgram = gl->glLinkProgramFn; + functions->fLinkProgram = bind_slow(gl->glLinkProgramFn, progress_reporter); functions->fMapBuffer = gl->glMapBufferFn; // GL 4.3 or GL_ARB_multi_draw_indirect or ES+GL_EXT_multi_draw_indirect @@ -206,7 +236,7 @@ functions->fStencilOpSeparate = gl->glStencilOpSeparateFn; functions->fTexBuffer = gl->glTexBufferFn; functions->fTexBufferRange = gl->glTexBufferRangeFn; - functions->fTexImage2D = gl->glTexImage2DFn; + functions->fTexImage2D = bind_slow(gl->glTexImage2DFn, progress_reporter); functions->fTexParameteri = gl->glTexParameteriFn; functions->fTexParameteriv = gl->glTexParameterivFn; functions->fTexStorage2D = gl->glTexStorage2DEXTFn; @@ -266,7 +296,8 @@ functions->fBindFramebuffer = gl->glBindFramebufferEXTFn; functions->fFramebufferTexture2D = gl->glFramebufferTexture2DEXTFn; functions->fCheckFramebufferStatus = gl->glCheckFramebufferStatusEXTFn; - functions->fDeleteFramebuffers = gl->glDeleteFramebuffersEXTFn; + functions->fDeleteFramebuffers = + bind_slow(gl->glDeleteFramebuffersEXTFn, progress_reporter); functions->fRenderbufferStorage = gl->glRenderbufferStorageEXTFn; functions->fGenRenderbuffers = gl->glGenRenderbuffersEXTFn; functions->fDeleteRenderbuffers = gl->glDeleteRenderbuffersEXTFn;
diff --git a/ui/gl/init/create_gr_gl_interface.h b/ui/gl/init/create_gr_gl_interface.h index 4b23ee7..9243fbe 100644 --- a/ui/gl/init/create_gr_gl_interface.h +++ b/ui/gl/init/create_gr_gl_interface.h
@@ -11,6 +11,7 @@ namespace gl { struct GLVersionInfo; +class ProgressReporter; } namespace gl { @@ -20,7 +21,8 @@ // GL bindings. GL_INIT_EXPORT sk_sp<GrGLInterface> CreateGrGLInterface( const gl::GLVersionInfo& version_info, - bool use_version_es2); + bool use_version_es2, + gl::ProgressReporter* progress_reporter = nullptr); } // namespace init } // namespace gl
diff --git a/ui/gl/progress_reporter.h b/ui/gl/progress_reporter.h new file mode 100644 index 0000000..5ebcfe0 --- /dev/null +++ b/ui/gl/progress_reporter.h
@@ -0,0 +1,22 @@ +// Copyright (c) 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_GL_PROGRESS_REPORTER_H_ +#define UI_GL_PROGRESS_REPORTER_H_ + +namespace gl { + +// ProgressReporter is used by ContextGroup and GrGLInterface to report when it +// is making forward progress in execution, delaying activation of the watchdog +// timeout. +class ProgressReporter { + public: + virtual ~ProgressReporter() = default; + + virtual void ReportProgress() = 0; +}; + +} // namespace gl + +#endif // UI_GL_PROGRESS_REPORTER_H_
diff --git a/ui/gl/test/gl_image_test_support.cc b/ui/gl/test/gl_image_test_support.cc index 659cedf..c4a0840 100644 --- a/ui/gl/test/gl_image_test_support.cc +++ b/ui/gl/test/gl_image_test_support.cc
@@ -6,6 +6,7 @@ #include <vector> +#include "base/stl_util.h" #include "ui/gfx/buffer_format_util.h" #include "ui/gfx/half_float.h" #include "ui/gl/init/gl_factory.h" @@ -33,8 +34,7 @@ DCHECK(!allowed_impls.empty()); GLImplementation impl = prefered_impl ? *prefered_impl : allowed_impls[0]; - DCHECK(std::find(allowed_impls.begin(), allowed_impls.end(), impl) != - allowed_impls.end()); + DCHECK(base::ContainsValue(allowed_impls, impl)); GLSurfaceTestSupport::InitializeOneOffImplementation(impl, true); #if defined(USE_OZONE)
diff --git a/ui/ozone/platform/wayland/BUILD.gn b/ui/ozone/platform/wayland/BUILD.gn index 7d3c40afd..9740ad9 100644 --- a/ui/ozone/platform/wayland/BUILD.gn +++ b/ui/ozone/platform/wayland/BUILD.gn
@@ -43,14 +43,16 @@ "wayland_input_method_context_factory.h", "wayland_keyboard.cc", "wayland_keyboard.h", - "wayland_native_display_delegate.cc", - "wayland_native_display_delegate.h", "wayland_object.cc", "wayland_object.h", "wayland_output.cc", "wayland_output.h", + "wayland_output_manager.cc", + "wayland_output_manager.h", "wayland_pointer.cc", "wayland_pointer.h", + "wayland_screen.cc", + "wayland_screen.h", "wayland_surface_factory.cc", "wayland_surface_factory.h", "wayland_touch.cc", @@ -114,6 +116,7 @@ "//ui/ozone/common/linux", "//ui/ozone/public/interfaces/wayland:wayland_interfaces", "//ui/platform_window", + "//ui/platform_window/platform_window_handler", ] defines = [ "OZONE_IMPLEMENTATION" ] @@ -156,6 +159,7 @@ "wayland_input_method_context_unittest.cc", "wayland_keyboard_unittest.cc", "wayland_pointer_unittest.cc", + "wayland_screen_unittest.cc", "wayland_surface_factory_unittest.cc", "wayland_test.cc", "wayland_test.h",
diff --git a/ui/ozone/platform/wayland/DEPS b/ui/ozone/platform/wayland/DEPS index 06292b5..56a383a0 100644 --- a/ui/ozone/platform/wayland/DEPS +++ b/ui/ozone/platform/wayland/DEPS
@@ -1,4 +1,5 @@ include_rules = [ + "+ui/base/hit_test.h", # UI hit test doesn't bring in all of ui/base. "+ui/base/ui_features.h", # UI features doesn't bring in all of ui/base. "+ui/base/ui_base_features.h", "+ui/base/ime/composition_text.h",
diff --git a/ui/ozone/platform/wayland/fake_server.cc b/ui/ozone/platform/wayland/fake_server.cc index d9edf99f..62e7f8c 100644 --- a/ui/ozone/platform/wayland/fake_server.cc +++ b/ui/ozone/platform/wayland/fake_server.cc
@@ -562,6 +562,21 @@ GetUserDataAs<MockXdgSurface>(resource)->SetAppId(app_id); } +void Move(wl_client* client, + wl_resource* resource, + wl_resource* seat, + uint32_t serial) { + GetUserDataAs<MockXdgSurface>(resource)->Move(serial); +} + +void Resize(wl_client* client, + wl_resource* resource, + wl_resource* seat, + uint32_t serial, + uint32_t edges) { + GetUserDataAs<MockXdgSurface>(resource)->Resize(serial, edges); +} + void AckConfigure(wl_client* client, wl_resource* resource, uint32_t serial) { GetUserDataAs<MockXdgSurface>(resource)->AckConfigure(serial); } @@ -604,8 +619,8 @@ &SetTitle, // set_title &SetAppId, // set_app_id nullptr, // show_window_menu - nullptr, // move - nullptr, // resize + &Move, // move + &Resize, // resize &AckConfigure, // ack_configure &SetWindowGeometry, // set_window_geometry &SetMaximized, // set_maximized @@ -707,8 +722,8 @@ &SetTitle, // set_title &SetAppId, // set_app_id nullptr, // show_window_menu - nullptr, // move - nullptr, // resize + &Move, // move + &Resize, // resize nullptr, // set_max_size nullptr, // set_min_size &SetMaximized, // set_maximized @@ -1068,7 +1083,8 @@ MockDataDeviceManager::~MockDataDeviceManager() {} MockOutput::MockOutput() - : Global(&wl_output_interface, nullptr, kOutputVersion) {} + : Global(&wl_output_interface, nullptr, kOutputVersion), + rect_(gfx::Rect(0, 0, 800, 600)) {} MockOutput::~MockOutput() {}
diff --git a/ui/ozone/platform/wayland/fake_server.h b/ui/ozone/platform/wayland/fake_server.h index 27b8f07..bd7decc8 100644 --- a/ui/ozone/platform/wayland/fake_server.h +++ b/ui/ozone/platform/wayland/fake_server.h
@@ -59,6 +59,8 @@ MOCK_METHOD1(SetParent, void(wl_resource* parent)); MOCK_METHOD1(SetTitle, void(const char* title)); MOCK_METHOD1(SetAppId, void(const char* app_id)); + MOCK_METHOD1(Move, void(uint32_t serial)); + MOCK_METHOD2(Resize, void(uint32_t serial, uint32_t edges)); MOCK_METHOD1(AckConfigure, void(uint32_t serial)); MOCK_METHOD4(SetWindowGeometry, void(int32_t x, int32_t y, int32_t width, int32_t height)); @@ -459,6 +461,8 @@ return &zwp_text_input_manager_v1_; } + wl_display* display() const { return display_.get(); } + private: void DoPause();
diff --git a/ui/ozone/platform/wayland/ozone_platform_wayland.cc b/ui/ozone/platform/wayland/ozone_platform_wayland.cc index f845a6b..8074471 100644 --- a/ui/ozone/platform/wayland/ozone_platform_wayland.cc +++ b/ui/ozone/platform/wayland/ozone_platform_wayland.cc
@@ -15,12 +15,13 @@ #include "ui/ozone/platform/wayland/wayland_connection.h" #include "ui/ozone/platform/wayland/wayland_connection_connector.h" #include "ui/ozone/platform/wayland/wayland_input_method_context_factory.h" -#include "ui/ozone/platform/wayland/wayland_native_display_delegate.h" +#include "ui/ozone/platform/wayland/wayland_output_manager.h" #include "ui/ozone/platform/wayland/wayland_surface_factory.h" #include "ui/ozone/platform/wayland/wayland_window.h" #include "ui/ozone/public/gpu_platform_support_host.h" #include "ui/ozone/public/input_controller.h" #include "ui/ozone/public/ozone_platform.h" +#include "ui/ozone/public/platform_screen.h" #include "ui/platform_window/platform_window_init_properties.h" #if BUILDFLAG(USE_XKBCOMMON) @@ -99,7 +100,14 @@ std::unique_ptr<display::NativeDisplayDelegate> CreateNativeDisplayDelegate() override { - return std::make_unique<WaylandNativeDisplayDelegate>(connection_.get()); + return std::make_unique<display::FakeDisplayDelegate>(); + } + + std::unique_ptr<PlatformScreen> CreateScreen() override { + // The WaylandConnection and the WaylandOutputManager must be created before + // PlatformScreen. + DCHECK(connection_ && connection_->wayland_output_manager()); + return connection_->wayland_output_manager()->CreateWaylandScreen(); } void InitializeUI(const InitParams& args) override {
diff --git a/ui/ozone/platform/wayland/wayland_connection.cc b/ui/ozone/platform/wayland/wayland_connection.cc index 0ddacd8..d4ce8fb 100644 --- a/ui/ozone/platform/wayland/wayland_connection.cc +++ b/ui/ozone/platform/wayland/wayland_connection.cc
@@ -18,6 +18,7 @@ #include "ui/ozone/platform/wayland/wayland_buffer_manager.h" #include "ui/ozone/platform/wayland/wayland_input_method_context.h" #include "ui/ozone/platform/wayland/wayland_object.h" +#include "ui/ozone/platform/wayland/wayland_output_manager.h" #include "ui/ozone/platform/wayland/wayland_window.h" static_assert(XDG_SHELL_VERSION_CURRENT == 5, "Unsupported xdg-shell version"); @@ -65,9 +66,10 @@ } wl_registry_add_listener(registry_.get(), ®istry_listener, this); - - while (!PrimaryOutput() || !PrimaryOutput()->is_ready()) + while (!wayland_output_manager_ || + !wayland_output_manager_->IsPrimaryOutputReady()) { wl_display_roundtrip(display_.get()); + } if (!compositor_) { LOG(ERROR) << "No wl_compositor object"; @@ -150,12 +152,6 @@ window_map_.erase(widget); } -WaylandOutput* WaylandConnection::PrimaryOutput() const { - if (!output_list_.size()) - return nullptr; - return output_list_.front().get(); -} - void WaylandConnection::SetCursorBitmap(const std::vector<SkBitmap>& bitmaps, const gfx::Point& location) { if (!pointer_ || !pointer_->cursor()) @@ -287,6 +283,11 @@ data_device_->RequestDragData(mime_type, std::move(callback)); } +void WaylandConnection::ResetPointerFlags() { + if (pointer_) + pointer_->ResetFlags(); +} + void WaylandConnection::GetAvailableMimeTypes( ClipboardDelegate::GetMimeTypesClosure callback) { std::move(callback).Run(data_device_->GetAvailableMimeTypes()); @@ -340,11 +341,6 @@ buffer_manager_->ClearState(); } -const std::vector<std::unique_ptr<WaylandOutput>>& -WaylandConnection::GetOutputList() const { - return output_list_; -} - // static void WaylandConnection::Global(void* data, wl_registry* registry, @@ -428,11 +424,12 @@ return; } - if (!connection->output_list_.empty()) - NOTIMPLEMENTED() << "Multiple screens support is not implemented"; - - connection->output_list_.push_back(base::WrapUnique(new WaylandOutput( - connection->get_next_display_id(), output.release()))); + if (!connection->wayland_output_manager_) { + connection->wayland_output_manager_ = + std::make_unique<WaylandOutputManager>(); + } + connection->wayland_output_manager_->AddWaylandOutput(name, + output.release()); } else if (!connection->data_device_manager_ && strcmp(interface, "wl_data_device_manager") == 0) { wl::Object<wl_data_device_manager> data_device_manager = @@ -473,7 +470,15 @@ void WaylandConnection::GlobalRemove(void* data, wl_registry* registry, uint32_t name) { - NOTIMPLEMENTED(); + WaylandConnection* connection = static_cast<WaylandConnection*>(data); + // The Wayland protocol distinguishes global objects by unique numeric names, + // which the WaylandOutputManager uses as unique output ids. But, it is only + // possible to figure out, what global object is going to be removed on the + // WaylandConnection::GlobalRemove call. Thus, whatever unique |name| comes, + // it's forwarded to the WaylandOutputManager, which checks if such a global + // output object exists and removes it. + if (connection->wayland_output_manager_) + connection->wayland_output_manager_->RemoveWaylandOutput(name); } // static
diff --git a/ui/ozone/platform/wayland/wayland_connection.h b/ui/ozone/platform/wayland/wayland_connection.h index 15eecf7..d2487cd 100644 --- a/ui/ozone/platform/wayland/wayland_connection.h +++ b/ui/ozone/platform/wayland/wayland_connection.h
@@ -26,8 +26,9 @@ namespace ui { -class WaylandWindow; class WaylandBufferManager; +class WaylandOutputManager; +class WaylandWindow; class WaylandConnection : public PlatformEventSource, public ClipboardDelegate, @@ -71,8 +72,8 @@ wl_compositor* compositor() { return compositor_.get(); } wl_subcompositor* subcompositor() { return subcompositor_.get(); } wl_shm* shm() { return shm_.get(); } - xdg_shell* shell() { return shell_.get(); } - zxdg_shell_v6* shell_v6() { return shell_v6_.get(); } + xdg_shell* shell() const { return shell_.get(); } + zxdg_shell_v6* shell_v6() const { return shell_v6_.get(); } wl_seat* seat() { return seat_.get(); } wl_data_device* data_device() { return data_device_->data_device(); } wp_presentation* presentation() const { return presentation_.get(); } @@ -86,10 +87,6 @@ void AddWindow(gfx::AcceleratedWidget widget, WaylandWindow* window); void RemoveWindow(gfx::AcceleratedWidget widget); - int64_t get_next_display_id() { return next_display_id_++; } - const std::vector<std::unique_ptr<WaylandOutput>>& GetOutputList() const; - WaylandOutput* PrimaryOutput() const; - void set_serial(uint32_t serial) { serial_ = serial; } uint32_t serial() { return serial_; } @@ -103,6 +100,10 @@ WaylandDataSource* drag_data_source() { return drag_data_source_.get(); } + WaylandOutputManager* wayland_output_manager() const { + return wayland_output_manager_.get(); + } + // Clipboard implementation. ClipboardDelegate* GetClipboardDelegate(); void DataSourceCancelled(); @@ -146,6 +147,13 @@ void RequestDragData(const std::string& mime_type, base::OnceCallback<void(const std::string&)> callback); + // Resets flags and keyboard modifiers. + // + // This method is specially handy for cases when the WaylandPointer state is + // modified by a POINTER_DOWN event, but the respective POINTER_UP event is + // not delivered. + void ResetPointerFlags(); + private: // WaylandInputMethodContextFactory needs access to DispatchUiEvent friend class WaylandInputMethodContextFactory; @@ -198,8 +206,9 @@ std::unique_ptr<WaylandDataDevice> data_device_; std::unique_ptr<WaylandDataSource> data_source_; std::unique_ptr<WaylandDataSource> drag_data_source_; - std::unique_ptr<WaylandPointer> pointer_; std::unique_ptr<WaylandKeyboard> keyboard_; + std::unique_ptr<WaylandOutputManager> wayland_output_manager_; + std::unique_ptr<WaylandPointer> pointer_; std::unique_ptr<WaylandTouch> touch_; // Objects that are using when GPU runs in own process. @@ -211,9 +220,6 @@ uint32_t serial_ = 0; - int64_t next_display_id_ = 0; - std::vector<std::unique_ptr<WaylandOutput>> output_list_; - // Holds a temporary instance of the client's clipboard content // so that we can asynchronously write to it. ClipboardDelegate::DataMap* data_map_ = nullptr;
diff --git a/ui/ozone/platform/wayland/wayland_connection_unittest.cc b/ui/ozone/platform/wayland/wayland_connection_unittest.cc index dea1530..9c6cc51 100644 --- a/ui/ozone/platform/wayland/wayland_connection_unittest.cc +++ b/ui/ozone/platform/wayland/wayland_connection_unittest.cc
@@ -8,42 +8,14 @@ #include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/display/types/display_snapshot.h" #include "ui/ozone/platform/wayland/fake_server.h" #include "ui/ozone/platform/wayland/wayland_connection.h" -#include "ui/ozone/platform/wayland/wayland_output.h" namespace ui { namespace { - -const uint32_t kXdgVersion5 = 5; -const uint32_t kNumOfDisplays = 1; -const uint32_t kWidth = 800; -const uint32_t kHeight = 600; - -void CheckDisplaySize(const std::vector<display::DisplaySnapshot*>& displays) { - ASSERT_TRUE(displays.size() == kNumOfDisplays); - - // TODO(msisov): add multiple displays support. - display::DisplaySnapshot* display_snapshot = displays.front(); - ASSERT_TRUE(display_snapshot->current_mode()->size() == - gfx::Size(kWidth, kHeight)); +constexpr uint32_t kXdgVersion5 = 5; } -} - -class OutputObserver : public WaylandOutput::Observer { - public: - explicit OutputObserver(const base::Closure& closure) : closure_(closure) {} - - void OnOutputReadyForUse() override { - if (!closure_.is_null()) - closure_.Run(); - } - - private: - const base::Closure closure_; -}; TEST(WaylandConnectionTest, UseUnstableVersion) { base::MessageLoopForUI message_loop; @@ -78,26 +50,4 @@ server.Pause(); } -TEST(WaylandConnectionTest, Output) { - base::MessageLoopForUI message_loop; - wl::FakeServer server; - ASSERT_TRUE(server.Start(kXdgVersion5)); - server.output()->SetRect(gfx::Rect(0, 0, kWidth, kHeight)); - WaylandConnection connection; - ASSERT_TRUE(connection.Initialize()); - connection.StartProcessingEvents(); - - base::RunLoop run_loop; - OutputObserver observer(run_loop.QuitClosure()); - connection.PrimaryOutput()->SetObserver(&observer); - run_loop.Run(); - - connection.PrimaryOutput()->GetDisplaysSnapshot( - base::BindOnce(&CheckDisplaySize)); - - server.Resume(); - base::RunLoop().RunUntilIdle(); - server.Pause(); -} - } // namespace ui
diff --git a/ui/ozone/platform/wayland/wayland_native_display_delegate.cc b/ui/ozone/platform/wayland/wayland_native_display_delegate.cc deleted file mode 100644 index 029da54..0000000 --- a/ui/ozone/platform/wayland/wayland_native_display_delegate.cc +++ /dev/null
@@ -1,105 +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 "ui/ozone/platform/wayland/wayland_native_display_delegate.h" - -#include "ui/display/types/display_snapshot.h" -#include "ui/display/types/native_display_observer.h" -#include "ui/ozone/platform/wayland/wayland_connection.h" - -namespace ui { - -WaylandNativeDisplayDelegate::WaylandNativeDisplayDelegate( - WaylandConnection* connection) - : connection_(connection) {} - -WaylandNativeDisplayDelegate::~WaylandNativeDisplayDelegate() { - connection_->PrimaryOutput()->SetObserver(nullptr); -} - -void WaylandNativeDisplayDelegate::Initialize() { - // TODO(msisov): Add support for secondary output. - WaylandOutput* primary_output = connection_->PrimaryOutput(); - if (!primary_output) - NOTREACHED() << "Asynchronous display data fetching is not available"; - - primary_output->SetObserver(this); -} - -void WaylandNativeDisplayDelegate::TakeDisplayControl( - display::DisplayControlCallback callback) { - NOTREACHED(); -} - -void WaylandNativeDisplayDelegate::RelinquishDisplayControl( - display::DisplayControlCallback callback) { - NOTREACHED(); -} - -void WaylandNativeDisplayDelegate::GetDisplays( - display::GetDisplaysCallback callback) { - if (displays_ready_) - connection_->PrimaryOutput()->GetDisplaysSnapshot(std::move(callback)); -} - -void WaylandNativeDisplayDelegate::Configure( - const display::DisplaySnapshot& output, - const display::DisplayMode* mode, - const gfx::Point& origin, - display::ConfigureCallback callback) { - NOTREACHED(); -} - -void WaylandNativeDisplayDelegate::GetHDCPState( - const display::DisplaySnapshot& output, - display::GetHDCPStateCallback callback) { - NOTREACHED(); -} - -void WaylandNativeDisplayDelegate::SetHDCPState( - const display::DisplaySnapshot& output, - display::HDCPState state, - display::SetHDCPStateCallback callback) { - NOTREACHED(); -} - -bool WaylandNativeDisplayDelegate::SetColorMatrix( - int64_t display_id, - const std::vector<float>& color_matrix) { - NOTREACHED(); - return false; -} - -bool WaylandNativeDisplayDelegate::SetGammaCorrection( - int64_t display_id, - const std::vector<display::GammaRampRGBEntry>& degamma_lut, - const std::vector<display::GammaRampRGBEntry>& gamma_lut) { - NOTREACHED(); - return false; -} - -void WaylandNativeDisplayDelegate::AddObserver( - display::NativeDisplayObserver* observer) { - observers_.AddObserver(observer); -} - -void WaylandNativeDisplayDelegate::RemoveObserver( - display::NativeDisplayObserver* observer) { - observers_.RemoveObserver(observer); -} - -display::FakeDisplayController* -WaylandNativeDisplayDelegate::GetFakeDisplayController() { - return nullptr; -} - -void WaylandNativeDisplayDelegate::OnOutputReadyForUse() { - if (!displays_ready_) - displays_ready_ = true; - - for (display::NativeDisplayObserver& observer : observers_) - observer.OnConfigurationChanged(); -} - -} // namespace ui
diff --git a/ui/ozone/platform/wayland/wayland_native_display_delegate.h b/ui/ozone/platform/wayland/wayland_native_display_delegate.h deleted file mode 100644 index e0559cb3..0000000 --- a/ui/ozone/platform/wayland/wayland_native_display_delegate.h +++ /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. - -#ifndef UI_OZONE_PLATFORM_WAYLAND_WAYLAND_NATIVE_DISPLAY_DELEGATE_H_ -#define UI_OZONE_PLATFORM_WAYLAND_WAYLAND_NATIVE_DISPLAY_DELEGATE_H_ - -#include <stdint.h> - -#include "base/macros.h" -#include "base/observer_list.h" -#include "ui/display/types/native_display_delegate.h" -#include "ui/ozone/platform/wayland/wayland_output.h" - -namespace ui { - -class WaylandConnection; - -class WaylandNativeDisplayDelegate : public display::NativeDisplayDelegate, - public WaylandOutput::Observer { - public: - explicit WaylandNativeDisplayDelegate(WaylandConnection* connection); - ~WaylandNativeDisplayDelegate() override; - - // display::NativeDisplayDelegate overrides: - void Initialize() override; - void TakeDisplayControl(display::DisplayControlCallback callback) override; - void RelinquishDisplayControl( - display::DisplayControlCallback callback) override; - void GetDisplays(display::GetDisplaysCallback callback) override; - void Configure(const display::DisplaySnapshot& output, - const display::DisplayMode* mode, - const gfx::Point& origin, - display::ConfigureCallback callback) override; - void GetHDCPState(const display::DisplaySnapshot& output, - display::GetHDCPStateCallback callback) override; - void SetHDCPState(const display::DisplaySnapshot& output, - display::HDCPState state, - display::SetHDCPStateCallback callback) override; - bool SetColorMatrix(int64_t display_id, - const std::vector<float>& color_matrix) override; - bool SetGammaCorrection( - int64_t display_id, - const std::vector<display::GammaRampRGBEntry>& degamma_lut, - const std::vector<display::GammaRampRGBEntry>& gamma_lut) override; - void AddObserver(display::NativeDisplayObserver* observer) override; - void RemoveObserver(display::NativeDisplayObserver* observer) override; - display::FakeDisplayController* GetFakeDisplayController() override; - - // WaylandOutput::Observer overrides: - void OnOutputReadyForUse() override; - - private: - WaylandConnection* connection_; // Not owned. - - base::ObserverList<display::NativeDisplayObserver>::Unchecked observers_; - - bool displays_ready_ = false; - - DISALLOW_COPY_AND_ASSIGN(WaylandNativeDisplayDelegate); -}; - -} // namespace ui - -#endif // UI_OZONE_PLATFORM_WAYLAND_WAYLAND_NATIVE_DISPLAY_DELEGATE_H_
diff --git a/ui/ozone/platform/wayland/wayland_output.cc b/ui/ozone/platform/wayland/wayland_output.cc index d9f8c44..fd14f45 100644 --- a/ui/ozone/platform/wayland/wayland_output.cc +++ b/ui/ozone/platform/wayland/wayland_output.cc
@@ -11,26 +11,32 @@ namespace ui { -WaylandOutput::WaylandOutput(const int64_t display_id, wl_output* output) - : display_id_(display_id), output_(output), observer_(nullptr) { +namespace { +constexpr float kDefaultScaleFactor = 1.0f; +} + +WaylandOutput::WaylandOutput(const uint32_t output_id, wl_output* output) + : output_id_(output_id), + output_(output), + device_scale_factor_(kDefaultScaleFactor), + rect_in_physical_pixels_(gfx::Rect()) {} + +WaylandOutput::~WaylandOutput() = default; + +void WaylandOutput::Initialize(Delegate* delegate) { + DCHECK(!delegate_); + delegate_ = delegate; static const wl_output_listener output_listener = { &WaylandOutput::OutputHandleGeometry, &WaylandOutput::OutputHandleMode, + &WaylandOutput::OutputHandleDone, &WaylandOutput::OutputHandleScale, }; - wl_output_add_listener(output, &output_listener, this); + wl_output_add_listener(output_.get(), &output_listener, this); } -WaylandOutput::~WaylandOutput() {} - -void WaylandOutput::SetObserver(Observer* observer) { - observer_ = observer; - if (current_mode_) - observer_->OnOutputReadyForUse(); -} - -void WaylandOutput::GetDisplaysSnapshot(display::GetDisplaysCallback callback) { - std::vector<display::DisplaySnapshot*> snapshot; - snapshot.push_back(current_snapshot_.get()); - std::move(callback).Run(snapshot); +void WaylandOutput::TriggerDelegateNotification() const { + DCHECK(!rect_in_physical_pixels_.IsEmpty()); + delegate_->OnOutputHandleMetrics(output_id_, rect_in_physical_pixels_, + device_scale_factor_); } // static @@ -45,13 +51,8 @@ const char* model, int32_t output_transform) { WaylandOutput* wayland_output = static_cast<WaylandOutput*>(data); - wayland_output->current_snapshot_.reset(new display::DisplaySnapshot( - wayland_output->display_id_, gfx::Point(x, y), - gfx::Size(physical_width, physical_height), - display::DisplayConnectionType::DISPLAY_CONNECTION_TYPE_NONE, false, - false, false, false, gfx::ColorSpace(), model, base::FilePath(), - display::DisplaySnapshot::DisplayModeList(), std::vector<uint8_t>(), - nullptr, nullptr, 0, 0, gfx::Size())); + if (wayland_output) + wayland_output->rect_in_physical_pixels_.set_origin(gfx::Point(x, y)); } // static @@ -61,17 +62,27 @@ int32_t width, int32_t height, int32_t refresh) { - WaylandOutput* output = static_cast<WaylandOutput*>(data); + WaylandOutput* wayland_output = static_cast<WaylandOutput*>(data); + if (wayland_output && (flags & WL_OUTPUT_MODE_CURRENT)) { + wayland_output->rect_in_physical_pixels_.set_width(width); + wayland_output->rect_in_physical_pixels_.set_height(height); + wayland_output->TriggerDelegateNotification(); + } +} - if (flags & WL_OUTPUT_MODE_CURRENT) { - std::unique_ptr<display::DisplayMode> previous_mode = - std::move(output->current_mode_); - output->current_mode_.reset( - new display::DisplayMode(gfx::Size(width, height), false, refresh)); - output->current_snapshot_->set_current_mode(output->current_mode_.get()); +// static +void WaylandOutput::OutputHandleDone(void* data, struct wl_output* wl_output) { + NOTIMPLEMENTED_LOG_ONCE(); +} - if (output->observer()) - output->observer()->OnOutputReadyForUse(); +// static +void WaylandOutput::OutputHandleScale(void* data, + struct wl_output* wl_output, + int32_t factor) { + WaylandOutput* wayland_output = static_cast<WaylandOutput*>(data); + if (wayland_output) { + wayland_output->device_scale_factor_ = factor; + wayland_output->TriggerDelegateNotification(); } }
diff --git a/ui/ozone/platform/wayland/wayland_output.h b/ui/ozone/platform/wayland/wayland_output.h index 94088ca..ddf7946b 100644 --- a/ui/ozone/platform/wayland/wayland_output.h +++ b/ui/ozone/platform/wayland/wayland_output.h
@@ -18,21 +18,27 @@ // that are available to the application. class WaylandOutput { public: - class Observer { + class Delegate { public: - // Will be called when wl_output is available. - virtual void OnOutputReadyForUse() = 0; + virtual ~Delegate() {} + + virtual void OnOutputHandleMetrics(uint32_t output_id, + const gfx::Rect& new_bounds, + int32_t scale_factor) = 0; }; - WaylandOutput(const int64_t display_id, wl_output* output); + WaylandOutput(const uint32_t output_id, wl_output* output); ~WaylandOutput(); - void SetObserver(Observer* observer); - Observer* observer() { return observer_; } + void Initialize(Delegate* delegate); - bool is_ready() const { return !!current_mode_; } + void TriggerDelegateNotification() const; - void GetDisplaysSnapshot(display::GetDisplaysCallback callback); + uint32_t output_id() const { return output_id_; } + + // Tells if the output has already received physical screen dimensions in the + // global compositor space. + bool is_ready() const { return !rect_in_physical_pixels_.IsEmpty(); } private: // Callback functions used for setting geometric properties of the output @@ -54,14 +60,17 @@ int32_t width, int32_t height, int32_t refresh); + static void OutputHandleDone(void* data, struct wl_output* wl_output); + static void OutputHandleScale(void* data, + struct wl_output* wl_output, + int32_t factor); - const int64_t display_id_ = 0; + const uint32_t output_id_ = 0; wl::Object<wl_output> output_; + float device_scale_factor_; + gfx::Rect rect_in_physical_pixels_; - Observer* observer_; - - std::unique_ptr<display::DisplaySnapshot> current_snapshot_; - std::unique_ptr<display::DisplayMode> current_mode_; + Delegate* delegate_ = nullptr; DISALLOW_COPY_AND_ASSIGN(WaylandOutput); };
diff --git a/ui/ozone/platform/wayland/wayland_output_manager.cc b/ui/ozone/platform/wayland/wayland_output_manager.cc new file mode 100644 index 0000000..c9db25c --- /dev/null +++ b/ui/ozone/platform/wayland/wayland_output_manager.cc
@@ -0,0 +1,117 @@ +// 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 "ui/ozone/platform/wayland/wayland_output_manager.h" + +#include "ui/ozone/platform/wayland/wayland_connection.h" +#include "ui/ozone/platform/wayland/wayland_output.h" + +namespace ui { + +WaylandOutputManager::WaylandOutputManager() = default; + +WaylandOutputManager::~WaylandOutputManager() = default; + +bool WaylandOutputManager::IsPrimaryOutputReady() const { + if (output_list_.empty()) + return false; + + // The very first output in the list is always treated as a primary output. + const auto& primary_output = output_list_.front(); + return primary_output->is_ready(); +} + +void WaylandOutputManager::AddWaylandOutput(const uint32_t output_id, + wl_output* output) { + // Make sure an output with |output_id| has not been added yet. It's very + // unlikely to happen, unless a compositor has a bug in the numeric names + // representation of global objects. + auto output_it = std::find_if(output_list_.begin(), output_list_.end(), + [output_id](const auto& output) { + return output->output_id() == output_id; + }); + DCHECK(output_it == output_list_.end()); + auto wayland_output = std::make_unique<WaylandOutput>(output_id, output); + WaylandOutput* wayland_output_ptr = wayland_output.get(); + output_list_.push_back(std::move(wayland_output)); + + OnWaylandOutputAdded(output_id); + + // If WaylandScreen has already been created, the output can be initialized, + // which results in setting up a wl_listener and getting the geometry and the + // scaling factor from the Wayland Compositor. + wayland_output_ptr->Initialize(this); +} + +void WaylandOutputManager::RemoveWaylandOutput(const uint32_t output_id) { + auto output_it = std::find_if(output_list_.begin(), output_list_.end(), + [output_id](const auto& output) { + return output->output_id() == output_id; + }); + + // Check the comment in the WaylandConnetion::GlobalRemove. + if (output_it == output_list_.end()) + return; + + bool was_primary_output = IsPrimaryOutput(output_id); + output_list_.erase(output_it); + + // If it was a primary output removed, make sure the second output, which + // became a primary one, announces that to observers. + if (was_primary_output && !output_list_.empty()) + output_list_.front()->TriggerDelegateNotification(); + + OnWaylandOutputRemoved(output_id); +} + +std::unique_ptr<WaylandScreen> WaylandOutputManager::CreateWaylandScreen() { + auto wayland_screen = std::make_unique<WaylandScreen>(); + wayland_screen_ = wayland_screen->GetWeakPtr(); + + // As long as |wl_output| sends geometry and other events asynchronously (that + // is, the initial configuration is sent once the interface is bound), we'll + // have to tell each output to manually inform the delegate about available + // geometry, scale factor and etc, which will result in feeding the + // WaylandScreen with the data through OnOutputHandleGeometry and + // OutOutputHandleScale. All the other hot geometry and scale changes are done + // automatically, and the |wayland_screen_| is notified immediately about the + // changes. + if (!output_list_.empty()) { + for (auto& output : output_list_) { + OnWaylandOutputAdded(output->output_id()); + output->TriggerDelegateNotification(); + } + } + + return wayland_screen; +} + +void WaylandOutputManager::OnWaylandOutputAdded(uint32_t output_id) { + if (wayland_screen_) + wayland_screen_->OnOutputAdded(output_id, IsPrimaryOutput(output_id)); +} + +void WaylandOutputManager::OnWaylandOutputRemoved(uint32_t output_id) { + if (wayland_screen_) + wayland_screen_->OnOutputRemoved(output_id); +} + +bool WaylandOutputManager::IsPrimaryOutput(uint32_t output_id) const { + DCHECK(!output_list_.empty()); + // The very first object in the |output_list_| is always treated as a primary + // output. + const auto& primary_output = output_list_.front(); + return primary_output->output_id() == output_id; +} + +void WaylandOutputManager::OnOutputHandleMetrics(uint32_t output_id, + const gfx::Rect& new_bounds, + int32_t scale_factor) { + if (wayland_screen_) { + wayland_screen_->OnOutputMetricsChanged(output_id, new_bounds, scale_factor, + IsPrimaryOutput(output_id)); + } +} + +} // namespace ui
diff --git a/ui/ozone/platform/wayland/wayland_output_manager.h b/ui/ozone/platform/wayland/wayland_output_manager.h new file mode 100644 index 0000000..5fcdced --- /dev/null +++ b/ui/ozone/platform/wayland/wayland_output_manager.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 UI_OZONE_PLATFORM_WAYLAND_WAYLAND_OUTPUT_MANAGER_H_ +#define UI_OZONE_PLATFORM_WAYLAND_WAYLAND_OUTPUT_MANAGER_H_ + +#include "ui/ozone/platform/wayland/wayland_object.h" + +#include <memory> +#include <vector> + +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "ui/ozone/platform/wayland/wayland_output.h" +#include "ui/ozone/platform/wayland/wayland_screen.h" + +struct wl_output; + +namespace ui { + +class WaylandOutput; + +class WaylandOutputManager : public WaylandOutput::Delegate { + public: + WaylandOutputManager(); + ~WaylandOutputManager() override; + + // The first output in the vector is always a primary output. + bool IsPrimaryOutputReady() const; + + void AddWaylandOutput(const uint32_t output_id, wl_output* output); + void RemoveWaylandOutput(const uint32_t output_id); + + // Creates a platform screen and feeds it with existing outputs. + std::unique_ptr<WaylandScreen> CreateWaylandScreen(); + + private: + void OnWaylandOutputAdded(uint32_t output_id); + void OnWaylandOutputRemoved(uint32_t output_id); + + bool IsPrimaryOutput(uint32_t output_id) const; + + // WaylandOutput::Delegate: + void OnOutputHandleMetrics(uint32_t output_id, + const gfx::Rect& new_bounds, + int32_t scale_factor) override; + + std::vector<std::unique_ptr<WaylandOutput>> output_list_; + + // Non-owned wayland screen instance. + base::WeakPtr<WaylandScreen> wayland_screen_; + + DISALLOW_COPY_AND_ASSIGN(WaylandOutputManager); +}; + +} // namespace ui + +#endif // UI_OZONE_PLATFORM_WAYLAND_WAYLAND_OUTPUT_MANAGER_H_
diff --git a/ui/ozone/platform/wayland/wayland_pointer.cc b/ui/ozone/platform/wayland/wayland_pointer.cc index 5aceb2f2..f977f63 100644 --- a/ui/ozone/platform/wayland/wayland_pointer.cc +++ b/ui/ozone/platform/wayland/wayland_pointer.cc
@@ -212,4 +212,9 @@ return flags_; } +void WaylandPointer::ResetFlags() { + flags_ = 0; + keyboard_modifiers_ = 0; +} + } // namespace ui
diff --git a/ui/ozone/platform/wayland/wayland_pointer.h b/ui/ozone/platform/wayland/wayland_pointer.h index 50f60f4..0c398d1 100644 --- a/ui/ozone/platform/wayland/wayland_pointer.h +++ b/ui/ozone/platform/wayland/wayland_pointer.h
@@ -27,6 +27,7 @@ } int GetFlagsWithKeyboardModifiers(); + void ResetFlags(); WaylandCursor* cursor() { return cursor_.get(); }
diff --git a/ui/ozone/platform/wayland/wayland_screen.cc b/ui/ozone/platform/wayland/wayland_screen.cc new file mode 100644 index 0000000..98ef35e --- /dev/null +++ b/ui/ozone/platform/wayland/wayland_screen.cc
@@ -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. + +#include "ui/ozone/platform/wayland/wayland_screen.h" + +#include "ui/display/display.h" +#include "ui/display/display_finder.h" +#include "ui/display/display_observer.h" +#include "ui/gfx/geometry/point.h" +#include "ui/gfx/geometry/size.h" + +namespace ui { + +WaylandScreen::WaylandScreen() : weak_factory_(this) {} + +WaylandScreen::~WaylandScreen() = default; + +void WaylandScreen::OnOutputAdded(uint32_t output_id, bool is_primary) { + display::Display new_display(output_id); + display_list_.AddDisplay(std::move(new_display), + is_primary + ? display::DisplayList::Type::PRIMARY + : display::DisplayList::Type::NOT_PRIMARY); +} + +void WaylandScreen::OnOutputRemoved(uint32_t output_id) { + display_list_.RemoveDisplay(output_id); +} + +void WaylandScreen::OnOutputMetricsChanged(uint32_t output_id, + const gfx::Rect& new_bounds, + float device_pixel_ratio, + bool is_primary) { + display::Display changed_display(output_id); + changed_display.set_device_scale_factor(device_pixel_ratio); + changed_display.set_bounds(new_bounds); + changed_display.set_work_area(new_bounds); + + display_list_.UpdateDisplay( + changed_display, is_primary ? display::DisplayList::Type::PRIMARY + : display::DisplayList::Type::NOT_PRIMARY); +} + +base::WeakPtr<WaylandScreen> WaylandScreen::GetWeakPtr() { + return weak_factory_.GetWeakPtr(); +} + +const std::vector<display::Display>& WaylandScreen::GetAllDisplays() const { + return display_list_.displays(); +} + +display::Display WaylandScreen::GetPrimaryDisplay() const { + auto iter = display_list_.GetPrimaryDisplayIterator(); + if (iter == display_list_.displays().end()) + return display::Display::GetDefaultDisplay(); + return *iter; +} + +display::Display WaylandScreen::GetDisplayForAcceleratedWidget( + gfx::AcceleratedWidget widget) const { + // TODO(msisov): implement wl_surface_listener::enter and + // wl_surface_listener::leave for a wl_surface to know what surface the window + // is located on. + // + // https://crbug.com/890271 + NOTIMPLEMENTED_LOG_ONCE(); + return GetPrimaryDisplay(); +} + +gfx::Point WaylandScreen::GetCursorScreenPoint() const { + NOTIMPLEMENTED_LOG_ONCE(); + return gfx::Point(); +} + +gfx::AcceleratedWidget WaylandScreen::GetAcceleratedWidgetAtScreenPoint( + const gfx::Point& point) const { + // TODO(msisov): implement this once wl_surface_listener::enter and ::leave + // are used. + // + // https://crbug.com/890271 + NOTIMPLEMENTED_LOG_ONCE(); + return gfx::kNullAcceleratedWidget; +} + +display::Display WaylandScreen::GetDisplayNearestPoint( + const gfx::Point& point) const { + NOTIMPLEMENTED_LOG_ONCE(); + return GetPrimaryDisplay(); +} + +display::Display WaylandScreen::GetDisplayMatching( + const gfx::Rect& match_rect) const { + // TODO(msisov): https://crbug.com/890272 + NOTIMPLEMENTED_LOG_ONCE(); + return GetPrimaryDisplay(); +} + +void WaylandScreen::AddObserver(display::DisplayObserver* observer) { + display_list_.AddObserver(observer); +} + +void WaylandScreen::RemoveObserver(display::DisplayObserver* observer) { + display_list_.RemoveObserver(observer); +} + +} // namespace ui
diff --git a/ui/ozone/platform/wayland/wayland_screen.h b/ui/ozone/platform/wayland/wayland_screen.h new file mode 100644 index 0000000..f6a0a661 --- /dev/null +++ b/ui/ozone/platform/wayland/wayland_screen.h
@@ -0,0 +1,62 @@ +// 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 UI_OZONE_PLATFORM_WAYLAND_WAYLAND_SCREEN_H_ +#define UI_OZONE_PLATFORM_WAYLAND_WAYLAND_SCREEN_H_ + +#include <vector> + +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "base/observer_list.h" +#include "ui/display/display_list.h" +#include "ui/ozone/platform/wayland/wayland_output.h" +#include "ui/ozone/public/ozone_platform.h" +#include "ui/ozone/public/platform_screen.h" + +namespace ui { + +// A PlatformScreen implementation for Wayland. +class WaylandScreen : public PlatformScreen { + public: + WaylandScreen(); + ~WaylandScreen() override; + + void OnOutputAdded(uint32_t output_id, bool is_primary); + void OnOutputRemoved(uint32_t output_id); + void OnOutputMetricsChanged(uint32_t output_id, + const gfx::Rect& bounds, + float device_pixel_ratio, + bool is_primary); + + base::WeakPtr<WaylandScreen> GetWeakPtr(); + + // display::Screen implementation. + const std::vector<display::Display>& GetAllDisplays() const override; + display::Display GetPrimaryDisplay() const override; + display::Display GetDisplayForAcceleratedWidget( + gfx::AcceleratedWidget widget) const override; + gfx::Point GetCursorScreenPoint() const override; + gfx::AcceleratedWidget GetAcceleratedWidgetAtScreenPoint( + const gfx::Point& point) const override; + display::Display GetDisplayNearestPoint( + const gfx::Point& point) const override; + display::Display GetDisplayMatching( + const gfx::Rect& match_rect) const override; + void AddObserver(display::DisplayObserver* observer) override; + void RemoveObserver(display::DisplayObserver* observer) override; + + private: + display::DisplayList display_list_; + + base::ObserverList<display::DisplayObserver>::Unchecked observers_; + + base::WeakPtrFactory<WaylandScreen> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(WaylandScreen); +}; + +} // namespace ui + +#endif // UI_OZONE_PLATFORM_WAYLAND_WAYLAND_SCREEN_H_
diff --git a/ui/ozone/platform/wayland/wayland_screen_unittest.cc b/ui/ozone/platform/wayland/wayland_screen_unittest.cc new file mode 100644 index 0000000..75878aea --- /dev/null +++ b/ui/ozone/platform/wayland/wayland_screen_unittest.cc
@@ -0,0 +1,189 @@ +// 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 <wayland-server.h> + +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/display/display_observer.h" +#include "ui/ozone/platform/wayland/fake_server.h" +#include "ui/ozone/platform/wayland/wayland_connection.h" +#include "ui/ozone/platform/wayland/wayland_output_manager.h" +#include "ui/ozone/platform/wayland/wayland_screen.h" +#include "ui/ozone/platform/wayland/wayland_test.h" + +namespace ui { + +namespace { + +constexpr uint32_t kNumberOfDisplays = 1; +constexpr uint32_t kOutputWidth = 1024; +constexpr uint32_t kOutputHeight = 768; + +class TestDisplayObserver : public display::DisplayObserver { + public: + TestDisplayObserver() {} + ~TestDisplayObserver() override {} + + display::Display GetDisplay() { return std::move(display_); } + uint32_t GetAndClearChangedMetrics() { + uint32_t changed_metrics = changed_metrics_; + changed_metrics_ = 0; + return changed_metrics; + } + + // display::DisplayObserver: + void OnDisplayAdded(const display::Display& new_display) override { + display_ = new_display; + } + + void OnDisplayRemoved(const display::Display& old_display) override { + display_ = old_display; + } + + void OnDisplayMetricsChanged(const display::Display& display, + uint32_t changed_metrics) override { + changed_metrics_ = changed_metrics; + display_ = display; + } + + private: + uint32_t changed_metrics_ = 0; + display::Display display_; + + DISALLOW_COPY_AND_ASSIGN(TestDisplayObserver); +}; + +} // namespace + +class WaylandScreenTest : public WaylandTest { + public: + WaylandScreenTest() {} + ~WaylandScreenTest() override {} + + void SetUp() override { + output_ = server_.output(); + output_->SetRect(gfx::Rect(0, 0, kOutputWidth, kOutputHeight)); + + WaylandTest::SetUp(); + + output_manager_ = connection_->wayland_output_manager(); + ASSERT_TRUE(output_manager_); + } + + protected: + wl::MockOutput* output_ = nullptr; + WaylandOutputManager* output_manager_ = nullptr; + + private: + DISALLOW_COPY_AND_ASSIGN(WaylandScreenTest); +}; + +// Tests whether a primary output has been initialized before PlatformScreen is +// created. +TEST_P(WaylandScreenTest, OutputBaseTest) { + EXPECT_TRUE(output_manager_->IsPrimaryOutputReady()); + + std::unique_ptr<WaylandScreen> platform_screen = + output_manager_->CreateWaylandScreen(); + + // Ensure there is only one display, which is the primary one. + auto& all_displays = platform_screen->GetAllDisplays(); + EXPECT_EQ(all_displays.size(), kNumberOfDisplays); + + // Ensure the size property of the primary display. + EXPECT_EQ(platform_screen->GetPrimaryDisplay().bounds(), + gfx::Rect(0, 0, kOutputWidth, kOutputHeight)); +} + +TEST_P(WaylandScreenTest, MultipleOutputsAddedAndRemoved) { + EXPECT_TRUE(output_manager_->IsPrimaryOutputReady()); + std::unique_ptr<WaylandScreen> platform_screen = + output_manager_->CreateWaylandScreen(); + + TestDisplayObserver observer; + platform_screen->AddObserver(&observer); + + // Add a second display. + wl::MockOutput output1; + output1.Initialize(server_.display()); + + Sync(); + + // Ensure that second display is not a primary one and have a different id. + int64_t added_display_id = observer.GetDisplay().id(); + EXPECT_NE(platform_screen->GetPrimaryDisplay().id(), added_display_id); + + // Remove the second output. + output_manager_->RemoveWaylandOutput(added_display_id); + + Sync(); + + // Ensure that removed display has correct id. + int64_t removed_display_id = observer.GetDisplay().id(); + EXPECT_EQ(added_display_id, removed_display_id); + + // Add a second display again. + wl::MockOutput output2; + output2.Initialize(server_.display()); + + Sync(); + + // The newly added display is not a primary yet. + added_display_id = observer.GetDisplay().id(); + EXPECT_NE(platform_screen->GetPrimaryDisplay().id(), added_display_id); + + // Make sure the geometry changes are sent by syncing one more time again. + Sync(); + + int64_t old_primary_display_id = platform_screen->GetPrimaryDisplay().id(); + output_manager_->RemoveWaylandOutput(old_primary_display_id); + + // Ensure that previously added display is now a primary one. + EXPECT_EQ(platform_screen->GetPrimaryDisplay().id(), added_display_id); + // Ensure that the removed display was the one, which was a primary display. + EXPECT_EQ(observer.GetDisplay().id(), old_primary_display_id); +} + +TEST_P(WaylandScreenTest, OutputPropertyChanges) { + std::unique_ptr<WaylandScreen> platform_screen = + output_manager_->CreateWaylandScreen(); + TestDisplayObserver observer; + platform_screen->AddObserver(&observer); + + const gfx::Rect new_rect(0, 0, 800, 600); + wl_output_send_geometry(output_->resource(), new_rect.x(), new_rect.y(), + 0 /* physical_width */, 0 /* physical_height */, + 0 /* subpixel */, "unkown_make", "unknown_model", + 0 /* transform */); + wl_output_send_mode(output_->resource(), WL_OUTPUT_MODE_CURRENT, + new_rect.width(), new_rect.height(), 0 /* refresh */); + + Sync(); + + uint32_t changed_values = 0; + changed_values |= display::DisplayObserver::DISPLAY_METRIC_BOUNDS; + changed_values |= display::DisplayObserver::DISPLAY_METRIC_WORK_AREA; + EXPECT_EQ(observer.GetAndClearChangedMetrics(), changed_values); + EXPECT_EQ(observer.GetDisplay().bounds(), new_rect); + + const float new_scale_value = 2.0f; + wl_output_send_scale(output_->resource(), new_scale_value); + + Sync(); + + changed_values = 0; + changed_values |= + display::DisplayObserver::DISPLAY_METRIC_DEVICE_SCALE_FACTOR; + EXPECT_EQ(observer.GetAndClearChangedMetrics(), changed_values); + EXPECT_EQ(observer.GetDisplay().device_scale_factor(), new_scale_value); +} + +INSTANTIATE_TEST_CASE_P(XdgVersionV5Test, + WaylandScreenTest, + ::testing::Values(kXdgShellV5)); +INSTANTIATE_TEST_CASE_P(XdgVersionV6Test, + WaylandScreenTest, + ::testing::Values(kXdgShellV6)); + +} // namespace ui
diff --git a/ui/ozone/platform/wayland/wayland_util.cc b/ui/ozone/platform/wayland/wayland_util.cc index 1ad2b556..0cd0534 100644 --- a/ui/ozone/platform/wayland/wayland_util.cc +++ b/ui/ozone/platform/wayland/wayland_util.cc
@@ -4,10 +4,15 @@ #include "ui/ozone/platform/wayland/wayland_util.h" +#include <xdg-shell-unstable-v5-client-protocol.h> +#include <xdg-shell-unstable-v6-client-protocol.h> + #include "base/memory/shared_memory.h" #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkSurface.h" +#include "ui/base/hit_test.h" #include "ui/gfx/skia_util.h" +#include "ui/ozone/platform/wayland/wayland_connection.h" namespace wl { @@ -16,6 +21,84 @@ const uint32_t kShmFormat = WL_SHM_FORMAT_ARGB8888; const SkColorType kColorType = kBGRA_8888_SkColorType; +uint32_t IdentifyDirectionV5(int hittest) { + uint32_t direction = 0; + switch (hittest) { + case HTBOTTOM: + direction = xdg_surface_resize_edge::XDG_SURFACE_RESIZE_EDGE_BOTTOM; + break; + case HTBOTTOMLEFT: + direction = xdg_surface_resize_edge::XDG_SURFACE_RESIZE_EDGE_BOTTOM_LEFT; + break; + case HTBOTTOMRIGHT: + direction = xdg_surface_resize_edge::XDG_SURFACE_RESIZE_EDGE_BOTTOM_RIGHT; + break; + case HTLEFT: + direction = xdg_surface_resize_edge::XDG_SURFACE_RESIZE_EDGE_LEFT; + break; + case HTRIGHT: + direction = xdg_surface_resize_edge::XDG_SURFACE_RESIZE_EDGE_RIGHT; + break; + case HTTOP: + direction = xdg_surface_resize_edge::XDG_SURFACE_RESIZE_EDGE_TOP; + break; + case HTTOPLEFT: + direction = xdg_surface_resize_edge::XDG_SURFACE_RESIZE_EDGE_TOP_LEFT; + break; + case HTTOPRIGHT: + direction = xdg_surface_resize_edge::XDG_SURFACE_RESIZE_EDGE_TOP_RIGHT; + break; + default: + direction = xdg_surface_resize_edge::XDG_SURFACE_RESIZE_EDGE_NONE; + break; + ; + } + return direction; +} + +uint32_t IdentifyDirectionV6(int hittest) { + uint32_t direction = 0; + switch (hittest) { + case HTBOTTOM: + direction = + zxdg_toplevel_v6_resize_edge::ZXDG_TOPLEVEL_V6_RESIZE_EDGE_BOTTOM; + break; + case HTBOTTOMLEFT: + direction = zxdg_toplevel_v6_resize_edge:: + ZXDG_TOPLEVEL_V6_RESIZE_EDGE_BOTTOM_LEFT; + break; + case HTBOTTOMRIGHT: + direction = zxdg_toplevel_v6_resize_edge:: + ZXDG_TOPLEVEL_V6_RESIZE_EDGE_BOTTOM_RIGHT; + break; + case HTLEFT: + direction = + zxdg_toplevel_v6_resize_edge::ZXDG_TOPLEVEL_V6_RESIZE_EDGE_LEFT; + break; + case HTRIGHT: + direction = + zxdg_toplevel_v6_resize_edge::ZXDG_TOPLEVEL_V6_RESIZE_EDGE_RIGHT; + break; + case HTTOP: + direction = + zxdg_toplevel_v6_resize_edge::ZXDG_TOPLEVEL_V6_RESIZE_EDGE_TOP; + break; + case HTTOPLEFT: + direction = + zxdg_toplevel_v6_resize_edge::ZXDG_TOPLEVEL_V6_RESIZE_EDGE_TOP_LEFT; + break; + case HTTOPRIGHT: + direction = + zxdg_toplevel_v6_resize_edge::ZXDG_TOPLEVEL_V6_RESIZE_EDGE_TOP_RIGHT; + break; + default: + direction = + zxdg_toplevel_v6_resize_edge::ZXDG_TOPLEVEL_V6_RESIZE_EDGE_NONE; + break; + } + return direction; +} + } // namespace wl_buffer* CreateSHMBuffer(const gfx::Size& size, @@ -68,4 +151,12 @@ canvas->drawBitmapRect(bitmap, damage, nullptr); } +uint32_t IdentifyDirection(const ui::WaylandConnection& connection, + int hittest) { + if (connection.shell_v6()) + return IdentifyDirectionV6(hittest); + DCHECK(connection.shell()); + return IdentifyDirectionV5(hittest); +} + } // namespace wl
diff --git a/ui/ozone/platform/wayland/wayland_util.h b/ui/ozone/platform/wayland/wayland_util.h index d104fc0..2a2db3ab 100644 --- a/ui/ozone/platform/wayland/wayland_util.h +++ b/ui/ozone/platform/wayland/wayland_util.h
@@ -7,6 +7,8 @@ #include <wayland-client.h> +#include <stdint.h> + #include "base/callback.h" #include "base/macros.h" #include "ui/ozone/platform/wayland/wayland_object.h" @@ -17,6 +19,10 @@ class SharedMemory; } +namespace ui { +class WaylandConnection; +} + namespace gfx { class Size; enum class SwapResult; @@ -36,6 +42,11 @@ const base::SharedMemory& shared_memory, const SkBitmap& bitmap); +// Identifies the direction of the "hittest" for Wayland. |connection| +// is used to identify whether values from shell v5 or v6 must be used. +uint32_t IdentifyDirection(const ui::WaylandConnection& connection, + int hittest); + } // namespace wl #endif // UI_OZONE_PLATFORM_WAYLAND_WAYLAND_UTIL_H_
diff --git a/ui/ozone/platform/wayland/wayland_window.cc b/ui/ozone/platform/wayland/wayland_window.cc index cb5e40b4..27ddd18 100644 --- a/ui/ozone/platform/wayland/wayland_window.cc +++ b/ui/ozone/platform/wayland/wayland_window.cc
@@ -9,6 +9,7 @@ #include "base/bind.h" #include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h" #include "ui/base/dragdrop/os_exchange_data.h" +#include "ui/base/hit_test.h" #include "ui/events/event.h" #include "ui/events/event_utils.h" #include "ui/events/ozone/events_ozone.h" @@ -73,7 +74,11 @@ : delegate_(delegate), connection_(connection), xdg_shell_objects_factory_(new XDGShellObjectFactory()), - state_(PlatformWindowState::PLATFORM_WINDOW_STATE_NORMAL) {} + state_(PlatformWindowState::PLATFORM_WINDOW_STATE_NORMAL) { + // Set a class property key, which allows |this| to be used for interactive + // events, e.g. move or resize. + SetWmMoveResizeHandler(this, AsWmMoveResizeHandler()); +} WaylandWindow::~WaylandWindow() { PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this); @@ -196,6 +201,20 @@ connection_->ScheduleFlush(); } +void WaylandWindow::DispatchHostWindowDragMovement( + int hittest, + const gfx::Point& pointer_location) { + DCHECK(xdg_surface_); + + connection_->ResetPointerFlags(); + if (hittest == HTCAPTION) + xdg_surface_->SurfaceMove(connection_); + else + xdg_surface_->SurfaceResize(connection_, hittest); + + connection_->ScheduleFlush(); +} + void WaylandWindow::Show() { if (!is_tooltip_) // Tooltip windows should not get keyboard focus set_keyboard_focus(true); @@ -572,4 +591,8 @@ return parent_window; } +WmMoveResizeHandler* WaylandWindow::AsWmMoveResizeHandler() { + return static_cast<WmMoveResizeHandler*>(this); +} + } // namespace ui
diff --git a/ui/ozone/platform/wayland/wayland_window.h b/ui/ozone/platform/wayland/wayland_window.h index 4148648..e1cb0f6 100644 --- a/ui/ozone/platform/wayland/wayland_window.h +++ b/ui/ozone/platform/wayland/wayland_window.h
@@ -12,6 +12,7 @@ #include "ui/ozone/platform/wayland/wayland_object.h" #include "ui/platform_window/platform_window.h" #include "ui/platform_window/platform_window_delegate.h" +#include "ui/platform_window/platform_window_handler/wm_move_resize_handler.h" namespace gfx { class PointF; @@ -32,7 +33,9 @@ class XDGShellObjectFactory; } // namespace -class WaylandWindow : public PlatformWindow, public PlatformEventDispatcher { +class WaylandWindow : public PlatformWindow, + public PlatformEventDispatcher, + public WmMoveResizeHandler { public: WaylandWindow(PlatformWindowDelegate* delegate, WaylandConnection* connection); @@ -73,6 +76,11 @@ bool is_active() const { return is_active_; } + // WmMoveResizeHandler + void DispatchHostWindowDragMovement( + int hittest, + const gfx::Point& pointer_location) override; + // PlatformWindow void Show() override; void Hide() override; @@ -131,6 +139,8 @@ // Gets a parent window for this window. WaylandWindow* GetParentWindow(gfx::AcceleratedWidget parent_widget); + WmMoveResizeHandler* AsWmMoveResizeHandler(); + PlatformWindowDelegate* delegate_; WaylandConnection* connection_; WaylandWindow* parent_window_ = nullptr;
diff --git a/ui/ozone/platform/wayland/wayland_window_unittest.cc b/ui/ozone/platform/wayland/wayland_window_unittest.cc index 2d885e3..a97b92eb 100644 --- a/ui/ozone/platform/wayland/wayland_window_unittest.cc +++ b/ui/ozone/platform/wayland/wayland_window_unittest.cc
@@ -13,10 +13,12 @@ #include "base/strings/utf_string_conversions.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/base/hit_test.h" #include "ui/events/base_event_utils.h" #include "ui/events/event.h" #include "ui/ozone/platform/wayland/fake_server.h" #include "ui/ozone/platform/wayland/wayland_test.h" +#include "ui/ozone/platform/wayland/wayland_util.h" #include "ui/ozone/test/mock_platform_window_delegate.h" #include "ui/platform_window/platform_window_init_properties.h" @@ -132,6 +134,17 @@ return window; } + void InitializeWithSupportedHitTestValues(std::vector<int>* hit_tests) { + hit_tests->push_back(static_cast<int>(HTBOTTOM)); + hit_tests->push_back(static_cast<int>(HTBOTTOMLEFT)); + hit_tests->push_back(static_cast<int>(HTBOTTOMRIGHT)); + hit_tests->push_back(static_cast<int>(HTLEFT)); + hit_tests->push_back(static_cast<int>(HTRIGHT)); + hit_tests->push_back(static_cast<int>(HTTOP)); + hit_tests->push_back(static_cast<int>(HTTOPLEFT)); + hit_tests->push_back(static_cast<int>(HTTOPRIGHT)); + } + wl::MockXdgSurface* xdg_surface_; MouseEvent test_mouse_event_; @@ -649,6 +662,25 @@ Sync(); } +TEST_P(WaylandWindowTest, DispatchWindowMove) { + EXPECT_CALL(*GetXdgSurface(), Move(_)); + window_->DispatchHostWindowDragMovement(HTCAPTION, gfx::Point()); +} + +// Makes sure hit tests are converted into right edges. +TEST_P(WaylandWindowTest, DispatchWindowResize) { + std::vector<int> hit_test_values; + InitializeWithSupportedHitTestValues(&hit_test_values); + + for (const int value : hit_test_values) { + { + uint32_t direction = wl::IdentifyDirection(*(connection_.get()), value); + EXPECT_CALL(*GetXdgSurface(), Resize(_, Eq(direction))); + window_->DispatchHostWindowDragMovement(value, gfx::Point()); + } + } +} + INSTANTIATE_TEST_CASE_P(XdgVersionV5Test, WaylandWindowTest, ::testing::Values(kXdgShellV5));
diff --git a/ui/ozone/platform/wayland/xdg_surface_wrapper_v5.cc b/ui/ozone/platform/wayland/xdg_surface_wrapper_v5.cc index eb8f289..7f9cdf8 100644 --- a/ui/ozone/platform/wayland/xdg_surface_wrapper_v5.cc +++ b/ui/ozone/platform/wayland/xdg_surface_wrapper_v5.cc
@@ -7,7 +7,9 @@ #include <xdg-shell-unstable-v5-client-protocol.h> #include "base/strings/utf_string_conversions.h" +#include "ui/base/hit_test.h" #include "ui/ozone/platform/wayland/wayland_connection.h" +#include "ui/ozone/platform/wayland/wayland_util.h" #include "ui/ozone/platform/wayland/wayland_window.h" namespace ui { @@ -53,20 +55,15 @@ } void XDGSurfaceWrapperV5::SurfaceMove(WaylandConnection* connection) { - NOTIMPLEMENTED(); + xdg_surface_move(xdg_surface_.get(), connection->seat(), + connection->serial()); } void XDGSurfaceWrapperV5::SurfaceResize(WaylandConnection* connection, uint32_t hittest) { - // TODO(msisov): implement resizing. - /* - * int direction; - * if (!IdentifyDirection(hittest, &direction)) - * return; - * xdg_surface_resize(xdg_surface_.get(), connection->seat(), - * connection->serial(), direction); - */ - NOTIMPLEMENTED(); + xdg_surface_resize(xdg_surface_.get(), connection->seat(), + connection->serial(), + wl::IdentifyDirection(*connection, hittest)); } void XDGSurfaceWrapperV5::SetTitle(const base::string16& title) {
diff --git a/ui/ozone/platform/wayland/xdg_surface_wrapper_v6.cc b/ui/ozone/platform/wayland/xdg_surface_wrapper_v6.cc index 14ab8434..f913d20 100644 --- a/ui/ozone/platform/wayland/xdg_surface_wrapper_v6.cc +++ b/ui/ozone/platform/wayland/xdg_surface_wrapper_v6.cc
@@ -7,7 +7,9 @@ #include <xdg-shell-unstable-v6-client-protocol.h> #include "base/strings/utf_string_conversions.h" +#include "ui/base/hit_test.h" #include "ui/ozone/platform/wayland/wayland_connection.h" +#include "ui/ozone/platform/wayland/wayland_util.h" #include "ui/ozone/platform/wayland/wayland_window.h" namespace ui { @@ -82,20 +84,17 @@ } void XDGSurfaceWrapperV6::SurfaceMove(WaylandConnection* connection) { - NOTIMPLEMENTED(); + DCHECK(zxdg_toplevel_v6_); + zxdg_toplevel_v6_move(zxdg_toplevel_v6_.get(), connection->seat(), + connection->serial()); } void XDGSurfaceWrapperV6::SurfaceResize(WaylandConnection* connection, uint32_t hittest) { - // TODO(msisov): implement resizing. - /* - * int direction; - * if (!IdentifyDirection(hittest, &direction)) - * return; - * xdg_surface_resize(xdg_surface_.get(), connection->seat(), - * connection->serial(), direction); - */ - NOTIMPLEMENTED(); + DCHECK(zxdg_toplevel_v6_); + zxdg_toplevel_v6_resize(zxdg_toplevel_v6_.get(), connection->seat(), + connection->serial(), + wl::IdentifyDirection(*connection, hittest)); } void XDGSurfaceWrapperV6::SetTitle(const base::string16& title) {
diff --git a/ui/platform_window/DEPS b/ui/platform_window/DEPS index 0e42d64..b51da65 100644 --- a/ui/platform_window/DEPS +++ b/ui/platform_window/DEPS
@@ -1,5 +1,4 @@ include_rules = [ - "+ui/base/cursor", - "+ui/base/ime", + "+ui/base", "+ui/gfx", ]
diff --git a/ui/platform_window/platform_window.h b/ui/platform_window/platform_window.h index 181ad85f..c7611ee 100644 --- a/ui/platform_window/platform_window.h +++ b/ui/platform_window/platform_window.h
@@ -8,6 +8,7 @@ #include <memory> #include "base/strings/string16.h" +#include "ui/base/class_property.h" #include "ui/base/cursor/cursor.h" #include "ui/platform_window/platform_window_delegate.h" @@ -24,7 +25,7 @@ // // Each instance of PlatformWindow represents a single window in the // underlying platform windowing system (i.e. X11/Win/OSX). -class PlatformWindow { +class PlatformWindow : public PropertyHandler { public: virtual ~PlatformWindow() {}
diff --git a/ui/platform_window/platform_window_handler/BUILD.gn b/ui/platform_window/platform_window_handler/BUILD.gn new file mode 100644 index 0000000..be75a75 --- /dev/null +++ b/ui/platform_window/platform_window_handler/BUILD.gn
@@ -0,0 +1,22 @@ +# Copyright 2018 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/jumbo.gni") + +jumbo_component("platform_window_handler") { + output_name = "platform_window_handler_libs" + + sources = [ + "wm_move_resize_handler.cc", + "wm_move_resize_handler.h", + "wm_platform_export.h", + ] + + defines = [ "PLATFORM_WINDOW_HANDLER_IMPLEMENTATION" ] + + deps = [ + "//ui/base", + "//ui/platform_window", + ] +}
diff --git a/ui/platform_window/platform_window_handler/DEPS b/ui/platform_window/platform_window_handler/DEPS new file mode 100644 index 0000000..381a2e478 --- /dev/null +++ b/ui/platform_window/platform_window_handler/DEPS
@@ -0,0 +1,4 @@ +include_rules = [ + "+ui/base/class_property.h", + "+ui/platform_window/platform_window.h", +]
diff --git a/ui/platform_window/platform_window_handler/wm_move_resize_handler.cc b/ui/platform_window/platform_window_handler/wm_move_resize_handler.cc new file mode 100644 index 0000000..5a295a0 --- /dev/null +++ b/ui/platform_window/platform_window_handler/wm_move_resize_handler.cc
@@ -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. + +#include "ui/platform_window/platform_window_handler/wm_move_resize_handler.h" + +#include "ui/base/class_property.h" +#include "ui/platform_window/platform_window.h" + +DEFINE_UI_CLASS_PROPERTY_TYPE(WmMoveResizeHandler*); + +namespace ui { + +DEFINE_UI_CLASS_PROPERTY_KEY(WmMoveResizeHandler*, + kWmMoveResizeHandlerKey, + nullptr); + +void SetWmMoveResizeHandler(PlatformWindow* platform_window, + WmMoveResizeHandler* move_resize_handler) { + platform_window->SetProperty(kWmMoveResizeHandlerKey, move_resize_handler); +} + +WmMoveResizeHandler* GetWmMoveResizeHandler( + const PlatformWindow& platform_window) { + return platform_window.GetProperty(kWmMoveResizeHandlerKey); +} + +} // namespace ui
diff --git a/ui/platform_window/platform_window_handler/wm_move_resize_handler.h b/ui/platform_window/platform_window_handler/wm_move_resize_handler.h new file mode 100644 index 0000000..cd5a696a --- /dev/null +++ b/ui/platform_window/platform_window_handler/wm_move_resize_handler.h
@@ -0,0 +1,62 @@ +// 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 UI_PLATFORM_WINDOW_PLATFORM_WINDOW_HANDLER_WM_MOVE_RESIZE_HANDLER_H_ +#define UI_PLATFORM_WINDOW_PLATFORM_WINDOW_HANDLER_WM_MOVE_RESIZE_HANDLER_H_ + +#include "ui/platform_window/platform_window_handler/wm_platform_export.h" + +namespace gfx { +class Point; +} // namespace gfx + +namespace ui { + +class PlatformWindow; + +class WmMoveResizeHandler { + public: + // A system window manager starts interactive drag or resize of a window based + // on the |hittest| value. The |hittest| value identifies in which direction + // the window should be resized or whether it should be moved. See + // ui/base/hit_test.h for a concrete example with chromium symbolic names + // defined. The |pointer_location| indicates the position of the button press + // with respect to the platform window, which is needed when sending a + // move/resize request in such backends as X11. See _NET_WM_MOVERESIZE section + // in https://specifications.freedesktop.org/wm-spec/1.4/ar01s04.html. + // + // There is no need to implement this by all the platforms except Ozone/X11 + // and Ozone/Wayland, compositors of which support interactive move/resize. + // + // This API must be used on mouse or touch events, which are targeted for + // non-client components (check ui/base/hit_test.h again) except the ones + // targeted for components like HTMAXBUTTON. In that case, the mouse events + // are used to identify clicks on maximize/minimize/restore buttons located in + // the top non-client area of the chromium window. See + // WindowEventFilter::OnMouseEvent for a concrete example of how mouse events + // are identified as client or non-client. + // + // When the API is called, there is no way to know that the call was + // successful or not. The browser continues performing as usual except that a + // system compositor does not send any mouse/keyboard/etc events until user + // releases a mouse button. Instead, the compositor sends new bounds, which a + // client uses to recreate gpu buffers and redraw visual represantation of the + // browser. + virtual void DispatchHostWindowDragMovement( + int hittest, + const gfx::Point& pointer_location) = 0; + + protected: + virtual ~WmMoveResizeHandler() {} +}; + +WM_PLATFORM_EXPORT void SetWmMoveResizeHandler( + PlatformWindow* platform_window, + WmMoveResizeHandler* move_resize_handler); +WM_PLATFORM_EXPORT WmMoveResizeHandler* GetWmMoveResizeHandler( + const PlatformWindow& platform_window); + +} // namespace ui + +#endif // UI_PLATFORM_WINDOW_PLATFORM_WINDOW_HANDLER_WM_MOVE_RESIZE_HANDLER_H_
diff --git a/ui/platform_window/platform_window_handler/wm_platform_export.h b/ui/platform_window/platform_window_handler/wm_platform_export.h new file mode 100644 index 0000000..37165fb7 --- /dev/null +++ b/ui/platform_window/platform_window_handler/wm_platform_export.h
@@ -0,0 +1,32 @@ +// 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 UI_PLATFORM_WINDOW_PLATFORM_WINDOW_HANDLER_WM_PLATFORM_EXPORT_H_ +#define UI_PLATFORM_WINDOW_PLATFORM_WINDOW_HANDLER_WM_PLATFORM_EXPORT_H_ + +// Defines WM_PLATFORM_EXPORT so that functionality implemented by the +// wm_platform module can be exported to consumers. + +#if defined(COMPONENT_BUILD) +#if defined(WIN32) + +#if defined(PLATFORM_WINDOW_HANDLER_IMPLEMENTATION) +#define WM_PLATFORM_EXPORT __declspec(dllexport) +#else +#define WM_PLATFORM_EXPORT __declspec(dllimport) +#endif // defined(WM_PLATFORM_IMPLEMENTATION) + +#else // defined(WIN32) +#if defined(PLATFORM_WINDOW_HANDLER_IMPLEMENTATION) +#define WM_PLATFORM_EXPORT __attribute__((visibility("default"))) +#else +#define WM_PLATFORM_EXPORT +#endif +#endif + +#else // defined(COMPONENT_BUILD) +#define WM_PLATFORM_EXPORT +#endif + +#endif // UI_PLATFORM_WINDOW_PLATFORM_WINDOW_HANDLER_WM_PLATFORM_EXPORT_H_
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn index e78872c..0cb7f71 100644 --- a/ui/views/BUILD.gn +++ b/ui/views/BUILD.gn
@@ -665,6 +665,7 @@ "//services/ws/public/mojom", "//ui/aura", "//ui/platform_window", + "//ui/platform_window/platform_window_handler", "//ui/touch_selection", "//ui/wm", "//ui/wm/public", @@ -1223,12 +1224,23 @@ "corewm/desktop_capture_controller_unittest.cc", "widget/native_widget_aura_interactive_uitest.cc", ] + deps += [ "//ui/aura", "//ui/aura:test_support", "//ui/wm", "//ui/wm/public", ] + + if (!is_chromeos && ((is_linux && !use_x11) || is_fuchsia)) { + sources += [ "widget/desktop_aura/desktop_window_tree_host_platform_interactive_uitest.cc" ] + } + + deps += [ + "//ui/events/platform", + "//ui/platform_window", + "//ui/platform_window/platform_window_handler", + ] } if (use_x11) {
diff --git a/ui/views/widget/desktop_aura/desktop_screen_ozone.cc b/ui/views/widget/desktop_aura/desktop_screen_ozone.cc index a5e871e..6dd57cd7 100644 --- a/ui/views/widget/desktop_aura/desktop_screen_ozone.cc +++ b/ui/views/widget/desktop_aura/desktop_screen_ozone.cc
@@ -4,6 +4,7 @@ #include "ui/views/widget/desktop_aura/desktop_screen_ozone.h" +#include "ui/aura/screen_ozone.h" #include "ui/display/display.h" #include "ui/display/types/display_constants.h" #include "ui/display/types/display_snapshot.h" @@ -55,7 +56,16 @@ ////////////////////////////////////////////////////////////////////////////// display::Screen* CreateDesktopScreen() { - return new DesktopScreenOzone; + auto platform_screen = ui::OzonePlatform::GetInstance()->CreateScreen(); + if (!platform_screen) { + // TODO: At the moment, only the Ozone/Headless uses this patch. Fix it: + // https://crbug.com/891613 + LOG(ERROR) << "PlatformScreen is not implemented for this ozone platform. " + "Falling back to old DesktopScreenOzone implementation. See " + "https://crbug.com/872339 for details"; + return new DesktopScreenOzone; + } + return new aura::ScreenOzone(std::move(platform_screen)); } } // namespace views
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc index dcf1d7d..fbfa8df1 100644 --- a/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc +++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc
@@ -6,13 +6,16 @@ #include "ui/aura/client/drag_drop_client.h" #include "ui/aura/client/transient_window_client.h" +#include "ui/base/hit_test.h" #include "ui/display/display.h" #include "ui/display/screen.h" #include "ui/gfx/geometry/dip_util.h" #include "ui/platform_window/platform_window.h" +#include "ui/platform_window/platform_window_handler/wm_move_resize_handler.h" #include "ui/platform_window/platform_window_init_properties.h" #include "ui/views/corewm/tooltip_aura.h" #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h" +#include "ui/views/widget/desktop_aura/window_event_filter.h" #include "ui/views/widget/widget_aura_utils.h" #include "ui/views/window/native_frame_view.h" #include "ui/wm/core/window_util.h" @@ -91,6 +94,19 @@ void DesktopWindowTreeHostPlatform::OnNativeWidgetCreated( const Widget::InitParams& params) { native_widget_delegate_->OnNativeWidgetCreated(true); + + // Setup a non_client_window_event_filter, which handles resize/move, double + // click and other events. + DCHECK(!non_client_window_event_filter_); + std::unique_ptr<WindowEventFilter> window_event_filter = + std::make_unique<WindowEventFilter>(this); + auto* wm_move_resize_handler = GetWmMoveResizeHandler(*platform_window()); + if (wm_move_resize_handler) + window_event_filter->SetWmMoveResizeHandler( + GetWmMoveResizeHandler(*(platform_window()))); + + non_client_window_event_filter_ = std::move(window_event_filter); + window()->AddPreTargetHandler(non_client_window_event_filter_.get()); } void DesktopWindowTreeHostPlatform::OnWidgetInitDone() {} @@ -135,6 +151,8 @@ if (!weak_ref || got_on_closed_) return; + RemoveNonClientEventFilter(); + native_widget_delegate_->OnNativeWidgetDestroying(); got_on_closed_ = true; @@ -449,7 +467,34 @@ return true; } +void DesktopWindowTreeHostPlatform::DispatchEvent(ui::Event* event) { +#if defined(USE_OZONE) + // Make sure the |event| is marked as a non-client if it's a non-client + // mouse down event. This is needed to make sure the WindowEventDispatcher + // does not set a |mouse_pressed_handler_| for such events, because they are + // not always followed with non-client mouse up events in case of + // Ozone/Wayland or Ozone/X11. + // + // Also see the comment in WindowEventDispatcher::PreDispatchMouseEvent.. + aura::Window* content_window = desktop_native_widget_aura_->content_window(); + if (content_window && content_window->delegate()) { + if (event->IsMouseEvent()) { + ui::MouseEvent* mouse_event = event->AsMouseEvent(); + int flags = mouse_event->flags(); + int hit_test_code = content_window->delegate()->GetNonClientComponent( + mouse_event->location()); + if (hit_test_code != HTCLIENT && hit_test_code != HTNOWHERE) + flags |= ui::EF_IS_NON_CLIENT; + mouse_event->set_flags(flags); + } + } +#endif + + WindowTreeHostPlatform::DispatchEvent(event); +} + void DesktopWindowTreeHostPlatform::OnClosed() { + RemoveNonClientEventFilter(); got_on_closed_ = true; desktop_native_widget_aura_->OnHostClosed(); } @@ -492,6 +537,14 @@ widget->GetRootView()->Layout(); } +void DesktopWindowTreeHostPlatform::RemoveNonClientEventFilter() { + if (!non_client_window_event_filter_) + return; + + window()->RemovePreTargetHandler(non_client_window_event_filter_.get()); + non_client_window_event_filter_.reset(); +} + Widget* DesktopWindowTreeHostPlatform::GetWidget() { return native_widget_delegate_->AsWidget(); }
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h b/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h index b6219dd..e0b98abd 100644 --- a/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h +++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h
@@ -12,6 +12,8 @@ namespace views { +class WindowEventFilter; + class VIEWS_EXPORT DesktopWindowTreeHostPlatform : public aura::WindowTreeHostPlatform, public DesktopWindowTreeHost { @@ -90,14 +92,19 @@ bool ShouldCreateVisibilityController() const override; // WindowTreeHostPlatform: + void DispatchEvent(ui::Event* event) override; void OnClosed() override; void OnWindowStateChanged(ui::PlatformWindowState new_state) override; void OnCloseRequest() override; void OnActivationChanged(bool active) override; private: + FRIEND_TEST_ALL_PREFIXES(DesktopWindowTreeHostPlatformTest, HitTest); + void Relayout(); + void RemoveNonClientEventFilter(); + Widget* GetWidget(); gfx::Rect ToDIPRect(const gfx::Rect& rect_in_pixels) const; @@ -113,6 +120,9 @@ bool is_active_ = false; + // A handler for events intended for non client area. + std::unique_ptr<WindowEventFilter> non_client_window_event_filter_; + base::WeakPtrFactory<DesktopWindowTreeHostPlatform> weak_factory_{this}; DISALLOW_COPY_AND_ASSIGN(DesktopWindowTreeHostPlatform);
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_platform_interactive_uitest.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_platform_interactive_uitest.cc new file mode 100644 index 0000000..f959917f --- /dev/null +++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_platform_interactive_uitest.cc
@@ -0,0 +1,272 @@ +// 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 "ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h" + +#include "ui/aura/window_tree_host_platform.h" +#include "ui/base/hit_test.h" +#include "ui/platform_window/platform_window.h" +#include "ui/platform_window/platform_window_handler/wm_move_resize_handler.h" +#include "ui/views/test/views_interactive_ui_test_base.h" +#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h" +#include "ui/views/widget/desktop_aura/window_event_filter.h" +#include "ui/views/widget/widget_delegate.h" +#include "ui/views/window/native_frame_view.h" + +namespace views { + +namespace { + +bool IsNonClientComponent(int hittest) { + switch (hittest) { + case HTBOTTOM: + case HTBOTTOMLEFT: + case HTBOTTOMRIGHT: + case HTCAPTION: + case HTLEFT: + case HTRIGHT: + case HTTOP: + case HTTOPLEFT: + case HTTOPRIGHT: + return true; + default: + return false; + } + return true; +} + +// A fake handler, which just stores the hittest and pointer location values. +class FakeWmMoveResizeHandler : public ui::WmMoveResizeHandler { + public: + using SetBoundsCallback = base::RepeatingCallback<void(gfx::Rect)>; + explicit FakeWmMoveResizeHandler(ui::PlatformWindow* window) + : platform_window_(window), hittest_(-1) {} + ~FakeWmMoveResizeHandler() override = default; + + void Reset() { + hittest_ = -1; + pointer_location_ = gfx::Point(); + } + + int hittest() const { return hittest_; } + gfx::Point pointer_location() const { return pointer_location_; } + + void set_bounds(const gfx::Rect& bounds) { bounds_ = bounds; } + + // ui::WmMoveResizeHandler + void DispatchHostWindowDragMovement( + int hittest, + const gfx::Point& pointer_location) override { + hittest_ = hittest; + pointer_location_ = pointer_location; + + platform_window_->SetBounds(bounds_); + } + + private: + ui::PlatformWindow* platform_window_; + gfx::Rect bounds_; + + int hittest_ = -1; + gfx::Point pointer_location_; + + DISALLOW_COPY_AND_ASSIGN(FakeWmMoveResizeHandler); +}; + +void SetExpectationBasedOnHittestValue(int hittest, + const FakeWmMoveResizeHandler& handler, + const gfx::Point& pointer_location) { + if (IsNonClientComponent(hittest)) { + // Ensure both the pointer location and the hit test value are passed to the + // fake move/resize handler. + EXPECT_EQ(handler.pointer_location().ToString(), + pointer_location.ToString()); + EXPECT_EQ(handler.hittest(), hittest); + return; + } + + // Ensure the handler does not receive the hittest value or the pointer + // location. + EXPECT_TRUE(handler.pointer_location().IsOrigin()); + EXPECT_NE(handler.hittest(), hittest); +} + +// This is used to return a customized result to NonClientHitTest. +class HitTestNonClientFrameView : public NativeFrameView { + public: + explicit HitTestNonClientFrameView(Widget* widget) + : NativeFrameView(widget), hit_test_result_(HTNOWHERE) {} + ~HitTestNonClientFrameView() override {} + + void set_hit_test_result(int component) { hit_test_result_ = component; } + + // NonClientFrameView overrides: + int NonClientHitTest(const gfx::Point& point) override { + return hit_test_result_; + } + + private: + int hit_test_result_; + + DISALLOW_COPY_AND_ASSIGN(HitTestNonClientFrameView); +}; + +// This is used to return HitTestNonClientFrameView on create call. +class HitTestWidgetDelegate : public views::WidgetDelegate { + public: + HitTestWidgetDelegate(views::Widget* widget, + HitTestNonClientFrameView* frame_view) + : widget_(widget), frame_view_(frame_view) {} + ~HitTestWidgetDelegate() override {} + + void set_can_resize(bool can_resize) { + can_resize_ = can_resize; + widget_->OnSizeConstraintsChanged(); + } + + // views::WidgetDelegate: + bool CanResize() const override { return can_resize_; } + views::Widget* GetWidget() override { return widget_; } + views::Widget* GetWidget() const override { return widget_; } + views::NonClientFrameView* CreateNonClientFrameView(Widget* widget) override { + return frame_view_; + } + + private: + views::Widget* widget_; + HitTestNonClientFrameView* frame_view_; + bool can_resize_ = false; + + DISALLOW_COPY_AND_ASSIGN(HitTestWidgetDelegate); +}; + +} // namespace + +class DesktopWindowTreeHostPlatformTest : public ViewsInteractiveUITestBase { + public: + DesktopWindowTreeHostPlatformTest() = default; + ~DesktopWindowTreeHostPlatformTest() override = default; + + protected: + Widget* BuildTopLevelDesktopWidget(const gfx::Rect& bounds) { + Widget* toplevel = new Widget; + frame_view_ = new HitTestNonClientFrameView(toplevel); + delegate_ = new HitTestWidgetDelegate(toplevel, frame_view_); + Widget::InitParams toplevel_params = + CreateParams(Widget::InitParams::TYPE_WINDOW); + toplevel_params.native_widget = + new views::DesktopNativeWidgetAura(toplevel); + toplevel_params.delegate = delegate_; + toplevel_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + toplevel_params.bounds = bounds; + toplevel_params.remove_standard_frame = true; + toplevel->Init(toplevel_params); + return toplevel; + } + + std::unique_ptr<ui::MouseEvent> CreateMouseEvent( + const gfx::Point& pointer_location, + ui::EventType event_type, + int flags) { + std::unique_ptr<ui::MouseEvent> mouse_event = + std::make_unique<ui::MouseEvent>(event_type, pointer_location, + pointer_location, + base::TimeTicks::Now(), flags, flags); + return mouse_event; + } + + HitTestNonClientFrameView* frame_view_ = nullptr; + HitTestWidgetDelegate* delegate_ = nullptr; + + private: + DISALLOW_COPY_AND_ASSIGN(DesktopWindowTreeHostPlatformTest); +}; + +TEST_F(DesktopWindowTreeHostPlatformTest, HitTest) { + gfx::Rect bounds(0, 0, 100, 100); + std::unique_ptr<Widget> widget(BuildTopLevelDesktopWidget(bounds)); + widget->Show(); + + aura::Window* window = widget->GetNativeWindow(); + DesktopWindowTreeHostPlatform* host = + static_cast<DesktopWindowTreeHostPlatform*>(window->GetHost()); + + // Install a fake move/resize handler to intercept the move/resize call. + WindowEventFilter* non_client_filter = + host->non_client_window_event_filter_.get(); + std::unique_ptr<FakeWmMoveResizeHandler> handler = + std::make_unique<FakeWmMoveResizeHandler>(host->platform_window()); + non_client_filter->SetWmMoveResizeHandler(handler.get()); + + delegate_->set_can_resize(true); + + // It is not important to use pointer locations corresponding to the hittests + // values used in the browser itself, because we fake the hit test results, + // which non client frame view sends back. Thus, just make sure the content + // window is able to receive these events. + gfx::Point pointer_location(10, 10); + + constexpr int hittest_values[] = { + HTBOTTOM, HTBOTTOMLEFT, HTBOTTOMRIGHT, HTCAPTION, HTLEFT, + HTRIGHT, HTTOP, HTTOPLEFT, HTTOPRIGHT, HTNOWHERE, + HTBORDER, HTCLIENT, HTCLOSE, HTERROR, HTGROWBOX, + HTHELP, HTHSCROLL, HTMENU, HTMAXBUTTON, HTMINBUTTON, + HTREDUCE, HTSIZE, HTSYSMENU, HTTRANSPARENT, HTVSCROLL, + HTZOOM, + }; + + for (int hittest : hittest_values) { + handler->Reset(); + + // Set the desired hit test result value, which will be returned, when + // WindowEventFilter starts to perform hit testing. + frame_view_->set_hit_test_result(hittest); + + gfx::Rect bounds = window->GetBoundsInScreen(); + + // The wm move/resize handler receives pointer location in the global screen + // coordinate, whereas event dispatcher receives event locations on a local + // system coordinate. Thus, add an offset of a new possible origin value of + // a window to the expected pointer location. + gfx::Point expected_pointer_location(pointer_location); + expected_pointer_location.Offset(bounds.x(), bounds.y()); + + if (hittest == HTCAPTION) { + // Move the window on HTCAPTION hit test value. + bounds = + gfx::Rect(gfx::Point(bounds.x() + 2, bounds.y() + 4), bounds.size()); + handler->set_bounds(bounds); + } else if (IsNonClientComponent(hittest)) { + // Resize the window on other than HTCAPTION non client hit test values. + bounds = gfx::Rect( + gfx::Point(bounds.origin()), + gfx::Size(bounds.size().width() + 5, bounds.size().height() + 10)); + handler->set_bounds(bounds); + } + + // Send mouse down event and make sure the WindowEventFilter calls the + // move/resize handler to start interactive move/resize with the |hittest| + // value we specified. + auto mouse_down_event = CreateMouseEvent( + pointer_location, ui::ET_MOUSE_PRESSED, ui::EF_LEFT_MOUSE_BUTTON); + host->DispatchEvent(mouse_down_event.get()); + + // The test expectation is based on the hit test component. If it is a + // non-client component, which results in a call to move/resize, the handler + // must receive the hittest value and the pointer location in global screen + // coordinate system. In other cases, it must not. + SetExpectationBasedOnHittestValue(hittest, *handler.get(), + expected_pointer_location); + // Make sure the bounds of the content window are correct. + EXPECT_EQ(window->GetBoundsInScreen().ToString(), bounds.ToString()); + + // Dispatch mouse up event to release mouse pressed handler and be able to + // consume future events. + auto mouse_up_event = CreateMouseEvent( + pointer_location, ui::ET_MOUSE_RELEASED, ui::EF_LEFT_MOUSE_BUTTON); + host->DispatchEvent(mouse_up_event.get()); + } +} + +} // namespace views
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11_unittest.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11_unittest.cc index 7350780..2f3f85b 100644 --- a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11_unittest.cc +++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11_unittest.cc
@@ -9,6 +9,7 @@ #include "base/command_line.h" #include "base/macros.h" #include "base/run_loop.h" +#include "base/stl_util.h" #include "ui/aura/window.h" #include "ui/aura/window_tree_host.h" #include "ui/base/hit_test.h" @@ -50,11 +51,8 @@ // X11PropertyChangeWaiter: bool ShouldKeepOnWaiting(const ui::PlatformEvent& event) override { std::vector<Atom> hints; - if (ui::GetAtomArrayProperty(xwindow(), "_NET_WM_STATE", &hints)) { - auto it = std::find(hints.cbegin(), hints.cend(), gfx::GetAtom(hint_)); - bool hint_set = (it != hints.cend()); - return hint_set != wait_till_set_; - } + if (ui::GetAtomArrayProperty(xwindow(), "_NET_WM_STATE", &hints)) + return base::ContainsValue(hints, gfx::GetAtom(hint_)) != wait_till_set_; return true; }
diff --git a/ui/views/widget/desktop_aura/window_event_filter.cc b/ui/views/widget/desktop_aura/window_event_filter.cc index 530b079..3b01fb99 100644 --- a/ui/views/widget/desktop_aura/window_event_filter.cc +++ b/ui/views/widget/desktop_aura/window_event_filter.cc
@@ -6,6 +6,7 @@ #include "services/ws/public/mojom/window_tree_constants.mojom.h" #include "ui/aura/client/aura_constants.h" +#include "ui/aura/env.h" #include "ui/aura/window.h" #include "ui/aura/window_delegate.h" #include "ui/aura/window_tree_host.h" @@ -14,6 +15,7 @@ #include "ui/display/screen.h" #include "ui/events/event.h" #include "ui/events/event_utils.h" +#include "ui/platform_window/platform_window_handler/wm_move_resize_handler.h" #include "ui/views/linux_ui/linux_ui.h" #include "ui/views/widget/desktop_aura/desktop_window_tree_host.h" #include "ui/views/widget/native_widget_aura.h" @@ -21,6 +23,28 @@ namespace views { +namespace { + +bool CanPerformDragOrResize(int hittest) { + switch (hittest) { + case HTBOTTOM: + case HTBOTTOMLEFT: + case HTBOTTOMRIGHT: + case HTCAPTION: + case HTLEFT: + case HTRIGHT: + case HTTOP: + case HTTOPLEFT: + case HTTOPRIGHT: + return true; + default: + return false; + } + return true; +} + +} // namespace + WindowEventFilter::WindowEventFilter(DesktopWindowTreeHost* window_tree_host) : window_tree_host_(window_tree_host), click_component_(HTNOWHERE) {} @@ -53,6 +77,12 @@ } } +void WindowEventFilter::SetWmMoveResizeHandler( + ui::WmMoveResizeHandler* handler) { + DCHECK(!handler_); + handler_ = handler; +} + void WindowEventFilter::OnClickedCaption(ui::MouseEvent* event, int previous_click_component) { aura::Window* target = static_cast<aura::Window*>(event->target()); @@ -149,6 +179,18 @@ void WindowEventFilter::MaybeDispatchHostWindowDragMovement( int hittest, - ui::MouseEvent* event) {} + ui::MouseEvent* event) { + if (handler_ && event->IsLeftMouseButton() && + CanPerformDragOrResize(hittest)) { + // Some platforms (eg X11) may require last pointer location not in the + // local surface coordinates, but rather in the screen coordinates for + // interactive move/resize. + const gfx::Point last_pointer_location = + aura::Env::GetInstance()->last_mouse_location(); + handler_->DispatchHostWindowDragMovement(hittest, last_pointer_location); + event->StopPropagation(); + return; + } +} } // namespace views
diff --git a/ui/views/widget/desktop_aura/window_event_filter.h b/ui/views/widget/desktop_aura/window_event_filter.h index a9bc0387..d3d7214 100644 --- a/ui/views/widget/desktop_aura/window_event_filter.h +++ b/ui/views/widget/desktop_aura/window_event_filter.h
@@ -10,6 +10,10 @@ #include "ui/events/event_handler.h" #include "ui/views/views_export.h" +namespace ui { +class WmMoveResizeHandler; +} + namespace views { class DesktopWindowTreeHost; @@ -24,6 +28,11 @@ // Overridden from ui::EventHandler: void OnMouseEvent(ui::MouseEvent* event) override; + // Sets a move resize handler. Currently initialized only by ozone platforms. + // See WaylandWindow::WaylandWindow in the wayland_window.cc file for an + // example. + void SetWmMoveResizeHandler(ui::WmMoveResizeHandler* handler); + private: // Called when the user clicked the caption area. void OnClickedCaption(ui::MouseEvent* event, int previous_click_component); @@ -52,6 +61,11 @@ // components. int click_component_; + // A handler, which is used for interactive move/resize events if set and + // unless MaybeDispatchHostWindowDragMovement is overridden by a derived + // class. + ui::WmMoveResizeHandler* handler_ = nullptr; + DISALLOW_COPY_AND_ASSIGN(WindowEventFilter); };
diff --git a/ui/views/widget/desktop_aura/x11_topmost_window_finder_interactive_uitest.cc b/ui/views/widget/desktop_aura/x11_topmost_window_finder_interactive_uitest.cc index e0a11a0..a688da8c 100644 --- a/ui/views/widget/desktop_aura/x11_topmost_window_finder_interactive_uitest.cc +++ b/ui/views/widget/desktop_aura/x11_topmost_window_finder_interactive_uitest.cc
@@ -11,6 +11,7 @@ #include <vector> #include "base/macros.h" +#include "base/stl_util.h" #include "third_party/skia/include/core/SkRect.h" #include "ui/aura/window.h" #include "ui/aura/window_tree_host.h" @@ -42,9 +43,8 @@ bool ShouldKeepOnWaiting(const ui::PlatformEvent& event) override { std::vector<Atom> wm_states; if (ui::GetAtomArrayProperty(xwindow(), "_NET_WM_STATE", &wm_states)) { - auto it = std::find(wm_states.cbegin(), wm_states.cend(), - gfx::GetAtom("_NET_WM_STATE_HIDDEN")); - return it == wm_states.cend(); + return !base::ContainsValue(wm_states, + gfx::GetAtom("_NET_WM_STATE_HIDDEN")); } return true; } @@ -80,8 +80,7 @@ std::vector<XID> stack; ui::GetXWindowStack(ui::GetX11RootWindow(), &stack); for (size_t i = 0; i < expected_windows_.size(); ++i) { - auto it = std::find(stack.cbegin(), stack.cend(), expected_windows_[i]); - if (it == stack.cend()) + if (!base::ContainsValue(stack, expected_windows_[i])) return true; } return false;