diff --git a/.gitignore b/.gitignore index e49951ff..f9873bb 100644 --- a/.gitignore +++ b/.gitignore
@@ -273,6 +273,7 @@ /ui/keyboard/keyboard_mojom_bindings.xml /ui/surface/surface.xml /ui/surface/surface_gpu_tests.xml +/ui/webui/internal /v8 /webkit/data /webpagereplay_logs/
diff --git a/BUILD.gn b/BUILD.gn index 9d06746..f445ca9 100644 --- a/BUILD.gn +++ b/BUILD.gn
@@ -630,7 +630,6 @@ "//mash:all", "//media/mojo/services:media_service_unittests", "//mojo", - "//services/ui/ws:tests", "//ui/views/mus:views_mus_interactive_ui_tests", "//ui/views/mus:views_mus_unittests", ]
diff --git a/DEPS b/DEPS index 71551e83..64f3a11 100644 --- a/DEPS +++ b/DEPS
@@ -109,7 +109,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': 'd7b61abe7b48928aed739f02bf7695732d359e7e', + 'v8_revision': '8766d3dde17ccd5412c6931c0367c6b89f554b5b', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other. @@ -117,7 +117,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': 'd754eb5620ed7eb6fc26f6b19494d37e4c6d19f1', + 'angle_revision': 'ba365939b90c76e5692aa97d2825dea6fe8bb200', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling build tools # and whatever else without interference from each other. @@ -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': 'c68109a2dac3be544b7753d1fd677255d859745b', + 'pdfium_revision': 'fda907f4ac7ee9589f52d6c13e4bc555f8216c52', # 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': '213eaf4f79bcdfc088cb7a6512948b7777403c7f', + 'catapult_revision': 'ddcfa34d6ad43fceb291a000fa013ad159dc731e', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -539,7 +539,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'b6704082f43ca9ac410ff6422a9c973fb0ca1e8e', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'c3bfa61aedfbf47d6d7b6d524ac1037ecc9c2134', 'condition': 'checkout_linux', }, @@ -559,12 +559,12 @@ }, 'src/third_party/custom_tabs_client/src': { - 'url': Var('chromium_git') + '/custom-tabs-client.git' + '@' + 'bd0bd8af3755f0941c766403c4603a1d8d2ef0f4', + 'url': Var('chromium_git') + '/custom-tabs-client.git' + '@' + '81a14bc0885944a65afa81acd00da16cecb74b8b', 'condition': 'checkout_android', }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '807abf149a5d70e80b2ed1fee11dcec2a7d255bc', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '60b9b6fb9147c8cd512c886bf3969ea114358a56', 'src/third_party/devtools-node-modules': Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'),
diff --git a/WATCHLISTS b/WATCHLISTS index 1225f01..6ee0dd3 100644 --- a/WATCHLISTS +++ b/WATCHLISTS
@@ -1622,6 +1622,16 @@ '|third_party/blink/public/platform/modules/webshare/'\ '|third_party/blink/renderer/modules/webshare/', }, + 'webauthn': { + 'filepath': 'chrome/android/java/src/org/chromium/chrome/browser/webauth/'\ + '|chrome/android/javatests/src/org/chromium/chrome/browser/webauth/'\ + '|chrome/browser/webauthn/'\ + '|chrome/browser/ui/webauthn/'\ + '|chrome/browser/ui/views/webauthn/'\ + '|content/browser/webauth/'\ + '|device/fido/'\ + '|third_party/blink/public/platform/modules/webauth/', + }, 'webgpu': { 'filepath': 'third_party/blink/renderer/modules/webgpu/', }, @@ -2342,6 +2352,7 @@ 'wake_lock': ['mattreynolds+watch@chromium.org'], 'web_package': ['twifkak+watch@chromium.org'], 'web_share': ['mgiuca+watch@chromium.org'], + 'webauthn': ['webauthn-reviews@chromium.org'], 'webgpu': ['cwallez+watch@chromium.org', 'kainino+watch@chromium.org'], 'webrtc_browser_tests': ['phoglund+watch@chromium.org'],
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index 804508c8..8a3ee955 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -1389,9 +1389,6 @@ "//services/preferences/public/cpp", "//services/service_manager/public/cpp", "//services/ui/gpu_host", - - # TODO(sky): this should not be necessary once --mash goes away. - "//services/ui:lib", "//services/ui/public/cpp/input_devices:input_device_controller", "//services/ui/public/interfaces/input_devices", @@ -1705,6 +1702,7 @@ "app_list/presenter/app_list_presenter_impl_unittest.cc", "app_menu/notification_menu_controller_unittest.cc", "app_menu/notification_menu_view_unittest.cc", + "app_menu/notification_overflow_view_unittest.cc", "ash_service_unittest.cc", "assistant/assistant_controller_unittest.cc", "assistant/assistant_screen_context_controller_unittest.cc",
diff --git a/ash/accessibility/accessibility_focus_ring_controller.cc b/ash/accessibility/accessibility_focus_ring_controller.cc index 6d1db06..b9241e17 100644 --- a/ash/accessibility/accessibility_focus_ring_controller.cc +++ b/ash/accessibility/accessibility_focus_ring_controller.cc
@@ -97,6 +97,7 @@ if (!focus_ring_group) return; focus_ring_group->ClearFocusRects(this); + OnLayerChange(focus_ring_group->focus_animation_info()); } void AccessibilityFocusRingController::SetHighlights(
diff --git a/ash/app_menu/BUILD.gn b/ash/app_menu/BUILD.gn index ea88544..24c6f7e 100644 --- a/ash/app_menu/BUILD.gn +++ b/ash/app_menu/BUILD.gn
@@ -18,6 +18,8 @@ "notification_menu_header_view.h", "notification_menu_view.cc", "notification_menu_view.h", + "notification_overflow_view.cc", + "notification_overflow_view.h", ] defines = [ "APP_MENU_IMPLEMENTATION" ]
diff --git a/ash/app_menu/notification_item_view.cc b/ash/app_menu/notification_item_view.cc index d4efe9a..2120ad4 100644 --- a/ash/app_menu/notification_item_view.cc +++ b/ash/app_menu/notification_item_view.cc
@@ -26,6 +26,10 @@ constexpr int kIconVerticalPadding = 4; constexpr int kIconHorizontalPadding = 12; +// Stroke width of MenuItemView border in dips, used to prevent +// NotificationItemView from exceeding the width of MenuItemView. +constexpr int kBorderStrokeWidth = 1; + // The size of the icon in NotificationItemView in dips. constexpr gfx::Size kProportionalIconViewSize(24, 24); @@ -40,7 +44,7 @@ } // namespace NotificationItemView::NotificationItemView( - NotificationItemView::Delegate* delegate, + NotificationMenuView::Delegate* delegate, message_center::SlideOutController::Delegate* slide_out_controller_delegate, const base::string16& title, const base::string16& message, @@ -107,8 +111,9 @@ } gfx::Size NotificationItemView::CalculatePreferredSize() const { - return gfx::Size(views::MenuConfig::instance().touchable_menu_width, - kNotificationItemViewHeight); + return gfx::Size( + views::MenuConfig::instance().touchable_menu_width - kBorderStrokeWidth, + kNotificationItemViewHeight); } void NotificationItemView::Layout() {
diff --git a/ash/app_menu/notification_item_view.h b/ash/app_menu/notification_item_view.h index dbdeaa43..2c81a97 100644 --- a/ash/app_menu/notification_item_view.h +++ b/ash/app_menu/notification_item_view.h
@@ -9,6 +9,7 @@ #include <string> #include "ash/app_menu/app_menu_export.h" +#include "ash/app_menu/notification_menu_view.h" #include "base/strings/string16.h" #include "ui/message_center/views/slide_out_controller.h" #include "ui/views/view.h" @@ -31,16 +32,7 @@ // The view which contains the details of a notification. class APP_MENU_EXPORT NotificationItemView : public views::View { public: - // Used to activate NotificationItemView. - class Delegate { - public: - // Activates the notification corresponding with |notification_id| and - // closes the menu. - virtual void ActivateNotificationAndClose( - const std::string& notification_id) = 0; - }; - - NotificationItemView(NotificationItemView::Delegate* delegate, + NotificationItemView(NotificationMenuView::Delegate* delegate, message_center::SlideOutController::Delegate* slide_out_controller_delegate, const base::string16& title, @@ -66,6 +58,9 @@ const std::string& notification_id() const { return notification_id_; } const base::string16& title() const { return title_; } const base::string16& message() const { return message_; } + const message_center::ProportionalImageView& proportional_image_view() const { + return *proportional_icon_view_; + } private: // Holds the title and message labels. Owned by the views hierarchy. @@ -81,7 +76,7 @@ views::Label* message_label_ = nullptr; // Owned by AppMenuModelAdapter. Used to activate notifications. - Delegate* const delegate_; + NotificationMenuView::Delegate* const delegate_; // Controls the sideways gesture drag behavior. std::unique_ptr<message_center::SlideOutController> slide_out_controller_;
diff --git a/ash/app_menu/notification_menu_controller.cc b/ash/app_menu/notification_menu_controller.cc index c6b5ea9..33f8ffc 100644 --- a/ash/app_menu/notification_menu_controller.cc +++ b/ash/app_menu/notification_menu_controller.cc
@@ -69,7 +69,7 @@ return; // Remove the view from the container. - notification_menu_view_->RemoveNotificationItemView(notification_id); + notification_menu_view_->OnNotificationRemoved(notification_id); if (!notification_menu_view_->IsEmpty()) return; @@ -110,6 +110,11 @@ app_menu_model_adapter_->Cancel(); } +void NotificationMenuController::OnOverflowAddedOrRemoved() { + // Make the root MenuItemView recalculate the menu bounds. + root_menu_->ChildrenChanged(); +} + void NotificationMenuController::InitializeNotificationMenuView() { DCHECK(!notification_menu_view_);
diff --git a/ash/app_menu/notification_menu_controller.h b/ash/app_menu/notification_menu_controller.h index b032ed0a..fa9bdf0 100644 --- a/ash/app_menu/notification_menu_controller.h +++ b/ash/app_menu/notification_menu_controller.h
@@ -6,7 +6,7 @@ #define ASH_APP_MENU_NOTIFICATION_MENU_CONTROLLER_H_ #include "ash/app_menu/app_menu_export.h" -#include "ash/app_menu/notification_item_view.h" +#include "ash/app_menu/notification_menu_view.h" #include "base/scoped_observer.h" #include "ui/message_center/message_center.h" #include "ui/message_center/message_center_observer.h" @@ -19,7 +19,6 @@ namespace ash { class AppMenuModelAdapter; -class NotificationMenuView; // Handles adding/removing NotificationMenuView from the root MenuItemView, // adding the container model entry, and updating the NotificationMenuView @@ -27,7 +26,7 @@ class APP_MENU_EXPORT NotificationMenuController : public message_center::MessageCenterObserver, public message_center::SlideOutController::Delegate, - public NotificationItemView::Delegate { + public NotificationMenuView::Delegate { public: NotificationMenuController(const std::string& app_id, views::MenuItemView* root_menu, @@ -46,7 +45,8 @@ void OnSlideChanged() override; void OnSlideOut() override; - // NotificationItemView::Delegate overrides: + // NotificationMenuView::Delegate overrides: + void OnOverflowAddedOrRemoved() override; void ActivateNotificationAndClose( const std::string& notification_id) override;
diff --git a/ash/app_menu/notification_menu_view.cc b/ash/app_menu/notification_menu_view.cc index 604b540..13702fe 100644 --- a/ash/app_menu/notification_menu_view.cc +++ b/ash/app_menu/notification_menu_view.cc
@@ -6,38 +6,36 @@ #include "ash/app_menu/notification_item_view.h" #include "ash/app_menu/notification_menu_header_view.h" +#include "ash/app_menu/notification_overflow_view.h" #include "ash/public/cpp/app_menu_constants.h" #include "ui/base/models/menu_separator_types.h" +#include "ui/gfx/geometry/point.h" +#include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size.h" #include "ui/message_center/public/cpp/notification.h" #include "ui/message_center/views/proportional_image_view.h" +#include "ui/views/controls/menu/menu_config.h" #include "ui/views/controls/menu/menu_item_view.h" #include "ui/views/controls/menu/menu_separator.h" -#include "ui/views/layout/box_layout.h" namespace ash { NotificationMenuView::NotificationMenuView( - - NotificationItemView::Delegate* notification_item_view_delegate, + Delegate* notification_item_view_delegate, message_center::SlideOutController::Delegate* slide_out_controller_delegate, const std::string& app_id) : app_id_(app_id), notification_item_view_delegate_(notification_item_view_delegate), - slide_out_controller_delegate_(slide_out_controller_delegate) { + slide_out_controller_delegate_(slide_out_controller_delegate), + double_separator_( + new views::MenuSeparator(ui::MenuSeparatorType::DOUBLE_SEPARATOR)), + header_view_(new NotificationMenuHeaderView()) { DCHECK(notification_item_view_delegate_); DCHECK(slide_out_controller_delegate_); DCHECK(!app_id_.empty()) << "Only context menus for applications can show notifications."; - SetLayoutManager(std::make_unique<views::BoxLayout>( - views::BoxLayout::Orientation::kVertical)); - - double_separator_ = - new views::MenuSeparator(ui::MenuSeparatorType::DOUBLE_SEPARATOR); AddChildView(double_separator_); - - header_view_ = new NotificationMenuHeaderView(); AddChildView(header_view_); } @@ -48,18 +46,44 @@ } gfx::Size NotificationMenuView::CalculatePreferredSize() const { - return gfx::Size(views::MenuConfig::instance().touchable_menu_width, - double_separator_->GetPreferredSize().height() + - header_view_->GetPreferredSize().height() + - kNotificationItemViewHeight); + return gfx::Size( + views::MenuConfig::instance().touchable_menu_width, + double_separator_->GetPreferredSize().height() + + header_view_->GetPreferredSize().height() + + kNotificationItemViewHeight + + (overflow_view_ ? overflow_view_->GetPreferredSize().height() : 0)); +} + +void NotificationMenuView::Layout() { + int y = 0; + double_separator_->SetBoundsRect( + gfx::Rect(gfx::Point(0, y), + gfx::Size(views::MenuConfig::instance().touchable_menu_width, + double_separator_->GetPreferredSize().height()))); + y += double_separator_->GetPreferredSize().height(); + + header_view_->SetBoundsRect( + gfx::Rect(gfx::Point(0, y), header_view_->GetPreferredSize())); + y += header_view_->GetPreferredSize().height(); + + if (!notification_item_views_.empty()) { + notification_item_views_.front()->SetBoundsRect( + gfx::Rect(gfx::Point(0, y), + notification_item_views_.front()->GetPreferredSize())); + y += notification_item_views_.front()->GetPreferredSize().height(); + } + + if (overflow_view_) { + overflow_view_->SetBoundsRect( + gfx::Rect(gfx::Point(0, y), overflow_view_->GetPreferredSize())); + } } void NotificationMenuView::AddNotificationItemView( const message_center::Notification& notification) { - // Remove the displayed NotificationItemView, it is still stored in - // |notification_item_views_|. - if (!notification_item_views_.empty()) - RemoveChildView(notification_item_views_.front().get()); + NotificationItemView* old_displayed_notification_item_view = + notification_item_views_.empty() ? nullptr + : notification_item_views_.front().get(); notification_item_views_.push_front(std::make_unique<NotificationItemView>( notification_item_view_delegate_, slide_out_controller_delegate_, @@ -69,8 +93,31 @@ AddChildView(notification_item_views_.front().get()); header_view_->UpdateCounter(notification_item_views_.size()); -} + if (!old_displayed_notification_item_view) + return; + + // Push |old_displayed_notification_item_view| to |overflow_view_|. + RemoveChildView(old_displayed_notification_item_view); + + const bool overflow_view_created = !overflow_view_; + if (!overflow_view_) { + overflow_view_ = std::make_unique<NotificationOverflowView>(); + overflow_view_->set_owned_by_client(); + AddChildView(overflow_view_.get()); + } + overflow_view_->AddIcon( + old_displayed_notification_item_view->proportional_image_view(), + old_displayed_notification_item_view->notification_id()); + + if (overflow_view_created) { + PreferredSizeChanged(); + // OnOverflowAddedOrRemoved must be called after PreferredSizeChange to + // ensure that enough room is allocated for the overflow view. + notification_item_view_delegate_->OnOverflowAddedOrRemoved(); + } + Layout(); +} void NotificationMenuView::UpdateNotificationItemView( const message_center::Notification& notification) { // Find the view which corresponds to |notification|. @@ -89,7 +136,7 @@ notification.icon()); } -void NotificationMenuView::RemoveNotificationItemView( +void NotificationMenuView::OnNotificationRemoved( const std::string& notification_id) { // Find the view which corresponds to |notification_id|. auto notification_iter = std::find_if( @@ -101,12 +148,27 @@ if (notification_iter == notification_item_views_.end()) return; + // Erase the notification from |notification_item_views_| and + // |overflow_view_|. notification_item_views_.erase(notification_iter); + if (overflow_view_) + overflow_view_->RemoveIcon(notification_id); header_view_->UpdateCounter(notification_item_views_.size()); - // Replace the displayed view, if it is already being shown this is a no-op. - if (!notification_item_views_.empty()) + // Display the next notification. + if (!notification_item_views_.empty()) { AddChildView(notification_item_views_.front().get()); + if (overflow_view_) { + overflow_view_->RemoveIcon( + notification_item_views_.front()->notification_id()); + } + } + + if (overflow_view_ && overflow_view_->is_empty()) { + overflow_view_.reset(); + PreferredSizeChanged(); + notification_item_view_delegate_->OnOverflowAddedOrRemoved(); + } } ui::Layer* NotificationMenuView::GetSlideOutLayer() {
diff --git a/ash/app_menu/notification_menu_view.h b/ash/app_menu/notification_menu_view.h index 4b67c01..ca88d3db 100644 --- a/ash/app_menu/notification_menu_view.h +++ b/ash/app_menu/notification_menu_view.h
@@ -9,7 +9,6 @@ #include <string> #include "ash/app_menu/app_menu_export.h" -#include "ash/app_menu/notification_item_view.h" #include "ui/message_center/views/slide_out_controller.h" #include "ui/views/view.h" @@ -24,16 +23,30 @@ namespace ash { class NotificationMenuHeaderView; +class NotificationOverflowView; +class NotificationItemView; // A view inserted into a container MenuItemView which shows a // NotificationItemView and a NotificationMenuHeaderView. class APP_MENU_EXPORT NotificationMenuView : public views::View { public: - explicit NotificationMenuView( - NotificationItemView::Delegate* notification_item_view_delegate, - message_center::SlideOutController::Delegate* - slide_out_controller_delegate, - const std::string& app_id); + // API for child views to interact with the NotificationMenuController. + class Delegate { + public: + virtual ~Delegate() = default; + // Activates the notification corresponding with |notification_id| and + // closes the menu. + virtual void ActivateNotificationAndClose( + const std::string& notification_id) = 0; + + // Called when an overflow view is added or remove. + virtual void OnOverflowAddedOrRemoved() = 0; + }; + + NotificationMenuView(Delegate* notification_item_view_delegate, + message_center::SlideOutController::Delegate* + slide_out_controller_delegate, + const std::string& app_id); ~NotificationMenuView() override; // Whether |notifications_for_this_app_| is empty. @@ -50,9 +63,10 @@ const message_center::Notification& notification); // Removes the NotificationItemView associated with |notification_id| and - // if it is the currently displayed NotificationItemView, replaces it with the - // next one if available. - void RemoveNotificationItemView(const std::string& notification_id); + // if it is the currently displayed NotificationItemView, replaces it with + // the next one if available. Also removes the notification from + // |overflow_view_| if it exists there. + void OnNotificationRemoved(const std::string& notification_id); // Gets the slide out layer, used to move the displayed NotificationItemView. ui::Layer* GetSlideOutLayer(); @@ -62,6 +76,7 @@ // views::View overrides: gfx::Size CalculatePreferredSize() const override; + void Layout() override; private: friend class NotificationMenuViewTestAPI; @@ -70,7 +85,7 @@ const std::string app_id_; // Owned by AppMenuModelAdapter. - NotificationItemView::Delegate* const notification_item_view_delegate_; + NotificationMenuView::Delegate* const notification_item_view_delegate_; // Owned by AppMenuModelAdapter. message_center::SlideOutController::Delegate* const @@ -80,13 +95,17 @@ // which is shown. std::deque<std::unique_ptr<NotificationItemView>> notification_item_views_; - // Holds the header and counter texts. Owned by views hierarchy. - NotificationMenuHeaderView* header_view_ = nullptr; - // A double separator used to distinguish notifications from context menu // options. Owned by views hierarchy. views::MenuSeparator* double_separator_; + // Holds the header and counter texts. Owned by views hierarchy. + NotificationMenuHeaderView* const header_view_; + + // A view that shows icons of notifications for this app that are not being + // shown. + std::unique_ptr<NotificationOverflowView> overflow_view_; + DISALLOW_COPY_AND_ASSIGN(NotificationMenuView); };
diff --git a/ash/app_menu/notification_menu_view_test_api.cc b/ash/app_menu/notification_menu_view_test_api.cc index 789398c..f764334 100644 --- a/ash/app_menu/notification_menu_view_test_api.cc +++ b/ash/app_menu/notification_menu_view_test_api.cc
@@ -7,6 +7,7 @@ #include "ash/app_menu/notification_item_view.h" #include "ash/app_menu/notification_menu_header_view.h" #include "ash/app_menu/notification_menu_view.h" +#include "ash/app_menu/notification_overflow_view.h" #include "ash/public/cpp/app_menu_constants.h" #include "ui/views/controls/label.h" @@ -33,4 +34,8 @@ : notification_menu_view_->notification_item_views_.front().get(); } +NotificationOverflowView* NotificationMenuViewTestAPI::GetOverflowView() const { + return notification_menu_view_->overflow_view_.get(); +} + } // namespace ash
diff --git a/ash/app_menu/notification_menu_view_test_api.h b/ash/app_menu/notification_menu_view_test_api.h index 354c91f..8fe5cb7 100644 --- a/ash/app_menu/notification_menu_view_test_api.h +++ b/ash/app_menu/notification_menu_view_test_api.h
@@ -12,6 +12,7 @@ class NotificationItemView; class NotificationMenuView; +class NotificationOverflowView; // Use the API in this class to test NotificationMenuView. class NotificationMenuViewTestAPI { @@ -29,6 +30,9 @@ // Returns the NotificationItemView currently being displayed. NotificationItemView* GetDisplayedNotificationItemView() const; + // Returns the NotificationOverflowView if it is being shown. + NotificationOverflowView* GetOverflowView() const; + private: NotificationMenuView* const notification_menu_view_;
diff --git a/ash/app_menu/notification_menu_view_unittest.cc b/ash/app_menu/notification_menu_view_unittest.cc index 3b73caf0..f62080d 100644 --- a/ash/app_menu/notification_menu_view_unittest.cc +++ b/ash/app_menu/notification_menu_view_unittest.cc
@@ -28,16 +28,20 @@ class MockNotificationMenuController : public message_center::SlideOutController::Delegate, - public NotificationItemView::Delegate { + public NotificationMenuView::Delegate { public: MockNotificationMenuController() = default; - virtual ~MockNotificationMenuController() = default; + ~MockNotificationMenuController() override = default; void ActivateNotificationAndClose( const std::string& notification_id) override { activation_count_++; } + void OnOverflowAddedOrRemoved() override { + overflow_added_or_removed_count_++; + } + ui::Layer* GetSlideOutLayer() override { return notification_menu_view_->GetSlideOutLayer(); } @@ -53,6 +57,7 @@ int slide_out_count_ = 0; int activation_count_ = 0; + int overflow_added_or_removed_count_ = 0; // Owned by NotificationMenuViewTest. NotificationMenuView* notification_menu_view_ = nullptr; @@ -229,12 +234,67 @@ CheckDisplayedNotification(notification_1); // Remove |notification_1|, |notification_0| should be shown. - notification_menu_view()->RemoveNotificationItemView(notification_1.id()); + notification_menu_view()->OnNotificationRemoved(notification_1.id()); EXPECT_EQ(base::IntToString16(1), test_api()->GetCounterViewContents()); EXPECT_EQ(1, test_api()->GetItemViewCount()); CheckDisplayedNotification(notification_0); } +TEST_F(NotificationMenuViewTest, MultipleNotificationsBasic) { + // Add multiple notifications to the view. + const message_center::Notification notification_0 = + AddNotification("notification_id_0", base::ASCIIToUTF16("title_0"), + base::ASCIIToUTF16("message_0")); + + // Overflow should not be created until there are two notifications. + EXPECT_FALSE(test_api()->GetOverflowView()); + EXPECT_EQ( + 0, mock_notification_menu_controller()->overflow_added_or_removed_count_); + + // Add a second notification, this will push |notification_0| into overflow. + const message_center::Notification notification_1 = + AddNotification("notification_id_1", base::ASCIIToUTF16("title_1"), + base::ASCIIToUTF16("message_1")); + + CheckDisplayedNotification(notification_1); + EXPECT_TRUE(test_api()->GetOverflowView()); + EXPECT_EQ( + 1, mock_notification_menu_controller()->overflow_added_or_removed_count_); + + // Remove the notification that is in overflow. + notification_menu_view()->OnNotificationRemoved(notification_0.id()); + + // The displayed notification should not have changed, and the overflow view + // should be deleted. + CheckDisplayedNotification(notification_1); + EXPECT_FALSE(test_api()->GetOverflowView()); +} + +// Tests that when the displayed NotificationItemView is removed, the +// notification from the overflow view becomes the displayed view. +TEST_F(NotificationMenuViewTest, ShowNotificationFromOverflow) { + // Add multiple notifications to the view. + const message_center::Notification notification_0 = + AddNotification("notification_id_0", base::ASCIIToUTF16("title_0"), + base::ASCIIToUTF16("message_0")); + + EXPECT_FALSE(test_api()->GetOverflowView()); + const message_center::Notification notification_1 = + AddNotification("notification_id_1", base::ASCIIToUTF16("title_1"), + base::ASCIIToUTF16("message_1")); + + // |notification_1| should be the displayed NotificationItemView. + CheckDisplayedNotification(notification_1); + EXPECT_TRUE(test_api()->GetOverflowView()); + + // Remove the displayed NotificationItemView, the overflow notification should + // take its place and overflow should be removed. + notification_menu_view()->OnNotificationRemoved(notification_1.id()); + + CheckDisplayedNotification(notification_0); + EXPECT_FALSE(test_api()->GetOverflowView()); +} + // Tests that removing a notification that is not being shown only updates the // counter. TEST_F(NotificationMenuViewTest, RemoveOlderNotification) { @@ -252,7 +312,7 @@ CheckDisplayedNotification(notification_1); // Remove the older notification, |notification_0|. - notification_menu_view()->RemoveNotificationItemView(notification_0.id()); + notification_menu_view()->OnNotificationRemoved(notification_0.id()); // The latest notification, |notification_1|, should be shown. EXPECT_EQ(base::IntToString16(1), test_api()->GetCounterViewContents());
diff --git a/ash/app_menu/notification_overflow_view.cc b/ash/app_menu/notification_overflow_view.cc new file mode 100644 index 0000000..21ef1cb --- /dev/null +++ b/ash/app_menu/notification_overflow_view.cc
@@ -0,0 +1,154 @@ +// 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/app_menu/notification_overflow_view.h" + +#include "ash/public/cpp/app_menu_constants.h" +#include "ui/base/models/menu_separator_types.h" +#include "ui/gfx/geometry/rect.h" +#include "ui/gfx/geometry/size.h" +#include "ui/gfx/image/image.h" +#include "ui/gfx/paint_vector_icon.h" +#include "ui/message_center/views/proportional_image_view.h" +#include "ui/views/background.h" +#include "ui/views/border.h" +#include "ui/views/controls/menu/menu_config.h" +#include "ui/views/controls/menu/menu_separator.h" +#include "ui/views/vector_icons.h" + +namespace { + +// Padding in dips between the overflow separator and overflow icons. +constexpr int kOverflowSeparatorToIconPadding = 8; + +// Padding in dips below the overflow icons. +constexpr int kOverflowAreaBottomPadding = 12; + +// Size of overflow icons in dips. +constexpr int kIconSize = 16; + +// Size used for laying out overflow icons in dips to prevent clipping. +constexpr int kIconLayoutSize = kIconSize + 1; + +// Padding between overflow icons in dips. +constexpr int kInterIconPadding = 8; + +// Color used for |overflow_icon_|. +constexpr SkColor kOverflowIconColor = SkColorSetRGB(0x5F, 0x63, 0x60); + +} // namespace + +namespace ash { + +// The icon which represents a notification. +class NotificationOverflowImageView + : public message_center::ProportionalImageView { + public: + NotificationOverflowImageView(const gfx::ImageSkia& image, + const std::string& notification_id) + : message_center::ProportionalImageView(gfx::Size(kIconSize, kIconSize)), + notification_id_(notification_id) { + set_id(kNotificationOverflowIconId); + set_owned_by_client(); + SetImage(image, gfx::Size(kIconSize, kIconSize)); + } + ~NotificationOverflowImageView() override = default; + + const std::string& notification_id() const { return notification_id_; } + + private: + std::string const notification_id_; + + DISALLOW_COPY_AND_ASSIGN(NotificationOverflowImageView); +}; + +NotificationOverflowView::NotificationOverflowView() + : separator_( + new views::MenuSeparator(ui::MenuSeparatorType::NORMAL_SEPARATOR)) { + SetBorder(views::CreateEmptyBorder( + gfx::Insets(0, kNotificationHorizontalPadding, kOverflowAreaBottomPadding, + kNotificationHorizontalPadding))); + SetBackground(views::CreateSolidBackground(SK_ColorWHITE)); + + AddChildView(separator_); +} + +NotificationOverflowView::~NotificationOverflowView() = default; + +void NotificationOverflowView::AddIcon( + const message_center::ProportionalImageView& image_view, + const std::string& notification_id) { + // Insert the image at the front of the list, so that it appears on the right + // side. + image_views_.insert(image_views_.begin(), + std::make_unique<NotificationOverflowImageView>( + image_view.image(), notification_id)); + AddChildView(image_views_.front().get()); + + if (image_views_.size() > kMaxOverflowIcons) { + if (!overflow_icon_) { + gfx::Image icon = gfx::Image(gfx::CreateVectorIcon( + views::kOptionsIcon, kIconSize, kOverflowIconColor)); + overflow_icon_ = std::make_unique<message_center::ProportionalImageView>( + gfx::Size(kIconSize, kIconSize)); + overflow_icon_->set_id(kOverflowIconId); + overflow_icon_->set_owned_by_client(); + overflow_icon_->SetImage(icon.AsImageSkia(), + gfx::Size(kIconSize, kIconSize)); + AddChildView(overflow_icon_.get()); + } + RemoveChildView(image_views_.at(kMaxOverflowIcons).get()); + } + Layout(); +} + +void NotificationOverflowView::RemoveIcon(const std::string& notification_id) { + for (auto it = image_views_.begin(); it != image_views_.end(); ++it) { + if ((*it)->notification_id() != notification_id) + continue; + + image_views_.erase(it); + MaybeRemoveOverflowIcon(); + Layout(); + return; + } +} + +void NotificationOverflowView::Layout() { + separator_->SetBoundsRect( + gfx::Rect(width(), separator_->GetPreferredSize().height())); + + int x = width() - GetInsets().right(); + const int y = + separator_->GetPreferredSize().height() + kOverflowSeparatorToIconPadding; + + for (size_t i = 0; i < image_views_.size() && i <= kMaxOverflowIcons; ++i) { + views::View* icon = image_views_.at(i).get(); + if (i == kMaxOverflowIcons) + icon = overflow_icon_.get(); + + x -= kIconLayoutSize; + icon->SetBounds(x, y, kIconLayoutSize, kIconLayoutSize); + x -= kInterIconPadding; + } +} + +gfx::Size NotificationOverflowView::CalculatePreferredSize() const { + // This view is the last element in a MenuItemView, which means it has extra + // padding on the bottom due to the corner radius of the root MenuItemView. If + // the corner radius changes, |kOverflowSeparatorToIconPadding| must be + // modified to vertically center the overflow icons. + return gfx::Size(views::MenuConfig::instance().touchable_menu_width, + separator_->GetPreferredSize().height() + + kOverflowSeparatorToIconPadding + kIconLayoutSize); +} + +void NotificationOverflowView::MaybeRemoveOverflowIcon() { + if (!overflow_icon_ || image_views_.size() > kMaxOverflowIcons) + return; + + overflow_icon_.reset(); +} + +} // namespace ash
diff --git a/ash/app_menu/notification_overflow_view.h b/ash/app_menu/notification_overflow_view.h new file mode 100644 index 0000000..9d88ce9 --- /dev/null +++ b/ash/app_menu/notification_overflow_view.h
@@ -0,0 +1,66 @@ +// 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_APP_MENU_NOTIFICATION_OVERFLOW_VIEW_H_ +#define ASH_APP_MENU_NOTIFICATION_OVERFLOW_VIEW_H_ + +#include <memory> +#include <vector> + +#include "ash/app_menu/app_menu_export.h" +#include "ash/app_menu/notification_item_view.h" + +namespace message_center { +class ProportionalImageView; +} + +namespace views { +class MenuSeparator; +} + +namespace ash { +class NotificationOverflowImageView; + +class APP_MENU_EXPORT NotificationOverflowView : public views::View { + public: + NotificationOverflowView(); + + ~NotificationOverflowView() override; + + // Creates a copy of |image_view| and adds it as a child view, using + // |notification_id| as an identifier. + void AddIcon(const message_center::ProportionalImageView& image_view, + const std::string& notification_id); + + // Removes an icon by its |notification_id|. + void RemoveIcon(const std::string& notification_id); + + // views::View overrides: + void Layout() override; + gfx::Size CalculatePreferredSize() const override; + + // Whether this has notifications to show. + bool is_empty() const { return image_views_.empty(); } + + private: + // Removes |overflow_icon_| if it is no longer needed. + void MaybeRemoveOverflowIcon(); + + // The horizontal separator that is placed between the displayed + // NotificationItemView and the overflow icons. Owned by the views hierarchy. + views::MenuSeparator* separator_; + + // The list of overflow icons. Listed in right to left ordering. + std::vector<std::unique_ptr<NotificationOverflowImageView>> image_views_; + + // The overflow icon shown when there are more than |kMaxOverflowIcons| + // notifications. + std::unique_ptr<message_center::ProportionalImageView> overflow_icon_; + + DISALLOW_COPY_AND_ASSIGN(NotificationOverflowView); +}; + +} // namespace ash + +#endif // ASH_APP_MENU_NOTIFICATION_OVERFLOW_VIEW_H_
diff --git a/ash/app_menu/notification_overflow_view_unittest.cc b/ash/app_menu/notification_overflow_view_unittest.cc new file mode 100644 index 0000000..cc090ca --- /dev/null +++ b/ash/app_menu/notification_overflow_view_unittest.cc
@@ -0,0 +1,125 @@ +// 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/app_menu/notification_overflow_view.h" + +#include <string> + +#include "ash/public/cpp/app_menu_constants.h" +#include "base/strings/string_number_conversions.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/message_center/views/proportional_image_view.h" +#include "ui/views/test/views_test_base.h" + +namespace ash { + +class NotificationOverflowViewTest : public views::ViewsTestBase { + public: + NotificationOverflowViewTest() {} + ~NotificationOverflowViewTest() override = default; + + // views::ViewsTestBase: + void SetUp() override { + views::ViewsTestBase::SetUp(); + notification_overflow_view_ = std::make_unique<NotificationOverflowView>(); + } + + // Adds a notification and returns the string identifier. + std::string AddNotification() { + message_center::ProportionalImageView image_view(gfx::Size(16, 16)); + std::string notification_id = base::IntToString(notification_identifier_++); + notification_overflow_view_->AddIcon(image_view, notification_id); + return notification_id; + } + + // Checks whether |expected_notification_icons| notification icons are being + // shown in the overflow. Does not include the overflow icon. + void CheckNumberOfNotificationIcons(int expected_notification_icons) { + int actual_notification_icons = 0; + for (auto* v : notification_overflow_view_->GetChildrenInZOrder()) { + if (v->id() != kNotificationOverflowIconId) + continue; + + actual_notification_icons++; + } + DCHECK_EQ(expected_notification_icons, actual_notification_icons); + } + + // Returns whether the overflow icon is being shown. + bool HasOverflowIcon() { + for (auto* v : notification_overflow_view_->GetChildrenInZOrder()) { + if (v->id() != kOverflowIconId) + continue; + + return true; + } + return false; + } + + NotificationOverflowView* notification_overflow_view() { + return notification_overflow_view_.get(); + } + + private: + int notification_identifier_ = 0; + std::unique_ptr<NotificationOverflowView> notification_overflow_view_; + + DISALLOW_COPY_AND_ASSIGN(NotificationOverflowViewTest); +}; + +// Tests that icons get added and removed when notifications come and go. +TEST_F(NotificationOverflowViewTest, Basic) { + // Initially no notification icons should be shown. + CheckNumberOfNotificationIcons(0); + EXPECT_FALSE(HasOverflowIcon()); + + // Add a notification, an icon should be created. + std::string id = AddNotification(); + CheckNumberOfNotificationIcons(1); + EXPECT_FALSE(HasOverflowIcon()); + + // Try to remove a notification that doesn't exist. Nothing should change. + notification_overflow_view()->RemoveIcon("non-existent-notification-id"); + CheckNumberOfNotificationIcons(1); + EXPECT_FALSE(HasOverflowIcon()); + + // Remove the notification that was added earlier, the icon should be removed. + notification_overflow_view()->RemoveIcon(id); + CheckNumberOfNotificationIcons(0); + EXPECT_FALSE(HasOverflowIcon()); +} + +// Tests that the overflow icon gets added when more than |kMaxOverflowIcons| +// icons are added. +TEST_F(NotificationOverflowViewTest, OverflowIcon) { + // Add notifications until just before overflow. + for (int i = 0; i < kMaxOverflowIcons; ++i) { + AddNotification(); + CheckNumberOfNotificationIcons(i + 1); + EXPECT_FALSE(HasOverflowIcon()); + } + + // Add one more notification, the overflow icon should appear instead of that + // new notification. + AddNotification(); + + CheckNumberOfNotificationIcons(kMaxOverflowIcons); + EXPECT_TRUE(HasOverflowIcon()); + + // Remove any notification that was added. The overflow icon should dissapear. + notification_overflow_view()->RemoveIcon(base::IntToString(0)); + CheckNumberOfNotificationIcons(kMaxOverflowIcons); + EXPECT_FALSE(HasOverflowIcon()); + + // Add a few more (over |kMaxOverflowIcons|) notifications to show the + // overflow icon. + AddNotification(); + AddNotification(); + AddNotification(); + + CheckNumberOfNotificationIcons(kMaxOverflowIcons); + EXPECT_TRUE(HasOverflowIcon()); +} + +} // namespace ash
diff --git a/ash/ash_service_unittest.cc b/ash/ash_service_unittest.cc index eeb7e0e..566b258e 100644 --- a/ash/ash_service_unittest.cc +++ b/ash/ash_service_unittest.cc
@@ -114,8 +114,7 @@ // |ash|, but is async. std::unique_ptr<aura::WindowTreeClient> client = aura::WindowTreeClient::CreateForWindowTreeFactory( - connector(), &window_tree_delegate, false, nullptr, - aura::WindowTreeClient::Config::kMus2); + connector(), &window_tree_delegate, false, nullptr); aura::test::EnvWindowTreeClientSetter env_window_tree_client_setter( client.get()); std::map<std::string, std::vector<uint8_t>> properties;
diff --git a/ash/assistant/assistant_screen_context_controller.cc b/ash/assistant/assistant_screen_context_controller.cc index 68260a5..fc71592 100644 --- a/ash/assistant/assistant_screen_context_controller.cc +++ b/ash/assistant/assistant_screen_context_controller.cc
@@ -109,6 +109,7 @@ AssistantScreenContextController::AssistantScreenContextController( AssistantController* assistant_controller) : assistant_controller_(assistant_controller), + assistant_screen_context_subscriber_binding_(this), screen_context_request_factory_(this) { assistant_controller_->AddObserver(this); Shell::Get()->highlighter_controller()->AddObserver(this); @@ -121,7 +122,12 @@ void AssistantScreenContextController::SetAssistant( chromeos::assistant::mojom::Assistant* assistant) { - assistant_ = std::move(assistant); + assistant_ = assistant; + + // Subscribe to Assistant screen context events. + chromeos::assistant::mojom::AssistantScreenContextSubscriberPtr ptr; + assistant_screen_context_subscriber_binding_.Bind(mojo::MakeRequest(&ptr)); + assistant_->AddAssistantScreenContextSubscriber(std::move(ptr)); } void AssistantScreenContextController::AddModelObserver( @@ -221,6 +227,14 @@ ScreenContextRequestState::kIdle); } +void AssistantScreenContextController::OnContextualHtmlResponse( + const std::string& html) { + // TODO(dmblack): Cache |html| in the |assistant_screen_context_model_| and + // notify a pool of observers. This HTML string is from a trusted source and + // will be rendered in a WebContents as is. + NOTIMPLEMENTED(); +} + std::unique_ptr<ui::LayerTreeOwner> AssistantScreenContextController::CreateLayerForAssistantSnapshotForTest() { aura::Window* root_window = Shell::GetPrimaryRootWindow();
diff --git a/ash/assistant/assistant_screen_context_controller.h b/ash/assistant/assistant_screen_context_controller.h index 6bbf545..0cdb081 100644 --- a/ash/assistant/assistant_screen_context_controller.h +++ b/ash/assistant/assistant_screen_context_controller.h
@@ -16,6 +16,7 @@ #include "base/macros.h" #include "base/observer_list.h" #include "chromeos/services/assistant/public/mojom/assistant.mojom.h" +#include "mojo/public/cpp/bindings/binding.h" #include "ui/gfx/geometry/rect.h" namespace ui { @@ -28,7 +29,8 @@ class AssistantScreenContextModelObserver; class ASH_EXPORT AssistantScreenContextController - : public AssistantControllerObserver, + : public chromeos::assistant::mojom::AssistantScreenContextSubscriber, + public AssistantControllerObserver, public AssistantUiModelObserver, public HighlighterController::Observer { public: @@ -68,6 +70,9 @@ // Invoked on screen context request finished event. void OnScreenContextRequestFinished(); + // chromeos::assistant::mojom::AssistantScreenContextSubscriber: + void OnContextualHtmlResponse(const std::string& html) override; + std::unique_ptr<ui::LayerTreeOwner> CreateLayerForAssistantSnapshotForTest(); private: @@ -75,6 +80,9 @@ AssistantController* const assistant_controller_; // Owned by Shell. + mojo::Binding<chromeos::assistant::mojom::AssistantScreenContextSubscriber> + assistant_screen_context_subscriber_binding_; + // Owned by AssistantController. chromeos::assistant::mojom::Assistant* assistant_ = nullptr;
diff --git a/ash/components/autoclick/autoclick_application.cc b/ash/components/autoclick/autoclick_application.cc index 74afbef3..01e55fb2 100644 --- a/ash/components/autoclick/autoclick_application.cc +++ b/ash/components/autoclick/autoclick_application.cc
@@ -96,7 +96,6 @@ views::AuraInit::InitParams params; params.connector = context()->connector(); params.identity = context()->identity(); - params.mode = views::AuraInit::Mode::AURA_MUS; params.register_path_provider = running_standalone_; aura_init_ = views::AuraInit::Create(params); if (!aura_init_) {
diff --git a/ash/components/quick_launch/quick_launch_application.cc b/ash/components/quick_launch/quick_launch_application.cc index 8e9ff3f..7c8af20 100644 --- a/ash/components/quick_launch/quick_launch_application.cc +++ b/ash/components/quick_launch/quick_launch_application.cc
@@ -177,7 +177,6 @@ views::AuraInit::InitParams params; params.connector = context()->connector(); params.identity = context()->identity(); - params.mode = views::AuraInit::Mode::AURA_MUS2; params.register_path_provider = running_standalone_; aura_init_ = views::AuraInit::Create(params); if (!aura_init_) {
diff --git a/ash/components/shortcut_viewer/shortcut_viewer_application.cc b/ash/components/shortcut_viewer/shortcut_viewer_application.cc index 79433bd..4d251c4 100644 --- a/ash/components/shortcut_viewer/shortcut_viewer_application.cc +++ b/ash/components/shortcut_viewer/shortcut_viewer_application.cc
@@ -36,7 +36,6 @@ views::AuraInit::InitParams params; params.connector = context()->connector(); params.identity = context()->identity(); - params.mode = views::AuraInit::Mode::AURA_MUS2; params.register_path_provider = false; params.use_accessibility_host = true; aura_init_ = views::AuraInit::Create(params);
diff --git a/ash/components/tap_visualizer/tap_visualizer_app.cc b/ash/components/tap_visualizer/tap_visualizer_app.cc index 86efb11c..d096081 100644 --- a/ash/components/tap_visualizer/tap_visualizer_app.cc +++ b/ash/components/tap_visualizer/tap_visualizer_app.cc
@@ -48,7 +48,6 @@ views::AuraInit::InitParams params; params.connector = context()->connector(); params.identity = context()->identity(); - params.mode = views::AuraInit::Mode::AURA_MUS2; params.register_path_provider = false; aura_init_ = views::AuraInit::Create(params); if (!aura_init_) {
diff --git a/ash/frame/custom_frame_view_ash_unittest.cc b/ash/frame/custom_frame_view_ash_unittest.cc index 0e32b41..6b4b50f 100644 --- a/ash/frame/custom_frame_view_ash_unittest.cc +++ b/ash/frame/custom_frame_view_ash_unittest.cc
@@ -617,6 +617,7 @@ CustomFrameViewAsh* custom_frame_view = delegate->custom_frame_view(); HeaderView* header_view = static_cast<HeaderView*>(custom_frame_view->GetHeaderView()); + widget->Maximize(); WideFrameView* wide_frame_view = WideFrameView::Create(widget.get()); wide_frame_view->GetWidget()->Show(); @@ -680,6 +681,13 @@ UpdateDisplay("1234x800"); EXPECT_EQ(1234, wide_frame_view->GetWidget()->GetWindowBoundsInScreen().width()); + + // Double Click + EXPECT_TRUE(widget->IsMaximized()); + generator->MoveMouseToCenterOf( + wide_header_view->GetWidget()->GetNativeWindow()); + generator->DoubleClickLeftButton(); + EXPECT_FALSE(widget->IsMaximized()); } TEST_F(CustomFrameViewAshTest, WideFrameButton) {
diff --git a/ash/frame/wide_frame_view.cc b/ash/frame/wide_frame_view.cc index e535429..af03f9e 100644 --- a/ash/frame/wide_frame_view.cc +++ b/ash/frame/wide_frame_view.cc
@@ -10,6 +10,9 @@ #include "ash/public/cpp/ash_layout_constants.h" #include "ash/public/cpp/immersive/immersive_fullscreen_controller.h" #include "ash/public/cpp/window_properties.h" +#include "ash/wm/window_state.h" +#include "ash/wm/wm_event.h" +#include "base/metrics/user_metrics.h" #include "ui/aura/window.h" #include "ui/aura/window_targeter.h" #include "ui/display/display.h" @@ -134,6 +137,18 @@ } } +void WideFrameView::OnMouseEvent(ui::MouseEvent* event) { + if (event->IsOnlyLeftMouseButton()) { + if ((event->flags() & ui::EF_IS_DOUBLE_CLICK)) { + base::RecordAction( + base::UserMetricsAction("Caption_ClickTogglesMaximize")); + const wm::WMEvent wm_event(wm::WM_EVENT_TOGGLE_MAXIMIZE_CAPTION); + wm::GetWindowState(target_->GetNativeWindow())->OnWMEvent(&wm_event); + } + event->SetHandled(); + } +} + void WideFrameView::OnWindowDestroying(aura::Window* window) { window->RemoveObserver(this); target_ = nullptr;
diff --git a/ash/frame/wide_frame_view.h b/ash/frame/wide_frame_view.h index 8e5ce1a..351d9c66 100644 --- a/ash/frame/wide_frame_view.h +++ b/ash/frame/wide_frame_view.h
@@ -62,6 +62,7 @@ // views::View: void Layout() override; + void OnMouseEvent(ui::MouseEvent* event) override; // aura::WindowObserver: void OnWindowDestroying(aura::Window* window) override;
diff --git a/ash/login/ui/lock_contents_view.cc b/ash/login/ui/lock_contents_view.cc index 65d864f..e46bfb73 100644 --- a/ash/login/ui/lock_contents_view.cc +++ b/ash/login/ui/lock_contents_view.cc
@@ -1443,6 +1443,9 @@ AcceleratorAction::kFocusNextUser; accel_map_[ui::Accelerator(ui::VKEY_LEFT, 0)] = AcceleratorAction::kFocusPreviousUser; + accel_map_[ui::Accelerator( + ui::VKEY_R, ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN)] = + AcceleratorAction::kShowResetScreen; AcceleratorController* controller = Shell::Get()->accelerator_controller(); for (const auto& item : accel_map_) @@ -1460,6 +1463,9 @@ case AcceleratorAction::kFocusPreviousUser: FocusPreviousUser(); return; + case AcceleratorAction::kShowResetScreen: + Shell::Get()->login_screen_controller()->ShowResetScreen(); + return; default: NOTREACHED(); }
diff --git a/ash/login/ui/lock_contents_view.h b/ash/login/ui/lock_contents_view.h index 52d7ba7a..7c9c3ccc 100644 --- a/ash/login/ui/lock_contents_view.h +++ b/ash/login/ui/lock_contents_view.h
@@ -104,6 +104,7 @@ kShowFeedback, kFocusNextUser, kFocusPreviousUser, + kShowResetScreen, }; // Number of login attempts before a login dialog is shown. For example, if
diff --git a/ash/public/cpp/app_menu_constants.h b/ash/public/cpp/app_menu_constants.h index 21d4356..125dbc7 100644 --- a/ash/public/cpp/app_menu_constants.h +++ b/ash/public/cpp/app_menu_constants.h
@@ -61,6 +61,16 @@ // Height of the NotificationItemView in dips. constexpr int kNotificationItemViewHeight = 48; +// The maximum number of overflow icons which can be shown without the +// showing |overflow_icon_|. +constexpr int kMaxOverflowIcons = 9; + +// The identifier used for notifications in the NotificationOverflowView. +constexpr int kNotificationOverflowIconId = 43; + +// The identifier used for the overflow icon in NotificationOverflowView. +constexpr int kOverflowIconId = 44; + } // namespace ash #endif // ASH_PUBLIC_CPP_APP_MENU_CONSTANTS_H_
diff --git a/ash/resources/vector_icons/BUILD.gn b/ash/resources/vector_icons/BUILD.gn index b9078b9..7130817 100644 --- a/ash/resources/vector_icons/BUILD.gn +++ b/ash/resources/vector_icons/BUILD.gn
@@ -142,6 +142,7 @@ "system_menu_mouse.icon", "system_menu_phone.icon", "system_menu_power.icon", + "system_menu_rollback.icon", "system_menu_rotation_lock_auto.icon", "system_menu_rotation_lock_landscape.icon", "system_menu_rotation_lock_portrait.icon",
diff --git a/ash/resources/vector_icons/system_menu_rollback.icon b/ash/resources/vector_icons/system_menu_rollback.icon new file mode 100644 index 0000000..8fec5be --- /dev/null +++ b/ash/resources/vector_icons/system_menu_rollback.icon
@@ -0,0 +1,37 @@ +// 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. + +CANVAS_DIMENSIONS, 40, +MOVE_TO, 20, 36, +R_CUBIC_TO, 8.84f, 0, 16, -7.16f, 16, -16, +CUBIC_TO_SHORTHAND, 28.84f, 4, 20, 4, +CUBIC_TO_SHORTHAND, 4, 11.16f, 4, 20, +R_CUBIC_TO, 0, 8.84f, 7.16f, 16, 16, 16, +CLOSE, +R_MOVE_TO, -4, -25, +R_H_LINE_TO, 8, +R_V_LINE_TO, 6, +R_H_LINE_TO, 6, +LINE_TO, 20, 29, +LINE_TO, 10, 17, +R_H_LINE_TO, 6, +R_V_LINE_TO, -6, +CLOSE + +CANVAS_DIMENSIONS, 20, +MOVE_TO, 10, 18, +R_CUBIC_TO, 4.42f, 0, 8, -3.58f, 8, -8, +R_CUBIC_TO, 0, -4.42f, -3.58f, -8, -8, -8, +R_CUBIC_TO, -4.42f, 0, -8, 3.58f, -8, 8, +R_CUBIC_TO, 0, 4.42f, 3.58f, 8, 8, 8, +CLOSE, +R_MOVE_TO, -2, -12, +R_H_LINE_TO, 4, +R_V_LINE_TO, 3, +R_H_LINE_TO, 3, +R_LINE_TO, -5, 6, +R_LINE_TO, -5, -6, +R_H_LINE_TO, 3, +R_V_LINE_TO, -3, +CLOSE
diff --git a/ash/system/update/update_notification_controller.cc b/ash/system/update/update_notification_controller.cc index c0c4ac4e..2a0a8d35 100644 --- a/ash/system/update/update_notification_controller.cc +++ b/ash/system/update/update_notification_controller.cc
@@ -61,7 +61,8 @@ base::BindRepeating( &UpdateNotificationController::HandleNotificationClick, weak_ptr_factory_.GetWeakPtr())), - kSystemMenuUpdateIcon, warning_level); + model_->rollback() ? kSystemMenuRollbackIcon : kSystemMenuUpdateIcon, + warning_level); notification->set_pinned(true); if (model_->update_required()) {
diff --git a/base/metrics/field_trial.h b/base/metrics/field_trial.h index ac4ea1c..f0e55ad8 100644 --- a/base/metrics/field_trial.h +++ b/base/metrics/field_trial.h
@@ -487,6 +487,8 @@ // the trial does not exist. The first call of this function on a given field // trial will mark it as active, so that its state will be reported with usage // metrics, crashes, etc. + // Note: Direct use of this function and related FieldTrial functions is + // generally discouraged - instead please use base::Feature when possible. static std::string FindFullName(const std::string& trial_name); // Returns true if the named trial has been registered.
diff --git a/base/values.cc b/base/values.cc index 085f0f0..be1313a8 100644 --- a/base/values.cc +++ b/base/values.cc
@@ -153,8 +153,11 @@ Value::Value(StringPiece16 in_string16) : Value(UTF16ToUTF8(in_string16)) {} -Value::Value(const BlobStorage& in_blob) - : type_(Type::BINARY), binary_value_(in_blob) {} +Value::Value(const std::vector<char>& in_blob) + : type_(Type::BINARY), binary_value_(in_blob.begin(), in_blob.end()) {} + +Value::Value(base::span<const uint8_t> in_blob) + : type_(Type::BINARY), binary_value_(in_blob.begin(), in_blob.end()) {} Value::Value(BlobStorage&& in_blob) noexcept : type_(Type::BINARY), binary_value_(std::move(in_blob)) {}
diff --git a/base/values.h b/base/values.h index e9253db4..2aa0376329 100644 --- a/base/values.h +++ b/base/values.h
@@ -80,7 +80,7 @@ // } class BASE_EXPORT Value { public: - using BlobStorage = std::vector<char>; + using BlobStorage = std::vector<uint8_t>; using DictStorage = flat_map<std::string, std::unique_ptr<Value>>; using ListStorage = std::vector<Value>; @@ -130,7 +130,8 @@ explicit Value(const char16* in_string16); explicit Value(StringPiece16 in_string16); - explicit Value(const BlobStorage& in_blob); + explicit Value(const std::vector<char>& in_blob); + explicit Value(base::span<const uint8_t> in_blob); explicit Value(BlobStorage&& in_blob) noexcept; explicit Value(const DictStorage& in_dict);
diff --git a/base/values_unittest.cc b/base/values_unittest.cc index b8efac7..c9185fd 100644 --- a/base/values_unittest.cc +++ b/base/values_unittest.cc
@@ -789,7 +789,7 @@ // Test the common case of a non-empty buffer Value::BlobStorage buffer(15); - char* original_buffer = buffer.data(); + uint8_t* original_buffer = buffer.data(); binary.reset(new Value(std::move(buffer))); ASSERT_TRUE(binary.get()); ASSERT_TRUE(binary->GetBlob().data()); @@ -801,7 +801,8 @@ binary = Value::CreateWithCopiedBuffer(stack_buffer, 42); ASSERT_TRUE(binary.get()); ASSERT_TRUE(binary->GetBlob().data()); - ASSERT_NE(stack_buffer, binary->GetBlob().data()); + ASSERT_NE(stack_buffer, + reinterpret_cast<const char*>(binary->GetBlob().data())); ASSERT_EQ(42U, binary->GetBlob().size()); ASSERT_EQ(0, memcmp(stack_buffer, binary->GetBlob().data(), binary->GetBlob().size()));
diff --git a/build/check_gn_headers_whitelist.txt b/build/check_gn_headers_whitelist.txt index d570a03f..9547f35 100644 --- a/build/check_gn_headers_whitelist.txt +++ b/build/check_gn_headers_whitelist.txt
@@ -51,6 +51,7 @@ chrome/browser/download/download_file_icon_extractor.h chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.h chrome/browser/extensions/api/omnibox/omnibox_api_testbase.h +chrome/browser/extensions/api/socket/mock_tcp_client_socket.h chrome/browser/mac/bluetooth_utility.h chrome/browser/media/router/mojo/media_route_provider_util_win.h chrome/browser/media/webrtc/desktop_media_list_ash.h
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni index 0de3860..bdba74d 100644 --- a/build/config/android/internal_rules.gni +++ b/build/config/android/internal_rules.gni
@@ -2027,57 +2027,6 @@ } } - # Compile resources for an APK. - # - # This is very similar to compile_resources, except that it can *also* - # compile the same set of inputs using the new protocol-buffer based - # format, if proto_outut and proto_resources_target are set. - # - # Takes the same variables as compile_resources, with the following - # extras: - # - # proto_output: optional. If provided, the path to an output file that - # will contain the resources compiled in the new protocol buffer format. - # proto_resources_target: required when proto_output is set. Name of the - # target associated with compiling the protocol-buffer based resources. - # - template("compile_apk_resources") { - # First call to compile_resources() is used to generate the compiled - # resources using the standard binary xml + resources.arsc format. - compile_resources(target_name) { - forward_variables_from(invoker, - "*", - [ - "proto_format", - "proto_output", - "proto_resources_target", - ]) - } - - # The second call is optional, and is only used to compile the resources - # using the new protocol buffer based format. This omits the generation of - # R.txt, /srcjar and proguard files (performed during the first call), or - # resources post-processing. - if (defined(invoker.proto_output)) { - compile_resources(invoker.proto_resources_target) { - forward_variables_from(invoker, - "*", - [ - "output", - "post_process_script", - "proguard_file", - "proguard_file_main_dex", - "proto_output", - "proto_resources_target", - "r_text_out_path", - "srcjar_path", - ]) - output = invoker.proto_output - proto_format = true - } - } - } - # Create an apk.jar.info file by merging several .jar.info files into one. # # Variables: @@ -3290,49 +3239,34 @@ # Create a zip archive corresponding to an application bundle module. # -# Each module corresponds to the content of an existing android_apk() target -# except that the internal directory layout is slightly different, and -# resources as well as xml files are compiled into a protocol buffer format, -# instead of the regular binary xml + resources.arsc. +# Compile all the components of a given android_apk_or_module() target into a zip archive +# suitable to later create an android_app_bundle() target. This archive's format is very +# similar to that on an APK, except for a few differences in internal directory +# layouts, and the fact that resources, as well ass xml files, are compiled using a +# protocol-buffer based format (instead of the regular binary xml + resources.arsc). # # A final application bundle is built from one or more module bundle modules, # plus some configuration file. # # Variables: -# apk_target: Name of the android_apk target this module refers to. -# The archive will contain the same content, but organized slightly -# differently. +# module_zip_path: Output module path. # -# module_path: Output module path. +# build_config: Path to build_config of the android_apk_or_module() target. # -template("android_app_bundle_module") { - _apk_target = invoker.apk_target - _apk_target_name = get_label_info(_apk_target, "name") - _apk_target_gen_dir = get_label_info(_apk_target, "target_gen_dir") - - _apk_build_config = "$_apk_target_gen_dir/${_apk_target_name}.build_config" - _rebased_apk_build_config = rebase_path(_apk_build_config, root_build_dir) +template("create_android_app_bundle_module") { + _build_config = invoker.build_config + _rebased_build_config = rebase_path(_build_config, root_build_dir) action(target_name) { forward_variables_from(invoker, [ "testonly", "visibility", + "deps", ]) script = "//build/android/gyp/apkbuilder.py" depfile = "$target_gen_dir/$target_name.d" - # NOTE: Building the APK is not necessary to build the bundle module, - # only its individual components, hence depend on their intermediate - # targets itself. This also allows building the APK and the bundle module - # in parallel if necessary. - deps = [ - "${_apk_target}__build_config", - "${_apk_target}__compile_proto_resources", - "${_apk_target}__create", # Required to get final dex zip. - "${_apk_target}__merge_manifests", - ] - # NOTE: Compared to the inputs of the "package_apk" template action, # this list is much smaller, since finalize_apk is never called # by apkbuild.py --format=bundle-module. This means not using @@ -3340,32 +3274,32 @@ # dependencies like extra native libraries are all pulled from the # .build_config through @FileArg() references (see below) and # will be listed in the generated depfile instead. - inputs = build_utils_py + [ _apk_build_config ] + inputs = build_utils_py + [ _build_config ] outputs = [ - invoker.module_path, + invoker.module_zip_path, ] args = [ "--depfile", rebase_path(depfile, root_build_dir), "--format=bundle-module", "--output-apk", - rebase_path(invoker.module_path, root_build_dir), - "--dex-file=@FileArg($_rebased_apk_build_config:final_dex:path)", + rebase_path(invoker.module_zip_path, root_build_dir), + "--dex-file=@FileArg($_rebased_build_config:final_dex:path)", "--resource-apk=@FileArg(" + - "$_rebased_apk_build_config:deps_info:proto_resources_path)", - "--assets=@FileArg($_rebased_apk_build_config:assets)", + "$_rebased_build_config:deps_info:proto_resources_path)", + "--assets=@FileArg($_rebased_build_config:assets)", "--uncompressed-assets=@FileArg(" + - "$_rebased_apk_build_config:uncompressed_assets)", - "--native-libs=@FileArg($_rebased_apk_build_config:native:libraries)", - "--native-libs=@FileArg($_rebased_apk_build_config:native:extra_shared_libraries)", + "$_rebased_build_config:uncompressed_assets)", + "--native-libs=@FileArg($_rebased_build_config:native:libraries)", + "--native-libs=@FileArg($_rebased_build_config:native:extra_shared_libraries)", "--android-abi=$android_app_abi", "--uncompress-shared-libraries=@FileArg(" + - "$_rebased_apk_build_config:native:uncompress_shared_libraries)", + "$_rebased_build_config:native:uncompress_shared_libraries)", ] if (defined(android_app_secondary_abi)) { args += [ "--secondary-native-libs=@FileArg(" + - "$_rebased_apk_build_config:native:secondary_abi_libraries)", + "$_rebased_build_config:native:secondary_abi_libraries)", "--secondary-android-abi=$android_app_secondary_abi", ] }
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni index d9df932..6dc0b802 100644 --- a/build/config/android/rules.gni +++ b/build/config/android/rules.gni
@@ -1851,21 +1851,14 @@ } } - # Declare an Android apk target - # - # This target creates an Android APK containing java code, resources, assets, - # and (possibly) native libraries. + # Declare an Android app module target, which is used as the basis for an + # Android APK or an Android app bundle module. # # Supports all variables of android_library(), plus: # android_manifest: Path to AndroidManifest.xml. # android_manifest_dep: Target that generates AndroidManifest (if applicable) # png_to_webp: If true, pngs (with the exception of 9-patch) are # converted to webp during resource packaging. - # dist_ijar_path: Path to create "${target_name}_dist_ijar" target - # (used by instrumentation_test_apk). - # apk_name: Name for final apk. - # final_apk_path: Path to final built apk. Default is - # $root_out_dir/apks/$apk_name.apk. Setting this will override apk_name. # loadable_modules: List of paths to native libraries to include. Different # from |shared_libraries| in that: # * dependencies of this .so are not automatically included @@ -1885,8 +1878,6 @@ # (optional). # secondary_native_lib_placeholders: List of placeholder filenames to add to # the apk for the secondary ABI (optional). - # apk_under_test: For an instrumentation test apk, this is the target of the - # tested apk. # write_asset_list: Adds an extra file to the assets, which contains a list of # all other asset files. # generate_buildconfig_java: If defined and false, skip generating the @@ -1899,9 +1890,6 @@ # linker does relocation unpacking, so we can enable it unconditionally. # secondary_native_libs (deprecated): The path of native libraries for secondary # app abi. - # proguard_jar_path: The path to proguard.jar you wish to use. If undefined, - # the proguard used will be the checked in one in //third_party/proguard. - # never_incremental: If true, |incremental_apk_by_default| will be ignored. # aapt_locale_whitelist: If set, all locales not in this list will be # stripped from resources.arsc. # exclude_xxxhdpi: Causes all drawable-xxxhdpi images to be excluded @@ -1918,29 +1906,10 @@ # shared_resources_whitelist_target: Optional name of a target specifying # an input R.txt file that lists the resources that can be exported # by the APK when shared_resources or app_as_shared_lib is defined. - # - # Example - # android_apk("foo_apk") { - # android_manifest = "AndroidManifest.xml" - # java_files = [ - # "android/org/chromium/foo/FooApplication.java", - # "android/org/chromium/foo/FooActivity.java", - # ] - # deps = [ - # ":foo_support_java" - # ":foo_resources" - # ] - # srcjar_deps = [ - # ":foo_generated_enum" - # ] - # shared_libraries = [ - # ":my_shared_lib", - # ] - # } - template("android_apk") { + template("android_apk_or_module") { forward_variables_from(invoker, [ "testonly" ]) - assert(defined(invoker.final_apk_path) || defined(invoker.apk_name)) + assert(defined(invoker.final_apk_path) || defined(invoker.name)) assert(defined(invoker.android_manifest)) _gen_dir = "$target_gen_dir/$target_name" _base_path = "$_gen_dir/$target_name" @@ -1954,6 +1923,9 @@ _rebased_lib_dex_path = rebase_path(_lib_dex_path, root_build_dir) _template_name = target_name + _is_bundle_module = + defined(invoker.is_bundle_module) && invoker.is_bundle_module + _enable_multidex = defined(invoker.enable_multidex) && invoker.enable_multidex if (_enable_multidex) { @@ -1965,8 +1937,10 @@ if (defined(invoker.final_apk_path)) { _final_apk_path = invoker.final_apk_path + } else if (!_is_bundle_module) { + _final_apk_path = "$root_build_dir/apks/${invoker.name}.apk" } else { - _final_apk_path = "$root_build_dir/apks/${invoker.apk_name}.apk" + _final_apk_path = "$root_build_dir/bundle_modules/${invoker.name}" } _final_apk_path_no_ext_list = process_file_template([ _final_apk_path ], @@ -1974,10 +1948,16 @@ _final_apk_path_no_ext = _final_apk_path_no_ext_list[0] assert(_final_apk_path_no_ext != "") # Mark as used. - # resource_sizes.py needs to be able to find the unpacked resources.arsc file based on apk name. - _packaged_resources_path = - "$root_gen_dir/arsc/" + - rebase_path(_final_apk_path_no_ext, root_build_dir) + ".ap_" + if (_is_bundle_module) { + # Path to the intermediate proto-format resources zip file. + _packaged_resources_path = "$target_gen_dir/$target_name.proto.ap_" + } else { + # resource_sizes.py needs to be able to find the unpacked resources.arsc + # file based on apk name. + _packaged_resources_path = + "$root_gen_dir/arsc/" + + rebase_path(_final_apk_path_no_ext, root_build_dir) + ".ap_" + } _incremental_install_json_path = "$target_gen_dir/$target_name.incremental.json" @@ -1991,15 +1971,6 @@ if (defined(invoker.version_name)) { _version_name = invoker.version_name } - _keystore_path = android_keystore_path - _keystore_name = android_keystore_name - _keystore_password = android_keystore_password - - if (defined(invoker.keystore_path)) { - _keystore_path = invoker.keystore_path - _keystore_name = invoker.keystore_name - _keystore_password = invoker.keystore_password - } _deps = [] if (defined(invoker.deps)) { @@ -2134,7 +2105,9 @@ _proguard_output_jar_path = "$_base_path.proguard.jar" } + # TODO(crbug.com/864142): Allow incremental installs of bundle modules. _incremental_allowed = + !_is_bundle_module && !(defined(invoker.never_incremental) && invoker.never_incremental) _android_manifest = @@ -2161,20 +2134,7 @@ } _compile_resources_target = "${_template_name}__compile_resources" - - # Path to the intermediate proto-format resources zip file. - _packaged_proto_resources_path = - "$root_gen_dir/proto_resources/" + - rebase_path(_final_apk_path_no_ext, root_build_dir) + ".proto.ap_" - - # Define another target used to generate an archive containing the - # resources compiled in protocol buffer format. This is not used by - # the APK itself, but by android_bundle_module() targets that depend - # on it. - _compile_proto_resources_target = - "${_template_name}__compile_proto_resources" - - compile_apk_resources(_compile_resources_target) { + compile_resources(_compile_resources_target) { forward_variables_from(invoker, [ "app_as_shared_lib", @@ -2206,6 +2166,9 @@ if (_enable_multidex) { proguard_file_main_dex = _generated_proguard_main_dex_config } + if (_is_bundle_module) { + proto_format = true + } output = _packaged_resources_path build_config = _build_config @@ -2226,9 +2189,6 @@ "${invoker.shared_resources_whitelist_target}__compile_resources", ] } - - proto_output = _packaged_proto_resources_path - proto_resources_target = _compile_proto_resources_target } _srcjar_deps += [ ":$_compile_resources_target" ] @@ -2368,7 +2328,9 @@ final_dex_path = _final_dex_path apk_path = _final_apk_path - proto_resources_path = _packaged_proto_resources_path + if (_is_bundle_module) { + proto_resources_path = _packaged_resources_path + } incremental_allowed = _incremental_allowed incremental_apk_path = "${_final_apk_path_no_ext}_incremental.apk" @@ -2509,8 +2471,12 @@ "@FileArg($_rebased_build_config:native:secondary_abi_libraries)" assert(_secondary_abi_native_libs_file_arg != "" && _secondary_abi_native_libs_file_arg_dep != "") # Mark as used. + _all_native_libs_deps = _native_libs_deps + _extra_native_libs_deps + + [ _native_libs_file_arg_dep ] + assert(_all_native_libs_deps == _all_native_libs_deps) # Mark as used. _extra_native_libs_even_when_incremental = [] + assert(_extra_native_libs_even_when_incremental == []) # Mark as used. if (_native_libs_deps != []) { _create_stack_script_rule_name = "${_template_name}__stack_script" _final_deps += [ ":${_create_stack_script_rule_name}" ] @@ -2525,10 +2491,10 @@ } # Generate .apk.jar.info files if needed. - if (defined(invoker.apk_name)) { + if (defined(invoker.name)) { _apk_jar_info_target = "${target_name}__apk_jar_info" create_apk_jar_info(_apk_jar_info_target) { - output = "$root_build_dir/size-info/${invoker.apk_name}.apk.jar.info" + output = "$root_build_dir/size-info/${invoker.name}.apk.jar.info" apk_build_config = _build_config deps = [ ":$_build_config_target", @@ -2538,73 +2504,92 @@ _deps += [ ":$_apk_jar_info_target" ] } - _final_deps += [ ":${_template_name}__create" ] - create_apk("${_template_name}__create") { - forward_variables_from(invoker, - [ - "public_deps", - "secondary_native_libs", - "shared_resources", - "uncompress_shared_libraries", - "write_asset_list", - ]) - packaged_resources_path = _packaged_resources_path - apk_path = _final_apk_path - assets_build_config = _build_config - dex_path = _final_dex_path - load_library_from_apk = _load_library_from_apk + if (!_is_bundle_module) { + _keystore_path = android_keystore_path + _keystore_name = android_keystore_name + _keystore_password = android_keystore_password - # This is used to generate *.apk.pak.info files. - apk_name = invoker.apk_name - - keystore_name = _keystore_name - keystore_path = _keystore_path - keystore_password = _keystore_password - - incremental_allowed = _incremental_allowed - if (_incremental_allowed) { - android_manifest = _android_manifest - base_path = _base_path + if (defined(invoker.keystore_path)) { + _keystore_path = invoker.keystore_path + _keystore_name = invoker.keystore_name + _keystore_password = invoker.keystore_password } - # Incremental apk does not use native libs nor final dex. - incremental_deps = _deps + [ - ":$_merge_manifest_target", - ":$_build_config_target", - ":$_compile_resources_target", - ] + _create_apk_target = "${_template_name}__create" + _final_deps += [ ":$_create_apk_target" ] + create_apk("$_create_apk_target") { + forward_variables_from(invoker, + [ + "public_deps", + "secondary_native_libs", + "shared_resources", + "uncompress_shared_libraries", + "write_asset_list", + ]) + packaged_resources_path = _packaged_resources_path + apk_path = _final_apk_path + assets_build_config = _build_config + dex_path = _final_dex_path + load_library_from_apk = _load_library_from_apk - # This target generates the input file _all_resources_zip_path. - deps = _deps + [ - ":$_merge_manifest_target", - ":$_build_config_target", - ":$_final_dex_target_name", - ":$_compile_resources_target", - ] + # This is used to generate *.apk.pak.info files. + apk_name = invoker.name - if (_native_libs_deps != [] || - _extra_native_libs_even_when_incremental != []) { - deps += _native_libs_deps + _extra_native_libs_deps + - [ _native_libs_file_arg_dep ] - native_libs_filearg = _native_libs_file_arg - native_libs = _extra_native_libs - native_libs_even_when_incremental = - _extra_native_libs_even_when_incremental + keystore_name = _keystore_name + keystore_path = _keystore_path + keystore_password = _keystore_password + + incremental_allowed = _incremental_allowed + if (_incremental_allowed) { + android_manifest = _android_manifest + base_path = _base_path + } + + # Incremental apk does not use native libs nor final dex. + incremental_deps = _deps + [ + ":$_merge_manifest_target", + ":$_build_config_target", + ":$_compile_resources_target", + ] + + # This target generates the input file _all_resources_zip_path. + deps = _deps + [ + ":$_merge_manifest_target", + ":$_build_config_target", + ":$_final_dex_target_name", + ":$_compile_resources_target", + ] + + if (_native_libs_deps != [] || + _extra_native_libs_even_when_incremental != []) { + deps += _all_native_libs_deps + native_libs_filearg = _native_libs_file_arg + native_libs = _extra_native_libs + native_libs_even_when_incremental = + _extra_native_libs_even_when_incremental + } + + if (_secondary_abi_native_libs_deps != []) { + deps += _secondary_abi_native_libs_deps + + [ _secondary_abi_native_libs_file_arg_dep ] + secondary_abi_native_libs_filearg = + _secondary_abi_native_libs_file_arg + } + + # Placeholders necessary for some older devices. + # http://crbug.com/395038 + forward_variables_from(invoker, + [ + "native_lib_placeholders", + "secondary_native_lib_placeholders", + ]) } - - if (_secondary_abi_native_libs_deps != []) { - deps += _secondary_abi_native_libs_deps + - [ _secondary_abi_native_libs_file_arg_dep ] - secondary_abi_native_libs_filearg = _secondary_abi_native_libs_file_arg - } - - # Placeholders necessary for some older devices. - # http://crbug.com/395038 - forward_variables_from(invoker, - [ - "native_lib_placeholders", - "secondary_native_lib_placeholders", - ]) + } else { + _final_deps += [ + ":$_merge_manifest_target", + ":$_build_config_target", + ":$_final_dex_target_name", + ] + _all_native_libs_deps } _write_installer_json_rule_name = "${_template_name}__incremental_json" @@ -2756,6 +2741,181 @@ } } + # Declare an Android APK target + # + # This target creates an Android APK containing java code, resources, assets, + # and (possibly) native libraries. + # + # Supports all variables of android_apk_or_module(), plus: + # apk_name: Name for final apk. + # + # Example + # android_apk("foo_apk") { + # android_manifest = "AndroidManifest.xml" + # java_files = [ + # "android/org/chromium/foo/FooApplication.java", + # "android/org/chromium/foo/FooActivity.java", + # ] + # deps = [ + # ":foo_support_java" + # ":foo_resources" + # ] + # srcjar_deps = [ + # ":foo_generated_enum" + # ] + # shared_libraries = [ + # ":my_shared_lib", + # ] + # } + template("android_apk") { + android_apk_or_module(target_name) { + forward_variables_from(invoker, + [ + "aapt_locale_whitelist", + "additional_jar_files", + "alternative_android_sdk_dep", + "android_manifest", + "android_manifest_dep", + "apk_under_test", + "app_as_shared_lib", + "build_hooks_android_impl_deps", + "chromium_code", + "classpath_deps", + "command_line_flags_file", + "create_apk_script", + "data", + "data_deps", + "deps", + "dist_ijar_path", + "emma_never_instrument", + "enable_chromium_linker_tests", + "enable_multidex", + "exclude_xxxhdpi", + "final_apk_path", + "firebase_app_id", + "generate_buildconfig_java", + "input_jars_paths", + "java_files", + "javac_args", + "load_library_from_apk", + "loadable_modules", + "native_lib_placeholders", + "native_lib_version_arg", + "native_lib_version_rule", + "negative_main_dex_globs", + "never_incremental", + "no_build_hooks", + "no_xml_namespaces", + "png_to_webp", + "post_process_package_resources_script", + "product_version_resources_dep", + "proguard_configs", + "proguard_enabled", + "proguard_jar_path", + "requires_sdk_api_level_23", + "secondary_abi_shared_libraries", + "secondary_native_lib_placeholders", + "secondary_native_libs", + "shared_libraries", + "shared_resources", + "shared_resources_whitelist_target", + "srcjar_deps", + "support_zh_hk", + "testonly", + "uncompress_shared_libraries", + "use_chromium_linker", + "version_code", + "version_name", + "write_asset_list", + "xxxhdpi_whitelist", + ]) + is_bundle_module = false + if (defined(invoker.apk_name)) { + name = invoker.apk_name + } + } + } + + # Declare an Android app bundle module target. + # + # The module can be used for an android_apk_or_module(). + # + # Supports all variables of android_library(), plus: + # module_name: Name of the module. + # is_base_module: If defined and true, indicates that this is the bundle's + # base module (optional). + template("android_app_bundle_module") { + _is_base_module = defined(invoker.is_base_module) && invoker.is_base_module + + if (!_is_base_module) { + assert(!defined(write_asset_list)) + assert(!defined(firebase_app_id)) + assert(!defined(app_as_shared_lib)) + assert(!defined(shared_resources)) + assert(!defined(shared_resources_whitelist_target)) + assert(!defined(build_hooks_android_impl_deps)) + assert(!defined(shared_libraries)) + } + + android_apk_or_module(target_name) { + forward_variables_from(invoker, + [ + "aapt_locale_whitelist", + "additional_jar_files", + "alternative_android_sdk_dep", + "android_manifest", + "android_manifest_dep", + "app_as_shared_lib", + "chromium_code", + "classpath_deps", + "data", + "data_deps", + "deps", + "emma_never_instrument", + "enable_chromium_linker_tests", + "enable_multidex", + "exclude_xxxhdpi", + "firebase_app_id", + "input_jars_paths", + "java_files", + "javac_args", + "load_library_from_apk", + "loadable_modules", + "native_lib_placeholders", + "native_lib_version_arg", + "native_lib_version_rule", + "negative_main_dex_globs", + "no_xml_namespaces", + "png_to_webp", + "product_version_resources_dep", + "proguard_configs", + "proguard_enabled", + "requires_sdk_api_level_23", + "secondary_abi_shared_libraries", + "secondary_native_lib_placeholders", + "secondary_native_libs", + "shared_libraries", + "shared_resources", + "shared_resources_whitelist_target", + "srcjar_deps", + "support_zh_hk", + "testonly", + "uncompress_shared_libraries", + "use_chromium_linker", + "version_code", + "version_name", + "write_asset_list", + "xxxhdpi_whitelist", + ]) + is_bundle_module = true + generate_buildconfig_java = _is_base_module + no_build_hooks = !_is_base_module + if (defined(invoker.module_name)) { + name = invoker.module_name + } + } + } + # Declare an Android instrumentation test apk # # This target creates an Android instrumentation test apk. @@ -3424,10 +3584,10 @@ # and zero or more associated android_apk. # # Variables: - # base_apk_target: Name of the android_apk target corresponding to the - # base module for this application bundle. The bundle file will include - # the same content in its base module, though in a slightly different - # format. + # base_module_target: Name of the android_app_bundle_module target + # corresponding to the base module for this application bundle. The + # bundle file will include the same content in its base module, though in + # a slightly different format. # # bundle_base_path: Optional. If set, the bundle will be output to this # directory. Defaults to "$root_build_dir/apks". @@ -3467,11 +3627,11 @@ # # Example: # android_app_bundle("chrome_public_bundle") { - # base_apk_target = "//chrome/android:chrome_public_apk" + # base_module_target = "//chrome/android:chrome_public_apk" # extra_modules = [ # { # NOTE: Scopes require one field per line, and no comma separators. # name = "my_module" - # apk_target = ":my_module_apk" + # module_target = ":my_module" # }, # ] # } @@ -3480,7 +3640,7 @@ _all_modules = [ { name = "base" - apk_target = invoker.base_apk_target + module_target = invoker.base_module_target }, ] @@ -3492,46 +3652,52 @@ "Missing 'name' field for extra module #${_module_count}.") assert(_module.name != "base", "Module name 'base' is reserved for the main bundle module") - assert(defined(_module.apk_target), - "Missing 'apk_target' field for extra module ${_module.name}.") + assert( + defined(_module.module_target), + "Missing 'module_target' field for extra module ${_module.name}.") } _all_modules += invoker.extra_modules } # Generate one module .zip file per APK. - _all_module_targets = [] - _all_module_paths = [] + _all_create_module_targets = [] + _all_module_zip_paths = [] _all_module_build_configs = [] foreach(_module, _all_modules) { # Important: the bundle tool uses the module's zip filename as # the internal module name inside the final bundle, in other words, # this file *must* be named ${_module.name}.zip - _module_target = "${target_name}__module__${_module.name}" - _module_path = "$target_gen_dir/$target_name/${_module.name}.zip" - _apk_target = _module.apk_target - _apk_build_config_target = "${_apk_target}__build_config" - - android_app_bundle_module(_module_target) { - apk_target = _apk_target - module_path = _module_path - } + _create_module_target = "${target_name}__${_module.name}__create" + _module_zip_path = "$target_gen_dir/$target_name/${_module.name}.zip" + _module_target = _module.module_target + _module_build_config_target = "${_module_target}__build_config" # Determine the rebased path to the module's target .build_config # In order to pass its list of uncompressed assets later. - _apk_target_name = get_label_info(_apk_target, "name") - _apk_target_gen_dir = get_label_info(_apk_target, "target_gen_dir") - _apk_build_config = - "$_apk_target_gen_dir/${_apk_target_name}.build_config" + _module_target_name = get_label_info(_module_target, "name") + _module_target_gen_dir = get_label_info(_module_target, "target_gen_dir") + _module_build_config = + "$_module_target_gen_dir/${_module_target_name}.build_config" - _all_module_targets += [ - ":$_module_target", - _apk_build_config_target, + create_android_app_bundle_module(_create_module_target) { + build_config = _module_build_config + module_zip_path = _module_zip_path + deps = [ + "$_module_build_config_target", + "$_module_target", + ] + } + + _all_create_module_targets += [ + ":$_create_module_target", + _module_build_config_target, ] - _all_module_paths += [ _module_path ] - _all_module_build_configs += [ _apk_build_config ] + _all_module_zip_paths += [ _module_zip_path ] + _all_module_build_configs += [ _module_build_config ] } - _all_rebased_module_paths = rebase_path(_all_module_paths, root_build_dir) + _all_rebased_module_zip_paths = + rebase_path(_all_module_zip_paths, root_build_dir) _bundle_name = target_name if (defined(invoker.bundle_name)) { @@ -3586,15 +3752,15 @@ _bundle_target_name = target_name action(_bundle_target_name) { script = "//build/android/gyp/create_app_bundle.py" - inputs = _all_module_paths + _all_module_build_configs + + inputs = _all_module_zip_paths + _all_module_build_configs + _create_app_bundle_py_imports outputs = [ _bundle_path, ] - deps = _all_module_targets + deps = _all_create_module_targets args = [ "--out-bundle=$_rebased_bundle_path", - "--module-zips=$_all_rebased_module_paths", + "--module-zips=$_all_rebased_module_zip_paths", ] if (_sign_bundle) { args += [
diff --git a/build/fuchsia/sdk.sha1 b/build/fuchsia/sdk.sha1 index 980afd99..52f580cb 100644 --- a/build/fuchsia/sdk.sha1 +++ b/build/fuchsia/sdk.sha1
@@ -1 +1 @@ -138f39e8ec632173fa8d82466242bf36032cdcce \ No newline at end of file +9b4813214fa05bed350c3beef2650fa7a0604aca \ No newline at end of file
diff --git a/cc/layers/heads_up_display_layer_impl.cc b/cc/layers/heads_up_display_layer_impl.cc index c45a685..3ee5b67 100644 --- a/cc/layers/heads_up_display_layer_impl.cc +++ b/cc/layers/heads_up_display_layer_impl.cc
@@ -14,6 +14,7 @@ #include "base/single_thread_task_runner.h" #include "base/stl_util.h" #include "base/strings/stringprintf.h" +#include "base/trace_event/process_memory_dump.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event_argument.h" #include "cc/debug/debug_colors.h" @@ -108,13 +109,17 @@ gl->DeleteTextures(1, &texture_id); } - base::trace_event::MemoryAllocatorDumpGuid MemoryDumpGuid( - uint64_t tracing_process_id) override { - return gl::GetGLTextureClientGUIDForTracing( + void OnMemoryDump( + base::trace_event::ProcessMemoryDump* pmd, + const base::trace_event::MemoryAllocatorDumpGuid& buffer_dump_guid, + uint64_t tracing_process_id, + int importance) const override { + auto texture_tracing_guid = gl::GetGLTextureClientGUIDForTracing( compositor_context_provider->ContextSupport()->ShareGroupTracingGUID(), texture_id); + pmd->CreateSharedGlobalAllocatorDump(texture_tracing_guid); + pmd->AddOwnershipEdge(buffer_dump_guid, texture_tracing_guid, importance); } - base::UnguessableToken SharedMemoryGuid() override { return {}; } viz::ContextProvider* compositor_context_provider; GLuint texture_id; @@ -126,8 +131,13 @@ layer_tree_frame_sink->DidDeleteSharedBitmap(shared_bitmap_id); } - base::UnguessableToken SharedMemoryGuid() override { - return shared_memory->mapped_id(); + void OnMemoryDump( + base::trace_event::ProcessMemoryDump* pmd, + const base::trace_event::MemoryAllocatorDumpGuid& buffer_dump_guid, + uint64_t tracing_process_id, + int importance) const override { + pmd->CreateSharedMemoryOwnershipEdge( + buffer_dump_guid, shared_memory->mapped_id(), importance); } LayerTreeFrameSink* layer_tree_frame_sink;
diff --git a/cc/paint/image_transfer_cache_entry.cc b/cc/paint/image_transfer_cache_entry.cc index fe63071a..c902b64 100644 --- a/cc/paint/image_transfer_cache_entry.cc +++ b/cc/paint/image_transfer_cache_entry.cc
@@ -75,9 +75,9 @@ safe_size += sizeof(uint32_t); // width safe_size += sizeof(uint32_t); // height safe_size += sizeof(uint32_t); // has mips - safe_size += sizeof(size_t); // pixels size - safe_size += target_color_space_size + sizeof(size_t); - safe_size += pixmap_color_space_size + sizeof(size_t); + safe_size += sizeof(uint64_t) + alignof(uint64_t); // pixels size + safe_size += target_color_space_size + sizeof(uint64_t) + alignof(uint64_t); + safe_size += pixmap_color_space_size + sizeof(uint64_t) + alignof(uint64_t); // Include 4 bytes of padding so we can always align our data pointer to a // 4-byte boundary. safe_size += 4;
diff --git a/cc/paint/paint_filter.cc b/cc/paint/paint_filter.cc index f410b27..0e0bd00 100644 --- a/cc/paint/paint_filter.cc +++ b/cc/paint/paint_filter.cc
@@ -443,7 +443,7 @@ size_t AlphaThresholdPaintFilter::SerializedSize() const { size_t region_size = region_.writeToMemory(nullptr); base::CheckedNumeric<size_t> total_size; - total_size = BaseSerializedSize() + sizeof(region_size) + region_size + + total_size = BaseSerializedSize() + sizeof(uint64_t) + region_size + sizeof(inner_min_) + sizeof(outer_max_); total_size += GetFilterSize(input_.get()); return total_size.ValueOrDefault(0u);
diff --git a/cc/paint/paint_op_buffer.h b/cc/paint/paint_op_buffer.h index c1477a1..909f0cd 100644 --- a/cc/paint/paint_op_buffer.h +++ b/cc/paint/paint_op_buffer.h
@@ -877,9 +877,7 @@ class CC_PAINT_EXPORT PaintOpBuffer : public SkRefCnt { public: enum { kInitialBufferSize = 4096 }; - // It's not necessarily the case that the op with the maximum alignment - // requirements is also the biggest op, but for now that's true. - static constexpr size_t PaintOpAlign = alignof(DrawDRRectOp); + static constexpr size_t PaintOpAlign = 8; static inline size_t ComputeOpSkip(size_t sizeof_op) { return MathUtil::UncheckedRoundUp(sizeof_op, PaintOpBuffer::PaintOpAlign); }
diff --git a/cc/paint/paint_op_reader.cc b/cc/paint/paint_op_reader.cc index ee3301f..99b1d82 100644 --- a/cc/paint/paint_op_reader.cc +++ b/cc/paint/paint_op_reader.cc
@@ -117,7 +117,7 @@ template <typename T> void PaintOpReader::ReadFlattenable(sk_sp<T>* val) { size_t bytes = 0; - ReadSimple(&bytes); + ReadSize(&bytes); if (remaining_bytes_ < bytes) SetInvalid(); if (!valid_) @@ -154,7 +154,10 @@ } void PaintOpReader::ReadSize(size_t* size) { - ReadSimple(size); + AlignMemory(8); + uint64_t size64; + ReadSimple(&size64); + *size = size64; } void PaintOpReader::Read(SkScalar* data) { @@ -212,19 +215,13 @@ ReadSimple(&flags->blend_mode_); ReadSimple(&flags->bitfields_uint_); - // Flattenables must be read at 4-byte boundary, which should be the case - // here. - AlignMemory(4); ReadFlattenable(&flags->path_effect_); - AlignMemory(4); ReadFlattenable(&flags->mask_filter_); - AlignMemory(4); ReadFlattenable(&flags->color_filter_); - AlignMemory(4); if (enable_security_constraints_) { size_t bytes = 0; - ReadSimple(&bytes); + ReadSize(&bytes); if (bytes != 0u) { SetInvalid(); return; @@ -331,7 +328,7 @@ void PaintOpReader::Read(sk_sp<SkData>* data) { size_t bytes = 0; - ReadSimple(&bytes); + ReadSize(&bytes); if (remaining_bytes_ < bytes) SetInvalid(); if (!valid_) @@ -378,7 +375,7 @@ void PaintOpReader::Read(scoped_refptr<PaintTextBlob>* paint_blob) { size_t data_bytes = 0u; - ReadSimple(&data_bytes); + ReadSize(&data_bytes); if (remaining_bytes_ < data_bytes || data_bytes == 0u) SetInvalid(); if (!valid_) @@ -458,7 +455,7 @@ shader_size = post_size - pre_size + record_size; } decltype(ref.colors_)::size_type colors_size = 0; - ReadSimple(&colors_size); + ReadSize(&colors_size); // If there are too many colors, abort. if (colors_size > kMaxShaderColorsSupported) { @@ -474,7 +471,7 @@ ReadData(colors_bytes, ref.colors_.data()); decltype(ref.positions_)::size_type positions_size = 0; - ReadSimple(&positions_size); + ReadSize(&positions_size); // Positions are optional. If they exist, they have the same count as colors. if (positions_size > 0 && positions_size != colors_size) { SetInvalid(); @@ -1188,9 +1185,9 @@ size_t PaintOpReader::Read(sk_sp<PaintRecord>* record) { size_t size_bytes = 0; - ReadSimple(&size_bytes); - AlignMemory(PaintOpBuffer::PaintOpAlign); + ReadSize(&size_bytes); + AlignMemory(PaintOpBuffer::PaintOpAlign); if (enable_security_constraints_) { // Validate that the record was not serialized if security constraints are // enabled. @@ -1219,7 +1216,7 @@ void PaintOpReader::Read(SkRegion* region) { size_t region_bytes = 0; - ReadSimple(®ion_bytes); + ReadSize(®ion_bytes); if (region_bytes == 0 || region_bytes > kMaxRegionByteSize) SetInvalid(); if (!valid_)
diff --git a/cc/paint/paint_op_writer.cc b/cc/paint/paint_op_writer.cc index 9426b0d..afba0a6 100644 --- a/cc/paint/paint_op_writer.cc +++ b/cc/paint/paint_op_writer.cc
@@ -39,7 +39,7 @@ size_t PaintOpWriter::GetFlattenableSize(const SkFlattenable* flattenable) { // The first bit is always written to indicate the serialized size of the // flattenable, or zero if it doesn't exist. - size_t total_size = sizeof(size_t); + size_t total_size = sizeof(uint64_t) + alignof(uint64_t); if (!flattenable) return total_size; @@ -60,7 +60,7 @@ image_size += sizeof(info.colorType()); image_size += sizeof(info.width()); image_size += sizeof(info.height()); - image_size += sizeof(size_t); + image_size += sizeof(uint64_t) + alignof(uint64_t); image_size += info.computeMinByteSize(); } return image_size; @@ -72,7 +72,7 @@ // TODO(khushalsagar): Querying the size of a PaintRecord is not supported. // This works only for security constrained serialization which ignores // records. - return sizeof(size_t); + return sizeof(uint64_t); } PaintOpWriter::PaintOpWriter(void* memory, @@ -104,14 +104,13 @@ } void PaintOpWriter::WriteFlattenable(const SkFlattenable* val) { - DCHECK(SkIsAlign4(reinterpret_cast<uintptr_t>(memory_))) - << "Flattenable must start writing at 4 byte alignment."; + AlignMemory(8); if (!val) { WriteSize(static_cast<size_t>(0u)); return; } - size_t size_offset = sizeof(size_t); + size_t size_offset = sizeof(uint64_t); EnsureBytes(size_offset); if (!valid_) return; @@ -125,13 +124,14 @@ valid_ = false; return; } - reinterpret_cast<size_t*>(size_memory)[0] = bytes_written; + reinterpret_cast<uint64_t*>(size_memory)[0] = bytes_written; memory_ += bytes_written; remaining_bytes_ -= bytes_written; } void PaintOpWriter::WriteSize(size_t size) { - WriteSimple(size); + AlignMemory(8); + WriteSimple<uint64_t>(size); } void PaintOpWriter::Write(SkScalar data) { @@ -185,16 +185,10 @@ WriteSimple(flags.blend_mode_); WriteSimple(flags.bitfields_uint_); - // Flattenables must be written starting at a 4 byte boundary, which should be - // the case here. - AlignMemory(4); WriteFlattenable(flags.path_effect_.get()); - AlignMemory(4); WriteFlattenable(flags.mask_filter_.get()); - AlignMemory(4); WriteFlattenable(flags.color_filter_.get()); - AlignMemory(4); if (enable_security_constraints_) WriteSize(static_cast<size_t>(0u)); else @@ -301,8 +295,10 @@ if (!valid_) return; + AlignMemory(8); + const auto& blob = paint_blob->ToSkTextBlob(); - size_t size_offset = sizeof(size_t); + size_t size_offset = sizeof(uint64_t); EnsureBytes(size_offset); if (!valid_) return; @@ -325,7 +321,7 @@ valid_ = false; return; } - reinterpret_cast<size_t*>(size_memory)[0] = bytes_written; + reinterpret_cast<uint64_t*>(size_memory)[0] = bytes_written; memory_ += bytes_written; remaining_bytes_ -= bytes_written; } @@ -421,10 +417,10 @@ Write(false); } - WriteSimple(shader->colors_.size()); + WriteSize(shader->colors_.size()); WriteData(shader->colors_.size() * sizeof(SkColor), shader->colors_.data()); - WriteSimple(shader->positions_.size()); + WriteSize(shader->positions_.size()); WriteData(shader->positions_.size() * sizeof(SkScalar), shader->positions_.data()); // Explicitly don't write the cached_shader_ because that can be regenerated @@ -736,10 +732,12 @@ const gfx::Rect& playback_rect, const gfx::SizeF& post_scale, const SkMatrix& post_matrix_for_analysis) { + AlignMemory(PaintOpBuffer::PaintOpAlign); + // We need to record how many bytes we will serialize, but we don't know this // information until we do the serialization. So, skip the amount needed // before writing. - size_t size_offset = sizeof(size_t); + size_t size_offset = sizeof(uint64_t); EnsureBytes(size_offset); if (!valid_) return; @@ -748,7 +746,6 @@ memory_ += size_offset; remaining_bytes_ -= size_offset; - AlignMemory(PaintOpBuffer::PaintOpAlign); if (!valid_) return; @@ -777,7 +774,7 @@ // Write the size to the size memory, which preceeds the memory for the // record. - reinterpret_cast<size_t*>(size_memory)[0] = serializer.written(); + reinterpret_cast<uint64_t*>(size_memory)[0] = serializer.written(); // The serializer should have failed if it ran out of space. DCHECK to verify // that it wrote at most as many bytes as we had left. @@ -792,7 +789,7 @@ size_t bytes_written = region.writeToMemory(data.get()); DCHECK_EQ(bytes_required, bytes_written); - WriteSimple(bytes_written); + WriteSize(bytes_written); WriteData(bytes_written, data.get()); }
diff --git a/cc/paint/paint_typeface_transfer_cache_entry.cc b/cc/paint/paint_typeface_transfer_cache_entry.cc index 34def03d..41c4d39 100644 --- a/cc/paint/paint_typeface_transfer_cache_entry.cc +++ b/cc/paint/paint_typeface_transfer_cache_entry.cc
@@ -90,13 +90,13 @@ writer->WriteSimple(typeface_.ttc_index()); break; case PaintTypeface::Type::kFilenameAndTtcIndex: - writer->WriteSimple(typeface_.filename().size()); + writer->template WriteSimple<uint64_t>(typeface_.filename().size()); writer->WriteData(typeface_.filename().size(), typeface_.filename().data()); writer->WriteSimple(typeface_.ttc_index()); break; case PaintTypeface::Type::kFamilyNameAndFontStyle: - writer->WriteSimple(typeface_.family_name().size()); + writer->template WriteSimple<uint64_t>(typeface_.family_name().size()); writer->WriteData(typeface_.family_name().size(), typeface_.family_name().data()); writer->WriteSimple(typeface_.font_style().weight()); @@ -151,7 +151,7 @@ } case PaintTypeface::Type::kFilenameAndTtcIndex: { size_t size; - ReadSimple(&size); + ReadSize(&size); if (!valid_ || size > kMaxFilenameSize) { valid_ = false; return false; @@ -170,7 +170,7 @@ } case PaintTypeface::Type::kFamilyNameAndFontStyle: { size_t size; - ReadSimple(&size); + ReadSize(&size); if (!valid_ || size > kMaxFamilyNameSize) { valid_ = false; return false; @@ -212,6 +212,12 @@ data_ = data_.subspan(sizeof(T)); } +void ServicePaintTypefaceTransferCacheEntry::ReadSize(size_t* size) { + uint64_t size64; + ReadSimple(&size64); + *size = size64; +} + void ServicePaintTypefaceTransferCacheEntry::ReadData(size_t bytes, void* data) { if (data_.size() < bytes)
diff --git a/cc/paint/paint_typeface_transfer_cache_entry.h b/cc/paint/paint_typeface_transfer_cache_entry.h index f1c1e75..294df15 100644 --- a/cc/paint/paint_typeface_transfer_cache_entry.h +++ b/cc/paint/paint_typeface_transfer_cache_entry.h
@@ -44,6 +44,7 @@ private: template <typename T> void ReadSimple(T* val); + void ReadSize(size_t* size); void ReadData(size_t bytes, void* data);
diff --git a/cc/raster/bitmap_raster_buffer_provider.cc b/cc/raster/bitmap_raster_buffer_provider.cc index c801facc..128b7c8 100644 --- a/cc/raster/bitmap_raster_buffer_provider.cc +++ b/cc/raster/bitmap_raster_buffer_provider.cc
@@ -11,6 +11,7 @@ #include "base/macros.h" #include "base/strings/stringprintf.h" +#include "base/trace_event/process_memory_dump.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event_argument.h" #include "cc/raster/raster_source.h" @@ -27,8 +28,13 @@ frame_sink->DidDeleteSharedBitmap(shared_bitmap_id); } - base::UnguessableToken SharedMemoryGuid() override { - return shared_memory->mapped_id(); + void OnMemoryDump( + base::trace_event::ProcessMemoryDump* pmd, + const base::trace_event::MemoryAllocatorDumpGuid& buffer_dump_guid, + uint64_t tracing_process_id, + int importance) const override { + pmd->CreateSharedMemoryOwnershipEdge( + buffer_dump_guid, shared_memory->mapped_id(), importance); } LayerTreeFrameSink* frame_sink;
diff --git a/cc/raster/gpu_raster_buffer_provider.cc b/cc/raster/gpu_raster_buffer_provider.cc index dd6a8470..bef9b6b 100644 --- a/cc/raster/gpu_raster_buffer_provider.cc +++ b/cc/raster/gpu_raster_buffer_provider.cc
@@ -10,6 +10,7 @@ #include "base/macros.h" #include "base/metrics/histogram_macros.h" +#include "base/trace_event/process_memory_dump.h" #include "base/trace_event/trace_event.h" #include "cc/base/histograms.h" #include "cc/paint/display_item_list.h" @@ -268,15 +269,20 @@ gl->DeleteTextures(1, &texture_id); } - base::trace_event::MemoryAllocatorDumpGuid MemoryDumpGuid( - uint64_t tracing_process_id) override { + void OnMemoryDump( + base::trace_event::ProcessMemoryDump* pmd, + const base::trace_event::MemoryAllocatorDumpGuid& buffer_dump_guid, + uint64_t tracing_process_id, + int importance) const override { if (!storage_allocated) - return {}; - return gl::GetGLTextureClientGUIDForTracing( + return; + + auto texture_tracing_guid = gl::GetGLTextureClientGUIDForTracing( compositor_context_provider->ContextSupport()->ShareGroupTracingGUID(), texture_id); + pmd->CreateSharedGlobalAllocatorDump(texture_tracing_guid); + pmd->AddOwnershipEdge(buffer_dump_guid, texture_tracing_guid, importance); } - base::UnguessableToken SharedMemoryGuid() override { return {}; } // The ContextProvider used to clean up the texture id. viz::ContextProvider* compositor_context_provider = nullptr;
diff --git a/cc/raster/one_copy_raster_buffer_provider.cc b/cc/raster/one_copy_raster_buffer_provider.cc index c978c85..4b04876 100644 --- a/cc/raster/one_copy_raster_buffer_provider.cc +++ b/cc/raster/one_copy_raster_buffer_provider.cc
@@ -12,6 +12,7 @@ #include "base/macros.h" #include "base/metrics/histogram_macros.h" +#include "base/trace_event/process_memory_dump.h" #include "base/trace_event/trace_event.h" #include "cc/base/histograms.h" #include "cc/base/math_util.h" @@ -53,15 +54,20 @@ gl->DeleteTextures(1, &texture_id); } - base::trace_event::MemoryAllocatorDumpGuid MemoryDumpGuid( - uint64_t tracing_process_id) override { + void OnMemoryDump( + base::trace_event::ProcessMemoryDump* pmd, + const base::trace_event::MemoryAllocatorDumpGuid& buffer_dump_guid, + uint64_t tracing_process_id, + int importance) const override { if (!storage_allocated) - return {}; - return gl::GetGLTextureClientGUIDForTracing( + return; + + auto texture_tracing_guid = gl::GetGLTextureClientGUIDForTracing( compositor_context_provider->ContextSupport()->ShareGroupTracingGUID(), texture_id); + pmd->CreateSharedGlobalAllocatorDump(texture_tracing_guid); + pmd->AddOwnershipEdge(buffer_dump_guid, texture_tracing_guid, importance); } - base::UnguessableToken SharedMemoryGuid() override { return {}; } // The ContextProvider used to clean up the texture id. viz::ContextProvider* compositor_context_provider = nullptr;
diff --git a/cc/raster/staging_buffer_pool.cc b/cc/raster/staging_buffer_pool.cc index f8da5555..eada8b1 100644 --- a/cc/raster/staging_buffer_pool.cc +++ b/cc/raster/staging_buffer_pool.cc
@@ -115,17 +115,9 @@ const uint64_t tracing_process_id = base::trace_event::MemoryDumpManager::GetInstance() ->GetTracingProcessId(); - auto shared_memory_guid = gpu_memory_buffer->GetHandle().handle.GetGUID(); const int kImportance = 2; - if (!shared_memory_guid.is_empty()) { - pmd->CreateSharedMemoryOwnershipEdge(buffer_dump->guid(), - shared_memory_guid, kImportance); - } else { - auto shared_buffer_guid = - gpu_memory_buffer->GetGUIDForTracing(tracing_process_id); - pmd->CreateSharedGlobalAllocatorDump(shared_buffer_guid); - pmd->AddOwnershipEdge(buffer_dump->guid(), shared_buffer_guid, kImportance); - } + gpu_memory_buffer->OnMemoryDump(pmd, buffer_dump->guid(), tracing_process_id, + kImportance); } StagingBufferPool::StagingBufferPool(
diff --git a/cc/raster/zero_copy_raster_buffer_provider.cc b/cc/raster/zero_copy_raster_buffer_provider.cc index b1ea442..a5a7e0a 100644 --- a/cc/raster/zero_copy_raster_buffer_provider.cc +++ b/cc/raster/zero_copy_raster_buffer_provider.cc
@@ -41,17 +41,15 @@ gl->DestroyImageCHROMIUM(image_id); } - base::trace_event::MemoryAllocatorDumpGuid MemoryDumpGuid( - uint64_t tracing_process_id) override { + void OnMemoryDump( + base::trace_event::ProcessMemoryDump* pmd, + const base::trace_event::MemoryAllocatorDumpGuid& buffer_dump_guid, + uint64_t tracing_process_id, + int importance) const override { if (!gpu_memory_buffer) - return {}; - return gpu_memory_buffer->GetGUIDForTracing(tracing_process_id); - } - - base::UnguessableToken SharedMemoryGuid() override { - if (!gpu_memory_buffer) - return {}; - return gpu_memory_buffer->GetHandle().handle.GetGUID(); + return; + gpu_memory_buffer->OnMemoryDump(pmd, buffer_dump_guid, tracing_process_id, + importance); } // The ContextProvider used to clean up the texture and image ids.
diff --git a/cc/resources/resource_pool.cc b/cc/resources/resource_pool.cc index 47f776c..9d8c3da 100644 --- a/cc/resources/resource_pool.cc +++ b/cc/resources/resource_pool.cc
@@ -587,28 +587,6 @@ int tracing_id, const viz::ClientResourceProvider* resource_provider, bool is_free) const { - base::UnguessableToken shm_guid; - base::trace_event::MemoryAllocatorDumpGuid backing_guid; - if (software_backing_) { - // Software resources are allocated in shared memory for use cross-process - // in the display compositor. So we use the guid for the shared memory to - // identify them in tracing in all processes. - shm_guid = software_backing_->SharedMemoryGuid(); - } else if (gpu_backing_) { - // We prefer the SharedMemoryGuid() if it exists, if the resource is backed - // by shared memory. - shm_guid = gpu_backing_->SharedMemoryGuid(); - if (shm_guid.is_empty()) { - auto* dump_manager = base::trace_event::MemoryDumpManager::GetInstance(); - backing_guid = - gpu_backing_->MemoryDumpGuid(dump_manager->GetTracingProcessId()); - } - } - - // If memory isn't allocated on the resource yet, then don't dump it. - if (shm_guid.is_empty() && backing_guid.empty()) - return; - // Resource IDs are not process-unique, so log with the ResourcePool's unique // tracing id. std::string dump_name = base::StringPrintf( @@ -620,12 +598,14 @@ // the root ownership. The gpu processes uses 0, so 2 is sufficient, and was // chosen historically and there is no need to adjust it. const int kImportance = 2; - if (!shm_guid.is_empty()) { - pmd->CreateSharedMemoryOwnershipEdge(dump->guid(), shm_guid, kImportance); - } else { - DCHECK(!backing_guid.empty()); - pmd->CreateSharedGlobalAllocatorDump(backing_guid); - pmd->AddOwnershipEdge(dump->guid(), backing_guid, kImportance); + auto* dump_manager = base::trace_event::MemoryDumpManager::GetInstance(); + uint64_t tracing_process_id = dump_manager->GetTracingProcessId(); + if (software_backing_) { + software_backing_->OnMemoryDump(pmd, dump->guid(), tracing_process_id, + kImportance); + } else if (gpu_backing_) { + gpu_backing_->OnMemoryDump(pmd, dump->guid(), tracing_process_id, + kImportance); } uint64_t total_bytes =
diff --git a/cc/resources/resource_pool.h b/cc/resources/resource_pool.h index ebc1f56..0fe162d 100644 --- a/cc/resources/resource_pool.h +++ b/cc/resources/resource_pool.h
@@ -56,14 +56,17 @@ public: virtual ~GpuBacking() = default; - // Guids for for memory dumps. This guid will be valid once the GpuBacking - // has memory allocated. Called on the compositor thread. - virtual base::trace_event::MemoryAllocatorDumpGuid MemoryDumpGuid( - uint64_t tracing_process_id) = 0; - // Some gpu resources can be shared memory-backed, and this guid should be - // prefered in that case. But if not then this will be empty. Called on the - // compositor thread. - virtual base::UnguessableToken SharedMemoryGuid() = 0; + // Dumps information about the memory backing the GpuBacking to |pmd|. + // The memory usage is attributed to |buffer_dump_guid|. + // |tracing_process_id| uniquely identifies the process owning the memory. + // |importance| is relevant only for the cases of co-ownership, the memory + // gets attributed to the owner with the highest importance. + // Called on the compositor thread. + virtual void OnMemoryDump( + base::trace_event::ProcessMemoryDump* pmd, + const base::trace_event::MemoryAllocatorDumpGuid& buffer_dump_guid, + uint64_t tracing_process_id, + int importance) const = 0; gpu::Mailbox mailbox; gpu::SyncToken mailbox_sync_token; @@ -88,8 +91,17 @@ public: virtual ~SoftwareBacking() = default; - // Return the guid for this resource, based on the shared memory backing it. - virtual base::UnguessableToken SharedMemoryGuid() = 0; + // Dumps information about the memory backing the SoftwareBacking to |pmd|. + // The memory usage is attributed to |buffer_dump_guid|. + // |tracing_process_id| uniquely identifies the process owning the memory. + // |importance| is relevant only for the cases of co-ownership, the memory + // gets attributed to the owner with the highest importance. + // Called on the compositor thread. + virtual void OnMemoryDump( + base::trace_event::ProcessMemoryDump* pmd, + const base::trace_event::MemoryAllocatorDumpGuid& buffer_dump_guid, + uint64_t tracing_process_id, + int importance) const = 0; viz::SharedBitmapId shared_bitmap_id; };
diff --git a/cc/resources/resource_pool_unittest.cc b/cc/resources/resource_pool_unittest.cc index 171b1776..8b6cf746 100644 --- a/cc/resources/resource_pool_unittest.cc +++ b/cc/resources/resource_pool_unittest.cc
@@ -37,11 +37,11 @@ protected: class StubGpuBacking : public ResourcePool::GpuBacking { public: - base::trace_event::MemoryAllocatorDumpGuid MemoryDumpGuid( - uint64_t tracing_process_id) override { - return {}; - } - base::UnguessableToken SharedMemoryGuid() override { return {}; } + void OnMemoryDump( + base::trace_event::ProcessMemoryDump* pmd, + const base::trace_event::MemoryAllocatorDumpGuid& buffer_dump_guid, + uint64_t tracing_process_id, + int importance) const override {} }; void SetBackingOnResource(const ResourcePool::InUsePoolResource& resource) {
diff --git a/cc/test/fake_raster_buffer_provider.cc b/cc/test/fake_raster_buffer_provider.cc index 009e6ee..a203f47 100644 --- a/cc/test/fake_raster_buffer_provider.cc +++ b/cc/test/fake_raster_buffer_provider.cc
@@ -10,11 +10,11 @@ class StubGpuBacking : public ResourcePool::GpuBacking { public: - base::trace_event::MemoryAllocatorDumpGuid MemoryDumpGuid( - uint64_t tracing_process_id) override { - return {}; - } - base::UnguessableToken SharedMemoryGuid() override { return {}; } + void OnMemoryDump( + base::trace_event::ProcessMemoryDump* pmd, + const base::trace_event::MemoryAllocatorDumpGuid& buffer_dump_guid, + uint64_t tracing_process_id, + int importance) const override {} }; FakeRasterBufferProviderImpl::FakeRasterBufferProviderImpl() = default;
diff --git a/cc/test/test_image_factory.cc b/cc/test/test_image_factory.cc index 7cbfd4f..c6334aa 100644 --- a/cc/test/test_image_factory.cc +++ b/cc/test/test_image_factory.cc
@@ -16,7 +16,7 @@ TestImageFactory::~TestImageFactory() = default; scoped_refptr<gl::GLImage> TestImageFactory::CreateImageForGpuMemoryBuffer( - const gfx::GpuMemoryBufferHandle& handle, + gfx::GpuMemoryBufferHandle handle, const gfx::Size& size, gfx::BufferFormat format, unsigned internalformat,
diff --git a/cc/test/test_image_factory.h b/cc/test/test_image_factory.h index d896d3a..45a1f3a5 100644 --- a/cc/test/test_image_factory.h +++ b/cc/test/test_image_factory.h
@@ -17,7 +17,7 @@ // Overridden from gpu::ImageFactory: scoped_refptr<gl::GLImage> CreateImageForGpuMemoryBuffer( - const gfx::GpuMemoryBufferHandle& handle, + gfx::GpuMemoryBufferHandle handle, const gfx::Size& size, gfx::BufferFormat format, unsigned internalformat,
diff --git a/cc/tiles/tile_manager_unittest.cc b/cc/tiles/tile_manager_unittest.cc index 9c437b1..9cfd207e 100644 --- a/cc/tiles/tile_manager_unittest.cc +++ b/cc/tiles/tile_manager_unittest.cc
@@ -1524,7 +1524,11 @@ class TestSoftwareBacking : public ResourcePool::SoftwareBacking { public: // No tracing is done during these tests. - base::UnguessableToken SharedMemoryGuid() override { return {}; } + void OnMemoryDump( + base::trace_event::ProcessMemoryDump* pmd, + const base::trace_event::MemoryAllocatorDumpGuid& buffer_dump_guid, + uint64_t tracing_process_id, + int importance) const override {} std::unique_ptr<uint32_t[]> pixels; };
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 708904e..e4ba039 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -1195,19 +1195,40 @@ _add_unwind_tables_in_chrome_public_apk = can_unwind_with_cfi_table && is_official_build -chrome_public_apk_tmpl_shared("chrome_public_apk") { - android_manifest = chrome_public_android_manifest - android_manifest_dep = ":chrome_public_android_manifest" - apk_name = "ChromePublic" - shared_libraries = [ ":libchrome" ] - add_unwind_tables_in_apk = _add_unwind_tables_in_chrome_public_apk - if (_add_unwind_tables_in_chrome_public_apk) { - shared_library_for_unwind_asset = "chrome" +template("chrome_public_apk_or_module_tmpl") { + chrome_public_apk_tmpl_shared(target_name) { + forward_variables_from(invoker, + [ + "apk_name", + "is_base_module", + "module_name", + "target_type", + ]) + + android_manifest = chrome_public_android_manifest + android_manifest_dep = ":chrome_public_android_manifest" + shared_libraries = [ ":libchrome" ] + add_unwind_tables_in_apk = _add_unwind_tables_in_chrome_public_apk + if (_add_unwind_tables_in_chrome_public_apk) { + shared_library_for_unwind_asset = "chrome" + } } } +chrome_public_apk_or_module_tmpl("chrome_public_apk") { + apk_name = "ChromePublic" + target_type = "android_apk" +} + +chrome_public_apk_or_module_tmpl("chrome_public_base_module") { + module_name = "ChromePublicBase" + target_type = "android_app_bundle_module" + is_base_module = true +} + chrome_public_apk_tmpl_shared("chrome_public_apk_for_test") { testonly = true + target_type = "android_apk" android_manifest = chrome_public_android_manifest android_manifest_dep = ":chrome_public_android_manifest" apk_name = "ChromePublicForTest" @@ -1228,22 +1249,42 @@ } } -chrome_public_apk_tmpl_shared("chrome_modern_public_apk") { - android_manifest = chrome_modern_public_android_manifest - android_manifest_dep = ":chrome_modern_public_android_manifest" +template("chrome_modern_public_apk_or_module_tmpl") { + chrome_public_apk_tmpl_shared(target_name) { + forward_variables_from(invoker, + [ + "apk_name", + "is_base_module", + "module_name", + "target_type", + ]) + + android_manifest = chrome_modern_public_android_manifest + android_manifest_dep = ":chrome_modern_public_android_manifest" + shared_libraries = [ ":libchrome" ] + add_unwind_tables_in_apk = _add_unwind_tables_in_chrome_public_apk + if (_add_unwind_tables_in_chrome_public_apk) { + shared_library_for_unwind_asset = "chrome" + } + + if (!is_java_debug) { + png_to_webp = true + } + + # Always enable load_library_from_apk. + load_library_from_apk = chromium_linker_supported + } +} + +chrome_modern_public_apk_or_module_tmpl("chrome_modern_public_apk") { apk_name = "ChromeModernPublic" - shared_libraries = [ ":libchrome" ] - add_unwind_tables_in_apk = _add_unwind_tables_in_chrome_public_apk - if (_add_unwind_tables_in_chrome_public_apk) { - shared_library_for_unwind_asset = "chrome" - } + target_type = "android_apk" +} - if (!is_java_debug) { - png_to_webp = true - } - - # Always enable load_library_from_apk. - load_library_from_apk = chromium_linker_supported +chrome_modern_public_apk_or_module_tmpl("chrome_modern_public_base_module") { + module_name = "ChromeModernPublicBase" + target_type = "android_app_bundle_module" + is_base_module = true } android_library("monochrome_java") { @@ -1258,33 +1299,54 @@ [ "java/src/org/chromium/chrome/browser/MonochromeApplication.java" ] } -monochrome_public_apk_tmpl("monochrome_public_apk") { - android_manifest = monochrome_public_android_manifest - android_manifest_dep = ":monochrome_public_android_manifest" +template("monochrome_public_apk_or_module_tmpl") { + monochrome_public_apk_tmpl(target_name) { + forward_variables_from(invoker, + [ + "apk_name", + "is_base_module", + "module_name", + "target_type", + ]) + + android_manifest = monochrome_public_android_manifest + android_manifest_dep = ":monochrome_public_android_manifest" + + if (public_android_sdk) { + # Resource whitelist used when generating R.java files and causes + # only the webview subset of resources to be marked as non-final. + shared_resources_whitelist_target = "//android_webview:system_webview_apk" + } + + deps = [ + ":monochrome_java", + "//android_webview:platform_service_bridge_upstream_implementation_java", + "//base:base_java", + "//chrome/android:app_hooks_java", + "//chrome/android:chrome_java", + ] + + add_unwind_tables_in_apk = _add_unwind_tables_in_chrome_public_apk + if (_add_unwind_tables_in_chrome_public_apk && can_unwind_with_cfi_table) { + shared_library_for_unwind_asset = "monochrome" + } + } +} + +monochrome_public_apk_or_module_tmpl("monochrome_public_apk") { apk_name = "MonochromePublic" + target_type = "android_apk" +} - if (public_android_sdk) { - # Resource whitelist used when generating R.java files and causes - # only the webview subset of resources to be marked as non-final. - shared_resources_whitelist_target = "//android_webview:system_webview_apk" - } - - deps = [ - ":monochrome_java", - "//android_webview:platform_service_bridge_upstream_implementation_java", - "//base:base_java", - "//chrome/android:app_hooks_java", - "//chrome/android:chrome_java", - ] - - add_unwind_tables_in_apk = _add_unwind_tables_in_chrome_public_apk - if (_add_unwind_tables_in_chrome_public_apk && can_unwind_with_cfi_table) { - shared_library_for_unwind_asset = "monochrome" - } +monochrome_public_apk_or_module_tmpl("monochrome_public_base_module") { + module_name = "MonochromePublicBase" + target_type = "android_app_bundle_module" + is_base_module = true } chrome_public_apk_tmpl_shared("chrome_sync_shell_apk") { testonly = true + target_type = "android_apk" android_manifest = chrome_sync_shell_android_manifest android_manifest_dep = ":chrome_sync_shell_android_manifest" apk_name = "ChromeSyncShell" @@ -1530,7 +1592,7 @@ # Generate application bundles if possible. android_app_bundle("chrome_public_bundle") { - base_apk_target = ":chrome_public_apk" + base_module_target = ":chrome_public_base_module" # Signing is very slow, only do that for official builds. sign_bundle = is_official_build @@ -1543,9 +1605,9 @@ } android_app_bundle("chrome_modern_public_bundle") { - base_apk_target = ":chrome_modern_public_apk" + base_module_target = ":chrome_modern_public_base_module" } android_app_bundle("monochrome_public_bundle") { - base_apk_target = ":monochrome_public_apk" + base_module_target = ":monochrome_public_base_module" }
diff --git a/chrome/android/chrome_public_apk_tmpl.gni b/chrome/android/chrome_public_apk_tmpl.gni index c5c6412..dbd56473f 100644 --- a/chrome/android/chrome_public_apk_tmpl.gni +++ b/chrome/android/chrome_public_apk_tmpl.gni
@@ -44,7 +44,12 @@ } } - android_apk(target_name) { + if (!defined(invoker.target_type)) { + _target_type = "android_apk" + } else { + _target_type = invoker.target_type + } + target(_target_type, target_name) { forward_variables_from(invoker, "*") exclude_xxxhdpi = true @@ -118,7 +123,9 @@ (current_cpu == "arm64" || current_cpu == "x64") } } - command_line_flags_file = "chrome-command-line" + if (_target_type == "android_apk") { + command_line_flags_file = "chrome-command-line" + } product_version_resources_dep = "//chrome/android:product_version_resources" if (defined(invoker.add_unwind_tables_in_apk) && @@ -150,8 +157,10 @@ # Webview supports all locales (has no omitted ones). aapt_locale_whitelist = locales - # Incremental install doesn't work for monochrome. See crbug.com/663492. - never_incremental = true + if (!defined(invoker.target_type) || invoker.target_type == "android_apk") { + # Incremental install doesn't work for monochrome. See crbug.com/663492. + never_incremental = true + } # Strip xml namespaces for monochrome. This should only be done for apks # targeting API > 21 which for chrome is only Monochrome. This is due to
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedContentStorage.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedContentStorage.java new file mode 100644 index 0000000..9926d3a --- /dev/null +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedContentStorage.java
@@ -0,0 +1,144 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.feed; + +import com.google.android.libraries.feed.common.Result; +import com.google.android.libraries.feed.common.functional.Consumer; +import com.google.android.libraries.feed.host.storage.CommitResult; +import com.google.android.libraries.feed.host.storage.ContentMutation; +import com.google.android.libraries.feed.host.storage.ContentOperation; +import com.google.android.libraries.feed.host.storage.ContentOperation.Delete; +import com.google.android.libraries.feed.host.storage.ContentOperation.DeleteByPrefix; +import com.google.android.libraries.feed.host.storage.ContentOperation.Type; +import com.google.android.libraries.feed.host.storage.ContentOperation.Upsert; +import com.google.android.libraries.feed.host.storage.ContentStorage; + +import org.chromium.base.Callback; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +/** + * Implementation of {@link ContentStorage} that persisits data on native side. + */ +public class FeedContentStorage implements ContentStorage { + private FeedStorageBridge mFeedStorageBridge; + + private static class StorageCallback<T> implements Callback<T> { + private final Consumer<Result<T>> mConsumer; + + public StorageCallback(Consumer<Result<T>> consumer) { + mConsumer = consumer; + } + + @Override + public void onResult(T data) { + // TODO(gangwu): Need to handle failure case. + mConsumer.accept(Result.success(data)); + } + } + + private static class CommitCallback implements Callback<Boolean> { + private final Consumer<CommitResult> mConsumer; + private int mOperationsLeft; + private boolean mSuccess; + + CommitCallback(Consumer<CommitResult> consumer, int operationsCount) { + mConsumer = consumer; + mOperationsLeft = operationsCount; + mSuccess = true; + } + + @Override + public void onResult(Boolean result) { + --mOperationsLeft; + assert mOperationsLeft >= 0; + + mSuccess &= result.booleanValue(); + // TODO(gangwu): if |result| is failure, all other operation should halt immediately. + if (mOperationsLeft == 0) { + if (mSuccess) { + mConsumer.accept(CommitResult.SUCCESS); + } else { + mConsumer.accept(CommitResult.FAILURE); + } + } + } + } + + /** + * Creates a {@link FeedContentStorage} for storing content for the current user. + * + * @param bridge {@link FeedStorageBridge} implementation can handle content storage request. + */ + public FeedContentStorage(FeedStorageBridge bridge) { + mFeedStorageBridge = bridge; + } + + /** Cleans up {@link FeedContentStorage}. */ + public void destroy() { + assert mFeedStorageBridge != null; + mFeedStorageBridge.destroy(); + mFeedStorageBridge = null; + } + + @Override + public void get(List<String> keys, Consumer < Result < Map<String, byte[]>>> consumer) { + assert mFeedStorageBridge != null; + mFeedStorageBridge.loadContent(keys, new StorageCallback<Map<String, byte[]>>(consumer)); + } + + @Override + public void getAll(String prefix, Consumer < Result < Map<String, byte[]>>> consumer) { + assert mFeedStorageBridge != null; + mFeedStorageBridge.loadContentByPrefix( + prefix, new StorageCallback<Map<String, byte[]>>(consumer)); + } + + @Override + public void commit(ContentMutation mutation, Consumer<CommitResult> consumer) { + assert mFeedStorageBridge != null; + + CommitCallback callback = new CommitCallback(consumer, mutation.getOperations().size()); + for (ContentOperation operation : mutation.getOperations()) { + switch (operation.getType()) { + case Type.UPSERT: + // TODO(gangwu): If upserts are continuous, we should conbine them into one + // array, and then send to native side. + Upsert upsert = (Upsert) operation; + String[] upsertKeys = {upsert.getKey()}; + byte[][] upsertData = {upsert.getValue()}; + mFeedStorageBridge.saveContent(upsertKeys, upsertData, callback); + break; + case Type.DELETE: + // TODO(gangwu): If deletes are continuous, we should conbine them into one + // array, and then send to native side. + Delete delete = (Delete) operation; + List<String> deleteKeys = Collections.singletonList(delete.getKey()); + mFeedStorageBridge.deleteContent(deleteKeys, callback); + break; + case Type.DELETE_BY_PREFIX: + DeleteByPrefix deleteByPrefix = (DeleteByPrefix) operation; + String prefix = deleteByPrefix.getPrefix(); + mFeedStorageBridge.deleteContentByPrefix(prefix, callback); + break; + case Type.DELETE_ALL: + mFeedStorageBridge.deleteAllContent(callback); + break; + default: + // Unsupport type of operations, so cannot performance the operation. + callback.onResult(false); + break; + } + } + } + + @Override + public void getAllKeys(Consumer < Result < List<String>>> consumer) { + assert mFeedStorageBridge != null; + mFeedStorageBridge.loadAllContentKeys(new StorageCallback<List<String>>(consumer)); + } +}
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedStorageBridge.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedStorageBridge.java new file mode 100644 index 0000000..b45d9719 --- /dev/null +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedStorageBridge.java
@@ -0,0 +1,116 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.feed; + +import org.chromium.base.Callback; +import org.chromium.base.annotations.CalledByNative; +import org.chromium.base.annotations.JNINamespace; +import org.chromium.chrome.browser.profiles.Profile; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Provides access to native implementations of content storage and journal storage. + */ +@JNINamespace("feed") +public class FeedStorageBridge { + private long mNativeFeedStorageBridge; + + /** + * Creates a {@link FeedStorageBridge} for accessing native content and journal storage + * implementation for the current user, and initial native side bridge. + * + * @param profile {@link Profile} of the user we are rendering the Feed for. + */ + public FeedStorageBridge() {} + + /** + * Inits native side bridge. + * + * @param profile {@link Profile} of the user we are rendering the Feed for. + */ + public void init(Profile profile) { + mNativeFeedStorageBridge = nativeInit(profile); + } + + /** Cleans up native half of this bridge. */ + public void destroy() { + assert mNativeFeedStorageBridge != 0; + nativeDestroy(mNativeFeedStorageBridge); + mNativeFeedStorageBridge = 0; + } + + public void loadContent(List<String> keys, Callback<Map<String, byte[]>> callback) { + assert mNativeFeedStorageBridge != 0; + String[] keysArray = keys.toArray(new String[keys.size()]); + nativeLoadContent(mNativeFeedStorageBridge, keysArray, callback); + } + + public void loadContentByPrefix(String prefix, Callback<Map<String, byte[]>> callback) { + assert mNativeFeedStorageBridge != 0; + nativeLoadContentByPrefix(mNativeFeedStorageBridge, prefix, callback); + } + + public void loadAllContentKeys(Callback<List<String>> callback) { + assert mNativeFeedStorageBridge != 0; + nativeLoadAllContentKeys(mNativeFeedStorageBridge, callback); + } + + public void saveContent(String[] keys, byte[][] data, Callback<Boolean> callback) { + assert mNativeFeedStorageBridge != 0; + nativeSaveContent(mNativeFeedStorageBridge, keys, data, callback); + } + + public void deleteContent(List<String> keys, Callback<Boolean> callback) { + assert mNativeFeedStorageBridge != 0; + String[] keysArray = keys.toArray(new String[keys.size()]); + nativeDeleteContent(mNativeFeedStorageBridge, keysArray, callback); + } + + public void deleteContentByPrefix(String prefix, Callback<Boolean> callback) { + assert mNativeFeedStorageBridge != 0; + nativeDeleteContentByPrefix(mNativeFeedStorageBridge, prefix, callback); + } + + public void deleteAllContent(Callback<Boolean> callback) { + assert mNativeFeedStorageBridge != 0; + nativeDeleteAllContent(mNativeFeedStorageBridge, callback); + } + + @CalledByNative + private static Object createKeyAndDataMap(String[] keys, byte[][] data) { + assert keys.length == data.length; + Map<String, byte[]> valueMap = new HashMap<>(keys.length); + for (int i = 0; i < keys.length && i < data.length; ++i) { + valueMap.put(keys[i], data[i]); + } + return valueMap; + } + + @CalledByNative + private static List<String> createJavaList(String[] keys) { + return Arrays.asList(keys); + } + + private native long nativeInit(Profile profile); + private native void nativeDestroy(long nativeFeedStorageBridge); + private native void nativeLoadContent( + long nativeFeedStorageBridge, String[] keys, Callback<Map<String, byte[]>> callback); + private native void nativeLoadContentByPrefix( + long nativeFeedStorageBridge, String prefix, Callback<Map<String, byte[]>> callback); + private native void nativeLoadAllContentKeys( + long nativeFeedStorageBridge, Callback<List<String>> callback); + private native void nativeSaveContent( + long nativeFeedStorageBridge, String[] keys, byte[][] data, Callback<Boolean> callback); + private native void nativeDeleteContent( + long nativeFeedStorageBridge, String[] keys, Callback<Boolean> callback); + private native void nativeDeleteContentByPrefix( + long nativeFeedStorageBridge, String prefix, Callback<Boolean> callback); + private native void nativeDeleteAllContent( + long nativeFeedStorageBridge, Callback<Boolean> callback); +}
diff --git a/chrome/android/feed/feed_java_sources.gni b/chrome/android/feed/feed_java_sources.gni index bb4ce6e..ebe41f4 100644 --- a/chrome/android/feed/feed_java_sources.gni +++ b/chrome/android/feed/feed_java_sources.gni
@@ -9,6 +9,7 @@ feed_deps = [ "//third_party/feed:feed_lib_java" ] feed_java_sources = [ + "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedContentStorage.java", "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedEventReporter.java", "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedImageLoader.java", "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedImageLoaderBridge.java", @@ -18,6 +19,7 @@ "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedProcessScopeFactory.java", "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedRefreshTask.java", "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSchedulerBridge.java", + "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedStorageBridge.java", "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/StreamLifecycleManager.java", "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/action/FeedActionHandler.java", ] @@ -25,6 +27,7 @@ feed_srcjar_deps = [ "//components/feed/core:feed_core_java_enums_srcjar" ] feed_junit_test_java_sources = [ + "junit/src/org/chromium/chrome/browser/feed/FeedContentStorageTest.java", "junit/src/org/chromium/chrome/browser/feed/FeedImageLoaderTest.java", "junit/src/org/chromium/chrome/browser/feed/StreamLifecycleManagerTest.java", ]
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ServiceTabLauncher.java b/chrome/android/java/src/org/chromium/chrome/browser/ServiceTabLauncher.java index 7efa5ff..3b13427 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ServiceTabLauncher.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ServiceTabLauncher.java
@@ -5,7 +5,9 @@ package org.chromium.chrome.browser; import android.app.Activity; +import android.content.Context; import android.content.Intent; +import android.content.pm.ResolveInfo; import android.net.Uri; import android.provider.Browser; import android.support.annotation.Nullable; @@ -16,6 +18,8 @@ import org.chromium.base.ThreadUtils; import org.chromium.base.annotations.CalledByNative; import org.chromium.chrome.R; +import org.chromium.chrome.browser.browserservices.BrowserServicesMetrics; +import org.chromium.chrome.browser.browserservices.TrustedWebActivityClient; import org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType; @@ -34,6 +38,8 @@ import org.chromium.webapk.lib.client.WebApkNavigationClient; import org.chromium.webapk.lib.client.WebApkValidator; +import java.util.List; + /** * Tab Launcher to be used to launch new tabs from background Android Services, * when it is not known whether an activity is available. It will send an intent to launch the @@ -80,9 +86,17 @@ private static void dispatchLaunch(final int requestId, final boolean incognito, final String url, final String referrerUrl, final int referrerPolicy, final String extraHeaders, final ResourceRequestBody postData) { - final String webApkPackageName = - WebApkValidator.queryWebApkPackage(ContextUtils.getApplicationContext(), url); + Context context = ContextUtils.getApplicationContext(); + + List<ResolveInfo> resolveInfos; + try (BrowserServicesMetrics.TimingMetric t = + BrowserServicesMetrics.getServiceTabResolveInfoTimingContext()) { + resolveInfos = WebApkValidator.resolveInfosForUrl(context, url); + } + String webApkPackageName = WebApkValidator.findWebApkPackage(context, resolveInfos); + if (webApkPackageName != null) { + final List<ResolveInfo> resolveInfosFinal = resolveInfos; WebApkIdentityServiceClient.CheckBrowserBacksWebApkCallback callback = doesBrowserBackWebApk -> { if (doesBrowserBackWebApk) { @@ -94,25 +108,37 @@ return; } launchTabOrWebapp(requestId, incognito, url, referrerUrl, - referrerPolicy, extraHeaders, postData); + referrerPolicy, extraHeaders, postData, resolveInfosFinal); }; ChromeWebApkHost.checkChromeBacksWebApkAsync(webApkPackageName, callback); return; } - launchTabOrWebapp( - requestId, incognito, url, referrerUrl, referrerPolicy, extraHeaders, postData); + launchTabOrWebapp(requestId, incognito, url, referrerUrl, referrerPolicy, extraHeaders, + postData, resolveInfos); } /** Launches WebappActivity or a tab for the |url|. */ private static void launchTabOrWebapp(int requestId, boolean incognito, String url, String referrerUrl, int referrerPolicy, String extraHeaders, - ResourceRequestBody postData) { + ResourceRequestBody postData, List<ResolveInfo> resolveInfosForUrl) { // Launch WebappActivity if one matches the target URL and was opened recently. // Otherwise, open the URL in a tab. WebappDataStorage storage = WebappRegistry.getInstance().getWebappDataStorageForUrl(url); TabDelegate tabDelegate = new TabDelegate(incognito); + // Launch into a TrustedWebActivity if one exists for the URL. + Context appContext = ContextUtils.getApplicationContext(); + if (!incognito) { + Intent twaIntent = TrustedWebActivityClient + .createLaunchIntentForTwa(appContext, url, resolveInfosForUrl); + + if (twaIntent != null) { + appContext.startActivity(twaIntent); + return; + } + } + // Open a new tab if: // - We did not find a WebappDataStorage corresponding to this URL. // OR
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegate.java index b89620b..7cbf93da 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegate.java
@@ -246,7 +246,7 @@ Context context = ContextUtils.getApplicationContext(); long addToHomeScreenStart = SystemClock.elapsedRealtime(); ResolveInfo resolveInfo = - WebApkValidator.queryResolveInfo(context, currentTab.getUrl()); + WebApkValidator.queryWebApkResolveInfo(context, currentTab.getUrl()); RecordHistogram.recordTimesHistogram("Android.PrepareMenu.OpenWebApkVisibilityCheck", SystemClock.elapsedRealtime() - addToHomeScreenStart, TimeUnit.MILLISECONDS);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/BrowserServicesMetrics.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/BrowserServicesMetrics.java index 69bcbf14..230737d2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/BrowserServicesMetrics.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/BrowserServicesMetrics.java
@@ -4,6 +4,7 @@ package org.chromium.chrome.browser.browserservices; +import android.os.SystemClock; import android.support.annotation.IntDef; import org.chromium.base.metrics.RecordHistogram; @@ -57,6 +58,38 @@ RecordHistogram.recordTimesHistogram("BrowserServices.TwaOpenTime", duration, unit); } + /** + * Returns a {@link TimingMetric} that records the amount of time spent querying the Android + * system for ResolveInfos that will deal with a given URL when launching from a background + * service. + */ + public static TimingMetric getServiceTabResolveInfoTimingContext() { + return new TimingMetric("BrowserServices.ServiceTabResolveInfoQuery"); + } + + /** + * A class to be used with a try-with-resources to record the elapsed time within the try block. + */ + public static class TimingMetric implements AutoCloseable { + private final String mMetric; + private final long mStart; + + private static long now() { + return SystemClock.uptimeMillis(); + } + + public TimingMetric(String metric) { + mMetric = metric; + mStart = now(); + } + + @Override + public void close() { + RecordHistogram.recordMediumTimesHistogram( + mMetric, now() - mStart, TimeUnit.MILLISECONDS); + } + } + // Don't let anyone instantiate. private BrowserServicesMetrics() {} }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/Origin.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/Origin.java index cb53f576..98f84cb 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/Origin.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/Origin.java
@@ -6,6 +6,8 @@ import android.net.Uri; +import org.chromium.chrome.browser.UrlConstants; + /** * A class to canonically represent a web origin in Java. In comparison to * {@link org.chromium.net.GURLUtils#getOrigin} it can be used before native is loaded and lets us @@ -41,8 +43,9 @@ // Make explicit ports implicit and remove any user:password. int port = uri.getPort(); - if (uri.getScheme().equals("http") && port == HTTP_DEFAULT_PORT) port = -1; - if (uri.getScheme().equals("https") && port == HTTPS_DEFAULT_PORT) port = -1; + String scheme = uri.getScheme(); + if (scheme.equals(UrlConstants.HTTP_SCHEME) && port == HTTP_DEFAULT_PORT) port = -1; + if (scheme.equals(UrlConstants.HTTPS_SCHEME) && port == HTTPS_DEFAULT_PORT) port = -1; String authority = uri.getHost(); if (port != -1) authority += ":" + port;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClient.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClient.java index 3b2ba81c..97f5172 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClient.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClient.java
@@ -4,15 +4,25 @@ package org.chromium.chrome.browser.browserservices; +import android.content.ComponentName; import android.content.Context; +import android.content.Intent; +import android.content.pm.ResolveInfo; import android.content.res.Resources; import android.net.Uri; +import android.support.annotation.Nullable; import android.support.customtabs.trusted.TrustedWebActivityServiceConnectionManager; import org.chromium.base.ContextUtils; import org.chromium.chrome.R; +import org.chromium.chrome.browser.ChromeFeatureList; +import org.chromium.chrome.browser.UrlConstants; import org.chromium.chrome.browser.notifications.NotificationBuilderBase; import org.chromium.chrome.browser.notifications.NotificationUmaTracker; +import org.chromium.chrome.browser.webapps.WebappLauncherActivity; + +import java.util.List; +import java.util.Set; /** * Uses a Trusted Web Activity client to display notifications. @@ -92,4 +102,46 @@ TrustedWebActivityServiceConnectionManager .registerClient(context, origin.toString(), clientPackage); } + + /** + * Searches through the given list of {@link ResolveInfo} for an Activity belonging to a package + * that is verified for the given url. If such an Activity is found, an Intent to start that + * Activity as a Trusted Web Activity is returned. Otherwise {@code null} is returned. + * + * If multiple {@link ResolveInfo}s in the list match this criteria, the first will be chosen. + */ + public static @Nullable Intent createLaunchIntentForTwa(Context appContext, String url, + List<ResolveInfo> resolveInfosForUrl) { + if (!ChromeFeatureList.isEnabled(ChromeFeatureList.TRUSTED_WEB_ACTIVITY)) return null; + + Origin origin = new Origin(url); + + // Trusted Web Activities only work with https so we can shortcut here. + if (!origin.uri().getScheme().equals(UrlConstants.HTTPS_SCHEME)) return null; + + Set<String> verifiedPackages = TrustedWebActivityServiceConnectionManager + .getVerifiedPackages(appContext, origin.toString()); + if (verifiedPackages == null || verifiedPackages.size() == 0) return null; + + String twaPackageName = null; + String twaActivityName = null; + for (ResolveInfo info : resolveInfosForUrl) { + if (info.activityInfo == null) continue; + + if (verifiedPackages.contains(info.activityInfo.packageName)) { + twaPackageName = info.activityInfo.packageName; + twaActivityName = info.activityInfo.name; + break; + } + } + + if (twaPackageName == null) return null; + + Intent intent = new Intent(); + intent.setData(Uri.parse(url)); + intent.setAction(Intent.ACTION_VIEW); + intent.setFlags(WebappLauncherActivity.getWebappActivityIntentFlags()); + intent.setComponent(new ComponentName(twaPackageName, twaActivityName)); + return intent; + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/filter/FilterCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/filter/FilterCoordinator.java index af04186..6884e3d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/filter/FilterCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/filter/FilterCoordinator.java
@@ -32,12 +32,15 @@ } private final ObserverList<Observer> mObserverList = new ObserverList<>(); - private final FilterModel mModel; - private final FilterViewBinder mViewBinder; - private final FilterView mView; + private FilterModel mModel; + private FilterViewBinder mViewBinder; + private FilterView mView; - private final ChipsCoordinator mChipsCoordinator; - private final FilterChipsProvider mChipsProvider; + private ChipsCoordinator mChipsCoordinator; + private FilterChipsProvider mChipsProvider; + + /** No-args constructor to be used by subclasses. */ + protected FilterCoordinator() {} /** * Builds a new FilterCoordinator. @@ -105,7 +108,11 @@ filterType = Filters.FilterType.PREFETCHED; } - for (Observer observer : mObserverList) observer.onFilterChanged(filterType); + notifyFilterChanged(filterType); + } + + protected void notifyFilterChanged(@FilterType int filter) { + for (Observer observer : mObserverList) observer.onFilterChanged(filter); } private void handleChipSelected() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/filter/FilterCoordinatorWithNoTabs.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/filter/FilterCoordinatorWithNoTabs.java new file mode 100644 index 0000000..f8e4547 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/filter/FilterCoordinatorWithNoTabs.java
@@ -0,0 +1,38 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.download.home.filter; + +import android.content.Context; +import android.view.View; + +import org.chromium.chrome.browser.download.home.filter.chips.ChipsCoordinator; + +/** + * An empty version of {@code FilterCoordinator} that doesn't contain any tabs. + */ + +public class FilterCoordinatorWithNoTabs extends FilterCoordinator { + private final ChipsCoordinator mChipsCoordinator; + private final FilterChipsProvider mChipsProvider; + + public FilterCoordinatorWithNoTabs(Context context, OfflineItemFilterSource chipFilterSource) { + mChipsProvider = new FilterChipsProvider(type -> handleChipSelected(), chipFilterSource); + mChipsCoordinator = new ChipsCoordinator(context, mChipsProvider); + } + + @Override + public View getView() { + return mChipsCoordinator.getView(); + } + + @Override + public void setSelectedFilter(int filter) { + mChipsProvider.setFilterSelected(filter); + } + + private void handleChipSelected() { + notifyFilterChanged(mChipsProvider.getSelectedFilter()); + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListCoordinator.java index c2d33cc..3ccddde 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListCoordinator.java
@@ -9,6 +9,7 @@ import org.chromium.base.Callback; import org.chromium.chrome.browser.download.home.filter.FilterCoordinator; +import org.chromium.chrome.browser.download.home.filter.FilterCoordinatorWithNoTabs; import org.chromium.chrome.browser.download.home.filter.Filters.FilterType; import org.chromium.chrome.browser.download.home.list.ListItem.ViewListItem; import org.chromium.chrome.browser.widget.selection.SelectionDelegate; @@ -68,7 +69,9 @@ offTheRecord, provider, deleteController, selectionDelegate, model); // Hook up the FilterCoordinator with our mediator. - mFilterCoordinator = new FilterCoordinator(context, mMediator.getFilterSource()); + mFilterCoordinator = shouldShowPrefetchTab() + ? new FilterCoordinator(context, mMediator.getFilterSource()) + : new FilterCoordinatorWithNoTabs(context, mMediator.getFilterSource()); mFilterCoordinator.addObserver(mMediator::onFilterTypeSelected); mFilterCoordinator.addObserver(filterObserver); decoratedModel.setHeader(new ViewListItem(Long.MAX_VALUE, mFilterCoordinator.getView())); @@ -98,4 +101,9 @@ public void onDeletionRequested(List<ListItem> items) { mMediator.onDeletionRequested(items); } + + private boolean shouldShowPrefetchTab() { + // TODO(shaktisahu): Check if prefetch UI is enabled. + return true; + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/router/ChromeMediaRouter.java b/chrome/android/java/src/org/chromium/chrome/browser/media/router/ChromeMediaRouter.java index bf4ee1ce..5256a99f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/router/ChromeMediaRouter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/router/ChromeMediaRouter.java
@@ -390,14 +390,14 @@ */ @Nullable @CalledByNative - public MediaControllerBridge getMediaControllerBridge(String routeId) { + public FlingingControllerBridge getFlingingControllerBridge(String routeId) { MediaRouteProvider provider = mRouteIdsToProviders.get(routeId); if (provider == null) return null; MediaController controller = provider.getMediaController(routeId); if (controller == null) return null; - return new MediaControllerBridge(controller); + return new FlingingControllerBridge(controller); } @VisibleForTesting
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/router/MediaControllerBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/media/router/FlingingControllerBridge.java similarity index 79% rename from chrome/android/java/src/org/chromium/chrome/browser/media/router/MediaControllerBridge.java rename to chrome/android/java/src/org/chromium/chrome/browser/media/router/FlingingControllerBridge.java index 3abcd92..e814562 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/router/MediaControllerBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/router/FlingingControllerBridge.java
@@ -8,15 +8,15 @@ import org.chromium.base.annotations.JNINamespace; /** - * A wrapper around a MediaController that allows the native code to use it. - * See chrome/browser/media/android/remote/media_controller_bridge.h for the corresponding native - * code. + * A wrapper around a MediaController that allows the native code to use it, and to subscribe to + * status changes. See chrome/browser/media/android/remote/flinging_controller_bridge.h for the + * corresponding native code. */ @JNINamespace("media_router") -public class MediaControllerBridge { +public class FlingingControllerBridge { private final MediaController mMediaController; - public MediaControllerBridge(MediaController mediaController) { + public FlingingControllerBridge(MediaController mediaController) { mMediaController = mediaController; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditText.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditText.java index 778a3d5..1fb9e4b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditText.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/AutocompleteEditText.java
@@ -6,7 +6,6 @@ import android.content.Context; import android.graphics.Rect; -import android.os.StrictMode; import android.provider.Settings; import android.support.annotation.CallSuper; import android.text.TextUtils; @@ -20,6 +19,7 @@ import android.widget.EditText; import org.chromium.base.Log; +import org.chromium.base.StrictModeContext; import org.chromium.base.VisibleForTesting; import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.widget.VerticallyFixedEditText; @@ -197,21 +197,26 @@ mDisableTextScrollingFromAutocomplete = false; // Avoid setting the same text as it will mess up the scroll/cursor position. - // Setting the text is also quite expensive, so only do it when the text has changed - // (since we apply spans when the view is not focused, we only optimize this when the - // text is being edited). - if (!TextUtils.equals(getEditableText(), text)) { - // Certain OEM implementations of setText trigger disk reads. crbug.com/633298 - StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); - try { + // Setting the text is also quite expensive, so only do it when the text has changed. + if (!isNewTextEquivalentToExistingText(text)) { + // Certain OEM implementations of setText trigger disk reads. https://crbug.com/633298 + try (StrictModeContext unused = StrictModeContext.allowDiskReads()) { super.setText(text, type); - } finally { - StrictMode.setThreadPolicy(oldPolicy); } } if (mModel != null) mModel.onSetText(text); } + /** + * Whether the specified new text is equivalent to what is already being shown in the TextView. + * + * @param newCharSequence The proposed new text to replace the existing text. + * @return Whether the text is the same. + */ + protected boolean isNewTextEquivalentToExistingText(CharSequence newCharSequence) { + return TextUtils.equals(getEditableText(), newCharSequence); + } + @Override public void sendAccessibilityEventUnchecked(AccessibilityEvent event) { if (shouldIgnoreAccessibilityEvent(event)) { @@ -238,11 +243,8 @@ public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { // Certain OEM implementations of onInitializeAccessibilityNodeInfo trigger disk reads // to access the clipboard. crbug.com/640993 - StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); - try { + try (StrictModeContext unused = StrictModeContext.allowDiskReads()) { super.onInitializeAccessibilityNodeInfo(info); - } finally { - StrictMode.setThreadPolicy(oldPolicy); } } @@ -315,4 +317,4 @@ getContext().getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD); return defaultIme == null ? "" : defaultIme; } -} \ No newline at end of file +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java index cf48fb9..2c067997 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
@@ -185,7 +185,6 @@ private boolean mSuggestionModalShown; private boolean mUseDarkColors; - private boolean mIsEmphasizingHttpsScheme; private Runnable mShowSuggestions; @@ -752,8 +751,8 @@ if (hasFocus) { if (mNativeInitialized) RecordUserAction.record("FocusLocation"); UrlBarData urlBarData = mToolbarDataProvider.getUrlBarData(); - if (urlBarData.editingText == null || !setUrlBarText(urlBarData)) { - mUrlBar.deEmphasizeUrl(); + if (urlBarData.editingText != null) { + setUrlBarText(urlBarData); } // Explicitly tell InputMethodManager that the url bar is focused before any callbacks @@ -771,7 +770,6 @@ // Focus change caused by a close-tab may result in an invalid current tab. if (mToolbarDataProvider.hasTab()) { setUrlToPageUrl(); - emphasizeUrl(); } // Moving focus away from UrlBar(EditText) to a non-editable focus holder, such as @@ -1045,9 +1043,7 @@ updateVerboseStatusVisibility(); - boolean shouldEmphasizeHttpsScheme = shouldEmphasizeHttpsScheme(); - if (mSecurityIconResource == id && mIsEmphasizingHttpsScheme == shouldEmphasizeHttpsScheme - && mLocationBarButtonType == getLocationBarButtonToShow()) { + if (mSecurityIconResource == id && mLocationBarButtonType == getLocationBarButtonToShow()) { return; } mSecurityIconResource = id; @@ -1055,26 +1051,8 @@ changeLocationBarIcon(); updateLocationBarIconContainerVisibility(); - emphasizeUrl(); - mIsEmphasizingHttpsScheme = shouldEmphasizeHttpsScheme; - } - - private void emphasizeUrl() { - if (mToolbarDataProvider.shouldDisplaySearchTerms()) return; - mUrlBar.emphasizeUrl(); - } - - @Override - public boolean shouldEmphasizeUrl() { - return true; - } - - @Override - public boolean shouldEmphasizeHttpsScheme() { - if (mToolbarDataProvider.isUsingBrandColor() || mToolbarDataProvider.isIncognito()) { - return false; - } - return true; + // Update the URL in case the scheme change triggers a URL emphasis change. + setUrlToPageUrl(); } /** @@ -1835,9 +1813,7 @@ } mOriginalUrl = currentUrl; - if (setUrlBarText(mToolbarDataProvider.getUrlBarData())) { - emphasizeUrl(); - } + setUrlBarText(mToolbarDataProvider.getUrlBarData()); if (!mToolbarDataProvider.hasTab()) return; // Profile may be null if switching to a tab that has not yet been initialized. @@ -2116,16 +2092,19 @@ */ @Override public void updateVisualsForState() { - if (updateUseDarkColors() || mIsEmphasizingHttpsScheme != shouldEmphasizeHttpsScheme()) { - updateSecurityIcon(); - } + if (updateUseDarkColors()) updateSecurityIcon(); int id = mUseDarkColors ? R.color.dark_mode_tint : R.color.light_mode_tint; ColorStateList colorStateList = AppCompatResources.getColorStateList(getContext(), id); mMicButton.setTint(colorStateList); mDeleteButton.setTint(colorStateList); setNavigationButtonType(mNavigationButtonType); - mUrlBar.setUseDarkTextColors(mUseDarkColors); + + // If the URL changed colors and is not focused, update the URL to account for the new + // color scheme. + if (mUrlBar.setUseDarkTextColors(mUseDarkColors) && !mUrlBar.hasFocus()) { + setUrlToPageUrl(); + } if (mSuggestionList != null) { mSuggestionList.refreshPopupBackground();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/OmniboxUrlEmphasizer.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/OmniboxUrlEmphasizer.java index af56d4e4..e8f787f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/OmniboxUrlEmphasizer.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/OmniboxUrlEmphasizer.java
@@ -94,8 +94,7 @@ * Denotes that a span is used for emphasizing the URL. */ @VisibleForTesting - interface UrlEmphasisSpan { - } + public interface UrlEmphasisSpan {} /** * Used for emphasizing the URL text by changing the text color. @@ -103,12 +102,25 @@ @VisibleForTesting static class UrlEmphasisColorSpan extends ForegroundColorSpan implements UrlEmphasisSpan { + private int mEmphasisColor; /** * @param color The color to set the text. */ public UrlEmphasisColorSpan(int color) { super(color); + mEmphasisColor = color; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof UrlEmphasisColorSpan)) return false; + return ((UrlEmphasisColorSpan) obj).mEmphasisColor == mEmphasisColor; + } + + @Override + public String toString() { + return getClass().getName() + ", color: " + mEmphasisColor; } } @@ -118,6 +130,10 @@ @VisibleForTesting static class UrlEmphasisSecurityErrorSpan extends StrikethroughSpan implements UrlEmphasisSpan { + @Override + public boolean equals(Object obj) { + return obj instanceof UrlEmphasisSecurityErrorSpan; + } } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBar.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBar.java index ef7d9391..3c2fb308 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBar.java
@@ -20,6 +20,7 @@ import android.text.Editable; import android.text.Layout; import android.text.Selection; +import android.text.Spanned; import android.text.TextUtils; import android.text.style.ReplacementSpan; import android.util.AttributeSet; @@ -38,14 +39,12 @@ import org.chromium.base.ThreadUtils; import org.chromium.chrome.R; import org.chromium.chrome.browser.WindowDelegate; +import org.chromium.chrome.browser.omnibox.OmniboxUrlEmphasizer.UrlEmphasisSpan; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.toolbar.ToolbarManager; -import org.chromium.chrome.browser.util.UrlUtilities; import org.chromium.ui.UiUtils; import java.net.MalformedURLException; -import java.net.URI; -import java.net.URISyntaxException; import java.net.URL; /** @@ -182,17 +181,6 @@ void onTextChangedForAutocomplete(); /** - * @return True if the displayed URL should be emphasized, false if the displayed text - * already has formatting for emphasis applied. - */ - boolean shouldEmphasizeUrl(); - - /** - * @return Whether the light security theme should be used. - */ - boolean shouldEmphasizeHttpsScheme(); - - /** * Called to notify that back key has been pressed while the URL bar has focus. */ void backKeyPressed(); @@ -285,9 +273,10 @@ * Specifies whether the URL bar should use dark text colors or light colors. * @param useDarkColors Whether the text colors should be dark (i.e. appropriate for use * on a light background). + * @return Whether this update resulted in a change from the previous state of text color state. */ - public void setUseDarkTextColors(boolean useDarkColors) { - if (mUseDarkColors != null && mUseDarkColors.booleanValue() == useDarkColors) return; + public boolean setUseDarkTextColors(boolean useDarkColors) { + if (mUseDarkColors != null && mUseDarkColors.booleanValue() == useDarkColors) return false; mUseDarkColors = useDarkColors; if (mUseDarkColors) { @@ -319,9 +308,7 @@ setIgnoreTextChangesForAutocomplete(false); } - if (!hasFocus()) { - emphasizeUrl(); - } + return true; } @Override @@ -715,6 +702,44 @@ return textChanged; } + @Override + protected boolean isNewTextEquivalentToExistingText(CharSequence newCharSequence) { + Spanned currentText = getEditableText(); + if (currentText == null) return newCharSequence == null; + + // Regardless of focus state, ensure the text content is the same. + if (!TextUtils.equals(currentText, newCharSequence)) return false; + + if (isFocused()) { + // When focused if the existing text has emphasis spans, then clear that text as well as + // those spans should only apply when unfocused. + return currentText.getSpans(0, currentText.length(), UrlEmphasisSpan.class).length == 0; + } + + // When not focused, compare the emphasis spans applied to the text to determine + // equality. Internally, TextView applies many additional spans that need to be + // ignored for this comparison to be useful, so this is scoped to only the span types + // applied by our UI. + if (!(newCharSequence instanceof Spanned)) return false; + + Spanned newText = (Spanned) newCharSequence; + UrlEmphasisSpan[] currentSpans = + currentText.getSpans(0, currentText.length(), UrlEmphasisSpan.class); + UrlEmphasisSpan[] newSpans = newText.getSpans(0, newText.length(), UrlEmphasisSpan.class); + if (currentSpans.length != newSpans.length) return false; + for (int i = 0; i < currentSpans.length; i++) { + UrlEmphasisSpan currentSpan = currentSpans[i]; + UrlEmphasisSpan newSpan = newSpans[i]; + if (!currentSpan.equals(newSpan) + || currentText.getSpanStart(currentSpan) != newText.getSpanStart(newSpan) + || currentText.getSpanEnd(currentSpan) != newText.getSpanEnd(newSpan) + || currentText.getSpanFlags(currentSpan) != newText.getSpanFlags(newSpan)) { + return false; + } + } + return true; + } + /** * Scrolls the omnibox text to a position determined by the call to * {@link UrlBarDelegate#getScrollType}. @@ -957,43 +982,6 @@ } } - /** - * Emphasize components of the URL for readability. - */ - public void emphasizeUrl() { - if (hasFocus()) return; - - if (mUrlBarDelegate != null && !mUrlBarDelegate.shouldEmphasizeUrl()) return; - - Editable url = getText(); - if (url.length() < 1) return; - - Tab currentTab = mUrlBarDelegate.getCurrentTab(); - if (currentTab == null || currentTab.getProfile() == null) return; - - boolean isInternalPage = false; - try { - String tabUrl = currentTab.getUrl(); - isInternalPage = UrlUtilities.isInternalScheme(new URI(tabUrl)); - } catch (URISyntaxException e) { - // Ignore as this only is for applying color - } - - // Since we emphasize the scheme of the URL based on the security type, we need to - // deEmphasize first to refresh. - deEmphasizeUrl(); - OmniboxUrlEmphasizer.emphasizeUrl(url, getResources(), currentTab.getProfile(), - currentTab.getSecurityLevel(), isInternalPage, - mUseDarkColors, mUrlBarDelegate.shouldEmphasizeHttpsScheme()); - } - - /** - * Reset the modifications done to emphasize components of the URL. - */ - public void deEmphasizeUrl() { - OmniboxUrlEmphasizer.deEmphasizeUrl(getText()); - } - @Override public CharSequence getAccessibilityClassName() { // When UrlBar is used as a read-only TextView, force Talkback to pronounce it like
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarData.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarData.java index 00a354a..64a800c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarData.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarData.java
@@ -7,6 +7,8 @@ import android.net.Uri; import android.os.Build; import android.support.annotation.Nullable; +import android.text.Spannable; +import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.TextUtils; @@ -58,18 +60,26 @@ } public static UrlBarData forUrlAndText( - String url, String displayText, @Nullable String editingText) { - int pathSearchOffset = 0; - String scheme = Uri.parse(displayText).getScheme(); - + String url, CharSequence displayText, @Nullable String editingText) { // Because Android versions 4.2 and before lack proper RTL support, // force the formatted URL to render as LTR using an LRM character. // See: https://www.ietf.org/rfc/rfc3987.txt and https://crbug.com/709417 if (displayText.length() > 0 && Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN_MR1 && displayText.charAt(0) != LRM) { - displayText = LRM + displayText; + if (displayText instanceof String) { + displayText = LRM + (String) displayText; + } else if (displayText instanceof Spannable) { + displayText = + new SpannableStringBuilder(displayText).insert(0, Character.toString(LRM)); + } else { + assert false : "Unsupported CharSequence type for display text"; + } } + int pathSearchOffset = 0; + String displayTextStr = displayText.toString(); + String scheme = Uri.parse(displayTextStr).getScheme(); + if (!TextUtils.isEmpty(scheme)) { if (UNSUPPORTED_SCHEMES_TO_SPLIT.contains(scheme)) { return create(url, displayText, 0, displayText.length(), editingText); @@ -84,14 +94,14 @@ } int pathOffset = -1; if (pathSearchOffset < displayText.length()) { - pathOffset = displayText.indexOf('/', pathSearchOffset); + pathOffset = displayTextStr.indexOf('/', pathSearchOffset); } if (pathOffset == -1) return create(url, displayText, 0, displayText.length(), editingText); // If the '/' is the last character and the beginning of the path, then just drop // the path entirely. if (pathOffset == displayText.length() - 1) { - String prePathText = displayText.substring(0, pathOffset); + String prePathText = displayTextStr.substring(0, pathOffset); return create(url, prePathText, 0, prePathText.length(), editingText); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/CustomTabToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/CustomTabToolbar.java index 3b70b06..82bca637 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/CustomTabToolbar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/CustomTabToolbar.java
@@ -276,20 +276,6 @@ } @Override - public boolean shouldEmphasizeUrl() { - // If the toolbar shows the publisher URL, it applies its own formatting for emphasis. - Tab currentTab = getCurrentTab(); - if (currentTab == null) return true; - - return currentTab.getTrustedCdnPublisherUrl() == null; - } - - @Override - public boolean shouldEmphasizeHttpsScheme() { - return !mToolbarDataProvider.isUsingBrandColor(); - } - - @Override public boolean shouldCutCopyVerbatim() { return false; } @@ -440,9 +426,7 @@ originEnd = displayText.length(); } - if (mUrlBar.setUrl(UrlBarData.create(url, displayText, originStart, originEnd, url))) { - mUrlBar.emphasizeUrl(); - } + mUrlBar.setUrl(UrlBarData.create(url, displayText, originStart, originEnd, url)); } @Override @@ -466,7 +450,9 @@ Resources resources = getResources(); updateSecurityIcon(); updateButtonsTint(); - mUrlBar.setUseDarkTextColors(mUseDarkColors); + if (mUrlBar.setUseDarkTextColors(mUseDarkColors)) { + setUrlToPageUrl(); + } int titleTextColor = mUseDarkColors ? ApiCompatibilityUtils.getColor(resources, R.color.url_emphasis_default_text) @@ -537,7 +523,7 @@ mAnimDelegate.showSecurityButton(); } - mUrlBar.emphasizeUrl(); + setUrlToPageUrl(); mUrlBar.invalidate(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java index 3bd03e5..7c5987b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -837,6 +837,11 @@ return mBookmarkBridge; } + /** Return the toolbar model for testing purposes. */ + public ToolbarModel getToolbarModelForTesting() { + return mToolbarModel; + } + /** * @return The toolbar interface that this manager handles. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarModel.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarModel.java index 0f0c37a..cbba5fcd 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarModel.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarModel.java
@@ -9,6 +9,7 @@ import android.support.annotation.DrawableRes; import android.support.annotation.Nullable; import android.support.v7.content.res.AppCompatResources; +import android.text.SpannableStringBuilder; import android.text.TextUtils; import org.chromium.base.ContextUtils; @@ -25,11 +26,13 @@ import org.chromium.chrome.browser.ntp.NewTabPage; import org.chromium.chrome.browser.offlinepages.OfflinePageUtils; import org.chromium.chrome.browser.omnibox.AutocompleteController; +import org.chromium.chrome.browser.omnibox.OmniboxUrlEmphasizer; import org.chromium.chrome.browser.omnibox.UrlBarData; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.search_engines.TemplateUrlService; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.util.ColorUtils; +import org.chromium.chrome.browser.util.UrlUtilities; import org.chromium.chrome.browser.widget.bottomsheet.BottomSheet; import org.chromium.components.dom_distiller.core.DomDistillerService; import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils; @@ -37,6 +40,7 @@ import org.chromium.content_public.browser.WebContents; import java.net.URI; +import java.net.URISyntaxException; /** * Provides a way of accessing toolbar data and state. @@ -155,7 +159,7 @@ } String formattedUrl = getFormattedFullUrl(); - if (mTab.isFrozen()) return UrlBarData.forUrlAndText(url, formattedUrl); + if (mTab.isFrozen()) return buildUrlBarData(url, formattedUrl); if (DomDistillerUrlUtils.isDistilledPage(url)) { DomDistillerService domDistillerService = @@ -164,16 +168,16 @@ if (!TextUtils.isEmpty(entryIdFromUrl) && domDistillerService.hasEntry(entryIdFromUrl)) { String originalUrl = domDistillerService.getUrlForEntry(entryIdFromUrl); - return UrlBarData.forUrl( + return buildUrlBarData( DomDistillerTabUtils.getFormattedUrlFromOriginalDistillerUrl(originalUrl)); } String originalUrl = DomDistillerUrlUtils.getOriginalUrlFromDistillerUrl(url); if (originalUrl != null) { - return UrlBarData.forUrl( + return buildUrlBarData( DomDistillerTabUtils.getFormattedUrlFromOriginalDistillerUrl(originalUrl)); } - return UrlBarData.forUrlAndText(url, formattedUrl); + return buildUrlBarData(url, formattedUrl); } if (isOfflinePage()) { @@ -183,26 +187,84 @@ // Clear the editing text for untrusted offline pages. if (!OfflinePageUtils.isShowingTrustedOfflinePage(mTab)) { - return UrlBarData.forUrlAndText(url, formattedUrl, ""); + return buildUrlBarData(url, formattedUrl, ""); } - return UrlBarData.forUrlAndText(url, formattedUrl); + return buildUrlBarData(url, formattedUrl); } if (shouldDisplaySearchTerms()) { // Show the search terms in the omnibox instead of the URL if this is a DSE search URL. - return UrlBarData.forUrlAndText(url, getDisplaySearchTerms()); + return buildUrlBarData(url, getDisplaySearchTerms()); } if (ChromeFeatureList.isEnabled( ChromeFeatureList.OMNIBOX_HIDE_SCHEME_DOMAIN_IN_STEADY_STATE)) { String urlForDisplay = getUrlForDisplay(); if (!urlForDisplay.equals(formattedUrl)) { - return UrlBarData.forUrlAndText(url, urlForDisplay, formattedUrl); + return buildUrlBarData(url, urlForDisplay, formattedUrl); } } - return UrlBarData.forUrlAndText(url, formattedUrl); + return buildUrlBarData(url, formattedUrl); + } + + private UrlBarData buildUrlBarData(String url) { + return buildUrlBarData(url, url, url); + } + + private UrlBarData buildUrlBarData(String url, String displayText) { + return buildUrlBarData(url, displayText, displayText); + } + + private UrlBarData buildUrlBarData(String url, String displayText, String editingText) { + SpannableStringBuilder spannableDisplayText = new SpannableStringBuilder(displayText); + + if (mNativeToolbarModelAndroid != 0 && spannableDisplayText.length() > 0 + && shouldEmphasizeUrl()) { + boolean isInternalPage = false; + try { + isInternalPage = UrlUtilities.isInternalScheme(new URI(url)); + } catch (URISyntaxException e) { + // Ignore as this only is for applying color + } + + OmniboxUrlEmphasizer.emphasizeUrl(spannableDisplayText, mContext.getResources(), + getProfile(), getSecurityLevel(), isInternalPage, shouldUseDarkUrlColors(), + shouldEmphasizeHttpsScheme()); + } + + return UrlBarData.forUrlAndText(url, spannableDisplayText, editingText); + } + + /** + * @return True if the displayed URL should be emphasized, false if the displayed text + * already has formatting for emphasis applied. + */ + private boolean shouldEmphasizeUrl() { + // If the toolbar shows the publisher URL, it applies its own formatting for emphasis. + if (mTab == null) return true; + + return !shouldDisplaySearchTerms() && mTab.getTrustedCdnPublisherUrl() == null; + } + + /** + * @return Whether the light security theme should be used. + */ + @VisibleForTesting + public boolean shouldEmphasizeHttpsScheme() { + return !isUsingBrandColor() && !isIncognito(); + } + + private boolean shouldUseDarkUrlColors() { + boolean brandColorNeedsLightText = false; + if (isUsingBrandColor()) { + int currentPrimaryColor = getPrimaryColor(); + brandColorNeedsLightText = + ColorUtils.shouldUseLightForegroundOnBackground(currentPrimaryColor); + } + + return !isIncognito() && (!hasTab() || !brandColorNeedsLightText); } @Override
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni index 96fe313a..4450c90 100644 --- a/chrome/android/java_sources.gni +++ b/chrome/android/java_sources.gni
@@ -448,6 +448,7 @@ "java/src/org/chromium/chrome/browser/download/home/filter/Filters.java", "java/src/org/chromium/chrome/browser/download/home/filter/FilterChipsProvider.java", "java/src/org/chromium/chrome/browser/download/home/filter/FilterCoordinator.java", + "java/src/org/chromium/chrome/browser/download/home/filter/FilterCoordinatorWithNoTabs.java", "java/src/org/chromium/chrome/browser/download/home/filter/FilterModel.java", "java/src/org/chromium/chrome/browser/download/home/filter/FilterView.java", "java/src/org/chromium/chrome/browser/download/home/filter/FilterViewBinder.java", @@ -723,8 +724,8 @@ "java/src/org/chromium/chrome/browser/media/router/ChromeMediaRouterDialogController.java", "java/src/org/chromium/chrome/browser/media/router/DiscoveryCallback.java", "java/src/org/chromium/chrome/browser/media/router/DiscoveryDelegate.java", + "java/src/org/chromium/chrome/browser/media/router/FlingingControllerBridge.java", "java/src/org/chromium/chrome/browser/media/router/MediaController.java", - "java/src/org/chromium/chrome/browser/media/router/MediaControllerBridge.java", "java/src/org/chromium/chrome/browser/media/router/MediaRoute.java", "java/src/org/chromium/chrome/browser/media/router/MediaRouteChooserDialogManager.java", "java/src/org/chromium/chrome/browser/media/router/MediaRouteControllerDialogManager.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java index 3b7392e..c09f825 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
@@ -893,7 +893,10 @@ "A custom tab toolbar is never shown", toolbarView instanceof CustomTabToolbar); CustomTabToolbar toolbar = (CustomTabToolbar) toolbarView; Assert.assertEquals(expectedColor, toolbar.getBackground().getColor()); - Assert.assertFalse(toolbar.shouldEmphasizeHttpsScheme()); + Assert.assertFalse(mCustomTabActivityTestRule.getActivity() + .getToolbarManager() + .getToolbarModelForTesting() + .shouldEmphasizeHttpsScheme()); if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) { Assert.assertEquals(ColorUtils.getDarkenedColorForStatusBar(expectedColor), mCustomTabActivityTestRule.getActivity().getWindow().getStatusBarColor());
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/display_cutout/WebappDisplayCutoutTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/display_cutout/WebappDisplayCutoutTest.java index 37716b8..c5def2d 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/display_cutout/WebappDisplayCutoutTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/display_cutout/WebappDisplayCutoutTest.java
@@ -11,6 +11,7 @@ import org.junit.runner.RunWith; import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.FlakyTest; import org.chromium.blink_public.platform.WebDisplayMode; import org.chromium.chrome.browser.ChromeSwitches; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; @@ -31,6 +32,7 @@ */ @Test @LargeTest + @FlakyTest(message = "crbug.com/862728") @WebappDisplayCutoutTestRule.TestConfiguration(displayMode = WebDisplayMode.UNDEFINED) public void testViewportFitWebapp() throws InterruptedException, TimeoutException { mTestRule.setViewportFit(DisplayCutoutTestRule.VIEWPORT_FIT_COVER); @@ -45,6 +47,7 @@ */ @Test @LargeTest + @FlakyTest(message = "crbug.com/862728") @WebappDisplayCutoutTestRule.TestConfiguration(displayMode = WebDisplayMode.FULLSCREEN) public void testViewportFitWebapp_Fullscreen() throws InterruptedException, TimeoutException { mTestRule.setViewportFit(DisplayCutoutTestRule.VIEWPORT_FIT_COVER); @@ -60,6 +63,7 @@ */ @Test @LargeTest + @FlakyTest(message = "crbug.com/862728") @WebappDisplayCutoutTestRule.TestConfiguration(displayMode = WebDisplayMode.MINIMAL_UI) public void testViewportFitWebapp_MinimalUi() throws InterruptedException, TimeoutException { mTestRule.setViewportFit(DisplayCutoutTestRule.VIEWPORT_FIT_COVER); @@ -75,6 +79,7 @@ */ @Test @LargeTest + @FlakyTest(message = "crbug.com/862728") @WebappDisplayCutoutTestRule.TestConfiguration(displayMode = WebDisplayMode.STANDALONE) public void testViewportFitWebapp_Standalone() throws InterruptedException, TimeoutException { mTestRule.setViewportFit(DisplayCutoutTestRule.VIEWPORT_FIT_COVER);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/OmniboxTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/OmniboxTest.java index 09cfb003..f749e93 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/OmniboxTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/OmniboxTest.java
@@ -771,9 +771,15 @@ securityButton.getId()); if (mActivityTestRule.getActivity().isTablet()) { - Assert.assertTrue(locationBarLayout.shouldEmphasizeHttpsScheme()); + Assert.assertTrue(mActivityTestRule.getActivity() + .getToolbarManager() + .getToolbarModelForTesting() + .shouldEmphasizeHttpsScheme()); } else { - Assert.assertFalse(locationBarLayout.shouldEmphasizeHttpsScheme()); + Assert.assertFalse(mActivityTestRule.getActivity() + .getToolbarManager() + .getToolbarModelForTesting() + .shouldEmphasizeHttpsScheme()); } } finally { testServer.stopAndDestroyServer();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/ToolbarModelTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/ToolbarModelTest.java index 569f2af..b4197a5 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/ToolbarModelTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/ToolbarModelTest.java
@@ -78,12 +78,12 @@ model.mUrl = "chrome://about"; model.mDisplayUrl = "chrome://about"; model.mFullUrl = "chrome://about"; - assertDisplayAndEditText(model, "chrome://about", null); + assertDisplayAndEditText(model, "chrome://about", "chrome://about"); model.mUrl = "https://www.foo.com"; model.mDisplayUrl = "foo.com"; model.mFullUrl = "https://foo.com"; - assertDisplayAndEditText(model, "https://foo.com", null); + assertDisplayAndEditText(model, "https://foo.com", "https://foo.com"); }); } @@ -99,7 +99,7 @@ model.mUrl = "chrome://about"; model.mDisplayUrl = "chrome://about"; model.mFullUrl = "chrome://about"; - assertDisplayAndEditText(model, "chrome://about", null); + assertDisplayAndEditText(model, "chrome://about", "chrome://about"); model.mUrl = "https://www.foo.com"; model.mDisplayUrl = "foo.com";
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/feed/FeedContentStorageTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/feed/FeedContentStorageTest.java new file mode 100644 index 0000000..36ae6f4 --- /dev/null +++ b/chrome/android/junit/src/org/chromium/chrome/browser/feed/FeedContentStorageTest.java
@@ -0,0 +1,245 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.feed; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import android.support.test.filters.SmallTest; + +import com.google.android.libraries.feed.common.Result; +import com.google.android.libraries.feed.common.functional.Consumer; +import com.google.android.libraries.feed.host.storage.CommitResult; +import com.google.android.libraries.feed.host.storage.ContentMutation; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import org.robolectric.annotation.Config; + +import org.chromium.base.Callback; +import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.chrome.browser.profiles.Profile; + +import java.nio.charset.Charset; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Unit tests for {@link FeedContentStorage}. + */ +@RunWith(BaseRobolectricTestRunner.class) +@Config(manifest = Config.NONE) +public class FeedContentStorageTest { + public static final String CONTENT_KEY1 = "CONTENT_KEY_1"; + public static final String CONTENT_KEY2 = "CONTENT_KEY_2"; + public static final String CONTENT_KEY3 = "CONTENT_KEY_3"; + public static final byte[] CONTENT_DATA1 = "CONTENT_DATA_1".getBytes(Charset.forName("UTF-8")); + public static final byte[] CONTENT_DATA2 = "CONTENT_DATA_2".getBytes(Charset.forName("UTF-8")); + public static final byte[] CONTENT_DATA3 = "CONTENT_DATA_3".getBytes(Charset.forName("UTF-8")); + + @Mock + private FeedStorageBridge mBridge; + @Mock + private Consumer<CommitResult> mBooleanConsumer; + @Mock + private Consumer < Result < List<String>>> mListConsumer; + @Mock + private Consumer < Result < Map<String, byte[]>>> mMapConsumer; + @Mock + private Profile mProfile; + @Captor + private ArgumentCaptor<CommitResult> mCommitResultCaptor; + @Captor + private ArgumentCaptor < Result < List<String>>> mStringListCaptor; + @Captor + private ArgumentCaptor < Result < Map<String, byte[]>>> mMapCaptor; + @Captor + private ArgumentCaptor<String> mStringArgument; + @Captor + private ArgumentCaptor<List<String>> mStringListArgument; + @Captor + private ArgumentCaptor<String[]> mStringArrayArgument; + @Captor + private ArgumentCaptor<byte[][]> mByteArrayOfArrayArgument; + @Captor + private ArgumentCaptor<Callback<Boolean>> mBooleanCallbackArgument; + @Captor + private ArgumentCaptor < Callback < List<String>>> mStringListCallbackArgument; + @Captor + private ArgumentCaptor < Callback < Map<String, byte[]>>> mMapCallbackArgument; + + private FeedContentStorage mContentStorage; + + private Answer<Void> createMapAnswer(Map<String, byte[]> map) { + return new Answer<Void>() { + @Override + public Void answer(InvocationOnMock invocation) { + mMapCallbackArgument.getValue().onResult(map); + return null; + } + }; + } + + private Answer<Void> createStringListAnswer(List<String> stringList) { + return new Answer<Void>() { + @Override + public Void answer(InvocationOnMock invocation) { + mStringListCallbackArgument.getValue().onResult(stringList); + return null; + } + }; + } + + private Answer<Void> createBooleanAnswer(Boolean bool) { + return new Answer<Void>() { + @Override + public Void answer(InvocationOnMock invocation) { + mBooleanCallbackArgument.getValue().onResult(bool); + return null; + } + }; + } + + private void verifyMapResult(Map<String, byte[]> expectedMap, boolean expectedBoolean, + Result<Map<String, byte[]>> actualResult) { + assertEquals(expectedBoolean, actualResult.isSuccessful()); + if (!expectedBoolean) return; + + Map<String, byte[]> actualMap = actualResult.getValue(); + assertEquals(expectedMap.size(), actualMap.size()); + for (Map.Entry<String, byte[]> entry : expectedMap.entrySet()) { + assertTrue(actualMap.containsKey(entry.getKey())); + assertEquals(entry.getValue(), actualMap.get(entry.getKey())); + } + } + + private void verifyStringListResult( + List<String> expectedList, boolean expectedBoolean, Result<List<String>> actualResult) { + assertEquals(expectedBoolean, actualResult.isSuccessful()); + if (!expectedBoolean) return; + + List<String> actualList = actualResult.getValue(); + assertEquals(expectedList.size(), actualList.size()); + for (String expectedString : expectedList) { + assertTrue(actualList.contains(expectedString)); + } + } + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + doNothing().when(mBridge).init(eq(mProfile)); + mBridge.init(mProfile); + mContentStorage = new FeedContentStorage(mBridge); + } + + @Test + @SmallTest + public void getTest() { + Map<String, byte[]> answerMap = new HashMap<>(); + answerMap.put(CONTENT_KEY1, CONTENT_DATA1); + Answer<Void> answer = createMapAnswer(answerMap); + doAnswer(answer).when(mBridge).loadContent( + mStringListArgument.capture(), mMapCallbackArgument.capture()); + List<String> keys = Arrays.asList(CONTENT_KEY1, CONTENT_KEY2); + + mContentStorage.get(keys, mMapConsumer); + verify(mBridge, times(1)).loadContent(eq(keys), mMapCallbackArgument.capture()); + verify(mMapConsumer, times(1)).accept(mMapCaptor.capture()); + verifyMapResult(answerMap, true, mMapCaptor.getValue()); + } + + @Test + @SmallTest + public void getAllTest() { + Map<String, byte[]> answerMap = new HashMap<>(); + answerMap.put(CONTENT_KEY1, CONTENT_DATA1); + answerMap.put(CONTENT_KEY2, CONTENT_DATA2); + answerMap.put(CONTENT_KEY3, CONTENT_DATA3); + Answer<Void> answer = createMapAnswer(answerMap); + doAnswer(answer).when(mBridge).loadContentByPrefix( + mStringArgument.capture(), mMapCallbackArgument.capture()); + + mContentStorage.getAll(CONTENT_KEY1, mMapConsumer); + verify(mBridge, times(1)) + .loadContentByPrefix(eq(CONTENT_KEY1), mMapCallbackArgument.capture()); + verify(mMapConsumer, times(1)).accept(mMapCaptor.capture()); + verifyMapResult(answerMap, true, mMapCaptor.getValue()); + } + + @Test + @SmallTest + public void getAllKeysTest() { + List<String> answerStrings = Arrays.asList(CONTENT_KEY1, CONTENT_KEY2, CONTENT_KEY3); + Answer<Void> answer = createStringListAnswer(answerStrings); + doAnswer(answer).when(mBridge).loadAllContentKeys(mStringListCallbackArgument.capture()); + + mContentStorage.getAllKeys(mListConsumer); + verify(mBridge, times(1)).loadAllContentKeys(mStringListCallbackArgument.capture()); + verify(mListConsumer, times(1)).accept(mStringListCaptor.capture()); + verifyStringListResult(answerStrings, true, mStringListCaptor.getValue()); + } + + @Test + @SmallTest + public void commitTest() { + Answer<Void> answerSaveContent = createBooleanAnswer(true); + doAnswer(answerSaveContent) + .when(mBridge) + .saveContent(mStringArrayArgument.capture(), mByteArrayOfArrayArgument.capture(), + mBooleanCallbackArgument.capture()); + + Answer<Void> answerDeleteContent = createBooleanAnswer(true); + doAnswer(answerDeleteContent) + .when(mBridge) + .deleteContent(mStringListArgument.capture(), mBooleanCallbackArgument.capture()); + + Answer<Void> answerDeleteContentByPrefix = createBooleanAnswer(true); + doAnswer(answerDeleteContentByPrefix) + .when(mBridge) + .deleteContentByPrefix( + mStringArgument.capture(), mBooleanCallbackArgument.capture()); + + Answer<Void> answerDeleteAllContent = createBooleanAnswer(true); + doAnswer(answerDeleteAllContent) + .when(mBridge) + .deleteAllContent(mBooleanCallbackArgument.capture()); + + mContentStorage.commit(new ContentMutation.Builder() + .upsert(CONTENT_KEY1, CONTENT_DATA1) + .delete(CONTENT_KEY2) + .deleteByPrefix(CONTENT_KEY3) + .deleteAll() + .build(), + mBooleanConsumer); + verify(mBridge, times(1)) + .saveContent(mStringArrayArgument.capture(), mByteArrayOfArrayArgument.capture(), + mBooleanCallbackArgument.capture()); + verify(mBridge, times(1)) + .deleteContent(mStringListArgument.capture(), mBooleanCallbackArgument.capture()); + verify(mBridge, times(1)) + .deleteContentByPrefix( + mStringArgument.capture(), mBooleanCallbackArgument.capture()); + verify(mBridge, times(1)).deleteAllContent(mBooleanCallbackArgument.capture()); + + verify(mBooleanConsumer, times(1)).accept(mCommitResultCaptor.capture()); + CommitResult commitResult = mCommitResultCaptor.getValue(); + assertEquals(CommitResult.SUCCESS, commitResult); + } +}
diff --git a/chrome/android/webapk/libs/client/src/org/chromium/webapk/lib/client/WebApkValidator.java b/chrome/android/webapk/libs/client/src/org/chromium/webapk/lib/client/WebApkValidator.java index 4661351..0ddbe20b 100644 --- a/chrome/android/webapk/libs/client/src/org/chromium/webapk/lib/client/WebApkValidator.java +++ b/chrome/android/webapk/libs/client/src/org/chromium/webapk/lib/client/WebApkValidator.java
@@ -58,9 +58,8 @@ * @return Package name of WebAPK which can handle the URL. Null if the url should not be * handled by a WebAPK. */ - public static String queryWebApkPackage(Context context, String url) { - return findWebApkPackage( - context, resolveInfosForUrlAndOptionalPackage(context, url, null /* package*/)); + public static @Nullable String queryWebApkPackage(Context context, String url) { + return findWebApkPackage(context, resolveInfosForUrl(context, url)); } /** @@ -75,25 +74,31 @@ * @return Resolve Info of a WebAPK which can handle the URL. Null if the url should not be * handled by a WebAPK. */ - public static ResolveInfo queryResolveInfo(Context context, String url) { - return findResolveInfo( - context, resolveInfosForUrlAndOptionalPackage(context, url, null /* package */)); + public static @Nullable ResolveInfo queryWebApkResolveInfo(Context context, String url) { + return findWebApkResolveInfo(context, resolveInfosForUrl(context, url)); } /** * @param context The context to use to check whether WebAPK is valid. - * @param infos The ResolveInfos to search. - * @return Package name of the ResolveInfo which corresponds to a WebAPK. Null if none of the - * ResolveInfos corresponds to a WebAPK. + * @param infos The {@link ResolveInfo}s to search. + * @return Package name of the {@link ResolveInfo} which corresponds to a WebAPK. Null if none + * of the {@link ResolveInfo}s corresponds to a WebAPK. */ - public static String findWebApkPackage(Context context, List<ResolveInfo> infos) { - ResolveInfo resolveInfo = findResolveInfo(context, infos); + public static @Nullable String findWebApkPackage(Context context, List<ResolveInfo> infos) { + ResolveInfo resolveInfo = findWebApkResolveInfo(context, infos); if (resolveInfo != null) { return resolveInfo.activityInfo.packageName; } return null; } + /** + * Whether the given package corresponds to a WebAPK that can handle the URL. + * @param context The application context. + * @param webApkPackage The package to consider. + * @param url The URL the package must be able to handle. + * @return Whether the URL can be handled by that package. + */ public static boolean canWebApkHandleUrl(Context context, String webApkPackage, String url) { List<ResolveInfo> infos = resolveInfosForUrlAndOptionalPackage(context, url, webApkPackage); for (ResolveInfo info : infos) { @@ -106,12 +111,22 @@ } /** - * Fetches the list of resolve infos from the PackageManager that can handle the URL. + * Fetches a list of {@link ResolveInfo}s from the PackageManager that can handle the URL. + * @param context The application context. + * @param url The URL to check. + * @return The list of {@link ResolveInfo}s found that can handle the URL. + */ + public static List<ResolveInfo> resolveInfosForUrl(Context context, String url) { + return resolveInfosForUrlAndOptionalPackage(context, url, null); + } + + /** + * Fetches the list of {@link ResolveInfo}s from the PackageManager that can handle the URL. * * @param context The application context. - * @param url The url to check. + * @param url The URL to check. * @param applicationPackage The optional package name to set for intent resolution. - * @return The list of resolve infos found that can handle the URL. + * @return The list of {@link ResolveInfo}s found that can handle the URL. */ private static List<ResolveInfo> resolveInfosForUrlAndOptionalPackage( Context context, String url, @Nullable String applicationPackage) { @@ -133,7 +148,6 @@ selector.addCategory(Intent.CATEGORY_BROWSABLE); selector.setComponent(null); } - List<ResolveInfo> resolveInfoList; // StrictMode is relaxed due to https://crbug.com/843092. StrictMode.ThreadPolicy policy = StrictMode.allowThreadDiskReads(); @@ -151,12 +165,14 @@ } /** + * Searches the given {@link ResolveInfo}s for one corresponding to a WebAPK. * @param context The context to use to check whether WebAPK is valid. - * @param infos The ResolveInfos to search. - * @return ResolveInfo which corresponds to a WebAPK. Null if none of the ResolveInfos + * @param infos The {@link ResolveInfo}s to search. + * @return {@link ResolveInfo} which corresponds to a WebAPK. Null if none of the ResolveInfos * corresponds to a WebAPK. */ - private static ResolveInfo findResolveInfo(Context context, List<ResolveInfo> infos) { + private static @Nullable ResolveInfo findWebApkResolveInfo( + Context context, List<ResolveInfo> infos) { for (ResolveInfo info : infos) { if (info.activityInfo != null && isValidWebApk(context, info.activityInfo.packageName)) { @@ -179,7 +195,7 @@ + "missing call to WebApkValidator.initWithBrowserHostSignature"); return false; } - PackageInfo packageInfo = null; + PackageInfo packageInfo; try { packageInfo = context.getPackageManager().getPackageInfo(webappPackageName, PackageManager.GET_SIGNATURES | PackageManager.GET_META_DATA); @@ -202,7 +218,7 @@ Log.d(TAG, "Matches Maps Lite"); return true; } - return verifyCommentSignedWebApk(packageInfo, webappPackageName); + return verifyCommentSignedWebApk(packageInfo); } /** Determine quickly whether this is definitely not a WebAPK */ @@ -231,8 +247,7 @@ } private static boolean verifyMapsLite(PackageInfo packageInfo, String webappPackageName) { - if (packageInfo.signatures == null || webappPackageName == null - || !webappPackageName.equals(MAPSLITE_PACKAGE_NAME)) { + if (!webappPackageName.equals(MAPSLITE_PACKAGE_NAME)) { return false; } String startUrl = packageInfo.applicationInfo.metaData.getString(START_URL); @@ -249,8 +264,7 @@ } /** Verify that the comment signed webapk matches the public key. */ - private static boolean verifyCommentSignedWebApk( - PackageInfo packageInfo, String webappPackageName) { + private static boolean verifyCommentSignedWebApk(PackageInfo packageInfo) { PublicKey commentSignedPublicKey; try { commentSignedPublicKey = getCommentSignedPublicKey();
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp index 10d2a26..643d715 100644 --- a/chrome/app/chromeos_strings.grdp +++ b/chrome/app/chromeos_strings.grdp
@@ -50,8 +50,8 @@ <message name="IDS_WALLPAPER_MANAGER_ACCESS_FAIL" desc="The string displayed to user when access wallpaper server failed."> Chrome cannot access wallpapers. Please connect to a network. </message> - <message name="IDS_WALLPAPER_MANAGER_NETWORK_ERROR" desc="The string displayed to user when access wallpaper server failed on the new wallpaper picker."> - The images are currently not available. Please reconnect to view the collections. + <message name="IDS_WALLPAPER_MANAGER_NETWORK_ERROR" desc="The string displayed when user can't use wallpaper picker because they're not connected to the internet."> + The images are currently not available. Please reconnect to the internet to see wallpaper collections. </message> <message name="IDS_WALLPAPER_MANAGER_DOWNLOAD_FAIL" desc="The string displayed to user when downloading the wallpaper failed."> Chrome cannot download this wallpaper.
diff --git a/chrome/app/md_extensions_strings.grdp b/chrome/app/md_extensions_strings.grdp index 997f5960..f091fb4 100644 --- a/chrome/app/md_extensions_strings.grdp +++ b/chrome/app/md_extensions_strings.grdp
@@ -264,6 +264,15 @@ <message name="IDS_MD_EXTENSIONS_APPS_TITLE" desc="The text displayed in the sidebar to go to the apps section of the page."> Chrome Apps </message> + <message name="IDS_MD_EXTENSIONS_RUNTIME_HOSTS_DIALOG_TITLE" desc="The title of the dialog used to allow a user to add a new site that an extension is allowed to run on."> + Add a site + </message> + <message name="IDS_MD_EXTENSIONS_RUNTIME_HOSTS_DIALOG_INPUT_ERROR" desc="The error message shown to the user when they entered an invalid site address into the input field."> + Not a valid web address + </message> + <message name="IDS_MD_EXTENSIONS_RUNTIME_HOSTS_DIALOG_INPUT_LABEL" desc="The label for the input field where a user enters a new site for an extension to run on."> + Site + </message> <message name="IDS_MD_EXTENSIONS_SIDEBAR_EXTENSIONS" desc="The text displayed in the sidebar to go to the extensions section of the page."> Extensions </message>
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index dbbba00..2c01bbb9 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -697,8 +697,6 @@ "media/webrtc/desktop_media_list_base.h", "media/webrtc/desktop_media_picker.cc", "media/webrtc/desktop_media_picker.h", - "media/webrtc/desktop_streams_registry.cc", - "media/webrtc/desktop_streams_registry.h", "media/webrtc/media_capture_devices_dispatcher.cc", "media/webrtc/media_capture_devices_dispatcher.h", "media/webrtc/media_stream_capture_indicator.cc", @@ -1803,7 +1801,6 @@ "//components/translate/core/browser", "//components/translate/core/common", "//components/ukm:observers", - "//components/ukm/content/debug_page", "//components/undo", "//components/unified_consent", "//components/update_client", @@ -2338,8 +2335,8 @@ "media/android/cdm/media_drm_license_manager.h", "media/android/cdm/media_drm_storage_factory.cc", "media/android/cdm/media_drm_storage_factory.h", - "media/android/remote/media_controller_bridge.cc", - "media/android/remote/media_controller_bridge.h", + "media/android/remote/flinging_controller_bridge.cc", + "media/android/remote/flinging_controller_bridge.h", "media/android/remote/record_cast_action.cc", "media/android/remote/remote_media_player_bridge.cc", "media/android/remote/remote_media_player_bridge.h", @@ -4334,6 +4331,8 @@ "android/feed/feed_network_bridge.h", "android/feed/feed_scheduler_bridge.cc", "android/feed/feed_scheduler_bridge.h", + "android/feed/feed_storage_bridge.cc", + "android/feed/feed_storage_bridge.h", ] deps += [ "//components/feed/core:feed_core" ] } @@ -4475,7 +4474,7 @@ "../android/java/src/org/chromium/chrome/browser/media/remote/RemoteMediaPlayerBridge.java", "../android/java/src/org/chromium/chrome/browser/media/router/ChromeMediaRouter.java", "../android/java/src/org/chromium/chrome/browser/media/router/ChromeMediaRouterDialogController.java", - "../android/java/src/org/chromium/chrome/browser/media/router/MediaControllerBridge.java", + "../android/java/src/org/chromium/chrome/browser/media/router/FlingingControllerBridge.java", "../android/java/src/org/chromium/chrome/browser/metrics/LaunchMetrics.java", "../android/java/src/org/chromium/chrome/browser/metrics/PageLoadMetrics.java", "../android/java/src/org/chromium/chrome/browser/metrics/UmaSessionStats.java", @@ -4595,6 +4594,7 @@ "../android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedImageLoaderBridge.java", "../android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNetworkBridge.java", "../android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSchedulerBridge.java", + "../android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedStorageBridge.java", ] }
diff --git a/chrome/browser/android/feed/feed_storage_bridge.cc b/chrome/browser/android/feed/feed_storage_bridge.cc new file mode 100644 index 0000000..3393ad2 --- /dev/null +++ b/chrome/browser/android/feed/feed_storage_bridge.cc
@@ -0,0 +1,198 @@ +// 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/android/feed/feed_storage_bridge.h" + +#include <jni.h> + +#include <string> +#include <vector> + +#include "base/android/callback_android.h" +#include "base/android/jni_array.h" +#include "base/android/jni_string.h" +#include "base/bind.h" +#include "base/threading/thread_task_runner_handle.h" +#include "chrome/browser/android/feed/feed_host_service_factory.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/profiles/profile_android.h" +#include "components/feed/core/feed_host_service.h" +#include "components/feed/core/feed_storage_database.h" +#include "jni/FeedStorageBridge_jni.h" +#include "ui/gfx/android/java_bitmap.h" +#include "ui/gfx/image/image.h" + +namespace feed { + +using base::android::AppendJavaStringArrayToStringVector; +using base::android::AttachCurrentThread; +using base::android::ConvertJavaStringToUTF8; +using base::android::JavaArrayOfByteArrayToStringVector; +using base::android::JavaIntArrayToIntVector; +using base::android::JavaRef; +using base::android::JavaParamRef; +using base::android::ScopedJavaGlobalRef; +using base::android::ScopedJavaLocalRef; +using base::android::ToJavaArrayOfByteArray; +using base::android::ToJavaArrayOfStrings; + +static jlong JNI_FeedStorageBridge_Init( + JNIEnv* env, + const JavaParamRef<jobject>& j_this, + const JavaParamRef<jobject>& j_profile) { + Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile); + FeedHostService* host_service = + FeedHostServiceFactory::GetForBrowserContext(profile); + DCHECK(host_service); + FeedStorageDatabase* feed_storage_database = + host_service->GetStorageDatabase(); + DCHECK(feed_storage_database); + FeedStorageBridge* native_storage_bridge = + new FeedStorageBridge(feed_storage_database); + return reinterpret_cast<intptr_t>(native_storage_bridge); +} + +FeedStorageBridge::FeedStorageBridge(FeedStorageDatabase* feed_storage_database) + : feed_storage_database_(feed_storage_database), weak_ptr_factory_(this) {} + +FeedStorageBridge::~FeedStorageBridge() = default; + +void FeedStorageBridge::Destroy(JNIEnv* env, const JavaRef<jobject>& j_this) { + delete this; +} + +void FeedStorageBridge::LoadContent(JNIEnv* j_env, + const JavaRef<jobject>& j_this, + const JavaRef<jobjectArray>& j_keys, + const JavaRef<jobject>& j_callback) { + std::vector<std::string> keys; + AppendJavaStringArrayToStringVector(j_env, j_keys.obj(), &keys); + ScopedJavaGlobalRef<jobject> callback(j_callback); + + feed_storage_database_->LoadContent( + keys, base::BindOnce(&FeedStorageBridge::OnLoadContentDone, + weak_ptr_factory_.GetWeakPtr(), callback)); +} + +void FeedStorageBridge::LoadContentByPrefix( + JNIEnv* j_env, + const JavaRef<jobject>& j_this, + const JavaRef<jstring>& j_prefix, + const JavaRef<jobject>& j_callback) { + std::string prefix = ConvertJavaStringToUTF8(j_env, j_prefix); + ScopedJavaGlobalRef<jobject> callback(j_callback); + + feed_storage_database_->LoadContentByPrefix( + prefix, base::BindOnce(&FeedStorageBridge::OnLoadContentDone, + weak_ptr_factory_.GetWeakPtr(), callback)); +} + +void FeedStorageBridge::LoadAllContentKeys(JNIEnv* j_env, + const JavaRef<jobject>& j_this, + const JavaRef<jobject>& j_callback) { + ScopedJavaGlobalRef<jobject> callback(j_callback); + + feed_storage_database_->LoadAllContentKeys( + base::BindOnce(&FeedStorageBridge::OnLoadAllContentKeysDone, + weak_ptr_factory_.GetWeakPtr(), callback)); +} + +void FeedStorageBridge::SaveContent(JNIEnv* j_env, + const JavaRef<jobject>& j_this, + const JavaRef<jobjectArray>& j_keys, + const JavaRef<jobjectArray>& j_data, + const JavaRef<jobject>& j_callback) { + std::vector<std::string> keys; + std::vector<std::string> data; + AppendJavaStringArrayToStringVector(j_env, j_keys.obj(), &keys); + JavaArrayOfByteArrayToStringVector(j_env, j_data.obj(), &data); + ScopedJavaGlobalRef<jobject> callback(j_callback); + + DCHECK_EQ(keys.size(), data.size()); + std::vector<FeedStorageDatabase::KeyAndData> pairs; + for (size_t i = 0; i < keys.size() && i < data.size(); ++i) { + pairs.emplace_back(keys[i], data[i]); + } + + feed_storage_database_->SaveContent( + std::move(pairs), + base::BindOnce(&FeedStorageBridge::OnStorageCommitDone, + weak_ptr_factory_.GetWeakPtr(), callback)); +} + +void FeedStorageBridge::DeleteContent(JNIEnv* j_env, + const JavaRef<jobject>& j_this, + const JavaRef<jobjectArray>& j_keys, + const JavaRef<jobject>& j_callback) { + std::vector<std::string> keys; + AppendJavaStringArrayToStringVector(j_env, j_keys.obj(), &keys); + ScopedJavaGlobalRef<jobject> callback(j_callback); + + feed_storage_database_->DeleteContent( + keys, base::BindOnce(&FeedStorageBridge::OnStorageCommitDone, + weak_ptr_factory_.GetWeakPtr(), callback)); +} + +void FeedStorageBridge::DeleteContentByPrefix( + JNIEnv* j_env, + const JavaRef<jobject>& j_this, + const JavaRef<jstring>& j_prefix, + const JavaRef<jobject>& j_callback) { + std::string prefix = ConvertJavaStringToUTF8(j_env, j_prefix); + ScopedJavaGlobalRef<jobject> callback(j_callback); + + feed_storage_database_->DeleteContentByPrefix( + prefix, base::BindOnce(&FeedStorageBridge::OnStorageCommitDone, + weak_ptr_factory_.GetWeakPtr(), callback)); +} + +void FeedStorageBridge::DeleteAllContent(JNIEnv* j_env, + const JavaRef<jobject>& j_this, + const JavaRef<jobject>& j_callback) { + ScopedJavaGlobalRef<jobject> callback(j_callback); + + feed_storage_database_->DeleteAllContent( + base::BindOnce(&FeedStorageBridge::OnStorageCommitDone, + weak_ptr_factory_.GetWeakPtr(), callback)); +} + +void FeedStorageBridge::OnLoadContentDone( + ScopedJavaGlobalRef<jobject> callback, + std::vector<FeedStorageDatabase::KeyAndData> pairs) { + std::vector<std::string> keys; + std::vector<std::string> data; + for (auto pair : pairs) { + keys.push_back(std::move(pair.first)); + data.push_back(std::move(pair.second)); + } + + JNIEnv* env = AttachCurrentThread(); + ScopedJavaLocalRef<jobjectArray> j_keys = ToJavaArrayOfStrings(env, keys); + ScopedJavaLocalRef<jobjectArray> j_data = ToJavaArrayOfByteArray(env, data); + + // Ceate Java Map by JNI call. + ScopedJavaLocalRef<jobject> j_pairs = + Java_FeedStorageBridge_createKeyAndDataMap(env, j_keys, j_data); + RunObjectCallbackAndroid(callback, j_pairs); +} + +void FeedStorageBridge::OnLoadAllContentKeysDone( + ScopedJavaGlobalRef<jobject> callback, + std::vector<std::string> keys) { + JNIEnv* env = AttachCurrentThread(); + ScopedJavaLocalRef<jobjectArray> j_keys = ToJavaArrayOfStrings(env, keys); + + // Ceate Java List by JNI call. + ScopedJavaLocalRef<jobject> j_keys_list = + Java_FeedStorageBridge_createJavaList(env, j_keys); + RunObjectCallbackAndroid(callback, j_keys_list); +} + +void FeedStorageBridge::OnStorageCommitDone( + ScopedJavaGlobalRef<jobject> callback, + bool success) { + RunBooleanCallbackAndroid(callback, success); +} + +} // namespace feed
diff --git a/chrome/browser/android/feed/feed_storage_bridge.h b/chrome/browser/android/feed/feed_storage_bridge.h new file mode 100644 index 0000000..19b7d8f --- /dev/null +++ b/chrome/browser/android/feed/feed_storage_bridge.h
@@ -0,0 +1,75 @@ +// 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_ANDROID_FEED_FEED_STORAGE_BRIDGE_H_ +#define CHROME_BROWSER_ANDROID_FEED_FEED_STORAGE_BRIDGE_H_ + +#include "base/android/scoped_java_ref.h" +#include "base/memory/weak_ptr.h" +#include "components/feed/core/feed_storage_database.h" + +namespace feed { + +class FeedStorageDatabase; + +// Native counterpart of FeedStorageBridge.java. Holds non-owning pointers +// to native implementation, to which operations are delegated. Results are +// passed back by a single argument callback so +// base::android::RunBooleanCallbackAndroid() and +// base::android::RunObjectCallbackAndroid() can be used. This bridge is +// instantiated, owned, and destroyed from Java. +class FeedStorageBridge { + public: + explicit FeedStorageBridge(FeedStorageDatabase* feed_Storage_database); + ~FeedStorageBridge(); + + void Destroy(JNIEnv* j_env, const base::android::JavaRef<jobject>& j_this); + + void LoadContent(JNIEnv* j_env, + const base::android::JavaRef<jobject>& j_this, + const base::android::JavaRef<jobjectArray>& j_keys, + const base::android::JavaRef<jobject>& j_callback); + void LoadContentByPrefix(JNIEnv* j_env, + const base::android::JavaRef<jobject>& j_this, + const base::android::JavaRef<jstring>& j_prefix, + const base::android::JavaRef<jobject>& j_callback); + void LoadAllContentKeys(JNIEnv* j_env, + const base::android::JavaRef<jobject>& j_this, + const base::android::JavaRef<jobject>& j_callback); + void SaveContent(JNIEnv* j_env, + const base::android::JavaRef<jobject>& j_this, + const base::android::JavaRef<jobjectArray>& j_keys, + const base::android::JavaRef<jobjectArray>& j_data, + const base::android::JavaRef<jobject>& j_callback); + void DeleteContent(JNIEnv* j_env, + const base::android::JavaRef<jobject>& j_this, + const base::android::JavaRef<jobjectArray>& j_keys, + const base::android::JavaRef<jobject>& j_callback); + void DeleteContentByPrefix(JNIEnv* j_env, + const base::android::JavaRef<jobject>& j_this, + const base::android::JavaRef<jstring>& j_prefix, + const base::android::JavaRef<jobject>& j_callback); + void DeleteAllContent(JNIEnv* j_env, + const base::android::JavaRef<jobject>& j_this, + const base::android::JavaRef<jobject>& j_callback); + + private: + void OnLoadContentDone(base::android::ScopedJavaGlobalRef<jobject> callback, + std::vector<FeedStorageDatabase::KeyAndData> pairs); + void OnLoadAllContentKeysDone( + base::android::ScopedJavaGlobalRef<jobject> callback, + std::vector<std::string> keys); + void OnStorageCommitDone(base::android::ScopedJavaGlobalRef<jobject> callback, + bool success); + + FeedStorageDatabase* feed_storage_database_; + + base::WeakPtrFactory<FeedStorageBridge> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(FeedStorageBridge); +}; + +} // namespace feed + +#endif // CHROME_BROWSER_ANDROID_FEED_FEED_STORAGE_BRIDGE_H_
diff --git a/chrome/browser/android/vr/arcore_device/ar_image_transport.cc b/chrome/browser/android/vr/arcore_device/ar_image_transport.cc index fc09e6f..a951fc6 100644 --- a/chrome/browser/android/vr/arcore_device/ar_image_transport.cc +++ b/chrome/browser/android/vr/arcore_device/ar_image_transport.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/android/vr/arcore_device/ar_image_transport.h" #include "base/android/android_hardware_buffer_compat.h" +#include "base/android/scoped_hardware_buffer_handle.h" #include "base/containers/queue.h" #include "base/trace_event/trace_event_argument.h" #include "chrome/browser/android/vr/mailbox_to_surface_bridge.h" @@ -122,9 +123,9 @@ auto img = base::MakeRefCounted<gl::GLImageAHardwareBuffer>(size); - AHardwareBuffer* ahb = - buffer->shared_gpu_memory_buffer->GetHandle().android_hardware_buffer; - bool ret = img->Initialize(ahb, false /* preserved */); + base::android::ScopedHardwareBufferHandle ahb = + buffer->shared_gpu_memory_buffer->CloneHandle().android_hardware_buffer; + bool ret = img->Initialize(ahb.get(), false /* preserved */); if (!ret) { DLOG(WARNING) << __FUNCTION__ << ": ERROR: failed to initialize image!"; return;
diff --git a/chrome/browser/android/vr/vr_controller.cc b/chrome/browser/android/vr/vr_controller.cc index d62b4ef..60e73ed3 100644 --- a/chrome/browser/android/vr/vr_controller.cc +++ b/chrome/browser/android/vr/vr_controller.cc
@@ -30,7 +30,7 @@ // being updated every frame on 3DOF devices. constexpr float kHeadOffsetDeadzone = 0.0005f; -void ClampTouchpadPosition(gfx::Vector2dF* position) { +void ClampTouchpadPosition(gfx::PointF* position) { position->set_x(base::ClampToRange(position->x(), 0.0f, 1.0f)); position->set_y(base::ClampToRange(position->y(), 0.0f, 1.0f)); } @@ -105,8 +105,7 @@ pad.timestamp = controller_state_->GetLastOrientationTimestamp(); if (pad.connected) { - pad.touch_pos.set_x(TouchPosX()); - pad.touch_pos.set_y(TouchPosY()); + pad.touch_pos = {GetPositionInTrackpad().x(), GetPositionInTrackpad().y()}; pad.orientation = Orientation(); // Use orientation to rotate acceleration/gyro into seated space. @@ -175,41 +174,37 @@ return state; } -bool VrController::IsTouching() { - return controller_state_->IsTouching(); -} - -float VrController::TouchPosX() { - return controller_state_->GetTouchPos().x; -} - -float VrController::TouchPosY() { - return controller_state_->GetTouchPos().y; -} - bool VrController::IsButtonDown(PlatformController::ButtonType type) const { return controller_state_->GetButtonState(PlatformToGvrButton(type)); } +bool VrController::IsTouchingTrackpad() const { + return controller_state_->IsTouching(); +} + +gfx::PointF VrController::GetPositionInTrackpad() const { + gfx::PointF position{controller_state_->GetTouchPos().x, + controller_state_->GetTouchPos().y}; + ClampTouchpadPosition(&position); + return position; +} + base::TimeTicks VrController::GetLastOrientationTimestamp() const { - // controller_state_->GetLast*Timestamp() returns timestamps in a - // different timebase from base::TimeTicks::Now(), so we can't use the - // timestamps in any meaningful way in the rest of Chrome. - // TODO(mthiesse): Use controller_state_->GetLastOrientationTimestamp() when - // b/62818778 is resolved. - return base::TimeTicks::Now(); + // TODO(crbug/866040): Use controller_state_->GetLastTouchTimestamp() when + // GVR is upgraded. + return last_orientation_timestamp_; } base::TimeTicks VrController::GetLastTouchTimestamp() const { - // TODO(mthiesse): Use controller_state_->GetLastTouchTimestamp() when - // b/62818778 is resolved. - return base::TimeTicks::Now(); + // TODO(crbug/866040): Use controller_state_->GetLastTouchTimestamp() when + // GVR is upgraded. + return last_touch_timestamp_; } base::TimeTicks VrController::GetLastButtonTimestamp() const { - // TODO(mthiesse): Use controller_state_->GetLastButtonTimestamp() when - // b/62818778 is resolved. - return base::TimeTicks::Now(); + // TODO(crbug/866040): Use controller_state_->GetLastButtonTimestamp() when + // GVR is upgraded. + return last_button_timestamp_; } PlatformController::Handedness VrController::GetHandedness() const { @@ -343,6 +338,7 @@ controller_state_->GetConnectionState()); } UpdateAlpha(); + UpdateTimestamps(); last_timestamp_nanos_ = gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos; } @@ -352,26 +348,26 @@ return std::make_unique<InputEventList>(); } - UpdateCurrentTouchInfo(); - return gesture_detector_->DetectGestures( - touch_info_, base::TimeTicks::Now(), - ButtonState(gvr::kControllerButtonClick)); + return gesture_detector_->DetectGestures(*this, base::TimeTicks::Now()); } -void VrController::UpdateCurrentTouchInfo() { - touch_info_.touch_up = TouchUpHappened(); - touch_info_.touch_down = TouchDownHappened(); - touch_info_.is_touching = IsTouching(); - touch_info_.touch_point.position.set_x(TouchPosX()); - touch_info_.touch_point.position.set_y(TouchPosY()); - ClampTouchpadPosition(&touch_info_.touch_point.position); - if (touch_info_.is_touching) { - touch_info_.touch_point.timestamp = - base::TimeTicks() + - base::TimeDelta::FromNanoseconds( - gvr::GvrApi::GetTimePointNow().monotonic_system_time_nanos); +void VrController::UpdateTimestamps() { + // controller_state_->GetLast*Timestamp() returns timestamps in a + // different timebase from base::TimeTicks::Now(), so we can't use the + // timestamps in any meaningful way in the rest of Chrome. + // TODO(crbug/866040): Use controller_state_->GetLast*Timestamp() after + // we upgrade GVR. + base::TimeTicks now = base::TimeTicks::Now(); + last_orientation_timestamp_ = now; + if (IsTouchingTrackpad()) + last_touch_timestamp_ = now; + for (int button = PlatformController::kButtonTypeFirst; + button < PlatformController::kButtonTypeNumber; ++button) { + if (IsButtonDown(static_cast<PlatformController::ButtonType>(button))) { + last_button_timestamp_ = now; + break; + } } - } void VrController::UpdateAlpha() {
diff --git a/chrome/browser/android/vr/vr_controller.h b/chrome/browser/android/vr/vr_controller.h index c2a1b06..d58cb04 100644 --- a/chrome/browser/android/vr/vr_controller.h +++ b/chrome/browser/android/vr/vr_controller.h
@@ -55,12 +55,6 @@ std::unique_ptr<InputEventList> DetectGestures(); - bool IsTouching(); - - float TouchPosX(); - - float TouchPosY(); - gfx::Quaternion Orientation() const; gfx::Point3F Position() const; void GetTransform(gfx::Transform* out) const; @@ -82,6 +76,8 @@ // PlatformController bool IsButtonDown(PlatformController::ButtonType type) const override; + bool IsTouchingTrackpad() const override; + gfx::PointF GetPositionInTrackpad() const override; base::TimeTicks GetLastOrientationTimestamp() const override; base::TimeTicks GetLastTouchTimestamp() const override; base::TimeTicks GetLastButtonTimestamp() const override; @@ -91,19 +87,9 @@ private: - struct ButtonInfo { - gvr::ControllerButton button; - bool button_up; - bool button_down; - bool button_state; - int64_t timestamp; - }; - bool GetButtonLongPressFromButtonInfo(); - void UpdateTouchInfo(); - - void UpdateCurrentTouchInfo(); + void UpdateTimestamps(); void UpdateOverallVelocity(); @@ -128,12 +114,13 @@ // Handedness from user prefs. gvr::ControllerHandedness handedness_; - // Current touch info from GVR. - TouchInfo touch_info_; - // Head offset. Keeps the controller at the user's side with 6DoF headsets. gfx::Point3F head_offset_; + base::TimeTicks last_orientation_timestamp_; + base::TimeTicks last_touch_timestamp_; + base::TimeTicks last_button_timestamp_; + int64_t last_timestamp_nanos_ = 0; float alpha_value_ = 1.0f;
diff --git a/chrome/browser/android/vr/vr_shell_gl.cc b/chrome/browser/android/vr/vr_shell_gl.cc index 3c4440d..d48b17e 100644 --- a/chrome/browser/android/vr/vr_shell_gl.cc +++ b/chrome/browser/android/vr/vr_shell_gl.cc
@@ -599,8 +599,9 @@ scoped_refptr<gl::GLImageAHardwareBuffer> img( new gl::GLImageAHardwareBuffer(webvr_surface_size_)); - AHardwareBuffer* ahb = buffer->gmb->GetHandle().android_hardware_buffer; - bool ret = img->Initialize(ahb, false /* preserved */); + base::android::ScopedHardwareBufferHandle ahb = + buffer->gmb->CloneHandle().android_hardware_buffer; + bool ret = img->Initialize(ahb.get(), false /* preserved */); if (!ret) { DLOG(WARNING) << __FUNCTION__ << ": ERROR: failed to initialize image!"; // Exiting VR is a bit drastic, but this error shouldn't occur under normal @@ -1299,9 +1300,9 @@ controller_model.laser_origin = laser_origin; controller_model.handedness = controller_->GetHandedness(); controller_model.recentered = controller_->GetRecentered(); - controller_model.touching_touchpad = controller_->IsTouching(); + controller_model.touching_touchpad = controller_->IsTouchingTrackpad(); controller_model.touchpad_touch_position = - gfx::PointF(controller_->TouchPosX(), controller_->TouchPosY()); + controller_->GetPositionInTrackpad(); controller_model.app_button_long_pressed = app_button_long_pressed_; controller_model.last_orientation_timestamp = controller_->GetLastOrientationTimestamp();
diff --git a/chrome/browser/autofill/autofill_captured_sites_interactive_uitest.cc b/chrome/browser/autofill/autofill_captured_sites_interactive_uitest.cc index ad9a55335..3287bbc 100644 --- a/chrome/browser/autofill/autofill_captured_sites_interactive_uitest.cc +++ b/chrome/browser/autofill/autofill_captured_sites_interactive_uitest.cc
@@ -56,6 +56,57 @@ namespace { const base::TimeDelta default_action_timeout = base::TimeDelta::FromSeconds(30); +const base::TimeDelta paint_event_check_interval = + base::TimeDelta::FromMilliseconds(500); +const int autofill_action_num_retries = 5; + +// PageActivityObserver waits until Chrome finishes loading a page and stops +// making visual updates to the page. +class PageActivityObserver : public content::WebContentsObserver { + public: + explicit PageActivityObserver(content::WebContents* web_contents) + : content::WebContentsObserver(web_contents) {} + ~PageActivityObserver() override = default; + + // Wait until Chrome finishes loading a page and updating the page's visuals. + // If Chrome finishes loading a page but continues to paint every half + // second, exit after |continuous_paint_timeout| expires since Chrome + // finished loading the page. + void WaitTillPageIsIdle( + base::TimeDelta continuous_paint_timeout = default_action_timeout) { + base::TimeTicks finished_load_time = base::TimeTicks::Now(); + bool page_is_loading = false; + do { + paint_occurred_during_last_loop_ = false; + base::RunLoop heart_beat; + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, heart_beat.QuitClosure(), paint_event_check_interval); + heart_beat.Run(); + page_is_loading = + web_contents()->IsWaitingForResponse() || web_contents()->IsLoading(); + if (page_is_loading) { + finished_load_time = base::TimeTicks::Now(); + } else if (base::TimeTicks::Now() - finished_load_time > + continuous_paint_timeout) { + // |continuous_paint_timeout| has expired since Chrome loaded the page. + // During this period of time, Chrome has been continuously painting + // the page. In this case, the page is probably idle, but a bug, a + // blinking caret or a persistent animation is making Chrome paint at + // regular intervals. Exit. + break; + } + } while (page_is_loading || paint_occurred_during_last_loop_); + } + + private: + void DidCommitAndDrawCompositorFrame() override { + paint_occurred_during_last_loop_ = true; + } + + bool paint_occurred_during_last_loop_ = false; + + DISALLOW_COPY_AND_ASSIGN(PageActivityObserver); +}; std::string FilePathToUTF8(const base::FilePath::StringType& str) { #if defined(OS_WIN) @@ -87,9 +138,7 @@ // has the '.test' extension. if (file.Extension().empty() && base::PathExists(file.AddExtension(FILE_PATH_LITERAL(".test")))) { - std::string file_name(file.BaseName().value().begin(), - file.BaseName().value().end()); - sites.push_back(file_name); + sites.push_back(FilePathToUTF8(file.BaseName().value())); } } std::sort(sites.begin(), sites.end()); @@ -113,7 +162,7 @@ void SetUpOnMainThread() override { AutofillUiTest::SetUpOnMainThread(); SetupTestProfile(); - ASSERT_TRUE(InstallWebPageReplayServerRootCert()) + EXPECT_TRUE(InstallWebPageReplayServerRootCert()) << "Cannot install the root certificate " << "for the local web page replay server."; CleanupSiteData(); @@ -197,7 +246,7 @@ return true; } - bool ReplayRecordedActions(const char* recipe_file_name) { + bool ReplayTestRecipe(const char* recipe_file_name) { // Read the text of the recipe file. base::FilePath src_dir; CHECK(base::PathService::Get(base::DIR_SOURCE_ROOT, &src_dir)); @@ -215,118 +264,42 @@ return false; } - // Navigate to the starting url. - std::string starting_url; - CHECK(recipe->GetString("startingURL", &starting_url)); - CHECK(content::ExecuteScript( - GetWebContents(), base::StringPrintf("window.location.href = '%s';", - starting_url.c_str()))); - // Iterate through and execute all the actions contained in the recipe. - base::ListValue* action_list; - CHECK(recipe->GetList("actions", &action_list)); - for (base::ListValue::iterator it_action = action_list->begin(); - it_action != action_list->end(); ++it_action) { + InitializeBrowserToExecuteRecipe(recipe); + + // Iterate through and execute each action in the recipe. + base::Value* action_list_container = recipe->FindKey("actions"); + CHECK(action_list_container); + CHECK_EQ(base::Value::Type::LIST, action_list_container->type()); + base::Value::ListStorage& action_list = action_list_container->GetList(); + + for (base::ListValue::iterator it_action = action_list.begin(); + it_action != action_list.end(); ++it_action) { base::DictionaryValue* action; CHECK(it_action->GetAsDictionary(&action)); - std::string type; - CHECK(action->GetString("type", &type)); + + base::Value* type_container = action->FindKey("type"); + CHECK(type_container); + CHECK_EQ(base::Value::Type::STRING, type_container->type()); + std::string type = type_container->GetString(); if (base::CompareCaseInsensitiveASCII(type, "waitFor") == 0) { - std::vector<std::string> state_assertions; - base::ListValue* assertions_list; - CHECK(action->GetList("assertions", &assertions_list)); - for (base::ListValue::iterator it_assertion = assertions_list->begin(); - it_assertion != assertions_list->end(); ++it_assertion) { - std::string assertion; - CHECK(it_assertion->GetAsString(&assertion)); - state_assertions.push_back(assertion); - } - CHECK(WaitForStateChange(state_assertions, default_action_timeout)); + ExecuteWaitForStateAction(action); + } else if (base::CompareCaseInsensitiveASCII(type, "execute") == 0) { + ExecuteRunCommandAction(action); + } else if (base::CompareCaseInsensitiveASCII(type, "click") == 0) { + ExecuteClickAction(action); + } else if (base::CompareCaseInsensitiveASCII(type, "type") == 0) { + ExecuteTypeAction(action); + } else if (base::CompareCaseInsensitiveASCII(type, "select") == 0) { + ExecuteSelectDropdownAction(action); + } else if (base::CompareCaseInsensitiveASCII(type, "autofill") == 0) { + ExecuteAutofillAction(action); + } else if (base::CompareCaseInsensitiveASCII(type, "validateField") == + 0) { + ExecuteValidateFieldValueAction(action); } else { - std::string xpath; - CHECK(action->GetString("selector", &xpath)); - LOG(INFO) << "Executing recipe action"; - LOG(INFO) << "type: " << type; - LOG(INFO) << "xpath: " << xpath; - - // Wait for the target element to be visible and enabled on the page. - std::vector<std::string> state_assertions; - state_assertions.push_back(base::StringPrintf( - "return automation_helper.isElementWithXpathReady(`%s`);", - xpath.c_str())); - CHECK(WaitForStateChange(state_assertions, default_action_timeout)); - - if (base::CompareCaseInsensitiveASCII(type, "click") == 0) { - CHECK(ExecuteJavaScriptOnElementByXpath(xpath, "target.click();")); - } else if (base::CompareCaseInsensitiveASCII(type, "type") == 0) { - std::string value; - CHECK(action->GetString("value", &value)); - CHECK(ExecuteJavaScriptOnElementByXpath( - xpath, base::StringPrintf( - "automation_helper.setInputElementValue(target, `%s`)", - value.c_str()))); - } else if (base::CompareCaseInsensitiveASCII(type, "select") == 0) { - int selected_index; - CHECK(action->GetInteger("index", &selected_index)); - CHECK(ExecuteJavaScriptOnElementByXpath( - xpath, base::StringPrintf( - "automation_helper" - ".selectOptionFromDropDownElementByIndex(target, %d)", - selected_index))); - } else if (base::CompareCaseInsensitiveASCII(type, "autofill") == 0) { - std::vector<std::string> additional_state_assertions; - base::ListValue* fields_list; - CHECK(action->GetList("fields", &fields_list)); - - // Wait for all the autofilled elements to become visible on the - // page, and also wait for the `autofill-prediction` attribute on - // each element to be appended. Without the `autofill-prediction` - // attribute, Chrome will not be able to autofill the field. - for (base::ListValue::iterator it_field = fields_list->begin(); - it_field != fields_list->end(); ++it_field) { - base::DictionaryValue* field; - CHECK(it_field->GetAsDictionary(&field)); - std::string field_xpath; - CHECK(field->GetString("selector", &field_xpath)); - additional_state_assertions.push_back(base::StringPrintf( - "return automation_helper.isElementWithXpathReady(`%s`);", - field_xpath.c_str())); - additional_state_assertions.push_back(base::StringPrintf( - "var attr = automation_helper.getElementByXpath(`%s`)" - ".getAttribute('autofill-prediction');" - "return (attr !== undefined && attr !== null);", - field_xpath.c_str())); - } - CHECK(WaitForStateChange(additional_state_assertions, - default_action_timeout)); - CHECK(TryFillForm(xpath, 5)); - // Go through each autofilled fields and verify that - // 1. The element has the expected autofill-prediction attribute. - // This attribute is set either by chrome's local heuristic or - // by Chrome Autofill team's prediction server. - // 2. The element has the expected value. - for (base::ListValue::iterator it_field = fields_list->begin(); - it_field != fields_list->end(); ++it_field) { - base::DictionaryValue* field; - CHECK(it_field->GetAsDictionary(&field)); - std::string field_xpath; - std::string autofill_prediction; - std::string expected_value; - CHECK(field->GetString("selector", &field_xpath)); - CHECK( - field->GetString("expectedAutofillType", &autofill_prediction)); - CHECK(field->GetString("expectedValue", &expected_value)); - ExpectElementPropertyEquals( - field_xpath.c_str(), - "return target.getAttribute('autofill-prediction');", - autofill_prediction, true); - ExpectElementPropertyEquals(field_xpath.c_str(), - "return target.value;", expected_value); - } - } else { - ADD_FAILURE() << "Unrecognized action type: " << type; - } - } // end if type != "waitFor" + ADD_FAILURE() << "Unrecognized action type: " << type; + } } // end foreach action return true; } @@ -524,6 +497,175 @@ return false; } + // Functions for deserializing and executing actions from the test recipe + // JSON object. + void InitializeBrowserToExecuteRecipe( + std::unique_ptr<base::DictionaryValue>& recipe) { + // Extract the starting URL from the test recipe. + base::Value* starting_url_container = recipe->FindKey("startingURL"); + CHECK(starting_url_container); + CHECK_EQ(base::Value::Type::STRING, starting_url_container->type()); + LOG(INFO) << "Navigating to " << starting_url_container->GetString(); + + // Navigate to the starting URL, wait for the page to complete loading. + PageActivityObserver page_activity_observer(GetWebContents()); + CHECK(content::ExecuteScript( + GetWebContents(), + base::StringPrintf("window.location.href = '%s';", + starting_url_container->GetString().c_str()))); + page_activity_observer.WaitTillPageIsIdle(); + } + + void ExecuteWaitForStateAction(base::DictionaryValue* action) { + // Extract the list of JavaScript assertions into a vector. + std::vector<std::string> state_assertions; + base::Value* assertions_list_container = action->FindKey("assertions"); + CHECK(assertions_list_container); + CHECK_EQ(base::Value::Type::LIST, assertions_list_container->type()); + base::Value::ListStorage& assertions_list = + assertions_list_container->GetList(); + for (base::ListValue::iterator it_assertion = assertions_list.begin(); + it_assertion != assertions_list.end(); ++it_assertion) { + CHECK_EQ(base::Value::Type::STRING, it_assertion->type()); + state_assertions.push_back(it_assertion->GetString()); + } + LOG(INFO) << "Waiting for page to reach a state."; + + // Wait for all of the assertions to become true on the current page. + CHECK(WaitForStateChange(state_assertions, default_action_timeout)); + } + + void ExecuteRunCommandAction(base::DictionaryValue* action) { + // Extract the list of JavaScript commands into a vector. + std::vector<std::string> commands; + base::Value* commands_list_container = action->FindKey("commands"); + CHECK(commands_list_container); + CHECK_EQ(base::Value::Type::LIST, commands_list_container->type()); + base::Value::ListStorage& commands_list = + commands_list_container->GetList(); + + for (base::ListValue::iterator it_command = commands_list.begin(); + it_command != commands_list.end(); ++it_command) { + CHECK_EQ(base::Value::Type::STRING, it_command->type()); + commands.push_back(it_command->GetString()); + } + LOG(INFO) << "Running JavaScript commands on the page."; + + // Execute the commands. + PageActivityObserver page_activity_observer(GetWebContents()); + for (const std::string& command : commands) { + CHECK(content::ExecuteScript(GetWebContents(), command)); + // Wait in case the JavaScript command triggers page load or layout + // changes. + page_activity_observer.WaitTillPageIsIdle(); + } + } + + void ExecuteClickAction(base::DictionaryValue* action) { + std::string xpath = GetTargetHTMLElementXpathFromAction(action); + WaitForElemementToBeReady(xpath); + + LOG(INFO) << "Left mouse clicking `" << xpath << "`."; + PageActivityObserver page_activity_observer(GetWebContents()); + CHECK(ExecuteJavaScriptOnElementByXpath(xpath, "target.click();")); + page_activity_observer.WaitTillPageIsIdle(); + } + + void ExecuteTypeAction(base::DictionaryValue* action) { + base::Value* value_container = action->FindKey("value"); + CHECK(value_container); + CHECK_EQ(base::Value::Type::STRING, value_container->type()); + std::string value = value_container->GetString(); + + std::string xpath = GetTargetHTMLElementXpathFromAction(action); + WaitForElemementToBeReady(xpath); + + LOG(INFO) << "Typing '" << value << "' inside `" << xpath << "`."; + PageActivityObserver page_activity_observer(GetWebContents()); + CHECK(ExecuteJavaScriptOnElementByXpath( + xpath, base::StringPrintf( + "automation_helper.setInputElementValue(target, `%s`);", + value.c_str()))); + page_activity_observer.WaitTillPageIsIdle(); + } + + void ExecuteSelectDropdownAction(base::DictionaryValue* action) { + base::Value* index_container = action->FindKey("index"); + CHECK(index_container); + CHECK_EQ(base::Value::Type::INTEGER, index_container->type()); + int index = index_container->GetInt(); + + std::string xpath = GetTargetHTMLElementXpathFromAction(action); + WaitForElemementToBeReady(xpath); + + LOG(INFO) << "Select option '" << index << "' from `" << xpath << "`."; + PageActivityObserver page_activity_observer(GetWebContents()); + CHECK(ExecuteJavaScriptOnElementByXpath( + xpath, base::StringPrintf( + "automation_helper" + " .selectOptionFromDropDownElementByIndex(target, %d);", + index_container->GetInt()))); + page_activity_observer.WaitTillPageIsIdle(); + } + + void ExecuteAutofillAction(base::DictionaryValue* action) { + std::string xpath = GetTargetHTMLElementXpathFromAction(action); + WaitForElemementToBeReady(xpath); + + LOG(INFO) << "Invoking Chrome Autofill on `" << xpath << "`."; + PageActivityObserver page_activity_observer(GetWebContents()); + // Clear the input box first, in case a previous value is there. + // If the text input box is not clear, pressing the down key will not + // bring up the autofill suggestion box. + // This can happen on sites that requires the user to sign in. After + // signing in, the site fills the form with the user's profile + // information. + CHECK(ExecuteJavaScriptOnElementByXpath( + xpath, "automation_helper.setInputElementValue(target, ``);")); + CHECK(TryFillForm(xpath, autofill_action_num_retries)); + page_activity_observer.WaitTillPageIsIdle(); + } + + void ExecuteValidateFieldValueAction(base::DictionaryValue* action) { + base::Value* autofill_prediction_container = + action->FindKey("expectedAutofillType"); + CHECK(autofill_prediction_container); + CHECK_EQ(base::Value::Type::STRING, autofill_prediction_container->type()); + std::string expected_autofill_prediction_type = + autofill_prediction_container->GetString(); + + base::Value* expected_value_container = action->FindKey("expectedValue"); + CHECK(expected_value_container); + CHECK_EQ(base::Value::Type::STRING, expected_value_container->type()); + std::string expected_value = expected_value_container->GetString(); + + std::string xpath = GetTargetHTMLElementXpathFromAction(action); + WaitForElemementToBeReady(xpath); + + LOG(INFO) << "Checking the field `" << xpath << "`."; + ExpectElementPropertyEquals( + xpath.c_str(), "return target.getAttribute('autofill-prediction');", + expected_autofill_prediction_type, true); + ExpectElementPropertyEquals(xpath.c_str(), "return target.value;", + expected_value); + } + + std::string GetTargetHTMLElementXpathFromAction( + base::DictionaryValue* action) { + base::Value* xpath_container = action->FindKey("selector"); + CHECK(xpath_container); + CHECK_EQ(base::Value::Type::STRING, xpath_container->type()); + return xpath_container->GetString(); + } + + void WaitForElemementToBeReady(std::string xpath) { + std::vector<std::string> state_assertions; + state_assertions.push_back(base::StringPrintf( + "return automation_helper.isElementWithXpathReady(`%s`);", + xpath.c_str())); + CHECK(WaitForStateChange(state_assertions, default_action_timeout)); + } + // The Web Page Replay server that will be serving the captured sites base::Process web_page_replay_server_; const int host_http_port_ = 8080; @@ -539,7 +681,7 @@ // Prints the path of the test to be executed. LOG(INFO) << GetParam(); ASSERT_TRUE(StartWebPageReplayServer(GetParam())); - ASSERT_TRUE(ReplayRecordedActions(GetParam().c_str())); + ASSERT_TRUE(ReplayTestRecipe(GetParam().c_str())); } struct GetParamAsString {
diff --git a/chrome/browser/autofill/autofill_interactive_uitest.cc b/chrome/browser/autofill/autofill_interactive_uitest.cc index 7db77aa..da7d3157 100644 --- a/chrome/browser/autofill/autofill_interactive_uitest.cc +++ b/chrome/browser/autofill/autofill_interactive_uitest.cc
@@ -2913,6 +2913,35 @@ ExpectFieldValue("phone", "15125551234"); } +// Test that form data gets saved after submitting dynamically changing form. +IN_PROC_BROWSER_TEST_P(AutofillDynamicFormInteractiveTest, + Submit_DynamicChangingFormFill) { + CreateTestProfile(); + + GURL url = embedded_test_server()->GetURL( + "a.com", "/autofill/dynamic_form_new_field.html"); + ASSERT_NO_FATAL_FAILURE(ui_test_utils::NavigateToURL(browser(), url)); + + TriggerFormFill("firstname"); + + // Wait for the re-fill to happen. + bool has_refilled = false; + ASSERT_TRUE(content::ExecuteScriptAndExtractBool( + GetWebContents(), "hasRefilled()", &has_refilled)); + ASSERT_TRUE(has_refilled); + + // Edit the company field. + ASSERT_TRUE(content::ExecuteScript( + GetWebContents(), "document.getElementById('company').value = 'NASA';")); + + // Submit the form. + ASSERT_TRUE(content::ExecuteScript( + GetWebContents(), "document.getElementById('form1').submit();")); + + // A new autofill profile gets added. + ASSERT_EQ(2u, GetProfiles(browser()).size()); +} + INSTANTIATE_TEST_CASE_P(All, AutofillInteractiveTest, testing::Bool()); INSTANTIATE_TEST_CASE_P(All, AutofillCreditCardInteractiveTest,
diff --git a/chrome/browser/autofill/autofill_uitest_util.cc b/chrome/browser/autofill/autofill_uitest_util.cc index b4dd07b..211bf64d 100644 --- a/chrome/browser/autofill/autofill_uitest_util.cc +++ b/chrome/browser/autofill/autofill_uitest_util.cc
@@ -99,4 +99,12 @@ observer.Wait(); } +std::vector<AutofillProfile*> GetProfiles(Browser* browser) { + // Wait for asynchronous updates to PersonalDataManager to complete. + PdmChangeWaiter observer(browser); + observer.Wait(); + + return GetPersonalDataManager(browser->profile())->GetProfiles(); +} + } // namespace autofill
diff --git a/chrome/browser/autofill/autofill_uitest_util.h b/chrome/browser/autofill/autofill_uitest_util.h index 6140db1c..c60faff 100644 --- a/chrome/browser/autofill/autofill_uitest_util.h +++ b/chrome/browser/autofill/autofill_uitest_util.h
@@ -21,6 +21,7 @@ void AddTestAutofillData(Browser* browser, const AutofillProfile& profile, const CreditCard& card); +std::vector<AutofillProfile*> GetProfiles(Browser* browser); } // namespace autofill #endif // CHROME_BROWSER_AUTOFILL_AUTOFILL_UITEST_UTIL_H_
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc index dd9b67d..bc7a146 100644 --- a/chrome/browser/browser_process_impl.cc +++ b/chrome/browser/browser_process_impl.cc
@@ -53,6 +53,7 @@ #include "chrome/browser/lifetime/application_lifetime.h" #include "chrome/browser/lifetime/switch_utils.h" #include "chrome/browser/loader/chrome_resource_dispatcher_host_delegate.h" +#include "chrome/browser/media/router/discovery/dial/dial_registry.h" #include "chrome/browser/media/webrtc/webrtc_event_log_manager.h" #include "chrome/browser/media/webrtc/webrtc_log_uploader.h" #include "chrome/browser/metrics/chrome_metrics_service_accessor.h" @@ -355,6 +356,10 @@ KeepAliveRegistry::GetInstance()->SetIsShuttingDown(); + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::BindOnce(&media_router::DialRegistry::Shutdown)); + // We need to destroy the MetricsServicesManager, IntranetRedirectDetector, // NetworkTimeTracker, and SafeBrowsing ClientSideDetectionService // (owned by the SafeBrowsingService) before the io_thread_ gets destroyed,
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd index 5c0a339..a4511969 100644 --- a/chrome/browser/browser_resources.grd +++ b/chrome/browser/browser_resources.grd
@@ -140,6 +140,8 @@ <include name="IDR_DOWNLOAD_INTERNALS_JS" file="resources\download_internals\download_internals.js" type="BINDATA" compress="gzip" /> <include name="IDR_DOWNLOAD_INTERNALS_BROWSER_PROXY_JS" file="resources\download_internals\download_internals_browser_proxy.js" type="BINDATA" compress="gzip" /> <include name="IDR_DOWNLOAD_INTERNALS_VISUALS_JS" file="resources\download_internals\download_internals_visuals.js" type="BINDATA" compress="gzip" /> + <include name="IDR_UKM_INTERNALS_HTML" file="resources/ukm/ukm_internals.html" flattenhtml="true" allowexternalscript="true" compress="gzip" type="BINDATA" /> + <include name="IDR_UKM_INTERNALS_JS" file="resources/ukm/ukm_internals.js" flattenhtml="true" compress="gzip" type="BINDATA" /> <if expr="not is_android"> <include name="IDR_MD_DOWNLOADS_1X_INCOGNITO_MARKER_PNG" file="resources\md_downloads\1x\incognito_marker.png" type="BINDATA" /> <include name="IDR_MD_DOWNLOADS_2X_INCOGNITO_MARKER_PNG" file="resources\md_downloads\2x\incognito_marker.png" type="BINDATA" />
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager.cc b/chrome/browser/chromeos/accessibility/accessibility_manager.cc index 775ffdc1..598afce 100644 --- a/chrome/browser/chromeos/accessibility/accessibility_manager.cc +++ b/chrome/browser/chromeos/accessibility/accessibility_manager.cc
@@ -247,17 +247,18 @@ chromevox_loader_ = base::WrapUnique(new AccessibilityExtensionLoader( extension_misc::kChromeVoxExtensionId, resources_path.Append(extension_misc::kChromeVoxExtensionPath), - base::Bind(&AccessibilityManager::PostUnloadChromeVox, - weak_ptr_factory_.GetWeakPtr()))); + base::BindRepeating(&AccessibilityManager::PostUnloadChromeVox, + weak_ptr_factory_.GetWeakPtr()))); select_to_speak_loader_ = base::WrapUnique(new AccessibilityExtensionLoader( extension_misc::kSelectToSpeakExtensionId, resources_path.Append(extension_misc::kSelectToSpeakExtensionPath), - base::Bind(&AccessibilityManager::PostUnloadSelectToSpeak, - weak_ptr_factory_.GetWeakPtr()))); + base::BindRepeating(&AccessibilityManager::PostUnloadSelectToSpeak, + weak_ptr_factory_.GetWeakPtr()))); switch_access_loader_ = base::WrapUnique(new AccessibilityExtensionLoader( extension_misc::kSwitchAccessExtensionId, resources_path.Append(extension_misc::kSwitchAccessExtensionPath), - base::Closure())); + base::BindRepeating(&AccessibilityManager::PostUnloadSwitchAccess, + weak_ptr_factory_.GetWeakPtr()))); // Connect to ash's AccessibilityController interface. content::ServiceManagerConnection::GetForProcess() @@ -1255,6 +1256,14 @@ TtsController::GetInstance()->Stop(); } +void AccessibilityManager::PostUnloadSwitchAccess() { + // Do any teardown work needed immediately after SwitchAccess actually + // unloads. + + // Clear the accessibility focus ring. + HideFocusRing(extension_misc::kSwitchAccessExtensionId); +} + void AccessibilityManager::SetKeyboardListenerExtensionId( const std::string& id, content::BrowserContext* context) {
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager.h b/chrome/browser/chromeos/accessibility/accessibility_manager.h index 61ff6d0..716001db 100644 --- a/chrome/browser/chromeos/accessibility/accessibility_manager.h +++ b/chrome/browser/chromeos/accessibility/accessibility_manager.h
@@ -319,6 +319,7 @@ void PostSwitchChromeVoxProfile(); void PostUnloadSelectToSpeak(); + void PostUnloadSwitchAccess(); void UpdateAlwaysShowMenuFromPref(); void OnLargeCursorChanged(); void OnStickyKeysChanged();
diff --git a/chrome/browser/chromeos/crostini/crostini_util.h b/chrome/browser/chromeos/crostini/crostini_util.h index 971ffdd..4cf0dde 100644 --- a/chrome/browser/chromeos/crostini/crostini_util.h +++ b/chrome/browser/chromeos/crostini/crostini_util.h
@@ -85,5 +85,8 @@ constexpr char kCrostiniDefaultContainerName[] = "penguin"; constexpr char kCrostiniCroshBuiltinAppId[] = "nkoccljplnhpfnfiajclkommnmllphnl"; +// In order to be compatible with sync folder id must match standard. +// Generated using crx_file::id_util::GenerateId("LinuxAppsFolder") +constexpr char kCrostiniFolderId[] = "ddolnhmblagmcagkedkbfejapapdimlk"; #endif // CHROME_BROWSER_CHROMEOS_CROSTINI_CROSTINI_UTIL_H_
diff --git a/chrome/browser/chromeos/extensions/wallpaper_api.cc b/chrome/browser/chromeos/extensions/wallpaper_api.cc index 5ad2145..544179b 100644 --- a/chrome/browser/chromeos/extensions/wallpaper_api.cc +++ b/chrome/browser/chromeos/extensions/wallpaper_api.cc
@@ -246,7 +246,7 @@ const std::string& response) { if (success) { params_->details.data.reset( - new std::vector<char>(response.begin(), response.end())); + new std::vector<uint8_t>(response.begin(), response.end())); StartDecode(*params_->details.data); // StartDecode() will Respond later through OnWallpaperDecoded() } else {
diff --git a/chrome/browser/chromeos/extensions/wallpaper_function_base.cc b/chrome/browser/chromeos/extensions/wallpaper_function_base.cc index 852c2b4a..0b6209c 100644 --- a/chrome/browser/chromeos/extensions/wallpaper_function_base.cc +++ b/chrome/browser/chromeos/extensions/wallpaper_function_base.cc
@@ -75,7 +75,7 @@ explicit UnsafeWallpaperDecoder(scoped_refptr<WallpaperFunctionBase> function) : function_(function) {} - void Start(const std::vector<char>& image_data) { + void Start(const std::vector<uint8_t>& image_data) { DCHECK_CURRENTLY_ON(BrowserThread::UI); // This function can only be called after user login. It is fine to use @@ -149,7 +149,7 @@ #endif } -void WallpaperFunctionBase::StartDecode(const std::vector<char>& data) { +void WallpaperFunctionBase::StartDecode(const std::vector<uint8_t>& data) { DCHECK_CURRENTLY_ON(BrowserThread::UI); if (unsafe_wallpaper_decoder_) unsafe_wallpaper_decoder_->Cancel();
diff --git a/chrome/browser/chromeos/extensions/wallpaper_function_base.h b/chrome/browser/chromeos/extensions/wallpaper_function_base.h index 54b8c6aa..c739a9b 100644 --- a/chrome/browser/chromeos/extensions/wallpaper_function_base.h +++ b/chrome/browser/chromeos/extensions/wallpaper_function_base.h
@@ -60,7 +60,7 @@ static UnsafeWallpaperDecoder* unsafe_wallpaper_decoder_; // Starts to decode |data|. Must run on UI thread. - void StartDecode(const std::vector<char>& data); + void StartDecode(const std::vector<uint8_t>& data); // Handles cancel case. No error message should be set. void OnCancel();
diff --git a/chrome/browser/chromeos/extensions/wallpaper_private_api.cc b/chrome/browser/chromeos/extensions/wallpaper_private_api.cc index 20fc438..8548477 100644 --- a/chrome/browser/chromeos/extensions/wallpaper_private_api.cc +++ b/chrome/browser/chromeos/extensions/wallpaper_private_api.cc
@@ -112,7 +112,7 @@ // directory can not be found/created or failed to write file. bool SaveData(int key, const std::string& file_name, - const std::vector<char>& data) { + const std::vector<uint8_t>& data) { base::FilePath data_dir; CHECK(base::PathService::Get(key, &data_dir)); if (!base::DirectoryExists(data_dir) && @@ -122,7 +122,8 @@ base::FilePath file_path = data_dir.Append(file_name); return base::PathExists(file_path) || - base::WriteFile(file_path, data.data(), data.size()) != -1; + base::WriteFile(file_path, reinterpret_cast<const char*>(data.data()), + data.size()) != -1; } // Gets |file_name| from directory with |key|. Return false if the directory can @@ -624,8 +625,9 @@ Respond(NoArguments()); } -void WallpaperPrivateSaveThumbnailFunction::Save(const std::vector<char>& data, - const std::string& file_name) { +void WallpaperPrivateSaveThumbnailFunction::Save( + const std::vector<uint8_t>& data, + const std::string& file_name) { WallpaperFunctionBase::AssertCalledOnWallpaperSequence( WallpaperFunctionBase::GetNonBlockingTaskRunner()); if (SaveData(chrome::DIR_CHROMEOS_WALLPAPER_THUMBNAILS, file_name, data)) { @@ -793,7 +795,7 @@ } Respond(ArgumentList(get_local_image_data::Results::Create( - std::vector<char>(image_data->begin(), image_data->end())))); + std::vector<uint8_t>(image_data->begin(), image_data->end())))); } WallpaperPrivateConfirmPreviewWallpaperFunction::
diff --git a/chrome/browser/chromeos/extensions/wallpaper_private_api.h b/chrome/browser/chromeos/extensions/wallpaper_private_api.h index 2c9969a..027bbe6 100644 --- a/chrome/browser/chromeos/extensions/wallpaper_private_api.h +++ b/chrome/browser/chromeos/extensions/wallpaper_private_api.h
@@ -236,7 +236,7 @@ void Success(); // Saves thumbnail to thumbnail directory as |file_name|. - void Save(const std::vector<char>& data, const std::string& file_name); + void Save(const std::vector<uint8_t>& data, const std::string& file_name); }; class WallpaperPrivateGetOfflineWallpaperListFunction
diff --git a/chrome/browser/chromeos/file_system_provider/operations/write_file_unittest.cc b/chrome/browser/chromeos/file_system_provider/operations/write_file_unittest.cc index f2537a99..c9d42ee3 100644 --- a/chrome/browser/chromeos/file_system_provider/operations/write_file_unittest.cc +++ b/chrome/browser/chromeos/file_system_provider/operations/write_file_unittest.cc
@@ -92,7 +92,7 @@ EXPECT_EQ(kFileHandle, options.open_request_id); EXPECT_EQ(kOffset, static_cast<double>(options.offset)); std::string write_data(kWriteData); - EXPECT_EQ(std::vector<char>(write_data.begin(), write_data.end()), + EXPECT_EQ(std::vector<uint8_t>(write_data.begin(), write_data.end()), options.data); }
diff --git a/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc b/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc index 34976ed7..f553a5a 100644 --- a/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc +++ b/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include <string> +#include <unordered_set> #include <vector> #include "base/barrier_closure.h" @@ -138,16 +139,6 @@ // If |files_must_exist| is true and a file already exists the class does not // wait when it changes. explicit KerberosFilesChangeWaiter(bool files_must_exist) { - barrier_closure_ = base::BarrierClosure(2, loop_.QuitClosure()); - - watch_callback_ = base::BindRepeating( - [](const base::RepeatingClosure& barrier_closure, - const base::FilePath& path, bool error) -> void { - EXPECT_FALSE(error); - barrier_closure.Run(); - }, - barrier_closure_); - config_watcher_ = std::make_unique<base::FilePathWatcher>(); MaybeStartWatch(&config_watcher_, base::FilePath(GetKerberosConfigFileName()), @@ -157,6 +148,8 @@ MaybeStartWatch(&creds_watcher_, base::FilePath(GetKerberosCredentialsCacheFileName()), files_must_exist); + if (watching_paths_.empty()) + loop_.Quit(); } // Should be called once. @@ -170,19 +163,31 @@ void MaybeStartWatch(std::unique_ptr<base::FilePathWatcher>* watcher, const base::FilePath& path, bool files_must_exist) { - (*watcher)->Watch(path, false /* recursive */, watch_callback_); + (*watcher)->Watch( + path, false /* recursive */, + base::BindRepeating(&KerberosFilesChangeWaiter::WatchCallback, + weak_factory_.GetWeakPtr())); if (!files_must_exist && base::PathExists(path)) { - watch_callback_.Run(path, false /* error */); + // File was written so stop the watch. watcher->reset(); + return; } + watching_paths_.insert(path.value()); } - base::RunLoop loop_; - base::RepeatingClosure barrier_closure_; - base::RepeatingCallback<void(const base::FilePath& path, bool error)> - watch_callback_; + void WatchCallback(const base::FilePath& path, bool error) { + EXPECT_FALSE(error); + watching_paths_.erase(path.value()); + if (watching_paths_.empty()) + loop_.Quit(); + } + + base::RunLoop loop_; + std::unordered_set<std::string> watching_paths_; std::unique_ptr<base::FilePathWatcher> config_watcher_; std::unique_ptr<base::FilePathWatcher> creds_watcher_; + + base::WeakPtrFactory<KerberosFilesChangeWaiter> weak_factory_{this}; }; } // namespace @@ -977,7 +982,7 @@ // Kerberos files. // Disabled due to flakiness, see https://crbug.com/865206. IN_PROC_BROWSER_TEST_F(ExistingUserControllerActiveDirectoryTest, - DISABLED_PolicyChangeTriggersFileUpdate) { + PolicyChangeTriggersFileUpdate) { LoginAdOnline(); ApplyPolicyAndWaitFilesChanged(false /* enable_dns_cname_lookup */); @@ -990,9 +995,8 @@ // Tests if user Kerberos files changed D-Bus signal triggers updating user // Kerberos files. // Disabled due to flakiness, see https://crbug.com/865206. -IN_PROC_BROWSER_TEST_F( - ExistingUserControllerActiveDirectoryTest, - DISABLED_UserKerberosFilesChangedSignalTriggersFileUpdate) { +IN_PROC_BROWSER_TEST_F(ExistingUserControllerActiveDirectoryTest, + UserKerberosFilesChangedSignalTriggersFileUpdate) { LoginAdOnline(); KerberosFilesChangeWaiter files_change_waiter(true /* files_must_exist */); fake_authpolicy_client()->SetUserKerberosFiles("new_kerberos_creds",
diff --git a/chrome/browser/chromeos/login/ui/login_display_host_mojo.cc b/chrome/browser/chromeos/login/ui/login_display_host_mojo.cc index 605d62c..ce16101cd 100644 --- a/chrome/browser/chromeos/login/ui/login_display_host_mojo.cc +++ b/chrome/browser/chromeos/login/ui/login_display_host_mojo.cc
@@ -190,6 +190,13 @@ return; } + if (signin_screen_started_) { + HideOobeDialog(); + return; + } + + signin_screen_started_ = true; + existing_user_controller_ = std::make_unique<ExistingUserController>(); login_display_->set_delegate(existing_user_controller_.get()); @@ -252,6 +259,8 @@ GetOobeUI()->GetGaiaScreenView()->ShowGaiaAsync(prefilled_account); LoadWallpaper(*prefilled_account); } else { + if (GetOobeUI()->current_screen() != OobeScreen::SCREEN_GAIA_SIGNIN) + GetOobeUI()->GetGaiaScreenView()->ShowGaiaAsync(base::nullopt); LoadSigninWallpaper(); }
diff --git a/chrome/browser/chromeos/login/ui/login_display_host_mojo.h b/chrome/browser/chromeos/login/ui/login_display_host_mojo.h index ece255da5..e5ea154 100644 --- a/chrome/browser/chromeos/login/ui/login_display_host_mojo.h +++ b/chrome/browser/chromeos/login/ui/login_display_host_mojo.h
@@ -156,6 +156,11 @@ // Updates UI when version info is changed. std::unique_ptr<MojoVersionInfoDispatcher> version_info_updater_; + // Prevents repeated calls to OnStartSigninScreen, which can happen when a + // user cancels the Powerwash dialog in the login screen. Set to true on the + // first OnStartSigninScreen and remains true afterward. + bool signin_screen_started_ = false; + base::WeakPtrFactory<LoginDisplayHostMojo> weak_factory_; DISALLOW_COPY_AND_ASSIGN(LoginDisplayHostMojo);
diff --git a/chrome/browser/chromeos/settings/system_settings_provider.cc b/chrome/browser/chromeos/settings/system_settings_provider.cc index 29baa3b..f2bfa9f 100644 --- a/chrome/browser/chromeos/settings/system_settings_provider.cc +++ b/chrome/browser/chromeos/settings/system_settings_provider.cc
@@ -8,6 +8,7 @@ #include "base/time/time.h" #include "base/values.h" #include "chrome/browser/chromeos/system/timezone_util.h" +#include "chrome/browser/profiles/profile_manager.h" #include "chromeos/login/login_state.h" #include "chromeos/settings/cros_settings_names.h" @@ -33,9 +34,10 @@ void SystemSettingsProvider::DoSet(const std::string& path, const base::Value& in_value) { - // Only non-guest users can change the time zone. + // Only non-guest and non-child users can change the time zone. if (LoginState::Get()->IsGuestSessionUser() || - LoginState::Get()->IsPublicSessionUser()) { + LoginState::Get()->IsPublicSessionUser() || + ProfileManager::GetActiveUserProfile()->IsChild()) { return; }
diff --git a/chrome/browser/chromeos/smb_client/smb_file_system.h b/chrome/browser/chromeos/smb_client/smb_file_system.h index ea16167..0fc1ddc 100644 --- a/chrome/browser/chromeos/smb_client/smb_file_system.h +++ b/chrome/browser/chromeos/smb_client/smb_file_system.h
@@ -39,10 +39,10 @@ class RequestManager; -// Smb provided file system implementation. For communication with Smb +// SMB provided file system implementation. For communication with SMB // filesystems. -// Smb is an application level protocol used by Windows and Samba fileservers. -// Allows Files App to mount smb filesystems. +// SMB is an application level protocol used by Windows and Samba fileservers. +// Allows Files App to mount SMB filesystems. class SmbFileSystem : public file_system_provider::ProvidedFileSystemInterface, public base::SupportsWeakPtr<SmbFileSystem> { public:
diff --git a/chrome/browser/conflicts/module_database_win.cc b/chrome/browser/conflicts/module_database_win.cc index 07d6662a..b8febb7 100644 --- a/chrome/browser/conflicts/module_database_win.cc +++ b/chrome/browser/conflicts/module_database_win.cc
@@ -15,6 +15,7 @@ #if defined(GOOGLE_CHROME_BUILD) #include "base/feature_list.h" #include "base/task_scheduler/post_task.h" +#include "base/win/windows_version.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/conflicts/third_party_conflicts_manager_win.h" #include "chrome/common/chrome_features.h" @@ -338,8 +339,9 @@ if (!IsThirdPartyBlockingPolicyEnabled()) return; - if (base::FeatureList::IsEnabled( - features::kIncompatibleApplicationsWarning) || + if ((base::FeatureList::IsEnabled( + features::kIncompatibleApplicationsWarning) && + base::win::GetVersion() >= base::win::VERSION_WIN10) || base::FeatureList::IsEnabled(features::kThirdPartyModulesBlocking)) { third_party_conflicts_manager_ = std::make_unique<ThirdPartyConflictsManager>(this);
diff --git a/chrome/browser/conflicts/third_party_conflicts_manager_win.cc b/chrome/browser/conflicts/third_party_conflicts_manager_win.cc index dab5bb5..0672df8 100644 --- a/chrome/browser/conflicts/third_party_conflicts_manager_win.cc +++ b/chrome/browser/conflicts/third_party_conflicts_manager_win.cc
@@ -19,6 +19,7 @@ #include "base/task_runner.h" #include "base/task_runner_util.h" #include "base/task_scheduler/post_task.h" +#include "base/win/windows_version.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/conflicts/incompatible_applications_updater_win.h" #include "chrome/browser/conflicts/installed_applications_win.h" @@ -126,6 +127,11 @@ if (!base::FeatureList::IsEnabled(features::kIncompatibleApplicationsWarning)) return; + // The incompatible applications warning feature is not available on Windows + // versions other than 10. + if (base::win::GetVersion() < base::win::VERSION_WIN10) + return; + base::PostTaskAndReplyWithResult( background_sequence_.get(), FROM_HERE, base::BindOnce([]() { return std::make_unique<InstalledApplications>();
diff --git a/chrome/browser/extensions/api/braille_display_private/braille_controller.h b/chrome/browser/extensions/api/braille_display_private/braille_controller.h index 5b575d2..5287209 100644 --- a/chrome/browser/extensions/api/braille_display_private/braille_controller.h +++ b/chrome/browser/extensions/api/braille_display_private/braille_controller.h
@@ -24,7 +24,7 @@ static BrailleController* GetInstance(); virtual std::unique_ptr<DisplayState> GetDisplayState() = 0; - virtual void WriteDots(const std::vector<char>& cells, + virtual void WriteDots(const std::vector<uint8_t>& cells, unsigned int cols, unsigned int rows) = 0; virtual void AddObserver(BrailleObserver* observer) = 0;
diff --git a/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.cc b/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.cc index a57126f..8a04b0e 100644 --- a/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.cc +++ b/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.cc
@@ -100,7 +100,7 @@ return display_state; } -void BrailleControllerImpl::WriteDots(const std::vector<char>& cells, +void BrailleControllerImpl::WriteDots(const std::vector<uint8_t>& cells, unsigned int cells_cols, unsigned int cells_rows) { DCHECK_CURRENTLY_ON(BrowserThread::IO);
diff --git a/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.h b/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.h index 82fe471..8bd0285 100644 --- a/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.h +++ b/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.h
@@ -25,7 +25,7 @@ public: static BrailleControllerImpl* GetInstance(); std::unique_ptr<DisplayState> GetDisplayState() override; - void WriteDots(const std::vector<char>& cells, + void WriteDots(const std::vector<uint8_t>& cells, unsigned int cols, unsigned int rows) override; void AddObserver(BrailleObserver* observer) override;
diff --git a/chrome/browser/extensions/api/braille_display_private/stub_braille_controller.cc b/chrome/browser/extensions/api/braille_display_private/stub_braille_controller.cc index 5e8a8c5b..e732981 100644 --- a/chrome/browser/extensions/api/braille_display_private/stub_braille_controller.cc +++ b/chrome/browser/extensions/api/braille_display_private/stub_braille_controller.cc
@@ -15,7 +15,7 @@ return std::unique_ptr<DisplayState>(new DisplayState); } -void StubBrailleController::WriteDots(const std::vector<char>& cells, +void StubBrailleController::WriteDots(const std::vector<uint8_t>& cells, unsigned int cols, unsigned int rows) {}
diff --git a/chrome/browser/extensions/api/braille_display_private/stub_braille_controller.h b/chrome/browser/extensions/api/braille_display_private/stub_braille_controller.h index cc159125..44f36ad 100644 --- a/chrome/browser/extensions/api/braille_display_private/stub_braille_controller.h +++ b/chrome/browser/extensions/api/braille_display_private/stub_braille_controller.h
@@ -17,7 +17,7 @@ public: StubBrailleController(); std::unique_ptr<DisplayState> GetDisplayState() override; - void WriteDots(const std::vector<char>& cells, + void WriteDots(const std::vector<uint8_t>& cells, unsigned int cols, unsigned int rows) override; void AddObserver(BrailleObserver* observer) override;
diff --git a/chrome/browser/extensions/api/certificate_provider/certificate_provider_api.cc b/chrome/browser/extensions/api/certificate_provider/certificate_provider_api.cc index 8596f7dd..260ed83 100644 --- a/chrome/browser/extensions/api/certificate_provider/certificate_provider_api.cc +++ b/chrome/browser/extensions/api/certificate_provider/certificate_provider_api.cc
@@ -96,7 +96,7 @@ } chromeos::certificate_provider::CertificateInfoList cert_infos; - std::vector<std::vector<char>> rejected_certificates; + std::vector<std::vector<uint8_t>> rejected_certificates; for (const api_cp::CertificateInfo& input_cert_info : *params->certificates) { chromeos::certificate_provider::CertificateInfo parsed_cert_info; @@ -122,7 +122,7 @@ ParseCertificateInfo( const api_cp::CertificateInfo& info, chromeos::certificate_provider::CertificateInfo* out_info) { - const std::vector<char>& cert_der = info.certificate; + const std::vector<uint8_t>& cert_der = info.certificate; if (cert_der.empty()) { WriteToConsole(content::CONSOLE_MESSAGE_LEVEL_ERROR, kCertificateProviderErrorInvalidX509Cert); @@ -134,7 +134,7 @@ net::X509Certificate::UnsafeCreateOptions options; options.printable_string_is_utf8 = true; out_info->certificate = net::X509Certificate::CreateFromBytesUnsafeOptions( - cert_der.data(), cert_der.size(), options); + reinterpret_cast<const char*>(cert_der.data()), cert_der.size(), options); if (!out_info->certificate) { WriteToConsole(content::CONSOLE_MESSAGE_LEVEL_ERROR, kCertificateProviderErrorInvalidX509Cert);
diff --git a/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api.cc b/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api.cc index 44223d6..a36c624 100644 --- a/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api.cc +++ b/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api.cc
@@ -32,7 +32,7 @@ // ContainsAppIdByHash returns true iff the SHA-256 hash of one of the // elements of |list| equals |hash|. bool ContainsAppIdByHash(const base::ListValue& list, - const std::vector<char>& hash) { + const std::vector<uint8_t>& hash) { if (hash.size() != crypto::kSHA256Length) { return false; } @@ -44,9 +44,10 @@ continue; } - if (crypto::SHA256HashString(s).compare(0, crypto::kSHA256Length, - hash.data(), - crypto::kSHA256Length) == 0) { + if (crypto::SHA256HashString(s).compare( + 0, crypto::kSHA256Length, + reinterpret_cast<const char*>(hash.data()), + crypto::kSHA256Length) == 0) { return true; } }
diff --git a/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc b/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc index 4e8b6cc..11947f5c 100644 --- a/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc +++ b/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc
@@ -13,7 +13,6 @@ #include "build/build_config.h" #include "chrome/browser/extensions/extension_tab_util.h" #include "chrome/browser/media/webrtc/desktop_media_list_ash.h" -#include "chrome/browser/media/webrtc/desktop_streams_registry.h" #include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h" #include "chrome/browser/media/webrtc/native_desktop_media_list.h" #include "chrome/browser/media/webrtc/tab_desktop_media_list.h" @@ -21,6 +20,7 @@ #include "chrome/browser/ui/browser_window.h" #include "chrome/grit/chromium_strings.h" #include "content/public/browser/desktop_capture.h" +#include "content/public/browser/desktop_streams_registry.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/web_contents.h" @@ -234,20 +234,15 @@ DesktopMediaID source) { std::string result; if (source.type != DesktopMediaID::TYPE_NONE && web_contents()) { - DesktopStreamsRegistry* registry = - MediaCaptureDevicesDispatcher::GetInstance()-> - GetDesktopStreamsRegistry(); // TODO(miu): Once render_frame_host() is being set, we should register the // exact RenderFrame requesting the stream, not the main RenderFrame. With // that change, also update // MediaCaptureDevicesDispatcher::ProcessDesktopCaptureAccessRequest(). // http://crbug.com/304341 content::RenderFrameHost* const main_frame = web_contents()->GetMainFrame(); - result = registry->RegisterStream(main_frame->GetProcess()->GetID(), - main_frame->GetRoutingID(), - origin_, - source, - extension()->name()); + result = content::DesktopStreamsRegistry::GetInstance()->RegisterStream( + main_frame->GetProcess()->GetID(), main_frame->GetRoutingID(), origin_, + source, extension()->name()); } Options options;
diff --git a/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_connection_manager.cc b/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_connection_manager.cc index 3d694cb..58ec3c09 100644 --- a/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_connection_manager.cc +++ b/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_connection_manager.cc
@@ -136,7 +136,7 @@ std::string event_name = api::easy_unlock_private::OnDataReceived::kEventName; events::HistogramValue histogram_value = events::EASY_UNLOCK_PRIVATE_ON_DATA_RECEIVED; - std::vector<char> data(message.body().begin(), message.body().end()); + std::vector<uint8_t> data(message.body().begin(), message.body().end()); std::unique_ptr<base::ListValue> args = api::easy_unlock_private::OnDataReceived::Create(0, data); DispatchConnectionEvent(event_name, histogram_value, &connection, @@ -156,7 +156,7 @@ api::easy_unlock_private::OnSendCompleted::kEventName; events::HistogramValue histogram_value = events::EASY_UNLOCK_PRIVATE_ON_SEND_COMPLETED; - std::vector<char> data(message.payload().begin(), message.payload().end()); + std::vector<uint8_t> data(message.payload().begin(), message.payload().end()); std::unique_ptr<base::ListValue> args = api::easy_unlock_private::OnSendCompleted::Create(0, data, success); DispatchConnectionEvent(event_name, histogram_value, &connection,
diff --git a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.cc b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.cc index 20f62bef..7136b03 100644 --- a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.cc +++ b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.cc
@@ -32,11 +32,11 @@ const char kEnterprisePlatformErrorInvalidX509Cert[] = "Certificate is not a valid X.509 certificate."; -std::vector<char> VectorFromString(const std::string& s) { - return std::vector<char>(s.begin(), s.end()); +std::vector<uint8_t> VectorFromString(const std::string& s) { + return std::vector<uint8_t>(s.begin(), s.end()); } -std::string StringFromVector(const std::vector<char>& v) { +std::string StringFromVector(const std::vector<uint8_t>& v) { return std::string(v.begin(), v.end()); } @@ -77,7 +77,7 @@ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (error_message.empty()) { Respond(ArgumentList(api_epki::GenerateKey::Results::Create( - std::vector<char>(public_key_der.begin(), public_key_der.end())))); + std::vector<uint8_t>(public_key_der.begin(), public_key_der.end())))); } else { Respond(Error(error_message)); } @@ -142,14 +142,15 @@ if (!platform_keys::ValidateToken(params->token_id, &platform_keys_token_id)) return RespondNow(Error(platform_keys::kErrorInvalidToken)); - const std::vector<char>& cert_der = params->certificate; + const std::vector<uint8_t>& cert_der = params->certificate; // Allow UTF-8 inside PrintableStrings in client certificates. See // crbug.com/770323 and crbug.com/788655. net::X509Certificate::UnsafeCreateOptions options; options.printable_string_is_utf8 = true; scoped_refptr<net::X509Certificate> cert_x509 = net::X509Certificate::CreateFromBytesUnsafeOptions( - cert_der.data(), cert_der.size(), options); + reinterpret_cast<const char*>(cert_der.data()), cert_der.size(), + options); if (!cert_x509.get()) return RespondNow(Error(kEnterprisePlatformErrorInvalidX509Cert)); @@ -185,14 +186,15 @@ if (!platform_keys::ValidateToken(params->token_id, &platform_keys_token_id)) return RespondNow(Error(platform_keys::kErrorInvalidToken)); - const std::vector<char>& cert_der = params->certificate; + const std::vector<uint8_t>& cert_der = params->certificate; // Allow UTF-8 inside PrintableStrings in client certificates. See // crbug.com/770323 and crbug.com/788655. net::X509Certificate::UnsafeCreateOptions options; options.printable_string_is_utf8 = true; scoped_refptr<net::X509Certificate> cert_x509 = net::X509Certificate::CreateFromBytesUnsafeOptions( - cert_der.data(), cert_der.size(), options); + reinterpret_cast<const char*>(cert_der.data()), cert_der.size(), + options); if (!cert_x509.get()) return RespondNow(Error(kEnterprisePlatformErrorInvalidX509Cert));
diff --git a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc index d6cdb21..f73ed9b6 100644 --- a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc +++ b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc
@@ -366,7 +366,7 @@ ASSERT_TRUE(value->is_blob()); EXPECT_EQ("response", - std::string(value->GetBlob().data(), value->GetBlob().size())); + std::string(value->GetBlob().begin(), value->GetBlob().end())); } TEST_F(EPKChallengeMachineKeyTest, KeyRegisteredSuccess) { @@ -395,7 +395,7 @@ ASSERT_TRUE(value->is_blob()); EXPECT_EQ("response", - std::string(value->GetBlob().data(), value->GetBlob().size())); + std::string(value->GetBlob().begin(), value->GetBlob().end())); } TEST_F(EPKChallengeMachineKeyTest, AttestationNotPrepared) { @@ -563,7 +563,7 @@ ASSERT_TRUE(value->is_blob()); EXPECT_EQ("response", - std::string(value->GetBlob().data(), value->GetBlob().size())); + std::string(value->GetBlob().begin(), value->GetBlob().end())); } TEST_F(EPKChallengeUserKeyTest, AttestationNotPrepared) {
diff --git a/chrome/browser/extensions/api/notifications/notifications_api.cc b/chrome/browser/extensions/api/notifications/notifications_api.cc index e6266922..e528a26 100644 --- a/chrome/browser/extensions/api/notifications/notifications_api.cc +++ b/chrome/browser/extensions/api/notifications/notifications_api.cc
@@ -152,7 +152,7 @@ return false; // Ensure we have rgba data. - std::vector<char>* rgba_data = notification_bitmap.data.get(); + std::vector<uint8_t>* rgba_data = notification_bitmap.data.get(); if (!rgba_data) return false; @@ -172,7 +172,7 @@ return false; uint32_t* pixels = bitmap.getAddr32(0, 0); - const char* c_rgba_data = rgba_data->data(); + const uint8_t* c_rgba_data = rgba_data->data(); for (size_t t = 0; t < rgba_area; ++t) { // |c_rgba_data| is RGBA, pixels is ARGB.
diff --git a/chrome/browser/extensions/api/platform_keys/platform_keys_api.cc b/chrome/browser/extensions/api/platform_keys/platform_keys_api.cc index 3cfa9e9..2983149 100644 --- a/chrome/browser/extensions/api/platform_keys/platform_keys_api.cc +++ b/chrome/browser/extensions/api/platform_keys/platform_keys_api.cc
@@ -129,7 +129,7 @@ api_pki::GetPublicKey::Params::Create(*args_)); EXTENSION_FUNCTION_VALIDATE(params); - const std::vector<char>& cert_der = params->certificate; + const std::vector<uint8_t>& cert_der = params->certificate; if (cert_der.empty()) return RespondNow(Error(platform_keys::kErrorInvalidX509Cert)); // Allow UTF-8 inside PrintableStrings in client certificates. See @@ -138,7 +138,8 @@ options.printable_string_is_utf8 = true; scoped_refptr<net::X509Certificate> cert_x509 = net::X509Certificate::CreateFromBytesUnsafeOptions( - cert_der.data(), cert_der.size(), options); + reinterpret_cast<const char*>(cert_der.data()), cert_der.size(), + options); if (!cert_x509) return RespondNow(Error(platform_keys::kErrorInvalidX509Cert)); @@ -163,8 +164,8 @@ &algorithm.additional_properties); return RespondNow(ArgumentList(api_pki::GetPublicKey::Results::Create( - std::vector<char>(key_info.public_key_spki_der.begin(), - key_info.public_key_spki_der.end()), + std::vector<uint8_t>(key_info.public_key_spki_der.begin(), + key_info.public_key_spki_der.end()), algorithm))); } @@ -184,7 +185,7 @@ DCHECK(service); chromeos::platform_keys::ClientCertificateRequest request; - for (const std::vector<char>& cert_authority : + for (const std::vector<uint8_t>& cert_authority : params->details.request.certificate_authorities) { request.certificate_authorities.push_back( std::string(cert_authority.begin(), cert_authority.end())); @@ -208,7 +209,7 @@ std::unique_ptr<net::CertificateList> client_certs; if (params->details.client_certs) { client_certs.reset(new net::CertificateList); - for (const std::vector<char>& client_cert_der : + for (const std::vector<uint8_t>& client_cert_der : *params->details.client_certs) { if (client_cert_der.empty()) return RespondNow(Error(platform_keys::kErrorInvalidX509Cert)); @@ -218,7 +219,8 @@ options.printable_string_is_utf8 = true; scoped_refptr<net::X509Certificate> client_cert_x509 = net::X509Certificate::CreateFromBytesUnsafeOptions( - client_cert_der.data(), client_cert_der.size(), options); + reinterpret_cast<const char*>(client_cert_der.data()), + client_cert_der.size(), options); if (!client_cert_x509) return RespondNow(Error(platform_keys::kErrorInvalidX509Cert)); client_certs->push_back(client_cert_x509); @@ -344,7 +346,7 @@ if (error_message.empty()) Respond(ArgumentList(api_pki::Sign::Results::Create( - std::vector<char>(signature.begin(), signature.end())))); + std::vector<uint8_t>(signature.begin(), signature.end())))); else Respond(Error(error_message)); }
diff --git a/chrome/browser/extensions/api/platform_keys/verify_trust_api.cc b/chrome/browser/extensions/api/platform_keys/verify_trust_api.cc index e1e4d05..686f3b53d 100644 --- a/chrome/browser/extensions/api/platform_keys/verify_trust_api.cc +++ b/chrome/browser/extensions/api/platform_keys/verify_trust_api.cc
@@ -162,7 +162,8 @@ } std::vector<base::StringPiece> der_cert_chain; - for (const std::vector<char>& cert_der : details.server_certificate_chain) { + for (const std::vector<uint8_t>& cert_der : + details.server_certificate_chain) { if (cert_der.empty()) { callback.Run(platform_keys::kErrorInvalidX509Cert, 0, 0); return;
diff --git a/chrome/browser/extensions/api/resources_private/resources_private_api.cc b/chrome/browser/extensions/api/resources_private/resources_private_api.cc index 7c3068a..bf1d431 100644 --- a/chrome/browser/extensions/api/resources_private/resources_private_api.cc +++ b/chrome/browser/extensions/api/resources_private/resources_private_api.cc
@@ -45,9 +45,6 @@ SetL10nString(dict, "pageReload", IDS_PDF_PAGE_RELOAD_BUTTON); SetL10nString(dict, "bookmarks", IDS_PDF_BOOKMARKS); SetL10nString(dict, "labelPageNumber", IDS_PDF_LABEL_PAGE_NUMBER); - SetL10nString(dict, "saveCalledTitle", IDS_PDF_SAVE_CALLED_TITLE); - SetL10nString(dict, "saveCalledText", IDS_PDF_SAVE_CALLED_TEXT); - SetL10nString(dict, "saveCalledButton", IDS_OK); SetL10nString(dict, "tooltipRotateCW", IDS_PDF_TOOLTIP_ROTATE_CW); SetL10nString(dict, "tooltipDownload", IDS_PDF_TOOLTIP_DOWNLOAD); SetL10nString(dict, "tooltipPrint", IDS_PDF_TOOLTIP_PRINT);
diff --git a/chrome/browser/extensions/api/settings_private/chromeos_resolve_time_zone_by_geolocation_on_off.cc b/chrome/browser/extensions/api/settings_private/chromeos_resolve_time_zone_by_geolocation_on_off.cc index f261f06..63e56da 100644 --- a/chrome/browser/extensions/api/settings_private/chromeos_resolve_time_zone_by_geolocation_on_off.cc +++ b/chrome/browser/extensions/api/settings_private/chromeos_resolve_time_zone_by_geolocation_on_off.cc
@@ -66,10 +66,12 @@ if (!value->is_bool()) return SetPrefResult::PREF_TYPE_MISMATCH; - // Check if preference is policy or primary-user controlled. + // Check if preference is policy or primary-user controlled, or if the user is + // a child, and therefore cannot deactivate automatic timezone. if (chromeos::system::TimeZoneResolverManager:: IsTimeZoneResolutionPolicyControlled() || - !profile_->IsSameProfile(ProfileManager::GetPrimaryUserProfile())) { + !profile_->IsSameProfile(ProfileManager::GetPrimaryUserProfile()) || + profile_->IsChild()) { return SetPrefResult::PREF_NOT_MODIFIABLE; }
diff --git a/chrome/browser/extensions/api/settings_private/generated_time_zone_pref_base.cc b/chrome/browser/extensions/api/settings_private/generated_time_zone_pref_base.cc index 1e3d563..de95d889 100644 --- a/chrome/browser/extensions/api/settings_private/generated_time_zone_pref_base.cc +++ b/chrome/browser/extensions/api/settings_private/generated_time_zone_pref_base.cc
@@ -36,8 +36,11 @@ void GeneratedTimeZonePrefBase::UpdateTimeZonePrefControlledBy( settings_api::PrefObject* out_pref) const { - if (chromeos::system::TimeZoneResolverManager:: - IsTimeZoneResolutionPolicyControlled()) { + if (profile_->IsChild()) { + out_pref->controlled_by = settings_api::CONTROLLED_BY_USER_POLICY; + out_pref->enforcement = settings_api::ENFORCEMENT_ENFORCED; + } else if (chromeos::system::TimeZoneResolverManager:: + IsTimeZoneResolutionPolicyControlled()) { out_pref->controlled_by = settings_api::CONTROLLED_BY_DEVICE_POLICY; out_pref->enforcement = settings_api::ENFORCEMENT_ENFORCED; } else if (!profile_->IsSameProfile(
diff --git a/chrome/browser/extensions/api/socket/combined_socket_unittest.cc b/chrome/browser/extensions/api/socket/combined_socket_unittest.cc new file mode 100644 index 0000000..6feb6fe9 --- /dev/null +++ b/chrome/browser/extensions/api/socket/combined_socket_unittest.cc
@@ -0,0 +1,145 @@ +// 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 <memory> + +#include "chrome/browser/extensions/api/socket/mock_tcp_client_socket.h" +#include "extensions/browser/api/socket/socket.h" +#include "extensions/browser/api/socket/tcp_socket.h" +#include "extensions/browser/api/socket/tls_socket.h" +#include "net/socket/stream_socket.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace extensions { + +const int kBufferLength = 10; + +template <typename T> +std::unique_ptr<T> CreateTestSocket( + std::unique_ptr<MockTCPClientSocket> stream); + +template <> +std::unique_ptr<TCPSocket> CreateTestSocket( + std::unique_ptr<MockTCPClientSocket> stream) { + return std::make_unique<TCPSocket>(std::move(stream), "fake id", + true /* is_connected */); +} + +template <> +std::unique_ptr<TLSSocket> CreateTestSocket( + std::unique_ptr<MockTCPClientSocket> stream) { + return std::make_unique<TLSSocket>(std::move(stream), "fake id"); +} + +class CombinedSocketTest : public testing::Test { + public: + CombinedSocketTest() : count_(0), io_buffer_(nullptr) {} + + // Strict test for synchronous (immediate) read behavior + template <typename T> + void TestRead() { + net::IOBuffer* buffer = nullptr; + + std::unique_ptr<MockTCPClientSocket> stream( + new testing::StrictMock<MockTCPClientSocket>()); + EXPECT_CALL(*stream, Read(testing::NotNull(), kBufferLength, testing::_)) + .WillOnce(DoAll(testing::SaveArg<0>(&buffer), + testing::Return(kBufferLength))); + EXPECT_CALL(*stream, Disconnect()); + + std::unique_ptr<T> socket = CreateTestSocket<T>(std::move(stream)); + ReadCompletionCallback read_callback = + base::Bind(&CombinedSocketTest::OnRead, base::Unretained(this)); + socket->Read(kBufferLength, read_callback); + EXPECT_EQ(kBufferLength, count_); + EXPECT_NE(nullptr, buffer); + EXPECT_EQ(buffer, io_buffer_); + } + + // Strict test for async read behavior (read returns PENDING) + template <typename T> + void TestReadPending() { + net::IOBuffer* buffer = nullptr; + net::CompletionCallback socket_cb; + + std::unique_ptr<MockTCPClientSocket> stream( + new testing::StrictMock<MockTCPClientSocket>()); + EXPECT_CALL(*stream, Read(testing::NotNull(), kBufferLength, testing::_)) + .WillOnce(DoAll(testing::SaveArg<0>(&buffer), + testing::SaveArg<2>(&socket_cb), + testing::Return(net::ERR_IO_PENDING))); + EXPECT_CALL(*stream, Disconnect()); + + std::unique_ptr<T> socket = CreateTestSocket<T>(std::move(stream)); + ReadCompletionCallback read_callback = + base::Bind(&CombinedSocketTest::OnRead, base::Unretained(this)); + socket->Read(kBufferLength, read_callback); + EXPECT_EQ(0, count_); + EXPECT_EQ(nullptr, io_buffer_); + socket_cb.Run(kBufferLength); + EXPECT_EQ(kBufferLength, count_); + EXPECT_NE(nullptr, buffer); + EXPECT_EQ(buffer, io_buffer_); + } + + // Even if the socket is closed, it may still have data left to read. + template <typename T> + void TestReadAfterDisconnect() { + net::IOBuffer* buffer = nullptr; + + std::unique_ptr<MockTCPClientSocket> stream( + new testing::NiceMock<MockTCPClientSocket>()); + EXPECT_CALL(*stream, Read(testing::NotNull(), kBufferLength, testing::_)) + .WillOnce(DoAll(testing::SaveArg<0>(&buffer), + testing::Return(kBufferLength))); + ON_CALL(*stream, IsConnected()).WillByDefault(testing::Return(false)); + EXPECT_CALL(*stream, Disconnect()); + + std::unique_ptr<T> socket = CreateTestSocket<T>(std::move(stream)); + ReadCompletionCallback read_callback = + base::Bind(&CombinedSocketTest::OnRead, base::Unretained(this)); + socket->Read(kBufferLength, read_callback); + EXPECT_EQ(kBufferLength, count_); + EXPECT_NE(nullptr, buffer); + EXPECT_EQ(buffer, io_buffer_); + } + + void OnRead(int count, + scoped_refptr<net::IOBuffer> io_buffer, + bool socket_destroying) { + count_ = count; + io_buffer_ = io_buffer.get(); + } + + protected: + int count_; + net::IOBuffer* io_buffer_; +}; + +TEST_F(CombinedSocketTest, TlsRead) { + TestRead<TLSSocket>(); +} + +TEST_F(CombinedSocketTest, TcpRead) { + TestRead<TCPSocket>(); +} + +TEST_F(CombinedSocketTest, TlsReadPending) { + TestReadPending<TLSSocket>(); +} + +TEST_F(CombinedSocketTest, TcpReadPending) { + TestReadPending<TCPSocket>(); +} + +TEST_F(CombinedSocketTest, TlsReadAfterDisconnect) { + TestReadAfterDisconnect<TLSSocket>(); +} + +TEST_F(CombinedSocketTest, TcpReadAfterDisconnect) { + TestReadAfterDisconnect<TCPSocket>(); +} + +} // namespace extensions
diff --git a/chrome/browser/extensions/api/socket/mock_tcp_client_socket.h b/chrome/browser/extensions/api/socket/mock_tcp_client_socket.h new file mode 100644 index 0000000..fddad10 --- /dev/null +++ b/chrome/browser/extensions/api/socket/mock_tcp_client_socket.h
@@ -0,0 +1,82 @@ +// 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. + +#ifndef CHROME_BROWSER_EXTENSIONS_API_SOCKET_MOCK_TCP_CLIENT_SOCKET_H_ +#define CHROME_BROWSER_EXTENSIONS_API_SOCKET_MOCK_TCP_CLIENT_SOCKET_H_ + +#include "base/callback_helpers.h" +#include "net/log/net_log_source.h" +#include "net/log/net_log_with_source.h" +#include "net/socket/tcp_client_socket.h" +#include "net/traffic_annotation/network_traffic_annotation_test_helper.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace extensions { +class MockTCPClientSocket : public net::TCPClientSocket { + public: + MockTCPClientSocket(); + ~MockTCPClientSocket() override; + + int Read(net::IOBuffer* buffer, + int bytes, + net::CompletionOnceCallback callback) override { + return Read(buffer, bytes, + base::AdaptCallbackForRepeating(std::move(callback))); + } + + int Write(net::IOBuffer* buffer, + int bytes, + net::CompletionOnceCallback callback, + const net::NetworkTrafficAnnotationTag& tag) override { + return Write(buffer, bytes, + base::AdaptCallbackForRepeating(std::move(callback)), tag); + } + + int Connect(net::CompletionOnceCallback callback) override { + return Connect(base::AdaptCallbackForRepeating(std::move(callback))); + } + + MOCK_METHOD3(Read, int(net::IOBuffer*, int, const net::CompletionCallback&)); + MOCK_METHOD4(Write, + int(net::IOBuffer*, + int, + const net::CompletionCallback&, + const net::NetworkTrafficAnnotationTag&)); + MOCK_METHOD1(SetReceiveBufferSize, int(int32_t)); + MOCK_METHOD1(SetSendBufferSize, int(int32_t)); + MOCK_METHOD1(Connect, int(const net::CompletionCallback&)); + MOCK_METHOD0(Disconnect, void()); + MOCK_CONST_METHOD0(IsConnected, bool()); + MOCK_CONST_METHOD0(IsConnectedAndIdle, bool()); + MOCK_CONST_METHOD1(GetPeerAddress, int(net::IPEndPoint*)); + MOCK_CONST_METHOD1(GetLocalAddress, int(net::IPEndPoint*)); + MOCK_CONST_METHOD0(NetLog, const net::NetLogWithSource&()); + MOCK_CONST_METHOD0(WasEverUsed, bool()); + MOCK_CONST_METHOD0(UsingTCPFastOpen, bool()); + MOCK_CONST_METHOD0(NumBytesRead, int64_t()); + MOCK_CONST_METHOD0(GetConnectTimeMicros, base::TimeDelta()); + MOCK_CONST_METHOD0(WasAlpnNegotiated, bool()); + MOCK_CONST_METHOD0(GetNegotiatedProtocol, net::NextProto()); + MOCK_METHOD1(GetSSLInfo, bool(net::SSLInfo*)); + MOCK_CONST_METHOD1(GetConnectionAttempts, void(net::ConnectionAttempts*)); + MOCK_METHOD0(ClearConnectionAttempts, void()); + MOCK_METHOD1(AddConnectionAttempts, void(const net::ConnectionAttempts&)); + MOCK_CONST_METHOD0(GetTotalReceivedBytes, int64_t()); + + // Methods specific to MockTCPClientSocket + MOCK_METHOD1(Bind, int(const net::IPEndPoint&)); + MOCK_METHOD2(SetKeepAlive, bool(bool, int)); + MOCK_METHOD1(SetNoDelay, bool(bool)); +}; + +MockTCPClientSocket::MockTCPClientSocket() + : TCPClientSocket(net::AddressList(), + nullptr, + nullptr, + net::NetLogSource()) {} +MockTCPClientSocket::~MockTCPClientSocket() {} + +} // namespace extensions + +#endif // CHROME_BROWSER_EXTENSIONS_API_SOCKET_MOCK_TCP_CLIENT_SOCKET_H_
diff --git a/chrome/browser/extensions/api/socket/tcp_socket_unittest.cc b/chrome/browser/extensions/api/socket/tcp_socket_unittest.cc index 90c7937..6351e3d 100644 --- a/chrome/browser/extensions/api/socket/tcp_socket_unittest.cc +++ b/chrome/browser/extensions/api/socket/tcp_socket_unittest.cc
@@ -4,717 +4,274 @@ #include <memory> +#include "base/callback_helpers.h" #include "base/macros.h" -#include "base/memory/scoped_refptr.h" -#include "base/test/bind_test_util.h" -#include "chrome/browser/extensions/extension_service_test_base.h" -#include "chrome/test/base/testing_profile.h" -#include "content/public/browser/browser_context.h" -#include "content/public/test/test_storage_partition.h" #include "extensions/browser/api/socket/tcp_socket.h" #include "net/base/address_list.h" #include "net/base/completion_callback.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" -#include "net/base/test_completion_callback.h" -#include "net/socket/socket_test_util.h" +#include "net/base/rand_callback.h" +#include "net/log/net_log_source.h" +#include "net/socket/tcp_client_socket.h" +#include "net/socket/tcp_server_socket.h" #include "net/traffic_annotation/network_traffic_annotation.h" -#include "net/url_request/url_request_test_util.h" -#include "services/network/network_context.h" -#include "services/network/public/mojom/network_context.mojom.h" +#include "testing/gmock/include/gmock/gmock.h" + +using testing::_; +using testing::DoAll; +using testing::Return; +using testing::SaveArg; namespace extensions { -namespace { +class MockTCPSocket : public net::TCPClientSocket { + public: + explicit MockTCPSocket(const net::AddressList& address_list) + : net::TCPClientSocket(address_list, NULL, NULL, net::NetLogSource()) {} -const char kTestMsg[] = "abcdefghij"; -const int kTestMsgLength = strlen(kTestMsg); + int Read(net::IOBuffer* buffer, + int bytes, + net::CompletionOnceCallback callback) override { + return Read(buffer, bytes, + base::AdaptCallbackForRepeating(std::move(callback))); + } + + int Write(net::IOBuffer* buffer, + int bytes, + net::CompletionOnceCallback callback, + const net::NetworkTrafficAnnotationTag& tag) override { + return Write(buffer, bytes, + base::AdaptCallbackForRepeating(std::move(callback)), tag); + } + + MOCK_METHOD3(Read, int(net::IOBuffer* buf, int buf_len, + const net::CompletionCallback& callback)); + MOCK_METHOD4(Write, + int(net::IOBuffer* buf, + int buf_len, + const net::CompletionCallback& callback, + const net::NetworkTrafficAnnotationTag&)); + MOCK_METHOD2(SetKeepAlive, bool(bool enable, int delay)); + MOCK_METHOD1(SetNoDelay, bool(bool no_delay)); + bool IsConnected() const override { + return true; + } + + private: + DISALLOW_COPY_AND_ASSIGN(MockTCPSocket); +}; + +class MockTCPServerSocket : public net::TCPServerSocket { + public: + MockTCPServerSocket() : net::TCPServerSocket(NULL, net::NetLogSource()) {} + MOCK_METHOD2(Listen, int(const net::IPEndPoint& address, int backlog)); + MOCK_METHOD2(Accept, + int(std::unique_ptr<net::StreamSocket>* socket, + const net::CompletionCallback& callback)); + + private: + DISALLOW_COPY_AND_ASSIGN(MockTCPServerSocket); +}; + +class CompleteHandler { + public: + CompleteHandler() {} + MOCK_METHOD1(OnComplete, void(int result_code)); + MOCK_METHOD3(OnReadComplete, + void(int result_code, + scoped_refptr<net::IOBuffer> io_buffer, + bool socket_destroying)); + + // MOCK_METHOD cannot mock a scoped_ptr argument. + MOCK_METHOD2(OnAcceptMock, void(int, net::TCPClientSocket*)); + void OnAccept(int count, std::unique_ptr<net::TCPClientSocket> socket) { + OnAcceptMock(count, socket.get()); + } + + private: + DISALLOW_COPY_AND_ASSIGN(CompleteHandler); +}; const char FAKE_ID[] = "abcdefghijklmnopqrst"; -class TCPSocketUnitTestBase : public extensions::ExtensionServiceTestBase { - public: - TCPSocketUnitTestBase() - : url_request_context_(true /* delay_initialization */) {} - ~TCPSocketUnitTestBase() override {} +TEST(SocketTest, TestTCPSocketRead) { + net::AddressList address_list; + std::unique_ptr<MockTCPSocket> tcp_client_socket( + new MockTCPSocket(address_list)); + CompleteHandler handler; - std::unique_ptr<TCPSocket> CreateSocket() { - auto socket = std::make_unique<TCPSocket>(&profile_, FAKE_ID); - socket->SetStoragePartitionForTest(&partition_); - return socket; - } + EXPECT_CALL(*tcp_client_socket, Read(_, _, _)) + .Times(1); + EXPECT_CALL(handler, OnReadComplete(_, _, _)).Times(1); - std::unique_ptr<TCPSocket> CreateAndConnectSocketWithAddress( - const net::IPEndPoint& ip_end_point) { - auto socket = CreateSocket(); - net::AddressList address(ip_end_point); - net::TestCompletionCallback callback; - socket->Connect(address, callback.callback()); - EXPECT_EQ(net::OK, callback.WaitForResult()); - return socket; - } - - std::unique_ptr<TCPSocket> CreateAndConnectSocket() { - net::IPEndPoint ip_end_point(net::IPAddress::IPv4Localhost(), 1234); - return CreateAndConnectSocketWithAddress(ip_end_point); - } - - // Reads data from |socket| and compares it with |expected_data|. - void ReadData(Socket* socket, const std::string& expected_data) { - std::string received_data; - const int count = 512; - while (true) { - base::RunLoop run_loop; - int net_error = net::ERR_FAILED; - socket->Read(count, - base::BindLambdaForTesting( - [&](int result, scoped_refptr<net::IOBuffer> io_buffer, - bool socket_destroying) { - net_error = result; - EXPECT_FALSE(socket_destroying); - if (result > 0) - received_data.append(io_buffer->data(), result); - run_loop.Quit(); - })); - run_loop.Run(); - if (net_error <= 0) - break; - } - EXPECT_EQ(expected_data, received_data); - } - - protected: - // extensions::ExtensionServiceTestBase implementation. - void SetUp() override { InitializeEmptyExtensionService(); } - - void Initialize() { - url_request_context_.Init(); - network_context_ = std::make_unique<network::NetworkContext>( - nullptr, mojo::MakeRequest(&network_context_ptr_), - &url_request_context_); - partition_.set_network_context(network_context_ptr_.get()); - } - - net::TestURLRequestContext url_request_context_; - - private: - TestingProfile profile_; - content::TestStoragePartition partition_; - std::unique_ptr<network::NetworkContext> network_context_; - network::mojom::NetworkContextPtr network_context_ptr_; -}; - -} // namespace - -class TCPSocketUnitTest : public TCPSocketUnitTestBase, - public ::testing::WithParamInterface<net::IoMode> { - public: - TCPSocketUnitTest() : TCPSocketUnitTestBase() { - mock_client_socket_factory_.set_enable_read_if_ready(true); - url_request_context_.set_client_socket_factory( - &mock_client_socket_factory_); - Initialize(); - } - ~TCPSocketUnitTest() override {} - - net::MockClientSocketFactory* mock_client_socket_factory() { - return &mock_client_socket_factory_; - } - - private: - net::MockClientSocketFactory mock_client_socket_factory_; -}; - -INSTANTIATE_TEST_CASE_P(/* no prefix */, - TCPSocketUnitTest, - testing::Values(net::SYNCHRONOUS, net::ASYNC)); - -TEST_F(TCPSocketUnitTest, SocketConnectError) { - net::IPEndPoint ip_end_point(net::IPAddress::IPv4Localhost(), 1234); - net::StaticSocketDataProvider data_provider((base::span<net::MockRead>()), - base::span<net::MockWrite>()); - data_provider.set_connect_data( - net::MockConnect(net::ASYNC, net::ERR_FAILED, ip_end_point)); - mock_client_socket_factory()->AddSocketDataProvider(&data_provider); - std::unique_ptr<TCPSocket> socket = CreateSocket(); - - net::AddressList address(ip_end_point); - net::TestCompletionCallback callback; - socket->Connect(address, callback.callback()); - EXPECT_EQ(net::ERR_FAILED, callback.WaitForResult()); -} - -TEST_P(TCPSocketUnitTest, SocketConnectAfterDisconnect) { - net::IoMode io_mode = GetParam(); - const net::MockRead kReads[] = {net::MockRead(io_mode, net::OK)}; - net::StaticSocketDataProvider data_provider1(kReads, - base::span<net::MockWrite>()); - net::StaticSocketDataProvider data_provider2(kReads, - base::span<net::MockWrite>()); - mock_client_socket_factory()->AddSocketDataProvider(&data_provider1); - mock_client_socket_factory()->AddSocketDataProvider(&data_provider2); - std::unique_ptr<TCPSocket> socket = CreateAndConnectSocket(); - socket->Disconnect(false /* socket_destroying */); - net::TestCompletionCallback callback2; - net::IPEndPoint ip_end_point(net::IPAddress::IPv4Localhost(), 1234); - net::AddressList address(ip_end_point); - socket->Connect(address, callback2.callback()); - EXPECT_EQ(net::OK, callback2.WaitForResult()); - - EXPECT_TRUE(data_provider1.AllReadDataConsumed()); - EXPECT_TRUE(data_provider1.AllWriteDataConsumed()); - EXPECT_TRUE(data_provider2.AllReadDataConsumed()); - EXPECT_TRUE(data_provider2.AllWriteDataConsumed()); -} - -TEST_F(TCPSocketUnitTest, DestroyWhileReadPending) { - const net::MockRead kReads[] = { - net::MockRead(net::SYNCHRONOUS, net::ERR_IO_PENDING)}; - net::StaticSocketDataProvider data_provider(kReads, - base::span<net::MockWrite>()); - mock_client_socket_factory()->AddSocketDataProvider(&data_provider); - std::unique_ptr<TCPSocket> socket = CreateAndConnectSocket(); - - int net_result = net::ERR_FAILED; - base::RunLoop run_loop; - int count = 1; - // Read one byte, and it should be pending. - socket->Read(count, - base::BindLambdaForTesting( - [&](int result, scoped_refptr<net::IOBuffer> io_buffer, - bool socket_destroying) { - net_result = result; - // |socket_destroying| should correctly denote that this - // read callback is invoked through the destructor of - // TCPSocket. - EXPECT_TRUE(socket_destroying); - run_loop.Quit(); - })); - // Destroy socket. - socket = nullptr; - // Wait for read callback. - run_loop.Run(); - EXPECT_EQ(net::ERR_CONNECTION_CLOSED, net_result); -} - -TEST_P(TCPSocketUnitTest, Read) { - net::IoMode io_mode = GetParam(); - const net::MockRead kReads[] = { - net::MockRead(io_mode, kTestMsg, kTestMsgLength), - net::MockRead(io_mode, net::OK)}; - net::StaticSocketDataProvider data_provider(kReads, - base::span<net::MockWrite>()); - - mock_client_socket_factory()->AddSocketDataProvider(&data_provider); - std::unique_ptr<TCPSocket> socket = CreateAndConnectSocket(); - - ReadData(socket.get(), kTestMsg); - EXPECT_TRUE(data_provider.AllReadDataConsumed()); - EXPECT_TRUE(data_provider.AllWriteDataConsumed()); -} - -// Tests the case where a message is split over two separate socket reads. -TEST_P(TCPSocketUnitTest, SocketMultipleRead) { - const char kFirstHalfTestMsg[] = "abcde"; - const char kSecondHalfTestMsg[] = "fghij"; - EXPECT_EQ(kTestMsg, std::string(kFirstHalfTestMsg) + kSecondHalfTestMsg); - net::IoMode io_mode = GetParam(); - const net::MockRead kReads[] = { - net::MockRead(io_mode, kFirstHalfTestMsg, strlen(kFirstHalfTestMsg)), - net::MockRead(io_mode, kSecondHalfTestMsg, strlen(kSecondHalfTestMsg)), - net::MockRead(io_mode, net::OK)}; - net::StaticSocketDataProvider data_provider(kReads, - base::span<net::MockWrite>()); - - mock_client_socket_factory()->AddSocketDataProvider(&data_provider); - std::unique_ptr<TCPSocket> socket = CreateAndConnectSocket(); - - ReadData(socket.get(), kTestMsg); - EXPECT_TRUE(data_provider.AllReadDataConsumed()); - EXPECT_TRUE(data_provider.AllWriteDataConsumed()); -} - -// Tests the case where read size is smaller than the actual message. -TEST_P(TCPSocketUnitTest, SocketPartialRead) { - net::IoMode io_mode = GetParam(); - const net::MockRead kReads[] = { - net::MockRead(io_mode, kTestMsg, kTestMsgLength), - net::MockRead(io_mode, net::OK)}; - net::StaticSocketDataProvider data_provider(kReads, - base::span<net::MockWrite>()); - mock_client_socket_factory()->AddSocketDataProvider(&data_provider); - std::unique_ptr<TCPSocket> socket = CreateAndConnectSocket(); - - int count = 1; - std::string received_data; - while (true) { - int net_result = net::ERR_FAILED; - base::RunLoop run_loop; - socket->Read(count, - base::BindLambdaForTesting( - [&](int result, scoped_refptr<net::IOBuffer> io_buffer, - bool socket_destroying) { - net_result = result; - EXPECT_FALSE(socket_destroying); - if (result > 0) - received_data.append(io_buffer->data(), result); - run_loop.Quit(); - })); - run_loop.Run(); - if (net_result <= 0) - break; - // Double the read size in the next iteration. - count *= 2; - } - EXPECT_EQ(kTestMsg, received_data); - EXPECT_TRUE(data_provider.AllReadDataConsumed()); - EXPECT_TRUE(data_provider.AllWriteDataConsumed()); -} - -TEST_P(TCPSocketUnitTest, ReadError) { - net::IoMode io_mode = GetParam(); - const net::MockRead kReads[] = { - net::MockRead(io_mode, kTestMsg, kTestMsgLength), - net::MockRead(io_mode, net::ERR_INSUFFICIENT_RESOURCES)}; - net::StaticSocketDataProvider data_provider(kReads, - base::span<net::MockWrite>()); - mock_client_socket_factory()->AddSocketDataProvider(&data_provider); - std::unique_ptr<TCPSocket> socket = CreateAndConnectSocket(); + std::unique_ptr<TCPSocket> socket(TCPSocket::CreateSocketForTesting( + std::move(tcp_client_socket), FAKE_ID, true)); const int count = 512; - int net_error = net::OK; - while (true) { - base::RunLoop run_loop; - socket->Read(count, - base::BindLambdaForTesting( - [&](int result, scoped_refptr<net::IOBuffer> io_buffer, - bool socket_destroying) { - net_error = result; - EXPECT_FALSE(socket_destroying); - if (result <= 0) { - EXPECT_FALSE(socket->IsConnected()); - EXPECT_EQ(nullptr, io_buffer); - } else { - EXPECT_TRUE(socket->IsConnected()); - } - run_loop.Quit(); - })); - run_loop.Run(); - if (net_error < 0) - break; - } - // Note that TCPSocket only detects that receive pipe is broken and propagates - // it as a net::ERR_FAILED. It doesn't know the specific net error code. To do - // that, it needs to register itself as a network::mojom::SocketObserver. - EXPECT_EQ(net::ERR_FAILED, net_error); - EXPECT_TRUE(data_provider.AllReadDataConsumed()); - EXPECT_TRUE(data_provider.AllWriteDataConsumed()); + socket->Read(count, base::Bind(&CompleteHandler::OnReadComplete, + base::Unretained(&handler))); } -TEST_P(TCPSocketUnitTest, Write) { - net::IoMode io_mode = GetParam(); - const net::MockRead kReads[] = { - net::MockRead(net::SYNCHRONOUS, net::ERR_IO_PENDING)}; - const net::MockWrite kWrites[] = { - net::MockWrite(io_mode, kTestMsg, kTestMsgLength)}; +TEST(SocketTest, TestTCPSocketWrite) { + net::AddressList address_list; + std::unique_ptr<MockTCPSocket> tcp_client_socket( + new MockTCPSocket(address_list)); + CompleteHandler handler; - net::StaticSocketDataProvider data_provider(kReads, kWrites); + net::CompletionCallback callback; + EXPECT_CALL(*tcp_client_socket, Write(_, _, _, _)) + .Times(2) + .WillRepeatedly(testing::DoAll(SaveArg<2>(&callback), Return(128))); + EXPECT_CALL(handler, OnComplete(_)) + .Times(1); - mock_client_socket_factory()->AddSocketDataProvider(&data_provider); - std::unique_ptr<TCPSocket> socket = CreateAndConnectSocket(); + std::unique_ptr<TCPSocket> socket(TCPSocket::CreateSocketForTesting( + std::move(tcp_client_socket), FAKE_ID, true)); - auto io_buffer = base::MakeRefCounted<net::StringIOBuffer>(kTestMsg); - net::TestCompletionCallback write_callback; - socket->Write(io_buffer.get(), kTestMsgLength, write_callback.callback()); - EXPECT_EQ(kTestMsgLength, write_callback.WaitForResult()); + scoped_refptr<net::IOBufferWithSize> io_buffer( + new net::IOBufferWithSize(256)); + socket->Write(io_buffer.get(), io_buffer->size(), + base::Bind(&CompleteHandler::OnComplete, base::Unretained(&handler))); } -// Tests the case where a message is split over two separate socket writes. -TEST_P(TCPSocketUnitTest, MultipleWrite) { - const char kFirstHalfTestMsg[] = "abcde"; - const char kSecondHalfTestMsg[] = "fghij"; - EXPECT_EQ(kTestMsg, std::string(kFirstHalfTestMsg) + kSecondHalfTestMsg); - net::IoMode io_mode = GetParam(); - const net::MockRead kReads[] = { - net::MockRead(net::SYNCHRONOUS, net::ERR_IO_PENDING)}; - const net::MockWrite kWrites[] = { - net::MockWrite(io_mode, kFirstHalfTestMsg, strlen(kFirstHalfTestMsg)), - net::MockWrite(io_mode, kSecondHalfTestMsg, strlen(kSecondHalfTestMsg))}; +TEST(SocketTest, TestTCPSocketBlockedWrite) { + net::AddressList address_list; + std::unique_ptr<MockTCPSocket> tcp_client_socket( + new MockTCPSocket(address_list)); + CompleteHandler handler; - net::StaticSocketDataProvider data_provider(kReads, kWrites); - mock_client_socket_factory()->AddSocketDataProvider(&data_provider); - std::unique_ptr<TCPSocket> socket = CreateAndConnectSocket(); + net::CompletionCallback callback; + EXPECT_CALL(*tcp_client_socket, Write(_, _, _, _)) + .Times(2) + .WillRepeatedly( + testing::DoAll(SaveArg<2>(&callback), Return(net::ERR_IO_PENDING))); - int num_bytes_written = 0; - auto io_buffer = base::MakeRefCounted<net::StringIOBuffer>(kTestMsg); - auto drainable_io_buffer = base::MakeRefCounted<net::DrainableIOBuffer>( - io_buffer.get(), kTestMsgLength); - while (num_bytes_written < kTestMsgLength) { - net::TestCompletionCallback write_callback; - socket->Write(drainable_io_buffer.get(), kTestMsgLength - num_bytes_written, - write_callback.callback()); - int result = write_callback.WaitForResult(); - ASSERT_GT(result, net::OK); - drainable_io_buffer->DidConsume(result); - num_bytes_written += result; - // Flushes the write. - base::RunLoop().RunUntilIdle(); - } - EXPECT_TRUE(data_provider.AllReadDataConsumed()); - EXPECT_TRUE(data_provider.AllWriteDataConsumed()); + std::unique_ptr<TCPSocket> socket(TCPSocket::CreateSocketForTesting( + std::move(tcp_client_socket), FAKE_ID, true)); + + scoped_refptr<net::IOBufferWithSize> io_buffer(new net::IOBufferWithSize(42)); + socket->Write(io_buffer.get(), io_buffer->size(), + base::Bind(&CompleteHandler::OnComplete, base::Unretained(&handler))); + + // Good. Original call came back unable to complete. Now pretend the socket + // finished, and confirm that we passed the error back. + EXPECT_CALL(handler, OnComplete(42)) + .Times(1); + callback.Run(40); + callback.Run(2); } -TEST_P(TCPSocketUnitTest, PartialWrite) { - net::IoMode io_mode = GetParam(); - const net::MockRead kReads[] = { - net::MockRead(net::SYNCHRONOUS, net::ERR_IO_PENDING)}; - const net::MockWrite kWrites[] = { - net::MockWrite(io_mode, "a", 1), net::MockWrite(io_mode, "bc", 2), - net::MockWrite(io_mode, "defg", 4), net::MockWrite(io_mode, "hij", 3)}; +TEST(SocketTest, TestTCPSocketBlockedWriteReentry) { + net::AddressList address_list; + std::unique_ptr<MockTCPSocket> tcp_client_socket( + new MockTCPSocket(address_list)); + CompleteHandler handlers[5]; - net::StaticSocketDataProvider data_provider(kReads, kWrites); + net::CompletionCallback callback; + EXPECT_CALL(*tcp_client_socket, Write(_, _, _, _)) + .Times(5) + .WillRepeatedly( + testing::DoAll(SaveArg<2>(&callback), Return(net::ERR_IO_PENDING))); - mock_client_socket_factory()->AddSocketDataProvider(&data_provider); - std::unique_ptr<TCPSocket> socket = CreateAndConnectSocket(); + std::unique_ptr<TCPSocket> socket(TCPSocket::CreateSocketForTesting( + std::move(tcp_client_socket), FAKE_ID, true)); - // Start with writing one byte, and double that in the next iteration. - int num_bytes_to_write = 1; - int num_bytes_written = 0; - auto io_buffer = base::MakeRefCounted<net::StringIOBuffer>(kTestMsg); - auto drainable_io_buffer = base::MakeRefCounted<net::DrainableIOBuffer>( - io_buffer.get(), kTestMsgLength); - while (num_bytes_written < kTestMsgLength) { - net::TestCompletionCallback write_callback; - socket->Write( - drainable_io_buffer.get(), - std::max(kTestMsgLength - num_bytes_written, num_bytes_to_write), - write_callback.callback()); - int result = write_callback.WaitForResult(); - ASSERT_GT(result, net::OK); - drainable_io_buffer->DidConsume(result); - num_bytes_written += result; - num_bytes_to_write *= 2; - // Flushes the write. - base::RunLoop().RunUntilIdle(); + scoped_refptr<net::IOBufferWithSize> io_buffers[5]; + int i; + for (i = 0; i < 5; i++) { + io_buffers[i] = new net::IOBufferWithSize(128 + i * 50); + scoped_refptr<net::IOBufferWithSize> io_buffer1( + new net::IOBufferWithSize(42)); + socket->Write(io_buffers[i].get(), io_buffers[i]->size(), + base::Bind(&CompleteHandler::OnComplete, + base::Unretained(&handlers[i]))); + + EXPECT_CALL(handlers[i], OnComplete(io_buffers[i]->size())) + .Times(1); } - EXPECT_TRUE(data_provider.AllReadDataConsumed()); - EXPECT_TRUE(data_provider.AllWriteDataConsumed()); + + for (i = 0; i < 5; i++) { + callback.Run(128 + i * 50); + } } -TEST_P(TCPSocketUnitTest, WriteError) { - net::IoMode io_mode = GetParam(); - const net::MockRead kReads[] = { - net::MockRead(net::SYNCHRONOUS, net::ERR_IO_PENDING)}; - const net::MockWrite kWrites[] = { - net::MockWrite(io_mode, net::ERR_INSUFFICIENT_RESOURCES)}; +TEST(SocketTest, TestTCPSocketSetNoDelay) { + net::AddressList address_list; + std::unique_ptr<MockTCPSocket> tcp_client_socket( + new MockTCPSocket(address_list)); - net::StaticSocketDataProvider data_provider(kReads, kWrites); - - mock_client_socket_factory()->AddSocketDataProvider(&data_provider); - std::unique_ptr<TCPSocket> socket = CreateAndConnectSocket(); - - // Mojo data pipe might buffer some write data, so continue writing until the - // write error is received. - auto io_buffer = base::MakeRefCounted<net::StringIOBuffer>(kTestMsg); - int net_error = net::OK; - while (true) { - base::RunLoop run_loop; - socket->Write(io_buffer.get(), kTestMsgLength, - base::BindLambdaForTesting([&](int result) { - EXPECT_EQ(result > 0, socket->IsConnected()); - net_error = result; - run_loop.Quit(); - })); - run_loop.Run(); - if (net_error <= 0) - break; - } - // Note that TCPSocket only detects that send pipe is broken and propagates - // it as a net::ERR_FAILED. It doesn't know the specific net error code. To do - // that, it needs to register itself as a network::mojom::SocketObserver. - EXPECT_EQ(net::ERR_FAILED, net_error); - EXPECT_TRUE(data_provider.AllReadDataConsumed()); - EXPECT_TRUE(data_provider.AllWriteDataConsumed()); -} - -namespace { - -class ExtensionsMockClientSocket : public net::MockTCPClientSocket { - public: - ExtensionsMockClientSocket(net::SocketDataProvider* provider, bool success) - : MockTCPClientSocket( - net::AddressList( - net::IPEndPoint(net::IPAddress::IPv4Localhost(), 1234)), - nullptr /* netlog */, - provider), - success_(success) { - this->set_enable_read_if_ready(true); - } - ~ExtensionsMockClientSocket() override {} - - bool SetNoDelay(bool no_delay) override { return success_; } - bool SetKeepAlive(bool enable, int delay) override { return success_; } - - private: - // Whether to return success for SetNoDelay() and SetKeepAlive(). - const bool success_; - - DISALLOW_COPY_AND_ASSIGN(ExtensionsMockClientSocket); -}; - -static const net::MockRead kMockReads[] = {net::MockRead(net::ASYNC, net::OK)}; - -// A ClientSocketFactory to create sockets that simulate SetNoDelay and -// SetKeepAlive success and failures. -class TestSocketFactory : public net::ClientSocketFactory { - public: - explicit TestSocketFactory(bool success) : success_(success) {} - ~TestSocketFactory() override = default; - - std::unique_ptr<net::DatagramClientSocket> CreateDatagramClientSocket( - net::DatagramSocket::BindType, - net::NetLog*, - const net::NetLogSource&) override { - NOTIMPLEMENTED(); - return nullptr; - } - std::unique_ptr<net::TransportClientSocket> CreateTransportClientSocket( - const net::AddressList&, - std::unique_ptr<net::SocketPerformanceWatcher>, - net::NetLog*, - const net::NetLogSource&) override { - providers_.push_back(std::make_unique<net::StaticSocketDataProvider>( - kMockReads, base::span<net::MockWrite>())); - return std::make_unique<ExtensionsMockClientSocket>(providers_.back().get(), - success_); - } - std::unique_ptr<net::SSLClientSocket> CreateSSLClientSocket( - std::unique_ptr<net::ClientSocketHandle>, - const net::HostPortPair&, - const net::SSLConfig&, - const net::SSLClientSocketContext&) override { - NOTIMPLEMENTED(); - return std::unique_ptr<net::SSLClientSocket>(); - } - std::unique_ptr<net::ProxyClientSocket> CreateProxyClientSocket( - std::unique_ptr<net::ClientSocketHandle> transport_socket, - const std::string& user_agent, - const net::HostPortPair& endpoint, - net::HttpAuthController* http_auth_controller, - bool tunnel, - bool using_spdy, - net::NextProto negotiated_protocol, - bool is_https_proxy, - const net::NetworkTrafficAnnotationTag& traffic_annotation) override { - NOTIMPLEMENTED(); - return nullptr; - } - void ClearSSLSessionCache() override { NOTIMPLEMENTED(); } - - private: - std::vector<std::unique_ptr<net::StaticSocketDataProvider>> providers_; - // Whether to return success for net::TransportClientSocket::SetNoDelay() and - // SetKeepAlive(). - const bool success_; - - DISALLOW_COPY_AND_ASSIGN(TestSocketFactory); -}; - -} // namespace - -class TCPSocketSettingsTest : public TCPSocketUnitTestBase, - public ::testing::WithParamInterface<bool> { - public: - TCPSocketSettingsTest() - : TCPSocketUnitTestBase(), client_socket_factory_(GetParam()) { - url_request_context_.set_client_socket_factory(&client_socket_factory_); - Initialize(); - } - ~TCPSocketSettingsTest() override {} - - private: - TestSocketFactory client_socket_factory_; -}; - -INSTANTIATE_TEST_CASE_P(/* no prefix */, - TCPSocketSettingsTest, - testing::Bool()); - -TEST_P(TCPSocketSettingsTest, SetNoDelay) { - std::unique_ptr<TCPSocket> socket = CreateAndConnectSocket(); - bool expected_success = GetParam(); + bool no_delay = false; { - base::RunLoop run_loop; - socket->SetNoDelay(true, base::BindLambdaForTesting([&](bool success) { - EXPECT_EQ(expected_success, success); - run_loop.Quit(); - })); - run_loop.Run(); + testing::InSequence dummy; + EXPECT_CALL(*tcp_client_socket, SetNoDelay(_)) + .WillOnce(testing::DoAll(SaveArg<0>(&no_delay), Return(true))); + EXPECT_CALL(*tcp_client_socket, SetNoDelay(_)) + .WillOnce(testing::DoAll(SaveArg<0>(&no_delay), Return(false))); } - { - base::RunLoop run_loop; - socket->SetNoDelay(false, base::BindLambdaForTesting([&](bool success) { - EXPECT_EQ(expected_success, success); - run_loop.Quit(); - })); - run_loop.Run(); - } + std::unique_ptr<TCPSocket> socket( + TCPSocket::CreateSocketForTesting(std::move(tcp_client_socket), FAKE_ID)); + + EXPECT_FALSE(no_delay); + int result = socket->SetNoDelay(true); + EXPECT_TRUE(result); + EXPECT_TRUE(no_delay); + + result = socket->SetNoDelay(false); + EXPECT_FALSE(result); + EXPECT_FALSE(no_delay); } -TEST_P(TCPSocketSettingsTest, SetKeepAlive) { - std::unique_ptr<TCPSocket> socket = CreateAndConnectSocket(); - bool expected_success = GetParam(); +TEST(SocketTest, TestTCPSocketSetKeepAlive) { + net::AddressList address_list; + std::unique_ptr<MockTCPSocket> tcp_client_socket( + new MockTCPSocket(address_list)); + + bool enable = false; + int delay = 0; { - base::RunLoop run_loop; - socket->SetKeepAlive(true /* enable */, 123 /* delay */, - base::BindLambdaForTesting([&](bool success) { - EXPECT_EQ(expected_success, success); - run_loop.Quit(); - })); - run_loop.Run(); + testing::InSequence dummy; + EXPECT_CALL(*tcp_client_socket, SetKeepAlive(_, _)) + .WillOnce(testing::DoAll(SaveArg<0>(&enable), SaveArg<1>(&delay), + Return(true))); + EXPECT_CALL(*tcp_client_socket, SetKeepAlive(_, _)) + .WillOnce(testing::DoAll(SaveArg<0>(&enable), SaveArg<1>(&delay), + Return(false))); } - { - base::RunLoop run_loop; - socket->SetKeepAlive(false /* enable */, 123 /* delay */, - base::BindLambdaForTesting([&](bool success) { - EXPECT_EQ(expected_success, success); - run_loop.Quit(); - })); - run_loop.Run(); - } + std::unique_ptr<TCPSocket> socket( + TCPSocket::CreateSocketForTesting(std::move(tcp_client_socket), FAKE_ID)); + + EXPECT_FALSE(enable); + int result = socket->SetKeepAlive(true, 4500); + EXPECT_TRUE(result); + EXPECT_TRUE(enable); + EXPECT_EQ(4500, delay); + + result = socket->SetKeepAlive(false, 0); + EXPECT_FALSE(result); + EXPECT_FALSE(enable); + EXPECT_EQ(0, delay); } -class TCPSocketServerTest : public TCPSocketUnitTestBase { - public: - TCPSocketServerTest() : TCPSocketUnitTestBase() { Initialize(); } - ~TCPSocketServerTest() override {} +TEST(SocketTest, TestTCPServerSocketListenAccept) { + std::unique_ptr<MockTCPServerSocket> tcp_server_socket( + new MockTCPServerSocket()); + CompleteHandler handler; - private: - net::MockClientSocketFactory mock_client_socket_factory_; -}; + EXPECT_CALL(*tcp_server_socket, Accept(_, _)).Times(1); + EXPECT_CALL(*tcp_server_socket, Listen(_, _)).Times(1); -TEST_F(TCPSocketServerTest, ListenAccept) { - // Create a server socket. - std::unique_ptr<TCPSocket> socket = CreateSocket(); - net::TestCompletionCallback callback; - base::RunLoop run_loop; - socket->Listen( - "127.0.0.1", 0 /* port */, 1 /* backlog */, - base::BindLambdaForTesting([&](int result, const std::string& error_msg) { - EXPECT_EQ(net::OK, result); - run_loop.Quit(); - })); - run_loop.Run(); - net::IPEndPoint server_addr; - EXPECT_TRUE(socket->GetLocalAddress(&server_addr)); + std::unique_ptr<TCPSocket> socket(TCPSocket::CreateServerSocketForTesting( + std::move(tcp_server_socket), FAKE_ID)); - base::RunLoop accept_run_loop; - net::IPEndPoint accept_client_addr; - socket->Accept(base::BindLambdaForTesting( - [&](int result, network::mojom::TCPConnectedSocketPtr accepted_socket, - const base::Optional<net::IPEndPoint>& remote_addr, - mojo::ScopedDataPipeConsumerHandle receive_handle, - mojo::ScopedDataPipeProducerHandle send_handle) { - EXPECT_EQ(net::OK, result); - accept_client_addr = remote_addr.value(); - accept_run_loop.Quit(); - })); + EXPECT_CALL(handler, OnAcceptMock(_, _)); - // Create a client socket to talk to the server socket. - auto client_socket = CreateAndConnectSocketWithAddress(server_addr); - accept_run_loop.Run(); - - net::IPEndPoint peer_addr; - EXPECT_TRUE(client_socket->GetPeerAddress(&peer_addr)); - net::IPEndPoint client_addr; - EXPECT_TRUE(client_socket->GetLocalAddress(&client_addr)); - EXPECT_EQ(server_addr, peer_addr); - EXPECT_EQ(client_addr, accept_client_addr); -} - -TEST_F(TCPSocketServerTest, ReadAndWrite) { - // Create a server socket. - std::unique_ptr<TCPSocket> socket = CreateSocket(); - net::TestCompletionCallback callback; - base::RunLoop run_loop; - socket->Listen( - "127.0.0.1", 0 /* port */, 1 /* backlog */, - base::BindLambdaForTesting([&](int result, const std::string& error_msg) { - EXPECT_EQ(net::OK, result); - run_loop.Quit(); - })); - run_loop.Run(); - net::IPEndPoint server_addr; - EXPECT_TRUE(socket->GetLocalAddress(&server_addr)); - - base::RunLoop accept_run_loop; - std::unique_ptr<TCPSocket> accepted_socket; - - socket->Accept(base::BindLambdaForTesting( - [&](int result, network::mojom::TCPConnectedSocketPtr connected_socket, - const base::Optional<net::IPEndPoint>& remote_addr, - mojo::ScopedDataPipeConsumerHandle receive_handle, - mojo::ScopedDataPipeProducerHandle send_handle) { - EXPECT_EQ(net::OK, result); - accepted_socket = std::make_unique<TCPSocket>( - std::move(connected_socket), std::move(receive_handle), - std::move(send_handle), remote_addr, FAKE_ID); - accept_run_loop.Quit(); - })); - - // Create a client socket to talk to the server socket. - auto client_socket = CreateAndConnectSocketWithAddress(server_addr); - net::TestCompletionCallback connect_callback; - accept_run_loop.Run(); - - // Send data from the client to the server. - auto io_buffer = base::MakeRefCounted<net::StringIOBuffer>(kTestMsg); - net::TestCompletionCallback write_callback; - client_socket->Write(io_buffer.get(), kTestMsgLength, - write_callback.callback()); - EXPECT_EQ(kTestMsgLength, write_callback.WaitForResult()); - - std::string received_contents; - while (received_contents.size() < kTestMsgLength) { - base::RunLoop run_loop; - accepted_socket->Read( - kTestMsgLength, - base::BindLambdaForTesting([&](int result, - scoped_refptr<net::IOBuffer> io_buffer, - bool socket_destroying) { - ASSERT_GT(result, 0); - EXPECT_FALSE(socket_destroying); - received_contents.append(std::string(io_buffer->data(), result)); - run_loop.Quit(); - })); - run_loop.Run(); - } - EXPECT_EQ(kTestMsg, received_contents); - - // Send data from the server to the client. - net::TestCompletionCallback write_callback2; - accepted_socket->Write(io_buffer.get(), kTestMsgLength, - write_callback2.callback()); - EXPECT_EQ(kTestMsgLength, write_callback2.WaitForResult()); - - std::string sent_contents; - while (sent_contents.size() < kTestMsgLength) { - base::RunLoop run_loop; - client_socket->Read( - kTestMsgLength, - base::BindLambdaForTesting([&](int result, - scoped_refptr<net::IOBuffer> io_buffer, - bool socket_destroying) { - ASSERT_GT(result, 0); - EXPECT_FALSE(socket_destroying); - sent_contents.append(std::string(io_buffer->data(), result)); - run_loop.Quit(); - })); - run_loop.Run(); - } - EXPECT_EQ(kTestMsg, sent_contents); + std::string err_msg; + EXPECT_EQ(net::OK, socket->Listen("127.0.0.1", 9999, 10, &err_msg)); + socket->Accept(base::Bind(&CompleteHandler::OnAccept, + base::Unretained(&handler))); } } // namespace extensions
diff --git a/chrome/browser/extensions/api/socket/tls_socket_unittest.cc b/chrome/browser/extensions/api/socket/tls_socket_unittest.cc index 5e25fcf0..678b630 100644 --- a/chrome/browser/extensions/api/socket/tls_socket_unittest.cc +++ b/chrome/browser/extensions/api/socket/tls_socket_unittest.cc
@@ -2,482 +2,372 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <stddef.h> +#include <stdint.h> + #include <memory> #include <utility> +#include "base/callback_helpers.h" +#include "base/containers/circular_deque.h" #include "base/macros.h" -#include "base/test/bind_test_util.h" -#include "chrome/browser/extensions/extension_service_test_base.h" -#include "chrome/test/base/testing_profile.h" -#include "content/public/browser/browser_context.h" -#include "content/public/test/test_storage_partition.h" +#include "base/strings/string_piece.h" #include "extensions/browser/api/socket/tls_socket.h" #include "net/base/address_list.h" #include "net/base/completion_callback.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" -#include "net/base/test_completion_callback.h" -#include "net/socket/socket_test_util.h" -#include "net/url_request/url_request_test_util.h" -#include "services/network/network_context.h" -#include "services/network/public/mojom/network_context.mojom.h" +#include "net/base/rand_callback.h" +#include "net/log/net_log_source.h" +#include "net/log/net_log_with_source.h" +#include "net/socket/next_proto.h" +#include "net/socket/socket_tag.h" +#include "net/socket/ssl_client_socket.h" +#include "net/socket/tcp_client_socket.h" +#include "net/traffic_annotation/network_traffic_annotation.h" +#include "testing/gmock/include/gmock/gmock.h" + +using testing::_; +using testing::DoAll; +using testing::Invoke; +using testing::Gt; +using testing::Return; +using testing::SaveArg; +using testing::WithArgs; +using base::StringPiece; namespace extensions { -namespace { - -const char kTestMsg[] = "abcdefghij"; -const int kTestMsgLength = strlen(kTestMsg); - -const char FAKE_ID[] = "abcdefghijklmnopqrst"; - -class TLSSocketTestBase : public extensions::ExtensionServiceTestBase { +class MockSSLClientSocket : public net::SSLClientSocket { public: - TLSSocketTestBase() : url_request_context_(true) {} - ~TLSSocketTestBase() override {} - - // Creates a TCP socket. - std::unique_ptr<TCPSocket> CreateTCPSocket() { - auto socket = std::make_unique<TCPSocket>(&profile_, FAKE_ID); - socket->SetStoragePartitionForTest(&partition_); - net::TestCompletionCallback connect_callback; - net::IPEndPoint ip_end_point(net::IPAddress::IPv4Localhost(), kPort); - socket->Connect(net::AddressList(ip_end_point), - connect_callback.callback()); - if (net::OK != connect_callback.WaitForResult()) { - return nullptr; - } - return socket; + MockSSLClientSocket() {} + int Read(net::IOBuffer* buffer, + int bytes, + net::CompletionOnceCallback callback) override { + return Read(buffer, bytes, + base::AdaptCallbackForRepeating(std::move(callback))); } - // Create a TCP socket and upgrade it to TLS. - std::unique_ptr<TLSSocket> CreateSocket() { - auto socket = CreateTCPSocket(); - if (!socket) - return nullptr; - base::RunLoop run_loop; - net::HostPortPair host_port_pair("example.com", kPort); - net::IPEndPoint local_addr; - net::IPEndPoint peer_addr; - if (!socket->GetLocalAddress(&local_addr) || - !socket->GetPeerAddress(&peer_addr)) { - return nullptr; - } - std::unique_ptr<TLSSocket> tls_socket; - socket->UpgradeToTLS( - nullptr /* options */, - base::BindLambdaForTesting( - [&](int result, network::mojom::TLSClientSocketPtr tls_socket_ptr, - const net::IPEndPoint& local_addr, - const net::IPEndPoint& peer_addr, - mojo::ScopedDataPipeConsumerHandle receive_handle, - mojo::ScopedDataPipeProducerHandle send_handle) { - if (net::OK == result) { - tls_socket = std::make_unique<TLSSocket>( - std::move(tls_socket_ptr), local_addr, peer_addr, - std::move(receive_handle), std::move(send_handle), FAKE_ID); - } - run_loop.Quit(); - })); - run_loop.Run(); - return tls_socket; + int Write(net::IOBuffer* buffer, + int bytes, + net::CompletionOnceCallback callback, + const net::NetworkTrafficAnnotationTag& tag) override { + return Write(buffer, bytes, + base::AdaptCallbackForRepeating(std::move(callback)), tag); } + int Connect(net::CompletionOnceCallback callback) override { + return Connect(base::AdaptCallbackForRepeating(std::move(callback))); + } + + MOCK_METHOD0(Disconnect, void()); + MOCK_METHOD3(Read, + int(net::IOBuffer* buf, + int buf_len, + const net::CompletionCallback& callback)); + MOCK_METHOD4(Write, + int(net::IOBuffer* buf, + int buf_len, + const net::CompletionCallback& callback, + const net::NetworkTrafficAnnotationTag&)); + MOCK_METHOD1(SetReceiveBufferSize, int(int32_t)); + MOCK_METHOD1(SetSendBufferSize, int(int32_t)); + MOCK_METHOD1(Connect, int(const CompletionCallback&)); + MOCK_CONST_METHOD0(IsConnectedAndIdle, bool()); + MOCK_CONST_METHOD1(GetPeerAddress, int(net::IPEndPoint*)); + MOCK_CONST_METHOD1(GetLocalAddress, int(net::IPEndPoint*)); + MOCK_CONST_METHOD0(NetLog, const net::NetLogWithSource&()); + MOCK_CONST_METHOD0(WasEverUsed, bool()); + MOCK_CONST_METHOD0(UsingTCPFastOpen, bool()); + MOCK_CONST_METHOD0(WasAlpnNegotiated, bool()); + MOCK_CONST_METHOD0(GetNegotiatedProtocol, net::NextProto()); + MOCK_METHOD1(GetSSLInfo, bool(net::SSLInfo*)); + MOCK_CONST_METHOD1(GetConnectionAttempts, void(net::ConnectionAttempts*)); + MOCK_METHOD0(ClearConnectionAttempts, void()); + MOCK_METHOD1(AddConnectionAttempts, void(const net::ConnectionAttempts&)); + MOCK_CONST_METHOD0(GetTotalReceivedBytes, int64_t()); + MOCK_METHOD1(ApplySocketTag, void(const net::SocketTag&)); + MOCK_METHOD5(ExportKeyingMaterial, + int(const StringPiece&, + bool, + const StringPiece&, + unsigned char*, + unsigned int)); + MOCK_CONST_METHOD1(GetSSLCertRequestInfo, void(net::SSLCertRequestInfo*)); + MOCK_CONST_METHOD0(GetUnverifiedServerCertificateChain, + scoped_refptr<net::X509Certificate>()); + MOCK_CONST_METHOD0(GetChannelIDService, net::ChannelIDService*()); + MOCK_METHOD3(GetTokenBindingSignature, + net::Error(crypto::ECPrivateKey*, + net::TokenBindingType, + std::vector<uint8_t>*)); + MOCK_CONST_METHOD0(GetChannelIDKey, crypto::ECPrivateKey*()); + bool IsConnected() const override { return true; } + + private: + DISALLOW_COPY_AND_ASSIGN(MockSSLClientSocket); +}; + +class MockTCPSocket : public net::TCPClientSocket { + public: + explicit MockTCPSocket(const net::AddressList& address_list) + : net::TCPClientSocket(address_list, NULL, NULL, net::NetLogSource()) {} + + int Read(net::IOBuffer* buffer, + int bytes, + net::CompletionOnceCallback callback) override { + return Read(buffer, bytes, + base::AdaptCallbackForRepeating(std::move(callback))); + } + + int Write(net::IOBuffer* buffer, + int bytes, + net::CompletionOnceCallback callback, + const net::NetworkTrafficAnnotationTag& tag) override { + return Write(buffer, bytes, + base::AdaptCallbackForRepeating(std::move(callback)), tag); + } + + MOCK_METHOD3(Read, + int(net::IOBuffer* buf, + int buf_len, + const net::CompletionCallback& callback)); + MOCK_METHOD4(Write, + int(net::IOBuffer* buf, + int buf_len, + const net::CompletionCallback& callback, + const net::NetworkTrafficAnnotationTag&)); + MOCK_METHOD2(SetKeepAlive, bool(bool enable, int delay)); + MOCK_METHOD1(SetNoDelay, bool(bool no_delay)); + + bool IsConnected() const override { return true; } + + private: + DISALLOW_COPY_AND_ASSIGN(MockTCPSocket); +}; + +class CompleteHandler { + public: + CompleteHandler() {} + MOCK_METHOD1(OnComplete, void(int result_code)); + MOCK_METHOD3(OnReadComplete, + void(int result_code, + scoped_refptr<net::IOBuffer> io_buffer, + bool socket_destroying)); + MOCK_METHOD2(OnAccept, void(int, net::TCPClientSocket*)); + + private: + DISALLOW_COPY_AND_ASSIGN(CompleteHandler); +}; + +class TLSSocketTest : public ::testing::Test { + public: + TLSSocketTest() {} + + void SetUp() override { + net::AddressList address_list; + // |ssl_socket_| is owned by |socket_|. TLSSocketTest keeps a pointer to + // it to expect invocations from TLSSocket to |ssl_socket_|. + std::unique_ptr<MockSSLClientSocket> ssl_sock(new MockSSLClientSocket); + ssl_socket_ = ssl_sock.get(); + socket_.reset(new TLSSocket(std::move(ssl_sock), "test_extension_id")); + EXPECT_CALL(*ssl_socket_, Disconnect()).Times(1); + }; + + void TearDown() override { + ssl_socket_ = NULL; + socket_.reset(); + }; + protected: - // extensions::ExtensionServiceTestBase implementation. - void SetUp() override { InitializeEmptyExtensionService(); } - - void Initialize() { - url_request_context_.Init(); - network_context_ = std::make_unique<network::NetworkContext>( - nullptr, mojo::MakeRequest(&network_context_ptr_), - &url_request_context_); - partition_.set_network_context(network_context_ptr_.get()); - } - - net::TestURLRequestContext url_request_context_; - - private: - static const int kPort = 1234; - TestingProfile profile_; - content::TestStoragePartition partition_; - std::unique_ptr<network::NetworkContext> network_context_; - network::mojom::NetworkContextPtr network_context_ptr_; + MockSSLClientSocket* ssl_socket_; + std::unique_ptr<TLSSocket> socket_; }; -} // namespace +// Verify that a Read() on TLSSocket will pass through into a Read() on +// |ssl_socket_| and invoke its completion callback. +TEST_F(TLSSocketTest, TestTLSSocketRead) { + CompleteHandler handler; -class TLSSocketTest : public TLSSocketTestBase, - public ::testing::WithParamInterface<net::IoMode> { - public: - TLSSocketTest() : TLSSocketTestBase() { - mock_client_socket_factory_.set_enable_read_if_ready(true); - url_request_context_.set_client_socket_factory( - &mock_client_socket_factory_); - Initialize(); - } - ~TLSSocketTest() override {} - - net::MockClientSocketFactory* mock_client_socket_factory() { - return &mock_client_socket_factory_; - } - - private: - net::MockClientSocketFactory mock_client_socket_factory_; -}; - -TEST_F(TLSSocketTest, DestroyWhileReadPending) { - const net::MockRead kReads[] = {net::MockRead(net::SYNCHRONOUS, net::OK, 1)}; - const net::MockWrite kWrites[] = { - net::MockWrite(net::ASYNC, kTestMsg, kTestMsgLength, 0)}; - net::StaticSocketDataProvider data_provider(kReads, kWrites); - mock_client_socket_factory()->AddSocketDataProvider(&data_provider); - net::SSLSocketDataProvider ssl_socket(net::ASYNC, net::OK); - mock_client_socket_factory()->AddSSLSocketDataProvider(&ssl_socket); - - std::unique_ptr<TLSSocket> socket = CreateSocket(); - - int net_result = net::ERR_FAILED; - base::RunLoop run_loop; - int count = 1; - // Read one byte, and it should be pending because it is blocked on the mock - // write. - socket->Read(count, - base::BindLambdaForTesting( - [&](int result, scoped_refptr<net::IOBuffer> io_buffer, - bool socket_destroying) { - net_result = result; - // |socket_destroying| should correctly denote that this - // read callback is invoked through the destructor of - // TLSSocket. - EXPECT_TRUE(socket_destroying); - run_loop.Quit(); - })); - // Destroy socket. - socket = nullptr; - // Wait for read callback. - run_loop.Run(); - EXPECT_EQ(net::ERR_CONNECTION_CLOSED, net_result); -} - -// UpgradeToTLS() fails when there is a pending read. -TEST_F(TLSSocketTest, UpgradeToTLSWhilePendingRead) { - const net::MockRead kReads[] = { - net::MockRead(net::ASYNC, net::ERR_IO_PENDING)}; - net::StaticSocketDataProvider data_provider(kReads, - base::span<net::MockWrite>()); - mock_client_socket_factory()->AddSocketDataProvider(&data_provider); - auto socket = CreateTCPSocket(); - // This read will be pending when UpgradeToTLS() is called. - socket->Read(1 /* count */, base::DoNothing()); - network::mojom::TLSClientSocketPtr tls_socket_ptr; - base::RunLoop run_loop; - socket->UpgradeToTLS( - nullptr /* options */, - base::BindLambdaForTesting( - [&](int result, network::mojom::TLSClientSocketPtr tls_socket_ptr, - const net::IPEndPoint& local_addr, - const net::IPEndPoint& peer_addr, - mojo::ScopedDataPipeConsumerHandle receive_handle, - mojo::ScopedDataPipeProducerHandle send_handle) { - EXPECT_EQ(net::ERR_FAILED, result); - run_loop.Quit(); - })); - run_loop.Run(); -} - -TEST_F(TLSSocketTest, UpgradeToTLSWithCustomOptions) { - // Mock data are not consumed. These are here so that net::StreamSocket::Read - // is always pending and blocked on the write. Otherwise, mock socket data - // will complains that there aren't any data to read. - const net::MockRead kReads[] = { - net::MockRead(net::ASYNC, kTestMsg, kTestMsgLength, 1), - net::MockRead(net::ASYNC, net::OK, 2)}; - const net::MockWrite kWrites[] = { - net::MockWrite(net::ASYNC, kTestMsg, kTestMsgLength, 0)}; - net::SequencedSocketData data_provider(kReads, kWrites); - net::SSLSocketDataProvider ssl_socket(net::ASYNC, net::OK); - ssl_socket.expected_ssl_version_min = net::SSL_PROTOCOL_VERSION_TLS1_1; - ssl_socket.expected_ssl_version_max = net::SSL_PROTOCOL_VERSION_TLS1_2; - mock_client_socket_factory()->AddSocketDataProvider(&data_provider); - mock_client_socket_factory()->AddSSLSocketDataProvider(&ssl_socket); - - auto socket = CreateTCPSocket(); - network::mojom::TLSClientSocketPtr tls_socket_ptr; - api::socket::SecureOptions options; - options.tls_version = std::make_unique<api::socket::TLSVersionConstraints>(); - options.tls_version->min = std::make_unique<std::string>("tls1.1"); - options.tls_version->max = std::make_unique<std::string>("tls1.2"); - int net_error = net::ERR_FAILED; - base::RunLoop run_loop; - socket->UpgradeToTLS( - &options, - base::BindLambdaForTesting( - [&](int result, network::mojom::TLSClientSocketPtr tls_socket_ptr, - const net::IPEndPoint& local_addr, - const net::IPEndPoint& peer_addr, - mojo::ScopedDataPipeConsumerHandle receive_handle, - mojo::ScopedDataPipeProducerHandle send_handle) { - net_error = result; - run_loop.Quit(); - })); - run_loop.Run(); - EXPECT_EQ(net::OK, net_error); - EXPECT_TRUE(ssl_socket.ConnectDataConsumed()); -} - -INSTANTIATE_TEST_CASE_P(/* no prefix */, - TLSSocketTest, - testing::Values(net::SYNCHRONOUS, net::ASYNC)); - -TEST_P(TLSSocketTest, ReadWrite) { - net::IoMode io_mode = GetParam(); - const net::MockRead kReads[] = { - net::MockRead(net::ASYNC, kTestMsg, kTestMsgLength, 1), - net::MockRead(io_mode, net::OK, 2)}; - const net::MockWrite kWrites[] = { - net::MockWrite(net::SYNCHRONOUS, kTestMsg, kTestMsgLength, 0)}; - net::SequencedSocketData data_provider(kReads, kWrites); - net::SSLSocketDataProvider ssl_socket(io_mode, net::OK); - - mock_client_socket_factory()->AddSocketDataProvider(&data_provider); - mock_client_socket_factory()->AddSSLSocketDataProvider(&ssl_socket); - std::unique_ptr<TLSSocket> socket = CreateSocket(); - - auto io_buffer = base::MakeRefCounted<net::StringIOBuffer>(kTestMsg); - net::TestCompletionCallback write_callback; - socket->Write(io_buffer.get(), kTestMsgLength, write_callback.callback()); - EXPECT_EQ(kTestMsgLength, write_callback.WaitForResult()); - - std::string received_data; - int count = 512; - while (true) { - base::RunLoop run_loop; - int net_error = net::ERR_FAILED; - socket->Read(count, - base::BindLambdaForTesting( - [&](int result, scoped_refptr<net::IOBuffer> io_buffer, - bool socket_destroying) { - net_error = result; - EXPECT_FALSE(socket_destroying); - if (result > 0) - received_data.append(io_buffer->data(), result); - run_loop.Quit(); - })); - run_loop.Run(); - if (net_error <= 0) - break; - } - EXPECT_EQ(kTestMsg, received_data); - EXPECT_TRUE(data_provider.AllReadDataConsumed()); - EXPECT_TRUE(data_provider.AllWriteDataConsumed()); - EXPECT_TRUE(ssl_socket.ConnectDataConsumed()); -} - -// Tests the case where read size is smaller than the actual message. -TEST_P(TLSSocketTest, PartialRead) { - net::IoMode io_mode = GetParam(); - const net::MockRead kReads[] = { - net::MockRead(net::ASYNC, kTestMsg, kTestMsgLength, 1), - net::MockRead(io_mode, net::OK, 2)}; - const net::MockWrite kWrites[] = { - net::MockWrite(net::SYNCHRONOUS, kTestMsg, kTestMsgLength, 0)}; - net::SequencedSocketData data_provider(kReads, kWrites); - net::SSLSocketDataProvider ssl_socket(io_mode, net::OK); - mock_client_socket_factory()->AddSocketDataProvider(&data_provider); - mock_client_socket_factory()->AddSSLSocketDataProvider(&ssl_socket); - std::unique_ptr<TLSSocket> socket = CreateSocket(); - - auto io_buffer = base::MakeRefCounted<net::StringIOBuffer>(kTestMsg); - net::TestCompletionCallback write_callback; - socket->Write(io_buffer.get(), kTestMsgLength, write_callback.callback()); - EXPECT_EQ(kTestMsgLength, write_callback.WaitForResult()); - - int count = 1; - std::string received_data; - while (true) { - int net_result = net::ERR_FAILED; - base::RunLoop run_loop; - socket->Read(count, - base::BindLambdaForTesting( - [&](int result, scoped_refptr<net::IOBuffer> io_buffer, - bool socket_destroying) { - net_result = result; - EXPECT_FALSE(socket_destroying); - if (result > 0) - received_data.append(io_buffer->data(), result); - run_loop.Quit(); - })); - run_loop.Run(); - if (net_result <= 0) - break; - // Double the read size in the next iteration. - count *= 2; - } - EXPECT_EQ(kTestMsg, received_data); - EXPECT_TRUE(data_provider.AllReadDataConsumed()); - EXPECT_TRUE(data_provider.AllWriteDataConsumed()); - EXPECT_TRUE(ssl_socket.ConnectDataConsumed()); -} - -TEST_P(TLSSocketTest, ReadError) { - net::IoMode io_mode = GetParam(); - const net::MockRead kReads[] = { - net::MockRead(net::ASYNC, net::ERR_INSUFFICIENT_RESOURCES, 1)}; - const net::MockWrite kWrites[] = { - net::MockWrite(net::SYNCHRONOUS, kTestMsg, kTestMsgLength, 0)}; - net::SequencedSocketData data_provider(kReads, kWrites); - net::SSLSocketDataProvider ssl_socket(io_mode, net::OK); - mock_client_socket_factory()->AddSocketDataProvider(&data_provider); - mock_client_socket_factory()->AddSSLSocketDataProvider(&ssl_socket); - - std::unique_ptr<TLSSocket> socket = CreateSocket(); - - auto io_buffer = base::MakeRefCounted<net::StringIOBuffer>(kTestMsg); - net::TestCompletionCallback write_callback; - socket->Write(io_buffer.get(), kTestMsgLength, write_callback.callback()); - EXPECT_EQ(kTestMsgLength, write_callback.WaitForResult()); + EXPECT_CALL(*ssl_socket_, Read(_, _, _)).Times(1); + EXPECT_CALL(handler, OnReadComplete(_, _, _)).Times(1); const int count = 512; - int net_error = net::OK; - while (true) { - base::RunLoop run_loop; - socket->Read(count, - base::BindLambdaForTesting( - [&](int result, scoped_refptr<net::IOBuffer> io_buffer, - bool socket_destroying) { - net_error = result; - EXPECT_FALSE(socket_destroying); - if (result <= 0) { - EXPECT_FALSE(socket->IsConnected()); - EXPECT_EQ(nullptr, io_buffer); - } else { - EXPECT_TRUE(socket->IsConnected()); - } - run_loop.Quit(); - })); - run_loop.Run(); - if (net_error < 0) - break; - } - EXPECT_TRUE(data_provider.AllReadDataConsumed()); - EXPECT_TRUE(data_provider.AllWriteDataConsumed()); - EXPECT_TRUE(ssl_socket.ConnectDataConsumed()); + socket_->Read( + count, + base::Bind(&CompleteHandler::OnReadComplete, base::Unretained(&handler))); } -// Tests the case where a message is split over two separate socket writes. -TEST_P(TLSSocketTest, MultipleWrite) { - const char kFirstHalfTestMsg[] = "abcde"; - const char kSecondHalfTestMsg[] = "fghij"; - EXPECT_EQ(kTestMsg, std::string(kFirstHalfTestMsg) + kSecondHalfTestMsg); - net::IoMode io_mode = GetParam(); - const net::MockRead kReads[] = {net::MockRead(net::ASYNC, net::OK, 2)}; - const net::MockWrite kWrites[] = { - net::MockWrite(io_mode, kFirstHalfTestMsg, strlen(kFirstHalfTestMsg), 0), - net::MockWrite(io_mode, kSecondHalfTestMsg, strlen(kSecondHalfTestMsg), - 1)}; - net::SequencedSocketData data_provider(kReads, kWrites); - net::SSLSocketDataProvider ssl_socket(io_mode, net::OK); - mock_client_socket_factory()->AddSocketDataProvider(&data_provider); - mock_client_socket_factory()->AddSSLSocketDataProvider(&ssl_socket); - std::unique_ptr<TLSSocket> socket = CreateSocket(); +// Verify that a Write() on a TLSSocket will pass through to Write() +// invocations on |ssl_socket_|, handling partial writes correctly, and calls +// the completion callback correctly. +TEST_F(TLSSocketTest, TestTLSSocketWrite) { + CompleteHandler handler; + net::CompletionCallback callback; - int num_bytes_written = 0; - auto io_buffer = base::MakeRefCounted<net::StringIOBuffer>(kTestMsg); - auto drainable_io_buffer = base::MakeRefCounted<net::DrainableIOBuffer>( - io_buffer.get(), kTestMsgLength); - while (num_bytes_written < kTestMsgLength) { - net::TestCompletionCallback write_callback; - socket->Write(drainable_io_buffer.get(), kTestMsgLength - num_bytes_written, - write_callback.callback()); - int result = write_callback.WaitForResult(); - ASSERT_GT(result, net::OK); - drainable_io_buffer->DidConsume(result); - num_bytes_written += result; - // Flushes the write. - base::RunLoop().RunUntilIdle(); - } - EXPECT_TRUE(data_provider.AllReadDataConsumed()); - EXPECT_TRUE(data_provider.AllWriteDataConsumed()); - EXPECT_TRUE(ssl_socket.ConnectDataConsumed()); + EXPECT_CALL(*ssl_socket_, Write(_, _, _, _)) + .Times(2) + .WillRepeatedly(DoAll(SaveArg<2>(&callback), Return(128))); + EXPECT_CALL(handler, OnComplete(_)).Times(1); + + scoped_refptr<net::IOBufferWithSize> io_buffer( + new net::IOBufferWithSize(256)); + socket_->Write( + io_buffer.get(), + io_buffer->size(), + base::Bind(&CompleteHandler::OnComplete, base::Unretained(&handler))); } -TEST_P(TLSSocketTest, PartialWrite) { - net::IoMode io_mode = GetParam(); - const net::MockRead kReads[] = {net::MockRead(net::ASYNC, net::OK, 4)}; - const net::MockWrite kWrites[] = {net::MockWrite(io_mode, "a", 1, 0), - net::MockWrite(io_mode, "bc", 2, 1), - net::MockWrite(io_mode, "defg", 4, 2), - net::MockWrite(io_mode, "hij", 3, 3)}; +// Simulate a blocked Write, and verify that, when simulating the Write going +// through, the callback gets invoked. +TEST_F(TLSSocketTest, TestTLSSocketBlockedWrite) { + CompleteHandler handler; + net::CompletionCallback callback; - net::SequencedSocketData data_provider(kReads, kWrites); - net::SSLSocketDataProvider ssl_socket(io_mode, net::OK); + // Return ERR_IO_PENDING to say the Write()'s blocked. Save the |callback| + // Write()'s passed. + EXPECT_CALL(*ssl_socket_, Write(_, _, _, _)) + .Times(2) + .WillRepeatedly( + DoAll(SaveArg<2>(&callback), Return(net::ERR_IO_PENDING))); - mock_client_socket_factory()->AddSocketDataProvider(&data_provider); - mock_client_socket_factory()->AddSSLSocketDataProvider(&ssl_socket); + scoped_refptr<net::IOBufferWithSize> io_buffer(new net::IOBufferWithSize(42)); + socket_->Write( + io_buffer.get(), + io_buffer->size(), + base::Bind(&CompleteHandler::OnComplete, base::Unretained(&handler))); - mock_client_socket_factory()->AddSocketDataProvider(&data_provider); - std::unique_ptr<TLSSocket> socket = CreateSocket(); - - // Start with writing one byte, and double that in the next iteration. - int num_bytes_to_write = 1; - int num_bytes_written = 0; - auto io_buffer = base::MakeRefCounted<net::StringIOBuffer>(kTestMsg); - auto drainable_io_buffer = base::MakeRefCounted<net::DrainableIOBuffer>( - io_buffer.get(), kTestMsgLength); - while (num_bytes_written < kTestMsgLength) { - net::TestCompletionCallback write_callback; - socket->Write( - drainable_io_buffer.get(), - std::max(kTestMsgLength - num_bytes_written, num_bytes_to_write), - write_callback.callback()); - int result = write_callback.WaitForResult(); - ASSERT_GT(result, net::OK); - drainable_io_buffer->DidConsume(result); - num_bytes_written += result; - num_bytes_to_write *= 2; - // Flushes the write. - base::RunLoop().RunUntilIdle(); - } - EXPECT_TRUE(data_provider.AllReadDataConsumed()); - EXPECT_TRUE(data_provider.AllWriteDataConsumed()); - EXPECT_TRUE(ssl_socket.ConnectDataConsumed()); + // After the simulated asynchronous writes come back (via calls to + // callback.Run()), hander's OnComplete() should get invoked with the total + // amount written. + EXPECT_CALL(handler, OnComplete(42)).Times(1); + callback.Run(40); + callback.Run(2); } -TEST_P(TLSSocketTest, WriteError) { - net::IoMode io_mode = GetParam(); - const net::MockRead kReads[] = {net::MockRead(net::ASYNC, net::OK, 1)}; - const net::MockWrite kWrites[] = { - net::MockWrite(io_mode, net::ERR_INSUFFICIENT_RESOURCES, 0)}; +// Simulate multiple blocked Write()s. +TEST_F(TLSSocketTest, TestTLSSocketBlockedWriteReentry) { + const int kNumIOs = 5; + CompleteHandler handlers[kNumIOs]; + net::CompletionCallback callback; + scoped_refptr<net::IOBufferWithSize> io_buffers[kNumIOs]; - net::SequencedSocketData data_provider(kReads, kWrites); - net::SSLSocketDataProvider ssl_socket(io_mode, net::OK); + // The implementation of TLSSocket::Write() is inherited from + // Socket::Write(), which implements an internal write queue that wraps + // TLSSocket::WriteImpl(). Each call from TLSSocket::WriteImpl() will invoke + // |ssl_socket_|'s Write() (mocked here). Save the |callback| (assume they + // will all be equivalent), and return ERR_IO_PENDING, to indicate a blocked + // request. The mocked SSLClientSocket::Write() will get one request per + // TLSSocket::Write() request invoked on |socket_| below. + EXPECT_CALL(*ssl_socket_, Write(_, _, _, _)) + .Times(kNumIOs) + .WillRepeatedly( + DoAll(SaveArg<2>(&callback), Return(net::ERR_IO_PENDING))); - mock_client_socket_factory()->AddSocketDataProvider(&data_provider); - mock_client_socket_factory()->AddSSLSocketDataProvider(&ssl_socket); - std::unique_ptr<TLSSocket> socket = CreateSocket(); + // Send out |kNuMIOs| requests, each with a different size. + for (int i = 0; i < kNumIOs; i++) { + io_buffers[i] = new net::IOBufferWithSize(128 + i * 50); + socket_->Write(io_buffers[i].get(), + io_buffers[i]->size(), + base::Bind(&CompleteHandler::OnComplete, + base::Unretained(&handlers[i]))); - // Mojo data pipe might buffer some write data, so continue writing until the - // write error is received. - auto io_buffer = base::MakeRefCounted<net::StringIOBuffer>(kTestMsg); - int net_error = net::OK; - while (true) { - base::RunLoop run_loop; - socket->Write(io_buffer.get(), kTestMsgLength, - base::BindLambdaForTesting([&](int result) { - if (result == net::ERR_FAILED) - EXPECT_FALSE(socket->IsConnected()); - net_error = result; - run_loop.Quit(); - })); - run_loop.Run(); - if (net_error <= 0) - break; + // Set up expectations on all |kNumIOs| handlers. + EXPECT_CALL(handlers[i], OnComplete(io_buffers[i]->size())).Times(1); } - // Note that TCPSocket only detects that send pipe is broken and propagates - // it as a net::ERR_FAILED. It doesn't know the specific net error code. To do - // that, it needs to register itself as a network::mojom::SocketObserver. - EXPECT_EQ(net::ERR_FAILED, net_error); + + // Finish each pending I/O. This should satisfy the expectations on the + // handlers. + for (int i = 0; i < kNumIOs; i++) { + callback.Run(128 + i * 50); + } +} + +typedef std::pair<net::CompletionCallback, int> PendingCallback; + +class CallbackList : public base::circular_deque<PendingCallback> { + public: + void append(const net::CompletionCallback& cb, int arg) { + push_back(std::make_pair(cb, arg)); + } +}; + +// Simulate Write()s above and below a SSLClientSocket size limit. +TEST_F(TLSSocketTest, TestTLSSocketLargeWrites) { + const int kSizeIncrement = 4096; + const int kNumIncrements = 10; + const int kFragmentIncrement = 4; + const int kSizeLimit = kSizeIncrement * kFragmentIncrement; + net::CompletionCallback callback; + CompleteHandler handler; + scoped_refptr<net::IOBufferWithSize> io_buffers[kNumIncrements]; + CallbackList pending_callbacks; + size_t total_bytes_requested = 0; + size_t total_bytes_written = 0; + + // Some implementations of SSLClientSocket may have write-size limits (e.g, + // max 1 TLS record, which is 16k). This test mocks a size limit at + // |kSizeIncrement| and calls Write() above and below that limit. It + // simulates SSLClientSocket::Write() behavior in only writing up to the size + // limit, requiring additional calls for the remaining data to be sent. + // Socket::Write() (and supporting methods) execute the additional calls as + // needed. This test verifies that this inherited implementation does + // properly issue additional calls, and that the total amount returned from + // all mocked SSLClientSocket::Write() calls is the same as originally + // requested. + + // |ssl_socket_|'s Write() will write at most |kSizeLimit| bytes. The + // inherited Socket::Write() will repeatedly call |ssl_socket_|'s Write() + // until the entire original request is sent. Socket::Write() will queue any + // additional write requests until the current request is complete. A + // request is complete when the callback passed to Socket::WriteImpl() is + // invoked with an argument equal to the original number of bytes requested + // from Socket::Write(). If the callback is invoked with a smaller number, + // Socket::WriteImpl() will get repeatedly invoked until the sum of the + // callbacks' arguments is equal to the original requested amount. + EXPECT_CALL(*ssl_socket_, Write(_, _, _, _)) + .WillRepeatedly(DoAll( + WithArgs<2, 1>(Invoke(&pending_callbacks, &CallbackList::append)), + Return(net::ERR_IO_PENDING))); + + // Observe what comes back from Socket::Write() here. + EXPECT_CALL(handler, OnComplete(Gt(0))).Times(kNumIncrements); + + // Send out |kNumIncrements| requests, each with a different size. The + // last request is the same size as the first, and the ones in the middle + // are monotonically increasing from the first. + for (int i = 0; i < kNumIncrements; i++) { + const bool last = i == (kNumIncrements - 1); + io_buffers[i] = new net::IOBufferWithSize(last ? kSizeIncrement + : kSizeIncrement * (i + 1)); + total_bytes_requested += io_buffers[i]->size(); + + // Invoke Socket::Write(). This will invoke |ssl_socket_|'s Write(), which + // this test mocks out. That mocked Write() is in an asynchronous waiting + // state until the passed callback (saved in the EXPECT_CALL for + // |ssl_socket_|'s Write()) is invoked. + socket_->Write( + io_buffers[i].get(), + io_buffers[i]->size(), + base::Bind(&CompleteHandler::OnComplete, base::Unretained(&handler))); + } + + // Invoke callbacks for pending I/Os. These can synchronously invoke more of + // |ssl_socket_|'s Write() as needed. The callback checks how much is left + // in the request, and then starts issuing any queued Socket::Write() + // invocations. + while (!pending_callbacks.empty()) { + PendingCallback cb = pending_callbacks.front(); + pending_callbacks.pop_front(); + + int amount_written_invocation = std::min(kSizeLimit, cb.second); + total_bytes_written += amount_written_invocation; + cb.first.Run(amount_written_invocation); + } + + ASSERT_EQ(total_bytes_requested, total_bytes_written) + << "There should be exactly as many bytes written as originally " + << "requested to Write()."; } } // namespace extensions
diff --git a/chrome/browser/extensions/api/tab_capture/tab_capture_api.cc b/chrome/browser/extensions/api/tab_capture/tab_capture_api.cc index 529970f..90802a4 100644 --- a/chrome/browser/extensions/api/tab_capture/tab_capture_api.cc +++ b/chrome/browser/extensions/api/tab_capture/tab_capture_api.cc
@@ -26,6 +26,7 @@ #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/common/chrome_switches.h" +#include "content/public/browser/desktop_media_id.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/web_contents.h" @@ -35,6 +36,8 @@ #include "extensions/common/permissions/permissions_data.h" #include "extensions/common/switches.h" +using content::DesktopMediaID; +using content::WebContentsMediaCaptureId; using extensions::api::tab_capture::MediaStreamConstraint; namespace TabCapture = extensions::api::tab_capture; @@ -116,21 +119,7 @@ } } -// Add Chrome-specific source identifiers to the MediaStreamConstraints objects -// in |options| to provide references to the |target_contents| to be captured. -void AddMediaStreamSourceConstraints(content::WebContents* target_contents, - TabCapture::CaptureOptions* options) { - DCHECK(options); - DCHECK(target_contents); - - MediaStreamConstraint* constraints_to_modify[2] = { nullptr, nullptr }; - - if (options->audio && *options->audio) { - if (!options->audio_constraints) - options->audio_constraints.reset(new MediaStreamConstraint); - constraints_to_modify[0] = options->audio_constraints.get(); - } - +bool GetAutoThrottlingFromOptions(TabCapture::CaptureOptions* options) { bool enable_auto_throttling = false; if (options->video && *options->video) { if (options->video_constraints) { @@ -146,21 +135,45 @@ // Remove the key from the properties to avoid an "unrecognized // constraint" error in the renderer. props.RemoveWithoutPathExpansion(kEnableAutoThrottlingKey, nullptr); - } else { - options->video_constraints.reset(new MediaStreamConstraint); } - constraints_to_modify[1] = options->video_constraints.get(); } - // Format the device ID that references the target tab. - content::RenderFrameHost* const main_frame = target_contents->GetMainFrame(); - // TODO(miu): We should instead use a "randomly generated device ID" scheme, - // like that employed by the desktop capture API. http://crbug.com/163100 - const std::string device_id = base::StringPrintf( - "web-contents-media-stream://%i:%i%s", - main_frame->GetProcess()->GetID(), - main_frame->GetRoutingID(), - enable_auto_throttling ? "?throttling=auto" : ""); + return enable_auto_throttling; +} + +DesktopMediaID BuildDesktopMediaID(content::WebContents* target_contents, + TabCapture::CaptureOptions* options) { + content::RenderFrameHost* const target_frame = + target_contents->GetMainFrame(); + DesktopMediaID source( + DesktopMediaID::TYPE_WEB_CONTENTS, DesktopMediaID::kNullId, + WebContentsMediaCaptureId(target_frame->GetProcess()->GetID(), + target_frame->GetRoutingID(), + GetAutoThrottlingFromOptions(options), false)); + return source; +} + +// Add Chrome-specific source identifiers to the MediaStreamConstraints objects +// in |options| to provide references to the |target_contents| to be captured. +void AddMediaStreamSourceConstraints(content::WebContents* target_contents, + TabCapture::CaptureOptions* options, + const std::string& device_id) { + DCHECK(options); + DCHECK(target_contents); + + MediaStreamConstraint* constraints_to_modify[2] = {nullptr, nullptr}; + + if (options->audio && *options->audio) { + if (!options->audio_constraints) + options->audio_constraints.reset(new MediaStreamConstraint); + constraints_to_modify[0] = options->audio_constraints.get(); + } + + if (options->video && *options->video) { + if (!options->video_constraints) + options->video_constraints.reset(new MediaStreamConstraint); + constraints_to_modify[1] = options->video_constraints.get(); + } // Append chrome specific tab constraints. for (MediaStreamConstraint* msc : constraints_to_modify) { @@ -217,14 +230,21 @@ if (!OptionsSpecifyAudioOrVideo(params->options)) return RespondNow(Error(kNoAudioOrVideo)); + DesktopMediaID source = + BuildDesktopMediaID(target_contents, ¶ms->options); + content::WebContents* const extension_web_contents = GetSenderWebContents(); + EXTENSION_FUNCTION_VALIDATE(extension_web_contents); TabCaptureRegistry* registry = TabCaptureRegistry::Get(browser_context()); - if (!registry->AddRequest(target_contents, extension_id, false)) { + std::string device_id = registry->AddRequest( + target_contents, extension_id, false, extension()->url(), source, + extension()->name(), extension_web_contents); + if (device_id.empty()) { // TODO(miu): Allow multiple consumers of single tab capture. // http://crbug.com/535336 return RespondNow(Error(kCapturingSameTab)); } FilterDeprecatedGoogConstraints(¶ms->options); - AddMediaStreamSourceConstraints(target_contents, ¶ms->options); + AddMediaStreamSourceConstraints(target_contents, ¶ms->options, device_id); // At this point, everything is set up in the browser process. It's now up to // the custom JS bindings in the extension's render process to request a @@ -283,15 +303,21 @@ if (!offscreen_tab) return RespondNow(Error(kTooManyOffscreenTabs)); - if (!TabCaptureRegistry::Get(browser_context())->AddRequest( - offscreen_tab->web_contents(), extension()->id(), true)) { + content::WebContents* target_contents = offscreen_tab->web_contents(); + const std::string& extension_id = extension()->id(); + DesktopMediaID source = + BuildDesktopMediaID(target_contents, ¶ms->options); + TabCaptureRegistry* registry = TabCaptureRegistry::Get(browser_context()); + std::string device_id = registry->AddRequest( + target_contents, extension_id, true, extension()->url(), source, + extension()->name(), extension_web_contents); + if (device_id.empty()) { // TODO(miu): Allow multiple consumers of single tab capture. // http://crbug.com/535336 return RespondNow(Error(kCapturingSameOffscreenTab)); } FilterDeprecatedGoogConstraints(¶ms->options); - AddMediaStreamSourceConstraints(offscreen_tab->web_contents(), - ¶ms->options); + AddMediaStreamSourceConstraints(target_contents, ¶ms->options, device_id); // At this point, everything is set up in the browser process. It's now up to // the custom JS bindings in the extension's render process to complete the
diff --git a/chrome/browser/extensions/api/tab_capture/tab_capture_registry.cc b/chrome/browser/extensions/api/tab_capture/tab_capture_registry.cc index c8a4493..9decb9d 100644 --- a/chrome/browser/extensions/api/tab_capture/tab_capture_registry.cc +++ b/chrome/browser/extensions/api/tab_capture/tab_capture_registry.cc
@@ -13,7 +13,9 @@ #include "chrome/browser/sessions/session_tab_helper.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/desktop_streams_registry.h" #include "content/public/browser/render_frame_host.h" +#include "content/public/browser/render_process_host.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_observer.h" #include "extensions/browser/event_router.h" @@ -138,8 +140,9 @@ #if defined(USE_AURA) window_agent_(target_contents->GetNativeView()), #endif - render_process_id_(-1), - render_frame_id_(-1) { + render_process_id_( + target_contents->GetMainFrame()->GetProcess()->GetID()), + render_frame_id_(target_contents->GetMainFrame()->GetRoutingID()) { DCHECK(web_contents()); DCHECK(registry_); } @@ -165,17 +168,8 @@ is_verified_ = true; } - // TODO(miu): See TODO(miu) in VerifyRequest() below. - void SetOriginallyTargettedRenderFrameID(int render_process_id, - int render_frame_id) { - DCHECK_GT(render_frame_id, 0); - DCHECK_EQ(render_frame_id_, -1); // Setting ID only once. - render_process_id_ = render_process_id; - render_frame_id_ = render_frame_id; - } - - bool WasOriginallyTargettingRenderFrameID(int render_process_id, - int render_frame_id) const { + bool WasTargettingRenderFrameID(int render_process_id, + int render_frame_id) const { return render_process_id_ == render_process_id && render_frame_id_ == render_frame_id; } @@ -298,16 +292,22 @@ } } -bool TabCaptureRegistry::AddRequest(content::WebContents* target_contents, - const std::string& extension_id, - bool is_anonymous) { +std::string TabCaptureRegistry::AddRequest( + content::WebContents* target_contents, + const std::string& extension_id, + bool is_anonymous, + const GURL& origin, + content::DesktopMediaID source, + const std::string& extension_name, + content::WebContents* caller_contents) { + std::string device_id; LiveRequest* const request = FindRequest(target_contents); // Currently, we do not allow multiple active captures for same tab. if (request != NULL) { if (request->capture_state() == tab_capture::TAB_CAPTURE_STATE_PENDING || request->capture_state() == tab_capture::TAB_CAPTURE_STATE_ACTIVE) { - return false; + return device_id; } else { // Delete the request before creating its replacement (below). KillRequest(request); @@ -316,7 +316,15 @@ requests_.push_back(std::make_unique<LiveRequest>( target_contents, extension_id, is_anonymous, this)); - return true; + + content::RenderFrameHost* const main_frame = caller_contents->GetMainFrame(); + if (main_frame) { + device_id = content::DesktopStreamsRegistry::GetInstance()->RegisterStream( + main_frame->GetProcess()->GetID(), main_frame->GetRoutingID(), origin, + source, extension_name); + } + + return device_id; } bool TabCaptureRegistry::VerifyRequest( @@ -325,36 +333,24 @@ const std::string& extension_id) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - LiveRequest* const request = FindRequest( - content::WebContents::FromRenderFrameHost( - content::RenderFrameHost::FromID( - render_process_id, render_frame_id))); - if (!request) + LiveRequest* const request = FindRequest(render_process_id, render_frame_id); + if (!request) { return false; // Unknown RenderFrameHost ID, or frame has gone away. + } - // TODO(miu): We should probably also verify the origin URL, like the desktop - // capture API. http://crbug.com/163100 if (request->is_verified() || request->extension_id() != extension_id || (request->capture_state() != tab_capture::TAB_CAPTURE_STATE_NONE && request->capture_state() != tab_capture::TAB_CAPTURE_STATE_PENDING)) return false; - // TODO(miu): The RenderFrameHost IDs should be set when LiveRequest is - // constructed, but ExtensionFunction does not yet support use of - // render_frame_host() to determine the exact RenderFrameHost for the call to - // AddRequest() above. Fix tab_capture_api.cc, and then fix this ugly hack. - // http://crbug.com/304341 - request->SetOriginallyTargettedRenderFrameID( - render_process_id, render_frame_id); - request->SetIsVerified(); return true; } void TabCaptureRegistry::OnRequestUpdate( - int original_target_render_process_id, - int original_target_render_frame_id, + int target_render_process_id, + int target_render_frame_id, content::MediaStreamType stream_type, const content::MediaRequestState new_state) { DCHECK_CURRENTLY_ON(BrowserThread::UI); @@ -363,18 +359,9 @@ return; } - LiveRequest* request = FindRequest(original_target_render_process_id, - original_target_render_frame_id); + LiveRequest* request = + FindRequest(target_render_process_id, target_render_frame_id); if (!request) { - // Fall-back: Search again using WebContents since this method may have been - // called before VerifyRequest() set the RenderFrameHost ID. If the - // RenderFrameHost has gone away, that's okay since the upcoming call to - // VerifyRequest() will fail, and that means the tracking of request updates - // doesn't matter anymore. - request = FindRequest(content::WebContents::FromRenderFrameHost( - content::RenderFrameHost::FromID(original_target_render_process_id, - original_target_render_frame_id))); - if (!request) return; // Stale or invalid request update. } @@ -444,12 +431,11 @@ } TabCaptureRegistry::LiveRequest* TabCaptureRegistry::FindRequest( - int original_target_render_process_id, - int original_target_render_frame_id) const { + int target_render_process_id, + int target_render_frame_id) const { for (const std::unique_ptr<LiveRequest>& request : requests_) { - if (request->WasOriginallyTargettingRenderFrameID( - original_target_render_process_id, - original_target_render_frame_id)) { + if (request->WasTargettingRenderFrameID(target_render_process_id, + target_render_frame_id)) { return request.get(); } }
diff --git a/chrome/browser/extensions/api/tab_capture/tab_capture_registry.h b/chrome/browser/extensions/api/tab_capture/tab_capture_registry.h index 4d4abd6..80b2b7e3 100644 --- a/chrome/browser/extensions/api/tab_capture/tab_capture_registry.h +++ b/chrome/browser/extensions/api/tab_capture/tab_capture_registry.h
@@ -13,6 +13,7 @@ #include "base/scoped_observer.h" #include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h" #include "chrome/common/extensions/api/tab_capture.h" +#include "content/public/browser/desktop_media_id.h" #include "content/public/browser/media_request_state.h" #include "extensions/browser/browser_context_keyed_api_factory.h" #include "extensions/browser/extension_registry_observer.h" @@ -47,18 +48,23 @@ base::ListValue* list_of_capture_info) const; // Add a tab capture request to the registry when a stream is requested - // through the API. |target_contents| refers to the WebContents associated - // with the tab to be captured. |extension_id| refers to the Extension - // initiating the request. |is_anonymous| is true if GetCapturedTabs() should - // not list the captured tab, and no status change events should be dispatched - // for it. - // - // TODO(miu): This is broken in that it's possible for a later WebContents - // instance to have the same pointer value as a previously-destroyed one. To - // be fixed while working on http://crbug.com/163100. - bool AddRequest(content::WebContents* target_contents, - const std::string& extension_id, - bool is_anonymous); + // through the API and create a randomly generated device id after user + // initiated access to |source| for the |origin|. If capture is already + // taking place for the same tab, this operation fails and returns an + // empty string. + // |target_contents|: the WebContents associated with the tab to be captured. + // |extension_id|: the Extension initiating the request. + // |is_anonymous| is true if GetCapturedTabs() should not list the captured + // tab, and no status change events should be dispatched for it. + // |caller_contents|: the WebContents associated with the tab/extension that + // starts the capture. + std::string AddRequest(content::WebContents* target_contents, + const std::string& extension_id, + bool is_anonymous, + const GURL& origin, + content::DesktopMediaID source, + const std::string& extension_name, + content::WebContents* caller_contents); // Called by MediaStreamDevicesController to verify the request before // creating the stream. |render_process_id| and |render_frame_id| are used to @@ -91,8 +97,8 @@ UnloadedExtensionReason reason) override; // MediaCaptureDevicesDispatcher::Observer implementation. - void OnRequestUpdate(int original_target_render_process_id, - int original_target_render_frame_id, + void OnRequestUpdate(int target_render_process_id, + int target_render_frame_id, content::MediaStreamType stream_type, const content::MediaRequestState state) override; @@ -102,8 +108,8 @@ // Look-up a LiveRequest associated with the given |target_contents| (or // the originally targetted RenderFrameHost), if any. LiveRequest* FindRequest(const content::WebContents* target_contents) const; - LiveRequest* FindRequest(int original_target_render_process_id, - int original_target_render_frame_id) const; + LiveRequest* FindRequest(int target_render_process_id, + int target_render_frame_id) const; // Removes the |request| from |requests_|, thus causing its destruction. void KillRequest(LiveRequest* request);
diff --git a/chrome/browser/extensions/api/web_request/web_request_apitest.cc b/chrome/browser/extensions/api/web_request/web_request_apitest.cc index 3b61cdd..0ad012a 100644 --- a/chrome/browser/extensions/api/web_request/web_request_apitest.cc +++ b/chrome/browser/extensions/api/web_request/web_request_apitest.cc
@@ -268,15 +268,17 @@ const char* expected_content_regular_window, const char* exptected_content_incognito_window); - // TODO(https://crbug.com/857577): remove this hack. When an unrelated - // browser issued request (typically from GaiaAuthFetcher) has run, it causes - // the StoragePartitionImpl to create and cache a URLLoaderFactory without the - // web request proxying. This resets it so one with the web request proxying - // is created the next time a request is made. - void ResetStoragePartitionURLLoaderFactory() { - base::RunLoop().RunUntilIdle(); + network::mojom::URLLoaderFactoryPtr CreateURLLoaderFactory() { + network::mojom::URLLoaderFactoryParamsPtr params = + network::mojom::URLLoaderFactoryParams::New(); + params->process_id = network::mojom::kBrowserProcessId; + params->is_corb_enabled = false; + network::mojom::URLLoaderFactoryPtr loader_factory; content::BrowserContext::GetDefaultStoragePartition(profile()) - ->ResetURLLoaderFactoryForBrowserProcessForTesting(); + ->GetNetworkContext() + ->CreateURLLoaderFactory(mojo::MakeRequest(&loader_factory), + std::move(params)); + return loader_factory; } }; @@ -1039,9 +1041,6 @@ EXPECT_EQ(200, loader->ResponseInfo()->headers->response_code()); }; - // TODO(https://crbug.com/857577): remove this call. - ResetStoragePartitionURLLoaderFactory(); - // Now perform a request to "client1.google.com" from the browser process. // This should *not* be visible to the WebRequest API. We should still have // only seen the single render-initiated request from the first half of the @@ -1362,9 +1361,6 @@ } }; - // TODO(https://crbug.com/857577): remove this call. - ResetStoragePartitionURLLoaderFactory(); - // Next, try a series of requests through URLRequestFetchers (rather than a // renderer). auto* url_loader_factory = @@ -1452,6 +1448,37 @@ } } +IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, + WebRequestApiClearsBindingOnFirstListener) { + if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) + return; + + auto loader_factory = CreateURLLoaderFactory(); + bool has_connection_error = false; + loader_factory.set_connection_error_handler( + base::BindLambdaForTesting([&]() { has_connection_error = true; })); + + auto* web_request_api = + extensions::BrowserContextKeyedAPIFactory<extensions::WebRequestAPI>::Get( + profile()); + web_request_api->OnListenerAdded( + EventListenerInfo("name", "id1", GURL(), profile())); + content::BrowserContext::GetDefaultStoragePartition(profile()) + ->FlushNetworkInterfaceForTesting(); + EXPECT_TRUE(has_connection_error); + + // The second time there should be no connection error. + loader_factory = CreateURLLoaderFactory(); + has_connection_error = false; + loader_factory.set_connection_error_handler( + base::BindLambdaForTesting([&]() { has_connection_error = true; })); + web_request_api->OnListenerAdded( + EventListenerInfo("name", "id2", GURL(), profile())); + content::BrowserContext::GetDefaultStoragePartition(profile()) + ->FlushNetworkInterfaceForTesting(); + EXPECT_FALSE(has_connection_error); +} + // Test fixture which sets a custom NTP Page. class NTPInterceptionWebRequestAPITest : public ExtensionApiTest { public:
diff --git a/chrome/browser/extensions/background_xhr_browsertest.cc b/chrome/browser/extensions/background_xhr_browsertest.cc index 5b12e8acd..03b32ac 100644 --- a/chrome/browser/extensions/background_xhr_browsertest.cc +++ b/chrome/browser/extensions/background_xhr_browsertest.cc
@@ -15,6 +15,7 @@ #include "chrome/common/chrome_switches.h" #include "chrome/test/base/ui_test_utils.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/network_service_instance.h" #include "extensions/browser/browsertest_util.h" #include "extensions/common/extension.h" #include "extensions/common/extension_urls.h" @@ -59,6 +60,16 @@ GURL test_url = net::AppendQueryParameter(extension->GetResourceURL(path), "url", url.spec()); ui_test_utils::NavigateToURL(browser(), test_url); + content::FlushNetworkServiceInstanceForTesting(); + constexpr char kSendXHRScript[] = R"( + var xhr = new XMLHttpRequest(); + xhr.open('GET', '%s'); + xhr.send(); + domAutomationController.send(''); + )"; + browsertest_util::ExecuteScriptInBackgroundPage( + profile(), extension->id(), + base::StringPrintf(kSendXHRScript, url.spec().c_str())); ASSERT_TRUE(catcher.GetNextResult()); } };
diff --git a/chrome/browser/extensions/extension_action.cc b/chrome/browser/extensions/extension_action.cc index 179114b..a8ad0a9 100644 --- a/chrome/browser/extensions/extension_action.cc +++ b/chrome/browser/extensions/extension_action.cc
@@ -129,8 +129,9 @@ std::string binary_string64; IPC::Message pickle; if (iter.value().is_blob()) { - pickle = IPC::Message(iter.value().GetBlob().data(), - iter.value().GetBlob().size()); + pickle = IPC::Message( + reinterpret_cast<const char*>(iter.value().GetBlob().data()), + iter.value().GetBlob().size()); } else if (iter.value().GetAsString(&binary_string64)) { std::string binary_string; if (!base::Base64Decode(binary_string64, &binary_string))
diff --git a/chrome/browser/media/android/remote/flinging_controller_bridge.cc b/chrome/browser/media/android/remote/flinging_controller_bridge.cc new file mode 100644 index 0000000..b5d1f27 --- /dev/null +++ b/chrome/browser/media/android/remote/flinging_controller_bridge.cc
@@ -0,0 +1,73 @@ +// 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/media/android/remote/flinging_controller_bridge.h" + +#include "jni/FlingingControllerBridge_jni.h" + +namespace media_router { + +FlingingControllerBridge::FlingingControllerBridge( + base::android::ScopedJavaGlobalRef<jobject> controller) + : j_flinging_controller_bridge_(controller) {} + +FlingingControllerBridge::~FlingingControllerBridge() = default; + +void FlingingControllerBridge::Play() { + JNIEnv* env = base::android::AttachCurrentThread(); + DCHECK(env); + + Java_FlingingControllerBridge_play(env, j_flinging_controller_bridge_); +} + +void FlingingControllerBridge::Pause() { + JNIEnv* env = base::android::AttachCurrentThread(); + DCHECK(env); + + Java_FlingingControllerBridge_pause(env, j_flinging_controller_bridge_); +} + +void FlingingControllerBridge::SetMute(bool mute) { + JNIEnv* env = base::android::AttachCurrentThread(); + DCHECK(env); + + Java_FlingingControllerBridge_setMute(env, j_flinging_controller_bridge_, + mute); +} + +void FlingingControllerBridge::SetVolume(float volume) { + JNIEnv* env = base::android::AttachCurrentThread(); + DCHECK(env); + + Java_FlingingControllerBridge_setVolume(env, j_flinging_controller_bridge_, + volume); +} + +void FlingingControllerBridge::Seek(base::TimeDelta time) { + JNIEnv* env = base::android::AttachCurrentThread(); + DCHECK(env); + + Java_FlingingControllerBridge_seek(env, j_flinging_controller_bridge_, + time.InMilliseconds()); +} + +media::MediaController* FlingingControllerBridge::GetMediaController() { + return this; +} + +void FlingingControllerBridge::AddMediaStatusObserver( + media::MediaStatusObserver* observer) { + NOTREACHED(); +} +void FlingingControllerBridge::RemoveMediaStatusObserver( + media::MediaStatusObserver* observer) { + NOTREACHED(); +} + +base::TimeDelta FlingingControllerBridge::GetApproximateCurrentTime() { + // TODO(https://crbug.com/830871): Implement this method. + return base::TimeDelta(); +} + +} // namespace media_router
diff --git a/chrome/browser/media/android/remote/flinging_controller_bridge.h b/chrome/browser/media/android/remote/flinging_controller_bridge.h new file mode 100644 index 0000000..866e3e5 --- /dev/null +++ b/chrome/browser/media/android/remote/flinging_controller_bridge.h
@@ -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. + +#ifndef CHROME_BROWSER_MEDIA_ANDROID_REMOTE_FLINGING_CONTROLLER_BRIDGE_H_ +#define CHROME_BROWSER_MEDIA_ANDROID_REMOTE_FLINGING_CONTROLLER_BRIDGE_H_ + +#include "base/android/scoped_java_ref.h" +#include "base/time/time.h" +#include "media/base/flinging_controller.h" +#include "media/base/media_controller.h" + +namespace media_router { + +// Allows native code to call into a Java FlingingController. +class FlingingControllerBridge : public media::FlingingController, + public media::MediaController { + public: + explicit FlingingControllerBridge( + base::android::ScopedJavaGlobalRef<jobject> controller); + ~FlingingControllerBridge() override; + + // FlingingController implementation. + media::MediaController* GetMediaController() override; + void AddMediaStatusObserver(media::MediaStatusObserver* observer) override; + void RemoveMediaStatusObserver(media::MediaStatusObserver* observer) override; + base::TimeDelta GetApproximateCurrentTime() override; + + // MediaController implementation. + void Play() override; + void Pause() override; + void SetMute(bool mute) override; + void SetVolume(float volume) override; + void Seek(base::TimeDelta time) override; + + private: + // Java MediaControllerBridge instance. + base::android::ScopedJavaGlobalRef<jobject> j_flinging_controller_bridge_; + + DISALLOW_COPY_AND_ASSIGN(FlingingControllerBridge); +}; + +} // namespace media_router + +#endif // CHROME_BROWSER_MEDIA_ANDROID_REMOTE_FLINGING_CONTROLLER_BRIDGE_H_
diff --git a/chrome/browser/media/android/remote/media_controller_bridge.cc b/chrome/browser/media/android/remote/media_controller_bridge.cc deleted file mode 100644 index 7f42cb7..0000000 --- a/chrome/browser/media/android/remote/media_controller_bridge.cc +++ /dev/null
@@ -1,53 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/media/android/remote/media_controller_bridge.h" - -#include "jni/MediaControllerBridge_jni.h" - -namespace media_router { - -MediaControllerBridge::MediaControllerBridge( - base::android::ScopedJavaGlobalRef<jobject> controller) - : j_media_controller_bridge_(controller) {} - -MediaControllerBridge::~MediaControllerBridge() = default; - -void MediaControllerBridge::Play() { - JNIEnv* env = base::android::AttachCurrentThread(); - DCHECK(env); - - Java_MediaControllerBridge_play(env, j_media_controller_bridge_); -} - -void MediaControllerBridge::Pause() { - JNIEnv* env = base::android::AttachCurrentThread(); - DCHECK(env); - - Java_MediaControllerBridge_pause(env, j_media_controller_bridge_); -} - -void MediaControllerBridge::SetMute(bool mute) { - JNIEnv* env = base::android::AttachCurrentThread(); - DCHECK(env); - - Java_MediaControllerBridge_setMute(env, j_media_controller_bridge_, mute); -} - -void MediaControllerBridge::SetVolume(float volume) { - JNIEnv* env = base::android::AttachCurrentThread(); - DCHECK(env); - - Java_MediaControllerBridge_setVolume(env, j_media_controller_bridge_, volume); -} - -void MediaControllerBridge::Seek(base::TimeDelta time) { - JNIEnv* env = base::android::AttachCurrentThread(); - DCHECK(env); - - Java_MediaControllerBridge_seek(env, j_media_controller_bridge_, - time.InMilliseconds()); -} - -} // namespace media_router
diff --git a/chrome/browser/media/android/remote/media_controller_bridge.h b/chrome/browser/media/android/remote/media_controller_bridge.h deleted file mode 100644 index a854346..0000000 --- a/chrome/browser/media/android/remote/media_controller_bridge.h +++ /dev/null
@@ -1,37 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_MEDIA_ANDROID_REMOTE_MEDIA_CONTROLLER_BRIDGE_H_ -#define CHROME_BROWSER_MEDIA_ANDROID_REMOTE_MEDIA_CONTROLLER_BRIDGE_H_ - -#include "base/android/scoped_java_ref.h" -#include "base/time/time.h" -#include "media/base/media_controller.h" - -namespace media_router { - -// Allows native code to call into a Java MediaController. -class MediaControllerBridge : public media::MediaController { - public: - explicit MediaControllerBridge( - base::android::ScopedJavaGlobalRef<jobject> controller); - ~MediaControllerBridge() override; - - // MediaController implementation. - void Play() override; - void Pause() override; - void SetMute(bool mute) override; - void SetVolume(float volume) override; - void Seek(base::TimeDelta time) override; - - private: - // Java MediaControllerBridge instance. - base::android::ScopedJavaGlobalRef<jobject> j_media_controller_bridge_; - - DISALLOW_COPY_AND_ASSIGN(MediaControllerBridge); -}; - -} // namespace media_router - -#endif // CHROME_BROWSER_MEDIA_ANDROID_REMOTE_MEDIA_CONTROLLER_BRIDGE_H_
diff --git a/chrome/browser/media/android/router/media_router_android.cc b/chrome/browser/media/android/router/media_router_android.cc index 3546db9..41656d2 100644 --- a/chrome/browser/media/android/router/media_router_android.cc +++ b/chrome/browser/media/android/router/media_router_android.cc
@@ -316,9 +316,9 @@ observer.OnRoutesUpdated(active_routes_, std::vector<MediaRoute::Id>()); } -std::unique_ptr<media::MediaController> MediaRouterAndroid::GetMediaController( - const MediaRoute::Id& route_id) { - return bridge_->GetMediaController(route_id); +std::unique_ptr<media::FlingingController> +MediaRouterAndroid::GetFlingingController(const MediaRoute::Id& route_id) { + return bridge_->GetFlingingController(route_id); } } // namespace media_router
diff --git a/chrome/browser/media/android/router/media_router_android.h b/chrome/browser/media/android/router/media_router_android.h index 74e89600..f500f489 100644 --- a/chrome/browser/media/android/router/media_router_android.h +++ b/chrome/browser/media/android/router/media_router_android.h
@@ -65,7 +65,7 @@ const std::string& search_input, const std::string& domain, MediaSinkSearchResponseCallback sink_callback) override; - std::unique_ptr<media::MediaController> GetMediaController( + std::unique_ptr<media::FlingingController> GetFlingingController( const MediaRoute::Id& route_id) override; // The methods called by the Java bridge.
diff --git a/chrome/browser/media/android/router/media_router_android_bridge.cc b/chrome/browser/media/android/router/media_router_android_bridge.cc index 9a07306..f20ab550 100644 --- a/chrome/browser/media/android/router/media_router_android_bridge.cc +++ b/chrome/browser/media/android/router/media_router_android_bridge.cc
@@ -6,7 +6,7 @@ #include "base/android/jni_android.h" #include "base/android/jni_string.h" -#include "chrome/browser/media/android/remote/media_controller_bridge.h" +#include "chrome/browser/media/android/remote/flinging_controller_bridge.h" #include "chrome/browser/media/android/router/media_router_android.h" #include "jni/ChromeMediaRouter_jni.h" #include "media/base/media_controller.h" @@ -120,21 +120,22 @@ jsource_id); } -std::unique_ptr<media::MediaController> -MediaRouterAndroidBridge::GetMediaController(const MediaRoute::Id& route_id) { +std::unique_ptr<media::FlingingController> +MediaRouterAndroidBridge::GetFlingingController( + const MediaRoute::Id& route_id) { JNIEnv* env = base::android::AttachCurrentThread(); ScopedJavaLocalRef<jstring> jroute_id = base::android::ConvertUTF8ToJavaString(env, route_id); - ScopedJavaGlobalRef<jobject> media_controller; + ScopedJavaGlobalRef<jobject> flinging_controller; - media_controller.Reset(Java_ChromeMediaRouter_getMediaControllerBridge( + flinging_controller.Reset(Java_ChromeMediaRouter_getFlingingControllerBridge( env, java_media_router_, jroute_id)); - if (media_controller.is_null()) + if (flinging_controller.is_null()) return nullptr; - return std::make_unique<MediaControllerBridge>(media_controller); + return std::make_unique<FlingingControllerBridge>(flinging_controller); } void MediaRouterAndroidBridge::OnSinksReceived(
diff --git a/chrome/browser/media/android/router/media_router_android_bridge.h b/chrome/browser/media/android/router/media_router_android_bridge.h index d5e81f9f..d4c7891a 100644 --- a/chrome/browser/media/android/router/media_router_android_bridge.h +++ b/chrome/browser/media/android/router/media_router_android_bridge.h
@@ -10,7 +10,7 @@ #include "chrome/common/media_router/media_route.h" #include "chrome/common/media_router/media_sink.h" #include "chrome/common/media_router/media_source.h" -#include "media/base/media_controller.h" +#include "media/base/flinging_controller.h" #include "url/origin.h" namespace media_router { @@ -44,7 +44,7 @@ virtual void DetachRoute(const MediaRoute::Id& route_id); virtual bool StartObservingMediaSinks(const MediaSource::Id& source_id); virtual void StopObservingMediaSinks(const MediaSource::Id& source_id); - virtual std::unique_ptr<media::MediaController> GetMediaController( + virtual std::unique_ptr<media::FlingingController> GetFlingingController( const MediaRoute::Id& route_id); // Methods called by the Java counterpart.
diff --git a/chrome/browser/media/router/discovery/dial/dial_media_sink_service_impl_unittest.cc b/chrome/browser/media/router/discovery/dial/dial_media_sink_service_impl_unittest.cc index e9d912f3..d6fa8fb 100644 --- a/chrome/browser/media/router/discovery/dial/dial_media_sink_service_impl_unittest.cc +++ b/chrome/browser/media/router/discovery/dial/dial_media_sink_service_impl_unittest.cc
@@ -69,8 +69,11 @@ mock_app_discovery_service_ = mock_app_discovery_service.get(); media_sink_service_->SetAppDiscoveryServiceForTest( std::move(mock_app_discovery_service)); + base::RunLoop().RunUntilIdle(); } + void TearDown() override { test_dial_registry_.DoShutdown(); } + DialMediaSinkServiceImpl::SinkQueryByAppSubscription StartMonitoringAvailableSinksForApp(const std::string& app_name) { return media_sink_service_->StartMonitoringAvailableSinksForApp(
diff --git a/chrome/browser/media/router/discovery/dial/dial_registry.cc b/chrome/browser/media/router/discovery/dial/dial_registry.cc index 3fb604ad..924e5dc6 100644 --- a/chrome/browser/media/router/discovery/dial/dial_registry.cc +++ b/chrome/browser/media/router/discovery/dial/dial_registry.cc
@@ -20,7 +20,6 @@ using base::Time; using base::TimeDelta; using content::BrowserThread; -using net::NetworkChangeNotifier; namespace { @@ -33,6 +32,10 @@ // The maximum number of devices retained at once in the registry. const size_t kDialMaxDevices = 256; +// We create a global instead of using base::Singleton so we can check whether +// an instance has been created. +media_router::DialRegistry* g_dial_registry_instance; + } // namespace namespace media_router { @@ -48,9 +51,12 @@ clock_(base::DefaultClock::GetInstance()) { DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK_GT(max_devices_, 0U); - // This is a leaky singleton, so there's no code to remove |this| as an - // observer. - NetworkChangeNotifier::AddNetworkChangeObserver(this); + BrowserThread::PostTaskAndReplyWithResult( + BrowserThread::UI, FROM_HERE, + base::BindOnce(&BrowserProcess::network_connection_tracker, + base::Unretained(g_browser_process)), + base::BindOnce(&DialRegistry::SetNetworkConnectionTracker, + base::Unretained(this))); } // This is a leaky singleton and the dtor won't be called. @@ -59,8 +65,31 @@ // static DialRegistry* DialRegistry::GetInstance() { DCHECK_CURRENTLY_ON(BrowserThread::IO); - return base::Singleton<DialRegistry, - base::LeakySingletonTraits<DialRegistry>>::get(); + if (!g_dial_registry_instance) + g_dial_registry_instance = new DialRegistry(); + return g_dial_registry_instance; +} + +// static +void DialRegistry::Shutdown() { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + if (g_dial_registry_instance) { + g_dial_registry_instance->StopPeriodicDiscovery(); + g_dial_registry_instance->DoShutdown(); + } +} + +void DialRegistry::SetNetworkConnectionTracker( + content::NetworkConnectionTracker* tracker) { + network_connection_tracker_ = tracker; + network_connection_tracker_->AddNetworkConnectionObserver(this); + // If there are no observers yet, it won't actually start. + StartPeriodicDiscovery(); +} + +void DialRegistry::DoShutdown() { + if (network_connection_tracker_) + network_connection_tracker_->RemoveNetworkConnectionObserver(this); } void DialRegistry::SetNetLog(net::NetLog* net_log) { @@ -134,12 +163,21 @@ OnDialError(DIAL_NO_LISTENERS); return false; } - if (NetworkChangeNotifier::IsOffline()) { + network::mojom::ConnectionType type; + if (!network_connection_tracker_ || + !network_connection_tracker_->GetConnectionType( + &type, base::BindOnce(&DialRegistry::OnConnectionChanged, + base::Unretained(this)))) { + // If the ConnectionType is unknown, return false. We'll try to start + // discovery again when we receive the OnConnectionChanged callback. + OnDialError(DIAL_UNKNOWN); + return false; + } + if (type == network::mojom::ConnectionType::CONNECTION_NONE) { OnDialError(DIAL_NETWORK_DISCONNECTED); return false; } - if (NetworkChangeNotifier::IsConnectionCellular( - NetworkChangeNotifier::GetConnectionType())) { + if (content::NetworkConnectionTracker::IsConnectionCellular(type)) { OnDialError(DIAL_CELLULAR_NETWORK); return false; } @@ -350,10 +388,9 @@ } } -void DialRegistry::OnNetworkChanged( - NetworkChangeNotifier::ConnectionType type) { +void DialRegistry::OnConnectionChanged(network::mojom::ConnectionType type) { switch (type) { - case NetworkChangeNotifier::CONNECTION_NONE: + case network::mojom::ConnectionType::CONNECTION_NONE: if (dial_) { VLOG(2) << "Lost connection, shutting down discovery and clearing" << " list."; @@ -367,13 +404,13 @@ MaybeSendEvent(); } break; - case NetworkChangeNotifier::CONNECTION_2G: - case NetworkChangeNotifier::CONNECTION_3G: - case NetworkChangeNotifier::CONNECTION_4G: - case NetworkChangeNotifier::CONNECTION_ETHERNET: - case NetworkChangeNotifier::CONNECTION_WIFI: - case NetworkChangeNotifier::CONNECTION_UNKNOWN: - case NetworkChangeNotifier::CONNECTION_BLUETOOTH: + case network::mojom::ConnectionType::CONNECTION_2G: + case network::mojom::ConnectionType::CONNECTION_3G: + case network::mojom::ConnectionType::CONNECTION_4G: + case network::mojom::ConnectionType::CONNECTION_ETHERNET: + case network::mojom::ConnectionType::CONNECTION_WIFI: + case network::mojom::ConnectionType::CONNECTION_UNKNOWN: + case network::mojom::ConnectionType::CONNECTION_BLUETOOTH: if (!dial_) { VLOG(2) << "Connection detected, restarting discovery."; StartPeriodicDiscovery();
diff --git a/chrome/browser/media/router/discovery/dial/dial_registry.h b/chrome/browser/media/router/discovery/dial/dial_registry.h index d061d1b..1426207 100644 --- a/chrome/browser/media/router/discovery/dial/dial_registry.h +++ b/chrome/browser/media/router/discovery/dial/dial_registry.h
@@ -19,7 +19,7 @@ #include "base/timer/timer.h" #include "chrome/browser/media/router/discovery/dial/dial_service.h" #include "chrome/browser/profiles/profile.h" -#include "net/base/network_change_notifier.h" +#include "content/public/browser/network_connection_tracker.h" namespace base { class Clock; @@ -35,8 +35,9 @@ // the observer with an updated, complete set of active devices. The registry's // observer (i.e., the Dial API) owns the registry instance. // DialRegistry lives on the IO thread. -class DialRegistry : public DialService::Observer, - public net::NetworkChangeNotifier::NetworkChangeObserver { +class DialRegistry + : public DialService::Observer, + public content::NetworkConnectionTracker::NetworkConnectionObserver { public: using DeviceList = std::vector<DialDeviceData>; @@ -62,6 +63,10 @@ static DialRegistry* GetInstance(); + // Stops discovery and shuts down the DialRegistry. Should be called as the + // browser is shutting down. + static void Shutdown(); + // Sets the NetLog object used for logging. Should be called right after // GetInstance(). If the registry already has a NetLog, does nothing. The // NetLog should live at least as long as the IO Thread. @@ -118,6 +123,11 @@ DialRegistry(); ~DialRegistry() override; + // Called when we've gotten the NetworkConnectionTracker from the UI thread. + void SetNetworkConnectionTracker(content::NetworkConnectionTracker* tracker); + + void DoShutdown(); + // DialService::Observer: void OnDiscoveryRequest(DialService* service) override; void OnDeviceDiscovered(DialService* service, @@ -126,9 +136,8 @@ void OnError(DialService* service, const DialService::DialServiceErrorCode& code) override; - // net::NetworkChangeObserver: - void OnNetworkChanged( - net::NetworkChangeNotifier::ConnectionType type) override; + // content::NetworkConnectionTracker::NetworkConnectionObserver: + void OnConnectionChanged(network::mojom::ConnectionType type) override; // Notify all observers about DialDeviceEvent or DialError. void OnDialDeviceEvent(const DeviceList& devices); @@ -203,8 +212,12 @@ // Set just after construction, only used on the IO thread. net::NetLog* net_log_ = nullptr; + content::NetworkConnectionTracker* network_connection_tracker_ = nullptr; + base::Clock* clock_; + friend class DialMediaSinkServiceImplTest; + friend class DialRegistryTest; FRIEND_TEST_ALL_PREFIXES(DialRegistryTest, TestAddRemoveListeners); FRIEND_TEST_ALL_PREFIXES(DialRegistryTest, TestNoDevicesDiscovered); FRIEND_TEST_ALL_PREFIXES(DialRegistryTest, TestDevicesDiscovered);
diff --git a/chrome/browser/media/router/discovery/dial/dial_registry_unittest.cc b/chrome/browser/media/router/discovery/dial/dial_registry_unittest.cc index f60d441f..1e701af 100644 --- a/chrome/browser/media/router/discovery/dial/dial_registry_unittest.cc +++ b/chrome/browser/media/router/discovery/dial/dial_registry_unittest.cc
@@ -5,6 +5,7 @@ #include <stddef.h> #include "base/memory/ptr_util.h" +#include "base/run_loop.h" #include "base/test/simple_test_clock.h" #include "chrome/browser/media/router/discovery/dial/dial_device_data.h" #include "chrome/browser/media/router/discovery/dial/dial_registry.h" @@ -86,8 +87,11 @@ list_with_second_device_({second_device_}), list_with_first_second_devices_({first_device_, second_device_}) { registry_->RegisterObserver(&mock_observer_); + base::RunLoop().RunUntilIdle(); } + void TearDown() override { registry_->DoShutdown(); } + protected: void SetListenerExpectations() { EXPECT_CALL(registry_->mock_service(), @@ -338,7 +342,9 @@ registry_->OnDeviceDiscovered(nullptr, first_device_); registry_->OnDiscoveryFinished(nullptr); - registry_->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_NONE); + registry_->OnConnectionChanged( + network::mojom::ConnectionType::CONNECTION_NONE); + base::RunLoop().RunUntilIdle(); registry_->OnDiscoveryRequest(nullptr); registry_->OnDiscoveryFinished(nullptr); @@ -377,18 +383,24 @@ registry_->OnDeviceDiscovered(nullptr, first_device_); registry_->OnDiscoveryFinished(nullptr); - registry_->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_NONE); + registry_->OnConnectionChanged( + network::mojom::ConnectionType::CONNECTION_NONE); + base::RunLoop().RunUntilIdle(); registry_->OnDiscoveryRequest(nullptr); registry_->OnDiscoveryFinished(nullptr); - registry_->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_WIFI); + registry_->OnConnectionChanged( + network::mojom::ConnectionType::CONNECTION_WIFI); + base::RunLoop().RunUntilIdle(); registry_->OnDiscoveryRequest(nullptr); registry_->OnDeviceDiscovered(nullptr, second_device_); registry_->OnDiscoveryFinished(nullptr); - registry_->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_ETHERNET); + registry_->OnConnectionChanged( + network::mojom::ConnectionType::CONNECTION_ETHERNET); + base::RunLoop().RunUntilIdle(); registry_->OnDiscoveryRequest(nullptr); registry_->OnDeviceDiscovered(nullptr, third_device_);
diff --git a/chrome/browser/media/router/media_router.h b/chrome/browser/media/router/media_router.h index a11f2395..cf856a5 100644 --- a/chrome/browser/media/router/media_router.h +++ b/chrome/browser/media/router/media_router.h
@@ -23,7 +23,7 @@ #include "components/keyed_service/core/keyed_service.h" #include "components/sessions/core/session_id.h" #include "content/public/browser/presentation_service_delegate.h" -#include "media/base/media_controller.h" +#include "media/base/flinging_controller.h" namespace content { class WebContents; @@ -190,9 +190,10 @@ // there is a change to the media routes, subclass MediaRoutesObserver. virtual std::vector<MediaRoute> GetCurrentRoutes() const = 0; - // Returns a controller that directly sends commands to media within a route. + // Returns a controller that sends commands to media within a route, and + // propagates MediaStatus changes. // Returns a nullptr if no controller can be be found from |route_id|. - virtual std::unique_ptr<media::MediaController> GetMediaController( + virtual std::unique_ptr<media::FlingingController> GetFlingingController( const MediaRoute::Id& route_id) = 0; #if !defined(OS_ANDROID)
diff --git a/chrome/browser/media/router/media_router_base.cc b/chrome/browser/media/router/media_router_base.cc index e5c4a5a..e08ec6c 100644 --- a/chrome/browser/media/router/media_router_base.cc +++ b/chrome/browser/media/router/media_router_base.cc
@@ -86,8 +86,8 @@ return internal_routes_observer_->current_routes; } -std::unique_ptr<media::MediaController> MediaRouterBase::GetMediaController( - const MediaRoute::Id& route_id) { +std::unique_ptr<media::FlingingController> +MediaRouterBase::GetFlingingController(const MediaRoute::Id& route_id) { return nullptr; }
diff --git a/chrome/browser/media/router/media_router_base.h b/chrome/browser/media/router/media_router_base.h index 330d14e..0f9916f 100644 --- a/chrome/browser/media/router/media_router_base.h +++ b/chrome/browser/media/router/media_router_base.h
@@ -17,7 +17,6 @@ #include "chrome/browser/media/router/media_router.h" #include "chrome/browser/media/router/media_routes_observer.h" #include "chrome/common/media_router/media_route.h" -#include "media/base/media_controller.h" #include "third_party/blink/public/platform/modules/presentation/presentation.mojom.h" namespace media_router { @@ -35,7 +34,7 @@ void OnIncognitoProfileShutdown() override; IssueManager* GetIssueManager() final; std::vector<MediaRoute> GetCurrentRoutes() const override; - std::unique_ptr<media::MediaController> GetMediaController( + std::unique_ptr<media::FlingingController> GetFlingingController( const MediaRoute::Id& route_id) override; #if !defined(OS_ANDROID) scoped_refptr<MediaRouteController> GetRouteController(
diff --git a/chrome/browser/media/router/mojo/media_router_mojo_impl.cc b/chrome/browser/media/router/mojo/media_router_mojo_impl.cc index f388b09..371bf712 100644 --- a/chrome/browser/media/router/mojo/media_router_mojo_impl.cc +++ b/chrome/browser/media/router/mojo/media_router_mojo_impl.cc
@@ -31,7 +31,6 @@ #include "content/public/browser/browser_thread.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" -#include "content/public/common/presentation_connection_message.h" #define DVLOG_WITH_INSTANCE(level) \ DVLOG(level) << "MR #" << instance_id_ << ": "
diff --git a/chrome/browser/media/router/presentation/browser_presentation_connection_proxy.cc b/chrome/browser/media/router/presentation/browser_presentation_connection_proxy.cc index 44b945d..b4a61d0 100644 --- a/chrome/browser/media/router/presentation/browser_presentation_connection_proxy.cc +++ b/chrome/browser/media/router/presentation/browser_presentation_connection_proxy.cc
@@ -42,16 +42,16 @@ BrowserPresentationConnectionProxy::~BrowserPresentationConnectionProxy() {} void BrowserPresentationConnectionProxy::OnMessage( - content::PresentationConnectionMessage message, + blink::mojom::PresentationConnectionMessagePtr message, OnMessageCallback on_message_callback) { DVLOG(2) << "BrowserPresentationConnectionProxy::OnMessage"; - if (message.is_binary()) { + if (message->is_data()) { router_->SendRouteBinaryMessage( route_id_, - std::make_unique<std::vector<uint8_t>>(std::move(message.data.value())), + std::make_unique<std::vector<uint8_t>>(std::move(message->get_data())), std::move(on_message_callback)); } else { - router_->SendRouteMessage(route_id_, message.message.value(), + router_->SendRouteMessage(route_id_, message->get_message(), std::move(on_message_callback)); } }
diff --git a/chrome/browser/media/router/presentation/browser_presentation_connection_proxy.h b/chrome/browser/media/router/presentation/browser_presentation_connection_proxy.h index d713890..0bc03b42 100644 --- a/chrome/browser/media/router/presentation/browser_presentation_connection_proxy.h +++ b/chrome/browser/media/router/presentation/browser_presentation_connection_proxy.h
@@ -11,6 +11,7 @@ #include "chrome/common/media_router/media_route.h" #include "content/public/browser/presentation_service_delegate.h" #include "mojo/public/cpp/bindings/binding.h" +#include "third_party/blink/public/platform/modules/presentation/presentation.mojom.h" namespace media_router { @@ -56,7 +57,7 @@ ~BrowserPresentationConnectionProxy() override; // blink::mojom::PresentationConnection implementation - void OnMessage(content::PresentationConnectionMessage message, + void OnMessage(blink::mojom::PresentationConnectionMessagePtr message, OnMessageCallback on_message_callback) override; // Underlying media route is always connected. Media route class does not
diff --git a/chrome/browser/media/router/presentation/browser_presentation_connection_proxy_unittest.cc b/chrome/browser/media/router/presentation/browser_presentation_connection_proxy_unittest.cc index 9b07c5e..7eacfe0 100644 --- a/chrome/browser/media/router/presentation/browser_presentation_connection_proxy_unittest.cc +++ b/chrome/browser/media/router/presentation/browser_presentation_connection_proxy_unittest.cc
@@ -7,16 +7,16 @@ #include <memory> #include "base/run_loop.h" -#include "base/test/mock_callback.h" #include "chrome/browser/media/router/route_message_util.h" #include "chrome/browser/media/router/test/mock_media_router.h" #include "chrome/browser/media/router/test/test_helper.h" #include "chrome/common/media_router/media_source.h" #include "chrome/common/media_router/media_source_helper.h" -#include "content/public/common/presentation_connection_message.h" #include "content/public/test/test_browser_thread_bundle.h" #include "testing/gmock/include/gmock/gmock.h" +using blink::mojom::PresentationConnectionMessage; +using blink::mojom::PresentationConnectionMessagePtr; using media_router::mojom::RouteMessagePtr; using ::testing::_; using ::testing::Invoke; @@ -28,9 +28,9 @@ namespace { void ExpectMessageAndRunCallback( - const content::PresentationConnectionMessage& expected_message, - const content::PresentationConnectionMessage& message, - OnMessageCallback& callback) { + const PresentationConnectionMessagePtr expected_message, + const PresentationConnectionMessagePtr message, + OnMessageCallback callback) { EXPECT_EQ(expected_message, message); std::move(callback).Run(true); } @@ -94,14 +94,14 @@ TEST_F(BrowserPresentationConnectionProxyTest, TestOnMessageTextMessage) { std::string message = "test message"; - content::PresentationConnectionMessage connection_message(message); + PresentationConnectionMessagePtr connection_message = + PresentationConnectionMessage::NewMessage(message); - base::MockCallback<base::OnceCallback<void(bool)>> mock_on_message_callback; EXPECT_CALL(*mock_router(), SendRouteMessageInternal(kMediaRouteId, message, _)); browser_connection_proxy()->OnMessage(std::move(connection_message), - mock_on_message_callback.Get()); + base::BindOnce([](bool result) {})); } TEST_F(BrowserPresentationConnectionProxyTest, TestOnMessageBinaryMessage) { @@ -109,9 +109,9 @@ expected_data.push_back(42); expected_data.push_back(36); - content::PresentationConnectionMessage connection_message(expected_data); + PresentationConnectionMessagePtr connection_message = + PresentationConnectionMessage::NewData(expected_data); - base::MockCallback<base::OnceCallback<void(bool)>> mock_on_message_callback; EXPECT_CALL(*mock_router(), SendRouteBinaryMessageInternal(_, _, _)) .WillOnce(Invoke([&expected_data](const MediaRoute::Id& route_id, std::vector<uint8_t>* data, @@ -120,32 +120,26 @@ })); browser_connection_proxy()->OnMessage(std::move(connection_message), - mock_on_message_callback.Get()); + base::BindOnce([](bool result) {})); } TEST_F(BrowserPresentationConnectionProxyTest, OnMessagesReceived) { - content::PresentationConnectionMessage message_1; - message_1.message = std::string("foo"); - content::PresentationConnectionMessage message_2; - message_2.data = std::vector<uint8_t>({1, 2, 3}); - - EXPECT_CALL(*controller_connection_proxy(), OnMessageInternal(_, _)) - .WillOnce(Invoke( - [&message_1](const content::PresentationConnectionMessage& message, - OnMessageCallback& callback) { - ExpectMessageAndRunCallback(message_1, message, callback); - })) - .WillOnce(Invoke( - [&message_2](const content::PresentationConnectionMessage& message, - OnMessageCallback& callback) { - ExpectMessageAndRunCallback(message_2, message, callback); - })); + EXPECT_CALL(*controller_connection_proxy(), OnMessage(_, _)) + .WillOnce([&](auto message, auto callback) { + ExpectMessageAndRunCallback( + PresentationConnectionMessage::NewMessage("foo"), + std::move(message), std::move(callback)); + }) + .WillOnce([&](auto message, auto callback) { + ExpectMessageAndRunCallback(PresentationConnectionMessage::NewData( + std::vector<uint8_t>({1, 2, 3})), + std::move(message), std::move(callback)); + }); std::vector<RouteMessagePtr> route_messages; + route_messages.emplace_back(message_util::RouteMessageFromString("foo")); route_messages.emplace_back( - message_util::RouteMessageFromString(message_1.message.value())); - route_messages.emplace_back( - message_util::RouteMessageFromData(message_2.data.value())); + message_util::RouteMessageFromData(std::vector<uint8_t>({1, 2, 3}))); browser_connection_proxy()->OnMessagesReceived(std::move(route_messages)); base::RunLoop().RunUntilIdle(); }
diff --git a/chrome/browser/media/router/presentation/local_presentation_manager.h b/chrome/browser/media/router/presentation/local_presentation_manager.h index dac45af6..4e543d3 100644 --- a/chrome/browser/media/router/presentation/local_presentation_manager.h +++ b/chrome/browser/media/router/presentation/local_presentation_manager.h
@@ -80,7 +80,8 @@ // PresentationConnctionPtr::SendString( // const blink::WebString& message) { // target_connection_->OnMessage( -// content::PresentationConnectionMessage(message.Utf8()), +// blink::mojom::PresentationConnectionMessage::NewMessage( +// message.Utf8()), // base::BindOnce(&OnMessageReceived)); // } //
diff --git a/chrome/browser/media/router/presentation/presentation_service_delegate_impl.cc b/chrome/browser/media/router/presentation/presentation_service_delegate_impl.cc index 1bab943..66f7a24 100644 --- a/chrome/browser/media/router/presentation/presentation_service_delegate_impl.cc +++ b/chrome/browser/media/router/presentation/presentation_service_delegate_impl.cc
@@ -673,8 +673,8 @@ observer.OnDefaultPresentationRemoved(); } -std::unique_ptr<media::MediaController> -PresentationServiceDelegateImpl::GetMediaController( +std::unique_ptr<media::FlingingController> +PresentationServiceDelegateImpl::GetFlingingController( int render_process_id, int render_frame_id, const std::string& presentation_id) { @@ -684,7 +684,7 @@ if (route_id.empty()) return nullptr; - return router_->GetMediaController(route_id); + return router_->GetFlingingController(route_id); } MediaRoute::Id PresentationServiceDelegateImpl::GetRouteId(
diff --git a/chrome/browser/media/router/presentation/presentation_service_delegate_impl.h b/chrome/browser/media/router/presentation/presentation_service_delegate_impl.h index 6f5e207..5db27b4 100644 --- a/chrome/browser/media/router/presentation/presentation_service_delegate_impl.h +++ b/chrome/browser/media/router/presentation/presentation_service_delegate_impl.h
@@ -25,7 +25,6 @@ #include "content/public/browser/presentation_service_delegate.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_user_data.h" -#include "media/base/media_controller.h" namespace content { class PresentationScreenAvailabilityListener; @@ -110,7 +109,7 @@ void Terminate(int render_process_id, int render_frame_id, const std::string& presentation_id) override; - std::unique_ptr<media::MediaController> GetMediaController( + std::unique_ptr<media::FlingingController> GetFlingingController( int render_process_id, int render_frame_id, const std::string& presentation_id) override;
diff --git a/chrome/browser/media/router/route_message_util.cc b/chrome/browser/media/router/route_message_util.cc index 9705dc6f..c6992b2 100644 --- a/chrome/browser/media/router/route_message_util.cc +++ b/chrome/browser/media/router/route_message_util.cc
@@ -26,18 +26,20 @@ return route_message; } -content::PresentationConnectionMessage PresentationConnectionFromRouteMessage( - RouteMessagePtr route_message) { +blink::mojom::PresentationConnectionMessagePtr +PresentationConnectionFromRouteMessage(RouteMessagePtr route_message) { + // NOTE: Makes a copy of |route_message| contents. This can be eliminated + // when media_router::mojom::RouteMessage is deleted. switch (route_message->type) { case RouteMessage::Type::TEXT: - return content::PresentationConnectionMessage( + return blink::mojom::PresentationConnectionMessage::NewMessage( route_message->message.value()); case RouteMessage::Type::BINARY: - return content::PresentationConnectionMessage( + return blink::mojom::PresentationConnectionMessage::NewData( route_message->data.value()); default: NOTREACHED() << "Unknown RouteMessageType " << route_message->type; - return content::PresentationConnectionMessage(); + return blink::mojom::PresentationConnectionMessage::New(); } }
diff --git a/chrome/browser/media/router/route_message_util.h b/chrome/browser/media/router/route_message_util.h index bed4b06..753a0fd 100644 --- a/chrome/browser/media/router/route_message_util.h +++ b/chrome/browser/media/router/route_message_util.h
@@ -10,7 +10,7 @@ #include <vector> #include "chrome/common/media_router/mojo/media_router.mojom.h" -#include "content/public/common/presentation_connection_message.h" +#include "third_party/blink/public/platform/modules/presentation/presentation.mojom.h" namespace media_router { namespace message_util { @@ -21,7 +21,8 @@ media_router::mojom::RouteMessagePtr RouteMessageFromData( std::vector<uint8_t> data); -content::PresentationConnectionMessage PresentationConnectionFromRouteMessage( +blink::mojom::PresentationConnectionMessagePtr +PresentationConnectionFromRouteMessage( media_router::mojom::RouteMessagePtr route_message); } // namespace message_util
diff --git a/chrome/browser/media/router/test/test_helper.h b/chrome/browser/media/router/test/test_helper.h index e8498b6..0be5dab 100644 --- a/chrome/browser/media/router/test/test_helper.h +++ b/chrome/browser/media/router/test/test_helper.h
@@ -18,8 +18,8 @@ #include "chrome/browser/media/router/media_routes_observer.h" #include "chrome/browser/media/router/media_sinks_observer.h" #include "content/public/browser/presentation_service_delegate.h" -#include "content/public/common/presentation_connection_message.h" #include "testing/gmock/include/gmock/gmock.h" +#include "third_party/blink/public/platform/modules/presentation/presentation.mojom.h" #if !defined(OS_ANDROID) @@ -99,18 +99,11 @@ class MockPresentationConnectionProxy : public blink::mojom::PresentationConnection { public: - // PresentationConnectionMessage is move-only. - // TODO(crbug.com/729950): Use MOCK_METHOD directly once GMock gets the - // move-only type support. MockPresentationConnectionProxy(); ~MockPresentationConnectionProxy() override; - void OnMessage(content::PresentationConnectionMessage message, - OnMessageCallback cb) override { - OnMessageInternal(message, cb); - } - MOCK_METHOD2(OnMessageInternal, - void(const content::PresentationConnectionMessage&, - OnMessageCallback&)); + MOCK_METHOD2(OnMessage, + void(blink::mojom::PresentationConnectionMessagePtr, + OnMessageCallback)); MOCK_METHOD1(DidChangeState, void(blink::mojom::PresentationConnectionState state)); MOCK_METHOD0(RequestClose, void());
diff --git a/chrome/browser/media/webrtc/desktop_capture_access_handler.cc b/chrome/browser/media/webrtc/desktop_capture_access_handler.cc index 42f38694c..316a264 100644 --- a/chrome/browser/media/webrtc/desktop_capture_access_handler.cc +++ b/chrome/browser/media/webrtc/desktop_capture_access_handler.cc
@@ -11,7 +11,6 @@ #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" -#include "chrome/browser/media/webrtc/desktop_streams_registry.h" #include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h" #include "chrome/browser/media/webrtc/media_stream_capture_indicator.h" #include "chrome/browser/ui/browser.h" @@ -23,6 +22,7 @@ #include "chrome/grit/generated_resources.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/desktop_media_id.h" +#include "content/public/browser/desktop_streams_registry.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" #include "content/public/common/content_switches.h" @@ -416,13 +416,11 @@ content::RenderFrameHost* const main_frame = web_contents_for_stream ? web_contents_for_stream->GetMainFrame() : NULL; if (main_frame) { - media_id = MediaCaptureDevicesDispatcher::GetInstance() - ->GetDesktopStreamsRegistry() - ->RequestMediaForStreamId(request.requested_video_device_id, - main_frame->GetProcess()->GetID(), - main_frame->GetRoutingID(), - request.security_origin, - &original_extension_name); + media_id = + content::DesktopStreamsRegistry::GetInstance()->RequestMediaForStreamId( + request.requested_video_device_id, + main_frame->GetProcess()->GetID(), main_frame->GetRoutingID(), + request.security_origin, &original_extension_name); } // Received invalid device id.
diff --git a/chrome/browser/media/webrtc/desktop_streams_registry.cc b/chrome/browser/media/webrtc/desktop_streams_registry.cc deleted file mode 100644 index 3b2794f5..0000000 --- a/chrome/browser/media/webrtc/desktop_streams_registry.cc +++ /dev/null
@@ -1,91 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/media/webrtc/desktop_streams_registry.h" - -#include "base/base64.h" -#include "base/location.h" -#include "base/macros.h" -#include "base/time/time.h" -#include "content/public/browser/browser_thread.h" -#include "crypto/random.h" - -namespace { - -const int kStreamIdLengthBytes = 16; - -const int kApprovedStreamTimeToLiveSeconds = 10; - -std::string GenerateRandomStreamId() { - char buffer[kStreamIdLengthBytes]; - crypto::RandBytes(buffer, arraysize(buffer)); - std::string result; - base::Base64Encode(base::StringPiece(buffer, arraysize(buffer)), - &result); - return result; -} - -} // namespace - -DesktopStreamsRegistry::DesktopStreamsRegistry() {} -DesktopStreamsRegistry::~DesktopStreamsRegistry() {} - -std::string DesktopStreamsRegistry::RegisterStream( - int render_process_id, - int render_frame_id, - const GURL& origin, - const content::DesktopMediaID& source, - const std::string& extension_name) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - - std::string id = GenerateRandomStreamId(); - DCHECK(approved_streams_.find(id) == approved_streams_.end()); - ApprovedDesktopMediaStream& stream = approved_streams_[id]; - stream.render_process_id = render_process_id; - stream.render_frame_id = render_frame_id; - stream.origin = origin; - stream.source = source; - stream.extension_name = extension_name; - - content::BrowserThread::PostDelayedTask( - content::BrowserThread::UI, FROM_HERE, - base::BindOnce(&DesktopStreamsRegistry::CleanupStream, - base::Unretained(this), id), - base::TimeDelta::FromSeconds(kApprovedStreamTimeToLiveSeconds)); - - return id; -} - -content::DesktopMediaID DesktopStreamsRegistry::RequestMediaForStreamId( - const std::string& id, - int render_process_id, - int render_frame_id, - const GURL& origin, - std::string* extension_name) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - - StreamsMap::iterator it = approved_streams_.find(id); - - // Verify that if there is a request with the specified ID it was created for - // the same origin and the same renderer. - if (it == approved_streams_.end() || - render_process_id != it->second.render_process_id || - render_frame_id != it->second.render_frame_id || - origin != it->second.origin) { - return content::DesktopMediaID(); - } - - content::DesktopMediaID result = it->second.source; - *extension_name = it->second.extension_name; - approved_streams_.erase(it); - return result; -} - -void DesktopStreamsRegistry::CleanupStream(const std::string& id) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - approved_streams_.erase(id); -} - -DesktopStreamsRegistry::ApprovedDesktopMediaStream::ApprovedDesktopMediaStream() - : render_process_id(-1), render_frame_id(-1) {}
diff --git a/chrome/browser/media/webrtc/desktop_streams_registry.h b/chrome/browser/media/webrtc/desktop_streams_registry.h deleted file mode 100644 index e8b9aa0..0000000 --- a/chrome/browser/media/webrtc/desktop_streams_registry.h +++ /dev/null
@@ -1,65 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_MEDIA_WEBRTC_DESKTOP_STREAMS_REGISTRY_H_ -#define CHROME_BROWSER_MEDIA_WEBRTC_DESKTOP_STREAMS_REGISTRY_H_ - -#include <map> -#include <string> - -#include "base/macros.h" -#include "chrome/browser/media/webrtc/desktop_media_list.h" -#include "url/gurl.h" - -// DesktopStreamsRegistry is used to store accepted desktop media streams for -// Desktop Capture API. Single instance of this class is created per browser in -// MediaCaptureDevicesDispatcher. -class DesktopStreamsRegistry { - public: - DesktopStreamsRegistry(); - ~DesktopStreamsRegistry(); - - // Adds new stream to the registry. Called by the implementation of - // desktopCapture.chooseDesktopMedia() API after user has approved access to - // |source| for the |origin|. Returns identifier of the new stream. - // |render_frame_id| refers to the RenderFrame requesting the stream. - std::string RegisterStream(int render_process_id, - int render_frame_id, - const GURL& origin, - const content::DesktopMediaID& source, - const std::string& extension_name); - - // Validates stream identifier specified in getUserMedia(). Returns null - // DesktopMediaID if the specified |id| is invalid, i.e. wasn't generated - // using RegisterStream() or if it was generated for a different - // RenderFrame/origin. Otherwise returns ID of the source and removes it from - // the registry. - content::DesktopMediaID RequestMediaForStreamId(const std::string& id, - int render_process_id, - int render_frame_id, - const GURL& origin, - std::string* extension_name); - - private: - // Type used to store list of accepted desktop media streams. - struct ApprovedDesktopMediaStream { - ApprovedDesktopMediaStream(); - - int render_process_id; - int render_frame_id; - GURL origin; - content::DesktopMediaID source; - std::string extension_name; - }; - typedef std::map<std::string, ApprovedDesktopMediaStream> StreamsMap; - - // Helper function that removes an expired stream from the registry. - void CleanupStream(const std::string& id); - - StreamsMap approved_streams_; - - DISALLOW_COPY_AND_ASSIGN(DesktopStreamsRegistry); -}; - -#endif // CHROME_BROWSER_MEDIA_WEBRTC_DESKTOP_STREAMS_REGISTRY_H_
diff --git a/chrome/browser/media/webrtc/media_capture_devices_dispatcher.cc b/chrome/browser/media/webrtc/media_capture_devices_dispatcher.cc index 2e01b9c..30fdcbf 100644 --- a/chrome/browser/media/webrtc/media_capture_devices_dispatcher.cc +++ b/chrome/browser/media/webrtc/media_capture_devices_dispatcher.cc
@@ -12,7 +12,6 @@ #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" #include "chrome/browser/media/media_access_handler.h" -#include "chrome/browser/media/webrtc/desktop_streams_registry.h" #include "chrome/browser/media/webrtc/media_stream_capture_indicator.h" #include "chrome/browser/media/webrtc/permission_bubble_media_access_handler.h" #include "chrome/browser/profiles/profile.h" @@ -305,13 +304,6 @@ return media_stream_capture_indicator_; } -DesktopStreamsRegistry* -MediaCaptureDevicesDispatcher::GetDesktopStreamsRegistry() { - if (!desktop_streams_registry_) - desktop_streams_registry_.reset(new DesktopStreamsRegistry()); - return desktop_streams_registry_.get(); -} - void MediaCaptureDevicesDispatcher::OnAudioCaptureDevicesChanged() { DCHECK_CURRENTLY_ON(BrowserThread::IO); BrowserThread::PostTask(
diff --git a/chrome/browser/media/webrtc/media_capture_devices_dispatcher.h b/chrome/browser/media/webrtc/media_capture_devices_dispatcher.h index 375fcfd..b2abed5 100644 --- a/chrome/browser/media/webrtc/media_capture_devices_dispatcher.h +++ b/chrome/browser/media/webrtc/media_capture_devices_dispatcher.h
@@ -19,7 +19,6 @@ #include "content/public/browser/web_contents_delegate.h" #include "content/public/common/media_stream_request.h" -class DesktopStreamsRegistry; class MediaAccessHandler; class MediaStreamCaptureIndicator; class Profile; @@ -152,8 +151,6 @@ scoped_refptr<MediaStreamCaptureIndicator> GetMediaStreamCaptureIndicator(); - DesktopStreamsRegistry* GetDesktopStreamsRegistry(); - // Return true if there is any ongoing insecured capturing. The capturing is // deemed secure if all connected video sinks are reported secure and the // extension is trusted. @@ -202,8 +199,6 @@ scoped_refptr<MediaStreamCaptureIndicator> media_stream_capture_indicator_; - std::unique_ptr<DesktopStreamsRegistry> desktop_streams_registry_; - // Handlers for processing media access requests. std::vector<std::unique_ptr<MediaAccessHandler>> media_access_handlers_;
diff --git a/chrome/browser/media/webrtc/screen_capture_infobar_delegate_android.cc b/chrome/browser/media/webrtc/screen_capture_infobar_delegate_android.cc index 62e3053..1051293 100644 --- a/chrome/browser/media/webrtc/screen_capture_infobar_delegate_android.cc +++ b/chrome/browser/media/webrtc/screen_capture_infobar_delegate_android.cc
@@ -7,12 +7,12 @@ #include "base/callback_helpers.h" #include "chrome/browser/android/android_theme_resources.h" #include "chrome/browser/infobars/infobar_service.h" -#include "chrome/browser/media/webrtc/desktop_streams_registry.h" #include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h" #include "chrome/browser/media/webrtc/media_stream_capture_indicator.h" #include "chrome/grit/generated_resources.h" #include "components/infobars/core/infobar.h" #include "components/url_formatter/elide_url.h" +#include "content/public/browser/desktop_media_id.h" #include "content/public/browser/web_contents.h" #include "content/public/common/media_stream_request.h" #include "third_party/webrtc/modules/desktop_capture/desktop_capture_types.h"
diff --git a/chrome/browser/metrics/chrome_metrics_service_client.cc b/chrome/browser/metrics/chrome_metrics_service_client.cc index 11f3c82d..bbf327fafc 100644 --- a/chrome/browser/metrics/chrome_metrics_service_client.cc +++ b/chrome/browser/metrics/chrome_metrics_service_client.cc
@@ -84,7 +84,6 @@ #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" #include "components/sync/device_info/device_count_metrics_provider.h" -#include "components/ukm/content/debug_page/debug_page.h" #include "components/ukm/ukm_service.h" #include "components/version_info/version_info.h" #include "content/public/browser/browser_thread.h" @@ -343,13 +342,6 @@ } #endif // OS_WIN -ukm::UkmService* BindableGetUkmService( - base::WeakPtr<ChromeMetricsServiceClient> weak_ptr) { - if (!weak_ptr) - return nullptr; - return weak_ptr->GetUkmService(); -} - #if defined(OS_ANDROID) class AndroidIncognitoObserver : public TabModelListObserver { public: @@ -888,10 +880,6 @@ } bool ChromeMetricsServiceClient::RegisterForProfileEvents(Profile* profile) { - // Register chrome://ukm handler - content::URLDataSource::Add( - profile, new ukm::debug::DebugPage(base::Bind( - &BindableGetUkmService, weak_ptr_factory_.GetWeakPtr()))); #if defined(OS_CHROMEOS) // Ignore the signin and lock screen app profile for sync disables / history // deletion.
diff --git a/chrome/browser/previews/resource_loading_hints/resource_loading_hints_browsertest.cc b/chrome/browser/previews/resource_loading_hints/resource_loading_hints_browsertest.cc index 5c60c7f..175291d 100644 --- a/chrome/browser/previews/resource_loading_hints/resource_loading_hints_browsertest.cc +++ b/chrome/browser/previews/resource_loading_hints/resource_loading_hints_browsertest.cc
@@ -285,11 +285,21 @@ ResourceLoadingHintsHttpsWhitelisted #define MAYBE_ResourceLoadingHintsHttpsWhitelistedRedirectToHttps \ ResourceLoadingHintsHttpsWhitelistedRedirectToHttps +#define MAYBE_ResourceLoadingHintsHttpsNoWhitelisted \ + ResourceLoadingHintsHttpsNoWhitelisted +#define MAYBE_ResourceLoadingHintsHttp ResourceLoadingHintsHttp +#define MAYBE_ResourceLoadingHintsHttpsWhitelistedNoTransform \ + ResourceLoadingHintsHttpsWhitelistedNoTransform #else #define MAYBE_ResourceLoadingHintsHttpsWhitelisted \ DISABLED_ResourceLoadingHintsHttpsWhitelisted #define MAYBE_ResourceLoadingHintsHttpsWhitelistedRedirectToHttps \ DISABLED_ResourceLoadingHintsHttpsWhitelistedRedirectToHttps +#define MAYBE_ResourceLoadingHintsHttpsNoWhitelisted \ + DISABLED_ResourceLoadingHintsHttpsNoWhitelisted +#define MAYBE_ResourceLoadingHintsHttp DISABLED_ResourceLoadingHintsHttp +#define MAYBE_ResourceLoadingHintsHttpsWhitelistedNoTransform \ + DISABLED_ResourceLoadingHintsHttpsWhitelistedNoTransform #endif IN_PROC_BROWSER_TEST_F(ResourceLoadingHintsBrowserTest, @@ -370,7 +380,7 @@ } IN_PROC_BROWSER_TEST_F(ResourceLoadingHintsBrowserTest, - ResourceLoadingHintsHttpsNoWhitelisted) { + MAYBE_ResourceLoadingHintsHttpsNoWhitelisted) { SetExpectedFooJpgRequest(true); SetExpectedBarJpgRequest(true); SetResourceLoadingHintsPatterns(); @@ -397,7 +407,7 @@ } IN_PROC_BROWSER_TEST_F(ResourceLoadingHintsBrowserTest, - ResourceLoadingHintsHttp) { + MAYBE_ResourceLoadingHintsHttp) { SetExpectedFooJpgRequest(true); SetExpectedBarJpgRequest(true); SetResourceLoadingHintsPatterns(); @@ -424,7 +434,7 @@ } IN_PROC_BROWSER_TEST_F(ResourceLoadingHintsBrowserTest, - ResourceLoadingHintsHttpsWhitelistedNoTransform) { + MAYBE_ResourceLoadingHintsHttpsWhitelistedNoTransform) { SetExpectedFooJpgRequest(true); SetExpectedBarJpgRequest(true); SetResourceLoadingHintsPatterns();
diff --git a/chrome/browser/resources/chromeos/select_to_speak/BUILD.gn b/chrome/browser/resources/chromeos/select_to_speak/BUILD.gn index ec431466..c94b0d86 100644 --- a/chrome/browser/resources/chromeos/select_to_speak/BUILD.gn +++ b/chrome/browser/resources/chromeos/select_to_speak/BUILD.gn
@@ -40,6 +40,7 @@ "options.css", "options.html", "paragraph_utils.js", + "prefs_manager.js", "rect_utils.js", "select_to_speak.js", "select_to_speak_gdocs_script.js", @@ -175,6 +176,7 @@ ":metrics_utils", ":node_utils", ":paragraph_utils", + ":prefs_manager", ":rect_utils", ":select_to_speak", ":select_to_speak_options", @@ -190,6 +192,7 @@ ":metrics_utils", ":node_utils", ":paragraph_utils", + ":prefs_manager", ":rect_utils", ":word_utils", ] @@ -252,7 +255,13 @@ js_library("rect_utils") { } +js_library("prefs_manager") { +} + js_library("metrics_utils") { + deps = [ + ":prefs_manager", + ] externs_list = [ "$externs_path/metrics_private.js" ] }
diff --git a/chrome/browser/resources/chromeos/select_to_speak/manifest.json.jinja2 b/chrome/browser/resources/chromeos/select_to_speak/manifest.json.jinja2 index 4b13056..42971ae2 100644 --- a/chrome/browser/resources/chromeos/select_to_speak/manifest.json.jinja2 +++ b/chrome/browser/resources/chromeos/select_to_speak/manifest.json.jinja2
@@ -20,6 +20,7 @@ "metrics_utils.js", "node_utils.js", "paragraph_utils.js", + "prefs_manager.js", "word_utils.js", "rect_utils.js", "select_to_speak.js",
diff --git a/chrome/browser/resources/chromeos/select_to_speak/metrics_utils.js b/chrome/browser/resources/chromeos/select_to_speak/metrics_utils.js index 582c56e..3e868494 100644 --- a/chrome/browser/resources/chromeos/select_to_speak/metrics_utils.js +++ b/chrome/browser/resources/chromeos/select_to_speak/metrics_utils.js
@@ -135,22 +135,22 @@ * Records an event that Select-to-Speak has begun speaking. * @param {number} method The CrosSelectToSpeakStartSpeechMethod enum * that reflects how this event was triggered by the user. - * @param {number} speechRate The current speech rate. - * @param {number} speechPitch The current speech pitch. - * @param {boolean} wordHighlightingEnabled If word highlighting is enabled. + * @param {PrefsManager} prefsManager A PrefsManager with the users's current + * preferences. * @public */ -MetricsUtils.recordStartEvent = function( - method, speechRate, speechPitch, wordHighlightingEnabled) { +MetricsUtils.recordStartEvent = function(method, prefsManager) { chrome.metricsPrivate.recordUserAction(MetricsUtils.START_SPEECH_METRIC); chrome.metricsPrivate.recordSparseValue( MetricsUtils.SPEECH_RATE_METRIC, - MetricsUtils.speechRateToSparceHistogramInt_(speechRate)); + MetricsUtils.speechRateToSparceHistogramInt_(prefsManager.speechRate())); chrome.metricsPrivate.recordSparseValue( MetricsUtils.SPEECH_PITCH_METRIC, - MetricsUtils.speechPitchToSparceHistogramInt_(speechPitch)); + MetricsUtils.speechPitchToSparceHistogramInt_( + prefsManager.speechPitch())); chrome.metricsPrivate.recordBoolean( - MetricsUtils.WORD_HIGHLIGHTING_METRIC, wordHighlightingEnabled); + MetricsUtils.WORD_HIGHLIGHTING_METRIC, + prefsManager.wordHighlightingEnabled()); chrome.metricsPrivate.recordEnumerationValue( MetricsUtils.START_SPEECH_METHOD_METRIC.METRIC_NAME, method, MetricsUtils.START_SPEECH_METHOD_METRIC.EVENT_COUNT);
diff --git a/chrome/browser/resources/chromeos/select_to_speak/prefs_manager.js b/chrome/browser/resources/chromeos/select_to_speak/prefs_manager.js new file mode 100644 index 0000000..889ffa6 --- /dev/null +++ b/chrome/browser/resources/chromeos/select_to_speak/prefs_manager.js
@@ -0,0 +1,209 @@ +// 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. + +/** + * Manages getting and storing user preferences. + * @constructor + */ +let PrefsManager = function() { + /** @private {?string} */ + this.voiceNameFromPrefs_ = null; + + /** @private {?string} */ + this.voiceNameFromLocale_ = null; + + /** @private {Set<string>} */ + this.validVoiceNames_ = new Set(); + + /** @private {number} */ + this.speechRate_ = 1.0; + + /** @private {number} */ + this.speechPitch_ = 1.0; + + /** @private {boolean} */ + this.wordHighlight_ = true; + + /** @const {string} */ + this.color_ = '#f73a98'; + + /** @private {string} */ + this.highlightColor_ = '#5e9bff'; + + /** + * Get the list of TTS voices, and set the default voice if not already set. + * @private + */ + this.updateDefaultVoice_ = function() { + var uiLocale = chrome.i18n.getMessage('@@ui_locale'); + uiLocale = uiLocale.replace('_', '-').toLowerCase(); + + chrome.tts.getVoices((voices) => { + this.validVoiceNames_ = new Set(); + + if (voices.length == 0) + return; + + voices.forEach((voice) => { + if (!voice.eventTypes.includes('start') || + !voice.eventTypes.includes('end') || + !voice.eventTypes.includes('word') || + !voice.eventTypes.includes('cancelled')) { + return; + } + this.validVoiceNames_.add(voice.voiceName); + }); + + voices.sort(function(a, b) { + function score(voice) { + if (voice.lang === undefined) + return -1; + var lang = voice.lang.toLowerCase(); + var s = 0; + if (lang == uiLocale) + s += 2; + if (lang.substr(0, 2) == uiLocale.substr(0, 2)) + s += 1; + return s; + } + return score(b) - score(a); + }); + + this.voiceNameFromLocale_ = voices[0].voiceName; + + chrome.storage.sync.get(['voice'], (prefs) => { + if (!prefs['voice']) { + chrome.storage.sync.set({'voice': voices[0].voiceName}); + } + }); + }); + }; +}; + +/** + * Loads preferences from chrome.storage, sets default values if + * necessary, and registers a listener to update prefs when they + * change. + * @public + */ +PrefsManager.prototype.initPreferences = function() { + var updatePrefs = () => { + chrome.storage.sync.get( + ['voice', 'rate', 'pitch', 'wordHighlight', 'highlightColor'], + (prefs) => { + if (prefs['voice']) { + this.voiceNameFromPrefs_ = prefs['voice']; + } + if (prefs['rate']) { + this.speechRate_ = parseFloat(prefs['rate']); + } else { + chrome.storage.sync.set({'rate': this.speechRate_}); + } + if (prefs['pitch']) { + this.speechPitch_ = parseFloat(prefs['pitch']); + } else { + chrome.storage.sync.set({'pitch': this.speechPitch_}); + } + if (prefs['wordHighlight'] !== undefined) { + this.wordHighlight_ = prefs['wordHighlight']; + } else { + chrome.storage.sync.set({'wordHighlight': this.wordHighlight_}); + } + if (prefs['highlightColor']) { + this.highlightColor_ = prefs['highlightColor']; + } else { + chrome.storage.sync.set({'highlightColor': this.highlightColor_}); + } + }); + }; + + updatePrefs(); + chrome.storage.onChanged.addListener(updatePrefs); + + this.updateDefaultVoice_(); + window.speechSynthesis.onvoiceschanged = (function() { + this.updateDefaultVoice_(); + }).bind(this); +}; + +/** + * Generates the basic speech options for Select-to-Speak based on user + * preferences. Call for each chrome.tts.speak. + * @return {Object} options The TTS options. + * @public + */ +PrefsManager.prototype.speechOptions = function() { + let options = { + rate: this.speechRate_, + pitch: this.speechPitch_, + enqueue: true + }; + + // Pick the voice name from prefs first, or the one that matches + // the locale next, but don't pick a voice that isn't currently + // loaded. If no voices are found, leave the voiceName option + // unset to let the browser try to route the speech request + // anyway if possible. + var valid = ''; + this.validVoiceNames_.forEach(function(voiceName) { + if (valid) + valid += ','; + valid += voiceName; + }); + if (this.voiceNameFromPrefs_ && + this.validVoiceNames_.has(this.voiceNameFromPrefs_)) { + options['voiceName'] = this.voiceNameFromPrefs_; + } else if ( + this.voiceNameFromLocale_ && + this.validVoiceNames_.has(this.voiceNameFromLocale_)) { + options['voiceName'] = this.voiceNameFromLocale_; + } + return options; +}; + +/** + * Gets the user's speech pitch preference. + * @return {number} The user-selected speech pitch. + * @public + */ +PrefsManager.prototype.speechPitch = function() { + return this.speechPitch_; +}; + +/** + * Gets the user's speech rate preference. + * @return {number} The user-selected speech rate. + * @public + */ +PrefsManager.prototype.speechRate = function() { + return this.speechRate_; +}; + +/** + * Gets the user's word highlighting enabled preference. + * @return {boolean} True if word highlighting is enabled. + * @public + */ +PrefsManager.prototype.wordHighlightingEnabled = function() { + return this.wordHighlight_; +}; + +/** + * Gets the user's word highlighting color preference. + * @return {string} Highlight color. + * @public + */ +PrefsManager.prototype.highlightColor = function() { + return this.highlightColor_; +}; + +/** + * Gets the focus ring color. This is not currently a user preference but it + * could be in the future; stored here for similarity to highlight color. + * @return {string} Highlight color. + * @public + */ +PrefsManager.prototype.focusRingColor = function() { + return this.color_; +}; \ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/select_to_speak/select_to_speak.js b/chrome/browser/resources/chromeos/select_to_speak/select_to_speak.js index de550f9..57c90c8e 100644 --- a/chrome/browser/resources/chromeos/select_to_speak/select_to_speak.js +++ b/chrome/browser/resources/chromeos/select_to_speak/select_to_speak.js
@@ -66,30 +66,6 @@ true); }.bind(this)); - /** @private {?string} */ - this.voiceNameFromPrefs_ = null; - - /** @private {?string} */ - this.voiceNameFromLocale_ = null; - - /** @private {Set<string>} */ - this.validVoiceNames_ = new Set(); - - /** @private {number} */ - this.speechRate_ = 1.0; - - /** @private {number} */ - this.speechPitch_ = 1.0; - - /** @private {boolean} */ - this.wordHighlight_ = true; - - /** @const {string} */ - this.color_ = '#f73a98'; - - /** @private {string} */ - this.highlightColor_ = '#5e9bff'; - /** @private {boolean} */ this.readAfterClose_ = true; @@ -130,7 +106,9 @@ /** @private {Audio} */ this.null_selection_tone_ = new Audio('earcons/null_selection.ogg'); - this.initPreferences_(); + /** @private {PrefsManager} */ + this.prefsManager_ = new PrefsManager(); + this.prefsManager_.initPreferences(); this.setUpEventListeners_(); }; @@ -148,8 +126,6 @@ SelectToSpeak.NODE_STATE_TEST_INTERVAL_MS = 1000; SelectToSpeak.prototype = { - - /** * Called in response to our hit test after the mouse is released, * when the user is in a mode where select-to-speak is capturing @@ -194,8 +170,7 @@ } this.startSpeechQueue_(nodes); MetricsUtils.recordStartEvent( - MetricsUtils.StartSpeechMethod.MOUSE, this.speechRate_, - this.speechPitch_, this.wordHighlight_); + MetricsUtils.StartSpeechMethod.MOUSE, this.prefsManager_); }.bind(this)); }, @@ -350,8 +325,7 @@ } this.initializeScrollingToOffscreenNodes_(focusedNode.root); MetricsUtils.recordStartEvent( - MetricsUtils.StartSpeechMethod.KEYSTROKE, this.speechRate_, - this.speechPitch_, this.wordHighlight_); + MetricsUtils.StartSpeechMethod.KEYSTROKE, this.prefsManager_); }, /** @@ -421,7 +395,8 @@ */ clearFocusRing_: function() { chrome.accessibilityPrivate.setFocusRing([]); - chrome.accessibilityPrivate.setHighlights([], this.highlightColor_); + chrome.accessibilityPrivate.setHighlights( + [], this.prefsManager_.highlightColor()); }, /** @@ -453,7 +428,8 @@ }, // onSelectionChanged: Mouse selection rect changed. onSelectionChanged: rect => { - chrome.accessibilityPrivate.setFocusRing([rect], this.color_); + chrome.accessibilityPrivate.setFocusRing( + [rect], this.prefsManager_.focusRingColor()); }, // onKeystrokeSelection: Keys pressed for reading highlighted text. onKeystrokeSelection: () => { @@ -515,7 +491,7 @@ */ startSpeech_: function(text) { this.prepareForSpeech_(); - let options = this.speechOptions_(); + let options = this.prefsManager_.speechOptions(); options.onEvent = (event) => { if (event.type == 'start') { this.onStateChanged_(SelectToSpeakState.SPEAKING); @@ -584,14 +560,14 @@ continue; } - let options = this.speechOptions_(); + let options = this.prefsManager_.speechOptions(); options.onEvent = (event) => { if (event.type == 'start' && nodeGroup.nodes.length > 0) { this.onStateChanged_(SelectToSpeakState.SPEAKING); this.currentBlockParent_ = nodeGroup.blockParent; this.currentNodeGroupIndex_ = 0; this.currentNode_ = nodeGroup.nodes[this.currentNodeGroupIndex_]; - if (this.wordHighlight_) { + if (this.prefsManager_.wordHighlightingEnabled()) { // At 'start', find the first word and highlight that. // Clear the previous word in the node. this.currentNodeWord_ = null; @@ -629,7 +605,7 @@ nodeUpdated = true; } if (nodeUpdated) { - if (!this.wordHighlight_) { + if (!this.prefsManager_.wordHighlightingEnabled()) { // If we are doing a per-word highlight, we will test the // node after figuring out what the currently highlighted // word is. @@ -637,7 +613,7 @@ } } } - if (this.wordHighlight_) { + if (this.prefsManager_.wordHighlightingEnabled()) { this.updateNodeHighlight_( nodeGroup.text, event.charIndex, undefined, isLast ? opt_endIndex : undefined); @@ -687,40 +663,6 @@ }, /** - * Generates the basic speech options for Select-to-Speak based on user - * preferences. Call for each chrome.tts.speak. - * @return {Object} options The TTS options. - */ - speechOptions_: function() { - let options = { - rate: this.speechRate_, - pitch: this.speechPitch_, - enqueue: true - }; - - // Pick the voice name from prefs first, or the one that matches - // the locale next, but don't pick a voice that isn't currently - // loaded. If no voices are found, leave the voiceName option - // unset to let the browser try to route the speech request - // anyway if possible. - var valid = ''; - this.validVoiceNames_.forEach(function(voiceName) { - if (valid) - valid += ','; - valid += voiceName; - }); - if (this.voiceNameFromPrefs_ && - this.validVoiceNames_.has(this.voiceNameFromPrefs_)) { - options['voiceName'] = this.voiceNameFromPrefs_; - } else if ( - this.voiceNameFromLocale_ && - this.validVoiceNames_.has(this.voiceNameFromLocale_)) { - options['voiceName'] = this.voiceNameFromLocale_; - } - return options; - }, - - /** * Cancels the current speech queue after doing a callback to * record a cancel event if speech was in progress. We must cancel * before the callback (rather than in it) to avoid race conditions @@ -739,105 +681,6 @@ }, /** - * Loads preferences from chrome.storage, sets default values if - * necessary, and registers a listener to update prefs when they - * change. - */ - initPreferences_: function() { - var updatePrefs = - (function() { - chrome.storage.sync.get( - ['voice', 'rate', 'pitch', 'wordHighlight', 'highlightColor'], - (function(prefs) { - if (prefs['voice']) { - this.voiceNameFromPrefs_ = prefs['voice']; - } - if (prefs['rate']) { - this.speechRate_ = parseFloat(prefs['rate']); - } else { - chrome.storage.sync.set({'rate': this.speechRate_}); - } - if (prefs['pitch']) { - this.speechPitch_ = parseFloat(prefs['pitch']); - } else { - chrome.storage.sync.set({'pitch': this.speechPitch_}); - } - if (prefs['wordHighlight'] !== undefined) { - this.wordHighlight_ = prefs['wordHighlight']; - } else { - chrome.storage.sync.set( - {'wordHighlight': this.wordHighlight_}); - } - if (prefs['highlightColor']) { - this.highlightColor_ = prefs['highlightColor']; - } else { - chrome.storage.sync.set( - {'highlightColor': this.highlightColor_}); - } - }).bind(this)); - }).bind(this); - - updatePrefs(); - chrome.storage.onChanged.addListener(updatePrefs); - - this.updateDefaultVoice_(); - window.speechSynthesis.onvoiceschanged = (function() { - this.updateDefaultVoice_(); - }).bind(this); - }, - - /** - * Get the list of TTS voices, and set the default voice if not already set. - */ - updateDefaultVoice_: function() { - var uiLocale = chrome.i18n.getMessage('@@ui_locale'); - uiLocale = uiLocale.replace('_', '-').toLowerCase(); - - chrome.tts.getVoices( - (function(voices) { - this.validVoiceNames_ = new Set(); - - if (voices.length == 0) - return; - - voices.forEach((voice) => { - if (!voice.eventTypes.includes('start') || - !voice.eventTypes.includes('end') || - !voice.eventTypes.includes('word') || - !voice.eventTypes.includes('cancelled')) { - return; - } - this.validVoiceNames_.add(voice.voiceName); - }); - - voices.sort(function(a, b) { - function score(voice) { - if (voice.lang === undefined) - return -1; - var lang = voice.lang.toLowerCase(); - var s = 0; - if (lang == uiLocale) - s += 2; - if (lang.substr(0, 2) == uiLocale.substr(0, 2)) - s += 1; - return s; - } - return score(b) - score(a); - }); - - this.voiceNameFromLocale_ = voices[0].voiceName; - - chrome.storage.sync.get( - ['voice'], - (function(prefs) { - if (!prefs['voice']) { - chrome.storage.sync.set({'voice': voices[0].voiceName}); - } - }).bind(this)); - }).bind(this)); - }, - - /** * Hides the speech and focus ring states if necessary based on a node's * current state. * @@ -894,7 +737,8 @@ if (this.scrollToSpokenNode_ && node.state.offscreen) { node.makeVisible(); } - if (this.wordHighlight_ && this.currentNodeWord_ != null) { + if (this.prefsManager_.wordHighlightingEnabled() && + this.currentNodeWord_ != null) { // Only show the highlight if this is an inline text box. // Otherwise we'd be highlighting entire nodes, like images. // Highlight should be only for text. @@ -905,9 +749,10 @@ [node.boundsForRange( this.currentNodeWord_.start - charIndexInParent, this.currentNodeWord_.end - charIndexInParent)], - this.highlightColor_); + this.prefsManager_.highlightColor()); } else { - chrome.accessibilityPrivate.setHighlights([], this.highlightColor_); + chrome.accessibilityPrivate.setHighlights( + [], this.prefsManager_.highlightColor()); } } // Show the parent element of the currently verbalized node with the @@ -919,9 +764,11 @@ if (this.currentBlockParent_ != null && node.role == RoleType.INLINE_TEXT_BOX) { chrome.accessibilityPrivate.setFocusRing( - [this.currentBlockParent_.location], this.color_); + [this.currentBlockParent_.location], + this.prefsManager_.focusRingColor()); } else { - chrome.accessibilityPrivate.setFocusRing([node.location], this.color_); + chrome.accessibilityPrivate.setFocusRing( + [node.location], this.prefsManager_.focusRingColor()); } },
diff --git a/chrome/browser/resources/component_extension_resources.grd b/chrome/browser/resources/component_extension_resources.grd index 6166470..3fc07a1a 100644 --- a/chrome/browser/resources/component_extension_resources.grd +++ b/chrome/browser/resources/component_extension_resources.grd
@@ -126,8 +126,6 @@ <include name="IDR_PDF_VIEWER_PASSWORD_SCREEN_JS" file="pdf/elements/viewer-password-screen/viewer-password-screen.js" type="BINDATA" /> <include name="IDR_PDF_VIEWER_PDF_TOOLBAR_HTML" file="pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.html" type="BINDATA" /> <include name="IDR_PDF_VIEWER_PDF_TOOLBAR_JS" file="pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.js" type="BINDATA" /> - <include name="IDR_PDF_VIEWER_SAVE_CALLED_HTML" file="pdf/elements/viewer-save-called-screen/viewer-save-called-screen.html" type="BINDATA" /> - <include name="IDR_PDF_VIEWER_SAVE_CALLED_JS" file="pdf/elements/viewer-save-called-screen/viewer-save-called-screen.js" type="BINDATA" /> <include name="IDR_PDF_VIEWER_TOOLBAR_DROPDOWN_HTML" file="pdf/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.html" type="BINDATA" /> <include name="IDR_PDF_VIEWER_TOOLBAR_DROPDOWN_JS" file="pdf/elements/viewer-toolbar-dropdown/viewer-toolbar-dropdown.js" type="BINDATA" /> <include name="IDR_PDF_VIEWER_ZOOM_BUTTON_HTML" file="pdf/elements/viewer-zoom-toolbar/viewer-zoom-button.html" type="BINDATA" />
diff --git a/chrome/browser/resources/inline_login/inline_login.html b/chrome/browser/resources/inline_login/inline_login.html index e7c5f0b..1354e2af 100644 --- a/chrome/browser/resources/inline_login/inline_login.html +++ b/chrome/browser/resources/inline_login/inline_login.html
@@ -3,10 +3,10 @@ <head> <title>$i18n{title}</title> <link rel="import" href="chrome://resources/html/polymer.html"> + <link rel="import" href="chrome://resources/cr_elements/icons.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html"> - <link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/iron-icons.html"> - <link rel="stylesheet" href="chrome://resources/css/text_defaults.css"> <link rel="stylesheet" href="chrome://resources/css/spinner.css"> + <link rel="stylesheet" href="chrome://resources/css/text_defaults.css"> <link rel="stylesheet" href="chrome://chrome-signin/inline_login.css"> <script src="chrome://resources/js/cr.js"></script> <script src="chrome://resources/js/cr/event_target.js"></script> @@ -24,7 +24,7 @@ </div> </div> <paper-icon-button id="navigation-button" - icon="icons:close"></paper-icon-button> + icon="cr:close"></paper-icon-button> <script src="chrome://resources/js/i18n_template.js"></script> </body> </html>
diff --git a/chrome/browser/resources/inline_login/inline_login.js b/chrome/browser/resources/inline_login/inline_login.js index a29c409..76af8b5 100644 --- a/chrome/browser/resources/inline_login/inline_login.js +++ b/chrome/browser/resources/inline_login/inline_login.js
@@ -117,7 +117,7 @@ function showBackButton() { $('navigation-button').icon = - isRTL() ? 'icons:arrow-forward' : 'icons:arrow-back'; + isRTL() ? 'cr:arrow-forward' : 'cr:arrow-back'; $('navigation-button') .setAttribute( @@ -125,7 +125,7 @@ } function showCloseButton() { - $('navigation-button').icon = 'icons:close'; + $('navigation-button').icon = 'cr:close'; $('navigation-button').classList.add('enabled'); $('navigation-button') .setAttribute(
diff --git a/chrome/browser/resources/md_extensions/BUILD.gn b/chrome/browser/resources/md_extensions/BUILD.gn index 4edc9f45..d0eab5f 100644 --- a/chrome/browser/resources/md_extensions/BUILD.gn +++ b/chrome/browser/resources/md_extensions/BUILD.gn
@@ -68,6 +68,7 @@ ":options_dialog", ":pack_dialog", ":pack_dialog_alert", + ":runtime_hosts_dialog", ":service", ":shortcut_input", ":shortcut_util", @@ -279,6 +280,13 @@ externs_list = [ "$externs_path/developer_private.js" ] } +js_library("runtime_hosts_dialog") { + deps = [ + "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog", + "//ui/webui/resources/cr_elements/cr_input:cr_input", + ] +} + js_library("service") { deps = [ ":error_page",
diff --git a/chrome/browser/resources/md_extensions/detail_view.html b/chrome/browser/resources/md_extensions/detail_view.html index 2fc8563..c4070c3 100644 --- a/chrome/browser/resources/md_extensions/detail_view.html +++ b/chrome/browser/resources/md_extensions/detail_view.html
@@ -19,6 +19,7 @@ <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-spinner/paper-spinner-lite.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html"> +<link rel="import" href="runtime_hosts_dialog.html"> <link rel="import" href="item_behavior.html"> <link rel="import" href="item_util.html"> <link rel="import" href="navigation_helper.html"> @@ -124,6 +125,13 @@ color: var(--cr-secondary-text-color); } + #add-runtime-hosts-section { + align-items: center; + display: flex; + justify-content: space-between; + margin-top: 10px; + } + .mid-section-header { color: var(--cr-primary-text-color); margin-top: 12px; @@ -360,7 +368,15 @@ </select> </div> <template is="dom-if" if="[[showSpecificSites_(data.*)]]"> - <div class="mid-section-header">$i18n{itemAllowedHosts}</div> + <div id="add-runtime-hosts-section"> + <div class="mid-section-header"> + $i18n{itemAllowedHosts} + </div> + <paper-button id="add-runtime-host" + on-click="onAddRuntimeHostClick_"> + $i18n{add} + </paper-button> + </div> <ul id="runtime-hosts"> <template is="dom-repeat" items="[[data.permissions.runtimeHostPermissions]]"> @@ -449,6 +465,12 @@ </cr-link-row> </div> </div> + <template is="dom-if" if="[[showRuntimeHostsDialog_]]" restamp> + <extensions-runtime-hosts-dialog + delegate="[[delegate]]" item-id="[[data.id]]" + on-close="onRuntimeHostsDialogClosed_"> + </extensions-runtime-hosts-dialog> + </template> </template> <script src="detail_view.js"></script> </dom-module>
diff --git a/chrome/browser/resources/md_extensions/detail_view.js b/chrome/browser/resources/md_extensions/detail_view.js index b6782ba..d69e4ec 100644 --- a/chrome/browser/resources/md_extensions/detail_view.js +++ b/chrome/browser/resources/md_extensions/detail_view.js
@@ -33,6 +33,12 @@ incognitoAvailable: Boolean, /** + * Whether the dialog to add a new host permission is shown. + * @private + */ + showRuntimeHostsDialog_: Boolean, + + /** * Proxying the enum to be used easily by the html template. * @private */ @@ -328,6 +334,17 @@ this.data.permissions.hostAccess == chrome.developerPrivate.HostAccess.ON_SPECIFIC_SITES; }, + + /** @private */ + onAddRuntimeHostClick_: function() { + this.showRuntimeHostsDialog_ = true; + }, + + /** @private */ + onRuntimeHostsDialogClosed_: function() { + this.showRuntimeHostsDialog_ = false; + cr.ui.focusWithoutInk(assert(this.$$('#add-runtime-host'))); + }, }); return {DetailView: DetailView};
diff --git a/chrome/browser/resources/md_extensions/extensions_resources.grd b/chrome/browser/resources/md_extensions/extensions_resources.grd index 7ae0088..c5279e2 100644 --- a/chrome/browser/resources/md_extensions/extensions_resources.grd +++ b/chrome/browser/resources/md_extensions/extensions_resources.grd
@@ -141,6 +141,12 @@ <structure name="IDR_MD_EXTENSIONS_PACK_DIALOG_ALERT_JS" file="pack_dialog_alert.js" type="chrome_html" /> + <structure name="IDR_MD_EXTENSIONS_RUNTIME_HOSTS_DIALOG_HTML" + file="runtime_hosts_dialog.html" + type="chrome_html" /> + <structure name="IDR_MD_EXTENSIONS_RUNTIME_HOSTS_DIALOG_JS" + file="runtime_hosts_dialog.js" + type="chrome_html" /> <structure name="IDR_MD_EXTENSIONS_SERVICE_HTML" file="service.html" type="chrome_html" />
diff --git a/chrome/browser/resources/md_extensions/item.js b/chrome/browser/resources/md_extensions/item.js index 3dec1563..6d8bc99 100644 --- a/chrome/browser/resources/md_extensions/item.js +++ b/chrome/browser/resources/md_extensions/item.js
@@ -69,6 +69,13 @@ * @return {!Promise<string>} */ getExtensionSize(id) {} + + /** + * @param {string} id + * @param {string} host + * @return {!Promise<string>} + */ + addRuntimeHostPermission(id, host) {} } const Item = Polymer({
diff --git a/chrome/browser/resources/md_extensions/runtime_hosts_dialog.html b/chrome/browser/resources/md_extensions/runtime_hosts_dialog.html new file mode 100644 index 0000000..082370a --- /dev/null +++ b/chrome/browser/resources/md_extensions/runtime_hosts_dialog.html
@@ -0,0 +1,36 @@ +<link rel="import" href="chrome://resources/html/polymer.html"> + +<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html"> +<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html"> +<link rel="import" href="chrome://resources/cr_elements/shared_style_css.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> + +<dom-module id="extensions-runtime-hosts-dialog"> + <template> + <style include="cr-shared-style paper-button-style"></style> + <cr-dialog id="dialog" close-text="$i18n{close}"> + <div slot="title">$i18n{runtimeHostsDialogTitle}</div> + <div slot="body"> + <cr-input id="input" label="$i18n{runtimeHostsDialogInputLabel}" + placeholder="http://example.com" + value="{{site_}}" on-input="validate_" + invalid="[[inputInvalid_]]" + error-message="$i18n{runtimeHostsDialogInputError}" + spellcheck="false" + autofocus> + </cr-input> + </div> + <div slot="button-container"> + <paper-button class="cancel-button" on-click="onCancelTap_"> + $i18n{cancel} + </paper-button> + <paper-button class="action-button" id="add" on-click="onAddTap_" + disabled="[[computeAddButtonDisabled_(inputInvalid_, site_)]]"> + $i18n{add} + </paper-button> + </div> + </cr-dialog> + </template> + <script src="runtime_hosts_dialog.js"></script> +</dom-module>
diff --git a/chrome/browser/resources/md_extensions/runtime_hosts_dialog.js b/chrome/browser/resources/md_extensions/runtime_hosts_dialog.js new file mode 100644 index 0000000..def01c5 --- /dev/null +++ b/chrome/browser/resources/md_extensions/runtime_hosts_dialog.js
@@ -0,0 +1,96 @@ +// 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. + +cr.define('extensions', function() { + 'use strict'; + + const RuntimeHostsDialog = Polymer({ + is: 'extensions-runtime-hosts-dialog', + + properties: { + /** @type {!extensions.ItemDelegate} */ + delegate: Object, + + /** @type {string} */ + itemId: String, + + /** + * The site to add an exception for. + * @private + */ + site_: String, + + /** + * Whether the currently-entered input is valid. + * @private + */ + inputInvalid_: { + type: Boolean, + value: false, + }, + }, + + /** @override */ + attached: function() { + this.$.dialog.showModal(); + }, + + /** + * Validates that the pattern entered is valid. + * @private + */ + validate_: function() { + // If input is empty, disable the action button, but don't show the red + // invalid message. + if (this.site_.trim().length == 0) { + this.inputInvalid_ = false; + return; + } + + let valid = true; + try { + // Check if the input parses as a valid URL. JS URL parsing isn't + // great, but it's quick and easy and better than nothing. If it's still + // not valid, the API will throw an error and the embedding element will + // call setInputInvalid(). + let testUrl = new URL(this.site_); + } catch (e) { + valid = false; + } + + this.inputInvalid_ = !valid; + }, + + /** + * @return {boolean} + * @private + */ + computeAddButtonDisabled_: function() { + return this.inputInvalid_ || this.site_.trim().length == 0; + }, + + /** @private */ + onCancelTap_: function() { + this.$.dialog.cancel(); + }, + + /** + * The tap handler for the Add [Site] button (adds the pattern and closes + * the dialog). + * @private + */ + onAddTap_: function() { + this.delegate.addRuntimeHostPermission(this.itemId, this.site_) + .then( + () => { + this.$.dialog.close(); + }, + () => { + this.inputInvalid_ = true; + }); + }, + }); + + return {RuntimeHostsDialog: RuntimeHostsDialog}; +});
diff --git a/chrome/browser/resources/md_extensions/service.js b/chrome/browser/resources/md_extensions/service.js index 2f964b5..10e3c79 100644 --- a/chrome/browser/resources/md_extensions/service.js +++ b/chrome/browser/resources/md_extensions/service.js
@@ -67,6 +67,19 @@ }); } + /** @override */ + addRuntimeHostPermission(id, host) { + return new Promise((resolve, reject) => { + chrome.developerPrivate.addHostPermission(id, host, () => { + if (chrome.runtime.lastError) { + reject(chrome.runtime.lastError.message); + return; + } + resolve(); + }); + }); + } + /** * Opens a file browser dialog for the user to select a file (or directory). * @param {chrome.developerPrivate.SelectType} selectType
diff --git a/chrome/browser/resources/media_router/elements/media_router_header/media_router_header.html b/chrome/browser/resources/media_router/elements/media_router_header/media_router_header.html index 7a0603a..3a58bc2 100644 --- a/chrome/browser/resources/media_router/elements/media_router_header/media_router_header.html +++ b/chrome/browser/resources/media_router/elements/media_router_header/media_router_header.html
@@ -1,4 +1,6 @@ <link rel="import" href="chrome://resources/html/polymer.html"> + +<link rel="import" href="chrome://resources/cr_elements/icons.html"> <link rel="import" href="chrome://resources/html/i18n_behavior.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html"> <link rel="import" href="../../icons/media_router_icons.html"> @@ -27,7 +29,7 @@ </div> </div> <div id="close-button-container"> - <paper-icon-button icon="media-router:close" id="close-button" + <paper-icon-button icon="cr:close" id="close-button" on-tap="onCloseButtonClick_" title="[[i18n('closeButtonTitle')]]"> </paper-icon-button> </div>
diff --git a/chrome/browser/resources/media_router/elements/media_router_header/media_router_header.js b/chrome/browser/resources/media_router/elements/media_router_header/media_router_header.js index 1c375cb..50ba150 100644 --- a/chrome/browser/resources/media_router/elements/media_router_header/media_router_header.js +++ b/chrome/browser/resources/media_router/elements/media_router_header/media_router_header.js
@@ -99,8 +99,7 @@ attached: function() { // isRTL() only works after i18n_template.js runs to set <html dir>. // Set the back button icon based on text direction. - this.arrowDropIcon_ = - isRTL() ? 'media-router:arrow-forward' : 'media-router:arrow-back'; + this.arrowDropIcon_ = isRTL() ? 'cr:arrow-forward' : 'cr:arrow-back'; }, /** @@ -110,8 +109,8 @@ */ computeArrowDropIcon_: function(view) { return view == media_router.MediaRouterView.CAST_MODE_LIST ? - 'media-router:arrow-drop-up' : - 'media-router:arrow-drop-down'; + 'cr:arrow-drop-up' : + 'cr:arrow-drop-down'; }, /**
diff --git a/chrome/browser/resources/media_router/icons/media_router_icons.html b/chrome/browser/resources/media_router/icons/media_router_icons.html index 758151b6..7d98ad6 100644 --- a/chrome/browser/resources/media_router/icons/media_router_icons.html +++ b/chrome/browser/resources/media_router/icons/media_router_icons.html
@@ -5,11 +5,6 @@ <iron-iconset-svg name="media-router" size="24"> <svg><defs> <!-- third_party/polymer/v1_0/components-chromium/iron-icons/iron-icons.html --> - <g id="arrow-back"><path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z"></path></g> - <g id="arrow-drop-down"><path d="M7 10l5 5 5-5z"></path></g> - <g id="arrow-drop-up"><path d="M7 14l5-5 5 5z"></path></g> - <g id="arrow-forward"><path d="M12 4l-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8z"></path></g> - <g id="close"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path></g> <g id="folder"><path d="M0 0h24v24H0z" fill="none"></path><path d="M20 6h-8l-2-2H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm0 12H4V8h16v10z"></path></g> <g id="search"><path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"></path></g> <g id="tab"><path d="M21 3H3c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H3V5h10v4h8v10z"></path></g>
diff --git a/chrome/browser/resources/pdf/BUILD.gn b/chrome/browser/resources/pdf/BUILD.gn index 30b642b9..5a3ce14 100644 --- a/chrome/browser/resources/pdf/BUILD.gn +++ b/chrome/browser/resources/pdf/BUILD.gn
@@ -13,7 +13,6 @@ "elements/viewer-page-indicator:closure_compile", "elements/viewer-page-selector:closure_compile", "elements/viewer-password-screen:closure_compile", - "elements/viewer-save-called-screen:closure_compile", ] }
diff --git a/chrome/browser/resources/pdf/elements/viewer-save-called-screen/viewer-save-called-screen.html b/chrome/browser/resources/pdf/elements/viewer-save-called-screen/viewer-save-called-screen.html deleted file mode 100644 index 29cb355..0000000 --- a/chrome/browser/resources/pdf/elements/viewer-save-called-screen/viewer-save-called-screen.html +++ /dev/null
@@ -1,21 +0,0 @@ -<link rel="import" href="chrome://resources/html/polymer.html"> - -<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html"> -<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> - -<dom-module id="viewer-save-called-screen"> - <template> - <style include="paper-button-style"></style> - <cr-dialog id="dialog" no-cancel> - <div slot="title">[[strings.saveCalledTitle]]</div> - <div slot="body">[[strings.saveCalledText]]</div> - <div slot="button-container"> - <paper-button class="action-button" on-click="dismiss_"> - [[strings.saveCalledButton]] - </paper-button> - </div> - </cr-dialog> - </template> - <script src="viewer-save-called-screen.js"></script> -</dom-module>
diff --git a/chrome/browser/resources/pdf/elements/viewer-save-called-screen/viewer-save-called-screen.js b/chrome/browser/resources/pdf/elements/viewer-save-called-screen/viewer-save-called-screen.js deleted file mode 100644 index f24206e..0000000 --- a/chrome/browser/resources/pdf/elements/viewer-save-called-screen/viewer-save-called-screen.js +++ /dev/null
@@ -1,20 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -Polymer({ - is: 'viewer-save-called-screen', - - properties: { - strings: Object, - }, - - show: function() { - this.$.dialog.showModal(); - }, - - /** @private */ - dismiss_: function() { - this.$.dialog.close(); - }, -});
diff --git a/chrome/browser/resources/pdf/index.html b/chrome/browser/resources/pdf/index.html index fabf9d2..dcec3cc 100644 --- a/chrome/browser/resources/pdf/index.html +++ b/chrome/browser/resources/pdf/index.html
@@ -7,7 +7,6 @@ <link rel="import" href="elements/viewer-page-selector/viewer-page-selector.html"> <link rel="import" href="elements/viewer-password-screen/viewer-password-screen.html"> <link rel="import" href="elements/viewer-pdf-toolbar/viewer-pdf-toolbar.html"> - <link rel="import" href="elements/viewer-save-called-screen/viewer-save-called-screen.html"> <link rel="import" href="elements/viewer-zoom-toolbar/viewer-zoom-toolbar.html"> <link rel="import" href="elements/shared-vars.html"> @@ -27,8 +26,6 @@ <viewer-error-screen id="error-screen"></viewer-error-screen> -<viewer-save-called-screen id="save-called-screen"></viewer-save-called-screen> - </body> <script src="pdf_fitting_type.js"></script> <script src="toolbar_manager.js"></script>
diff --git a/chrome/browser/resources/pdf/pdf.js b/chrome/browser/resources/pdf/pdf.js index c9b0f38..6de1c5c 100644 --- a/chrome/browser/resources/pdf/pdf.js +++ b/chrome/browser/resources/pdf/pdf.js
@@ -629,7 +629,6 @@ $('zoom-toolbar').strings = strings; $('password-screen').strings = strings; $('error-screen').strings = strings; - $('save-called-screen').strings = strings; }, /** @@ -762,9 +761,6 @@ case 'transformPagePointReply': this.coordsTransformer_.onReplyReceived(message); break; - case 'saveCalled': - $('save-called-screen').show(); - break; } },
diff --git a/chrome/browser/resources/settings/privacy_page/personalization_options.html b/chrome/browser/resources/settings/privacy_page/personalization_options.html index 344da18..c3e2807 100644 --- a/chrome/browser/resources/settings/privacy_page/personalization_options.html +++ b/chrome/browser/resources/settings/privacy_page/personalization_options.html
@@ -76,12 +76,14 @@ </settings-toggle-button> </if><!-- not chromeos --> </if><!-- _google_chrome --> - <settings-toggle-button - pref="{{prefs.url_keyed_anonymized_data_collection.enabled}}" - label="$i18n{urlKeyedAnonymizedDataCollection}" - sub-label="$i18n{urlKeyedAnonymizedDataCollectionDesc}" - disabled="[[unifiedConsentGiven]]"> - </settings-toggle-button> + <template is="dom-if" if="[[unifiedConsentEnabled]]"> + <settings-toggle-button + pref="{{prefs.url_keyed_anonymized_data_collection.enabled}}" + label="$i18n{urlKeyedAnonymizedDataCollection}" + sub-label="$i18n{urlKeyedAnonymizedDataCollectionDesc}" + disabled="[[unifiedConsentGiven]]"> + </settings-toggle-button> + </template> <if expr="_google_chrome"> <template is="dom-if" if="[[!unifiedConsentEnabled]]"> <settings-toggle-button id="spellCheckControl"
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_page.html b/chrome/browser/resources/settings/privacy_page/privacy_page.html index e973f46..f14f0e74 100644 --- a/chrome/browser/resources/settings/privacy_page/privacy_page.html +++ b/chrome/browser/resources/settings/privacy_page/privacy_page.html
@@ -230,7 +230,8 @@ label="$i18n{thirdPartyCookie}" sub-label="$i18n{thirdPartyCookieSublabel}"> </settings-toggle-button> - <div class="settings-box" actionable on-click="onSiteDataTap_"> + <div id="site-data-trigger" class="settings-box" actionable + on-click="onSiteDataTap_"> <div class="start" id="cookiesLink"> $i18n{siteSettingsCookieLink} </div>
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_page.js b/chrome/browser/resources/settings/privacy_page/privacy_page.js index 6aa3471..bc30d06c 100644 --- a/chrome/browser/resources/settings/privacy_page/privacy_page.js +++ b/chrome/browser/resources/settings/privacy_page/privacy_page.js
@@ -108,6 +108,12 @@ settings.routes.SITE_SETTINGS.path, '#site-settings-subpage-trigger .subpage-arrow button'); } + + if (settings.routes.SITE_SETTINGS_SITE_DATA) { + map.set( + settings.routes.SITE_SETTINGS_SITE_DATA.path, + '#site-data-trigger .subpage-arrow button'); + } return map; }, },
diff --git a/chrome/browser/resources/settings/settings_page/BUILD.gn b/chrome/browser/resources/settings/settings_page/BUILD.gn index 559306a7..d354bfa 100644 --- a/chrome/browser/resources/settings/settings_page/BUILD.gn +++ b/chrome/browser/resources/settings/settings_page/BUILD.gn
@@ -31,6 +31,7 @@ "//ui/webui/resources/js:assert", "//ui/webui/resources/js:cr", "//ui/webui/resources/js:load_time_data", + "//ui/webui/resources/js:util", "//ui/webui/resources/js/cr/ui:focus_without_ink", ] }
diff --git a/chrome/browser/resources/settings/settings_page/settings_animated_pages.html b/chrome/browser/resources/settings/settings_page/settings_animated_pages.html index 655b3fa..10c922d3 100644 --- a/chrome/browser/resources/settings/settings_page/settings_animated_pages.html +++ b/chrome/browser/resources/settings/settings_page/settings_animated_pages.html
@@ -4,6 +4,7 @@ <link rel="import" href="chrome://resources/html/cr.html"> <link rel="import" href="chrome://resources/html/cr/ui.html"> <link rel="import" href="chrome://resources/html/cr/ui/focus_without_ink.html"> +<link rel="import" href="chrome://resources/html/util.html"> <link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/animations/slide-from-left-animation.html"> <link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/animations/slide-from-right-animation.html"> <link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/animations/slide-left-animation.html">
diff --git a/chrome/browser/resources/settings/settings_page/settings_animated_pages.js b/chrome/browser/resources/settings/settings_page/settings_animated_pages.js index ff698ee..7492cde1 100644 --- a/chrome/browser/resources/settings/settings_page/settings_animated_pages.js +++ b/chrome/browser/resources/settings/settings_page/settings_animated_pages.js
@@ -31,9 +31,10 @@ /** * A Map specifying which element should be focused when exiting a subpage. - * The key of the map holds a settings.Route path, and the value holds a - * query selector that identifies the desired element. - * @type {?Map<string, string>} + * The key of the map holds a settings.Route path, and the value holds + * either a query selector that identifies the desired element or a function + * to be run when a neon-animation-finish event is handled. + * @type {?Map<string, (string|Function)>} */ focusConfig: Object, }, @@ -80,33 +81,43 @@ if (!settings.lastRouteChangeWasPopstate()) return; - // Only handle iron-select events from neon-animatable elements and the - // given whitelist of settings-subpage instances. - let whitelist = 'settings-subpage#site-settings'; + const subpagePaths = []; + if (settings.routes.SITE_SETTINGS_COOKIES) + subpagePaths.push(settings.routes.SITE_SETTINGS_COOKIES.path); - if (settings.routes.SITE_SETTINGS_COOKIES) { - whitelist += ', settings-subpage[route-path=\"' + - settings.routes.SITE_SETTINGS_COOKIES.path + '\"]'; - } + if (settings.routes.SITE_SETTINGS_SITE_DATA) + subpagePaths.push(settings.routes.SITE_SETTINGS_SITE_DATA.path); // <if expr="chromeos"> - if (settings.routes.INTERNET_NETWORKS) { - whitelist += ', settings-subpage[route-path=\"' + - settings.routes.INTERNET_NETWORKS.path + '\"]'; - } + if (settings.routes.INTERNET_NETWORKS) + subpagePaths.push(settings.routes.INTERNET_NETWORKS.path); // </if> - if (!e.detail.item.matches('neon-animatable, ' + whitelist)) + // Only handle iron-select events from neon-animatable elements and the + // given whitelist of settings-subpage instances. + const whitelist = ['settings-subpage#site-settings', 'neon-animatable']; + whitelist.push.apply( + whitelist, + subpagePaths.map(path => `settings-subpage[route-path="${path}"]`)); + const query = whitelist.join(', '); + + if (!e.detail.item.matches(query)) return; - const selector = this.focusConfig.get(this.previousRoute_.path); - if (selector) { - // neon-animatable has "display: none" until the animation finishes, so - // calling focus() on any of its children has no effect until "display: - // none" is removed. Therefore, don't set focus from within the - // currentRouteChanged callback. Using 'iron-select' listener which fires - // after the animation has finished allows setting focus to work. - cr.ui.focusWithoutInk(assert(this.querySelector(selector))); + const selectorOrFunction = this.focusConfig.get(this.previousRoute_.path); + if (selectorOrFunction) { + // neon-animatable has "display: none" until the animation finishes, + // so calling focus() on any of its children has no effect until + // "display:none" is removed. Therefore, don't set focus from within + // the currentRouteChanged callback. + listenOnce(this, 'neon-animation-finish', () => { + if (typeof selectorOrFunction == 'function') { + selectorOrFunction(); + } else { + const selector = /** @type {string} */ (selectorOrFunction); + cr.ui.focusWithoutInk(assert(this.querySelector(selector))); + } + }); } },
diff --git a/chrome/browser/resources/settings/settings_resources.grd b/chrome/browser/resources/settings/settings_resources.grd index 1d1120ef..697768c9 100644 --- a/chrome/browser/resources/settings/settings_resources.grd +++ b/chrome/browser/resources/settings/settings_resources.grd
@@ -986,6 +986,12 @@ <structure name="IDR_SETTINGS_SITE_DATA_DETAILS_SUBPAGE_JS" file="site_settings/site_data_details_subpage.js" type="chrome_html" /> + <structure name="IDR_SETTINGS_SITE_DATA_ENTRY_HTML" + file="site_settings/site_data_entry.html" + type="chrome_html" /> + <structure name="IDR_SETTINGS_SITE_DATA_ENTRY_JS" + file="site_settings/site_data_entry.js" + type="chrome_html" /> <structure name="IDR_SETTINGS_SITE_LIST_HTML" file="site_settings/site_list.html" type="chrome_html" />
diff --git a/chrome/browser/resources/settings/site_settings/BUILD.gn b/chrome/browser/resources/settings/site_settings/BUILD.gn index 1a7dcca..ea34fe26 100644 --- a/chrome/browser/resources/settings/site_settings/BUILD.gn +++ b/chrome/browser/resources/settings/site_settings/BUILD.gn
@@ -17,6 +17,7 @@ ":protocol_handlers", ":site_data", ":site_data_details_subpage", + ":site_data_entry", ":site_details", ":site_details_permission", ":site_entry", @@ -124,6 +125,7 @@ deps = [ ":cookie_info", ":local_data_browser_proxy", + ":site_data_entry", ":site_settings_behavior", "..:global_scroll_target_behavior", "../settings_page:settings_subpage_search", @@ -146,6 +148,16 @@ ] } +js_library("site_data_entry") { + deps = [ + ":cookie_info", + ":local_data_browser_proxy", + "..:focus_row_behavior", + "//ui/webui/resources/js:cr", + "//ui/webui/resources/js:icon", + ] +} + js_library("site_details") { deps = [ ":constants",
diff --git a/chrome/browser/resources/settings/site_settings/site_data.html b/chrome/browser/resources/settings/site_settings/site_data.html index 91b8cb84..78e9124 100644 --- a/chrome/browser/resources/settings/site_settings/site_data.html +++ b/chrome/browser/resources/settings/site_settings/site_data.html
@@ -17,14 +17,11 @@ <link rel="import" href="cookie_info.html"> <link rel="import" href="local_data_browser_proxy.html"> <link rel="import" href="site_settings_behavior.html"> +<link rel="import" href="site_data_entry.html"> <dom-module id="site-data"> <template> <style include="settings-shared"> - [first] { - border-top: none; - } - paper-spinner-lite { @apply --cr-icon-height-width; opacity: 0; @@ -38,10 +35,6 @@ #removeShowingSites { -webkit-margin-start: auto; } - - .separator { - -webkit-padding-start: 0; - } </style> <div class="settings-box continuation"> <paper-spinner-lite active="[[isLoading_]]"></paper-spinner-lite> @@ -52,27 +45,13 @@ </paper-button> </div> <iron-list id="list" items="[[sites]]" preserve-focus - scroll-target="[[subpageScrollTarget]]"> + scroll-target="[[subpageScrollTarget]]" class="cr-separators"> <template> - <div class="settings-box two-line site-item" first$="[[!index]]" - on-click="onSiteTap_" actionable> - <div class="favicon-image" - style$="background-image: [[favicon_(item.site)]]"> - </div> - <div class="middle"> - <span class="url-directionality">[[item.site]]</span> - <div class="secondary">[[item.localData]]</div> - </div> - <paper-icon-button-light class="subpage-arrow"> - <button aria-label$="[[item.site]]"></button> - </paper-icon-button-light> - <div class="separator"></div> - <paper-icon-button-light class="icon-delete-gray"> - <button title$="[[i18n('siteSettingsCookieRemoveSite', item.site)]]" - on-click="onRemoveSiteTap_"> - </button> - </paper-icon-button-light> - </div> + <site-data-entry id$="siteItem_[[item.site]]" actionable + model="[[item]]" first$="[[!index]]" tabindex$="[[tabIndex]]" + iron-list-tab-index="[[tabIndex]]" last-focused="{{lastFocused_}}" + on-click="onSiteClick_" on-remove-site="onRemoveSite_"> + </site-data-entry> </template> </iron-list>
diff --git a/chrome/browser/resources/settings/site_settings/site_data.js b/chrome/browser/resources/settings/site_settings/site_data.js index 56a1e6eb..a1caa294 100644 --- a/chrome/browser/resources/settings/site_settings/site_data.js +++ b/chrome/browser/resources/settings/site_settings/site_data.js
@@ -25,16 +25,6 @@ */ let CookieRemovePacket; -/** - * TODO(dbeam): upstream to polymer externs? - * @constructor - * @extends {Event} - */ -function DomRepeatEvent() {} - -/** @type {?} */ -DomRepeatEvent.prototype.model; - Polymer({ is: 'site-data', @@ -55,7 +45,7 @@ type: String, }, - /** @type {!Map<string, string>} */ + /** @type {!Map<string, (string|Function)>} */ focusConfig: { type: Object, observer: 'focusConfigChanged_', @@ -63,7 +53,7 @@ isLoading_: Boolean, - /** @type {!Array<!LocalDataItem>} */ + /** @type {!Array<!CookieDataSummaryItem>} */ sites: { type: Array, value: function() { @@ -79,11 +69,22 @@ type: Object, value: settings.routes.SITE_SETTINGS_SITE_DATA, }, + + /** @private */ + lastFocused_: Object, }, /** @private {settings.LocalDataBrowserProxy} */ browserProxy_: null, + /** + * When navigating to site data details sub-page, |lastSelected_| holds the + * site name as well as the index of the selected site. This is used when + * navigating back to site data in order to focus on the correct site. + * @private {!{item: CookieDataSummaryItem, index: number}|null} + */ + lastSelected_: null, + /** @override */ ready: function() { this.browserProxy_ = settings.LocalDataBrowserProxyImpl.getInstance(); @@ -126,8 +127,8 @@ }, /** - * @param {!Map<string, string>} newConfig - * @param {?Map<string, string>} oldConfig + * @param {!Map<string, (string|Function)>} newConfig + * @param {?Map<string, (string|Function)>} oldConfig * @private */ focusConfigChanged_: function(newConfig, oldConfig) { @@ -139,9 +140,34 @@ // element, with additional entries that correspond to subpage trigger // elements residing in this element's Shadow DOM. if (settings.routes.SITE_SETTINGS_DATA_DETAILS) { + const onNavigatedTo = () => this.async(() => { + if (this.lastSelected_ == null || this.sites.length == 0) + return; + + const lastSelectedSite = this.lastSelected_.item.site; + const lastSelectedIndex = this.lastSelected_.index; + this.lastSelected_ = null; + + const indexFromId = + this.sites.findIndex(site => site.site == lastSelectedSite); + + // If the site is no longer in |sites|, use the index as a fallback. + // Since the sites are sorted, an alternative could be to select the + // site that comes next in sort order. + const indexFallback = lastSelectedIndex < this.sites.length ? + lastSelectedIndex : + this.sites.length - 1; + const index = indexFromId > -1 ? indexFromId : indexFallback; + const ironList = + /** @type {!IronListElement} */ (this.$$('iron-list')); + ironList.focusItem(index); + const siteToSelect = this.sites[index].site.replace(/[.]/g, '\\.'); + const button = + this.$$(`#siteItem_${siteToSelect}`).$$('.subpage-arrow button'); + cr.ui.focusWithoutInk(assert(button)); + }); this.focusConfig.set( - settings.routes.SITE_SETTINGS_DATA_DETAILS.path, - '* /deep/ #filter /deep/ #searchInput'); + settings.routes.SITE_SETTINGS_DATA_DETAILS.path, onNavigatedTo); } }, @@ -209,22 +235,13 @@ }, /** - * Deletes all site data for a given site. - * @param {!DomRepeatEvent} e + * @param {!{model: !{item: CookieDataSummaryItem, index: number}}} event * @private */ - onRemoveSiteTap_: function(e) { - e.stopPropagation(); - this.browserProxy_.removeItem(e.model.item.site); - }, - - /** - * @param {!{model: !{item: CookieDataSummaryItem}}} event - * @private - */ - onSiteTap_: function(event) { + onSiteClick_: function(event) { settings.navigateTo( settings.routes.SITE_SETTINGS_DATA_DETAILS, new URLSearchParams('site=' + event.model.item.site)); + this.lastSelected_ = event.model; }, });
diff --git a/chrome/browser/resources/settings/site_settings/site_data_entry.html b/chrome/browser/resources/settings/site_settings/site_data_entry.html new file mode 100644 index 0000000..adce11d --- /dev/null +++ b/chrome/browser/resources/settings/site_settings/site_data_entry.html
@@ -0,0 +1,39 @@ +<link rel="import" href="chrome://resources/html/polymer.html"> + +<link rel="import" href="chrome://resources/html/i18n_behavior.html"> +<link rel="import" href="chrome://resources/cr_elements/icons.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-icon-button/paper-icon-button-light.html"> +<link rel="import" href="../focus_row_behavior.html"> +<link rel="import" href="../settings_shared_css.html"> +<link rel="import" href="cookie_info.html"> + +<dom-module id="site-data-entry"> + <template> + <style include="settings-shared"> + .settings-box { + border: none; + } + </style> + <div class="settings-box two-line site-item" focus-row-container actionable> + <div class="favicon-image" + style$="background-image: [[favicon_]]"> + </div> + <div class="middle"> + <span class="url-directionality">[[model.site]]</span> + <div class="secondary">[[model.localData]]</div> + </div> + <paper-icon-button-light class="subpage-arrow"> + <button aria-label$="[[model.site]]" focus-row-control + focus-type="showDetails"></button> + </paper-icon-button-light> + <div class="separator"></div> + <paper-icon-button-light class="icon-delete-gray"> + <button title$="[[i18n('siteSettingsCookieRemoveSite', model.site)]]" + on-click="onRemove_" focus-row-control focus-type="remove"> + </button> + </paper-icon-button-light> + </div> + </template> + <script src="site_data_entry.js"></script> +</dom-module>
diff --git a/chrome/browser/resources/settings/site_settings/site_data_entry.js b/chrome/browser/resources/settings/site_settings/site_data_entry.js new file mode 100644 index 0000000..7163f97 --- /dev/null +++ b/chrome/browser/resources/settings/site_settings/site_data_entry.js
@@ -0,0 +1,61 @@ +// 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 + * 'site-data-entry' handles showing the local storage summary for a site. + */ + +Polymer({ + is: 'site-data-entry', + + behaviors: [ + FocusRowBehavior, + I18nBehavior, + ], + + properties: { + /** @type {!CookieDataSummaryItem} */ + model: Object, + + /** + * Icon to use for a given site. + * @private + */ + favicon_: { + type: String, + computed: 'computeFavicon_(model)', + }, + }, + + /** @private {settings.LocalDataBrowserProxy} */ + browserProxy_: null, + + /** @override */ + ready: function() { + this.browserProxy_ = settings.LocalDataBrowserProxyImpl.getInstance(); + }, + + /** + * @return {string} + * @private + */ + computeFavicon_: function() { + const url = this.model.site; + // If the url doesn't have a scheme, inject HTTP as the scheme. Otherwise, + // the URL isn't valid and no icon will be returned. + const urlWithScheme = url.includes('://') ? url : 'http://' + url; + return cr.icon.getFavicon(urlWithScheme); + }, + + /** + * Deletes all site data for this site. + * @param {!Event} e + * @private + */ + onRemove_: function(e) { + e.stopPropagation(); + this.browserProxy_.removeItem(this.model.site); + }, +});
diff --git a/chrome/browser/resources/settings/site_settings_page/site_settings_page.js b/chrome/browser/resources/settings/site_settings_page/site_settings_page.js index 4f611936..72f0f5db3 100644 --- a/chrome/browser/resources/settings/site_settings_page/site_settings_page.js +++ b/chrome/browser/resources/settings/site_settings_page/site_settings_page.js
@@ -130,9 +130,8 @@ [R.SITE_SETTINGS_SENSORS, 'sensors'], ]; - if (this.enablePaymentHandlerContentSetting_) { - pairs.push([R.SITE_SETTINGS_PAYMENT_HANDLER, 'payment-handler']); - } + if (this.enablePaymentHandlerContentSetting_) + pairs.push([R.SITE_SETTINGS_PAYMENT_HANDLER, 'paymentHandler']); pairs.forEach(pair => { const route = pair[0];
diff --git a/chrome/browser/resources/pdf/elements/viewer-save-called-screen/BUILD.gn b/chrome/browser/resources/ukm/BUILD.gn similarity index 67% rename from chrome/browser/resources/pdf/elements/viewer-save-called-screen/BUILD.gn rename to chrome/browser/resources/ukm/BUILD.gn index 1e2b08cc..4fe10b1 100644 --- a/chrome/browser/resources/pdf/elements/viewer-save-called-screen/BUILD.gn +++ b/chrome/browser/resources/ukm/BUILD.gn
@@ -6,12 +6,13 @@ js_type_check("closure_compile") { deps = [ - ":viewer-save-called-screen", + ":ukm_internals", ] } -js_library("viewer-save-called-screen") { +js_library("ukm_internals") { deps = [ - "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog", + "//ui/webui/resources/js:cr", + "//ui/webui/resources/js:util", ] }
diff --git a/chrome/browser/resources/ukm/ukm_internals.html b/chrome/browser/resources/ukm/ukm_internals.html new file mode 100644 index 0000000..34c5e43 --- /dev/null +++ b/chrome/browser/resources/ukm/ukm_internals.html
@@ -0,0 +1,20 @@ +<!-- 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.--> +<!doctype html> +<html lang="en"> +<meta charset="utf-8"> +<script src="chrome://resources/js/cr.js"></script> +<script src="chrome://resources/js/promise_resolver.js"></script> +<script src="chrome://resources/js/util.js"></script> +<title>UKM Debug page</title> +<h1>UKM Debug page</h1> +<div> + <p>Is Enabled:<span id="state"></span></p> + <p>Client Id:<span id="clientid"></span></p> + <p>Session Id:<span id="sessionid"></span></p> + <h2>Sources</h2> + <div id="sources"></div> +</div> +<script src="ukm_internals.js"></script> +</html>
diff --git a/chrome/browser/resources/ukm/ukm_internals.js b/chrome/browser/resources/ukm/ukm_internals.js new file mode 100644 index 0000000..9449c73 --- /dev/null +++ b/chrome/browser/resources/ukm/ukm_internals.js
@@ -0,0 +1,42 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * Fetches data from the Ukm service and updates the DOM to display it as a + * list. + */ +function updateUkmData() { + cr.sendWithPromise('requestUkmData').then((ukmData) => { + $('state').innerText = ukmData.state ? 'True' : 'False'; + $('clientid').innerText = ukmData.client_id; + $('sessionid').innerText = ukmData.session_id; + + sourceDiv = $('sources'); + for (const source of ukmData.sources) { + const sourceElement = document.createElement('h3'); + if (source.url !== undefined) + sourceElement.innerText = `Id: ${source.id} Url: ${source.url}`; + else + sourceElement.innerText = `Id: ${source.id}`; + sourceDiv.appendChild(sourceElement); + + for (const entry of source.entries) { + const entryElement = document.createElement('h4'); + entryElement.innerText = `Entry: ${entry.name}`; + sourceDiv.appendChild(entryElement); + + if (entry.metrics === undefined) + continue; + for (const metric of entry.metrics) { + const metricElement = document.createElement('h5'); + metricElement.innerText = + `Metric: ${metric.name} Value: ${metric.value}`; + sourceDiv.appendChild(metricElement); + } + } + } + }); +} + +updateUkmData();
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 3b35f12..c96dfe1 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -844,6 +844,8 @@ "webui/translate_internals/translate_internals_handler.h", "webui/translate_internals/translate_internals_ui.cc", "webui/translate_internals/translate_internals_ui.h", + "webui/ukm/ukm_internals_ui.cc", + "webui/ukm/ukm_internals_ui.h", "webui/usb_internals/usb_internals_page_handler.cc", "webui/usb_internals/usb_internals_page_handler.h", "webui/usb_internals/usb_internals_ui.cc", @@ -963,6 +965,7 @@ "//components/keyed_service/core", "//components/language/core/browser", "//components/language/core/common", + "//components/metrics_services_manager", "//components/navigation_metrics", "//components/net_log", "//components/ntp_snippets", @@ -1015,6 +1018,7 @@ "//components/ui_devtools", "//components/ukm:ukm", "//components/ukm/content", + "//components/ukm/debug:util", "//components/undo", "//components/unified_consent", "//components/update_client",
diff --git a/chrome/browser/ui/app_list/chrome_app_list_item.h b/chrome/browser/ui/app_list/chrome_app_list_item.h index 4118bdd..edd14e8 100644 --- a/chrome/browser/ui/app_list/chrome_app_list_item.h +++ b/chrome/browser/ui/app_list/chrome_app_list_item.h
@@ -112,6 +112,9 @@ std::string ToDebugString() const; + // Set the default position if it exists. + void SetDefaultPositionIfApplicable(); + protected: ChromeAppListItem(Profile* profile, const std::string& app_id); @@ -130,9 +133,6 @@ void UpdateFromSync( const app_list::AppListSyncableService::SyncItem* sync_item); - // Set the default position if it exists. - void SetDefaultPositionIfApplicable(); - // Get the context menu of a certain app. This could be different for // different kinds of items. virtual app_list::AppContextMenu* GetAppContextMenu();
diff --git a/chrome/browser/ui/app_list/crostini/crostini_app_item.cc b/chrome/browser/ui/app_list/crostini/crostini_app_item.cc index b5d996e..6c0a14a 100644 --- a/chrome/browser/ui/app_list/crostini/crostini_app_item.cc +++ b/chrome/browser/ui/app_list/crostini/crostini_app_item.cc
@@ -35,6 +35,10 @@ UpdateFromSync(sync_item); } else { SetDefaultPositionIfApplicable(); + + // Crostini app is created from scratch. Move it to default folder. + DCHECK(folder_id().empty()); + SetFolderId(kCrostiniFolderId); } // Set model updater last to avoid being called during construction.
diff --git a/chrome/browser/ui/app_list/crostini/crostini_app_model_builder.cc b/chrome/browser/ui/app_list/crostini/crostini_app_model_builder.cc index 4fe20dd..dbb9178 100644 --- a/chrome/browser/ui/app_list/crostini/crostini_app_model_builder.cc +++ b/chrome/browser/ui/app_list/crostini/crostini_app_model_builder.cc
@@ -11,6 +11,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/app_list/app_list_controller_delegate.h" #include "chrome/browser/ui/app_list/crostini/crostini_app_item.h" +#include "chrome/grit/generated_resources.h" #include "components/prefs/pref_change_registrar.h" #include "ui/base/l10n/l10n_util.h" @@ -52,6 +53,8 @@ *registry_service->GetRegistration(app_id); if (registration.NoDisplay()) return; + + MaybeCreateRootFolder(); InsertApp(std::make_unique<CrostiniAppItem>(profile(), model_updater(), GetSyncItem(app_id), app_id, registration.Name())); @@ -96,3 +99,23 @@ RemoveApp(kCrostiniTerminalId, unsynced_change); } } + +void CrostiniAppModelBuilder::MaybeCreateRootFolder() { + if (root_folder_created_) + return; + + root_folder_created_ = true; + const app_list::AppListSyncableService::SyncItem* sync_item = + GetSyncItem(kCrostiniFolderId); + if (sync_item) + return; + + std::unique_ptr<ChromeAppListItem> crositini_folder = + std::make_unique<ChromeAppListItem>(profile(), kCrostiniFolderId, + model_updater()); + crositini_folder->SetChromeIsFolder(true); + crositini_folder->SetName( + l10n_util::GetStringUTF8(IDS_APP_LIST_CROSTINI_DEFAULT_FOLDER_NAME)); + crositini_folder->SetDefaultPositionIfApplicable(); + InsertApp(std::move(crositini_folder)); +}
diff --git a/chrome/browser/ui/app_list/crostini/crostini_app_model_builder.h b/chrome/browser/ui/app_list/crostini/crostini_app_model_builder.h index 784d50c..faae2c6 100644 --- a/chrome/browser/ui/app_list/crostini/crostini_app_model_builder.h +++ b/chrome/browser/ui/app_list/crostini/crostini_app_model_builder.h
@@ -38,6 +38,14 @@ void OnCrostiniEnabledChanged(); + // Creates root folder for Crostini apps in case it was not created or sync + // item does not exist. Once it is created sync item is allocated and it will + // be reusedto restore root folder on demand automatically. + void MaybeCreateRootFolder(); + + // Set to true in case root folder was created on demand. + bool root_folder_created_ = false; + // Observer Crostini installation so we can start showing The Terminal app. std::unique_ptr<PrefChangeRegistrar> pref_change_registrar_;
diff --git a/chrome/browser/ui/app_list/crostini/crostini_app_model_builder_unittest.cc b/chrome/browser/ui/app_list/crostini/crostini_app_model_builder_unittest.cc index cf1ccb3c7..63a2d270 100644 --- a/chrome/browser/ui/app_list/crostini/crostini_app_model_builder_unittest.cc +++ b/chrome/browser/ui/app_list/crostini/crostini_app_model_builder_unittest.cc
@@ -21,25 +21,58 @@ namespace { -std::vector<ChromeAppListItem*> GetAppListItems( +constexpr char kRootFolderName[] = "Linux apps"; +constexpr char kDummpyApp1Name[] = "dummy1"; +constexpr char kDummpyApp2Id[] = "dummy2"; +constexpr char kDummpyApp2Name[] = "dummy2"; +constexpr char kAppNewName[] = "new name"; +constexpr char kBananaAppId[] = "banana"; +constexpr char kBananaAppName[] = "banana app name"; + +// Returns map of items, key-ed by id. +std::map<std::string, ChromeAppListItem*> GetAppListItems( AppListModelUpdater* model_updater) { - std::vector<ChromeAppListItem*> result; - for (size_t i = 0; i < model_updater->ItemCount(); ++i) - result.push_back(model_updater->ItemAtForTest(i)); + std::map<std::string, ChromeAppListItem*> result; + for (size_t i = 0; i < model_updater->ItemCount(); ++i) { + ChromeAppListItem* item = model_updater->ItemAtForTest(i); + result[item->id()] = item; + } return result; } std::vector<std::string> GetAppIds(AppListModelUpdater* model_updater) { std::vector<std::string> result; - for (ChromeAppListItem* item : GetAppListItems(model_updater)) - result.push_back(item->id()); + for (auto item : GetAppListItems(model_updater)) + result.push_back(item.first); return result; } +// This also includes parent folder name, if applicable. std::vector<std::string> GetAppNames(AppListModelUpdater* model_updater) { std::vector<std::string> result; - for (ChromeAppListItem* item : GetAppListItems(model_updater)) - result.push_back(item->name()); + std::map<std::string, ChromeAppListItem*> items = + GetAppListItems(model_updater); + for (auto item : items) { + const std::string folder_id = item.second->folder_id(); + if (folder_id.empty()) { + result.push_back(item.second->name()); + continue; + } + ChromeAppListItem* parent = items[folder_id]; + DCHECK(parent && parent->is_folder()); + result.push_back(parent->name() + "/" + item.second->name()); + } + return result; +} + +std::string GetFullName(const std::string& app_name) { + return std::string(kRootFolderName) + "/" + app_name; +} + +std::vector<std::string> AppendRootFolderId( + const std::vector<std::string> ids) { + std::vector<std::string> result = ids; + result.emplace_back(kCrostiniFolderId); return result; } @@ -94,95 +127,108 @@ TEST_F(CrostiniAppModelBuilderTest, EnableCrostini) { EXPECT_EQ(0u, model_updater_->ItemCount()); CrostiniTestHelper::EnableCrostini(profile()); - EXPECT_EQ(1u, model_updater_->ItemCount()); - ChromeAppListItem* item = model_updater_->ItemAtForTest(0); - EXPECT_EQ(kCrostiniTerminalId, item->id()); - EXPECT_EQ(kCrostiniTerminalAppName, item->name()); + // Root folder + terminal app. + EXPECT_THAT( + GetAppIds(model_updater_.get()), + testing::UnorderedElementsAre(kCrostiniFolderId, kCrostiniTerminalId)); + EXPECT_THAT(GetAppNames(model_updater_.get()), + testing::UnorderedElementsAre( + kRootFolderName, GetFullName(kCrostiniTerminalAppName))); } TEST_F(CrostiniAppModelBuilderTest, AppInstallation) { CrostiniTestHelper test_helper(profile()); - EXPECT_EQ(1u, model_updater_->ItemCount()); + // Root folder + terminal app. + EXPECT_EQ(2u, model_updater_->ItemCount()); test_helper.SetupDummyApps(); EXPECT_THAT(GetAppIds(model_updater_.get()), - testing::UnorderedElementsAreArray( - RegistryService()->GetRegisteredAppIds())); + testing::UnorderedElementsAreArray(AppendRootFolderId( + RegistryService()->GetRegisteredAppIds()))); EXPECT_THAT(GetAppNames(model_updater_.get()), - testing::UnorderedElementsAre(kCrostiniTerminalAppName, "dummy1", - "dummy2")); + testing::UnorderedElementsAre( + kRootFolderName, GetFullName(kCrostiniTerminalAppName), + GetFullName(kDummpyApp1Name), GetFullName(kDummpyApp2Name))); - test_helper.AddApp(CrostiniTestHelper::BasicApp("banana", "banana app name")); + test_helper.AddApp( + CrostiniTestHelper::BasicApp(kBananaAppId, kBananaAppName)); EXPECT_THAT(GetAppIds(model_updater_.get()), - testing::UnorderedElementsAreArray( - RegistryService()->GetRegisteredAppIds())); + testing::UnorderedElementsAreArray(AppendRootFolderId( + RegistryService()->GetRegisteredAppIds()))); EXPECT_THAT(GetAppNames(model_updater_.get()), - testing::UnorderedElementsAre(kCrostiniTerminalAppName, "dummy1", - "dummy2", "banana app name")); + testing::UnorderedElementsAre( + kRootFolderName, GetFullName(kCrostiniTerminalAppName), + GetFullName(kDummpyApp1Name), GetFullName(kDummpyApp2Name), + GetFullName(kBananaAppName))); } // Test that the app model builder correctly picks up changes to existing apps. TEST_F(CrostiniAppModelBuilderTest, UpdateApps) { CrostiniTestHelper test_helper(profile()); test_helper.SetupDummyApps(); - EXPECT_EQ(3u, model_updater_->ItemCount()); + // 3 apps + root folder. + EXPECT_EQ(4u, model_updater_->ItemCount()); // Setting NoDisplay to true should hide an app. vm_tools::apps::App dummy1 = test_helper.GetApp(0); dummy1.set_no_display(true); test_helper.AddApp(dummy1); - EXPECT_EQ(2u, model_updater_->ItemCount()); - EXPECT_THAT( - GetAppIds(model_updater_.get()), - testing::UnorderedElementsAre( - kCrostiniTerminalId, CrostiniTestHelper::GenerateAppId("dummy2"))); + EXPECT_EQ(3u, model_updater_->ItemCount()); + EXPECT_THAT(GetAppIds(model_updater_.get()), + testing::UnorderedElementsAre( + kCrostiniFolderId, kCrostiniTerminalId, + CrostiniTestHelper::GenerateAppId(kDummpyApp2Id))); // Setting NoDisplay to false should unhide an app. dummy1.set_no_display(false); test_helper.AddApp(dummy1); - EXPECT_EQ(3u, model_updater_->ItemCount()); + EXPECT_EQ(4u, model_updater_->ItemCount()); EXPECT_THAT(GetAppIds(model_updater_.get()), - testing::UnorderedElementsAreArray( - RegistryService()->GetRegisteredAppIds())); + testing::UnorderedElementsAreArray(AppendRootFolderId( + RegistryService()->GetRegisteredAppIds()))); // Changes to app names should be detected. vm_tools::apps::App dummy2 = - CrostiniTestHelper::BasicApp("dummy2", "new name"); + CrostiniTestHelper::BasicApp(kDummpyApp2Id, kAppNewName); test_helper.AddApp(dummy2); - EXPECT_EQ(3u, model_updater_->ItemCount()); + EXPECT_EQ(4u, model_updater_->ItemCount()); EXPECT_THAT(GetAppIds(model_updater_.get()), - testing::UnorderedElementsAreArray( - RegistryService()->GetRegisteredAppIds())); + testing::UnorderedElementsAreArray(AppendRootFolderId( + RegistryService()->GetRegisteredAppIds()))); EXPECT_THAT(GetAppNames(model_updater_.get()), - testing::UnorderedElementsAre(kCrostiniTerminalAppName, "dummy1", - "new name")); + testing::UnorderedElementsAre( + kRootFolderName, GetFullName(kCrostiniTerminalAppName), + GetFullName(kDummpyApp1Name), GetFullName(kAppNewName))); } // Test that the app model builder handles removed apps TEST_F(CrostiniAppModelBuilderTest, RemoveApps) { CrostiniTestHelper test_helper(profile()); test_helper.SetupDummyApps(); - EXPECT_EQ(3u, model_updater_->ItemCount()); + // 3 apps + root folder. + EXPECT_EQ(4u, model_updater_->ItemCount()); // Remove dummy1 test_helper.RemoveApp(0); - EXPECT_EQ(2u, model_updater_->ItemCount()); + EXPECT_EQ(3u, model_updater_->ItemCount()); // Remove dummy2 test_helper.RemoveApp(0); - EXPECT_EQ(1u, model_updater_->ItemCount()); + EXPECT_EQ(2u, model_updater_->ItemCount()); } // Test that the Terminal app is removed when Crostini is disabled. TEST_F(CrostiniAppModelBuilderTest, DisableCrostini) { CrostiniTestHelper test_helper(profile()); test_helper.SetupDummyApps(); - EXPECT_EQ(3u, model_updater_->ItemCount()); + // 3 apps + root folder. + EXPECT_EQ(4u, model_updater_->ItemCount()); // The uninstall flow removes all apps before setting the CrostiniEnabled pref // to false, so we need to do that explicitly too. RegistryService()->ClearApplicationList(kCrostiniDefaultVmName, kCrostiniDefaultContainerName); CrostiniTestHelper::DisableCrostini(profile()); - EXPECT_EQ(0u, model_updater_->ItemCount()); + // Root folder is left. We rely on default handling of empty folder. + EXPECT_EQ(1u, model_updater_->ItemCount()); }
diff --git a/chrome/browser/ui/cocoa/touchbar/suggested_text_touch_bar_controller.mm b/chrome/browser/ui/cocoa/touchbar/suggested_text_touch_bar_controller.mm index 55c7fa2..028c40a 100644 --- a/chrome/browser/ui/cocoa/touchbar/suggested_text_touch_bar_controller.mm +++ b/chrome/browser/ui/cocoa/touchbar/suggested_text_touch_bar_controller.mm
@@ -117,10 +117,14 @@ NSCandidateListTouchBarItem* candidateListItem = [[NSCandidateListTouchBarItem alloc] initWithIdentifier:kSuggestedTextItemsTouchId]; - candidateListItem.delegate = self; [candidateListItem setCandidates:suggestions_ forSelectedRange:selectionRange_ inString:text_]; + + candidateListItem.delegate = self; + if (selectionRange_.length) + candidateListItem.collapsed = YES; + return candidateListItem; }
diff --git a/chrome/browser/ui/cocoa/touchbar/suggested_text_touch_bar_controller_unittest.mm b/chrome/browser/ui/cocoa/touchbar/suggested_text_touch_bar_controller_unittest.mm index 0a8001b7..4b97c46 100644 --- a/chrome/browser/ui/cocoa/touchbar/suggested_text_touch_bar_controller_unittest.mm +++ b/chrome/browser/ui/cocoa/touchbar/suggested_text_touch_bar_controller_unittest.mm
@@ -31,12 +31,23 @@ return gfx::Range(range); } - SuggestedTextTouchBarController* controller() { return controller_; } - - private: base::scoped_nsobject<SuggestedTextTouchBarController> controller_; }; +TEST_F(SuggestedTextTouchBarControllerUnitTest, CollapsedCandidateListTest) { + if (@available(macOS 10.12.2, *)) { + base::scoped_nsobject<NSCandidateListTouchBarItem> item; + + [controller_ setSelectionRange:NSMakeRange(0, 0)]; + item.reset([controller_ createCandidateListItem]); + EXPECT_FALSE([item isCollapsed]); + + [controller_ setSelectionRange:NSMakeRange(0, 1)]; + item.reset([controller_ createCandidateListItem]); + EXPECT_TRUE([item isCollapsed]); + } +} + // Tests that the proper range representing the location of the editing word is // calculated for a given text and cursor position. TEST_F(SuggestedTextTouchBarControllerUnitTest, EditingWordRangeTest) { @@ -106,7 +117,7 @@ TEST_F(SuggestedTextTouchBarControllerUnitTest, TouchBarMetricTest) { if (@available(macOS 10.12.2, *)) { base::HistogramTester histogram_tester; - [controller() candidateListTouchBarItem:nil endSelectingCandidateAtIndex:1]; + [controller_ candidateListTouchBarItem:nil endSelectingCandidateAtIndex:1]; histogram_tester.ExpectBucketCount("TouchBar.Default.Metrics", ui::TouchBarAction::TEXT_SUGGESTION, 1); }
diff --git a/chrome/browser/ui/media_router/presentation_receiver_window_controller_browsertest.cc b/chrome/browser/ui/media_router/presentation_receiver_window_controller_browsertest.cc index 2c5836c..e8e6a8d 100644 --- a/chrome/browser/ui/media_router/presentation_receiver_window_controller_browsertest.cc +++ b/chrome/browser/ui/media_router/presentation_receiver_window_controller_browsertest.cc
@@ -24,7 +24,6 @@ #include "content/public/browser/navigation_entry.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/web_contents_observer.h" -#include "content/public/common/presentation_connection_message.h" #include "content/public/test/browser_test_utils.h" #include "extensions/browser/script_executor.h" #include "mojo/public/cpp/bindings/binding.h" @@ -36,6 +35,9 @@ #include "ui/views/widget/widget.h" #include "url/gurl.h" +using testing::_; +using testing::Invoke; + namespace { using RenderFrameHostId = std::pair<int, int>; @@ -94,18 +96,14 @@ void SendTextMessage(const std::string& message) { ASSERT_TRUE(receiver_connection_.is_bound()); receiver_connection_->OnMessage( - content::PresentationConnectionMessage(message), + blink::mojom::PresentationConnectionMessage::NewMessage(message), base::BindOnce([](bool success) { ASSERT_TRUE(success); })); } // blink::mojom::PresentationConnection implementation - void OnMessage(content::PresentationConnectionMessage message, - OnMessageCallback callback) override { - OnMessageMock(message); - std::move(callback).Run(true); - } - MOCK_METHOD1(OnMessageMock, - void(content::PresentationConnectionMessage message)); + MOCK_METHOD2(OnMessage, + void(blink::mojom::PresentationConnectionMessagePtr message, + OnMessageCallback callback)); void DidChangeState( blink::mojom::PresentationConnectionState state) override {} void RequestClose() override {} @@ -303,26 +301,25 @@ "sink", "desc", true, true)); base::RunLoop connection_loop; - EXPECT_CALL(controller_connection, OnMessageMock(::testing::_)) - .WillOnce(::testing::Invoke( - [&connection_loop](content::PresentationConnectionMessage msg) { - ASSERT_TRUE(msg.message); - EXPECT_EQ("ready", *msg.message); - connection_loop.Quit(); - })); + EXPECT_CALL(controller_connection, OnMessage(_, _)) + .WillOnce([&](auto response, auto callback) { + ASSERT_TRUE(response->is_message()); + EXPECT_EQ("ready", response->get_message()); + std::move(callback).Run(true); + connection_loop.Quit(); + }); connection_loop.Run(); // Test ping-pong message. const std::string message("turtles"); base::RunLoop run_loop; - EXPECT_CALL(controller_connection, OnMessageMock(::testing::_)) - .WillOnce(::testing::Invoke( - [&run_loop, - &message](content::PresentationConnectionMessage response) { - ASSERT_TRUE(response.message); - EXPECT_EQ("Pong: " + message, *response.message); - run_loop.Quit(); - })); + EXPECT_CALL(controller_connection, OnMessage(_, _)) + .WillOnce([&](auto response, auto callback) { + ASSERT_TRUE(response->is_message()); + EXPECT_EQ("Pong: " + message, response->get_message()); + std::move(callback).Run(true); + run_loop.Quit(); + }); controller_connection.SendTextMessage(message); run_loop.Run();
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc index ebc7e53..6f95df5 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc +++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
@@ -1766,9 +1766,11 @@ button->SetAccessibleName(node->GetTitle()); button->set_id(VIEW_ID_BOOKMARK_BAR_ELEMENT); // We don't always have a theme provider (ui tests, for example). - if (GetThemeProvider()) { - SkColor color = - GetThemeProvider()->GetColor(ThemeProperties::COLOR_BOOKMARK_TEXT); + const ui::ThemeProvider* const tp = GetThemeProvider(); + if (tp) { + SkColor color = color_utils::GetColorWithMinimumContrast( + tp->GetColor(ThemeProperties::COLOR_BOOKMARK_TEXT), + tp->GetColor(ThemeProperties::COLOR_TOOLBAR)); button->SetEnabledTextColors(color); if (node->is_folder()) { button->SetImage(views::Button::STATE_NORMAL,
diff --git a/chrome/browser/ui/views/chrome_browser_main_extra_parts_views.cc b/chrome/browser/ui/views/chrome_browser_main_extra_parts_views.cc index 51f7bd6..73f9d37 100644 --- a/chrome/browser/ui/views/chrome_browser_main_extra_parts_views.cc +++ b/chrome/browser/ui/views/chrome_browser_main_extra_parts_views.cc
@@ -168,7 +168,6 @@ content::BrowserThread::IO); // WMState is owned as a member, so don't have MusClient create it. params.create_wm_state = false; - params.wtc_config = aura::WindowTreeClient::Config::kMus2; mus_client_ = std::make_unique<views::MusClient>(params); #endif // defined(OS_CHROMEOS) }
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc index 6c04da2..77313b5 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc
@@ -138,8 +138,12 @@ if (MD::IsRefreshUi() && state == TAB_INACTIVE && !GetThemeProvider()->HasCustomColor( ThemeProperties::COLOR_BACKGROUND_TAB_TEXT)) { - return color_utils::IsDark(GetFrameColor()) ? SK_ColorWHITE - : gfx::kGoogleGrey800; + const SkColor background_color = GetTabBackgroundColor(TAB_INACTIVE); + const SkColor default_color = color_utils::IsDark(background_color) + ? gfx::kGoogleGrey500 + : gfx::kGoogleGrey700; + return color_utils::GetColorWithMinimumContrast(default_color, + background_color); } const auto color_id = state == TAB_ACTIVE
diff --git a/chrome/browser/ui/views/tabs/new_tab_button.cc b/chrome/browser/ui/views/tabs/new_tab_button.cc index 7bbdaadb..ceefd28 100644 --- a/chrome/browser/ui/views/tabs/new_tab_button.cc +++ b/chrome/browser/ui/views/tabs/new_tab_button.cc
@@ -571,8 +571,9 @@ const float radius = GetCornerRadius() * scale; const float rect_width = 2 * radius + - (is_incognito_ ? scale * (incognito_icon_.width() + kDistanceBetweenIcons) - : 0); + (ShouldDrawIncognitoIcon() + ? scale * (incognito_icon_.width() + kDistanceBetweenIcons) + : 0); const SkRect button_rect = SkRect::MakeXYWH(0, button_y, rect_width, 2 * radius);
diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc index be8b073..ab3d2d2 100644 --- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc +++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -59,6 +59,7 @@ #include "chrome/browser/ui/webui/sync_internals_ui.h" #include "chrome/browser/ui/webui/task_scheduler_internals/task_scheduler_internals_ui.h" #include "chrome/browser/ui/webui/translate_internals/translate_internals_ui.h" +#include "chrome/browser/ui/webui/ukm/ukm_internals_ui.h" #include "chrome/browser/ui/webui/usb_internals/usb_internals_ui.h" #include "chrome/browser/ui/webui/user_actions/user_actions_ui.h" #include "chrome/browser/ui/webui/version_ui.h" @@ -408,6 +409,8 @@ return &NewWebUI<TaskSchedulerInternalsUI>; if (url.host_piece() == chrome::kChromeUITranslateInternalsHost) return &NewWebUI<TranslateInternalsUI>; + if (url.host_piece() == chrome::kChromeUIUkmHost) + return &NewWebUI<UkmInternalsUI>; if (url.host_piece() == chrome::kChromeUIUsbInternalsHost) return &NewWebUI<UsbInternalsUI>; if (url.host_piece() == chrome::kChromeUIUserActionsHost)
diff --git a/chrome/browser/ui/webui/conflicts/conflicts_handler.cc b/chrome/browser/ui/webui/conflicts/conflicts_handler.cc index 5009ff7..0ba7fba 100644 --- a/chrome/browser/ui/webui/conflicts/conflicts_handler.cc +++ b/chrome/browser/ui/webui/conflicts/conflicts_handler.cc
@@ -12,6 +12,7 @@ #include "base/strings/string16.h" #include "base/strings/string_number_conversions.h" #include "base/values.h" +#include "base/win/windows_version.h" #include "chrome/browser/conflicts/module_database_win.h" #include "chrome/browser/conflicts/module_info_win.h" #include "chrome/common/chrome_features.h" @@ -301,6 +302,9 @@ case ThirdPartyFeaturesStatus::kPolicyDisabled: return "The ThirdPartyBlockingEnabled group policy is disabled."; case ThirdPartyFeaturesStatus::kFeatureDisabled: + if (base::win::GetVersion() < base::win::VERSION_WIN10) + return "The ThirdPartyModulesBlocking feature is disabled."; + return "Both the IncompatibleApplicationsWarning and " "ThirdPartyModulesBlocking features are disabled."; case ThirdPartyFeaturesStatus::kModuleListInvalid: @@ -308,12 +312,17 @@ case ThirdPartyFeaturesStatus::kNoModuleListAvailable: return "Disabled - There is no Module List version available."; case ThirdPartyFeaturesStatus::kWarningInitialized: + DCHECK_GE(base::win::GetVersion(), base::win::VERSION_WIN10); return "The IncompatibleApplicationsWarning feature is enabled, while " "the ThirdPartyModulesBlocking feature is disabled."; case ThirdPartyFeaturesStatus::kBlockingInitialized: + if (base::win::GetVersion() < base::win::VERSION_WIN10) + return "The ThirdPartyModulesBlocking feature is enabled."; + return "The ThirdPartyModulesBlocking feature is enabled, while the " "IncompatibleApplicationsWarning feature is disabled."; case ThirdPartyFeaturesStatus::kWarningAndBlockingInitialized: + DCHECK_GE(base::win::GetVersion(), base::win::VERSION_WIN10); return "Both the IncompatibleApplicationsWarning and " "ThirdPartyModulesBlocking features are enabled"; }
diff --git a/chrome/browser/ui/webui/extensions/extensions_ui.cc b/chrome/browser/ui/webui/extensions/extensions_ui.cc index 77af995..288f145 100644 --- a/chrome/browser/ui/webui/extensions/extensions_ui.cc +++ b/chrome/browser/ui/webui/extensions/extensions_ui.cc
@@ -218,6 +218,11 @@ {"loadErrorErrorLabel", IDS_MD_EXTENSIONS_LOAD_ERROR_ERROR_LABEL}, {"loadErrorRetry", IDS_MD_EXTENSIONS_LOAD_ERROR_RETRY}, {"noErrorsToShow", IDS_EXTENSIONS_ERROR_NO_ERRORS_CODE_MESSAGE}, + {"runtimeHostsDialogInputError", + IDS_MD_EXTENSIONS_RUNTIME_HOSTS_DIALOG_INPUT_ERROR}, + {"runtimeHostsDialogInputLabel", + IDS_MD_EXTENSIONS_RUNTIME_HOSTS_DIALOG_INPUT_LABEL}, + {"runtimeHostsDialogTitle", IDS_MD_EXTENSIONS_RUNTIME_HOSTS_DIALOG_TITLE}, {"packDialogTitle", IDS_MD_EXTENSIONS_PACK_DIALOG_TITLE}, {"packDialogWarningTitle", IDS_MD_EXTENSIONS_PACK_DIALOG_WARNING_TITLE}, {"packDialogErrorTitle", IDS_MD_EXTENSIONS_PACK_DIALOG_ERROR_TITLE},
diff --git a/chrome/browser/ui/webui/ukm/ukm_internals_ui.cc b/chrome/browser/ui/webui/ukm/ukm_internals_ui.cc new file mode 100644 index 0000000..1f25b7d --- /dev/null +++ b/chrome/browser/ui/webui/ukm/ukm_internals_ui.cc
@@ -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. + +#include "chrome/browser/ui/webui/ukm/ukm_internals_ui.h" + +#include <stddef.h> + +#include <memory> +#include <string> +#include <utility> + +#include "chrome/browser/browser_process.h" +#include "chrome/common/url_constants.h" +#include "chrome/grit/browser_resources.h" +#include "components/metrics_services_manager/metrics_services_manager.h" +#include "components/ukm/debug/ukm_debug_data_extractor.h" +#include "components/ukm/ukm_service.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_ui.h" +#include "content/public/browser/web_ui_data_source.h" +#include "content/public/browser/web_ui_message_handler.h" + +namespace { + +content::WebUIDataSource* CreateUkmHTMLSource() { + content::WebUIDataSource* source = + content::WebUIDataSource::Create(chrome::kChromeUIUkmHost); + + source->AddResourcePath("ukm_internals.js", IDR_UKM_INTERNALS_JS); + source->SetDefaultResource(IDR_UKM_INTERNALS_HTML); + source->UseGzip(); + return source; +} + +// This class receives javascript messages from the renderer. +// Note that the WebUI infrastructure runs on the UI thread, therefore all of +// this class's methods are expected to run on the UI thread. +class UkmMessageHandler : public content::WebUIMessageHandler { + public: + explicit UkmMessageHandler(const ukm::UkmService* ukm_service); + ~UkmMessageHandler() override; + + // WebUIMessageHandler: + void RegisterMessages() override; + + private: + void HandleRequestUkmData(const base::ListValue* args); + + const ukm::UkmService* ukm_service_; + + DISALLOW_COPY_AND_ASSIGN(UkmMessageHandler); +}; + +UkmMessageHandler::UkmMessageHandler(const ukm::UkmService* ukm_service) + : ukm_service_(ukm_service) {} + +UkmMessageHandler::~UkmMessageHandler() {} + +void UkmMessageHandler::HandleRequestUkmData(const base::ListValue* args) { + AllowJavascript(); + + // Identifies the callback, used for when resolving. + std::string callback_id; + args->GetString(0, &callback_id); + + base::Value ukm_debug_data = + ukm::debug::UkmDebugDataExtractor::GetStructuredData(ukm_service_); + + ResolveJavascriptCallback(base::Value(callback_id), + std::move(ukm_debug_data)); +} + +void UkmMessageHandler::RegisterMessages() { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + // We can use base::Unretained() here, as both the callback and this class are + // owned by UkmInternalsUI. + web_ui()->RegisterMessageCallback( + "requestUkmData", + base::BindRepeating(&UkmMessageHandler::HandleRequestUkmData, + base::Unretained(this))); +} + +} // namespace + +UkmInternalsUI::UkmInternalsUI(content::WebUI* web_ui) + : content::WebUIController(web_ui) { + ukm::UkmService* ukm_service = + g_browser_process->GetMetricsServicesManager()->GetUkmService(); + web_ui->AddMessageHandler(std::make_unique<UkmMessageHandler>(ukm_service)); + + // Set up the chrome://ukm/ source. + content::BrowserContext* browser_context = + web_ui->GetWebContents()->GetBrowserContext(); + content::WebUIDataSource::Add(browser_context, CreateUkmHTMLSource()); +}
diff --git a/chrome/browser/ui/webui/ukm/ukm_internals_ui.h b/chrome/browser/ui/webui/ukm/ukm_internals_ui.h new file mode 100644 index 0000000..1605536 --- /dev/null +++ b/chrome/browser/ui/webui/ukm/ukm_internals_ui.h
@@ -0,0 +1,20 @@ +// 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_UI_WEBUI_UKM_UKM_INTERNALS_UI_H_ +#define CHROME_BROWSER_UI_WEBUI_UKM_UKM_INTERNALS_UI_H_ + +#include "base/macros.h" +#include "content/public/browser/web_ui_controller.h" + +// Handles serving the chrome://ukm HTML and JS. +class UkmInternalsUI : public content::WebUIController { + public: + explicit UkmInternalsUI(content::WebUI* web_ui); + + private: + DISALLOW_COPY_AND_ASSIGN(UkmInternalsUI); +}; + +#endif // CHROME_BROWSER_UI_WEBUI_UKM_UKM_INTERNALS_UI_H_
diff --git a/chrome/browser/vr/gesture_detector.cc b/chrome/browser/vr/gesture_detector.cc index ee7a321..2bf766ea 100644 --- a/chrome/browser/vr/gesture_detector.cc +++ b/chrome/browser/vr/gesture_detector.cc
@@ -6,6 +6,7 @@ #include "base/numerics/math_constants.h" #include "chrome/browser/vr/input_event.h" +#include "chrome/browser/vr/platform_controller.h" namespace vr { @@ -32,6 +33,11 @@ // Horizontal distance from the border to the center of slop. constexpr float kSlopHorizontal = 0.15f; +struct TouchPoint { + gfx::Vector2dF position; + base::TimeTicks timestamp; +}; + } // namespace GestureDetector::GestureDetector() { @@ -40,17 +46,21 @@ GestureDetector::~GestureDetector() = default; std::unique_ptr<InputEventList> GestureDetector::DetectGestures( - const TouchInfo& input_touch_info, - base::TimeTicks current_timestamp, - bool force_cancel) { - touch_position_changed_ = UpdateCurrentTouchPoint(input_touch_info); - TouchInfo touch_info = input_touch_info; - ExtrapolateTouchInfo(&touch_info, current_timestamp); + const PlatformController& controller, + base::TimeTicks current_timestamp) { + touch_position_changed_ = UpdateCurrentTouchPoint(controller); + TouchPoint touch_point{.position = controller.GetPositionInTrackpad(), + .timestamp = controller.GetLastTouchTimestamp()}; + ExtrapolateTouchPoint(&touch_point, current_timestamp); if (touch_position_changed_) - UpdateOverallVelocity(touch_info); + UpdateOverallVelocity(touch_point); + is_select_button_pressed_ = + controller.IsButtonDown(PlatformController::kButtonSelect); + last_touching_state_ = is_touching_trackpad_; + is_touching_trackpad_ = controller.IsTouchingTrackpad(); auto gesture_list = std::make_unique<InputEventList>(); - auto gesture = GetGestureFromTouchInfo(touch_info, force_cancel); + auto gesture = GetGestureFromTouchInfo(touch_point); if (!gesture) return gesture_list; @@ -65,27 +75,26 @@ } std::unique_ptr<InputEvent> GestureDetector::GetGestureFromTouchInfo( - const TouchInfo& touch_info, - bool force_cancel) { + const TouchPoint& touch_point) { std::unique_ptr<InputEvent> gesture; switch (state_->label) { // User has not put finger on touch pad. case WAITING: - gesture = HandleWaitingState(touch_info); + gesture = HandleWaitingState(touch_point); break; // User has not started a gesture (by moving out of slop). case TOUCHING: - gesture = HandleDetectingState(touch_info, force_cancel); + gesture = HandleDetectingState(touch_point); break; // User is scrolling on touchpad case SCROLLING: - gesture = HandleScrollingState(touch_info, force_cancel); + gesture = HandleScrollingState(touch_point); break; // The user has finished scrolling, but we'll hallucinate a few points // before really finishing. case POST_SCROLL: - gesture = HandlePostScrollingState(touch_info, force_cancel); + gesture = HandlePostScrollingState(touch_point); break; default: NOTREACHED(); @@ -93,20 +102,20 @@ } if (gesture) - gesture->set_time_stamp(touch_info.touch_point.timestamp); + gesture->set_time_stamp(touch_point.timestamp); return gesture; } std::unique_ptr<InputEvent> GestureDetector::HandleWaitingState( - const TouchInfo& touch_info) { + const TouchPoint& touch_point) { // User puts finger on touch pad (or when the touch down for current gesture // is missed, initiate gesture from current touch point). - if (touch_info.touch_down || touch_info.is_touching) { + if (is_touching_trackpad_) { // update initial touchpoint - state_->initial_touch_point = touch_info.touch_point; + state_->initial_touch_point = touch_point; // update current touchpoint - state_->cur_touch_point = touch_info.touch_point; + state_->cur_touch_point = touch_point; state_->label = TOUCHING; return std::make_unique<InputEvent>(InputEvent::kFlingCancel); @@ -115,21 +124,20 @@ } std::unique_ptr<InputEvent> GestureDetector::HandleDetectingState( - const TouchInfo& touch_info, - bool force_cancel) { + const TouchPoint& touch_point) { // User lifts up finger from touch pad. - if (touch_info.touch_up || !touch_info.is_touching) { + if (!is_touching_trackpad_) { Reset(); return nullptr; } // Touch position is changed, the touch point moves outside of slop, // and the Controller's button is not down. - if (touch_position_changed_ && touch_info.is_touching && - !InSlop(touch_info.touch_point.position) && !force_cancel) { + if (touch_position_changed_ && is_touching_trackpad_ && + !InSlop(touch_point.position) && !is_select_button_pressed_) { state_->label = SCROLLING; auto gesture = std::make_unique<InputEvent>(InputEvent::kScrollBegin); - UpdateGestureParameters(touch_info); + UpdateGestureParameters(touch_point); UpdateGestureWithScrollDelta(gesture.get()); return gesture; } @@ -137,18 +145,16 @@ } std::unique_ptr<InputEvent> GestureDetector::HandleScrollingState( - const TouchInfo& touch_info, - bool force_cancel) { - if (force_cancel) { - UpdateGestureParameters(touch_info); + const TouchPoint& touch_point) { + if (is_select_button_pressed_) { + UpdateGestureParameters(touch_point); return std::make_unique<InputEvent>(InputEvent::kScrollEnd); } - if (touch_info.touch_up || !(touch_info.is_touching)) { + if (!is_touching_trackpad_) state_->label = POST_SCROLL; - } if (touch_position_changed_) { auto gesture = std::make_unique<InputEvent>(InputEvent::kScrollUpdate); - UpdateGestureParameters(touch_info); + UpdateGestureParameters(touch_point); UpdateGestureWithScrollDelta(gesture.get()); return gesture; } @@ -156,14 +162,13 @@ } std::unique_ptr<InputEvent> GestureDetector::HandlePostScrollingState( - const TouchInfo& touch_info, - bool force_cancel) { - if (extrapolated_touch_ == 0 || force_cancel) { - UpdateGestureParameters(touch_info); + const TouchPoint& touch_point) { + if (extrapolated_touch_ == 0 || is_select_button_pressed_) { + UpdateGestureParameters(touch_point); return std::make_unique<InputEvent>(InputEvent::kScrollEnd); } else { auto gesture = std::make_unique<InputEvent>(InputEvent::kScrollUpdate); - UpdateGestureParameters(touch_info); + UpdateGestureParameters(touch_point); UpdateGestureWithScrollDelta(gesture.get()); return gesture; } @@ -176,55 +181,55 @@ state_->displacement.y() * kDisplacementScaleFactor; } -bool GestureDetector::UpdateCurrentTouchPoint(const TouchInfo& touch_info) { - if (touch_info.is_touching || touch_info.touch_up) { +bool GestureDetector::UpdateCurrentTouchPoint( + const PlatformController& controller) { + if (controller.IsTouchingTrackpad() || last_touching_state_) { // Update the touch point when the touch position has changed. - if (state_->cur_touch_point.position != touch_info.touch_point.position) { + if (state_->cur_touch_point.position != + controller.GetPositionInTrackpad()) { state_->prev_touch_point = state_->cur_touch_point; - state_->cur_touch_point = touch_info.touch_point; + state_->cur_touch_point = { + .position = controller.GetPositionInTrackpad(), + .timestamp = controller.GetLastTouchTimestamp()}; return true; } } return false; } -void GestureDetector::ExtrapolateTouchInfo(TouchInfo* touch_info, - base::TimeTicks current_timestamp) { +void GestureDetector::ExtrapolateTouchPoint(TouchPoint* touch_point, + base::TimeTicks current_timestamp) { const bool effectively_scrolling = state_->label == SCROLLING || state_->label == POST_SCROLL; if (effectively_scrolling && extrapolated_touch_ < kMaxNumOfExtrapolations && - (touch_info->touch_point.timestamp == last_touch_timestamp_ || - state_->cur_touch_point.position == state_->prev_touch_point.position)) { + (touch_point->timestamp == last_touch_timestamp_ || + touch_point->position == state_->prev_touch_point.position)) { extrapolated_touch_++; touch_position_changed_ = true; - // Fill the touch_info float duration = (current_timestamp - last_timestamp_).InSecondsF(); - touch_info->touch_point.position.set_x( - state_->cur_touch_point.position.x() + - state_->overall_velocity.x() * duration); - touch_info->touch_point.position.set_y( - state_->cur_touch_point.position.y() + - state_->overall_velocity.y() * duration); + touch_point->position.set_x(state_->cur_touch_point.position.x() + + state_->overall_velocity.x() * duration); + touch_point->position.set_y(state_->cur_touch_point.position.y() + + state_->overall_velocity.y() * duration); } else { if (extrapolated_touch_ == kMaxNumOfExtrapolations) { state_->overall_velocity = {0, 0}; } extrapolated_touch_ = 0; } - last_touch_timestamp_ = touch_info->touch_point.timestamp; + last_touch_timestamp_ = touch_point->timestamp; last_timestamp_ = current_timestamp; } -void GestureDetector::UpdateOverallVelocity(const TouchInfo& touch_info) { +void GestureDetector::UpdateOverallVelocity(const TouchPoint& touch_point) { float duration = - (touch_info.touch_point.timestamp - state_->prev_touch_point.timestamp) - .InSecondsF(); + (touch_point.timestamp - state_->prev_touch_point.timestamp).InSecondsF(); // If the timestamp does not change, do not update velocity. if (duration < kDelta) return; const gfx::Vector2dF& displacement = - touch_info.touch_point.position - state_->prev_touch_point.position; + touch_point.position - state_->prev_touch_point.position; const gfx::Vector2dF& velocity = ScaleVector2d(displacement, (1 / duration)); @@ -235,12 +240,12 @@ ScaleVector2d(velocity, weight); } -void GestureDetector::UpdateGestureParameters(const TouchInfo& touch_info) { +void GestureDetector::UpdateGestureParameters(const TouchPoint& touch_point) { state_->displacement = - touch_info.touch_point.position - state_->prev_touch_point.position; + touch_point.position - state_->prev_touch_point.position; } -bool GestureDetector::InSlop(const gfx::Vector2dF touch_position) const { +bool GestureDetector::InSlop(const gfx::PointF touch_position) const { return (std::abs(touch_position.x() - state_->initial_touch_point.position.x()) < kSlopHorizontal) &&
diff --git a/chrome/browser/vr/gesture_detector.h b/chrome/browser/vr/gesture_detector.h index 16579452..bb8d7b5 100644 --- a/chrome/browser/vr/gesture_detector.h +++ b/chrome/browser/vr/gesture_detector.h
@@ -10,35 +10,24 @@ #include "base/macros.h" #include "base/time/time.h" #include "chrome/browser/vr/vr_export.h" +#include "ui/gfx/geometry/point_f.h" #include "ui/gfx/geometry/vector2d_f.h" namespace vr { class InputEvent; +class PlatformController; using InputEventList = std::vector<std::unique_ptr<InputEvent>>; -struct TouchPoint { - gfx::Vector2dF position; - base::TimeTicks timestamp; -}; - -struct TouchInfo { - TouchPoint touch_point; - bool touch_up; - bool touch_down; - bool is_touching; -}; - class VR_EXPORT GestureDetector { public: GestureDetector(); virtual ~GestureDetector(); std::unique_ptr<InputEventList> DetectGestures( - const TouchInfo& touch_info, - base::TimeTicks current_timestamp, - bool force_cancel); + const PlatformController& controller, + base::TimeTicks current_timestamp); private: enum GestureDetectorStateLabel { @@ -48,6 +37,11 @@ POST_SCROLL // scroll has finished and we are hallucinating events }; + struct TouchPoint { + gfx::PointF position; + base::TimeTicks timestamp; + }; + struct GestureDetectorState { GestureDetectorStateLabel label = WAITING; TouchPoint prev_touch_point; @@ -60,42 +54,44 @@ }; std::unique_ptr<InputEvent> GetGestureFromTouchInfo( - const TouchInfo& input_touch_info, - bool force_cancel); + const TouchPoint& touch_point); - std::unique_ptr<InputEvent> HandleWaitingState(const TouchInfo& touch_info); - std::unique_ptr<InputEvent> HandleDetectingState(const TouchInfo& touch_info, - bool force_cancel); - std::unique_ptr<InputEvent> HandleScrollingState(const TouchInfo& touch_info, - bool force_cancel); + std::unique_ptr<InputEvent> HandleWaitingState(const TouchPoint& touch_point); + std::unique_ptr<InputEvent> HandleDetectingState( + const TouchPoint& touch_point); + std::unique_ptr<InputEvent> HandleScrollingState( + const TouchPoint& touch_point); std::unique_ptr<InputEvent> HandlePostScrollingState( - const TouchInfo& touch_info, - bool force_cancel); + const TouchPoint& touch_point); void UpdateGestureWithScrollDelta(InputEvent* gesture); // If the user is touching the touch pad and the touch point is different from // before, update the touch point and return true. Otherwise, return false. - bool UpdateCurrentTouchPoint(const TouchInfo& touch_info); + bool UpdateCurrentTouchPoint(const PlatformController& controller); - void ExtrapolateTouchInfo(TouchInfo* touch_info, - base::TimeTicks current_timestamp); + void ExtrapolateTouchPoint(TouchPoint* touch_point, + base::TimeTicks current_timestamp); - void UpdateOverallVelocity(const TouchInfo& touch_info); + void UpdateOverallVelocity(const TouchPoint& touch_info); - void UpdateGestureParameters(const TouchInfo& touch_info); + void UpdateGestureParameters(const TouchPoint& touch_info); - bool InSlop(const gfx::Vector2dF touch_position) const; + bool InSlop(const gfx::PointF touch_position) const; void Reset(); std::unique_ptr<GestureDetectorState> state_; + bool is_select_button_pressed_ = false; + bool is_touching_trackpad_ = false; + // Number of consecutively extrapolated touch points int extrapolated_touch_ = 0; base::TimeTicks last_touch_timestamp_; base::TimeTicks last_timestamp_; + bool last_touching_state_ = false; bool touch_position_changed_;
diff --git a/chrome/browser/vr/gesture_detector_unittest.cc b/chrome/browser/vr/gesture_detector_unittest.cc index 4de4c2cc0..a15186a 100644 --- a/chrome/browser/vr/gesture_detector_unittest.cc +++ b/chrome/browser/vr/gesture_detector_unittest.cc
@@ -5,46 +5,75 @@ #include "chrome/browser/vr/gesture_detector.h" #include "chrome/browser/vr/input_event.h" +#include "chrome/browser/vr/platform_controller.h" #include "testing/gtest/include/gtest/gtest.h" namespace { constexpr float kDelta = 0.001f; -} + +class MockPlatformController : public vr::PlatformController { + public: + MockPlatformController() = default; + MockPlatformController(bool touching_trackpad, + base::TimeTicks touch_timestamp) + : is_touching_trackpad(touching_trackpad), + last_touch_timestamp(touch_timestamp) {} + + bool IsButtonDown(vr::PlatformController::ButtonType type) const override { + return type == vr::PlatformController::kButtonSelect ? is_button_down + : false; + } + + bool IsTouchingTrackpad() const override { return is_touching_trackpad; } + + gfx::PointF GetPositionInTrackpad() const override { + return position_in_trackpad; + } + + base::TimeTicks GetLastOrientationTimestamp() const override { + return base::TimeTicks(); + } + + base::TimeTicks GetLastTouchTimestamp() const override { + return last_touch_timestamp; + } + + base::TimeTicks GetLastButtonTimestamp() const override { + return base::TimeTicks(); + } + + vr::PlatformController::Handedness GetHandedness() const override { + return vr::PlatformController::kRightHanded; + } + + bool GetRecentered() const override { return false; } + + int GetBatteryLevel() const override { return 100; } + + bool is_button_down = false; + bool is_touching_trackpad = false; + gfx::PointF position_in_trackpad; + base::TimeTicks last_touch_timestamp; +}; + +} // namespace namespace vr { -TEST(GestureDetector, NotTouching) { - GestureDetector detector; - - TouchInfo touch_info{ - .touch_up = false, .touch_down = false, .is_touching = false}; - auto gestures = detector.DetectGestures(touch_info, base::TimeTicks(), false); - EXPECT_TRUE(gestures->empty()); -} - TEST(GestureDetector, StartTouchWithoutMoving) { GestureDetector detector; base::TimeTicks timestamp; - TouchInfo touch_info{ - .touch_point = {.position = {0, 0}, .timestamp = timestamp}, - .touch_up = false, - .touch_down = true, - .is_touching = true, - }; - auto gestures = detector.DetectGestures(touch_info, timestamp, false); + MockPlatformController controller(true, timestamp); + auto gestures = detector.DetectGestures(controller, timestamp); EXPECT_EQ(gestures->front()->type(), InputEvent::kFlingCancel); // A small move doesn't trigger scrolling yet. timestamp += base::TimeDelta::FromMilliseconds(1); - touch_info = TouchInfo{ - .touch_point = {.position = {kDelta, kDelta}, .timestamp = timestamp}, - .touch_up = false, - .touch_down = true, - .is_touching = true, - }; - gestures = detector.DetectGestures(touch_info, timestamp, false); + controller.last_touch_timestamp = timestamp; + controller.position_in_trackpad = {kDelta, kDelta}; + gestures = detector.DetectGestures(controller, timestamp); EXPECT_TRUE(gestures->empty()); } @@ -52,23 +81,14 @@ GestureDetector detector; base::TimeTicks timestamp; - TouchInfo touch_info{ - .touch_point = {.position = {0.0f, 0.0f}, .timestamp = timestamp}, - .touch_up = false, - .touch_down = true, - .is_touching = true, - }; - detector.DetectGestures(touch_info, timestamp, false); + MockPlatformController controller(true, timestamp); + detector.DetectGestures(controller, timestamp); // Move to the right. timestamp += base::TimeDelta::FromMilliseconds(1); - touch_info = TouchInfo{ - .touch_point = {.position = {0.3f, 0.0f}, .timestamp = timestamp}, - .touch_up = false, - .touch_down = false, - .is_touching = true, - }; - auto gestures = detector.DetectGestures(touch_info, timestamp, false); + controller.last_touch_timestamp = timestamp; + controller.position_in_trackpad = {0.3f, 0.0f}; + auto gestures = detector.DetectGestures(controller, timestamp); EXPECT_EQ(gestures->front()->type(), InputEvent::kScrollBegin); auto* gesture = static_cast<InputEvent*>(gestures->front().get()); EXPECT_GT(gesture->scroll_data.delta_x, 0.0f); @@ -76,33 +96,27 @@ // Move slightly up. timestamp += base::TimeDelta::FromMilliseconds(1); - touch_info = TouchInfo{ - .touch_point = {.position = {0.3f, 0.01f}, .timestamp = timestamp}, - .touch_up = false, - .touch_down = false, - .is_touching = true, - }; - gestures = detector.DetectGestures(touch_info, timestamp, false); + controller.last_touch_timestamp = timestamp; + controller.position_in_trackpad = {0.3f, 0.01f}; + gestures = detector.DetectGestures(controller, timestamp); EXPECT_EQ(gestures->front()->type(), InputEvent::kScrollUpdate); gesture = static_cast<InputEvent*>(gestures->front().get()); EXPECT_EQ(gesture->scroll_data.delta_x, 0.0f); EXPECT_GT(gesture->scroll_data.delta_y, 0.0f); // Release touch. Scroll is extrapolated for 2 frames. - touch_info.touch_up = true; - touch_info.is_touching = false; + controller.is_touching_trackpad = false; timestamp += base::TimeDelta::FromMilliseconds(1); - gestures = detector.DetectGestures(touch_info, timestamp, false); + gestures = detector.DetectGestures(controller, timestamp); EXPECT_EQ(gestures->front()->type(), InputEvent::kScrollUpdate); gesture = static_cast<InputEvent*>(gestures->front().get()); EXPECT_GT(gesture->scroll_data.delta_x, 0.0f); EXPECT_GT(gesture->scroll_data.delta_y, 0.0f); - touch_info.touch_up = false; timestamp += base::TimeDelta::FromMilliseconds(1); - gestures = detector.DetectGestures(touch_info, timestamp, false); + gestures = detector.DetectGestures(controller, timestamp); EXPECT_EQ(gestures->front()->type(), InputEvent::kScrollUpdate); timestamp += base::TimeDelta::FromMilliseconds(1); - gestures = detector.DetectGestures(touch_info, timestamp, false); + gestures = detector.DetectGestures(controller, timestamp); EXPECT_EQ(gestures->front()->type(), InputEvent::kScrollEnd); } @@ -110,27 +124,21 @@ GestureDetector detector; base::TimeTicks timestamp; - TouchInfo touch_info{ - .touch_point = {.position = {0.0f, 0.0f}, .timestamp = timestamp}, - .touch_up = false, - .touch_down = true, - .is_touching = true, - }; - detector.DetectGestures(touch_info, timestamp, false); + MockPlatformController controller(true, timestamp); + detector.DetectGestures(controller, timestamp); // Move to the right. timestamp += base::TimeDelta::FromMilliseconds(1); - touch_info = TouchInfo{ - .touch_point = {.position = {0.3f, 0.0f}, .timestamp = timestamp}, - .touch_up = false, - .touch_down = false, - .is_touching = true, - }; - auto gestures = detector.DetectGestures(touch_info, timestamp, false); + controller.last_touch_timestamp = timestamp; + controller.position_in_trackpad = {0.3f, 0.0f}; + auto gestures = detector.DetectGestures(controller, timestamp); EXPECT_EQ(gestures->front()->type(), InputEvent::kScrollBegin); - // Cancel. - gestures = detector.DetectGestures(touch_info, timestamp, true); + // Button down. + timestamp += base::TimeDelta::FromMilliseconds(1); + controller.last_touch_timestamp = timestamp; + controller.is_button_down = true; + gestures = detector.DetectGestures(controller, timestamp); EXPECT_EQ(gestures->front()->type(), InputEvent::kScrollEnd); } @@ -138,34 +146,26 @@ GestureDetector detector; base::TimeTicks timestamp; - TouchInfo touch_info{ - .touch_point = {.position = {0.0f, 0.0f}, .timestamp = timestamp}, - .touch_up = false, - .touch_down = true, - .is_touching = true, - }; - detector.DetectGestures(touch_info, timestamp, false); + MockPlatformController controller(true, timestamp); + detector.DetectGestures(controller, timestamp); // Move to the right. timestamp += base::TimeDelta::FromMilliseconds(1); - touch_info = TouchInfo{ - .touch_point = {.position = {0.3f, 0.0f}, .timestamp = timestamp}, - .touch_up = false, - .touch_down = false, - .is_touching = true, - }; - auto gestures = detector.DetectGestures(touch_info, timestamp, false); + controller.last_touch_timestamp = timestamp; + controller.position_in_trackpad = {0.3f, 0.0f}; + auto gestures = detector.DetectGestures(controller, timestamp); EXPECT_EQ(gestures->front()->type(), InputEvent::kScrollBegin); // Release touch. We should see extrapolated scrolling. - touch_info.touch_up = true; - touch_info.is_touching = false; - gestures = detector.DetectGestures(touch_info, timestamp, false); + timestamp += base::TimeDelta::FromMilliseconds(1); + controller.is_touching_trackpad = false; + gestures = detector.DetectGestures(controller, timestamp); EXPECT_EQ(gestures->front()->type(), InputEvent::kScrollUpdate); - // Cancel. - touch_info.touch_up = false; - gestures = detector.DetectGestures(touch_info, timestamp, true); + // Button down. + timestamp += base::TimeDelta::FromMilliseconds(1); + controller.is_button_down = true; + gestures = detector.DetectGestures(controller, timestamp); EXPECT_EQ(gestures->front()->type(), InputEvent::kScrollEnd); } @@ -173,38 +173,27 @@ GestureDetector detector; base::TimeTicks timestamp; - TouchInfo touch_info{ - .touch_point = {.position = {0.0f, 0.0f}, .timestamp = timestamp}, - .touch_up = false, - .touch_down = true, - .is_touching = true, - }; - detector.DetectGestures(touch_info, timestamp, false); + MockPlatformController controller(true, timestamp); + detector.DetectGestures(controller, timestamp); // Move to the right. timestamp += base::TimeDelta::FromMilliseconds(1); - touch_info = TouchInfo{ - .touch_point = {.position = {0.3f, 0.0f}, .timestamp = timestamp}, - .touch_up = false, - .touch_down = false, - .is_touching = true, - }; - auto gestures = detector.DetectGestures(touch_info, timestamp, false); + controller.last_touch_timestamp = timestamp; + controller.position_in_trackpad = {0.3f, 0.0f}; + auto gestures = detector.DetectGestures(controller, timestamp); EXPECT_EQ(gestures->front()->type(), InputEvent::kScrollBegin); // Release touch. We should see extrapolated scrolling. timestamp += base::TimeDelta::FromMilliseconds(1); - touch_info.touch_up = true; - touch_info.is_touching = false; - gestures = detector.DetectGestures(touch_info, timestamp, false); + controller.is_touching_trackpad = false; + gestures = detector.DetectGestures(controller, timestamp); EXPECT_EQ(gestures->front()->type(), InputEvent::kScrollUpdate); - // Cancel and touch. + // Touch and button down. timestamp += base::TimeDelta::FromMilliseconds(1); - touch_info.touch_up = false; - touch_info.touch_down = true; - touch_info.is_touching = true; - gestures = detector.DetectGestures(touch_info, timestamp, true); + controller.is_button_down = true; + controller.is_touching_trackpad = true; + gestures = detector.DetectGestures(controller, timestamp); EXPECT_EQ(gestures->front()->type(), InputEvent::kScrollEnd); }
diff --git a/chrome/browser/vr/platform_controller.h b/chrome/browser/vr/platform_controller.h index dc3c965..2da20ffb 100644 --- a/chrome/browser/vr/platform_controller.h +++ b/chrome/browser/vr/platform_controller.h
@@ -7,6 +7,10 @@ #include "base/time/time.h" +namespace gfx { +class PointF; +} + namespace vr { // This class is not platform-specific. It will be backed by platform-specific @@ -19,8 +23,10 @@ public: enum ButtonType { kButtonHome, + kButtonTypeFirst = kButtonHome, kButtonMenu, kButtonSelect, + kButtonTypeNumber }; enum SwipeDirection { @@ -39,6 +45,8 @@ virtual ~PlatformController() {} virtual bool IsButtonDown(ButtonType type) const = 0; + virtual bool IsTouchingTrackpad() const = 0; + virtual gfx::PointF GetPositionInTrackpad() const = 0; virtual base::TimeTicks GetLastOrientationTimestamp() const = 0; virtual base::TimeTicks GetLastTouchTimestamp() const = 0; virtual base::TimeTicks GetLastButtonTimestamp() const = 0;
diff --git a/chrome/common/webui_url_constants.cc b/chrome/common/webui_url_constants.cc index 8de2ab8..984797f6 100644 --- a/chrome/common/webui_url_constants.cc +++ b/chrome/common/webui_url_constants.cc
@@ -155,6 +155,7 @@ const char kChromeUIThumbnailListHost[] = "thumbnails"; const char kChromeUIThumbnailURL[] = "chrome://thumb/"; const char kChromeUITranslateInternalsHost[] = "translate-internals"; +const char kChromeUIUkmHost[] = "ukm"; const char kChromeUIUberHost[] = "chrome"; const char kChromeUIUsbInternalsHost[] = "usb-internals"; const char kChromeUIUserActionsHost[] = "user-actions";
diff --git a/chrome/common/webui_url_constants.h b/chrome/common/webui_url_constants.h index 5934388..23005ad 100644 --- a/chrome/common/webui_url_constants.h +++ b/chrome/common/webui_url_constants.h
@@ -155,6 +155,7 @@ extern const char kChromeUIThumbnailListHost[]; extern const char kChromeUIThumbnailURL[]; extern const char kChromeUITranslateInternalsHost[]; +extern const char kChromeUIUkmHost[]; extern const char kChromeUIUberHost[]; extern const char kChromeUIUsbInternalsHost[]; extern const char kChromeUIUserActionsHost[];
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 77b5f23..f97fa4b2 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -3471,6 +3471,7 @@ "../browser/extensions/api/signed_in_devices/id_mapping_helper_unittest.cc", "../browser/extensions/api/signed_in_devices/signed_in_devices_api_unittest.cc", "../browser/extensions/api/signed_in_devices/signed_in_devices_manager_unittest.cc", + "../browser/extensions/api/socket/combined_socket_unittest.cc", "../browser/extensions/api/socket/socket_api_unittest.cc", "../browser/extensions/api/socket/tcp_socket_unittest.cc", "../browser/extensions/api/socket/tls_socket_unittest.cc",
diff --git a/chrome/test/data/autofill/captured_sites/amazon.test b/chrome/test/data/autofill/captured_sites/amazon.test index 73247bb..b8e720a 100644 --- a/chrome/test/data/autofill/captured_sites/amazon.test +++ b/chrome/test/data/autofill/captured_sites/amazon.test
@@ -18,51 +18,56 @@ "selectorType": "xpath", "selector": "//*[@id=\"enterAddressFullName\"]", "context": [], - "type": "autofill", - "fields" : [ - { - "selector": "//*[@id=\"enterAddressFullName\"]", - "context": [], - "expectedAutofillType": "NAME_FULL", - "expectedValue": "Milton C. Waddams" - }, - { - "selector": "//*[@id=\"enterAddressAddressLine1\"]", - "context": [], - "expectedAutofillType": "ADDRESS_HOME_LINE1", - "expectedValue": "4120 Freidrich Lane" - }, - { - "selector": "//*[@id=\"enterAddressAddressLine2\"]", - "context": [], - "expectedAutofillType": "ADDRESS_HOME_LINE2", - "expectedValue": "Apt 8" - }, - { - "selector": "//*[@id=\"enterAddressCity\"]", - "context": [], - "expectedAutofillType": "ADDRESS_HOME_CITY", - "expectedValue": "Austin" - }, - { - "selector": "//*[@id=\"enterAddressStateOrRegion\"]", - "context": [], - "expectedAutofillType": "ADDRESS_HOME_STATE", - "expectedValue": "Texas" - }, - { - "selector": "//*[@id=\"enterAddressPostalCode\"]", - "context": [], - "expectedAutofillType": "ADDRESS_HOME_ZIP", - "expectedValue": "78744" - }, - { - "selector": "//*[@id=\"enterAddressPhoneNumber\"]", - "context": [], - "expectedAutofillType": "PHONE_HOME_CITY_AND_NUMBER", - "expectedValue": "5125551234" - } - ] + "type": "autofill" + }, + { + "selector": "//*[@id=\"enterAddressFullName\"]", + "context": [], + "expectedAutofillType": "NAME_FULL", + "expectedValue": "Milton C. Waddams", + "type": "validateField" + }, + { + "selector": "//*[@id=\"enterAddressAddressLine1\"]", + "context": [], + "expectedAutofillType": "ADDRESS_HOME_LINE1", + "expectedValue": "4120 Freidrich Lane", + "type": "validateField" + }, + { + "selector": "//*[@id=\"enterAddressAddressLine2\"]", + "context": [], + "expectedAutofillType": "ADDRESS_HOME_LINE2", + "expectedValue": "Apt 8", + "type": "validateField" + }, + { + "selector": "//*[@id=\"enterAddressCity\"]", + "context": [], + "expectedAutofillType": "ADDRESS_HOME_CITY", + "expectedValue": "Austin", + "type": "validateField" + }, + { + "selector": "//*[@id=\"enterAddressStateOrRegion\"]", + "context": [], + "expectedAutofillType": "ADDRESS_HOME_STATE", + "expectedValue": "Texas", + "type": "validateField" + }, + { + "selector": "//*[@id=\"enterAddressPostalCode\"]", + "context": [], + "expectedAutofillType": "ADDRESS_HOME_ZIP", + "expectedValue": "78744", + "type": "validateField" + }, + { + "selector": "//*[@id=\"enterAddressPhoneNumber\"]", + "context": [], + "expectedAutofillType": "PHONE_HOME_CITY_AND_NUMBER", + "expectedValue": "5125551234", + "type": "validateField" }, { "selectorType": "xpath", @@ -71,13 +76,6 @@ "type": "click" }, { - "context": [], - "type": "waitFor", - "assertions": [ - "return document.querySelector(`#spinner-anchor`).style.display === 'none';" - ] - }, - { "selectorType": "xpath", "selector": "//*[@id=\"shippingOptionFormId\"]/div[1]/div[2]/div/span[contains(., '')]/span[contains(., '')]/input[@type='submit' and @value='Continue']", "context": [], @@ -87,33 +85,35 @@ "selectorType": "xpath", "selector": "//*[@id=\"ccName\"]", "context": [], - "type": "autofill", - "fields" : [ - { - "selector": "//*[@id=\"addCreditCardNumber\"]", - "context": [], - "expectedAutofillType": "CREDIT_CARD_NUMBER", - "expectedValue": "9621327911759602" - }, - { - "selector": "//*[@id=\"ccName\"]", - "context": [], - "expectedAutofillType": "CREDIT_CARD_NAME_FULL", - "expectedValue": "Milton Waddams" - }, - { - "selector": "//*[@id=\"ccMonth\"]", - "context": [], - "expectedAutofillType": "CREDIT_CARD_EXP_MONTH", - "expectedValue": "5" - }, - { - "selector": "//*[@id=\"ccYear\"]", - "context": [], - "expectedAutofillType": "CREDIT_CARD_EXP_4_DIGIT_YEAR", - "expectedValue": "2027" - } - ] + "type": "autofill" + }, + { + "selector": "//*[@id=\"addCreditCardNumber\"]", + "context": [], + "expectedAutofillType": "CREDIT_CARD_NUMBER", + "expectedValue": "9621327911759602", + "type": "validateField" + }, + { + "selector": "//*[@id=\"ccName\"]", + "context": [], + "expectedAutofillType": "CREDIT_CARD_NAME_FULL", + "expectedValue": "Milton Waddams", + "type": "validateField" + }, + { + "selector": "//*[@id=\"ccMonth\"]", + "context": [], + "expectedAutofillType": "CREDIT_CARD_EXP_MONTH", + "expectedValue": "5", + "type": "validateField" + }, + { + "selector": "//*[@id=\"ccYear\"]", + "context": [], + "expectedAutofillType": "CREDIT_CARD_EXP_4_DIGIT_YEAR", + "expectedValue": "2027", + "type": "validateField" } ] -} \ No newline at end of file +}
diff --git a/chrome/test/data/autofill/captured_sites/apple.test b/chrome/test/data/autofill/captured_sites/apple.test index bc28ea1..1576218 100644 --- a/chrome/test/data/autofill/captured_sites/apple.test +++ b/chrome/test/data/autofill/captured_sites/apple.test
@@ -31,69 +31,77 @@ "selectorType": "xpath", "selector": "//*[@id=\"shipping-user-firstName\"]", "context": [], - "type": "autofill", - "fields" : [ - { - "selector": "//*[@id=\"shipping-user-firstName\"]", - "context": [], - "expectedAutofillType": "NAME_FIRST", - "expectedValue": "Milton" - }, - { - "selector": "//*[@id=\"shipping-user-lastName\"]", - "context": [], - "expectedAutofillType": "NAME_LAST", - "expectedValue": "Waddams" - }, - { - "selector": "//*[@id=\"shipping-user-companyName\"]", - "context": [], - "expectedAutofillType": "COMPANY_NAME", - "expectedValue": "Initech" - }, - { - "selector": "//*[@id=\"shipping-user-street\"]", - "context": [], - "expectedAutofillType": "ADDRESS_HOME_LINE1", - "expectedValue": "4120 Freidrich Lane" - }, - { - "selector": "//*[@id=\"shipping-user-street2\"]", - "context": [], - "expectedAutofillType": "ADDRESS_HOME_LINE2", - "expectedValue": "Apt 8" - }, - { - "selector": "//*[@id=\"shipping-user-city\"]", - "context": [], - "expectedAutofillType": "ADDRESS_HOME_CITY", - "expectedValue": "Austin" - }, - { - "selector": "//*[@id=\"shipping-user-state\"]", - "context": [], - "expectedAutofillType": "ADDRESS_HOME_STATE", - "expectedValue": "TX" - }, - { - "selector": "//*[@id=\"shipping-user-emailAddress\"]", - "context": [], - "expectedAutofillType": "EMAIL_ADDRESS", - "expectedValue": "red.swingline@initech.com" - }, - { - "selector": "//*[@id=\"shipping-user-daytimePhoneAreaCode\"]", - "context": [], - "expectedAutofillType": "PHONE_HOME_CITY_CODE", - "expectedValue": "512" - }, - { - "selector": "//*[@id=\"shipping-user-daytimePhone\"]", - "context": [], - "expectedAutofillType": "PHONE_HOME_NUMBER", - "expectedValue": "5551234" - } - ] + "type": "autofill" + }, + { + "selector": "//*[@id=\"shipping-user-firstName\"]", + "context": [], + "expectedAutofillType": "NAME_FIRST", + "expectedValue": "Milton", + "type": "validateField" + }, + { + "selector": "//*[@id=\"shipping-user-lastName\"]", + "context": [], + "expectedAutofillType": "NAME_LAST", + "expectedValue": "Waddams", + "type": "validateField" + }, + { + "selector": "//*[@id=\"shipping-user-companyName\"]", + "context": [], + "expectedAutofillType": "COMPANY_NAME", + "expectedValue": "Initech", + "type": "validateField" + }, + { + "selector": "//*[@id=\"shipping-user-street\"]", + "context": [], + "expectedAutofillType": "ADDRESS_HOME_LINE1", + "expectedValue": "4120 Freidrich Lane", + "type": "validateField" + }, + { + "selector": "//*[@id=\"shipping-user-street2\"]", + "context": [], + "expectedAutofillType": "ADDRESS_HOME_LINE2", + "expectedValue": "Apt 8", + "type": "validateField" + }, + { + "selector": "//*[@id=\"shipping-user-city\"]", + "context": [], + "expectedAutofillType": "ADDRESS_HOME_CITY", + "expectedValue": "Austin", + "type": "validateField" + }, + { + "selector": "//*[@id=\"shipping-user-state\"]", + "context": [], + "expectedAutofillType": "ADDRESS_HOME_STATE", + "expectedValue": "TX", + "type": "validateField" + }, + { + "selector": "//*[@id=\"shipping-user-emailAddress\"]", + "context": [], + "expectedAutofillType": "EMAIL_ADDRESS", + "expectedValue": "red.swingline@initech.com", + "type": "validateField" + }, + { + "selector": "//*[@id=\"shipping-user-daytimePhoneAreaCode\"]", + "context": [], + "expectedAutofillType": "PHONE_HOME_CITY_CODE", + "expectedValue": "512", + "type": "validateField" + }, + { + "selector": "//*[@id=\"shipping-user-daytimePhone\"]", + "context": [], + "expectedAutofillType": "PHONE_HOME_NUMBER", + "expectedValue": "5551234", + "type": "validateField" }, { "selectorType": "xpath", @@ -111,95 +119,104 @@ "selectorType": "xpath", "selector": "//*[@id=\"payment-credit-user-address-firstName\"]", "context": [], - "type": "autofill", - "fields" : [ - { - "selector": "//*[@id=\"payment-credit-user-address-firstName\"]", - "context": [], - "expectedAutofillType": "NAME_FIRST", - "expectedValue": "Milton" - }, - { - "selector": "//*[@id=\"payment-credit-user-address-lastName\"]", - "context": [], - "expectedAutofillType": "NAME_LAST", - "expectedValue": "Waddams" - }, - { - "selector": "//*[@id=\"payment-credit-user-address-companyName\"]", - "context": [], - "expectedAutofillType": "COMPANY_NAME", - "expectedValue": "Initech" - }, - { - "selector": "//*[@id=\"payment-credit-user-address-street\"]", - "context": [], - "expectedAutofillType": "ADDRESS_HOME_LINE1", - "expectedValue": "4120 Freidrich Lane" - }, - { - "selector": "//*[@id=\"payment-credit-user-address-street2\"]", - "context": [], - "expectedAutofillType": "ADDRESS_HOME_LINE2", - "expectedValue": "Apt 8" - }, - { - "selector": "//*[@id=\"payment-credit-user-address-postalCode\"]", - "context": [], - "expectedAutofillType": "ADDRESS_HOME_ZIP", - "expectedValue": "78744" - }, - { - "selector": "//*[@id=\"payment-credit-user-country-selector-countryCode\"]", - "context": [], - "expectedAutofillType": "ADDRESS_HOME_COUNTRY", - "expectedValue": "US" - }, - { - "selector": "//*[@id=\"payment-credit-user-address-emailAddress\"]", - "context": [], - "expectedAutofillType": "EMAIL_ADDRESS", - "expectedValue": "red.swingline@initech.com" - }, - { - "selector": "//*[@id=\"payment-credit-user-address-daytimePhoneAreaCode\"]", - "context": [], - "expectedAutofillType": "PHONE_HOME_CITY_CODE", - "expectedValue": "512" - }, - { - "selector": "//*[@id=\"payment-credit-user-address-daytimePhone\"]", - "context": [], - "expectedAutofillType": "PHONE_HOME_NUMBER", - "expectedValue": "5551234" - } - ] + "type": "autofill" + }, + { + "selector": "//*[@id=\"payment-credit-user-address-firstName\"]", + "context": [], + "expectedAutofillType": "NAME_FIRST", + "expectedValue": "Milton", + "type": "validateField" + }, + { + "selector": "//*[@id=\"payment-credit-user-address-lastName\"]", + "context": [], + "expectedAutofillType": "NAME_LAST", + "expectedValue": "Waddams", + "type": "validateField" + }, + { + "selector": "//*[@id=\"payment-credit-user-address-companyName\"]", + "context": [], + "expectedAutofillType": "COMPANY_NAME", + "expectedValue": "Initech", + "type": "validateField" + }, + { + "selector": "//*[@id=\"payment-credit-user-address-street\"]", + "context": [], + "expectedAutofillType": "ADDRESS_HOME_LINE1", + "expectedValue": "4120 Freidrich Lane", + "type": "validateField" + }, + { + "selector": "//*[@id=\"payment-credit-user-address-street2\"]", + "context": [], + "expectedAutofillType": "ADDRESS_HOME_LINE2", + "expectedValue": "Apt 8", + "type": "validateField" + }, + { + "selector": "//*[@id=\"payment-credit-user-address-postalCode\"]", + "context": [], + "expectedAutofillType": "ADDRESS_HOME_ZIP", + "expectedValue": "78744", + "type": "validateField" + }, + { + "selector": "//*[@id=\"payment-credit-user-country-selector-countryCode\"]", + "context": [], + "expectedAutofillType": "ADDRESS_HOME_COUNTRY", + "expectedValue": "US", + "type": "validateField" + }, + { + "selector": "//*[@id=\"payment-credit-user-address-emailAddress\"]", + "context": [], + "expectedAutofillType": "EMAIL_ADDRESS", + "expectedValue": "red.swingline@initech.com", + "type": "validateField" + }, + { + "selector": "//*[@id=\"payment-credit-user-address-daytimePhoneAreaCode\"]", + "context": [], + "expectedAutofillType": "PHONE_HOME_CITY_CODE", + "expectedValue": "512", + "type": "validateField" + }, + { + "selector": "//*[@id=\"payment-credit-user-address-daytimePhone\"]", + "context": [], + "expectedAutofillType": "PHONE_HOME_NUMBER", + "expectedValue": "5551234", + "type": "validateField" }, { "selectorType": "xpath", "selector": "//*[@id=\"payment-credit-method-cc0-cardNumber\"]", "context": [], - "type": "autofill", - "fields" : [ - { - "selector": "//*[@id=\"payment-credit-method-cc0-cardNumber\"]", - "context": [], - "expectedAutofillType": "CREDIT_CARD_NUMBER", - "expectedValue": "9621327911759602" - }, - { - "selector": "//*[@id=\"payment-credit-method-cc0-expirationMonth\"]", - "context": [], - "expectedAutofillType": "CREDIT_CARD_EXP_MONTH", - "expectedValue": "05" - }, - { - "selector": "//*[@id=\"payment-credit-method-cc0-expirationYear\"]", - "context": [], - "expectedAutofillType": "CREDIT_CARD_EXP_4_DIGIT_YEAR", - "expectedValue": "2027" - } - ] + "type": "autofill" + }, + { + "selector": "//*[@id=\"payment-credit-method-cc0-cardNumber\"]", + "context": [], + "expectedAutofillType": "CREDIT_CARD_NUMBER", + "expectedValue": "9621327911759602", + "type": "validateField" + }, + { + "selector": "//*[@id=\"payment-credit-method-cc0-expirationMonth\"]", + "context": [], + "expectedAutofillType": "CREDIT_CARD_EXP_MONTH", + "expectedValue": "05", + "type": "validateField" + }, + { + "selector": "//*[@id=\"payment-credit-method-cc0-expirationYear\"]", + "context": [], + "expectedAutofillType": "CREDIT_CARD_EXP_4_DIGIT_YEAR", + "expectedValue": "2027", + "type": "validateField" } ] -} \ No newline at end of file +}
diff --git a/chrome/test/data/autofill/captured_sites/ebay.test b/chrome/test/data/autofill/captured_sites/ebay.test index 0e1ad54..94915951 100644 --- a/chrome/test/data/autofill/captured_sites/ebay.test +++ b/chrome/test/data/autofill/captured_sites/ebay.test
@@ -18,69 +18,77 @@ "selectorType": "xpath", "selector": "//*[@id=\"af-first-name\"]", "context": [], - "type": "autofill", - "fields" : [ - { - "selector": "//*[@id=\"af-first-name\"]", - "context": [], - "expectedAutofillType": "HTML_TYPE_GIVEN_NAME", - "expectedValue": "Milton" - }, - { - "selector": "//*[@id=\"af-last-name\"]", - "context": [], - "expectedAutofillType": "HTML_TYPE_FAMILY_NAME", - "expectedValue": "Waddams" - }, - { - "selector": "//*[@id=\"af-address1\"]", - "context": [], - "expectedAutofillType": "ADDRESS_HOME_LINE1", - "expectedValue": "4120 Freidrich Lane" - }, - { - "selector": "//*[@id=\"af-address2\"]", - "context": [], - "expectedAutofillType": "HTML_TYPE_ADDRESS_LINE2", - "expectedValue": "Apt 8" - }, - { - "selector": "//*[@id=\"af-city\"]", - "context": [], - "expectedAutofillType": "HTML_TYPE_ADDRESS_LEVEL2", - "expectedValue": "Austin" - }, - { - "selector": "//*[@id=\"af-state\"]", - "context": [], - "expectedAutofillType": "HTML_TYPE_ADDRESS_LEVEL1", - "expectedValue": "TX" - }, - { - "selector": "//*[@id=\"af-zip\"]", - "context": [], - "expectedAutofillType": "HTML_TYPE_POSTAL_CODE", - "expectedValue": "78744" - }, - { - "selector": "//*[@id=\"af-email\"]", - "context": [], - "expectedAutofillType": "HTML_TYPE_EMAIL", - "expectedValue": "red.swingline@initech.com" - }, - { - "selector": "//*[@id=\"af-email-confirm\"]", - "context": [], - "expectedAutofillType": "HTML_TYPE_EMAIL", - "expectedValue": "red.swingline@initech.com" - }, - { - "selector": "//span[contains(., 'Phone number')]/input[@type='tel']", - "context": [], - "expectedAutofillType": "HTML_TYPE_TEL", - "expectedValue": "(512) 555-1234" - } - ] + "type": "autofill" + }, + { + "selector": "//*[@id=\"af-first-name\"]", + "context": [], + "expectedAutofillType": "HTML_TYPE_GIVEN_NAME", + "expectedValue": "Milton", + "type": "validateField" + }, + { + "selector": "//*[@id=\"af-last-name\"]", + "context": [], + "expectedAutofillType": "HTML_TYPE_FAMILY_NAME", + "expectedValue": "Waddams", + "type": "validateField" + }, + { + "selector": "//*[@id=\"af-address1\"]", + "context": [], + "expectedAutofillType": "ADDRESS_HOME_LINE1", + "expectedValue": "4120 Freidrich Lane", + "type": "validateField" + }, + { + "selector": "//*[@id=\"af-address2\"]", + "context": [], + "expectedAutofillType": "HTML_TYPE_ADDRESS_LINE2", + "expectedValue": "Apt 8", + "type": "validateField" + }, + { + "selector": "//*[@id=\"af-city\"]", + "context": [], + "expectedAutofillType": "HTML_TYPE_ADDRESS_LEVEL2", + "expectedValue": "Austin", + "type": "validateField" + }, + { + "selector": "//*[@id=\"af-state\"]", + "context": [], + "expectedAutofillType": "HTML_TYPE_ADDRESS_LEVEL1", + "expectedValue": "TX", + "type": "validateField" + }, + { + "selector": "//*[@id=\"af-zip\"]", + "context": [], + "expectedAutofillType": "HTML_TYPE_POSTAL_CODE", + "expectedValue": "78744", + "type": "validateField" + }, + { + "selector": "//*[@id=\"af-email\"]", + "context": [], + "expectedAutofillType": "HTML_TYPE_EMAIL", + "expectedValue": "red.swingline@initech.com", + "type": "validateField" + }, + { + "selector": "//*[@id=\"af-email-confirm\"]", + "context": [], + "expectedAutofillType": "HTML_TYPE_EMAIL", + "expectedValue": "red.swingline@initech.com", + "type": "validateField" + }, + { + "selector": "//span[contains(., 'Phone number')]/input[@type='tel']", + "context": [], + "expectedAutofillType": "HTML_TYPE_TEL", + "expectedValue": "(512) 555-1234", + "type": "validateField" }, { "selectorType": "xpath", @@ -89,13 +97,6 @@ "type": "click" }, { - "context": [], - "type": "waitFor", - "assertions": [ - "return automation_helper.isElementWithXpathReady(`//*[@id=\"sa-change-link\"]`);" - ] - }, - { "selectorType": "xpath", "selector": "//*[@id=\"CC\"]", "context": [], @@ -105,21 +106,21 @@ "selectorType": "xpath", "selector": "//*[@id=\"cardNumber\"]", "context": [], - "type": "autofill", - "fields" : [ - { - "selector": "//*[@id=\"cardNumber\"]", - "context": [], - "expectedAutofillType": "HTML_TYPE_CREDIT_CARD_NUMBER", - "expectedValue": "9621327911759602" - }, - { - "selector": "//*[@id=\"cardExp\"]", - "context": [], - "expectedAutofillType": "HTML_TYPE_CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR", - "expectedValue": "05 / 27" - } - ] + "type": "autofill" + }, + { + "selector": "//*[@id=\"cardNumber\"]", + "context": [], + "expectedAutofillType": "HTML_TYPE_CREDIT_CARD_NUMBER", + "expectedValue": "9621327911759602", + "type": "validateField" + }, + { + "selector": "//*[@id=\"cardExp\"]", + "context": [], + "expectedAutofillType": "HTML_TYPE_CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR", + "expectedValue": "05 / 27", + "type": "validateField" } ] -} \ No newline at end of file +}
diff --git a/chrome/test/data/autofill/captured_sites/walmart.test b/chrome/test/data/autofill/captured_sites/walmart.test index e0470e6..c6a53b7 100644 --- a/chrome/test/data/autofill/captured_sites/walmart.test +++ b/chrome/test/data/autofill/captured_sites/walmart.test
@@ -28,72 +28,79 @@ "selectorType": "xpath", "selector": "//input[@type='text' and @name='firstName']", "context": [], - "type": "autofill", - "fields" : [ - { - "selectorType": "xpath", - "selector": "//input[@type='text' and @name='firstName']", - "context": [], - "expectedAutofillType": "NAME_FIRST", - "expectedValue": "Milton" - }, - { - "selectorType": "xpath", - "selector": "//input[@type='text' and @name='lastName']", - "context": [], - "expectedAutofillType": "NAME_LAST", - "expectedValue": "Waddams" - }, - { - "selectorType": "xpath", - "selector": "//input[@type='text' and @name='phone']", - "context": [], - "expectedAutofillType": "PHONE_HOME_CITY_AND_NUMBER", - "expectedValue": "5125551234" - }, - { - "selectorType": "xpath", - "selector": "//input[@type='text' and @name='email']", - "context": [], - "expectedAutofillType": "EMAIL_ADDRESS", - "expectedValue": "red.swingline@initech.com" - }, - { - "selectorType": "xpath", - "selector": "//input[@type='text' and @name='addressLineOne']", - "context": [], - "expectedAutofillType": "ADDRESS_HOME_LINE1", - "expectedValue": "4120 Freidrich Lane" - }, - { - "selectorType": "xpath", - "selector": "//input[@type='text' and @name='addressLineTwo']", - "context": [], - "expectedAutofillType": "ADDRESS_HOME_LINE2", - "expectedValue": "Apt 8" - }, - { - "selectorType": "xpath", - "selector": "//input[@type='text' and @name='city']", - "context": [], - "expectedAutofillType": "ADDRESS_HOME_CITY", - "expectedValue": "Austin" - }, - { - "selectorType": "xpath", - "selector": "//*[@name='state']", - "context": [], - "expectedAutofillType": "ADDRESS_HOME_STATE", - "expectedValue": "TX" - }, - { - "selectorType": "xpath", - "selector": "//input[@type='text' and @name='postalCode']", - "context": [], - "expectedAutofillType": "ADDRESS_HOME_ZIP", - "expectedValue": "78744" - } - ] + "type": "autofill" + }, + { + "selectorType": "xpath", + "selector": "//input[@type='text' and @name='firstName']", + "context": [], + "expectedAutofillType": "NAME_FIRST", + "expectedValue": "Milton", + "type": "validateField" + }, + { + "selectorType": "xpath", + "selector": "//input[@type='text' and @name='lastName']", + "context": [], + "expectedAutofillType": "NAME_LAST", + "expectedValue": "Waddams", + "type": "validateField" + }, + { + "selectorType": "xpath", + "selector": "//input[@type='text' and @name='phone']", + "context": [], + "expectedAutofillType": "PHONE_HOME_CITY_AND_NUMBER", + "expectedValue": "5125551234", + "type": "validateField" + }, + { + "selectorType": "xpath", + "selector": "//input[@type='text' and @name='email']", + "context": [], + "expectedAutofillType": "EMAIL_ADDRESS", + "expectedValue": "red.swingline@initech.com", + "type": "validateField" + }, + { + "selectorType": "xpath", + "selector": "//input[@type='text' and @name='addressLineOne']", + "context": [], + "expectedAutofillType": "ADDRESS_HOME_LINE1", + "expectedValue": "4120 Freidrich Lane", + "type": "validateField" + }, + { + "selectorType": "xpath", + "selector": "//input[@type='text' and @name='addressLineTwo']", + "context": [], + "expectedAutofillType": "ADDRESS_HOME_LINE2", + "expectedValue": "Apt 8", + "type": "validateField" + }, + { + "selectorType": "xpath", + "selector": "//input[@type='text' and @name='city']", + "context": [], + "expectedAutofillType": "ADDRESS_HOME_CITY", + "expectedValue": "Austin", + "type": "validateField" + }, + { + "selectorType": "xpath", + "selector": "//*[@name='state']", + "context": [], + "expectedAutofillType": "ADDRESS_HOME_STATE", + "expectedValue": "TX", + "type": "validateField" + }, + { + "selectorType": "xpath", + "selector": "//input[@type='text' and @name='postalCode']", + "context": [], + "expectedAutofillType": "ADDRESS_HOME_ZIP", + "expectedValue": "78744", + "type": "validateField" }, { "selectorType": "xpath", @@ -102,13 +109,6 @@ "type": "click" }, { - "context": [], - "type": "waitFor", - "assertions": [ - "return automation_helper.isElementWithXpathReady(`//div[@data-automation-id='address-validation-message-address']`);" - ] - }, - { "selectorType": "xpath", "selector": "//button[contains(., 'Use Address Provided')]", "context": [], @@ -118,30 +118,31 @@ "selectorType": "xpath", "selector": "//*[@id=\"creditCard\"]", "context": [], - "type": "autofill", - "fields" : [ - { - "selectorType": "xpath", - "selector": "//*[@id=\"creditCard\"]", - "context": [], - "expectedAutofillType": "HTML_TYPE_CREDIT_CARD_NUMBER", - "expectedValue": "9621327911759602" - }, - { - "selectorType": "xpath", - "selector": "//*[@id=\"month-chooser\"]", - "context": [], - "expectedAutofillType": "HTML_TYPE_CREDIT_CARD_EXP_MONTH", - "expectedValue": "05" - }, - { - "selectorType": "xpath", - "selector": "//*[@id=\"year-chooser\"]", - "context": [], - "expectedAutofillType": "HTML_TYPE_CREDIT_CARD_EXP_YEAR", - "expectedValue": "2027" - } - ] + "type": "autofill" + }, + { + "selectorType": "xpath", + "selector": "//*[@id=\"creditCard\"]", + "context": [], + "expectedAutofillType": "HTML_TYPE_CREDIT_CARD_NUMBER", + "expectedValue": "9621327911759602", + "type": "validateField" + }, + { + "selectorType": "xpath", + "selector": "//*[@id=\"month-chooser\"]", + "context": [], + "expectedAutofillType": "HTML_TYPE_CREDIT_CARD_EXP_MONTH", + "expectedValue": "05", + "type": "validateField" + }, + { + "selectorType": "xpath", + "selector": "//*[@id=\"year-chooser\"]", + "context": [], + "expectedAutofillType": "HTML_TYPE_CREDIT_CARD_EXP_YEAR", + "expectedValue": "2027", + "type": "validateField" } ] -} \ No newline at end of file +}
diff --git a/chrome/test/data/autofill/captured_sites/zappos.test b/chrome/test/data/autofill/captured_sites/zappos.test index 63b25191..3c9c2c9 100644 --- a/chrome/test/data/autofill/captured_sites/zappos.test +++ b/chrome/test/data/autofill/captured_sites/zappos.test
@@ -18,51 +18,56 @@ "selectorType": "xpath", "selector": "//*[@id=\"AddressForm_NAME\"]", "context": [], - "type": "autofill", - "fields" : [ - { - "selector": "//*[@id=\"AddressForm_NAME\"]", - "context": [], - "expectedAutofillType": "NAME_FULL", - "expectedValue": "Milton C. Waddams" - }, - { - "selector": "//*[@id=\"AddressForm_ADDRESS_LINE_1\"]", - "context": [], - "expectedAutofillType": "ADDRESS_HOME_LINE1", - "expectedValue": "4120 Freidrich Lane" - }, - { - "selector": "//*[@id=\"AddressForm_ADDRESS_LINE_2\"]", - "context": [], - "expectedAutofillType": "ADDRESS_HOME_LINE2", - "expectedValue": "Apt 8" - }, - { - "selector": "//*[@id=\"AddressForm_CITY\"]", - "context": [], - "expectedAutofillType": "ADDRESS_HOME_CITY", - "expectedValue": "Austin" - }, - { - "selector": "//*[@id=\"AddressForm_STATE_OR_REGION\"]", - "context": [], - "expectedAutofillType": "ADDRESS_HOME_STATE", - "expectedValue": "Texas" - }, - { - "selector": "//*[@id=\"AddressForm_ZIP_CODE\"]", - "context": [], - "expectedAutofillType": "ADDRESS_HOME_ZIP", - "expectedValue": "78744" - }, - { - "selector": "//*[@id=\"AddressForm_PHONE_NUMBER\"]", - "context": [], - "expectedAutofillType": "PHONE_HOME_CITY_AND_NUMBER", - "expectedValue": "5125551234" - } - ] + "type": "autofill" + }, + { + "selector": "//*[@id=\"AddressForm_NAME\"]", + "context": [], + "expectedAutofillType": "NAME_FULL", + "expectedValue": "Milton C. Waddams", + "type": "validateField" + }, + { + "selector": "//*[@id=\"AddressForm_ADDRESS_LINE_1\"]", + "context": [], + "expectedAutofillType": "ADDRESS_HOME_LINE1", + "expectedValue": "4120 Freidrich Lane", + "type": "validateField" + }, + { + "selector": "//*[@id=\"AddressForm_ADDRESS_LINE_2\"]", + "context": [], + "expectedAutofillType": "ADDRESS_HOME_LINE2", + "expectedValue": "Apt 8", + "type": "validateField" + }, + { + "selector": "//*[@id=\"AddressForm_CITY\"]", + "context": [], + "expectedAutofillType": "ADDRESS_HOME_CITY", + "expectedValue": "Austin", + "type": "validateField" + }, + { + "selector": "//*[@id=\"AddressForm_STATE_OR_REGION\"]", + "context": [], + "expectedAutofillType": "ADDRESS_HOME_STATE", + "expectedValue": "Texas", + "type": "validateField" + }, + { + "selector": "//*[@id=\"AddressForm_ZIP_CODE\"]", + "context": [], + "expectedAutofillType": "ADDRESS_HOME_ZIP", + "expectedValue": "78744", + "type": "validateField" + }, + { + "selector": "//*[@id=\"AddressForm_PHONE_NUMBER\"]", + "context": [], + "expectedAutofillType": "PHONE_HOME_CITY_AND_NUMBER", + "expectedValue": "5125551234", + "type": "validateField" }, { "selectorType": "xpath", @@ -74,33 +79,35 @@ "selectorType": "xpath", "selector": "//*[@id=\"ccNumber\"]", "context": [], - "type": "autofill", - "fields" : [ - { - "selector": "//*[@id=\"ccNumber\"]", - "context": [], - "expectedAutofillType": "CREDIT_CARD_NUMBER", - "expectedValue": "9621327911759602" - }, - { - "selector": "//*[@id=\"ccName\"]", - "context": [], - "expectedAutofillType": "CREDIT_CARD_NAME_FULL", - "expectedValue": "Milton Waddams" - }, - { - "selector": "//*[@id=\"ccMonth\"]", - "context": [], - "expectedAutofillType": "CREDIT_CARD_EXP_MONTH", - "expectedValue": "5" - }, - { - "selector": "//*[@id=\"ccYear\"]", - "context": [], - "expectedAutofillType": "CREDIT_CARD_EXP_4_DIGIT_YEAR", - "expectedValue": "2027" - } - ] + "type": "autofill" + }, + { + "selector": "//*[@id=\"ccNumber\"]", + "context": [], + "expectedAutofillType": "CREDIT_CARD_NUMBER", + "expectedValue": "9621327911759602", + "type": "validateField" + }, + { + "selector": "//*[@id=\"ccName\"]", + "context": [], + "expectedAutofillType": "CREDIT_CARD_NAME_FULL", + "expectedValue": "Milton Waddams", + "type": "validateField" + }, + { + "selector": "//*[@id=\"ccMonth\"]", + "context": [], + "expectedAutofillType": "CREDIT_CARD_EXP_MONTH", + "expectedValue": "5", + "type": "validateField" + }, + { + "selector": "//*[@id=\"ccYear\"]", + "context": [], + "expectedAutofillType": "CREDIT_CARD_EXP_4_DIGIT_YEAR", + "expectedValue": "2027", + "type": "validateField" } ] }
diff --git a/chrome/test/data/autofill/dynamic_form_new_field.html b/chrome/test/data/autofill/dynamic_form_new_field.html new file mode 100644 index 0000000..29fa59e --- /dev/null +++ b/chrome/test/data/autofill/dynamic_form_new_field.html
@@ -0,0 +1,63 @@ +<!-- A page that is used to test that a dynamic form fill feature works properly. --> +<body> + <form name="addr1.1" id="form1" action="https://example.com/" method="post"> + Name: <input type="text" name="firstname" id="firstname"><br> + Address: <input type="text" name="address1" id="address1"><br> + City: <input type="text" name="city" id="city"><br> + State: <select name="state" id="state"> + <option value="CA">CA</option> + <option value="MA">MA</option> + <option value="NY">NY</option> + <option value="MD">MD</option> + <option value="OR">OR</option> + <option value="OH">OH</option> + <option value="IL">IL</option> + <option value="DC">DC</option> + </select> <br> + Country: <select name="country" id="country" onchange="CountryChanged()"> + <option value="CA">Canada</option> + <option value="US">United States</option> + </select> <br> + Company: <input name="company" id="company"> <br> + Email: <input name="email" id="email"> <br> + Phone: <input name="phone" id="phone"> <br> + <input type="reset" value="Reset"> + <input type="submit" value="Submit" id="profile_submit"> + </form> +</body> + +<script src="dynamic_form_utils.js"></script> +<script> + +var notify_on_first_name_input_change = false; +var first_name_input_changed = false; + +function CountryChanged() { + form = document.getElementById('form1'); + + var first_name_input = form.elements[0]; + first_name_input.value = ''; + first_name_input.onchange = function() { + if (notify_on_first_name_input_change) + window.domAutomationController.send(first_name_input.value != ''); + else + first_name_input_changed = true; + } + + var zip_input = document.createElement('input'); + zip_input.setAttribute('type', 'text'); + zip_input.setAttribute('name', 'zip'); + zip_input.setAttribute('id', 'zip'); + form.insertBefore(zip_input, form.elements[form.elements.length - 2]); +} + +function hasRefilled() { + var first_name_input = document.getElementById('firstname'); + if (first_name_input && first_name_input_changed) { + window.domAutomationController.send(first_name_input.value != ''); + } else { + notify_on_first_name_input_change = true; + } +} + +</script>
diff --git a/chrome/test/data/extensions/api_test/socket/api/background.js b/chrome/test/data/extensions/api_test/socket/api/background.js index 4e675fa8..d093aa0 100644 --- a/chrome/test/data/extensions/api_test/socket/api/background.js +++ b/chrome/test/data/extensions/api_test/socket/api/background.js
@@ -200,16 +200,16 @@ socket.read(acceptedSocketId, function(readInfo) { arrayBuffer2String(readInfo.data, function (s) { assertDataMatch(request, s); - // Rather than using a timeout, use another read to detect the peer - // termination. - socket.read(acceptedSocketId, function(readInfo2) { - chrome.test.assertEq(-2, readInfo2.resultCode); + succeeded = true; + // Test whether socket.getInfo correctly reflects the connection status + // if the peer has closed the connection. + setTimeout(function() { socket.getInfo(acceptedSocketId, function(info) { chrome.test.assertFalse(info.connected); socket.destroy(socketId); chrome.test.succeed(); }); - }); + }, 500); }); }); }
diff --git a/chrome/test/data/extensions/background_xhr/background.js b/chrome/test/data/extensions/background_xhr/background.js index 52c8e34..a7402a4 100644 --- a/chrome/test/data/extensions/background_xhr/background.js +++ b/chrome/test/data/extensions/background_xhr/background.js
@@ -1,13 +1,3 @@ // Copyright 2015 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. - -chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) { - if (message.type == "xhr") { - var xhr = new XMLHttpRequest(); - xhr.open(message.method, message.url); - xhr.send(); - } else { - console.error("Unknown message: " + JSON.stringify(message)); - } -});
diff --git a/chrome/test/data/extensions/background_xhr/test_http_auth.js b/chrome/test/data/extensions/background_xhr/test_http_auth.js index beb26e8..7089781 100644 --- a/chrome/test/data/extensions/background_xhr/test_http_auth.js +++ b/chrome/test/data/extensions/background_xhr/test_http_auth.js
@@ -2,9 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// TODO(davidben): When URLSearchParams is stable and implemented, switch this -// (and a lot of other test code) to it. https://crbug.com/303152 -var url = decodeURIComponent(/url=([^&]*)/.exec(location.search)[1]); +var url = new URL(location.href).searchParams.get('url'); var filter = {urls: [url], types: ["xmlhttprequest"]}; chrome.webRequest.onCompleted.addListener(function(details) { @@ -19,5 +17,3 @@ chrome.webRequest.onErrorOccurred.addListener(function(details) { chrome.test.notifyFail("Request failed"); }, filter); - -chrome.runtime.sendMessage({type: "xhr", method: "GET", url: url});
diff --git a/chrome/test/data/extensions/background_xhr/test_tls_client_auth.js b/chrome/test/data/extensions/background_xhr/test_tls_client_auth.js index 4a48af7..f91b2937 100644 --- a/chrome/test/data/extensions/background_xhr/test_tls_client_auth.js +++ b/chrome/test/data/extensions/background_xhr/test_tls_client_auth.js
@@ -2,9 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// TODO(davidben): When URLSearchParams is stable and implemented, switch this -// (and a lot of other test code) to it. https://crbug.com/303152 -var url = decodeURIComponent(/url=([^&]*)/.exec(location.search)[1]); +var url = new URL(location.href).searchParams.get('url'); var filter = {urls: [url], types: ["xmlhttprequest"]}; chrome.webRequest.onCompleted.addListener(function(details) { @@ -19,5 +17,3 @@ chrome.test.notifyPass(); }, filter); - -chrome.runtime.sendMessage({type: "xhr", method: "GET", url: url});
diff --git a/chrome/test/data/webui/cr_elements/cr_dialog_test.js b/chrome/test/data/webui/cr_elements/cr_dialog_test.js index 4512037..b6f181dc 100644 --- a/chrome/test/data/webui/cr_elements/cr_dialog_test.js +++ b/chrome/test/data/webui/cr_elements/cr_dialog_test.js
@@ -40,6 +40,46 @@ }); }); + // cr-dialog has to catch and re-fire 'close' events fired from it's native + // <dialog> child to force them to bubble in Shadow DOM V1. Ensure that this + // mechanism does not interfere with nested <cr-dialog> 'close' events. + test('close events not fired from <dialog> are not affected', function() { + document.body.innerHTML = ` + <cr-dialog id="outer"> + <div slot="title">outer dialog title</div> + <div slot="body"> + <cr-dialog id="inner"> + <div slot="title">inner dialog title</div> + <div slot="body">body</div> + </cr-dialog> + </div> + </cr-dialog>`; + + const outer = document.body.querySelector('#outer'); + assertTrue(!!outer); + const inner = document.body.querySelector('#inner'); + assertTrue(!!inner); + + outer.showModal(); + inner.showModal(); + + let whenFired = test_util.eventToPromise('close', window); + inner.close(); + + return whenFired + .then(e => { + // Check that the event's target is the inner dialog. + assertEquals(inner, e.target); + whenFired = test_util.eventToPromise('close', window); + outer.close(); + return whenFired; + }) + .then(e => { + // Check that the event's target is the outer dialog. + assertEquals(outer, e.target); + }); + }); + test('cancel and close events bubbles when cancelled', function() { document.body.innerHTML = ` <cr-dialog>
diff --git a/chrome/test/data/webui/extensions/cr_extensions_browsertest.js b/chrome/test/data/webui/extensions/cr_extensions_browsertest.js index 7bcf037..e196dbbd 100644 --- a/chrome/test/data/webui/extensions/cr_extensions_browsertest.js +++ b/chrome/test/data/webui/extensions/cr_extensions_browsertest.js
@@ -835,3 +835,23 @@ }); GEN('#endif'); + +//////////////////////////////////////////////////////////////////////////////// +// RuntimeHostsDialog tests + +CrExtensionsRuntimeHostsDialogTest = class extends CrExtensionsBrowserTest { + /** @override */ + get browserPreload() { + return 'chrome://extensions/runtime_hosts_dialog.html'; + } + + get extraLibraries() { + return super.extraLibraries.concat([ + 'extension_runtime_hosts_dialog_test.js', + ]); + } +}; + +TEST_F('CrExtensionsRuntimeHostsDialogTest', 'All', () => { + mocha.run(); +});
diff --git a/chrome/test/data/webui/extensions/extension_runtime_hosts_dialog_test.js b/chrome/test/data/webui/extensions/extension_runtime_hosts_dialog_test.js new file mode 100644 index 0000000..0215a6d --- /dev/null +++ b/chrome/test/data/webui/extensions/extension_runtime_hosts_dialog_test.js
@@ -0,0 +1,82 @@ +// 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. + +suite('RuntimeHostsDialog', function() { + /** @type {extensions.RuntimeHostsDialogElement} */ let dialog; + /** @type {extensions.TestService} */ let delegate; + const ITEM_ID = 'a'.repeat(32); + + setup(function() { + PolymerTest.clearBody(); + dialog = document.createElement('extensions-runtime-hosts-dialog'); + + delegate = new extensions.TestService(); + dialog.delegate = delegate; + dialog.itemId = ITEM_ID; + + document.body.appendChild(dialog); + }); + + teardown(function() { + dialog.remove(); + }); + + test('valid input', function() { + const input = dialog.$$('cr-input'); + const site = 'http://www.example.com'; + input.value = site; + input.fire('input'); + assertFalse(input.invalid); + + const add = dialog.$.add; + assertFalse(add.disabled); + MockInteractions.tap(add); + return delegate.whenCalled('addRuntimeHostPermission').then((args) => { + let id = args[0]; + let input = args[1]; + assertEquals(ITEM_ID, id); + assertEquals(site, input); + }); + }); + + test('invalid input', function() { + // Initially the action button should be disabled, but the error warning + // should not be shown for an empty input. + const input = dialog.$$('cr-input'); + assertFalse(input.invalid); + const add = dialog.$.add; + assertTrue(add.disabled); + + // Simulate user input of invalid text. + const invalidSite = 'foobar'; + input.value = invalidSite; + input.fire('input'); + assertTrue(input.invalid); + assertTrue(add.disabled); + + // Entering valid text should clear the error and enable the add button. + input.value = 'http://www.example.com'; + input.fire('input'); + assertFalse(input.invalid); + assertFalse(add.disabled); + }); + + test('delegate indicates invalid input', function() { + delegate.acceptRuntimeHostPermission = false; + + const input = dialog.$$('cr-input'); + const site = 'http://http://http://'; + input.value = site; + input.fire('input'); + assertFalse(input.invalid); + + const add = dialog.$.add; + assertFalse(add.disabled); + MockInteractions.tap(add); + return delegate.whenCalled('addRuntimeHostPermission').then(() => { + assertTrue(input.invalid); + assertTrue(add.disabled); + }); + }); +});
diff --git a/chrome/test/data/webui/extensions/test_service.js b/chrome/test/data/webui/extensions/test_service.js index 097a556e..81d8db16 100644 --- a/chrome/test/data/webui/extensions/test_service.js +++ b/chrome/test/data/webui/extensions/test_service.js
@@ -7,6 +7,7 @@ class TestService extends TestBrowserProxy { constructor() { super([ + 'addRuntimeHostPermission', 'getExtensionsInfo', 'getExtensionSize', 'getProfileConfiguration', @@ -24,6 +25,9 @@ this.itemStateChangedTarget = new FakeChromeEvent(); this.profileStateChangedTarget = new FakeChromeEvent(); + /** @type {boolean} */ + this.acceptRuntimeHostPermission = true; + /** @private {!chrome.developerPrivate.LoadError} */ this.retryLoadUnpackedError_; @@ -46,6 +50,13 @@ } /** @override */ + addRuntimeHostPermission(id, site) { + this.methodCalled('addRuntimeHostPermission', [id, site]); + return this.acceptRuntimeHostPermission ? Promise.resolve() : + Promise.reject(); + } + + /** @override */ getProfileConfiguration() { this.methodCalled('getProfileConfiguration'); return Promise.resolve({inDeveloperMode: false});
diff --git a/chrome/test/data/webui/media_router/media_router_header_tests.js b/chrome/test/data/webui/media_router/media_router_header_tests.js index 6c70eb97..5287e70 100644 --- a/chrome/test/data/webui/media_router/media_router_header_tests.js +++ b/chrome/test/data/webui/media_router/media_router_header_tests.js
@@ -192,21 +192,21 @@ // Tests the |computeArrowDropIcon_| function. test('compute arrow drop icon', function() { assertEquals( - 'media-router:arrow-drop-up', + 'cr:arrow-drop-up', header.computeArrowDropIcon_( media_router.MediaRouterView.CAST_MODE_LIST)); assertEquals( - 'media-router:arrow-drop-down', + 'cr:arrow-drop-down', header.computeArrowDropIcon_(media_router.MediaRouterView.FILTER)); assertEquals( - 'media-router:arrow-drop-down', + 'cr:arrow-drop-down', header.computeArrowDropIcon_(media_router.MediaRouterView.ISSUE)); assertEquals( - 'media-router:arrow-drop-down', + 'cr:arrow-drop-down', header.computeArrowDropIcon_( media_router.MediaRouterView.ROUTE_DETAILS)); assertEquals( - 'media-router:arrow-drop-down', + 'cr:arrow-drop-down', header.computeArrowDropIcon_( media_router.MediaRouterView.SINK_LIST)); });
diff --git a/chrome/test/data/webui/settings/site_data_test.js b/chrome/test/data/webui/settings/site_data_test.js index 84eef08..9d4bdd2 100644 --- a/chrome/test/data/webui/settings/site_data_test.js +++ b/chrome/test/data/webui/settings/site_data_test.js
@@ -26,7 +26,7 @@ .then(() => { Polymer.dom.flush(); const button = - siteData.$$('.site-item').querySelector('.icon-delete-gray'); + siteData.$$('site-data-entry').$$('.icon-delete-gray'); assertTrue(!!button); assertEquals('PAPER-ICON-BUTTON-LIGHT', button.tagName); button.querySelector('button').click();
diff --git a/chrome/utility/BUILD.gn b/chrome/utility/BUILD.gn index f31a91a..20b78f06 100644 --- a/chrome/utility/BUILD.gn +++ b/chrome/utility/BUILD.gn
@@ -153,7 +153,6 @@ "//ash/components/tap_visualizer:lib", "//ash/components/tap_visualizer/public/mojom", "//chrome/services/file_util:lib", - "//services/ui:lib", "//services/ui/public/interfaces", ] }
diff --git a/chromeos/components/proximity_auth/webui/proximity_auth_webui_handler.cc b/chromeos/components/proximity_auth/webui/proximity_auth_webui_handler.cc index 7aa85c5..de10cb51 100644 --- a/chromeos/components/proximity_auth/webui/proximity_auth_webui_handler.cc +++ b/chromeos/components/proximity_auth/webui/proximity_auth_webui_handler.cc
@@ -23,7 +23,7 @@ #include "chromeos/components/proximity_auth/remote_status_update.h" #include "components/cryptauth/cryptauth_enrollment_manager.h" #include "components/cryptauth/proto/cryptauth_api.pb.h" -#include "components/cryptauth/proto/enum_string_util.h" +#include "components/cryptauth/proto/enum_util.h" #include "components/cryptauth/remote_device_loader.h" #include "components/cryptauth/remote_device_ref.h" #include "components/cryptauth/secure_context.h" @@ -660,11 +660,13 @@ dictionary->SetBoolean( kExternalDeviceUnlockKey, base::ContainsValue(device_info.enabled_software_features(), - cryptauth::SoftwareFeature::EASY_UNLOCK_HOST)); + cryptauth::SoftwareFeatureEnumToString( + cryptauth::SoftwareFeature::EASY_UNLOCK_HOST))); dictionary->SetBoolean( kExternalDeviceMobileHotspot, base::ContainsValue(device_info.supported_software_features(), - cryptauth::SoftwareFeature::MAGIC_TETHER_HOST)); + cryptauth::SoftwareFeatureEnumToString( + cryptauth::SoftwareFeature::MAGIC_TETHER_HOST))); dictionary->SetBoolean(kExternalDeviceIsArcPlusPlusEnrollment, device_info.arc_plus_plus()); dictionary->SetBoolean(kExternalDeviceIsPixelPhone,
diff --git a/chromeos/dbus/fake_image_loader_client.cc b/chromeos/dbus/fake_image_loader_client.cc index 144336a1..4f327fa 100644 --- a/chromeos/dbus/fake_image_loader_client.cc +++ b/chromeos/dbus/fake_image_loader_client.cc
@@ -6,45 +6,103 @@ #include <utility> +#include "base/bind.h" +#include "base/callback.h" +#include "base/files/file_path.h" +#include "base/location.h" #include "base/optional.h" +#include "base/threading/thread_task_runner_handle.h" namespace chromeos { +FakeImageLoaderClient::FakeImageLoaderClient() = default; + +FakeImageLoaderClient::~FakeImageLoaderClient() = default; + +void FakeImageLoaderClient::SetMountPathForComponent( + const std::string& component_name, + const base::FilePath& mount_path) { + mount_paths_[component_name] = mount_path; +} + void FakeImageLoaderClient::RegisterComponent( const std::string& name, const std::string& version, const std::string& component_folder_abs_path, DBusMethodCallback<bool> callback) { - std::move(callback).Run(base::nullopt); + registered_components_[name] = version; + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce(std::move(callback), base::make_optional(true))); } void FakeImageLoaderClient::LoadComponent( const std::string& name, DBusMethodCallback<std::string> callback) { - std::move(callback).Run(base::nullopt); + const auto& version_it = registered_components_.find(name); + if (version_it == registered_components_.end()) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), base::nullopt)); + return; + } + + const auto& mount_path_it = mount_paths_.find(name); + if (mount_path_it == mount_paths_.end()) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), base::nullopt)); + return; + } + + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce( + std::move(callback), + base::make_optional( + mount_path_it->second.Append(version_it->second).value()))); } + void FakeImageLoaderClient::LoadComponentAtPath( const std::string& name, const base::FilePath& path, DBusMethodCallback<base::FilePath> callback) { - std::move(callback).Run(base::nullopt); + const auto& mount_path_it = mount_paths_.find(name); + if (mount_path_it == mount_paths_.end()) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), base::nullopt)); + return; + } + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), + base::make_optional(mount_path_it->second))); } void FakeImageLoaderClient::RemoveComponent(const std::string& name, DBusMethodCallback<bool> callback) { - std::move(callback).Run(base::nullopt); + registered_components_.erase(name); + UnmountComponent(name, std::move(callback)); } void FakeImageLoaderClient::RequestComponentVersion( const std::string& name, DBusMethodCallback<std::string> callback) { - std::move(callback).Run(base::nullopt); + const auto& version_it = registered_components_.find(name); + if (version_it == registered_components_.end()) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), base::nullopt)); + return; + } + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), + base::make_optional(version_it->second))); } void FakeImageLoaderClient::UnmountComponent( const std::string& name, DBusMethodCallback<bool> callback) { - std::move(callback).Run(base::nullopt); + mount_paths_.erase(name); + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce(std::move(callback), base::make_optional(true))); } } // namespace chromeos
diff --git a/chromeos/dbus/fake_image_loader_client.h b/chromeos/dbus/fake_image_loader_client.h index cb7f397..9b0615c 100644 --- a/chromeos/dbus/fake_image_loader_client.h +++ b/chromeos/dbus/fake_image_loader_client.h
@@ -5,20 +5,29 @@ #ifndef CHROMEOS_DBUS_FAKE_IMAGE_LOADER_CLIENT_H_ #define CHROMEOS_DBUS_FAKE_IMAGE_LOADER_CLIENT_H_ +#include <map> #include <string> #include "base/macros.h" #include "chromeos/dbus/image_loader_client.h" +namespace base { +class FilePath; +} + namespace chromeos { // A fake implementation of ImageLoaderClient. This class does nothing. class CHROMEOS_EXPORT FakeImageLoaderClient : public ImageLoaderClient { public: - FakeImageLoaderClient() {} - ~FakeImageLoaderClient() override {} + FakeImageLoaderClient(); + ~FakeImageLoaderClient() override; - // DBusClient ovveride. + // Sets intended mount path for a component. + void SetMountPathForComponent(const std::string& component_name, + const base::FilePath& mount_path); + + // DBusClient override. void Init(dbus::Bus* dbus) override {} // ImageLoaderClient override: @@ -41,6 +50,14 @@ DBusMethodCallback<bool> callback) override; private: + // Maps registered component name to its registered varsion. + std::map<std::string, std::string> registered_components_; + + // Maps component names to paths to which they should be mounted. + // Registered using SetMountPathForComponent() before LoadComponent*() is + // called, and removed by a later call to UnmountComponent(). + std::map<std::string, base::FilePath> mount_paths_; + DISALLOW_COPY_AND_ASSIGN(FakeImageLoaderClient); };
diff --git a/chromeos/services/assistant/assistant_manager_service_impl.cc b/chromeos/services/assistant/assistant_manager_service_impl.cc index 19ad3e9..5b4a4cf 100644 --- a/chromeos/services/assistant/assistant_manager_service_impl.cc +++ b/chromeos/services/assistant/assistant_manager_service_impl.cc
@@ -190,7 +190,6 @@ base::BindOnce(&AssistantManagerServiceImpl::OnAssistantStructureReceived, weak_factory_.GetWeakPtr(), on_done)); - // TODO(muyuanli): handle metalayer and grab only part of the screen. service_->assistant_controller()->RequestScreenshot( region, base::BindOnce( &AssistantManagerServiceImpl::OnAssistantScreenshotReceived, @@ -228,6 +227,11 @@ notification_subscribers_.AddPtr(std::move(subscriber)); } +void AssistantManagerServiceImpl::AddAssistantScreenContextSubscriber( + mojom::AssistantScreenContextSubscriberPtr subscriber) { + screen_context_subscribers_.AddPtr(std::move(subscriber)); +} + void AssistantManagerServiceImpl::RetrieveNotification( mojom::AssistantNotificationPtr notification, int action_index) { @@ -287,6 +291,15 @@ weak_factory_.GetWeakPtr(), resolution)); } +void AssistantManagerServiceImpl::OnShowContextualHtml( + const std::string& html) { + main_thread_task_runner_->PostTask( + FROM_HERE, + base::BindOnce( + &AssistantManagerServiceImpl::OnShowContextualHtmlOnMainThread, + weak_factory_.GetWeakPtr(), html)); +} + void AssistantManagerServiceImpl::OnShowHtml(const std::string& html) { main_thread_task_runner_->PostTask( FROM_HERE, @@ -614,6 +627,12 @@ } } +void AssistantManagerServiceImpl::OnShowContextualHtmlOnMainThread( + const std::string& html) { + screen_context_subscribers_.ForAllPtrs( + [&html](auto* ptr) { ptr->OnContextualHtmlResponse(html); }); +} + void AssistantManagerServiceImpl::OnShowHtmlOnMainThread( const std::string& html) { interaction_subscribers_.ForAllPtrs(
diff --git a/chromeos/services/assistant/assistant_manager_service_impl.h b/chromeos/services/assistant/assistant_manager_service_impl.h index 344c4ba..e3ff714e 100644 --- a/chromeos/services/assistant/assistant_manager_service_impl.h +++ b/chromeos/services/assistant/assistant_manager_service_impl.h
@@ -89,6 +89,8 @@ mojom::AssistantInteractionSubscriberPtr subscriber) override; void AddAssistantNotificationSubscriber( mojom::AssistantNotificationSubscriberPtr subscriber) override; + void AddAssistantScreenContextSubscriber( + mojom::AssistantScreenContextSubscriberPtr subscriber) override; void RetrieveNotification(mojom::AssistantNotificationPtr notification, int action_index) override; void DismissNotification( @@ -97,6 +99,7 @@ RequestScreenContextCallback callback) override; // AssistantActionObserver overrides: + void OnShowContextualHtml(const std::string& html) override; void OnShowHtml(const std::string& html) override; void OnShowSuggestions( const std::vector<action::Suggestion>& suggestions) override; @@ -161,6 +164,7 @@ void OnConversationTurnStartedOnMainThread(bool is_mic_open); void OnConversationTurnFinishedOnMainThread( assistant_client::ConversationStateListener::Resolution resolution); + void OnShowContextualHtmlOnMainThread(const std::string& html); void OnShowHtmlOnMainThread(const std::string& html); void OnShowSuggestionsOnMainThread( const std::vector<mojom::AssistantSuggestionPtr>& suggestions); @@ -204,6 +208,8 @@ interaction_subscribers_; mojo::InterfacePtrSet<mojom::AssistantNotificationSubscriber> notification_subscribers_; + mojo::InterfacePtrSet<mojom::AssistantScreenContextSubscriber> + screen_context_subscribers_; ash::mojom::VoiceInteractionControllerPtr voice_interaction_controller_; mojo::Binding<ash::mojom::VoiceInteractionObserver> voice_interaction_observer_binding_;
diff --git a/chromeos/services/assistant/fake_assistant_manager_service_impl.cc b/chromeos/services/assistant/fake_assistant_manager_service_impl.cc index ec9d51f..75b5a12 100644 --- a/chromeos/services/assistant/fake_assistant_manager_service_impl.cc +++ b/chromeos/services/assistant/fake_assistant_manager_service_impl.cc
@@ -58,6 +58,9 @@ void FakeAssistantManagerServiceImpl::AddAssistantNotificationSubscriber( mojom::AssistantNotificationSubscriberPtr subscriber) {} +void FakeAssistantManagerServiceImpl::AddAssistantScreenContextSubscriber( + mojom::AssistantScreenContextSubscriberPtr subscriber) {} + void FakeAssistantManagerServiceImpl::RetrieveNotification( mojom::AssistantNotificationPtr notification, int action_index) {}
diff --git a/chromeos/services/assistant/fake_assistant_manager_service_impl.h b/chromeos/services/assistant/fake_assistant_manager_service_impl.h index 42125f3..7d9f667 100644 --- a/chromeos/services/assistant/fake_assistant_manager_service_impl.h +++ b/chromeos/services/assistant/fake_assistant_manager_service_impl.h
@@ -45,6 +45,8 @@ mojom::AssistantInteractionSubscriberPtr subscriber) override; void AddAssistantNotificationSubscriber( mojom::AssistantNotificationSubscriberPtr subscriber) override; + void AddAssistantScreenContextSubscriber( + mojom::AssistantScreenContextSubscriberPtr subscriber) override; void RetrieveNotification(mojom::AssistantNotificationPtr notification, int action_index) override; void DismissNotification(
diff --git a/chromeos/services/assistant/public/mojom/assistant.mojom b/chromeos/services/assistant/public/mojom/assistant.mojom index 6f86637..ec8d533c 100644 --- a/chromeos/services/assistant/public/mojom/assistant.mojom +++ b/chromeos/services/assistant/public/mojom/assistant.mojom
@@ -32,6 +32,10 @@ AddAssistantNotificationSubscriber( AssistantNotificationSubscriber subscriber); + // Registers assistant screen context event subscriber. + AddAssistantScreenContextSubscriber( + AssistantScreenContextSubscriber subscriber); + // Retrieves a notification. A voiceless interaction will be sent to server to // retrieve the notification payload, which can trigger other assistant's // events such as OnTextResponse to show the result in the UI. The reteived @@ -47,9 +51,10 @@ RequestScreenContext(gfx.mojom.Rect region) => (); }; -// Subscribes to assistant's interaction event. Responses from the assistant may -// contain untrusted third-party content. Subscriber implementations must be -// sure to handle the response data appropriately. +// Subscribes to assistant's interaction event. These events are server driven +// in response to the user's direct interaction with the assistant. Responses +// from the assistant may contain untrusted third-party content. Subscriber +// implementations must be sure to handle the response data appropriately. interface AssistantInteractionSubscriber { // Assistant interaction has started. In the event of a voice interaction, // |is_voice_interaction| will be true. This implies that the mic is open. @@ -87,7 +92,8 @@ OnSpeechLevelUpdated(float speech_level); }; -// Subscribes to assistant's notification event. +// Subscribes to assistant's notification event. These events are server +// driven and pertain to push notifications. interface AssistantNotificationSubscriber { // Assistant got notification from server. OnShowNotification(AssistantNotification notification); @@ -97,6 +103,14 @@ OnRemoveNotification(string grouping_key); }; +// Subscribes to assistant's screen context events. These events are server +// driven and pertain to the user's screen context. Screen context includes +// both screenshot and view hierarchy data. +interface AssistantScreenContextSubscriber { + // Assistant got contextual Html response from server. + OnContextualHtmlResponse(string response); +}; + // Interface for browser to bind and start assistant. interface AssistantPlatform { // Initiates assistant and provides interfaces for assistant to call into the
diff --git a/chromeos/services/assistant/test_support/mock_assistant.h b/chromeos/services/assistant/test_support/mock_assistant.h index 055ffafb4..4535b28 100644 --- a/chromeos/services/assistant/test_support/mock_assistant.h +++ b/chromeos/services/assistant/test_support/mock_assistant.h
@@ -35,6 +35,10 @@ AddAssistantNotificationSubscriber, void(chromeos::assistant::mojom::AssistantNotificationSubscriberPtr)); + MOCK_METHOD1( + AddAssistantScreenContextSubscriber, + void(chromeos::assistant::mojom::AssistantScreenContextSubscriberPtr)); + MOCK_METHOD2(RetrieveNotification, void(chromeos::assistant::mojom::AssistantNotificationPtr, int));
diff --git a/components/autofill/core/browser/autofill_handler.cc b/components/autofill/core/browser/autofill_handler.cc index 04c50fa0..4038683 100644 --- a/components/autofill/core/browser/autofill_handler.cc +++ b/components/autofill/core/browser/autofill_handler.cc
@@ -51,7 +51,10 @@ for (const FormData& form : forms) { const auto parse_form_start_time = TimeTicks::Now(); FormStructure* form_structure = nullptr; - if (!ParseForm(form, /*cached_form=*/nullptr, &form_structure)) + // Try to find the FormStructure that corresponds to |form|. + // |form_structure| may still be nullptr after this call. + ignore_result(FindCachedForm(form, &form_structure)); + if (!ParseForm(form, form_structure, &form_structure)) continue; DCHECK(form_structure); if (form_structure == nullptr) @@ -182,6 +185,7 @@ // We need to keep the server data if available. We need to use them while // determining the heuristics. form_structure->RetrieveFromCache(*cached_form, + /*apply_value=*/true, /*apply_is_autofilled=*/true, /*only_server_and_autofill_state=*/true); }
diff --git a/components/autofill/core/browser/autofill_manager.cc b/components/autofill/core/browser/autofill_manager.cc index 3402686..f423f18 100644 --- a/components/autofill/core/browser/autofill_manager.cc +++ b/components/autofill/core/browser/autofill_manager.cc
@@ -1403,6 +1403,7 @@ return std::unique_ptr<FormStructure>(); submitted_form->RetrieveFromCache(*cached_submitted_form, + /*apply_value=*/false, /*apply_is_autofilled=*/false, /*only_server_and_autofill_state=*/false); return submitted_form;
diff --git a/components/autofill/core/browser/form_structure.cc b/components/autofill/core/browser/form_structure.cc index f712a2d4..0a5d3d29 100644 --- a/components/autofill/core/browser/form_structure.cc +++ b/components/autofill/core/browser/form_structure.cc
@@ -730,6 +730,7 @@ void FormStructure::RetrieveFromCache( const FormStructure& cached_form, + const bool apply_value, const bool apply_is_autofilled, const bool only_server_and_autofill_state) { // Map from field signatures to cached fields. @@ -754,11 +755,14 @@ if (apply_is_autofilled) { field->is_autofilled = cached_field->second->is_autofilled; } - if (field->form_control_type != "select-one" && - field->value == cached_field->second->value) { - // From the perspective of learning user data, text fields containing - // default values are equivalent to empty fields. - field->value = base::string16(); + if (field->form_control_type != "select-one") { + if (apply_value) { + field->value = cached_field->second->value; + } else if (field->value == cached_field->second->value) { + // From the perspective of learning user data, text fields containing + // default values are equivalent to empty fields. + field->value = base::string16(); + } } field->set_server_type(cached_field->second->server_type()); field->set_previously_autofilled(
diff --git a/components/autofill/core/browser/form_structure.h b/components/autofill/core/browser/form_structure.h index d41617d..7f3e97c 100644 --- a/components/autofill/core/browser/form_structure.h +++ b/components/autofill/core/browser/form_structure.h
@@ -132,8 +132,10 @@ // server. bool ShouldBeUploaded() const; - // Sets the field types to be those set for |cached_form|. + // Sets the field types to be those set for |cached_form|. if |apply_value| is + // true, value is copied over from |cached_form| for non-select elements only. void RetrieveFromCache(const FormStructure& cached_form, + const bool apply_value, const bool apply_is_autofilled, const bool only_server_and_autofill_state);
diff --git a/components/cryptauth/BUILD.gn b/components/cryptauth/BUILD.gn index a8350c1d..6afc50e2 100644 --- a/components/cryptauth/BUILD.gn +++ b/components/cryptauth/BUILD.gn
@@ -217,6 +217,7 @@ ":test_support", "//base/test:test_support", "//components/cryptauth/ble:unit_tests", + "//components/cryptauth/proto:util", "//components/gcm_driver:test_support", "//components/prefs:test_support", "//google_apis:test_support",
diff --git a/components/cryptauth/cryptauth_device_manager_impl.cc b/components/cryptauth/cryptauth_device_manager_impl.cc index 989dc93..be37474 100644 --- a/components/cryptauth/cryptauth_device_manager_impl.cc +++ b/components/cryptauth/cryptauth_device_manager_impl.cc
@@ -17,6 +17,7 @@ #include "chromeos/components/proximity_auth/logging/logging.h" #include "components/cryptauth/cryptauth_client.h" #include "components/cryptauth/pref_names.h" +#include "components/cryptauth/proto/enum_util.h" #include "components/cryptauth/software_feature_state.h" #include "components/cryptauth/sync_scheduler_impl.h" #include "components/prefs/pref_registry_simple.h" @@ -109,20 +110,22 @@ // value that can be stored in user prefs. std::unique_ptr<base::DictionaryValue> SupportedAndEnabledSoftwareFeaturesToDictionaryValue( - const google::protobuf::RepeatedField<int>& supported_software_features, - const google::protobuf::RepeatedField<int>& enabled_software_features, + const google::protobuf::RepeatedPtrField<std::string>& + supported_software_features, + const google::protobuf::RepeatedPtrField<std::string>& + enabled_software_features, bool legacy_unlock_key, bool legacy_mobile_hotspot_supported) { std::unique_ptr<base::DictionaryValue> dictionary = std::make_unique<base::DictionaryValue>(); for (const auto& supported_software_feature : supported_software_features) { - dictionary->SetInteger(std::to_string(supported_software_feature), + dictionary->SetInteger(supported_software_feature, static_cast<int>(SoftwareFeatureState::kSupported)); } for (const auto& enabled_software_feature : enabled_software_features) { - std::string software_feature_key = std::to_string(enabled_software_feature); + std::string software_feature_key = enabled_software_feature; int software_feature_state; if (!dictionary->GetInteger(software_feature_key, @@ -148,13 +151,15 @@ // software features, and only serving the deprecated booleans. int software_feature_state; std::string software_feature_key; - software_feature_key = std::to_string(SoftwareFeature::EASY_UNLOCK_HOST); + software_feature_key = + SoftwareFeatureEnumToString(cryptauth::SoftwareFeature::EASY_UNLOCK_HOST); if (legacy_unlock_key && !dictionary->GetInteger(software_feature_key, &software_feature_state)) { dictionary->SetInteger(software_feature_key, static_cast<int>(SoftwareFeatureState::kEnabled)); } - software_feature_key = std::to_string(SoftwareFeature::MAGIC_TETHER_HOST); + software_feature_key = SoftwareFeatureEnumToString( + cryptauth::SoftwareFeature::MAGIC_TETHER_HOST); if (legacy_mobile_hotspot_supported && !dictionary->GetInteger(software_feature_key, &software_feature_state)) { dictionary->SetInteger(software_feature_key, @@ -301,14 +306,12 @@ continue; } - SoftwareFeature software_feature = - static_cast<SoftwareFeature>(std::stoi(it.first)); switch (static_cast<SoftwareFeatureState>(software_feature_state)) { case SoftwareFeatureState::kEnabled: - external_device->add_enabled_software_features(software_feature); + external_device->add_enabled_software_features(it.first); FALLTHROUGH; case SoftwareFeatureState::kSupported: - external_device->add_supported_software_features(software_feature); + external_device->add_supported_software_features(it.first); break; default: break; @@ -321,22 +324,25 @@ // software features. To work around this, these pref values are migrated to // software features locally. if (old_unlock_key_value_from_prefs) { - if (!base::ContainsValue(external_device->supported_software_features(), - SoftwareFeature::EASY_UNLOCK_HOST)) { + if (!base::ContainsValue( + external_device->supported_software_features(), + SoftwareFeatureEnumToString(SoftwareFeature::EASY_UNLOCK_HOST))) { external_device->add_supported_software_features( - SoftwareFeature::EASY_UNLOCK_HOST); + SoftwareFeatureEnumToString(SoftwareFeature::EASY_UNLOCK_HOST)); } - if (!base::ContainsValue(external_device->enabled_software_features(), - SoftwareFeature::EASY_UNLOCK_HOST)) { + if (!base::ContainsValue( + external_device->enabled_software_features(), + SoftwareFeatureEnumToString(SoftwareFeature::EASY_UNLOCK_HOST))) { external_device->add_enabled_software_features( - SoftwareFeature::EASY_UNLOCK_HOST); + SoftwareFeatureEnumToString(SoftwareFeature::EASY_UNLOCK_HOST)); } } if (old_mobile_hotspot_supported_from_prefs) { - if (!base::ContainsValue(external_device->supported_software_features(), - SoftwareFeature::MAGIC_TETHER_HOST)) { + if (!base::ContainsValue( + external_device->supported_software_features(), + SoftwareFeatureEnumToString(SoftwareFeature::MAGIC_TETHER_HOST))) { external_device->add_supported_software_features( - SoftwareFeature::MAGIC_TETHER_HOST); + SoftwareFeatureEnumToString(SoftwareFeature::MAGIC_TETHER_HOST)); } } } @@ -561,8 +567,9 @@ const { std::vector<ExternalDeviceInfo> unlock_keys; for (const auto& device : synced_devices_) { - if (base::ContainsValue(device.enabled_software_features(), - SoftwareFeature::EASY_UNLOCK_HOST)) { + if (base::ContainsValue( + device.enabled_software_features(), + SoftwareFeatureEnumToString(SoftwareFeature::EASY_UNLOCK_HOST))) { unlock_keys.push_back(device); } } @@ -573,8 +580,9 @@ const { std::vector<ExternalDeviceInfo> unlock_keys; for (const auto& device : synced_devices_) { - if (base::ContainsValue(device.enabled_software_features(), - SoftwareFeature::EASY_UNLOCK_HOST) && + if (base::ContainsValue( + device.enabled_software_features(), + SoftwareFeatureEnumToString(SoftwareFeature::EASY_UNLOCK_HOST)) && device.pixel_phone()) { unlock_keys.push_back(device); } @@ -586,8 +594,9 @@ const { std::vector<ExternalDeviceInfo> tether_hosts; for (const auto& device : synced_devices_) { - if (base::ContainsValue(device.supported_software_features(), - SoftwareFeature::MAGIC_TETHER_HOST)) { + if (base::ContainsValue( + device.supported_software_features(), + SoftwareFeatureEnumToString(SoftwareFeature::MAGIC_TETHER_HOST))) { tether_hosts.push_back(device); } } @@ -598,8 +607,9 @@ CryptAuthDeviceManagerImpl::GetPixelTetherHosts() const { std::vector<ExternalDeviceInfo> tether_hosts; for (const auto& device : synced_devices_) { - if (base::ContainsValue(device.supported_software_features(), - SoftwareFeature::MAGIC_TETHER_HOST) && + if (base::ContainsValue( + device.supported_software_features(), + SoftwareFeatureEnumToString(SoftwareFeature::MAGIC_TETHER_HOST)) && device.pixel_phone()) tether_hosts.push_back(device); }
diff --git a/components/cryptauth/cryptauth_device_manager_impl_unittest.cc b/components/cryptauth/cryptauth_device_manager_impl_unittest.cc index ae860b7..309aacf 100644 --- a/components/cryptauth/cryptauth_device_manager_impl_unittest.cc +++ b/components/cryptauth/cryptauth_device_manager_impl_unittest.cc
@@ -21,6 +21,7 @@ #include "components/cryptauth/mock_sync_scheduler.h" #include "components/cryptauth/network_request_error.h" #include "components/cryptauth/pref_names.h" +#include "components/cryptauth/proto/enum_util.h" #include "components/cryptauth/software_feature_state.h" #include "components/prefs/scoped_user_pref_update.h" #include "components/prefs/testing_pref_service.h" @@ -317,7 +318,7 @@ ASSERT_TRUE(it.second.GetAsInteger(&software_feature_state)); SoftwareFeature software_feature = - static_cast<SoftwareFeature>(std::stoi(it.first)); + SoftwareFeatureStringToEnum(it.first); switch (static_cast<SoftwareFeatureState>(software_feature_state)) { case SoftwareFeatureState::kEnabled: enabled_software_features.push_back(software_feature); @@ -338,13 +339,15 @@ enabled_software_features.size()); for (auto supported_software_feature : expected_device.supported_software_features()) { - EXPECT_TRUE(base::ContainsValue(supported_software_features, - supported_software_feature)); + EXPECT_TRUE(base::ContainsValue( + supported_software_features, + SoftwareFeatureStringToEnum(supported_software_feature))); } for (auto enabled_software_feature : expected_device.enabled_software_features()) { - EXPECT_TRUE(base::ContainsValue(enabled_software_features, - enabled_software_feature)); + EXPECT_TRUE(base::ContainsValue( + enabled_software_features, + SoftwareFeatureStringToEnum(enabled_software_feature))); } } else { EXPECT_FALSE(expected_device.supported_software_features_size()); @@ -418,14 +421,15 @@ unlock_key.set_arc_plus_plus(kArcPlusPlus1); unlock_key.set_pixel_phone(kPixelPhone1); unlock_key.add_supported_software_features( - SoftwareFeature::EASY_UNLOCK_HOST); - unlock_key.add_enabled_software_features(SoftwareFeature::EASY_UNLOCK_HOST); - unlock_key.add_supported_software_features( - SoftwareFeature::BETTER_TOGETHER_HOST); - unlock_key.add_supported_software_features( - SoftwareFeature::BETTER_TOGETHER_CLIENT); + SoftwareFeatureEnumToString(SoftwareFeature::EASY_UNLOCK_HOST)); unlock_key.add_enabled_software_features( - SoftwareFeature::BETTER_TOGETHER_HOST); + SoftwareFeatureEnumToString(SoftwareFeature::EASY_UNLOCK_HOST)); + unlock_key.add_supported_software_features( + SoftwareFeatureEnumToString(SoftwareFeature::BETTER_TOGETHER_HOST)); + unlock_key.add_supported_software_features( + SoftwareFeatureEnumToString(SoftwareFeature::BETTER_TOGETHER_CLIENT)); + unlock_key.add_enabled_software_features( + SoftwareFeatureEnumToString(SoftwareFeature::BETTER_TOGETHER_HOST)); devices_in_response_.push_back(unlock_key); ExternalDeviceInfo unlockable_device; @@ -443,11 +447,11 @@ unlockable_device.set_arc_plus_plus(kArcPlusPlus2); unlockable_device.set_pixel_phone(kPixelPhone2); unlockable_device.add_supported_software_features( - SoftwareFeature::MAGIC_TETHER_HOST); + SoftwareFeatureEnumToString(SoftwareFeature::MAGIC_TETHER_HOST)); unlockable_device.add_supported_software_features( - SoftwareFeature::MAGIC_TETHER_CLIENT); + SoftwareFeatureEnumToString(SoftwareFeature::MAGIC_TETHER_CLIENT)); unlockable_device.add_enabled_software_features( - SoftwareFeature::MAGIC_TETHER_HOST); + SoftwareFeatureEnumToString(SoftwareFeature::MAGIC_TETHER_HOST)); devices_in_response_.push_back(unlockable_device); } @@ -693,15 +697,16 @@ EXPECT_FALSE(synced_devices[0].mobile_hotspot_supported()); EXPECT_EQ(2, synced_devices[0].supported_software_features().size()); - EXPECT_TRUE( - base::ContainsValue(synced_devices[0].supported_software_features(), - SoftwareFeature::EASY_UNLOCK_HOST)); - EXPECT_TRUE( - base::ContainsValue(synced_devices[0].supported_software_features(), - SoftwareFeature::MAGIC_TETHER_HOST)); + EXPECT_TRUE(base::ContainsValue( + synced_devices[0].supported_software_features(), + SoftwareFeatureEnumToString(SoftwareFeature::EASY_UNLOCK_HOST))); + EXPECT_TRUE(base::ContainsValue( + synced_devices[0].supported_software_features(), + SoftwareFeatureEnumToString(SoftwareFeature::MAGIC_TETHER_HOST))); EXPECT_EQ(1, synced_devices[0].enabled_software_features().size()); - EXPECT_TRUE(base::ContainsValue(synced_devices[0].enabled_software_features(), - SoftwareFeature::EASY_UNLOCK_HOST)); + EXPECT_TRUE(base::ContainsValue( + synced_devices[0].enabled_software_features(), + SoftwareFeatureEnumToString(SoftwareFeature::EASY_UNLOCK_HOST))); } TEST_F(CryptAuthDeviceManagerImplTest, SyncSucceedsForFirstTime) { @@ -876,9 +881,9 @@ synced_device2.set_friendly_device_name("new device name"); synced_device2.set_bluetooth_address("aa:bb:cc:dd:ee:ff"); synced_device2.add_supported_software_features( - SoftwareFeature::EASY_UNLOCK_HOST); + SoftwareFeatureEnumToString(SoftwareFeature::EASY_UNLOCK_HOST)); synced_device2.add_enabled_software_features( - SoftwareFeature::EASY_UNLOCK_HOST); + SoftwareFeatureEnumToString(SoftwareFeature::EASY_UNLOCK_HOST)); response.add_devices()->CopyFrom(synced_device2); @@ -945,9 +950,9 @@ ExternalDeviceInfo device_with_only_public_key; device_with_only_public_key.set_public_key("publicKey1"); device_with_only_public_key.add_supported_software_features( - SoftwareFeature::EASY_UNLOCK_HOST); + SoftwareFeatureEnumToString(SoftwareFeature::EASY_UNLOCK_HOST)); device_with_only_public_key.add_enabled_software_features( - SoftwareFeature::EASY_UNLOCK_HOST); + SoftwareFeatureEnumToString(SoftwareFeature::EASY_UNLOCK_HOST)); // Second, use a device with all fields filled out. This ensures that all // device details are properly saved. @@ -975,12 +980,12 @@ device_with_all_fields.set_pixel_phone(true); device_with_all_fields.add_supported_software_features( - SoftwareFeature::EASY_UNLOCK_HOST); + SoftwareFeatureEnumToString(SoftwareFeature::EASY_UNLOCK_HOST)); device_with_all_fields.add_supported_software_features( - SoftwareFeature::MAGIC_TETHER_HOST); + SoftwareFeatureEnumToString(SoftwareFeature::MAGIC_TETHER_HOST)); device_with_all_fields.add_enabled_software_features( - SoftwareFeature::EASY_UNLOCK_HOST); + SoftwareFeatureEnumToString(SoftwareFeature::EASY_UNLOCK_HOST)); std::vector<ExternalDeviceInfo> expected_devices; expected_devices.push_back(device_with_only_public_key); @@ -1052,14 +1057,18 @@ EXPECT_FALSE(synced_device.unlock_key()); EXPECT_FALSE(synced_device.mobile_hotspot_supported()); - EXPECT_TRUE(base::ContainsValue(synced_device.supported_software_features(), - SoftwareFeature::EASY_UNLOCK_HOST)); - EXPECT_TRUE(base::ContainsValue(synced_device.enabled_software_features(), - SoftwareFeature::EASY_UNLOCK_HOST)); - EXPECT_TRUE(base::ContainsValue(synced_device.supported_software_features(), - SoftwareFeature::MAGIC_TETHER_HOST)); - EXPECT_FALSE(base::ContainsValue(synced_device.enabled_software_features(), - SoftwareFeature::MAGIC_TETHER_HOST)); + EXPECT_TRUE(base::ContainsValue( + synced_device.supported_software_features(), + SoftwareFeatureEnumToString(SoftwareFeature::EASY_UNLOCK_HOST))); + EXPECT_TRUE(base::ContainsValue( + synced_device.enabled_software_features(), + SoftwareFeatureEnumToString(SoftwareFeature::EASY_UNLOCK_HOST))); + EXPECT_TRUE(base::ContainsValue( + synced_device.supported_software_features(), + SoftwareFeatureEnumToString(SoftwareFeature::MAGIC_TETHER_HOST))); + EXPECT_FALSE(base::ContainsValue( + synced_device.enabled_software_features(), + SoftwareFeatureEnumToString(SoftwareFeature::MAGIC_TETHER_HOST))); } TEST_F(CryptAuthDeviceManagerImplTest, @@ -1072,9 +1081,12 @@ device.set_unlock_key(false); device.set_mobile_hotspot_supported(false); - device.add_supported_software_features(SoftwareFeature::EASY_UNLOCK_HOST); - device.add_enabled_software_features(SoftwareFeature::EASY_UNLOCK_HOST); - device.add_supported_software_features(SoftwareFeature::MAGIC_TETHER_HOST); + device.add_supported_software_features( + SoftwareFeatureEnumToString(SoftwareFeature::EASY_UNLOCK_HOST)); + device.add_enabled_software_features( + SoftwareFeatureEnumToString(SoftwareFeature::EASY_UNLOCK_HOST)); + device.add_supported_software_features( + SoftwareFeatureEnumToString(SoftwareFeature::MAGIC_TETHER_HOST)); devices_in_response_.push_back(device); get_my_devices_response_.add_devices()->CopyFrom(device); @@ -1091,14 +1103,18 @@ EXPECT_FALSE(synced_device.unlock_key()); EXPECT_FALSE(synced_device.mobile_hotspot_supported()); - EXPECT_TRUE(base::ContainsValue(synced_device.supported_software_features(), - SoftwareFeature::EASY_UNLOCK_HOST)); - EXPECT_TRUE(base::ContainsValue(synced_device.enabled_software_features(), - SoftwareFeature::EASY_UNLOCK_HOST)); - EXPECT_TRUE(base::ContainsValue(synced_device.supported_software_features(), - SoftwareFeature::MAGIC_TETHER_HOST)); - EXPECT_FALSE(base::ContainsValue(synced_device.enabled_software_features(), - SoftwareFeature::MAGIC_TETHER_HOST)); + EXPECT_TRUE(base::ContainsValue( + synced_device.supported_software_features(), + SoftwareFeatureEnumToString(SoftwareFeature::EASY_UNLOCK_HOST))); + EXPECT_TRUE(base::ContainsValue( + synced_device.enabled_software_features(), + SoftwareFeatureEnumToString(SoftwareFeature::EASY_UNLOCK_HOST))); + EXPECT_TRUE(base::ContainsValue( + synced_device.supported_software_features(), + SoftwareFeatureEnumToString(SoftwareFeature::MAGIC_TETHER_HOST))); + EXPECT_FALSE(base::ContainsValue( + synced_device.enabled_software_features(), + SoftwareFeatureEnumToString(SoftwareFeature::MAGIC_TETHER_HOST))); } } // namespace cryptauth
diff --git a/components/cryptauth/cryptauth_enrollment_manager_impl.cc b/components/cryptauth/cryptauth_enrollment_manager_impl.cc index ea84cc34..aafa12e2 100644 --- a/components/cryptauth/cryptauth_enrollment_manager_impl.cc +++ b/components/cryptauth/cryptauth_enrollment_manager_impl.cc
@@ -15,7 +15,7 @@ #include "chromeos/components/proximity_auth/logging/logging.h" #include "components/cryptauth/cryptauth_enroller.h" #include "components/cryptauth/pref_names.h" -#include "components/cryptauth/proto/enum_string_util.h" +#include "components/cryptauth/proto/enum_util.h" #include "components/cryptauth/secure_message_delegate.h" #include "components/cryptauth/sync_scheduler_impl.h" #include "components/prefs/pref_registry_simple.h"
diff --git a/components/cryptauth/proto/BUILD.gn b/components/cryptauth/proto/BUILD.gn index 58743b4..334639f 100644 --- a/components/cryptauth/proto/BUILD.gn +++ b/components/cryptauth/proto/BUILD.gn
@@ -13,8 +13,8 @@ static_library("util") { sources = [ - "enum_string_util.cc", - "enum_string_util.h", + "enum_util.cc", + "enum_util.h", ] public_deps = [
diff --git a/components/cryptauth/proto/cryptauth_api.proto b/components/cryptauth/proto/cryptauth_api.proto index 1293019..ecda43c 100644 --- a/components/cryptauth/proto/cryptauth_api.proto +++ b/components/cryptauth/proto/cryptauth_api.proto
@@ -25,6 +25,7 @@ optional string device_software_package = 19; // Device type/platform. + // TODO(khorimoto): Change this to a string so it works with Apiary endpoints. optional DeviceType device_type = 32 [default = UNKNOWN]; } @@ -90,6 +91,7 @@ optional bool mobile_hotspot_supported = 7 [ default = false ]; // The type of the device (e.g. Android vs iOS). + // TODO(khorimoto): Change this to a string so it works with Apiary endpoints. optional DeviceType device_type = 8 [ default = UNKNOWN ]; // A list of seeds for EID BLE advertisements targeting this device. @@ -102,11 +104,11 @@ optional bool pixel_phone = 11 [default = false]; // A list of multi-device software features supported by the device. - repeated SoftwareFeature supported_software_features = 12; + repeated string supported_software_features = 12; // A list of multi-device software features currently enabled (active) on the // device. - repeated SoftwareFeature enabled_software_features = 13; + repeated string enabled_software_features = 13; } // Determine if the calling device is allowed to promote the SmartLock @@ -163,7 +165,7 @@ // The feature for which eligibility should be checked. Note that this RPC is // overloaded instead of adding new RPCs due to the ongoing V2 transition. // See go/unified-better-together-cryptauth for more details. - optional SoftwareFeature feature = 8 [default = EASY_UNLOCK_HOST]; + optional string feature = 8 [default = "easyUnlockHost"]; } // Response containing a list of devices that could be made Unlock Keys @@ -290,6 +292,7 @@ optional string device_manufacturer = 31; // Used to indicate which type of device this is. + // TODO(khorimoto): Change this to a string so it works with Apiary endpoints. optional DeviceType device_type = 32 [default = ANDROIDOS]; // Fields corresponding to screenlock type/features and hardware features @@ -606,7 +609,7 @@ // The feature for which enabled state should be toggled. Note that this RPC // is overloaded instead of adding new RPCs due to the ongoing V2 transition. // See go/unified-better-together-cryptauth for more details. - optional SoftwareFeature feature = 5 [default = EASY_UNLOCK_HOST]; + optional string feature = 5 [default = "easyUnlockHost"]; // True if enabling one device for this feature should disable all others on // the account.
diff --git a/components/cryptauth/proto/enum_string_util.cc b/components/cryptauth/proto/enum_string_util.cc deleted file mode 100644 index 73ba603..0000000 --- a/components/cryptauth/proto/enum_string_util.cc +++ /dev/null
@@ -1,43 +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 "components/cryptauth/proto/enum_string_util.h" - -namespace cryptauth { - -std::ostream& operator<<(std::ostream& stream, - const SoftwareFeature& software_feature) { - switch (software_feature) { - case SoftwareFeature::BETTER_TOGETHER_HOST: - stream << "[Better Together host]"; - break; - case SoftwareFeature::BETTER_TOGETHER_CLIENT: - stream << "[Better Together client]"; - break; - case SoftwareFeature::EASY_UNLOCK_HOST: - stream << "[EasyUnlock host]"; - break; - case SoftwareFeature::EASY_UNLOCK_CLIENT: - stream << "[EasyUnlock client]"; - break; - case SoftwareFeature::MAGIC_TETHER_HOST: - stream << "[Instant Tethering host]"; - break; - case SoftwareFeature::MAGIC_TETHER_CLIENT: - stream << "[Instant Tethering client]"; - break; - case SoftwareFeature::SMS_CONNECT_HOST: - stream << "[SMS Connect host]"; - break; - case SoftwareFeature::SMS_CONNECT_CLIENT: - stream << "[SMS Connect client]"; - break; - default: - stream << "[unknown software feature]"; - break; - } - return stream; -} - -} // namespace cryptauth
diff --git a/components/cryptauth/proto/enum_string_util.h b/components/cryptauth/proto/enum_string_util.h deleted file mode 100644 index 6bb0fc9..0000000 --- a/components/cryptauth/proto/enum_string_util.h +++ /dev/null
@@ -1,19 +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 COMPONENTS_CRYPTAUTH_PROTO_ENUM_STRING_UTIL_H_ -#define COMPONENTS_CRYPTAUTH_PROTO_ENUM_STRING_UTIL_H_ - -#include <ostream> - -#include "components/cryptauth/proto/cryptauth_api.pb.h" - -namespace cryptauth { - -std::ostream& operator<<(std::ostream& stream, - const SoftwareFeature& software_fature); - -} // namespace cryptauth - -#endif // COMPONENTS_CRYPTAUTH_PROTO_ENUM_STRING_UTIL_H_
diff --git a/components/cryptauth/proto/enum_util.cc b/components/cryptauth/proto/enum_util.cc new file mode 100644 index 0000000..c2ffdb56 --- /dev/null +++ b/components/cryptauth/proto/enum_util.cc
@@ -0,0 +1,89 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/cryptauth/proto/enum_util.h" + +namespace cryptauth { + +std::ostream& operator<<(std::ostream& stream, + const SoftwareFeature& software_feature) { + switch (software_feature) { + case SoftwareFeature::BETTER_TOGETHER_HOST: + stream << "[Better Together host]"; + break; + case SoftwareFeature::BETTER_TOGETHER_CLIENT: + stream << "[Better Together client]"; + break; + case SoftwareFeature::EASY_UNLOCK_HOST: + stream << "[EasyUnlock host]"; + break; + case SoftwareFeature::EASY_UNLOCK_CLIENT: + stream << "[EasyUnlock client]"; + break; + case SoftwareFeature::MAGIC_TETHER_HOST: + stream << "[Instant Tethering host]"; + break; + case SoftwareFeature::MAGIC_TETHER_CLIENT: + stream << "[Instant Tethering client]"; + break; + case SoftwareFeature::SMS_CONNECT_HOST: + stream << "[SMS Connect host]"; + break; + case SoftwareFeature::SMS_CONNECT_CLIENT: + stream << "[SMS Connect client]"; + break; + default: + stream << "[unknown software feature]"; + break; + } + return stream; +} + +cryptauth::SoftwareFeature SoftwareFeatureStringToEnum( + const std::string& software_feature_as_string) { + if (software_feature_as_string == "betterTogetherHost") + return cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST; + if (software_feature_as_string == "betterTogetherClient") + return cryptauth::SoftwareFeature::BETTER_TOGETHER_CLIENT; + if (software_feature_as_string == "easyUnlockHost") + return cryptauth::SoftwareFeature::EASY_UNLOCK_HOST; + if (software_feature_as_string == "easyUnlockClient") + return cryptauth::SoftwareFeature::EASY_UNLOCK_CLIENT; + if (software_feature_as_string == "magicTetherHost") + return cryptauth::SoftwareFeature::MAGIC_TETHER_HOST; + if (software_feature_as_string == "magicTetherClient") + return cryptauth::SoftwareFeature::MAGIC_TETHER_CLIENT; + if (software_feature_as_string == "smsConnectHost") + return cryptauth::SoftwareFeature::SMS_CONNECT_HOST; + if (software_feature_as_string == "smsConnectClient") + return cryptauth::SoftwareFeature::SMS_CONNECT_CLIENT; + + return cryptauth::SoftwareFeature::UNKNOWN_FEATURE; +} + +std::string SoftwareFeatureEnumToString( + cryptauth::SoftwareFeature software_feature) { + switch (software_feature) { + case SoftwareFeature::BETTER_TOGETHER_HOST: + return "betterTogetherHost"; + case SoftwareFeature::BETTER_TOGETHER_CLIENT: + return "betterTogetherClient"; + case SoftwareFeature::EASY_UNLOCK_HOST: + return "easyUnlockHost"; + case SoftwareFeature::EASY_UNLOCK_CLIENT: + return "easyUnlockClient"; + case SoftwareFeature::MAGIC_TETHER_HOST: + return "magicTetherHost"; + case SoftwareFeature::MAGIC_TETHER_CLIENT: + return "magicTetherClient"; + case SoftwareFeature::SMS_CONNECT_HOST: + return "smsConnectHost"; + case SoftwareFeature::SMS_CONNECT_CLIENT: + return "smsConnectClient"; + default: + return "unknownFeature"; + } +} + +} // namespace cryptauth
diff --git a/components/cryptauth/proto/enum_util.h b/components/cryptauth/proto/enum_util.h new file mode 100644 index 0000000..3873f49 --- /dev/null +++ b/components/cryptauth/proto/enum_util.h
@@ -0,0 +1,35 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_CRYPTAUTH_PROTO_ENUM_UTIL_H_ +#define COMPONENTS_CRYPTAUTH_PROTO_ENUM_UTIL_H_ + +#include <ostream> + +#include "components/cryptauth/proto/cryptauth_api.pb.h" + +namespace cryptauth { + +std::ostream& operator<<(std::ostream& stream, + const SoftwareFeature& software_fature); + +// Converts the string representation of a SoftwareFeature to its associated +// Proto enum value. Some Proto messages are sent to Apiary endpoints, which +// translate Proto enums to strings instead of leaving them as enums. Thus, when +// communicating with those endpoints, the proto values should be converted from +// enums to strings before sending them. +cryptauth::SoftwareFeature SoftwareFeatureStringToEnum( + const std::string& software_feature_as_string); + +// Converts a Proto enum SoftwareFeature to its associated string +// representation. Some Proto messages are sent to Apiary endpoints, which +// translate Proto enums to strings instead of leaving them as enums. Thus, when +// communicating with those endpoints, the proto values should be converted from +// strings to enums after receiving them. +std::string SoftwareFeatureEnumToString( + cryptauth::SoftwareFeature software_feature); + +} // namespace cryptauth + +#endif // COMPONENTS_CRYPTAUTH_PROTO_ENUM_UTIL_H_
diff --git a/components/cryptauth/remote_device_loader.cc b/components/cryptauth/remote_device_loader.cc index 87fbe38..d55ad601 100644 --- a/components/cryptauth/remote_device_loader.cc +++ b/components/cryptauth/remote_device_loader.cc
@@ -11,10 +11,13 @@ #include "base/bind.h" #include "base/memory/ptr_util.h" #include "chromeos/components/proximity_auth/logging/logging.h" +#include "components/cryptauth/proto/enum_util.h" #include "components/cryptauth/remote_device.h" #include "components/cryptauth/remote_device_ref.h" #include "components/cryptauth/secure_message_delegate.h" +namespace cryptauth { + namespace { std::map<cryptauth::SoftwareFeature, cryptauth::SoftwareFeatureState> @@ -23,12 +26,14 @@ software_feature_to_state_map; for (int i = 0; i < device.supported_software_features_size(); ++i) { - software_feature_to_state_map[device.supported_software_features(i)] = + software_feature_to_state_map[SoftwareFeatureStringToEnum( + device.supported_software_features(i))] = cryptauth::SoftwareFeatureState::kSupported; } for (int i = 0; i < device.enabled_software_features_size(); ++i) { - software_feature_to_state_map[device.enabled_software_features(i)] = + software_feature_to_state_map[SoftwareFeatureStringToEnum( + device.enabled_software_features(i))] = cryptauth::SoftwareFeatureState::kEnabled; } @@ -37,8 +42,6 @@ } // namespace -namespace cryptauth { - // static RemoteDeviceLoader::Factory* RemoteDeviceLoader::Factory::factory_instance_ = nullptr;
diff --git a/components/cryptauth/remote_device_loader_unittest.cc b/components/cryptauth/remote_device_loader_unittest.cc index 5750456..00eb852 100644 --- a/components/cryptauth/remote_device_loader_unittest.cc +++ b/components/cryptauth/remote_device_loader_unittest.cc
@@ -12,6 +12,7 @@ #include "base/bind.h" #include "base/macros.h" #include "components/cryptauth/fake_secure_message_delegate.h" +#include "components/cryptauth/proto/enum_util.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -148,10 +149,14 @@ BETTER_TOGETHER_HOST}; cryptauth::ExternalDeviceInfo first = CreateDeviceInfo("0"); - for (const auto& software_feature : kSupportedSoftwareFeatures) - first.add_supported_software_features(software_feature); - for (const auto& software_feature : kEnabledSoftwareFeatures) - first.add_enabled_software_features(software_feature); + for (const auto& software_feature : kSupportedSoftwareFeatures) { + first.add_supported_software_features( + SoftwareFeatureEnumToString(software_feature)); + } + for (const auto& software_feature : kEnabledSoftwareFeatures) { + first.add_enabled_software_features( + SoftwareFeatureEnumToString(software_feature)); + } std::vector<cryptauth::ExternalDeviceInfo> device_infos{first};
diff --git a/components/cryptauth/software_feature_manager_impl.cc b/components/cryptauth/software_feature_manager_impl.cc index 95437005..9030187 100644 --- a/components/cryptauth/software_feature_manager_impl.cc +++ b/components/cryptauth/software_feature_manager_impl.cc
@@ -10,6 +10,7 @@ #include "base/memory/ptr_util.h" #include "base/no_destructor.h" #include "components/cryptauth/proto/cryptauth_api.pb.h" +#include "components/cryptauth/proto/enum_util.h" namespace cryptauth { @@ -79,7 +80,8 @@ // Note: For legacy reasons, this proto message mentions "ToggleEasyUnlock" // instead of "SetSoftwareFeature" in its name. auto request = std::make_unique<ToggleEasyUnlockRequest>(); - request->set_feature(software_feature); + request->set_feature( + cryptauth::SoftwareFeatureEnumToString(software_feature)); request->set_enable(enabled); request->set_is_exclusive(enabled && is_exclusive); @@ -105,7 +107,8 @@ // Note: For legacy reasons, this proto message mentions "UnlockDevices" // instead of "MultiDeviceHosts" in its name. auto request = std::make_unique<FindEligibleUnlockDevicesRequest>(); - request->set_feature(software_feature); + request->set_feature( + cryptauth::SoftwareFeatureEnumToString(software_feature)); pending_requests_.emplace(std::make_unique<Request>( std::move(request), success_callback, error_callback));
diff --git a/components/cryptauth/software_feature_manager_impl_unittest.cc b/components/cryptauth/software_feature_manager_impl_unittest.cc index 34f3d061..975e60b5 100644 --- a/components/cryptauth/software_feature_manager_impl_unittest.cc +++ b/components/cryptauth/software_feature_manager_impl_unittest.cc
@@ -7,6 +7,7 @@ #include "base/bind.h" #include "base/macros.h" #include "components/cryptauth/mock_cryptauth_client.h" +#include "components/cryptauth/proto/enum_util.h" #include "components/cryptauth/remote_device_ref.h" #include "components/cryptauth/remote_device_test_util.h" #include "testing/gmock/include/gmock/gmock.h" @@ -263,28 +264,30 @@ false /* enable */); FindEligibleDevices(SoftwareFeature::BETTER_TOGETHER_CLIENT); - EXPECT_EQ(SoftwareFeature::BETTER_TOGETHER_HOST, + EXPECT_EQ(SoftwareFeatureEnumToString(SoftwareFeature::BETTER_TOGETHER_HOST), last_toggle_request_.feature()); EXPECT_EQ(true, last_toggle_request_.enable()); EXPECT_EQ(false, last_toggle_request_.is_exclusive()); InvokeSetSoftwareFeatureCallback(); EXPECT_EQ(Result::kSuccess, GetResultAndReset()); - EXPECT_EQ(SoftwareFeature::BETTER_TOGETHER_HOST, + EXPECT_EQ(SoftwareFeatureEnumToString(SoftwareFeature::BETTER_TOGETHER_HOST), last_find_request_.feature()); InvokeFindEligibleDevicesCallback(CreateFindEligibleUnlockDevicesResponse()); EXPECT_EQ(Result::kSuccess, GetResultAndReset()); VerifyDeviceEligibility(); - EXPECT_EQ(SoftwareFeature::BETTER_TOGETHER_CLIENT, - last_toggle_request_.feature()); + EXPECT_EQ( + SoftwareFeatureEnumToString(SoftwareFeature::BETTER_TOGETHER_CLIENT), + last_toggle_request_.feature()); EXPECT_EQ(false, last_toggle_request_.enable()); EXPECT_EQ(false, last_toggle_request_.is_exclusive()); InvokeSetSoftwareFeatureCallback(); EXPECT_EQ(Result::kSuccess, GetResultAndReset()); - EXPECT_EQ(SoftwareFeature::BETTER_TOGETHER_CLIENT, - last_find_request_.feature()); + EXPECT_EQ( + SoftwareFeatureEnumToString(SoftwareFeature::BETTER_TOGETHER_CLIENT), + last_find_request_.feature()); InvokeFindEligibleDevicesCallback(CreateFindEligibleUnlockDevicesResponse()); EXPECT_EQ(Result::kSuccess, GetResultAndReset()); VerifyDeviceEligibility(); @@ -302,21 +305,22 @@ test_eligible_external_devices_infos_[2], true /* enable */); - EXPECT_EQ(SoftwareFeature::BETTER_TOGETHER_HOST, + EXPECT_EQ(SoftwareFeatureEnumToString(SoftwareFeature::BETTER_TOGETHER_HOST), last_toggle_request_.feature()); EXPECT_EQ(true, last_toggle_request_.enable()); EXPECT_EQ(false, last_toggle_request_.is_exclusive()); InvokeErrorCallback(); EXPECT_EQ(Result::kErrorSettingFeature, GetResultAndReset()); - EXPECT_EQ(SoftwareFeature::BETTER_TOGETHER_CLIENT, - last_toggle_request_.feature()); + EXPECT_EQ( + SoftwareFeatureEnumToString(SoftwareFeature::BETTER_TOGETHER_CLIENT), + last_toggle_request_.feature()); EXPECT_EQ(false, last_toggle_request_.enable()); EXPECT_EQ(false, last_toggle_request_.is_exclusive()); InvokeSetSoftwareFeatureCallback(); EXPECT_EQ(Result::kSuccess, GetResultAndReset()); - EXPECT_EQ(SoftwareFeature::BETTER_TOGETHER_HOST, + EXPECT_EQ(SoftwareFeatureEnumToString(SoftwareFeature::BETTER_TOGETHER_HOST), last_toggle_request_.feature()); EXPECT_EQ(true, last_toggle_request_.enable()); EXPECT_EQ(false, last_toggle_request_.is_exclusive()); @@ -330,18 +334,19 @@ FindEligibleDevices(SoftwareFeature::BETTER_TOGETHER_CLIENT); FindEligibleDevices(SoftwareFeature::BETTER_TOGETHER_HOST); - EXPECT_EQ(SoftwareFeature::BETTER_TOGETHER_HOST, + EXPECT_EQ(SoftwareFeatureEnumToString(SoftwareFeature::BETTER_TOGETHER_HOST), last_find_request_.feature()); InvokeFindEligibleDevicesCallback(CreateFindEligibleUnlockDevicesResponse()); EXPECT_EQ(Result::kSuccess, GetResultAndReset()); VerifyDeviceEligibility(); - EXPECT_EQ(SoftwareFeature::BETTER_TOGETHER_CLIENT, - last_find_request_.feature()); + EXPECT_EQ( + SoftwareFeatureEnumToString(SoftwareFeature::BETTER_TOGETHER_CLIENT), + last_find_request_.feature()); InvokeErrorCallback(); EXPECT_EQ(Result::kErrorFindingEligible, GetResultAndReset()); - EXPECT_EQ(SoftwareFeature::BETTER_TOGETHER_HOST, + EXPECT_EQ(SoftwareFeatureEnumToString(SoftwareFeature::BETTER_TOGETHER_HOST), last_find_request_.feature()); InvokeFindEligibleDevicesCallback(CreateFindEligibleUnlockDevicesResponse()); EXPECT_EQ(Result::kSuccess, GetResultAndReset()); @@ -354,12 +359,12 @@ true /* enable */); FindEligibleDevices(SoftwareFeature::BETTER_TOGETHER_HOST); - EXPECT_EQ(SoftwareFeature::BETTER_TOGETHER_HOST, + EXPECT_EQ(SoftwareFeatureEnumToString(SoftwareFeature::BETTER_TOGETHER_HOST), last_toggle_request_.feature()); InvokeErrorCallback(); EXPECT_EQ(Result::kErrorSettingFeature, GetResultAndReset()); - EXPECT_EQ(SoftwareFeature::BETTER_TOGETHER_HOST, + EXPECT_EQ(SoftwareFeatureEnumToString(SoftwareFeature::BETTER_TOGETHER_HOST), last_find_request_.feature()); InvokeErrorCallback(); EXPECT_EQ(Result::kErrorFindingEligible, GetResultAndReset()); @@ -370,7 +375,7 @@ test_eligible_external_devices_infos_[0], true /* enable */, true /* is_exclusive */); - EXPECT_EQ(SoftwareFeature::BETTER_TOGETHER_HOST, + EXPECT_EQ(SoftwareFeatureEnumToString(SoftwareFeature::BETTER_TOGETHER_HOST), last_toggle_request_.feature()); EXPECT_EQ(true, last_toggle_request_.enable()); EXPECT_EQ(true, last_toggle_request_.is_exclusive()); @@ -383,7 +388,8 @@ test_eligible_external_devices_infos_[0], false /* enable */); - EXPECT_EQ(SoftwareFeature::EASY_UNLOCK_HOST, last_toggle_request_.feature()); + EXPECT_EQ(SoftwareFeatureEnumToString(SoftwareFeature::EASY_UNLOCK_HOST), + last_toggle_request_.feature()); EXPECT_EQ(false, last_toggle_request_.enable()); // apply_to_all() should be false when disabling EasyUnlock host capabilities. EXPECT_EQ(true, last_toggle_request_.apply_to_all());
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.cc index febc0e1..7272010a 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.cc
@@ -469,6 +469,8 @@ weak_factory_.GetWeakPtr())); } + InitializeWeeklyAggregateDataUse(base::Time::Now()); + if (delay_.is_zero()) return; @@ -517,8 +519,6 @@ InitListPref(prefs::kDailyHttpReceivedContentLength); InitListPref(prefs::kDailyOriginalContentLengthViaDataReductionProxy); InitListPref(prefs::kDailyOriginalContentLengthWithDataReductionProxyEnabled); - - InitializeWeeklyAggregateDataUse(base::Time::Now()); } void DataReductionProxyCompressionStats::RecordDataUseWithMimeType(
diff --git a/components/exo/BUILD.gn b/components/exo/BUILD.gn index 6e4c020..755fe0e 100644 --- a/components/exo/BUILD.gn +++ b/components/exo/BUILD.gn
@@ -60,6 +60,8 @@ "surface_observer.h", "surface_tree_host.cc", "surface_tree_host.h", + "text_input.cc", + "text_input.h", "touch.cc", "touch.h", "touch_delegate.h", @@ -81,6 +83,7 @@ "//services/ui/public/interfaces", "//skia", "//ui/aura", + "//ui/base/ime", "//ui/compositor", "//ui/compositor_extra", "//ui/display/manager", @@ -89,6 +92,7 @@ "//ui/gfx", "//ui/gfx/geometry", "//ui/gl", + "//ui/keyboard", "//ui/ozone", "//ui/views", "//ui/views/mus", @@ -148,6 +152,7 @@ "shell_surface_unittest.cc", "sub_surface_unittest.cc", "surface_unittest.cc", + "text_input_unittest.cc", "touch_unittest.cc", ]
diff --git a/components/exo/text_input.cc b/components/exo/text_input.cc new file mode 100644 index 0000000..6fecb7b --- /dev/null +++ b/components/exo/text_input.cc
@@ -0,0 +1,282 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/exo/text_input.h" + +#include "components/exo/surface.h" +#include "components/exo/wm_helper.h" +#include "third_party/icu/source/common/unicode/uchar.h" +#include "ui/aura/window.h" +#include "ui/aura/window_tree_host.h" +#include "ui/base/ime/input_method.h" +#include "ui/events/event.h" +#include "ui/keyboard/keyboard_controller.h" + +namespace exo { + +namespace { + +ui::InputMethod* GetInputMethod(aura::Window* window) { + if (!window || !window->GetHost()) + return nullptr; + return window->GetHost()->GetInputMethod(); +} + +} // namespace + +TextInput::TextInput(std::unique_ptr<Delegate> delegate) + : delegate_(std::move(delegate)) {} + +TextInput::~TextInput() { + if (keyboard_controller_) + keyboard_controller_->RemoveObserver(this); + if (input_method_) + Deactivate(); +} + +void TextInput::Activate(Surface* surface) { + DLOG_IF(ERROR, window_) << "Already activated with " << window_; + DCHECK(surface); + + window_ = surface->window(); + AttachInputMethod(); +} + +void TextInput::Deactivate() { + DetachInputMethod(); + window_ = nullptr; +} + +void TextInput::ShowVirtualKeyboardIfEnabled() { + // Some clients may ask showing virtual keyboard before sending activation. + if (!input_method_) { + pending_vk_visible_ = true; + return; + } + input_method_->ShowVirtualKeyboardIfEnabled(); +} + +void TextInput::HideVirtualKeyboard() { + if (keyboard_controller_) + keyboard_controller_->HideKeyboardByUser(); + pending_vk_visible_ = false; +} + +void TextInput::Resync() { + if (input_method_) + input_method_->OnCaretBoundsChanged(this); +} + +void TextInput::SetSurroundingText(const base::string16& text, + uint32_t cursor_pos) { + NOTIMPLEMENTED(); +} + +void TextInput::SetTypeModeFlags(ui::TextInputType type, + ui::TextInputMode mode, + int flags, + bool should_do_learning) { + if (!input_method_) + return; + bool changed = (input_type_ != type); + input_type_ = type; + input_mode_ = mode; + flags_ = flags; + should_do_learning_ = should_do_learning; + if (changed) + input_method_->OnTextInputTypeChanged(this); +} + +void TextInput::SetCaretBounds(const gfx::Rect& bounds) { + if (caret_bounds_ == bounds) + return; + caret_bounds_ = bounds; + if (!input_method_) + return; + input_method_->OnCaretBoundsChanged(this); +} + +void TextInput::SetCompositionText(const ui::CompositionText& composition) { + composition_ = composition; + delegate_->SetCompositionText(composition); +} + +void TextInput::ConfirmCompositionText() { + delegate_->Commit(composition_.text); +} + +void TextInput::ClearCompositionText() { + composition_ = ui::CompositionText(); + delegate_->SetCompositionText(composition_); +} + +void TextInput::InsertText(const base::string16& text) { + delegate_->Commit(text); +} + +void TextInput::InsertChar(const ui::KeyEvent& event) { + base::char16 ch = event.GetCharacter(); + if (u_isprint(ch)) { + InsertText(base::string16(1, ch)); + return; + } + delegate_->SendKey(event); +} + +ui::TextInputType TextInput::GetTextInputType() const { + return input_type_; +} + +ui::TextInputMode TextInput::GetTextInputMode() const { + return input_mode_; +} + +base::i18n::TextDirection TextInput::GetTextDirection() const { + return direction_; +} + +int TextInput::GetTextInputFlags() const { + return flags_; +} + +bool TextInput::CanComposeInline() const { + return true; +} + +gfx::Rect TextInput::GetCaretBounds() const { + return caret_bounds_ + window_->GetBoundsInScreen().OffsetFromOrigin(); +} + +bool TextInput::GetCompositionCharacterBounds(uint32_t index, + gfx::Rect* rect) const { + return false; +} + +bool TextInput::HasCompositionText() const { + return !composition_.text.empty(); +} + +ui::TextInputClient::FocusReason TextInput::GetFocusReason() const { + NOTIMPLEMENTED_LOG_ONCE(); + return ui::TextInputClient::FOCUS_REASON_OTHER; +} + +bool TextInput::GetTextRange(gfx::Range* range) const { + NOTIMPLEMENTED_LOG_ONCE(); + return false; +} + +bool TextInput::GetCompositionTextRange(gfx::Range* range) const { + NOTIMPLEMENTED_LOG_ONCE(); + return false; +} + +bool TextInput::GetSelectionRange(gfx::Range* range) const { + NOTIMPLEMENTED_LOG_ONCE(); + return false; +} + +bool TextInput::SetSelectionRange(const gfx::Range& range) { + NOTIMPLEMENTED_LOG_ONCE(); + return false; +} + +bool TextInput::DeleteRange(const gfx::Range& range) { + // TODO(mukai): call delegate_->DeleteSurroundingText(range) once it's + // supported. + NOTIMPLEMENTED_LOG_ONCE(); + return false; +} + +bool TextInput::GetTextFromRange(const gfx::Range& range, + base::string16* text) const { + // TODO(mukai): support of surrounding text. + NOTIMPLEMENTED_LOG_ONCE(); + return false; +} + +void TextInput::OnInputMethodChanged() { + ui::InputMethod* input_method = GetInputMethod(window_); + if (input_method == input_method_) + return; + input_method_->DetachTextInputClient(this); + input_method_ = input_method; + input_method_->SetFocusedTextInputClient(this); +} + +bool TextInput::ChangeTextDirectionAndLayoutAlignment( + base::i18n::TextDirection direction) { + if (direction == direction_) + return true; + direction_ = direction; + delegate_->OnTextDirectionChanged(direction_); + return true; +} + +void TextInput::ExtendSelectionAndDelete(size_t before, size_t after) {} + +void TextInput::EnsureCaretNotInRect(const gfx::Rect& rect) {} + +bool TextInput::IsTextEditCommandEnabled(ui::TextEditCommand command) const { + return false; +} + +void TextInput::SetTextEditCommandForNextKeyEvent(ui::TextEditCommand command) { +} + +ukm::SourceId TextInput::GetClientSourceForMetrics() const { + NOTIMPLEMENTED_LOG_ONCE(); + return ukm::kInvalidSourceId; +} + +bool TextInput::ShouldDoLearning() { + return should_do_learning_; +} + +void TextInput::OnKeyboardVisibilityStateChanged(bool is_visible) { + delegate_->OnVirtualKeyboardVisibilityChanged(is_visible); +} + +void TextInput::AttachInputMethod() { + DCHECK(!input_method_); + + ui::InputMethod* input_method = GetInputMethod(window_); + if (!input_method) { + LOG(ERROR) << "input method not found"; + return; + } + + input_mode_ = ui::TEXT_INPUT_MODE_TEXT; + input_type_ = ui::TEXT_INPUT_TYPE_TEXT; + input_method_ = input_method; + input_method_->SetFocusedTextInputClient(this); + delegate_->Activated(); + + if (!keyboard_controller_ && keyboard::KeyboardController::HasInstance()) { + auto* keyboard_controller = keyboard::KeyboardController::Get(); + if (keyboard_controller->enabled()) { + keyboard_controller_ = keyboard_controller; + keyboard_controller_->AddObserver(this); + } + } + + if (pending_vk_visible_) { + input_method_->ShowVirtualKeyboardIfEnabled(); + pending_vk_visible_ = false; + } +} + +void TextInput::DetachInputMethod() { + if (!input_method_) { + DLOG(ERROR) << "input method already detached"; + return; + } + input_mode_ = ui::TEXT_INPUT_MODE_DEFAULT; + input_type_ = ui::TEXT_INPUT_TYPE_NONE; + input_method_->DetachTextInputClient(this); + input_method_ = nullptr; + delegate_->Deactivated(); +} + +} // namespace exo
diff --git a/components/exo/text_input.h b/components/exo/text_input.h new file mode 100644 index 0000000..96c6f444 --- /dev/null +++ b/components/exo/text_input.h
@@ -0,0 +1,158 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_EXO_TEXT_INPUT_H_ +#define COMPONENTS_EXO_TEXT_INPUT_H_ + +#include "ui/base/ime/text_input_client.h" +#include "ui/base/ime/text_input_flags.h" +#include "ui/base/ime/text_input_mode.h" +#include "ui/base/ime/text_input_type.h" +#include "ui/gfx/geometry/rect.h" +#include "ui/keyboard/keyboard_controller_observer.h" + +namespace ui { +class InputMethod; +} + +namespace keyboard { +class KeyboardController; +} + +namespace exo { +class Surface; + +// This class bridges the ChromeOS input method and a text-input context. +class TextInput : public ui::TextInputClient, + public keyboard::KeyboardControllerObserver { + public: + class Delegate { + public: + virtual ~Delegate() = default; + + // Called when the text input session is activated. + virtual void Activated() = 0; + + // Called when the text input session is deactivated. TextInput does not + // refer to the delegate anymore. + virtual void Deactivated() = 0; + + // Called when the virtual keyboard visibility state has changed. + virtual void OnVirtualKeyboardVisibilityChanged(bool is_visible) = 0; + + // Set the 'composition text' of the current text input. + virtual void SetCompositionText(const ui::CompositionText& composition) = 0; + + // Commit |text| to the current text input session. + virtual void Commit(const base::string16& text) = 0; + + // Set the cursor position. + virtual void SetCursor(const gfx::Range& selection) = 0; + + // Delete the surrounding text of the current text input. + virtual void DeleteSurroundingText(const gfx::Range& range) = 0; + + // Sends a key event. + virtual void SendKey(const ui::KeyEvent& event) = 0; + + // Called when the text direction has changed. + virtual void OnTextDirectionChanged( + base::i18n::TextDirection direction) = 0; + }; + + TextInput(std::unique_ptr<Delegate> delegate); + ~TextInput() override; + + // Activates the text input context on the surface. Note that surface can be + // an app surface (hosted by a shell surface) or can be an independent one + // created by the text-input client. + void Activate(Surface* surface); + + // Deactivates the text input context. + void Deactivate(); + + // Shows the virtual keyboard if needed. + void ShowVirtualKeyboardIfEnabled(); + + // Hides the virtual keyboard. + void HideVirtualKeyboard(); + + // Re-synchronize the current status when the surrounding text has changed + // during the text input session. + void Resync(); + + // Sets the surrounding text in the app. + void SetSurroundingText(const base::string16& text, uint32_t cursor_pos); + + // Sets the text input type, mode, flags, and |should_do_learning|. + void SetTypeModeFlags(ui::TextInputType type, + ui::TextInputMode mode, + int flags, + bool should_do_learning); + + // Sets the bounds of the text caret, relative to the window origin. + void SetCaretBounds(const gfx::Rect& bounds); + + Delegate* delegate() { return delegate_.get(); } + + // ui::TextInputClient: + void SetCompositionText(const ui::CompositionText& composition) override; + void ConfirmCompositionText() override; + void ClearCompositionText() override; + void InsertText(const base::string16& text) override; + void InsertChar(const ui::KeyEvent& event) override; + ui::TextInputType GetTextInputType() const override; + ui::TextInputMode GetTextInputMode() const override; + base::i18n::TextDirection GetTextDirection() const override; + int GetTextInputFlags() const override; + bool CanComposeInline() const override; + gfx::Rect GetCaretBounds() const override; + bool GetCompositionCharacterBounds(uint32_t index, + gfx::Rect* rect) const override; + bool HasCompositionText() const override; + ui::TextInputClient::FocusReason GetFocusReason() const override; + bool GetTextRange(gfx::Range* range) const override; + bool GetCompositionTextRange(gfx::Range* range) const override; + bool GetSelectionRange(gfx::Range* range) const override; + bool SetSelectionRange(const gfx::Range& range) override; + bool DeleteRange(const gfx::Range& range) override; + bool GetTextFromRange(const gfx::Range& range, + base::string16* text) const override; + void OnInputMethodChanged() override; + bool ChangeTextDirectionAndLayoutAlignment( + base::i18n::TextDirection direction) override; + void ExtendSelectionAndDelete(size_t before, size_t after) override; + void EnsureCaretNotInRect(const gfx::Rect& rect) override; + bool IsTextEditCommandEnabled(ui::TextEditCommand command) const override; + void SetTextEditCommandForNextKeyEvent(ui::TextEditCommand command) override; + ukm::SourceId GetClientSourceForMetrics() const override; + bool ShouldDoLearning() override; + + // keyboard::KeyboardControllerObserver: + void OnKeyboardVisibilityStateChanged(bool is_visible) override; + + private: + void AttachInputMethod(); + void DetachInputMethod(); + + std::unique_ptr<Delegate> delegate_; + keyboard::KeyboardController* keyboard_controller_ = nullptr; + + bool pending_vk_visible_ = false; + aura::Window* window_ = nullptr; + ui::InputMethod* input_method_ = nullptr; + gfx::Rect caret_bounds_; + ui::TextInputType input_type_ = ui::TEXT_INPUT_TYPE_NONE; + ui::TextInputMode input_mode_ = ui::TEXT_INPUT_MODE_DEFAULT; + int flags_ = ui::TEXT_INPUT_FLAG_NONE; + bool should_do_learning_ = true; + ui::CompositionText composition_; + base::i18n::TextDirection direction_ = base::i18n::UNKNOWN_DIRECTION; + + DISALLOW_COPY_AND_ASSIGN(TextInput); +}; + +} // namespace exo + +#endif // COMPONENTS_EXO_KEYBOARD_H_
diff --git a/components/exo/text_input_unittest.cc b/components/exo/text_input_unittest.cc new file mode 100644 index 0000000..a83ff8f --- /dev/null +++ b/components/exo/text_input_unittest.cc
@@ -0,0 +1,280 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/exo/text_input.h" + +#include "base/strings/utf_string_conversions.h" +#include "components/exo/buffer.h" +#include "components/exo/shell_surface.h" +#include "components/exo/surface.h" +#include "components/exo/test/exo_test_base.h" +#include "components/exo/test/exo_test_helper.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "ui/aura/window_tree_host.h" +#include "ui/base/ime/composition_text.h" +#include "ui/base/ime/input_method_factory.h" +#include "ui/base/ime/input_method_observer.h" +#include "ui/views/widget/widget.h" + +using testing::_; + +namespace exo { + +namespace { + +class MockTextInputDelegate : public TextInput::Delegate { + public: + MockTextInputDelegate() = default; + + // TextInput::Delegate: + MOCK_METHOD0(Activated, void()); + MOCK_METHOD0(Deactivated, void()); + MOCK_METHOD1(OnVirtualKeyboardVisibilityChanged, void(bool)); + MOCK_METHOD1(SetCompositionText, void(const ui::CompositionText&)); + MOCK_METHOD1(Commit, void(const base::string16&)); + MOCK_METHOD1(SetCursor, void(const gfx::Range&)); + MOCK_METHOD1(DeleteSurroundingText, void(const gfx::Range&)); + MOCK_METHOD1(SendKey, void(const ui::KeyEvent&)); + MOCK_METHOD1(OnLanguageChanged, void(const std::string&)); + MOCK_METHOD1(OnTextDirectionChanged, + void(base::i18n::TextDirection direction)); + + private: + DISALLOW_COPY_AND_ASSIGN(MockTextInputDelegate); +}; + +class TestingInputMethodObserver : public ui::InputMethodObserver { + public: + TestingInputMethodObserver(ui::InputMethod* input_method) + : input_method_(input_method) { + input_method_->AddObserver(this); + } + + ~TestingInputMethodObserver() override { + input_method_->RemoveObserver(this); + } + + // ui::InputMethodObserver + MOCK_METHOD0(OnFocus, void()); + MOCK_METHOD0(OnBlur, void()); + MOCK_METHOD1(OnCaretBoundsChanged, void(const ui::TextInputClient*)); + MOCK_METHOD1(OnTextInputStateChanged, void(const ui::TextInputClient*)); + MOCK_METHOD1(OnInputMethodDestroyed, void(const ui::InputMethod*)); + MOCK_METHOD0(OnShowVirtualKeyboardIfEnabled, void()); + + private: + ui::InputMethod* input_method_ = nullptr; + + DISALLOW_COPY_AND_ASSIGN(TestingInputMethodObserver); +}; + +class TextInputTest : public test::ExoTestBase { + public: + TextInputTest() = default; + + void SetUp() override { + ui::SetUpInputMethodFactoryForTesting(); + test::ExoTestBase::SetUp(); + text_input_ = + std::make_unique<TextInput>(std::make_unique<MockTextInputDelegate>()); + SetupSurface(); + } + + void TearDown() override { + TearDownSurface(); + text_input_.reset(); + test::ExoTestBase::TearDown(); + } + + void SetupSurface() { + gfx::Size buffer_size(32, 32); + buffer_ = std::make_unique<Buffer>( + exo_test_helper()->CreateGpuMemoryBuffer(buffer_size)); + surface_ = std::make_unique<Surface>(); + shell_surface_ = std::make_unique<ShellSurface>(surface_.get()); + + surface_->Attach(buffer_.get()); + surface_->Commit(); + + gfx::Point origin(100, 100); + shell_surface_->SetGeometry(gfx::Rect(origin, buffer_size)); + } + + void TearDownSurface() { + shell_surface_.reset(); + surface_.reset(); + buffer_.reset(); + } + + protected: + TextInput* text_input() { return text_input_.get(); } + MockTextInputDelegate* delegate() { + return static_cast<MockTextInputDelegate*>(text_input_->delegate()); + } + Surface* surface() { return surface_.get(); } + + ui::InputMethod* GetInputMethod() { + return surface_->window()->GetHost()->GetInputMethod(); + } + + private: + std::unique_ptr<TextInput> text_input_; + + std::unique_ptr<Buffer> buffer_; + std::unique_ptr<Surface> surface_; + std::unique_ptr<ShellSurface> shell_surface_; + + DISALLOW_COPY_AND_ASSIGN(TextInputTest); +}; + +TEST_F(TextInputTest, Activate) { + EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, text_input()->GetTextInputType()); + EXPECT_EQ(ui::TEXT_INPUT_MODE_DEFAULT, text_input()->GetTextInputMode()); + + EXPECT_CALL(*delegate(), Activated).Times(1); + text_input()->Activate(surface()); + EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, text_input()->GetTextInputType()); + EXPECT_EQ(ui::TEXT_INPUT_MODE_TEXT, text_input()->GetTextInputMode()); + EXPECT_EQ(0, text_input()->GetTextInputFlags()); + + EXPECT_CALL(*delegate(), Deactivated).Times(1); + text_input()->Deactivate(); + EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, text_input()->GetTextInputType()); + EXPECT_EQ(ui::TEXT_INPUT_MODE_DEFAULT, text_input()->GetTextInputMode()); +} + +TEST_F(TextInputTest, ShowVirtualKeyboardIfEnabled) { + TestingInputMethodObserver observer(GetInputMethod()); + + EXPECT_CALL(observer, OnTextInputStateChanged(text_input())).Times(1); + EXPECT_CALL(*delegate(), Activated).Times(1); + text_input()->Activate(surface()); + + EXPECT_CALL(observer, OnShowVirtualKeyboardIfEnabled) + .WillOnce(testing::Invoke( + [this]() { text_input()->OnKeyboardVisibilityStateChanged(true); })); + EXPECT_CALL(*delegate(), OnVirtualKeyboardVisibilityChanged(true)).Times(1); + text_input()->ShowVirtualKeyboardIfEnabled(); + + EXPECT_CALL(*delegate(), Deactivated).Times(1); + text_input()->Deactivate(); +} + +TEST_F(TextInputTest, ShowVirtualKeyboardIfEnabledBeforeActivated) { + TestingInputMethodObserver observer(GetInputMethod()); + + // ShowVirtualKeyboardIfEnabled before activation. + text_input()->ShowVirtualKeyboardIfEnabled(); + + EXPECT_CALL(observer, OnTextInputStateChanged(text_input())).Times(1); + EXPECT_CALL(observer, OnShowVirtualKeyboardIfEnabled) + .WillOnce(testing::Invoke( + [this]() { text_input()->OnKeyboardVisibilityStateChanged(true); })); + EXPECT_CALL(*delegate(), Activated).Times(1); + EXPECT_CALL(*delegate(), OnVirtualKeyboardVisibilityChanged(true)).Times(1); + text_input()->Activate(surface()); + + EXPECT_CALL(*delegate(), Deactivated).Times(1); +} + +TEST_F(TextInputTest, SetTypeModeFlag) { + TestingInputMethodObserver observer(GetInputMethod()); + + EXPECT_CALL(observer, OnTextInputStateChanged(text_input())).Times(1); + EXPECT_CALL(*delegate(), Activated).Times(1); + text_input()->Activate(surface()); + EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, text_input()->GetTextInputType()); + EXPECT_EQ(ui::TEXT_INPUT_MODE_TEXT, text_input()->GetTextInputMode()); + EXPECT_EQ(0, text_input()->GetTextInputFlags()); + EXPECT_TRUE(text_input()->ShouldDoLearning()); + + int flags = ui::TEXT_INPUT_FLAG_AUTOCOMPLETE_OFF | + ui::TEXT_INPUT_FLAG_AUTOCAPITALIZE_NONE; + EXPECT_CALL(observer, OnTextInputStateChanged(text_input())).Times(1); + text_input()->SetTypeModeFlags(ui::TEXT_INPUT_TYPE_URL, + ui::TEXT_INPUT_MODE_URL, flags, false); + + EXPECT_EQ(ui::TEXT_INPUT_TYPE_URL, text_input()->GetTextInputType()); + EXPECT_EQ(ui::TEXT_INPUT_MODE_URL, text_input()->GetTextInputMode()); + EXPECT_EQ(flags, text_input()->GetTextInputFlags()); + EXPECT_FALSE(text_input()->ShouldDoLearning()); + + EXPECT_CALL(*delegate(), Deactivated).Times(1); +} + +TEST_F(TextInputTest, CaretBounds) { + TestingInputMethodObserver observer(GetInputMethod()); + + EXPECT_CALL(observer, OnTextInputStateChanged(text_input())).Times(1); + EXPECT_CALL(*delegate(), Activated).Times(1); + text_input()->Activate(surface()); + + gfx::Rect bounds(10, 10, 0, 16); + EXPECT_CALL(observer, OnCaretBoundsChanged(text_input())).Times(1); + text_input()->SetCaretBounds(bounds); + + EXPECT_EQ(bounds.size().ToString(), + text_input()->GetCaretBounds().size().ToString()); + gfx::Point origin = surface()->window()->GetBoundsInScreen().origin(); + origin += bounds.OffsetFromOrigin(); + EXPECT_EQ(origin.ToString(), + text_input()->GetCaretBounds().origin().ToString()); + + EXPECT_CALL(*delegate(), Deactivated).Times(1); +} + +TEST_F(TextInputTest, CompositionText) { + ui::CompositionText t; + t.text = base::ASCIIToUTF16("composition"); + t.selection = gfx::Range(1u); + t.ime_text_spans.push_back( + ui::ImeTextSpan(0, t.text.size(), ui::ImeTextSpan::Thickness::kThick)); + + ui::CompositionText empty; + EXPECT_CALL(*delegate(), SetCompositionText(t)).Times(1); + EXPECT_CALL(*delegate(), SetCompositionText(empty)).Times(1); + + text_input()->SetCompositionText(t); + text_input()->ClearCompositionText(); +} + +TEST_F(TextInputTest, CommitCompositionText) { + ui::CompositionText t; + t.text = base::ASCIIToUTF16("composition"); + t.selection = gfx::Range(1u); + t.ime_text_spans.push_back( + ui::ImeTextSpan(0, t.text.size(), ui::ImeTextSpan::Thickness::kThick)); + + EXPECT_CALL(*delegate(), SetCompositionText(t)).Times(1); + EXPECT_CALL(*delegate(), Commit(t.text)).Times(1); + + text_input()->SetCompositionText(t); + text_input()->ConfirmCompositionText(); +} + +TEST_F(TextInputTest, Commit) { + base::string16 s = base::ASCIIToUTF16("commit text"); + + EXPECT_CALL(*delegate(), Commit(s)).Times(1); + text_input()->InsertText(s); +} + +TEST_F(TextInputTest, InsertChar) { + ui::KeyEvent ev(ui::ET_KEY_PRESSED, ui::VKEY_RETURN, 0); + + EXPECT_CALL(*delegate(), SendKey(testing::Ref(ev))).Times(1); + text_input()->InsertChar(ev); +} + +TEST_F(TextInputTest, InsertCharNormalKey) { + base::char16 ch = 'x'; + ui::KeyEvent ev(ch, ui::VKEY_X, 0); + + EXPECT_CALL(*delegate(), Commit(base::string16(1, ch))).Times(1); + EXPECT_CALL(*delegate(), SendKey(_)).Times(0); + text_input()->InsertChar(ev); +} + +} // anonymous namespace +} // namespace exo \ No newline at end of file
diff --git a/components/exo/wayland/BUILD.gn b/components/exo/wayland/BUILD.gn index 4000a2b..2e77461 100644 --- a/components/exo/wayland/BUILD.gn +++ b/components/exo/wayland/BUILD.gn
@@ -61,6 +61,7 @@ "//third_party/wayland-protocols:secure_output_protocol", "//third_party/wayland-protocols:stylus_protocol", "//third_party/wayland-protocols:stylus_tools_protocol", + "//third_party/wayland-protocols:text_input_protocol", "//third_party/wayland-protocols:viewporter_protocol", "//third_party/wayland-protocols:vsync_feedback_protocol", "//third_party/wayland-protocols:xdg_shell_protocol",
diff --git a/components/exo/wayland/server.cc b/components/exo/wayland/server.cc index 2bdfa1b..ef7e5a2 100644 --- a/components/exo/wayland/server.cc +++ b/components/exo/wayland/server.cc
@@ -22,6 +22,7 @@ #include <stdint.h> #include <stylus-tools-unstable-v1-server-protocol.h> #include <stylus-unstable-v2-server-protocol.h> +#include <text-input-unstable-v1-server-protocol.h> #include <viewporter-server-protocol.h> #include <vsync-feedback-unstable-v1-server-protocol.h> #include <wayland-server-core.h> @@ -85,6 +86,7 @@ #include "components/exo/shell_surface.h" #include "components/exo/sub_surface.h" #include "components/exo/surface.h" +#include "components/exo/text_input.h" #include "components/exo/touch.h" #include "components/exo/touch_delegate.h" #include "components/exo/touch_stylus_delegate.h" @@ -5322,6 +5324,350 @@ resource, &input_timestamps_manager_implementation, nullptr, nullptr); } +//////////////////////////////////////////////////////////////////////////////// +// text_input_v1 interface: + +size_t OffsetFromUTF8Offset(const base::StringPiece& text, uint32_t offset) { + return base::UTF8ToUTF16(text.substr(0, offset)).size(); +} + +size_t OffsetFromUTF16Offset(const base::StringPiece16& text, uint32_t offset) { + return base::UTF16ToUTF8(text.substr(0, offset)).size(); +} + +class WaylandTextInputDelegate : public TextInput::Delegate { + public: + WaylandTextInputDelegate(wl_resource* text_input) : text_input_(text_input) {} + ~WaylandTextInputDelegate() override = default; + + void set_surface(wl_resource* surface) { surface_ = surface; } + + private: + wl_client* client() { return wl_resource_get_client(text_input_); } + + uint32_t next_serial() { + return wl_display_next_serial(wl_client_get_display(client())); + } + + // TextInput::Delegate: + void Activated() override { + zwp_text_input_v1_send_enter(text_input_, surface_); + wl_client_flush(client()); + } + + void Deactivated() override { + zwp_text_input_v1_send_leave(text_input_); + wl_client_flush(client()); + } + + void OnVirtualKeyboardVisibilityChanged(bool is_visible) override { + zwp_text_input_v1_send_input_panel_state(text_input_, is_visible); + wl_client_flush(client()); + } + + void SetCompositionText(const ui::CompositionText& composition) override { + for (const auto& span : composition.ime_text_spans) { + uint32_t style = ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_DEFAULT; + switch (span.type) { + case ui::ImeTextSpan::Type::kComposition: + if (span.thickness == ui::ImeTextSpan::Thickness::kThick) { + style = ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_HIGHLIGHT; + } else { + style = ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_UNDERLINE; + } + break; + case ui::ImeTextSpan::Type::kSuggestion: + style = ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_SELECTION; + break; + case ui::ImeTextSpan::Type::kMisspellingSuggestion: + style = ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_INCORRECT; + break; + } + const size_t start = + OffsetFromUTF16Offset(composition.text, span.start_offset); + const size_t end = + OffsetFromUTF16Offset(composition.text, span.end_offset); + zwp_text_input_v1_send_preedit_styling(text_input_, start, end - start, + style); + } + + const size_t pos = + OffsetFromUTF16Offset(composition.text, composition.selection.start()); + zwp_text_input_v1_send_preedit_cursor(text_input_, pos); + + const std::string utf8 = base::UTF16ToUTF8(composition.text); + zwp_text_input_v1_send_preedit_string(text_input_, next_serial(), + utf8.c_str(), utf8.c_str()); + + wl_client_flush(client()); + } + + void Commit(const base::string16& text) override { + zwp_text_input_v1_send_commit_string(text_input_, next_serial(), + base::UTF16ToUTF8(text).c_str()); + wl_client_flush(client()); + } + + void SetCursor(const gfx::Range& selection) override { + // TODO(mukai): compute the utf8 offset for |selection| and call + // zwp_text_input_v1_send_cursor_position. + NOTIMPLEMENTED(); + } + + void DeleteSurroundingText(const gfx::Range& range) override { + // TODO(mukai): compute the utf8 offset for |range| and call + // zwp_text_input_send_delete_surrounding_text. + NOTIMPLEMENTED(); + } + + void SendKey(const ui::KeyEvent& event) override { + uint32_t code = ui::KeycodeConverter::DomCodeToNativeKeycode(event.code()); + bool pressed = event.flags() | ui::ET_KEY_PRESSED; + // TODO(mukai): consolidate the definition of this modifiers_mask with other + // similar ones in components/exo/keyboard.cc or arc_ime_service.cc. + constexpr uint32_t modifiers_mask = + ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN | + ui::EF_COMMAND_DOWN | ui::EF_ALTGR_DOWN | ui::EF_MOD3_DOWN; + // 1-bit shifts to adjust the bitpattern for the modifiers; see also + // WaylandTextInputDelegate::SendModifiers(). + uint32_t modifiers = (event.flags() & modifiers_mask) >> 1; + zwp_text_input_v1_send_keysym(text_input_, + TimeTicksToMilliseconds(event.time_stamp()), + next_serial(), code, + pressed ? WL_KEYBOARD_KEY_STATE_PRESSED + : WL_KEYBOARD_KEY_STATE_RELEASED, + modifiers); + wl_client_flush(client()); + } + + void OnTextDirectionChanged(base::i18n::TextDirection direction) override { + uint32_t wayland_direction = ZWP_TEXT_INPUT_V1_TEXT_DIRECTION_AUTO; + switch (direction) { + case base::i18n::RIGHT_TO_LEFT: + wayland_direction = ZWP_TEXT_INPUT_V1_TEXT_DIRECTION_LTR; + break; + case base::i18n::LEFT_TO_RIGHT: + wayland_direction = ZWP_TEXT_INPUT_V1_TEXT_DIRECTION_RTL; + break; + case base::i18n::UNKNOWN_DIRECTION: + LOG(ERROR) << "Unrecognized direction: " << direction; + } + zwp_text_input_v1_send_text_direction(text_input_, next_serial(), + wayland_direction); + } + + wl_resource* text_input_; + wl_resource* surface_ = nullptr; + + DISALLOW_COPY_AND_ASSIGN(WaylandTextInputDelegate); +}; + +void text_input_activate(wl_client* client, + wl_resource* resource, + wl_resource* seat, + wl_resource* surface_resource) { + TextInput* text_input = GetUserDataAs<TextInput>(resource); + Surface* surface = GetUserDataAs<Surface>(surface_resource); + static_cast<WaylandTextInputDelegate*>(text_input->delegate()) + ->set_surface(surface_resource); + text_input->Activate(surface); + + // Sending modifiers. + constexpr const char* kModifierNames[] = { + XKB_MOD_NAME_SHIFT, + XKB_MOD_NAME_CTRL, + XKB_MOD_NAME_ALT, + XKB_MOD_NAME_LOGO, + "Mod5", + "Mod3", + }; + wl_array modifiers; + wl_array_init(&modifiers); + for (const char* modifier : kModifierNames) { + char* p = + static_cast<char*>(wl_array_add(&modifiers, ::strlen(modifier) + 1)); + ::strcpy(p, modifier); + } + zwp_text_input_v1_send_modifiers_map(resource, &modifiers); + wl_array_release(&modifiers); +} + +void text_input_deactivate(wl_client* client, + wl_resource* resource, + wl_resource* seat) { + TextInput* text_input = GetUserDataAs<TextInput>(resource); + text_input->Deactivate(); +} + +void text_input_show_input_panel(wl_client* client, wl_resource* resource) { + GetUserDataAs<TextInput>(resource)->ShowVirtualKeyboardIfEnabled(); +} + +void text_input_hide_input_panel(wl_client* client, wl_resource* resource) { + GetUserDataAs<TextInput>(resource)->HideVirtualKeyboard(); +} + +void text_input_reset(wl_client* client, wl_resource* resource) { + GetUserDataAs<TextInput>(resource)->Resync(); +} + +void text_input_set_surrounding_text(wl_client* client, + wl_resource* resource, + const char* text, + uint32_t cursor, + uint32_t anchor) { + TextInput* text_input = GetUserDataAs<TextInput>(resource); + text_input->SetSurroundingText(base::UTF8ToUTF16(text), + OffsetFromUTF8Offset(text, cursor)); +} + +void text_input_set_content_type(wl_client* client, + wl_resource* resource, + uint32_t hint, + uint32_t purpose) { + TextInput* text_input = GetUserDataAs<TextInput>(resource); + ui::TextInputType type = ui::TEXT_INPUT_TYPE_TEXT; + ui::TextInputMode mode = ui::TEXT_INPUT_MODE_DEFAULT; + int flags = ui::TEXT_INPUT_FLAG_NONE; + bool should_do_learning = true; + if (hint & ZWP_TEXT_INPUT_V1_CONTENT_HINT_AUTO_COMPLETION) + flags |= ui::TEXT_INPUT_FLAG_AUTOCOMPLETE_ON; + if (hint & ZWP_TEXT_INPUT_V1_CONTENT_HINT_AUTO_CORRECTION) + flags |= ui::TEXT_INPUT_FLAG_AUTOCORRECT_ON; + if (hint & ZWP_TEXT_INPUT_V1_CONTENT_HINT_AUTO_CAPITALIZATION) + flags |= ui::TEXT_INPUT_FLAG_AUTOCAPITALIZE_SENTENCES; + if (hint & ZWP_TEXT_INPUT_V1_CONTENT_HINT_LOWERCASE) + flags |= ui::TEXT_INPUT_FLAG_AUTOCAPITALIZE_NONE; + if (hint & ZWP_TEXT_INPUT_V1_CONTENT_HINT_UPPERCASE) + flags |= ui::TEXT_INPUT_FLAG_AUTOCAPITALIZE_CHARACTERS; + if (hint & ZWP_TEXT_INPUT_V1_CONTENT_HINT_TITLECASE) + flags |= ui::TEXT_INPUT_FLAG_AUTOCAPITALIZE_WORDS; + if (hint & ZWP_TEXT_INPUT_V1_CONTENT_HINT_HIDDEN_TEXT) { + flags |= ui::TEXT_INPUT_FLAG_AUTOCOMPLETE_OFF | + ui::TEXT_INPUT_FLAG_AUTOCORRECT_OFF; + } + if (hint & ZWP_TEXT_INPUT_V1_CONTENT_HINT_SENSITIVE_DATA) + should_do_learning = false; + // Unused hints: LATIN, MULTILINE. + + switch (purpose) { + case ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_DIGITS: + mode = ui::TEXT_INPUT_MODE_DECIMAL; + type = ui::TEXT_INPUT_TYPE_NUMBER; + break; + case ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_NUMBER: + mode = ui::TEXT_INPUT_MODE_NUMERIC; + type = ui::TEXT_INPUT_TYPE_NUMBER; + break; + case ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_PHONE: + mode = ui::TEXT_INPUT_MODE_TEL; + type = ui::TEXT_INPUT_TYPE_TELEPHONE; + break; + case ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_URL: + mode = ui::TEXT_INPUT_MODE_URL; + type = ui::TEXT_INPUT_TYPE_URL; + break; + case ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_EMAIL: + mode = ui::TEXT_INPUT_MODE_EMAIL; + type = ui::TEXT_INPUT_TYPE_EMAIL; + break; + case ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_PASSWORD: + DCHECK(!should_do_learning); + type = ui::TEXT_INPUT_TYPE_PASSWORD; + break; + case ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_DATE: + type = ui::TEXT_INPUT_TYPE_DATE; + break; + case ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_TIME: + type = ui::TEXT_INPUT_TYPE_TIME; + break; + case ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_DATETIME: + type = ui::TEXT_INPUT_TYPE_DATE_TIME; + break; + case ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_NORMAL: + case ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_ALPHA: + case ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_NAME: + case ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_TERMINAL: + // No special type / mode are set. + break; + } + + text_input->SetTypeModeFlags(type, mode, flags, should_do_learning); +} + +void text_input_set_cursor_rectangle(wl_client* client, + wl_resource* resource, + int32_t x, + int32_t y, + int32_t width, + int32_t height) { + GetUserDataAs<TextInput>(resource)->SetCaretBounds( + gfx::Rect(x, y, width, height)); +} + +void text_input_set_preferred_language(wl_client* client, + wl_resource* resource, + const char* language) { + // Nothing needs to be done. +} + +void text_input_commit_state(wl_client* client, + wl_resource* resource, + uint32_t serial) { + // Nothing needs to be done. +} + +void text_input_invoke_action(wl_client* client, + wl_resource* resource, + uint32_t button, + uint32_t index) { + GetUserDataAs<TextInput>(resource)->Resync(); +} + +const struct zwp_text_input_v1_interface text_input_v1_implementation = { + text_input_activate, + text_input_deactivate, + text_input_show_input_panel, + text_input_hide_input_panel, + text_input_reset, + text_input_set_surrounding_text, + text_input_set_content_type, + text_input_set_cursor_rectangle, + text_input_set_preferred_language, + text_input_commit_state, + text_input_invoke_action, +}; + +//////////////////////////////////////////////////////////////////////////////// +// text_input_manager_v1 interface: + +void text_input_manager_create_text_input(wl_client* client, + wl_resource* resource, + uint32_t id) { + wl_resource* text_input_resource = + wl_resource_create(client, &zwp_text_input_v1_interface, 1, id); + + SetImplementation( + text_input_resource, &text_input_v1_implementation, + std::make_unique<TextInput>( + std::make_unique<WaylandTextInputDelegate>(text_input_resource))); +} + +const struct zwp_text_input_manager_v1_interface + text_input_manager_implementation = { + text_input_manager_create_text_input, +}; + +void bind_text_input_manager(wl_client* client, + void* data, + uint32_t version, + uint32_t id) { + wl_resource* resource = + wl_resource_create(client, &zwp_text_input_manager_v1_interface, 1, id); + wl_resource_set_implementation(resource, &text_input_manager_implementation, + data, nullptr); +} + } // namespace //////////////////////////////////////////////////////////////////////////////// @@ -5392,6 +5738,8 @@ wl_global_create(wl_display_.get(), &zwp_input_timestamps_manager_v1_interface, 1, display_, bind_input_timestamps_manager); + wl_global_create(wl_display_.get(), &zwp_text_input_manager_v1_interface, 1, + display_, bind_text_input_manager); } Server::~Server() {
diff --git a/components/pdf_strings.grdp b/components/pdf_strings.grdp index 150be9dd..14a7c2f9 100644 --- a/components/pdf_strings.grdp +++ b/components/pdf_strings.grdp
@@ -60,12 +60,5 @@ =1 {Page 1} other {Page #}} </message> - <message name="IDS_PDF_SAVE_CALLED_TITLE" desc="Title of the dialog which shows a message warning the user that saving documents directly is not implemented."> - Warning - </message> - <message name="IDS_PDF_SAVE_CALLED_TEXT" - desc="Contents of the dialog shown when a save operation is attempted in the PDF viewer. Indicates to the user that the operation is not currently implemented and that they will need to print the PDF and use 'Save as PDF' to create a new PDF with their data."> - Saving content entered into PDF forms is currently not supported. Please print the PDF and use the 'Save as PDF' destination to create a new PDF with the entered data. - </message> </if> </grit-part>
diff --git a/components/test/data/autofill/web_page_replay_support_files/wpr_cert.pem b/components/test/data/autofill/web_page_replay_support_files/wpr_cert.pem index b9d7f2b40..05fa861 100644 --- a/components/test/data/autofill/web_page_replay_support_files/wpr_cert.pem +++ b/components/test/data/autofill/web_page_replay_support_files/wpr_cert.pem
@@ -17,4 +17,4 @@ 7IKaN26mpsH+HCT3SDFIAkxP93ZZ+VLR+0BTeHplop8bj4ApMrcwFSn7PmMP7+mD Z6TaZfMjzuoX0Uw56WemxnbEhTj0xP2bEK7LlC2vvykzfBvx5r8qTTr4QFN4NaOW /JUrXf1RNvkF0R+C09ftRJqBRU15vPQF9bZ4jFqUAvMIw/6ABTY+2MgwOkk= ------END CERTIFICATE----- \ No newline at end of file +-----END CERTIFICATE-----
diff --git a/components/test/data/autofill/web_page_replay_support_files/wpr_key.pem b/components/test/data/autofill/web_page_replay_support_files/wpr_key.pem index b9d7f2b40..b511c04 100644 --- a/components/test/data/autofill/web_page_replay_support_files/wpr_key.pem +++ b/components/test/data/autofill/web_page_replay_support_files/wpr_key.pem
@@ -1,20 +1,28 @@ ------BEGIN CERTIFICATE----- -MIIDWDCCAkACCQCjJ6dB+xU8zTANBgkqhkiG9w0BAQsFADBuMQswCQYDVQQGEwJV -UzELMAkGA1UECAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxEjAQBgNVBAoMCVJpY2sg -TGFiczEUMBIGA1UECwwLTW9ydHkgR3JvdXAxFjAUBgNVBAMMDVJpY2sgTGFicyBJ -bmMwHhcNMTgwMTI5MTcwNTQyWhcNMjgwMTI3MTcwNTQyWjBuMQswCQYDVQQGEwJV -UzELMAkGA1UECAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxEjAQBgNVBAoMCVJpY2sg -TGFiczEUMBIGA1UECwwLTW9ydHkgR3JvdXAxFjAUBgNVBAMMDVJpY2sgTGFicyBJ -bmMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDvan2SUSEOhQe2pVH2 -59NQEet3ekDqpojqPLQ5i7ZC9YQccZQqNpq5uNd6jesABMkoa4tgBCV7VwyiRJfz -1jM6d1Rv/pVSWBUaB1kbAAgwmdXQ+kyfij99xMJVgThFydXQ8d7lX53aPzitqr8M -nQL1FxcWQZQojBXEXfx1evtrz86SXh/USWI1SmXUPi3Dtb2XqkhKzR56/MM1DDNB -GFwxbvr5jDOt4lSF88YnbI8hyuaC7D38sMjeM+peNBDhnW2JRUQzbAJxz7b1pbxr -f6JAi2YYz7MFX3vsIRDqsV79oBlg5F0Q0XMioh710SwzQlb2Evhg85Lr2pAprStr -owe1AgMBAAEwDQYJKoZIhvcNAQELBQADggEBALDIsZwlKykoJbz9oOmlm6GHqiBA -FVD23ulvw+WDS18zDXmtYuKfXxecXKqFuI+Q90TinZBIqqBTRw7ncRm8apBxC2cr -mwQ+7H6pC1yiI5xL3wQvPSs7+HWMVApEo0wD7/HWxC42Wo7Sh3tWJ5Pp0zSiCeOC -7IKaN26mpsH+HCT3SDFIAkxP93ZZ+VLR+0BTeHplop8bj4ApMrcwFSn7PmMP7+mD -Z6TaZfMjzuoX0Uw56WemxnbEhTj0xP2bEK7LlC2vvykzfBvx5r8qTTr4QFN4NaOW -/JUrXf1RNvkF0R+C09ftRJqBRU15vPQF9bZ4jFqUAvMIw/6ABTY+2MgwOkk= ------END CERTIFICATE----- \ No newline at end of file +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDvan2SUSEOhQe2 +pVH259NQEet3ekDqpojqPLQ5i7ZC9YQccZQqNpq5uNd6jesABMkoa4tgBCV7Vwyi +RJfz1jM6d1Rv/pVSWBUaB1kbAAgwmdXQ+kyfij99xMJVgThFydXQ8d7lX53aPzit +qr8MnQL1FxcWQZQojBXEXfx1evtrz86SXh/USWI1SmXUPi3Dtb2XqkhKzR56/MM1 +DDNBGFwxbvr5jDOt4lSF88YnbI8hyuaC7D38sMjeM+peNBDhnW2JRUQzbAJxz7b1 +pbxrf6JAi2YYz7MFX3vsIRDqsV79oBlg5F0Q0XMioh710SwzQlb2Evhg85Lr2pAp +rStrowe1AgMBAAECggEAVyGPX6+s8ybQ/tS9trj5+5r58fqJI5zGGVFMWeERzN6j +XOKtBIvo1YyCxzRdAR28w7wX9jKsHW45x9hk4LXk4PNKxJOHbndl/poMALqLQHzM +BwkA19Mtdi0keI/Vlfh1m1xbPWkF/sahbvrEGugNinsDyPLG49bPmS6HUY4XcE11 +X2orbBHX2jXV2vTWYOd3hpN9Fjf4LC9tkLnSCWV946vqCULX6vNeiFvgYYNsQL7+ +68m8IJbLz/Zp4akAg7QBE999HbiYRsDriEbIqi1KYFYSLJARK/HLB2QJIGTcUORN +kqJRGHH8whqiP3HRyPFjTg9MmDTnK4ck2CgPIbhTYQKBgQD+xUNzwpgQ/bQaTXOJ +EpOaVW2xpkNAxeYfLi84MaevH05rQpq7UJTarvQaMQRRAiEhOnnPE6XW1DLi/ufn +DmSdJ4WInLWFQvZCOX6uR6nlL1B0fir5p0ZJ/8JYLmsZJyuEWuQtnbWXx5lrafnj +dxbkuokLfWM+uGb0XuyOvDWB3QKBgQDwkkImps688lxS4Y5BEXSml0mGk/93ddSk +8r6u4jyNVKeA7BiJl/fBLSELWx6wmnBRn40ruiOYdiZ9XNdBHpiqLC8GyLNw1gH+ +G8AtWlQQRp+mHCYd7YGm3FVxR3xOr0LvhD88VQiApcFJ9kAMpw4x/+tl7wWIU/ha +ozvAjC97uQKBgQDJTIfdQVXxpuPVHHk7RuhFO1au1RWyaitHW7CHkARUBEJr0XZ8 +plDW8QGCaFRmxW3z2UZBbd7M/WEvpgUJtX+eBIonxNpP7vawoMkNXyZIJbhGMyI1 +nAuXkHO4RQTuHNrvevlraX7/6/+2tUdyiLgYBaMe5vWxqvX+A7qZlPAaKQKBgDvx +lb4fzl/SXCLixRl9if2AsPdxpTRVDflT6yOUh9YHg/1h1vNiBIAECLnVqJ4EvXv5 +L6n3par1tb2DBrfZMd0lSUp9dAjnqnNw4r/qRAwSLPGtDepjJe039apWT6kjjqAz +6bXU0luL8c/GJkuAzM60oCk0F8LSeY3MIrVluOcxAoGAQCRVEQaYl35X4xcP+dZV +oyNC1WiDwUhnsJ15BhB4N+NbasI+xcszuunYZVMTwI+i9wQpY03ABDvr3skxQ1tW +y9//wNhmVcTZghS2MRW03Bktv0QJxl5lm8GBGWvAFOJYo/MZirDI1jJHy0yDtxqe +qP5kp/Ncp4eHubLjVdstcQc= +-----END PRIVATE KEY-----
diff --git a/components/ukm/content/debug_page/BUILD.gn b/components/ukm/content/debug_page/BUILD.gn deleted file mode 100644 index a22951e..0000000 --- a/components/ukm/content/debug_page/BUILD.gn +++ /dev/null
@@ -1,18 +0,0 @@ -# Copyright 2018 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -static_library("debug_page") { - sources = [ - "debug_page.cc", - "debug_page.h", - ] - - deps = [ - "//base", - "//components/ukm", - "//components/ukm/debug:util", - "//content/public/browser", - "//url", - ] -}
diff --git a/components/ukm/content/debug_page/debug_page.cc b/components/ukm/content/debug_page/debug_page.cc deleted file mode 100644 index 0b2ff6f..0000000 --- a/components/ukm/content/debug_page/debug_page.cc +++ /dev/null
@@ -1,39 +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 "components/ukm/content/debug_page/debug_page.h" - -#include "base/memory/ref_counted_memory.h" -#include "components/ukm/debug/ukm_debug_data_extractor.h" - -namespace ukm { -namespace debug { - -DebugPage::DebugPage(ServiceGetter service_getter) - : service_getter_(service_getter) {} - -DebugPage::~DebugPage() {} - -std::string DebugPage::GetSource() const { - return "ukm"; -} - -std::string DebugPage::GetMimeType(const std::string& path) const { - return "text/html"; -} - -void DebugPage::StartDataRequest( - const std::string& path, - const content::ResourceRequestInfo::WebContentsGetter& wc_getter, - const content::URLDataSource::GotDataCallback& callback) { - std::string data = UkmDebugDataExtractor::GetHTMLData(service_getter_.Run()); - callback.Run(base::RefCountedString::TakeString(&data)); -} - -bool DebugPage::AllowCaching() const { - return false; -} - -} // namespace debug -} // namespace ukm
diff --git a/components/ukm/content/debug_page/debug_page.h b/components/ukm/content/debug_page/debug_page.h deleted file mode 100644 index e693b1bf..0000000 --- a/components/ukm/content/debug_page/debug_page.h +++ /dev/null
@@ -1,47 +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 COMPONENTS_UKM_DEBUG_PAGE_REQUEST_JOB_H_ -#define COMPONENTS_UKM_DEBUG_PAGE_REQUEST_JOB_H_ - -#include <string> - -#include "base/callback.h" -#include "base/macros.h" -#include "content/public/browser/url_data_source.h" - -namespace ukm { - -class UkmService; - -namespace debug { - -// Implements the chrome://ukm page for debugging UKM state. -class DebugPage : public content::URLDataSource { - public: - typedef base::RepeatingCallback<UkmService*()> ServiceGetter; - - explicit DebugPage(ServiceGetter service_getter); - - // content::URLDataSource: - std::string GetSource() const override; - std::string GetMimeType(const std::string& path) const override; - void StartDataRequest( - const std::string& path, - const content::ResourceRequestInfo::WebContentsGetter& wc_getter, - const content::URLDataSource::GotDataCallback& callback) override; - bool AllowCaching() const override; - - private: - ~DebugPage() override; - - ServiceGetter service_getter_; - - DISALLOW_IMPLICIT_CONSTRUCTORS(DebugPage); -}; - -} // namespace debug -} // namespace ukm - -#endif // COMPONENTS_UKM_DEBUG_PAGE_REQUEST_JOB_H_
diff --git a/components/ukm/debug/ukm_debug_data_extractor.cc b/components/ukm/debug/ukm_debug_data_extractor.cc index d3e105c9..fc768528 100644 --- a/components/ukm/debug/ukm_debug_data_extractor.cc +++ b/components/ukm/debug/ukm_debug_data_extractor.cc
@@ -6,8 +6,11 @@ #include <inttypes.h> +#include <map> +#include <utility> +#include <vector> + #include "base/strings/stringprintf.h" -#include "components/ukm/ukm_service.h" #include "components/ukm/ukm_source.h" #include "services/metrics/public/cpp/ukm_decode.h" #include "url/gurl.h" @@ -29,6 +32,32 @@ return it->second; } +base::Value ConvertEntryToValue(const ukm::builders::DecodeMap& decode_map, + const mojom::UkmEntry& entry) { + base::DictionaryValue entry_value; + + const auto it = decode_map.find(entry.event_hash); + if (it == decode_map.end()) { + entry_value.SetKey("name", + base::Value(static_cast<double>(entry.event_hash))); + } else { + entry_value.SetKey("name", base::Value(it->second.name)); + + base::ListValue metrics_list; + auto* metrics_list_storage = &metrics_list.GetList(); + for (const auto& metric : entry.metrics) { + base::DictionaryValue metric_value; + metric_value.SetKey("name", + base::Value(GetName(it->second, metric.first))); + metric_value.SetKey("value", + base::Value(static_cast<double>(metric.second))); + metrics_list_storage->push_back(std::move(metric_value)); + } + entry_value.SetKey("metrics", std::move(metrics_list)); + } + return std::move(entry_value); +} + } // namespace UkmDebugDataExtractor::UkmDebugDataExtractor() = default; @@ -36,7 +65,57 @@ UkmDebugDataExtractor::~UkmDebugDataExtractor() = default; // static -std::string UkmDebugDataExtractor::GetHTMLData(UkmService* ukm_service) { +base::Value UkmDebugDataExtractor::GetStructuredData( + const UkmService* ukm_service) { + if (!ukm_service) + return {}; + + base::DictionaryValue ukm_data; + ukm_data.SetKey("state", base::Value(ukm_service->recording_enabled_)); + ukm_data.SetKey("client_id", + base::Value(static_cast<double>(ukm_service->client_id_))); + ukm_data.SetKey("session_id", + base::Value(static_cast<double>(ukm_service->session_id_))); + + std::map<SourceId, SourceData> source_data; + for (const auto& kv : ukm_service->recordings_.sources) { + source_data[kv.first].source = kv.second.get(); + } + + for (const auto& v : ukm_service->recordings_.entries) { + source_data[v->source_id].entries.push_back(v.get()); + } + + base::ListValue sources_list; + auto* source_list_storage = &sources_list.GetList(); + for (const auto& kv : source_data) { + const auto* src = kv.second.source; + + base::DictionaryValue source_value; + if (src) { + source_value.SetKey("id", base::Value(static_cast<double>(src->id()))); + source_value.SetKey("url", base::Value(src->url().spec())); + } else { + source_value.SetKey("id", base::Value(static_cast<double>(kv.first))); + } + + base::ListValue entries_list; + auto* entries_list_storage = &entries_list.GetList(); + for (auto* entry : kv.second.entries) { + entries_list_storage->push_back( + ConvertEntryToValue(ukm_service->decode_map_, *entry)); + } + + source_value.SetKey("entries", std::move(entries_list)); + + source_list_storage->push_back(std::move(source_value)); + } + ukm_data.SetKey("sources", std::move(sources_list)); + return std::move(ukm_data); +} + +// static +std::string UkmDebugDataExtractor::GetHTMLData(const UkmService* ukm_service) { std::string output; output.append(R"""(<!DOCTYPE html> <html>
diff --git a/components/ukm/debug/ukm_debug_data_extractor.h b/components/ukm/debug/ukm_debug_data_extractor.h index 42d953c..0a55cdf 100644 --- a/components/ukm/debug/ukm_debug_data_extractor.h +++ b/components/ukm/debug/ukm_debug_data_extractor.h
@@ -8,6 +8,8 @@ #include <string> #include "base/macros.h" +#include "base/values.h" +#include "components/ukm/ukm_service.h" namespace ukm { @@ -21,8 +23,12 @@ UkmDebugDataExtractor(); ~UkmDebugDataExtractor(); + // Returns UKM data structured in a DictionaryValue. + static base::Value GetStructuredData(const UkmService* ukm_service); + // Returns UKM data as an HTML page. - static std::string GetHTMLData(UkmService* ukm_service); + // TODO(etiennep): Use GetStructuredData() instead. + static std::string GetHTMLData(const UkmService* ukm_service); private: DISALLOW_COPY_AND_ASSIGN(UkmDebugDataExtractor);
diff --git a/components/variations/variations_http_header_provider.cc b/components/variations/variations_http_header_provider.cc index a7a2097..cec9343 100644 --- a/components/variations/variations_http_header_provider.cc +++ b/components/variations/variations_http_header_provider.cc
@@ -241,10 +241,10 @@ // This is the bottleneck for the creation of the header, so validate the size // here. Force a hard maximum on the ID count in case the Variations server // returns too many IDs and DOSs receiving servers with large requests. - DCHECK_LE(total_id_count, 10U); + DCHECK_LE(total_id_count, 20U); UMA_HISTOGRAM_COUNTS_100("Variations.Headers.ExperimentCount", total_id_count); - if (total_id_count > 20) + if (total_id_count > 30) return std::string(); std::string serialized;
diff --git a/components/viz/service/display_embedder/buffer_queue_unittest.cc b/components/viz/service/display_embedder/buffer_queue_unittest.cc index 03b95cc9..3afe4534 100644 --- a/components/viz/service/display_embedder/buffer_queue_unittest.cc +++ b/components/viz/service/display_embedder/buffer_queue_unittest.cc
@@ -43,18 +43,26 @@ return gfx::BufferFormat::BGRX_8888; } int stride(size_t plane) const override { return 0; } + gfx::GpuMemoryBufferType GetType() const override { + return gfx::EMPTY_BUFFER; + } gfx::GpuMemoryBufferId GetId() const override { return gfx::GpuMemoryBufferId(0); } void SetColorSpace(const gfx::ColorSpace& color_space) override { *set_color_space_count_ += 1; } - gfx::GpuMemoryBufferHandle GetHandle() const override { + gfx::GpuMemoryBufferHandle CloneHandle() const override { return gfx::GpuMemoryBufferHandle(); } ClientBuffer AsClientBuffer() override { return reinterpret_cast<ClientBuffer>(this); } + void OnMemoryDump( + base::trace_event::ProcessMemoryDump* pmd, + const base::trace_event::MemoryAllocatorDumpGuid& buffer_dump_guid, + uint64_t tracing_process_id, + int importance) const override {} size_t* set_color_space_count_; };
diff --git a/components/viz/service/gl/gpu_service_impl.cc b/components/viz/service/gl/gpu_service_impl.cc index e4a80f8..5b35f1b 100644 --- a/components/viz/service/gl/gpu_service_impl.cc +++ b/components/viz/service/gl/gpu_service_impl.cc
@@ -271,8 +271,8 @@ shutdown_event_ = owned_shutdown_event_.get(); } - scheduler_ = std::make_unique<gpu::Scheduler>( - base::ThreadTaskRunnerHandle::Get(), sync_point_manager_); + scheduler_ = + std::make_unique<gpu::Scheduler>(main_runner_, sync_point_manager_); skia_output_surface_sequence_id_ = scheduler_->CreateSequence(gpu::SchedulingPriority::kHigh);
diff --git a/components/viz/test/test_gpu_memory_buffer_manager.cc b/components/viz/test/test_gpu_memory_buffer_manager.cc index 84de35e..d3dab409 100644 --- a/components/viz/test/test_gpu_memory_buffer_manager.cc +++ b/components/viz/test/test_gpu_memory_buffer_manager.cc
@@ -63,11 +63,15 @@ return base::checked_cast<int>(gfx::RowSizeForBufferFormat( size_.width(), format_, static_cast<int>(plane))); } + gfx::GpuMemoryBufferType GetType() const override { + return gfx::SHARED_MEMORY_BUFFER; + } gfx::GpuMemoryBufferId GetId() const override { return id_; } - gfx::GpuMemoryBufferHandle GetHandle() const override { + gfx::GpuMemoryBufferHandle CloneHandle() const override { gfx::GpuMemoryBufferHandle handle; handle.type = gfx::SHARED_MEMORY_BUFFER; - handle.handle = shared_memory_->handle(); + handle.handle = + base::SharedMemory::DuplicateHandle(shared_memory_->handle()); handle.offset = base::checked_cast<uint32_t>(offset_); handle.stride = base::checked_cast<int32_t>(stride_); return handle; @@ -75,6 +79,11 @@ ClientBuffer AsClientBuffer() override { return reinterpret_cast<ClientBuffer>(this); } + void OnMemoryDump( + base::trace_event::ProcessMemoryDump* pmd, + const base::trace_event::MemoryAllocatorDumpGuid& buffer_dump_guid, + uint64_t tracing_process_id, + int importance) const override {} private: TestGpuMemoryBufferManager* manager_; @@ -109,12 +118,20 @@ return client_buffer_->stride(plane); } gfx::GpuMemoryBufferId GetId() const override { return id_; } - gfx::GpuMemoryBufferHandle GetHandle() const override { - return client_buffer_->GetHandle(); + gfx::GpuMemoryBufferType GetType() const override { + return client_buffer_->GetType(); + } + gfx::GpuMemoryBufferHandle CloneHandle() const override { + return client_buffer_->CloneHandle(); } ClientBuffer AsClientBuffer() override { return client_buffer_->AsClientBuffer(); } + void OnMemoryDump( + base::trace_event::ProcessMemoryDump* pmd, + const base::trace_event::MemoryAllocatorDumpGuid& buffer_dump_guid, + uint64_t tracing_process_id, + int importance) const override {} private: TestGpuMemoryBufferManager* manager_;
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index abaa573..132917c 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -1091,6 +1091,8 @@ "media/capture/audio_mirroring_manager.h", "media/capture/desktop_capture_device_uma_types.cc", "media/capture/desktop_capture_device_uma_types.h", + "media/capture/desktop_streams_registry_impl.cc", + "media/capture/desktop_streams_registry_impl.h", "media/capture/web_contents_audio_input_stream.cc", "media/capture/web_contents_audio_input_stream.h", "media/capture/web_contents_audio_muter.cc", @@ -1505,6 +1507,8 @@ "sandbox_ipc_linux.h", "sandbox_parameters_mac.h", "sandbox_parameters_mac.mm", + "scheduler/responsiveness/calculator.cc", + "scheduler/responsiveness/calculator.h", "scoped_active_url.cc", "scoped_active_url.h", "screen_orientation/screen_orientation_provider.cc", @@ -2302,7 +2306,6 @@ if (use_aura) { deps += [ - "//services/ui:lib", "//services/ui/public/cpp", "//services/ui/public/interfaces", "//ui/aura",
diff --git a/content/browser/gpu/browser_gpu_memory_buffer_manager.cc b/content/browser/gpu/browser_gpu_memory_buffer_manager.cc index 8568d3f5..dcf7689 100644 --- a/content/browser/gpu/browser_gpu_memory_buffer_manager.cc +++ b/content/browser/gpu/browser_gpu_memory_buffer_manager.cc
@@ -294,16 +294,17 @@ // Note: Unretained is safe as IO thread is stopped before manager is // destroyed. - request->result = gpu::GpuMemoryBufferImplSharedMemory::Create( + auto shared_memory_buffer = gpu::GpuMemoryBufferImplSharedMemory::Create( new_id, request->size, request->format, request->usage, base::Bind( &GpuMemoryBufferDeleted, BrowserThread::GetTaskRunnerForThread(BrowserThread::IO), base::Bind(&BrowserGpuMemoryBufferManager::DestroyGpuMemoryBufferOnIO, base::Unretained(this), new_id, request->client_id))); - if (request->result) { + if (shared_memory_buffer) { buffers.find(new_id)->second.shared_memory_guid = - request->result->GetHandle().handle.GetGUID(); + shared_memory_buffer->GetSharedMemoryGUID(); + request->result = std::move(shared_memory_buffer); } request->event.Signal(); }
diff --git a/content/browser/loader/navigation_url_loader_impl_unittest.cc b/content/browser/loader/navigation_url_loader_impl_unittest.cc index 538274d..c950c09 100644 --- a/content/browser/loader/navigation_url_loader_impl_unittest.cc +++ b/content/browser/loader/navigation_url_loader_impl_unittest.cc
@@ -145,6 +145,10 @@ } ~NavigationURLLoaderImplTest() override { + // The context needs to be deleted before ServiceManagerConnection is + // destroyed, so the storage partition in the context does not try to + // reconnect to the network service after ServiceManagerConnection is dead. + browser_context_.reset(); ServiceManagerConnection::DestroyForProcess(); }
diff --git a/content/browser/media/capture/desktop_streams_registry_impl.cc b/content/browser/media/capture/desktop_streams_registry_impl.cc new file mode 100644 index 0000000..d3b72fc --- /dev/null +++ b/content/browser/media/capture/desktop_streams_registry_impl.cc
@@ -0,0 +1,110 @@ +// 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 "content/browser/media/capture/desktop_streams_registry_impl.h" + +#include "base/base64.h" +#include "base/location.h" +#include "base/macros.h" +#include "base/no_destructor.h" +#include "base/stl_util.h" +#include "base/time/time.h" +#include "content/public/browser/browser_thread.h" +#include "crypto/random.h" + +namespace { + +const int kStreamIdLengthBytes = 16; + +const int kApprovedStreamTimeToLiveSeconds = 10; + +std::string GenerateRandomStreamId() { + char buffer[kStreamIdLengthBytes]; + crypto::RandBytes(buffer, base::size(buffer)); + std::string result; + base::Base64Encode(base::StringPiece(buffer, base::size(buffer)), &result); + return result; +} + +} // namespace + +namespace content { + +// static +DesktopStreamsRegistry* DesktopStreamsRegistry::GetInstance() { + return DesktopStreamsRegistryImpl::GetInstance(); +} + +// static +DesktopStreamsRegistryImpl* DesktopStreamsRegistryImpl::GetInstance() { + static base::NoDestructor<DesktopStreamsRegistryImpl> instance; + return instance.get(); +} + +DesktopStreamsRegistryImpl::DesktopStreamsRegistryImpl() {} +DesktopStreamsRegistryImpl::~DesktopStreamsRegistryImpl() {} + +std::string DesktopStreamsRegistryImpl::RegisterStream( + int render_process_id, + int render_frame_id, + const GURL& origin, + const DesktopMediaID& source, + const std::string& extension_name) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + std::string id = GenerateRandomStreamId(); + DCHECK(approved_streams_.find(id) == approved_streams_.end()); + ApprovedDesktopMediaStream& stream = approved_streams_[id]; + stream.render_process_id = render_process_id; + stream.render_frame_id = render_frame_id; + stream.origin = origin; + stream.source = source; + stream.extension_name = extension_name; + + BrowserThread::PostDelayedTask( + BrowserThread::UI, FROM_HERE, + base::BindOnce(&DesktopStreamsRegistryImpl::CleanupStream, + base::Unretained(this), id), + base::TimeDelta::FromSeconds(kApprovedStreamTimeToLiveSeconds)); + + return id; +} + +DesktopMediaID DesktopStreamsRegistryImpl::RequestMediaForStreamId( + const std::string& id, + int render_process_id, + int render_frame_id, + const GURL& origin, + std::string* extension_name) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + StreamsMap::iterator it = approved_streams_.find(id); + + // Verify that if there is a request with the specified ID it was created for + // the same origin and the same renderer. + if (it == approved_streams_.end() || + render_process_id != it->second.render_process_id || + render_frame_id != it->second.render_frame_id || + origin != it->second.origin) { + return DesktopMediaID(); + } + + DesktopMediaID result = it->second.source; + if (extension_name) { + *extension_name = it->second.extension_name; + } + approved_streams_.erase(it); + return result; +} + +void DesktopStreamsRegistryImpl::CleanupStream(const std::string& id) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + approved_streams_.erase(id); +} + +DesktopStreamsRegistryImpl::ApprovedDesktopMediaStream:: + ApprovedDesktopMediaStream() + : render_process_id(-1), render_frame_id(-1) {} + +} // namespace content \ No newline at end of file
diff --git a/content/browser/media/capture/desktop_streams_registry_impl.h b/content/browser/media/capture/desktop_streams_registry_impl.h new file mode 100644 index 0000000..993555a --- /dev/null +++ b/content/browser/media/capture/desktop_streams_registry_impl.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 CONTENT_BROWSER_MEDIA_CAPTURE_DESKTOP_STREAMS_REGISTRY_IMPL_H_ +#define CONTENT_BROWSER_MEDIA_CAPTURE_DESKTOP_STREAMS_REGISTRY_IMPL_H_ + +#include <map> +#include <string> + +#include "content/common/content_export.h" +#include "content/public/browser/desktop_media_id.h" +#include "content/public/browser/desktop_streams_registry.h" +#include "url/gurl.h" + +namespace content { + +class CONTENT_EXPORT DesktopStreamsRegistryImpl + : public DesktopStreamsRegistry { + public: + DesktopStreamsRegistryImpl(); + ~DesktopStreamsRegistryImpl() override; + + // Returns the DesktopStreamRegistryImpl singleton. + static DesktopStreamsRegistryImpl* GetInstance(); + + std::string RegisterStream(int render_process_id, + int render_frame_id, + const GURL& origin, + const DesktopMediaID& source, + const std::string& extension_name) override; + + DesktopMediaID RequestMediaForStreamId(const std::string& id, + int render_process_id, + int render_frame_id, + const GURL& origin, + std::string* extension_name) override; + + private: + // Type used to store list of accepted desktop media streams. + struct ApprovedDesktopMediaStream { + ApprovedDesktopMediaStream(); + + int render_process_id; + int render_frame_id; + GURL origin; + DesktopMediaID source; + std::string extension_name; + }; + typedef std::map<std::string, ApprovedDesktopMediaStream> StreamsMap; + + // Helper function that removes an expired stream from the registry. + void CleanupStream(const std::string& id); + + StreamsMap approved_streams_; + + DISALLOW_COPY_AND_ASSIGN(DesktopStreamsRegistryImpl); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_MEDIA_CAPTURE_DESKTOP_STREAMS_REGISTRY_IMPL_H_
diff --git a/content/browser/media/flinging_renderer.cc b/content/browser/media/flinging_renderer.cc index b6119358..fd24901 100644 --- a/content/browser/media/flinging_renderer.cc +++ b/content/browser/media/flinging_renderer.cc
@@ -15,7 +15,7 @@ namespace content { FlingingRenderer::FlingingRenderer( - std::unique_ptr<media::MediaController> controller) + std::unique_ptr<media::FlingingController> controller) : controller_(std::move(controller)) {} FlingingRenderer::~FlingingRenderer() = default; @@ -43,15 +43,15 @@ if (!presentation_delegate) return nullptr; - auto media_controller = presentation_delegate->GetMediaController( + auto flinging_controller = presentation_delegate->GetFlingingController( render_frame_host->GetProcess()->GetID(), render_frame_host->GetRoutingID(), presentation_id); - if (!media_controller) + if (!flinging_controller) return nullptr; return base::WrapUnique<FlingingRenderer>( - new FlingingRenderer(std::move(media_controller))); + new FlingingRenderer(std::move(flinging_controller))); } // media::Renderer implementation @@ -76,21 +76,21 @@ void FlingingRenderer::StartPlayingFrom(base::TimeDelta time) { DVLOG(2) << __func__; - controller_->Seek(time); - controller_->Play(); + controller_->GetMediaController()->Seek(time); + controller_->GetMediaController()->Play(); } void FlingingRenderer::SetPlaybackRate(double playback_rate) { DVLOG(2) << __func__; if (playback_rate == 0) - controller_->Pause(); + controller_->GetMediaController()->Pause(); else - controller_->Play(); + controller_->GetMediaController()->Play(); } void FlingingRenderer::SetVolume(float volume) { DVLOG(2) << __func__; - controller_->SetVolume(volume); + controller_->GetMediaController()->SetVolume(volume); } base::TimeDelta FlingingRenderer::GetMediaTime() {
diff --git a/content/browser/media/flinging_renderer.h b/content/browser/media/flinging_renderer.h index 38c411c..f5a0eee 100644 --- a/content/browser/media/flinging_renderer.h +++ b/content/browser/media/flinging_renderer.h
@@ -7,7 +7,7 @@ #include "base/callback.h" #include "content/common/content_export.h" -#include "media/base/media_controller.h" +#include "media/base/flinging_controller.h" #include "media/base/media_resource.h" #include "media/base/renderer.h" #include "media/base/renderer_client.h" @@ -50,9 +50,10 @@ private: friend class FlingingRendererTest; - explicit FlingingRenderer(std::unique_ptr<media::MediaController> controller); + explicit FlingingRenderer( + std::unique_ptr<media::FlingingController> controller); - std::unique_ptr<media::MediaController> controller_; + std::unique_ptr<media::FlingingController> controller_; DISALLOW_COPY_AND_ASSIGN(FlingingRenderer); };
diff --git a/content/browser/media/flinging_renderer_unittest.cc b/content/browser/media/flinging_renderer_unittest.cc index 680ac22..629e79c 100644 --- a/content/browser/media/flinging_renderer_unittest.cc +++ b/content/browser/media/flinging_renderer_unittest.cc
@@ -4,6 +4,7 @@ #include "content/browser/media/flinging_renderer.h" +#include "base/time/time.h" #include "base/version.h" #include "media/base/media_controller.h" #include "testing/gmock/include/gmock/gmock.h" @@ -23,14 +24,33 @@ MOCK_METHOD1(Seek, void(base::TimeDelta)); }; +class MockFlingingController : public media::FlingingController { + public: + explicit MockFlingingController(media::MediaController* media_controller) + : media_controller_(media_controller) {} + + media::MediaController* GetMediaController() { return media_controller_; } + + MOCK_METHOD1(AddMediaStatusObserver, void(media::MediaStatusObserver*)); + MOCK_METHOD1(RemoveMediaStatusObserver, void(media::MediaStatusObserver*)); + MOCK_METHOD0(GetApproximateCurrentTime, base::TimeDelta()); + + private: + media::MediaController* media_controller_; +}; + class FlingingRendererTest : public testing::Test { public: FlingingRendererTest() : media_controller_(new StrictMock<MockMediaController>()), - renderer_(std::unique_ptr<media::MediaController>(media_controller_)) {} + flinging_controller_( + new StrictMock<MockFlingingController>(media_controller_.get())), + renderer_( + std::unique_ptr<media::FlingingController>(flinging_controller_)) {} protected: - StrictMock<MockMediaController>* media_controller_; + std::unique_ptr<MockMediaController> media_controller_; + StrictMock<MockFlingingController>* flinging_controller_; FlingingRenderer renderer_; };
diff --git a/content/browser/presentation/OWNERS b/content/browser/presentation/OWNERS index 4c81ef2..1a85e3fd 100644 --- a/content/browser/presentation/OWNERS +++ b/content/browser/presentation/OWNERS
@@ -1,9 +1,4 @@ # Presentation API OWNERS -# -# This file also covers ownership of the following directories: -# //content/common/presentation/ -# //content/renderer/presentation/ - imcheng@chromium.org mfoltz@chromium.org mlamouri@chromium.org
diff --git a/content/browser/presentation/presentation_service_impl.cc b/content/browser/presentation/presentation_service_impl.cc index 321adbda..137b1c3 100644 --- a/content/browser/presentation/presentation_service_impl.cc +++ b/content/browser/presentation/presentation_service_impl.cc
@@ -21,7 +21,6 @@ #include "content/public/common/content_client.h" #include "content/public/common/content_switches.h" #include "content/public/common/frame_navigate_params.h" -#include "content/public/common/presentation_connection_message.h" using blink::mojom::PresentationConnectionState; using blink::mojom::PresentationError;
diff --git a/content/browser/presentation/presentation_service_impl.h b/content/browser/presentation/presentation_service_impl.h index 333d2ac..a0fd228 100644 --- a/content/browser/presentation/presentation_service_impl.h +++ b/content/browser/presentation/presentation_service_impl.h
@@ -29,7 +29,6 @@ namespace content { -struct PresentationConnectionMessage; class RenderFrameHost; // Implementation of Mojo PresentationService. @@ -113,9 +112,6 @@ // Maximum number of pending ReconnectPresentation requests at any given time. static const int kMaxQueuedRequests = 10; - using ConnectionMessagesCallback = - base::OnceCallback<void(std::vector<PresentationConnectionMessage>)>; - // Listener implementation owned by PresentationServiceImpl. An instance of // this is created when PresentationRequest.getAvailability() is resolved. // The instance receives screen availability results from the embedder and @@ -214,12 +210,6 @@ void ListenForConnectionStateChange( const blink::mojom::PresentationInfo& connection); - // Passed to embedder's implementation of PresentationServiceDelegate for - // later invocation when connection messages arrive. - void OnConnectionMessages( - const blink::mojom::PresentationInfo& presentation_info, - std::vector<content::PresentationConnectionMessage> messages); - // A callback registered to LocalPresentationManager when // the PresentationServiceImpl for the presentation receiver is initialized. // Calls |receiver_| to create a new PresentationConnection on receiver page.
diff --git a/content/browser/presentation/presentation_service_impl_unittest.cc b/content/browser/presentation/presentation_service_impl_unittest.cc index a635d44..52d3253d 100644 --- a/content/browser/presentation/presentation_service_impl_unittest.cc +++ b/content/browser/presentation/presentation_service_impl_unittest.cc
@@ -17,16 +17,21 @@ #include "content/public/browser/navigation_handle.h" #include "content/public/browser/presentation_request.h" #include "content/public/browser/presentation_service_delegate.h" -#include "content/public/common/presentation_connection_message.h" #include "content/test/test_render_frame_host.h" #include "content/test/test_render_view_host.h" #include "content/test/test_web_contents.h" #include "mojo/public/cpp/bindings/interface_ptr.h" #include "testing/gmock/include/gmock/gmock.h" +using blink::mojom::PresentationConnection; using blink::mojom::PresentationConnectionCloseReason; +using blink::mojom::PresentationConnectionMessagePtr; +using blink::mojom::PresentationConnectionPtr; using blink::mojom::PresentationConnectionState; +using blink::mojom::PresentationController; +using blink::mojom::PresentationControllerPtr; using blink::mojom::PresentationError; +using blink::mojom::PresentationErrorPtr; using blink::mojom::PresentationErrorType; using blink::mojom::PresentationInfo; using blink::mojom::PresentationInfoPtr; @@ -52,6 +57,11 @@ return expected.url == arg.url && expected.id == arg.id; } +// Matches blink::mojom::PresentationInfoPtr. +MATCHER_P(InfoPtrEquals, expected, "") { + return expected.url == arg->url && expected.id == arg->id; +} + ACTION_TEMPLATE(SaveArgByMove, HAS_1_TEMPLATE_PARAMS(int, k), AND_1_VALUE_PARAMS(pointer)) { @@ -97,32 +107,15 @@ MOCK_METHOD2(SetDefaultPresentationUrls, void(const PresentationRequest& request, DefaultPresentationConnectionCallback callback)); - - // TODO(crbug.com/729950): Use MOCK_METHOD directly once GMock gets the - // move-only type support. - void StartPresentation( - const PresentationRequest& request, - PresentationConnectionCallback success_cb, - PresentationConnectionErrorCallback error_cb) override { - StartPresentationInternal(request, success_cb, error_cb); - } - MOCK_METHOD3(StartPresentationInternal, + MOCK_METHOD3(StartPresentation, void(const PresentationRequest& request, - PresentationConnectionCallback& success_cb, - PresentationConnectionErrorCallback& error_cb)); - void ReconnectPresentation( - const PresentationRequest& request, - const std::string& presentation_id, - PresentationConnectionCallback success_cb, - PresentationConnectionErrorCallback error_cb) override { - ReconnectPresentationInternal(request, presentation_id, success_cb, - error_cb); - } - MOCK_METHOD4(ReconnectPresentationInternal, + PresentationConnectionCallback success_cb, + PresentationConnectionErrorCallback error_cb)); + MOCK_METHOD4(ReconnectPresentation, void(const PresentationRequest& request, const std::string& presentation_id, - PresentationConnectionCallback& success_cb, - PresentationConnectionErrorCallback& error_cb)); + PresentationConnectionCallback success_cb, + PresentationConnectionErrorCallback error_cb)); MOCK_METHOD3(CloseConnection, void(int render_process_id, int render_frame_id, @@ -131,53 +124,29 @@ void(int render_process_id, int render_frame_id, const std::string& presentation_id)); - MOCK_METHOD3(GetMediaController, - std::unique_ptr<media::MediaController>( + MOCK_METHOD3(GetFlingingController, + std::unique_ptr<media::FlingingController>( int render_process_id, int render_frame_id, const std::string& presentation_id)); - - // PresentationConnectionMessage is move-only. - // TODO(crbug.com/729950): Use MOCK_METHOD directly once GMock gets the - // move-only type support. - void SendMessage(int render_process_id, - int render_frame_id, - const PresentationInfo& presentation_info, - PresentationConnectionMessage message, - SendMessageCallback send_message_cb) { - SendMessageInternal(render_process_id, render_frame_id, presentation_info, - message, send_message_cb); - } - MOCK_METHOD5(SendMessageInternal, + MOCK_METHOD5(SendMessage, void(int render_process_id, int render_frame_id, const PresentationInfo& presentation_info, - const PresentationConnectionMessage& message, + PresentationConnectionMessagePtr message, const SendMessageCallback& send_message_cb)); - MOCK_METHOD4( ListenForConnectionStateChange, void(int render_process_id, int render_frame_id, const PresentationInfo& connection, const PresentationConnectionStateChangedCallback& state_changed_cb)); - - void ConnectToPresentation( - int render_process_id, - int render_frame_id, - const PresentationInfo& presentation_info, - PresentationConnectionPtr controller_conn_ptr, - PresentationConnectionRequest receiver_conn_request) override { - RegisterLocalPresentationConnectionRaw(render_process_id, render_frame_id, - presentation_info, - controller_conn_ptr.get()); - } - - MOCK_METHOD4(RegisterLocalPresentationConnectionRaw, + MOCK_METHOD5(ConnectToPresentation, void(int render_process_id, int render_frame_id, const PresentationInfo& presentation_info, - blink::mojom::PresentationConnection* connection)); + PresentationConnectionPtr controller_conn_ptr, + PresentationConnectionRequest receiver_conn_request)); void set_screen_availability_listening_supported(bool value) { screen_availability_listening_supported_ = value; @@ -189,16 +158,10 @@ class MockPresentationReceiver : public blink::mojom::PresentationReceiver { public: - void OnReceiverConnectionAvailable( - PresentationInfoPtr info, - blink::mojom::PresentationConnectionPtr controller_connection, - blink::mojom::PresentationConnectionRequest receiver_connection_request) - override { - OnReceiverConnectionAvailable(*info); - } - - MOCK_METHOD1(OnReceiverConnectionAvailable, - void(const PresentationInfo& info)); + MOCK_METHOD3(OnReceiverConnectionAvailable, + void(PresentationInfoPtr info, + PresentationConnectionPtr controller_connection, + PresentationConnectionRequest receiver_connection_request)); }; class MockReceiverPresentationServiceDelegate @@ -215,16 +178,11 @@ void(const ReceiverConnectionAvailableCallback&)); }; -class MockPresentationConnection : public blink::mojom::PresentationConnection { +class MockPresentationConnection : public PresentationConnection { public: - // PresentationConnectionMessage is move-only. - void OnMessage(PresentationConnectionMessage message, - base::OnceCallback<void(bool)> send_message_cb) override { - OnMessageInternal(message, send_message_cb); - } - MOCK_METHOD2(OnMessageInternal, - void(const PresentationConnectionMessage& message, - base::OnceCallback<void(bool)>& send_message_cb)); + MOCK_METHOD2(OnMessage, + void(PresentationConnectionMessagePtr message, + base::OnceCallback<void(bool)> send_message_cb)); MOCK_METHOD1(DidChangeState, void(PresentationConnectionState state)); MOCK_METHOD0(RequestClose, void()); }; @@ -233,38 +191,19 @@ public: MOCK_METHOD2(OnScreenAvailabilityUpdated, void(const GURL& url, ScreenAvailability availability)); - void OnConnectionStateChanged(PresentationInfoPtr connection, - PresentationConnectionState new_state) { - OnConnectionStateChangedInternal(*connection, new_state); - } - MOCK_METHOD2(OnConnectionStateChangedInternal, - void(const PresentationInfo& connection, + MOCK_METHOD2(OnConnectionStateChanged, + void(PresentationInfoPtr connection, PresentationConnectionState new_state)); - void OnConnectionClosed( - PresentationInfoPtr connection, - blink::mojom::PresentationConnectionCloseReason reason, - const std::string& message) { - OnConnectionClosedInternal(*connection, reason, message); - } - MOCK_METHOD3(OnConnectionClosedInternal, - void(const PresentationInfo& connection, - blink::mojom::PresentationConnectionCloseReason reason, + MOCK_METHOD3(OnConnectionClosed, + void(PresentationInfoPtr connection, + PresentationConnectionCloseReason reason, const std::string& message)); - // PresentationConnectionMessage is move-only. - void OnConnectionMessagesReceived( - PresentationInfoPtr presentation_info, - std::vector<PresentationConnectionMessage> messages) { - OnConnectionMessagesReceivedInternal(*presentation_info, messages); - } MOCK_METHOD2( - OnConnectionMessagesReceivedInternal, + OnConnectionMessagesReceived, void(const PresentationInfo& presentation_info, - const std::vector<PresentationConnectionMessage>& messages)); - void OnDefaultPresentationStarted(PresentationInfoPtr presentation_info) { - OnDefaultPresentationStartedInternal(*presentation_info); - } - MOCK_METHOD1(OnDefaultPresentationStartedInternal, - void(const PresentationInfo& presentation_info)); + const std::vector<PresentationConnectionMessagePtr>& messages)); + MOCK_METHOD1(OnDefaultPresentationStarted, + void(PresentationInfoPtr presentation_info)); }; class PresentationServiceImplTest : public RenderViewHostImplTestHarness { @@ -286,10 +225,9 @@ service_impl_.reset(new PresentationServiceImpl( render_frame_host, contents(), &mock_delegate_, nullptr)); - blink::mojom::PresentationControllerPtr controller_ptr; - controller_binding_.reset( - new mojo::Binding<blink::mojom::PresentationController>( - &mock_controller_, mojo::MakeRequest(&controller_ptr))); + PresentationControllerPtr controller_ptr; + controller_binding_.reset(new mojo::Binding<PresentationController>( + &mock_controller_, mojo::MakeRequest(&controller_ptr))); service_impl_->SetController(std::move(controller_ptr)); presentation_urls_.push_back(presentation_url1_); @@ -356,14 +294,14 @@ } void ExpectPresentationSuccess(PresentationInfoPtr info, - blink::mojom::PresentationErrorPtr error) { + PresentationErrorPtr error) { EXPECT_FALSE(info.is_null()); EXPECT_TRUE(error.is_null()); presentation_cb_was_run_ = true; } void ExpectPresentationError(PresentationInfoPtr info, - blink::mojom::PresentationErrorPtr error) { + PresentationErrorPtr error) { EXPECT_TRUE(info.is_null()); EXPECT_FALSE(error.is_null()); presentation_cb_was_run_ = true; @@ -380,8 +318,7 @@ std::unique_ptr<PresentationServiceImpl> service_impl_; MockPresentationController mock_controller_; - std::unique_ptr<mojo::Binding<blink::mojom::PresentationController>> - controller_binding_; + std::unique_ptr<mojo::Binding<PresentationController>> controller_binding_; GURL presentation_url1_; GURL presentation_url2_; @@ -469,8 +406,8 @@ PresentationInfo presentation_info(presentation_url2_, kPresentationId); - EXPECT_CALL(mock_controller_, OnDefaultPresentationStartedInternal( - InfoEquals(presentation_info))); + EXPECT_CALL(mock_controller_, + OnDefaultPresentationStarted(InfoPtrEquals(presentation_info))); EXPECT_CALL(mock_delegate_, ListenForConnectionStateChange(_, _, _, _)); std::move(callback).Run( PresentationInfo(presentation_url2_, kPresentationId)); @@ -503,8 +440,8 @@ .WillOnce(SaveArg<3>(&state_changed_cb)); service_impl_->ListenForConnectionStateChange(connection); - EXPECT_CALL(mock_controller_, OnConnectionStateChangedInternal( - InfoEquals(presentation_connection), + EXPECT_CALL(mock_controller_, OnConnectionStateChanged( + InfoPtrEquals(presentation_connection), PresentationConnectionState::TERMINATED)); state_changed_cb.Run(PresentationConnectionStateChangeInfo( PresentationConnectionState::TERMINATED)); @@ -526,10 +463,10 @@ closed_info.close_reason = PresentationConnectionCloseReason::WENT_AWAY; closed_info.message = "Foo"; - EXPECT_CALL(mock_controller_, - OnConnectionClosedInternal( - InfoEquals(presentation_connection), - PresentationConnectionCloseReason::WENT_AWAY, "Foo")); + EXPECT_CALL( + mock_controller_, + OnConnectionClosed(InfoPtrEquals(presentation_connection), + PresentationConnectionCloseReason::WENT_AWAY, "Foo")); state_changed_cb.Run(closed_info); base::RunLoop().RunUntilIdle(); } @@ -545,33 +482,37 @@ } TEST_F(PresentationServiceImplTest, StartPresentationSuccess) { - base::OnceCallback<void(const PresentationInfo&)> success_cb; - EXPECT_CALL(mock_delegate_, StartPresentationInternal(_, _, _)) - .WillOnce(SaveArgByMove<1>(&success_cb)); + base::OnceCallback<void(const PresentationInfo&)> saved_success_cb; + EXPECT_CALL(mock_delegate_, StartPresentation(_, _, _)) + .WillOnce([&](const auto& request, auto success_cb, auto error_cb) { + saved_success_cb = std::move(success_cb); + }); service_impl_->StartPresentation(presentation_urls_, std::move(expect_presentation_success_cb_)); - EXPECT_FALSE(success_cb.is_null()); + EXPECT_FALSE(saved_success_cb.is_null()); EXPECT_CALL(mock_delegate_, ListenForConnectionStateChange(_, _, _, _)) .Times(1); - std::move(success_cb) + std::move(saved_success_cb) .Run(PresentationInfo(presentation_url1_, kPresentationId)); ExpectPresentationCallbackWasRun(); } TEST_F(PresentationServiceImplTest, StartPresentationError) { - base::OnceCallback<void(const PresentationError&)> error_cb; - EXPECT_CALL(mock_delegate_, StartPresentationInternal(_, _, _)) - .WillOnce(SaveArgByMove<2>(&error_cb)); + base::OnceCallback<void(const PresentationError&)> saved_error_cb; + EXPECT_CALL(mock_delegate_, StartPresentation(_, _, _)) + .WillOnce([&](const auto& request, auto success_cb, auto error_cb) { + saved_error_cb = std::move(error_cb); + }); service_impl_->StartPresentation(presentation_urls_, std::move(expect_presentation_error_cb_)); - EXPECT_FALSE(error_cb.is_null()); - std::move(error_cb).Run( - PresentationError(PresentationErrorType::UNKNOWN, "Error message")); + EXPECT_FALSE(saved_error_cb.is_null()); + std::move(saved_error_cb) + .Run(PresentationError(PresentationErrorType::UNKNOWN, "Error message")); ExpectPresentationCallbackWasRun(); } TEST_F(PresentationServiceImplTest, StartPresentationInProgress) { - EXPECT_CALL(mock_delegate_, StartPresentationInternal(_, _, _)).Times(1); + EXPECT_CALL(mock_delegate_, StartPresentation(_, _, _)).Times(1); // Uninvoked callbacks must outlive |service_impl_| since they get invoked // at |service_impl_|'s destruction. service_impl_->StartPresentation(presentation_urls_, base::DoNothing()); @@ -584,32 +525,33 @@ } TEST_F(PresentationServiceImplTest, ReconnectPresentationSuccess) { - base::OnceCallback<void(const PresentationInfo&)> success_cb; - EXPECT_CALL(mock_delegate_, - ReconnectPresentationInternal(_, kPresentationId, _, _)) - .WillOnce(SaveArgByMove<2>(&success_cb)); + base::OnceCallback<void(const PresentationInfo&)> saved_success_cb; + EXPECT_CALL(mock_delegate_, ReconnectPresentation(_, kPresentationId, _, _)) + .WillOnce( + [&](const auto& request, const std::string& id, auto success_cb, + auto error_cb) { saved_success_cb = std::move(success_cb); }); service_impl_->ReconnectPresentation( presentation_urls_, kPresentationId, std::move(expect_presentation_success_cb_)); - EXPECT_FALSE(success_cb.is_null()); + EXPECT_FALSE(saved_success_cb.is_null()); EXPECT_CALL(mock_delegate_, ListenForConnectionStateChange(_, _, _, _)) .Times(1); - std::move(success_cb) + std::move(saved_success_cb) .Run(PresentationInfo(presentation_url1_, kPresentationId)); ExpectPresentationCallbackWasRun(); } TEST_F(PresentationServiceImplTest, ReconnectPresentationError) { - base::OnceCallback<void(const PresentationError&)> error_cb; - EXPECT_CALL(mock_delegate_, - ReconnectPresentationInternal(_, kPresentationId, _, _)) - .WillOnce(SaveArgByMove<3>(&error_cb)); + base::OnceCallback<void(const PresentationError&)> saved_error_cb; + EXPECT_CALL(mock_delegate_, ReconnectPresentation(_, kPresentationId, _, _)) + .WillOnce([&](const auto& request, const std::string& id, auto success_cb, + auto error_cb) { saved_error_cb = std::move(error_cb); }); service_impl_->ReconnectPresentation( presentation_urls_, kPresentationId, std::move(expect_presentation_error_cb_)); - EXPECT_FALSE(error_cb.is_null()); - std::move(error_cb).Run( - PresentationError(PresentationErrorType::UNKNOWN, "Error message")); + EXPECT_FALSE(saved_error_cb.is_null()); + std::move(saved_error_cb) + .Run(PresentationError(PresentationErrorType::UNKNOWN, "Error message")); ExpectPresentationCallbackWasRun(); } @@ -618,7 +560,7 @@ const char* presentation_id = "presentationId%d"; int num_requests = PresentationServiceImpl::kMaxQueuedRequests; int i = 0; - EXPECT_CALL(mock_delegate_, ReconnectPresentationInternal(_, _, _, _)) + EXPECT_CALL(mock_delegate_, ReconnectPresentation(_, _, _, _)) .Times(num_requests); for (; i < num_requests; ++i) { std::vector<GURL> urls = {GURL(base::StringPrintf(presentation_url, i))}; @@ -650,16 +592,16 @@ PresentationInfoPtr presentation_info = PresentationInfo::New(presentation_url1_, kPresentationId); - blink::mojom::PresentationConnectionPtr connection; + PresentationConnectionPtr connection; MockPresentationConnection mock_presentation_connection; - mojo::Binding<blink::mojom::PresentationConnection> connection_binding( + mojo::Binding<PresentationConnection> connection_binding( &mock_presentation_connection, mojo::MakeRequest(&connection)); - blink::mojom::PresentationConnectionPtr receiver_connection; + PresentationConnectionPtr receiver_connection; auto request = mojo::MakeRequest(&receiver_connection); PresentationInfo expected(presentation_url1_, kPresentationId); - EXPECT_CALL(mock_delegate_, RegisterLocalPresentationConnectionRaw( - _, _, InfoEquals(expected), _)); + EXPECT_CALL(mock_delegate_, + ConnectToPresentation(_, _, InfoEquals(expected), _, _)); service_impl_->SetPresentationConnection( std::move(presentation_info), std::move(connection), std::move(request)); @@ -687,14 +629,14 @@ PresentationInfo expected(presentation_url1_, kPresentationId); // Client gets notified of receiver connections. - blink::mojom::PresentationConnectionPtr controller_connection; + PresentationConnectionPtr controller_connection; MockPresentationConnection mock_presentation_connection; - mojo::Binding<blink::mojom::PresentationConnection> connection_binding( + mojo::Binding<PresentationConnection> connection_binding( &mock_presentation_connection, mojo::MakeRequest(&controller_connection)); - blink::mojom::PresentationConnectionPtr receiver_connection; + PresentationConnectionPtr receiver_connection; EXPECT_CALL(mock_receiver, - OnReceiverConnectionAvailable(InfoEquals(expected))) + OnReceiverConnectionAvailable(InfoPtrEquals(expected), _, _)) .Times(1); callback.Run(PresentationInfo::New(expected), std::move(controller_connection), @@ -716,10 +658,9 @@ RegisterReceiverConnectionAvailableCallback(_)) .Times(0); - blink::mojom::PresentationControllerPtr controller_ptr; - controller_binding_.reset( - new mojo::Binding<blink::mojom::PresentationController>( - &mock_controller_, mojo::MakeRequest(&controller_ptr))); + PresentationControllerPtr controller_ptr; + controller_binding_.reset(new mojo::Binding<PresentationController>( + &mock_controller_, mojo::MakeRequest(&controller_ptr))); service_impl.controller_delegate_ = nullptr; service_impl.SetController(std::move(controller_ptr));
diff --git a/content/browser/renderer_host/delegated_frame_host.cc b/content/browser/renderer_host/delegated_frame_host.cc index a7f1432..d1f257e1 100644 --- a/content/browser/renderer_host/delegated_frame_host.cc +++ b/content/browser/renderer_host/delegated_frame_host.cc
@@ -402,8 +402,16 @@ } void DelegatedFrameHost::EvictDelegatedFrame() { - // Replaces the SurfaceLayer with a SolidColorLayer. - client_->DelegatedFrameHostGetLayer()->SetShowSolidColorContent(); + // Reset fallback and primary surfaces. + if (HasFallbackSurface()) { + client_->DelegatedFrameHostGetLayer()->SetFallbackSurfaceId( + viz::SurfaceId()); + } + if (HasPrimarySurface()) { + client_->DelegatedFrameHostGetLayer()->SetShowPrimarySurface( + viz::SurfaceId(), current_frame_size_in_dip_, GetGutterColor(), + cc::DeadlinePolicy::UseDefaultDeadline(), false); + } if (!HasSavedFrame()) return;
diff --git a/content/browser/renderer_host/media/media_stream_manager.cc b/content/browser/renderer_host/media/media_stream_manager.cc index 71f7853..eb94f21 100644 --- a/content/browser/renderer_host/media/media_stream_manager.cc +++ b/content/browser/renderer_host/media/media_stream_manager.cc
@@ -42,7 +42,7 @@ #include "content/browser/renderer_host/render_process_host_impl.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/content_browser_client.h" -#include "content/public/browser/desktop_media_id.h" +#include "content/public/browser/desktop_streams_registry.h" #include "content/public/browser/media_observer.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/web_contents_media_capture_id.h" @@ -588,7 +588,7 @@ // MediaStreamManager is deleted on the UI thread, after the IO thread has // been stopped. BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, - base::BindOnce(&MediaStreamManager::SetupRequest, + base::BindOnce(&MediaStreamManager::SetUpRequest, base::Unretained(this), label)); return label; } @@ -632,7 +632,7 @@ // MediaStreamManager is deleted on the UI thread, after the IO thread has // been stopped. BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, - base::BindOnce(&MediaStreamManager::SetupRequest, + base::BindOnce(&MediaStreamManager::SetUpRequest, base::Unretained(this), label)); } @@ -830,7 +830,7 @@ // MediaStreamManager is deleted on the UI thread, after the IO thread has // been stopped. BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, - base::BindOnce(&MediaStreamManager::SetupRequest, + base::BindOnce(&MediaStreamManager::SetUpRequest, base::Unretained(this), label)); } @@ -1083,11 +1083,11 @@ media::AudioParameters::UnavailableDeviceParams()))); } -void MediaStreamManager::SetupRequest(const std::string& label) { +void MediaStreamManager::SetUpRequest(const std::string& label) { DCHECK_CURRENTLY_ON(BrowserThread::IO); DeviceRequest* request = FindRequest(label); if (!request) { - DVLOG(1) << "SetupRequest label " << label << " doesn't exist!!"; + DVLOG(1) << "SetUpRequest label " << label << " doesn't exist!!"; return; // This can happen if the request has been canceled. } @@ -1099,13 +1099,15 @@ const bool is_web_contents_capture = audio_type == MEDIA_TAB_AUDIO_CAPTURE || video_type == MEDIA_TAB_VIDEO_CAPTURE; - if (is_web_contents_capture && !SetupTabCaptureRequest(request)) { - FinalizeRequestFailed(label, request, MEDIA_DEVICE_TAB_CAPTURE_FAILURE); + if (is_web_contents_capture) { + if (!SetUpTabCaptureRequest(request, label)) { + FinalizeRequestFailed(label, request, MEDIA_DEVICE_TAB_CAPTURE_FAILURE); + } return; } const bool is_screen_capture = video_type == MEDIA_DESKTOP_VIDEO_CAPTURE; - if (is_screen_capture && !SetupScreenCaptureRequest(request)) { + if (is_screen_capture && !SetUpScreenCaptureRequest(request)) { FinalizeRequestFailed(label, request, MEDIA_DEVICE_SCREEN_CAPTURE_FAILURE); return; } @@ -1118,7 +1120,7 @@ } // If no actual device capture is requested, set up the request with an // empty device list. - if (!SetupDeviceCaptureRequest(request, MediaDeviceEnumeration())) { + if (!SetUpDeviceCaptureRequest(request, MediaDeviceEnumeration())) { FinalizeRequestFailed(label, request, MEDIA_DEVICE_NO_HARDWARE); return; } @@ -1126,7 +1128,7 @@ ReadOutputParamsAndPostRequestToUI(label, request, MediaDeviceEnumeration()); } -bool MediaStreamManager::SetupDeviceCaptureRequest( +bool MediaStreamManager::SetUpDeviceCaptureRequest( DeviceRequest* request, const MediaDeviceEnumeration& enumeration) { DCHECK((request->audio_type() == MEDIA_DEVICE_AUDIO_CAPTURE || @@ -1156,7 +1158,8 @@ return true; } -bool MediaStreamManager::SetupTabCaptureRequest(DeviceRequest* request) { +bool MediaStreamManager::SetUpTabCaptureRequest(DeviceRequest* request, + const std::string& label) { DCHECK(request->audio_type() == MEDIA_TAB_AUDIO_CAPTURE || request->video_type() == MEDIA_TAB_VIDEO_CAPTURE); @@ -1169,17 +1172,56 @@ return false; } - // Customize controls for a WebContents based capture. - WebContentsMediaCaptureId web_id; - bool has_valid_device_id = - WebContentsMediaCaptureId::Parse(capture_device_id, &web_id); - if (!has_valid_device_id || - (request->audio_type() != MEDIA_TAB_AUDIO_CAPTURE && + if ((request->audio_type() != MEDIA_TAB_AUDIO_CAPTURE && request->audio_type() != MEDIA_NO_SERVICE) || (request->video_type() != MEDIA_TAB_VIDEO_CAPTURE && request->video_type() != MEDIA_NO_SERVICE)) { return false; } + + BrowserThread::PostTaskAndReplyWithResult( + BrowserThread::UI, FROM_HERE, + base::BindOnce(&MediaStreamManager::ResolveTabCaptureDeviceIdOnUIThread, + base::Unretained(this), capture_device_id, + request->requesting_process_id, + request->requesting_frame_id, + request->salt_and_origin.origin.GetURL()), + base::BindOnce( + &MediaStreamManager::FinishTabCaptureRequestSetupWithDeviceId, + base::Unretained(this), label)); + return true; +} + +DesktopMediaID MediaStreamManager::ResolveTabCaptureDeviceIdOnUIThread( + const std::string& capture_device_id, + int requesting_process_id, + int requesting_frame_id, + const GURL& origin) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + // Resolve DesktopMediaID for the specified device id. + return DesktopStreamsRegistry::GetInstance()->RequestMediaForStreamId( + capture_device_id, requesting_process_id, requesting_frame_id, origin, + nullptr); +} + +void MediaStreamManager::FinishTabCaptureRequestSetupWithDeviceId( + const std::string& label, + const DesktopMediaID& device_id) { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + + DeviceRequest* request = FindRequest(label); + if (!request) { + DVLOG(1) << "SetUpRequest label " << label << " doesn't exist!!"; + return; // This can happen if the request has been canceled. + } + + // Received invalid device id. + if (device_id.type != content::DesktopMediaID::TYPE_WEB_CONTENTS) { + FinalizeRequestFailed(label, request, MEDIA_DEVICE_TAB_CAPTURE_FAILURE); + return; + } + + content::WebContentsMediaCaptureId web_id = device_id.web_contents_id; web_id.disable_local_echo = request->controls.disable_local_echo; request->tab_capture_device_id = web_id.ToString(); @@ -1187,16 +1229,17 @@ request->CreateTabCaptureUIRequest(web_id.render_process_id, web_id.main_render_frame_id); - DVLOG(3) << "SetupTabCaptureRequest " - << ", {capture_device_id = " << capture_device_id << "}" + DVLOG(3) << "SetUpTabCaptureRequest " + << ", {capture_device_id = " << web_id.ToString() << "}" << ", {target_render_process_id = " << web_id.render_process_id << "}" << ", {target_render_frame_id = " << web_id.main_render_frame_id << "}"; - return true; + + ReadOutputParamsAndPostRequestToUI(label, request, MediaDeviceEnumeration()); } -bool MediaStreamManager::SetupScreenCaptureRequest(DeviceRequest* request) { +bool MediaStreamManager::SetUpScreenCaptureRequest(DeviceRequest* request) { DCHECK(request->audio_type() == MEDIA_DESKTOP_AUDIO_CAPTURE || request->video_type() == MEDIA_DESKTOP_VIDEO_CAPTURE); @@ -1493,7 +1536,7 @@ } } - if (!SetupDeviceCaptureRequest(request, enumeration)) + if (!SetUpDeviceCaptureRequest(request, enumeration)) FinalizeRequestFailed(label, request, MEDIA_DEVICE_NO_HARDWARE); else ReadOutputParamsAndPostRequestToUI(label, request, enumeration);
diff --git a/content/browser/renderer_host/media/media_stream_manager.h b/content/browser/renderer_host/media/media_stream_manager.h index c73c8d60..569745f 100644 --- a/content/browser/renderer_host/media/media_stream_manager.h +++ b/content/browser/renderer_host/media/media_stream_manager.h
@@ -49,6 +49,7 @@ #include "content/common/content_export.h" #include "content/common/media/media_devices.h" #include "content/common/media/media_stream_controls.h" +#include "content/public/browser/desktop_media_id.h" #include "content/public/browser/media_request_state.h" #include "content/public/common/media_stream_request.h" #include "media/base/video_facing.h" @@ -351,20 +352,30 @@ void DeleteRequest(const std::string& label); // Prepare the request with label |label| by starting device enumeration if // needed. - void SetupRequest(const std::string& label); + void SetUpRequest(const std::string& label); // Prepare |request| of type MEDIA_DEVICE_AUDIO_CAPTURE and/or // MEDIA_DEVICE_VIDEO_CAPTURE for being posted to the UI by parsing // StreamControls for requested device IDs. - bool SetupDeviceCaptureRequest(DeviceRequest* request, + bool SetUpDeviceCaptureRequest(DeviceRequest* request, const MediaDeviceEnumeration& enumeration); - // Prepare |request| of type MEDIA_TAB_AUDIO_CAPTURE and/or - // MEDIA_TAB_VIDEO_CAPTURE for being posted to the UI by parsing - // StreamControls for requested tab capture IDs. - bool SetupTabCaptureRequest(DeviceRequest* request); // Prepare |request| of type MEDIA_DESKTOP_AUDIO_CAPTURE and/or // MEDIA_DESKTOP_VIDEO_CAPTURE for being posted to the UI by parsing // StreamControls for the requested desktop ID. - bool SetupScreenCaptureRequest(DeviceRequest* request); + bool SetUpScreenCaptureRequest(DeviceRequest* request); + // Resolve the random device ID of tab capture on UI thread before proceeding + // with the tab capture UI request. + bool SetUpTabCaptureRequest(DeviceRequest* request, const std::string& label); + DesktopMediaID ResolveTabCaptureDeviceIdOnUIThread( + const std::string& capture_device_id, + int requesting_process_id, + int requesting_frame_id, + const GURL& origin); + // Prepare |request| of type MEDIA_TAB_AUDIO_CAPTURE and/or + // MEDIA_TAB_VIDEO_CAPTURE for being posted to the UI after the requested + // tab capture IDs are resolved from registry. + void FinishTabCaptureRequestSetupWithDeviceId( + const std::string& label, + const DesktopMediaID& device_id); // Called when a request has been setup and devices have been enumerated if // needed. void ReadOutputParamsAndPostRequestToUI(
diff --git a/content/browser/scheduler/responsiveness/OWNERS b/content/browser/scheduler/responsiveness/OWNERS new file mode 100644 index 0000000..8b3b15d --- /dev/null +++ b/content/browser/scheduler/responsiveness/OWNERS
@@ -0,0 +1,2 @@ +erikchen@chromium.org +tdresser@chromium.org
diff --git a/content/browser/scheduler/responsiveness/README b/content/browser/scheduler/responsiveness/README new file mode 100644 index 0000000..68ee4d9 --- /dev/null +++ b/content/browser/scheduler/responsiveness/README
@@ -0,0 +1,35 @@ +The classes in this folder estimate the responsiveness of Chrome by measuring +execution latency on the UI and IO threads of the browser process. + +There are four types of work executed on the UI and IO threads. +1) Both the UI and IO threads can have tasks posted to them via the Task + Scheduler [e.g. via content::BrowserThread::PostTask]. +2) The UI thread processes native events directly from the message loop + [NSEvents on macOS, MSGs on Windows, InputEvents on Android, XEvents on + X11, etc.] +3) The IO thread's message pump processes IPCs by listening on data channels + [e.g. fds] and waking up on available data. +4) The UI thread's message loop may process other platform-specific sources. + +Execution latency is a measure of the duration between when a task or event is +scheduled or created, and when it finishes executing. We measure this for (1) +and (2) but not (3) and (4). More details: + +1) Record TimeTicks::Now() when the event is scheduled and compare to + TimeTicks::Now() when the event finishes execution. +2) All native events have a creation timestamp. Compare that to + TimeTicks::Now() when the event finishes execution. +3) There's no good solution here, since the current wire format for IPCs does + not record the time at which the IPC was written to the data channel. The + time between reading from the data channel and finishing execution is + typically small, as heavy tasks are supposed to be dispatched off the IO + thread. +4) There is no consistent way to measure the execution latency of work that + is neither a task nor an event. If individual sources prove to be + a source of non-responsiveness, they will need to be addressed on a + case-by-case basis. + +Note: As long as there are any tasks or events queued, jank caused by (3) or +(4) will be accounted for, as it will show up as increased queueing time. + +Design doc: https://docs.google.com/document/d/1vDSGFvJblh7yJ3U3RVB_7qZLubyfTbQdQjuN1GoUNkc/edit
diff --git a/content/browser/scheduler/responsiveness/calculator.cc b/content/browser/scheduler/responsiveness/calculator.cc new file mode 100644 index 0000000..e042113 --- /dev/null +++ b/content/browser/scheduler/responsiveness/calculator.cc
@@ -0,0 +1,216 @@ +// 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 "content/browser/scheduler/responsiveness/calculator.h" + +#include <algorithm> +#include <set> + +#include "content/public/browser/browser_thread.h" + +namespace responsiveness { + +namespace { + +// We divide the measurement interval into discretized time slices. +// Each slice is marked as janky if it contained a janky task. A janky task is +// one whose execution latency is greater than kJankThreshold. +constexpr base::TimeDelta kMeasurementInterval = + base::TimeDelta::FromSeconds(30); + +// A task or event longer than kJankThreshold is considered janky. +constexpr base::TimeDelta kJankThreshold = + base::TimeDelta::FromMilliseconds(100); + +// If there have been no events/tasks on the UI thread for a significant period +// of time, it's likely because Chrome was suspended. +// This value is copied from queueing_time_estimator.cc:kInvalidPeriodThreshold. +constexpr base::TimeDelta kSuspendInterval = base::TimeDelta::FromSeconds(30); + +// Given a |jank|, finds each janky slice between |start_time| and |end_time|, +// and adds it to |janky_slices|. +void AddJankySlices(std::set<int>* janky_slices, + const Calculator::Jank& jank, + base::TimeTicks start_time, + base::TimeTicks end_time) { + // Ignore the first jank threshold, since that's the part of the task/event + // that wasn't janky. + base::TimeTicks jank_start = jank.start_time + kJankThreshold; + + // Bound by |start_time| and |end_time|. + jank_start = std::max(jank_start, start_time); + base::TimeTicks jank_end = std::min(jank.end_time, end_time); + + // Find each janky slice, and add it to |janky_slices|. + while (jank_start < jank_end) { + // Convert |jank_start| to a slice label. + int label = (jank_start - start_time) / kJankThreshold; + janky_slices->insert(label); + + jank_start += kJankThreshold; + } +} + +} // namespace + +Calculator::Jank::Jank(base::TimeTicks start_time, base::TimeTicks end_time) + : start_time(start_time), end_time(end_time) { + DCHECK_LE(start_time, end_time); +} + +Calculator::Calculator() + : last_calculation_time_(base::TimeTicks::Now()), + most_recent_activity_time_(last_calculation_time_) {} +Calculator::~Calculator() = default; + +void Calculator::TaskOrEventFinishedOnUIThread(base::TimeTicks schedule_time, + base::TimeTicks finish_time) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + if (finish_time - schedule_time >= kJankThreshold) { + GetJanksOnUIThread().emplace_back(schedule_time, finish_time); + } + + // We rely on the assumption that |finish_time| is the current time. + CalculateResponsivenessIfNecessary(/*current_time=*/finish_time); +} + +void Calculator::TaskOrEventFinishedOnIOThread(base::TimeTicks schedule_time, + base::TimeTicks finish_time) { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + if (finish_time - schedule_time >= kJankThreshold) { + base::AutoLock lock(io_thread_lock_); + GetJanksOnIOThread().emplace_back(schedule_time, finish_time); + } +} + +void Calculator::EmitResponsiveness(int janky_slices) { + // TODO(erikchen): Emit an UMA metric. https://crbug.com/859155. +} + +base::TimeTicks Calculator::GetLastCalculationTime() { + return last_calculation_time_; +} + +void Calculator::CalculateResponsivenessIfNecessary( + base::TimeTicks current_time) { + base::TimeTicks last_activity_time = most_recent_activity_time_; + most_recent_activity_time_ = current_time; + + // We intentionally dump all data if it appears that Chrome was suspended. + // [e.g. machine is asleep, process is backgrounded on Android]. We don't have + // an explicit signal for this. Instead, we rely on the assumption that when + // Chrome is not suspended, there is a steady stream of tasks and events on + // the UI thread. If there's been a significant amount of time since the last + // calculation, then it's likely because Chrome was suspended. + if (current_time - last_activity_time > kSuspendInterval) { + last_calculation_time_ = current_time; + GetJanksOnUIThread().clear(); + { + base::AutoLock lock(io_thread_lock_); + GetJanksOnIOThread().clear(); + } + return; + } + + base::TimeDelta time_since_last_calculation = + current_time - last_calculation_time_; + if (time_since_last_calculation <= kMeasurementInterval) + return; + + // At least |kMeasurementInterval| time has passed, so we want to move forward + // |last_calculation_time_| and make measurements based on janks in that + // interval. + int number_of_measurement_intervals = + time_since_last_calculation / kMeasurementInterval; + DCHECK(number_of_measurement_intervals >= 1); + + base::TimeTicks new_calculation_time = + last_calculation_time_ + + number_of_measurement_intervals * kMeasurementInterval; + + // Acquire the janks in the measurement interval from the UI and IO threads. + std::vector<JankList> janks_from_multiple_threads; + janks_from_multiple_threads.push_back( + TakeJanksOlderThanTime(&GetJanksOnUIThread(), new_calculation_time)); + { + base::AutoLock lock(io_thread_lock_); + janks_from_multiple_threads.push_back( + TakeJanksOlderThanTime(&GetJanksOnIOThread(), new_calculation_time)); + } + + CalculateResponsiveness(std::move(janks_from_multiple_threads), + last_calculation_time_, new_calculation_time); + + last_calculation_time_ = new_calculation_time; +} + +void Calculator::CalculateResponsiveness( + std::vector<JankList> janks_from_multiple_threads, + base::TimeTicks start_time, + base::TimeTicks end_time) { + while (start_time < end_time) { + base::TimeTicks current_interval_end_time = + start_time + kMeasurementInterval; + + // We divide the current measurement interval into slices. Each slice is + // given a monotonically increasing label, from 0 to |kNumberOfSlices - 1|. + // Example [all times in milliseconds since UNIX epoch]: + // The measurement interval is [50135, 80135]. + // The slice [50135, 50235] is labeled 0. + // The slice [50235, 50335] is labeled 1. + // ... + // The slice [80035, 80135] is labeled 299. + std::set<int> janky_slices; + + for (const JankList& janks : janks_from_multiple_threads) { + for (const Jank& jank : janks) { + AddJankySlices(&janky_slices, jank, start_time, + current_interval_end_time); + } + } + + EmitResponsiveness(janky_slices.size()); + + start_time = current_interval_end_time; + } +} + +Calculator::JankList& Calculator::GetJanksOnUIThread() { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + return janks_on_ui_thread_; +} + +Calculator::JankList& Calculator::GetJanksOnIOThread() { + io_thread_lock_.AssertAcquired(); + return janks_on_io_thread_; +} + +Calculator::JankList Calculator::TakeJanksOlderThanTime( + JankList* janks, + base::TimeTicks end_time) { + // Copy all janks with Jank.start_time < |end_time|. + auto it = + std::lower_bound(janks->begin(), janks->end(), end_time, + [](const Jank& jank, const base::TimeTicks& end_time) { + return jank.start_time < end_time; + }); + + // We don't need to remove any Janks either, since Jank.end_time >= + // Jank.start_time. + if (it == janks->begin()) + return JankList(); + + JankList janks_to_return(janks->begin(), it); + + // Remove all janks with Jank.end_time < |end_time|. + auto first_jank_to_keep = + std::lower_bound(janks->begin(), janks->end(), end_time, + [](const Jank& jank, const base::TimeTicks& end_time) { + return jank.end_time < end_time; + }); + janks->erase(janks->begin(), first_jank_to_keep); + return janks_to_return; +} + +} // namespace responsiveness
diff --git a/content/browser/scheduler/responsiveness/calculator.h b/content/browser/scheduler/responsiveness/calculator.h new file mode 100644 index 0000000..be09565f4 --- /dev/null +++ b/content/browser/scheduler/responsiveness/calculator.h
@@ -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. + +#ifndef CONTENT_BROWSER_SCHEDULER_RESPONSIVENESS_CALCULATOR_H_ +#define CONTENT_BROWSER_SCHEDULER_RESPONSIVENESS_CALCULATOR_H_ + +#include <vector> + +#include "base/macros.h" +#include "base/synchronization/lock.h" +#include "base/time/time.h" +#include "content/common/content_export.h" + +namespace responsiveness { + +// This class receives execution latency on events and tasks, and uses that to +// estimate responsiveness. +// +// All members are UI-thread affine, with the exception of +// |janks_on_io_thread_| which is protected by |io_thread_lock_|. +class CONTENT_EXPORT Calculator { + public: + Calculator(); + virtual ~Calculator(); + + // Must be called from the UI thread. + void TaskOrEventFinishedOnUIThread(base::TimeTicks schedule_time, + base::TimeTicks finish_time); + + // Must be called from the IO thread. + void TaskOrEventFinishedOnIOThread(base::TimeTicks schedule_time, + base::TimeTicks finish_time); + + // Each janking task/event is fully defined by |start_time| and |end_time|. + // Note that |duration| = |end_time| - |start_time|. + struct Jank { + Jank(base::TimeTicks start_time, base::TimeTicks end_time); + + base::TimeTicks start_time; + base::TimeTicks end_time; + }; + + protected: + // Emits an UMA metric for responsiveness of a single measurement interval. + // Exposed for testing. + virtual void EmitResponsiveness(int janky_slices); + + // Exposed for testing. + base::TimeTicks GetLastCalculationTime(); + + private: + using JankList = std::vector<Jank>; + + // If sufficient time has passed since the last calculation, then calculate + // responsiveness again and update |last_calculation_time_|. + // + // We only trigger this from the UI thread since triggering it from the IO + // thread would require us to grab the lock, which could cause contention. We + // only need this to trigger every 30s or so, and we generally expect there to + // be some activity on the UI thread if Chrome is actually in use. + void CalculateResponsivenessIfNecessary(base::TimeTicks current_time); + + // Responsiveness is calculated by: + // 1) Discretizing time into small intervals. + // 2) In each interval, looking to see if there is a Janky event. If so, the + // interval is marked as |janky|. + // 3) Computing the percentage of intervals that are janky. + // The caller guarantees that Jank.end_time < |end_time|. + // + // This method intentionally takes a std::vector<JankList>, as we may want to + // extend it in the future to take JankLists from other threads/processes. + void CalculateResponsiveness( + std::vector<JankList> janks_from_multiple_threads, + base::TimeTicks start_time, + base::TimeTicks end_time); + + // Accessor for |janks_on_ui_thread_|. Must be called from the UI thread. + JankList& GetJanksOnUIThread(); + + // Accessor for |janks_on_io_thread_|. Requires that |io_thread_lock_| has + // already been taken. May be called from any thread. + JankList& GetJanksOnIOThread(); + + // |janks| must be sorted by Jank.end_time. This method modifies |janks| to + // remove all janks older than |end_time|, and returns those. + JankList TakeJanksOlderThanTime(JankList* janks, base::TimeTicks end_time); + + // This should only be accessed via the accessor, which checks that the caller + // is on the UI thread. + JankList janks_on_ui_thread_; + + // We expect there to be low contention and this lock to cause minimal + // overhead. If performance of this lock proves to be a problem, we can move + // to a lock-free data structure. + base::Lock io_thread_lock_; + + // This should only be accessed via the accessor, which checks that + // |io_thread_lock_| has been acquired. + JankList janks_on_io_thread_; + + // The last time at which metrics were emitted. All janks older than this time + // have been consumed. Newer janks are still in their JankLists waiting to be + // consumed. + base::TimeTicks last_calculation_time_; + + // This class keeps track of the time at which any activity occurred on the UI + // thread. If a sufficiently long period of time passes without any activity, + // then it's assumed that the process was suspended. In this case, we should + // not emit any responsiveness metrics. + // + // Note that the process may be suspended while a task or event is being + // executed, so a very long execution time should be treated similarly. + base::TimeTicks most_recent_activity_time_; + + DISALLOW_COPY_AND_ASSIGN(Calculator); +}; + +} // namespace responsiveness + +#endif // CONTENT_BROWSER_SCHEDULER_RESPONSIVENESS_CALCULATOR_H_
diff --git a/content/browser/scheduler/responsiveness/calculator_unittest.cc b/content/browser/scheduler/responsiveness/calculator_unittest.cc new file mode 100644 index 0000000..351e0da --- /dev/null +++ b/content/browser/scheduler/responsiveness/calculator_unittest.cc
@@ -0,0 +1,213 @@ +// 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 "content/browser/scheduler/responsiveness/calculator.h" + +#include "content/public/test/test_browser_thread_bundle.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace responsiveness { + +namespace { +// Copied from calculator.cc. +constexpr int kMeasurementIntervalInMs = 30 * 1000; +constexpr int kJankThresholdInMs = 100; +} // namespace + +class FakeCalculator : public Calculator { + public: + std::vector<int>& Emissions() { return janky_slices_; } + + void EmitResponsiveness(int janky_slices) override { + janky_slices_.push_back(janky_slices); + } + + using Calculator::GetLastCalculationTime; + + private: + std::vector<int> janky_slices_; +}; + +class ResponsivenessCalculatorTest : public testing::Test { + public: + void SetUp() override { + calculator_ = std::make_unique<FakeCalculator>(); + last_calculation_time_ = calculator_->GetLastCalculationTime(); + } + + void AddEventUI(int schedule_time_in_ms, int finish_time_in_ms) { + calculator_->TaskOrEventFinishedOnUIThread( + last_calculation_time_ + + base::TimeDelta::FromMilliseconds(schedule_time_in_ms), + last_calculation_time_ + + base::TimeDelta::FromMilliseconds(finish_time_in_ms)); + } + + void AddEventIO(int schedule_time_in_ms, int finish_time_in_ms) { + calculator_->TaskOrEventFinishedOnIOThread( + last_calculation_time_ + + base::TimeDelta::FromMilliseconds(schedule_time_in_ms), + last_calculation_time_ + + base::TimeDelta::FromMilliseconds(finish_time_in_ms)); + } + + void TriggerCalculation() { + AddEventUI(kMeasurementIntervalInMs + 1, kMeasurementIntervalInMs + 2); + last_calculation_time_ = calculator_->GetLastCalculationTime(); + } + + protected: + // This member sets up BrowserThread::IO and BrowserThread::UI. It must be the + // first member, as other members may depend on these abstractions. + content::TestBrowserThreadBundle test_browser_thread_bundle_; + + std::unique_ptr<FakeCalculator> calculator_; + base::TimeTicks last_calculation_time_; +}; + +// A single event of length slightly longer than kJankThresholdInMs. +TEST_F(ResponsivenessCalculatorTest, ShortJank) { + AddEventUI(40, 40 + kJankThresholdInMs + 5); + TriggerCalculation(); + + ASSERT_EQ(1u, calculator_->Emissions().size()); + EXPECT_EQ(1, calculator_->Emissions()[0]); +} + +// A single event of length slightly longer than 10 * kJankThresholdInMs. +TEST_F(ResponsivenessCalculatorTest, LongJank) { + AddEventUI(40, 40 + 10 * kJankThresholdInMs + 5); + TriggerCalculation(); + + ASSERT_EQ(1u, calculator_->Emissions().size()); + EXPECT_EQ(10, calculator_->Emissions()[0]); +} + +// Events that last less than 100ms do not jank, regardless of start time. +TEST_F(ResponsivenessCalculatorTest, NoJank) { + int base_time = 30; + for (int i = 0; i < kJankThresholdInMs; ++i) { + AddEventUI(base_time, base_time + i); + } + + base_time += kJankThresholdInMs; + for (int i = 0; i < kJankThresholdInMs; ++i) { + AddEventUI(base_time + i, base_time + 2 * i); + } + + TriggerCalculation(); + ASSERT_EQ(1u, calculator_->Emissions().size()); + EXPECT_EQ(0, calculator_->Emissions()[0]); +} + +// 10 Jank events, but very closely overlapping. Time slices are discretized and +// fixed, e.g. [0 100] [100 200] [200 300]. In this test, the events all start +// in the [0 100] slice and end in the [100 200] slice. All of them end up +// marking the [100 200] slice as janky. +TEST_F(ResponsivenessCalculatorTest, OverlappingJank) { + int base_time = 30; + for (int i = 0; i < 10; ++i) { + AddEventUI(base_time, base_time + kJankThresholdInMs + 10); + } + + TriggerCalculation(); + ASSERT_EQ(1u, calculator_->Emissions().size()); + EXPECT_EQ(1, calculator_->Emissions()[0]); +} + +// UI thread has 3 jank events on slices 1, 2, 3 +// IO thread has 3 jank events on slices 3, 4, 5, +// There should be a total of 5 jank events. +TEST_F(ResponsivenessCalculatorTest, OverlappingJankMultipleThreads) { + int base_time = 105; + for (int i = 0; i < 3; ++i) { + AddEventUI(base_time + i * kJankThresholdInMs, + base_time + (i + 1) * kJankThresholdInMs + 10); + } + + base_time = 305; + for (int i = 0; i < 3; ++i) { + AddEventIO(base_time + i * kJankThresholdInMs, + base_time + (i + 1) * kJankThresholdInMs + 10); + } + + TriggerCalculation(); + ASSERT_EQ(1u, calculator_->Emissions().size()); + EXPECT_EQ(5, calculator_->Emissions()[0]); +} + +// Three janks, each of length 2, separated by some shorter events. +TEST_F(ResponsivenessCalculatorTest, SeparatedJanks) { + int base_time = 105; + + for (int i = 0; i < 3; ++i) { + AddEventUI(base_time, base_time + 1); + AddEventUI(base_time, base_time + 2 * kJankThresholdInMs + 1); + base_time += 10 * kJankThresholdInMs; + } + TriggerCalculation(); + + ASSERT_EQ(1u, calculator_->Emissions().size()); + EXPECT_EQ(6, calculator_->Emissions()[0]); +} + +TEST_F(ResponsivenessCalculatorTest, MultipleTrigger) { + int base_time = 105; + + // 3 Janks, then trigger, then repeat. + for (int i = 0; i < 10; ++i) { + for (int j = 0; j < 3; ++j) { + AddEventUI(base_time, base_time + 3 * kJankThresholdInMs + 1); + base_time += 3 * kJankThresholdInMs; + } + TriggerCalculation(); + } + + ASSERT_EQ(10u, calculator_->Emissions().size()); + for (int i = 0; i < 10; ++i) { + EXPECT_EQ(9, calculator_->Emissions()[i]); + } +} + +// A long delay means that the machine likely went to sleep. +TEST_F(ResponsivenessCalculatorTest, LongDelay) { + int base_time = 105; + AddEventUI(base_time, base_time + 3 * kJankThresholdInMs + 1); + base_time += 10 * kMeasurementIntervalInMs; + AddEventUI(base_time, base_time + 1); + + ASSERT_EQ(0u, calculator_->Emissions().size()); +} + +// A long event means that the machine likely went to sleep. +TEST_F(ResponsivenessCalculatorTest, LongEvent) { + int base_time = 105; + AddEventUI(base_time, base_time + 10 * kMeasurementIntervalInMs); + + ASSERT_EQ(0u, calculator_->Emissions().size()); +} + +// An event that crosses a measurement interval boundary should count towards +// both measurement intervals. +TEST_F(ResponsivenessCalculatorTest, EventCrossesBoundary) { + // Dummy event so that Calculator doesn't think the process is suspended. + AddEventUI(0.5 * kMeasurementIntervalInMs, 0.5 * kMeasurementIntervalInMs); + + // The event goes from [29801, 30150]. It should count as 1 jank in the first + // measurement interval and 2 in the second. + AddEventUI(kMeasurementIntervalInMs - 2 * kJankThresholdInMs + 1, + kMeasurementIntervalInMs + 1.5 * kJankThresholdInMs); + + // Dummy event so that Calculator doesn't think the process is suspended. + AddEventUI(1.5 * kMeasurementIntervalInMs, 1.5 * kMeasurementIntervalInMs); + + // Trigger another calculation. + AddEventUI(2 * kMeasurementIntervalInMs + 1, + 2 * kMeasurementIntervalInMs + 1); + ASSERT_EQ(2u, calculator_->Emissions().size()); + EXPECT_EQ(1, calculator_->Emissions()[0]); + EXPECT_EQ(2, calculator_->Emissions()[1]); +} + +} // namespace responsiveness
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc index ab6a04d6..5740fc2e41 100644 --- a/content/browser/storage_partition_impl.cc +++ b/content/browser/storage_partition_impl.cc
@@ -687,23 +687,8 @@ } network::mojom::NetworkContext* StoragePartitionImpl::GetNetworkContext() { - if (!network_context_.is_bound() || network_context_.encountered_error()) { - network_context_ = GetContentClient()->browser()->CreateNetworkContext( - browser_context_, is_in_memory_, relative_partition_path_); - if (!network_context_) { - // TODO(mmenke): Remove once https://crbug.com/827928 is fixed. - CHECK(url_request_context_); - - DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService)); - DCHECK(!network_context_owner_); - network_context_owner_ = std::make_unique<NetworkContextOwner>(); - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::BindOnce(&NetworkContextOwner::Initialize, - base::Unretained(network_context_owner_.get()), - MakeRequest(&network_context_), url_request_context_)); - } - } + if (!network_context_.is_bound()) + InitNetworkContext(); return network_context_.get(); } @@ -1237,6 +1222,26 @@ std::move(callback)); } +void StoragePartitionImpl::InitNetworkContext() { + network_context_ = GetContentClient()->browser()->CreateNetworkContext( + browser_context_, is_in_memory_, relative_partition_path_); + if (!network_context_) { + // TODO(mmenke): Remove once https://crbug.com/827928 is fixed. + CHECK(url_request_context_); + + DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService)); + DCHECK(!network_context_owner_); + network_context_owner_ = std::make_unique<NetworkContextOwner>(); + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::BindOnce(&NetworkContextOwner::Initialize, + base::Unretained(network_context_owner_.get()), + MakeRequest(&network_context_), url_request_context_)); + } + network_context_.set_connection_error_handler(base::BindOnce( + &StoragePartitionImpl::InitNetworkContext, weak_factory_.GetWeakPtr())); +} + network::mojom::URLLoaderFactory* StoragePartitionImpl::GetURLLoaderFactoryForBrowserProcessInternal() { // Create the URLLoaderFactory as needed, but make sure not to reuse a
diff --git a/content/browser/storage_partition_impl.h b/content/browser/storage_partition_impl.h index e79f8775..c7314b00 100644 --- a/content/browser/storage_partition_impl.h +++ b/content/browser/storage_partition_impl.h
@@ -274,6 +274,10 @@ // storage configuration info. void GetQuotaSettings(storage::OptionalQuotaSettingsCallback callback); + // Called to initialize |network_context_| when |GetNetworkContext()| is + // first called or there is an error. + void InitNetworkContext(); + network::mojom::URLLoaderFactory* GetURLLoaderFactoryForBrowserProcessInternal();
diff --git a/content/browser/url_loader_factory_getter.cc b/content/browser/url_loader_factory_getter.cc index d3f0380..d34adb3 100644 --- a/content/browser/url_loader_factory_getter.cc +++ b/content/browser/url_loader_factory_getter.cc
@@ -111,13 +111,18 @@ // ----------------------------------------------------------------------------- -URLLoaderFactoryGetter::URLLoaderFactoryGetter() {} +URLLoaderFactoryGetter::URLLoaderFactoryGetter() : weak_factory_(this) {} void URLLoaderFactoryGetter::Initialize(StoragePartitionImpl* partition) { DCHECK(partition); - DCHECK(!pending_network_factory_request_.is_pending()); - partition_ = partition; + Reinitialize(); +} + +void URLLoaderFactoryGetter::Reinitialize() { + if (!partition_) + return; + DCHECK(!pending_network_factory_request_.is_pending()); network::mojom::URLLoaderFactoryPtr network_factory; pending_network_factory_request_ = MakeRequest(&network_factory); @@ -128,7 +133,8 @@ BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, - base::BindOnce(&URLLoaderFactoryGetter::InitializeOnIOThread, this, + base::BindOnce(&URLLoaderFactoryGetter::InitializeOnIOThread, + weak_factory_.GetWeakPtr(), network_factory.PassInterface())); } @@ -166,16 +172,18 @@ if (test_factory_) return test_factory_; - if (!network_factory_.is_bound() || network_factory_.encountered_error()) { - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::BindOnce( - &URLLoaderFactoryGetter::HandleNetworkFactoryRequestOnUIThread, - this, mojo::MakeRequest(&network_factory_))); - } + if (!network_factory_.is_bound()) + HandleURLLoaderFactoryConnectionError(); return network_factory_.get(); } +void URLLoaderFactoryGetter::HandleURLLoaderFactoryConnectionError() { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::BindOnce(&URLLoaderFactoryGetter::Reinitialize, this)); +} + void URLLoaderFactoryGetter::CloneNetworkFactory( network::mojom::URLLoaderFactoryRequest network_factory_request) { DCHECK_CURRENTLY_ON(BrowserThread::IO); @@ -201,18 +209,18 @@ void URLLoaderFactoryGetter::FlushNetworkInterfaceOnIOThreadForTesting() { DCHECK_CURRENTLY_ON(BrowserThread::UI); base::RunLoop run_loop; - BrowserThread::PostTaskAndReply( + BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, base::BindOnce(&URLLoaderFactoryGetter::FlushNetworkInterfaceForTesting, - this), - run_loop.QuitClosure()); + this, run_loop.QuitClosure())); run_loop.Run(); } -void URLLoaderFactoryGetter::FlushNetworkInterfaceForTesting() { +void URLLoaderFactoryGetter::FlushNetworkInterfaceForTesting( + base::OnceClosure callback) { DCHECK_CURRENTLY_ON(BrowserThread::IO); if (network_factory_) - network_factory_.FlushForTesting(); + network_factory_.FlushAsyncForTesting(std::move(callback)); } URLLoaderFactoryGetter::~URLLoaderFactoryGetter() {} @@ -220,6 +228,9 @@ void URLLoaderFactoryGetter::InitializeOnIOThread( network::mojom::URLLoaderFactoryPtrInfo network_factory) { network_factory_.Bind(std::move(network_factory)); + network_factory_.set_connection_error_handler(base::BindOnce( + &URLLoaderFactoryGetter::HandleURLLoaderFactoryConnectionError, + weak_factory_.GetWeakPtr())); } void URLLoaderFactoryGetter::HandleNetworkFactoryRequestOnUIThread(
diff --git a/content/browser/url_loader_factory_getter.h b/content/browser/url_loader_factory_getter.h index 39bfbab5..af8d381 100644 --- a/content/browser/url_loader_factory_getter.h +++ b/content/browser/url_loader_factory_getter.h
@@ -107,8 +107,15 @@ // The pointer shouldn't be cached. network::mojom::URLLoaderFactory* GetURLLoaderFactory(); - // Call |network_factory_.FlushForTesting()|. For test use only. - void FlushNetworkInterfaceForTesting(); + // Called when there is a connection error on |network_factory_|. + void HandleURLLoaderFactoryConnectionError(); + + // Called either during initialization or when an error occurs. + void Reinitialize(); + + // Call |network_factory_.FlushForTesting()|. For test use only. When the + // flush is complete, |callback| will be called. + void FlushNetworkInterfaceForTesting(base::OnceClosure callback); // Bound with appropriate URLLoaderFactories at HandleFactoryRequests(). network::mojom::URLLoaderFactoryRequest pending_network_factory_request_; @@ -122,6 +129,8 @@ // when it's going away. StoragePartitionImpl* partition_ = nullptr; + base::WeakPtrFactory<URLLoaderFactoryGetter> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(URLLoaderFactoryGetter); };
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index 26384f8..828082de 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -802,6 +802,8 @@ IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(WebContentsImpl, message, render_view_host) IPC_MESSAGE_HANDLER(ViewHostMsg_DidFirstVisuallyNonEmptyPaint, OnFirstVisuallyNonEmptyPaint) + IPC_MESSAGE_HANDLER(ViewHostMsg_DidCommitAndDrawCompositorFrame, + OnCommitAndDrawCompositorFrame) IPC_MESSAGE_HANDLER(ViewHostMsg_GoToEntryAtOffset, OnGoToEntryAtOffset) IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateZoomLimits, OnUpdateZoomLimits) IPC_MESSAGE_HANDLER(ViewHostMsg_PageScaleFactorChanged, @@ -4753,6 +4755,12 @@ } } +void WebContentsImpl::OnCommitAndDrawCompositorFrame( + RenderViewHostImpl* source) { + for (auto& observer : observers_) + observer.DidCommitAndDrawCompositorFrame(); +} + void WebContentsImpl::NotifyBeforeFormRepostWarningShow() { for (auto& observer : observers_) observer.BeforeFormRepostWarningShow();
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h index d16a991..71ae1bf 100644 --- a/content/browser/web_contents/web_contents_impl.h +++ b/content/browser/web_contents/web_contents_impl.h
@@ -1223,6 +1223,7 @@ void OnUpdateFaviconURL(RenderFrameHostImpl* source, const std::vector<FaviconURL>& candidates); void OnFirstVisuallyNonEmptyPaint(RenderViewHostImpl* source); + void OnCommitAndDrawCompositorFrame(RenderViewHostImpl* source); void OnShowValidationMessage(RenderViewHostImpl* source, const gfx::Rect& anchor_in_root_view, const base::string16& main_text,
diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn index d02f2ea..53e9623af 100644 --- a/content/common/BUILD.gn +++ b/content/common/BUILD.gn
@@ -242,8 +242,6 @@ "possibly_associated_interface_ptr.h", "possibly_associated_interface_ptr_info.h", "possibly_associated_wrapper_shared_url_loader_factory.h", - "presentation/presentation_struct_traits.cc", - "presentation/presentation_struct_traits.h", "process_type.cc", "render_widget_surface_properties.cc", "render_widget_surface_properties.h",
diff --git a/content/common/android/gin_java_bridge_value.cc b/content/common/android/gin_java_bridge_value.cc index c34d0413..6f0d034 100644 --- a/content/common/android/gin_java_bridge_value.cc +++ b/content/common/android/gin_java_bridge_value.cc
@@ -59,7 +59,8 @@ return false; if (value->GetBlob().size() < sizeof(Header)) return false; - base::Pickle pickle(value->GetBlob().data(), value->GetBlob().size()); + base::Pickle pickle(reinterpret_cast<const char*>(value->GetBlob().data()), + value->GetBlob().size()); // Broken binary value: payload or header size is wrong if (!pickle.data() || pickle.size() - pickle.payload_size() != sizeof(Header)) return false; @@ -111,7 +112,8 @@ } GinJavaBridgeValue::GinJavaBridgeValue(const base::Value* value) - : pickle_(value->GetBlob().data(), value->GetBlob().size()) { + : pickle_(reinterpret_cast<const char*>(value->GetBlob().data()), + value->GetBlob().size()) { DCHECK(ContainsGinJavaBridgeValue(value)); }
diff --git a/content/common/presentation/OWNERS b/content/common/presentation/OWNERS deleted file mode 100644 index 27a12f5..0000000 --- a/content/common/presentation/OWNERS +++ /dev/null
@@ -1,7 +0,0 @@ -file://content/browser/presentation/OWNERS - -# For SECURITY_OWNERS review of Mojo typemaps. -per-file *_struct_traits*.*=set noparent -per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS -per-file *.typemap=set noparent -per-file *.typemap=file://ipc/SECURITY_OWNERS \ No newline at end of file
diff --git a/content/common/presentation/presentation.typemap b/content/common/presentation/presentation.typemap deleted file mode 100644 index f69f4453..0000000 --- a/content/common/presentation/presentation.typemap +++ /dev/null
@@ -1,12 +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. - -mojom = "//third_party/blink/public/platform/modules/presentation/presentation.mojom" -public_headers = [ "//content/public/common/presentation_connection_message.h" ] -traits_headers = - [ "//content/common/presentation/presentation_struct_traits.h" ] -deps = [ - "//url", -] -type_mappings = [ "blink.mojom.PresentationConnectionMessage=content::PresentationConnectionMessage[move_only]" ]
diff --git a/content/common/presentation/presentation_struct_traits.cc b/content/common/presentation/presentation_struct_traits.cc deleted file mode 100644 index 484a772a..0000000 --- a/content/common/presentation/presentation_struct_traits.cc +++ /dev/null
@@ -1,26 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/common/presentation/presentation_struct_traits.h" - -#include "url/mojom/url_gurl_mojom_traits.h" - -namespace mojo { - -bool UnionTraits<blink::mojom::PresentationConnectionMessageDataView, - content::PresentationConnectionMessage>:: - Read(blink::mojom::PresentationConnectionMessageDataView data, - content::PresentationConnectionMessage* out) { - if (data.is_message()) { - if (!data.ReadMessage(&(out->message))) { - return false; - } - } else { - if (!data.ReadData(&(out->data))) { - return false; - } - } - return true; -} -}
diff --git a/content/common/presentation/presentation_struct_traits.h b/content/common/presentation/presentation_struct_traits.h deleted file mode 100644 index 01e5e1a..0000000 --- a/content/common/presentation/presentation_struct_traits.h +++ /dev/null
@@ -1,49 +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 CONTENT_COMMON_PRESENTATION_PRESENTATION_STRUCT_TRAITS_H_ -#define CONTENT_COMMON_PRESENTATION_PRESENTATION_STRUCT_TRAITS_H_ - -#include <string> -#include <vector> - -#include "base/macros.h" -#include "base/optional.h" -#include "base/strings/string_util.h" -#include "content/public/common/presentation_connection_message.h" -#include "third_party/blink/public/platform/modules/presentation/presentation.mojom.h" -#include "url/mojom/url.mojom.h" - -namespace mojo { - -template <> -struct UnionTraits<blink::mojom::PresentationConnectionMessageDataView, - content::PresentationConnectionMessage> { - static blink::mojom::PresentationConnectionMessageDataView::Tag GetTag( - const content::PresentationConnectionMessage& message) { - return message.is_binary() - ? blink::mojom::PresentationConnectionMessageDataView::Tag::DATA - : blink::mojom::PresentationConnectionMessageDataView::Tag:: - MESSAGE; - } - - static const std::string& message( - const content::PresentationConnectionMessage& message) { - DCHECK(!message.is_binary()); - return message.message.value(); - } - - static const std::vector<uint8_t>& data( - const content::PresentationConnectionMessage& message) { - DCHECK(message.is_binary()); - return message.data.value(); - } - - static bool Read(blink::mojom::PresentationConnectionMessageDataView data, - content::PresentationConnectionMessage* out); -}; - -} // namespace mojo - -#endif // CONTENT_COMMON_PRESENTATION_PRESENTATION_STRUCT_TRAITS_H_
diff --git a/content/common/presentation/typemaps.gni b/content/common/presentation/typemaps.gni deleted file mode 100644 index dbc927c..0000000 --- a/content/common/presentation/typemaps.gni +++ /dev/null
@@ -1,5 +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. - -typemaps = [ "//content/common/presentation/presentation.typemap" ]
diff --git a/content/common/view_messages.h b/content/common/view_messages.h index 74d2df78..1c1cd39 100644 --- a/content/common/view_messages.h +++ b/content/common/view_messages.h
@@ -686,6 +686,9 @@ // after the frame widget has painted something. IPC_MESSAGE_ROUTED0(ViewHostMsg_DidFirstVisuallyNonEmptyPaint) +// Sent once the RenderWidgetCompositor issues a draw command. +IPC_MESSAGE_ROUTED0(ViewHostMsg_DidCommitAndDrawCompositorFrame) + // Sent in reply to ViewMsg_WaitForNextFrameForTests. IPC_MESSAGE_ROUTED0(ViewHostMsg_WaitForNextFrameForTests_ACK)
diff --git a/content/public/browser/BUILD.gn b/content/public/browser/BUILD.gn index cb9b7ba..13483e65 100644 --- a/content/public/browser/BUILD.gn +++ b/content/public/browser/BUILD.gn
@@ -101,6 +101,7 @@ "desktop_capture.h", "desktop_media_id.cc", "desktop_media_id.h", + "desktop_streams_registry.h", "devtools_agent_host.h", "devtools_agent_host_client.cc", "devtools_agent_host_client.h",
diff --git a/content/public/browser/desktop_streams_registry.h b/content/public/browser/desktop_streams_registry.h new file mode 100644 index 0000000..fdd29124 --- /dev/null +++ b/content/public/browser/desktop_streams_registry.h
@@ -0,0 +1,50 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_PUBLIC_BROWSER_DESKTOP_STREAMS_REGISTRY_H_ +#define CONTENT_PUBLIC_BROWSER_DESKTOP_STREAMS_REGISTRY_H_ + +#include "content/common/content_export.h" + +class GURL; + +namespace content { + +struct DesktopMediaID; + +// Interface to DesktopStreamsRegistry which is used to store accepted desktop +// media streams for Desktop Capture API. Single instance of this class is +// created at first time use. This should be called on UI thread. +class CONTENT_EXPORT DesktopStreamsRegistry { + public: + virtual ~DesktopStreamsRegistry() {} + + static DesktopStreamsRegistry* GetInstance(); + + // Adds new stream to the registry. Called by the implementation of + // desktopCapture.chooseDesktopMedia() API after user has approved access to + // |source| for the |origin|. Returns identifier of the new stream. + // |render_frame_id| refers to the RenderFrame requesting the stream. + virtual std::string RegisterStream(int render_process_id, + int render_frame_id, + const GURL& origin, + const DesktopMediaID& source, + const std::string& extension_name) = 0; + + // Validates stream identifier specified in getUserMedia(). Returns null + // DesktopMediaID if the specified |id| is invalid, i.e. wasn't generated + // using RegisterStream() or if it was generated for a different + // RenderFrame/origin. Otherwise returns ID of the source and removes it from + // the registry. + virtual DesktopMediaID RequestMediaForStreamId( + const std::string& id, + int render_process_id, + int render_frame_id, + const GURL& origin, + std::string* extension_name) = 0; +}; + +} // namespace content + +#endif // CONTENT_PUBLIC_BROWSER_DESKTOP_STREAMS_REGISTRY_H_
diff --git a/content/public/browser/presentation_service_delegate.h b/content/public/browser/presentation_service_delegate.h index 03202644..a6b7374 100644 --- a/content/public/browser/presentation_service_delegate.h +++ b/content/public/browser/presentation_service_delegate.h
@@ -12,8 +12,7 @@ #include "base/callback.h" #include "content/common/content_export.h" -#include "content/public/common/presentation_connection_message.h" -#include "media/base/media_controller.h" +#include "media/base/flinging_controller.h" #include "third_party/blink/public/platform/modules/presentation/presentation.mojom.h" namespace content { @@ -170,11 +169,11 @@ int render_frame_id, const std::string& presentation_id) = 0; - // Gets a MediaController for a given presentation ID. + // Gets a FlingingController for a given presentation ID. // |render_process_id|, |render_frame_id|: ID of originating frame. // |presentation_id|: The ID of the presentation for which we want a // Controller. - virtual std::unique_ptr<media::MediaController> GetMediaController( + virtual std::unique_ptr<media::FlingingController> GetFlingingController( int render_process_id, int render_frame_id, const std::string& presentation_id) = 0;
diff --git a/content/public/browser/web_contents_observer.h b/content/public/browser/web_contents_observer.h index 35dab31..c10ae50 100644 --- a/content/public/browser/web_contents_observer.h +++ b/content/public/browser/web_contents_observer.h
@@ -536,6 +536,11 @@ const std::string& interface_name, mojo::ScopedMessagePipeHandle* interface_pipe) {} + // Notifies that the RenderWidgetCompositor has issued a draw command. An + // observer can use this method to detect when Chrome visually updated a + // tab. + virtual void DidCommitAndDrawCompositorFrame() {} + // IPC::Listener implementation. // DEPRECATED: Use (i.e. override) the other overload instead: // virtual bool OnMessageReceived(const IPC::Message& message,
diff --git a/content/public/common/BUILD.gn b/content/public/common/BUILD.gn index f0cad2d..bf008317 100644 --- a/content/public/common/BUILD.gn +++ b/content/public/common/BUILD.gn
@@ -184,8 +184,6 @@ "persistent_notification_status.h", "platform_notification_data.cc", "platform_notification_data.h", - "presentation_connection_message.cc", - "presentation_connection_message.h", "previews_state.h", "process_type.h", "push_event_payload.h",
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index b74e10c..bcb5bc7e 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -239,7 +239,7 @@ // Mojo-based Session Storage. const base::Feature kMojoSessionStorage{"MojoSessionStorage", - base::FEATURE_DISABLED_BY_DEFAULT}; + base::FEATURE_ENABLED_BY_DEFAULT}; // Enables/disables the video capture service. const base::Feature kMojoVideoCapture {
diff --git a/content/public/common/presentation_connection_message.cc b/content/public/common/presentation_connection_message.cc deleted file mode 100644 index d8c0e58..0000000 --- a/content/public/common/presentation_connection_message.cc +++ /dev/null
@@ -1,44 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/public/common/presentation_connection_message.h" - -#include <utility> - -namespace content { - -PresentationConnectionMessage::PresentationConnectionMessage() = default; - -PresentationConnectionMessage::PresentationConnectionMessage( - std::string message) - : message(std::move(message)) {} - -PresentationConnectionMessage::PresentationConnectionMessage( - std::vector<uint8_t> data) - : data(std::move(data)) {} - -PresentationConnectionMessage::PresentationConnectionMessage( - const PresentationConnectionMessage& other) = default; - -PresentationConnectionMessage::PresentationConnectionMessage( - PresentationConnectionMessage&& other) noexcept = default; - -PresentationConnectionMessage::~PresentationConnectionMessage() {} - -bool PresentationConnectionMessage::operator==( - const PresentationConnectionMessage& other) const { - return this->data == other.data && this->message == other.message; -} - -PresentationConnectionMessage& PresentationConnectionMessage::operator=( - const PresentationConnectionMessage& other) = default; - -PresentationConnectionMessage& PresentationConnectionMessage::operator=( - PresentationConnectionMessage&& other) = default; - -bool PresentationConnectionMessage::is_binary() const { - return data.has_value(); -} - -} // namespace content
diff --git a/content/public/common/presentation_connection_message.h b/content/public/common/presentation_connection_message.h deleted file mode 100644 index 3beccc9..0000000 --- a/content/public/common/presentation_connection_message.h +++ /dev/null
@@ -1,51 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_PUBLIC_COMMON_PRESENTATION_CONNECTION_MESSAGE_H_ -#define CONTENT_PUBLIC_COMMON_PRESENTATION_CONNECTION_MESSAGE_H_ - -#include <stddef.h> // For size_t -#include <stdint.h> - -#include <string> -#include <vector> - -#include "base/optional.h" -#include "content/common/content_export.h" - -namespace content { - -// Represents a presentation connection message. If this is a text message, -// |data| is null; otherwise, |message| is null. Empty messages are allowed. -struct CONTENT_EXPORT PresentationConnectionMessage { - public: - // Constructs a new, untyped message (for Mojo). These messages are not valid - // and exactly one of |message| or |data| must be set. - PresentationConnectionMessage(); - // Copy constructor / assignment are necessary due to MediaRouter allowing - // multiple RouteMessageObserver instances per MediaRoute. - PresentationConnectionMessage(const PresentationConnectionMessage& other); - PresentationConnectionMessage(PresentationConnectionMessage&& other) noexcept; - // Constructs a text message from |message|. - explicit PresentationConnectionMessage(std::string message); - // Constructs a binary message from |data|. - explicit PresentationConnectionMessage(std::vector<uint8_t> data); - - ~PresentationConnectionMessage(); - - bool is_binary() const; - - bool operator==(const PresentationConnectionMessage& other) const; - PresentationConnectionMessage& operator=( - const PresentationConnectionMessage& other); - PresentationConnectionMessage& operator=( - PresentationConnectionMessage&& other); - - base::Optional<std::string> message; - base::Optional<std::vector<uint8_t>> data; -}; - -} // namespace content - -#endif // CONTENT_PUBLIC_COMMON_PRESENTATION_CONNECTION_MESSAGE_H_
diff --git a/content/public/renderer/BUILD.gn b/content/public/renderer/BUILD.gn index ea773ce..eb312e8 100644 --- a/content/public/renderer/BUILD.gn +++ b/content/public/renderer/BUILD.gn
@@ -55,7 +55,6 @@ "navigation_state.cc", "navigation_state.h", "pepper_plugin_instance.h", - "platform_event_observer.h", "plugin_instance_throttler.h", "render_accessibility.h", "render_frame.h", @@ -72,7 +71,6 @@ "render_view_observer.h", "render_view_observer_tracker.h", "render_view_visitor.h", - "renderer_gamepad_provider.h", "renderer_ppapi_host.h", "request_peer.h", "resource_dispatcher_delegate.h",
diff --git a/content/public/renderer/platform_event_observer.h b/content/public/renderer/platform_event_observer.h deleted file mode 100644 index ab80085..0000000 --- a/content/public/renderer/platform_event_observer.h +++ /dev/null
@@ -1,133 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_PUBLIC_RENDERER_PLATFORM_EVENT_OBSERVER_H_ -#define CONTENT_PUBLIC_RENDERER_PLATFORM_EVENT_OBSERVER_H_ - -#include "base/logging.h" -#include "base/macros.h" -#include "content/public/renderer/render_thread.h" -#include "content/public/renderer/render_thread_observer.h" - -namespace blink { -class WebPlatformEventListener; -} - -namespace content { - -// This class is used as a base class for PlatformEventObserver<ListenerType> to -// allow storing PlatformEventObserver<> with different typename in the same -// place. -class PlatformEventObserverBase { - public: - virtual ~PlatformEventObserverBase() { } - - // Methods that need to be exposed in PlatformEventObserverBase. Their purpose - // is described in PlatformEventObserver<>. - - virtual void Start(blink::WebPlatformEventListener* listener) = 0; - virtual void Stop() = 0; -}; - -// PlatformEventObserver<> defines the basic skeleton for an object requesting -// the browser process to start/stop listening to some platform/hardware events -// and observe the result. -// The results are received via IPC, assuming that the object was correctly -// registered as an observer via the constructor taking a RenderThread. -template <typename ListenerType> -class PlatformEventObserver : public PlatformEventObserverBase, - public RenderThreadObserver { - public: - // Creates a PlatformEventObserver that doesn't listen to responses from the - // browser process. Can be used for testing purposes or for observers that - // have other means to get their results. - PlatformEventObserver() - : is_observing_(false), - listener_(0) { - } - - // Creates a PlatformEventObserver that registers to the RenderThread in order - // to intercept the received IPC messages (via OnControlMessageReceived). If - // |thread| is null, it will not register. - explicit PlatformEventObserver(RenderThread* thread) - : is_observing_(false), - listener_(0) { - if (thread) - thread->AddObserver(this); - } - - // The observer must automatically stop observing when destroyed in case it - // did not stop before. Implementations of PlatformEventObserver must do - // so by calling StopIfObserving() from their destructors. - ~PlatformEventObserver() override { - // If this assert fails, the derived destructor failed to invoke - // StopIfObserving(). - DCHECK(!is_observing()); - } - - // Called when a new IPC message is received. Must be used to listen to the - // responses from the browser process if any expected. - bool OnControlMessageReceived(const IPC::Message& msg) override { - return false; - } - - // Start observing. Will request the browser process to start listening to the - // events. |listener| will receive any response from the browser process. - // Note: should not be called if already observing. - void Start(blink::WebPlatformEventListener* listener) override { - DCHECK(!is_observing()); - listener_ = static_cast<ListenerType*>(listener); - is_observing_ = true; - - SendStartMessage(); - } - - // Stop observing. Will let the browser know that it doesn't need to observe - // anymore. - void Stop() override { - DCHECK(is_observing()); - listener_ = 0; - is_observing_ = false; - - SendStopMessage(); - } - - protected: - // This method is expected to send an IPC to the browser process to let it - // know that it should start observing. - // It is expected for subclasses to override it. - virtual void SendStartMessage() = 0; - - // This method is expected to send an IPC to the browser process to let it - // know that it should start observing. - // It is expected for subclasses to override it. - virtual void SendStopMessage() = 0; - - // Implementations of PlatformEventObserver must call StopIfObserving() - // from their destructor to shutdown in an orderly manner. - // (As Stop() calls a virtual method, it cannot be handled by - // ~PlatformEventObserver.) - void StopIfObserving() { - if (is_observing()) - Stop(); - } - - bool is_observing() const { - return is_observing_; - } - - ListenerType* listener() { - return listener_; - } - - private: - bool is_observing_; - ListenerType* listener_; - - DISALLOW_COPY_AND_ASSIGN(PlatformEventObserver); -}; - -} // namespace content - -#endif // CONTENT_PUBLIC_RENDERER_PLATFORM_EVENT_OBSERVER_H_
diff --git a/content/public/renderer/renderer_gamepad_provider.h b/content/public/renderer/renderer_gamepad_provider.h deleted file mode 100644 index fe5e69e..0000000 --- a/content/public/renderer/renderer_gamepad_provider.h +++ /dev/null
@@ -1,37 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_PUBLIC_RENDERER_RENDERER_GAMEPAD_PROVIDER_H_ -#define CONTENT_PUBLIC_RENDERER_RENDERER_GAMEPAD_PROVIDER_H_ - -#include "base/macros.h" -#include "content/public/renderer/platform_event_observer.h" - -namespace blink { -class WebGamepadListener; -} - -namespace device { -class Gamepads; -} - -namespace content { - -// Provides gamepad data and events for blink. -class RendererGamepadProvider - : public PlatformEventObserver<blink::WebGamepadListener> { - public: - RendererGamepadProvider() {} - ~RendererGamepadProvider() override {} - - // Provides latest snapshot of gamepads. - virtual void SampleGamepads(device::Gamepads& gamepads) = 0; - - protected: - DISALLOW_COPY_AND_ASSIGN(RendererGamepadProvider); -}; - -} // namespace content - -#endif // CONTENT_PUBLIC_RENDERER_RENDERER_GAMEPAD_PROVIDER_H_
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc index cc609dc..398ffad4 100644 --- a/content/renderer/render_widget.cc +++ b/content/renderer/render_widget.cc
@@ -1046,6 +1046,9 @@ // Notify subclasses that we initiated the paint operation. DidInitiatePaint(); + + QueueMessage(new ViewHostMsg_DidCommitAndDrawCompositorFrame(routing_id_), + MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE); } void RenderWidget::DidCommitCompositorFrame() {
diff --git a/content/shell/renderer/layout_test/blink_test_runner.cc b/content/shell/renderer/layout_test/blink_test_runner.cc index c390c21..daceca6 100644 --- a/content/shell/renderer/layout_test/blink_test_runner.cc +++ b/content/shell/renderer/layout_test/blink_test_runner.cc
@@ -38,9 +38,9 @@ #include "content/public/common/web_preferences.h" #include "content/public/renderer/media_stream_utils.h" #include "content/public/renderer/render_frame.h" +#include "content/public/renderer/render_thread.h" #include "content/public/renderer/render_view.h" #include "content/public/renderer/render_view_visitor.h" -#include "content/public/renderer/renderer_gamepad_provider.h" #include "content/public/test/layouttest_support.h" #include "content/shell/common/layout_test/layout_test_messages.h" #include "content/shell/common/shell_messages.h"
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index 15a64a4..e9eb8aa 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -1509,6 +1509,7 @@ "../browser/renderer_host/render_widget_host_view_mac_unittest.mm", "../browser/renderer_host/text_input_client_mac_unittest.mm", "../browser/resolve_proxy_msg_helper_unittest.cc", + "../browser/scheduler/responsiveness/calculator_unittest.cc", "../browser/screen_orientation/screen_orientation_provider_unittest.cc", "../browser/service_worker/embedded_worker_instance_unittest.cc", "../browser/service_worker/service_worker_cache_writer_unittest.cc",
diff --git a/content/test/gpu/gpu_tests/pixel_expectations.py b/content/test/gpu/gpu_tests/pixel_expectations.py index 2678156..4a93632 100644 --- a/content/test/gpu/gpu_tests/pixel_expectations.py +++ b/content/test/gpu/gpu_tests/pixel_expectations.py
@@ -45,10 +45,6 @@ self.Fail('Pixel_ScissorTestWithPreserveDrawingBuffer', ['android'], bug=521588) - # Tests crashing on marshmallow bot - self.Fail('Pixel_CanvasLowLatency2D', ['android'], bug=865957) - self.Fail('Pixel_CanvasUnacceleratedLowLatency2D', ['android'], bug=865957) - # TODO(vmiura) check / generate reference images for Android devices self.Fail('Pixel_SolidColorBackground', ['mac', 'android'], bug=624256)
diff --git a/content/test/layouttest_support.cc b/content/test/layouttest_support.cc index 6081a4f..b8dbec2c 100644 --- a/content/test/layouttest_support.cc +++ b/content/test/layouttest_support.cc
@@ -30,7 +30,6 @@ #include "content/public/browser/storage_partition.h" #include "content/public/common/page_state.h" #include "content/public/common/screen_info.h" -#include "content/public/renderer/renderer_gamepad_provider.h" #include "content/renderer/gpu/layer_tree_view.h" #include "content/renderer/input/render_widget_input_handler_delegate.h" #include "content/renderer/layout_test_dependencies.h"
diff --git a/device/fido/fido_request_handler.h b/device/fido/fido_request_handler.h index f456e98..1c360e38 100644 --- a/device/fido/fido_request_handler.h +++ b/device/fido/fido_request_handler.h
@@ -100,6 +100,9 @@ case CtapDeviceResponseCode::kCtap2ErrCredentialNotValid: case CtapDeviceResponseCode::kCtap2ErrNoCredentials: return FidoReturnCode::kUserConsentButCredentialNotRecognized; + + // For all other errors, the authenticator will be dropped, and other + // authenticators may continue. default: return base::nullopt; }
diff --git a/device/fido/fido_task.h b/device/fido/fido_task.h index b2ca94b..ab4c8ad 100644 --- a/device/fido/fido_task.h +++ b/device/fido/fido_task.h
@@ -18,13 +18,9 @@ namespace device { // Encapsulates per-device request logic shared between MakeCredential and -// GetAssertion. Handles issuing the AuthenticatorGetInfo command to tokens, -// caching device info, and distinguishing U2F tokens from CTAP tokens. +// GetAssertion. // -// FidoTask is owned by FidoRequestHandler and manages all interaction with -// |device_|. It is created when a new device is discovered by FidoDiscovery and -// destroyed when the device is removed or when a successful response has been -// issued to the relying party from another authenticator. +// TODO(martinkr): FidoTask should be subsumed by FidoDeviceAuthenticator. class COMPONENT_EXPORT(DEVICE_FIDO) FidoTask { public: // The |device| must outlive the FidoTask instance.
diff --git a/device/fido/get_assertion_handler_unittest.cc b/device/fido/get_assertion_handler_unittest.cc index ed8267e..fffaf21d 100644 --- a/device/fido/get_assertion_handler_unittest.cc +++ b/device/fido/get_assertion_handler_unittest.cc
@@ -37,13 +37,21 @@ discovery_ = scoped_fake_discovery_factory_.ForgeNextHidDiscovery(); } - std::unique_ptr<GetAssertionRequestHandler> CreateGetAssertionHandler() { + std::unique_ptr<GetAssertionRequestHandler> CreateGetAssertionHandlerU2f() { CtapGetAssertionRequest request(test_data::kRelyingPartyId, test_data::kClientDataHash); request.SetAllowList( {{CredentialType::kPublicKey, fido_parsing_utils::Materialize(test_data::kU2fSignKeyHandle)}}); + return CreateGetAssertionHandlerWithRequest(std::move(request)); + } + std::unique_ptr<GetAssertionRequestHandler> CreateGetAssertionHandlerCtap() { + CtapGetAssertionRequest request(test_data::kRelyingPartyId, + test_data::kClientDataHash); + request.SetAllowList({{CredentialType::kPublicKey, + fido_parsing_utils::Materialize( + test_data::kTestGetAssertionCredentialId)}}); return CreateGetAssertionHandlerWithRequest(std::move(request)); } @@ -76,15 +84,10 @@ TestGetAssertionRequestCallback get_assertion_cb_; }; -TEST_F(FidoGetAssertionHandlerTest, TestGetAssertionRequestOnSingleDevice) { - auto request_handler = CreateGetAssertionHandler(); +TEST_F(FidoGetAssertionHandlerTest, CtapRequestOnSingleDevice) { + auto request_handler = CreateGetAssertionHandlerCtap(); discovery()->WaitForCallToStartAndSimulateSuccess(); - auto device = std::make_unique<MockFidoDevice>(); - - EXPECT_CALL(*device, GetId()).WillRepeatedly(testing::Return("device0")); - device->ExpectCtap2CommandAndRespondWith( - CtapRequestCommand::kAuthenticatorGetInfo, - test_data::kTestAuthenticatorGetInfoResponse); + auto device = MockFidoDevice::MakeCtapWithGetInfoExpectation(); device->ExpectCtap2CommandAndRespondWith( CtapRequestCommand::kAuthenticatorGetAssertion, test_data::kTestGetAssertionResponse); @@ -99,13 +102,10 @@ // Test a scenario where the connected authenticator is a U2F device. TEST_F(FidoGetAssertionHandlerTest, TestU2fSign) { - auto request_handler = CreateGetAssertionHandler(); + auto request_handler = CreateGetAssertionHandlerU2f(); discovery()->WaitForCallToStartAndSimulateSuccess(); - auto device = std::make_unique<MockFidoDevice>(); - EXPECT_CALL(*device, GetId()).WillRepeatedly(testing::Return("device0")); - device->ExpectCtap2CommandAndRespondWith( - CtapRequestCommand::kAuthenticatorGetInfo, base::nullopt); + auto device = MockFidoDevice::MakeU2fWithGetInfoExpectation(); device->ExpectRequestAndRespondWith( test_data::kU2fCheckOnlySignCommandApdu, test_data::kApduEncodedNoErrorSignResponse); @@ -124,7 +124,7 @@ // "WebAuthenticationCtap2" flag is not enabled. TEST_F(FidoGetAssertionHandlerTest, TestU2fSignWithoutCtapFlag) { InitFeatureListAndDisableCtapFlag(); - auto request_handler = CreateGetAssertionHandler(); + auto request_handler = CreateGetAssertionHandlerU2f(); discovery()->WaitForCallToStartAndSimulateSuccess(); auto device = std::make_unique<MockFidoDevice>(); @@ -151,10 +151,7 @@ CreateGetAssertionHandlerWithRequest(std::move(request)); discovery()->WaitForCallToStartAndSimulateSuccess(); - auto device = std::make_unique<MockFidoDevice>(); - EXPECT_CALL(*device, GetId()).WillRepeatedly(testing::Return("device0")); - device->ExpectCtap2CommandAndRespondWith( - CtapRequestCommand::kAuthenticatorGetInfo, + auto device = MockFidoDevice::MakeCtapWithGetInfoExpectation( test_data::kTestGetInfoResponseWithoutUvSupport); discovery()->AddDevice(std::move(device)); @@ -175,10 +172,65 @@ CreateGetAssertionHandlerWithRequest(std::move(request)); discovery()->WaitForCallToStartAndSimulateSuccess(); - auto device = std::make_unique<MockFidoDevice>(); - EXPECT_CALL(*device, GetId()).WillRepeatedly(testing::Return("device0")); + auto device = MockFidoDevice::MakeU2fWithGetInfoExpectation(); + discovery()->AddDevice(std::move(device)); + + scoped_task_environment_.FastForwardUntilNoTasksRemain(); + EXPECT_FALSE(get_assertion_callback().was_called()); +} + +TEST_F(FidoGetAssertionHandlerTest, IncorrectRpIdHash) { + auto request_handler = + CreateGetAssertionHandlerWithRequest(CtapGetAssertionRequest( + test_data::kRelyingPartyId, test_data::kClientDataHash)); + discovery()->WaitForCallToStartAndSimulateSuccess(); + auto device = MockFidoDevice::MakeCtapWithGetInfoExpectation(); device->ExpectCtap2CommandAndRespondWith( - CtapRequestCommand::kAuthenticatorGetInfo, base::nullopt); + CtapRequestCommand::kAuthenticatorGetAssertion, + test_data::kTestGetAssertionResponseWithIncorrectRpIdHash); + + discovery()->AddDevice(std::move(device)); + + scoped_task_environment_.FastForwardUntilNoTasksRemain(); + EXPECT_FALSE(get_assertion_callback().was_called()); +} + +// Tests a scenario where the authenticator responds with credential ID that +// is not included in the allowed list. +TEST_F(FidoGetAssertionHandlerTest, InvalidCredential) { + CtapGetAssertionRequest request(test_data::kRelyingPartyId, + test_data::kClientDataHash); + request.SetAllowList( + {{CredentialType::kPublicKey, + fido_parsing_utils::Materialize(test_data::kKeyHandleAlpha)}}); + auto request_handler = + CreateGetAssertionHandlerWithRequest(std::move(request)); + discovery()->WaitForCallToStartAndSimulateSuccess(); + // Resident Keys must be disabled, otherwise allow list check is skipped. + auto device = MockFidoDevice::MakeCtapWithGetInfoExpectation( + test_data::kTestGetInfoResponseWithoutResidentKeySupport); + device->ExpectCtap2CommandAndRespondWith( + CtapRequestCommand::kAuthenticatorGetAssertion, + test_data::kTestGetAssertionResponse); + + discovery()->AddDevice(std::move(device)); + + scoped_task_environment_.FastForwardUntilNoTasksRemain(); + EXPECT_FALSE(get_assertion_callback().was_called()); +} + +// Tests a scenario where authenticator responds without user entity in its +// response but client is expecting a resident key credential. +TEST_F(FidoGetAssertionHandlerTest, IncorrectUserEntity) { + // Use a GetAssertion request with an empty allow list. + auto request_handler = + CreateGetAssertionHandlerWithRequest(CtapGetAssertionRequest( + test_data::kRelyingPartyId, test_data::kClientDataHash)); + discovery()->WaitForCallToStartAndSimulateSuccess(); + auto device = MockFidoDevice::MakeCtapWithGetInfoExpectation(); + device->ExpectCtap2CommandAndRespondWith( + CtapRequestCommand::kAuthenticatorGetAssertion, + test_data::kTestGetAssertionResponse); discovery()->AddDevice(std::move(device));
diff --git a/device/fido/get_assertion_request_handler.cc b/device/fido/get_assertion_request_handler.cc index dcf5aa0..bc300d8 100644 --- a/device/fido/get_assertion_request_handler.cc +++ b/device/fido/get_assertion_request_handler.cc
@@ -4,6 +4,7 @@ #include "device/fido/get_assertion_request_handler.h" +#include <algorithm> #include <utility> #include "base/bind.h" @@ -14,6 +15,71 @@ namespace device { +namespace { + +// PublicKeyUserEntity field in GetAssertion response is optional with the +// following constraints: +// - If assertion has been made without user verification, user identifiable +// information must not be included. +// - For resident key credentials, user id of the user entity is mandatory. +// - When multiple accounts exist for specified RP ID, user entity is +// mandatory. +// TODO(hongjunchoi) : Add link to section of the CTAP spec once it is +// published. +bool CheckRequirementsOnResponseUserEntity( + const CtapGetAssertionRequest& request, + const AuthenticatorGetAssertionResponse& response) { + // If assertion has been made without user verification, user identifiable + // information must not be included. + const auto& user_entity = response.user_entity(); + const bool has_user_identifying_info = + user_entity && (user_entity->user_display_name() || + user_entity->user_name() || user_entity->user_icon_url()); + if (!response.auth_data().obtained_user_verification() && + has_user_identifying_info) { + return false; + } + + // For resident key credentials, user id of the user entity is mandatory. + if ((!request.allow_list() || request.allow_list()->empty()) && + !user_entity) { + return false; + } + + // When multiple accounts exist for specified RP ID, user entity is mandatory. + if (response.num_credentials().value_or(0u) > 1 && !user_entity) { + return false; + } + + return true; +} + +// Checks whether credential ID returned from the authenticator was included +// in the allowed list for authenticators. If the device has resident key +// support, returned credential ID may be resident credential. Thus, returned +// credential ID need not be in allowed list. +// TODO(hongjunchoi) : Add link to section of the CTAP spec once it is +// published. +bool CheckResponseCredentialIdMatchesRequestAllowList( + const FidoAuthenticator& authenticator, + const CtapGetAssertionRequest request, + const AuthenticatorGetAssertionResponse& response) { + const auto& allow_list = request.allow_list(); + if (!allow_list || allow_list->empty()) { + // Allow list can't be empty for authenticators w/o resident key support. + return authenticator.Options().supports_resident_key(); + } + // Credential ID may be omitted if allow list has size 1. Otherwise, it needs + // to match. + return (allow_list->size() == 1 && !response.credential()) || + std::any_of(allow_list->cbegin(), allow_list->cend(), + [&response](const auto& credential) { + return credential.id() == response.raw_credential_id(); + }); +} + +} // namespace + GetAssertionRequestHandler::GetAssertionRequestHandler( service_manager::Connector* connector, const base::flat_set<FidoTransportProtocol>& protocols, @@ -99,8 +165,29 @@ authenticator->GetAssertion( std::move(request_copy), - base::BindOnce(&GetAssertionRequestHandler::OnAuthenticatorResponse, + base::BindOnce(&GetAssertionRequestHandler::HandleResponse, weak_factory_.GetWeakPtr(), authenticator)); } +void GetAssertionRequestHandler::HandleResponse( + FidoAuthenticator* authenticator, + CtapDeviceResponseCode response_code, + base::Optional<AuthenticatorGetAssertionResponse> response) { + if (response_code != CtapDeviceResponseCode::kSuccess) { + OnAuthenticatorResponse(authenticator, response_code, base::nullopt); + return; + } + + if (!response || !response->CheckRpIdHash(request_.rp_id()) || + !CheckResponseCredentialIdMatchesRequestAllowList(*authenticator, + request_, *response) || + !CheckRequirementsOnResponseUserEntity(request_, *response)) { + OnAuthenticatorResponse( + authenticator, CtapDeviceResponseCode::kCtap2ErrOther, base::nullopt); + return; + } + + OnAuthenticatorResponse(authenticator, response_code, std::move(response)); +} + } // namespace device
diff --git a/device/fido/get_assertion_request_handler.h b/device/fido/get_assertion_request_handler.h index 594a89c1..7483287 100644 --- a/device/fido/get_assertion_request_handler.h +++ b/device/fido/get_assertion_request_handler.h
@@ -49,6 +49,11 @@ // FidoRequestHandlerBase: void DispatchRequest(FidoAuthenticator* authenticator) override; + void HandleResponse( + FidoAuthenticator* authenticator, + CtapDeviceResponseCode response_code, + base::Optional<AuthenticatorGetAssertionResponse> response); + CtapGetAssertionRequest request_; base::WeakPtrFactory<GetAssertionRequestHandler> weak_factory_;
diff --git a/device/fido/get_assertion_task.cc b/device/fido/get_assertion_task.cc index e381b64..f6032c93 100644 --- a/device/fido/get_assertion_task.cc +++ b/device/fido/get_assertion_task.cc
@@ -4,34 +4,16 @@ #include "device/fido/get_assertion_task.h" -#include <algorithm> #include <utility> #include "base/bind.h" #include "device/base/features.h" #include "device/fido/authenticator_get_assertion_response.h" #include "device/fido/ctap2_device_operation.h" -#include "device/fido/ctap_empty_authenticator_request.h" -#include "device/fido/device_response_converter.h" -#include "device/fido/u2f_command_constructor.h" #include "device/fido/u2f_sign_operation.h" namespace device { -namespace { - -bool ResponseContainsUserIdentifiableInfo( - const AuthenticatorGetAssertionResponse& response) { - const auto& user_entity = response.user_entity(); - if (!user_entity) - return false; - - return user_entity->user_display_name() || user_entity->user_name() || - user_entity->user_icon_url(); -} - -} // namespace - GetAssertionTask::GetAssertionTask(FidoDevice* device, CtapGetAssertionRequest request, GetAssertionTaskCallback callback) @@ -55,9 +37,7 @@ sign_operation_ = std::make_unique<Ctap2DeviceOperation<CtapGetAssertionRequest, AuthenticatorGetAssertionResponse>>( - device(), request_, - base::BindOnce(&GetAssertionTask::OnCtapGetAssertionResponseReceived, - weak_factory_.GetWeakPtr()), + device(), request_, std::move(callback_), base::BindOnce(&ReadCTAPGetAssertionResponse)); sign_operation_->Start(); } @@ -66,71 +46,9 @@ DCHECK(!device()->device_info()); DCHECK_EQ(ProtocolVersion::kU2f, device()->supported_protocol()); - sign_operation_ = std::make_unique<U2fSignOperation>( - device(), request_, - base::BindOnce(&GetAssertionTask::OnCtapGetAssertionResponseReceived, - weak_factory_.GetWeakPtr())); + sign_operation_ = std::make_unique<U2fSignOperation>(device(), request_, + std::move(callback_)); sign_operation_->Start(); } -bool GetAssertionTask::CheckRequirementsOnReturnedUserEntities( - const AuthenticatorGetAssertionResponse& response) { - // If assertion has been made without user verification, user identifiable - // information must not be included. - if (!response.auth_data().obtained_user_verification() && - ResponseContainsUserIdentifiableInfo(response)) { - return false; - } - - // For resident key credentials, user id of the user entity is mandatory. - if ((!request_.allow_list() || request_.allow_list()->empty()) && - !response.user_entity()) { - return false; - } - - // When multiple accounts exist for specified RP ID, user entity is mandatory. - if (response.num_credentials().value_or(0u) > 1 && !response.user_entity()) { - return false; - } - - return true; -} - -bool GetAssertionTask::CheckRequirementsOnReturnedCredentialId( - const AuthenticatorGetAssertionResponse& response) { - if (device()->device_info() && - device()->device_info()->options().supports_resident_key()) { - return true; - } - - const auto& allow_list = request_.allow_list(); - return allow_list && - (allow_list->size() == 1 || - std::any_of(allow_list->cbegin(), allow_list->cend(), - [&response](const auto& credential) { - return credential.id() == response.raw_credential_id(); - })); -} - -void GetAssertionTask::OnCtapGetAssertionResponseReceived( - CtapDeviceResponseCode response_code, - base::Optional<AuthenticatorGetAssertionResponse> device_response) { - if (response_code != CtapDeviceResponseCode::kSuccess) { - std::move(callback_).Run(response_code, base::nullopt); - return; - } - - // TODO(martinkr): CheckRpIdHash invocation needs to move into the Request - // handler. See https://crbug.com/863988. - if (!device_response || !device_response->CheckRpIdHash(request_.rp_id()) || - !CheckRequirementsOnReturnedCredentialId(*device_response) || - !CheckRequirementsOnReturnedUserEntities(*device_response)) { - std::move(callback_).Run(CtapDeviceResponseCode::kCtap2ErrOther, - base::nullopt); - return; - } - - std::move(callback_).Run(response_code, std::move(device_response)); -} - } // namespace device
diff --git a/device/fido/get_assertion_task.h b/device/fido/get_assertion_task.h index b993d84..366341d 100644 --- a/device/fido/get_assertion_task.h +++ b/device/fido/get_assertion_task.h
@@ -46,31 +46,6 @@ void GetAssertion(); void U2fSign(); - // PublicKeyUserEntity field in GetAssertion response is optional with the - // following constraints: - // - If assertion has been made without user verification, user identifiable - // information must not be included. - // - For resident key credentials, user id of the user entity is mandatory. - // - When multiple accounts exist for specified RP ID, user entity is - // mandatory. - // TODO(hongjunchoi) : Add link to section of the CTAP spec once it is - // published. - bool CheckRequirementsOnReturnedUserEntities( - const AuthenticatorGetAssertionResponse& response); - - // Checks whether credential ID returned from the authenticator was included - // in the allowed list for authenticators. If the device has resident key - // support, returned credential ID may be resident credential. Thus, returned - // credential ID need not be in allowed list. - // TODO(hongjunchoi) : Add link to section of the CTAP spec once it is - // published. - bool CheckRequirementsOnReturnedCredentialId( - const AuthenticatorGetAssertionResponse& response); - - void OnCtapGetAssertionResponseReceived( - CtapDeviceResponseCode response_code, - base::Optional<AuthenticatorGetAssertionResponse> device_response); - CtapGetAssertionRequest request_; std::unique_ptr<SignOperation> sign_operation_; GetAssertionTaskCallback callback_;
diff --git a/device/fido/get_assertion_task_unittest.cc b/device/fido/get_assertion_task_unittest.cc index 87599e5..0355efd 100644 --- a/device/fido/get_assertion_task_unittest.cc +++ b/device/fido/get_assertion_task_unittest.cc
@@ -177,64 +177,6 @@ EXPECT_TRUE(get_assertion_callback_receiver().value()); } -// Tests a scenario where the authenticator responds with credential ID that -// is not included in the allowed list. -TEST_F(FidoGetAssertionTaskTest, TestGetAssertionInvalidCredential) { - auto device = MockFidoDevice::MakeCtap(); - device->ExpectCtap2CommandAndRespondWith( - CtapRequestCommand::kAuthenticatorGetAssertion, - test_data::kTestGetAssertionResponse); - - auto task = std::make_unique<GetAssertionTask>( - device.get(), - CtapGetAssertionRequest(test_data::kRelyingPartyId, - test_data::kClientDataHash), - get_assertion_callback_receiver().callback()); - - get_assertion_callback_receiver().WaitForCallback(); - EXPECT_EQ(CtapDeviceResponseCode::kCtap2ErrOther, - get_assertion_callback_receiver().status()); - EXPECT_FALSE(get_assertion_callback_receiver().value()); -} - -// Tests a scenario where authenticator responds without user entity in its -// response but client is expecting a resident key credential. -TEST_F(FidoGetAssertionTaskTest, TestGetAsserionIncorrectUserEntity) { - auto device = MockFidoDevice::MakeCtap(); - device->ExpectCtap2CommandAndRespondWith( - CtapRequestCommand::kAuthenticatorGetAssertion, - test_data::kTestGetAssertionResponse); - - auto task = std::make_unique<GetAssertionTask>( - device.get(), - CtapGetAssertionRequest(test_data::kRelyingPartyId, - test_data::kClientDataHash), - get_assertion_callback_receiver().callback()); - - get_assertion_callback_receiver().WaitForCallback(); - EXPECT_EQ(CtapDeviceResponseCode::kCtap2ErrOther, - get_assertion_callback_receiver().status()); - EXPECT_FALSE(get_assertion_callback_receiver().value()); -} - -TEST_F(FidoGetAssertionTaskTest, TestGetAsserionIncorrectRpIdHash) { - auto device = MockFidoDevice::MakeCtap(); - device->ExpectCtap2CommandAndRespondWith( - CtapRequestCommand::kAuthenticatorGetAssertion, - test_data::kTestGetAssertionResponseWithIncorrectRpIdHash); - - auto task = std::make_unique<GetAssertionTask>( - device.get(), - CtapGetAssertionRequest(test_data::kRelyingPartyId, - test_data::kClientDataHash), - get_assertion_callback_receiver().callback()); - - get_assertion_callback_receiver().WaitForCallback(); - EXPECT_EQ(CtapDeviceResponseCode::kCtap2ErrOther, - get_assertion_callback_receiver().status()); - EXPECT_FALSE(get_assertion_callback_receiver().value()); -} - TEST_F(FidoGetAssertionTaskTest, TestIncorrectGetAssertionResponse) { auto device = MockFidoDevice::MakeCtap(); device->ExpectCtap2CommandAndRespondWith(
diff --git a/device/fido/make_credential_handler_unittest.cc b/device/fido/make_credential_handler_unittest.cc index f5b277d..2421f3e 100644 --- a/device/fido/make_credential_handler_unittest.cc +++ b/device/fido/make_credential_handler_unittest.cc
@@ -88,16 +88,12 @@ auto request_handler = CreateMakeCredentialHandler(); discovery()->WaitForCallToStartAndSimulateSuccess(); - auto device = std::make_unique<MockFidoDevice>(); - EXPECT_CALL(*device, GetId()).WillRepeatedly(testing::Return("device0")); - device->ExpectCtap2CommandAndRespondWith( - CtapRequestCommand::kAuthenticatorGetInfo, - test_data::kTestAuthenticatorGetInfoResponse); + auto device = MockFidoDevice::MakeCtapWithGetInfoExpectation(); device->ExpectCtap2CommandAndRespondWith( CtapRequestCommand::kAuthenticatorMakeCredential, test_data::kTestMakeCredentialResponse); - discovery()->AddDevice(std::move(device)); + callback().WaitForCallback(); EXPECT_EQ(FidoReturnCode::kSuccess, callback().status()); EXPECT_TRUE(request_handler->is_complete()); @@ -108,15 +104,12 @@ auto request_handler = CreateMakeCredentialHandler(); discovery()->WaitForCallToStartAndSimulateSuccess(); - auto device = std::make_unique<MockFidoDevice>(); - EXPECT_CALL(*device, GetId()).WillRepeatedly(testing::Return("device0")); - device->ExpectCtap2CommandAndRespondWith( - CtapRequestCommand::kAuthenticatorGetInfo, base::nullopt); + auto device = MockFidoDevice::MakeU2fWithGetInfoExpectation(); device->ExpectRequestAndRespondWith( test_data::kU2fRegisterCommandApdu, test_data::kApduEncodedNoErrorRegisterResponse); - discovery()->AddDevice(std::move(device)); + callback().WaitForCallback(); EXPECT_EQ(FidoReturnCode::kSuccess, callback().status()); EXPECT_TRUE(request_handler->is_complete()); @@ -150,11 +143,7 @@ UserVerificationRequirement::kRequired)); discovery()->WaitForCallToStartAndSimulateSuccess(); - auto device = std::make_unique<MockFidoDevice>(); - EXPECT_CALL(*device, GetId()).WillRepeatedly(testing::Return("device0")); - device->ExpectCtap2CommandAndRespondWith( - CtapRequestCommand::kAuthenticatorGetInfo, base::nullopt); - + auto device = MockFidoDevice::MakeU2fWithGetInfoExpectation(); discovery()->AddDevice(std::move(device)); scoped_task_environment_.FastForwardUntilNoTasksRemain(); @@ -172,11 +161,7 @@ UserVerificationRequirement::kPreferred)); discovery()->WaitForCallToStartAndSimulateSuccess(); - auto device = std::make_unique<MockFidoDevice>(); - EXPECT_CALL(*device, GetId()).WillRepeatedly(testing::Return("device0")); - device->ExpectCtap2CommandAndRespondWith( - CtapRequestCommand::kAuthenticatorGetInfo, base::nullopt); - + auto device = MockFidoDevice::MakeU2fWithGetInfoExpectation(); discovery()->AddDevice(std::move(device)); scoped_task_environment_.FastForwardUntilNoTasksRemain(); @@ -192,11 +177,7 @@ UserVerificationRequirement::kPreferred)); discovery()->WaitForCallToStartAndSimulateSuccess(); - auto device = std::make_unique<MockFidoDevice>(); - EXPECT_CALL(*device, GetId()).WillRepeatedly(testing::Return("device0")); - device->ExpectCtap2CommandAndRespondWith( - CtapRequestCommand::kAuthenticatorGetInfo, base::nullopt); - + auto device = MockFidoDevice::MakeU2fWithGetInfoExpectation(); discovery()->AddDevice(std::move(device)); scoped_task_environment_.FastForwardUntilNoTasksRemain(); @@ -213,12 +194,8 @@ UserVerificationRequirement::kRequired)); discovery()->WaitForCallToStartAndSimulateSuccess(); - auto device = std::make_unique<MockFidoDevice>(); - EXPECT_CALL(*device, GetId()).WillRepeatedly(testing::Return("device0")); - device->ExpectCtap2CommandAndRespondWith( - CtapRequestCommand::kAuthenticatorGetInfo, + auto device = MockFidoDevice::MakeCtapWithGetInfoExpectation( test_data::kTestGetInfoResponseWithoutUvSupport); - discovery()->AddDevice(std::move(device)); scoped_task_environment_.FastForwardUntilNoTasksRemain(); @@ -236,12 +213,8 @@ UserVerificationRequirement::kRequired)); discovery()->WaitForCallToStartAndSimulateSuccess(); - auto device = std::make_unique<MockFidoDevice>(); - EXPECT_CALL(*device, GetId()).WillRepeatedly(testing::Return("device0")); - device->ExpectCtap2CommandAndRespondWith( - CtapRequestCommand::kAuthenticatorGetInfo, + auto device = MockFidoDevice::MakeCtapWithGetInfoExpectation( test_data::kTestGetInfoResponseCrossPlatformDevice); - discovery()->AddDevice(std::move(device)); scoped_task_environment_.FastForwardUntilNoTasksRemain(); @@ -258,12 +231,8 @@ UserVerificationRequirement::kPreferred)); discovery()->WaitForCallToStartAndSimulateSuccess(); - auto device = std::make_unique<MockFidoDevice>(); - EXPECT_CALL(*device, GetId()).WillRepeatedly(testing::Return("device0")); - device->ExpectCtap2CommandAndRespondWith( - CtapRequestCommand::kAuthenticatorGetInfo, + auto device = MockFidoDevice::MakeCtapWithGetInfoExpectation( test_data::kTestGetInfoResponseWithoutResidentKeySupport); - discovery()->AddDevice(std::move(device)); scoped_task_environment_.FastForwardUntilNoTasksRemain(); @@ -281,15 +250,10 @@ UserVerificationRequirement::kRequired)); discovery()->WaitForCallToStartAndSimulateSuccess(); - auto device = std::make_unique<MockFidoDevice>(); - EXPECT_CALL(*device, GetId()).WillRepeatedly(testing::Return("device0")); - device->ExpectCtap2CommandAndRespondWith( - CtapRequestCommand::kAuthenticatorGetInfo, - test_data::kTestAuthenticatorGetInfoResponse); + auto device = MockFidoDevice::MakeCtapWithGetInfoExpectation(); device->ExpectCtap2CommandAndRespondWith( CtapRequestCommand::kAuthenticatorMakeCredential, test_data::kTestMakeCredentialResponse); - discovery()->AddDevice(std::move(device)); scoped_task_environment_.FastForwardUntilNoTasksRemain(); @@ -306,12 +270,27 @@ UserVerificationRequirement::kRequired)); discovery()->WaitForCallToStartAndSimulateSuccess(); - auto device = std::make_unique<MockFidoDevice>(); - EXPECT_CALL(*device, GetId()).WillRepeatedly(testing::Return("device0")); - device->ExpectCtap2CommandAndRespondWith( - CtapRequestCommand::kAuthenticatorGetInfo, + auto device = MockFidoDevice::MakeCtapWithGetInfoExpectation( test_data::kTestGetInfoResponseWithoutUvSupport); + discovery()->AddDevice(std::move(device)); + scoped_task_environment_.FastForwardUntilNoTasksRemain(); + EXPECT_FALSE(callback().was_called()); +} + +TEST_F(FidoMakeCredentialHandlerTest, IncorrectRpIdHash) { + auto request_handler = + CreateMakeCredentialHandlerWithAuthenticatorSelectionCriteria( + AuthenticatorSelectionCriteria( + AuthenticatorSelectionCriteria::AuthenticatorAttachment::kAny, + false /* require_resident_key */, + UserVerificationRequirement::kPreferred)); + discovery()->WaitForCallToStartAndSimulateSuccess(); + + auto device = MockFidoDevice::MakeCtapWithGetInfoExpectation(); + device->ExpectCtap2CommandAndRespondWith( + CtapRequestCommand::kAuthenticatorMakeCredential, + test_data::kTestMakeCredentialResponseWithIncorrectRpIdHash); discovery()->AddDevice(std::move(device)); scoped_task_environment_.FastForwardUntilNoTasksRemain();
diff --git a/device/fido/make_credential_request_handler.cc b/device/fido/make_credential_request_handler.cc index 804bb75..a8b40ce 100644 --- a/device/fido/make_credential_request_handler.cc +++ b/device/fido/make_credential_request_handler.cc
@@ -99,8 +99,26 @@ authenticator->MakeCredential( std::move(request_copy), - base::BindOnce(&MakeCredentialRequestHandler::OnAuthenticatorResponse, + base::BindOnce(&MakeCredentialRequestHandler::HandleResponse, weak_factory_.GetWeakPtr(), authenticator)); } +void MakeCredentialRequestHandler::HandleResponse( + FidoAuthenticator* authenticator, + CtapDeviceResponseCode response_code, + base::Optional<AuthenticatorMakeCredentialResponse> response) { + if (response_code != CtapDeviceResponseCode::kSuccess) { + OnAuthenticatorResponse(authenticator, response_code, base::nullopt); + return; + } + + if (!response || !response->CheckRpIdHash(request_parameter_.rp().rp_id())) { + OnAuthenticatorResponse( + authenticator, CtapDeviceResponseCode::kCtap2ErrOther, base::nullopt); + return; + } + + OnAuthenticatorResponse(authenticator, response_code, std::move(response)); +} + } // namespace device
diff --git a/device/fido/make_credential_request_handler.h b/device/fido/make_credential_request_handler.h index 6edfdc0f..1ae2e0d 100644 --- a/device/fido/make_credential_request_handler.h +++ b/device/fido/make_credential_request_handler.h
@@ -52,6 +52,11 @@ // FidoRequestHandlerBase: void DispatchRequest(FidoAuthenticator* authenticator) final; + void HandleResponse( + FidoAuthenticator* authenticator, + CtapDeviceResponseCode response_code, + base::Optional<AuthenticatorMakeCredentialResponse> response); + CtapMakeCredentialRequest request_parameter_; AuthenticatorSelectionCriteria authenticator_selection_criteria_; base::WeakPtrFactory<MakeCredentialRequestHandler> weak_factory_;
diff --git a/device/fido/make_credential_task.cc b/device/fido/make_credential_task.cc index d609836..dcd3f48 100644 --- a/device/fido/make_credential_task.cc +++ b/device/fido/make_credential_task.cc
@@ -9,8 +9,6 @@ #include "base/bind.h" #include "device/base/features.h" #include "device/fido/ctap2_device_operation.h" -#include "device/fido/ctap_empty_authenticator_request.h" -#include "device/fido/device_response_converter.h" #include "device/fido/u2f_command_constructor.h" #include "device/fido/u2f_register_operation.h" @@ -39,9 +37,7 @@ void MakeCredentialTask::MakeCredential() { register_operation_ = std::make_unique<Ctap2DeviceOperation< CtapMakeCredentialRequest, AuthenticatorMakeCredentialResponse>>( - device(), request_parameter_, - base::BindOnce(&MakeCredentialTask::OnCtapMakeCredentialResponseReceived, - weak_factory_.GetWeakPtr()), + device(), request_parameter_, std::move(callback_), base::BindOnce(&ReadCTAPMakeCredentialResponse)); register_operation_->Start(); } @@ -54,30 +50,8 @@ } register_operation_ = std::make_unique<U2fRegisterOperation>( - device(), request_parameter_, - base::BindOnce(&MakeCredentialTask::OnCtapMakeCredentialResponseReceived, - weak_factory_.GetWeakPtr())); + device(), request_parameter_, std::move(callback_)); register_operation_->Start(); } -void MakeCredentialTask::OnCtapMakeCredentialResponseReceived( - CtapDeviceResponseCode return_code, - base::Optional<AuthenticatorMakeCredentialResponse> response_data) { - if (return_code != CtapDeviceResponseCode::kSuccess) { - std::move(callback_).Run(return_code, base::nullopt); - return; - } - - // TODO(martinkr): CheckRpIdHash invocation needs to move into the Request - // handler. See https://crbug.com/863988. - if (!response_data || - !response_data->CheckRpIdHash(request_parameter_.rp().rp_id())) { - std::move(callback_).Run(CtapDeviceResponseCode::kCtap2ErrOther, - base::nullopt); - return; - } - - std::move(callback_).Run(return_code, std::move(response_data)); -} - } // namespace device
diff --git a/device/fido/make_credential_task.h b/device/fido/make_credential_task.h index fc8ae97..61e35f6 100644 --- a/device/fido/make_credential_task.h +++ b/device/fido/make_credential_task.h
@@ -45,9 +45,6 @@ void MakeCredential(); void U2fRegister(); - void OnCtapMakeCredentialResponseReceived( - CtapDeviceResponseCode return_code, - base::Optional<AuthenticatorMakeCredentialResponse> response_data); CtapMakeCredentialRequest request_parameter_; std::unique_ptr<RegisterOperation> register_operation_;
diff --git a/device/fido/make_credential_task_unittest.cc b/device/fido/make_credential_task_unittest.cc index ee16b84..e35314b1 100644 --- a/device/fido/make_credential_task_unittest.cc +++ b/device/fido/make_credential_task_unittest.cc
@@ -103,19 +103,6 @@ make_credential_callback_receiver().value()->raw_credential_id().size()); } -TEST_F(FidoMakeCredentialTaskTest, MakeCredentialWithIncorrectRpIdHash) { - auto device = MockFidoDevice::MakeCtap(); - device->ExpectCtap2CommandAndRespondWith( - CtapRequestCommand::kAuthenticatorMakeCredential, - test_data::kTestMakeCredentialResponseWithIncorrectRpIdHash); - - const auto task = CreateMakeCredentialTask(device.get()); - make_credential_callback_receiver().WaitForCallback(); - - EXPECT_EQ(CtapDeviceResponseCode::kCtap2ErrOther, - make_credential_callback_receiver().status()); -} - TEST_F(FidoMakeCredentialTaskTest, FallbackToU2fRegisterSuccess) { auto device = MockFidoDevice::MakeU2f(); device->ExpectRequestAndRespondWith(
diff --git a/device/fido/mock_fido_device.cc b/device/fido/mock_fido_device.cc index cf499d5b..a90d29b 100644 --- a/device/fido/mock_fido_device.cc +++ b/device/fido/mock_fido_device.cc
@@ -8,6 +8,7 @@ #include "base/bind.h" #include "base/location.h" +#include "base/strings/strcat.h" #include "base/threading/thread_task_runner_handle.h" #include "components/apdu/apdu_response.h" #include "device/fido/device_response_converter.h" @@ -38,6 +39,29 @@ std::move(*device_info)); } +// static +std::unique_ptr<MockFidoDevice> +MockFidoDevice::MakeU2fWithGetInfoExpectation() { + auto device = std::make_unique<MockFidoDevice>(); + device->StubGetId(); + device->ExpectCtap2CommandAndRespondWith( + CtapRequestCommand::kAuthenticatorGetInfo, base::nullopt); + return device; +} + +// static +std::unique_ptr<MockFidoDevice> MockFidoDevice::MakeCtapWithGetInfoExpectation( + base::Optional<base::span<const uint8_t>> get_info_response) { + auto device = std::make_unique<MockFidoDevice>(); + device->StubGetId(); + if (!get_info_response) { + get_info_response = test_data::kTestAuthenticatorGetInfoResponse; + } + device->ExpectCtap2CommandAndRespondWith( + CtapRequestCommand::kAuthenticatorGetInfo, std::move(get_info_response)); + return device; +} + // Matcher to compare the fist byte of the incoming requests. MATCHER_P(IsCtap2Command, expected_command, "") { return !arg.empty() && arg[0] == base::strict_cast<uint8_t>(expected_command); @@ -68,6 +92,14 @@ EXPECT_CALL(*this, TryWinkRef(::testing::_)).Times(::testing::AtLeast(1)); } +void MockFidoDevice::StubGetId() { + // Use a counter to keep the device ID unique. + static size_t i = 0; + EXPECT_CALL(*this, GetId()) + .WillRepeatedly( + testing::Return(base::StrCat({"mockdevice", std::to_string(i)}))); +} + void MockFidoDevice::ExpectCtap2CommandAndRespondWith( CtapRequestCommand command, base::Optional<base::span<const uint8_t>> response,
diff --git a/device/fido/mock_fido_device.h b/device/fido/mock_fido_device.h index 0df85aa9..ee9cdf6 100644 --- a/device/fido/mock_fido_device.h +++ b/device/fido/mock_fido_device.h
@@ -23,9 +23,27 @@ class MockFidoDevice : public FidoDevice { public: + // MakeU2f returns a fully initialized U2F device. This represents the state + // after |DiscoverSupportedProtocolAndDeviceInfo| has been called by the + // FidoDiscovery. static std::unique_ptr<MockFidoDevice> MakeU2f(); + // MakeCtap returns a fully initialized CTAP device. This represents the + // state after |DiscoverSupportedProtocolAndDeviceInfo| has been called by + // the FidoDiscovery. static std::unique_ptr<MockFidoDevice> MakeCtap( base::Optional<AuthenticatorGetInfoResponse> device_info = base::nullopt); + // MakeU2fWithDeviceInfoExpectation returns a uninitialized U2F device + // suitable for injecting into a FidoDiscovery, which will determine its + // protocol version by invoking |DiscoverSupportedProtocolAndDeviceInfo|. + static std::unique_ptr<MockFidoDevice> MakeU2fWithGetInfoExpectation(); + // MakeCtapWithDeviceInfoExpectation returns a uninitialized CTAP device + // suitable for injecting into a FidoDiscovery, which will determine its + // protocol version by invoking |DiscoverSupportedProtocolAndDeviceInfo|. If a + // response is supplied, the mock will use that to reply; otherwise it will + // use |test_data::kTestAuthenticatorGetInfoResponse|. + static std::unique_ptr<MockFidoDevice> MakeCtapWithGetInfoExpectation( + base::Optional<base::span<const uint8_t>> get_info_response = + base::nullopt); MockFidoDevice(); MockFidoDevice(ProtocolVersion protocol_version, @@ -57,6 +75,7 @@ base::TimeDelta delay = base::TimeDelta()); void ExpectCtap2CommandAndDoNotRespond(CtapRequestCommand command); void ExpectRequestAndDoNotRespond(base::span<const uint8_t> request); + void StubGetId(); base::WeakPtr<FidoDevice> GetWeakPtr() override;
diff --git a/extensions/browser/api/bluetooth_low_energy/bluetooth_low_energy_event_router.cc b/extensions/browser/api/bluetooth_low_energy/bluetooth_low_energy_event_router.cc index 2c92bc26..896f001b 100644 --- a/extensions/browser/api/bluetooth_low_energy/bluetooth_low_energy_event_router.cc +++ b/extensions/browser/api/bluetooth_low_energy/bluetooth_low_energy_event_router.cc
@@ -122,7 +122,7 @@ if (value.empty()) return; - out->value.reset(new std::vector<char>(value.begin(), value.end())); + out->value.reset(new std::vector<uint8_t>(value)); } void PopulateDescriptor(const BluetoothRemoteGattDescriptor* descriptor, @@ -140,7 +140,7 @@ if (value.empty()) return; - out->value.reset(new std::vector<char>(value.begin(), value.end())); + out->value.reset(new std::vector<uint8_t>(value)); } void PopulateDevice(const device::BluetoothDevice* device, @@ -1131,8 +1131,7 @@ request.request_id = StoreSentRequest( extension_id, std::make_unique<AttributeValueRequest>(callback, error_callback)); - request.value = - std::make_unique<std::vector<char>>(value.begin(), value.end()); + request.value = std::make_unique<std::vector<uint8_t>>(value); PopulateDevice(device, &request); DispatchEventToExtension( extension_id, @@ -1207,8 +1206,7 @@ request.request_id = StoreSentRequest( extension_id, std::make_unique<AttributeValueRequest>(callback, error_callback)); - request.value = - std::make_unique<std::vector<char>>(value.begin(), value.end()); + request.value = std::make_unique<std::vector<uint8_t>>(value); PopulateDevice(device, &request); DispatchEventToExtension( extension_id,
diff --git a/extensions/browser/api/bluetooth_socket/bluetooth_socket_api.cc b/extensions/browser/api/bluetooth_socket/bluetooth_socket_api.cc index 69134a8a..c8e0ba40 100644 --- a/extensions/browser/api/bluetooth_socket/bluetooth_socket_api.cc +++ b/extensions/browser/api/bluetooth_socket/bluetooth_socket_api.cc
@@ -549,7 +549,8 @@ EXTENSION_FUNCTION_VALIDATE(params_.get()); io_buffer_size_ = params_->data.size(); - io_buffer_ = new net::WrappedIOBuffer(params_->data.data()); + io_buffer_ = new net::WrappedIOBuffer( + reinterpret_cast<const char*>(params_->data.data())); BluetoothApiSocket* socket = GetSocket(params_->socket_id); if (!socket)
diff --git a/extensions/browser/api/clipboard/clipboard_api.cc b/extensions/browser/api/clipboard/clipboard_api.cc index 6db4049..3b26a0f5 100644 --- a/extensions/browser/api/clipboard/clipboard_api.cc +++ b/extensions/browser/api/clipboard/clipboard_api.cc
@@ -64,7 +64,8 @@ } ExtensionsAPIClient::Get()->SaveImageDataToClipboard( - params->image_data, params->type, std::move(*params->additional_items), + std::vector<char>(params->image_data.begin(), params->image_data.end()), + params->type, std::move(*params->additional_items), base::Bind(&ClipboardSetImageDataFunction::OnSaveImageDataSuccess, this), base::Bind(&ClipboardSetImageDataFunction::OnSaveImageDataError, this)); return RespondLater();
diff --git a/extensions/browser/api/declarative/declarative_api.cc b/extensions/browser/api/declarative/declarative_api.cc index 6614174..c04e7d2f 100644 --- a/extensions/browser/api/declarative/declarative_api.cc +++ b/extensions/browser/api/declarative/declarative_api.cc
@@ -96,7 +96,7 @@ // Encodes |binary| as base64 and returns a new StringValue populated with the // encoded string. base::Value ConvertBinaryToBase64(const base::Value& binary) { - std::string binary_data(binary.GetBlob().data(), binary.GetBlob().size()); + std::string binary_data(binary.GetBlob().begin(), binary.GetBlob().end()); std::string data64; base::Base64Encode(binary_data, &data64); return base::Value(std::move(data64));
diff --git a/extensions/browser/api/declarative/rules_cache_delegate.cc b/extensions/browser/api/declarative/rules_cache_delegate.cc index 5efd926..181996c2 100644 --- a/extensions/browser/api/declarative/rules_cache_delegate.cc +++ b/extensions/browser/api/declarative/rules_cache_delegate.cc
@@ -104,6 +104,9 @@ DCHECK(value.is_list()); has_nonempty_ruleset_ = !value.GetList().empty(); + for (auto& observer : observers_) + observer.OnUpdateRules(); + if (type_ == Type::kEphemeral) return; @@ -123,6 +126,16 @@ return has_nonempty_ruleset_; } +void RulesCacheDelegate::AddObserver(Observer* observer) { + DCHECK(observer); + observers_.AddObserver(observer); +} + +void RulesCacheDelegate::RemoveObserver(Observer* observer) { + DCHECK(observer); + observers_.RemoveObserver(observer); +} + void RulesCacheDelegate::CheckIfReady() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (notified_registry_ || !waiting_for_extensions_.empty())
diff --git a/extensions/browser/api/declarative/rules_cache_delegate.h b/extensions/browser/api/declarative/rules_cache_delegate.h index c9b7b1ea9..b24cc58 100644 --- a/extensions/browser/api/declarative/rules_cache_delegate.h +++ b/extensions/browser/api/declarative/rules_cache_delegate.h
@@ -10,6 +10,7 @@ #include <string> #include "base/gtest_prod_util.h" +#include "base/observer_list.h" #include "base/values.h" #include "content/public/browser/browser_thread.h" @@ -27,6 +28,15 @@ // registering rules on initialization will be logged with UMA. class RulesCacheDelegate { public: + class Observer { + public: + // Called when |UpdateRules| is called on the |RulesCacheDelegate|. + virtual void OnUpdateRules() = 0; + + protected: + virtual ~Observer() {} + }; + // Determines the type of a cache, indicating whether or not its rules are // persisted to storage. enum class Type { @@ -60,6 +70,10 @@ // Indicates whether or not this registry has any registered rules cached. bool HasRules() const; + // Adds or removes an observer. + void AddObserver(Observer* observer); + void RemoveObserver(Observer* observer); + base::WeakPtr<RulesCacheDelegate> GetWeakPtr() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); return weak_ptr_factory_.GetWeakPtr(); @@ -127,6 +141,8 @@ // We notified the RulesRegistry that the rules are loaded. bool notified_registry_; + base::ObserverList<Observer> observers_; + // Use this factory to generate weak pointers bound to the UI thread. base::WeakPtrFactory<RulesCacheDelegate> weak_ptr_factory_; };
diff --git a/extensions/browser/api/declarative/rules_registry_service.cc b/extensions/browser/api/declarative/rules_registry_service.cc index d92d3d5..ac80129f 100644 --- a/extensions/browser/api/declarative/rules_registry_service.cc +++ b/extensions/browser/api/declarative/rules_registry_service.cc
@@ -158,11 +158,27 @@ }); } +void RulesRegistryService::AddObserver(Observer* observer) { + DCHECK(observer); + observers_.AddObserver(observer); +} + +void RulesRegistryService::RemoveObserver(Observer* observer) { + DCHECK(observer); + observers_.RemoveObserver(observer); +} + void RulesRegistryService::SimulateExtensionUninstalled( const Extension* extension) { NotifyRegistriesHelper(&RulesRegistry::OnExtensionUninstalled, extension); } +void RulesRegistryService::OnUpdateRules() { + // Forward rule updates to observers. + for (auto& observer : observers_) + observer.OnUpdateRules(); +} + scoped_refptr<RulesRegistry> RulesRegistryService::RegisterWebRequestRulesRegistry( int rules_registry_id, @@ -179,6 +195,7 @@ base::MakeRefCounted<WebRequestRulesRegistry>( browser_context_, web_request_cache_delegate.get(), rules_registry_id); + web_request_cache_delegate->AddObserver(this); cache_delegates_.push_back(std::move(web_request_cache_delegate)); RegisterRulesRegistry(web_request_rules_registry); content::BrowserThread::PostTask( @@ -217,6 +234,7 @@ ExtensionsAPIClient::Get()->CreateContentRulesRegistry( browser_context_, content_rules_cache_delegate.get()); if (content_rules_registry) { + content_rules_cache_delegate->AddObserver(this); cache_delegates_.push_back(std::move(content_rules_cache_delegate)); RegisterRulesRegistry(content_rules_registry); content_rules_registry_ = content_rules_registry.get();
diff --git a/extensions/browser/api/declarative/rules_registry_service.h b/extensions/browser/api/declarative/rules_registry_service.h index 2e0a794..eb8664a 100644 --- a/extensions/browser/api/declarative/rules_registry_service.h +++ b/extensions/browser/api/declarative/rules_registry_service.h
@@ -33,7 +33,8 @@ // This class owns all RulesRegistries implementations of an ExtensionService. // This class lives on the UI thread. class RulesRegistryService : public BrowserContextKeyedAPI, - public ExtensionRegistryObserver { + public ExtensionRegistryObserver, + public RulesCacheDelegate::Observer { public: static const int kDefaultRulesRegistryID; static const int kInvalidRulesRegistryID; @@ -49,6 +50,15 @@ } }; + class Observer { + public: + // Called when any of the |cache_delegates_| have rule updates. + virtual void OnUpdateRules() = 0; + + protected: + virtual ~Observer() {} + }; + explicit RulesRegistryService(content::BrowserContext* context); ~RulesRegistryService() override; @@ -92,6 +102,10 @@ // Indicates whether any registry has rules registered. bool HasAnyRegisteredRules() const; + // Adds or removes an observer. + void AddObserver(Observer* observer); + void RemoveObserver(Observer* observer); + // For testing. void SimulateExtensionUninstalled(const Extension* extension); @@ -120,6 +134,9 @@ const Extension* extension, extensions::UninstallReason reason) override; + // RulesCacheDelegate::Observer implementation. + void OnUpdateRules() override; + // Iterates over all registries, and calls |notification_callback| on them // with |extension| as the argument. If a registry lives on a different // thread, the call is posted to that thread, so no guarantee of synchronous @@ -152,6 +169,8 @@ content::BrowserContext* browser_context_; + base::ObserverList<Observer> observers_; + DISALLOW_COPY_AND_ASSIGN(RulesRegistryService); };
diff --git a/extensions/browser/api/declarative_net_request/rules_monitor_service.cc b/extensions/browser/api/declarative_net_request/rules_monitor_service.cc index 02e24ae..35696c35 100644 --- a/extensions/browser/api/declarative_net_request/rules_monitor_service.cc +++ b/extensions/browser/api/declarative_net_request/rules_monitor_service.cc
@@ -78,6 +78,16 @@ extensions_with_rulesets_.end(); } +void RulesMonitorService::AddObserver(Observer* observer) { + DCHECK(observer); + observers_.AddObserver(observer); +} + +void RulesMonitorService::RemoveObserver(Observer* observer) { + DCHECK(observer); + observers_.RemoveObserver(observer); +} + // Helper to pass information related to the ruleset being loaded. struct RulesMonitorService::LoadRulesetInfo { LoadRulesetInfo(scoped_refptr<const Extension> extension, @@ -328,6 +338,8 @@ return; extensions_with_rulesets_.insert(info.extension->id()); + for (auto& observer : observers_) + observer.OnRulesetLoaded(); base::OnceClosure load_ruleset_on_io = base::BindOnce( &LoadRulesetOnIOThread, info.extension->id(), std::move(matcher),
diff --git a/extensions/browser/api/declarative_net_request/rules_monitor_service.h b/extensions/browser/api/declarative_net_request/rules_monitor_service.h index 4c9d8e7..ac8a66aa 100644 --- a/extensions/browser/api/declarative_net_request/rules_monitor_service.h +++ b/extensions/browser/api/declarative_net_request/rules_monitor_service.h
@@ -36,6 +36,15 @@ class RulesMonitorService : public BrowserContextKeyedAPI, public ExtensionRegistryObserver { public: + class Observer { + public: + // Called when this service loads a new ruleset. + virtual void OnRulesetLoaded() = 0; + + protected: + virtual ~Observer() {} + }; + // BrowserContextKeyedAPI implementation. static BrowserContextKeyedAPIFactory<RulesMonitorService>* GetFactoryInstance(); @@ -46,6 +55,10 @@ // the given |extension_id|. bool HasRegisteredRuleset(const ExtensionId& extension_id) const; + // Adds or removes an observer. + void AddObserver(Observer* observer); + void RemoveObserver(Observer* observer); + private: struct LoadRulesetInfo; class FileSequenceState; @@ -89,6 +102,8 @@ ExtensionRegistry* const extension_registry_; WarningService* const warning_service_; + base::ObserverList<Observer> observers_; + // Must be the last member variable. See WeakPtrFactory documentation for // details. base::WeakPtrFactory<RulesMonitorService> weak_factory_;
diff --git a/extensions/browser/api/lock_screen_data/lock_screen_data_api.cc b/extensions/browser/api/lock_screen_data/lock_screen_data_api.cc index 1ad64e0..7de8668 100644 --- a/extensions/browser/api/lock_screen_data/lock_screen_data_api.cc +++ b/extensions/browser/api/lock_screen_data/lock_screen_data_api.cc
@@ -135,8 +135,8 @@ lock_screen_data::OperationResult::kCount); if (result == lock_screen_data::OperationResult::kSuccess) { - Respond(ArgumentList( - api::lock_screen_data::GetContent::Results::Create(*data))); + Respond(ArgumentList(api::lock_screen_data::GetContent::Results::Create( + std::vector<uint8_t>(data->begin(), data->end())))); return; } Respond(Error(GetErrorString(result))); @@ -157,7 +157,8 @@ return RespondNow(Error("Not available")); storage->SetItemContent( - extension_id(), params->id, params->data, + extension_id(), params->id, + std::vector<char>(params->data.begin(), params->data.end()), base::Bind(&LockScreenDataSetContentFunction::OnDone, this)); return RespondLater(); }
diff --git a/extensions/browser/api/media_perception_private/conversion_utils.cc b/extensions/browser/api/media_perception_private/conversion_utils.cc index 6483a812..a17fc643b 100644 --- a/extensions/browser/api/media_perception_private/conversion_utils.cc +++ b/extensions/browser/api/media_perception_private/conversion_utils.cc
@@ -413,7 +413,7 @@ } if (image_frame.has_pixel_data()) { - image_frame_result.frame = std::make_unique<std::vector<char>>( + image_frame_result.frame = std::make_unique<std::vector<uint8_t>>( image_frame.pixel_data().begin(), image_frame.pixel_data().end()); }
diff --git a/extensions/browser/api/serial/serial_connection.cc b/extensions/browser/api/serial/serial_connection.cc index c46ecf6..d9439a4 100644 --- a/extensions/browser/api/serial/serial_connection.cc +++ b/extensions/browser/api/serial/serial_connection.cc
@@ -263,20 +263,19 @@ return true; } -bool SerialConnection::Send(const std::vector<char>& data, +bool SerialConnection::Send(const std::vector<uint8_t>& data, SendCompleteCallback callback) { DCHECK_CURRENTLY_ON(BrowserThread::IO); if (send_complete_) return false; DCHECK(io_handler_); send_complete_ = std::move(callback); - io_handler_->Write( - std::vector<uint8_t>(data.data(), data.data() + data.size()), - mojo::WrapCallbackWithDefaultInvokeIfNotRun( - base::BindOnce(&SerialConnection::OnAsyncWriteComplete, - weak_factory_.GetWeakPtr()), - static_cast<uint32_t>(0), - device::mojom::SerialSendError::DISCONNECTED)); + io_handler_->Write(data, + mojo::WrapCallbackWithDefaultInvokeIfNotRun( + base::BindOnce(&SerialConnection::OnAsyncWriteComplete, + weak_factory_.GetWeakPtr()), + static_cast<uint32_t>(0), + device::mojom::SerialSendError::DISCONNECTED)); send_timeout_task_.Cancel(); if (send_timeout_ > 0) { send_timeout_task_.Reset(base::Bind(&SerialConnection::OnSendTimeout, @@ -411,9 +410,7 @@ DCHECK(receive_complete_); receive_timeout_task_.Cancel(); std::move(receive_complete_) - .Run(std::vector<char>(data_read.data(), - data_read.data() + data_read.size()), - ConvertReceiveErrorFromMojo(error)); + .Run(data_read, ConvertReceiveErrorFromMojo(error)); } void SerialConnection::OnAsyncWriteComplete(
diff --git a/extensions/browser/api/serial/serial_connection.h b/extensions/browser/api/serial/serial_connection.h index 77363373..6bfb8f8e 100644 --- a/extensions/browser/api/serial/serial_connection.h +++ b/extensions/browser/api/serial/serial_connection.h
@@ -39,7 +39,7 @@ // does not necessarily imply an empty |data| string, since a receive may // complete partially before being interrupted by an error condition. using ReceiveCompleteCallback = - base::OnceCallback<void(std::vector<char> data, + base::OnceCallback<void(std::vector<uint8_t> data, api::serial::ReceiveError error)>; // This is the callback type expected by Send. Note that an error result @@ -108,7 +108,7 @@ // Begins an asynchronous send operation. Calling this while a Send // is already pending is a no-op and returns |false| without calling // |callback|. - virtual bool Send(const std::vector<char>& data, + virtual bool Send(const std::vector<uint8_t>& data, SendCompleteCallback callback); // Flushes input and output buffers.
diff --git a/extensions/browser/api/serial/serial_event_dispatcher.cc b/extensions/browser/api/serial/serial_event_dispatcher.cc index 4984c6b..e0a5a5b 100644 --- a/extensions/browser/api/serial/serial_event_dispatcher.cc +++ b/extensions/browser/api/serial/serial_event_dispatcher.cc
@@ -98,7 +98,7 @@ // static void SerialEventDispatcher::ReceiveCallback(const ReceiveParams& params, - std::vector<char> data, + std::vector<uint8_t> data, serial::ReceiveError error) { DCHECK_CURRENTLY_ON(params.thread_id);
diff --git a/extensions/browser/api/serial/serial_event_dispatcher.h b/extensions/browser/api/serial/serial_event_dispatcher.h index 500a352..63b863eb 100644 --- a/extensions/browser/api/serial/serial_event_dispatcher.h +++ b/extensions/browser/api/serial/serial_event_dispatcher.h
@@ -62,7 +62,7 @@ static void StartReceive(const ReceiveParams& params); static void ReceiveCallback(const ReceiveParams& params, - std::vector<char> data, + std::vector<uint8_t> data, serial::ReceiveError error); static void PostEvent(const ReceiveParams& params,
diff --git a/extensions/browser/api/socket/BUILD.gn b/extensions/browser/api/socket/BUILD.gn index e20046a05..a707906e 100644 --- a/extensions/browser/api/socket/BUILD.gn +++ b/extensions/browser/api/socket/BUILD.gn
@@ -9,8 +9,6 @@ source_set("socket") { sources = [ - "mojo_data_pump.cc", - "mojo_data_pump.h", "socket.cc", "socket.h", "socket_api.cc",
diff --git a/extensions/browser/api/socket/mojo_data_pump.cc b/extensions/browser/api/socket/mojo_data_pump.cc deleted file mode 100644 index fdc22f73..0000000 --- a/extensions/browser/api/socket/mojo_data_pump.cc +++ /dev/null
@@ -1,117 +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 "extensions/browser/api/socket/mojo_data_pump.h" - -#include <utility> - -#include "base/memory/ptr_util.h" -#include "net/base/completion_callback.h" -#include "net/base/io_buffer.h" -#include "net/base/net_errors.h" - -namespace extensions { - -MojoDataPump::MojoDataPump(mojo::ScopedDataPipeConsumerHandle receive_stream, - mojo::ScopedDataPipeProducerHandle send_stream) - : receive_stream_(std::move(receive_stream)), - receive_stream_watcher_(FROM_HERE, - mojo::SimpleWatcher::ArmingPolicy::MANUAL), - send_stream_(std::move(send_stream)), - send_stream_watcher_(FROM_HERE, - mojo::SimpleWatcher::ArmingPolicy::MANUAL) { - DCHECK(receive_stream_.is_valid()); - DCHECK(send_stream_.is_valid()); - receive_stream_watcher_.Watch( - receive_stream_.get(), - MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED, - base::BindRepeating(&MojoDataPump::ReceiveMore, base::Unretained(this))); - send_stream_watcher_.Watch( - send_stream_.get(), - MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, - MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED, - base::BindRepeating(&MojoDataPump::SendMore, base::Unretained(this))); -} - -MojoDataPump::~MojoDataPump() {} - -void MojoDataPump::Read(int count, ReadCallback callback) { - DCHECK(callback); - DCHECK(!read_callback_); - - if (count <= 0) { - std::move(callback).Run(net::ERR_INVALID_ARGUMENT, nullptr); - return; - } - - read_size_ = count; - read_callback_ = std::move(callback); - receive_stream_watcher_.ArmOrNotify(); -} - -void MojoDataPump::Write(net::IOBuffer* io_buffer, - int io_buffer_size, - net::CompletionOnceCallback callback) { - DCHECK(callback); - DCHECK(!write_callback_); - - write_callback_ = std::move(callback); - pending_write_buffer_ = io_buffer; - pending_write_buffer_size_ = io_buffer_size; - - send_stream_watcher_.ArmOrNotify(); -} - -void MojoDataPump::ReceiveMore(MojoResult result, - const mojo::HandleSignalsState& /* ignored */) { - DCHECK(read_callback_); - DCHECK_NE(0u, read_size_); - - if (result != MOJO_RESULT_OK) { - read_size_ = 0; - std::move(read_callback_).Run(net::ERR_FAILED, nullptr); - return; - } - - uint32_t num_bytes = read_size_; - auto io_buffer = - base::MakeRefCounted<net::IOBuffer>(static_cast<size_t>(num_bytes)); - result = receive_stream_->ReadData(io_buffer->data(), &num_bytes, - MOJO_READ_DATA_FLAG_NONE); - if (result != MOJO_RESULT_OK) { - read_size_ = 0; - std::move(read_callback_).Run(net::ERR_FAILED, nullptr); - return; - } - - if (result == MOJO_RESULT_SHOULD_WAIT) { - receive_stream_watcher_.ArmOrNotify(); - return; - } - read_size_ = 0; - std::move(read_callback_).Run(num_bytes, io_buffer); -} - -void MojoDataPump::SendMore(MojoResult result, - const mojo::HandleSignalsState& state) { - DCHECK(write_callback_); - - uint32_t num_bytes = pending_write_buffer_size_; - result = send_stream_->WriteData(pending_write_buffer_->data(), &num_bytes, - MOJO_WRITE_DATA_FLAG_NONE); - if (result == MOJO_RESULT_SHOULD_WAIT) { - send_stream_watcher_.ArmOrNotify(); - return; - } - pending_write_buffer_ = nullptr; - pending_write_buffer_size_ = 0; - if (result != MOJO_RESULT_OK) { - std::move(write_callback_).Run(net::ERR_FAILED); - return; - } - std::move(write_callback_).Run(num_bytes); -} - -} // namespace extensions
diff --git a/extensions/browser/api/socket/mojo_data_pump.h b/extensions/browser/api/socket/mojo_data_pump.h deleted file mode 100644 index f4f6876..0000000 --- a/extensions/browser/api/socket/mojo_data_pump.h +++ /dev/null
@@ -1,71 +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 EXTENSIONS_BROWSER_API_SOCKET_MOJO_DATA_PUMP_H_ -#define EXTENSIONS_BROWSER_API_SOCKET_MOJO_DATA_PUMP_H_ - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "extensions/browser/api/socket/socket.h" -#include "mojo/public/cpp/system/data_pipe.h" -#include "mojo/public/cpp/system/simple_watcher.h" -#include "net/base/completion_once_callback.h" - -namespace net { -class IOBuffer; -}; - -namespace extensions { - -// Helper class to read from a mojo consumer handle and write to mojo producer -// handle. -class MojoDataPump { - public: - using ReadCallback = - base::OnceCallback<void(int, scoped_refptr<net::IOBuffer> io_buffer)>; - - MojoDataPump(mojo::ScopedDataPipeConsumerHandle receive_stream, - mojo::ScopedDataPipeProducerHandle send_stream); - - ~MojoDataPump(); - - // Reads from |receive_stream|. It's illegal to call Read() when a previous - // one hasn't completed yet. - void Read(int count, ReadCallback callback); - - // Writes to |send_stream|. It's illegal to call Write() when a previous one - // hasn't completed yet. - void Write(net::IOBuffer* io_buffer, - int io_buffer_size, - net::CompletionOnceCallback callback); - - // Returns whether a read is pending. - bool HasPendingRead() const { return !read_callback_.is_null(); } - - // Returns whether a write is pending. - bool HasPendingWrite() const { return !write_callback_.is_null(); } - - private: - void OnReadComplete(scoped_refptr<net::IOBuffer> io_buffer, int result); - void StartWatching(); - void ReceiveMore(MojoResult result, const mojo::HandleSignalsState& state); - void SendMore(MojoResult result, const mojo::HandleSignalsState& state); - - mojo::ScopedDataPipeConsumerHandle receive_stream_; - mojo::SimpleWatcher receive_stream_watcher_; - mojo::ScopedDataPipeProducerHandle send_stream_; - mojo::SimpleWatcher send_stream_watcher_; - - ReadCallback read_callback_; - net::CompletionOnceCallback write_callback_; - scoped_refptr<net::IOBuffer> pending_write_buffer_; - int pending_write_buffer_size_ = 0; - uint32_t read_size_ = 0; - - DISALLOW_COPY_AND_ASSIGN(MojoDataPump); -}; - -} // namespace extensions - -#endif // EXTENSIONS_BROWSER_API_SOCKET_MOJO_DATA_PUMP_H_
diff --git a/extensions/browser/api/socket/socket.cc b/extensions/browser/api/socket/socket.cc index 23dac927..74f1132d 100644 --- a/extensions/browser/api/socket/socket.cc +++ b/extensions/browser/api/socket/socket.cc
@@ -85,27 +85,20 @@ WriteData(); } -void Socket::SetKeepAlive(bool enable, - int delay, - SetKeepAliveCallback callback) { - std::move(callback).Run(false); +bool Socket::SetKeepAlive(bool enable, int delay) { return false; } + +bool Socket::SetNoDelay(bool no_delay) { return false; } + +int Socket::Listen(const std::string& address, + uint16_t port, + int backlog, + std::string* error_msg) { + *error_msg = kSocketTypeNotSupported; + return net::ERR_FAILED; } -void Socket::SetNoDelay(bool no_delay, SetNoDelayCallback callback) { - std::move(callback).Run(false); -} - -void Socket::Listen(const std::string& address, - uint16_t port, - int backlog, - ListenCallback callback) { - std::move(callback).Run(net::ERR_FAILED, kSocketTypeNotSupported); -} - -void Socket::Accept(AcceptCompletionCallback callback) { - std::move(callback).Run(net::ERR_FAILED, nullptr /* socket */, base::nullopt, - mojo::ScopedDataPipeConsumerHandle(), - mojo::ScopedDataPipeProducerHandle()); +void Socket::Accept(const AcceptCompletionCallback& callback) { + callback.Run(net::ERR_FAILED, NULL); } // static
diff --git a/extensions/browser/api/socket/socket.h b/extensions/browser/api/socket/socket.h index a55eede..d83b94c 100644 --- a/extensions/browser/api/socket/socket.h +++ b/extensions/browser/api/socket/socket.h
@@ -7,7 +7,6 @@ #include <stdint.h> -#include <memory> #include <string> #include <utility> @@ -18,13 +17,11 @@ #include "content/public/browser/browser_thread.h" #include "extensions/browser/api/api_resource.h" #include "extensions/browser/api/api_resource_manager.h" -#include "net/base/completion_once_callback.h" +#include "net/base/completion_callback.h" #include "net/base/io_buffer.h" #include "net/base/ip_endpoint.h" #include "net/socket/tcp_client_socket.h" #include "net/traffic_annotation/network_traffic_annotation.h" -#include "services/network/public/mojom/tcp_socket.mojom.h" -#include "services/network/public/mojom/tls_socket.mojom.h" #if defined(OS_CHROMEOS) #include "extensions/browser/api/socket/app_firewall_hole_manager.h" @@ -39,9 +36,7 @@ namespace extensions { using CompletionCallback = base::Callback<void(int)>; -using SetNoDelayCallback = base::OnceCallback<void(bool)>; -using SetKeepAliveCallback = base::OnceCallback<void(bool)>; -using ReadCompletionCallback = base::OnceCallback< +using ReadCompletionCallback = base::Callback< void(int, scoped_refptr<net::IOBuffer> io_buffer, bool socket_destroying)>; using RecvFromCompletionCallback = base::Callback<void(int, @@ -49,15 +44,8 @@ bool socket_destroying, const std::string&, uint16_t)>; -using ListenCallback = - base::OnceCallback<void(int, const std::string& error_msg)>; - using AcceptCompletionCallback = - base::OnceCallback<void(int, - network::mojom::TCPConnectedSocketPtr, - const base::Optional<net::IPEndPoint>&, - mojo::ScopedDataPipeConsumerHandle, - mojo::ScopedDataPipeProducerHandle)>; + base::Callback<void(int, std::unique_ptr<net::TCPClientSocket>)>; // A Socket wraps a low-level socket and includes housekeeping information that // we need to manage it in the context of an extension. @@ -90,7 +78,7 @@ // the remote endpoint. In order to upgrade this socket to TLS, callers // must also supply the hostname of the endpoint via set_hostname(). virtual void Connect(const net::AddressList& address, - net::CompletionOnceCallback callback) = 0; + const CompletionCallback& callback) = 0; // |socket_destroying| is true if disconnect is due to destruction of the // socket. virtual void Disconnect(bool socket_destroying) = 0; @@ -100,7 +88,7 @@ // The |callback| will be called with the number of bytes read into the // buffer, or a negative number if an error occurred. - virtual void Read(int count, ReadCompletionCallback callback) = 0; + virtual void Read(int count, const ReadCompletionCallback& callback) = 0; // The |callback| will be called with |byte_count| or a negative number if an // error occurred. @@ -115,15 +103,13 @@ const net::IPEndPoint& address, const CompletionCallback& callback) = 0; - virtual void SetKeepAlive(bool enable, - int delay, - SetKeepAliveCallback callback); - virtual void SetNoDelay(bool no_delay, SetNoDelayCallback callback); - virtual void Listen(const std::string& address, - uint16_t port, - int backlog, - ListenCallback callback); - virtual void Accept(AcceptCompletionCallback callback); + virtual bool SetKeepAlive(bool enable, int delay); + virtual bool SetNoDelay(bool no_delay); + virtual int Listen(const std::string& address, + uint16_t port, + int backlog, + std::string* error_msg); + virtual void Accept(const AcceptCompletionCallback& callback); virtual bool IsConnected() = 0;
diff --git a/extensions/browser/api/socket/socket_api.cc b/extensions/browser/api/socket/socket_api.cc index 647fa587..8f7c8cf 100644 --- a/extensions/browser/api/socket/socket_api.cc +++ b/extensions/browser/api/socket/socket_api.cc
@@ -4,6 +4,7 @@ #include "extensions/browser/api/socket/socket_api.h" +#include <memory> #include <utility> #include <vector> @@ -253,7 +254,7 @@ void SocketCreateFunction::Work() { Socket* socket = NULL; if (socket_type_ == kSocketTypeTCP) { - socket = new TCPSocket(browser_context(), extension_->id()); + socket = new TCPSocket(extension_->id()); } else if (socket_type_ == kSocketTypeUDP) { socket = new UDPSocket(std::move(socket_), std::move(socket_receiver_request_), @@ -462,27 +463,15 @@ return; } - socket->Listen(params_->address, params_->port, - params_->backlog.get() ? *params_->backlog : 5, - base::BindOnce(&SocketListenFunction::OnCompleted, this)); -} - -void SocketListenFunction::OnCompleted(int result, - const std::string& error_msg) { - DCHECK_NE(net::ERR_IO_PENDING, result); - Socket* socket = GetSocket(params_->socket_id); - if (!socket) { - error_ = kSocketNotFoundError; - SetResult(std::make_unique<base::Value>(-1)); - AsyncWorkCompleted(); - return; - } + int result = + socket->Listen(params_->address, params_->port, + params_->backlog.get() ? *params_->backlog : 5, &error_); SetResult(std::make_unique<base::Value>(result)); if (result != net::OK) { - error_ = error_msg; AsyncWorkCompleted(); return; } + OpenFirewallHole(params_->address, params_->socket_id, socket); } @@ -499,27 +488,21 @@ void SocketAcceptFunction::AsyncWorkStart() { Socket* socket = GetSocket(params_->socket_id); if (socket) { - socket->Accept(base::BindOnce(&SocketAcceptFunction::OnAccept, this)); + socket->Accept(base::Bind(&SocketAcceptFunction::OnAccept, this)); } else { error_ = kSocketNotFoundError; - OnAccept(net::ERR_FAILED, nullptr, base::nullopt, - mojo::ScopedDataPipeConsumerHandle(), - mojo::ScopedDataPipeProducerHandle()); + OnAccept(-1, NULL); } } void SocketAcceptFunction::OnAccept( int result_code, - network::mojom::TCPConnectedSocketPtr socket, - const base::Optional<net::IPEndPoint>& remote_addr, - mojo::ScopedDataPipeConsumerHandle receive_pipe_handle, - mojo::ScopedDataPipeProducerHandle send_pipe_handle) { + std::unique_ptr<net::TCPClientSocket> socket) { std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue()); result->SetInteger(kResultCodeKey, result_code); - if (result_code == net::OK) { + if (socket) { Socket* client_socket = - new TCPSocket(std::move(socket), std::move(receive_pipe_handle), - std::move(send_pipe_handle), remote_addr, extension_id()); + new TCPSocket(std::move(socket), extension_id(), true); result->SetInteger(kSocketIdKey, AddSocket(client_socket)); } SetResult(std::move(result)); @@ -546,7 +529,7 @@ } socket->Read(params_->buffer_size.get() ? *params_->buffer_size : 4096, - base::BindOnce(&SocketReadFunction::OnCompleted, this)); + base::BindRepeating(&SocketReadFunction::OnCompleted, this)); } void SocketReadFunction::OnCompleted(int bytes_read, @@ -581,8 +564,8 @@ socket_id_ = socket_id_value.GetInt(); io_buffer_size_ = data_value.GetBlob().size(); - io_buffer_ = - base::MakeRefCounted<net::WrappedIOBuffer>(data_value.GetBlob().data()); + io_buffer_ = base::MakeRefCounted<net::WrappedIOBuffer>( + reinterpret_cast<const char*>(data_value.GetBlob().data())); return true; } @@ -679,8 +662,8 @@ hostname_ = hostname_value.GetString(); io_buffer_size_ = data_value.GetBlob().size(); - io_buffer_ = - base::MakeRefCounted<net::WrappedIOBuffer>(data_value.GetBlob().data()); + io_buffer_ = base::MakeRefCounted<net::WrappedIOBuffer>( + reinterpret_cast<const char*>(data_value.GetBlob().data())); return true; } @@ -748,25 +731,18 @@ return true; } -void SocketSetKeepAliveFunction::AsyncWorkStart() { +void SocketSetKeepAliveFunction::Work() { + bool result = false; Socket* socket = GetSocket(params_->socket_id); - if (!socket) { - SetResult(std::make_unique<base::Value>(false)); + if (socket) { + int delay = 0; + if (params_->delay.get()) + delay = *params_->delay; + result = socket->SetKeepAlive(params_->enable, delay); + } else { error_ = kSocketNotFoundError; - AsyncWorkCompleted(); - return; } - int delay = 0; - if (params_->delay.get()) - delay = *params_->delay; - socket->SetKeepAlive( - params_->enable, delay, - base::BindOnce(&SocketSetKeepAliveFunction::OnCompleted, this)); -} - -void SocketSetKeepAliveFunction::OnCompleted(bool success) { - SetResult(std::make_unique<base::Value>(success)); - AsyncWorkCompleted(); + SetResult(std::make_unique<base::Value>(result)); } SocketSetNoDelayFunction::SocketSetNoDelayFunction() {} @@ -779,22 +755,14 @@ return true; } -void SocketSetNoDelayFunction::AsyncWorkStart() { +void SocketSetNoDelayFunction::Work() { + bool result = false; Socket* socket = GetSocket(params_->socket_id); - if (!socket) { + if (socket) + result = socket->SetNoDelay(params_->no_delay); + else error_ = kSocketNotFoundError; - SetResult(std::make_unique<base::Value>(false)); - AsyncWorkCompleted(); - return; - } - socket->SetNoDelay( - params_->no_delay, - base::BindOnce(&SocketSetNoDelayFunction::OnCompleted, this)); -} - -void SocketSetNoDelayFunction::OnCompleted(bool success) { - SetResult(std::make_unique<base::Value>(success)); - AsyncWorkCompleted(); + SetResult(std::make_unique<base::Value>(result)); } SocketGetInfoFunction::SocketGetInfoFunction() {} @@ -1116,6 +1084,8 @@ DCHECK_CURRENTLY_ON(BrowserThread::UI); params_ = api::socket::Secure::Params::Create(*args_); EXTENSION_FUNCTION_VALIDATE(params_.get()); + url_request_getter_ = content::BrowserContext::GetDefaultStoragePartition( + browser_context())->GetURLRequestContext(); return true; } @@ -1133,7 +1103,8 @@ } // Make sure that the socket is a TCP client socket. - if (socket->GetSocketType() != Socket::TYPE_TCP) { + if (socket->GetSocketType() != Socket::TYPE_TCP || + static_cast<TCPSocket*>(socket)->ClientStream() == NULL) { SetResult(std::make_unique<base::Value>(net::ERR_INVALID_ARGUMENT)); error_ = kSecureSocketTypeError; AsyncWorkCompleted(); @@ -1147,32 +1118,31 @@ return; } - TCPSocket* tcp_socket = static_cast<TCPSocket*>(socket); - tcp_socket->UpgradeToTLS( + net::URLRequestContext* url_request_context = + url_request_getter_->GetURLRequestContext(); + + TLSSocket::UpgradeSocketToTLS( + socket, url_request_context->ssl_config_service(), + url_request_context->cert_verifier(), + url_request_context->transport_security_state(), + url_request_context->cert_transparency_verifier(), + url_request_context->ct_policy_enforcer(), extension_id(), params_->options.get(), - base::BindOnce(&SocketSecureFunction::TlsConnectDone, this)); + base::Bind(&SocketSecureFunction::TlsConnectDone, this)); } -void SocketSecureFunction::TlsConnectDone( - int result, - network::mojom::TLSClientSocketPtr tls_socket, - const net::IPEndPoint& local_addr, - const net::IPEndPoint& peer_addr, - mojo::ScopedDataPipeConsumerHandle receive_pipe_handle, - mojo::ScopedDataPipeProducerHandle send_pipe_handle) { - if (result != net::OK) { +void SocketSecureFunction::TlsConnectDone(std::unique_ptr<TLSSocket> socket, + int result) { + // if an error occurred, socket MUST be NULL. + DCHECK(result == net::OK || socket == NULL); + + if (socket && result == net::OK) { + ReplaceSocket(params_->socket_id, socket.release()); + } else { RemoveSocket(params_->socket_id); error_ = net::ErrorToString(result); - results_ = api::socket::Secure::Results::Create(result); - AsyncWorkCompleted(); - return; } - auto socket = - std::make_unique<TLSSocket>(std::move(tls_socket), local_addr, peer_addr, - std::move(receive_pipe_handle), - std::move(send_pipe_handle), extension_id()); - ReplaceSocket(params_->socket_id, socket.release()); results_ = api::socket::Secure::Results::Create(result); AsyncWorkCompleted(); }
diff --git a/extensions/browser/api/socket/socket_api.h b/extensions/browser/api/socket/socket_api.h index eae243f..cf52938 100644 --- a/extensions/browser/api/socket/socket_api.h +++ b/extensions/browser/api/socket/socket_api.h
@@ -8,7 +8,6 @@ #include <stddef.h> #include <stdint.h> -#include <memory> #include <string> #include "base/gtest_prod_util.h" @@ -42,6 +41,7 @@ namespace extensions { class Socket; +class TLSSocket; // A simple interface to ApiResourceManager<Socket> or derived class. The goal // of this interface is to allow Socket API functions to use distinct instances @@ -184,10 +184,8 @@ FRIEND_TEST_ALL_PREFIXES(SocketUnitTest, Create); enum SocketType { kSocketTypeInvalid = -1, kSocketTypeTCP, kSocketTypeUDP }; - // These two fields are only applicable if |socket_type_| is UDP. network::mojom::UDPSocketPtrInfo socket_; network::mojom::UDPSocketReceiverRequest socket_receiver_request_; - std::unique_ptr<api::socket::Create::Params> params_; SocketType socket_type_; }; @@ -280,7 +278,6 @@ void AsyncWorkStart() override; private: - void OnCompleted(int result, const std::string& error_msg); std::unique_ptr<api::socket::Listen::Params> params_; }; @@ -298,11 +295,7 @@ void AsyncWorkStart() override; private: - void OnAccept(int result_code, - network::mojom::TCPConnectedSocketPtr socket, - const base::Optional<net::IPEndPoint>& remote_addr, - mojo::ScopedDataPipeConsumerHandle receive_pipe_handle, - mojo::ScopedDataPipeProducerHandle send_pipe_handle); + void OnAccept(int result_code, std::unique_ptr<net::TCPClientSocket> socket); std::unique_ptr<api::socket::Accept::Params> params_; }; @@ -407,11 +400,9 @@ // AsyncApiFunction: bool Prepare() override; - void AsyncWorkStart() override; + void Work() override; private: - void OnCompleted(bool success); - std::unique_ptr<api::socket::SetKeepAlive::Params> params_; }; @@ -426,11 +417,9 @@ // AsyncApiFunction: bool Prepare() override; - void AsyncWorkStart() override; + void Work() override; private: - void OnCompleted(bool success); - std::unique_ptr<api::socket::SetNoDelay::Params> params_; }; @@ -572,14 +561,11 @@ void AsyncWorkStart() override; private: - void TlsConnectDone(int result, - network::mojom::TLSClientSocketPtr tls_socket, - const net::IPEndPoint& local_addr, - const net::IPEndPoint& peer_addr, - mojo::ScopedDataPipeConsumerHandle receive_pipe_handle, - mojo::ScopedDataPipeProducerHandle send_pipe_handle); + // Callback from TLSSocket::UpgradeSocketToTLS(). + void TlsConnectDone(std::unique_ptr<TLSSocket> socket, int result); std::unique_ptr<api::socket::Secure::Params> params_; + scoped_refptr<net::URLRequestContextGetter> url_request_getter_; DISALLOW_COPY_AND_ASSIGN(SocketSecureFunction); };
diff --git a/extensions/browser/api/socket/tcp_socket.cc b/extensions/browser/api/socket/tcp_socket.cc index e80bd771..a1ee755 100644 --- a/extensions/browser/api/socket/tcp_socket.cc +++ b/extensions/browser/api/socket/tcp_socket.cc
@@ -4,49 +4,21 @@ #include "extensions/browser/api/socket/tcp_socket.h" -#include <utility> - #include "base/callback_helpers.h" #include "base/lazy_instance.h" #include "base/logging.h" #include "base/macros.h" #include "base/memory/ptr_util.h" -#include "content/public/browser/browser_context.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/storage_partition.h" #include "extensions/browser/api/api_resource.h" -#include "extensions/browser/api/socket/mojo_data_pump.h" #include "net/base/address_list.h" #include "net/base/ip_endpoint.h" #include "net/base/net_errors.h" -#include "net/base/url_util.h" -#include "services/network/public/mojom/ssl_config.mojom.h" +#include "net/base/rand_callback.h" +#include "net/log/net_log_source.h" +#include "net/socket/tcp_client_socket.h" namespace extensions { -namespace { - -// Returns true if successfully parsed the SSL protocol version that is -// represented by a string. Returns false if |version_str| is invalid. -bool SSLProtocolVersionFromString(const std::string& version_str, - network::mojom::SSLVersion* version_out) { - if (version_str == "tls1") { - *version_out = network::mojom::SSLVersion::kTLS1; - return true; - } - if (version_str == "tls1.1") { - *version_out = network::mojom::SSLVersion::kTLS11; - return true; - } - if (version_str == "tls1.2") { - *version_out = network::mojom::SSLVersion::kTLS12; - return true; - } - return false; -} - -} // namespace - const char kTCPSocketTypeInvalidError[] = "Cannot call both connect and listen on the same socket."; const char kSocketListenError[] = "Could not listen on the specified port."; @@ -73,31 +45,38 @@ return g_server_factory.Pointer(); } -TCPSocket::TCPSocket(content::BrowserContext* browser_context, +TCPSocket::TCPSocket(const std::string& owner_extension_id) + : Socket(owner_extension_id), socket_mode_(UNKNOWN) {} + +TCPSocket::TCPSocket(std::unique_ptr<net::TCPClientSocket> tcp_client_socket, + const std::string& owner_extension_id, + bool is_connected) + : Socket(owner_extension_id), + socket_(std::move(tcp_client_socket)), + socket_mode_(CLIENT) { + this->is_connected_ = is_connected; +} + +TCPSocket::TCPSocket(std::unique_ptr<net::TCPServerSocket> tcp_server_socket, const std::string& owner_extension_id) : Socket(owner_extension_id), - browser_context_(browser_context), - socket_mode_(UNKNOWN), - mojo_data_pump_(nullptr), - task_runner_(base::SequencedTaskRunnerHandle::Get()), - weak_factory_(this) {} + server_socket_(std::move(tcp_server_socket)), + socket_mode_(SERVER) {} -TCPSocket::TCPSocket(network::mojom::TCPConnectedSocketPtr socket, - mojo::ScopedDataPipeConsumerHandle receive_stream, - mojo::ScopedDataPipeProducerHandle send_stream, - const base::Optional<net::IPEndPoint>& remote_addr, - const std::string& owner_extension_id) - : Socket(owner_extension_id), - browser_context_(nullptr), - socket_mode_(CLIENT), - client_socket_(std::move(socket)), - mojo_data_pump_(std::make_unique<MojoDataPump>(std::move(receive_stream), - std::move(send_stream))), - task_runner_(base::SequencedTaskRunnerHandle::Get()), - peer_addr_(remote_addr), +// static +TCPSocket* TCPSocket::CreateSocketForTesting( + std::unique_ptr<net::TCPClientSocket> tcp_client_socket, + const std::string& owner_extension_id, + bool is_connected) { + return new TCPSocket(std::move(tcp_client_socket), owner_extension_id, + is_connected); +} - weak_factory_(this) { - is_connected_ = true; +// static +TCPSocket* TCPSocket::CreateServerSocketForTesting( + std::unique_ptr<net::TCPServerSocket> tcp_server_socket, + const std::string& owner_extension_id) { + return new TCPSocket(std::move(tcp_server_socket), owner_extension_id); } TCPSocket::~TCPSocket() { @@ -105,57 +84,48 @@ } void TCPSocket::Connect(const net::AddressList& address, - net::CompletionOnceCallback callback) { - DCHECK(callback); + const CompletionCallback& callback) { + DCHECK(!callback.is_null()); - if (socket_mode_ == SERVER || connect_callback_) { - std::move(callback).Run(net::ERR_CONNECTION_FAILED); + if (socket_mode_ == SERVER || !connect_callback_.is_null()) { + callback.Run(net::ERR_CONNECTION_FAILED); return; } if (is_connected_) { - std::move(callback).Run(net::ERR_SOCKET_IS_CONNECTED); + callback.Run(net::ERR_SOCKET_IS_CONNECTED); return; } - DCHECK(!server_socket_); + DCHECK(!server_socket_.get()); socket_mode_ = CLIENT; - connect_callback_ = std::move(callback); + connect_callback_ = callback; - // |completion_callback| is called on current thread. - network::mojom::NetworkContext::CreateTCPConnectedSocketCallback - completion_callback = base::BindOnce(&TCPSocket::OnConnectComplete, - weak_factory_.GetWeakPtr()); + int result = net::ERR_CONNECTION_FAILED; + if (!is_connected_) { + socket_.reset( + new net::TCPClientSocket(address, NULL, NULL, net::NetLogSource())); + result = socket_->Connect( + base::Bind(&TCPSocket::OnConnectComplete, base::Unretained(this))); + } - // |completion_callback_ui| is called on the UI thread. - network::mojom::NetworkContext::CreateTCPConnectedSocketCallback - completion_callback_ui = - base::BindOnce(&TCPSocket::OnConnectCompleteOnUIThread, task_runner_, - std::move(completion_callback)); - - content::BrowserThread::PostTask( - content::BrowserThread::UI, FROM_HERE, - base::BindOnce(&TCPSocket::ConnectOnUIThread, storage_partition_, - browser_context_, address, - mojo::MakeRequest(&client_socket_), - std::move(completion_callback_ui))); + if (result != net::ERR_IO_PENDING) + OnConnectComplete(result); } void TCPSocket::Disconnect(bool socket_destroying) { is_connected_ = false; - local_addr_ = base::nullopt; - peer_addr_ = base::nullopt; - mojo_data_pump_ = nullptr; - client_socket_.reset(); - server_socket_.reset(); - listen_callback_.Reset(); + if (socket_.get()) + socket_->Disconnect(); + server_socket_.reset(NULL); connect_callback_.Reset(); - accept_callback_.Reset(); // TODO(devlin): Should we do this for all callbacks? - if (read_callback_) { - std::move(read_callback_) + if (!read_callback_.is_null()) { + base::ResetAndReturn(&read_callback_) .Run(net::ERR_CONNECTION_CLOSED, nullptr, socket_destroying); } + accept_callback_.Reset(); + accept_socket_.reset(NULL); } void TCPSocket::Bind(const std::string& address, @@ -164,30 +134,42 @@ callback.Run(net::ERR_FAILED); } -void TCPSocket::Read(int count, ReadCompletionCallback callback) { - DCHECK(callback); +void TCPSocket::Read(int count, const ReadCompletionCallback& callback) { + DCHECK(!callback.is_null()); const bool socket_destroying = false; if (socket_mode_ != CLIENT) { - std::move(callback).Run(net::ERR_FAILED, nullptr, socket_destroying); + callback.Run(net::ERR_FAILED, nullptr, socket_destroying); return; } - if (!mojo_data_pump_) { - std::move(callback).Run(net::ERR_SOCKET_NOT_CONNECTED, nullptr, - socket_destroying); - return; - } - if (mojo_data_pump_->HasPendingRead() || connect_callback_) { + if (!read_callback_.is_null() || !connect_callback_.is_null()) { // It's illegal to read a net::TCPSocket while a pending Connect or Read is // already in progress. - std::move(callback).Run(net::ERR_IO_PENDING, nullptr, socket_destroying); + callback.Run(net::ERR_IO_PENDING, nullptr, socket_destroying); return; } - read_callback_ = std::move(callback); - mojo_data_pump_->Read(count, base::BindOnce(&TCPSocket::OnReadComplete, - base::Unretained(this))); + if (count < 0) { + callback.Run(net::ERR_INVALID_ARGUMENT, nullptr, socket_destroying); + return; + } + + if (!socket_.get() || !is_connected_) { + callback.Run(net::ERR_SOCKET_NOT_CONNECTED, nullptr, socket_destroying); + return; + } + + read_callback_ = callback; + scoped_refptr<net::IOBuffer> io_buffer = new net::IOBuffer(count); + int result = socket_->Read( + io_buffer.get(), + count, + base::Bind( + &TCPSocket::OnReadComplete, base::Unretained(this), io_buffer)); + + if (result != net::ERR_IO_PENDING) + OnReadComplete(io_buffer, result); } void TCPSocket::RecvFrom(int count, @@ -203,105 +185,85 @@ callback.Run(net::ERR_FAILED); } -void TCPSocket::SetKeepAlive(bool enable, - int delay, - SetKeepAliveCallback callback) { - if (!client_socket_) { - std::move(callback).Run(net::ERR_FAILED); - return; - } - client_socket_->SetKeepAlive(enable, delay, std::move(callback)); +bool TCPSocket::SetKeepAlive(bool enable, int delay) { + if (!socket_.get()) + return false; + return socket_->SetKeepAlive(enable, delay); } -void TCPSocket::SetNoDelay(bool no_delay, SetNoDelayCallback callback) { - if (!client_socket_) { - std::move(callback).Run(net::ERR_FAILED); - return; - } - client_socket_->SetNoDelay(no_delay, std::move(callback)); +bool TCPSocket::SetNoDelay(bool no_delay) { + if (!socket_.get()) + return false; + return socket_->SetNoDelay(no_delay); } -void TCPSocket::Listen(const std::string& address, - uint16_t port, - int backlog, - ListenCallback callback) { - DCHECK(!server_socket_); - DCHECK(!client_socket_); - DCHECK(!listen_callback_); - +int TCPSocket::Listen(const std::string& address, + uint16_t port, + int backlog, + std::string* error_msg) { if (socket_mode_ == CLIENT) { - std::move(callback).Run(net::ERR_NOT_IMPLEMENTED, - kTCPSocketTypeInvalidError); - return; + *error_msg = kTCPSocketTypeInvalidError; + return net::ERR_NOT_IMPLEMENTED; } - - net::IPEndPoint ip_end_point; - if (!StringAndPortToIPEndPoint(address, port, &ip_end_point)) { - std::move(callback).Run(net::ERR_INVALID_ARGUMENT, ""); - return; - } - + DCHECK(!socket_.get()); socket_mode_ = SERVER; - listen_callback_ = std::move(callback); + if (!server_socket_.get()) { + server_socket_.reset(new net::TCPServerSocket(NULL, net::NetLogSource())); + } - // |completion_callback| is called on current thread. - network::mojom::NetworkContext::CreateTCPServerSocketCallback - completion_callback = base::BindOnce(&TCPSocket::OnListenComplete, - weak_factory_.GetWeakPtr()); - - // |completion_callback_ui| is called on the UI thread. - network::mojom::NetworkContext::CreateTCPServerSocketCallback - completion_callback_ui = - base::BindOnce(&TCPSocket::OnListenCompleteOnUIThread, task_runner_, - std::move(completion_callback)); - - content::BrowserThread::PostTask( - content::BrowserThread::UI, FROM_HERE, - base::BindOnce(&TCPSocket::ListenOnUIThread, storage_partition_, - browser_context_, ip_end_point, backlog, - mojo::MakeRequest(&server_socket_), - std::move(completion_callback_ui))); + int result = server_socket_->ListenWithAddressAndPort(address, port, backlog); + if (result) { + server_socket_.reset(); + *error_msg = kSocketListenError; + } + return result; } -void TCPSocket::Accept(AcceptCompletionCallback callback) { +void TCPSocket::Accept(const AcceptCompletionCallback& callback) { if (socket_mode_ != SERVER || !server_socket_.get()) { - std::move(callback).Run(net::ERR_FAILED, nullptr, base::nullopt, - mojo::ScopedDataPipeConsumerHandle(), - mojo::ScopedDataPipeProducerHandle()); + callback.Run(net::ERR_FAILED, NULL); return; } // Limits to only 1 blocked accept call. - if (accept_callback_) { - std::move(callback).Run(net::ERR_FAILED, nullptr, base::nullopt, - mojo::ScopedDataPipeConsumerHandle(), - mojo::ScopedDataPipeProducerHandle()); + if (!accept_callback_.is_null()) { + callback.Run(net::ERR_FAILED, NULL); return; } - accept_callback_ = std::move(callback); - server_socket_->Accept( - nullptr /* observer */, - base::BindOnce(&TCPSocket::OnAccept, base::Unretained(this))); + int result = server_socket_->Accept( + &accept_socket_, + base::Bind(&TCPSocket::OnAccept, base::Unretained(this))); + if (result == net::ERR_IO_PENDING) { + accept_callback_ = callback; + } else if (result == net::OK) { + accept_callback_ = callback; + this->OnAccept(result); + } else { + callback.Run(result, NULL); + } } bool TCPSocket::IsConnected() { + RefreshConnectionStatus(); return is_connected_; } bool TCPSocket::GetPeerAddress(net::IPEndPoint* address) { - if (!peer_addr_) + if (!socket_.get()) return false; - *address = peer_addr_.value(); - return true; + return !socket_->GetPeerAddress(address); } bool TCPSocket::GetLocalAddress(net::IPEndPoint* address) { - if (!local_addr_) + if (socket_.get()) { + return !socket_->GetLocalAddress(address); + } else if (server_socket_.get()) { + return !server_socket_->GetLocalAddress(address); + } else { return false; - *address = local_addr_.value(); - return true; + } } Socket::SocketType TCPSocket::GetSocketType() const { return Socket::TYPE_TCP; } @@ -309,265 +271,97 @@ int TCPSocket::WriteImpl(net::IOBuffer* io_buffer, int io_buffer_size, const net::CompletionCallback& callback) { - if (!mojo_data_pump_) + if (socket_mode_ != CLIENT) + return net::ERR_FAILED; + else if (!socket_.get() || !IsConnected()) return net::ERR_SOCKET_NOT_CONNECTED; - - mojo_data_pump_->Write(io_buffer, io_buffer_size, - base::BindOnce(&TCPSocket::OnWriteComplete, - base::Unretained(this), callback)); - return net::ERR_IO_PENDING; + else + return socket_->Write(io_buffer, io_buffer_size, callback, + Socket::GetNetworkTrafficAnnotationTag()); } -// static -void TCPSocket::ConnectOnUIThread( - content::StoragePartition* storage_partition, - content::BrowserContext* browser_context, - const net::AddressList& remote_addr_list, - network::mojom::TCPConnectedSocketRequest request, - network::mojom::NetworkContext::CreateTCPConnectedSocketCallback - completion_callback) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - - if (!storage_partition) { - storage_partition = - content::BrowserContext::GetDefaultStoragePartition(browser_context); +void TCPSocket::RefreshConnectionStatus() { + if (!is_connected_) + return; + if (server_socket_) + return; + if (!socket_->IsConnected()) { + Disconnect(false /* socket_destroying */); } - storage_partition->GetNetworkContext()->CreateTCPConnectedSocket( - base::nullopt, remote_addr_list, - net::MutableNetworkTrafficAnnotationTag( - Socket::GetNetworkTrafficAnnotationTag()), - std::move(request), nullptr /* observer */, - std::move(completion_callback)); } -// static -void TCPSocket::OnConnectCompleteOnUIThread( - scoped_refptr<base::SequencedTaskRunner> original_task_runner, - network::mojom::NetworkContext::CreateTCPConnectedSocketCallback callback, - int result, - const base::Optional<net::IPEndPoint>& local_addr, - const base::Optional<net::IPEndPoint>& peer_addr, - mojo::ScopedDataPipeConsumerHandle receive_stream, - mojo::ScopedDataPipeProducerHandle send_stream) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - - original_task_runner->PostTask( - FROM_HERE, - base::BindOnce(std::move(callback), result, local_addr, peer_addr, - std::move(receive_stream), std::move(send_stream))); -} - -void TCPSocket::OnConnectComplete( - int result, - const base::Optional<net::IPEndPoint>& local_addr, - const base::Optional<net::IPEndPoint>& peer_addr, - mojo::ScopedDataPipeConsumerHandle receive_stream, - mojo::ScopedDataPipeProducerHandle send_stream) { +void TCPSocket::OnConnectComplete(int result) { + DCHECK(!connect_callback_.is_null()); DCHECK(!is_connected_); - DCHECK(connect_callback_); - DCHECK(task_runner_->RunsTasksInCurrentSequence()); + is_connected_ = result == net::OK; - if (result == net::OK) { - is_connected_ = true; - local_addr_ = local_addr; - peer_addr_ = peer_addr; - mojo_data_pump_ = std::make_unique<MojoDataPump>(std::move(receive_stream), - std::move(send_stream)); + // The completion callback may re-enter TCPSocket, e.g. to Read(); therefore + // we reset |connect_callback_| before calling it. + CompletionCallback connect_callback = connect_callback_; + connect_callback_.Reset(); + connect_callback.Run(result); +} + +void TCPSocket::OnReadComplete(scoped_refptr<net::IOBuffer> io_buffer, + int result) { + DCHECK(!read_callback_.is_null()); + read_callback_.Run(result, io_buffer, false /* socket_destroying */); + read_callback_.Reset(); +} + +void TCPSocket::OnAccept(int result) { + DCHECK(!accept_callback_.is_null()); + if (result == net::OK && accept_socket_.get()) { + accept_callback_.Run(result, + base::WrapUnique(static_cast<net::TCPClientSocket*>( + accept_socket_.release()))); + } else { + accept_callback_.Run(result, NULL); } - std::move(connect_callback_).Run(result); + accept_callback_.Reset(); } -// static -void TCPSocket::ListenOnUIThread( - content::StoragePartition* storage_partition, - content::BrowserContext* browser_context, - const net::IPEndPoint& local_addr, - int backlog, - network::mojom::TCPServerSocketRequest request, - network::mojom::NetworkContext::CreateTCPServerSocketCallback callback) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); +void TCPSocket::Release() { + // Release() is only invoked when the underlying sockets are taken (via + // ClientStream()) by TLSSocket. TLSSocket only supports CLIENT-mode + // sockets. + DCHECK(!server_socket_.release() && !accept_socket_.release() && + socket_mode_ == CLIENT) + << "Called in server mode."; - if (!storage_partition) { - storage_partition = - content::BrowserContext::GetDefaultStoragePartition(browser_context); - } - storage_partition->GetNetworkContext()->CreateTCPServerSocket( - local_addr, backlog, - net::MutableNetworkTrafficAnnotationTag( - Socket::GetNetworkTrafficAnnotationTag()), - std::move(request), std::move(callback)); + // Release() doesn't disconnect the underlying sockets, but it does + // disconnect them from this TCPSocket. + is_connected_ = false; + + connect_callback_.Reset(); + read_callback_.Reset(); + accept_callback_.Reset(); + + DCHECK(socket_.get()) << "Called on null client socket."; + ignore_result(socket_.release()); } -// static -void TCPSocket::OnListenCompleteOnUIThread( - const scoped_refptr<base::SequencedTaskRunner>& original_task_runner, - network::mojom::NetworkContext::CreateTCPServerSocketCallback callback, - int result, - const base::Optional<net::IPEndPoint>& local_addr) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - - original_task_runner->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), result, local_addr)); +net::TCPClientSocket* TCPSocket::ClientStream() { + if (socket_mode_ != CLIENT || GetSocketType() != TYPE_TCP) + return NULL; + return socket_.get(); } -void TCPSocket::OnListenComplete( - int result, - const base::Optional<net::IPEndPoint>& local_addr) { - DCHECK(task_runner_->RunsTasksInCurrentSequence()); - DCHECK(listen_callback_); - - if (result != net::OK) { - server_socket_.reset(); - std::move(listen_callback_).Run(result, kSocketListenError); - return; - } - local_addr_ = local_addr; - std::move(listen_callback_).Run(result, ""); +bool TCPSocket::HasPendingRead() const { + return !read_callback_.is_null(); } -content::StoragePartition* TCPSocket::GetStoragePartitionHelper() { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - return storage_partition_ - ? storage_partition_ - : content::BrowserContext::GetDefaultStoragePartition( - browser_context_); -} - -void TCPSocket::OnAccept(int result, - const base::Optional<net::IPEndPoint>& remote_addr, - network::mojom::TCPConnectedSocketPtr connected_socket, - mojo::ScopedDataPipeConsumerHandle receive_stream, - mojo::ScopedDataPipeProducerHandle send_stream) { - DCHECK(accept_callback_); - std::move(accept_callback_) - .Run(result, std::move(connected_socket), remote_addr, - std::move(receive_stream), std::move(send_stream)); -} - -void TCPSocket::OnWriteComplete(const net::CompletionCallback& callback, - int result) { - if (result < 0) { - // Write side has terminated. This can be an error or a graceful close. - // TCPSocketEventDispatcher doesn't distinguish between the two. - Disconnect(false /* socket_destroying */); - } - callback.Run(result); -} - -void TCPSocket::OnReadComplete(int result, - scoped_refptr<net::IOBuffer> io_buffer) { - DCHECK(read_callback_); - - // Use a local variable for |read_callback_|, because otherwise Disconnect() - // will try to invoke |read_callback_| with a hardcoded result code. - ReadCompletionCallback callback = std::move(read_callback_); - if (result < 0) { - // Read side has terminated. This can be an error or a graceful close. - // TCPSocketEventDispatcher doesn't distinguish between the two. - Disconnect(false /* socket_destroying */); - } - std::move(callback).Run(result, io_buffer, false /* socket_destroying */); -} - -void TCPSocket::OnUpgradeToTLSComplete( - UpgradeToTLSCallback callback, - network::mojom::TLSClientSocketPtr tls_socket, - const net::IPEndPoint& local_addr, - const net::IPEndPoint& peer_addr, - int result, - mojo::ScopedDataPipeConsumerHandle receive_stream, - mojo::ScopedDataPipeProducerHandle send_stream) { - std::move(callback).Run(result, std::move(tls_socket), local_addr, peer_addr, - std::move(receive_stream), std::move(send_stream)); -} - -void TCPSocket::UpgradeToTLS(api::socket::SecureOptions* options, - UpgradeToTLSCallback callback) { - if (!client_socket_ || !mojo_data_pump_ || - mojo_data_pump_->HasPendingRead() || mojo_data_pump_->HasPendingWrite()) { - std::move(callback).Run(net::ERR_FAILED, nullptr, net::IPEndPoint(), - net::IPEndPoint(), - mojo::ScopedDataPipeConsumerHandle(), - mojo::ScopedDataPipeProducerHandle()); - return; - } - if (!local_addr_ || !peer_addr_) { - DVLOG(1) << "Could not get local address or peer address."; - std::move(callback).Run(net::ERR_FAILED, nullptr, net::IPEndPoint(), - net::IPEndPoint(), - mojo::ScopedDataPipeConsumerHandle(), - mojo::ScopedDataPipeProducerHandle()); - return; - } - - // Convert any U-LABELs to A-LABELs. - url::CanonHostInfo host_info; - std::string canon_host = net::CanonicalizeHost(hostname(), &host_info); - - // Canonicalization shouldn't fail: the socket is already connected with a - // host, using this hostname. - if (host_info.family == url::CanonHostInfo::BROKEN) { - DVLOG(1) << "Could not canonicalize hostname"; - std::move(callback).Run(net::ERR_FAILED, nullptr, net::IPEndPoint(), - net::IPEndPoint(), - mojo::ScopedDataPipeConsumerHandle(), - mojo::ScopedDataPipeProducerHandle()); - return; - } - - mojo_data_pump_ = nullptr; - network::mojom::TLSClientSocketOptionsPtr mojo_socket_options = - network::mojom::TLSClientSocketOptions::New(); - if (options && options->tls_version.get()) { - network::mojom::SSLVersion version_min, version_max; - bool has_version_min = false; - bool has_version_max = false; - api::socket::TLSVersionConstraints* versions = options->tls_version.get(); - if (versions->min.get()) { - has_version_min = - SSLProtocolVersionFromString(*versions->min, &version_min); - } - if (versions->max.get()) { - has_version_max = - SSLProtocolVersionFromString(*versions->max, &version_max); - } - if (has_version_min) - mojo_socket_options->version_min = version_min; - if (has_version_max) - mojo_socket_options->version_max = version_max; - } - network::mojom::TLSClientSocketPtr tls_socket; - network::mojom::TLSClientSocketRequest tls_socket_request = - mojo::MakeRequest(&tls_socket); - net::HostPortPair host_port_pair(canon_host, peer_addr_.value().port()); - client_socket_->UpgradeToTLS( - host_port_pair, std::move(mojo_socket_options), - net::MutableNetworkTrafficAnnotationTag( - Socket::GetNetworkTrafficAnnotationTag()), - std::move(tls_socket_request), nullptr /* observer */, - base::BindOnce(&TCPSocket::OnUpgradeToTLSComplete, base::Unretained(this), - std::move(callback), std::move(tls_socket), - local_addr_.value(), peer_addr_.value())); -} - -ResumableTCPSocket::ResumableTCPSocket(content::BrowserContext* browser_context, - const std::string& owner_extension_id) - : TCPSocket(browser_context, owner_extension_id), +ResumableTCPSocket::ResumableTCPSocket(const std::string& owner_extension_id) + : TCPSocket(owner_extension_id), persistent_(false), buffer_size_(0), paused_(false) {} ResumableTCPSocket::ResumableTCPSocket( - network::mojom::TCPConnectedSocketPtr socket, - mojo::ScopedDataPipeConsumerHandle receive_stream, - mojo::ScopedDataPipeProducerHandle send_stream, - const base::Optional<net::IPEndPoint>& remote_addr, - const std::string& owner_extension_id) - : TCPSocket(std::move(socket), - std::move(receive_stream), - std::move(send_stream), - remote_addr, - owner_extension_id), + std::unique_ptr<net::TCPClientSocket> tcp_client_socket, + const std::string& owner_extension_id, + bool is_connected) + : TCPSocket(std::move(tcp_client_socket), owner_extension_id, is_connected), persistent_(false), buffer_size_(0), paused_(false) {} @@ -583,11 +377,8 @@ bool ResumableTCPSocket::IsPersistent() const { return persistent(); } ResumableTCPServerSocket::ResumableTCPServerSocket( - content::BrowserContext* browser_context, const std::string& owner_extension_id) - : TCPSocket(browser_context, owner_extension_id), - persistent_(false), - paused_(false) {} + : TCPSocket(owner_extension_id), persistent_(false), paused_(false) {} bool ResumableTCPServerSocket::IsPersistent() const { return persistent(); }
diff --git a/extensions/browser/api/socket/tcp_socket.h b/extensions/browser/api/socket/tcp_socket.h index f834301..bdff76ed 100644 --- a/extensions/browser/api/socket/tcp_socket.h +++ b/extensions/browser/api/socket/tcp_socket.h
@@ -7,88 +7,76 @@ #include <stdint.h> -#include <memory> #include <string> -#include "base/memory/weak_ptr.h" -#include "base/sequenced_task_runner.h" #include "extensions/browser/api/socket/socket.h" -#include "extensions/browser/api/socket/tcp_socket.h" -#include "extensions/common/api/socket.h" -#include "net/base/completion_once_callback.h" -#include "services/network/public/mojom/network_service.mojom.h" -#include "services/network/public/mojom/tcp_socket.mojom.h" -#include "services/network/public/mojom/tls_socket.mojom.h" -namespace content { -class BrowserContext; -class StoragePartition; +// This looks like it should be forward-declarable, but it does some tricky +// moves that make it easier to just include it. +#include "net/socket/tcp_client_socket.h" +#include "net/socket/tcp_server_socket.h" + +namespace net { +class Socket; } namespace extensions { -class MojoDataPump; - class TCPSocket : public Socket { public: - using UpgradeToTLSCallback = - base::OnceCallback<void(int, - network::mojom::TLSClientSocketPtr, - const net::IPEndPoint&, - const net::IPEndPoint&, - mojo::ScopedDataPipeConsumerHandle, - mojo::ScopedDataPipeProducerHandle)>; - - // Constuctor for when |socket_mode_| is unknown. The |socket_mode_| will be - // filled in when the consumer calls Listen/Connect. - TCPSocket(content::BrowserContext* browser_context, - const std::string& owner_extension_id); - - // Created using TCPServerSocket::Accept(). - TCPSocket(network::mojom::TCPConnectedSocketPtr socket, - mojo::ScopedDataPipeConsumerHandle receive_stream, - mojo::ScopedDataPipeProducerHandle send_stream, - const base::Optional<net::IPEndPoint>& remote_addr, - const std::string& owner_extension_id); + explicit TCPSocket(const std::string& owner_extension_id); + TCPSocket(std::unique_ptr<net::TCPClientSocket> tcp_client_socket, + const std::string& owner_extension_id, + bool is_connected = false); ~TCPSocket() override; void Connect(const net::AddressList& address, - net::CompletionOnceCallback callback) override; + const CompletionCallback& callback) override; void Disconnect(bool socket_destroying) override; void Bind(const std::string& address, uint16_t port, const CompletionCallback& callback) override; - void Read(int count, ReadCompletionCallback callback) override; + void Read(int count, const ReadCompletionCallback& callback) override; void RecvFrom(int count, const RecvFromCompletionCallback& callback) override; void SendTo(scoped_refptr<net::IOBuffer> io_buffer, int byte_count, const net::IPEndPoint& address, const CompletionCallback& callback) override; - void SetKeepAlive(bool enable, - int delay, - SetKeepAliveCallback callback) override; - void SetNoDelay(bool no_delay, SetNoDelayCallback callback) override; - void Listen(const std::string& address, - uint16_t port, - int backlog, - ListenCallback callback) override; - void Accept(AcceptCompletionCallback callback) override; + bool SetKeepAlive(bool enable, int delay) override; + bool SetNoDelay(bool no_delay) override; + int Listen(const std::string& address, + uint16_t port, + int backlog, + std::string* error_msg) override; + void Accept(const AcceptCompletionCallback& callback) override; bool IsConnected() override; bool GetPeerAddress(net::IPEndPoint* address) override; bool GetLocalAddress(net::IPEndPoint* address) override; + // Like Disconnect(), only Release() doesn't delete the underlying stream + // or attempt to close it. Useful when giving away ownership with + // ClientStream(). + virtual void Release(); + Socket::SocketType GetSocketType() const override; - void UpgradeToTLS(api::socket::SecureOptions* options, - UpgradeToTLSCallback callback); + static TCPSocket* CreateSocketForTesting( + std::unique_ptr<net::TCPClientSocket> tcp_client_socket, + const std::string& owner_extension_id, + bool is_connected = false); + static TCPSocket* CreateServerSocketForTesting( + std::unique_ptr<net::TCPServerSocket> tcp_server_socket, + const std::string& owner_extension_id); - void SetStoragePartitionForTest( - content::StoragePartition* storage_partition) { - storage_partition_ = storage_partition; - } + // Returns NULL if GetSocketType() isn't TYPE_TCP or if the connection + // wasn't set up via Connect() (vs Listen()/Accept()). + net::TCPClientSocket* ClientStream(); + + // Whether a Read() has been issued, that hasn't come back yet. + bool HasPendingRead() const; protected: int WriteImpl(net::IOBuffer* io_buffer, @@ -96,101 +84,26 @@ const net::CompletionCallback& callback) override; private: - // Connects a client TCP socket. This is done on the UI thread because - // StoragePartition::GetNetworkContext() needs to happen on the UI thread. - // The completion callback is posted back to the thread on which |this| lives. - static void ConnectOnUIThread( - content::StoragePartition* storage_partition, - content::BrowserContext* browser_context, - const net::AddressList& remote_address_list, - network::mojom::TCPConnectedSocketRequest request, - network::mojom::NetworkContext::CreateTCPConnectedSocketCallback - callback); - static void OnConnectCompleteOnUIThread( - scoped_refptr<base::SequencedTaskRunner> original_task_runner, - network::mojom::NetworkContext::CreateTCPConnectedSocketCallback callback, - int result, - const base::Optional<net::IPEndPoint>& local_addr, - const base::Optional<net::IPEndPoint>& peer_addr, - mojo::ScopedDataPipeConsumerHandle receive_stream, - mojo::ScopedDataPipeProducerHandle send_stream); - void OnConnectComplete(int result, - const base::Optional<net::IPEndPoint>& local_addr, - const base::Optional<net::IPEndPoint>& peer_addr, - mojo::ScopedDataPipeConsumerHandle receive_stream, - mojo::ScopedDataPipeProducerHandle send_stream); + void RefreshConnectionStatus(); + void OnConnectComplete(int result); + void OnReadComplete(scoped_refptr<net::IOBuffer> io_buffer, int result); + void OnAccept(int result); - // Connects a server TCP socket. This is done on the UI thread because - // StoragePartition::GetNetworkContext() needs to happen on the UI thread. - // The completion callback is posted back to the thread on which |this| lives. - static void ListenOnUIThread( - content::StoragePartition* storage_partition, - content::BrowserContext* browser_context, - const net::IPEndPoint& local_addr, - int backlog, - network::mojom::TCPServerSocketRequest request, - network::mojom::NetworkContext::CreateTCPServerSocketCallback callback); - static void OnListenCompleteOnUIThread( - const scoped_refptr<base::SequencedTaskRunner>& original_task_runner, - network::mojom::NetworkContext::CreateTCPServerSocketCallback callback, - int result, - const base::Optional<net::IPEndPoint>& local_addr); - void OnListenComplete(int result, - const base::Optional<net::IPEndPoint>& local_addr); - void OnAccept(int result, - const base::Optional<net::IPEndPoint>& remote_addr, - network::mojom::TCPConnectedSocketPtr connected_socket, - mojo::ScopedDataPipeConsumerHandle receive_stream, - mojo::ScopedDataPipeProducerHandle send_stream); - void OnWriteComplete(const net::CompletionCallback& callback, int result); - void OnReadComplete(int result, scoped_refptr<net::IOBuffer> io_buffer); - void OnUpgradeToTLSComplete(UpgradeToTLSCallback callback, - network::mojom::TLSClientSocketPtr tls_socket, - const net::IPEndPoint& local_addr, - const net::IPEndPoint& peer_addr, - int result, - mojo::ScopedDataPipeConsumerHandle receive_stream, - mojo::ScopedDataPipeProducerHandle send_stream); + TCPSocket(std::unique_ptr<net::TCPServerSocket> tcp_server_socket, + const std::string& owner_extension_id); - content::StoragePartition* GetStoragePartitionHelper(); + std::unique_ptr<net::TCPClientSocket> socket_; + std::unique_ptr<net::TCPServerSocket> server_socket_; - enum SocketMode { - UNKNOWN = 0, - CLIENT, - SERVER, - }; - - // |this| doesn't outlive |browser_context_| because |this| is owned by - // ApiResourceManager which is a BrowserContextKeyedAPI. - content::BrowserContext* browser_context_; - + enum SocketMode { UNKNOWN = 0, CLIENT, SERVER, }; SocketMode socket_mode_; - // CLIENT mode. - network::mojom::TCPConnectedSocketPtr client_socket_; - // SERVER mode. - network::mojom::TCPServerSocketPtr server_socket_; + CompletionCallback connect_callback_; - net::CompletionOnceCallback connect_callback_; - ListenCallback listen_callback_; - AcceptCompletionCallback accept_callback_; ReadCompletionCallback read_callback_; - std::unique_ptr<MojoDataPump> mojo_data_pump_; - - scoped_refptr<base::SequencedTaskRunner> task_runner_; - - base::Optional<net::IPEndPoint> local_addr_; - base::Optional<net::IPEndPoint> peer_addr_; - - // Only used in tests. - content::StoragePartition* storage_partition_ = nullptr; - - // WeakPtr is used when posting tasks to |task_runner_| which might outlive - // |this|. - base::WeakPtrFactory<TCPSocket> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(TCPSocket); + std::unique_ptr<net::StreamSocket> accept_socket_; + AcceptCompletionCallback accept_callback_; }; // TCP Socket instances from the "sockets.tcp" namespace. These are regular @@ -198,14 +111,11 @@ // the "sockets.tcp" namespace. class ResumableTCPSocket : public TCPSocket { public: - ResumableTCPSocket(content::BrowserContext* browser_context, - const std::string& owner_extension_id); - // Created using TCPServerSocket::Accept(). - ResumableTCPSocket(network::mojom::TCPConnectedSocketPtr socket, - mojo::ScopedDataPipeConsumerHandle receive_stream, - mojo::ScopedDataPipeProducerHandle send_stream, - const base::Optional<net::IPEndPoint>& remote_addr, - const std::string& owner_extension_id); + explicit ResumableTCPSocket(const std::string& owner_extension_id); + explicit ResumableTCPSocket( + std::unique_ptr<net::TCPClientSocket> tcp_client_socket, + const std::string& owner_extension_id, + bool is_connected); ~ResumableTCPSocket() override; @@ -245,8 +155,7 @@ // defined in the "sockets.tcpServer" namespace. class ResumableTCPServerSocket : public TCPSocket { public: - ResumableTCPServerSocket(content::BrowserContext* browser_context, - const std::string& owner_extension_id); + explicit ResumableTCPServerSocket(const std::string& owner_extension_id); // Overriden from ApiResource bool IsPersistent() const override;
diff --git a/extensions/browser/api/socket/tls_socket.cc b/extensions/browser/api/socket/tls_socket.cc index 0c39bf0c..aa2a4a0 100644 --- a/extensions/browser/api/socket/tls_socket.cc +++ b/extensions/browser/api/socket/tls_socket.cc
@@ -10,142 +10,307 @@ #include "base/logging.h" #include "content/public/browser/browser_thread.h" #include "extensions/browser/api/api_resource.h" -#include "extensions/browser/api/socket/mojo_data_pump.h" #include "net/base/address_list.h" #include "net/base/ip_endpoint.h" #include "net/base/net_errors.h" +#include "net/base/rand_callback.h" #include "net/base/url_util.h" +#include "net/socket/client_socket_factory.h" +#include "net/socket/client_socket_handle.h" +#include "net/socket/ssl_client_socket.h" +#include "net/socket/tcp_client_socket.h" #include "url/url_canon.h" +namespace { + +// Returns the SSL protocol version (as a uint16_t) represented by a string. +// Returns 0 if the string is invalid. +uint16_t SSLProtocolVersionFromString(const std::string& version_str) { + uint16_t version = 0; // Invalid. + if (version_str == "tls1") { + version = net::SSL_PROTOCOL_VERSION_TLS1; + } else if (version_str == "tls1.1") { + version = net::SSL_PROTOCOL_VERSION_TLS1_1; + } else if (version_str == "tls1.2") { + version = net::SSL_PROTOCOL_VERSION_TLS1_2; + } + return version; +} + +void TlsConnectDone(std::unique_ptr<net::SSLClientSocket> ssl_socket, + const std::string& extension_id, + const extensions::TLSSocket::SecureCallback& callback, + int result) { + DVLOG(1) << "Got back result " << result << " " << net::ErrorToString(result); + + // No matter how the TLS connection attempt went, the underlying socket's + // no longer bound to the original TCPSocket. It belongs to |ssl_socket|, + // which is promoted here to a new API-accessible socket (via a TLSSocket + // wrapper), or deleted. + if (result != net::OK) { + callback.Run(nullptr, result); + return; + }; + + // Wrap the StreamSocket in a TLSSocket, which matches the extension socket + // API. Set the handle of the socket to the new value, so that it can be + // used for read/write/close/etc. + std::unique_ptr<extensions::TLSSocket> wrapper( + new extensions::TLSSocket(std::move(ssl_socket), extension_id)); + + // Caller will end up deleting the prior TCPSocket, once it calls + // SetSocket(..,wrapper). + callback.Run(std::move(wrapper), result); +} + +} // namespace + namespace extensions { const char kTLSSocketTypeInvalidError[] = "Cannot listen on a socket that is already connected."; -TLSSocket::TLSSocket(network::mojom::TLSClientSocketPtr tls_socket, - const net::IPEndPoint& local_addr, - const net::IPEndPoint& peer_addr, - mojo::ScopedDataPipeConsumerHandle receive_stream, - mojo::ScopedDataPipeProducerHandle send_stream, +TLSSocket::TLSSocket(std::unique_ptr<net::StreamSocket> tls_socket, const std::string& owner_extension_id) - : ResumableTCPSocket(nullptr, owner_extension_id), - tls_socket_(std::move(tls_socket)), - local_addr_(local_addr), - peer_addr_(peer_addr), - mojo_data_pump_(std::make_unique<MojoDataPump>(std::move(receive_stream), - std::move(send_stream))) { - DCHECK(tls_socket_); - is_connected_ = true; -} + : ResumableTCPSocket(owner_extension_id), + tls_socket_(std::move(tls_socket)) {} TLSSocket::~TLSSocket() { Disconnect(true /* socket_destroying */); } void TLSSocket::Connect(const net::AddressList& address, - net::CompletionOnceCallback callback) { - std::move(callback).Run(net::ERR_CONNECTION_FAILED); + const CompletionCallback& callback) { + callback.Run(net::ERR_CONNECTION_FAILED); } void TLSSocket::Disconnect(bool socket_destroying) { - is_connected_ = false; - tls_socket_.reset(); - local_addr_ = base::nullopt; - peer_addr_ = base::nullopt; - mojo_data_pump_ = nullptr; - // TODO(devlin): Should we do this for all callbacks? - if (read_callback_) { - std::move(read_callback_) - .Run(net::ERR_CONNECTION_CLOSED, nullptr, socket_destroying); + if (tls_socket_) { + tls_socket_->Disconnect(); + tls_socket_.reset(); } } -void TLSSocket::Read(int count, ReadCompletionCallback callback) { - DCHECK(callback); - DCHECK(!read_callback_); +void TLSSocket::Read(int count, const ReadCompletionCallback& callback) { + DCHECK(!callback.is_null()); const bool socket_destroying = false; - if (!mojo_data_pump_) { - std::move(callback).Run(net::ERR_SOCKET_NOT_CONNECTED, nullptr, - socket_destroying); + if (!read_callback_.is_null()) { + callback.Run(net::ERR_IO_PENDING, nullptr, socket_destroying); return; } - if (mojo_data_pump_->HasPendingRead()) { - std::move(callback).Run(net::ERR_IO_PENDING, nullptr, socket_destroying); + + if (count <= 0) { + callback.Run(net::ERR_INVALID_ARGUMENT, nullptr, socket_destroying); return; } - read_callback_ = std::move(callback); - mojo_data_pump_->Read(count, base::BindOnce(&TLSSocket::OnReadComplete, - base::Unretained(this))); + + if (!tls_socket_.get()) { + callback.Run(net::ERR_SOCKET_NOT_CONNECTED, nullptr, socket_destroying); + return; + } + + read_callback_ = callback; + scoped_refptr<net::IOBuffer> io_buffer(new net::IOBuffer(count)); + // |tls_socket_| is owned by this class and the callback won't be run once + // |tls_socket_| is gone (as in an a call to Disconnect()). Therefore, it is + // safe to use base::Unretained() here. + int result = tls_socket_->Read( + io_buffer.get(), + count, + base::Bind( + &TLSSocket::OnReadComplete, base::Unretained(this), io_buffer)); + + if (result != net::ERR_IO_PENDING) { + OnReadComplete(io_buffer, result); + } } -void TLSSocket::Listen(const std::string& address, - uint16_t port, - int backlog, - ListenCallback callback) { - std::move(callback).Run(net::ERR_NOT_IMPLEMENTED, kTLSSocketTypeInvalidError); +void TLSSocket::OnReadComplete(const scoped_refptr<net::IOBuffer>& io_buffer, + int result) { + DCHECK(!read_callback_.is_null()); + base::ResetAndReturn(&read_callback_) + .Run(result, io_buffer, false /* socket_destroying */); +} + +int TLSSocket::WriteImpl(net::IOBuffer* io_buffer, + int io_buffer_size, + const net::CompletionCallback& callback) { + if (!IsConnected()) { + return net::ERR_SOCKET_NOT_CONNECTED; + } + return tls_socket_->Write(io_buffer, io_buffer_size, callback, + Socket::GetNetworkTrafficAnnotationTag()); +} + +bool TLSSocket::SetKeepAlive(bool enable, int delay) { + return false; +} + +bool TLSSocket::SetNoDelay(bool no_delay) { + return false; +} + +int TLSSocket::Listen(const std::string& address, + uint16_t port, + int backlog, + std::string* error_msg) { + *error_msg = kTLSSocketTypeInvalidError; + return net::ERR_NOT_IMPLEMENTED; +} + +void TLSSocket::Accept(const AcceptCompletionCallback& callback) { + callback.Run(net::ERR_FAILED, NULL); } bool TLSSocket::IsConnected() { - return is_connected_; + return tls_socket_.get() && tls_socket_->IsConnected(); } bool TLSSocket::GetPeerAddress(net::IPEndPoint* address) { - if (!IsConnected()) - return false; - if (!peer_addr_) - return false; - *address = peer_addr_.value(); - return true; + return IsConnected() && tls_socket_->GetPeerAddress(address); } bool TLSSocket::GetLocalAddress(net::IPEndPoint* address) { - if (!IsConnected()) - return false; - if (!local_addr_) - return false; - *address = local_addr_.value(); - return true; + return IsConnected() && tls_socket_->GetLocalAddress(address); } Socket::SocketType TLSSocket::GetSocketType() const { return Socket::TYPE_TLS; } -int TLSSocket::WriteImpl(net::IOBuffer* io_buffer, - int io_buffer_size, - const net::CompletionCallback& callback) { - if (!mojo_data_pump_) - return net::ERR_SOCKET_NOT_CONNECTED; - mojo_data_pump_->Write(io_buffer, io_buffer_size, - base::BindOnce(&TLSSocket::OnWriteComplete, - base::Unretained(this), callback)); - return net::ERR_IO_PENDING; -} +// static +void TLSSocket::UpgradeSocketToTLS( + Socket* socket, + net::SSLConfigService* ssl_config_service, + net::CertVerifier* cert_verifier, + net::TransportSecurityState* transport_security_state, + net::CTVerifier* ct_verifier, + net::CTPolicyEnforcer* ct_policy_enforcer, + const std::string& extension_id, + api::socket::SecureOptions* options, + const TLSSocket::SecureCallback& callback) { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + TCPSocket* tcp_socket = static_cast<TCPSocket*>(socket); + std::unique_ptr<net::SSLClientSocket> null_sock; -void TLSSocket::OnWriteComplete(const net::CompletionCallback& callback, - int result) { - if (result < 0) { - // Write side has terminated. This can be an error or a graceful close. - // TCPSocketEventDispatcher doesn't distinguish between the two. - Disconnect(false /* socket_destroying */); + if (!tcp_socket || tcp_socket->GetSocketType() != Socket::TYPE_TCP || + !tcp_socket->ClientStream() || !tcp_socket->IsConnected() || + tcp_socket->HasPendingRead()) { + DVLOG(1) << "Failing before trying. socket is " << tcp_socket; + if (tcp_socket) { + DVLOG(1) << "type: " << tcp_socket->GetSocketType() + << ", ClientStream is " << tcp_socket->ClientStream() + << ", IsConnected: " << tcp_socket->IsConnected() + << ", HasPendingRead: " << tcp_socket->HasPendingRead(); + } + TlsConnectDone(std::move(null_sock), extension_id, callback, + net::ERR_INVALID_ARGUMENT); + return; } - callback.Run(result); -} -void TLSSocket::OnReadComplete(int result, - scoped_refptr<net::IOBuffer> io_buffer) { - DCHECK(read_callback_); - - // Use a local variable for |read_callback_|, because otherwise Disconnect() - // will try to invoke |read_callback_| with a hardcoded result code. - ReadCompletionCallback callback = std::move(read_callback_); - if (result < 0) { - // Read side has terminated. This can be an error or a graceful close. - // TCPSocketEventDispatcher doesn't distinguish between the two. - Disconnect(false /* socket_destroying */); + net::IPEndPoint dest_host_port_pair; + if (!tcp_socket->GetPeerAddress(&dest_host_port_pair)) { + DVLOG(1) << "Could not get peer address."; + TlsConnectDone(std::move(null_sock), extension_id, callback, + net::ERR_INVALID_ARGUMENT); + return; } - std::move(callback).Run(result, io_buffer, false /* socket_destroying */); + + // Convert any U-LABELs to A-LABELs. + url::CanonHostInfo host_info; + std::string canon_host = + net::CanonicalizeHost(tcp_socket->hostname(), &host_info); + + // Canonicalization shouldn't fail: the socket is already connected with a + // host, using this hostname. + if (host_info.family == url::CanonHostInfo::BROKEN) { + DVLOG(1) << "Could not canonicalize hostname"; + TlsConnectDone(std::move(null_sock), extension_id, callback, + net::ERR_INVALID_ARGUMENT); + return; + } + + net::HostPortPair host_and_port(canon_host, dest_host_port_pair.port()); + + std::unique_ptr<net::ClientSocketHandle> socket_handle( + new net::ClientSocketHandle()); + + // Set the socket handle to the socket's client stream (that should be the + // only one active here). Then have the old socket release ownership on + // that client stream. + socket_handle->SetSocket( + base::WrapUnique<net::StreamSocket>(tcp_socket->ClientStream())); + tcp_socket->Release(); + + DCHECK(transport_security_state); + net::SSLClientSocketContext context; + context.cert_verifier = cert_verifier; + context.transport_security_state = transport_security_state; + context.cert_transparency_verifier = ct_verifier; + context.ct_policy_enforcer = ct_policy_enforcer; + + // Fill in the SSL socket params. + net::SSLConfig ssl_config; + ssl_config_service->GetSSLConfig(&ssl_config); + if (options && options->tls_version.get()) { + uint16_t version_min = 0, version_max = 0; + api::socket::TLSVersionConstraints* versions = options->tls_version.get(); + if (versions->min.get()) { + version_min = SSLProtocolVersionFromString(*versions->min); + } + if (versions->max.get()) { + version_max = SSLProtocolVersionFromString(*versions->max); + } + if (version_min) { + ssl_config.version_min = version_min; + } + if (version_max) { + ssl_config.version_max = version_max; + } + } + + net::ClientSocketFactory* socket_factory = + net::ClientSocketFactory::GetDefaultFactory(); + + // Create the socket. + std::unique_ptr<net::SSLClientSocket> ssl_socket( + socket_factory->CreateSSLClientSocket( + std::move(socket_handle), host_and_port, ssl_config, context)); + + DVLOG(1) << "Attempting to secure a connection to " << tcp_socket->hostname() + << ":" << dest_host_port_pair.port(); + + // We need the contents of |ssl_socket| in order to invoke its Connect() + // method. It belongs to |ssl_socket|, and we own that until our internal + // callback (|connect_cb|, below) is invoked. + net::SSLClientSocket* saved_ssl_socket = ssl_socket.get(); + + // Try establish a TLS connection. Pass ownership of |ssl_socket| to + // TlsConnectDone, which will pass it on to |callback|. |connect_cb| below + // is only for UpgradeSocketToTLS use, and not be confused with the + // argument |callback|, which gets invoked by TlsConnectDone() after + // Connect() below returns. + base::Callback<void(int)> connect_cb(base::Bind( + &TlsConnectDone, base::Passed(&ssl_socket), extension_id, callback)); + int status = saved_ssl_socket->Connect(connect_cb); + saved_ssl_socket = NULL; + + // Connect completed synchronously, or failed. + if (status != net::ERR_IO_PENDING) { + // Note: this can't recurse -- if |socket| is already a connected + // TLSSocket, it will return TYPE_TLS instead of TYPE_TCP, causing + // UpgradeSocketToTLS() to fail with an error above. If + // UpgradeSocketToTLS() is called on |socket| twice, the call to + // Release() on |socket| above causes the additional call to + // fail with an error above. + if (status != net::OK) { + DVLOG(1) << "Status is not OK or IO-pending: " + << net::ErrorToString(status); + } + connect_cb.Run(status); + } } } // namespace extensions +
diff --git a/extensions/browser/api/socket/tls_socket.h b/extensions/browser/api/socket/tls_socket.h index 99846ea..c3208e2 100644 --- a/extensions/browser/api/socket/tls_socket.h +++ b/extensions/browser/api/socket/tls_socket.h
@@ -7,19 +7,24 @@ #include <stdint.h> -#include <memory> #include <string> -#include "extensions/browser/api/socket/mojo_data_pump.h" #include "extensions/browser/api/socket/socket.h" #include "extensions/browser/api/socket/socket_api.h" #include "extensions/browser/api/socket/tcp_socket.h" -#include "mojo/public/cpp/system/data_pipe.h" -#include "services/network/public/mojom/tls_socket.mojom.h" +#include "net/ssl/ssl_config_service.h" + +namespace net { +class Socket; +class CertVerifier; +class CTPolicyEnforcer; +class CTVerifier; +class TransportSecurityState; +} namespace extensions { -class MojoDataPump; +class TLSSocket; // TLS Sockets from the chrome.socket and chrome.sockets.tcp APIs. A regular // TCPSocket is converted to a TLSSocket via chrome.socket.secure() or @@ -33,55 +38,84 @@ // touch any socket state. class TLSSocket : public ResumableTCPSocket { public: - TLSSocket(network::mojom::TLSClientSocketPtr tls_socket, - const net::IPEndPoint& local_addr, - const net::IPEndPoint& peer_addr, - mojo::ScopedDataPipeConsumerHandle receive_stream, - mojo::ScopedDataPipeProducerHandle send_stream, + typedef base::Callback<void(std::unique_ptr<TLSSocket>, int)> SecureCallback; + + TLSSocket(std::unique_ptr<net::StreamSocket> tls_socket, const std::string& owner_extension_id); ~TLSSocket() override; + // Most of these methods either fail or forward the method call on to the + // inner net::StreamSocket. The remaining few do actual TLS work. + // Fails. void Connect(const net::AddressList& address, - net::CompletionOnceCallback callback) override; + const CompletionCallback& callback) override; // Forwards. void Disconnect(bool socket_destroying) override; // Attempts to read |count| bytes of decrypted data from the TLS socket, // invoking |callback| with the actual number of bytes read, or a network // error code if an error occurred. - void Read(int count, ReadCompletionCallback callback) override; + void Read(int count, const ReadCompletionCallback& callback) override; + + // Fails. This should have been called on the TCP socket before secure() was + // invoked. + bool SetKeepAlive(bool enable, int delay) override; + + // Fails. This should have been called on the TCP socket before secure() was + // invoked. + bool SetNoDelay(bool no_delay) override; // Fails. TLSSocket is only a client. - void Listen(const std::string& address, - uint16_t port, - int backlog, - ListenCallback callback) override; + int Listen(const std::string& address, + uint16_t port, + int backlog, + std::string* error_msg) override; + + // Fails. TLSSocket is only a client. + void Accept(const AcceptCompletionCallback& callback) override; // Forwards. bool IsConnected() override; + // Forwards. bool GetPeerAddress(net::IPEndPoint* address) override; + // Forwards. bool GetLocalAddress(net::IPEndPoint* address) override; // Returns TYPE_TLS. SocketType GetSocketType() const override; + // Convert |socket| to a TLS socket. |socket| must be an open TCP client + // socket. |socket| must not have a pending read. UpgradeSocketToTLS() must + // be invoked in the IO thread. |callback| will always be invoked. |options| + // may be NULL. + // Note: |callback| may be synchronously invoked before + // UpgradeSocketToTLS() returns. Currently using the older chrome.socket + // version of SecureOptions, to avoid having the older API implementation + // depend on the newer one. + static void UpgradeSocketToTLS( + Socket* socket, + net::SSLConfigService* config_service, + net::CertVerifier* cert_verifier, + net::TransportSecurityState* transport_security_state, + net::CTVerifier* ct_verifier, + net::CTPolicyEnforcer* ct_policy_enforcer, + const std::string& extension_id, + api::socket::SecureOptions* options, + const SecureCallback& callback); + private: int WriteImpl(net::IOBuffer* io_buffer, int io_buffer_size, const net::CompletionCallback& callback) override; - void OnWriteComplete(const net::CompletionCallback& callback, int result); - void OnReadComplete(int result, scoped_refptr<net::IOBuffer> io_buffer); - network::mojom::TLSClientSocketPtr tls_socket_; - base::Optional<net::IPEndPoint> local_addr_; - base::Optional<net::IPEndPoint> peer_addr_; - std::unique_ptr<MojoDataPump> mojo_data_pump_; + void OnReadComplete(const scoped_refptr<net::IOBuffer>& io_buffer, + int result); + + std::unique_ptr<net::StreamSocket> tls_socket_; ReadCompletionCallback read_callback_; - - DISALLOW_COPY_AND_ASSIGN(TLSSocket); }; } // namespace extensions
diff --git a/extensions/browser/api/socket/udp_socket.cc b/extensions/browser/api/socket/udp_socket.cc index f9b8aa9..094508e3 100644 --- a/extensions/browser/api/socket/udp_socket.cc +++ b/extensions/browser/api/socket/udp_socket.cc
@@ -5,7 +5,6 @@ #include "extensions/browser/api/socket/udp_socket.h" #include <algorithm> -#include <utility> #include "base/callback_helpers.h" #include "base/lazy_instance.h" @@ -47,9 +46,9 @@ } void UDPSocket::Connect(const net::AddressList& address, - net::CompletionOnceCallback callback) { + const net::CompletionCallback& callback) { if (IsConnectedOrBound()) { - std::move(callback).Run(net::ERR_CONNECTION_FAILED); + callback.Run(net::ERR_CONNECTION_FAILED); return; } // UDP API only connects to the first address received from DNS so @@ -58,7 +57,7 @@ socket_->Connect( ip_end_point, std::move(socket_options_), base::BindOnce(&UDPSocket::OnConnectCompleted, base::Unretained(this), - std::move(callback), ip_end_point)); + callback, ip_end_point)); } void UDPSocket::Bind(const std::string& address, @@ -95,28 +94,27 @@ multicast_groups_.clear(); } -void UDPSocket::Read(int count, ReadCompletionCallback callback) { +void UDPSocket::Read(int count, const ReadCompletionCallback& callback) { DCHECK(!callback.is_null()); if (!read_callback_.is_null()) { - std::move(callback).Run(net::ERR_IO_PENDING, nullptr, - false /* socket_destroying */); + callback.Run(net::ERR_IO_PENDING, nullptr, false /* socket_destroying */); return; } if (count < 0) { - std::move(callback).Run(net::ERR_INVALID_ARGUMENT, nullptr, - false /* socket_destroying */); + callback.Run(net::ERR_INVALID_ARGUMENT, nullptr, + false /* socket_destroying */); return; } if (!IsConnected()) { - std::move(callback).Run(net::ERR_SOCKET_NOT_CONNECTED, nullptr, - false /* socket_destroying */); + callback.Run(net::ERR_SOCKET_NOT_CONNECTED, nullptr, + false /* socket_destroying */); return; } - read_callback_ = std::move(callback); + read_callback_ = callback; socket_->ReceiveMoreWithBufferSize(1, count); return; } @@ -222,7 +220,7 @@ uint16_t port = 0; if (result != net::OK) { if (!read_callback_.is_null()) { - std::move(read_callback_) + base::ResetAndReturn(&read_callback_) .Run(result, nullptr, false /* socket_destroying */); return; } @@ -236,7 +234,7 @@ memcpy(io_buffer->data(), data.value().data(), data.value().size()); if (!read_callback_.is_null()) { - std::move(read_callback_) + base::ResetAndReturn(&read_callback_) .Run(data.value().size(), io_buffer, false /* socket_destroying */); return; } @@ -248,18 +246,18 @@ } void UDPSocket::OnConnectCompleted( - net::CompletionOnceCallback callback, + const net::CompletionCallback& callback, const net::IPEndPoint& remote_addr, int result, const base::Optional<net::IPEndPoint>& local_addr) { if (result != net::OK) { - std::move(callback).Run(result); + callback.Run(result); return; } local_addr_ = local_addr; peer_addr_ = remote_addr; is_connected_ = true; - std::move(callback).Run(result); + callback.Run(result); } void UDPSocket::OnBindCompleted(
diff --git a/extensions/browser/api/socket/udp_socket.h b/extensions/browser/api/socket/udp_socket.h index 9c4fdfc..6f46aaa 100644 --- a/extensions/browser/api/socket/udp_socket.h +++ b/extensions/browser/api/socket/udp_socket.h
@@ -28,12 +28,12 @@ // Socket implementation. void Connect(const net::AddressList& address, - net::CompletionOnceCallback callback) override; + const CompletionCallback& callback) override; void Disconnect(bool socket_destroying) override; void Bind(const std::string& address, uint16_t port, const CompletionCallback& callback) override; - void Read(int count, ReadCompletionCallback callback) override; + void Read(int count, const ReadCompletionCallback& callback) override; void RecvFrom(int count, const RecvFromCompletionCallback& callback) override; void SendTo(scoped_refptr<net::IOBuffer> io_buffer, int byte_count, @@ -76,7 +76,7 @@ const base::Optional<net::IPEndPoint>& src_addr, base::Optional<base::span<const uint8_t>> data) override; - void OnConnectCompleted(net::CompletionOnceCallback user_callback, + void OnConnectCompleted(const net::CompletionCallback& user_callback, const net::IPEndPoint& remote_addr, int result, const base::Optional<net::IPEndPoint>& local_addr);
diff --git a/extensions/browser/api/sockets_tcp/sockets_tcp_api.cc b/extensions/browser/api/sockets_tcp/sockets_tcp_api.cc index d31f24f..dbc43166 100644 --- a/extensions/browser/api/sockets_tcp/sockets_tcp_api.cc +++ b/extensions/browser/api/sockets_tcp/sockets_tcp_api.cc
@@ -4,10 +4,6 @@ #include "extensions/browser/api/sockets_tcp/sockets_tcp_api.h" -#include <string> -#include <utility> -#include <vector> - #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/storage_partition.h" @@ -128,8 +124,7 @@ } void SocketsTcpCreateFunction::Work() { - ResumableTCPSocket* socket = - new ResumableTCPSocket(browser_context(), extension_->id()); + ResumableTCPSocket* socket = new ResumableTCPSocket(extension_->id()); sockets_tcp::SocketProperties* properties = params_->properties.get(); if (properties) { @@ -208,28 +203,20 @@ return true; } -void SocketsTcpSetKeepAliveFunction::AsyncWorkStart() { +void SocketsTcpSetKeepAliveFunction::Work() { ResumableTCPSocket* socket = GetTcpSocket(params_->socket_id); if (!socket) { error_ = kSocketNotFoundError; - results_ = sockets_tcp::SetKeepAlive::Results::Create(net::ERR_FAILED); - AsyncWorkCompleted(); return; } int delay = params_->delay ? *params_->delay : 0; - socket->SetKeepAlive( - params_->enable, delay, - base::BindOnce(&SocketsTcpSetKeepAliveFunction::OnCompleted, this)); -} - -void SocketsTcpSetKeepAliveFunction::OnCompleted(bool success) { + bool success = socket->SetKeepAlive(params_->enable, delay); int net_result = (success ? net::OK : net::ERR_FAILED); - results_ = sockets_tcp::SetKeepAlive::Results::Create(net_result); if (net_result != net::OK) error_ = net::ErrorToString(net_result); - AsyncWorkCompleted(); + results_ = sockets_tcp::SetKeepAlive::Results::Create(net_result); } SocketsTcpSetNoDelayFunction::SocketsTcpSetNoDelayFunction() {} @@ -242,25 +229,18 @@ return true; } -void SocketsTcpSetNoDelayFunction::AsyncWorkStart() { +void SocketsTcpSetNoDelayFunction::Work() { ResumableTCPSocket* socket = GetTcpSocket(params_->socket_id); if (!socket) { error_ = kSocketNotFoundError; - results_ = sockets_tcp::SetNoDelay::Results::Create(net::ERR_FAILED); - AsyncWorkCompleted(); return; } - socket->SetNoDelay( - params_->no_delay, - base::BindOnce(&SocketsTcpSetNoDelayFunction::OnCompleted, this)); -} -void SocketsTcpSetNoDelayFunction::OnCompleted(bool success) { + bool success = socket->SetNoDelay(params_->no_delay); int net_result = (success ? net::OK : net::ERR_FAILED); - results_ = sockets_tcp::SetNoDelay::Results::Create(net_result); if (net_result != net::OK) error_ = net::ErrorToString(net_result); - AsyncWorkCompleted(); + results_ = sockets_tcp::SetNoDelay::Results::Create(net_result); } SocketsTcpConnectFunction::SocketsTcpConnectFunction() @@ -364,7 +344,8 @@ params_ = sockets_tcp::Send::Params::Create(*args_); EXTENSION_FUNCTION_VALIDATE(params_.get()); io_buffer_size_ = params_->data.size(); - io_buffer_ = new net::WrappedIOBuffer(params_->data.data()); + io_buffer_ = new net::WrappedIOBuffer( + reinterpret_cast<const char*>(params_->data.data())); return true; } @@ -477,6 +458,8 @@ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); params_ = api::sockets_tcp::Secure::Params::Create(*args_); EXTENSION_FUNCTION_VALIDATE(params_.get()); + url_request_getter_ = content::BrowserContext::GetDefaultStoragePartition( + browser_context())->GetURLRequestContext(); return true; } @@ -498,7 +481,8 @@ // Make sure it's a connected TCP client socket. Error out if it's already // secure()'d. - if (socket->GetSocketType() != Socket::TYPE_TCP) { + if (socket->GetSocketType() != Socket::TYPE_TCP || + socket->ClientStream() == NULL) { SetResult(std::make_unique<base::Value>(net::ERR_INVALID_ARGUMENT)); error_ = kInvalidSocketStateError; AsyncWorkCompleted(); @@ -512,6 +496,9 @@ return; } + net::URLRequestContext* url_request_context = + url_request_getter_->GetURLRequestContext(); + // UpgradeSocketToTLS() uses the older API's SecureOptions. Copy over the // only values inside -- TLSVersionConstraints's |min| and |max|, api::socket::SecureOptions legacy_params; @@ -527,33 +514,29 @@ } } - network::mojom::TLSClientSocketPtr tls_socket; - socket->UpgradeToTLS( - &legacy_params, - base::BindOnce(&SocketsTcpSecureFunction::TlsConnectDone, this)); + TLSSocket::UpgradeSocketToTLS( + socket, url_request_context->ssl_config_service(), + url_request_context->cert_verifier(), + url_request_context->transport_security_state(), + url_request_context->cert_transparency_verifier(), + url_request_context->ct_policy_enforcer(), extension_id(), &legacy_params, + base::Bind(&SocketsTcpSecureFunction::TlsConnectDone, this)); } -void SocketsTcpSecureFunction::TlsConnectDone( - int result, - network::mojom::TLSClientSocketPtr tls_socket, - const net::IPEndPoint& local_addr, - const net::IPEndPoint& peer_addr, - mojo::ScopedDataPipeConsumerHandle receive_pipe_handle, - mojo::ScopedDataPipeProducerHandle send_pipe_handle) { - if (result != net::OK) { +void SocketsTcpSecureFunction::TlsConnectDone(std::unique_ptr<TLSSocket> socket, + int result) { + // If an error occurred, socket MUST be NULL + DCHECK(result == net::OK || socket == NULL); + + if (socket && result == net::OK) { + socket->set_persistent(persistent_); + socket->set_paused(paused_); + ReplaceSocket(params_->socket_id, socket.release()); + } else { RemoveSocket(params_->socket_id); error_ = net::ErrorToString(result); - results_ = api::sockets_tcp::Secure::Results::Create(result); - AsyncWorkCompleted(); - return; } - auto socket = - std::make_unique<TLSSocket>(std::move(tls_socket), local_addr, peer_addr, - std::move(receive_pipe_handle), - std::move(send_pipe_handle), extension_id()); - socket->set_persistent(persistent_); - socket->set_paused(paused_); - ReplaceSocket(params_->socket_id, socket.release()); + results_ = api::sockets_tcp::Secure::Results::Create(result); AsyncWorkCompleted(); }
diff --git a/extensions/browser/api/sockets_tcp/sockets_tcp_api.h b/extensions/browser/api/sockets_tcp/sockets_tcp_api.h index fd004e7..c4b3ee8 100644 --- a/extensions/browser/api/sockets_tcp/sockets_tcp_api.h +++ b/extensions/browser/api/sockets_tcp/sockets_tcp_api.h
@@ -7,16 +7,14 @@ #include <stddef.h> -#include <memory> - #include "base/gtest_prod_util.h" #include "base/macros.h" #include "extensions/browser/api/socket/socket_api.h" #include "extensions/common/api/sockets_tcp.h" -#include "services/network/public/mojom/tcp_socket.mojom.h" namespace extensions { class ResumableTCPSocket; +class TLSSocket; } namespace extensions { @@ -110,11 +108,9 @@ // AsyncApiFunction bool Prepare() override; - void AsyncWorkStart() override; + void Work() override; private: - void OnCompleted(bool success); - std::unique_ptr<sockets_tcp::SetKeepAlive::Params> params_; }; @@ -129,11 +125,9 @@ // AsyncApiFunction bool Prepare() override; - void AsyncWorkStart() override; + void Work() override; private: - void OnCompleted(bool success); - std::unique_ptr<sockets_tcp::SetNoDelay::Params> params_; }; @@ -261,16 +255,13 @@ void AsyncWorkStart() override; private: - void TlsConnectDone(int result, - network::mojom::TLSClientSocketPtr tls_socket, - const net::IPEndPoint& local_addr, - const net::IPEndPoint& peer_addr, - mojo::ScopedDataPipeConsumerHandle receive_pipe_handle, - mojo::ScopedDataPipeProducerHandle send_pipe_handle); + virtual void TlsConnectDone(std::unique_ptr<extensions::TLSSocket> sock, + int result); bool paused_; bool persistent_; std::unique_ptr<sockets_tcp::Secure::Params> params_; + scoped_refptr<net::URLRequestContextGetter> url_request_getter_; DISALLOW_COPY_AND_ASSIGN(SocketsTcpSecureFunction); };
diff --git a/extensions/browser/api/sockets_tcp/sockets_tcp_apitest.cc b/extensions/browser/api/sockets_tcp/sockets_tcp_apitest.cc index 918b2a0e..4d62b093 100644 --- a/extensions/browser/api/sockets_tcp/sockets_tcp_apitest.cc +++ b/extensions/browser/api/sockets_tcp/sockets_tcp_apitest.cc
@@ -4,14 +4,8 @@ #include <utility> -#include "base/command_line.h" #include "base/memory/ref_counted.h" #include "base/strings/stringprintf.h" -#include "content/public/common/content_features.h" -#include "content/public/common/content_switches.h" -#include "content/public/common/service_manager_connection.h" -#include "content/public/common/service_names.mojom.h" -#include "content/public/test/network_service_test_helper.h" #include "extensions/browser/api/dns/host_resolver_wrapper.h" #include "extensions/browser/api/dns/mock_host_resolver_creator.h" #include "extensions/browser/api/sockets_tcp/sockets_tcp_api.h" @@ -22,11 +16,8 @@ #include "extensions/shell/test/shell_test.h" #include "extensions/test/extension_test_message_listener.h" #include "extensions/test/result_catcher.h" -#include "mojo/public/cpp/bindings/sync_call_restrictions.h" #include "net/dns/mock_host_resolver.h" #include "net/test/spawned_test_server/spawned_test_server.h" -#include "services/network/public/cpp/features.h" -#include "services/service_manager/public/cpp/connector.h" namespace extensions { @@ -34,18 +25,14 @@ class SocketsTcpApiTest : public ShellApiTest { public: - SocketsTcpApiTest() : resolver_creator_(new MockHostResolverCreator()) { - if (base::FeatureList::IsEnabled(network::features::kNetworkService)) { - base::CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kUseMockCertVerifierForTesting); - } - } + SocketsTcpApiTest() + : resolver_event_(base::WaitableEvent::ResetPolicy::MANUAL, + base::WaitableEvent::InitialState::NOT_SIGNALED), + resolver_creator_(new MockHostResolverCreator()) {} void SetUpOnMainThread() override { ShellApiTest::SetUpOnMainThread(); - // TODO(xunjieli): Figure out what to do with this in-process host resolver - // which doesn't work with the out-of-process network service. HostResolverWrapper::GetInstance()->SetHostResolverForTesting( resolver_creator_->CreateMockHostResolver()); } @@ -58,6 +45,8 @@ } private: + base::WaitableEvent resolver_event_; + // The MockHostResolver asserts that it's used on the same thread on which // it's created, which is actually a stronger rule than its real counterpart. // But that's fine; it's good practice. @@ -112,19 +101,6 @@ } IN_PROC_BROWSER_TEST_F(SocketsTcpApiTest, SocketTcpExtensionTLS) { - network::mojom::NetworkServiceTestPtr network_service_test; - // If network service is running in a utility process, the cert of the - // SpawnedTestServer won't be recognized, so inject mock cert verifier through - // the test helper interface. - if (base::FeatureList::IsEnabled(network::features::kNetworkService)) { - content::ServiceManagerConnection::GetForProcess() - ->GetConnector() - ->BindInterface(content::mojom::kNetworkServiceName, - &network_service_test); - mojo::ScopedAllowSyncCallForTesting allow_sync_call; - network_service_test->MockCertVerifierSetDefaultResult(net::OK); - } - std::unique_ptr<net::SpawnedTestServer> test_https_server( new net::SpawnedTestServer( net::SpawnedTestServer::TYPE_HTTPS, net::BaseTestServer::SSLOptions(),
diff --git a/extensions/browser/api/sockets_tcp_server/sockets_tcp_server_api.cc b/extensions/browser/api/sockets_tcp_server/sockets_tcp_server_api.cc index 45b8a780..021ea5f 100644 --- a/extensions/browser/api/sockets_tcp_server/sockets_tcp_server_api.cc +++ b/extensions/browser/api/sockets_tcp_server/sockets_tcp_server_api.cc
@@ -4,8 +4,6 @@ #include "extensions/browser/api/sockets_tcp_server/sockets_tcp_server_api.h" -#include <vector> - #include "content/public/common/socket_permission_request.h" #include "extensions/browser/api/socket/tcp_socket.h" #include "extensions/browser/api/sockets_tcp_server/tcp_server_socket_event_dispatcher.h" @@ -86,8 +84,8 @@ } void SocketsTcpServerCreateFunction::Work() { - auto* socket = - new ResumableTCPServerSocket(browser_context(), extension_->id()); + ResumableTCPServerSocket* socket = + new ResumableTCPServerSocket(extension_->id()); sockets_tcp_server::SocketProperties* properties = params_->properties.get(); if (properties) { @@ -192,23 +190,10 @@ return; } - socket->Listen( + int net_result = socket->Listen( params_->address, params_->port, params_->backlog.get() ? *params_->backlog : kDefaultListenBacklog, - base::BindOnce(&SocketsTcpServerListenFunction::OnCompleted, this)); -} - -void SocketsTcpServerListenFunction::OnCompleted( - int net_result, - const std::string& /* error_msg */) { - DCHECK_NE(net::ERR_IO_PENDING, net_result); - - ResumableTCPServerSocket* socket = GetTcpSocket(params_->socket_id); - if (!socket) { - error_ = kSocketNotFoundError; - AsyncWorkCompleted(); - return; - } + &error_); results_ = sockets_tcp_server::Listen::Results::Create(net_result); if (net_result == net::OK) { socket_event_dispatcher_->OnServerSocketListen(extension_->id(),
diff --git a/extensions/browser/api/sockets_tcp_server/sockets_tcp_server_api.h b/extensions/browser/api/sockets_tcp_server/sockets_tcp_server_api.h index 96ed487..b5f93c63 100644 --- a/extensions/browser/api/sockets_tcp_server/sockets_tcp_server_api.h +++ b/extensions/browser/api/sockets_tcp_server/sockets_tcp_server_api.h
@@ -5,9 +5,6 @@ #ifndef EXTENSIONS_BROWSER_API_SOCKETS_TCP_SERVER_SOCKETS_TCP_SERVER_API_H_ #define EXTENSIONS_BROWSER_API_SOCKETS_TCP_SERVER_SOCKETS_TCP_SERVER_API_H_ -#include <memory> -#include <string> - #include "base/gtest_prod_util.h" #include "extensions/browser/api/socket/socket_api.h" #include "extensions/common/api/sockets_tcp_server.h" @@ -101,8 +98,6 @@ void AsyncWorkStart() override; private: - void OnCompleted(int result, const std::string& error_msg); - std::unique_ptr<sockets_tcp_server::Listen::Params> params_; TCPServerSocketEventDispatcher* socket_event_dispatcher_; };
diff --git a/extensions/browser/api/sockets_tcp_server/tcp_server_socket_event_dispatcher.cc b/extensions/browser/api/sockets_tcp_server/tcp_server_socket_event_dispatcher.cc index 565a037..4854e8b7 100644 --- a/extensions/browser/api/sockets_tcp_server/tcp_server_socket_event_dispatcher.cc +++ b/extensions/browser/api/sockets_tcp_server/tcp_server_socket_event_dispatcher.cc
@@ -117,24 +117,19 @@ return; socket->Accept( - base::BindOnce(&TCPServerSocketEventDispatcher::AcceptCallback, params)); + base::Bind(&TCPServerSocketEventDispatcher::AcceptCallback, params)); } // static void TCPServerSocketEventDispatcher::AcceptCallback( const AcceptParams& params, int result_code, - network::mojom::TCPConnectedSocketPtr socket, - const base::Optional<net::IPEndPoint>& remote_addr, - mojo::ScopedDataPipeConsumerHandle receive_pipe_handle, - mojo::ScopedDataPipeProducerHandle send_pipe_handle) { + std::unique_ptr<net::TCPClientSocket> socket) { DCHECK_CURRENTLY_ON(params.thread_id); - DCHECK_GE(net::OK, result_code); - if (result_code == net::OK) { - ResumableTCPSocket* client_socket = new ResumableTCPSocket( - std::move(socket), std::move(receive_pipe_handle), - std::move(send_pipe_handle), remote_addr, params.extension_id); + if (result_code >= 0) { + ResumableTCPSocket* client_socket = + new ResumableTCPSocket(std::move(socket), params.extension_id, true); client_socket->set_paused(true); int client_socket_id = params.client_sockets->Add(client_socket);
diff --git a/extensions/browser/api/sockets_tcp_server/tcp_server_socket_event_dispatcher.h b/extensions/browser/api/sockets_tcp_server/tcp_server_socket_event_dispatcher.h index 3da1e491..98fc928d 100644 --- a/extensions/browser/api/sockets_tcp_server/tcp_server_socket_event_dispatcher.h +++ b/extensions/browser/api/sockets_tcp_server/tcp_server_socket_event_dispatcher.h
@@ -5,14 +5,10 @@ #ifndef EXTENSIONS_BROWSER_API_SOCKETS_TCP_SERVER_TCP_SERVER_SOCKET_EVENT_DISPATCHER_H_ #define EXTENSIONS_BROWSER_API_SOCKETS_TCP_SERVER_TCP_SERVER_SOCKET_EVENT_DISPATCHER_H_ -#include <memory> -#include <string> - #include "content/public/browser/browser_thread.h" #include "extensions/browser/api/api_resource_manager.h" #include "extensions/browser/api/sockets_tcp/sockets_tcp_api.h" #include "extensions/browser/api/sockets_tcp_server/sockets_tcp_server_api.h" -#include "services/network/public/mojom/tcp_socket.mojom.h" namespace content { class BrowserContext; @@ -81,13 +77,9 @@ static void StartAccept(const AcceptParams& params); // Called when socket accepts a new connection. - static void AcceptCallback( - const AcceptParams& params, - int result, - network::mojom::TCPConnectedSocketPtr socket, - const base::Optional<net::IPEndPoint>& remote_addr, - mojo::ScopedDataPipeConsumerHandle receive_pipe_handle, - mojo::ScopedDataPipeProducerHandle send_pipe_handle); + static void AcceptCallback(const AcceptParams& params, + int result_code, + std::unique_ptr<net::TCPClientSocket> socket); // Post an extension event from |thread_id| to UI thread static void PostEvent(const AcceptParams& params,
diff --git a/extensions/browser/api/sockets_udp/sockets_udp_api.cc b/extensions/browser/api/sockets_udp/sockets_udp_api.cc index 620b51f..3b169c9 100644 --- a/extensions/browser/api/sockets_udp/sockets_udp_api.cc +++ b/extensions/browser/api/sockets_udp/sockets_udp_api.cc
@@ -240,7 +240,8 @@ params_ = sockets_udp::Send::Params::Create(*args_); EXTENSION_FUNCTION_VALIDATE(params_.get()); io_buffer_size_ = params_->data.size(); - io_buffer_ = new net::WrappedIOBuffer(params_->data.data()); + io_buffer_ = new net::WrappedIOBuffer( + reinterpret_cast<const char*>(params_->data.data())); return true; }
diff --git a/extensions/browser/api/vpn_provider/vpn_provider_api.cc b/extensions/browser/api/vpn_provider/vpn_provider_api.cc index 07748613..23816e79 100644 --- a/extensions/browser/api/vpn_provider/vpn_provider_api.cc +++ b/extensions/browser/api/vpn_provider/vpn_provider_api.cc
@@ -293,7 +293,8 @@ } service->SendPacket( - extension_id(), params->data, + extension_id(), + std::vector<char>(params->data.begin(), params->data.end()), base::Bind(&VpnProviderSendPacketFunction::SignalCallCompletionSuccess, this), base::Bind(&VpnProviderNotifyConnectionStateChangedFunction::
diff --git a/extensions/browser/api/vpn_provider/vpn_service.cc b/extensions/browser/api/vpn_provider/vpn_service.cc index 62678a5..b1c249f1 100644 --- a/extensions/browser/api/vpn_provider/vpn_service.cc +++ b/extensions/browser/api/vpn_provider/vpn_service.cc
@@ -115,7 +115,8 @@ pepper_vpn_provider_proxy_->SendOnPacketReceived(data); } else { std::unique_ptr<base::ListValue> event_args = - api_vpn::OnPacketReceived::Create(data); + api_vpn::OnPacketReceived::Create( + std::vector<uint8_t>(data.begin(), data.end())); vpn_service_->SendSignalToExtension( extension_id_, extensions::events::VPN_PROVIDER_ON_PACKET_RECEIVED, api_vpn::OnPacketReceived::kEventName, std::move(event_args));
diff --git a/extensions/browser/api/web_request/web_request_api.cc b/extensions/browser/api/web_request/web_request_api.cc index dda04f4..52928ed8 100644 --- a/extensions/browser/api/web_request/web_request_api.cc +++ b/extensions/browser/api/web_request/web_request_api.cc
@@ -31,13 +31,12 @@ #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/resource_request_info.h" +#include "content/public/browser/storage_partition.h" #include "content/public/browser/web_contents.h" #include "content/public/common/browser_side_navigation_policy.h" #include "content/public/common/child_process_host.h" #include "content/public/common/resource_type.h" #include "extensions/browser/api/activity_log/web_request_constants.h" -#include "extensions/browser/api/declarative/rules_registry_service.h" -#include "extensions/browser/api/declarative_net_request/rules_monitor_service.h" #include "extensions/browser/api/declarative_net_request/ruleset_manager.h" #include "extensions/browser/api/declarative_webrequest/request_stage.h" #include "extensions/browser/api/declarative_webrequest/webrequest_constants.h" @@ -447,7 +446,10 @@ : browser_context_(context), info_map_(ExtensionSystem::Get(browser_context_)->info_map()), proxies_(base::MakeRefCounted<ProxySet>()), - request_id_generator_(base::MakeRefCounted<RequestIDGenerator>()) { + request_id_generator_(base::MakeRefCounted<RequestIDGenerator>()), + may_have_proxies_(MayHaveProxies()), + rules_monitor_observer_(this), + rules_registry_observer_(this) { EventRouter* event_router = EventRouter::Get(browser_context_); for (size_t i = 0; i < arraysize(kWebRequestEvents); ++i) { // Observe the webRequest event. @@ -459,6 +461,13 @@ 0, sizeof(kWebRequestEventPrefix) - 1, webview::kWebViewEventPrefix); event_router->RegisterObserver(this, event_name); } + + rules_monitor_observer_.Add( + BrowserContextKeyedAPIFactory< + declarative_net_request::RulesMonitorService>::Get(browser_context_)); + rules_registry_observer_.Add( + BrowserContextKeyedAPIFactory<RulesRegistryService>::Get( + browser_context_)); } WebRequestAPI::~WebRequestAPI() { @@ -469,6 +478,8 @@ void WebRequestAPI::Shutdown() { EventRouter::Get(browser_context_)->UnregisterObserver(this); + rules_monitor_observer_.RemoveAll(); + rules_registry_observer_.RemoveAll(); } static base::LazyInstance< @@ -484,12 +495,14 @@ void WebRequestAPI::OnListenerAdded(const EventListenerInfo& details) { DCHECK_CURRENTLY_ON(BrowserThread::UI); ++listener_count_; + UpdateMayHaveProxies(); } void WebRequestAPI::OnListenerRemoved(const EventListenerInfo& details) { DCHECK_CURRENTLY_ON(BrowserThread::UI); --listener_count_; DCHECK_GE(listener_count_, 0); + UpdateMayHaveProxies(); // Note that details.event_name includes the sub-event details (e.g. "/123"). // TODO(fsamuel): <webview> events will not be removed through this code path. @@ -586,17 +599,8 @@ network::mojom::WebSocketRequest* request, network::mojom::AuthenticationHandlerPtr* auth_handler) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - const auto* rules_registry_service = - BrowserContextKeyedAPIFactory<RulesRegistryService>::Get( - browser_context_); - const auto* rules_monitor_service = BrowserContextKeyedAPIFactory< - declarative_net_request::RulesMonitorService>::Get(browser_context_); - if (!base::FeatureList::IsEnabled(network::features::kNetworkService) || - (listener_count_ == 0 && - !rules_registry_service->HasAnyRegisteredRules() && - !rules_monitor_service->HasAnyRegisteredRulesets())) { + if (!MayHaveProxies()) return; - } network::mojom::WebSocketPtrInfo proxied_socket_ptr_info; auto proxied_request = std::move(*request); @@ -621,6 +625,8 @@ if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) return false; + // If any other conditions are added here, make sure to call + // |UpdateMayHaveProxies()| when those conditions may change. const auto* rules_registry_service = BrowserContextKeyedAPIFactory<RulesRegistryService>::Get( browser_context_); @@ -631,6 +637,27 @@ rules_monitor_service->HasAnyRegisteredRulesets(); } +void WebRequestAPI::UpdateMayHaveProxies() { + if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) + return; + + bool may_have_proxies = MayHaveProxies(); + if (!may_have_proxies_ && may_have_proxies) { + content::BrowserContext::GetDefaultStoragePartition(browser_context_) + ->GetNetworkContext() + ->ResetURLLoaderFactories(); + } + may_have_proxies_ = may_have_proxies; +} + +void WebRequestAPI::OnRulesetLoaded() { + UpdateMayHaveProxies(); +} + +void WebRequestAPI::OnUpdateRules() { + UpdateMayHaveProxies(); +} + // Represents a single unique listener to an event, along with whatever filter // parameters and extra_info_spec were specified at the time the listener was // added.
diff --git a/extensions/browser/api/web_request/web_request_api.h b/extensions/browser/api/web_request/web_request_api.h index c4bb1ae..dd976ed 100644 --- a/extensions/browser/api/web_request/web_request_api.h +++ b/extensions/browser/api/web_request/web_request_api.h
@@ -24,6 +24,8 @@ #include "content/public/browser/content_browser_client.h" #include "content/public/browser/global_request_id.h" #include "extensions/browser/api/declarative/rules_registry.h" +#include "extensions/browser/api/declarative/rules_registry_service.h" +#include "extensions/browser/api/declarative_net_request/rules_monitor_service.h" #include "extensions/browser/api/declarative_webrequest/request_stage.h" #include "extensions/browser/api/web_request/web_request_api_helpers.h" #include "extensions/browser/api/web_request/web_request_permissions.h" @@ -72,8 +74,11 @@ // work is done by ExtensionWebRequestEventRouter below. This class observes // extensions::EventRouter to deal with event listeners. There is one instance // per BrowserContext which is shared with incognito. -class WebRequestAPI : public BrowserContextKeyedAPI, - public EventRouter::Observer { +class WebRequestAPI + : public BrowserContextKeyedAPI, + public EventRouter::Observer, + public declarative_net_request::RulesMonitorService::Observer, + public RulesRegistryService::Observer { public: // A callback used to asynchronously respond to an intercepted authentication // request when the Network Service is enabled. If |should_cancel| is true @@ -236,6 +241,16 @@ // installed to support the API with Network Service enabled. bool MayHaveProxies() const; + // Checks if |MayHaveProxies()| has changed from false to true, and resets + // URLLoaderFactories if so. + void UpdateMayHaveProxies(); + + // RulesMonitorService::Observer implementation. + void OnRulesetLoaded() override; + + // RulesRegistryService::Observer implementation. + void OnUpdateRules() override; + // A count of active event listeners registered in this BrowserContext. This // is eventually consistent with the state of int listener_count_ = 0; @@ -248,6 +263,16 @@ scoped_refptr<RequestIDGenerator> request_id_generator_; + // Stores the last result of |MayHaveProxies()|, so it can be used in + // |UpdateMayHaveProxies()|. + bool may_have_proxies_; + + ScopedObserver<declarative_net_request::RulesMonitorService, + declarative_net_request::RulesMonitorService::Observer> + rules_monitor_observer_; + ScopedObserver<RulesRegistryService, RulesRegistryService::Observer> + rules_registry_observer_; + DISALLOW_COPY_AND_ASSIGN(WebRequestAPI); };
diff --git a/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.cc b/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.cc index 5d4baf9..ec0e7bb 100644 --- a/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.cc +++ b/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.cc
@@ -337,16 +337,15 @@ } info_->AddResponseInfoFromResourceResponse(current_response_); + auto continuation = + base::BindRepeating(&InProgressRequest::OnAuthRequestHandled, + weak_factory_.GetWeakPtr(), base::Passed(&callback)); auth_credentials_.emplace(); net::NetworkDelegate::AuthRequiredResponse response = ExtensionWebRequestEventRouter::GetInstance()->OnAuthRequired( factory_->browser_context_, factory_->info_map_, &info_.value(), - *auth_info, - base::BindRepeating(&InProgressRequest::OnAuthRequestHandled, - weak_factory_.GetWeakPtr(), - base::Passed(&callback)), - &auth_credentials_.value()); + *auth_info, continuation, &auth_credentials_.value()); // At least one extension has a blocking handler for this request, so we'll // just wait for them to finish. |OnAuthRequestHandled()| will be invoked @@ -357,10 +356,7 @@ // We're not touching this auth request. Let the default browser behavior // proceed. DCHECK_EQ(response, net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION); - content::BrowserThread::PostTask( - content::BrowserThread::UI, FROM_HERE, - base::BindOnce(std::move(callback), base::nullopt, - false /* should_cancel */)); + continuation.Run(response); } void WebRequestProxyingURLLoaderFactory::InProgressRequest::
diff --git a/extensions/browser/api/webcam_private/visca_webcam.cc b/extensions/browser/api/webcam_private/visca_webcam.cc index 4d873daf6..d73bb31 100644 --- a/extensions/browser/api/webcam_private/visca_webcam.cc +++ b/extensions/browser/api/webcam_private/visca_webcam.cc
@@ -248,8 +248,9 @@ const CommandCompleteCallback& callback) { CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); serial_connection_->Send( - data, base::Bind(&ViscaWebcam::OnSendCompleted, - weak_ptr_factory_.GetWeakPtr(), callback)); + std::vector<uint8_t>(data.begin(), data.end()), + base::Bind(&ViscaWebcam::OnSendCompleted, weak_ptr_factory_.GetWeakPtr(), + callback)); } void ViscaWebcam::OnSendCompleted(const CommandCompleteCallback& callback, @@ -272,7 +273,7 @@ } void ViscaWebcam::OnReceiveCompleted(const CommandCompleteCallback& callback, - std::vector<char> data, + std::vector<uint8_t> data, api::serial::ReceiveError error) { CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); data_buffer_.insert(data_buffer_.end(), data.begin(), data.end());
diff --git a/extensions/browser/api/webcam_private/visca_webcam.h b/extensions/browser/api/webcam_private/visca_webcam.h index 1fe22b5e..d36e909 100644 --- a/extensions/browser/api/webcam_private/visca_webcam.h +++ b/extensions/browser/api/webcam_private/visca_webcam.h
@@ -76,7 +76,7 @@ api::serial::SendError error); void ReceiveLoop(const CommandCompleteCallback& callback); void OnReceiveCompleted(const CommandCompleteCallback& callback, - std::vector<char> data, + std::vector<uint8_t> data, api::serial::ReceiveError error); // Callback function that will be called after the send and reply of a command
diff --git a/extensions/browser/api/webcam_private/visca_webcam_unittest.cc b/extensions/browser/api/webcam_private/visca_webcam_unittest.cc index 63df950..6ce7d8a 100644 --- a/extensions/browser/api/webcam_private/visca_webcam_unittest.cc +++ b/extensions/browser/api/webcam_private/visca_webcam_unittest.cc
@@ -23,11 +23,11 @@ } ~TestSerialConnection() override {} - void SetReceiveBuffer(const std::vector<char>& receive_buffer) { + void SetReceiveBuffer(const std::vector<uint8_t>& receive_buffer) { receive_buffer_ = receive_buffer; } - void CheckSendBufferAndClear(const std::vector<char>& expectations) { + void CheckSendBufferAndClear(const std::vector<uint8_t>& expectations) { EXPECT_EQ(send_buffer_, expectations); send_buffer_.clear(); } @@ -46,15 +46,15 @@ return true; } - bool Send(const std::vector<char>& data, + bool Send(const std::vector<uint8_t>& data, SendCompleteCallback callback) override { send_buffer_.insert(send_buffer_.end(), data.begin(), data.end()); std::move(callback).Run(data.size(), api::serial::SEND_ERROR_NONE); return true; } - std::vector<char> receive_buffer_; - std::vector<char> send_buffer_; + std::vector<uint8_t> receive_buffer_; + std::vector<uint8_t> send_buffer_; DISALLOW_COPY_AND_ASSIGN(TestSerialConnection); }; @@ -94,8 +94,10 @@ DISALLOW_COPY_AND_ASSIGN(SetPTZExpectations); }; -#define CHAR_VECTOR_FROM_ARRAY(array) \ - std::vector<char>(array, array + arraysize(array)) +template <size_t N> +std::vector<uint8_t> ToByteVector(const char (&array)[N]) { + return std::vector<uint8_t>(array, array + N); +} } // namespace @@ -126,32 +128,27 @@ // Check getting the zoom. const char kGetZoomCommand[] = {0x81, 0x09, 0x04, 0x47, 0xFF}; const char kGetZoomResponse[] = {0x00, 0x50, 0x01, 0x02, 0x03, 0x04, 0xFF}; - serial_connection()->SetReceiveBuffer( - CHAR_VECTOR_FROM_ARRAY(kGetZoomResponse)); + serial_connection()->SetReceiveBuffer(ToByteVector(kGetZoomResponse)); Webcam::GetPTZCompleteCallback receive_callback = base::Bind(&GetPTZExpectations::OnCallback, base::Owned(new GetPTZExpectations(true, 0x1234))); webcam()->GetZoom(receive_callback); base::RunLoop().RunUntilIdle(); - serial_connection()->CheckSendBufferAndClear( - CHAR_VECTOR_FROM_ARRAY(kGetZoomCommand)); + serial_connection()->CheckSendBufferAndClear(ToByteVector(kGetZoomCommand)); // Check setting the zoom. const char kSetZoomCommand[] = {0x81, 0x01, 0x04, 0x47, 0x06, 0x02, 0x05, 0x03, 0xFF}; // Note: this is a valid, but empty value because nothing is checking it. const char kSetZoomResponse[] = {0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0xFF}; - serial_connection()->SetReceiveBuffer( - CHAR_VECTOR_FROM_ARRAY(kSetZoomResponse)); + serial_connection()->SetReceiveBuffer(ToByteVector(kSetZoomResponse)); Webcam::SetPTZCompleteCallback send_callback = base::Bind(&SetPTZExpectations::OnCallback, base::Owned(new SetPTZExpectations(true))); - serial_connection()->SetReceiveBuffer( - CHAR_VECTOR_FROM_ARRAY(kSetZoomResponse)); + serial_connection()->SetReceiveBuffer(ToByteVector(kSetZoomResponse)); webcam()->SetZoom(0x6253, send_callback); base::RunLoop().RunUntilIdle(); - serial_connection()->CheckSendBufferAndClear( - CHAR_VECTOR_FROM_ARRAY(kSetZoomCommand)); + serial_connection()->CheckSendBufferAndClear(ToByteVector(kSetZoomCommand)); } } // namespace extensions
diff --git a/extensions/browser/extension_message_filter.cc b/extensions/browser/extension_message_filter.cc index c2aefef..9e553d3 100644 --- a/extensions/browser/extension_message_filter.cc +++ b/extensions/browser/extension_message_filter.cc
@@ -118,10 +118,6 @@ } bool ExtensionMessageFilter::OnMessageReceived(const IPC::Message& message) { - // If we have been shut down already, return. - if (!browser_context_) - return true; - bool handled = true; IPC_BEGIN_MESSAGE_MAP(ExtensionMessageFilter, message) IPC_MESSAGE_HANDLER(ExtensionHostMsg_AddListener, @@ -429,6 +425,7 @@ void ExtensionMessageFilter::OnOpenMessagePort( int routing_id, const PortId& port_id) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); if (!browser_context_) return; @@ -440,6 +437,7 @@ int routing_id, const PortId& port_id, bool force_close) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); if (!browser_context_) return; @@ -449,6 +447,7 @@ void ExtensionMessageFilter::OnPostMessage(const PortId& port_id, const Message& message) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); if (!browser_context_) return;
diff --git a/gin/v8_platform.cc b/gin/v8_platform.cc index 8e885b9..a10c407 100644 --- a/gin/v8_platform.cc +++ b/gin/v8_platform.cc
@@ -119,7 +119,11 @@ TimeClamper() : secret_(base::RandUint64()) {} double ClampTimeResolution(double time_seconds) const { - DCHECK_GE(time_seconds, 0); + bool was_negative = false; + if (time_seconds < 0) { + was_negative = true; + time_seconds = -time_seconds; + } // For each clamped time interval, compute a pseudorandom transition // threshold. The reported time will either be the start of that interval or // the next one depending on which side of the threshold |time_seconds| is. @@ -128,7 +132,9 @@ double tick_threshold = ThresholdFor(clamped_time); if (time_seconds >= tick_threshold) - return (interval + 1) * kResolutionSeconds; + clamped_time = (interval + 1) * kResolutionSeconds; + if (was_negative) + clamped_time = -clamped_time; return clamped_time; }
diff --git a/gpu/command_buffer/client/client_font_manager.cc b/gpu/command_buffer/client/client_font_manager.cc index 33a62a9..bae68cf 100644 --- a/gpu/command_buffer/client/client_font_manager.cc +++ b/gpu/command_buffer/client/client_font_manager.cc
@@ -91,7 +91,7 @@ std::vector<uint8_t> strike_data; strike_server_.writeStrikeData(&strike_data); - const size_t num_handles_created = + const uint64_t num_handles_created = last_allocated_handle_id_ - last_serialized_handle_id_; if (strike_data.size() == 0u && num_handles_created == 0u && locked_handles_.size() == 0u) { @@ -102,14 +102,14 @@ // Size requires for serialization. size_t bytes_required = // Skia data size. - +sizeof(size_t) + alignof(size_t) + strike_data.size() + - alignof(std::max_align_t) + +sizeof(uint64_t) + alignof(uint64_t) + strike_data.size() + + 16 // num of handles created + SerializableHandles. - + sizeof(size_t) + alignof(size_t) + + + sizeof(uint64_t) + alignof(uint64_t) + num_handles_created * sizeof(SerializableSkiaHandle) + alignof(SerializableSkiaHandle) + // num of handles locked + DiscardableHandleIds. - +sizeof(size_t) + alignof(size_t) + + +sizeof(uint64_t) + alignof(uint64_t) + locked_handles_.size() * sizeof(SkDiscardableHandleId) + alignof(SkDiscardableHandleId); @@ -123,7 +123,7 @@ Serializer serializer(reinterpret_cast<char*>(memory), bytes_required); // Serialize all new handles. - serializer.Write<size_t>(&num_handles_created); + serializer.Write<uint64_t>(&num_handles_created); for (SkDiscardableHandleId handle_id = last_serialized_handle_id_ + 1; handle_id <= last_allocated_handle_id_; handle_id++) { auto it = discardable_handle_map_.find(handle_id); @@ -136,16 +136,15 @@ } // Serialize all locked handle ids, so the raster unlocks them when done. - const size_t num_locked_handles = locked_handles_.size(); - serializer.Write<size_t>(&num_locked_handles); + const uint64_t num_locked_handles = locked_handles_.size(); + serializer.Write<uint64_t>(&num_locked_handles); for (auto handle_id : locked_handles_) serializer.Write<SkDiscardableHandleId>(&handle_id); // Serialize skia data. - const size_t skia_data_size = strike_data.size(); - serializer.Write<size_t>(&skia_data_size); - serializer.WriteData(strike_data.data(), strike_data.size(), - alignof(std::max_align_t)); + const uint64_t skia_data_size = strike_data.size(); + serializer.Write<uint64_t>(&skia_data_size); + serializer.WriteData(strike_data.data(), strike_data.size(), 16); // Reset all state for what has been serialized. last_serialized_handle_id_ = last_allocated_handle_id_;
diff --git a/gpu/command_buffer/service/gles2_cmd_clear_framebuffer.cc b/gpu/command_buffer/service/gles2_cmd_clear_framebuffer.cc index ffd22bb4..359fac03 100644 --- a/gpu/command_buffer/service/gles2_cmd_clear_framebuffer.cc +++ b/gpu/command_buffer/service/gles2_cmd_clear_framebuffer.cc
@@ -6,6 +6,7 @@ #include "gpu/command_buffer/service/gl_utils.h" #include "gpu/command_buffer/service/gles2_cmd_decoder.h" +#include "gpu/command_buffer/service/shader_manager.h" #include "ui/gfx/geometry/size.h" namespace { @@ -34,23 +35,6 @@ ), }; -void CompileShader(GLuint shader, const char* shader_source) { - glShaderSource(shader, 1, &shader_source, 0); - glCompileShader(shader); -#if DCHECK_IS_ON() - GLint compile_status = GL_FALSE; - glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status); - if (GL_TRUE != compile_status) { - char buffer[1024]; - GLsizei length = 0; - glGetShaderInfoLog(shader, sizeof(buffer), &length, buffer); - std::string log(buffer, length); - DLOG(ERROR) << "Error compiling shader: " << log; - DLOG(ERROR) << "Shader compilation failure."; - } -#endif -} - } // namespace namespace gpu { @@ -113,10 +97,10 @@ if (!program_) { program_ = glCreateProgram(); GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER); - CompileShader(vertex_shader, g_vertex_shader_source); + CompileShaderWithLog(vertex_shader, g_vertex_shader_source); glAttachShader(program_, vertex_shader); GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); - CompileShader(fragment_shader, g_fragment_shader_source); + CompileShaderWithLog(fragment_shader, g_fragment_shader_source); glAttachShader(program_, fragment_shader); glBindAttribLocation(program_, kVertexPositionAttrib, "a_position"); glLinkProgram(program_);
diff --git a/gpu/command_buffer/service/gles2_cmd_copy_tex_image.cc b/gpu/command_buffer/service/gles2_cmd_copy_tex_image.cc index 69385a1..2da3d7f8 100644 --- a/gpu/command_buffer/service/gles2_cmd_copy_tex_image.cc +++ b/gpu/command_buffer/service/gles2_cmd_copy_tex_image.cc
@@ -5,24 +5,10 @@ #include "gpu/command_buffer/service/gles2_cmd_copy_tex_image.h" #include "gpu/command_buffer/service/decoder_context.h" +#include "gpu/command_buffer/service/shader_manager.h" #include "gpu/command_buffer/service/texture_manager.h" #include "ui/gl/gl_version_info.h" -namespace { - -void CompileShader(GLuint shader, const char* shader_source) { - glShaderSource(shader, 1, &shader_source, 0); - glCompileShader(shader); -#ifndef NDEBUG - GLint compile_status; - glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status); - if (GL_TRUE != compile_status) - DLOG(ERROR) << "CopyTexImage: shader compilation failure."; -#endif -} - -} // anonymous namespace - namespace gpu { namespace gles2 { @@ -65,7 +51,7 @@ "}\n"; GLuint vs = glCreateShader(GL_VERTEX_SHADER); - CompileShader(vs, vs_source); + CompileShaderWithLog(vs, vs_source); glAttachShader(blit_program_, vs); glDeleteShader(vs); @@ -82,7 +68,7 @@ "}\n"; GLuint fs = glCreateShader(GL_FRAGMENT_SHADER); - CompileShader(fs, fs_source); + CompileShaderWithLog(fs, fs_source); glAttachShader(blit_program_, fs); glDeleteShader(fs);
diff --git a/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc b/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc index 0006dca..57385fcd 100644 --- a/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc +++ b/gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc
@@ -11,6 +11,7 @@ #include "gpu/command_buffer/service/decoder_context.h" #include "gpu/command_buffer/service/gl_utils.h" #include "gpu/command_buffer/service/gles2_cmd_copy_tex_image.h" +#include "gpu/command_buffer/service/shader_manager.h" #include "gpu/command_buffer/service/texture_manager.h" #include "ui/gl/gl_version_info.h" @@ -507,24 +508,6 @@ } } -void CompileShader(GLuint shader, const char* shader_source) { - glShaderSource(shader, 1, &shader_source, 0); - glCompileShader(shader); -#if DCHECK_IS_ON() - { - GLint compile_status; - glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status); - if (GL_TRUE != compile_status) { - char buffer[1024]; - GLsizei length = 0; - glGetShaderInfoLog(shader, sizeof(buffer), &length, buffer); - std::string log(buffer, length); - DLOG(ERROR) << "CopyTextureCHROMIUM: shader compilation failure: " << log; - } - } -#endif -} - void DeleteShader(GLuint shader) { if (shader) glDeleteShader(shader); @@ -1420,7 +1403,7 @@ *vertex_shader = glCreateShader(GL_VERTEX_SHADER); std::string source = GetVertexShaderSource(gl_version_info, source_target); - CompileShader(*vertex_shader, source.c_str()); + CompileShaderWithLog(*vertex_shader, source.c_str()); } glAttachShader(info->program, *vertex_shader); GLuint* fragment_shader = &fragment_shaders_[fragment_shader_id]; @@ -1430,7 +1413,7 @@ gl_version_info, premultiply_alpha, unpremultiply_alpha, dither, nv_egl_stream_consumer_external_, source_target, source_format, dest_format); - CompileShader(*fragment_shader, source.c_str()); + CompileShaderWithLog(*fragment_shader, source.c_str()); } glAttachShader(info->program, *fragment_shader); glBindAttribLocation(info->program, kVertexPositionAttrib, "a_position");
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index f10b0b2d..0539795 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -2360,6 +2360,9 @@ void ReadBackBuffersIntoShadowCopies( base::flat_set<scoped_refptr<Buffer>> buffers_to_shadow_copy); + // Compiles the given shader and exits command processing early. + void CompileShaderAndExitCommandProcessingEarly(Shader* shader); + // Generate a member function prototype for each command in an automated and // typesafe way. #define GLES2_CMD_OP(name) \ @@ -11030,7 +11033,7 @@ case GL_COMPILE_STATUS: case GL_INFO_LOG_LENGTH: case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE: - shader->DoCompile(); + CompileShaderAndExitCommandProcessingEarly(shader); break; default: @@ -11096,7 +11099,7 @@ } // Make sure translator has been utilized in compile. - shader->DoCompile(); + CompileShaderAndExitCommandProcessingEarly(shader); bucket->SetFromString(shader->translated_source().c_str()); return error::kNoError; @@ -11135,7 +11138,7 @@ } // Shader must be compiled in order to get the info log. - shader->DoCompile(); + CompileShaderAndExitCommandProcessingEarly(shader); bucket->SetFromString(shader->log_info().c_str()); return error::kNoError; @@ -20251,6 +20254,21 @@ writes_submitted_but_not_completed_.insert(buffer); } +void GLES2DecoderImpl::CompileShaderAndExitCommandProcessingEarly( + Shader* shader) { + // No need to call DoCompile or exit command processing early if the call + // to DoCompile will be a no-op. + if (!shader->CanCompile()) + return; + + shader->DoCompile(); + + // Shader compilation can be very slow (see https://crbug.com/844780), Exit + // command processing to allow for context preemption and GPU watchdog + // checks. + ExitCommandProcessingEarly(); +} + // Include the auto-generated part of this file. We split this because it means // we can easily edit the non-auto generated parts right here in this file // instead of having to edit some template or the code generator.
diff --git a/gpu/command_buffer/service/gles2_cmd_srgb_converter.cc b/gpu/command_buffer/service/gles2_cmd_srgb_converter.cc index 4ce108a..02875468 100644 --- a/gpu/command_buffer/service/gles2_cmd_srgb_converter.cc +++ b/gpu/command_buffer/service/gles2_cmd_srgb_converter.cc
@@ -4,24 +4,10 @@ #include "gpu/command_buffer/service/gles2_cmd_srgb_converter.h" +#include "gpu/command_buffer/service/shader_manager.h" #include "gpu/command_buffer/service/texture_manager.h" #include "ui/gl/gl_version_info.h" -namespace { - -void CompileShader(GLuint shader, const char* shader_source) { - glShaderSource(shader, 1, &shader_source, 0); - glCompileShader(shader); -#ifndef NDEBUG - GLint compile_status; - glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status); - if (GL_TRUE != compile_status) - DLOG(ERROR) << "CopyTexImage: shader compilation failure."; -#endif -} - -} // anonymous namespace - namespace gpu { namespace gles2 { @@ -91,7 +77,7 @@ " v_texcoord = quad_positions[gl_VertexID];\n" "}\n"; GLuint vs = glCreateShader(GL_VERTEX_SHADER); - CompileShader(vs, vs_source.c_str()); + CompileShaderWithLog(vs, vs_source.c_str()); glAttachShader(srgb_converter_program_, vs); glDeleteShader(vs); @@ -150,7 +136,7 @@ "}\n"; GLuint fs = glCreateShader(GL_FRAGMENT_SHADER); - CompileShader(fs, fs_source.c_str()); + CompileShaderWithLog(fs, fs_source.c_str()); glAttachShader(srgb_converter_program_, fs); glDeleteShader(fs);
diff --git a/gpu/command_buffer/service/image_factory.h b/gpu/command_buffer/service/image_factory.h index 5a71975..76cd6d8 100644 --- a/gpu/command_buffer/service/image_factory.h +++ b/gpu/command_buffer/service/image_factory.h
@@ -25,7 +25,7 @@ // |client_id| should be set to the client requesting the creation of instance // and can be used by factory implementation to verify access rights. virtual scoped_refptr<gl::GLImage> CreateImageForGpuMemoryBuffer( - const gfx::GpuMemoryBufferHandle& handle, + gfx::GpuMemoryBufferHandle handle, const gfx::Size& size, gfx::BufferFormat format, unsigned internalformat,
diff --git a/gpu/command_buffer/service/service_font_manager.cc b/gpu/command_buffer/service/service_font_manager.cc index 21eb859..5809fcd 100644 --- a/gpu/command_buffer/service/service_font_manager.cc +++ b/gpu/command_buffer/service/service_font_manager.cc
@@ -36,7 +36,7 @@ if (size == 0u) return true; - if (!AlignMemory(size, alignof(std::max_align_t))) + if (!AlignMemory(size, 16)) return false; if (!strike_client->readStrikeData(memory_, size)) @@ -121,8 +121,8 @@ // All new handles. Deserializer deserializer(memory, memory_size); - size_t new_handles_created; - if (!deserializer.Read<size_t>(&new_handles_created)) + uint64_t new_handles_created; + if (!deserializer.Read<uint64_t>(&new_handles_created)) return false; for (size_t i = 0; i < new_handles_created; ++i) { @@ -143,8 +143,8 @@ } // All locked handles - size_t num_locked_handles; - if (!deserializer.Read<size_t>(&num_locked_handles)) + uint64_t num_locked_handles; + if (!deserializer.Read<uint64_t>(&num_locked_handles)) return false; locked_handles->resize(num_locked_handles); @@ -154,8 +154,8 @@ } // Skia font data. - size_t skia_data_size = 0u; - if (!deserializer.Read<size_t>(&skia_data_size)) + uint64_t skia_data_size = 0u; + if (!deserializer.Read<uint64_t>(&skia_data_size)) return false; if (!deserializer.ReadStrikeData(strike_client_.get(), skia_data_size))
diff --git a/gpu/command_buffer/service/shader_manager.cc b/gpu/command_buffer/service/shader_manager.cc index 104d71d..3ec5927 100644 --- a/gpu/command_buffer/service/shader_manager.cc +++ b/gpu/command_buffer/service/shader_manager.cc
@@ -27,6 +27,24 @@ } // namespace anonymous +void CompileShaderWithLog(GLuint shader, const char* shader_source) { + glShaderSource(shader, 1, &shader_source, 0); + glCompileShader(shader); +#if DCHECK_IS_ON() + GLint compile_status = GL_FALSE; + glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status); + if (GL_TRUE != compile_status) { + GLint info_log_length; + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_log_length); + std::vector<GLchar> info_log(info_log_length); + glGetShaderInfoLog(shader, info_log_length, NULL, &info_log[0]); + std::string log(&info_log[0], info_log_length - 1); + DLOG(ERROR) << "Error compiling shader: " << log; + DLOG(ERROR) << "Shader compilation failure."; + } +#endif +} + Shader::Shader(GLuint service_id, GLenum shader_type) : use_count_(0), shader_state_(kShaderStateWaiting), @@ -57,9 +75,7 @@ } void Shader::DoCompile() { - // We require that RequestCompile() must be called before DoCompile(), - // so we can return early if the shader state is not what we expect. - if (shader_state_ != kShaderStateCompileRequested) { + if (!CanCompile()) { return; }
diff --git a/gpu/command_buffer/service/shader_manager.h b/gpu/command_buffer/service/shader_manager.h index 5ad07d9a..97a8038 100644 --- a/gpu/command_buffer/service/shader_manager.h +++ b/gpu/command_buffer/service/shader_manager.h
@@ -27,6 +27,10 @@ SHADER_VARIABLE_UNDEFINED_TYPE = 0x00 }; +// Compiles shader_source into shader and gives informative logging if +// the compilation fails. +void CompileShaderWithLog(GLuint shader, const char* shader_source); + // This is used to keep the source code for a shader. This is because in order // to emluate GLES2 the shaders will have to be re-written before passed to // the underlying OpenGL. But, when the user calls glGetShaderSource they @@ -49,6 +53,9 @@ void RequestCompile(scoped_refptr<ShaderTranslatorInterface> translator, TranslatedShaderSourceType type); + // Returns true if we are ready to call DoCompile. If we have not yet called + // RequestCompile or if we've already compiled, returns false. + bool CanCompile() { return shader_state_ == kShaderStateCompileRequested; } void DoCompile(); void RefreshTranslatedShaderSource();
diff --git a/gpu/command_buffer/tests/gl_manager.cc b/gpu/command_buffer/tests/gl_manager.cc index e4d4117e..877a6d1 100644 --- a/gpu/command_buffer/tests/gl_manager.cc +++ b/gpu/command_buffer/tests/gl_manager.cc
@@ -101,13 +101,21 @@ NOTREACHED(); return gfx::GpuMemoryBufferId(0); } - gfx::GpuMemoryBufferHandle GetHandle() const override { + gfx::GpuMemoryBufferType GetType() const override { + return gfx::NATIVE_PIXMAP; + } + gfx::GpuMemoryBufferHandle CloneHandle() const override { NOTREACHED(); return gfx::GpuMemoryBufferHandle(); } ClientBuffer AsClientBuffer() override { return reinterpret_cast<ClientBuffer>(this); } + void OnMemoryDump( + base::trace_event::ProcessMemoryDump* pmd, + const base::trace_event::MemoryAllocatorDumpGuid& buffer_dump_guid, + uint64_t tracing_process_id, + int importance) const override {} base::RefCountedBytes* bytes() { return bytes_.get(); } @@ -159,13 +167,21 @@ NOTREACHED(); return gfx::GpuMemoryBufferId(0); } - gfx::GpuMemoryBufferHandle GetHandle() const override { + gfx::GpuMemoryBufferType GetType() const override { + return gfx::IO_SURFACE_BUFFER; + } + gfx::GpuMemoryBufferHandle CloneHandle() const override { NOTREACHED(); return gfx::GpuMemoryBufferHandle(); } ClientBuffer AsClientBuffer() override { return reinterpret_cast<ClientBuffer>(this); } + void OnMemoryDump( + base::trace_event::ProcessMemoryDump* pmd, + const base::trace_event::MemoryAllocatorDumpGuid& buffer_dump_guid, + uint64_t tracing_process_id, + int importance) const override {} IOSurfaceRef iosurface() { return iosurface_; } @@ -509,13 +525,12 @@ gfx::GpuMemoryBuffer* gpu_memory_buffer = reinterpret_cast<gfx::GpuMemoryBuffer*>(buffer); DCHECK(gpu_memory_buffer); - if (gpu_memory_buffer->GetHandle().type == gfx::NATIVE_PIXMAP) { - gfx::GpuMemoryBufferHandle handle = - gfx::CloneHandleForIPC(gpu_memory_buffer->GetHandle()); + if (gpu_memory_buffer->GetType() == gfx::NATIVE_PIXMAP) { + gfx::GpuMemoryBufferHandle handle = gpu_memory_buffer->CloneHandle(); gfx::BufferFormat format = gpu_memory_buffer->GetFormat(); gl_image = gpu_memory_buffer_factory_->AsImageFactory() ->CreateImageForGpuMemoryBuffer( - handle, size, format, internalformat, + std::move(handle), size, format, internalformat, gpu::kInProcessCommandBufferClientId, gpu::kNullSurfaceHandle); if (!gl_image)
diff --git a/gpu/command_buffer/tests/texture_image_factory.cc b/gpu/command_buffer/tests/texture_image_factory.cc index 79a250c..509fb80 100644 --- a/gpu/command_buffer/tests/texture_image_factory.cc +++ b/gpu/command_buffer/tests/texture_image_factory.cc
@@ -52,7 +52,7 @@ }; scoped_refptr<gl::GLImage> TextureImageFactory::CreateImageForGpuMemoryBuffer( - const gfx::GpuMemoryBufferHandle& handle, + gfx::GpuMemoryBufferHandle handle, const gfx::Size& size, gfx::BufferFormat format, unsigned internalformat,
diff --git a/gpu/command_buffer/tests/texture_image_factory.h b/gpu/command_buffer/tests/texture_image_factory.h index c5bd377..0bd5671a 100644 --- a/gpu/command_buffer/tests/texture_image_factory.h +++ b/gpu/command_buffer/tests/texture_image_factory.h
@@ -14,7 +14,7 @@ class TextureImageFactory : public gpu::ImageFactory { public: scoped_refptr<gl::GLImage> CreateImageForGpuMemoryBuffer( - const gfx::GpuMemoryBufferHandle& handle, + gfx::GpuMemoryBufferHandle handle, const gfx::Size& size, gfx::BufferFormat format, unsigned internalformat,
diff --git a/gpu/ipc/client/command_buffer_proxy_impl.cc b/gpu/ipc/client/command_buffer_proxy_impl.cc index fe6c426..3b4bf75 100644 --- a/gpu/ipc/client/command_buffer_proxy_impl.cc +++ b/gpu/ipc/client/command_buffer_proxy_impl.cc
@@ -438,8 +438,7 @@ // This handle is owned by the GPU process and must be passed to it or it // will leak. In otherwords, do not early out on error between here and the // sending of the CreateImage IPC below. - gfx::GpuMemoryBufferHandle handle = - gfx::CloneHandleForIPC(gpu_memory_buffer->GetHandle()); + gfx::GpuMemoryBufferHandle handle = gpu_memory_buffer->CloneHandle(); bool requires_sync_token = handle.type == gfx::IO_SURFACE_BUFFER; uint64_t image_fence_sync = 0;
diff --git a/gpu/ipc/common/gpu_memory_buffer_impl.cc b/gpu/ipc/common/gpu_memory_buffer_impl.cc index d95c88b2..5cf38dd 100644 --- a/gpu/ipc/common/gpu_memory_buffer_impl.cc +++ b/gpu/ipc/common/gpu_memory_buffer_impl.cc
@@ -4,7 +4,8 @@ #include "gpu/ipc/common/gpu_memory_buffer_impl.h" -#include "base/logging.h" +#include "base/trace_event/memory_allocator_dump_guid.h" +#include "base/trace_event/process_memory_dump.h" namespace gpu { @@ -40,4 +41,15 @@ return reinterpret_cast<ClientBuffer>(this); } +void GpuMemoryBufferImpl::OnMemoryDump( + base::trace_event::ProcessMemoryDump* pmd, + const base::trace_event::MemoryAllocatorDumpGuid& buffer_dump_guid, + uint64_t tracing_process_id, + int importance) const { + auto shared_buffer_guid = + gfx::GetGenericSharedGpuMemoryGUIDForTracing(tracing_process_id, GetId()); + pmd->CreateSharedGlobalAllocatorDump(shared_buffer_guid); + pmd->AddOwnershipEdge(buffer_dump_guid, shared_buffer_guid, importance); +} + } // namespace gpu
diff --git a/gpu/ipc/common/gpu_memory_buffer_impl.h b/gpu/ipc/common/gpu_memory_buffer_impl.h index 11f133d4..62e70e4 100644 --- a/gpu/ipc/common/gpu_memory_buffer_impl.h +++ b/gpu/ipc/common/gpu_memory_buffer_impl.h
@@ -30,6 +30,11 @@ gfx::BufferFormat GetFormat() const override; gfx::GpuMemoryBufferId GetId() const override; ClientBuffer AsClientBuffer() override; + void OnMemoryDump( + base::trace_event::ProcessMemoryDump* pmd, + const base::trace_event::MemoryAllocatorDumpGuid& buffer_dump_guid, + uint64_t tracing_process_id, + int importance) const override; void set_destruction_sync_token(const gpu::SyncToken& sync_token) { destruction_sync_token_ = sync_token;
diff --git a/gpu/ipc/common/gpu_memory_buffer_impl_android_hardware_buffer.cc b/gpu/ipc/common/gpu_memory_buffer_impl_android_hardware_buffer.cc index 9c9fcd8..9a7d17c2 100644 --- a/gpu/ipc/common/gpu_memory_buffer_impl_android_hardware_buffer.cc +++ b/gpu/ipc/common/gpu_memory_buffer_impl_android_hardware_buffer.cc
@@ -93,16 +93,15 @@ // static std::unique_ptr<GpuMemoryBufferImplAndroidHardwareBuffer> GpuMemoryBufferImplAndroidHardwareBuffer::CreateFromHandle( - const gfx::GpuMemoryBufferHandle& handle, + gfx::GpuMemoryBufferHandle handle, const gfx::Size& size, gfx::BufferFormat format, gfx::BufferUsage usage, const DestructionCallback& callback) { - DCHECK(handle.android_hardware_buffer); + DCHECK(handle.android_hardware_buffer.is_valid()); return base::WrapUnique(new GpuMemoryBufferImplAndroidHardwareBuffer( handle.id, size, format, callback, - base::android::ScopedHardwareBufferHandle::Adopt( - handle.android_hardware_buffer))); + std::move(handle.android_hardware_buffer))); } bool GpuMemoryBufferImplAndroidHardwareBuffer::Map() { @@ -119,12 +118,17 @@ return 0; } -gfx::GpuMemoryBufferHandle GpuMemoryBufferImplAndroidHardwareBuffer::GetHandle() +gfx::GpuMemoryBufferType GpuMemoryBufferImplAndroidHardwareBuffer::GetType() const { + return gfx::ANDROID_HARDWARE_BUFFER; +} + +gfx::GpuMemoryBufferHandle +GpuMemoryBufferImplAndroidHardwareBuffer::CloneHandle() const { gfx::GpuMemoryBufferHandle handle; handle.type = gfx::ANDROID_HARDWARE_BUFFER; handle.id = id_; - handle.android_hardware_buffer = hardware_buffer_handle_.get(); + handle.android_hardware_buffer = hardware_buffer_handle_.Clone(); return handle; } @@ -141,7 +145,8 @@ AHardwareBuffer_Desc desc = GetBufferDescription(size, format, usage); base::AndroidHardwareBufferCompat::GetInstance().Allocate(&desc, &buffer); DCHECK(buffer); - handle->android_hardware_buffer = buffer; + handle->android_hardware_buffer = + base::android::ScopedHardwareBufferHandle::Adopt(buffer); return base::DoNothing(); }
diff --git a/gpu/ipc/common/gpu_memory_buffer_impl_android_hardware_buffer.h b/gpu/ipc/common/gpu_memory_buffer_impl_android_hardware_buffer.h index f6ffec1..eae2bf1 100644 --- a/gpu/ipc/common/gpu_memory_buffer_impl_android_hardware_buffer.h +++ b/gpu/ipc/common/gpu_memory_buffer_impl_android_hardware_buffer.h
@@ -28,7 +28,7 @@ const DestructionCallback& callback); static std::unique_ptr<GpuMemoryBufferImplAndroidHardwareBuffer> - CreateFromHandle(const gfx::GpuMemoryBufferHandle& handle, + CreateFromHandle(gfx::GpuMemoryBufferHandle handle, const gfx::Size& size, gfx::BufferFormat format, gfx::BufferUsage usage, @@ -44,7 +44,8 @@ void* memory(size_t plane) override; void Unmap() override; int stride(size_t plane) const override; - gfx::GpuMemoryBufferHandle GetHandle() const override; + gfx::GpuMemoryBufferType GetType() const override; + gfx::GpuMemoryBufferHandle CloneHandle() const override; private: GpuMemoryBufferImplAndroidHardwareBuffer(
diff --git a/gpu/ipc/common/gpu_memory_buffer_impl_dxgi.cc b/gpu/ipc/common/gpu_memory_buffer_impl_dxgi.cc index c695db6..9f653bf 100644 --- a/gpu/ipc/common/gpu_memory_buffer_impl_dxgi.cc +++ b/gpu/ipc/common/gpu_memory_buffer_impl_dxgi.cc
@@ -98,13 +98,24 @@ return gfx::RowSizeForBufferFormat(size_.width(), format_, plane); } -gfx::GpuMemoryBufferHandle GpuMemoryBufferImplDXGI::GetHandle() const { +gfx::GpuMemoryBufferType GpuMemoryBufferImplDXGI::GetType() const { + return gfx::DXGI_SHARED_HANDLE; +} + +gfx::GpuMemoryBufferHandle GpuMemoryBufferImplDXGI::CloneHandle() const { gfx::GpuMemoryBufferHandle handle; handle.type = gfx::DXGI_SHARED_HANDLE; handle.id = id_; handle.offset = 0; handle.stride = stride(0); - handle.dxgi_handle = IPC::PlatformFileForTransit(dxgi_handle_.Get()); + base::ProcessHandle process = ::GetCurrentProcess(); + HANDLE duplicated_handle; + BOOL result = + ::DuplicateHandle(process, dxgi_handle_.Get(), process, + &duplicated_handle, 0, FALSE, DUPLICATE_SAME_ACCESS); + if (!result) + DPLOG(ERROR) << "Failed to duplicate DXGI resource handle."; + handle.dxgi_handle = IPC::PlatformFileForTransit(duplicated_handle); return handle; }
diff --git a/gpu/ipc/common/gpu_memory_buffer_impl_dxgi.h b/gpu/ipc/common/gpu_memory_buffer_impl_dxgi.h index 12d90621..d143da17 100644 --- a/gpu/ipc/common/gpu_memory_buffer_impl_dxgi.h +++ b/gpu/ipc/common/gpu_memory_buffer_impl_dxgi.h
@@ -41,7 +41,8 @@ void* memory(size_t plane) override; void Unmap() override; int stride(size_t plane) const override; - gfx::GpuMemoryBufferHandle GetHandle() const override; + gfx::GpuMemoryBufferType GetType() const override; + gfx::GpuMemoryBufferHandle CloneHandle() const override; private: GpuMemoryBufferImplDXGI(gfx::GpuMemoryBufferId id,
diff --git a/gpu/ipc/common/gpu_memory_buffer_impl_io_surface.cc b/gpu/ipc/common/gpu_memory_buffer_impl_io_surface.cc index 8969751..f648f6a 100644 --- a/gpu/ipc/common/gpu_memory_buffer_impl_io_surface.cc +++ b/gpu/ipc/common/gpu_memory_buffer_impl_io_surface.cc
@@ -131,10 +131,15 @@ IOSurfaceSetColorSpace(io_surface_, color_space); } -gfx::GpuMemoryBufferHandle GpuMemoryBufferImplIOSurface::GetHandle() const { +gfx::GpuMemoryBufferType GpuMemoryBufferImplIOSurface::GetType() const { + return gfx::IO_SURFACE_BUFFER; +} + +gfx::GpuMemoryBufferHandle GpuMemoryBufferImplIOSurface::CloneHandle() const { gfx::GpuMemoryBufferHandle handle; handle.type = gfx::IO_SURFACE_BUFFER; handle.id = id_; + handle.mach_port.reset(IOSurfaceCreateMachPort(io_surface_)); return handle; }
diff --git a/gpu/ipc/common/gpu_memory_buffer_impl_io_surface.h b/gpu/ipc/common/gpu_memory_buffer_impl_io_surface.h index f1d0db1..d88f930 100644 --- a/gpu/ipc/common/gpu_memory_buffer_impl_io_surface.h +++ b/gpu/ipc/common/gpu_memory_buffer_impl_io_surface.h
@@ -45,7 +45,8 @@ void Unmap() override; int stride(size_t plane) const override; void SetColorSpace(const gfx::ColorSpace& color_space) override; - gfx::GpuMemoryBufferHandle GetHandle() const override; + gfx::GpuMemoryBufferType GetType() const override; + gfx::GpuMemoryBufferHandle CloneHandle() const override; private: GpuMemoryBufferImplIOSurface(gfx::GpuMemoryBufferId id,
diff --git a/gpu/ipc/common/gpu_memory_buffer_impl_native_pixmap.cc b/gpu/ipc/common/gpu_memory_buffer_impl_native_pixmap.cc index 9dfc506..38c2569 100644 --- a/gpu/ipc/common/gpu_memory_buffer_impl_native_pixmap.cc +++ b/gpu/ipc/common/gpu_memory_buffer_impl_native_pixmap.cc
@@ -134,15 +134,20 @@ return pixmap_->GetStride(plane); } -gfx::GpuMemoryBufferHandle GpuMemoryBufferImplNativePixmap::GetHandle() const { +gfx::GpuMemoryBufferType GpuMemoryBufferImplNativePixmap::GetType() const { + return gfx::NATIVE_PIXMAP; +} + +gfx::GpuMemoryBufferHandle GpuMemoryBufferImplNativePixmap::CloneHandle() + const { gfx::GpuMemoryBufferHandle handle; handle.type = gfx::NATIVE_PIXMAP; handle.id = id_; - if (fd_.is_valid()) { - handle.native_pixmap_handle.fds.emplace_back(fd_.get(), - false /* auto_close */); - } - handle.native_pixmap_handle.planes = planes_; + gfx::NativePixmapHandle native_pixmap_handle; + if (fd_.is_valid()) + native_pixmap_handle.fds.emplace_back(fd_.get(), false /* auto_close */); + native_pixmap_handle.planes = planes_; + handle.native_pixmap_handle = gfx::CloneHandleForIPC(native_pixmap_handle); return handle; }
diff --git a/gpu/ipc/common/gpu_memory_buffer_impl_native_pixmap.h b/gpu/ipc/common/gpu_memory_buffer_impl_native_pixmap.h index ae25ba7..ede8d50 100644 --- a/gpu/ipc/common/gpu_memory_buffer_impl_native_pixmap.h +++ b/gpu/ipc/common/gpu_memory_buffer_impl_native_pixmap.h
@@ -45,7 +45,8 @@ void* memory(size_t plane) override; void Unmap() override; int stride(size_t plane) const override; - gfx::GpuMemoryBufferHandle GetHandle() const override; + gfx::GpuMemoryBufferType GetType() const override; + gfx::GpuMemoryBufferHandle CloneHandle() const override; private: GpuMemoryBufferImplNativePixmap(
diff --git a/gpu/ipc/common/gpu_memory_buffer_impl_shared_memory.cc b/gpu/ipc/common/gpu_memory_buffer_impl_shared_memory.cc index cefa45e2..13a9fd8 100644 --- a/gpu/ipc/common/gpu_memory_buffer_impl_shared_memory.cc +++ b/gpu/ipc/common/gpu_memory_buffer_impl_shared_memory.cc
@@ -14,6 +14,8 @@ #include "base/numerics/safe_math.h" #include "base/process/memory.h" #include "base/strings/stringprintf.h" +#include "base/trace_event/memory_allocator_dump_guid.h" +#include "base/trace_event/process_memory_dump.h" #include "ui/gfx/buffer_format_util.h" #include "ui/gl/gl_bindings.h" @@ -218,21 +220,33 @@ return gfx::RowSizeForBufferFormat(size_.width(), format_, plane); } -gfx::GpuMemoryBufferHandle GpuMemoryBufferImplSharedMemory::GetHandle() const { +gfx::GpuMemoryBufferType GpuMemoryBufferImplSharedMemory::GetType() const { + return gfx::SHARED_MEMORY_BUFFER; +} + +gfx::GpuMemoryBufferHandle GpuMemoryBufferImplSharedMemory::CloneHandle() + const { gfx::GpuMemoryBufferHandle handle; handle.type = gfx::SHARED_MEMORY_BUFFER; handle.id = id_; handle.offset = offset_; handle.stride = stride_; - handle.handle = shared_memory_->handle(); + handle.handle = base::SharedMemory::DuplicateHandle(shared_memory_->handle()); return handle; } -base::trace_event::MemoryAllocatorDumpGuid -GpuMemoryBufferImplSharedMemory::GetGUIDForTracing( - uint64_t tracing_process_id) const { - return base::trace_event::MemoryAllocatorDumpGuid(base::StringPrintf( - "shared_memory_gpu/%" PRIx64 "/%d", tracing_process_id, id_.id)); +void GpuMemoryBufferImplSharedMemory::OnMemoryDump( + base::trace_event::ProcessMemoryDump* pmd, + const base::trace_event::MemoryAllocatorDumpGuid& buffer_dump_guid, + uint64_t tracing_process_id, + int importance) const { + pmd->CreateSharedMemoryOwnershipEdge(buffer_dump_guid, GetSharedMemoryGUID(), + importance); +} + +base::UnguessableToken GpuMemoryBufferImplSharedMemory::GetSharedMemoryGUID() + const { + return shared_memory_->mapped_id(); } } // namespace gpu
diff --git a/gpu/ipc/common/gpu_memory_buffer_impl_shared_memory.h b/gpu/ipc/common/gpu_memory_buffer_impl_shared_memory.h index 794bcb78..921a7e3 100644 --- a/gpu/ipc/common/gpu_memory_buffer_impl_shared_memory.h +++ b/gpu/ipc/common/gpu_memory_buffer_impl_shared_memory.h
@@ -59,9 +59,16 @@ void* memory(size_t plane) override; void Unmap() override; int stride(size_t plane) const override; - gfx::GpuMemoryBufferHandle GetHandle() const override; - base::trace_event::MemoryAllocatorDumpGuid GetGUIDForTracing( - uint64_t tracing_process_id) const override; + gfx::GpuMemoryBufferType GetType() const override; + gfx::GpuMemoryBufferHandle CloneHandle() const override; + void OnMemoryDump( + base::trace_event::ProcessMemoryDump* pmd, + const base::trace_event::MemoryAllocatorDumpGuid& buffer_dump_guid, + uint64_t tracing_process_id, + int importance) const override; + + // Returns the shared memory GUID associated with buffer. + base::UnguessableToken GetSharedMemoryGUID() const; private: GpuMemoryBufferImplSharedMemory(
diff --git a/gpu/ipc/in_process_command_buffer.cc b/gpu/ipc/in_process_command_buffer.cc index 20aeea5..c167212 100644 --- a/gpu/ipc/in_process_command_buffer.cc +++ b/gpu/ipc/in_process_command_buffer.cc
@@ -851,8 +851,7 @@ // This handle is owned by the GPU thread and must be passed to it or it // will leak. In otherwords, do not early out on error between here and the // queuing of the CreateImage task below. - gfx::GpuMemoryBufferHandle handle = - gfx::CloneHandleForIPC(gpu_memory_buffer->GetHandle()); + gfx::GpuMemoryBufferHandle handle = gpu_memory_buffer->CloneHandle(); bool requires_sync_point = handle.type == gfx::IO_SURFACE_BUFFER; uint64_t fence_sync = 0;
diff --git a/gpu/ipc/service/command_buffer_stub.cc b/gpu/ipc/service/command_buffer_stub.cc index a5109da..9f05111 100644 --- a/gpu/ipc/service/command_buffer_stub.cc +++ b/gpu/ipc/service/command_buffer_stub.cc
@@ -797,10 +797,9 @@ } void CommandBufferStub::OnCreateImage( - const GpuCommandBufferMsg_CreateImage_Params& params) { + GpuCommandBufferMsg_CreateImage_Params params) { TRACE_EVENT0("gpu", "CommandBufferStub::OnCreateImage"); const int32_t id = params.id; - const gfx::GpuMemoryBufferHandle& handle = params.gpu_memory_buffer; const gfx::Size& size = params.size; const gfx::BufferFormat& format = params.format; const uint32_t internalformat = params.internal_format; @@ -831,7 +830,8 @@ } scoped_refptr<gl::GLImage> image = channel()->CreateImageForGpuMemoryBuffer( - handle, size, format, internalformat, surface_handle_); + std::move(params.gpu_memory_buffer), size, format, internalformat, + surface_handle_); if (!image.get()) return;
diff --git a/gpu/ipc/service/command_buffer_stub.h b/gpu/ipc/service/command_buffer_stub.h index 35550ea..8c653b53 100644 --- a/gpu/ipc/service/command_buffer_stub.h +++ b/gpu/ipc/service/command_buffer_stub.h
@@ -206,7 +206,7 @@ void OnWaitSyncTokenCompleted(const SyncToken& sync_token); - void OnCreateImage(const GpuCommandBufferMsg_CreateImage_Params& params); + void OnCreateImage(GpuCommandBufferMsg_CreateImage_Params params); void OnDestroyImage(int32_t id); void OnCreateStreamTexture(uint32_t texture_id, int32_t stream_id,
diff --git a/gpu/ipc/service/gpu_channel.cc b/gpu/ipc/service/gpu_channel.cc index f55fbd7..cf267e86 100644 --- a/gpu/ipc/service/gpu_channel.cc +++ b/gpu/ipc/service/gpu_channel.cc
@@ -715,7 +715,7 @@ } scoped_refptr<gl::GLImage> GpuChannel::CreateImageForGpuMemoryBuffer( - const gfx::GpuMemoryBufferHandle& handle, + gfx::GpuMemoryBufferHandle handle, const gfx::Size& size, gfx::BufferFormat format, uint32_t internalformat, @@ -740,8 +740,9 @@ return manager->gpu_memory_buffer_factory() ->AsImageFactory() - ->CreateImageForGpuMemoryBuffer(handle, size, format, internalformat, - client_id_, surface_handle); + ->CreateImageForGpuMemoryBuffer(std::move(handle), size, format, + internalformat, client_id_, + surface_handle); } } }
diff --git a/gpu/ipc/service/gpu_channel.h b/gpu/ipc/service/gpu_channel.h index a209d570..4bed25c 100644 --- a/gpu/ipc/service/gpu_channel.h +++ b/gpu/ipc/service/gpu_channel.h
@@ -160,7 +160,7 @@ uint64_t GetMemoryUsage() const; scoped_refptr<gl::GLImage> CreateImageForGpuMemoryBuffer( - const gfx::GpuMemoryBufferHandle& handle, + gfx::GpuMemoryBufferHandle handle, const gfx::Size& size, gfx::BufferFormat format, uint32_t internalformat,
diff --git a/gpu/ipc/service/gpu_memory_buffer_factory_android_hardware_buffer.cc b/gpu/ipc/service/gpu_memory_buffer_factory_android_hardware_buffer.cc index b58bdf0c..031738c 100644 --- a/gpu/ipc/service/gpu_memory_buffer_factory_android_hardware_buffer.cc +++ b/gpu/ipc/service/gpu_memory_buffer_factory_android_hardware_buffer.cc
@@ -40,7 +40,7 @@ scoped_refptr<gl::GLImage> GpuMemoryBufferFactoryAndroidHardwareBuffer::CreateImageForGpuMemoryBuffer( - const gfx::GpuMemoryBufferHandle& handle, + gfx::GpuMemoryBufferHandle handle, const gfx::Size& size, gfx::BufferFormat format, unsigned internalformat, @@ -50,12 +50,14 @@ // AHardwareBuffer. DCHECK_EQ(handle.type, gfx::ANDROID_HARDWARE_BUFFER); - AHardwareBuffer* buffer = handle.android_hardware_buffer; - DCHECK(buffer); + base::android::ScopedHardwareBufferHandle& buffer = + handle.android_hardware_buffer; + DCHECK(buffer.is_valid()); scoped_refptr<gl::GLImageAHardwareBuffer> image( new gl::GLImageAHardwareBuffer(size)); - if (!image->Initialize(buffer, /* preserved */ false)) { + if (!image->Initialize(buffer.get(), + /* preserved */ false)) { DLOG(ERROR) << "Failed to create GLImage " << size.ToString(); image = nullptr; } @@ -67,7 +69,7 @@ // release here to avoid an excess reference. We want to pass ownership to // the image. Also release in the failure case to ensure we consistently // consume the GpuMemoryBufferHandle. - base::AndroidHardwareBufferCompat::GetInstance().Release(buffer); + buffer.reset(); return image; }
diff --git a/gpu/ipc/service/gpu_memory_buffer_factory_android_hardware_buffer.h b/gpu/ipc/service/gpu_memory_buffer_factory_android_hardware_buffer.h index ff2ccdf3..fc7a862 100644 --- a/gpu/ipc/service/gpu_memory_buffer_factory_android_hardware_buffer.h +++ b/gpu/ipc/service/gpu_memory_buffer_factory_android_hardware_buffer.h
@@ -36,7 +36,7 @@ // Overridden from ImageFactory: scoped_refptr<gl::GLImage> CreateImageForGpuMemoryBuffer( - const gfx::GpuMemoryBufferHandle& handle, + gfx::GpuMemoryBufferHandle handle, const gfx::Size& size, gfx::BufferFormat format, unsigned internalformat,
diff --git a/gpu/ipc/service/gpu_memory_buffer_factory_dxgi.cc b/gpu/ipc/service/gpu_memory_buffer_factory_dxgi.cc index 98d370e..5e747a30 100644 --- a/gpu/ipc/service/gpu_memory_buffer_factory_dxgi.cc +++ b/gpu/ipc/service/gpu_memory_buffer_factory_dxgi.cc
@@ -99,7 +99,7 @@ scoped_refptr<gl::GLImage> GpuMemoryBufferFactoryDXGI::CreateImageForGpuMemoryBuffer( - const gfx::GpuMemoryBufferHandle& handle, + gfx::GpuMemoryBufferHandle handle, const gfx::Size& size, gfx::BufferFormat format, unsigned internalformat,
diff --git a/gpu/ipc/service/gpu_memory_buffer_factory_dxgi.h b/gpu/ipc/service/gpu_memory_buffer_factory_dxgi.h index b76ff9d0..c2cf970 100644 --- a/gpu/ipc/service/gpu_memory_buffer_factory_dxgi.h +++ b/gpu/ipc/service/gpu_memory_buffer_factory_dxgi.h
@@ -47,7 +47,7 @@ // Overridden from ImageFactory: scoped_refptr<gl::GLImage> CreateImageForGpuMemoryBuffer( - const gfx::GpuMemoryBufferHandle& handle, + gfx::GpuMemoryBufferHandle handle, const gfx::Size& size, gfx::BufferFormat format, unsigned internalformat,
diff --git a/gpu/ipc/service/gpu_memory_buffer_factory_io_surface.cc b/gpu/ipc/service/gpu_memory_buffer_factory_io_surface.cc index 7440adb..98d3d82 100644 --- a/gpu/ipc/service/gpu_memory_buffer_factory_io_surface.cc +++ b/gpu/ipc/service/gpu_memory_buffer_factory_io_surface.cc
@@ -105,7 +105,7 @@ scoped_refptr<gl::GLImage> GpuMemoryBufferFactoryIOSurface::CreateImageForGpuMemoryBuffer( - const gfx::GpuMemoryBufferHandle& handle, + gfx::GpuMemoryBufferHandle handle, const gfx::Size& size, gfx::BufferFormat format, unsigned internalformat,
diff --git a/gpu/ipc/service/gpu_memory_buffer_factory_io_surface.h b/gpu/ipc/service/gpu_memory_buffer_factory_io_surface.h index bde2464..96f27f00 100644 --- a/gpu/ipc/service/gpu_memory_buffer_factory_io_surface.h +++ b/gpu/ipc/service/gpu_memory_buffer_factory_io_surface.h
@@ -48,7 +48,7 @@ // Overridden from ImageFactory: scoped_refptr<gl::GLImage> CreateImageForGpuMemoryBuffer( - const gfx::GpuMemoryBufferHandle& handle, + gfx::GpuMemoryBufferHandle handle, const gfx::Size& size, gfx::BufferFormat format, unsigned internalformat,
diff --git a/gpu/ipc/service/gpu_memory_buffer_factory_native_pixmap.cc b/gpu/ipc/service/gpu_memory_buffer_factory_native_pixmap.cc index 4a8e90d..2900b61 100644 --- a/gpu/ipc/service/gpu_memory_buffer_factory_native_pixmap.cc +++ b/gpu/ipc/service/gpu_memory_buffer_factory_native_pixmap.cc
@@ -79,7 +79,7 @@ scoped_refptr<gl::GLImage> GpuMemoryBufferFactoryNativePixmap::CreateImageForGpuMemoryBuffer( - const gfx::GpuMemoryBufferHandle& handle, + gfx::GpuMemoryBufferHandle handle, const gfx::Size& size, gfx::BufferFormat format, unsigned internalformat,
diff --git a/gpu/ipc/service/gpu_memory_buffer_factory_native_pixmap.h b/gpu/ipc/service/gpu_memory_buffer_factory_native_pixmap.h index 3626486..69745d2 100644 --- a/gpu/ipc/service/gpu_memory_buffer_factory_native_pixmap.h +++ b/gpu/ipc/service/gpu_memory_buffer_factory_native_pixmap.h
@@ -43,7 +43,7 @@ // Overridden from ImageFactory: scoped_refptr<gl::GLImage> CreateImageForGpuMemoryBuffer( - const gfx::GpuMemoryBufferHandle& handle, + gfx::GpuMemoryBufferHandle handle, const gfx::Size& size, gfx::BufferFormat format, unsigned internalformat,
diff --git a/headless/test/data/protocol/helpers/frame-navigation-helper.js b/headless/test/data/protocol/helpers/frame-navigation-helper.js new file mode 100644 index 0000000..1d509169 --- /dev/null +++ b/headless/test/data/protocol/helpers/frame-navigation-helper.js
@@ -0,0 +1,105 @@ +// 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. + +/** + * A helper class to keep track of renderer tests frame navigations. + */ +(class FrameNavigationHelper { + /** + * @param {!TestRunner} testRunner Host TestRunner instance. + * @param {!Proxy} dp DevTools session protocol instance. + * @param {!Page} page TestRunner.Page instance. + */ + constructor(testRunner, dp, page) { + this.testRunner_ = testRunner; + this.dp_ = dp; + this.page_ = page; + this.frames_ = new Map(); + this.scheduledNavigations_ = new Map(); + this.state_ = 'INIT'; + this.mainFrameId_ = null; + } + + /** + * Navigates to the specified url. + * + * @param {!string} Url to navigate to. + */ + async navigate(url) { + this.state_ = 'STARTING'; + await this.dp_.Page.navigate({url}); + } + + /** + * Initializes the helper returning reference to itself to allow assignment. + * + * @return {!object} FrameNavigationHelper reference. + */ + async init() { + await this.dp_.Page.enable(); + + await this.dp_.Page.onFrameStartedLoading(event => { + if (this.state_ === 'STARTING') { + this.state_ = 'LOADING'; + this.mainFrameId_ = event.params.frameId; + } + }); + + await this.dp_.Page.onLoadEventFired(event => { + if (this.state_ === 'STARTING' || this.state_ === 'LOADING') { + this.state_ = 'RENDERING'; + } + }); + + await this.dp_.Page.onFrameNavigated(event => { + const frameId = event.params.frame.id; + let value = this.frames_.get(frameId) || []; + value.push(event.params.frame); + this.frames_.set(frameId, value); + }); + + await this.dp_.Page.onFrameScheduledNavigation(event => { + const frameId = event.params.frameId; + const reason = event.params.reason; + const url = event.params.url; + let value = this.scheduledNavigations_.get(frameId) || []; + value.push({url, reason}); + this.scheduledNavigations_.set(frameId, value); + }); + + return this; + } + + /** + * Logs navigated frames. + */ + logFrames() { + this.testRunner_.log(`Frames: ${this.frames_.size}`); + for (const [frameId, frames] of this.frames_.entries()) { + this.testRunner_.log(` frameId=${this.getFrameId_(frameId)}`); + for (const frame of frames) { + this.testRunner_.log(` url=${frame.url}`); + } + } + } + + /** + * Logs scheduled navigations. + */ + logScheduledNavigations() { + this.testRunner_.log( + `ScheduledNavigations: ${this.scheduledNavigations_.size}`); + for (const [frameId, navs] of this.scheduledNavigations_.entries()) { + this.testRunner_.log(` frameId=${this.getFrameId_(frameId)}`); + for (const nav of navs) { + this.testRunner_.log(` url=${nav.url} reason=${nav.reason}`); + } + } + } + + getFrameId_(frameId) { + return frameId === this.mainFrameId_ ? 'MainFrame' : frameId + } + +});
diff --git a/headless/test/data/protocol/helpers/http-interceptor.js b/headless/test/data/protocol/helpers/http-interceptor.js new file mode 100644 index 0000000..4721c53 --- /dev/null +++ b/headless/test/data/protocol/helpers/http-interceptor.js
@@ -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. + +/** + * A helper class to allow renderer tests to conveniently intercept network + * requests and provide HTTP headers and body. + */ +(class HttpInterceptor { + /** + * @param {!TestRunner} testRunner Host TestRunner instance. + * @param {!Proxy} dp DevTools session protocol instance. + * @param {!Page} page TestRunner.Page instance. + */ + constructor(testRunner, dp) { + this.testRunner_ = testRunner; + this.dp_ = dp; + this.responses_ = new Map(); + } + + /** + * Initializes the helper returning reference to itself to allow assignment. + * + * @return {!object} HttpInterceptor reference. + */ + async init() { + await this.dp_.Network.enable(); + await this.dp_.Network.setRequestInterception( + { patterns: [{ urlPattern: '*' }] }); + + this.dp_.Network.onRequestIntercepted(event => { + const url = event.params.request.url; + if (this.responses_.has(url)) { + this.testRunner_.log(`requested url: ${url}`); + } else { + this.testRunner_.log(`requested url: ${url} is not known`); + this.logResponses(); + } + const body = this.responses_.get(url).body || ''; + const headers = this.responses_.get(url).headers || []; + const response = headers.join('\r\n') + '\r\n\r\n' + body; + this.dp_.Network.continueInterceptedRequest({ + interceptionId: event.params.interceptionId, + rawResponse: btoa(response) + }); + }); + + return this; + } + + addResponse(url, body, headers) { + this.responses_.set(url, {body, headers}); + } + + logResponses() { + for (const [url, value] of this.responses_.entries()) { + this.testRunner_.log( + `url=${url}\nbody=${value.body}\nheaders=${value.headers}`); + } + } + +});
diff --git a/headless/test/data/protocol/helpers/renderer-test-helper.js b/headless/test/data/protocol/helpers/renderer-test-helper.js new file mode 100644 index 0000000..1568fb6 --- /dev/null +++ b/headless/test/data/protocol/helpers/renderer-test-helper.js
@@ -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. + +/** + * A helper class to instantiate classes commonly used in renderer tests. + */ +(class RendererTestHelper { + /** + * @param {!TestRunner} testRunner Host TestRunner instance. + * @param {!Proxy} dp DevTools session protocol instance. + * @param {!Page} page TestRunner.Page instance. + */ + constructor(testRunner, dp, page) { + this.testRunner_ = testRunner; + this.dp_ = dp; + this.page_ = page; + } + + /** + * Initializes the helper returning references to useful objects. + * + * @return {!object} httpInterceptor, frameNavigationHelper and + * virtualTimeController references. + */ + async init() { + await this.dp_.Target.enable(); + await this.dp_.Page.enable(); + + let HttpInterceptor = await this.testRunner_.loadScript( + '../helpers/http-interceptor.js'); + let httpInterceptor = + await (new HttpInterceptor(this.testRunner_, this.dp_)) + .init(); + + let FrameNavigationHelper = await this.testRunner_.loadScript( + '../helpers/frame-navigation-helper.js'); + let frameNavigationHelper = + await (new FrameNavigationHelper( + this.testRunner_, this.dp_, this.page_)) + .init(); + + let VirtualTimeController = await this.testRunner_.loadScript( + '../helpers/virtual-time-controller.js'); + let virtualTimeController = + new VirtualTimeController(this.testRunner_, this.dp_, 25); + + return {httpInterceptor, frameNavigationHelper, virtualTimeController}; + } + +});
diff --git a/infra/config/branch/cq.cfg b/infra/config/branch/cq.cfg index 6c010b8..11d8983 100644 --- a/infra/config/branch/cq.cfg +++ b/infra/config/branch/cq.cfg
@@ -66,6 +66,11 @@ experiment_percentage: 10 } builders { name: "linux-chromeos-rel" } + # https://crbug.com/833482 + builders { + name: "linux-dcheck-off-rel" + experiment_percentage: 10 + } # https://crbug.com/855319 builders { name: "linux-goma-rbe-staging-rel"
diff --git a/infra/config/global/cr-buildbucket.cfg b/infra/config/global/cr-buildbucket.cfg index fe51cf2..a10c823 100644 --- a/infra/config/global/cr-buildbucket.cfg +++ b/infra/config/global/cr-buildbucket.cfg
@@ -740,6 +740,12 @@ } builders { + name: "android-mojo-webview-rel" + dimensions: "os:Ubuntu-14.04" + mixins: "fyi-ci" + } + + builders { name: "Cast Android (dbg)" mixins: "android-ci" dimensions: "os:Ubuntu-14.04"
diff --git a/infra/config/global/luci-milo.cfg b/infra/config/global/luci-milo.cfg index 74169a9..195acfa 100644 --- a/infra/config/global/luci-milo.cfg +++ b/infra/config/global/luci-milo.cfg
@@ -2291,18 +2291,27 @@ builders { name: "buildbucket/luci.chromium.ci/Mojo Android" category: "mojo" + short_name: "and" + } + builders { + name: "buildbucket/luci.chromium.ci/android-mojo-webview-rel" + category: "mojo" + short_name: "aw" } builders { name: "buildbucket/luci.chromium.ci/Mojo ChromiumOS" category: "mojo" + short_name: "cr" } builders { name: "buildbucket/luci.chromium.ci/Mojo Linux" category: "mojo" + short_name: "lnx" } builders { name: "buildbucket/luci.chromium.ci/Mojo Windows" category: "mojo" + short_name: "win" } builders { name: "buildbucket/luci.chromium.ci/linux-chromium-tests-staging-builder" @@ -2647,21 +2656,30 @@ name: "buildbot/chromium.fyi/Mojo Android" name: "buildbucket/luci.chromium.ci/Mojo Android" category: "mojo" + short_name: "and" + } + builders { + name: "buildbucket/luci.chromium.ci/android-mojo-webview-rel" + category: "mojo" + short_name: "aw" } builders { name: "buildbot/chromium.fyi/Mojo ChromiumOS" name: "buildbucket/luci.chromium.ci/Mojo ChromiumOS" category: "mojo" + short_name: "cr" } builders { name: "buildbot/chromium.fyi/Mojo Linux" name: "buildbucket/luci.chromium.ci/Mojo Linux" category: "mojo" + short_name: "lnx" } builders { name: "buildbot/chromium.fyi/Mojo Windows" name: "buildbucket/luci.chromium.ci/Mojo Windows" category: "mojo" + short_name: "win" } builders { name: "buildbucket/luci.chromium.ci/linux-chromium-tests-staging-builder"
diff --git a/infra/config/global/luci-scheduler.cfg b/infra/config/global/luci-scheduler.cfg index 13f0756f..644e00c 100644 --- a/infra/config/global/luci-scheduler.cfg +++ b/infra/config/global/luci-scheduler.cfg
@@ -212,6 +212,7 @@ triggers: "Windows deterministic" triggers: "android-kitkat-arm-rel" triggers: "android-marshmallow-arm64-rel" + triggers: "android-mojo-webview-rel" triggers: "chromeos-amd64-generic-rel" triggers: "chromeos-amd64-generic-rel-goma-canary" triggers: "chromeos-amd64-generic-rel-vm-tests" @@ -562,6 +563,16 @@ } job { + id: "android-mojo-webview-rel" + acl_sets: "default" + buildbucket: { + server: "cr-buildbucket.appspot.com" + bucket: "luci.chromium.ci" + builder: "android-mojo-webview-rel" + } +} + +job { id: "Cast Android (dbg)" acl_sets: "default" buildbucket: {
diff --git a/ios/chrome/browser/BUILD.gn b/ios/chrome/browser/BUILD.gn index 23e91391..e71ef21 100644 --- a/ios/chrome/browser/BUILD.gn +++ b/ios/chrome/browser/BUILD.gn
@@ -57,11 +57,14 @@ "install_time_util.mm", "installation_notifier.h", "installation_notifier.mm", + "ios_chrome_field_trials.cc", "ios_chrome_field_trials.h", "ios_chrome_flag_descriptions.cc", "ios_chrome_flag_descriptions.h", "ios_chrome_io_thread.h", "ios_chrome_io_thread.mm", + "ios_first_run_field_trials.cc", + "ios_first_run_field_trials.h", "notification_promo.cc", "notification_promo.h", "pref_names.cc",
diff --git a/ios/chrome/browser/ios_chrome_field_trials.cc b/ios/chrome/browser/ios_chrome_field_trials.cc new file mode 100644 index 0000000..797ec995 --- /dev/null +++ b/ios/chrome/browser/ios_chrome_field_trials.cc
@@ -0,0 +1,105 @@ +// 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 "ios/chrome/browser/ios_chrome_field_trials.h" + +#include <string> +#include <vector> + +#include "base/metrics/field_trial.h" +#include "components/variations/variations_associated_data.h" +#include "components/version_info/version_info.h" +#include "ios/chrome/browser/ios_first_run_field_trials.h" +#include "ios/chrome/browser/ui/ui_feature_flags.h" +#include "ios/chrome/common/channel_info.h" + +namespace { + +// Probabilities for all field trial groups add up to kTotalProbability. +const base::FieldTrial::Probability kTotalProbability = 100; + +// Each field trial has 3 trial groups. +// Default - Majority of users will be in default group which receive the +// default UI. In the case of UI Refresh rollout, this will be the new UI. +// Old UI - A small percentage of users will be held back in the old UI for +// so usage metrics differences between users with old UI can be compared +// against users with new UI. +// New UI - Same sized group as Old UI for comparison. +const char kDefaultGroup[] = "NewUIRollout"; +const char kOldUIControlGroup[] = "OldUIControl"; +const char kNewUIExperimentGroup[] = "NewUIExperiment"; +// Experiment IDs defined for the above field trial groups. +const variations::VariationID kDefaultTrialID = 3314527; +const variations::VariationID kOldUIControlTrialID = 3314528; +const variations::VariationID kNewUIExperimentTrialID = 3314529; + +// Returns the percentage of users who are to be held back in "old" UI. The +// same percentage will be placed in a separate experiment group, but shown +// the "new" UI such that there will be two equal sized groups for comparing +// user behavior under "old" and "new" UI. Field trial configuration depends +// on release channel. +base::FieldTrial::Probability UIRefreshHoldbackPercent( + version_info::Channel channel) { + switch (channel) { + // Stable Channel has 3% of users held back with Old UI. + case version_info::Channel::STABLE: + case version_info::Channel::UNKNOWN: // Same as DEFAULT + return 3; + // Beta Channel is 50/50 split between Old UI and New UI. + case version_info::Channel::BETA: + return 50; + // Canary and Dev is 100% rolled out with New UI. + case version_info::Channel::CANARY: + case version_info::Channel::DEV: + return 0; + } +} + +// Field trials do not take effect until configurations have been downloaded. +// In order for field trials involving substantial UI changes to take effect +// at first run, the configuration must be pre-defined in client code. This +// sets up the field trial for UI Refresh. +void SetupUIRefreshFieldTrial(base::FeatureList* feature_list) { + // Field trial configuration pre-defined here for UI Refresh should match the + // configuration stored on the servers. Server-stored configuration will + // override this pre-defined configuration. + base::FieldTrial::Probability holdback = + UIRefreshHoldbackPercent(GetChannel()); + FirstRunFieldTrialConfig config("IOSUIRefreshRolloutWithHoldback"); + config.AddGroup(kDefaultGroup, kDefaultTrialID, + kTotalProbability - 2 * holdback); + config.AddGroup(kOldUIControlGroup, kOldUIControlTrialID, holdback); + config.AddGroup(kNewUIExperimentGroup, kNewUIExperimentTrialID, holdback); + + scoped_refptr<base::FieldTrial> trial( + base::FieldTrialList::FactoryGetFieldTrial( + config.trial_name(), kTotalProbability, kDefaultGroup, + config.expire_year(), config.expire_month(), + config.expire_day_of_month(), base::FieldTrial::ONE_TIME_RANDOMIZED, + /*default_group_number=*/nullptr)); + for (const auto& group : config.groups()) { + variations::AssociateGoogleVariationID(variations::GOOGLE_WEB_PROPERTIES, + config.trial_name(), group.name(), + group.variation()); + trial->AppendGroup(group.name(), group.percentage()); + } + + // Tests which group this user has been assigned to. Based on the group, + // sets the UI Refresh Phase 1 feature flag. + const std::string& chosen_group_name = trial->GetGroupNameWithoutActivation(); + base::FeatureList::OverrideState feature_state = + chosen_group_name == kOldUIControlGroup + ? base::FeatureList::OVERRIDE_DISABLE_FEATURE + : base::FeatureList::OVERRIDE_ENABLE_FEATURE; + feature_list->RegisterFieldTrialOverride(kUIRefreshPhase1.name, feature_state, + trial.get()); +} + +} // namespace + +void IOSChromeFieldTrials::SetupFeatureControllingFieldTrials( + bool has_seed, + base::FeatureList* feature_list) { + SetupUIRefreshFieldTrial(feature_list); +}
diff --git a/ios/chrome/browser/ios_chrome_field_trials.h b/ios/chrome/browser/ios_chrome_field_trials.h index f9cb9aa..68c2b05b 100644 --- a/ios/chrome/browser/ios_chrome_field_trials.h +++ b/ios/chrome/browser/ios_chrome_field_trials.h
@@ -19,7 +19,7 @@ void SetupFieldTrials() override {} void SetupFeatureControllingFieldTrials( bool has_seed, - base::FeatureList* feature_list) override {} + base::FeatureList* feature_list) override; private: DISALLOW_COPY_AND_ASSIGN(IOSChromeFieldTrials);
diff --git a/ios/chrome/browser/ios_first_run_field_trials.cc b/ios/chrome/browser/ios_first_run_field_trials.cc new file mode 100644 index 0000000..97fc02a --- /dev/null +++ b/ios/chrome/browser/ios_first_run_field_trials.cc
@@ -0,0 +1,41 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ios/chrome/browser/ios_first_run_field_trials.h" + +// FirstRunFieldTrialGroup +FirstRunFieldTrialGroup::FirstRunFieldTrialGroup( + const std::string& name, + variations::VariationID variation, + base::FieldTrial::Probability percentage) + : name_(name), variation_(variation), percentage_(percentage) {} + +FirstRunFieldTrialGroup::~FirstRunFieldTrialGroup() {} + +// FirstRunFieldTrialConfig +FirstRunFieldTrialConfig::FirstRunFieldTrialConfig( + const std::string& trial_name) + : FirstRunFieldTrialConfig(trial_name, + base::FieldTrialList::kNoExpirationYear, + 1, + 1) {} + +FirstRunFieldTrialConfig::FirstRunFieldTrialConfig( + const std::string& trial_name, + int year, + int month, + int day_of_month) + : trial_name_(trial_name), + expire_year_(year), + expire_month_(month), + expire_day_of_month_(day_of_month) {} + +FirstRunFieldTrialConfig::~FirstRunFieldTrialConfig() {} + +void FirstRunFieldTrialConfig::AddGroup( + const std::string& name, + variations::VariationID variation, + base::FieldTrial::Probability percentage) { + groups_.emplace_back(name, variation, percentage); +}
diff --git a/ios/chrome/browser/ios_first_run_field_trials.h b/ios/chrome/browser/ios_first_run_field_trials.h new file mode 100644 index 0000000..59162ea --- /dev/null +++ b/ios/chrome/browser/ios_first_run_field_trials.h
@@ -0,0 +1,75 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_IOS_FIRST_RUN_FIELD_TRIALS_H_ +#define IOS_CHROME_BROWSER_IOS_FIRST_RUN_FIELD_TRIALS_H_ + +#include <string> +#include <vector> + +#include "base/metrics/field_trial.h" +#include "components/variations/variations_associated_data.h" + +// Helper class defining a FieldTrial group. +class FirstRunFieldTrialGroup { + public: + FirstRunFieldTrialGroup(const std::string& name, + variations::VariationID variation, + base::FieldTrial::Probability percentage); + ~FirstRunFieldTrialGroup(); + + // Accessors for this FieldTrial group. + const std::string& name() const { return name_; } + variations::VariationID variation() const { return variation_; } + base::FieldTrial::Probability percentage() const { return percentage_; } + + private: + std::string name_; + variations::VariationID variation_; + base::FieldTrial::Probability percentage_; +}; + +// Helper class defining a FieldTrial configuration that will be valid at the +// time of Chrome First Run. Since server-provided FieldTrial configurations +// that need to be downloaded will not take effect until at least the second +// run, FieldTrials involving substantial UI changes that need to take effect +// at first run must be pre-defined in client code. +class FirstRunFieldTrialConfig { + public: + // Initializes with |trial_name| as the name of the FieldTrial with default + // duration. + FirstRunFieldTrialConfig(const std::string& trial_name); + // Initializes with |trial_name| as the name of the FieldTrial and one that + // ends on (year, month, day_of_month). + FirstRunFieldTrialConfig(const std::string& trial_name, + int year, + int month, + int day_of_month); + ~FirstRunFieldTrialConfig(); + + // Adds a new FieldTrial group of |name| with a probability of |percentage|. + // |variation| defines a server-side variation configuration. + void AddGroup(const std::string& name, + variations::VariationID variation, + base::FieldTrial::Probability percentage); + + // Returns a vector of FieldTrial groups for this FieldTrial configuration. + const std::vector<FirstRunFieldTrialGroup>& groups() const { return groups_; } + // Accessors for this FieldTrial. + const std::string& trial_name() { return trial_name_; } + int expire_year() { return expire_year_; } + int expire_month() { return expire_month_; } + int expire_day_of_month() { return expire_day_of_month_; } + + private: + std::string trial_name_; + std::vector<FirstRunFieldTrialGroup> groups_; + int expire_year_; + int expire_month_; + int expire_day_of_month_; + + DISALLOW_COPY_AND_ASSIGN(FirstRunFieldTrialConfig); +}; + +#endif // IOS_CHROME_BROWSER_IOS_FIRST_RUN_FIELD_TRIALS_H_
diff --git a/ios/chrome/browser/ui/history/history_table_view_controller.mm b/ios/chrome/browser/ui/history/history_table_view_controller.mm index e7f0f781..447abadc 100644 --- a/ios/chrome/browser/ui/history/history_table_view_controller.mm +++ b/ios/chrome/browser/ui/history/history_table_view_controller.mm
@@ -769,7 +769,7 @@ TableViewTextItem* entriesStatusItem = [[TableViewTextItem alloc] initWithType:ItemTypeEntriesStatus]; entriesStatusItem.text = statusMessage; - entriesStatusItem.textColor = TextItemColorBlack; + entriesStatusItem.textColor = [UIColor blackColor]; statusMessageItem = entriesStatusItem; } return statusMessageItem;
diff --git a/ios/chrome/browser/ui/recent_tabs/resources/show_history.imageset/show_history.png b/ios/chrome/browser/ui/recent_tabs/resources/show_history.imageset/show_history.png index fef5957..915840e7 100644 --- a/ios/chrome/browser/ui/recent_tabs/resources/show_history.imageset/show_history.png +++ b/ios/chrome/browser/ui/recent_tabs/resources/show_history.imageset/show_history.png Binary files differ
diff --git a/ios/chrome/browser/ui/recent_tabs/resources/show_history.imageset/show_history@2x.png b/ios/chrome/browser/ui/recent_tabs/resources/show_history.imageset/show_history@2x.png index 90e3616..8830c1d 100644 --- a/ios/chrome/browser/ui/recent_tabs/resources/show_history.imageset/show_history@2x.png +++ b/ios/chrome/browser/ui/recent_tabs/resources/show_history.imageset/show_history@2x.png Binary files differ
diff --git a/ios/chrome/browser/ui/recent_tabs/resources/show_history.imageset/show_history@3x.png b/ios/chrome/browser/ui/recent_tabs/resources/show_history.imageset/show_history@3x.png index 3dde2324..6ea710e 100644 --- a/ios/chrome/browser/ui/recent_tabs/resources/show_history.imageset/show_history@3x.png +++ b/ios/chrome/browser/ui/recent_tabs/resources/show_history.imageset/show_history@3x.png Binary files differ
diff --git a/ios/chrome/browser/ui/settings/table_cell_catalog_view_controller.mm b/ios/chrome/browser/ui/settings/table_cell_catalog_view_controller.mm index dae4dca..a3007240 100644 --- a/ios/chrome/browser/ui/settings/table_cell_catalog_view_controller.mm +++ b/ios/chrome/browser/ui/settings/table_cell_catalog_view_controller.mm
@@ -77,7 +77,7 @@ [[TableViewTextItem alloc] initWithType:ItemTypeText]; textItem.text = @"Simple Text Cell"; textItem.textAlignment = NSTextAlignmentCenter; - textItem.textColor = TextItemColorBlack; + textItem.textColor = [UIColor blackColor]; [model addItem:textItem toSectionWithIdentifier:SectionIdentifierText]; TableViewAccessoryItem* textAccessoryItem =
diff --git a/ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h b/ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h index 548ff5c2..ce33adeb 100644 --- a/ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h +++ b/ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h
@@ -34,4 +34,7 @@ // Spacing between text label and cell contentView. extern const CGFloat kTableViewLabelVerticalTopSpacing; +// Hex Value for light gray label text color. +extern const CGFloat kTableViewTextLabelColorLightGrey; + #endif // IOS_CHROME_BROWSER_UI_TABLE_VIEW_CELLS_TABLE_VIEW_CELLS_CONSTANTS_H_
diff --git a/ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.mm b/ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.mm index db56255..aafa55d 100644 --- a/ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.mm +++ b/ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.mm
@@ -17,3 +17,5 @@ const CGFloat kTableViewHighlightedCellColorAlpha = 0.5; const CGFloat kUseDefaultFontSize = 0.0; const CGFloat kTableViewLabelVerticalTopSpacing = 13.0; + +const CGFloat kTableViewTextLabelColorLightGrey = 0x6D6D72;
diff --git a/ios/chrome/browser/ui/table_view/cells/table_view_text_item.h b/ios/chrome/browser/ui/table_view/cells/table_view_text_item.h index 02dd658b..c9d9663 100644 --- a/ios/chrome/browser/ui/table_view/cells/table_view_text_item.h +++ b/ios/chrome/browser/ui/table_view/cells/table_view_text_item.h
@@ -9,22 +9,16 @@ #import "ios/chrome/browser/ui/table_view/cells/table_view_item.h" -// Defines the colors used for the cell text. -typedef NS_ENUM(UInt32, TextItemColor) { - TextItemColorLightGrey = 0x6D6D72, - TextItemColorBlack = 0x000000, -}; - // TableViewTextItem contains the model data for a TableViewTextCell. @interface TableViewTextItem : TableViewItem // Text Alignment for the cell's textLabel. Default is NSTextAlignmentLeft. @property(nonatomic, assign) NSTextAlignment textAlignment; -// Hex color for the cell's textLabel. Default is TextItemColorLightGrey. -// ChromeTableViewStyler's |cellTitleColor| takes precedence over the default -// color, but not over |textColor|. -@property(nonatomic, assign) TextItemColor textColor; +// UIColor for the cell's textLabel. Default is +// kTableViewTextLabelColorLightGrey. ChromeTableViewStyler's |cellTitleColor| +// takes precedence over the default color, but not over |textColor|. +@property(nonatomic, assign) UIColor* textColor; @property(nonatomic, readwrite, strong) NSString* text;
diff --git a/ios/chrome/browser/ui/table_view/cells/table_view_text_item.mm b/ios/chrome/browser/ui/table_view/cells/table_view_text_item.mm index 44b1d6c2..4e46f0d 100644 --- a/ios/chrome/browser/ui/table_view/cells/table_view_text_item.mm +++ b/ios/chrome/browser/ui/table_view/cells/table_view_text_item.mm
@@ -42,13 +42,13 @@ cell.textLabel.backgroundColor = styler.tableViewBackgroundColor; // This item's text color takes precedence over the global styler. // TODO(crbug.com/854249): redo the logic for this convoluted if clause. - if (self.textColor == TextItemColorBlack || - self.textColor == TextItemColorLightGrey) { - cell.textLabel.textColor = UIColorFromRGB(self.textColor); + if (self.textColor) { + cell.textLabel.textColor = self.textColor; } else if (styler.cellTitleColor) { cell.textLabel.textColor = styler.cellTitleColor; } else { - cell.textLabel.textColor = UIColorFromRGB(TextItemColorLightGrey); + cell.textLabel.textColor = + UIColorFromRGB(kTableViewTextLabelColorLightGrey); } cell.textLabel.textAlignment = self.textAlignment ? self.textAlignment : NSTextAlignmentLeft;
diff --git a/ios/chrome/browser/ui/table_view/cells/table_view_text_item_unittest.mm b/ios/chrome/browser/ui/table_view/cells/table_view_text_item_unittest.mm index 8218e00..ec99de0 100644 --- a/ios/chrome/browser/ui/table_view/cells/table_view_text_item_unittest.mm +++ b/ios/chrome/browser/ui/table_view/cells/table_view_text_item_unittest.mm
@@ -5,7 +5,9 @@ #import "ios/chrome/browser/ui/table_view/cells/table_view_text_item.h" #include "base/mac/foundation_util.h" +#import "ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h" #import "ios/chrome/browser/ui/table_view/chrome_table_view_styler.h" +#import "ios/chrome/browser/ui/uikit_ui_util.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest_mac.h" #include "testing/platform_test.h" @@ -43,8 +45,36 @@ ASSERT_TRUE([cell isMemberOfClass:[TableViewTextCell class]]); ChromeTableViewStyler* styler = [[ChromeTableViewStyler alloc] init]; + UIColor* testTextColor = [UIColor redColor]; + styler.cellTitleColor = testTextColor; + UIColor* testBackgroundColor = [UIColor blueColor]; + styler.tableViewBackgroundColor = testBackgroundColor; + [item configureCell:cell withStyler:styler]; + EXPECT_NSEQ(testBackgroundColor, cell.textLabel.backgroundColor); + EXPECT_NSEQ(testTextColor, cell.textLabel.textColor); +} + +TEST_F(TableViewTextItemTest, ConfigureLabelColorWithProperty) { + TableViewTextItem* item = [[TableViewTextItem alloc] initWithType:0]; + UIColor* textColor = [UIColor blueColor]; + item.textColor = textColor; + TableViewTextCell* cell = [[[item cellClass] alloc] init]; + ASSERT_TRUE([cell isMemberOfClass:[TableViewTextCell class]]); + + ChromeTableViewStyler* styler = [[ChromeTableViewStyler alloc] init]; UIColor* testColor = [UIColor redColor]; styler.tableViewBackgroundColor = testColor; [item configureCell:cell withStyler:styler]; - EXPECT_NSEQ(testColor, cell.textLabel.backgroundColor); + EXPECT_NSEQ(textColor, cell.textLabel.textColor); + EXPECT_NSNE(testColor, cell.textLabel.textColor); +} + +TEST_F(TableViewTextItemTest, ConfigureLabelColorWithDefaultColor) { + TableViewTextItem* item = [[TableViewTextItem alloc] initWithType:0]; + TableViewTextCell* cell = [[[item cellClass] alloc] init]; + ASSERT_TRUE([cell isMemberOfClass:[TableViewTextCell class]]); + ChromeTableViewStyler* styler = [[ChromeTableViewStyler alloc] init]; + [item configureCell:cell withStyler:styler]; + EXPECT_NSEQ(UIColorFromRGB(kTableViewTextLabelColorLightGrey), + cell.textLabel.textColor); }
diff --git a/ios/chrome/browser/ui/webui/url_keyed_metrics_ui.cc b/ios/chrome/browser/ui/webui/url_keyed_metrics_ui.cc index b909bbb..d9851e6 100644 --- a/ios/chrome/browser/ui/webui/url_keyed_metrics_ui.cc +++ b/ios/chrome/browser/ui/webui/url_keyed_metrics_ui.cc
@@ -55,6 +55,7 @@ void URLKeyedMetricsUIHTMLSource::StartDataRequest( const std::string& path, const web::URLDataSourceIOS::GotDataCallback& callback) { + // TODO(crbug.com/843181): Use GetStructuredData() instead. std::string data = ukm::debug::UkmDebugDataExtractor::GetHTMLData(GetUkmService()); callback.Run(base::RefCountedString::TakeString(&data));
diff --git a/ipc/ipc_message_utils.cc b/ipc/ipc_message_utils.cc index 01c37988..a0614240 100644 --- a/ipc/ipc_message_utils.cc +++ b/ipc/ipc_message_utils.cc
@@ -122,7 +122,7 @@ break; } case base::Value::Type::BINARY: { - m->WriteData(value->GetBlob().data(), + m->WriteData(reinterpret_cast<const char*>(value->GetBlob().data()), base::checked_cast<int>(value->GetBlob().size())); break; } @@ -572,16 +572,14 @@ #endif // defined(OS_POSIX) || defined(OS_FUCHSIA) #if defined(OS_ANDROID) -void ParamTraits<AHardwareBuffer*>::Write(base::Pickle* m, - const param_type& p) { - const bool is_valid = p != nullptr; +void ParamTraits<base::android::ScopedHardwareBufferHandle>::Write( + base::Pickle* m, + const param_type& p) { + const bool is_valid = p.is_valid(); WriteParam(m, is_valid); if (!is_valid) return; - // Assume ownership of the input AHardwareBuffer. - auto handle = base::android::ScopedHardwareBufferHandle::Adopt(p); - // We must keep a ref to the AHardwareBuffer alive until the receiver has // acquired its own reference. We do this by sending a message pipe handle // along with the buffer. When the receiver deserializes (or even if they @@ -590,19 +588,20 @@ mojo::MessagePipe tracking_pipe; m->WriteAttachment(new internal::MojoHandleAttachment( mojo::ScopedHandle::From(std::move(tracking_pipe.handle0)))); - WriteParam(m, - base::FileDescriptor(handle.SerializeAsFileDescriptor().release(), - true /* auto_close */)); + WriteParam(m, base::FileDescriptor(p.SerializeAsFileDescriptor().release(), + true /* auto_close */)); // Pass ownership of the input handle to our tracking pipe to keep the AHB // alive long enough to be deserialized by the receiver. - mojo::ScopeToMessagePipe(std::move(handle), std::move(tracking_pipe.handle1)); + mojo::ScopeToMessagePipe(std::move(const_cast<param_type&>(p)), + std::move(tracking_pipe.handle1)); } -bool ParamTraits<AHardwareBuffer*>::Read(const base::Pickle* m, - base::PickleIterator* iter, - param_type* r) { - *r = nullptr; +bool ParamTraits<base::android::ScopedHardwareBufferHandle>::Read( + const base::Pickle* m, + base::PickleIterator* iter, + param_type* r) { + *r = base::android::ScopedHardwareBufferHandle(); bool is_valid; if (!ReadParam(m, iter, &is_valid)) @@ -633,13 +632,15 @@ return false; *r = base::android::ScopedHardwareBufferHandle::DeserializeFromFileDescriptor( - std::move(scoped_fd)) - .Take(); + std::move(scoped_fd)); return true; } -void ParamTraits<AHardwareBuffer*>::Log(const param_type& p, std::string* l) { - l->append(base::StringPrintf("AHardwareBuffer(%p)", p)); +void ParamTraits<base::android::ScopedHardwareBufferHandle>::Log( + const param_type& p, + std::string* l) { + l->append(base::StringPrintf("base::android::ScopedHardwareBufferHandle(%p)", + p.get())); } #endif // defined(OS_ANDROID)
diff --git a/ipc/ipc_message_utils.h b/ipc/ipc_message_utils.h index 00a164a..99e0644d 100644 --- a/ipc/ipc_message_utils.h +++ b/ipc/ipc_message_utils.h
@@ -566,8 +566,9 @@ #if defined(OS_ANDROID) template <> -struct COMPONENT_EXPORT(IPC) ParamTraits<AHardwareBuffer*> { - typedef AHardwareBuffer* param_type; +struct COMPONENT_EXPORT(IPC) + ParamTraits<base::android::ScopedHardwareBufferHandle> { + typedef base::android::ScopedHardwareBufferHandle param_type; static void Write(base::Pickle* m, const param_type& p); static bool Read(const base::Pickle* m, base::PickleIterator* iter,
diff --git a/mash/BUILD.gn b/mash/BUILD.gn index 0116125..3d6f3f4b 100644 --- a/mash/BUILD.gn +++ b/mash/BUILD.gn
@@ -19,7 +19,6 @@ "//mash/example", "//mash/runner", "//mash/session", - "//mash/simple_wm", "//mash/task_viewer", ]
diff --git a/mash/catalog_viewer/catalog_viewer.cc b/mash/catalog_viewer/catalog_viewer.cc index 22518a6c..f666abf7 100644 --- a/mash/catalog_viewer/catalog_viewer.cc +++ b/mash/catalog_viewer/catalog_viewer.cc
@@ -225,7 +225,6 @@ views::AuraInit::InitParams params; params.connector = context()->connector(); params.identity = context()->identity(); - params.mode = views::AuraInit::Mode::AURA_MUS; aura_init_ = views::AuraInit::Create(params); if (!aura_init_) context()->QuitNow();
diff --git a/mash/example/BUILD.gn b/mash/example/BUILD.gn index f18ad9b..a210a3c 100644 --- a/mash/example/BUILD.gn +++ b/mash/example/BUILD.gn
@@ -12,7 +12,6 @@ "//mash/example/views_examples", "//mash/example/window_type_launcher", "//mash/runner", - "//mash/simple_wm", ] if (is_chromeos) { @@ -24,6 +23,5 @@ standalone_services = [ "//mash/example/views_examples:manifest", "//mash/example/window_type_launcher:manifest", - "//mash/simple_wm:manifest", ] }
diff --git a/mash/example/views_examples/views_examples.cc b/mash/example/views_examples/views_examples.cc index 0347849..9105a4db8 100644 --- a/mash/example/views_examples/views_examples.cc +++ b/mash/example/views_examples/views_examples.cc
@@ -34,7 +34,6 @@ views::AuraInit::InitParams params; params.connector = context()->connector(); params.identity = context()->identity(); - params.mode = views::AuraInit::Mode::AURA_MUS; aura_init_ = views::AuraInit::Create(params); if (!aura_init_) context()->QuitNow();
diff --git a/mash/example/window_type_launcher/window_type_launcher.cc b/mash/example/window_type_launcher/window_type_launcher.cc index 609c009..50ba6234 100644 --- a/mash/example/window_type_launcher/window_type_launcher.cc +++ b/mash/example/window_type_launcher/window_type_launcher.cc
@@ -456,7 +456,6 @@ views::AuraInit::InitParams params; params.connector = context()->connector(); params.identity = context()->identity(); - params.mode = views::AuraInit::Mode::AURA_MUS; aura_init_ = views::AuraInit::Create(params); if (!aura_init_) context()->QuitNow();
diff --git a/mash/simple_wm/BUILD.gn b/mash/simple_wm/BUILD.gn deleted file mode 100644 index b1fb47a..0000000 --- a/mash/simple_wm/BUILD.gn +++ /dev/null
@@ -1,66 +0,0 @@ -# Copyright 2016 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//build/config/ui.gni") -import("//services/service_manager/public/cpp/service.gni") -import("//services/service_manager/public/service_manifest.gni") -import("//tools/grit/repack.gni") - -service("simple_wm") { - testonly = true - - sources = [ - "main.cc", - ] - - deps = [ - ":lib", - "//base", - "//services/service_manager/public/cpp", - "//ui/views/mus:for_mojo_application", - ] - - resources = [ "$root_out_dir/views_mus_resources.pak" ] -} - -source_set("lib") { - testonly = true - sources = [ - "move_event_handler.cc", - "move_event_handler.h", - "move_loop.cc", - "move_loop.h", - "simple_wm.cc", - "simple_wm.h", - ] - - deps = [ - "//base", - "//services/service_manager/public/cpp", - "//services/ui/public/cpp", - "//services/ui/public/interfaces", - "//ui/aura", - "//ui/aura:test_support", - "//ui/display", - "//ui/display:test_support", - "//ui/gfx/geometry/mojo", - "//ui/views", - "//ui/views/mus:mus", - "//ui/wm", - "//ui/wm/public", - ] - - public_deps = [ - "//skia", # Due to use of Sk types in service header. - ] - - data_deps = [ - "//services/ui", - ] -} - -service_manifest("manifest") { - name = "simple_wm" - source = "manifest.json" -}
diff --git a/mash/simple_wm/OWNERS b/mash/simple_wm/OWNERS deleted file mode 100644 index 59dfd4b3..0000000 --- a/mash/simple_wm/OWNERS +++ /dev/null
@@ -1,2 +0,0 @@ -per-file manifest.json=set noparent -per-file manifest.json=file://ipc/SECURITY_OWNERS
diff --git a/mash/simple_wm/main.cc b/mash/simple_wm/main.cc deleted file mode 100644 index 42311306..0000000 --- a/mash/simple_wm/main.cc +++ /dev/null
@@ -1,12 +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 "mash/simple_wm/simple_wm.h" -#include "services/service_manager/public/c/main.h" -#include "services/service_manager/public/cpp/service_runner.h" - -MojoResult ServiceMain(MojoHandle service_request_handle) { - service_manager::ServiceRunner runner(new simple_wm::SimpleWM); - return runner.Run(service_request_handle); -}
diff --git a/mash/simple_wm/manifest.json b/mash/simple_wm/manifest.json deleted file mode 100644 index d0f38b6..0000000 --- a/mash/simple_wm/manifest.json +++ /dev/null
@@ -1,12 +0,0 @@ -{ - "name": "simple_wm", - "display_name": "Simple Window Manager", - "interface_provider_specs": { - "service_manager:connector": { - "requires": { - "*": [ "app" ], - "ui": [ "window_manager" ] - } - } - } -}
diff --git a/mash/simple_wm/move_event_handler.cc b/mash/simple_wm/move_event_handler.cc deleted file mode 100644 index 4e1d58aa..0000000 --- a/mash/simple_wm/move_event_handler.cc +++ /dev/null
@@ -1,122 +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 "mash/simple_wm/move_event_handler.h" - -#include "mash/simple_wm/move_loop.h" -#include "services/ui/public/interfaces/cursor/cursor.mojom.h" -#include "ui/aura/mus/window_port_mus.h" -#include "ui/aura/window.h" -#include "ui/aura/window_delegate.h" -#include "ui/base/cursor/cursor.h" -#include "ui/base/hit_test.h" -#include "ui/events/event.h" - -namespace simple_wm { -namespace { - -ui::CursorType CursorForWindowComponent(int window_component) { - switch (window_component) { - case HTBOTTOM: - return ui::CursorType::kSouthResize; - case HTBOTTOMLEFT: - return ui::CursorType::kSouthWestResize; - case HTBOTTOMRIGHT: - return ui::CursorType::kSouthEastResize; - case HTLEFT: - return ui::CursorType::kWestResize; - case HTRIGHT: - return ui::CursorType::kEastResize; - case HTTOP: - return ui::CursorType::kNorthResize; - case HTTOPLEFT: - return ui::CursorType::kNorthWestResize; - case HTTOPRIGHT: - return ui::CursorType::kNorthEastResize; - default: - return ui::CursorType::kNull; - } -} - -} // namespace - -MoveEventHandler::MoveEventHandler(aura::Window* window) - : window_(window) { - window_->AddObserver(this); - window_->AddPreTargetHandler(this); -} - -MoveEventHandler::~MoveEventHandler() { - Detach(); -} - -void MoveEventHandler::ProcessLocatedEvent(ui::LocatedEvent* event) { - const bool had_move_loop = move_loop_.get() != nullptr; - DCHECK(event->IsMouseEvent() || event->IsTouchEvent()); - - // This event handler can receive mouse events like ET_MOUSE_CAPTURE_CHANGED - // that cannot be converted to PointerEvents. Ignore them because they aren't - // needed for move handling. - if (!ui::PointerEvent::CanConvertFrom(*event)) - return; - - // TODO(moshayedi): no need for this once MoveEventHandler directly receives - // pointer events. - std::unique_ptr<ui::PointerEvent> pointer_event; - if (event->IsMouseEvent()) - pointer_event.reset(new ui::PointerEvent(*event->AsMouseEvent())); - else - pointer_event.reset(new ui::PointerEvent(*event->AsTouchEvent())); - - if (move_loop_) { - if (move_loop_->Move(*pointer_event.get()) == MoveLoop::DONE) - move_loop_.reset(); - } else if (pointer_event->type() == ui::ET_POINTER_DOWN) { - const int ht_location = - GetNonClientComponentForEvent(pointer_event.get()); - if (ht_location != HTNOWHERE) - move_loop_ = MoveLoop::Create(window_, ht_location, *pointer_event.get()); - } else if (pointer_event->type() == ui::ET_POINTER_MOVED) { - const int ht_location = GetNonClientComponentForEvent(pointer_event.get()); - aura::WindowPortMus::Get(window_)->SetCursor( - ui::CursorData(CursorForWindowComponent(ht_location))); - } - if (had_move_loop || move_loop_) - event->SetHandled(); -} - -int MoveEventHandler::GetNonClientComponentForEvent( - const ui::LocatedEvent* event) { - return window_->delegate()->GetNonClientComponent(event->location()); -} - -void MoveEventHandler::Detach() { - window_->RemoveObserver(this); - window_->RemovePreTargetHandler(this); - window_ = nullptr; -} - -void MoveEventHandler::OnMouseEvent(ui::MouseEvent* event) { - ProcessLocatedEvent(event); -} - -void MoveEventHandler::OnTouchEvent(ui::TouchEvent* event) { - ProcessLocatedEvent(event); -} - -void MoveEventHandler::OnCancelMode(ui::CancelModeEvent* event) { - if (!move_loop_) - return; - - move_loop_->Revert(); - move_loop_.reset(); - event->SetHandled(); -} - -void MoveEventHandler::OnWindowDestroying(aura::Window* window) { - DCHECK_EQ(window_, window); - Detach(); -} - -} // namespace simple_wm
diff --git a/mash/simple_wm/move_event_handler.h b/mash/simple_wm/move_event_handler.h deleted file mode 100644 index c6638bb..0000000 --- a/mash/simple_wm/move_event_handler.h +++ /dev/null
@@ -1,55 +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. - -#ifndef MASH_SIMPLE_WM_MOVE_EVENT_HANDLER_H_ -#define MASH_SIMPLE_WM_MOVE_EVENT_HANDLER_H_ - -#include <memory> - -#include "base/macros.h" -#include "ui/aura/window_observer.h" -#include "ui/events/event_handler.h" - -namespace aura { -class Window; -} - -namespace ui { -class LocatedEvent; -} - -namespace simple_wm { - -class MoveLoop; - -// EventHandler attached to the root. Starts a MoveLoop as necessary. -class MoveEventHandler : public ui::EventHandler, public aura::WindowObserver { - public: - explicit MoveEventHandler(aura::Window* window); - ~MoveEventHandler() override; - - private: - void ProcessLocatedEvent(ui::LocatedEvent* event); - int GetNonClientComponentForEvent(const ui::LocatedEvent* event); - - // Removes observer and EventHandler installed on |window_|. - void Detach(); - - // Overridden from ui::EventHandler: - void OnMouseEvent(ui::MouseEvent* event) override; - void OnTouchEvent(ui::TouchEvent* event) override; - void OnCancelMode(ui::CancelModeEvent* event) override; - - // Overridden from aura::WindowObserver: - void OnWindowDestroying(aura::Window* window) override; - - aura::Window* window_; - std::unique_ptr<MoveLoop> move_loop_; - - DISALLOW_COPY_AND_ASSIGN(MoveEventHandler); -}; - -} // namespace simple_wm - -#endif // MASH_SIMPLE_WM_MOVE_EVENT_HANDLER_H_
diff --git a/mash/simple_wm/move_loop.cc b/mash/simple_wm/move_loop.cc deleted file mode 100644 index 1336e34d..0000000 --- a/mash/simple_wm/move_loop.cc +++ /dev/null
@@ -1,238 +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 "mash/simple_wm/move_loop.h" - -#include "base/auto_reset.h" -#include "base/memory/ptr_util.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/window.h" -#include "ui/base/hit_test.h" -#include "ui/base/ui_base_types.h" -#include "ui/events/event.h" -#include "ui/gfx/geometry/point_conversions.h" -#include "ui/gfx/geometry/rect.h" - -namespace simple_wm { -namespace { - -int MouseOnlyEventFlags(int flags) { - return flags & (ui::EF_LEFT_MOUSE_BUTTON | ui::EF_MIDDLE_MOUSE_BUTTON | - ui::EF_RIGHT_MOUSE_BUTTON); -} - -} // namespace - -MoveLoop::~MoveLoop() { - if (target_) - target_->RemoveObserver(this); -} - -// static -std::unique_ptr<MoveLoop> MoveLoop::Create(aura::Window* target, - int ht_location, - const ui::PointerEvent& event) { - DCHECK_EQ(event.type(), ui::ET_POINTER_DOWN); - // Start a move on left mouse, or any other type of pointer. - if (event.IsMousePointerEvent() && - MouseOnlyEventFlags(event.flags()) != ui::EF_LEFT_MOUSE_BUTTON) { - return nullptr; - } - - Type type; - HorizontalLocation h_loc; - VerticalLocation v_loc; - if (!DetermineType(ht_location, &type, &h_loc, &v_loc)) - return nullptr; - - return base::WrapUnique(new MoveLoop(target, event, type, h_loc, v_loc)); -} - -MoveLoop::MoveResult MoveLoop::Move(const ui::PointerEvent& event) { - switch (event.type()) { - case ui::ET_POINTER_CANCELLED: - if (event.pointer_details().id == pointer_id_) { - if (target_) - Revert(); - return MoveResult::DONE; - } - return MoveResult::CONTINUE; - - case ui::ET_POINTER_MOVED: - if (target_ && event.pointer_details().id == pointer_id_) - MoveImpl(event); - return MoveResult::CONTINUE; - - case ui::ET_POINTER_UP: - if (event.pointer_details().id == pointer_id_) { - // TODO(sky): need to support changed_flags. - if (target_) - MoveImpl(event); - return MoveResult::DONE; - } - return MoveResult::CONTINUE; - - default: - break; - } - return MoveResult::CONTINUE; -} - -void MoveLoop::Revert() { - if (!target_) - return; - - base::AutoReset<bool> resetter(&changing_bounds_, true); - target_->SetBounds(initial_window_bounds_); -} - -MoveLoop::MoveLoop(aura::Window* target, - const ui::PointerEvent& event, - Type type, - HorizontalLocation h_loc, - VerticalLocation v_loc) - : target_(target), - type_(type), - h_loc_(h_loc), - v_loc_(v_loc), - pointer_id_(event.pointer_details().id), - initial_event_screen_location_(event.root_location()), - initial_window_bounds_(target->bounds()), - initial_user_set_bounds_(target->bounds()), - changing_bounds_(false) { - target->AddObserver(this); -} - -// static -bool MoveLoop::DetermineType(int ht_location, - Type* type, - HorizontalLocation* h_loc, - VerticalLocation* v_loc) { - *h_loc = HorizontalLocation::OTHER; - *v_loc = VerticalLocation::OTHER; - switch (ht_location) { - case HTCAPTION: - *type = Type::MOVE; - *v_loc = VerticalLocation::TOP; - return true; - case HTTOPLEFT: - *type = Type::RESIZE; - *v_loc = VerticalLocation::TOP; - *h_loc = HorizontalLocation::LEFT; - return true; - case HTTOP: - *type = Type::RESIZE; - *v_loc = VerticalLocation::TOP; - return true; - case HTTOPRIGHT: - *type = Type::RESIZE; - *v_loc = VerticalLocation::TOP; - *h_loc = HorizontalLocation::RIGHT; - return true; - case HTRIGHT: - *type = Type::RESIZE; - *h_loc = HorizontalLocation::RIGHT; - return true; - case HTBOTTOMRIGHT: - *type = Type::RESIZE; - *v_loc = VerticalLocation::BOTTOM; - *h_loc = HorizontalLocation::RIGHT; - return true; - case HTBOTTOM: - *type = Type::RESIZE; - *v_loc = VerticalLocation::BOTTOM; - return true; - case HTBOTTOMLEFT: - *type = Type::RESIZE; - *v_loc = VerticalLocation::BOTTOM; - *h_loc = HorizontalLocation::LEFT; - return true; - case HTLEFT: - *type = Type::RESIZE; - *h_loc = HorizontalLocation::LEFT; - return true; - default: - break; - } - return false; -} - -void MoveLoop::MoveImpl(const ui::PointerEvent& event) { - ui::WindowShowState show_state = - target_->GetProperty(aura::client::kShowStateKey); - // TODO(beng): figure out if there might not be another place to put this, - // perhaps prior to move loop creation. - if (show_state == ui::SHOW_STATE_MAXIMIZED) { - base::AutoReset<bool> resetter(&changing_bounds_, true); - target_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); - gfx::Rect restored_bounds = - *target_->GetProperty(aura::client::kRestoreBoundsKey); - // TODO(beng): Not just enough to adjust width and height, probably also - // need to take some action to recenter the window relative to - // the pointer position within the titlebar. - initial_window_bounds_.set_width(restored_bounds.width()); - initial_window_bounds_.set_height(restored_bounds.height()); - } - const gfx::Vector2d delta = - event.root_location() - initial_event_screen_location_; - const gfx::Rect new_bounds(DetermineBoundsFromDelta(delta)); - base::AutoReset<bool> resetter(&changing_bounds_, true); - target_->SetBounds(new_bounds); -} - -void MoveLoop::Cancel() { - target_->RemoveObserver(this); - target_ = nullptr; -} - -gfx::Rect MoveLoop::DetermineBoundsFromDelta(const gfx::Vector2d& delta) { - if (type_ == Type::MOVE) { - return gfx::Rect(initial_window_bounds_.origin() + delta, - initial_window_bounds_.size()); - } - - // TODO(sky): support better min sizes, make sure doesn't get bigger than - // screen and max. Also make sure keep some portion on screen. - gfx::Rect bounds(initial_window_bounds_); - if (h_loc_ == HorizontalLocation::LEFT) { - const int x = std::min(bounds.right() - 1, bounds.x() + delta.x()); - const int width = bounds.right() - x; - bounds.set_x(x); - bounds.set_width(width); - } else if (h_loc_ == HorizontalLocation::RIGHT) { - bounds.set_width(std::max(1, bounds.width() + delta.x())); - } - - if (v_loc_ == VerticalLocation::TOP) { - const int y = std::min(bounds.bottom() - 1, bounds.y() + delta.y()); - const int height = bounds.bottom() - y; - bounds.set_y(y); - bounds.set_height(height); - } else if (v_loc_ == VerticalLocation::BOTTOM) { - bounds.set_height(std::max(1, bounds.height() + delta.y())); - } - - return bounds; -} - -void MoveLoop::OnWindowHierarchyChanged(const HierarchyChangeParams& params) { - if (params.target == target_) - Cancel(); -} - -void MoveLoop::OnWindowBoundsChanged(aura::Window* window, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds, - ui::PropertyChangeReason reason) { - DCHECK_EQ(window, target_); - if (!changing_bounds_) - Cancel(); -} - -void MoveLoop::OnWindowVisibilityChanged(aura::Window* window, bool visible) { - DCHECK_EQ(window, target_); - Cancel(); -} - -} // namespace simple_wm
diff --git a/mash/simple_wm/move_loop.h b/mash/simple_wm/move_loop.h deleted file mode 100644 index dd115bd..0000000 --- a/mash/simple_wm/move_loop.h +++ /dev/null
@@ -1,124 +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. - -#ifndef MASH_SIMPLE_WM_MOVE_LOOP_H_ -#define MASH_SIMPLE_WM_MOVE_LOOP_H_ - -#include <stdint.h> -#include <memory> - -#include "base/macros.h" -#include "ui/aura/window_observer.h" -#include "ui/gfx/geometry/point.h" -#include "ui/gfx/geometry/rect.h" - -namespace ui { -class PointerEvent; -} - -namespace simple_wm { - -// MoveLoop is responsible for moving/resizing windows. -class MoveLoop : public aura::WindowObserver { - public: - enum MoveResult { - // The move is still ongoing. - CONTINUE, - // The move is done and the MoveLoop should be destroyed. - DONE, - }; - - enum class HorizontalLocation { - LEFT, - RIGHT, - OTHER, - }; - - enum class VerticalLocation { - TOP, - BOTTOM, - OTHER, - }; - - ~MoveLoop() override; - - // If a move/resize loop should occur for the specified parameters creates - // and returns a new MoveLoop. All events should be funneled to the MoveLoop - // until done (Move()). |ht_location| is one of the constants defined by - // HitTestCompat. - static std::unique_ptr<MoveLoop> Create(aura::Window* target, - int ht_location, - const ui::PointerEvent& event); - - // Processes an event for a move/resize loop. - MoveResult Move(const ui::PointerEvent& event); - - // If possible reverts any changes made during the move loop. - void Revert(); - - private: - enum class Type { - MOVE, - RESIZE, - }; - - MoveLoop(aura::Window* target, - const ui::PointerEvent& event, - Type type, - HorizontalLocation h_loc, - VerticalLocation v_loc); - - // Determines the type of move from the specified HitTestCompat value. - // Returns true if a move/resize should occur. - static bool DetermineType(int ht_location, - Type* type, - HorizontalLocation* h_loc, - VerticalLocation* v_loc); - - // Does the actual move/resize. - void MoveImpl(const ui::PointerEvent& event); - - // Cancels the loop. This sets |target_| to null and removes the observer. - // After this the MoveLoop is still ongoing and won't stop until the - // appropriate event is received. - void Cancel(); - - gfx::Rect DetermineBoundsFromDelta(const gfx::Vector2d& delta); - - // aura::WindowObserver: - void OnWindowHierarchyChanged(const HierarchyChangeParams& params) override; - void OnWindowBoundsChanged(aura::Window* window, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds, - ui::PropertyChangeReason reason) override; - void OnWindowVisibilityChanged(aura::Window* window, bool visible) override; - - // The window this MoveLoop is acting on. |target_| is set to null if the - // window unexpectedly changes while the move is in progress. - aura::Window* target_; - - const Type type_; - const HorizontalLocation h_loc_; - const VerticalLocation v_loc_; - - // The id of the pointer that triggered the move. - const int32_t pointer_id_; - - // Location of the event (in screen coordinates) that triggered the move. - const gfx::Point initial_event_screen_location_; - - // Original bounds of the window. - gfx::Rect initial_window_bounds_; - const gfx::Rect initial_user_set_bounds_; - - // Set to true when MoveLoop changes the bounds of |target_|. The move is - // canceled if the bounds change unexpectedly during the move. - bool changing_bounds_; - - DISALLOW_COPY_AND_ASSIGN(MoveLoop); -}; - -} // namespace simple_wm - -#endif // MASH_SIMPLE_WM_MOVE_LOOP_H_
diff --git a/mash/simple_wm/simple_wm.cc b/mash/simple_wm/simple_wm.cc deleted file mode 100644 index 6370eac..0000000 --- a/mash/simple_wm/simple_wm.cc +++ /dev/null
@@ -1,610 +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 "mash/simple_wm/simple_wm.h" - -#include <memory> - -#include "base/observer_list.h" -#include "base/strings/utf_string_conversions.h" -#include "mash/simple_wm/move_event_handler.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/layout_manager.h" -#include "ui/display/screen_base.h" -#include "ui/gfx/canvas.h" -#include "ui/gfx/geometry/mojo/geometry.mojom.h" -#include "ui/views/controls/button/md_text_button.h" -#include "ui/views/controls/label.h" -#include "ui/views/mus/aura_init.h" -#include "ui/views/mus/mus_client.h" -#include "ui/views/widget/native_widget_aura.h" -#include "ui/views/widget/widget.h" -#include "ui/views/widget/widget_delegate.h" -#include "ui/wm/core/focus_controller.h" - -namespace simple_wm { - -namespace { - -const int kNonClientTopHeight = 24; -const int kNonClientSize = 5; -const int kNonClientMaximizedTopOverlap = 4; - -} // namespace - -class SimpleWM::WindowListModelObserver { - public: - virtual void OnWindowAddedOrRemoved() = 0; - virtual void OnWindowTitleChanged(size_t index, - const base::string16& title) = 0; -}; - -class SimpleWM::WindowListModel : public aura::WindowObserver { - public: - explicit WindowListModel(aura::Window* window_container) - : window_container_(window_container) { - window_container_->AddObserver(this); - } - ~WindowListModel() override { - window_container_->RemoveObserver(this); - for (auto* window : windows_) - window->RemoveObserver(this); - } - - size_t GetSize() const { - return windows_.size(); - } - base::string16 GetTitle(size_t index) const { - return windows_.at(index)->GetTitle(); - } - aura::Window* GetWindow(size_t index) const { - return windows_.at(index); - } - - void AddObserver(WindowListModelObserver* observer) { - observers_.AddObserver(observer); - } - void RemoveObserver(WindowListModelObserver* observer) { - observers_.RemoveObserver(observer); - } - - private: - // aura::WindowObserver: - void OnWindowAdded(aura::Window* window) override { - if (window->parent() == window_container_) - AddWindow(window); - for (auto& observer : observers_) - observer.OnWindowAddedOrRemoved(); - } - void OnWillRemoveWindow(aura::Window* window) override { - window->RemoveObserver(this); - for (auto& observer : observers_) - observer.OnWindowAddedOrRemoved(); - auto it = std::find(windows_.begin(), windows_.end(), window); - DCHECK(it != windows_.end()); - windows_.erase(it); - } - void OnWindowTitleChanged(aura::Window* window) override { - auto it = std::find(windows_.begin(), windows_.end(), window); - size_t index = it - windows_.begin(); - for (auto& observer : observers_) - observer.OnWindowTitleChanged(index, window->GetTitle()); - } - - void AddWindow(aura::Window* window) { - window->AddObserver(this); - auto it = std::find(windows_.begin(), windows_.end(), window); - DCHECK(it == windows_.end()); - windows_.push_back(window); - } - - aura::Window* window_container_; - std::vector<aura::Window*> windows_; - base::ObserverList<WindowListModelObserver> observers_; - - DISALLOW_COPY_AND_ASSIGN(WindowListModel); -}; - -class SimpleWM::WindowListView : public views::WidgetDelegateView, - public views::ButtonListener, - public SimpleWM::WindowListModelObserver { - public: - using ActivateCallback = base::Callback<void(aura::Window*)>; - - WindowListView(WindowListModel* model, ActivateCallback activate_callback) - : model_(model), activate_callback_(activate_callback) { - model_->AddObserver(this); - Rebuild(); - } - ~WindowListView() override { - model_->RemoveObserver(this); - } - - static const int kButtonSpacing = 5; - - // views::View - void Layout() override { - int x_offset = kButtonSpacing; - for (int i = 0; i < child_count(); ++i) { - View* v = child_at(i); - gfx::Size ps = v->GetPreferredSize(); - gfx::Rect bounds(x_offset, kButtonSpacing, ps.width(), ps.height()); - v->SetBoundsRect(bounds); - x_offset = bounds.right() + kButtonSpacing; - } - } - void OnPaint(gfx::Canvas* canvas) override { - canvas->DrawColor(SK_ColorLTGRAY); - gfx::Rect stroke_bounds = GetLocalBounds(); - stroke_bounds.set_height(1); - canvas->FillRect(stroke_bounds, SK_ColorDKGRAY); - } - gfx::Size CalculatePreferredSize() const override { - std::unique_ptr<views::MdTextButton> measure_button( - views::MdTextButton::Create(nullptr, base::UTF8ToUTF16("Sample"))); - int height = - measure_button->GetPreferredSize().height() + 2 * kButtonSpacing; - return gfx::Size(0, height); - } - - private: - // views::ButtonListener: - void ButtonPressed(views::Button* sender, const ui::Event& event) override { - activate_callback_.Run( - model_->GetWindow(static_cast<size_t>(sender->tag()))); - } - - // WindowListModelObserver: - void OnWindowAddedOrRemoved() override { - Rebuild(); - } - void OnWindowTitleChanged(size_t index, - const base::string16& new_title) override { - views::MdTextButton* label = - static_cast<views::MdTextButton*>(child_at(static_cast<int>(index))); - label->SetText(new_title); - Layout(); - } - - void Rebuild() { - RemoveAllChildViews(true); - - size_t size = model_->GetSize(); - for (size_t i = 0; i < size; ++i) { - base::string16 title = model_->GetTitle(i); - if (title.empty()) - title = base::UTF8ToUTF16("Untitled"); - views::MdTextButton* button = views::MdTextButton::Create(this, title); - button->set_tag(static_cast<int>(i)); - AddChildView(button); - } - Layout(); - } - - WindowListModel* model_; - ActivateCallback activate_callback_; - - DISALLOW_COPY_AND_ASSIGN(WindowListView); -}; - -class SimpleWM::FrameView : public views::WidgetDelegateView, - public aura::WindowObserver { - public: - explicit FrameView(aura::Window* client_window) - : client_window_(client_window) { - client_window_->AddObserver(this); - } - ~FrameView() override = default; - - void Init() { - move_event_handler_ = - std::make_unique<MoveEventHandler>(GetWidget()->GetNativeWindow()); - } - - private: - // views::WidgetDelegateView: - base::string16 GetWindowTitle() const override { - base::string16* title_from_property = - client_window_->GetProperty(aura::client::kTitleKey); - base::string16 title = title_from_property ? *title_from_property - : base::UTF8ToUTF16("(Window)"); - // TODO(beng): quick hack to cause WindowObserver::OnWindowTitleChanged to - // fire. - GetWidget()->GetNativeWindow()->SetTitle(title); - return title; - } - void Layout() override { - // Client offsets are applied automatically by the window service. - gfx::Rect parent_bounds = GetWidget()->GetNativeWindow()->bounds(); - parent_bounds.set_origin(gfx::Point()); - - if (GetWidget()->IsMaximized()) { - parent_bounds.Inset(-kNonClientSize, -kNonClientMaximizedTopOverlap, - -kNonClientSize, -kNonClientSize); - } - - client_window_->SetBounds(parent_bounds); - } - bool CanMaximize() const override { - return (client_window_->GetProperty(aura::client::kResizeBehaviorKey) & - ui::mojom::kResizeBehaviorCanMaximize) != 0; - } - - bool CanMinimize() const override { - return (client_window_->GetProperty(aura::client::kResizeBehaviorKey) & - ui::mojom::kResizeBehaviorCanMinimize) != 0; - } - - bool CanResize() const override { - return (client_window_->GetProperty(aura::client::kResizeBehaviorKey) & - ui::mojom::kResizeBehaviorCanResize) != 0; - } - - // aura::WindowObserver: - void OnWindowPropertyChanged(aura::Window* window, const void* key, - intptr_t old) override { - if (key == aura::client::kTitleKey) - GetWidget()->UpdateWindowTitle(); - else if (key == aura::client::kResizeBehaviorKey) - GetWidget()->non_client_view()->frame_view()->Layout(); - } - - aura::Window* client_window_; - std::unique_ptr<MoveEventHandler> move_event_handler_; - - DISALLOW_COPY_AND_ASSIGN(FrameView); -}; - -class SimpleWM::WorkspaceLayoutManager : public aura::WindowObserver { - public: - explicit WorkspaceLayoutManager(aura::Window* window_root) - : window_root_(window_root) {} - ~WorkspaceLayoutManager() override = default; - - private: - // aura::WindowObserver: - void OnWindowPropertyChanged(aura::Window* window, const void* key, - intptr_t old) override { - if (key == aura::client::kShowStateKey) { - ui::WindowShowState show_state = - window->GetProperty(aura::client::kShowStateKey); - switch (show_state) { - case ui::SHOW_STATE_NORMAL: - window->Show(); - window->SetBounds( - *window->GetProperty(aura::client::kRestoreBoundsKey)); - break; - case ui::SHOW_STATE_MINIMIZED: - window->Hide(); - break; - case ui::SHOW_STATE_MAXIMIZED: - window->Show(); - window->SetProperty(aura::client::kRestoreBoundsKey, - new gfx::Rect(window->bounds())); - window->SetBounds(gfx::Rect(window_root_->bounds().size())); - break; - default: - NOTREACHED(); - break; - } - } - } - void OnWindowDestroying(aura::Window* window) override { - window->RemoveObserver(this); - } - - aura::Window* window_root_; - - DISALLOW_COPY_AND_ASSIGN(WorkspaceLayoutManager); -}; - -class SimpleWM::DisplayLayoutManager : public aura::LayoutManager { - public: - DisplayLayoutManager(aura::Window* display_root, - aura::Window* window_root, - SimpleWM::WindowListView* window_list_view) - : display_root_(display_root), - window_root_(window_root), - window_list_view_(window_list_view) {} - ~DisplayLayoutManager() override = default; - - private: - // aura::LayoutManager: - void OnWindowResized() override {} - void OnWindowAddedToLayout(aura::Window* child) override { - Layout(); - } - void OnWillRemoveWindowFromLayout(aura::Window* child) override {} - void OnWindowRemovedFromLayout(aura::Window* child) override {} - void OnChildWindowVisibilityChanged(aura::Window* child, - bool visible) override {} - void SetChildBounds(aura::Window* child, - const gfx::Rect& requested_bounds) override { - SetChildBoundsDirect(child, requested_bounds); - } - - void Layout() { - gfx::Size ps = window_list_view_->GetPreferredSize(); - gfx::Rect bounds = display_root_->bounds(); - gfx::Rect window_root_bounds = bounds; - window_root_bounds.set_height(window_root_bounds.height() - ps.height()); - window_root_->SetBounds(window_root_bounds); - gfx::Rect window_list_view_bounds = bounds; - window_list_view_bounds.set_height(ps.height()); - window_list_view_bounds.set_y(window_root_bounds.bottom()); - window_list_view_->GetWidget()->SetBounds(window_list_view_bounds); - } - - aura::Window* display_root_; - aura::Window* window_root_; - SimpleWM::WindowListView* window_list_view_; - - DISALLOW_COPY_AND_ASSIGN(DisplayLayoutManager); -}; - -//////////////////////////////////////////////////////////////////////////////// -// SimpleWM, public: - -SimpleWM::SimpleWM() = default; - -SimpleWM::~SimpleWM() { - // WindowTreeHost uses state from WindowTreeClient, so destroy it first. - window_tree_host_.reset(); - - // WindowTreeClient destruction may callback to us. - window_tree_client_.reset(); - - display::Screen::SetScreenInstance(nullptr); -} - -//////////////////////////////////////////////////////////////////////////////// -// SimpleWM, service_manager::Service implementation: - -void SimpleWM::OnStart() { - CHECK(!started_); - started_ = true; - screen_ = std::make_unique<display::ScreenBase>(); - display::Screen::SetScreenInstance(screen_.get()); - views::AuraInit::InitParams params; - params.connector = context()->connector(); - params.identity = context()->identity(); - params.mode = views::AuraInit::Mode::AURA_MUS_WINDOW_MANAGER; - aura_init_ = views::AuraInit::Create(params); - if (!aura_init_) { - context()->QuitNow(); - return; - } - window_tree_client_ = aura::WindowTreeClient::CreateForWindowManager( - context()->connector(), this, this); - aura::Env::GetInstance()->SetWindowTreeClient(window_tree_client_.get()); -} - -//////////////////////////////////////////////////////////////////////////////// -// SimpleWM, aura::WindowTreeClientDelegate implementation: - -void SimpleWM::OnEmbed( - std::unique_ptr<aura::WindowTreeHostMus> window_tree_host) { - // WindowTreeClients configured as the window manager should never get - // OnEmbed(). - NOTREACHED(); -} - -void SimpleWM::OnLostConnection(aura::WindowTreeClient* client) { - window_tree_host_.reset(); - window_tree_client_.reset(); -} - -void SimpleWM::OnEmbedRootDestroyed(aura::WindowTreeHostMus* window_tree_host) { - // WindowTreeClients configured as the window manager should never get - // OnEmbedRootDestroyed(). - NOTREACHED(); -} - -void SimpleWM::OnPointerEventObserved(const ui::PointerEvent& event, - int64_t display_id, - aura::Window* target) { - // Don't care. -} - -aura::PropertyConverter* SimpleWM::GetPropertyConverter() { - return &property_converter_; -} - -//////////////////////////////////////////////////////////////////////////////// -// SimpleWM, aura::WindowManagerDelegate implementation: - -void SimpleWM::SetWindowManagerClient( - aura::WindowManagerClient* client) { - window_manager_client_ = client; -} - -void SimpleWM::OnWmConnected() {} - -void SimpleWM::OnWmSetBounds(aura::Window* window, const gfx::Rect& bounds) { - FrameView* frame_view = GetFrameViewForClientWindow(window); - frame_view->GetWidget()->SetBounds(bounds); -} - -bool SimpleWM::OnWmSetProperty( - aura::Window* window, - const std::string& name, - std::unique_ptr<std::vector<uint8_t>>* new_data) { - return true; -} - -void SimpleWM::OnWmSetModalType(aura::Window* window, ui::ModalType type) {} - -void SimpleWM::OnWmSetCanFocus(aura::Window* window, bool can_focus) {} - -aura::Window* SimpleWM::OnWmCreateTopLevelWindow( - ui::mojom::WindowType window_type, - std::map<std::string, std::vector<uint8_t>>* properties) { - aura::Window* client_window = new aura::Window(nullptr); - SetWindowType(client_window, window_type); - client_window->Init(ui::LAYER_NOT_DRAWN); - - views::Widget* frame_widget = new views::Widget; - views::NativeWidgetAura* frame_native_widget = - new views::NativeWidgetAura(frame_widget, true); - views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW); - FrameView* frame_view = new FrameView(client_window); - params.delegate = frame_view; - params.native_widget = frame_native_widget; - params.parent = window_root_; - params.bounds = gfx::Rect(10, 10, 500, 500); - frame_widget->Init(params); - frame_widget->Show(); - frame_view->Init(); - - frame_widget->GetNativeWindow()->AddChild(client_window); - frame_widget->GetNativeWindow()->AddObserver(workspace_layout_manager_.get()); - - client_window_to_frame_view_[client_window] = frame_view; - // TODO(beng): probably need to observe client_window from now on so we can - // clean up this map. - - return client_window; -} - -void SimpleWM::OnWmClientJankinessChanged( - const std::set<aura::Window*>& client_windows, - bool janky) { - // Don't care. -} - -void SimpleWM::OnWmBuildDragImage(const gfx::Point& screen_location, - const gfx::ImageSkia& drag_image, - const gfx::Vector2d& drag_image_offset, - ui::mojom::PointerKind source) {} - -void SimpleWM::OnWmMoveDragImage(const gfx::Point& screen_location) {} - -void SimpleWM::OnWmDestroyDragImage() {} - -void SimpleWM::OnWmWillCreateDisplay(const display::Display& display) { - screen_->display_list().AddDisplay(display, - display::DisplayList::Type::PRIMARY); -} - -void SimpleWM::OnWmNewDisplay( - std::unique_ptr<aura::WindowTreeHostMus> window_tree_host, - const display::Display& display) { - // Only handles a single root. - DCHECK(!window_root_); - window_tree_host_ = std::move(window_tree_host); - window_tree_host_->InitHost(); - window_tree_host_->window()->Show(); - display_root_ = window_tree_host_->window(); - window_root_ = new aura::Window(nullptr); - window_root_->Init(ui::LAYER_SOLID_COLOR); - window_root_->layer()->SetColor(SK_ColorWHITE); - display_root_->AddChild(window_root_); - window_root_->Show(); - workspace_layout_manager_ = - std::make_unique<WorkspaceLayoutManager>(window_root_); - - window_list_model_ = std::make_unique<WindowListModel>(window_root_); - - views::Widget* window_list_widget = new views::Widget; - views::NativeWidgetAura* window_list_widget_native_widget = - new views::NativeWidgetAura(window_list_widget, true); - views::Widget::InitParams params(views::Widget::InitParams::TYPE_CONTROL); - WindowListView* window_list_view = - new WindowListView(window_list_model_.get(), - base::Bind(&SimpleWM::OnWindowListViewItemActivated, - base::Unretained(this))); - params.delegate = window_list_view; - params.native_widget = window_list_widget_native_widget; - params.parent = display_root_; - window_list_widget->Init(params); - window_list_widget->Show(); - - display_root_->SetLayoutManager(new DisplayLayoutManager( - display_root_, window_root_, window_list_view)); - - DCHECK(window_manager_client_); - window_manager_client_->AddActivationParent(window_root_); - ui::mojom::FrameDecorationValuesPtr frame_decoration_values = - ui::mojom::FrameDecorationValues::New(); - frame_decoration_values->normal_client_area_insets.Set( - kNonClientTopHeight, kNonClientSize, kNonClientSize, kNonClientSize); - frame_decoration_values->max_title_bar_button_width = 0; - window_manager_client_->SetFrameDecorationValues( - std::move(frame_decoration_values)); - focus_controller_ = std::make_unique<wm::FocusController>(this); - aura::client::SetFocusClient(display_root_, focus_controller_.get()); - wm::SetActivationClient(display_root_, focus_controller_.get()); - display_root_->AddPreTargetHandler(focus_controller_.get()); -} - -void SimpleWM::OnWmDisplayRemoved( - aura::WindowTreeHostMus* window_tree_host) { - DCHECK_EQ(window_tree_host, window_tree_host_.get()); - window_root_ = nullptr; - window_tree_host_.reset(); -} - -void SimpleWM::OnWmDisplayModified(const display::Display& display) {} - -void SimpleWM::OnWmPerformMoveLoop( - aura::Window* window, - ui::mojom::MoveLoopSource source, - const gfx::Point& cursor_location, - const base::Callback<void(bool)>& on_done) { - // Don't care. -} - -void SimpleWM::OnWmCancelMoveLoop(aura::Window* window) {} - -void SimpleWM::OnCursorTouchVisibleChanged(bool enabled) {} - -void SimpleWM::OnWmSetClientArea( - aura::Window* window, - const gfx::Insets& insets, - const std::vector<gfx::Rect>& additional_client_areas) {} - -bool SimpleWM::IsWindowActive(aura::Window* window) { return false; } - -void SimpleWM::OnWmDeactivateWindow(aura::Window* window) {} - -void SimpleWM::OnWmPerformAction(aura::Window* window, - const std::string& action) {} - -//////////////////////////////////////////////////////////////////////////////// -// SimpleWM, wm::BaseFocusRules implementation: - -bool SimpleWM::SupportsChildActivation(aura::Window* window) const { - return window == window_root_; -} - -bool SimpleWM::IsWindowConsideredVisibleForActivation( - aura::Window* window) const { - if (window->IsVisible()) - return true; - - ui::WindowShowState show_state = - window->GetProperty(aura::client::kShowStateKey); - if (show_state == ui::SHOW_STATE_MINIMIZED) - return true; - - return window->TargetVisibility(); -} - -//////////////////////////////////////////////////////////////////////////////// -// SimpleWM, private: - -SimpleWM::FrameView* SimpleWM::GetFrameViewForClientWindow( - aura::Window* client_window) { - auto it = client_window_to_frame_view_.find(client_window); - return it != client_window_to_frame_view_.end() ? it->second : nullptr; -} - -void SimpleWM::OnWindowListViewItemActivated(aura::Window* window) { - window->Show(); - wm::ActivationClient* activation_client = - wm::GetActivationClient(window->GetRootWindow()); - activation_client->ActivateWindow(window); -} - -} // namespace simple_wm
diff --git a/mash/simple_wm/simple_wm.h b/mash/simple_wm/simple_wm.h deleted file mode 100644 index 2bc758d..0000000 --- a/mash/simple_wm/simple_wm.h +++ /dev/null
@@ -1,147 +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. - -#ifndef MASH_SIMPLE_WM_SIMPLE_WM_H_ -#define MASH_SIMPLE_WM_SIMPLE_WM_H_ - -#include <memory> -#include <utility> - -#include "base/memory/ptr_util.h" -#include "base/threading/thread_task_runner_handle.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "services/service_manager/public/cpp/connector.h" -#include "services/service_manager/public/cpp/service.h" -#include "services/service_manager/public/cpp/service_context.h" -#include "ui/aura/env.h" -#include "ui/aura/mus/property_converter.h" -#include "ui/aura/mus/property_utils.h" -#include "ui/aura/mus/window_manager_delegate.h" -#include "ui/aura/mus/window_tree_client.h" -#include "ui/aura/mus/window_tree_client_delegate.h" -#include "ui/aura/mus/window_tree_host_mus.h" -#include "ui/aura/window.h" -#include "ui/display/display.h" -#include "ui/wm/core/base_focus_rules.h" -#include "ui/wm/core/capture_controller.h" -#include "ui/wm/core/wm_state.h" - -namespace display { -class ScreenBase; -} - -namespace views { -class AuraInit; -} - -namespace wm { -class FocusController; -} - -namespace simple_wm { - -class SimpleWM : public service_manager::Service, - public aura::WindowTreeClientDelegate, - public aura::WindowManagerDelegate, - public wm::BaseFocusRules { - public: - SimpleWM(); - ~SimpleWM() override; - - private: - class DisplayLayoutManager; - class FrameView; - class WindowListModel; - class WindowListModelObserver; - class WindowListView; - class WorkspaceLayoutManager; - - // service_manager::Service: - void OnStart() override; - - // aura::WindowTreeClientDelegate: - void OnEmbed( - std::unique_ptr<aura::WindowTreeHostMus> window_tree_host) override; - void OnLostConnection(aura::WindowTreeClient* client) override; - void OnEmbedRootDestroyed(aura::WindowTreeHostMus* window_tree_host) override; - void OnPointerEventObserved(const ui::PointerEvent& event, - int64_t display_id, - aura::Window* target) override; - aura::PropertyConverter* GetPropertyConverter() override; - - // aura::WindowManagerDelegate: - void SetWindowManagerClient(aura::WindowManagerClient* client) override; - void OnWmConnected() override; - void OnWmAcceleratedWidgetAvailableForDisplay( - int64_t display_id, - gfx::AcceleratedWidget widget) override {} - void OnWmSetBounds(aura::Window* window, const gfx::Rect& bounds) override; - bool OnWmSetProperty( - aura::Window* window, - const std::string& name, - std::unique_ptr<std::vector<uint8_t>>* new_data) override; - void OnWmSetModalType(aura::Window* window, ui::ModalType type) override; - void OnWmSetCanFocus(aura::Window* window, bool can_focus) override; - aura::Window* OnWmCreateTopLevelWindow( - ui::mojom::WindowType window_type, - std::map<std::string, std::vector<uint8_t>>* properties) override; - void OnWmClientJankinessChanged(const std::set<aura::Window*>& client_windows, - bool janky) override; - void OnWmBuildDragImage(const gfx::Point& screen_location, - const gfx::ImageSkia& drag_image, - const gfx::Vector2d& drag_image_offset, - ui::mojom::PointerKind source) override; - void OnWmMoveDragImage(const gfx::Point& screen_location) override; - void OnWmDestroyDragImage() override; - void OnWmWillCreateDisplay(const display::Display& display) override; - void OnWmNewDisplay(std::unique_ptr<aura::WindowTreeHostMus> window_tree_host, - const display::Display& display) override; - void OnWmDisplayRemoved(aura::WindowTreeHostMus* window_tree_host) override; - void OnWmDisplayModified(const display::Display& display) override; - void OnWmPerformMoveLoop(aura::Window* window, - ui::mojom::MoveLoopSource source, - const gfx::Point& cursor_location, - const base::Callback<void(bool)>& on_done) override; - void OnWmCancelMoveLoop(aura::Window* window) override; - void OnCursorTouchVisibleChanged(bool enabled) override; - void OnWmSetClientArea( - aura::Window* window, - const gfx::Insets& insets, - const std::vector<gfx::Rect>& additional_client_areas) override; - bool IsWindowActive(aura::Window* window) override; - void OnWmDeactivateWindow(aura::Window* window) override; - void OnWmPerformAction(aura::Window* window, - const std::string& action) override; - - // wm::BaseFocusRules: - bool SupportsChildActivation(aura::Window* window) const override; - bool IsWindowConsideredVisibleForActivation( - aura::Window* window) const override; - - FrameView* GetFrameViewForClientWindow(aura::Window* client_window); - - void OnWindowListViewItemActivated(aura::Window* index); - - std::unique_ptr<views::AuraInit> aura_init_; - wm::WMState wm_state_; - std::unique_ptr<display::ScreenBase> screen_; - aura::PropertyConverter property_converter_; - std::unique_ptr<wm::FocusController> focus_controller_; - std::unique_ptr<aura::WindowTreeHostMus> window_tree_host_; - aura::Window* display_root_ = nullptr; - aura::Window* window_root_ = nullptr; - aura::WindowManagerClient* window_manager_client_ = nullptr; - std::unique_ptr<aura::WindowTreeClient> window_tree_client_; - std::map<aura::Window*, FrameView*> client_window_to_frame_view_; - std::unique_ptr<WindowListModel> window_list_model_; - std::unique_ptr<WorkspaceLayoutManager> workspace_layout_manager_; - - bool started_ = false; - - DISALLOW_COPY_AND_ASSIGN(SimpleWM); -}; - -} // namespace simple_wm - -#endif // MASH_SIMPLE_WM_SIMPLE_WM_H_
diff --git a/mash/task_viewer/task_viewer.cc b/mash/task_viewer/task_viewer.cc index dee6a844..902830d 100644 --- a/mash/task_viewer/task_viewer.cc +++ b/mash/task_viewer/task_viewer.cc
@@ -300,7 +300,6 @@ views::AuraInit::InitParams params; params.connector = context()->connector(); params.identity = context()->identity(); - params.mode = views::AuraInit::Mode::AURA_MUS; aura_init_ = views::AuraInit::Create(params); if (!aura_init_) context()->QuitNow();
diff --git a/media/base/BUILD.gn b/media/base/BUILD.gn index ac60e933..7d33caaa 100644 --- a/media/base/BUILD.gn +++ b/media/base/BUILD.gn
@@ -144,6 +144,7 @@ "fallback_video_decoder.cc", "fallback_video_decoder.h", "feedback_signal_accumulator.h", + "flinging_controller.h", "hdr_metadata.cc", "hdr_metadata.h", "key_system_names.cc",
diff --git a/media/base/flinging_controller.h b/media/base/flinging_controller.h new file mode 100644 index 0000000..1bf26345 --- /dev/null +++ b/media/base/flinging_controller.h
@@ -0,0 +1,37 @@ +// 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 MEDIA_BASE_FLINGING_CONTROLLER_H_ +#define MEDIA_BASE_FLINGING_CONTROLLER_H_ + +#include "base/time/time.h" +#include "media/base/media_controller.h" +#include "media/base/media_status_observer.h" + +namespace media { + +// Interface that groups all the necessary hooks to control media that is being +// flung to a cast device, as part of RemotePlayback. +// TODO(https://crbug.com/820277): Rename this interface to MediaRouteController +// and change media_router::MediaRouteController to MojoMediaRouteController. +class FlingingController { + public: + virtual ~FlingingController() = default; + + // Gets a MediaContoller owned by |this| to issue simple commands. + virtual MediaController* GetMediaController() = 0; + + // Subscribe or un-subscribe to changes in the media status. + virtual void AddMediaStatusObserver(MediaStatusObserver* observer) = 0; + virtual void RemoveMediaStatusObserver(MediaStatusObserver* observer) = 0; + + // Gets the current media playback time. Implementers may sacrifice precision + // to avoid a round-trip query to cast devices (see + // RemoteMediaPlayer.getApproximateStreamPosition() for example). + virtual base::TimeDelta GetApproximateCurrentTime() = 0; +}; + +} // namespace media + +#endif // MEDIA_BASE_FLINGING_CONTROLLER_H_
diff --git a/media/base/video_frame_metadata.cc b/media/base/video_frame_metadata.cc index 1d6958d..4e0874f 100644 --- a/media/base/video_frame_metadata.cc +++ b/media/base/video_frame_metadata.cc
@@ -111,8 +111,8 @@ DCHECK(value); const base::Value* const binary_value = GetBinaryValue(key); if (binary_value) - value->assign(binary_value->GetBlob().data(), - binary_value->GetBlob().size()); + value->assign(binary_value->GetBlob().begin(), + binary_value->GetBlob().end()); return !!binary_value; }
diff --git a/media/capture/video/chromeos/local_gpu_memory_buffer_manager.cc b/media/capture/video/chromeos/local_gpu_memory_buffer_manager.cc index eab11a8..49e9d03 100644 --- a/media/capture/video/chromeos/local_gpu_memory_buffer_manager.cc +++ b/media/capture/video/chromeos/local_gpu_memory_buffer_manager.cc
@@ -8,6 +8,9 @@ #include <xf86drm.h> #include <memory> +#include "base/trace_event/memory_allocator_dump_guid.h" +#include "base/trace_event/process_memory_dump.h" + namespace media { namespace { @@ -150,14 +153,35 @@ gfx::GpuMemoryBufferId GetId() const override { return handle_.id; } - gfx::GpuMemoryBufferHandle GetHandle() const override { - return gfx::CloneHandleForIPC(handle_); + gfx::GpuMemoryBufferType GetType() const override { + return gfx::NATIVE_PIXMAP; + } + + gfx::GpuMemoryBufferHandle CloneHandle() const override { + DCHECK_EQ(handle_.type, gfx::NATIVE_PIXMAP); + gfx::GpuMemoryBufferHandle handle; + handle.type = gfx::NATIVE_PIXMAP; + handle.id = handle_.id; + handle.native_pixmap_handle = + gfx::CloneHandleForIPC(handle_.native_pixmap_handle); + return handle; } ClientBuffer AsClientBuffer() override { return reinterpret_cast<ClientBuffer>(this); } + void OnMemoryDump( + base::trace_event::ProcessMemoryDump* pmd, + const base::trace_event::MemoryAllocatorDumpGuid& buffer_dump_guid, + uint64_t tracing_process_id, + int importance) const override { + auto shared_buffer_guid = gfx::GetGenericSharedGpuMemoryGUIDForTracing( + tracing_process_id, GetId()); + pmd->CreateSharedGlobalAllocatorDump(shared_buffer_guid); + pmd->AddOwnershipEdge(buffer_dump_guid, shared_buffer_guid, importance); + } + private: struct MappedPlane { void* addr;
diff --git a/media/capture/video/chromeos/stream_buffer_manager.cc b/media/capture/video/chromeos/stream_buffer_manager.cc index e728307..8ee18ef 100644 --- a/media/capture/video/chromeos/stream_buffer_manager.cc +++ b/media/capture/video/chromeos/stream_buffer_manager.cc
@@ -315,12 +315,18 @@ stream_context_[stream_type]->stream->format; gfx::NativePixmapHandle buffer_handle = - buffer->GetHandle().native_pixmap_handle; + buffer->CloneHandle().native_pixmap_handle; + // Take ownership of FD at index 0. + base::ScopedFD fd(buffer_handle.fds[0].fd); + // There should be only one FD. Close all remaining FDs if there are any. + DCHECK_EQ(buffer_handle.fds.size(), 1U); + for (size_t i = 1; i < buffer_handle.fds.size(); ++i) + base::ScopedFD scoped_fd(buffer_handle.fds[i].fd); + size_t num_planes = buffer_handle.planes.size(); std::vector<StreamCaptureInterface::Plane> planes(num_planes); for (size_t i = 0; i < num_planes; ++i) { - // There is only one fd. - int dup_fd = dup(buffer_handle.fds[0].fd); + int dup_fd = dup(fd.get()); if (dup_fd == -1) { device_context_->SetErrorState(FROM_HERE, "Failed to dup fd"); return;
diff --git a/media/capture/video/mock_gpu_memory_buffer_manager.cc b/media/capture/video/mock_gpu_memory_buffer_manager.cc index 9b8befe..e4bb4f6 100644 --- a/media/capture/video/mock_gpu_memory_buffer_manager.cc +++ b/media/capture/video/mock_gpu_memory_buffer_manager.cc
@@ -6,6 +6,8 @@ #include <memory> +#include "build/build_config.h" + #if defined(OS_CHROMEOS) #include "media/capture/video/chromeos/stream_buffer_manager.h" #endif @@ -93,8 +95,19 @@ gfx::GpuMemoryBufferId GetId() const override { return handle_.id; } - gfx::GpuMemoryBufferHandle GetHandle() const override { - return gfx::CloneHandleForIPC(handle_); + gfx::GpuMemoryBufferType GetType() const override { + return gfx::NATIVE_PIXMAP; + } + + gfx::GpuMemoryBufferHandle CloneHandle() const override { + gfx::GpuMemoryBufferHandle handle; + handle.type = gfx::NATIVE_PIXMAP; + handle.id = handle_.id; +#if defined(OS_LINUX) + handle.native_pixmap_handle = + gfx::CloneHandleForIPC(handle_.native_pixmap_handle); +#endif + return handle; } ClientBuffer AsClientBuffer() override { @@ -102,6 +115,12 @@ return ClientBuffer(); } + void OnMemoryDump( + base::trace_event::ProcessMemoryDump* pmd, + const base::trace_event::MemoryAllocatorDumpGuid& buffer_dump_guid, + uint64_t tracing_process_id, + int importance) const override {} + private: gfx::Size size_; gfx::BufferFormat format_;
diff --git a/media/video/gpu_memory_buffer_video_frame_pool.cc b/media/video/gpu_memory_buffer_video_frame_pool.cc index 734606a..029feed1 100644 --- a/media/video/gpu_memory_buffer_video_frame_pool.cc +++ b/media/video/gpu_memory_buffer_video_frame_pool.cc
@@ -639,18 +639,8 @@ dump->AddScalar("free_size", base::trace_event::MemoryAllocatorDump::kUnitsBytes, frame_resources->is_used() ? 0 : buffer_size_in_bytes); - auto shared_memory_guid = - plane_resource.gpu_memory_buffer->GetHandle().handle.GetGUID(); - if (!shared_memory_guid.is_empty()) { - pmd->CreateSharedMemoryOwnershipEdge(dump->guid(), shared_memory_guid, - kImportance); - } else { - auto shared_buffer_guid = - plane_resource.gpu_memory_buffer->GetGUIDForTracing( - tracing_process_id); - pmd->CreateSharedGlobalAllocatorDump(shared_buffer_guid); - pmd->AddOwnershipEdge(dump->guid(), shared_buffer_guid, kImportance); - } + plane_resource.gpu_memory_buffer->OnMemoryDump( + pmd, dump->guid(), tracing_process_id, kImportance); } } }
diff --git a/media/video/mock_gpu_video_accelerator_factories.cc b/media/video/mock_gpu_video_accelerator_factories.cc index f892569..b058262 100644 --- a/media/video/mock_gpu_video_accelerator_factories.cc +++ b/media/video/mock_gpu_video_accelerator_factories.cc
@@ -61,13 +61,21 @@ size_.width(), format_, static_cast<int>(plane))); } gfx::GpuMemoryBufferId GetId() const override { return id_; } - gfx::GpuMemoryBufferHandle GetHandle() const override { + gfx::GpuMemoryBufferType GetType() const override { + return gfx::NATIVE_PIXMAP; + } + gfx::GpuMemoryBufferHandle CloneHandle() const override { NOTREACHED(); return gfx::GpuMemoryBufferHandle(); } ClientBuffer AsClientBuffer() override { return reinterpret_cast<ClientBuffer>(this); } + void OnMemoryDump( + base::trace_event::ProcessMemoryDump* pmd, + const base::trace_event::MemoryAllocatorDumpGuid& buffer_dump_guid, + uint64_t tracing_process_id, + int importance) const override {} private: static const size_t kMaxPlanes = 3;
diff --git a/mojo/public/cpp/base/values_mojom_traits.h b/mojo/public/cpp/base/values_mojom_traits.h index ee1dbee..cdb9bbb 100644 --- a/mojo/public/cpp/base/values_mojom_traits.h +++ b/mojo/public/cpp/base/values_mojom_traits.h
@@ -105,11 +105,8 @@ return value.GetString(); } - static base::span<const uint8_t> binary_value(const base::Value& value) { - // TODO(dcheng): Change base::Value::BlobStorage to uint8_t. - return base::make_span( - reinterpret_cast<const uint8_t*>(value.GetBlob().data()), - value.GetBlob().size()); + static const std::vector<uint8_t>& binary_value(const base::Value& value) { + return value.GetBlob(); } static const base::Value& list_value(const base::Value& value) {
diff --git a/mojo/public/tools/bindings/chromium_bindings_configuration.gni b/mojo/public/tools/bindings/chromium_bindings_configuration.gni index 1893db1..4a55c2d 100644 --- a/mojo/public/tools/bindings/chromium_bindings_configuration.gni +++ b/mojo/public/tools/bindings/chromium_bindings_configuration.gni
@@ -18,7 +18,6 @@ "//components/typemaps.gni", "//content/common/bluetooth/typemaps.gni", "//content/common/indexed_db/typemaps.gni", - "//content/common/presentation/typemaps.gni", "//content/common/typemaps.gni", "//content/public/common/typemaps.gni", "//device/bluetooth/public/mojom/typemaps.gni",
diff --git a/net/BUILD.gn b/net/BUILD.gn index 7f9901a..937545e 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -1479,7 +1479,6 @@ "third_party/quic/platform/api/quic_containers.h", "third_party/quic/platform/api/quic_endian.h", "third_party/quic/platform/api/quic_estimate_memory_usage.h", - "third_party/quic/platform/api/quic_expect_bug.h", "third_party/quic/platform/api/quic_export.h", "third_party/quic/platform/api/quic_exported_stats.h", "third_party/quic/platform/api/quic_fallthrough.h", @@ -1524,7 +1523,6 @@ "third_party/quic/platform/impl/quic_containers_impl.h", "third_party/quic/platform/impl/quic_endian_impl.h", "third_party/quic/platform/impl/quic_estimate_memory_usage_impl.h", - "third_party/quic/platform/impl/quic_expect_bug_impl.h", "third_party/quic/platform/impl/quic_export_impl.h", "third_party/quic/platform/impl/quic_exported_stats_impl.h", "third_party/quic/platform/impl/quic_fallthrough_impl.h", @@ -3054,12 +3052,14 @@ "quic/chromium/crypto_test_utils_chromium.cc", "third_party/quic/core/quic_trace_visitor.cc", "third_party/quic/core/quic_trace_visitor.h", + "third_party/quic/platform/api/quic_expect_bug.h", "third_party/quic/platform/api/quic_mock_log.h", "third_party/quic/platform/api/quic_test.h", "third_party/quic/platform/api/quic_test_loopback.cc", "third_party/quic/platform/api/quic_test_loopback.h", "third_party/quic/platform/api/quic_test_mem_slice_vector.h", "third_party/quic/platform/api/quic_test_output.h", + "third_party/quic/platform/impl/quic_expect_bug_impl.h", "third_party/quic/platform/impl/quic_mock_log_impl.h", "third_party/quic/platform/impl/quic_test_impl.cc", "third_party/quic/platform/impl/quic_test_impl.h", @@ -3215,8 +3215,6 @@ "third_party/quic/core/quic_dispatcher.h", "third_party/quic/core/quic_packet_writer_wrapper.cc", "third_party/quic/core/quic_packet_writer_wrapper.h", - "third_party/quic/core/quic_per_connection_packet_writer.cc", - "third_party/quic/core/quic_per_connection_packet_writer.h", "third_party/quic/core/quic_process_packet_interface.h", "third_party/quic/core/quic_spdy_client_session.cc", "third_party/quic/core/quic_spdy_client_session.h",
diff --git a/net/quic/chromium/quic_http_stream_test.cc b/net/quic/chromium/quic_http_stream_test.cc index 944a43aa..2eea213 100644 --- a/net/quic/chromium/quic_http_stream_test.cc +++ b/net/quic/chromium/quic_http_stream_test.cc
@@ -2218,19 +2218,10 @@ client_packet_number++, kIncludeVersion, promise_id_, 0, DEFAULT_PRIORITY, &header_stream_offset)); } - if (FLAGS_quic_reloadable_flag_quic_deprecate_scoped_scheduler2) { - AddWrite(ConstructClientRstStreamVaryMismatchAndRequestHeadersPacket( - client_packet_number++, stream_id_ + 2, !kIncludeVersion, kFin, - DEFAULT_PRIORITY, promise_id_, &spdy_request_header_frame_length, - &header_stream_offset)); - } else { - AddWrite( - ConstructClientRstStreamVaryMismatchPacket(client_packet_number++)); - AddWrite(InnerConstructRequestHeadersPacket( - client_packet_number++, stream_id_ + 2, !kIncludeVersion, kFin, - DEFAULT_PRIORITY, promise_id_, &spdy_request_header_frame_length, - &header_stream_offset)); - } + AddWrite(ConstructClientRstStreamVaryMismatchAndRequestHeadersPacket( + client_packet_number++, stream_id_ + 2, !kIncludeVersion, kFin, + DEFAULT_PRIORITY, promise_id_, &spdy_request_header_frame_length, + &header_stream_offset)); AddWrite(ConstructClientAckPacket(client_packet_number++, 3, 1, 1)); AddWrite(ConstructClientRstStreamCancelledPacket(client_packet_number++));
diff --git a/net/third_party/quic/core/congestion_control/bbr_sender.cc b/net/third_party/quic/core/congestion_control/bbr_sender.cc index 6d0f3ce0..8cc75c7 100644 --- a/net/third_party/quic/core/congestion_control/bbr_sender.cc +++ b/net/third_party/quic/core/congestion_control/bbr_sender.cc
@@ -129,6 +129,7 @@ rate_based_startup_(false), initial_conservation_in_startup_(CONSERVATION), enable_ack_aggregation_during_startup_(false), + expire_ack_aggregation_in_startup_(false), drain_to_target_(false), probe_rtt_based_on_bdp_(false), probe_rtt_skipped_if_similar_rtt_(false), @@ -280,6 +281,11 @@ QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_bbr_slower_startup3, 4, 4); set_drain_gain(kModerateProbeRttMultiplier); } + if (GetQuicReloadableFlag(quic_bbr_slower_startup4) && + config.HasClientRequestedIndependentOption(kBBQ5, perspective)) { + QUIC_FLAG_COUNT(quic_reloadable_flag_quic_bbr_slower_startup4); + expire_ack_aggregation_in_startup_ = true; + } if (config.HasClientRequestedIndependentOption(kMIN1, perspective)) { min_congestion_window_ = kMaxSegmentSize; } @@ -537,6 +543,10 @@ if (BandwidthEstimate() >= target) { bandwidth_at_last_round_ = BandwidthEstimate(); rounds_without_bandwidth_gain_ = 0; + if (expire_ack_aggregation_in_startup_) { + // Expire old excess delivery measurements now that bandwidth increased. + max_ack_height_.Reset(0, round_trip_count_); + } return; }
diff --git a/net/third_party/quic/core/congestion_control/bbr_sender.h b/net/third_party/quic/core/congestion_control/bbr_sender.h index 5017c9ee..ba1595aa 100644 --- a/net/third_party/quic/core/congestion_control/bbr_sender.h +++ b/net/third_party/quic/core/congestion_control/bbr_sender.h
@@ -364,6 +364,9 @@ RecoveryState initial_conservation_in_startup_; // When true, add the most recent ack aggregation measurement during STARTUP. bool enable_ack_aggregation_during_startup_; + // When true, expire the windowed ack aggregation values in STARTUP when + // bandwidth increases more than 25%. + bool expire_ack_aggregation_in_startup_; // If true, will not exit low gain mode until bytes_in_flight drops below BDP // or it's time for high gain mode.
diff --git a/net/third_party/quic/core/congestion_control/general_loss_algorithm.cc b/net/third_party/quic/core/congestion_control/general_loss_algorithm.cc index a284b200..b7e7c52 100644 --- a/net/third_party/quic/core/congestion_control/general_loss_algorithm.cc +++ b/net/third_party/quic/core/congestion_control/general_loss_algorithm.cc
@@ -30,17 +30,8 @@ GeneralLossAlgorithm::GeneralLossAlgorithm() : GeneralLossAlgorithm(kNack) {} GeneralLossAlgorithm::GeneralLossAlgorithm(LossDetectionType loss_type) - : loss_detection_timeout_(QuicTime::Zero()), - largest_sent_on_spurious_retransmit_(0), - loss_type_(loss_type), - reordering_shift_(loss_type == kAdaptiveTime - ? kDefaultAdaptiveLossDelayShift - : kDefaultLossDelayShift), - largest_previously_acked_(0), - largest_lost_(0) {} - -LossDetectionType GeneralLossAlgorithm::GetLossDetectionType() const { - return loss_type_; + : loss_detection_timeout_(QuicTime::Zero()), largest_lost_(0) { + SetLossDetectionType(loss_type); } void GeneralLossAlgorithm::SetLossDetectionType(LossDetectionType loss_type) { @@ -50,9 +41,18 @@ reordering_shift_ = loss_type == kAdaptiveTime ? kDefaultAdaptiveLossDelayShift : kDefaultLossDelayShift; + if (GetQuicReloadableFlag(quic_eighth_rtt_loss_detection) && + loss_type == kTime) { + QUIC_FLAG_COUNT(quic_reloadable_flag_quic_eighth_rtt_loss_detection); + reordering_shift_ = 3; + } largest_previously_acked_ = 0; } +LossDetectionType GeneralLossAlgorithm::GetLossDetectionType() const { + return loss_type_; +} + // Uses nack counts to decide when packets are lost. void GeneralLossAlgorithm::DetectLosses( const QuicUnackedPacketMap& unacked_packets,
diff --git a/net/third_party/quic/core/congestion_control/general_loss_algorithm_test.cc b/net/third_party/quic/core/congestion_control/general_loss_algorithm_test.cc index 6324815..689ac174 100644 --- a/net/third_party/quic/core/congestion_control/general_loss_algorithm_test.cc +++ b/net/third_party/quic/core/congestion_control/general_loss_algorithm_test.cc
@@ -293,8 +293,13 @@ for (size_t i = 1; i < 500; ++i) { VerifyLosses(2, std::vector<QuicPacketNumber>{}); } - EXPECT_EQ(1.25 * rtt_stats_.smoothed_rtt(), - loss_algorithm_.GetLossTimeout() - clock_.Now()); + if (GetQuicReloadableFlag(quic_eighth_rtt_loss_detection)) { + EXPECT_EQ(1.125 * rtt_stats_.smoothed_rtt(), + loss_algorithm_.GetLossTimeout() - clock_.Now()); + } else { + EXPECT_EQ(1.25 * rtt_stats_.smoothed_rtt(), + loss_algorithm_.GetLossTimeout() - clock_.Now()); + } } TEST_F(GeneralLossAlgorithmTest, NoLossUntilTimeout) { @@ -310,9 +315,15 @@ // The packet should not be lost until 1.25 RTTs pass. unacked_packets_.RemoveFromInFlight(2); VerifyLosses(2, std::vector<QuicPacketNumber>{}); - // Expect the timer to be set to 0.25 RTT's in the future. - EXPECT_EQ(0.25 * rtt_stats_.smoothed_rtt(), - loss_algorithm_.GetLossTimeout() - clock_.Now()); + if (GetQuicReloadableFlag(quic_eighth_rtt_loss_detection)) { + // Expect the timer to be set to 0.25 RTT's in the future. + EXPECT_EQ(0.125 * rtt_stats_.smoothed_rtt(), + loss_algorithm_.GetLossTimeout() - clock_.Now()); + } else { + // Expect the timer to be set to 0.25 RTT's in the future. + EXPECT_EQ(0.25 * rtt_stats_.smoothed_rtt(), + loss_algorithm_.GetLossTimeout() - clock_.Now()); + } VerifyLosses(2, std::vector<QuicPacketNumber>{}); clock_.AdvanceTime(0.25 * rtt_stats_.smoothed_rtt()); VerifyLosses(2, {1}); @@ -355,9 +366,15 @@ // The packet should not be lost until 1.25 RTTs pass. unacked_packets_.RemoveFromInFlight(10); VerifyLosses(10, std::vector<QuicPacketNumber>{}); - // Expect the timer to be set to 0.25 RTT's in the future. - EXPECT_EQ(0.25 * rtt_stats_.smoothed_rtt(), - loss_algorithm_.GetLossTimeout() - clock_.Now()); + if (GetQuicReloadableFlag(quic_eighth_rtt_loss_detection)) { + // Expect the timer to be set to 0.25 RTT's in the future. + EXPECT_EQ(0.125 * rtt_stats_.smoothed_rtt(), + loss_algorithm_.GetLossTimeout() - clock_.Now()); + } else { + // Expect the timer to be set to 0.25 RTT's in the future. + EXPECT_EQ(0.25 * rtt_stats_.smoothed_rtt(), + loss_algorithm_.GetLossTimeout() - clock_.Now()); + } clock_.AdvanceTime(0.25 * rtt_stats_.smoothed_rtt()); VerifyLosses(10, {1, 2, 3, 4, 5, 6, 7, 8, 9}); EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); @@ -377,9 +394,15 @@ unacked_packets_.RemoveFromInFlight(10); VerifyLosses(10, std::vector<QuicPacketNumber>{}); - // Expect the timer to be set to 0.25 RTT's in the future. - EXPECT_EQ(0.25 * rtt_stats_.smoothed_rtt(), - loss_algorithm_.GetLossTimeout() - clock_.Now()); + if (GetQuicReloadableFlag(quic_eighth_rtt_loss_detection)) { + // Expect the timer to be set to 0.25 RTT's in the future. + EXPECT_EQ(0.125 * rtt_stats_.smoothed_rtt(), + loss_algorithm_.GetLossTimeout() - clock_.Now()); + } else { + // Expect the timer to be set to 0.25 RTT's in the future. + EXPECT_EQ(0.25 * rtt_stats_.smoothed_rtt(), + loss_algorithm_.GetLossTimeout() - clock_.Now()); + } clock_.AdvanceTime(0.25 * rtt_stats_.smoothed_rtt()); // Now ack packets 1 to 9 and ensure the timer is no longer set and no packets // are lost.
diff --git a/net/third_party/quic/core/crypto/crypto_protocol.h b/net/third_party/quic/core/crypto/crypto_protocol.h index cee3d2e..904590e 100644 --- a/net/third_party/quic/core/crypto/crypto_protocol.h +++ b/net/third_party/quic/core/crypto/crypto_protocol.h
@@ -107,6 +107,9 @@ const QuicTag kBBQ3 = TAG('B', 'B', 'Q', '3'); // BBR with ack aggregation // compensation in STARTUP. const QuicTag kBBQ4 = TAG('B', 'B', 'Q', '4'); // Drain gain of 0.75. +const QuicTag kBBQ5 = TAG('B', 'B', 'Q', '5'); // Expire ack aggregation upon + // bandwidth increase in + // STARTUP. const QuicTag kRENO = TAG('R', 'E', 'N', 'O'); // Reno Congestion Control const QuicTag kTPCC = TAG('P', 'C', 'C', '\0'); // Performance-Oriented // Congestion Control
diff --git a/net/third_party/quic/core/end_to_end_test.cc b/net/third_party/quic/core/end_to_end_test.cc index d26e7ec..bb39a7b 100644 --- a/net/third_party/quic/core/end_to_end_test.cc +++ b/net/third_party/quic/core/end_to_end_test.cc
@@ -32,6 +32,7 @@ #include "net/third_party/quic/core/quic_spdy_client_session_base.h" #include "net/third_party/quic/core/quic_spdy_client_stream.h" #include "net/third_party/quic/core/quic_utils.h" +#include "net/third_party/quic/platform/api/quic_expect_bug.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" @@ -3063,40 +3064,46 @@ EXPECT_EQ("200", client_->response_headers()->find(":status")->second); } -TEST_P(EndToEndTest, PreSharedKeyMismatch) { +// TODO: reenable once we have a way to make this run faster. +TEST_P(EndToEndTest, DISABLED_PreSharedKeyMismatch) { client_config_.set_max_time_before_crypto_handshake( - QuicTime::Delta::FromMilliseconds(100)); + QuicTime::Delta::FromSeconds(1)); client_config_.set_max_idle_time_before_crypto_handshake( - QuicTime::Delta::FromMilliseconds(100)); + QuicTime::Delta::FromSeconds(1)); pre_shared_key_client_ = "foo"; pre_shared_key_server_ = "bar"; - ASSERT_TRUE(Initialize()); - - EXPECT_EQ("", client_->SendSynchronousRequest("/foo")); + // One of two things happens when Initialize() returns: + // 1. Crypto handshake has completed, and it is unsuccessful. Initialize() + // returns false. + // 2. Crypto handshake has not completed, Initialize() returns true. The call + // to WaitForCryptoHandshakeConfirmed() will wait for the handshake and + // return whether it is successful. + ASSERT_FALSE(Initialize() && + client_->client()->WaitForCryptoHandshakeConfirmed()); EXPECT_EQ(QUIC_HANDSHAKE_TIMEOUT, client_->connection_error()); } -TEST_P(EndToEndTest, PreSharedKeyNoClient) { +// TODO: reenable once we have a way to make this run faster. +TEST_P(EndToEndTest, DISABLED_PreSharedKeyNoClient) { client_config_.set_max_time_before_crypto_handshake( - QuicTime::Delta::FromMilliseconds(100)); + QuicTime::Delta::FromSeconds(1)); client_config_.set_max_idle_time_before_crypto_handshake( - QuicTime::Delta::FromMilliseconds(100)); + QuicTime::Delta::FromSeconds(1)); pre_shared_key_server_ = "foobar"; - ASSERT_TRUE(Initialize()); - - EXPECT_EQ("", client_->SendSynchronousRequest("/foo")); + ASSERT_FALSE(Initialize() && + client_->client()->WaitForCryptoHandshakeConfirmed()); EXPECT_EQ(QUIC_HANDSHAKE_TIMEOUT, client_->connection_error()); } -TEST_P(EndToEndTest, PreSharedKeyNoServer) { +// TODO: reenable once we have a way to make this run faster. +TEST_P(EndToEndTest, DISABLED_PreSharedKeyNoServer) { client_config_.set_max_time_before_crypto_handshake( - QuicTime::Delta::FromMilliseconds(100)); + QuicTime::Delta::FromSeconds(1)); client_config_.set_max_idle_time_before_crypto_handshake( - QuicTime::Delta::FromMilliseconds(100)); + QuicTime::Delta::FromSeconds(1)); pre_shared_key_client_ = "foobar"; - ASSERT_TRUE(Initialize()); - - EXPECT_EQ("", client_->SendSynchronousRequest("/foo")); + ASSERT_FALSE(Initialize() && + client_->client()->WaitForCryptoHandshakeConfirmed()); EXPECT_EQ(QUIC_HANDSHAKE_TIMEOUT, client_->connection_error()); }
diff --git a/net/third_party/quic/core/frames/quic_frames_test.cc b/net/third_party/quic/core/frames/quic_frames_test.cc index 2165974..9c5045f 100644 --- a/net/third_party/quic/core/frames/quic_frames_test.cc +++ b/net/third_party/quic/core/frames/quic_frames_test.cc
@@ -14,6 +14,7 @@ #include "net/third_party/quic/core/frames/quic_stop_waiting_frame.h" #include "net/third_party/quic/core/frames/quic_stream_frame.h" #include "net/third_party/quic/core/frames/quic_window_update_frame.h" +#include "net/third_party/quic/platform/api/quic_expect_bug.h" #include "net/third_party/quic/platform/api/quic_interval.h" #include "net/third_party/quic/platform/api/quic_test.h" #include "net/third_party/quic/test_tools/quic_test_utils.h"
diff --git a/net/third_party/quic/core/quic_config_test.cc b/net/third_party/quic/core/quic_config_test.cc index 8e79db0..c14db33 100644 --- a/net/third_party/quic/core/quic_config_test.cc +++ b/net/third_party/quic/core/quic_config_test.cc
@@ -9,6 +9,7 @@ #include "net/third_party/quic/core/quic_packets.h" #include "net/third_party/quic/core/quic_time.h" #include "net/third_party/quic/core/quic_utils.h" +#include "net/third_party/quic/platform/api/quic_expect_bug.h" #include "net/third_party/quic/platform/api/quic_string.h" #include "net/third_party/quic/platform/api/quic_test.h" #include "net/third_party/quic/platform/api/quic_uint128.h"
diff --git a/net/third_party/quic/core/quic_connection.cc b/net/third_party/quic/core/quic_connection.cc index c6ca176f..d5460ad 100644 --- a/net/third_party/quic/core/quic_connection.cc +++ b/net/third_party/quic/core/quic_connection.cc
@@ -254,7 +254,6 @@ ack_decimation_delay_(kAckDecimationDelay), unlimited_ack_decimation_(false), fast_ack_after_quiescence_(false), - delay_setting_retransmission_alarm_(false), pending_retransmission_alarm_(false), defer_send_in_response_to_packets_(false), ping_timeout_(QuicTime::Delta::FromSeconds(kPingTimeoutSecs)), @@ -296,8 +295,7 @@ clock_, &stats_, GetQuicReloadableFlag(quic_default_to_bbr) ? kBBR : kCubicBytes, - kNack, - this), + kNack), version_negotiation_state_(START_NEGOTIATION), perspective_(perspective), connected_(true), @@ -319,8 +317,6 @@ processing_ack_frame_(false), supports_release_time_(writer->SupportsReleaseTime()), release_time_into_future_(QuicTime::Delta::Zero()), - deprecate_scheduler_( - GetQuicReloadableFlag(quic_deprecate_scoped_scheduler2)), add_to_blocked_list_if_writer_blocked_( GetQuicReloadableFlag(quic_add_to_blocked_list_if_writer_blocked)), ack_reordered_packets_(GetQuicReloadableFlag(quic_ack_reordered_packets)), @@ -329,9 +325,6 @@ if (ack_mode_ == ACK_DECIMATION) { QUIC_FLAG_COUNT(quic_reloadable_flag_quic_enable_ack_decimation); } - if (deprecate_scheduler_) { - QUIC_FLAG_COUNT(quic_reloadable_flag_quic_deprecate_scoped_scheduler2); - } QUIC_DLOG(INFO) << ENDPOINT << "Created connection with connection_id: " << connection_id << " and version: " @@ -504,15 +497,6 @@ return false; } -QuicString QuicConnection::DebugStringForAckProcessing() const { - return QuicStrCat( - "{sent_packet_manager: ", - sent_packet_manager_.DebugStringForAckProcessing(), - ", largest_seen_pkn_with_ack: ", largest_seen_packet_with_ack_, - ", max_generated_pkn: ", packet_generator_.packet_number(), - ", framer: ", framer_.VerboseDebugString(), "}"); -} - void QuicConnection::OnError(QuicFramer* framer) { // Packets that we can not or have not decrypted are dropped. // TODO(rch): add stats to measure this. @@ -1517,7 +1501,6 @@ // which decrypter will be used on an ack packet following a handshake // packet (a handshake packet from client to server could result in a REJ or a // SHLO from the server, leading to two different decrypters at the server.) - ScopedRetransmissionScheduler alarm_delayer(this); ScopedPacketFlusher flusher(this, SEND_ACK_IF_PENDING); return packet_generator_.ConsumeData(id, write_length, offset, state); } @@ -1649,8 +1632,7 @@ QUIC_DVLOG(1) << ENDPOINT << "time of last received packet: " << time_of_last_received_packet_.ToDebuggingValue(); - ScopedRetransmissionScheduler alarm_delayer(this); - ScopedPacketFlusher flusher(deprecate_scheduler_ ? this : nullptr, NO_ACK); + ScopedPacketFlusher flusher(this, NO_ACK); if (!framer_.ProcessPacket(packet)) { // If we are unable to decrypt this packet, it might be // because the CHLO or SHLO packet was lost. @@ -2105,12 +2087,10 @@ DCHECK_EQ(WRITE_STATUS_BLOCKED, result.status); } - if (GetQuicReloadableFlag(quic_export_connection_write_packet_results)) { - QUIC_HISTOGRAM_ENUM( - "QuicConnection.WritePacketStatus", result.status, - WRITE_STATUS_NUM_VALUES, - "Status code returned by writer_->WritePacket() in QuicConnection."); - } + QUIC_HISTOGRAM_ENUM( + "QuicConnection.WritePacketStatus", result.status, + WRITE_STATUS_NUM_VALUES, + "Status code returned by writer_->WritePacket() in QuicConnection."); if (result.status == WRITE_STATUS_BLOCKED) { // Ensure the writer is still write blocked, otherwise QUIC may continue @@ -2475,13 +2455,11 @@ } while (connected_ && !undecryptable_packets_.empty()) { - if (deprecate_scheduler_) { - // Making sure there is no pending frames when processing next undecrypted - // packet because the queued ack frame may change. - packet_generator_.FlushAllQueuedFrames(); - if (!connected_) { - return; - } + // Making sure there is no pending frames when processing next undecrypted + // packet because the queued ack frame may change. + packet_generator_.FlushAllQueuedFrames(); + if (!connected_) { + return; } QUIC_DVLOG(1) << ENDPOINT << "Attempting to process undecryptable packet"; QuicEncryptedPacket* packet = undecryptable_packets_.front().get(); @@ -2716,7 +2694,7 @@ } void QuicConnection::SetRetransmissionAlarm() { - if (delay_setting_retransmission_alarm_) { + if (packet_generator_.PacketFlusherAttached()) { pending_retransmission_alarm_ = true; return; } @@ -2758,20 +2736,13 @@ QuicConnection* connection, AckBundling ack_mode) : connection_(connection), - flush_on_delete_(false), - set_retransmission_alarm_on_delete_if_pending_(false) { + flush_and_set_pending_retransmission_alarm_on_delete_(false) { if (connection_ == nullptr) { return; } - if (connection_->deprecate_scheduler_) { - set_retransmission_alarm_on_delete_if_pending_ = - !connection_->delay_setting_retransmission_alarm_; - connection_->delay_setting_retransmission_alarm_ = true; - } - if (!connection_->packet_generator_.PacketFlusherAttached()) { - flush_on_delete_ = true; + flush_and_set_pending_retransmission_alarm_on_delete_ = true; connection->packet_generator_.AttachPacketFlusher(); } // If caller wants us to include an ack, check the delayed-ack timer to see if @@ -2810,7 +2781,7 @@ return; } - if (flush_on_delete_) { + if (flush_and_set_pending_retransmission_alarm_on_delete_) { connection_->packet_generator_.Flush(); connection_->FlushPackets(); if (connection_->session_decides_what_to_write()) { @@ -2837,45 +2808,14 @@ // 1 ms, the caller should send at least 125k bytes in order to not // be marked as application-limited. connection_->CheckIfApplicationLimited(); - } - DCHECK_EQ(flush_on_delete_, - !connection_->packet_generator_.PacketFlusherAttached()); - if (connection_->deprecate_scheduler_) { - if (!set_retransmission_alarm_on_delete_if_pending_) { - return; - } - connection_->delay_setting_retransmission_alarm_ = false; if (connection_->pending_retransmission_alarm_) { connection_->SetRetransmissionAlarm(); connection_->pending_retransmission_alarm_ = false; } } -} - -QuicConnection::ScopedRetransmissionScheduler::ScopedRetransmissionScheduler( - QuicConnection* connection) - : connection_(connection), - already_delayed_(connection_->delay_setting_retransmission_alarm_) { - if (connection_->deprecate_scheduler()) { - return; - } - connection_->delay_setting_retransmission_alarm_ = true; -} - -QuicConnection::ScopedRetransmissionScheduler:: - ~ScopedRetransmissionScheduler() { - if (connection_->deprecate_scheduler()) { - return; - } - if (already_delayed_) { - return; - } - connection_->delay_setting_retransmission_alarm_ = false; - if (connection_->pending_retransmission_alarm_) { - connection_->SetRetransmissionAlarm(); - connection_->pending_retransmission_alarm_ = false; - } + DCHECK_EQ(flush_and_set_pending_retransmission_alarm_on_delete_, + !connection_->packet_generator_.PacketFlusherAttached()); } HasRetransmittableData QuicConnection::IsRetransmittable(
diff --git a/net/third_party/quic/core/quic_connection.h b/net/third_party/quic/core/quic_connection.h index 9d5975c..a3ab651c 100644 --- a/net/third_party/quic/core/quic_connection.h +++ b/net/third_party/quic/core/quic_connection.h
@@ -31,7 +31,6 @@ #include "net/third_party/quic/core/quic_alarm_factory.h" #include "net/third_party/quic/core/quic_blocked_writer_interface.h" #include "net/third_party/quic/core/quic_connection_stats.h" -#include "net/third_party/quic/core/quic_debug_info_provider_interface.h" #include "net/third_party/quic/core/quic_framer.h" #include "net/third_party/quic/core/quic_one_block_arena.h" #include "net/third_party/quic/core/quic_packet_creator.h" @@ -308,8 +307,7 @@ }; class QUIC_EXPORT_PRIVATE QuicConnection - : public QuicDebugInfoProviderInterface, - public QuicFramerVisitorInterface, + : public QuicFramerVisitorInterface, public QuicBlockedWriterInterface, public QuicPacketGenerator::DelegateInterface, public QuicSentPacketManager::NetworkChangeVisitor { @@ -453,9 +451,6 @@ return framer_.supported_versions(); } - // From QuicConnectionDebugInfoProviderInterface - QuicString DebugStringForAckProcessing() const override; - // From QuicFramerVisitorInterface void OnError(QuicFramer* framer) override; bool OnProtocolVersionMismatch(ParsedQuicVersion received_version) override; @@ -664,9 +659,10 @@ bool CanWrite(HasRetransmittableData retransmittable); // When the flusher is out of scope, only the outermost flusher will cause a - // flush of the connection. In addition, this flusher can be configured to - // ensure that an ACK frame is included in the first packet created, if - // there's new ack information to be sent. + // flush of the connection and set the retransmission alarm if there is one + // pending. In addition, this flusher can be configured to ensure that an ACK + // frame is included in the first packet created, if there's new ack + // information to be sent. class QUIC_EXPORT_PRIVATE ScopedPacketFlusher { public: // Setting |include_ack| to true ensures that an ACK frame is @@ -678,29 +674,9 @@ bool ShouldSendAck(AckBundling ack_mode) const; QuicConnection* connection_; - // If true, flush connection when this flusher goes out of scope. - bool flush_on_delete_; - // If true, set retransmission alarm if there is one pending when this - // flusher goes out of scope. - // TODO(fayang): Consider to combine flush_on_delete_ and - // set_retransmission_alarm_on_delete_if_pending_ when deprecating - // quic_reloadable_flag_quic_deprecate_scoped_scheduler2. - bool set_retransmission_alarm_on_delete_if_pending_; - }; - - // Delays setting the retransmission alarm until the scope is exited. - // When nested, only the outermost scheduler will set the alarm, and inner - // ones have no effect. - class QUIC_EXPORT_PRIVATE ScopedRetransmissionScheduler { - public: - explicit ScopedRetransmissionScheduler(QuicConnection* connection); - ~ScopedRetransmissionScheduler(); - - private: - QuicConnection* connection_; - // Set to the connection's delay_setting_retransmission_alarm_ value in the - // constructor and when true, causes this class to do nothing. - const bool already_delayed_; + // If true, when this flusher goes out of scope, flush connection and set + // retransmission alarm if there is one pending. + bool flush_and_set_pending_retransmission_alarm_on_delete_; }; QuicPacketWriter* writer() { return writer_; } @@ -792,8 +768,6 @@ bool IsPathDegrading() const { return is_path_degrading_; } - bool deprecate_scheduler() const { return deprecate_scheduler_; } - protected: // Calls cancel() on all the alarms owned by this connection. void CancelAllAlarms(); @@ -1142,9 +1116,6 @@ // was received. bool fast_ack_after_quiescence_; - // Indicates the retransmit alarm is going to be set by the - // ScopedRetransmitAlarmDelayer - bool delay_setting_retransmission_alarm_; // Indicates the retransmission alarm needs to be set. bool pending_retransmission_alarm_; @@ -1315,11 +1286,6 @@ // Time this connection can release packets into the future. QuicTime::Delta release_time_into_future_; - // Latched value of quic_reloadable_flag_quic_deprecate_scoped_scheduler2. - // TODO(fayang): Remove ScopedRetransmissionScheduler when deprecating - // quic_reloadable_flag_quic_deprecate_scoped_scheduler2. - const bool deprecate_scheduler_; - // Latched value of // gfe2_reloadable_flag_quic_add_to_blocked_list_if_writer_blocked. const bool add_to_blocked_list_if_writer_blocked_;
diff --git a/net/third_party/quic/core/quic_connection_test.cc b/net/third_party/quic/core/quic_connection_test.cc index c8be24e..714f521a 100644 --- a/net/third_party/quic/core/quic_connection_test.cc +++ b/net/third_party/quic/core/quic_connection_test.cc
@@ -22,6 +22,7 @@ #include "net/third_party/quic/core/quic_packets.h" #include "net/third_party/quic/core/quic_simple_buffer_allocator.h" #include "net/third_party/quic/core/quic_utils.h" +#include "net/third_party/quic/platform/api/quic_expect_bug.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"
diff --git a/net/third_party/quic/core/quic_data_reader.cc b/net/third_party/quic/core/quic_data_reader.cc index a69bd9d..5a87492 100644 --- a/net/third_party/quic/core/quic_data_reader.cc +++ b/net/third_party/quic/core/quic_data_reader.cc
@@ -9,7 +9,6 @@ #include "net/third_party/quic/platform/api/quic_bug_tracker.h" #include "net/third_party/quic/platform/api/quic_flags.h" #include "net/third_party/quic/platform/api/quic_str_cat.h" -#include "net/third_party/quic/platform/api/quic_text_utils.h" namespace quic { @@ -282,10 +281,5 @@ return QuicStrCat(" { length: ", len_, ", position: ", pos_, " }"); } -QuicString QuicDataReader::VerboseDebugString() const { - return QuicStrCat(" {length: ", len_, ", position: ", pos_, " data:\n", - QuicTextUtils::HexDump(QuicStringPiece(data_, len_)), " }"); -} - #undef ENDPOINT // undef for jumbo builds } // namespace quic
diff --git a/net/third_party/quic/core/quic_data_reader.h b/net/third_party/quic/core/quic_data_reader.h index 053fee6..256ed1b 100644 --- a/net/third_party/quic/core/quic_data_reader.h +++ b/net/third_party/quic/core/quic_data_reader.h
@@ -139,8 +139,6 @@ QuicString DebugString() const; - QuicString VerboseDebugString() const; - private: // Returns true if the underlying buffer has enough room to read the given // amount of bytes.
diff --git a/net/third_party/quic/core/quic_debug_info_provider_interface.h b/net/third_party/quic/core/quic_debug_info_provider_interface.h deleted file mode 100644 index 9d7afa3d..0000000 --- a/net/third_party/quic/core/quic_debug_info_provider_interface.h +++ /dev/null
@@ -1,23 +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. - -#ifndef NET_THIRD_PARTY_QUIC_CORE_QUIC_DEBUG_INFO_PROVIDER_INTERFACE_H_ -#define NET_THIRD_PARTY_QUIC_CORE_QUIC_DEBUG_INFO_PROVIDER_INTERFACE_H_ - -#include "net/third_party/quic/platform/api/quic_export.h" -#include "net/third_party/quic/platform/api/quic_string.h" - -namespace quic { - -class QUIC_EXPORT_PRIVATE QuicDebugInfoProviderInterface { - public: - virtual ~QuicDebugInfoProviderInterface() {} - - // Get ack processing related debug information of the connection. - virtual QuicString DebugStringForAckProcessing() const = 0; -}; - -} // namespace quic - -#endif // NET_THIRD_PARTY_QUIC_CORE_QUIC_DEBUG_INFO_PROVIDER_INTERFACE_H_
diff --git a/net/third_party/quic/core/quic_dispatcher.cc b/net/third_party/quic/core/quic_dispatcher.cc index e2683da1..b863b78 100644 --- a/net/third_party/quic/core/quic_dispatcher.cc +++ b/net/third_party/quic/core/quic_dispatcher.cc
@@ -10,7 +10,6 @@ #include "net/third_party/quic/core/chlo_extractor.h" #include "net/third_party/quic/core/crypto/crypto_protocol.h" #include "net/third_party/quic/core/crypto/quic_random.h" -#include "net/third_party/quic/core/quic_per_connection_packet_writer.h" #include "net/third_party/quic/core/quic_time_wait_list_manager.h" #include "net/third_party/quic/core/quic_utils.h" #include "net/third_party/quic/core/stateless_rejector.h" @@ -950,10 +949,6 @@ return true; } -QuicPacketWriter* QuicDispatcher::CreatePerConnectionWriter() { - return new QuicPerConnectionPacketWriter(writer_.get()); -} - void QuicDispatcher::SetLastError(QuicErrorCode error) { last_error_ = error; }
diff --git a/net/third_party/quic/core/quic_dispatcher.h b/net/third_party/quic/core/quic_dispatcher.h index 1e993440..2b5402a 100644 --- a/net/third_party/quic/core/quic_dispatcher.h +++ b/net/third_party/quic/core/quic_dispatcher.h
@@ -277,13 +277,6 @@ QuicPacketWriter* writer() { return writer_.get(); } - // Creates per-connection packet writers out of the QuicDispatcher's shared - // QuicPacketWriter. The per-connection writers' IsWriteBlocked() state must - // always be the same as the shared writer's IsWriteBlocked(), or else the - // QuicDispatcher::OnCanWrite logic will not work. (This will hopefully be - // cleaned up for bug 16950226.) - virtual QuicPacketWriter* CreatePerConnectionWriter(); - // Returns true if a session should be created for a connection with an // unknown version identified by |version_label|. virtual bool ShouldCreateSessionForUnknownVersion(
diff --git a/net/third_party/quic/core/quic_flags_list.h b/net/third_party/quic/core/quic_flags_list.h index 5600084c..f2aa8d7 100644 --- a/net/third_party/quic/core/quic_flags_list.h +++ b/net/third_party/quic/core/quic_flags_list.h
@@ -118,12 +118,6 @@ // incoming initial RTT values. QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_no_irtt, true) -// If true, put ScopedRetransmissionScheduler's functionality to -// ScopedPacketFlusher. -QUIC_FLAG(bool, - FLAGS_quic_reloadable_flag_quic_deprecate_scoped_scheduler2, - true) - // If it's been more than SRTT since receiving a packet, set the ack alarm for // 1ms instead of the standard delayed ack timer. QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_fast_ack_after_quiescence, true) @@ -140,17 +134,6 @@ // If true, enable QUIC v44. QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_version_44, true) -// If true, export packet write results in QuicConnection. -QUIC_FLAG( - bool, - FLAGS_quic_reloadable_flag_quic_export_connection_write_packet_results, - true) - -// If true, enable extra CHECKs in ack processing to debug b/110029150. -QUIC_FLAG(bool, - FLAGS_quic_reloadable_flag_quic_extra_checks_in_ack_processing, - false) - // If true, close connection if largest observed in ack frame is greater than // largest sent packet. QUIC_FLAG(bool, @@ -180,11 +163,11 @@ // Stop checking QuicUnackedPacketMap::HasUnackedRetransmittableFrames and // instead rely on the existing check that bytes_in_flight > 0 -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_optimize_inflight_check, true) +QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_optimize_inflight_check, false) // When you\'re app-limited entering recovery, stay app-limited until you exit // recovery in QUIC BBR. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_bbr_app_limited_recovery, false) +QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_bbr_app_limited_recovery, true) // If true, mark QUIC as app-limited after sending queued packets or // retransmisssions and we then become congestion control blocked. @@ -211,3 +194,14 @@ // Add 3 connection options to decrease the pacing and CWND gain in QUIC BBR // STARTUP. QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_bbr_slower_startup3, false) + +// When true, the LOSS connection option allows for 1/8 RTT of reording instead +// of the current 1/8th threshold which has been found to be too large for fast +// loss recovery. +QUIC_FLAG(bool, + FLAGS_quic_reloadable_flag_quic_eighth_rtt_loss_detection, + false) + +// Enables the BBQ5 connection option, which forces saved aggregation values to +// expire when the bandwidth increases more than 25% in QUIC BBR STARTUP. +QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_bbr_slower_startup4, false)
diff --git a/net/third_party/quic/core/quic_flow_controller_test.cc b/net/third_party/quic/core/quic_flow_controller_test.cc index fec3945..b4a201b9 100644 --- a/net/third_party/quic/core/quic_flow_controller_test.cc +++ b/net/third_party/quic/core/quic_flow_controller_test.cc
@@ -6,6 +6,7 @@ #include <memory> +#include "net/third_party/quic/platform/api/quic_expect_bug.h" #include "net/third_party/quic/platform/api/quic_ptr_util.h" #include "net/third_party/quic/platform/api/quic_str_cat.h" #include "net/third_party/quic/platform/api/quic_test.h"
diff --git a/net/third_party/quic/core/quic_framer.cc b/net/third_party/quic/core/quic_framer.cc index aa4b529..c289c90 100644 --- a/net/third_party/quic/core/quic_framer.cc +++ b/net/third_party/quic/core/quic_framer.cc
@@ -31,7 +31,6 @@ #include "net/third_party/quic/platform/api/quic_ptr_util.h" #include "net/third_party/quic/platform/api/quic_str_cat.h" #include "net/third_party/quic/platform/api/quic_string.h" -#include "net/third_party/quic/platform/api/quic_string_utils.h" #include "net/third_party/quic/platform/api/quic_text_utils.h" namespace quic { @@ -238,21 +237,6 @@ return static_cast<uint8_t>(length - kConnectionIdLengthAdjustment); } -class TrackedDataReader : public QuicDataReader { - public: - TrackedDataReader(const char* data, - const size_t len, - Endianness endianness, - QuicDataReader** preader) - : QuicDataReader(data, len, endianness), preader_(preader) { - *preader_ = this; - } - ~TrackedDataReader() { *preader_ = nullptr; } - - private: - QuicDataReader** preader_; -}; - } // namespace QuicFramer::QuicFramer(const ParsedQuicVersionVector& supported_versions, @@ -272,8 +256,7 @@ alternative_decrypter_latch_(false), perspective_(perspective), validate_flags_(true), - data_producer_(nullptr), - decrypted_payload_reader_(nullptr) { + data_producer_(nullptr) { DCHECK(!supported_versions.empty()); version_ = supported_versions_[0]; decrypter_ = QuicMakeUnique<NullDecrypter>(perspective); @@ -1213,8 +1196,7 @@ set_detailed_error("Unable to decrypt payload."); return RaiseError(QUIC_DECRYPTION_FAILURE); } - TrackedDataReader reader(decrypted_buffer, decrypted_length, endianness(), - &decrypted_payload_reader_); + QuicDataReader reader(decrypted_buffer, decrypted_length, endianness()); // Update the largest packet number after we have decrypted the packet // so we are confident is not attacker controlled. @@ -1276,8 +1258,7 @@ return RaiseError(QUIC_DECRYPTION_FAILURE); } - TrackedDataReader reader(decrypted_buffer, decrypted_length, endianness(), - &decrypted_payload_reader_); + QuicDataReader reader(decrypted_buffer, decrypted_length, endianness()); // Update the largest packet number after we have decrypted the packet // so we are confident is not attacker controlled. @@ -4461,18 +4442,5 @@ return true; } -QuicString QuicFramer::VerboseDebugString() const { - QuicString str = - QuicStrCat("{ version:", ParsedQuicVersionToString(version_)); - - if (decrypted_payload_reader_ != nullptr) { - QuicStrAppend(&str, " decrypted_payload_reader:", - decrypted_payload_reader_->VerboseDebugString()); - } - - QuicStrAppend(&str, "\n}"); - return str; -} - #undef ENDPOINT // undef for jumbo builds } // namespace quic
diff --git a/net/third_party/quic/core/quic_framer.h b/net/third_party/quic/core/quic_framer.h index e3ac38f..95420ef9 100644 --- a/net/third_party/quic/core/quic_framer.h +++ b/net/third_party/quic/core/quic_framer.h
@@ -462,8 +462,6 @@ return version_.transport_version == QUIC_VERSION_99; } - QuicString VerboseDebugString() const; - private: friend class test::QuicFramerPeer; @@ -766,11 +764,6 @@ // owned. TODO(fayang): Consider add data producer to framer's constructor. QuicStreamFrameDataProducer* data_producer_; - // If the framer is processing a decrypted payload of a data packet, - // |decrypted_payload_reader_| will be set to the reader of that payload, - // otherwise nullptr. - QuicDataReader* decrypted_payload_reader_; - DISALLOW_COPY_AND_ASSIGN(QuicFramer); };
diff --git a/net/third_party/quic/core/quic_framer_test.cc b/net/third_party/quic/core/quic_framer_test.cc index b0e4a6d..329b921 100644 --- a/net/third_party/quic/core/quic_framer_test.cc +++ b/net/third_party/quic/core/quic_framer_test.cc
@@ -17,6 +17,7 @@ #include "net/third_party/quic/core/quic_packets.h" #include "net/third_party/quic/core/quic_utils.h" #include "net/third_party/quic/platform/api/quic_arraysize.h" +#include "net/third_party/quic/platform/api/quic_expect_bug.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"
diff --git a/net/third_party/quic/core/quic_headers_stream_test.cc b/net/third_party/quic/core/quic_headers_stream_test.cc index 86744f0..8016e2a 100644 --- a/net/third_party/quic/core/quic_headers_stream_test.cc +++ b/net/third_party/quic/core/quic_headers_stream_test.cc
@@ -14,6 +14,7 @@ #include "net/third_party/quic/core/quic_utils.h" #include "net/third_party/quic/core/spdy_utils.h" #include "net/third_party/quic/platform/api/quic_bug_tracker.h" +#include "net/third_party/quic/platform/api/quic_expect_bug.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"
diff --git a/net/third_party/quic/core/quic_one_block_arena_test.cc b/net/third_party/quic/core/quic_one_block_arena_test.cc index e89a8ba..dfb5c67 100644 --- a/net/third_party/quic/core/quic_one_block_arena_test.cc +++ b/net/third_party/quic/core/quic_one_block_arena_test.cc
@@ -7,6 +7,7 @@ #include <cstdint> #include "net/third_party/quic/platform/api/quic_containers.h" +#include "net/third_party/quic/platform/api/quic_expect_bug.h" #include "net/third_party/quic/platform/api/quic_test.h" #include "net/third_party/quic/test_tools/quic_test_utils.h"
diff --git a/net/third_party/quic/core/quic_packet_creator_test.cc b/net/third_party/quic/core/quic_packet_creator_test.cc index 269d6fd..c1655e6 100644 --- a/net/third_party/quic/core/quic_packet_creator_test.cc +++ b/net/third_party/quic/core/quic_packet_creator_test.cc
@@ -16,6 +16,7 @@ #include "net/third_party/quic/core/quic_pending_retransmission.h" #include "net/third_party/quic/core/quic_simple_buffer_allocator.h" #include "net/third_party/quic/core/quic_utils.h" +#include "net/third_party/quic/platform/api/quic_expect_bug.h" #include "net/third_party/quic/platform/api/quic_socket_address.h" #include "net/third_party/quic/platform/api/quic_string.h" #include "net/third_party/quic/platform/api/quic_string_piece.h"
diff --git a/net/third_party/quic/core/quic_packet_generator_test.cc b/net/third_party/quic/core/quic_packet_generator_test.cc index a7915d8..4b11b4c 100644 --- a/net/third_party/quic/core/quic_packet_generator_test.cc +++ b/net/third_party/quic/core/quic_packet_generator_test.cc
@@ -14,6 +14,7 @@ #include "net/third_party/quic/core/crypto/quic_encrypter.h" #include "net/third_party/quic/core/quic_simple_buffer_allocator.h" #include "net/third_party/quic/core/quic_utils.h" +#include "net/third_party/quic/platform/api/quic_expect_bug.h" #include "net/third_party/quic/platform/api/quic_socket_address.h" #include "net/third_party/quic/platform/api/quic_string.h" #include "net/third_party/quic/platform/api/quic_string_piece.h"
diff --git a/net/third_party/quic/core/quic_per_connection_packet_writer.cc b/net/third_party/quic/core/quic_per_connection_packet_writer.cc deleted file mode 100644 index 7596eb19..0000000 --- a/net/third_party/quic/core/quic_per_connection_packet_writer.cc +++ /dev/null
@@ -1,58 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/third_party/quic/core/quic_per_connection_packet_writer.h" - -namespace quic { - -QuicPerConnectionPacketWriter::QuicPerConnectionPacketWriter( - QuicPacketWriter* shared_writer) - : shared_writer_(shared_writer) {} - -QuicPerConnectionPacketWriter::~QuicPerConnectionPacketWriter() = default; - -WriteResult QuicPerConnectionPacketWriter::WritePacket( - const char* buffer, - size_t buf_len, - const QuicIpAddress& self_address, - const QuicSocketAddress& peer_address, - PerPacketOptions* options) { - return shared_writer_->WritePacket(buffer, buf_len, self_address, - peer_address, options); -} - -bool QuicPerConnectionPacketWriter::IsWriteBlockedDataBuffered() const { - return shared_writer_->IsWriteBlockedDataBuffered(); -} - -bool QuicPerConnectionPacketWriter::IsWriteBlocked() const { - return shared_writer_->IsWriteBlocked(); -} - -void QuicPerConnectionPacketWriter::SetWritable() { - shared_writer_->SetWritable(); -} - -QuicByteCount QuicPerConnectionPacketWriter::GetMaxPacketSize( - const QuicSocketAddress& peer_address) const { - return shared_writer_->GetMaxPacketSize(peer_address); -} - -bool QuicPerConnectionPacketWriter::SupportsReleaseTime() const { - return shared_writer_->SupportsReleaseTime(); -} - -bool QuicPerConnectionPacketWriter::IsBatchMode() const { - return shared_writer_->IsBatchMode(); -} - -char* QuicPerConnectionPacketWriter::GetNextWriteLocation() const { - return shared_writer_->GetNextWriteLocation(); -} - -WriteResult QuicPerConnectionPacketWriter::Flush() { - return shared_writer_->Flush(); -} - -} // namespace quic
diff --git a/net/third_party/quic/core/quic_per_connection_packet_writer.h b/net/third_party/quic/core/quic_per_connection_packet_writer.h deleted file mode 100644 index 19327e80..0000000 --- a/net/third_party/quic/core/quic_per_connection_packet_writer.h +++ /dev/null
@@ -1,50 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_THIRD_PARTY_QUIC_CORE_QUIC_PER_CONNECTION_PACKET_WRITER_H_ -#define NET_THIRD_PARTY_QUIC_CORE_QUIC_PER_CONNECTION_PACKET_WRITER_H_ - -#include <cstddef> - -#include "base/macros.h" -#include "net/third_party/quic/core/quic_connection.h" -#include "net/third_party/quic/core/quic_packet_writer.h" - -namespace quic { - -// A connection-specific packet writer that wraps a shared writer. -// TODO(wub): Get rid of this class. -class QuicPerConnectionPacketWriter : public QuicPacketWriter { - public: - // Does not take ownership of |shared_writer|. - explicit QuicPerConnectionPacketWriter(QuicPacketWriter* shared_writer); - ~QuicPerConnectionPacketWriter() override; - - // Default implementation of the QuicPacketWriter interface: Passes everything - // to |shared_writer_|. - WriteResult WritePacket(const char* buffer, - size_t buf_len, - const QuicIpAddress& self_address, - const QuicSocketAddress& peer_address, - PerPacketOptions* options) override; - bool IsWriteBlockedDataBuffered() const override; - bool IsWriteBlocked() const override; - void SetWritable() override; - QuicByteCount GetMaxPacketSize( - const QuicSocketAddress& peer_address) const override; - bool SupportsReleaseTime() const override; - - bool IsBatchMode() const override; - char* GetNextWriteLocation() const override; - WriteResult Flush() override; - - private: - QuicPacketWriter* shared_writer_; // Not owned. - - DISALLOW_COPY_AND_ASSIGN(QuicPerConnectionPacketWriter); -}; - -} // namespace quic - -#endif // NET_THIRD_PARTY_QUIC_CORE_QUIC_PER_CONNECTION_PACKET_WRITER_H_
diff --git a/net/third_party/quic/core/quic_sent_packet_manager.cc b/net/third_party/quic/core/quic_sent_packet_manager.cc index 8bc4104..4c82a89 100644 --- a/net/third_party/quic/core/quic_sent_packet_manager.cc +++ b/net/third_party/quic/core/quic_sent_packet_manager.cc
@@ -5,7 +5,6 @@ #include "net/third_party/quic/core/quic_sent_packet_manager.h" #include <algorithm> -#include <sstream> #include "net/third_party/quic/core/congestion_control/general_loss_algorithm.h" #include "net/third_party/quic/core/congestion_control/pacing_sender.h" @@ -58,20 +57,6 @@ QuicConnectionStats* stats, CongestionControlType congestion_control_type, LossDetectionType loss_type) - : QuicSentPacketManager(perspective, - clock, - stats, - congestion_control_type, - loss_type, - this) {} - -QuicSentPacketManager::QuicSentPacketManager( - Perspective perspective, - const QuicClock* clock, - QuicConnectionStats* stats, - CongestionControlType congestion_control_type, - LossDetectionType loss_type, - QuicDebugInfoProviderInterface* debug_info_provider) : unacked_packets_(), perspective_(perspective), clock_(clock), @@ -106,25 +91,12 @@ delayed_ack_time_( QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs)), rtt_updated_(false), - extra_checks_in_ack_processing_( - GetQuicReloadableFlag(quic_extra_checks_in_ack_processing)), - debug_info_provider_(debug_info_provider), acked_packets_iter_(last_ack_frame_.packets.rbegin()) { SetSendAlgorithm(congestion_control_type); } QuicSentPacketManager::~QuicSentPacketManager() {} -QuicString QuicSentPacketManager::DebugStringForAckProcessing() const { - std::ostringstream s; - s << "{ last_ack_frame: " << last_ack_frame_ - << ", largest_observed: " << GetLargestObserved() - << ", least_unacked: " << unacked_packets_.GetLeastUnacked() - << ", unacked_packets_size: " << unacked_packets_.Size() - << ", packets_acked: " << packets_acked_ << " }"; - return s.str(); -} - void QuicSentPacketManager::SetFromConfig(const QuicConfig& config) { if (config.HasReceivedInitialRoundTripTimeUs() && config.ReceivedInitialRoundTripTimeUs() > 0) { @@ -507,16 +479,8 @@ QuicPacketNumber QuicSentPacketManager::GetNewestRetransmission( QuicPacketNumber packet_number, const QuicTransmissionInfo& transmission_info) const { - const QuicPacketNumber original_packet_number = packet_number; QuicPacketNumber retransmission = transmission_info.retransmission; while (retransmission != 0) { - if (extra_checks_in_ack_processing_) { - CHECK(unacked_packets_.Contains(retransmission)) - << "Retransmisstted pkn out of bound. original_pkn: " - << original_packet_number << ", last_retrans_pkn: " << packet_number - << ", oob_retrans_pkn: " << retransmission - << " Context:" << debug_info_provider_->DebugStringForAckProcessing(); - } packet_number = retransmission; retransmission = unacked_packets_.GetTransmissionInfo(retransmission).retransmission; @@ -1061,11 +1025,6 @@ // Reverse packets_acked_ so that it is in ascending order. reverse(packets_acked_.begin(), packets_acked_.end()); for (AckedPacket& acked_packet : packets_acked_) { - if (extra_checks_in_ack_processing_) { - CHECK(unacked_packets_.Contains(acked_packet.packet_number)) - << "Acked pkn out of bound. pkn: " << acked_packet.packet_number - << " Context:" << debug_info_provider_->DebugStringForAckProcessing(); - } QuicTransmissionInfo* info = unacked_packets_.GetMutableTransmissionInfo(acked_packet.packet_number); if (!QuicUtils::IsAckable(info->state)) {
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 7037836..ef8e796 100644 --- a/net/third_party/quic/core/quic_sent_packet_manager.h +++ b/net/third_party/quic/core/quic_sent_packet_manager.h
@@ -19,7 +19,6 @@ #include "net/third_party/quic/core/congestion_control/rtt_stats.h" #include "net/third_party/quic/core/congestion_control/send_algorithm_interface.h" #include "net/third_party/quic/core/proto/cached_network_parameters.pb.h" -#include "net/third_party/quic/core/quic_debug_info_provider_interface.h" #include "net/third_party/quic/core/quic_packets.h" #include "net/third_party/quic/core/quic_pending_retransmission.h" #include "net/third_party/quic/core/quic_sustained_bandwidth_recorder.h" @@ -46,8 +45,7 @@ // retransmittable data associated with each packet. If a packet is // retransmitted, it will keep track of each version of a packet so that if a // previous transmission is acked, the data will not be retransmitted. -class QUIC_EXPORT_PRIVATE QuicSentPacketManager - : public QuicDebugInfoProviderInterface { +class QUIC_EXPORT_PRIVATE QuicSentPacketManager { public: // Interface which gets callbacks from the QuicSentPacketManager at // interesting points. Implementations must not mutate the state of @@ -91,19 +89,8 @@ QuicConnectionStats* stats, CongestionControlType congestion_control_type, LossDetectionType loss_type); - - QuicSentPacketManager(Perspective perspective, - const QuicClock* clock, - QuicConnectionStats* stats, - CongestionControlType congestion_control_type, - LossDetectionType loss_type, - QuicDebugInfoProviderInterface* debug_info_provider); - virtual ~QuicSentPacketManager(); - // From QuicDebugInfoProviderInterface - QuicString DebugStringForAckProcessing() const override; - virtual void SetFromConfig(const QuicConfig& config); // Pass the CachedNetworkParameters to the send algorithm. @@ -561,10 +548,6 @@ // Record whether RTT gets updated by last largest acked.. bool rtt_updated_; - // Latched value of quic_reloadable_flag_quic_extra_checks_in_ack_processing. - const bool extra_checks_in_ack_processing_; - QuicDebugInfoProviderInterface* debug_info_provider_; - // A reverse iterator of last_ack_frame_.packets. This is reset in // OnAckRangeStart, and gradually moves in OnAckRange.. PacketNumberQueue::const_reverse_iterator acked_packets_iter_;
diff --git a/net/third_party/quic/core/quic_server_session_base_test.cc b/net/third_party/quic/core/quic_server_session_base_test.cc index 538c1bf..8ef5d3a 100644 --- a/net/third_party/quic/core/quic_server_session_base_test.cc +++ b/net/third_party/quic/core/quic_server_session_base_test.cc
@@ -17,6 +17,7 @@ #include "net/third_party/quic/core/quic_epoll_connection_helper.h" #include "net/third_party/quic/core/quic_utils.h" #include "net/third_party/quic/core/tls_server_handshaker.h" +#include "net/third_party/quic/platform/api/quic_expect_bug.h" #include "net/third_party/quic/platform/api/quic_flags.h" #include "net/third_party/quic/platform/api/quic_ptr_util.h" #include "net/third_party/quic/platform/api/quic_socket_address.h"
diff --git a/net/third_party/quic/core/quic_session_test.cc b/net/third_party/quic/core/quic_session_test.cc index d6a8874..8d0d234 100644 --- a/net/third_party/quic/core/quic_session_test.cc +++ b/net/third_party/quic/core/quic_session_test.cc
@@ -15,6 +15,7 @@ #include "net/third_party/quic/core/quic_packets.h" #include "net/third_party/quic/core/quic_stream.h" #include "net/third_party/quic/core/quic_utils.h" +#include "net/third_party/quic/platform/api/quic_expect_bug.h" #include "net/third_party/quic/platform/api/quic_flags.h" #include "net/third_party/quic/platform/api/quic_map_util.h" #include "net/third_party/quic/platform/api/quic_ptr_util.h"
diff --git a/net/third_party/quic/core/quic_spdy_session_test.cc b/net/third_party/quic/core/quic_spdy_session_test.cc index 8696d8fe..5edfb7e 100644 --- a/net/third_party/quic/core/quic_spdy_session_test.cc +++ b/net/third_party/quic/core/quic_spdy_session_test.cc
@@ -15,6 +15,7 @@ #include "net/third_party/quic/core/quic_packets.h" #include "net/third_party/quic/core/quic_stream.h" #include "net/third_party/quic/core/quic_utils.h" +#include "net/third_party/quic/platform/api/quic_expect_bug.h" #include "net/third_party/quic/platform/api/quic_flags.h" #include "net/third_party/quic/platform/api/quic_map_util.h" #include "net/third_party/quic/platform/api/quic_ptr_util.h"
diff --git a/net/third_party/quic/core/quic_spdy_stream_test.cc b/net/third_party/quic/core/quic_spdy_stream_test.cc index 01584c2..f2a9963 100644 --- a/net/third_party/quic/core/quic_spdy_stream_test.cc +++ b/net/third_party/quic/core/quic_spdy_stream_test.cc
@@ -12,6 +12,7 @@ #include "net/third_party/quic/core/quic_write_blocked_list.h" #include "net/third_party/quic/core/spdy_utils.h" #include "net/third_party/quic/platform/api/quic_arraysize.h" +#include "net/third_party/quic/platform/api/quic_expect_bug.h" #include "net/third_party/quic/platform/api/quic_map_util.h" #include "net/third_party/quic/platform/api/quic_ptr_util.h" #include "net/third_party/quic/platform/api/quic_string.h"
diff --git a/net/third_party/quic/core/quic_stream.cc b/net/third_party/quic/core/quic_stream.cc index fceba632..98c4be6 100644 --- a/net/third_party/quic/core/quic_stream.cc +++ b/net/third_party/quic/core/quic_stream.cc
@@ -505,15 +505,9 @@ // written on this stream before termination. Done here if needed, using a // RST_STREAM frame. QUIC_DLOG(INFO) << ENDPOINT << "Sending RST_STREAM in OnClose: " << id(); - if (session_->connection()->deprecate_scheduler()) { - session_->SendRstStream(id(), QUIC_RST_ACKNOWLEDGEMENT, - stream_bytes_written()); - session_->OnStreamDoneWaitingForAcks(id_); - } else { - session_->OnStreamDoneWaitingForAcks(id_); - session_->SendRstStream(id(), QUIC_RST_ACKNOWLEDGEMENT, - stream_bytes_written()); - } + session_->SendRstStream(id(), QUIC_RST_ACKNOWLEDGEMENT, + stream_bytes_written()); + session_->OnStreamDoneWaitingForAcks(id_); rst_sent_ = true; }
diff --git a/net/third_party/quic/core/quic_stream_send_buffer_test.cc b/net/third_party/quic/core/quic_stream_send_buffer_test.cc index cfc01db..0cc45f7f 100644 --- a/net/third_party/quic/core/quic_stream_send_buffer_test.cc +++ b/net/third_party/quic/core/quic_stream_send_buffer_test.cc
@@ -7,6 +7,7 @@ #include "net/third_party/quic/core/quic_data_writer.h" #include "net/third_party/quic/core/quic_simple_buffer_allocator.h" #include "net/third_party/quic/core/quic_utils.h" +#include "net/third_party/quic/platform/api/quic_expect_bug.h" #include "net/third_party/quic/platform/api/quic_flags.h" #include "net/third_party/quic/platform/api/quic_string.h" #include "net/third_party/quic/platform/api/quic_test.h" @@ -104,8 +105,8 @@ // Invalid data copy. QuicDataWriter writer3(4000, buf, HOST_BYTE_ORDER); EXPECT_FALSE(send_buffer_.WriteStreamData(3000, 1024, &writer3)); - EXPECT_DFATAL(send_buffer_.WriteStreamData(0, 4000, &writer3), - "Writer fails to write."); + EXPECT_QUIC_BUG(send_buffer_.WriteStreamData(0, 4000, &writer3), + "Writer fails to write."); send_buffer_.OnStreamDataConsumed(3840); EXPECT_EQ(3840u, send_buffer_.stream_bytes_written());
diff --git a/net/third_party/quic/core/quic_stream_sequencer_test.cc b/net/third_party/quic/core/quic_stream_sequencer_test.cc index 1b4b637..3dd4db9 100644 --- a/net/third_party/quic/core/quic_stream_sequencer_test.cc +++ b/net/third_party/quic/core/quic_stream_sequencer_test.cc
@@ -15,6 +15,7 @@ #include "net/third_party/quic/core/quic_stream.h" #include "net/third_party/quic/core/quic_utils.h" #include "net/third_party/quic/platform/api/quic_arraysize.h" +#include "net/third_party/quic/platform/api/quic_expect_bug.h" #include "net/third_party/quic/platform/api/quic_logging.h" #include "net/third_party/quic/platform/api/quic_string.h" #include "net/third_party/quic/platform/api/quic_string_piece.h"
diff --git a/net/third_party/quic/core/quic_stream_test.cc b/net/third_party/quic/core/quic_stream_test.cc index 508d090..fade002 100644 --- a/net/third_party/quic/core/quic_stream_test.cc +++ b/net/third_party/quic/core/quic_stream_test.cc
@@ -9,7 +9,6 @@ #include "net/third_party/quic/core/quic_connection.h" #include "net/third_party/quic/core/quic_utils.h" #include "net/third_party/quic/core/quic_write_blocked_list.h" -#include "net/third_party/quic/core/spdy_utils.h" #include "net/third_party/quic/platform/api/quic_arraysize.h" #include "net/third_party/quic/platform/api/quic_expect_bug.h" #include "net/third_party/quic/platform/api/quic_flags.h" @@ -26,7 +25,6 @@ #include "net/third_party/quic/test_tools/quic_stream_sequencer_peer.h" #include "net/third_party/quic/test_tools/quic_test_utils.h" -using spdy::SpdyHeaderBlock; using testing::_; using testing::AnyNumber; using testing::AtLeast; @@ -74,33 +72,6 @@ : initial_flow_control_window_bytes_(kMaxPacketSize), zero_(QuicTime::Delta::Zero()), supported_versions_(AllSupportedVersions()) { - headers_[":host"] = "www.google.com"; - headers_[":path"] = "/index.hml"; - headers_[":scheme"] = "https"; - headers_["cookie"] = - "__utma=208381060.1228362404.1372200928.1372200928.1372200928.1; " - "__utmc=160408618; " - "GX=DQAAAOEAAACWJYdewdE9rIrW6qw3PtVi2-d729qaa-74KqOsM1NVQblK4VhX" - "hoALMsy6HOdDad2Sz0flUByv7etmo3mLMidGrBoljqO9hSVA40SLqpG_iuKKSHX" - "RW3Np4bq0F0SDGDNsW0DSmTS9ufMRrlpARJDS7qAI6M3bghqJp4eABKZiRqebHT" - "pMU-RXvTI5D5oCF1vYxYofH_l1Kviuiy3oQ1kS1enqWgbhJ2t61_SNdv-1XJIS0" - "O3YeHLmVCs62O6zp89QwakfAWK9d3IDQvVSJzCQsvxvNIvaZFa567MawWlXg0Rh" - "1zFMi5vzcns38-8_Sns; " - "GA=v*2%2Fmem*57968640*47239936%2Fmem*57968640*47114716%2Fno-nm-" - "yj*15%2Fno-cc-yj*5%2Fpc-ch*133685%2Fpc-s-cr*133947%2Fpc-s-t*1339" - "47%2Fno-nm-yj*4%2Fno-cc-yj*1%2Fceft-as*1%2Fceft-nqas*0%2Fad-ra-c" - "v_p%2Fad-nr-cv_p-f*1%2Fad-v-cv_p*859%2Fad-ns-cv_p-f*1%2Ffn-v-ad%" - "2Fpc-t*250%2Fpc-cm*461%2Fpc-s-cr*722%2Fpc-s-t*722%2Fau_p*4" - "SICAID=AJKiYcHdKgxum7KMXG0ei2t1-W4OD1uW-ecNsCqC0wDuAXiDGIcT_HA2o1" - "3Rs1UKCuBAF9g8rWNOFbxt8PSNSHFuIhOo2t6bJAVpCsMU5Laa6lewuTMYI8MzdQP" - "ARHKyW-koxuhMZHUnGBJAM1gJODe0cATO_KGoX4pbbFxxJ5IicRxOrWK_5rU3cdy6" - "edlR9FsEdH6iujMcHkbE5l18ehJDwTWmBKBzVD87naobhMMrF6VvnDGxQVGp9Ir_b" - "Rgj3RWUoPumQVCxtSOBdX0GlJOEcDTNCzQIm9BSfetog_eP_TfYubKudt5eMsXmN6" - "QnyXHeGeK2UINUzJ-D30AFcpqYgH9_1BvYSpi7fc7_ydBU8TaD8ZRxvtnzXqj0RfG" - "tuHghmv3aD-uzSYJ75XDdzKdizZ86IG6Fbn1XFhYZM-fbHhm3mVEXnyRW4ZuNOLFk" - "Fas6LMcVC6Q8QLlHYbXBpdNFuGbuZGUnav5C-2I_-46lL0NGg3GewxGKGHvHEfoyn" - "EFFlEYHsBQ98rXImL8ySDycdLEFvBPdtctPmWCfTxwmoSMLHU2SCVDhbqMWU5b0yr" - "JBCScs_ejbKaqBDoB7ZGxTvqlrB__2ZmnHHjCr8RgMRtKNtIeuZAo "; } void Initialize(bool stream_should_process_data) { @@ -156,7 +127,6 @@ MockQuicConnection* connection_; std::unique_ptr<MockQuicSession> session_; TestStream* stream_; - SpdyHeaderBlock headers_; QuicWriteBlockedList* write_blocked_list_; uint32_t initial_flow_control_window_bytes_; QuicTime::Delta zero_;
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 4587ccc..ef14e46 100644 --- a/net/third_party/quic/core/quic_unacked_packet_map.h +++ b/net/third_party/quic/core/quic_unacked_packet_map.h
@@ -39,15 +39,6 @@ QuicTime sent_time, bool set_in_flight); - // Returns true iff |packet_number| is in the map. - bool Contains(QuicPacketNumber packet_number) const { - return packet_number >= least_unacked_ && - packet_number < least_unacked_ + unacked_packets_.size(); - } - - // Returns the number of packets in the map. - size_t Size() const { return unacked_packets_.size(); } - // Returns true if the packet |packet_number| is unacked. bool IsUnacked(QuicPacketNumber packet_number) const;
diff --git a/net/third_party/quic/platform/api/quic_expect_bug.h b/net/third_party/quic/platform/api/quic_expect_bug.h index 3afb2c9..d32305c 100644 --- a/net/third_party/quic/platform/api/quic_expect_bug.h +++ b/net/third_party/quic/platform/api/quic_expect_bug.h
@@ -3,6 +3,7 @@ #include "net/third_party/quic/platform/impl/quic_expect_bug_impl.h" +#define EXPECT_QUIC_BUG EXPECT_QUIC_BUG_IMPL #define EXPECT_QUIC_PEER_BUG(statement, regex) \ EXPECT_QUIC_PEER_BUG_IMPL(statement, regex)
diff --git a/net/third_party/quic/platform/impl/quic_expect_bug_impl.h b/net/third_party/quic/platform/impl/quic_expect_bug_impl.h index 5bef353..eb9f579 100644 --- a/net/third_party/quic/platform/impl/quic_expect_bug_impl.h +++ b/net/third_party/quic/platform/impl/quic_expect_bug_impl.h
@@ -1,6 +1,9 @@ #ifndef NET_THIRD_PARTY_QUIC_PLATFORM_IMPL_QUIC_EXPECT_BUG_IMPL_H_ #define NET_THIRD_PARTY_QUIC_PLATFORM_IMPL_QUIC_EXPECT_BUG_IMPL_H_ +#include "net/test/gtest_util.h" + +#define EXPECT_QUIC_BUG_IMPL EXPECT_DFATAL #define EXPECT_QUIC_PEER_BUG_IMPL(statement, regex) statement; #endif // NET_THIRD_PARTY_QUIC_PLATFORM_IMPL_QUIC_EXPECT_BUG_IMPL_H_
diff --git a/net/third_party/quic/quartc/quartc_factory.cc b/net/third_party/quic/quartc/quartc_factory.cc index 0dc5d2e..099808c 100644 --- a/net/third_party/quic/quartc/quartc_factory.cc +++ b/net/third_party/quic/quartc/quartc_factory.cc
@@ -117,14 +117,6 @@ QuicMakeUnique<QuartcPacketWriter>(quartc_session_config.packet_transport, quartc_session_config.max_packet_size); - // This setting fixes an issue with excessive ACKs being sent for reordered - // packets, and instead bundles those ACKs better together. Combined with - // ACK_DECIMATION_WITH_REORDERING we reduce the number of excessive ACKs - // significantly. (Each one of the two features reduces ACKs by ~20%, but - // together they reduce number of standalone acks by 25-30%). - // This flag must be set before quic connection is created. - SetQuicReloadableFlag(quic_deprecate_scoped_scheduler2, true); - // ACK less aggressively when reordered packets are present. // Must be set before the connection is created. SetQuicReloadableFlag(quic_ack_reordered_packets, true); @@ -140,6 +132,9 @@ SetQuicReloadableFlag(quic_enable_ack_decimation, false); copt.push_back(kAKD2); + // Enable time-based loss detection. + copt.push_back(kTIME); + if (quartc_session_config.congestion_control == QuartcCongestionControl::kBBR) { copt.push_back(kTBBR);
diff --git a/net/third_party/quic/test_tools/quic_test_server.cc b/net/third_party/quic/test_tools/quic_test_server.cc index ac575b9b..edcef09 100644 --- a/net/third_party/quic/test_tools/quic_test_server.cc +++ b/net/third_party/quic/test_tools/quic_test_server.cc
@@ -94,10 +94,10 @@ crypto_stream_factory_ == nullptr) { return QuicSimpleDispatcher::CreateQuicSession(id, client, alpn); } - QuicConnection* connection = new QuicConnection( - id, client, helper(), alarm_factory(), CreatePerConnectionWriter(), - /* owns_writer= */ true, Perspective::IS_SERVER, - GetSupportedVersions()); + QuicConnection* connection = + new QuicConnection(id, client, helper(), alarm_factory(), writer(), + /* owns_writer= */ false, Perspective::IS_SERVER, + GetSupportedVersions()); QuicServerSessionBase* session = nullptr; if (stream_factory_ != nullptr || crypto_stream_factory_ != nullptr) {
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 5e8b458..b3b4b422 100644 --- a/net/third_party/quic/test_tools/quic_test_utils.h +++ b/net/third_party/quic/test_tools/quic_test_utils.h
@@ -22,7 +22,6 @@ #include "net/third_party/quic/core/quic_connection.h" #include "net/third_party/quic/core/quic_connection_close_delegate_interface.h" #include "net/third_party/quic/core/quic_framer.h" -#include "net/third_party/quic/core/quic_per_connection_packet_writer.h" #include "net/third_party/quic/core/quic_sent_packet_manager.h" #include "net/third_party/quic/core/quic_server_session_base.h" #include "net/third_party/quic/core/quic_simple_buffer_allocator.h" @@ -33,13 +32,6 @@ #include "net/third_party/quic/test_tools/mock_random.h" #include "testing/gmock/include/gmock/gmock.h" -// EXPECT_QUIC_BUG is like EXPECT_DFATAL, except it ensures that no DFATAL -// logging is skipped due to exponential backoff. -// -// For external QUIC, EXPECT_QUIC_BUG should be #defined to EXPECT_DFATAL. -// TODO(danzh): Move to third_party/quic/platform/api/quic_expect_bug.h. -#define EXPECT_QUIC_BUG EXPECT_DFATAL - namespace quic { namespace test {
diff --git a/net/third_party/quic/tools/quic_simple_dispatcher.cc b/net/third_party/quic/tools/quic_simple_dispatcher.cc index 41979cd1..21fc0e9 100644 --- a/net/third_party/quic/tools/quic_simple_dispatcher.cc +++ b/net/third_party/quic/tools/quic_simple_dispatcher.cc
@@ -52,9 +52,8 @@ QuicStringPiece /*alpn*/) { // The QuicServerSessionBase takes ownership of |connection| below. QuicConnection* connection = new QuicConnection( - connection_id, client_address, helper(), alarm_factory(), - CreatePerConnectionWriter(), - /* owns_writer= */ true, Perspective::IS_SERVER, GetSupportedVersions()); + connection_id, client_address, helper(), alarm_factory(), writer(), + /* owns_writer= */ false, Perspective::IS_SERVER, GetSupportedVersions()); QuicServerSessionBase* session = new QuicSimpleServerSession( config(), connection, this, session_helper(), crypto_config(),
diff --git a/net/third_party/quic/tools/quic_simple_server_session_test.cc b/net/third_party/quic/tools/quic_simple_server_session_test.cc index 2c8718e..8352e96a 100644 --- a/net/third_party/quic/tools/quic_simple_server_session_test.cc +++ b/net/third_party/quic/tools/quic_simple_server_session_test.cc
@@ -17,6 +17,7 @@ #include "net/third_party/quic/core/quic_utils.h" #include "net/third_party/quic/core/tls_server_handshaker.h" #include "net/third_party/quic/platform/api/quic_containers.h" +#include "net/third_party/quic/platform/api/quic_expect_bug.h" #include "net/third_party/quic/platform/api/quic_flags.h" #include "net/third_party/quic/platform/api/quic_ptr_util.h" #include "net/third_party/quic/platform/api/quic_socket_address.h"
diff --git a/net/third_party/quic/tools/quic_simple_server_stream_test.cc b/net/third_party/quic/tools/quic_simple_server_stream_test.cc index 428933de..771a7c4 100644 --- a/net/third_party/quic/tools/quic_simple_server_stream_test.cc +++ b/net/third_party/quic/tools/quic_simple_server_stream_test.cc
@@ -13,6 +13,7 @@ #include "net/third_party/quic/core/spdy_utils.h" #include "net/third_party/quic/core/tls_server_handshaker.h" #include "net/third_party/quic/platform/api/quic_arraysize.h" +#include "net/third_party/quic/platform/api/quic_expect_bug.h" #include "net/third_party/quic/platform/api/quic_ptr_util.h" #include "net/third_party/quic/platform/api/quic_socket_address.h" #include "net/third_party/quic/platform/api/quic_test.h"
diff --git a/pdf/out_of_process_instance.cc b/pdf/out_of_process_instance.cc index a82d74a..0358d15f 100644 --- a/pdf/out_of_process_instance.cc +++ b/pdf/out_of_process_instance.cc
@@ -162,9 +162,6 @@ const char kJSFieldFocusType[] = "formFocusChange"; const char kJSFieldFocus[] = "focused"; -// Notify when a save attempt has occured (Plugin -> Page) -const char kJSSaveCalledType[] = "saveCalled"; - const int kFindResultCooldownMs = 100; // Same value as printing::COMPLETE_PREVIEW_DOCUMENT_INDEX. @@ -1911,12 +1908,6 @@ return top_toolbar_height_in_viewport_coords_ * device_scale_; } -void OutOfProcessInstance::SaveCalled() { - pp::VarDictionary message; - message.Set(pp::Var(kType), pp::Var(kJSSaveCalledType)); - PostMessage(message); -} - void OutOfProcessInstance::ProcessPreviewPageInfo(const std::string& url, int dest_page_index) { DCHECK(IsPrintPreview());
diff --git a/pdf/out_of_process_instance.h b/pdf/out_of_process_instance.h index ed808b6..18ce432 100644 --- a/pdf/out_of_process_instance.h +++ b/pdf/out_of_process_instance.h
@@ -152,7 +152,6 @@ void SelectionChanged(const pp::Rect& left, const pp::Rect& right) override; void IsEditModeChanged(bool is_edit_mode) override; float GetToolbarHeightInScreenCoords() override; - void SaveCalled() override; // PreviewModeClient::Client implementation. void PreviewDocumentLoadComplete() override;
diff --git a/pdf/pdf_engine.h b/pdf/pdf_engine.h index 7ac39f9..b8be454 100644 --- a/pdf/pdf_engine.h +++ b/pdf/pdf_engine.h
@@ -275,9 +275,6 @@ // Gets the height of the top toolbar in screen coordinates. This is // independent of whether it is hidden or not at the moment. virtual float GetToolbarHeightInScreenCoords() = 0; - - // Notifies the client that there was an attempt to save the document - virtual void SaveCalled() {} }; // Factory method to create an instance of the PDF Engine.
diff --git a/pdf/pdfium/pdfium_engine.cc b/pdf/pdfium/pdfium_engine.cc index 73372929..d67cb1a 100644 --- a/pdf/pdfium/pdfium_engine.cc +++ b/pdf/pdfium/pdfium_engine.cc
@@ -2703,7 +2703,6 @@ if (document_->form_status() != PDF_FORM_NOTAVAIL || doc_loader_->IsDocumentComplete()) { document_->InitializeForm(&form_filler_); - form_filler_.RegisterSaveCalledHandler(); #if defined(PDF_ENABLE_XFA) FPDF_LoadXFA(doc()); #endif
diff --git a/pdf/pdfium/pdfium_form_filler.cc b/pdf/pdfium/pdfium_form_filler.cc index dce0645..c64ccaf 100644 --- a/pdf/pdfium/pdfium_form_filler.cc +++ b/pdf/pdfium/pdfium_form_filler.cc
@@ -82,10 +82,6 @@ PDFiumFormFiller::~PDFiumFormFiller() = default; -void PDFiumFormFiller::RegisterSaveCalledHandler() { - FORM_SetSaveCallback(engine_->form(), PDFiumFormFiller::Form_SaveCalled); -} - // static void PDFiumFormFiller::Form_Invalidate(FPDF_FORMFILLINFO* param, FPDF_PAGE page, @@ -271,11 +267,6 @@ engine->ScrollToPage(page_index); } -// static -void PDFiumFormFiller::Form_SaveCalled(FPDF_FORMFILLINFO* param) { - GetEngine(param)->client_->SaveCalled(); -} - #if defined(PDF_ENABLE_XFA) // static
diff --git a/pdf/pdfium/pdfium_form_filler.h b/pdf/pdfium/pdfium_form_filler.h index 65799958..df4c7fb3 100644 --- a/pdf/pdfium/pdfium_form_filler.h +++ b/pdf/pdfium/pdfium_form_filler.h
@@ -22,8 +22,6 @@ PDFiumFormFiller(PDFiumEngine* engine, bool enable_javascript); ~PDFiumFormFiller(); - void RegisterSaveCalledHandler(); - private: // FPDF_FORMFILLINFO callbacks. static void Form_Invalidate(FPDF_FORMFILLINFO* param, @@ -63,7 +61,6 @@ int zoom_mode, float* position_array, int size_of_array); - static void Form_SaveCalled(FPDF_FORMFILLINFO* param); #if defined(PDF_ENABLE_XFA) static void Form_EmailTo(FPDF_FORMFILLINFO* param,
diff --git a/ppapi/shared_impl/private/ppb_x509_certificate_private_shared.cc b/ppapi/shared_impl/private/ppb_x509_certificate_private_shared.cc index be869c8..6ffff36 100644 --- a/ppapi/shared_impl/private/ppb_x509_certificate_private_shared.cc +++ b/ppapi/shared_impl/private/ppb_x509_certificate_private_shared.cc
@@ -65,7 +65,7 @@ } case base::Value::Type::BINARY: { uint32_t size = static_cast<uint32_t>(value->GetBlob().size()); - const char* buffer = value->GetBlob().data(); + const uint8_t* buffer = value->GetBlob().data(); PP_Var array_buffer = PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(size, buffer);
diff --git a/remoting/base/chromoting_event.cc b/remoting/base/chromoting_event.cc index 92c1625..d4c614ee 100644 --- a/remoting/base/chromoting_event.cc +++ b/remoting/base/chromoting_event.cc
@@ -116,6 +116,7 @@ const char ChromotingEvent::kRoleKey[] = "role"; const char ChromotingEvent::kRoundtripLatencyKey[] = "roundtrip_latency"; const char ChromotingEvent::kSessionDurationKey[] = "session_duration"; +const char ChromotingEvent::kSessionEntryPointKey[] = "session_entry_point"; const char ChromotingEvent::kSessionIdKey[] = "session_id"; const char ChromotingEvent::kSessionStateKey[] = "session_state"; const char ChromotingEvent::kTypeKey[] = "type";
diff --git a/remoting/base/chromoting_event.h b/remoting/base/chromoting_event.h index c624d628..5778def 100644 --- a/remoting/base/chromoting_event.h +++ b/remoting/base/chromoting_event.h
@@ -88,6 +88,13 @@ CREATING_PLUGIN = 17, }; + enum SessionEntryPoint { + CONNECT_BUTTON = 1, + RECONNECT_BUTTON = 2, + AUTO_RECONNECT_ON_CONNECTION_DROPPED = 3, + AUTO_RECONNECT_ON_HOST_OFFLINE = 4, + }; + enum class Type { SESSION_STATE = 1, CONNECTION_STATISTICS = 2, @@ -123,6 +130,7 @@ static const char kRoleKey[]; static const char kRoundtripLatencyKey[]; static const char kSessionDurationKey[]; + static const char kSessionEntryPointKey[]; static const char kSessionIdKey[]; static const char kSessionStateKey[]; static const char kTypeKey[];
diff --git a/remoting/client/chromoting_session.cc b/remoting/client/chromoting_session.cc index fc54f9e..6736b978 100644 --- a/remoting/client/chromoting_session.cc +++ b/remoting/client/chromoting_session.cc
@@ -593,7 +593,8 @@ DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread()); logger_ = std::make_unique<ClientTelemetryLogger>( - runtime_->log_writer(), ChromotingEvent::Mode::ME2ME); + runtime_->log_writer(), ChromotingEvent::Mode::ME2ME, + info.session_entry_point); // logger is set when connection is started. session_context_ = std::make_unique<SessionContext>();
diff --git a/remoting/client/client_telemetry_logger.cc b/remoting/client/client_telemetry_logger.cc index de66358..5d532c6 100644 --- a/remoting/client/client_telemetry_logger.cc +++ b/remoting/client/client_telemetry_logger.cc
@@ -33,8 +33,12 @@ ClientTelemetryLogger::ClientTelemetryLogger( ChromotingEventLogWriter* log_writer, - ChromotingEvent::Mode mode) - : mode_(mode), log_writer_(log_writer), weak_factory_(this) { + ChromotingEvent::Mode mode, + ChromotingEvent::SessionEntryPoint entry_point) + : mode_(mode), + entry_point_(entry_point), + log_writer_(log_writer), + weak_factory_(this) { thread_checker_.DetachFromThread(); } @@ -214,6 +218,7 @@ void ClientTelemetryLogger::FillEventContext(ChromotingEvent* event) const { event->SetEnum(ChromotingEvent::kModeKey, mode_); event->SetEnum(ChromotingEvent::kRoleKey, ChromotingEvent::Role::CLIENT); + event->SetEnum(ChromotingEvent::kSessionEntryPointKey, entry_point_); if (auth_method_ != ChromotingEvent::AuthMethod::NOT_SET) { event->SetEnum(ChromotingEvent::kAuthMethodKey, auth_method_); }
diff --git a/remoting/client/client_telemetry_logger.h b/remoting/client/client_telemetry_logger.h index 0647e7e1..266aceb7 100644 --- a/remoting/client/client_telemetry_logger.h +++ b/remoting/client/client_telemetry_logger.h
@@ -28,7 +28,8 @@ public: // |log_writer| must outlive ClientTelemetryLogger. ClientTelemetryLogger(ChromotingEventLogWriter* log_writer, - ChromotingEvent::Mode mode); + ChromotingEvent::Mode mode, + ChromotingEvent::SessionEntryPoint entry_point); ~ClientTelemetryLogger(); void SetAuthMethod(ChromotingEvent::AuthMethod auth_method); @@ -105,6 +106,8 @@ ChromotingEvent::Mode mode_; + ChromotingEvent::SessionEntryPoint entry_point_; + std::unique_ptr<HostInfo> host_info_; std::unique_ptr<protocol::TransportRoute> transport_route_;
diff --git a/remoting/client/client_telemetry_logger_unittest.cc b/remoting/client/client_telemetry_logger_unittest.cc index 0a58076..85bf493 100644 --- a/remoting/client/client_telemetry_logger_unittest.cc +++ b/remoting/client/client_telemetry_logger_unittest.cc
@@ -89,8 +89,9 @@ void ClientTelemetryLoggerTest::SetUp() { log_writer_.reset(new FakeLogWriter()); - logger_.reset(new ClientTelemetryLogger(log_writer_.get(), - ChromotingEvent::Mode::ME2ME)); + logger_.reset(new ClientTelemetryLogger( + log_writer_.get(), ChromotingEvent::Mode::ME2ME, + ChromotingEvent::SessionEntryPoint::CONNECT_BUTTON)); } TEST_F(ClientTelemetryLoggerTest, LogSessionStateChange) {
diff --git a/remoting/client/connect_to_host_info.h b/remoting/client/connect_to_host_info.h index f8885ea3..877c569 100644 --- a/remoting/client/connect_to_host_info.h +++ b/remoting/client/connect_to_host_info.h
@@ -7,6 +7,8 @@ #include <string> +#include "remoting/base/chromoting_event.h" + namespace remoting { struct ConnectToHostInfo { @@ -29,6 +31,8 @@ std::string host_version; std::string host_os; std::string host_os_version; + ChromotingEvent::SessionEntryPoint session_entry_point = + ChromotingEvent::SessionEntryPoint::CONNECT_BUTTON; }; } // namespace remoting
diff --git a/remoting/ios/app/client_connection_view_controller.mm b/remoting/ios/app/client_connection_view_controller.mm index 3cc494d3..68bff3f 100644 --- a/remoting/ios/app/client_connection_view_controller.mm +++ b/remoting/ios/app/client_connection_view_controller.mm
@@ -47,6 +47,8 @@ static NSString* const kConnectionErrorFeedbackContext = @"ConnectionErrorFeedbackContext"; +using EntryPoint = remoting::ChromotingEvent::SessionEntryPoint; + @interface ClientConnectionViewController ()<PinEntryDelegate, SessionReconnectViewDelegate> { UIImageView* _iconView; @@ -178,7 +180,7 @@ name:kHostSessionStatusChanged object:nil]; - [self attemptConnectionToHost]; + [self attemptConnectionToHostWithEntryPoint:EntryPoint::CONNECT_BUTTON]; // Although keyboard listeners are registered here, they won't work properly // if the keyboard shows/hides before the view appears. @@ -382,7 +384,7 @@ #pragma mark - SessionReconnectViewDelegate - (void)didTapReconnect { - [self attemptConnectionToHost]; + [self attemptConnectionToHostWithEntryPoint:EntryPoint::RECONNECT_BUTTON]; } - (void)didTapReport { @@ -396,7 +398,7 @@ #pragma mark - Private -- (void)attemptConnectionToHost { +- (void)attemptConnectionToHostWithEntryPoint:(EntryPoint)entryPoint { _client = [[RemotingClient alloc] init]; __weak ClientConnectionViewController* weakSelf = self; __weak RemotingClient* weakClient = _client; @@ -407,7 +409,8 @@ if (status == RemotingAuthenticationStatusSuccess) { [weakClient connectToHost:weakHostInfo username:userEmail - accessToken:accessToken]; + accessToken:accessToken + entryPoint:entryPoint]; } else { LOG(ERROR) << "Failed to fetch access token for connectToHost. (" << status << ")";
diff --git a/remoting/ios/session/remoting_client.h b/remoting/ios/session/remoting_client.h index 85e7329..953236bf 100644 --- a/remoting/ios/session/remoting_client.h +++ b/remoting/ios/session/remoting_client.h
@@ -10,6 +10,7 @@ #import "remoting/ios/display/gl_display_handler.h" +#include "remoting/base/chromoting_event.h" #include "remoting/client/feedback_data.h" #include "remoting/protocol/client_authentication_config.h" #include "remoting/protocol/connection_to_host.h" @@ -50,9 +51,11 @@ // |hostInfo| is all the details around a host. // |username| is the username to be used when connecting. // |accessToken| is the oAuth access token to provided to create the session. +// |entryPoint| is the entry point of the session. Only used for telemetry. - (void)connectToHost:(HostInfo*)hostInfo username:(NSString*)username - accessToken:(NSString*)accessToken; + accessToken:(NSString*)accessToken + entryPoint:(remoting::ChromotingEvent::SessionEntryPoint)entryPoint; // Disconnect the current host connection. - (void)disconnectFromHost;
diff --git a/remoting/ios/session/remoting_client.mm b/remoting/ios/session/remoting_client.mm index a7956ca..b0a4bcbc 100644 --- a/remoting/ios/session/remoting_client.mm +++ b/remoting/ios/session/remoting_client.mm
@@ -100,7 +100,8 @@ - (void)connectToHost:(HostInfo*)hostInfo username:(NSString*)username - accessToken:(NSString*)accessToken { + accessToken:(NSString*)accessToken + entryPoint:(remoting::ChromotingEvent::SessionEntryPoint)entryPoint { DCHECK(_runtime->ui_task_runner()->BelongsToCurrentThread()); DCHECK(hostInfo); DCHECK(hostInfo.jabberId); @@ -124,6 +125,8 @@ info.pairing_id = pairing.pairing_id(); info.pairing_secret = pairing.pairing_secret(); + info.session_entry_point = entryPoint; + info.capabilities = ""; if ([RemotingPreferences.instance boolForFlag:RemotingFlagUseWebRTC]) { info.flags = "useWebrtc";
diff --git a/services/content/simple_browser/simple_browser_service.cc b/services/content/simple_browser/simple_browser_service.cc index d2f6b9f..8cb79564 100644 --- a/services/content/simple_browser/simple_browser_service.cc +++ b/services/content/simple_browser/simple_browser_service.cc
@@ -28,7 +28,6 @@ views::AuraInit::InitParams params; params.connector = context()->connector(); params.identity = context()->identity(); - params.mode = views::AuraInit::Mode::AURA_MUS2; params.register_path_provider = false; aura_init_ = views::AuraInit::Create(params); CHECK(aura_init_);
diff --git a/services/network/cors/cors_url_loader_factory.cc b/services/network/cors/cors_url_loader_factory.cc index b9f7561..47e0854 100644 --- a/services/network/cors/cors_url_loader_factory.cc +++ b/services/network/cors/cors_url_loader_factory.cc
@@ -96,6 +96,10 @@ bindings_.AddBinding(this, std::move(request)); } +void CORSURLLoaderFactory::ClearBindings() { + bindings_.CloseAllBindings(); +} + void CORSURLLoaderFactory::DeleteIfNeeded() { if (!context_) return;
diff --git a/services/network/cors/cors_url_loader_factory.h b/services/network/cors/cors_url_loader_factory.h index 6697570..61db987 100644 --- a/services/network/cors/cors_url_loader_factory.h +++ b/services/network/cors/cors_url_loader_factory.h
@@ -48,6 +48,10 @@ void OnLoaderCreated(std::unique_ptr<mojom::URLLoader> loader); void DestroyURLLoader(mojom::URLLoader* loader); + // Clears the bindings for this factory, but does not touch any in-progress + // URLLoaders. + void ClearBindings(); + private: // Implements mojom::URLLoaderFactory. void CreateLoaderAndStart(mojom::URLLoaderRequest request,
diff --git a/services/network/network_context.cc b/services/network/network_context.cc index 2ba3a07..84d195de 100644 --- a/services/network/network_context.cc +++ b/services/network/network_context.cc
@@ -512,7 +512,7 @@ } void NetworkContext::DestroyURLLoaderFactory( - mojom::URLLoaderFactory* url_loader_factory) { + cors::CORSURLLoaderFactory* url_loader_factory) { auto it = url_loader_factories_.find(url_loader_factory); DCHECK(it != url_loader_factories_.end()); url_loader_factories_.erase(it); @@ -831,6 +831,11 @@ base::saturated_cast<int32_t>(num_streams), request_info); } +void NetworkContext::ResetURLLoaderFactories() { + for (const auto& factory : url_loader_factories_) + factory->ClearBindings(); +} + // ApplyContextParamsToBuilder represents the core configuration for // translating |network_context_params| into a set of configuration that can // be used to build a request context. All new initialization should be done
diff --git a/services/network/network_context.h b/services/network/network_context.h index 83459ab..457eca6 100644 --- a/services/network/network_context.h +++ b/services/network/network_context.h
@@ -58,6 +58,10 @@ class URLRequestContextBuilderMojo; class WebSocketFactory; +namespace cors { +class CORSURLLoaderFactory; +} // namespace cors + // A NetworkContext creates and manages access to a URLRequestContext. // // When the network service is enabled, NetworkContexts are created through @@ -203,13 +207,14 @@ const GURL& url, int32_t load_flags, bool privacy_mode_enabled) override; + void ResetURLLoaderFactories() override; // Disables use of QUIC by the NetworkContext. void DisableQuic(); // Destroys the specified factory. Called by the factory itself when it has // no open pipes. - void DestroyURLLoaderFactory(mojom::URLLoaderFactory* url_loader_factory); + void DestroyURLLoaderFactory(cors::CORSURLLoaderFactory* url_loader_factory); private: class ContextNetworkDelegate; @@ -274,7 +279,8 @@ // This must be below |url_request_context_| so that the URLRequestContext // outlives all the URLLoaderFactories and URLLoaders that depend on it. - std::set<std::unique_ptr<mojom::URLLoaderFactory>, base::UniquePtrComparator> + std::set<std::unique_ptr<cors::CORSURLLoaderFactory>, + base::UniquePtrComparator> url_loader_factories_; mojo::StrongBindingSet<mojom::NetLogExporter> net_log_exporter_bindings_;
diff --git a/services/network/public/mojom/network_context.mojom b/services/network/public/mojom/network_context.mojom index 35d1e55..3091427 100644 --- a/services/network/public/mojom/network_context.mojom +++ b/services/network/public/mojom/network_context.mojom
@@ -521,6 +521,11 @@ int32 load_flags, bool privacy_mode_enabled); + // Destroys all URLLoaderFactory bindings, which should then be regenerated. + // This should be called if there is a change to the proxies which should be + // used on URLLoaders. + ResetURLLoaderFactories(); + [Sync] // Adds explicitly-specified data as if it was processed from an // HSTS header.
diff --git a/services/network/test/test_network_context.h b/services/network/test/test_network_context.h index 005a4e79..a81e5861 100644 --- a/services/network/test/test_network_context.h +++ b/services/network/test/test_network_context.h
@@ -111,6 +111,7 @@ const GURL& url, int32_t load_flags, bool privacy_mode_enabled) override {} + void ResetURLLoaderFactories() override {} }; } // namespace network
diff --git a/services/network/test/test_url_loader_factory_unittest.cc b/services/network/test/test_url_loader_factory_unittest.cc index bb7945d..5a06088 100644 --- a/services/network/test/test_url_loader_factory_unittest.cc +++ b/services/network/test/test_url_loader_factory_unittest.cc
@@ -214,11 +214,10 @@ TEST_F(TestURLLoaderFactoryTest, SimulateResponse) { std::string url = "http://foo/"; - std::string cookie_line = "my_cookie=myvalue"; network::URLLoaderCompletionStatus ok_status(net::OK); ResourceResponseHead response_head = CreateResourceResponseHead(net::HTTP_NOT_FOUND); - AddCookiesToResourceResponseHead({cookie_line}, &response_head); + response_head.headers->AddHeader("Foo: Bar"); // By default no request is pending. EXPECT_FALSE(factory()->SimulateResponseForPendingRequest( @@ -238,16 +237,11 @@ ASSERT_TRUE(client()->response_head().headers); EXPECT_EQ(net::HTTP_NOT_FOUND, client()->response_head().headers->response_code()); - // Our cookie should be set. - int cookie_count = 0; + // Our header should be set. std::string value; - size_t iter = 0; - while (client()->response_head().headers->EnumerateHeader(&iter, "Set-Cookie", - &value)) { - EXPECT_EQ(cookie_line, value); - cookie_count++; - } - EXPECT_EQ(1, cookie_count); + EXPECT_TRUE( + client()->response_head().headers->GetNormalizedHeader("Foo", &value)); + EXPECT_EQ("Bar", value); std::string response; EXPECT_TRUE( mojo::BlockingCopyToString(client()->response_body_release(), &response));
diff --git a/services/ui/BUILD.gn b/services/ui/BUILD.gn index aea14eac..f2b12d28 100644 --- a/services/ui/BUILD.gn +++ b/services/ui/BUILD.gn
@@ -2,118 +2,9 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//build/config/ui.gni") -import("//testing/test.gni") -import("//services/service_manager/public/cpp/service.gni") import("//services/service_manager/public/service_manifest.gni") -import("//tools/grit/repack.gni") - -group("all") { - testonly = true - deps = [ - ":ui", - "//services/ui/ime/test_ime_driver", - "//services/viz", - ] -} - -service("ui") { - sources = [ - "main.cc", - ] - - deps = [ - ":lib", - "//services/service_manager/public/cpp", - ] - - data_deps = [ - ":resources_100", - ":resources_200", - ":resources_strings", - "//services/viz", - ] -} service_manifest("manifest") { name = "ui" source = "manifest.json" } - -source_set("lib") { - sources = [ - "service.cc", - "service.h", - ] - - public_deps = [ - "//services/ui/common:mus_common", - ] - deps = [ - "//base", - "//cc", - "//components/discardable_memory/public/interfaces", - "//components/discardable_memory/service", - "//components/viz/service", - "//mojo/public/cpp/system", - "//services/catalog/public/cpp", - "//services/catalog/public/mojom:constants", - "//services/service_manager/public/cpp", - "//services/ui/gpu_host", - "//services/ui/ime:lib", - "//services/ui/input_devices", - "//services/ui/public/interfaces", - "//services/ui/ws:lib", - "//services/ui/ws:test_interface", - "//ui/base/mojo:lib", - "//ui/events", - "//ui/events/ozone:events_ozone_layout", - "//ui/gl:gl", - "//ui/platform_window:platform_impls", - "//ui/platform_window:platform_window", - ] - - if (use_x11) { - public_configs = [ "//build/config/linux:x11" ] - public_deps += [ "//ui/events/platform/x11" ] - } - - if (use_ozone) { - deps += [ "//ui/ozone:ozone" ] - } - - if (is_chromeos) { - deps += [ "//services/ui/public/cpp/input_devices:input_device_controller" ] - } -} - -repack("resources_strings") { - sources = [ - "$root_gen_dir/ui/strings/app_locale_settings_en-US.pak", - "$root_gen_dir/ui/strings/ui_strings_en-US.pak", - ] - output = "$root_out_dir/mus_app_resources_strings.pak" - deps = [ - "//ui/strings", - ] -} - -repack("resources_100") { - sources = [ - "$root_gen_dir/ui/resources/ui_resources_100_percent.pak", - ] - output = "$root_out_dir/mus_app_resources_100.pak" - deps = [ - "//ui/resources", - ] -} - -repack("resources_200") { - sources = [ - "$root_gen_dir/ui/resources/ui_resources_200_percent.pak", - ] - output = "$root_out_dir/mus_app_resources_200.pak" - deps = [ - "//ui/resources", - ] -}
diff --git a/services/ui/ime/BUILD.gn b/services/ui/ime/BUILD.gn index 8f82b69..93b70a47 100644 --- a/services/ui/ime/BUILD.gn +++ b/services/ui/ime/BUILD.gn
@@ -41,7 +41,6 @@ data_deps = [ ":lib", - "//services/ui", "//services/ui/ime/test_ime_driver", ] }
diff --git a/services/ui/main.cc b/services/ui/main.cc deleted file mode 100644 index 2f3f812..0000000 --- a/services/ui/main.cc +++ /dev/null
@@ -1,17 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "services/service_manager/public/c/main.h" -#include "base/message_loop/message_loop.h" -#include "services/service_manager/public/cpp/service_runner.h" -#include "services/ui/service.h" - -MojoResult ServiceMain(MojoHandle service_request_handle) { - ui::Service::InitParams params; - params.running_standalone = true; - ui::Service* ui_service = new ui::Service(params); - service_manager::ServiceRunner runner(ui_service); - runner.set_message_loop_type(base::MessageLoop::TYPE_UI); - return runner.Run(service_request_handle); -}
diff --git a/services/ui/service.cc b/services/ui/service.cc deleted file mode 100644 index 5011695..0000000 --- a/services/ui/service.cc +++ /dev/null
@@ -1,546 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "services/ui/service.h" - -#include <set> - -#include "base/bind.h" -#include "base/command_line.h" -#include "base/run_loop.h" -#include "base/threading/platform_thread.h" -#include "base/trace_event/trace_event.h" -#include "build/build_config.h" -#include "components/discardable_memory/service/discardable_shared_memory_manager.h" -#include "mojo/public/cpp/bindings/strong_binding.h" -#include "services/catalog/public/cpp/resource_loader.h" -#include "services/catalog/public/mojom/constants.mojom.h" -#include "services/service_manager/public/c/main.h" -#include "services/service_manager/public/cpp/connector.h" -#include "services/service_manager/public/cpp/service_context.h" -#include "services/ui/common/image_cursors_set.h" -#include "services/ui/common/switches.h" -#include "services/ui/display/screen_manager.h" -#include "services/ui/gpu_host/gpu_host.h" -#include "services/ui/ime/ime_driver_bridge.h" -#include "services/ui/ime/ime_registrar_impl.h" -#include "services/ui/ws/accessibility_manager.h" -#include "services/ui/ws/display_binding.h" -#include "services/ui/ws/display_creation_config.h" -#include "services/ui/ws/display_manager.h" -#include "services/ui/ws/event_injector.h" -#include "services/ui/ws/threaded_image_cursors.h" -#include "services/ui/ws/threaded_image_cursors_factory.h" -#include "services/ui/ws/user_activity_monitor.h" -#include "services/ui/ws/user_display_manager.h" -#include "services/ui/ws/window_server.h" -#include "services/ui/ws/window_server_test_impl.h" -#include "services/ui/ws/window_tree.h" -#include "services/ui/ws/window_tree_binding.h" -#include "services/ui/ws/window_tree_factory.h" -#include "services/ui/ws/window_tree_host_factory.h" -#include "ui/base/cursor/image_cursors.h" -#include "ui/base/mojo/clipboard_host.h" -#include "ui/base/platform_window_defaults.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/base/ui_base_features.h" -#include "ui/base/ui_base_paths.h" -#include "ui/events/event_switches.h" -#include "ui/events/platform/platform_event_source.h" -#include "ui/gfx/geometry/rect.h" -#include "ui/gl/gl_surface.h" - -#if defined(USE_X11) -#include "ui/base/x/x11_util.h" // nogncheck -#include "ui/gfx/x/x11.h" -#include "ui/platform_window/x11/x11_window.h" -#elif defined(USE_OZONE) -#include "services/ui/display/screen_manager_forwarding.h" -#include "ui/events/ozone/layout/keyboard_layout_engine.h" -#include "ui/events/ozone/layout/keyboard_layout_engine_manager.h" -#include "ui/ozone/public/ozone_platform.h" -#endif - -#if defined(OS_CHROMEOS) -#include "services/ui/public/cpp/input_devices/input_device_controller.h" -#endif - -using mojo::InterfaceRequest; -using ui::mojom::WindowServerTest; -using ui::mojom::WindowTreeHostFactory; - -namespace ui { - -namespace { - -const char kResourceFileStrings[] = "mus_app_resources_strings.pak"; -const char kResourceFile100[] = "mus_app_resources_100.pak"; -const char kResourceFile200[] = "mus_app_resources_200.pak"; - -class ThreadedImageCursorsFactoryImpl : public ws::ThreadedImageCursorsFactory { - public: - explicit ThreadedImageCursorsFactoryImpl(const Service::InitParams& params) { - // When running in-process use |resource_runner_| to load cursors. - if (params.resource_runner) { - resource_runner_ = params.resource_runner; - // |params.image_cursors_set_weak_ptr| must be set, but don't DCHECK - // because it can only be dereferenced on |resource_runner_|. - image_cursors_set_weak_ptr_ = params.image_cursors_set_weak_ptr; - } - } - - ~ThreadedImageCursorsFactoryImpl() override = default; - - // ws::ThreadedImageCursorsFactory: - std::unique_ptr<ws::ThreadedImageCursors> CreateCursors() override { - // When running out-of-process lazily initialize the resource runner to the - // UI service's thread. - if (!resource_runner_) { - resource_runner_ = base::ThreadTaskRunnerHandle::Get(); - image_cursors_set_ = std::make_unique<ui::ImageCursorsSet>(); - image_cursors_set_weak_ptr_ = image_cursors_set_->GetWeakPtr(); - } - return std::make_unique<ws::ThreadedImageCursors>( - resource_runner_, image_cursors_set_weak_ptr_); - } - - private: - scoped_refptr<base::SingleThreadTaskRunner> resource_runner_; - base::WeakPtr<ui::ImageCursorsSet> image_cursors_set_weak_ptr_; - - // Used when UI Service doesn't run inside WM's process. - std::unique_ptr<ui::ImageCursorsSet> image_cursors_set_; - - DISALLOW_COPY_AND_ASSIGN(ThreadedImageCursorsFactoryImpl); -}; - -} // namespace - -// TODO(sky): this is a pretty typical pattern, make it easier to do. -struct Service::PendingRequest { - service_manager::BindSourceInfo source_info; - std::unique_ptr<mojom::WindowTreeFactoryRequest> wtf_request; - std::unique_ptr<mojom::ScreenProviderRequest> screen_request; -}; - -Service::InitParams::InitParams() = default; - -Service::InitParams::~InitParams() = default; - -Service::Service(const InitParams& params) - : running_standalone_(params.running_standalone), - threaded_image_cursors_factory_( - std::make_unique<ThreadedImageCursorsFactoryImpl>(params)), - test_config_(false), - ime_registrar_(&ime_driver_), - discardable_shared_memory_manager_(params.memory_manager), - should_host_viz_(params.should_host_viz) { - // UI service must host viz when running in its own process. - DCHECK(!running_standalone_ || should_host_viz_); -} - -Service::~Service() { - in_destructor_ = true; - - // Destroy |window_server_| first, since it depends on |event_source_|. - // WindowServer (or more correctly its Displays) may have state that needs to - // be destroyed before GpuState as well. - window_server_.reset(); - - // Must be destroyed before calling OzonePlatform::Shutdown(). - threaded_image_cursors_factory_.reset(); - -#if defined(OS_CHROMEOS) - // InputDeviceController uses ozone. - input_device_controller_.reset(); -#endif - -#if defined(USE_OZONE) - OzonePlatform::Shutdown(); -#endif -} - -bool Service::InitializeResources(service_manager::Connector* connector) { - if (!running_standalone_ || ui::ResourceBundle::HasSharedInstance()) - return true; - - std::set<std::string> resource_paths; - resource_paths.insert(kResourceFileStrings); - resource_paths.insert(kResourceFile100); - resource_paths.insert(kResourceFile200); - - catalog::ResourceLoader loader; - filesystem::mojom::DirectoryPtr directory; - connector->BindInterface(catalog::mojom::kServiceName, &directory); - if (!loader.OpenFiles(std::move(directory), resource_paths)) { - LOG(ERROR) << "Service failed to open resource files."; - return false; - } - - ui::RegisterPathProvider(); - - // Initialize resource bundle with 1x and 2x cursor bitmaps. - ui::ResourceBundle::InitSharedInstanceWithPakFileRegion( - loader.TakeFile(kResourceFileStrings), - base::MemoryMappedFile::Region::kWholeFile); - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); - rb.AddDataPackFromFile(loader.TakeFile(kResourceFile100), - ui::SCALE_FACTOR_100P); - rb.AddDataPackFromFile(loader.TakeFile(kResourceFile200), - ui::SCALE_FACTOR_200P); - return true; -} - -void Service::OnStart() { - base::PlatformThread::SetName("mus"); - TRACE_EVENT0("mus", "Service::Initialize started"); - - test_config_ = base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kUseTestConfig); -#if defined(USE_X11) - XInitThreads(); - ui::SetDefaultX11ErrorHandlers(); -#endif - - if (test_config_) - ui::test::EnableTestConfigForPlatformWindows(); - - // If resources are unavailable do not complete start-up. - if (!InitializeResources(context()->connector())) { - context()->QuitNow(); - return; - } - -#if defined(USE_OZONE) - // The ozone platform can provide its own event source. So initialize the - // platform before creating the default event source. - // Because GL libraries need to be initialized before entering the sandbox, - // in MUS, |InitializeForUI| will load the GL libraries. - ui::OzonePlatform::InitParams params; - if (should_host_viz_) { - // If mus is hosting viz, then it needs to set up ozone so that it can - // connect to the gpu service through the connector. - // Currently mus hosting viz (i.e. mash mode) only runs single-process. - params.connector = context()->connector(); - params.single_process = true; - params.using_mojo = true; - } else { - params.using_mojo = features::IsOzoneDrmMojo(); - } - ui::OzonePlatform::InitializeForUI(params); - - // Assume a client will change the layout to an appropriate configuration. - ui::KeyboardLayoutEngineManager::GetKeyboardLayoutEngine() - ->SetCurrentLayoutByName("us"); -#endif - -#if defined(OS_CHROMEOS) - input_device_controller_ = std::make_unique<InputDeviceController>(); - input_device_controller_->AddInterface(®istry_); -#endif - -#if !defined(OS_ANDROID) - event_source_ = ui::PlatformEventSource::CreateDefault(); -#endif - - // This needs to happen after DeviceDataManager has been constructed. That - // happens either during OzonePlatform or PlatformEventSource initialization, - // so keep this line below both of those. - input_device_server_.RegisterAsObserver(); - - if (!discardable_shared_memory_manager_) { - owned_discardable_shared_memory_manager_ = - std::make_unique<discardable_memory::DiscardableSharedMemoryManager>(); - discardable_shared_memory_manager_ = - owned_discardable_shared_memory_manager_.get(); - } - - window_server_ = std::make_unique<ws::WindowServer>(this, should_host_viz_); - if (should_host_viz_) { - std::unique_ptr<gpu_host::GpuHost> gpu_host = - std::make_unique<gpu_host::DefaultGpuHost>( - window_server_.get(), context()->connector(), - discardable_shared_memory_manager_); - window_server_->SetGpuHost(std::move(gpu_host)); - - registry_.AddInterface<mojom::Gpu>( - base::BindRepeating(&Service::BindGpuRequest, base::Unretained(this))); -#if defined(OS_CHROMEOS) - registry_.AddInterface<mojom::Arc>( - base::BindRepeating(&Service::BindArcRequest, base::Unretained(this))); -#endif // defined(OS_CHROMEOS) - } - registry_.AddInterface<mojom::VideoDetector>(base::BindRepeating( - &Service::BindVideoDetectorRequest, base::Unretained(this))); - - ime_driver_.Init(context()->connector(), test_config_); - - registry_with_source_info_.AddInterface<mojom::AccessibilityManager>( - base::BindRepeating(&Service::BindAccessibilityManagerRequest, - base::Unretained(this))); - registry_with_source_info_.AddInterface<mojom::ClipboardHost>( - base::BindRepeating(&Service::BindClipboardHostRequest, - base::Unretained(this))); - registry_with_source_info_.AddInterface<mojom::ScreenProvider>( - base::BindRepeating(&Service::BindScreenProviderRequest, - base::Unretained(this))); - registry_.AddInterface<mojom::IMERegistrar>(base::BindRepeating( - &Service::BindIMERegistrarRequest, base::Unretained(this))); - registry_.AddInterface<mojom::IMEDriver>(base::BindRepeating( - &Service::BindIMEDriverRequest, base::Unretained(this))); - registry_with_source_info_.AddInterface<mojom::UserActivityMonitor>( - base::BindRepeating(&Service::BindUserActivityMonitorRequest, - base::Unretained(this))); - registry_with_source_info_.AddInterface<WindowTreeHostFactory>( - base::BindRepeating(&Service::BindWindowTreeHostFactoryRequest, - base::Unretained(this))); - registry_with_source_info_ - .AddInterface<mojom::WindowManagerWindowTreeFactory>(base::BindRepeating( - &Service::BindWindowManagerWindowTreeFactoryRequest, - base::Unretained(this))); - registry_with_source_info_.AddInterface<mojom::WindowTreeFactory>( - base::BindRepeating(&Service::BindWindowTreeFactoryRequest, - base::Unretained(this))); - registry_with_source_info_ - .AddInterface<discardable_memory::mojom::DiscardableSharedMemoryManager>( - base::BindRepeating( - &Service::BindDiscardableSharedMemoryManagerRequest, - base::Unretained(this))); - if (test_config_) { - registry_.AddInterface<WindowServerTest>(base::BindRepeating( - &Service::BindWindowServerTestRequest, base::Unretained(this))); - } - registry_.AddInterface<mojom::EventInjector>(base::BindRepeating( - &Service::BindEventInjectorRequest, base::Unretained(this))); - - // On non-Linux platforms there will be no DeviceDataManager instance and no - // purpose in adding the Mojo interface to connect to. - if (input_device_server_.IsRegisteredAsObserver()) { - registry_.AddInterface<mojom::InputDeviceServer>(base::BindRepeating( - &Service::BindInputDeviceServerRequest, base::Unretained(this))); - } - -#if defined(OS_CHROMEOS) - registry_.AddInterface<mojom::TouchDeviceServer>(base::BindRepeating( - &Service::BindTouchDeviceServerRequest, base::Unretained(this))); -#endif // defined(OS_CHROMEOS) - -#if defined(USE_OZONE) - ui::OzonePlatform::GetInstance()->AddInterfaces(®istry_); -#endif -} - -void Service::OnBindInterface( - const service_manager::BindSourceInfo& source_info, - const std::string& interface_name, - mojo::ScopedMessagePipeHandle interface_pipe) { - if (!registry_with_source_info_.TryBindInterface( - interface_name, &interface_pipe, source_info)) { - registry_.BindInterface(interface_name, std::move(interface_pipe)); - } -} - -void Service::StartDisplayInit() { - DCHECK(!is_gpu_ready_); // This should only be called once. - is_gpu_ready_ = true; - if (screen_manager_) - screen_manager_->Init(window_server_->display_manager()); -} - -void Service::OnFirstDisplayReady() { - PendingRequests requests; - requests.swap(pending_requests_); - for (auto& request : requests) { - if (request->wtf_request) { - BindWindowTreeFactoryRequest(std::move(*request->wtf_request), - request->source_info); - } else { - BindScreenProviderRequest(std::move(*request->screen_request), - request->source_info); - } - } -} - -void Service::OnNoMoreDisplays() { - // We may get here from the destructor. Don't try to use RequestQuit() when - // that happens as ServiceContext DCHECKs in this case. - if (in_destructor_) - return; - - DCHECK(context()); - context()->CreateQuitClosure().Run(); -} - -bool Service::IsTestConfig() const { - return test_config_; -} - -void Service::OnWillCreateTreeForWindowManager( - bool automatically_create_display_roots) { - if (window_server_->display_creation_config() != - ws::DisplayCreationConfig::UNKNOWN) { - return; - } - - DVLOG(3) << "OnWillCreateTreeForWindowManager " - << automatically_create_display_roots; - ws::DisplayCreationConfig config = automatically_create_display_roots - ? ws::DisplayCreationConfig::AUTOMATIC - : ws::DisplayCreationConfig::MANUAL; - window_server_->SetDisplayCreationConfig(config); - if (window_server_->display_creation_config() == - ws::DisplayCreationConfig::MANUAL) { -#if defined(OS_CHROMEOS) - display::ScreenManagerForwarding::Mode mode = - running_standalone_ - ? display::ScreenManagerForwarding::Mode::OWN_PROCESS - : display::ScreenManagerForwarding::Mode::IN_WM_PROCESS; - screen_manager_ = std::make_unique<display::ScreenManagerForwarding>(mode); -#else - CHECK(false); -#endif - } else { - screen_manager_ = display::ScreenManager::Create(); - } - screen_manager_->AddInterfaces(®istry_with_source_info_); - if (is_gpu_ready_) - screen_manager_->Init(window_server_->display_manager()); -} - -ws::ThreadedImageCursorsFactory* Service::GetThreadedImageCursorsFactory() { - return threaded_image_cursors_factory_.get(); -} - -void Service::BindAccessibilityManagerRequest( - mojom::AccessibilityManagerRequest request, - const service_manager::BindSourceInfo& source_info) { - if (!accessibility_) { - accessibility_ = - std::make_unique<ws::AccessibilityManager>(window_server_.get()); - } - accessibility_->Bind(std::move(request)); -} - -void Service::BindClipboardHostRequest( - mojom::ClipboardHostRequest request, - const service_manager::BindSourceInfo& source_info) { - if (!clipboard_host_) - clipboard_host_ = std::make_unique<ClipboardHost>(); - clipboard_host_->AddBinding(std::move(request)); -} - -void Service::BindScreenProviderRequest( - mojom::ScreenProviderRequest request, - const service_manager::BindSourceInfo& source_info) { - // Wait for the DisplayManager to be configured before binding display - // requests. Otherwise the client sees no displays. - if (!window_server_->display_manager()->IsReady()) { - std::unique_ptr<PendingRequest> pending_request(new PendingRequest); - pending_request->source_info = source_info; - pending_request->screen_request = - std::make_unique<mojom::ScreenProviderRequest>(std::move(request)); - pending_requests_.push_back(std::move(pending_request)); - return; - } - window_server_->display_manager() - ->GetUserDisplayManager() - ->AddDisplayManagerBinding(std::move(request)); -} - -void Service::BindGpuRequest(mojom::GpuRequest request) { - window_server_->gpu_host()->Add(std::move(request)); -} - -void Service::BindIMERegistrarRequest(mojom::IMERegistrarRequest request) { - ime_registrar_.AddBinding(std::move(request)); -} - -void Service::BindIMEDriverRequest(mojom::IMEDriverRequest request) { - ime_driver_.AddBinding(std::move(request)); -} - -void Service::BindInputDeviceServerRequest( - mojom::InputDeviceServerRequest request) { - input_device_server_.AddBinding(std::move(request)); -} - -void Service::BindUserActivityMonitorRequest( - mojom::UserActivityMonitorRequest request, - const service_manager::BindSourceInfo& source_info) { - window_server_->user_activity_monitor()->Add(std::move(request)); -} - -void Service::BindWindowManagerWindowTreeFactoryRequest( - mojom::WindowManagerWindowTreeFactoryRequest request, - const service_manager::BindSourceInfo& source_info) { - window_server_->BindWindowManagerWindowTreeFactory(std::move(request)); -} - -void Service::BindWindowTreeFactoryRequest( - mojom::WindowTreeFactoryRequest request, - const service_manager::BindSourceInfo& source_info) { - if (!window_server_->display_manager()->IsReady()) { - std::unique_ptr<PendingRequest> pending_request(new PendingRequest); - pending_request->source_info = source_info; - pending_request->wtf_request.reset( - new mojom::WindowTreeFactoryRequest(std::move(request))); - pending_requests_.push_back(std::move(pending_request)); - return; - } - mojo::MakeStrongBinding( - std::make_unique<ws::WindowTreeFactory>(window_server_.get(), - source_info.identity.name()), - std::move(request)); -} - -void Service::BindWindowTreeHostFactoryRequest( - mojom::WindowTreeHostFactoryRequest request, - const service_manager::BindSourceInfo& source_info) { - if (!window_tree_host_factory_) { - window_tree_host_factory_ = - std::make_unique<ws::WindowTreeHostFactory>(window_server_.get()); - } - window_tree_host_factory_->AddBinding(std::move(request)); -} - -void Service::BindDiscardableSharedMemoryManagerRequest( - discardable_memory::mojom::DiscardableSharedMemoryManagerRequest request, - const service_manager::BindSourceInfo& source_info) { - discardable_shared_memory_manager_->Bind(std::move(request), source_info); -} - -void Service::BindWindowServerTestRequest( - mojom::WindowServerTestRequest request) { - if (!test_config_) - return; - mojo::MakeStrongBinding( - std::make_unique<ws::WindowServerTestImpl>(window_server_.get()), - std::move(request)); -} - -void Service::BindEventInjectorRequest(mojom::EventInjectorRequest request) { - mojo::MakeStrongBinding( - std::make_unique<ws::EventInjector>(window_server_.get()), - std::move(request)); -} - -void Service::BindVideoDetectorRequest(mojom::VideoDetectorRequest request) { - if (!should_host_viz_) - return; - window_server_->video_detector()->AddBinding(std::move(request)); -} - -#if defined(OS_CHROMEOS) -void Service::BindArcRequest(mojom::ArcRequest request) { - window_server_->gpu_host()->AddArc(std::move(request)); -} - -void Service::BindTouchDeviceServerRequest( - mojom::TouchDeviceServerRequest request) { - touch_device_server_.AddBinding(std::move(request)); -} - -#endif // defined(OS_CHROMEOS) - -} // namespace ui
diff --git a/services/ui/service.h b/services/ui/service.h deleted file mode 100644 index 59bae85..0000000 --- a/services/ui/service.h +++ /dev/null
@@ -1,242 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SERVICES_UI_SERVICE_H_ -#define SERVICES_UI_SERVICE_H_ - -#include <stdint.h> - -#include <map> -#include <memory> -#include <string> -#include <vector> - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/memory/weak_ptr.h" -#include "base/single_thread_task_runner.h" -#include "components/discardable_memory/public/interfaces/discardable_shared_memory_manager.mojom.h" -#include "services/service_manager/public/cpp/binder_registry.h" -#include "services/service_manager/public/cpp/connector.h" -#include "services/service_manager/public/cpp/service.h" -#include "services/service_manager/public/cpp/service_runner.h" -#include "services/ui/ime/ime_driver_bridge.h" -#include "services/ui/ime/ime_registrar_impl.h" -#include "services/ui/input_devices/input_device_server.h" -#include "services/ui/public/interfaces/accessibility_manager.mojom.h" -#include "services/ui/public/interfaces/event_injector.mojom.h" -#include "services/ui/public/interfaces/gpu.mojom.h" -#include "services/ui/public/interfaces/ime/ime.mojom.h" -#include "services/ui/public/interfaces/screen_provider.mojom.h" -#include "services/ui/public/interfaces/user_activity_monitor.mojom.h" -#include "services/ui/public/interfaces/video_detector.mojom.h" -#include "services/ui/public/interfaces/window_manager_window_tree_factory.mojom.h" -#include "services/ui/public/interfaces/window_server_test.mojom.h" -#include "services/ui/public/interfaces/window_tree.mojom.h" -#include "services/ui/public/interfaces/window_tree_host_factory.mojom.h" -#include "services/ui/ws/window_server_delegate.h" -#include "ui/base/mojo/clipboard.mojom.h" - -#if defined(OS_CHROMEOS) -#include "services/ui/input_devices/touch_device_server.h" -#include "services/ui/public/interfaces/arc.mojom.h" -#endif // defined(OS_CHROMEOS) - -namespace discardable_memory { -class DiscardableSharedMemoryManager; -} - -namespace display { -class ScreenManager; -} - -namespace service_manager { -class Connector; -class Identity; -} - -namespace ui { - -class ClipboardHost; -class ImageCursorsSet; -class InputDeviceController; -class PlatformEventSource; - -namespace ws { -class AccessibilityManager; -class ThreadedImageCursorsFactory; -class WindowServer; -class WindowTreeHostFactory; -} - -class Service : public service_manager::Service, - public ws::WindowServerDelegate { - public: - // TODO(jamescook): Audit these. Some may be unused after the elimination of - // "mus" mode. - struct InitParams { - InitParams(); - ~InitParams(); - - // UI service runs in its own process (i.e. not embedded in browser or ash). - bool running_standalone = false; - - // Can be used to load resources. - scoped_refptr<base::SingleThreadTaskRunner> resource_runner = nullptr; - - // Can only be de-referenced on |resource_runner_|. - base::WeakPtr<ImageCursorsSet> image_cursors_set_weak_ptr = nullptr; - - // If null Service creates a DiscardableSharedMemoryManager. - discardable_memory::DiscardableSharedMemoryManager* memory_manager = - nullptr; - - // Whether mus should host viz, or whether an external client (e.g. the - // window manager) would be responsible for hosting viz. - bool should_host_viz = true; - - private: - DISALLOW_COPY_AND_ASSIGN(InitParams); - }; - - explicit Service(const InitParams& params); - ~Service() override; - - private: - // Holds InterfaceRequests received before the first WindowTreeHost Display - // has been established. - struct PendingRequest; - - // Attempts to initialize the resource bundle. Returns true if successful, - // otherwise false if resources cannot be loaded. - bool InitializeResources(service_manager::Connector* connector); - - void AddUserIfNecessary(const service_manager::Identity& remote_identity); - - // service_manager::Service: - void OnStart() override; - void OnBindInterface(const service_manager::BindSourceInfo& source_info, - const std::string& interface_name, - mojo::ScopedMessagePipeHandle interface_pipe) override; - - // WindowServerDelegate: - void StartDisplayInit() override; - void OnFirstDisplayReady() override; - void OnNoMoreDisplays() override; - bool IsTestConfig() const override; - void OnWillCreateTreeForWindowManager( - bool automatically_create_display_roots) override; - ws::ThreadedImageCursorsFactory* GetThreadedImageCursorsFactory() override; - - void BindAccessibilityManagerRequest( - mojom::AccessibilityManagerRequest request, - const service_manager::BindSourceInfo& source_info); - - void BindClipboardHostRequest( - mojom::ClipboardHostRequest request, - const service_manager::BindSourceInfo& source_info); - - void BindScreenProviderRequest( - mojom::ScreenProviderRequest request, - const service_manager::BindSourceInfo& source_info); - - void BindGpuRequest(mojom::GpuRequest request); - - void BindIMERegistrarRequest(mojom::IMERegistrarRequest request); - - void BindIMEDriverRequest(mojom::IMEDriverRequest request); - - void BindInputDeviceServerRequest(mojom::InputDeviceServerRequest request); - - void BindUserActivityMonitorRequest( - mojom::UserActivityMonitorRequest request, - const service_manager::BindSourceInfo& source_info); - - void BindWindowManagerWindowTreeFactoryRequest( - mojom::WindowManagerWindowTreeFactoryRequest request, - const service_manager::BindSourceInfo& source_info); - - void BindWindowTreeFactoryRequest( - mojom::WindowTreeFactoryRequest request, - const service_manager::BindSourceInfo& source_info); - - void BindWindowTreeHostFactoryRequest( - mojom::WindowTreeHostFactoryRequest request, - const service_manager::BindSourceInfo& source_info); - - void BindDiscardableSharedMemoryManagerRequest( - discardable_memory::mojom::DiscardableSharedMemoryManagerRequest request, - const service_manager::BindSourceInfo& source_info); - - void BindWindowServerTestRequest(mojom::WindowServerTestRequest request); - - void BindEventInjectorRequest(mojom::EventInjectorRequest request); - - void BindVideoDetectorRequest(mojom::VideoDetectorRequest request); - -#if defined(OS_CHROMEOS) - void BindArcRequest(mojom::ArcRequest request); - void BindTouchDeviceServerRequest(mojom::TouchDeviceServerRequest request); -#endif // defined(OS_CHROMEOS) - - std::unique_ptr<ws::WindowServer> window_server_; - std::unique_ptr<PlatformEventSource> event_source_; - using PendingRequests = std::vector<std::unique_ptr<PendingRequest>>; - PendingRequests pending_requests_; - - // Provides input-device information via Mojo IPC. Registers Mojo interfaces - // and must outlive |registry_|. - InputDeviceServer input_device_server_; - - // True if the UI Service runs runs inside its own process, false if it is - // embedded in another process. - const bool running_standalone_; - - std::unique_ptr<ws::ThreadedImageCursorsFactory> - threaded_image_cursors_factory_; - - bool test_config_; - -#if defined(OS_CHROMEOS) - std::unique_ptr<InputDeviceController> input_device_controller_; - TouchDeviceServer touch_device_server_; -#endif - - // Manages display hardware and handles display management. May register Mojo - // interfaces and must outlive |registry_|. - std::unique_ptr<display::ScreenManager> screen_manager_; - - IMERegistrarImpl ime_registrar_; - IMEDriverBridge ime_driver_; - - discardable_memory::DiscardableSharedMemoryManager* - discardable_shared_memory_manager_; - - // non-null if this created the DiscardableSharedMemoryManager. Null when - // running in-process. - std::unique_ptr<discardable_memory::DiscardableSharedMemoryManager> - owned_discardable_shared_memory_manager_; - - const bool should_host_viz_; - - service_manager::BinderRegistryWithArgs< - const service_manager::BindSourceInfo&> - registry_with_source_info_; - service_manager::BinderRegistry registry_; - - // Set to true in StartDisplayInit(). - bool is_gpu_ready_ = false; - - bool in_destructor_ = false; - - std::unique_ptr<ClipboardHost> clipboard_host_; - std::unique_ptr<ws::AccessibilityManager> accessibility_; - std::unique_ptr<ws::WindowTreeHostFactory> window_tree_host_factory_; - - DISALLOW_COPY_AND_ASSIGN(Service); -}; - -} // namespace ui - -#endif // SERVICES_UI_SERVICE_H_
diff --git a/services/ui/ws/BUILD.gn b/services/ui/ws/BUILD.gn deleted file mode 100644 index cb54a12..0000000 --- a/services/ui/ws/BUILD.gn +++ /dev/null
@@ -1,335 +0,0 @@ -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//build/config/ui.gni") -import("//testing/test.gni") -import("//services/catalog/public/tools/catalog.gni") -import("//services/service_manager/public/cpp/service.gni") -import("//services/service_manager/public/service_manifest.gni") -import("//services/service_manager/public/tools/test/service_test.gni") - -# In external window mode, top-level windows are native platform windows i.e. -# not children of a Chrome OS window manager's root window. -is_external_mode = use_ozone && !is_chromeos - -static_library("lib") { - sources = [ - "accelerator.cc", - "accelerator.h", - "access_policy.h", - "access_policy_delegate.h", - "accessibility_manager.cc", - "accessibility_manager.h", - "async_event_dispatcher.h", - "async_event_dispatcher_lookup.h", - "compositor_frame_sink_client_binding.cc", - "compositor_frame_sink_client_binding.h", - "cursor_location_manager.cc", - "cursor_location_manager.h", - "cursor_state.cc", - "cursor_state.h", - "cursor_state_delegate.h", - "debug_utils.cc", - "debug_utils.h", - "default_access_policy.cc", - "default_access_policy.h", - "display.cc", - "display.h", - "display_binding.cc", - "display_binding.h", - "display_creation_config.h", - "display_manager.cc", - "display_manager.h", - "drag_controller.cc", - "drag_controller.h", - "drag_cursor_updater.h", - "drag_source.h", - "drag_target_connection.h", - "event_dispatcher.h", - "event_dispatcher_delegate.h", - "event_dispatcher_impl.cc", - "event_dispatcher_impl.h", - "event_injector.cc", - "event_injector.h", - "event_location.h", - "event_matcher.cc", - "event_matcher.h", - "event_processor.cc", - "event_processor.h", - "event_processor_delegate.h", - "event_targeter.cc", - "event_targeter.h", - "event_targeter_delegate.h", - "focus_controller.cc", - "focus_controller.h", - "focus_controller_observer.h", - "frame_generator.cc", - "frame_generator.h", - "modal_window_controller.cc", - "modal_window_controller.h", - "operation.cc", - "operation.h", - "platform_display.cc", - "platform_display.h", - "platform_display_default.cc", - "platform_display_default.h", - "platform_display_delegate.h", - "platform_display_factory.h", - "platform_display_mirror.cc", - "platform_display_mirror.h", - "server_window.cc", - "server_window.h", - "server_window_delegate.h", - "server_window_drawn_tracker.cc", - "server_window_drawn_tracker.h", - "server_window_drawn_tracker_observer.h", - "server_window_observer.h", - "server_window_tracker.h", - "threaded_image_cursors.cc", - "threaded_image_cursors.h", - "threaded_image_cursors_factory.h", - "user_activity_monitor.cc", - "user_activity_monitor.h", - "user_display_manager.cc", - "user_display_manager.h", - "user_display_manager_delegate.h", - "video_detector_impl.cc", - "video_detector_impl.h", - "window_coordinate_conversions.cc", - "window_coordinate_conversions.h", - "window_finder.cc", - "window_finder.h", - "window_manager_access_policy.cc", - "window_manager_access_policy.h", - "window_manager_display_root.cc", - "window_manager_display_root.h", - "window_manager_state.cc", - "window_manager_state.h", - "window_manager_window_tree_factory.cc", - "window_manager_window_tree_factory.h", - "window_manager_window_tree_factory_observer.h", - "window_server.cc", - "window_server.h", - "window_server_delegate.cc", - "window_server_delegate.h", - "window_tree.cc", - "window_tree.h", - "window_tree_binding.cc", - "window_tree_binding.h", - "window_tree_factory.cc", - "window_tree_factory.h", - "window_tree_host_factory.cc", - "window_tree_host_factory.h", - ] - - deps = [ - "//components/discardable_memory/service", - "//components/viz/service/main", # TODO(sad): Temporary until GPU process split. - "//gpu/command_buffer/client", - "//gpu/command_buffer/client:gles2_interface", - "//gpu/ipc/client", - "//gpu/ipc/common", - "//services/ui/gpu_host", - "//services/viz/privileged/interfaces", - ] - - public_deps = [ - "//base", - "//cc", - "//components/viz/common", - "//components/viz/host", - "//components/viz/service", - "//mojo/public/cpp/bindings", - "//mojo/public/cpp/system", - "//services/service_manager/public/cpp", - "//services/service_manager/public/mojom", - "//services/ui/common:mus_common", - "//services/ui/display", - "//services/ui/public/interfaces", - "//services/viz/privileged/interfaces/compositing", - "//ui/base", - "//ui/display", - "//ui/events", - "//ui/events/devices", - "//ui/events/platform", - "//ui/gfx", - "//ui/gfx/geometry", - "//ui/gfx/geometry/mojo", - "//ui/gl", - "//ui/platform_window", - "//ui/platform_window:platform_impls", - "//ui/platform_window/mojo", - ] - - if (use_ozone) { - public_deps += [ "//ui/ozone" ] - } - if (is_chromeos) { - public_deps += [ "//ui/chromeos/events" ] - if (use_ozone) { - public_deps += [ "//ui/events/ozone:events_ozone" ] - } - } - - # ui service should not depend on below components. - assert_no_deps = [ - "//ash", - "//content/public/browser", - "//content/public/common", - "//ui/aura", - "//ui/views", - ] -} - -static_library("test_interface") { - sources = [ - "window_server_test_impl.cc", - "window_server_test_impl.h", - ] - - deps = [ - ":lib", - "//mojo/public/cpp/bindings:bindings", - "//services/ui/public/interfaces", - "//ui/gfx", - ] -} - -static_library("test_support") { - testonly = true - - sources = [ - "test_change_tracker.cc", - "test_change_tracker.h", - "window_server_service_test_base.cc", - "window_server_service_test_base.h", - ] - - if (!is_external_mode) { - # WindowServerTestBase assumes an initial display (and root) is provided - # at startup, which is not the case on platforms running external window - # mode. - sources += [ - "window_server_test_base.cc", - "window_server_test_base.h", - ] - } - - deps = [ - "//base", - "//base/test:test_config", - "//base/test:test_support", - "//components/viz/test:test_support", - "//mojo/public/cpp/bindings:bindings", - "//services/service_manager/public/cpp", - "//services/service_manager/public/cpp:service_test_support", - "//services/ui/common:mus_common", - "//services/ui/public/cpp", - "//services/ui/public/interfaces", - "//testing/gtest", - "//ui/aura", - "//ui/display:test_support", - "//ui/gfx/geometry/mojo", - "//ui/gl", - "//ui/wm", - ] - - data_deps = [ - "//services/ui/ime/test_ime_driver", - ] -} - -source_set("tests") { - testonly = true - - sources = [ - "cursor_location_manager_unittest.cc", - "cursor_state_unittest.cc", - "cursor_unittest.cc", - "display_unittest.cc", - "drag_controller_unittest.cc", - "event_dispatcher_impl_test_api.cc", - "event_dispatcher_impl_test_api.h", - "event_matcher_unittest.cc", - "event_processor_unittest.cc", - "focus_controller_unittest.cc", - "frame_generator_unittest.cc", - "modal_window_controller_unittest.cc", - "server_window_drawn_tracker_unittest.cc", - "test_server_window_delegate.cc", - "test_server_window_delegate.h", - "test_utils.cc", - "test_utils.h", - "transient_windows_unittest.cc", - "user_activity_monitor_unittest.cc", - "user_display_manager_unittest.cc", - "window_coordinate_conversions_unittest.cc", - "window_finder_unittest.cc", - "window_manager_state_unittest.cc", - "window_tree_client_unittest.cc", - "window_tree_unittest.cc", - ] - - if (!is_external_mode) { - # A window manager client is not needed on platforms running external - # window mode, since the host system is always the window manager. - sources += [ "window_manager_client_unittest.cc" ] - } - - # TODO(jamescook): Run this test on non-ozone platforms. This will require - # initializing all the platform-specific windowing support. - if (use_ozone) { - sources += [ "platform_display_default_unittest.cc" ] - } - - deps = [ - ":lib", - ":test_support", - "//base", - "//base/test:test_config", - "//base/test:test_support", - "//cc:cc", - "//cc:test_support", - "//components/discardable_memory/service", - "//components/viz/service/main", - "//components/viz/test:test_support", - "//gpu/ipc/client", - "//mojo/public/cpp/bindings:bindings", - "//services/service_manager/public/cpp", - "//services/service_manager/public/cpp:service_test_support", - "//services/service_manager/public/mojom", - "//services/ui/common:mus_common", - "//services/ui/common:task_runner_test_base", - "//services/ui/gpu_host", - "//services/ui/gpu_host:test_support", - "//services/ui/public/cpp", - "//services/ui/public/interfaces", - "//testing/gtest", - "//third_party/mesa:osmesa", - "//ui/aura", - "//ui/aura:test_support", - "//ui/events", - "//ui/gfx", - "//ui/gfx:test_support", - "//ui/gfx/geometry", - "//ui/gfx/geometry/mojo", - "//ui/gl", - "//ui/gl/init", - ] - - data_deps = [ - "//services/ui", - ] -} - -service_manifest("unittests_manifest") { - name = "ui_service_unittests" - source = "test_manifest.json" -} - -catalog("tests_catalog") { - testonly = true - embedded_services = [ ":unittests_manifest" ] - standalone_services = [ "//services/ui:manifest" ] -}
diff --git a/services/ui/ws/DEPS b/services/ui/ws/DEPS deleted file mode 100644 index 67bb2c7..0000000 --- a/services/ui/ws/DEPS +++ /dev/null
@@ -1,16 +0,0 @@ -include_rules = [ - "+components/viz/common", - "+components/viz/host", - "+gpu/command_buffer/client", - "+gpu/config", - "+gpu/ipc/client", - "+gpu/ipc/common", - "+services/viz/privileged/interfaces", - "+services/viz/public/interfaces", -] - -specific_include_rules = { - ".*_(unit|pixel|perf)test.*\.cc": [ - "+components/viz/test", - ], -}
diff --git a/services/ui/ws/OWNERS b/services/ui/ws/OWNERS deleted file mode 100644 index c47f9de..0000000 --- a/services/ui/ws/OWNERS +++ /dev/null
@@ -1,8 +0,0 @@ -per-file *gpu*=fsamuel@chromium.org -per-file *gpu*=sadrul@chromium.org -per-file *compositor_frame*=fsamuel@chromium.org -per-file *compositor_frame*=rjkroege@chromium.org -per-file *frame_generator*=fsamuel@chromium.org - -per-file test_manifest.json=set noparent -per-file test_manifest.json=file://ipc/SECURITY_OWNERS
diff --git a/services/ui/ws/README.md b/services/ui/ws/README.md deleted file mode 100644 index 35688fe5..0000000 --- a/services/ui/ws/README.md +++ /dev/null
@@ -1,113 +0,0 @@ -This directory contains the Window Service implementation. - -## Ids - -Each client connected to the Window Service is assigned a unique id inside the -Window Service. This id is a monotonically increasing uint32_t. This is often -referred to as the client_id. - -The Window Service uses a client_id of 1 for itself; 0 is not a valid client_id -in the Window Service. - -As clients do not know their id, they always supply 0 as the client id in the -mojom related functions. Internally the Window Service maps 0 to the real client -id. - -Windows have a couple of different (related) ids. - -### ClientWindowId - -ClientWindowId is a uint64_t pairing of a client_id and a window_id. The -window_id is a uint32_t assigned by the client, and should be unique within that -client's scope. When communicating with the Window Service, clients may use 0 as -the client_id to refer to their own windows. The Window Service maps 0 to the -real client_id. In Window Service code the id from the client is typically -referred to as the transport_window_id. Mojom functions that receive the -transport_window_id map it to a ClientWindowId. ClientWindowId is a real class -that provides type safety. - -When a client is embedded in an existing window, the embedded client is given -visibility to a Window created by the embedder. In this case the Window Service -supplies the ClientWindowId to the embedded client and uses the ClientWindowId -at the time the Window was created (the ClientWindowId actually comes from the -FrameSinkId, see below for details on FrameSinkId). In other words, both the -embedder and embedded client use the same ClientWindowId for the Window. See -discussion on FrameSinkId for more details. - -For a client to establish an embed root, it first calls -ScheduleEmbedForExistingClient(), so it can provide a window_id that is unique -within its own scope. That client then passes the returned token to what will -become its embedder to call EmbedUsingToken(). In this case, the embedder and -embedded client do not use the same ClientWindowId for the Window. - -ClientWindowId is globally unique, but a Window may have multiple -ClientWindowIds associated with it. - -TODO(sky): See http://crbug.com/817850 for making it so there is only one -ClientWindowId per Window. - -### FrameSinkId - -Each Window has a FrameSinkId that is needed for both hit-testing and -embedding. The FrameSinkId is initialized to the ClientWindowId of the client -creating the Window, but it changes during an embedding. In particular, when a -client calls Embed() the FrameSinkId of the Window changes such that the -client_id of the FrameSinkId matches the client_id of the client being -embedded and the sink_id is set to 0. The embedder is informed of this by way of -OnFrameSinkIdAllocated(). The embedded client is informed of the original -FrameSinkId (the client_id of the FrameSinkId matches the embedder's client_id). -In client code the embedded client ends up *always* using a client_id of 0 for -the FrameSinkId. This works because Viz knows the real client_id and handles -mapping 0 to the real client_id. - -The FrameSinkId of top-level windows is set to the ClientWindowId from the -client requesting the top-level (top-levels are created and owned by the Window -Manager). The Window Manager is told the updated FrameSinkId when it is asked -to create the top-level (WmCreateTopLevelWindow()). - -The FrameSinkId of an embed root's Window is set to the ClientWindowId of the -embed root's Window from the embedded client. - -### LocalSurfaceId - -The LocalSurfaceId (which contains unguessable) is necessary if the client wants -to submit a compositor-frame for the Window (it wants to show something on -screen), and not needed if the client only wants to submit a hit-test region. -The LocalSurfaceId may be assigned when the bounds and/or device-scale-factor -changes. The LocalSurfaceId can change at other times as well (perhaps to -synchronize an effect with the embedded client). The LocalSurfaceId is intended -to allow for smooth resizes and ensures at embed points the CompositorFrame from -both clients match. Client code supplies a LocalSurfaceId for windows that have -another client embedded in them as well as windows with a LayerTreeFrameSink. -The LocalSurfaceId comes from the owner of the window. The embedded client is -told of changes to the LocalSurfaceId by way of OnWindowBoundsChanged(). This is -still very much a work in progress. - -FrameSinkId is derived from the embedded client, where as LocalSurfaceId -comes from the embedder. - -### Event Processing - -One of the key operations of the Window Service is event processing. This -includes maintaining state associated with the current input devices (such -as the location of the mouse cursor) as well dispatching to the appropriate -client. Event processing includes the following classes, see each for more -details: -. EventDispatcherImpl: events received from the platform are sent here first. - If not already processing an event EventDispatcherImpl forwards the event to - EventProcessor. If EventDispatcherImpl is processing an event it queues the - event for later processing. -. EventProcessor: maintains state related to event processing, passing the - appropriate events and targets to EventDispatcher for dispatch. -. AsyncEventDispatcher: dispatches an event to the client, notifying a callback - when done. This interface is largely for testing with WindowTree providing - the implementation. -. EventTargeter: used by EventProcessor to determine the ServerWindow to send an - event to. Targetting is potentially asynchronous. - -EventDispatcherImpl and EventProcessor both have delegates that can impact -targetting, as well as being notified during the lifecycle of processing. - -EventInjector is not a core part of event processing. It allows remote clients -to inject events for testing, remoting and similar use cases. Events injected -via EventInjector end up going to EventProcessor.
diff --git a/services/ui/ws/accelerator.cc b/services/ui/ws/accelerator.cc deleted file mode 100644 index ede15dd9..0000000 --- a/services/ui/ws/accelerator.cc +++ /dev/null
@@ -1,33 +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 "services/ui/ws/accelerator.h" - -namespace ui { -namespace ws { - -Accelerator::Accelerator(uint32_t id, const mojom::EventMatcher& matcher) - : id_(id), - accelerator_phase_(matcher.accelerator_phase), - event_matcher_(matcher), - weak_factory_(this) {} - -Accelerator::~Accelerator() {} - -bool Accelerator::MatchesEvent(const ui::Event& event, - const ui::mojom::AcceleratorPhase phase) const { - if (accelerator_phase_ != phase) - return false; - if (!event_matcher_.MatchesEvent(event)) - return false; - return true; -} - -bool Accelerator::EqualEventMatcher(const Accelerator* other) const { - return accelerator_phase_ == other->accelerator_phase_ && - event_matcher_.Equals(other->event_matcher_); -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/accelerator.h b/services/ui/ws/accelerator.h deleted file mode 100644 index 03bd535e..0000000 --- a/services/ui/ws/accelerator.h +++ /dev/null
@@ -1,57 +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. - -#ifndef SERVICES_UI_WS_ACCELERATOR_H_ -#define SERVICES_UI_WS_ACCELERATOR_H_ - -#include <stdint.h> - -#include "base/macros.h" -#include "base/memory/weak_ptr.h" -#include "services/ui/public/interfaces/event_matcher.mojom.h" -#include "services/ui/ws/event_matcher.h" - -namespace ui { -class Event; -} - -namespace ui { -namespace ws { - -// An Accelerator encompasses an id defined by the client, along with a unique -// mojom::EventMatcher. See WindowManagerClient. -// -// This provides a WeakPtr, as the client might delete the accelerator between -// an event having been matched and the dispatch of the accelerator to the -// client. -class Accelerator { - public: - Accelerator(uint32_t id, const mojom::EventMatcher& matcher); - ~Accelerator(); - - // Returns true if |event| and |phase | matches the definition in the - // mojom::EventMatcher used for initialization. - bool MatchesEvent(const ui::Event& event, - const ui::mojom::AcceleratorPhase phase) const; - - // Returns true if |other| was created with an identical mojom::EventMatcher. - bool EqualEventMatcher(const Accelerator* other) const; - - base::WeakPtr<Accelerator> GetWeakPtr() { return weak_factory_.GetWeakPtr(); } - - uint32_t id() const { return id_; } - - private: - uint32_t id_; - ui::mojom::AcceleratorPhase accelerator_phase_; - EventMatcher event_matcher_; - base::WeakPtrFactory<Accelerator> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(Accelerator); -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_ACCELERATOR_H_
diff --git a/services/ui/ws/access_policy.h b/services/ui/ws/access_policy.h deleted file mode 100644 index 2184e71..0000000 --- a/services/ui/ws/access_policy.h +++ /dev/null
@@ -1,96 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SERVICES_UI_WS_ACCESS_POLICY_H_ -#define SERVICES_UI_WS_ACCESS_POLICY_H_ - -#include <stdint.h> - -#include "services/ui/public/interfaces/window_tree.mojom.h" -#include "services/ui/public/interfaces/window_tree_constants.mojom.h" -#include "services/ui/ws/ids.h" - -namespace ui { -namespace ws { - -class AccessPolicyDelegate; -class ServerWindow; - -// AccessPolicy is used by WindowTree to determine what the WindowTree is -// allowed to do. -class AccessPolicy { - public: - virtual ~AccessPolicy() {} - - virtual void Init(ClientSpecificId client_id, - AccessPolicyDelegate* delegate) = 0; - - // Unless otherwise mentioned all arguments have been validated. That is the - // |window| arguments are non-null unless otherwise stated (eg CanSetWindow() - // is allowed to take a NULL window). - virtual bool CanRemoveWindowFromParent(const ServerWindow* window) const = 0; - virtual bool CanAddWindow(const ServerWindow* parent, - const ServerWindow* child) const = 0; - virtual bool CanAddTransientWindow(const ServerWindow* parent, - const ServerWindow* child) const = 0; - virtual bool CanRemoveTransientWindowFromParent( - const ServerWindow* window) const = 0; - virtual bool CanSetModal(const ServerWindow* window) const = 0; - virtual bool CanSetChildModalParent( - const ServerWindow* window, - const ServerWindow* modal_parent) const = 0; - virtual bool CanReorderWindow(const ServerWindow* window, - const ServerWindow* relative_window, - mojom::OrderDirection direction) const = 0; - virtual bool CanDeleteWindow(const ServerWindow* window) const = 0; - virtual bool CanGetWindowTree(const ServerWindow* window) const = 0; - // Used when building a window tree (GetWindowTree()) to decide if we should - // descend into |window|. - virtual bool CanDescendIntoWindowForWindowTree( - const ServerWindow* window) const = 0; - virtual bool CanEmbed(const ServerWindow* window) const = 0; - virtual bool CanChangeWindowVisibility(const ServerWindow* window) const = 0; - virtual bool CanChangeWindowOpacity(const ServerWindow* window) const = 0; - virtual bool CanSetWindowCompositorFrameSink( - const ServerWindow* window) const = 0; - virtual bool CanSetWindowBounds(const ServerWindow* window) const = 0; - virtual bool CanSetWindowTransform(const ServerWindow* window) const = 0; - virtual bool CanSetWindowProperties(const ServerWindow* window) const = 0; - virtual bool CanSetWindowTextInputState(const ServerWindow* window) const = 0; - virtual bool CanSetCapture(const ServerWindow* window) const = 0; - virtual bool CanSetFocus(const ServerWindow* window) const = 0; - virtual bool CanSetClientArea(const ServerWindow* window) const = 0; - virtual bool CanSetHitTestMask(const ServerWindow* window) const = 0; - virtual bool CanSetAcceptDrops(const ServerWindow* window) const = 0; - virtual bool CanSetEventTargetingPolicy(const ServerWindow* window) const = 0; - virtual bool CanStackAbove(const ServerWindow* above, - const ServerWindow* below) const = 0; - virtual bool CanStackAtTop(const ServerWindow* window) const = 0; - virtual bool CanPerformWmAction(const ServerWindow* window) const = 0; - // Used for all client controllable cursor properties; which cursor should be - // displayed, visibility, locking, etc. - virtual bool CanSetCursorProperties(const ServerWindow* window) const = 0; - virtual bool CanInitiateDragLoop(const ServerWindow* window) const = 0; - virtual bool CanInitiateMoveLoop(const ServerWindow* window) const = 0; - - // Returns whether the client should notify on a hierarchy change. - // |new_parent| and |old_parent| are initially set to the new and old parents - // but may be altered so that the client only sees a certain set of windows. - virtual bool ShouldNotifyOnHierarchyChange( - const ServerWindow* window, - const ServerWindow** new_parent, - const ServerWindow** old_parent) const = 0; - virtual bool CanSetWindowManager() const = 0; - - // Returns the window to supply to the client when focus changes to |focused|. - virtual const ServerWindow* GetWindowForFocusChange( - const ServerWindow* focused) = 0; - - virtual bool IsValidIdForNewWindow(const ClientWindowId& id) const = 0; -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_ACCESS_POLICY_H_
diff --git a/services/ui/ws/access_policy_delegate.h b/services/ui/ws/access_policy_delegate.h deleted file mode 100644 index 378995dc4..0000000 --- a/services/ui/ws/access_policy_delegate.h +++ /dev/null
@@ -1,42 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SERVICES_UI_WS_ACCESS_POLICY_DELEGATE_H_ -#define SERVICES_UI_WS_ACCESS_POLICY_DELEGATE_H_ - -namespace ui { -namespace ws { - -class ServerWindow; - -// Delegate used by the AccessPolicy implementations to get state. -class AccessPolicyDelegate { - public: - // Returns true if the tree has |window| as one of its roots. - virtual bool HasRootForAccessPolicy(const ServerWindow* window) const = 0; - - // Returns true if |window| has been exposed to the client. - virtual bool IsWindowKnownForAccessPolicy( - const ServerWindow* window) const = 0; - - // Returns true if Embed(window) has been invoked on |window|. - virtual bool IsWindowRootOfAnotherTreeForAccessPolicy( - const ServerWindow* window) const = 0; - - // Returns true if |window| was created by the window manager. - virtual bool IsWindowCreatedByWindowManager( - const ServerWindow* window) const = 0; - - // Returns true if the tree intercepts events targetted at |window|. - virtual bool ShouldInterceptEventsForAccessPolicy( - const ServerWindow* window) const = 0; - - protected: - virtual ~AccessPolicyDelegate() {} -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_ACCESS_POLICY_DELEGATE_H_
diff --git a/services/ui/ws/accessibility_manager.cc b/services/ui/ws/accessibility_manager.cc deleted file mode 100644 index 02d8781..0000000 --- a/services/ui/ws/accessibility_manager.cc +++ /dev/null
@@ -1,29 +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 "services/ui/ws/accessibility_manager.h" - -#include "services/ui/ws/window_server.h" - -namespace ui { -namespace ws { - -AccessibilityManager::AccessibilityManager(WindowServer* window_server) - : window_server_(window_server), binding_(this) { - DCHECK(window_server_); -} - -AccessibilityManager::~AccessibilityManager() {} - -void AccessibilityManager::Bind(mojom::AccessibilityManagerRequest request) { - binding_.Close(); - binding_.Bind(std::move(request)); -} - -void AccessibilityManager::SetHighContrastMode(bool enabled) { - window_server_->SetHighContrastMode(enabled); -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/accessibility_manager.h b/services/ui/ws/accessibility_manager.h deleted file mode 100644 index a4d65b3f..0000000 --- a/services/ui/ws/accessibility_manager.h +++ /dev/null
@@ -1,36 +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. - -#ifndef SERVICES_UI_WS_ACCESSIBILITY_MANAGER_H_ -#define SERVICES_UI_WS_ACCESSIBILITY_MANAGER_H_ - -#include "mojo/public/cpp/bindings/binding.h" -#include "services/ui/public/interfaces/accessibility_manager.mojom.h" - -namespace ui { -namespace ws { - -class WindowServer; - -class AccessibilityManager : public mojom::AccessibilityManager { - public: - explicit AccessibilityManager(WindowServer* window_server); - ~AccessibilityManager() override; - - void Bind(mojom::AccessibilityManagerRequest request); - - private: - // mojom::AccessibilityManager: - void SetHighContrastMode(bool enabled) override; - - WindowServer* window_server_; - mojo::Binding<mojom::AccessibilityManager> binding_; - - DISALLOW_COPY_AND_ASSIGN(AccessibilityManager); -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_ACCESSIBILITY_MANAGER_H_
diff --git a/services/ui/ws/async_event_dispatcher.h b/services/ui/ws/async_event_dispatcher.h deleted file mode 100644 index a4d889e..0000000 --- a/services/ui/ws/async_event_dispatcher.h +++ /dev/null
@@ -1,66 +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 SERVICES_UI_WS_ASYNC_EVENT_DISPATCHER_H_ -#define SERVICES_UI_WS_ASYNC_EVENT_DISPATCHER_H_ - -#include <stdint.h> - -#include <string> - -#include "base/callback_forward.h" -#include "base/containers/flat_map.h" - -namespace ui { -class Event; -} - -namespace ui { -namespace mojom { -enum class EventReslut; -} -namespace ws { - -class ServerWindow; - -struct EventLocation; - -// AsyncEventDispatchers dispatch events asynchronously. A callback is run once -// the accelerator or event is dispatched. This class allows the event -// dispatching code to be independent of WindowTree (for testing and -// modularity). -// -// If an AsyncEventDispatcher does not run the callback in a reasonable amount -// of time, Dispatch* may be called again. -class AsyncEventDispatcher { - public: - using DispatchEventCallback = base::OnceCallback<void(mojom::EventResult)>; - // Dispatches |event| to |target|, running |callback| with the result. - // |event_location| is only useful for located events. - virtual void DispatchEvent(ServerWindow* target, - const Event& event, - const EventLocation& event_location, - DispatchEventCallback callback) = 0; - - // In addition to the result of the accelerator, AcceleratorCallback is - // supplied arbitrary key-value pairs that are added to the event if - // further processing is necessary (EventResult::UNHANDLED is supplied to the - // callback). The intepretation of the key-value pairs is left to clients (see - // ash/public/interfaces/event_properties.mojom for examples). - using AcceleratorCallback = base::OnceCallback<void( - mojom::EventResult, - const base::flat_map<std::string, std::vector<uint8_t>>&)>; - - // Dispatches an accelerator that matches |event|, running the callback with - // the result and key-value pairs. |accelerator_id| identifies the - // accelerator. - virtual void DispatchAccelerator(uint32_t accelerator_id, - const Event& event, - AcceleratorCallback callback) = 0; -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_ASYNC_EVENT_DISPATCHER_H_
diff --git a/services/ui/ws/async_event_dispatcher_lookup.h b/services/ui/ws/async_event_dispatcher_lookup.h deleted file mode 100644 index e4ee1eab..0000000 --- a/services/ui/ws/async_event_dispatcher_lookup.h +++ /dev/null
@@ -1,26 +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 SERVICES_UI_WS_ASYNC_EVENT_DISPATCHER_LOOKUP_H_ -#define SERVICES_UI_WS_ASYNC_EVENT_DISPATCHER_LOOKUP_H_ - -#include "services/ui/common/types.h" - -namespace ui { -namespace ws { - -class AsyncEventDispatcher; - -// Looks up an AsyncEventDispatcher by id. This is used so that event processing -// related code does not have a dependency on WindowTree or WindowService. -class AsyncEventDispatcherLookup { - public: - virtual AsyncEventDispatcher* GetAsyncEventDispatcherById( - ClientSpecificId id) = 0; -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_ASYNC_EVENT_DISPATCHER_LOOKUP_H_
diff --git a/services/ui/ws/compositor_frame_sink_client_binding.cc b/services/ui/ws/compositor_frame_sink_client_binding.cc deleted file mode 100644 index 95626cfd..0000000 --- a/services/ui/ws/compositor_frame_sink_client_binding.cc +++ /dev/null
@@ -1,64 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "services/ui/ws/compositor_frame_sink_client_binding.h" - -namespace ui { -namespace ws { - -CompositorFrameSinkClientBinding::CompositorFrameSinkClientBinding( - viz::mojom::CompositorFrameSinkClient* sink_client, - viz::mojom::CompositorFrameSinkClientRequest sink_client_request, - viz::mojom::CompositorFrameSinkAssociatedPtr compositor_frame_sink) - : binding_(sink_client, std::move(sink_client_request)), - compositor_frame_sink_(std::move(compositor_frame_sink)) {} - -CompositorFrameSinkClientBinding::~CompositorFrameSinkClientBinding() = default; - -void CompositorFrameSinkClientBinding::SetWantsAnimateOnlyBeginFrames() { - compositor_frame_sink_->SetWantsAnimateOnlyBeginFrames(); -} - -void CompositorFrameSinkClientBinding::SetNeedsBeginFrame( - bool needs_begin_frame) { - compositor_frame_sink_->SetNeedsBeginFrame(needs_begin_frame); -} - -void CompositorFrameSinkClientBinding::SubmitCompositorFrame( - const viz::LocalSurfaceId& local_surface_id, - viz::CompositorFrame frame, - base::Optional<viz::HitTestRegionList> hit_test_region_list, - uint64_t submit_time) { - compositor_frame_sink_->SubmitCompositorFrame( - local_surface_id, std::move(frame), std::move(hit_test_region_list), - submit_time); -} - -void CompositorFrameSinkClientBinding::SubmitCompositorFrameSync( - const viz::LocalSurfaceId& local_surface_id, - viz::CompositorFrame frame, - base::Optional<viz::HitTestRegionList> hit_test_region_list, - uint64_t submit_time, - const SubmitCompositorFrameSyncCallback callback) { - NOTIMPLEMENTED(); -} - -void CompositorFrameSinkClientBinding::DidNotProduceFrame( - const viz::BeginFrameAck& ack) { - compositor_frame_sink_->DidNotProduceFrame(ack); -} - -void CompositorFrameSinkClientBinding::DidAllocateSharedBitmap( - mojo::ScopedSharedBufferHandle buffer, - const viz::SharedBitmapId& id) { - compositor_frame_sink_->DidAllocateSharedBitmap(std::move(buffer), id); -} - -void CompositorFrameSinkClientBinding::DidDeleteSharedBitmap( - const viz::SharedBitmapId& id) { - compositor_frame_sink_->DidDeleteSharedBitmap(id); -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/compositor_frame_sink_client_binding.h b/services/ui/ws/compositor_frame_sink_client_binding.h deleted file mode 100644 index c9f48485..0000000 --- a/services/ui/ws/compositor_frame_sink_client_binding.h +++ /dev/null
@@ -1,57 +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 SERVICES_UI_WS_COMPOSITOR_FRAME_SINK_CLIENT_BINDING_H_ -#define SERVICES_UI_WS_COMPOSITOR_FRAME_SINK_CLIENT_BINDING_H_ - -#include "base/macros.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "services/viz/privileged/interfaces/compositing/frame_sink_manager.mojom.h" -#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h" - -namespace ui { -namespace ws { - -// CompositorFrameSinkClientBinding manages the binding between a FrameGenerator -// and its CompositorFrameSink. CompositorFrameSinkClientBinding exists so -// that a mock implementation of CompositorFrameSink can be injected for -// tests. FrameGenerator owns its associated CompositorFrameSinkClientBinding. -class CompositorFrameSinkClientBinding - : public viz::mojom::CompositorFrameSink { - public: - CompositorFrameSinkClientBinding( - viz::mojom::CompositorFrameSinkClient* sink_client, - viz::mojom::CompositorFrameSinkClientRequest sink_client_request, - viz::mojom::CompositorFrameSinkAssociatedPtr compositor_frame_sink); - ~CompositorFrameSinkClientBinding() override; - - private: - // viz::mojom::CompositorFrameSink implementation: - void SubmitCompositorFrame( - const viz::LocalSurfaceId& local_surface_id, - viz::CompositorFrame frame, - base::Optional<viz::HitTestRegionList> hit_test_region_list, - uint64_t submit_time) override; - void SubmitCompositorFrameSync( - const viz::LocalSurfaceId& local_surface_id, - viz::CompositorFrame frame, - base::Optional<viz::HitTestRegionList> hit_test_region_list, - uint64_t submit_time, - const SubmitCompositorFrameSyncCallback callback) override; - void SetNeedsBeginFrame(bool needs_begin_frame) override; - void SetWantsAnimateOnlyBeginFrames() override; - void DidNotProduceFrame(const viz::BeginFrameAck& ack) override; - void DidAllocateSharedBitmap(mojo::ScopedSharedBufferHandle buffer, - const viz::SharedBitmapId& id) override; - void DidDeleteSharedBitmap(const viz::SharedBitmapId& id) override; - - mojo::Binding<viz::mojom::CompositorFrameSinkClient> binding_; - viz::mojom::CompositorFrameSinkAssociatedPtr compositor_frame_sink_; - - DISALLOW_COPY_AND_ASSIGN(CompositorFrameSinkClientBinding); -}; -} -} - -#endif // SERVICES_UI_WS_COMPOSITOR_FRAME_SINK_CLIENT_BINDING_H_
diff --git a/services/ui/ws/cursor_location_manager.cc b/services/ui/ws/cursor_location_manager.cc deleted file mode 100644 index a958716..0000000 --- a/services/ui/ws/cursor_location_manager.cc +++ /dev/null
@@ -1,50 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "services/ui/ws/cursor_location_manager.h" - -#include "ui/gfx/geometry/point.h" - -namespace ui { -namespace ws { - -CursorLocationManager::CursorLocationManager() {} - -CursorLocationManager::~CursorLocationManager() {} - -void CursorLocationManager::OnMouseCursorLocationChanged( - const gfx::Point& point_in_dip) { - current_cursor_location_ = static_cast<base::subtle::Atomic32>( - (point_in_dip.x() & 0xFFFF) << 16 | (point_in_dip.y() & 0xFFFF)); - if (cursor_location_memory()) { - base::subtle::NoBarrier_Store(cursor_location_memory(), - current_cursor_location_); - } -} - -mojo::ScopedSharedBufferHandle -CursorLocationManager::GetCursorLocationMemory() { - if (!cursor_location_handle_.is_valid()) { - // Create our shared memory segment to share the cursor state with our - // window clients. - cursor_location_handle_ = - mojo::SharedBufferHandle::Create(sizeof(base::subtle::Atomic32)); - - if (!cursor_location_handle_.is_valid()) - return mojo::ScopedSharedBufferHandle(); - - cursor_location_mapping_ = - cursor_location_handle_->Map(sizeof(base::subtle::Atomic32)); - if (!cursor_location_mapping_) - return mojo::ScopedSharedBufferHandle(); - base::subtle::NoBarrier_Store(cursor_location_memory(), - current_cursor_location_); - } - - return cursor_location_handle_->Clone( - mojo::SharedBufferHandle::AccessMode::READ_ONLY); -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/cursor_location_manager.h b/services/ui/ws/cursor_location_manager.h deleted file mode 100644 index 348ee43..0000000 --- a/services/ui/ws/cursor_location_manager.h +++ /dev/null
@@ -1,64 +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 SERVICES_UI_WS_CURSOR_LOCATION_MANAGER_H_ -#define SERVICES_UI_WS_CURSOR_LOCATION_MANAGER_H_ - -#include "base/atomicops.h" -#include "base/macros.h" -#include "mojo/public/cpp/system/buffer.h" - -namespace gfx { -class Point; -} - -namespace ui { -namespace ws { -namespace test { -class CursorLocationManagerTestApi; -} - -// Manages a shared memory buffer that stores the cursor location. -class CursorLocationManager { - public: - CursorLocationManager(); - ~CursorLocationManager(); - - // Sets the current cursor location to |point|. Atomically writes the location - // to shared memory. |point| should be in screen-coord and DIP. - void OnMouseCursorLocationChanged(const gfx::Point& point_in_dip); - - // Returns a read-only handle to the shared memory which contains the global - // mouse cursor position. Each call returns a new handle. - mojo::ScopedSharedBufferHandle GetCursorLocationMemory(); - - private: - friend test::CursorLocationManagerTestApi; - - base::subtle::Atomic32* cursor_location_memory() { - return reinterpret_cast<base::subtle::Atomic32*>( - cursor_location_mapping_.get()); - } - - // The current location of the cursor. This is always kept up to date so we - // can atomically write this to |cursor_location_memory()| once it is created. - base::subtle::Atomic32 current_cursor_location_ = 0; - - // A handle to a shared memory buffer that is one 32 bit integer long. We - // share this with any client as the same user. This buffer is lazily - // created on the first access. - mojo::ScopedSharedBufferHandle cursor_location_handle_; - - // The one int32 in |cursor_location_handle_|. When we write to this - // location, we must always write to it atomically. (On the other side of the - // mojo connection, this data must be read atomically.) - mojo::ScopedSharedBufferMapping cursor_location_mapping_; - - DISALLOW_COPY_AND_ASSIGN(CursorLocationManager); -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_CURSOR_LOCATION_MANAGER_H_
diff --git a/services/ui/ws/cursor_location_manager_unittest.cc b/services/ui/ws/cursor_location_manager_unittest.cc deleted file mode 100644 index 6548a40..0000000 --- a/services/ui/ws/cursor_location_manager_unittest.cc +++ /dev/null
@@ -1,58 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "services/ui/ws/cursor_location_manager.h" - -#include "base/atomicops.h" -#include "services/ui/ws/test_utils.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/gfx/geometry/point.h" - -namespace ui { -namespace ws { -namespace test { - -TEST(CursorLocationManagerTest, PositiveCoordinates) { - const gfx::Point point(100, 150); - - CursorLocationManager cursor_location_manager; - cursor_location_manager.OnMouseCursorLocationChanged(point); - - base::subtle::Atomic32* cursor_location_memory = nullptr; - mojo::ScopedSharedBufferHandle handle = - cursor_location_manager.GetCursorLocationMemory(); - mojo::ScopedSharedBufferMapping cursor_location_mapping = - handle->Map(sizeof(base::subtle::Atomic32)); - ASSERT_TRUE(cursor_location_mapping); - cursor_location_memory = - reinterpret_cast<base::subtle::Atomic32*>(cursor_location_mapping.get()); - - base::subtle::Atomic32 location = - base::subtle::NoBarrier_Load(cursor_location_memory); - EXPECT_EQ(point, Atomic32ToPoint(location)); -} - -TEST(CursorLocationManagerTest, NegativeCoordinates) { - const gfx::Point point(-10, -11); - - CursorLocationManager cursor_location_manager; - cursor_location_manager.OnMouseCursorLocationChanged(point); - - base::subtle::Atomic32* cursor_location_memory = nullptr; - mojo::ScopedSharedBufferHandle handle = - cursor_location_manager.GetCursorLocationMemory(); - mojo::ScopedSharedBufferMapping cursor_location_mapping = - handle->Map(sizeof(base::subtle::Atomic32)); - ASSERT_TRUE(cursor_location_mapping); - cursor_location_memory = - reinterpret_cast<base::subtle::Atomic32*>(cursor_location_mapping.get()); - - base::subtle::Atomic32 location = - base::subtle::NoBarrier_Load(cursor_location_memory); - EXPECT_EQ(point, Atomic32ToPoint(location)); -} - -} // namespace test -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/cursor_state.cc b/services/ui/ws/cursor_state.cc deleted file mode 100644 index a921378..0000000 --- a/services/ui/ws/cursor_state.cc +++ /dev/null
@@ -1,168 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "services/ui/ws/cursor_state.h" - -#include "services/ui/ws/display.h" -#include "services/ui/ws/display_manager.h" -#include "ui/base/cursor/cursor.h" - -namespace ui { -namespace ws { - -class CursorState::StateSnapshot { - public: - StateSnapshot() = default; - StateSnapshot(const StateSnapshot& rhs) = default; - ~StateSnapshot() = default; - - const base::Optional<ui::CursorData>& global_override_cursor() const { - return global_override_cursor_; - } - void SetGlobalOverrideCursor(const base::Optional<ui::CursorData>& cursor) { - global_override_cursor_ = cursor; - } - - const ui::CursorData& cursor_data() const { return cursor_data_; } - void SetCursorData(const ui::CursorData& data) { cursor_data_ = data; } - - bool visible() const { return visible_; } - void set_visible(bool visible) { visible_ = visible; } - - ui::CursorSize cursor_size() const { return cursor_size_; } - void set_cursor_size(ui::CursorSize cursor_size) { - cursor_size_ = cursor_size; - } - - bool cursor_touch_visible() const { return cursor_touch_visible_; } - void set_cursor_touch_visible(bool enabled) { - cursor_touch_visible_ = enabled; - } - - private: - // An optional cursor set by the window manager which overrides per-window - // requests. - base::Optional<ui::CursorData> global_override_cursor_; - - // The last cursor set. Used to track whether we need to change the cursor. - ui::CursorData cursor_data_ = ui::CursorData(ui::CursorType::kNull); - - // Which cursor set to use. - ui::CursorSize cursor_size_ = CursorSize::kNormal; - - // Whether the cursor is visible. - bool visible_ = true; - - // An extra visibility check separate from user control which shows/hides - // based on whether the last event was a touch or a mouse event. - bool cursor_touch_visible_ = true; -}; - -CursorState::CursorState(DisplayManager* display_manager, - CursorStateDelegate* delegate) - : display_manager_(display_manager), - delegate_(delegate), - current_state_(std::make_unique<StateSnapshot>()), - state_on_unlock_(std::make_unique<StateSnapshot>()) {} - -CursorState::~CursorState() {} - -void CursorState::SetCurrentWindowCursor(const ui::CursorData& cursor) { - if (!state_on_unlock_->cursor_data().IsSameAs(cursor)) - state_on_unlock_->SetCursorData(cursor); - - if (cursor_lock_count_ == 0 && - !current_state_->cursor_data().IsSameAs(cursor)) { - current_state_->SetCursorData(cursor); - SetPlatformCursor(); - } -} - -void CursorState::LockCursor() { - cursor_lock_count_++; -} - -void CursorState::UnlockCursor() { - cursor_lock_count_--; - DCHECK_GE(cursor_lock_count_, 0); - if (cursor_lock_count_ > 0) - return; - - if (current_state_->cursor_touch_visible() != - state_on_unlock_->cursor_touch_visible()) { - NotifyCursorTouchVisibleChanged(state_on_unlock_->cursor_touch_visible()); - } - - *current_state_ = *state_on_unlock_; - SetPlatformCursorSize(); - SetPlatformCursor(); -} - -void CursorState::SetCursorVisible(bool visible) { - state_on_unlock_->set_visible(visible); - if (cursor_lock_count_ == 0 && - current_state_->visible() != state_on_unlock_->visible()) { - current_state_->set_visible(visible); - SetPlatformCursor(); - } -} - -void CursorState::SetGlobalOverrideCursor( - const base::Optional<ui::CursorData>& cursor) { - state_on_unlock_->SetGlobalOverrideCursor(cursor); - if (cursor_lock_count_ == 0) { - current_state_->SetGlobalOverrideCursor(cursor); - SetPlatformCursor(); - } -} - -void CursorState::SetCursorSize(ui::CursorSize cursor_size) { - state_on_unlock_->set_cursor_size(cursor_size); - if (cursor_lock_count_ == 0 && - current_state_->cursor_size() != state_on_unlock_->cursor_size()) { - current_state_->set_cursor_size(cursor_size); - SetPlatformCursorSize(); - SetPlatformCursor(); - } -} - -void CursorState::SetCursorTouchVisible(bool enabled) { - state_on_unlock_->set_cursor_touch_visible(enabled); - if (cursor_lock_count_ == 0 && current_state_->cursor_touch_visible() != - state_on_unlock_->cursor_touch_visible()) { - current_state_->set_cursor_touch_visible(enabled); - NotifyCursorTouchVisibleChanged(enabled); - SetPlatformCursor(); - } -} - -void CursorState::NotifyCursorTouchVisibleChanged(bool enabled) { - delegate_->OnCursorTouchVisibleChanged(enabled); -} - -void CursorState::SetPlatformCursorSize() { - DisplayManager* manager = display_manager_; - for (Display* display : manager->displays()) - display->SetNativeCursorSize(current_state_->cursor_size()); -} - -void CursorState::SetPlatformCursor() { - DisplayManager* manager = display_manager_; - auto set_on_all = [manager](const ui::CursorData& cursor) { - for (Display* display : manager->displays()) - display->SetNativeCursor(cursor); - }; - - if (current_state_->visible() && current_state_->cursor_touch_visible()) { - if (current_state_->global_override_cursor().has_value()) - set_on_all(current_state_->global_override_cursor().value()); - else - set_on_all(current_state_->cursor_data()); - } else { - set_on_all(ui::CursorData(ui::CursorType::kNone)); - } -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/cursor_state.h b/services/ui/ws/cursor_state.h deleted file mode 100644 index 5db99e38..0000000 --- a/services/ui/ws/cursor_state.h +++ /dev/null
@@ -1,85 +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 SERVICES_UI_WS_CURSOR_STATE_H_ -#define SERVICES_UI_WS_CURSOR_STATE_H_ - -#include <memory> - -#include "base/optional.h" -#include "services/ui/ws/cursor_state_delegate.h" -#include "ui/base/cursor/cursor_data.h" - -namespace ui { - -enum class CursorSize; - -namespace ws { - -class DisplayManager; - -// Owns all the state about if and how the cursor is displayed in mus. -class CursorState { - public: - CursorState(DisplayManager* display_manager, CursorStateDelegate* delegate); - ~CursorState(); - - // Sets the normal cursor which would be used if the window manager hasn't - // set an override cursor. - void SetCurrentWindowCursor(const ui::CursorData& cursor); - - // When the cursor is locked, changes to the cursor are queued up. Queued - // changes are performed atomically when the cursor is unlocked. - void LockCursor(); - void UnlockCursor(); - - // Whether the cursor is visible on the display. - void SetCursorVisible(bool visible); - - // Sets a cursor globally, which overrides the per-window cursors. - void SetGlobalOverrideCursor(const base::Optional<ui::CursorData>& cursor); - - // Sets the cursor size. - void SetCursorSize(ui::CursorSize cursor_size); - - // Sets whether the cursor is hidden because the user is interacting with the - // touch screen. - void SetCursorTouchVisible(bool enabled); - - private: - // A snapshot of the cursor state at a specific time. - class StateSnapshot; - - // Notifies the window manager when the value of mouse events enabled changes. - void NotifyCursorTouchVisibleChanged(bool enabled); - - // Synchronizes cursor set data with all platform displays. - void SetPlatformCursorSize(); - - // Synchronizes the current cursor state with all the platform displays. - void SetPlatformCursor(); - - // Contains are the displays we notify on cursor changes. - DisplayManager* display_manager_; - - // Receives messages when mouse events enabled changes. - CursorStateDelegate* delegate_; - - // Number of times LockCursor() has been invoked without a corresponding - // UnlockCursor(). - int cursor_lock_count_ = 0; - - // The current state of the cursor. - std::unique_ptr<StateSnapshot> current_state_; - - // The cursor state to restore when the cursor is unlocked. - std::unique_ptr<StateSnapshot> state_on_unlock_; - - DISALLOW_COPY_AND_ASSIGN(CursorState); -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_CURSOR_STATE_H_
diff --git a/services/ui/ws/cursor_state_delegate.h b/services/ui/ws/cursor_state_delegate.h deleted file mode 100644 index 2b70974..0000000 --- a/services/ui/ws/cursor_state_delegate.h +++ /dev/null
@@ -1,26 +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 SERVICES_UI_WS_CURSOR_STATE_DELEGATE_H_ -#define SERVICES_UI_WS_CURSOR_STATE_DELEGATE_H_ - -namespace ui { - -namespace ws { - -// Interface used for the CursorState object to message back to the window -// manager. -class CursorStateDelegate { - public: - virtual void OnCursorTouchVisibleChanged(bool enabled) = 0; - - protected: - virtual ~CursorStateDelegate() {} -}; - -} // namespace ws - -} // namespace ui - -#endif // SERVICES_UI_WS_CURSOR_STATE_DELEGATE_H_
diff --git a/services/ui/ws/cursor_state_unittest.cc b/services/ui/ws/cursor_state_unittest.cc deleted file mode 100644 index 3f8f076..0000000 --- a/services/ui/ws/cursor_state_unittest.cc +++ /dev/null
@@ -1,173 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "services/ui/ws/cursor_state.h" - -#include "services/ui/ws/display_manager.h" -#include "services/ui/ws/test_utils.h" -#include "services/ui/ws/window_server.h" -#include "services/ui/ws/window_server_delegate.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/base/cursor/cursor.h" - -namespace ui { -namespace ws { -namespace test { - -class CursorStateTest : public testing::Test, public CursorStateDelegate { - public: - CursorStateTest() {} - ~CursorStateTest() override {} - - WindowServer* window_server() { return ws_test_helper_.window_server(); } - DisplayManager* display_manager() { - return window_server()->display_manager(); - } - TestScreenManager& screen_manager() { return screen_manager_; } - const base::Optional<bool>& last_mouse_events_enabled_send() { - return last_mouse_events_enabled_send_; - } - CursorState* cursor_state() { return cursor_state_.get(); } - const ui::CursorData& cursor() { return ws_test_helper_.cursor(); } - - protected: - // testing::Test: - void SetUp() override { - screen_manager_.Init(window_server()->display_manager()); - cursor_state_ = std::make_unique<CursorState>(display_manager(), this); - - AddWindowManager(window_server()); - screen_manager().AddDisplay(MakeDisplay(0, 0, 1024, 768, 1.0f)); - ASSERT_EQ(1u, display_manager()->displays().size()); - } - - // CursorStateDelegate: - void OnCursorTouchVisibleChanged(bool enabled) override { - last_mouse_events_enabled_send_ = enabled; - } - - private: - WindowServerTestHelper ws_test_helper_; - TestScreenManager screen_manager_; - - base::Optional<bool> last_mouse_events_enabled_send_; - - std::unique_ptr<CursorState> cursor_state_; - - DISALLOW_COPY_AND_ASSIGN(CursorStateTest); -}; - -TEST_F(CursorStateTest, CursorLockTest) { - cursor_state()->SetCurrentWindowCursor(ui::CursorData(ui::CursorType::kWait)); - EXPECT_TRUE(cursor().IsType(ui::CursorType::kWait)); - - cursor_state()->LockCursor(); - cursor_state()->SetCurrentWindowCursor(ui::CursorData(ui::CursorType::kCell)); - EXPECT_TRUE(cursor().IsType(ui::CursorType::kWait)); - - cursor_state()->UnlockCursor(); - EXPECT_TRUE(cursor().IsType(ui::CursorType::kCell)); - - EXPECT_FALSE(last_mouse_events_enabled_send().has_value()); -} - -TEST_F(CursorStateTest, CursorVisibilityTest) { - cursor_state()->SetCurrentWindowCursor(ui::CursorData(ui::CursorType::kWait)); - EXPECT_TRUE(cursor().IsType(ui::CursorType::kWait)); - - cursor_state()->SetCursorVisible(false); - EXPECT_TRUE(cursor().IsType(ui::CursorType::kNone)); - - cursor_state()->SetCursorVisible(true); - EXPECT_TRUE(cursor().IsType(ui::CursorType::kWait)); - - cursor_state()->SetCursorVisible(false); - cursor_state()->SetCurrentWindowCursor(ui::CursorData(ui::CursorType::kCell)); - EXPECT_TRUE(cursor().IsType(ui::CursorType::kNone)); - - cursor_state()->SetCursorVisible(true); - EXPECT_TRUE(cursor().IsType(ui::CursorType::kCell)); - - EXPECT_FALSE(last_mouse_events_enabled_send().has_value()); -} - -TEST_F(CursorStateTest, CursorOverrideTest) { - cursor_state()->SetCurrentWindowCursor(ui::CursorData(ui::CursorType::kWait)); - EXPECT_TRUE(cursor().IsType(ui::CursorType::kWait)); - - cursor_state()->SetGlobalOverrideCursor( - ui::CursorData(ui::CursorType::kCell)); - EXPECT_TRUE(cursor().IsType(ui::CursorType::kCell)); - - cursor_state()->SetGlobalOverrideCursor(base::nullopt); - EXPECT_TRUE(cursor().IsType(ui::CursorType::kWait)); - - EXPECT_FALSE(last_mouse_events_enabled_send().has_value()); -} - -TEST_F(CursorStateTest, CursorOverrideLockTest) { - // This test is meant to mimic the calls in ScreenshotController when it sets - // a cursor. - cursor_state()->SetCurrentWindowCursor(ui::CursorData(ui::CursorType::kWait)); - EXPECT_TRUE(cursor().IsType(ui::CursorType::kWait)); - - cursor_state()->SetGlobalOverrideCursor( - ui::CursorData(ui::CursorType::kCross)); - cursor_state()->LockCursor(); - cursor_state()->SetGlobalOverrideCursor(base::nullopt); - EXPECT_TRUE(cursor().IsType(ui::CursorType::kCross)); - - cursor_state()->UnlockCursor(); - EXPECT_TRUE(cursor().IsType(ui::CursorType::kWait)); - - EXPECT_FALSE(last_mouse_events_enabled_send().has_value()); -} - -TEST_F(CursorStateTest, CursorOverrideVisibilityTest) { - // This test is meant to mimic the calls in ScreenshotController when it - // hides the cursor. - cursor_state()->SetCurrentWindowCursor(ui::CursorData(ui::CursorType::kWait)); - EXPECT_TRUE(cursor().IsType(ui::CursorType::kWait)); - - cursor_state()->SetCursorVisible(false); - cursor_state()->LockCursor(); - cursor_state()->SetGlobalOverrideCursor(base::nullopt); - cursor_state()->SetCursorVisible(true); - EXPECT_TRUE(cursor().IsType(ui::CursorType::kNone)); - - cursor_state()->UnlockCursor(); - EXPECT_TRUE(cursor().IsType(ui::CursorType::kWait)); - - EXPECT_FALSE(last_mouse_events_enabled_send().has_value()); -} - -TEST_F(CursorStateTest, SetCursorTouchVisibleWhileUnlock) { - cursor_state()->SetCurrentWindowCursor(ui::CursorData(ui::CursorType::kWait)); - EXPECT_TRUE(cursor().IsType(ui::CursorType::kWait)); - - cursor_state()->SetCursorTouchVisible(false); - EXPECT_TRUE(cursor().IsType(ui::CursorType::kNone)); - EXPECT_EQ(false, last_mouse_events_enabled_send()); - - cursor_state()->SetCursorTouchVisible(true); - EXPECT_EQ(true, last_mouse_events_enabled_send()); -} - -TEST_F(CursorStateTest, SetCursorTouchVisibleWhileLocked) { - cursor_state()->SetCurrentWindowCursor(ui::CursorData(ui::CursorType::kWait)); - EXPECT_TRUE(cursor().IsType(ui::CursorType::kWait)); - - cursor_state()->LockCursor(); - cursor_state()->SetCursorTouchVisible(false); - EXPECT_TRUE(cursor().IsType(ui::CursorType::kWait)); - EXPECT_FALSE(last_mouse_events_enabled_send().has_value()); - - cursor_state()->UnlockCursor(); - EXPECT_TRUE(cursor().IsType(ui::CursorType::kNone)); - EXPECT_EQ(false, last_mouse_events_enabled_send()); -} - -} // namespace test -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/cursor_unittest.cc b/services/ui/ws/cursor_unittest.cc deleted file mode 100644 index 010c1c74..0000000 --- a/services/ui/ws/cursor_unittest.cc +++ /dev/null
@@ -1,190 +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 <stdint.h> - -#include <string> - -#include "base/macros.h" -#include "services/ui/common/types.h" -#include "services/ui/common/util.h" -#include "services/ui/public/interfaces/window_tree.mojom.h" -#include "services/ui/ws/display_manager.h" -#include "services/ui/ws/ids.h" -#include "services/ui/ws/platform_display.h" -#include "services/ui/ws/platform_display_factory.h" -#include "services/ui/ws/server_window.h" -#include "services/ui/ws/test_utils.h" -#include "services/ui/ws/window_manager_display_root.h" -#include "services/ui/ws/window_manager_state.h" -#include "services/ui/ws/window_server.h" -#include "services/ui/ws/window_server_delegate.h" -#include "services/ui/ws/window_tree.h" -#include "services/ui/ws/window_tree_binding.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/base/cursor/cursor.h" -#include "ui/events/event.h" -#include "ui/gfx/geometry/rect.h" - -namespace ui { -namespace ws { -namespace test { - -class CursorTest : public testing::Test { - public: - CursorTest() {} - ~CursorTest() override {} - - WindowServer* window_server() { return ws_test_helper_.window_server(); } - TestWindowServerDelegate* window_server_delegate() { - return ws_test_helper_.window_server_delegate(); - } - ui::CursorType cursor_type() const { - return ws_test_helper_.cursor().cursor_type(); - } - - protected: - // testing::Test: - void SetUp() override { - screen_manager_.Init(window_server()->display_manager()); - screen_manager_.AddDisplay(); - AddWindowManager(window_server()); - } - - ServerWindow* GetRoot() { - DisplayManager* display_manager = window_server()->display_manager(); - Display* display = *display_manager->displays().begin(); - return display->window_manager_display_root()->GetClientVisibleRoot(); - } - - // Create a 30x30 window where the outer 10 pixels is non-client. - ServerWindow* BuildServerWindow() { - DisplayManager* display_manager = window_server()->display_manager(); - Display* display = *display_manager->displays().begin(); - WindowManagerDisplayRoot* active_display_root = - display->window_manager_display_root(); - WindowTree* tree = - active_display_root->window_manager_state()->window_tree(); - ClientWindowId child_window_id; - if (!NewWindowInTree(tree, &child_window_id)) - return nullptr; - - ServerWindow* w = tree->GetWindowByClientId(child_window_id); - w->SetBounds(gfx::Rect(10, 10, 30, 30)); - w->SetClientArea(gfx::Insets(10, 10), std::vector<gfx::Rect>()); - w->SetVisible(true); - - return w; - } - - void MoveCursorTo(const gfx::Point& p) { - DisplayManager* display_manager = window_server()->display_manager(); - ASSERT_EQ(1u, display_manager->displays().size()); - Display* display = *display_manager->displays().begin(); - WindowManagerDisplayRoot* active_display_root = - display->window_manager_display_root(); - ASSERT_TRUE(active_display_root); - PointerEvent event( - MouseEvent(ET_MOUSE_MOVED, p, p, base::TimeTicks(), 0, 0)); - ignore_result(static_cast<PlatformDisplayDelegate*>(display) - ->GetEventSink() - ->OnEventFromSource(&event)); - WindowManagerState* wms = active_display_root->window_manager_state(); - ASSERT_TRUE(WindowManagerStateTestApi(wms).AckInFlightEvent( - mojom::EventResult::HANDLED)); - } - - private: - WindowServerTestHelper ws_test_helper_; - TestScreenManager screen_manager_; - DISALLOW_COPY_AND_ASSIGN(CursorTest); -}; - -TEST_F(CursorTest, ChangeByMouseMove) { - ServerWindow* win = BuildServerWindow(); - win->SetCursor(ui::CursorData(ui::CursorType::kIBeam)); - win->parent()->SetCursor(ui::CursorData(ui::CursorType::kCell)); - EXPECT_EQ(ui::CursorType::kIBeam, win->cursor().cursor_type()); - win->SetNonClientCursor(ui::CursorData(ui::CursorType::kEastResize)); - EXPECT_EQ(ui::CursorType::kEastResize, - win->non_client_cursor().cursor_type()); - - // Non client area - MoveCursorTo(gfx::Point(15, 15)); - EXPECT_EQ(ui::CursorType::kEastResize, cursor_type()); - - // Client area, which comes from win->parent(). - MoveCursorTo(gfx::Point(25, 25)); - EXPECT_EQ(ui::CursorType::kCell, cursor_type()); -} - -TEST_F(CursorTest, ChangeByClientAreaChange) { - ServerWindow* win = BuildServerWindow(); - win->parent()->SetCursor(ui::CursorData(ui::CursorType::kCross)); - win->SetCursor(ui::CursorData(ui::CursorType::kIBeam)); - EXPECT_EQ(ui::CursorType::kIBeam, win->cursor().cursor_type()); - win->SetNonClientCursor(ui::CursorData(ui::CursorType::kEastResize)); - EXPECT_EQ(ui::CursorType::kEastResize, - win->non_client_cursor().cursor_type()); - - // Non client area before we move. - MoveCursorTo(gfx::Point(15, 15)); - EXPECT_EQ(ui::CursorType::kEastResize, cursor_type()); - - // Changing the client area should cause a change. The cursor for the client - // area comes from root ancestor, which is win->parent(). - win->SetClientArea(gfx::Insets(1, 1), std::vector<gfx::Rect>()); - EXPECT_EQ(ui::CursorType::kCross, cursor_type()); -} - -TEST_F(CursorTest, NonClientCursorChange) { - ServerWindow* win = BuildServerWindow(); - win->SetCursor(ui::CursorData(ui::CursorType::kIBeam)); - EXPECT_EQ(ui::CursorType::kIBeam, win->cursor().cursor_type()); - win->SetNonClientCursor(ui::CursorData(ui::CursorType::kEastResize)); - EXPECT_EQ(ui::CursorType::kEastResize, - win->non_client_cursor().cursor_type()); - - MoveCursorTo(gfx::Point(15, 15)); - EXPECT_EQ(ui::CursorType::kEastResize, cursor_type()); - - win->SetNonClientCursor(ui::CursorData(ui::CursorType::kWestResize)); - EXPECT_EQ(ui::CursorType::kWestResize, cursor_type()); -} - -TEST_F(CursorTest, IgnoreClientCursorChangeInNonClientArea) { - ServerWindow* win = BuildServerWindow(); - win->SetCursor(ui::CursorData(ui::CursorType::kIBeam)); - EXPECT_EQ(ui::CursorType::kIBeam, win->cursor().cursor_type()); - win->SetNonClientCursor(ui::CursorData(ui::CursorType::kEastResize)); - EXPECT_EQ(ui::CursorType::kEastResize, - win->non_client_cursor().cursor_type()); - - MoveCursorTo(gfx::Point(15, 15)); - EXPECT_EQ(ui::CursorType::kEastResize, cursor_type()); - - win->SetCursor(ui::CursorData(ui::CursorType::kHelp)); - EXPECT_EQ(ui::CursorType::kEastResize, cursor_type()); -} - -TEST_F(CursorTest, NonClientToClientByBoundsChange) { - ServerWindow* win = BuildServerWindow(); - win->parent()->SetCursor(ui::CursorData(ui::CursorType::kCopy)); - win->SetCursor(ui::CursorData(ui::CursorType::kIBeam)); - EXPECT_EQ(ui::CursorType::kIBeam, win->cursor().cursor_type()); - win->SetNonClientCursor(ui::CursorData(ui::CursorType::kEastResize)); - EXPECT_EQ(ui::CursorType::kEastResize, - win->non_client_cursor().cursor_type()); - - // Non client area before we move. - MoveCursorTo(gfx::Point(15, 15)); - EXPECT_EQ(ui::CursorType::kEastResize, cursor_type()); - - win->SetBounds(gfx::Rect(0, 0, 30, 30)); - EXPECT_EQ(ui::CursorType::kCopy, cursor_type()); -} - -} // namespace test -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/debug_utils.cc b/services/ui/ws/debug_utils.cc deleted file mode 100644 index a617aaf..0000000 --- a/services/ui/ws/debug_utils.cc +++ /dev/null
@@ -1,17 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "services/ui/ws/debug_utils.h" - -#include "services/ui/ws/server_window.h" - -namespace ui { -namespace ws { - -std::string DebugWindowId(const ServerWindow* window) { - return window ? window->frame_sink_id().ToString() : "null"; -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/debug_utils.h b/services/ui/ws/debug_utils.h deleted file mode 100644 index dbac1c6..0000000 --- a/services/ui/ws/debug_utils.h +++ /dev/null
@@ -1,21 +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 SERVICES_UI_WS_DEBUG_UTILS_H_ -#define SERVICES_UI_WS_DEBUG_UTILS_H_ - -#include <string> - -namespace ui { -namespace ws { - -class ServerWindow; - -// Returns a debug string for |window|, returns "null" if |window| is null. -std::string DebugWindowId(const ServerWindow* window); - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_DEBUG_UTILS_H_
diff --git a/services/ui/ws/default_access_policy.cc b/services/ui/ws/default_access_policy.cc deleted file mode 100644 index 9d0c7a9..0000000 --- a/services/ui/ws/default_access_policy.cc +++ /dev/null
@@ -1,281 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "services/ui/ws/default_access_policy.h" - -#include "services/ui/ws/access_policy_delegate.h" -#include "services/ui/ws/server_window.h" - -namespace ui { -namespace ws { - -DefaultAccessPolicy::DefaultAccessPolicy() {} - -DefaultAccessPolicy::~DefaultAccessPolicy() {} - -void DefaultAccessPolicy::Init(ClientSpecificId client_id, - AccessPolicyDelegate* delegate) { - client_id_ = client_id; - delegate_ = delegate; -} - -bool DefaultAccessPolicy::CanRemoveWindowFromParent( - const ServerWindow* window) const { - if (!WasCreatedByThisClient(window)) - return false; // Can only unparent windows we created. - - return delegate_->HasRootForAccessPolicy(window->parent()) || - WasCreatedByThisClient(window->parent()); -} - -bool DefaultAccessPolicy::CanAddWindow(const ServerWindow* parent, - const ServerWindow* child) const { - return WasCreatedByThisClient(child) && - (delegate_->HasRootForAccessPolicy(parent) || - (WasCreatedByThisClient(parent) && - !delegate_->IsWindowRootOfAnotherTreeForAccessPolicy(parent))); -} - -bool DefaultAccessPolicy::CanAddTransientWindow( - const ServerWindow* parent, - const ServerWindow* child) const { - return (delegate_->HasRootForAccessPolicy(child) || - WasCreatedByThisClient(child)) && - (delegate_->HasRootForAccessPolicy(parent) || - WasCreatedByThisClient(parent)); -} - -bool DefaultAccessPolicy::CanRemoveTransientWindowFromParent( - const ServerWindow* window) const { - return (delegate_->HasRootForAccessPolicy(window) || - WasCreatedByThisClient(window)) && - (delegate_->HasRootForAccessPolicy(window->transient_parent()) || - WasCreatedByThisClient(window->transient_parent())); -} - -bool DefaultAccessPolicy::CanSetModal(const ServerWindow* window) const { - return delegate_->HasRootForAccessPolicy(window) || - WasCreatedByThisClient(window); -} - -bool DefaultAccessPolicy::CanSetChildModalParent( - const ServerWindow* window, - const ServerWindow* modal_parent) const { - return (delegate_->HasRootForAccessPolicy(window) || - WasCreatedByThisClient(window)) && - (!modal_parent || delegate_->HasRootForAccessPolicy(modal_parent) || - WasCreatedByThisClient(modal_parent)); -} - -bool DefaultAccessPolicy::CanReorderWindow( - const ServerWindow* window, - const ServerWindow* relative_window, - mojom::OrderDirection direction) const { - return WasCreatedByThisClient(window) && - WasCreatedByThisClient(relative_window); -} - -bool DefaultAccessPolicy::CanDeleteWindow(const ServerWindow* window) const { - return WasCreatedByThisClient(window); -} - -bool DefaultAccessPolicy::CanGetWindowTree(const ServerWindow* window) const { - return WasCreatedByThisClient(window) || - delegate_->HasRootForAccessPolicy(window) || - delegate_->ShouldInterceptEventsForAccessPolicy(window); -} - -bool DefaultAccessPolicy::CanDescendIntoWindowForWindowTree( - const ServerWindow* window) const { - return (WasCreatedByThisClient(window) && - !delegate_->IsWindowRootOfAnotherTreeForAccessPolicy(window)) || - delegate_->HasRootForAccessPolicy(window) || - delegate_->ShouldInterceptEventsForAccessPolicy(window); -} - -bool DefaultAccessPolicy::CanEmbed(const ServerWindow* window) const { - return WasCreatedByThisClient(window); -} - -bool DefaultAccessPolicy::CanChangeWindowVisibility( - const ServerWindow* window) const { - return WasCreatedByThisClient(window) || - delegate_->HasRootForAccessPolicy(window); -} - -bool DefaultAccessPolicy::CanChangeWindowOpacity( - const ServerWindow* window) const { - return WasCreatedByThisClient(window) || - delegate_->HasRootForAccessPolicy(window); -} - -bool DefaultAccessPolicy::CanSetWindowCompositorFrameSink( - const ServerWindow* window) const { - // Once a window embeds another app, the embedder app is no longer able to - // call SetWindowSurfaceId() - this ability is transferred to the embedded - // app. - if (delegate_->IsWindowRootOfAnotherTreeForAccessPolicy(window)) - return false; - return WasCreatedByThisClient(window) || - delegate_->HasRootForAccessPolicy(window); -} - -bool DefaultAccessPolicy::CanSetWindowBounds(const ServerWindow* window) const { - return WasCreatedByThisClient(window); -} - -bool DefaultAccessPolicy::CanSetWindowTransform( - const ServerWindow* window) const { - return WasCreatedByThisClient(window); -} - -bool DefaultAccessPolicy::CanSetWindowProperties( - const ServerWindow* window) const { - return WasCreatedByThisClient(window); -} - -bool DefaultAccessPolicy::CanSetWindowTextInputState( - const ServerWindow* window) const { - return WasCreatedByThisClient(window) || - delegate_->HasRootForAccessPolicy(window); -} - -bool DefaultAccessPolicy::CanSetCapture(const ServerWindow* window) const { - return WasCreatedByThisClient(window) || - delegate_->HasRootForAccessPolicy(window); -} - -bool DefaultAccessPolicy::CanSetFocus(const ServerWindow* window) const { - return !window || WasCreatedByThisClient(window) || - delegate_->HasRootForAccessPolicy(window); -} - -bool DefaultAccessPolicy::CanSetClientArea(const ServerWindow* window) const { - return WasCreatedByThisClient(window) || - delegate_->HasRootForAccessPolicy(window); -} - -bool DefaultAccessPolicy::CanSetHitTestMask(const ServerWindow* window) const { - return WasCreatedByThisClient(window) || - delegate_->HasRootForAccessPolicy(window); -} - -bool DefaultAccessPolicy::CanSetAcceptDrops(const ServerWindow* window) const { - return (WasCreatedByThisClient(window) && - !delegate_->IsWindowRootOfAnotherTreeForAccessPolicy(window)) || - delegate_->HasRootForAccessPolicy(window); -} - -bool DefaultAccessPolicy::CanSetEventTargetingPolicy( - const ServerWindow* window) const { - return WasCreatedByThisClient(window) || - delegate_->HasRootForAccessPolicy(window); -} - -bool DefaultAccessPolicy::CanStackAbove(const ServerWindow* above, - const ServerWindow* below) const { - return delegate_->HasRootForAccessPolicy(above) && - delegate_->IsWindowCreatedByWindowManager(above) && - delegate_->HasRootForAccessPolicy(below) && - delegate_->IsWindowCreatedByWindowManager(below); -} - -bool DefaultAccessPolicy::CanStackAtTop(const ServerWindow* window) const { - return delegate_->HasRootForAccessPolicy(window) && - delegate_->IsWindowCreatedByWindowManager(window); -} - -bool DefaultAccessPolicy::CanPerformWmAction(const ServerWindow* window) const { - return WasCreatedByThisClient(window) || - delegate_->HasRootForAccessPolicy(window); -} - -bool DefaultAccessPolicy::CanSetCursorProperties( - const ServerWindow* window) const { - return WasCreatedByThisClient(window) || - delegate_->HasRootForAccessPolicy(window); -} - -bool DefaultAccessPolicy::CanInitiateDragLoop( - const ServerWindow* window) const { - return WasCreatedByThisClient(window) || - delegate_->HasRootForAccessPolicy(window); -} - -bool DefaultAccessPolicy::CanInitiateMoveLoop( - const ServerWindow* window) const { - return delegate_->HasRootForAccessPolicy(window); -} - -bool DefaultAccessPolicy::ShouldNotifyOnHierarchyChange( - const ServerWindow* window, - const ServerWindow** new_parent, - const ServerWindow** old_parent) const { - if (!WasCreatedByThisClient(window)) { - // The window may have been exposed to the client because of - // ShouldInterceptEventsForAccessPolicy(). Notify the parent in this case, - // but the |old_parent| and/or |new_parent| may need to be updated. - if (delegate_->IsWindowKnownForAccessPolicy(window)) { - if (*old_parent && !delegate_->IsWindowKnownForAccessPolicy(*old_parent)) - *old_parent = nullptr; - if (*new_parent && - (!delegate_->IsWindowKnownForAccessPolicy(*new_parent) && - delegate_->ShouldInterceptEventsForAccessPolicy(*new_parent))) { - *new_parent = nullptr; - } - return true; - } - - // Let the client know about |window| if the client intercepts events for - // |new_parent|. - if (*new_parent && - delegate_->ShouldInterceptEventsForAccessPolicy(*new_parent)) { - if (*old_parent && - !delegate_->ShouldInterceptEventsForAccessPolicy(*old_parent)) { - *old_parent = nullptr; - } - return true; - } - return false; - } - - if (*new_parent && !WasCreatedByThisClient(*new_parent) && - !delegate_->HasRootForAccessPolicy((*new_parent))) { - *new_parent = nullptr; - } - - if (*old_parent && !WasCreatedByThisClient(*old_parent) && - !delegate_->HasRootForAccessPolicy((*old_parent))) { - *old_parent = nullptr; - } - return true; -} - -const ServerWindow* DefaultAccessPolicy::GetWindowForFocusChange( - const ServerWindow* focused) { - if (WasCreatedByThisClient(focused) || - delegate_->HasRootForAccessPolicy(focused)) - return focused; - return nullptr; -} - -bool DefaultAccessPolicy::CanSetWindowManager() const { - return false; -} - -bool DefaultAccessPolicy::WasCreatedByThisClient( - const ServerWindow* window) const { - return window->owning_tree_id() == client_id_; -} - -bool DefaultAccessPolicy::IsValidIdForNewWindow( - const ClientWindowId& id) const { - // Clients using DefaultAccessPolicy only see windows they have created (for - // the embed point they choose the id), which should have the same client_id - // as the client_id_ since we should have already filled in the real one. - return base::checked_cast<ClientSpecificId>(id.client_id()) == client_id_; -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/default_access_policy.h b/services/ui/ws/default_access_policy.h deleted file mode 100644 index 9a8a974..0000000 --- a/services/ui/ws/default_access_policy.h +++ /dev/null
@@ -1,87 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SERVICES_UI_WS_DEFAULT_ACCESS_POLICY_H_ -#define SERVICES_UI_WS_DEFAULT_ACCESS_POLICY_H_ - -#include <stdint.h> - -#include "base/macros.h" -#include "services/ui/ws/access_policy.h" - -namespace ui { -namespace ws { - -class AccessPolicyDelegate; - -// AccessPolicy for all clients, except the window manager. -class DefaultAccessPolicy : public AccessPolicy { - public: - DefaultAccessPolicy(); - ~DefaultAccessPolicy() override; - - // AccessPolicy: - void Init(ClientSpecificId client_id, - AccessPolicyDelegate* delegate) override; - bool CanRemoveWindowFromParent(const ServerWindow* window) const override; - bool CanAddWindow(const ServerWindow* parent, - const ServerWindow* child) const override; - bool CanAddTransientWindow(const ServerWindow* parent, - const ServerWindow* child) const override; - bool CanRemoveTransientWindowFromParent( - const ServerWindow* window) const override; - bool CanSetModal(const ServerWindow* window) const override; - bool CanSetChildModalParent(const ServerWindow* window, - const ServerWindow* modal_parent) const override; - bool CanReorderWindow(const ServerWindow* window, - const ServerWindow* relative_window, - mojom::OrderDirection direction) const override; - bool CanDeleteWindow(const ServerWindow* window) const override; - bool CanGetWindowTree(const ServerWindow* window) const override; - bool CanDescendIntoWindowForWindowTree( - const ServerWindow* window) const override; - bool CanEmbed(const ServerWindow* window) const override; - bool CanChangeWindowVisibility(const ServerWindow* window) const override; - bool CanChangeWindowOpacity(const ServerWindow* window) const override; - bool CanSetWindowCompositorFrameSink( - const ServerWindow* window) const override; - bool CanSetWindowBounds(const ServerWindow* window) const override; - bool CanSetWindowTransform(const ServerWindow* window) const override; - bool CanSetWindowProperties(const ServerWindow* window) const override; - bool CanSetWindowTextInputState(const ServerWindow* window) const override; - bool CanSetCapture(const ServerWindow* window) const override; - bool CanSetFocus(const ServerWindow* window) const override; - bool CanSetClientArea(const ServerWindow* window) const override; - bool CanSetHitTestMask(const ServerWindow* window) const override; - bool CanSetAcceptDrops(const ServerWindow* window) const override; - bool CanSetEventTargetingPolicy(const ServerWindow* window) const override; - bool CanStackAbove(const ServerWindow* above, - const ServerWindow* below) const override; - bool CanStackAtTop(const ServerWindow* window) const override; - bool CanPerformWmAction(const ServerWindow* window) const override; - bool CanSetCursorProperties(const ServerWindow* window) const override; - bool CanInitiateDragLoop(const ServerWindow* window) const override; - bool CanInitiateMoveLoop(const ServerWindow* window) const override; - bool ShouldNotifyOnHierarchyChange( - const ServerWindow* window, - const ServerWindow** new_parent, - const ServerWindow** old_parent) const override; - const ServerWindow* GetWindowForFocusChange( - const ServerWindow* focused) override; - bool CanSetWindowManager() const override; - bool IsValidIdForNewWindow(const ClientWindowId& id) const override; - - private: - bool WasCreatedByThisClient(const ServerWindow* window) const; - - ClientSpecificId client_id_ = 0u; - AccessPolicyDelegate* delegate_ = nullptr; - - DISALLOW_COPY_AND_ASSIGN(DefaultAccessPolicy); -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_DEFAULT_ACCESS_POLICY_H_
diff --git a/services/ui/ws/display.cc b/services/ui/ws/display.cc deleted file mode 100644 index ae0f8df..0000000 --- a/services/ui/ws/display.cc +++ /dev/null
@@ -1,383 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "services/ui/ws/display.h" - -#include <set> -#include <utility> -#include <vector> - -#include "base/strings/utf_string_conversions.h" -#include "services/service_manager/public/mojom/connector.mojom.h" -#include "services/ui/common/types.h" -#include "services/ui/display/viewport_metrics.h" -#include "services/ui/public/interfaces/cursor/cursor.mojom.h" -#include "services/ui/ws/debug_utils.h" -#include "services/ui/ws/display_binding.h" -#include "services/ui/ws/display_manager.h" -#include "services/ui/ws/focus_controller.h" -#include "services/ui/ws/platform_display.h" -#include "services/ui/ws/user_activity_monitor.h" -#include "services/ui/ws/window_manager_display_root.h" -#include "services/ui/ws/window_manager_state.h" -#include "services/ui/ws/window_manager_window_tree_factory.h" -#include "services/ui/ws/window_server.h" -#include "services/ui/ws/window_server_delegate.h" -#include "services/ui/ws/window_tree.h" -#include "services/ui/ws/window_tree_binding.h" -#include "ui/base/cursor/cursor.h" -#include "ui/display/screen.h" - -namespace ui { -namespace ws { - -Display::Display(WindowServer* window_server) : window_server_(window_server) { - window_server_->window_manager_window_tree_factory()->AddObserver(this); -} - -Display::~Display() { - window_server_->window_manager_window_tree_factory()->RemoveObserver(this); - - if (focus_controller_) { - focus_controller_->RemoveObserver(this); - focus_controller_.reset(); - } - - if (!binding_) { - if (window_manager_display_root_) { - window_manager_display_root_->window_manager_state()->OnDisplayDestroying( - this); - } - } else if (window_manager_display_root_) { - // If there is a |binding_| then the tree was created specifically for this - // display (which corresponds to a WindowTreeHost). - window_server_->DestroyTree( - window_manager_display_root_->window_manager_state()->window_tree()); - } -} - -void Display::Init(const display::ViewportMetrics& metrics, - std::unique_ptr<DisplayBinding> binding) { - binding_ = std::move(binding); - display_manager()->AddDisplay(this); - - CreateRootWindow(metrics.bounds_in_pixels.size()); - - platform_display_ = PlatformDisplay::Create( - root_.get(), metrics, window_server_->GetThreadedImageCursorsFactory()); - platform_display_->Init(this); - UpdateCursorConfig(); -} - -void Display::InitWindowManagerDisplayRoots() { - if (binding_) { - std::unique_ptr<WindowManagerDisplayRoot> display_root_ptr( - new WindowManagerDisplayRoot(this)); - window_manager_display_root_ = display_root_ptr.get(); - WindowManagerDisplayRoot* display_root = display_root_ptr.get(); - WindowTree* window_tree = binding_->CreateWindowTree(display_root->root()); - display_root->window_manager_state_ = window_tree->window_manager_state(); - window_tree->window_manager_state()->AddWindowManagerDisplayRoot( - std::move(display_root_ptr)); - } else { - CreateWindowManagerDisplayRootFromFactory(); - } - display_manager()->OnDisplayUpdated(display_); -} - -int64_t Display::GetId() const { - // TODO(tonikitoo): Implement a different ID for external window mode. - return display_.id(); -} - -void Display::SetDisplay(const display::Display& display) { - display_ = display; - - UpdateCursorConfig(); -} - -const display::Display& Display::GetDisplay() { - return display_; -} - -const display::ViewportMetrics& Display::GetViewportMetrics() const { - return platform_display_->GetViewportMetrics(); -} - -DisplayManager* Display::display_manager() { - return window_server_->display_manager(); -} - -const DisplayManager* Display::display_manager() const { - return window_server_->display_manager(); -} - -gfx::Size Display::GetSize() const { - DCHECK(root_); - return root_->bounds().size(); -} - -WindowManagerDisplayRoot* Display::GetWindowManagerDisplayRootWithRoot( - const ServerWindow* window) { - return (window_manager_display_root_ && - window_manager_display_root_->root() == window) - ? window_manager_display_root_ - : nullptr; -} - -bool Display::SetFocusedWindow(ServerWindow* new_focused_window) { - DVLOG(3) << "Display::SetFocusedWindow id=" - << DebugWindowId(new_focused_window); - ServerWindow* old_focused_window = focus_controller_->GetFocusedWindow(); - if (old_focused_window == new_focused_window) - return true; - DCHECK(!new_focused_window || root_->Contains(new_focused_window)); - return focus_controller_->SetFocusedWindow(new_focused_window); -} - -ServerWindow* Display::GetFocusedWindow() { - return focus_controller_->GetFocusedWindow(); -} - -void Display::UpdateTextInputState(ServerWindow* window, - const ui::TextInputState& state) { - // Do not need to update text input for unfocused windows. - if (!platform_display_ || focus_controller_->GetFocusedWindow() != window) - return; - platform_display_->UpdateTextInputState(state); -} - -void Display::SetImeVisibility(ServerWindow* window, bool visible) { - // Do not need to show or hide IME for unfocused window. - if (focus_controller_->GetFocusedWindow() != window) - return; - platform_display_->SetImeVisibility(visible); -} - -void Display::OnWillDestroyTree(WindowTree* tree) { - if (window_manager_display_root_ && - window_manager_display_root_->window_manager_state()->window_tree() == - tree) { - window_manager_display_root_ = nullptr; - } -} - -void Display::RemoveWindowManagerDisplayRoot( - WindowManagerDisplayRoot* display_root) { - DCHECK_EQ(window_manager_display_root_, display_root); - window_manager_display_root_ = nullptr; - display_manager()->DestroyDisplay(this); -} - -void Display::SetNativeCursor(const ui::CursorData& cursor) { - platform_display_->SetCursor(cursor); -} - -void Display::SetNativeCursorSize(ui::CursorSize cursor_size) { - platform_display_->SetCursorSize(cursor_size); -} - -void Display::SetSize(const gfx::Size& size) { - platform_display_->SetViewportSize(size); -} - -void Display::SetTitle(const std::string& title) { - platform_display_->SetTitle(base::UTF8ToUTF16(title)); -} - -void Display::CreateWindowManagerDisplayRootFromFactory() { - WindowManagerWindowTreeFactory* factory = - window_server_->window_manager_window_tree_factory(); - if (!factory->window_tree()) - return; - - std::unique_ptr<WindowManagerDisplayRoot> display_root_ptr = - std::make_unique<WindowManagerDisplayRoot>(this); - window_manager_display_root_ = display_root_ptr.get(); - WindowManagerState* window_manager_state = - factory->window_tree()->window_manager_state(); - window_manager_display_root_->window_manager_state_ = window_manager_state; - window_manager_display_root_->root()->SetVisible(true); - window_manager_state->window_tree()->AddRootForWindowManager( - window_manager_display_root_->root()); - window_manager_state->AddWindowManagerDisplayRoot( - std::move(display_root_ptr)); -} - -void Display::CreateRootWindow(const gfx::Size& size) { - DCHECK(!root_); - - const ClientWindowId client_window_id = - display_manager()->GetAndAdvanceNextRootId(); - root_.reset(window_server_->CreateServerWindow(client_window_id, - ServerWindow::Properties())); - root_->set_event_targeting_policy( - mojom::EventTargetingPolicy::DESCENDANTS_ONLY); - root_->SetBounds(gfx::Rect(size), allocator_.GenerateId()); - root_->SetVisible(true); - focus_controller_ = std::make_unique<FocusController>(root_.get()); - focus_controller_->AddObserver(this); -} - -void Display::UpdateCursorConfig() { - float scale = display_.device_scale_factor(); - - if (!display_manager()->IsInternalDisplay(display_)) - scale *= ui::mojom::kCursorMultiplierForExternalDisplays; - - if (platform_display_) - platform_display_->SetCursorConfig(display_.rotation(), scale); -} - -ServerWindow* Display::GetRootWindow() { - return root_.get(); -} - -EventSink* Display::GetEventSink() { - return this; -} - -void Display::OnAcceleratedWidgetAvailable() { - display_manager()->OnDisplayAcceleratedWidgetAvailable(this); - InitWindowManagerDisplayRoots(); -} - -void Display::OnNativeCaptureLost() { - if (window_manager_display_root_) { - window_manager_display_root_->window_manager_state()->SetCapture( - nullptr, kInvalidClientId); - } -} - -bool Display::IsHostingViz() const { - return window_server_->is_hosting_viz(); -} - -void Display::OnViewportMetricsChanged( - const display::ViewportMetrics& metrics) { - platform_display_->UpdateViewportMetrics(metrics); - - SetBoundsInPixels(metrics.bounds_in_pixels); -} - -void Display::SetBoundsInPixels(const gfx::Rect& bounds_in_pixels) { - if (root_->bounds().size() == bounds_in_pixels.size()) - return; - - gfx::Rect new_bounds(bounds_in_pixels.size()); - root_->SetBounds(new_bounds, allocator_.GenerateId()); - if (window_manager_display_root_) { - window_manager_display_root_->root()->SetBounds(new_bounds, - allocator_.GenerateId()); - } -} - -ServerWindow* Display::GetActiveRootWindow() { - if (window_manager_display_root_) - return window_manager_display_root_->root(); - return nullptr; -} - -void Display::ProcessEvent(ui::Event* event, - base::OnceClosure event_processed_callback) { - if (window_manager_display_root_) { - WindowManagerState* wm_state = - window_manager_display_root_->window_manager_state(); - wm_state->ProcessEvent(event, GetId()); - if (event_processed_callback) { - wm_state->ScheduleCallbackWhenDoneProcessingEvents( - std::move(event_processed_callback)); - } - } else if (event_processed_callback) { - std::move(event_processed_callback).Run(); - } - - window_server_->user_activity_monitor()->OnUserActivity(); -} - -void Display::OnActivationChanged(ServerWindow* old_active_window, - ServerWindow* new_active_window) { - // Don't do anything here. We assume the window manager handles restacking. If - // we did attempt to restack then we would be reordering windows owned by - // the window-manager, which breaks the assumption that only the owner of a - // window reorders the children. -} - -void Display::OnFocusChanged(FocusControllerChangeSource change_source, - ServerWindow* old_focused_window, - ServerWindow* new_focused_window) { - // TODO(sky): focus is global, not per windowtreehost. Move. - - // There are up to four clients that need to be notified: - // . the client containing |old_focused_window|. - // . the client with |old_focused_window| as its root. - // . the client containing |new_focused_window|. - // . the client with |new_focused_window| as its root. - // Some of these client may be the same. The following takes care to notify - // each only once. - WindowTree* owning_tree_old = nullptr; - WindowTree* embedded_tree_old = nullptr; - - if (old_focused_window) { - owning_tree_old = - window_server_->GetTreeWithId(old_focused_window->owning_tree_id()); - if (owning_tree_old) { - owning_tree_old->ProcessFocusChanged(old_focused_window, - new_focused_window); - } - embedded_tree_old = window_server_->GetTreeWithRoot(old_focused_window); - if (embedded_tree_old) { - DCHECK_NE(owning_tree_old, embedded_tree_old); - embedded_tree_old->ProcessFocusChanged(old_focused_window, - new_focused_window); - } - } - WindowTree* owning_tree_new = nullptr; - WindowTree* embedded_tree_new = nullptr; - if (new_focused_window) { - owning_tree_new = - window_server_->GetTreeWithId(new_focused_window->owning_tree_id()); - if (owning_tree_new && owning_tree_new != owning_tree_old && - owning_tree_new != embedded_tree_old) { - owning_tree_new->ProcessFocusChanged(old_focused_window, - new_focused_window); - } - embedded_tree_new = window_server_->GetTreeWithRoot(new_focused_window); - if (embedded_tree_new && embedded_tree_new != owning_tree_old && - embedded_tree_new != embedded_tree_old) { - DCHECK_NE(owning_tree_new, embedded_tree_new); - embedded_tree_new->ProcessFocusChanged(old_focused_window, - new_focused_window); - } - } - - // WindowManagers are always notified of focus changes. - if (window_manager_display_root_) { - WindowTree* wm_tree = - window_manager_display_root_->window_manager_state()->window_tree(); - if (wm_tree != owning_tree_old && wm_tree != embedded_tree_old && - wm_tree != owning_tree_new && wm_tree != embedded_tree_new) { - wm_tree->ProcessFocusChanged(old_focused_window, new_focused_window); - } - } - - if (new_focused_window) { - UpdateTextInputState(new_focused_window, - new_focused_window->text_input_state()); - } -} - -void Display::OnWindowManagerWindowTreeFactoryReady( - WindowManagerWindowTreeFactory* factory) { - if (!binding_) - CreateWindowManagerDisplayRootFromFactory(); -} - -EventDispatchDetails Display::OnEventFromSource(Event* event) { - ProcessEvent(event); - return EventDispatchDetails(); -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/display.h b/services/ui/ws/display.h deleted file mode 100644 index 3a19b1a..0000000 --- a/services/ui/ws/display.h +++ /dev/null
@@ -1,214 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SERVICES_UI_WS_DISPLAY_H_ -#define SERVICES_UI_WS_DISPLAY_H_ - -#include <stdint.h> - -#include <memory> -#include <queue> -#include <set> - -#include "base/callback_forward.h" -#include "base/macros.h" -#include "base/memory/weak_ptr.h" -#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h" -#include "services/ui/common/types.h" -#include "services/ui/public/interfaces/window_tree_constants.mojom.h" -#include "services/ui/public/interfaces/window_tree_host.mojom.h" -#include "services/ui/ws/focus_controller_observer.h" -#include "services/ui/ws/platform_display.h" -#include "services/ui/ws/platform_display_delegate.h" -#include "services/ui/ws/server_window.h" -#include "services/ui/ws/server_window_observer.h" -#include "services/ui/ws/window_manager_window_tree_factory_observer.h" -#include "ui/display/display.h" -#include "ui/events/event_sink.h" - -namespace display { -struct ViewportMetrics; -} - -namespace ui { -namespace ws { - -class DisplayBinding; -class DisplayManager; -class FocusController; -class WindowManagerDisplayRoot; -class WindowServer; -class WindowTree; - -namespace test { -class DisplayTestApi; -} - -// Displays manages the state associated with a single display. Display has a -// single root window whose children are the roots for a per-user -// WindowManager. Display is configured in two distinct ways: -// . with a DisplayBinding. In this mode there is only ever one WindowManager -// for the display, which comes from the client that created the -// Display. -// . without a DisplayBinding. In this mode a WindowManager is automatically -// created per user. -class Display : public PlatformDisplayDelegate, - public mojom::WindowTreeHost, - public FocusControllerObserver, - public WindowManagerWindowTreeFactoryObserver, - public EventSink { - public: - explicit Display(WindowServer* window_server); - ~Display() override; - - // Initializes the display root ServerWindow and PlatformDisplay. Adds this to - // DisplayManager as a pending display, until accelerated widget is available. - void Init(const display::ViewportMetrics& metrics, - std::unique_ptr<DisplayBinding> binding); - - // Initialize the display's root window to host window manager content. - void InitWindowManagerDisplayRoots(); - - // Returns the ID for this display. In internal mode this is the - // display::Display ID. In external mode this hasn't been defined yet. - int64_t GetId() const; - - // Sets the display::Display corresponding to this ws::Display. - void SetDisplay(const display::Display& display); - - // PlatformDisplayDelegate: - const display::Display& GetDisplay() override; - - const display::ViewportMetrics& GetViewportMetrics() const; - - DisplayManager* display_manager(); - const DisplayManager* display_manager() const; - - PlatformDisplay* platform_display() { return platform_display_.get(); } - - // Returns the size of the display in physical pixels. - gfx::Size GetSize() const; - - WindowServer* window_server() { return window_server_; } - - // Returns the root of the Display. The root's children are the roots - // of the corresponding WindowManagers. - ServerWindow* root_window() { return root_.get(); } - const ServerWindow* root_window() const { return root_.get(); } - - WindowManagerDisplayRoot* GetWindowManagerDisplayRootWithRoot( - const ServerWindow* window); - - WindowManagerDisplayRoot* window_manager_display_root() { - return window_manager_display_root_; - } - - const WindowManagerDisplayRoot* window_manager_display_root() const { - return window_manager_display_root_; - } - - // TODO(sky): this should only be called by WindowServer, move to interface - // used by WindowServer. - // See description of WindowServer::SetFocusedWindow() for details on return - // value. - bool SetFocusedWindow(ServerWindow* window); - // NOTE: this returns the focused window only if the focused window is in this - // display. If this returns null focus may be in another display. - ServerWindow* GetFocusedWindow(); - - void UpdateTextInputState(ServerWindow* window, - const ui::TextInputState& state); - void SetImeVisibility(ServerWindow* window, bool visible); - - // Called just before |tree| is destroyed. - void OnWillDestroyTree(WindowTree* tree); - - // Called prior to |display_root| being destroyed. - void RemoveWindowManagerDisplayRoot(WindowManagerDisplayRoot* display_root); - - // Sets the native cursor to |cursor|. - void SetNativeCursor(const ui::CursorData& curosor); - - // Sets the native cursor size to |cursor_size|. - void SetNativeCursorSize(ui::CursorSize cursor_size); - - // mojom::WindowTreeHost: - void SetSize(const gfx::Size& size) override; - void SetTitle(const std::string& title) override; - - // Updates the size of display root ServerWindow and WM root ServerWindow(s). - void OnViewportMetricsChanged(const display::ViewportMetrics& metrics); - - void SetBoundsInPixels(const gfx::Rect& bounds_in_pixels); - - // Returns the root window of the active user. - ServerWindow* GetActiveRootWindow(); - - // Processes an event. |event_processed_callback| is run once the appropriate - // client processes the event. - // TODO(sky): move event processing code into standalone classes. Display - // shouldn't have logic like this. - void ProcessEvent( - ui::Event* event, - base::OnceClosure event_processed_callback = base::OnceClosure()); - - private: - friend class test::DisplayTestApi; - - class CursorState; - - // Creates a WindowManagerDisplayRoot from the - // WindowManagerWindowTreeFactory. - void CreateWindowManagerDisplayRootFromFactory(); - - // Creates the root ServerWindow for this display, where |size| is in physical - // pixels. - void CreateRootWindow(const gfx::Size& size); - - // Applyes the cursor scale and rotation to the PlatformDisplay. - void UpdateCursorConfig(); - - // PlatformDisplayDelegate: - ServerWindow* GetRootWindow() override; - EventSink* GetEventSink() override; - void OnAcceleratedWidgetAvailable() override; - void OnNativeCaptureLost() override; - bool IsHostingViz() const override; - - // FocusControllerObserver: - void OnActivationChanged(ServerWindow* old_active_window, - ServerWindow* new_active_window) override; - void OnFocusChanged(FocusControllerChangeSource change_source, - ServerWindow* old_focused_window, - ServerWindow* new_focused_window) override; - - // WindowManagerWindowTreeFactoryObserver: - void OnWindowManagerWindowTreeFactoryReady( - WindowManagerWindowTreeFactory* factory) override; - - // EventSink: - EventDispatchDetails OnEventFromSource(Event* event) override; - - std::unique_ptr<DisplayBinding> binding_; - WindowServer* const window_server_; - std::unique_ptr<ServerWindow> root_; - std::unique_ptr<PlatformDisplay> platform_display_; - std::unique_ptr<FocusController> focus_controller_; - - // In internal window mode this contains information about the display. In - // external window mode this will be invalid. - display::Display display_; - - viz::ParentLocalSurfaceIdAllocator allocator_; - - // This is owned by WindowManagerState. - WindowManagerDisplayRoot* window_manager_display_root_ = nullptr; - - DISALLOW_COPY_AND_ASSIGN(Display); -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_DISPLAY_H_
diff --git a/services/ui/ws/display_binding.cc b/services/ui/ws/display_binding.cc deleted file mode 100644 index 476b946..0000000 --- a/services/ui/ws/display_binding.cc +++ /dev/null
@@ -1,38 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "services/ui/ws/display_binding.h" - -#include "base/memory/ptr_util.h" -#include "services/service_manager/public/mojom/connector.mojom.h" -#include "services/ui/ws/display.h" -#include "services/ui/ws/window_manager_access_policy.h" -#include "services/ui/ws/window_server.h" -#include "services/ui/ws/window_tree.h" - -namespace ui { -namespace ws { - -DisplayBindingImpl::DisplayBindingImpl(mojom::WindowTreeHostRequest request, - Display* display, - mojom::WindowTreeClientPtr client, - WindowServer* window_server) - : window_server_(window_server), - binding_(display, std::move(request)), - client_(std::move(client)) {} - -DisplayBindingImpl::~DisplayBindingImpl() {} - -WindowTree* DisplayBindingImpl::CreateWindowTree(ServerWindow* root) { - const uint32_t embed_flags = 0; - WindowTree* tree = window_server_->EmbedAtWindow( - root, std::move(client_), embed_flags, - base::WrapUnique(new WindowManagerAccessPolicy)); - const bool automatically_create_display_roots = true; - tree->ConfigureWindowManager(automatically_create_display_roots); - return tree; -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/display_binding.h b/services/ui/ws/display_binding.h deleted file mode 100644 index 3b88965..0000000 --- a/services/ui/ws/display_binding.h +++ /dev/null
@@ -1,58 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SERVICES_UI_WS_DISPLAY_BINDING_H_ -#define SERVICES_UI_WS_DISPLAY_BINDING_H_ - -#include <memory> - -#include "base/macros.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "services/ui/public/interfaces/window_tree.mojom.h" -#include "services/ui/public/interfaces/window_tree_host.mojom.h" - -namespace ui { -namespace ws { - -class Display; -class ServerWindow; -class WindowServer; -class WindowTree; - -// DisplayBinding manages the binding between a Display and it's mojo clients. -// DisplayBinding is used when a Display is created via a -// WindowTreeHostFactory. -// -// DisplayBinding is owned by Display. -class DisplayBinding { - public: - virtual ~DisplayBinding() {} - - virtual WindowTree* CreateWindowTree(ServerWindow* root) = 0; -}; - -// Live implementation of DisplayBinding. -class DisplayBindingImpl : public DisplayBinding { - public: - DisplayBindingImpl(mojom::WindowTreeHostRequest request, - Display* display, - mojom::WindowTreeClientPtr client, - WindowServer* window_server); - ~DisplayBindingImpl() override; - - private: - // DisplayBinding: - WindowTree* CreateWindowTree(ServerWindow* root) override; - - WindowServer* window_server_; - mojo::Binding<mojom::WindowTreeHost> binding_; - mojom::WindowTreeClientPtr client_; - - DISALLOW_COPY_AND_ASSIGN(DisplayBindingImpl); -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_DISPLAY_BINDING_H_
diff --git a/services/ui/ws/display_creation_config.h b/services/ui/ws/display_creation_config.h deleted file mode 100644 index 65b1f52..0000000 --- a/services/ui/ws/display_creation_config.h +++ /dev/null
@@ -1,25 +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 SERVICES_UI_WS_DISPLAY_CREATION_CONFIG_H_ -#define SERVICES_UI_WS_DISPLAY_CREATION_CONFIG_H_ - -namespace ui { -namespace ws { - -enum class DisplayCreationConfig { - // Initial state. - UNKNOWN, - - // Displays are created automatically based on the system. - AUTOMATIC, - - // Used when the window manager manually creates displays. - MANUAL, -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_DISPLAY_CREATION_CONFIG_H_
diff --git a/services/ui/ws/display_manager.cc b/services/ui/ws/display_manager.cc deleted file mode 100644 index f40f244..0000000 --- a/services/ui/ws/display_manager.cc +++ /dev/null
@@ -1,453 +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 "services/ui/ws/display_manager.h" - -#include <vector> - -#include "base/containers/flat_set.h" -#include "base/trace_event/trace_event.h" -#include "services/ui/display/screen_manager.h" -#include "services/ui/display/viewport_metrics.h" -#include "services/ui/ws/cursor_location_manager.h" -#include "services/ui/ws/display.h" -#include "services/ui/ws/display_binding.h" -#include "services/ui/ws/display_creation_config.h" -#include "services/ui/ws/event_processor.h" -#include "services/ui/ws/frame_generator.h" -#include "services/ui/ws/platform_display_mirror.h" -#include "services/ui/ws/server_window.h" -#include "services/ui/ws/user_display_manager.h" -#include "services/ui/ws/user_display_manager_delegate.h" -#include "services/ui/ws/window_manager_state.h" -#include "services/ui/ws/window_manager_window_tree_factory.h" -#include "services/ui/ws/window_server_delegate.h" -#include "services/ui/ws/window_tree.h" -#include "ui/display/display_list.h" -#include "ui/display/screen_base.h" -#include "ui/display/types/display_constants.h" -#include "ui/events/event_rewriter.h" -#include "ui/gfx/geometry/point_conversions.h" - -#if defined(OS_CHROMEOS) -#include "ui/chromeos/events/event_rewriter_chromeos.h" -#endif - -namespace ui { -namespace ws { - -DisplayManager::DisplayManager(WindowServer* window_server, bool is_hosting_viz) - : window_server_(window_server), - cursor_location_manager_(std::make_unique<CursorLocationManager>()) { -#if defined(OS_CHROMEOS) - if (is_hosting_viz) { - // TODO: http://crbug.com/701468 fix function key preferences and sticky - // keys. - ui::EventRewriterChromeOS::Delegate* delegate = nullptr; - ui::EventRewriter* sticky_keys_controller = nullptr; - event_rewriter_ = std::make_unique<ui::EventRewriterChromeOS>( - delegate, sticky_keys_controller); - } -#endif -} - -DisplayManager::~DisplayManager() { - DestroyAllDisplays(); -} - -void DisplayManager::OnDisplayCreationConfigSet() { - if (window_server_->display_creation_config() == - DisplayCreationConfig::MANUAL) { - if (user_display_manager_) - user_display_manager_->DisableAutomaticNotification(); - } else { - // In AUTOMATIC mode SetDisplayConfiguration() is never called. - got_initial_config_from_window_manager_ = true; - } -} - -bool DisplayManager::SetDisplayConfiguration( - const std::vector<display::Display>& displays, - const std::vector<display::ViewportMetrics>& viewport_metrics, - int64_t primary_display_id, - int64_t internal_display_id, - const std::vector<display::Display>& mirrors) { - DCHECK_NE(display::kUnifiedDisplayId, internal_display_id); - if (window_server_->display_creation_config() != - DisplayCreationConfig::MANUAL) { - LOG(ERROR) << "SetDisplayConfiguration is only valid when roots manually " - "created"; - return false; - } - if (displays.size() + mirrors.size() != viewport_metrics.size()) { - LOG(ERROR) << "SetDisplayConfiguration called with mismatch in sizes"; - return false; - } - - size_t primary_display_index = std::numeric_limits<size_t>::max(); - - // Check the mirrors before potentially passing them to a unified display. - base::flat_set<int64_t> mirror_ids; - for (const auto& mirror : mirrors) { - if (mirror.id() == display::kInvalidDisplayId) { - LOG(ERROR) << "SetDisplayConfiguration passed invalid display id"; - return false; - } - if (mirror.id() == display::kUnifiedDisplayId) { - LOG(ERROR) << "SetDisplayConfiguration passed unified display in mirrors"; - return false; - } - if (!mirror_ids.insert(mirror.id()).second) { - LOG(ERROR) << "SetDisplayConfiguration passed duplicate display id"; - return false; - } - if (mirror.id() == primary_display_id) { - LOG(ERROR) << "SetDisplayConfiguration passed primary display in mirrors"; - return false; - } - } - - base::flat_set<int64_t> display_ids; - for (size_t i = 0; i < displays.size(); ++i) { - const display::Display& display = displays[i]; - if (display.id() == display::kInvalidDisplayId) { - LOG(ERROR) << "SetDisplayConfiguration passed invalid display id"; - return false; - } - if (!display_ids.insert(display.id()).second) { - LOG(ERROR) << "SetDisplayConfiguration passed duplicate display id"; - return false; - } - if (display.id() == primary_display_id) - primary_display_index = i; - Display* ws_display = GetDisplayById(display.id()); - if (!ws_display && display.id() != display::kUnifiedDisplayId) { - LOG(ERROR) << "SetDisplayConfiguration passed unknown display id " - << display.id(); - return false; - } - } - if (primary_display_index == std::numeric_limits<size_t>::max()) { - LOG(ERROR) << "SetDisplayConfiguration primary id not in displays"; - return false; - } - - // See comment in header as to why this doesn't use Display::SetInternalId(). - // NOTE: the internal display might not be listed in |displays| or |mirrors|. - internal_display_id_ = internal_display_id; - - display::DisplayList& display_list = - display::ScreenManager::GetInstance()->GetScreen()->display_list(); - // Update the primary display first, in case the old primary has been removed. - display_list.AddOrUpdateDisplay(displays[primary_display_index], - display::DisplayList::Type::PRIMARY); - - // Remove any existing displays that are not included in the configuration. - for (int i = display_list.displays().size() - 1; i >= 0; --i) { - const int64_t id = display_list.displays()[i].id(); - if (display_ids.count(id) == 0) { - // The display list also contains mirrors, which do not have ws::Displays. - // If the destroyed display still has a root window, it is orphaned here. - // Root windows are destroyed by explicit window manager instruction. - if (Display* ws_display = GetDisplayById(id)) - DestroyDisplay(ws_display); - // Do not remove display::Display entries for mirroring displays. - if (mirror_ids.count(id) == 0) - display_list.RemoveDisplay(id); - } - } - - // Remove any existing mirrors that are not included in the configuration. - for (int i = mirrors_.size() - 1; i >= 0; --i) { - if (mirror_ids.count(mirrors_[i]->display().id()) == 0) { - // Do not remove display::Display entries for extended displays. - if (display_ids.count(mirrors_[i]->display().id()) == 0) - display_list.RemoveDisplay(mirrors_[i]->display().id()); - mirrors_.erase(mirrors_.begin() + i); - } - } - - // Add or update any displays that are included in the configuration. - for (size_t i = 0; i < displays.size(); ++i) { - Display* ws_display = GetDisplayById(displays[i].id()); - DCHECK(ws_display); - ws_display->SetDisplay(displays[i]); - ws_display->OnViewportMetricsChanged(viewport_metrics[i]); - if (i != primary_display_index) { - display_list.AddOrUpdateDisplay(displays[i], - display::DisplayList::Type::NOT_PRIMARY); - } - } - - // Add or update any mirrors that are included in the configuration. - for (size_t i = 0; i < mirrors.size(); ++i) { - DCHECK(!GetDisplayById(mirrors[i].id())); - Display* ws_display_to_mirror = GetDisplayById(displays[0].id()); - - const auto& metrics = viewport_metrics[displays.size() + i]; - PlatformDisplayMirror* mirror = nullptr; - for (size_t i = 0; i < mirrors_.size(); ++i) { - if (mirrors_[i]->display().id() == mirrors[i].id()) { - mirror = mirrors_[i].get(); - break; - } - } - if (mirror) { - mirror->set_display(mirrors[i]); - mirror->UpdateViewportMetrics(metrics); - } else { - mirrors_.push_back(std::make_unique<PlatformDisplayMirror>( - mirrors[i], metrics, window_server_, ws_display_to_mirror)); - } - } - - std::set<int64_t> existing_display_ids; - for (const display::Display& display : display_list.displays()) - existing_display_ids.insert(display.id()); - std::set<int64_t> removed_display_ids = - base::STLSetDifference<std::set<int64_t>>(existing_display_ids, - display_ids); - for (int64_t display_id : removed_display_ids) - display_list.RemoveDisplay(display_id); - - if (user_display_manager_) - user_display_manager_->CallOnDisplaysChanged(); - - if (!got_initial_config_from_window_manager_) { - got_initial_config_from_window_manager_ = true; - window_server_->delegate()->OnFirstDisplayReady(); - } - - return true; -} - -UserDisplayManager* DisplayManager::GetUserDisplayManager() { - if (!user_display_manager_) { - user_display_manager_ = - std::make_unique<UserDisplayManager>(window_server_); - if (window_server_->display_creation_config() == - DisplayCreationConfig::MANUAL) { - user_display_manager_->DisableAutomaticNotification(); - } - } - return user_display_manager_.get(); -} - -void DisplayManager::AddDisplay(Display* display) { - DCHECK_EQ(0u, pending_displays_.count(display)); - pending_displays_.insert(display); -} - -Display* DisplayManager::AddDisplayForWindowManager( - bool is_primary_display, - const display::Display& display, - const display::ViewportMetrics& metrics) { - DCHECK_EQ(DisplayCreationConfig::MANUAL, - window_server_->display_creation_config()); - const display::DisplayList::Type display_type = - is_primary_display ? display::DisplayList::Type::PRIMARY - : display::DisplayList::Type::NOT_PRIMARY; - display::DisplayList& display_list = - display::ScreenManager::GetInstance()->GetScreen()->display_list(); - // The display may already be listed as a mirror destination display. - display_list.AddOrUpdateDisplay(display, display_type); - OnDisplayAdded(display, metrics); - return GetDisplayById(display.id()); -} - -void DisplayManager::DestroyDisplay(Display* display) { - const bool is_pending = pending_displays_.count(display) > 0; - if (is_pending) { - pending_displays_.erase(display); - } else { - DCHECK(displays_.count(display)); - displays_.erase(display); - window_server_->OnDisplayDestroyed(display); - } - const int64_t display_id = display->GetId(); - delete display; - - // If we have no more roots left, let the app know so it can terminate. - // TODO(sky): move to delegate/observer. - if (displays_.empty() && pending_displays_.empty()) - window_server_->OnNoMoreDisplays(); - else if (user_display_manager_) - user_display_manager_->OnDisplayDestroyed(display_id); -} - -void DisplayManager::DestroyAllDisplays() { - while (!pending_displays_.empty()) - DestroyDisplay(*pending_displays_.begin()); - DCHECK(pending_displays_.empty()); - - while (!displays_.empty()) - DestroyDisplay(*displays_.begin()); - DCHECK(displays_.empty()); -} - -std::set<const Display*> DisplayManager::displays() const { - std::set<const Display*> ret_value(displays_.begin(), displays_.end()); - return ret_value; -} - -void DisplayManager::OnDisplayUpdated(const display::Display& display) { - if (user_display_manager_) - user_display_manager_->OnDisplayUpdated(display); -} - -Display* DisplayManager::GetDisplayContaining(const ServerWindow* window) { - return const_cast<Display*>( - static_cast<const DisplayManager*>(this)->GetDisplayContaining(window)); -} - -const Display* DisplayManager::GetDisplayContaining( - const ServerWindow* window) const { - while (window && window->parent()) - window = window->parent(); - for (Display* display : displays_) { - if (window == display->root_window()) - return display; - } - return nullptr; -} - -const Display* DisplayManager::GetDisplayById(int64_t display_id) const { - for (Display* display : displays_) { - if (display->GetId() == display_id) - return display; - } - return nullptr; -} - -const WindowManagerDisplayRoot* DisplayManager::GetWindowManagerDisplayRoot( - const ServerWindow* window) const { - const ServerWindow* last = window; - while (window && window->parent()) { - last = window; - window = window->parent(); - } - for (Display* display : displays_) { - if (window == display->root_window()) - return display->GetWindowManagerDisplayRootWithRoot(last); - } - return nullptr; -} - -WindowManagerDisplayRoot* DisplayManager::GetWindowManagerDisplayRoot( - const ServerWindow* window) { - return const_cast<WindowManagerDisplayRoot*>( - const_cast<const DisplayManager*>(this)->GetWindowManagerDisplayRoot( - window)); -} - -bool DisplayManager::InUnifiedDisplayMode() const { - return GetDisplayById(display::kUnifiedDisplayId) != nullptr; -} - -ClientWindowId DisplayManager::GetAndAdvanceNextRootId() { - const ClientSpecificId id = next_root_id_++; - CHECK_NE(0u, next_root_id_); - return ClientWindowId(kWindowServerClientId, id); -} - -void DisplayManager::OnDisplayAcceleratedWidgetAvailable(Display* display) { - DCHECK_NE(0u, pending_displays_.count(display)); - DCHECK_EQ(0u, displays_.count(display)); - const bool is_first_display = - displays_.empty() && got_initial_config_from_window_manager_; - displays_.insert(display); - pending_displays_.erase(display); - if (event_rewriter_) - display->platform_display()->AddEventRewriter(event_rewriter_.get()); - window_server_->OnDisplayReady(display, is_first_display); -} - -void DisplayManager::OnWindowManagerSurfaceActivation( - Display* display, - const viz::SurfaceInfo& surface_info) { - display->platform_display()->GetFrameGenerator()->SetEmbeddedSurface( - surface_info); - // Also pass the surface info to any displays mirroring the given display. - for (const auto& mirror : mirrors_) { - if (mirror->display_to_mirror() == display) - mirror->GetFrameGenerator()->SetEmbeddedSurface(surface_info); - } -} - -void DisplayManager::SetHighContrastMode(bool enabled) { - for (Display* display : displays_) { - display->platform_display()->GetFrameGenerator()->SetHighContrastMode( - enabled); - } -} - -bool DisplayManager::IsInternalDisplay(const display::Display& display) const { - return display.id() == GetInternalDisplayId(); -} - -int64_t DisplayManager::GetInternalDisplayId() const { - if (window_server_->display_creation_config() == - DisplayCreationConfig::MANUAL) { - return internal_display_id_; - } - return display::Display::HasInternalDisplay() - ? display::Display::InternalDisplayId() - : display::kInvalidDisplayId; -} - -void DisplayManager::CreateDisplay(const display::Display& display, - const display::ViewportMetrics& metrics) { - ws::Display* ws_display = new ws::Display(window_server_); - ws_display->SetDisplay(display); - ws_display->Init(metrics, nullptr); -} - -void DisplayManager::OnDisplayAdded(const display::Display& display, - const display::ViewportMetrics& metrics) { - DVLOG(3) << "OnDisplayAdded: " << display.ToString(); - CreateDisplay(display, metrics); -} - -void DisplayManager::OnDisplayRemoved(int64_t display_id) { - DVLOG(3) << "OnDisplayRemoved: " << display_id; - Display* display = GetDisplayById(display_id); - if (display) - DestroyDisplay(display); -} - -void DisplayManager::OnDisplayModified( - const display::Display& display, - const display::ViewportMetrics& metrics) { - DVLOG(3) << "OnDisplayModified: " << display.ToString(); - - Display* ws_display = GetDisplayById(display.id()); - DCHECK(ws_display); - - // Update the cached display information. - ws_display->SetDisplay(display); - - // Send IPC to WMs with new display information. - WindowManagerWindowTreeFactory* factory = - window_server_->window_manager_window_tree_factory(); - if (factory->window_tree()) - factory->window_tree()->OnWmDisplayModified(display); - - // Update the PlatformWindow and ServerWindow size. This must happen after - // OnWmDisplayModified() so the WM has updated the display size. - ws_display->OnViewportMetricsChanged(metrics); - - OnDisplayUpdated(display); -} - -void DisplayManager::OnPrimaryDisplayChanged(int64_t primary_display_id) { - DVLOG(3) << "OnPrimaryDisplayChanged: " << primary_display_id; - // TODO(kylechar): Send IPCs to WM clients first. - - // Send IPCs to any DisplayManagerObservers. - if (user_display_manager_) - user_display_manager_->OnPrimaryDisplayChanged(primary_display_id); -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/display_manager.h b/services/ui/ws/display_manager.h deleted file mode 100644 index e5d2caf8..0000000 --- a/services/ui/ws/display_manager.h +++ /dev/null
@@ -1,179 +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. - -#ifndef SERVICES_UI_WS_DISPLAY_MANAGER_H_ -#define SERVICES_UI_WS_DISPLAY_MANAGER_H_ - -#include <map> -#include <memory> -#include <set> - -#include "base/macros.h" -#include "components/viz/common/surfaces/surface_info.h" -#include "services/ui/display/screen_manager_delegate.h" -#include "services/ui/public/interfaces/window_tree_constants.mojom.h" -#include "services/ui/ws/ids.h" -#include "ui/display/display.h" - -namespace display { -struct ViewportMetrics; -} -namespace ui { -class EventRewriter; -namespace ws { - -class CursorLocationManager; -class Display; -class PlatformDisplayMirror; -class ServerWindow; -class UserDisplayManager; -class WindowManagerDisplayRoot; -class WindowServer; - -// DisplayManager manages the set of Displays. DisplayManager distinguishes -// between displays that do not yet have an accelerated widget (pending), vs -// those that do. -class DisplayManager : public display::ScreenManagerDelegate { - public: - DisplayManager(WindowServer* window_server, bool is_hosting_viz); - ~DisplayManager() override; - - // Called once WindowServer::display_creation_config() has been determined. - void OnDisplayCreationConfigSet(); - - // Indicates the display configuration is valid. Set to true when the - // display_creation_config() has been determined and the config is - // AUTOMATIC, or MANUAL and the SetDisplayConfiguration() has been called. - bool got_initial_config_from_window_manager() const { - return got_initial_config_from_window_manager_; - } - - // Sets the display configuration from the window manager. Returns true - // on success, false if the arguments aren't valid. - bool SetDisplayConfiguration( - const std::vector<display::Display>& displays, - const std::vector<display::ViewportMetrics>& viewport_metrics, - int64_t primary_display_id, - int64_t internal_display_id, - const std::vector<display::Display>& mirrors); - - // Returns the UserDisplayManager. DisplayManager owns the return value. - UserDisplayManager* GetUserDisplayManager(); - - // Returns the CursorLocationManager. - CursorLocationManager* cursor_location_manager() { - return cursor_location_manager_.get(); - } - - // Adds/removes a Display. DisplayManager owns the Displays. - // TODO(sky): make add take a scoped_ptr. - void AddDisplay(Display* display); - // Called when the window manager explicitly adds a new display. - Display* AddDisplayForWindowManager(bool is_primary_display, - const display::Display& display, - const display::ViewportMetrics& metrics); - void DestroyDisplay(Display* display); - void DestroyAllDisplays(); - const std::set<Display*>& displays() { return displays_; } - std::set<const Display*> displays() const; - - // Notifies when something about the Display changes. - void OnDisplayUpdated(const display::Display& display); - - // Returns the Display that contains |window|, or null if |window| is not - // attached to a display. - Display* GetDisplayContaining(const ServerWindow* window); - const Display* GetDisplayContaining(const ServerWindow* window) const; - - // Returns the display with the specified display id, or null if there is no - // display with that id. - const Display* GetDisplayById(int64_t display_id) const; - Display* GetDisplayById(int64_t display_id) { - return const_cast<Display*>( - const_cast<const DisplayManager*>(this)->GetDisplayById(display_id)); - } - - const WindowManagerDisplayRoot* GetWindowManagerDisplayRoot( - const ServerWindow* window) const; - // TODO(sky): constness here is wrong! fix! - WindowManagerDisplayRoot* GetWindowManagerDisplayRoot( - const ServerWindow* window); - - bool IsReady() const { - return !displays_.empty() && got_initial_config_from_window_manager_; - } - bool has_active_or_pending_displays() const { - return !displays_.empty() || !pending_displays_.empty(); - } - - bool InUnifiedDisplayMode() const; - - // Returns the id for the next root window (both for the root of a Display - // as well as the root of WindowManagers). - ClientWindowId GetAndAdvanceNextRootId(); - - // Called when the AcceleratedWidget is available for |display|. - void OnDisplayAcceleratedWidgetAvailable(Display* display); - - // Called when a new surface for a WindowManager root has been created. - void OnWindowManagerSurfaceActivation(Display* display, - const viz::SurfaceInfo& surface_info); - - // Switch the high contrast mode of all Displays to |enabled|. - void SetHighContrastMode(bool enabled); - - bool IsInternalDisplay(const display::Display& display) const; - int64_t GetInternalDisplayId() const; - - private: - void CreateDisplay(const display::Display& display, - const display::ViewportMetrics& metrics); - - // NOTE: these functions are *not* called when the WindowManager manually - // creates roots. - // display::ScreenManagerDelegate: - void OnDisplayAdded(const display::Display& display, - const display::ViewportMetrics& metrics) override; - void OnDisplayRemoved(int64_t id) override; - void OnDisplayModified(const display::Display& display, - const display::ViewportMetrics& metrics) override; - void OnPrimaryDisplayChanged(int64_t primary_display_id) override; - - WindowServer* window_server_; - - // For rewriting ChromeOS function keys. - std::unique_ptr<ui::EventRewriter> event_rewriter_; - - // Displays are initially added to |pending_displays_|. When the display is - // initialized it is moved to |displays_|. WindowServer owns the Displays. - std::set<Display*> pending_displays_; - std::set<Display*> displays_; - - // Displays that mirror the contents of another display in |displays_|. - std::vector<std::unique_ptr<PlatformDisplayMirror>> mirrors_; - - std::unique_ptr<UserDisplayManager> user_display_manager_; - - std::unique_ptr<CursorLocationManager> cursor_location_manager_; - - // ID to use for next root node. - // TODO(sky): figure out why this starts at 2. - ClientSpecificId next_root_id_ = 2; - - bool got_initial_config_from_window_manager_ = false; - - // Id of the internal display, or kInvalidDisplayId. This is only set when - // WindowManager is configured to manually create display roots. This is - // not mirrored in Display::SetInternalId() as mus may be running in the - // same process as the window-manager, so that if this did set the value in - // Display there could be race conditions. - int64_t internal_display_id_ = display::kInvalidDisplayId; - - DISALLOW_COPY_AND_ASSIGN(DisplayManager); -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_DISPLAY_MANAGER_H_
diff --git a/services/ui/ws/display_unittest.cc b/services/ui/ws/display_unittest.cc deleted file mode 100644 index c500f46f..0000000 --- a/services/ui/ws/display_unittest.cc +++ /dev/null
@@ -1,261 +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 <stdint.h> - -#include <string> - -#include "base/macros.h" -#include "services/ui/common/types.h" -#include "services/ui/common/util.h" -#include "services/ui/display/viewport_metrics.h" -#include "services/ui/public/interfaces/window_tree.mojom.h" -#include "services/ui/ws/display_manager.h" -#include "services/ui/ws/ids.h" -#include "services/ui/ws/platform_display.h" -#include "services/ui/ws/platform_display_factory.h" -#include "services/ui/ws/server_window.h" -#include "services/ui/ws/test_utils.h" -#include "services/ui/ws/window_manager_display_root.h" -#include "services/ui/ws/window_manager_state.h" -#include "services/ui/ws/window_server.h" -#include "services/ui/ws/window_server_delegate.h" -#include "services/ui/ws/window_tree.h" -#include "services/ui/ws/window_tree_binding.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/base/cursor/cursor.h" -#include "ui/display/display.h" -#include "ui/events/event.h" -#include "ui/gfx/geometry/rect.h" - -namespace ui { -namespace ws { -namespace test { -namespace { - -// Returns the root ServerWindow for the specified Display. -ServerWindow* GetRootOnDisplay(WindowTree* tree, Display* display) { - for (const ServerWindow* root : tree->roots()) { - if (tree->GetDisplay(root) == display) - return const_cast<ServerWindow*>(root); - } - return nullptr; -} - -// Tracks destruction of a ServerWindow, setting a bool* to true when -// OnWindowDestroyed() is called -class ServerWindowDestructionObserver : public ServerWindowObserver { - public: - ServerWindowDestructionObserver(ServerWindow* window, bool* destroyed) - : window_(window), destroyed_(destroyed) { - window_->AddObserver(this); - } - ~ServerWindowDestructionObserver() override { - if (window_) - window_->RemoveObserver(this); - } - - // ServerWindowObserver: - void OnWindowDestroyed(ServerWindow* window) override { - *destroyed_ = true; - window_->RemoveObserver(this); - window_ = nullptr; - } - - private: - ServerWindow* window_; - bool* destroyed_; - - DISALLOW_COPY_AND_ASSIGN(ServerWindowDestructionObserver); -}; - -} // namespace - -// ----------------------------------------------------------------------------- - -class DisplayTest : public testing::Test { - public: - DisplayTest() {} - ~DisplayTest() override {} - - WindowServer* window_server() { return ws_test_helper_.window_server(); } - DisplayManager* display_manager() { - return window_server()->display_manager(); - } - TestWindowServerDelegate* window_server_delegate() { - return ws_test_helper_.window_server_delegate(); - } - TestScreenManager& screen_manager() { return screen_manager_; } - const ui::CursorData& cursor() { return ws_test_helper_.cursor(); } - - protected: - // testing::Test: - void SetUp() override { - screen_manager_.Init(window_server()->display_manager()); - } - - private: - WindowServerTestHelper ws_test_helper_; - TestScreenManager screen_manager_; - - DISALLOW_COPY_AND_ASSIGN(DisplayTest); -}; - -TEST_F(DisplayTest, CreateDisplay) { - AddWindowManager(window_server()); - const int64_t display_id = - screen_manager().AddDisplay(MakeDisplay(0, 0, 1024, 768, 1.0f)); - - ASSERT_EQ(1u, display_manager()->displays().size()); - Display* display = display_manager()->GetDisplayById(display_id); - - // Display should have root window with correct size. - ASSERT_NE(nullptr, display->root_window()); - EXPECT_EQ("0,0 1024x768", display->root_window()->bounds().ToString()); - - // Display should have a WM root window with the correct size too. - WindowManagerDisplayRoot* root1 = display->window_manager_display_root(); - ASSERT_NE(nullptr, root1); - ASSERT_NE(nullptr, root1->root()); - EXPECT_EQ("0,0 1024x768", root1->root()->bounds().ToString()); -} - -TEST_F(DisplayTest, CreateDisplayBeforeWM) { - // Add one display, no WM exists yet. - const int64_t display_id = - screen_manager().AddDisplay(MakeDisplay(0, 0, 1024, 768, 1.0f)); - EXPECT_EQ(1u, display_manager()->displays().size()); - - Display* display = display_manager()->GetDisplayById(display_id); - - // Display should have root window with correct size. - ASSERT_NE(nullptr, display->root_window()); - EXPECT_EQ("0,0 1024x768", display->root_window()->bounds().ToString()); - - // There should be no WM state for display yet. - EXPECT_EQ(nullptr, display->window_manager_display_root()); - - AddWindowManager(window_server()); - - // After adding a WM display should have WM state and WM root for the display. - WindowManagerDisplayRoot* root1 = display->window_manager_display_root(); - ASSERT_NE(nullptr, root1); - ASSERT_NE(nullptr, root1->root()); - EXPECT_EQ("0,0 1024x768", root1->root()->bounds().ToString()); -} - -TEST_F(DisplayTest, CreateDisplayWithDeviceScaleFactor) { - // The display bounds should be the pixel_size / device_scale_factor. - display::Display display = MakeDisplay(0, 0, 1024, 768, 2.0f); - EXPECT_EQ("0,0 512x384", display.bounds().ToString()); - - const int64_t display_id = screen_manager().AddDisplay(display); - display.set_id(display_id); - Display* ws_display = display_manager()->GetDisplayById(display_id); - - // The root ServerWindow bounds should be in PP. - EXPECT_EQ("0,0 1024x768", ws_display->root_window()->bounds().ToString()); - - // Modify the display work area to be 48 DIPs smaller. - display::Display modified_display = display; - gfx::Rect modified_work_area = display.work_area(); - modified_work_area.set_height(modified_work_area.height() - 48); - modified_display.set_work_area(modified_work_area); - screen_manager().ModifyDisplay(modified_display); - - // The display work area should have changed. - EXPECT_EQ("0,0 512x336", ws_display->GetDisplay().work_area().ToString()); - - // The root ServerWindow should still be in PP after updating the work area. - EXPECT_EQ("0,0 1024x768", ws_display->root_window()->bounds().ToString()); -} - -TEST_F(DisplayTest, Destruction) { - AddWindowManager(window_server()); - - int64_t display_id = screen_manager().AddDisplay(); - - ASSERT_EQ(1u, display_manager()->displays().size()); - EXPECT_EQ(1u, window_server()->num_trees()); - - WindowManagerState* state = window_server()->GetWindowManagerState(); - // Destroy the tree associated with |state|. Should result in deleting - // |state|. - window_server()->DestroyTree(state->window_tree()); - EXPECT_EQ(1u, display_manager()->displays().size()); - EXPECT_EQ(0u, window_server()->num_trees()); - EXPECT_FALSE(window_server_delegate()->got_on_no_more_displays()); - screen_manager().RemoveDisplay(display_id); - EXPECT_TRUE(window_server_delegate()->got_on_no_more_displays()); -} - -// Verifies a single tree is used for multiple displays. -TEST_F(DisplayTest, MultipleDisplays) { - screen_manager().AddDisplay(); - screen_manager().AddDisplay(); - AddWindowManager(window_server()); - ASSERT_EQ(1u, window_server_delegate()->bindings()->size()); - TestWindowTreeBinding* window_tree_binding = - (*window_server_delegate()->bindings())[0]; - WindowTree* tree = window_tree_binding->tree(); - ASSERT_EQ(2u, tree->roots().size()); - std::set<const ServerWindow*> roots = tree->roots(); - auto it = roots.begin(); - ServerWindow* root1 = const_cast<ServerWindow*>(*it); - ++it; - ServerWindow* root2 = const_cast<ServerWindow*>(*it); - ASSERT_NE(root1, root2); - Display* display1 = tree->GetDisplay(root1); - WindowManagerState* display1_wms = - display1->window_manager_display_root()->window_manager_state(); - Display* display2 = tree->GetDisplay(root2); - WindowManagerState* display2_wms = - display2->window_manager_display_root()->window_manager_state(); - EXPECT_EQ(display1_wms->window_tree(), display2_wms->window_tree()); -} - -// Assertions around destroying a secondary display. -TEST_F(DisplayTest, DestroyingDisplayDoesntDelete) { - AddWindowManager(window_server()); - screen_manager().AddDisplay(); - const int64_t secondary_display_id = screen_manager().AddDisplay(); - ASSERT_EQ(1u, window_server_delegate()->bindings()->size()); - WindowTree* tree = (*window_server_delegate()->bindings())[0]->tree(); - ASSERT_EQ(2u, tree->roots().size()); - Display* secondary_display = - display_manager()->GetDisplayById(secondary_display_id); - ASSERT_TRUE(secondary_display); - bool secondary_root_destroyed = false; - ServerWindow* secondary_root = GetRootOnDisplay(tree, secondary_display); - ASSERT_TRUE(secondary_root); - ServerWindowDestructionObserver observer(secondary_root, - &secondary_root_destroyed); - ClientWindowId secondary_root_id = - ClientWindowIdForWindow(tree, secondary_root); - TestWindowTreeClient* tree_client = - static_cast<TestWindowTreeClient*>(tree->client()); - tree_client->tracker()->changes()->clear(); - TestWindowManager* test_window_manager = - window_server_delegate()->last_binding()->window_manager(); - EXPECT_FALSE(test_window_manager->got_display_removed()); - screen_manager().RemoveDisplay(secondary_display_id); - - // Destroying the display should result in the following: - // . The WindowManager should be told it was removed with the right id. - EXPECT_TRUE(test_window_manager->got_display_removed()); - EXPECT_EQ(secondary_display_id, test_window_manager->display_removed_id()); - EXPECT_FALSE(secondary_root_destroyed); - // The window should still be valid on the server side. - ASSERT_TRUE(tree->GetWindowByClientId(secondary_root_id)); - // No changes. - ASSERT_EQ(0u, tree_client->tracker()->changes()->size()); - - // The window should be destroyed when the client says so. - ASSERT_TRUE(tree->DeleteWindow(secondary_root_id)); - EXPECT_TRUE(secondary_root_destroyed); -} - -} // namespace test -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/drag_controller.cc b/services/ui/ws/drag_controller.cc deleted file mode 100644 index 2e3b332..0000000 --- a/services/ui/ws/drag_controller.cc +++ /dev/null
@@ -1,376 +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 "services/ui/ws/drag_controller.h" - -#include <utility> - -#include "base/logging.h" -#include "services/ui/public/interfaces/cursor/cursor.mojom.h" -#include "services/ui/ws/drag_cursor_updater.h" -#include "services/ui/ws/drag_source.h" -#include "services/ui/ws/drag_target_connection.h" -#include "services/ui/ws/server_window.h" -#include "ui/base/cursor/cursor.h" - -namespace ui { -namespace ws { - -struct DragController::Operation { - OperationType type; - uint32_t event_flags; - gfx::Point screen_position; -}; - -struct DragController::WindowState { - // Set to true once we've observed the ServerWindow* that is the key to this - // instance in |window_state_|. - bool observed = false; - - // If we're waiting for a response, this is the type of message. NONE means - // there's no outstanding - OperationType waiting_on_reply = OperationType::NONE; - - // The operation that we'll send off if |waiting_on_reply| isn't NONE. - Operation queued_operation = {OperationType::NONE, 0, gfx::Point()}; - - // The current set of operations that this window accepts. This gets updated - // on each return message. - DropEffectBitmask bitmask = 0u; -}; - -DragController::DragController( - DragCursorUpdater* cursor_updater, - DragSource* source, - ServerWindow* source_window, - DragTargetConnection* source_connection, - int32_t drag_pointer, - const base::flat_map<std::string, std::vector<uint8_t>>& mime_data, - DropEffectBitmask drag_operations) - : source_(source), - cursor_updater_(cursor_updater), - drag_operations_(drag_operations), - drag_pointer_id_(drag_pointer), - current_cursor_(ui::CursorType::kNoDrop), - source_window_(source_window), - source_connection_(source_connection), - mime_data_(mime_data), - weak_factory_(this) { - SetCurrentTargetWindow(nullptr); - EnsureWindowObserved(source_window_); -} - -DragController::~DragController() { - for (auto& pair : window_state_) { - if (pair.second.observed) - pair.first->RemoveObserver(this); - } -} - -void DragController::Cancel() { - MessageDragCompleted(false, ui::mojom::kDropEffectNone); - // |this| may be deleted now. -} - -bool DragController::DispatchPointerEvent(const ui::PointerEvent& event, - ServerWindow* current_target) { - DVLOG(2) << "DragController dispatching pointer event at " - << event.location().ToString(); - uint32_t event_flags = - event.flags() & - (ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN); - gfx::Point screen_position = event.location(); - - if (waiting_for_final_drop_response_) { - // If we're waiting on a target window to respond to the final drag drop - // call, don't process any more pointer events. - DVLOG(1) << "Ignoring event because we're waiting for final drop response"; - return false; - } - - if (event.pointer_details().id != drag_pointer_id_) { - DVLOG(1) << "Ignoring event from different pointer " - << event.pointer_details().id; - return false; - } - - // If |current_target| doesn't accept drags, walk its hierarchy up until we - // find one that does (or set to nullptr at the top of the tree). - while (current_target && !current_target->can_accept_drops()) - current_target = current_target->parent(); - - if (current_target) { - // If we're non-null, we're about to use |current_target| in some - // way. Ensure that we receive notifications that this window has gone - // away. - EnsureWindowObserved(current_target); - } - - source_->OnDragMoved(screen_position); - - if (current_target && current_target == current_target_window_ && - event.type() != ET_POINTER_UP) { - QueueOperation(current_target, OperationType::OVER, event_flags, - screen_position); - } else if (current_target != current_target_window_) { - if (current_target_window_) { - QueueOperation(current_target_window_, OperationType::LEAVE, event_flags, - screen_position); - } - - if (current_target) { - // TODO(erg): If we have a queued LEAVE operation, does this turn into a - // noop? - QueueOperation(current_target, OperationType::ENTER, event_flags, - screen_position); - } - - SetCurrentTargetWindow(current_target); - } else if (event.type() != ET_POINTER_UP) { - DVLOG(1) << "Performing no action for pointer event at " - << screen_position.ToString() - << "! current_target=" << current_target; - } - - if (event.type() == ET_POINTER_UP) { - if (current_target) { - QueueOperation(current_target, OperationType::DROP, event_flags, - screen_position); - waiting_for_final_drop_response_ = true; - } else { - // The pointer was released over no window or a window that doesn't - // accept drags. - MessageDragCompleted(false, ui::mojom::kDropEffectNone); - } - } - - return true; -} - -void DragController::OnWillDestroyDragTargetConnection( - DragTargetConnection* connection) { - called_on_drag_mime_types_.erase(connection); -} - -void DragController::MessageDragCompleted(bool success, - DropEffect action_taken) { - DVLOG(1) << "Drag Completed: success=" << success - << ", action_taken=" << action_taken; - for (DragTargetConnection* connection : called_on_drag_mime_types_) - connection->PerformOnDragDropDone(); - called_on_drag_mime_types_.clear(); - - source_->OnDragCompleted(success, action_taken); - // |this| may be deleted now. -} - -size_t DragController::GetSizeOfQueueForWindow(ServerWindow* window) { - auto it = window_state_.find(window); - if (it == window_state_.end()) - return 0u; - if (it->second.waiting_on_reply == OperationType::NONE) - return 0u; - if (it->second.queued_operation.type == OperationType::NONE) - return 1u; - return 2u; -} - -void DragController::SetWindowDropOperations(ServerWindow* window, - DropEffectBitmask bitmask) { - WindowState& state = window_state_[window]; - state.bitmask = bitmask; - - if (current_target_window_ == window) { - current_cursor_ = CursorForEffectBitmask(bitmask); - cursor_updater_->OnDragCursorUpdated(); - } -} - -ui::CursorData DragController::CursorForEffectBitmask( - DropEffectBitmask bitmask) { - DropEffectBitmask combined = bitmask & drag_operations_; - return combined == ui::mojom::kDropEffectNone - ? ui::CursorData(ui::CursorType::kNoDrop) - : ui::CursorData(ui::CursorType::kCopy); -} - -void DragController::SetCurrentTargetWindow(ServerWindow* current_target) { - current_target_window_ = current_target; - - if (current_target_window_) { - // Immediately set the cursor to the last known set of operations (which - // could be none). - WindowState& state = window_state_[current_target_window_]; - current_cursor_ = CursorForEffectBitmask(state.bitmask); - } else { - // Can't drop in empty areas. - current_cursor_ = ui::CursorData(ui::CursorType::kNoDrop); - } - - cursor_updater_->OnDragCursorUpdated(); -} - -void DragController::EnsureWindowObserved(ServerWindow* window) { - if (!window) - return; - - WindowState& state = window_state_[window]; - if (!state.observed) { - state.observed = true; - window->AddObserver(this); - } -} - -void DragController::QueueOperation(ServerWindow* window, - OperationType type, - uint32_t event_flags, - const gfx::Point& screen_position) { - DVLOG(2) << "Queueing operation " << ToString(type) << " to " << window; - - // If this window doesn't have the mime data, send it. - DragTargetConnection* connection = source_->GetDragTargetForWindow(window); - if (connection != source_connection_ && - !base::ContainsKey(called_on_drag_mime_types_, connection)) { - connection->PerformOnDragDropStart(mime_data_); - called_on_drag_mime_types_.insert(connection); - } - - WindowState& state = window_state_[window]; - // Set the queued operation to the incoming. - state.queued_operation = {type, event_flags, screen_position}; - - if (state.waiting_on_reply == OperationType::NONE) { - // Send the operation immediately. - DispatchOperation(window, &state); - } -} - -void DragController::DispatchOperation(ServerWindow* target, - WindowState* state) { - DragTargetConnection* connection = source_->GetDragTargetForWindow(target); - - DCHECK_EQ(OperationType::NONE, state->waiting_on_reply); - Operation& op = state->queued_operation; - switch (op.type) { - case OperationType::NONE: { - // NONE case to silence the compiler. - NOTREACHED(); - break; - } - case OperationType::ENTER: { - std::unique_ptr<ServerWindowTracker> tracker = - std::make_unique<ServerWindowTracker>(); - tracker->Add(target); - connection->PerformOnDragEnter( - target, op.event_flags, op.screen_position, drag_operations_, - base::Bind(&DragController::OnDragStatusCompleted, - weak_factory_.GetWeakPtr(), base::Passed(&tracker))); - state->waiting_on_reply = OperationType::ENTER; - break; - } - case OperationType::OVER: { - std::unique_ptr<ServerWindowTracker> tracker = - std::make_unique<ServerWindowTracker>(); - tracker->Add(target); - connection->PerformOnDragOver( - target, op.event_flags, op.screen_position, drag_operations_, - base::Bind(&DragController::OnDragStatusCompleted, - weak_factory_.GetWeakPtr(), base::Passed(&tracker))); - state->waiting_on_reply = OperationType::OVER; - break; - } - case OperationType::LEAVE: { - connection->PerformOnDragLeave(target); - state->waiting_on_reply = OperationType::NONE; - break; - } - case OperationType::DROP: { - std::unique_ptr<ServerWindowTracker> tracker = - std::make_unique<ServerWindowTracker>(); - tracker->Add(target); - connection->PerformOnCompleteDrop( - target, op.event_flags, op.screen_position, drag_operations_, - base::Bind(&DragController::OnDragDropCompleted, - weak_factory_.GetWeakPtr(), base::Passed(&tracker))); - state->waiting_on_reply = OperationType::DROP; - break; - } - } - - state->queued_operation = {OperationType::NONE, 0, gfx::Point()}; -} - -void DragController::OnRespondToOperation(ServerWindow* window) { - WindowState& state = window_state_[window]; - DCHECK_NE(OperationType::NONE, state.waiting_on_reply); - state.waiting_on_reply = OperationType::NONE; - if (state.queued_operation.type != OperationType::NONE) - DispatchOperation(window, &state); -} - -void DragController::OnDragStatusCompleted( - std::unique_ptr<ServerWindowTracker> tracker, - DropEffectBitmask bitmask) { - if (tracker->windows().empty()) { - // The window has been deleted and its queue is empty. - return; - } - - // We must remove the completed item. - OnRespondToOperation(*(tracker->windows().begin())); - SetWindowDropOperations(*(tracker->windows().begin()), bitmask); -} - -void DragController::OnDragDropCompleted( - std::unique_ptr<ServerWindowTracker> tracker, - DropEffect action) { - if (tracker->windows().empty()) { - // The window has been deleted after we sent the drop message. It's really - // hard to recover from this so just signal to the source that our drag - // failed. - MessageDragCompleted(false, ui::mojom::kDropEffectNone); - return; - } - - OnRespondToOperation(*(tracker->windows().begin())); - MessageDragCompleted(action != 0u, action); -} - -void DragController::OnWindowDestroying(ServerWindow* window) { - auto it = window_state_.find(window); - if (it != window_state_.end()) { - window->RemoveObserver(this); - window_state_.erase(it); - } - - if (current_target_window_ == window) - SetCurrentTargetWindow(nullptr); - - if (source_window_ == window) { - source_window_ = nullptr; - // Our source window is being deleted, fail the drag. - MessageDragCompleted(false, ui::mojom::kDropEffectNone); - } -} - -// static -std::string DragController::ToString(OperationType type) { - switch (type) { - case OperationType::NONE: - return "NONE"; - case OperationType::ENTER: - return "ENTER"; - case OperationType::OVER: - return "OVER"; - case OperationType::LEAVE: - return "LEAVE"; - case OperationType::DROP: - return "DROP"; - } - NOTREACHED(); - return std::string(); -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/drag_controller.h b/services/ui/ws/drag_controller.h deleted file mode 100644 index 25a5a4d..0000000 --- a/services/ui/ws/drag_controller.h +++ /dev/null
@@ -1,168 +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. - -#ifndef SERVICES_UI_WS_DRAG_CONTROLLER_H_ -#define SERVICES_UI_WS_DRAG_CONTROLLER_H_ - -#include <map> -#include <memory> -#include <set> - -#include "base/containers/flat_map.h" -#include "base/memory/weak_ptr.h" -#include "services/ui/common/types.h" -#include "services/ui/public/interfaces/cursor/cursor.mojom.h" -#include "services/ui/ws/ids.h" -#include "services/ui/ws/server_window_observer.h" -#include "services/ui/ws/server_window_tracker.h" - -namespace gfx { -class Point; -} - -namespace ui { -class PointerEvent; - -namespace ws { - -namespace test { -class DragControllerTestApi; -} - -class DragCursorUpdater; -class DragSource; -class DragTargetConnection; - -// A single ui::mojom::kDropEffect operation. -using DropEffect = uint32_t; - -// A bitmask of ui::mojom::kDropEffect operations. -using DropEffectBitmask = uint32_t; - -// Represents all the data around the current ongoing drag operation. -// -// There should only be one instance of this class per userid. The -// WindowManagerState's EventDispatcher creates and owns this instance. -class DragController : public ServerWindowObserver { - public: - DragController( - DragCursorUpdater* cursor_updater, - DragSource* source, - ServerWindow* source_window, - DragTargetConnection* source_connection, - int32_t drag_pointer, - const base::flat_map<std::string, std::vector<uint8_t>>& mime_data, - DropEffectBitmask drag_operations); - ~DragController() override; - - const ui::CursorData& current_cursor() const { return current_cursor_; } - - // Cancels the current drag, ie, due to the user pressing Escape. - void Cancel(); - - // Responds to a pointer move/release event. Returns true if the event was - // handled by the drag. - bool DispatchPointerEvent(const ui::PointerEvent& event, - ServerWindow* current_target); - - void OnWillDestroyDragTargetConnection(DragTargetConnection* connection); - - private: - friend class test::DragControllerTestApi; - enum class OperationType { NONE, ENTER, OVER, LEAVE, DROP }; - struct Operation; - struct WindowState; - - // Notifies all windows we messaged that the drag is finished, and then tell - // |source| the result. - void MessageDragCompleted(bool success, DropEffect action_taken); - - // Returns the number of events on |window|. A value of 1 means that there's - // a single event outstanding that we're waiting for a response from the - // client, all values over 1 are queued and will be dispatched when the event - // in the front of the queue gets a response. - size_t GetSizeOfQueueForWindow(ServerWindow* window); - - // Sets |current_target_window_| to |current_target|, making sure that we add - // and release ServerWindow observers correctly. - void SetCurrentTargetWindow(ServerWindow* current_target); - - // Updates the possible cursor effects for |window|. |bitmask| is a - // bitmask of the current valid drag operations. - void SetWindowDropOperations(ServerWindow* window, DropEffectBitmask bitmask); - - // Returns the cursor for the window |bitmask|, adjusted for types that the - // drag source allows. - ui::CursorData CursorForEffectBitmask(DropEffectBitmask bitmask); - - // Ensure that |window| has an entry in |window_state_| and that we're an - // observer. - void EnsureWindowObserved(ServerWindow* window); - - void QueueOperation(ServerWindow* window, - OperationType type, - uint32_t event_flags, - const gfx::Point& screen_position); - void DispatchOperation(ServerWindow* window, WindowState* state); - void OnRespondToOperation(ServerWindow* window); - - // Callback methods. |tracker| contains the window being queried and is null - // if the window was destroyed while waiting for client. - void OnDragStatusCompleted(std::unique_ptr<ServerWindowTracker> tracker, - DropEffectBitmask bitmask); - void OnDragDropCompleted(std::unique_ptr<ServerWindowTracker> tracker, - DropEffect action); - - // ServerWindowObserver: - void OnWindowDestroying(ServerWindow* window) override; - - static std::string ToString(OperationType type); - - // Our owner. - DragSource* source_; - - // Object to notify about all cursor changes. - DragCursorUpdater* cursor_updater_; - - // A bit-field of acceptable drag operations offered by the source. - const DropEffectBitmask drag_operations_; - - // Only act on pointer events that meet this id. - const int32_t drag_pointer_id_; - - // The current mouse cursor during the drag. - ui::CursorData current_cursor_; - - // Sending OnDragOver() to our |source_| destroys us; there is a period where - // we have to continue to exist, but not process any more pointer events. - bool waiting_for_final_drop_response_ = false; - - ServerWindow* source_window_; - ServerWindow* current_target_window_ = nullptr; - - // The target connection that |source_window_| is part of. - DragTargetConnection* source_connection_; - - // A list of the offered mime types. - base::flat_map<std::string, std::vector<uint8_t>> mime_data_; - - // We need to keep track of state on a per window basis. A window being in - // this map means that we're observing it. WindowState also keeps track of - // what type of operation we're waiting for a response from the window's - // client, along with a queued operation to send when we get a reply. - std::map<ServerWindow*, WindowState> window_state_; - - // A set of DragTargetConnections* which have received the - // PerformOnDragMimeTypes() call. - std::set<DragTargetConnection*> called_on_drag_mime_types_; - - base::WeakPtrFactory<DragController> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(DragController); -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_DRAG_CONTROLLER_H_
diff --git a/services/ui/ws/drag_controller_unittest.cc b/services/ui/ws/drag_controller_unittest.cc deleted file mode 100644 index cdd5944..0000000 --- a/services/ui/ws/drag_controller_unittest.cc +++ /dev/null
@@ -1,684 +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 "services/ui/ws/drag_controller.h" - -#include <map> -#include <memory> -#include <utility> - -#include "base/containers/queue.h" -#include "services/ui/public/interfaces/cursor/cursor.mojom.h" -#include "services/ui/ws/drag_source.h" -#include "services/ui/ws/drag_target_connection.h" -#include "services/ui/ws/ids.h" -#include "services/ui/ws/server_window.h" -#include "services/ui/ws/test_server_window_delegate.h" -#include "services/ui/ws/test_utils.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/base/cursor/cursor.h" -#include "ui/events/base_event_utils.h" - -namespace ui { -namespace ws { - -enum class QueuedType { NONE, ENTER, OVER, LEAVE, DROP }; - -class DragControllerTest; - -// All the classes to represent a window. -class DragTestWindow : public DragTargetConnection { - public: - struct DragEvent { - QueuedType type; - uint32_t key_state; - gfx::Point cursor_offset; - uint32_t effect_bitmask; - base::Callback<void(uint32_t)> callback; - }; - - DragTestWindow(DragControllerTest* parent, - TestServerWindowDelegate* window_delegate, - const viz::FrameSinkId& id) - : parent_(parent), - window_delegate_(window_delegate), - window_(window_delegate_, id) { - window_.SetCanAcceptDrops(true); - } - ~DragTestWindow() override; - - TestServerWindowDelegate* delegate() { return window_delegate_; } - ServerWindow* window() { return &window_; } - - QueuedType queue_response_type() { - if (queued_callbacks_.empty()) - return QueuedType::NONE; - return queued_callbacks_.front().type; - } - - const DragEvent& queue_front() { return queued_callbacks_.front(); } - - size_t queue_size() { return queued_callbacks_.size(); } - - uint32_t times_received_drag_drop_start() { - return times_received_drag_drop_start_; - } - - void SetParent(DragTestWindow* p) { p->window_.Add(&window_); } - - void OptOutOfDrag() { window_.SetCanAcceptDrops(false); } - - // Calls the callback at the front of the queue. - void Respond(bool respond_with_effect) { - if (queued_callbacks_.size()) { - if (!queued_callbacks_.front().callback.is_null()) { - queued_callbacks_.front().callback.Run( - respond_with_effect ? queued_callbacks_.front().effect_bitmask : 0); - } - - queued_callbacks_.pop(); - } - } - - // Overridden from DragTestConnection: - void PerformOnDragDropStart( - const base::flat_map<std::string, std::vector<uint8_t>>& mime_data) - override { - times_received_drag_drop_start_++; - mime_data_ = mime_data; - } - - void PerformOnDragEnter( - const ServerWindow* window, - uint32_t key_state, - const gfx::Point& cursor_offset, - uint32_t effect_bitmask, - const base::Callback<void(uint32_t)>& callback) override { - DCHECK_EQ(window, &window_); - queued_callbacks_.push({QueuedType::ENTER, key_state, cursor_offset, - effect_bitmask, callback}); - } - - void PerformOnDragOver( - const ServerWindow* window, - uint32_t key_state, - const gfx::Point& cursor_offset, - uint32_t effect_bitmask, - const base::Callback<void(uint32_t)>& callback) override { - DCHECK_EQ(window, &window_); - queued_callbacks_.push( - {QueuedType::OVER, key_state, cursor_offset, effect_bitmask, callback}); - } - - void PerformOnDragLeave(const ServerWindow* window) override { - DCHECK_EQ(window, &window_); - queued_callbacks_.push({QueuedType::LEAVE, 0, gfx::Point(), 0, - base::Callback<void(uint32_t)>()}); - } - - void PerformOnCompleteDrop( - const ServerWindow* window, - uint32_t key_state, - const gfx::Point& cursor_offset, - uint32_t effect_bitmask, - const base::Callback<void(uint32_t)>& callback) override { - DCHECK_EQ(window, &window_); - queued_callbacks_.push( - {QueuedType::DROP, key_state, cursor_offset, effect_bitmask, callback}); - } - - void PerformOnDragDropDone() override { mime_data_.clear(); } - - private: - DragControllerTest* parent_; - TestServerWindowDelegate* window_delegate_; - ServerWindow window_; - base::flat_map<std::string, std::vector<uint8_t>> mime_data_; - uint32_t times_received_drag_drop_start_ = 0; - - base::queue<DragEvent> queued_callbacks_; -}; - -class DragControllerTest : public testing::Test, - public DragCursorUpdater, - public DragSource { - public: - std::unique_ptr<DragTestWindow> BuildWindow() { - viz::FrameSinkId id(1, ++window_id_); - std::unique_ptr<DragTestWindow> p = - std::make_unique<DragTestWindow>(this, window_delegate_.get(), id); - connection_by_window_[p->window()] = p.get(); - return p; - } - - void StartDragOperation( - DragTestWindow* window, - uint32_t drag_operations) { - window->PerformOnDragDropStart( - base::flat_map<std::string, std::vector<uint8_t>>()); - drag_operation_ = std::make_unique<DragController>( - this, this, window->window(), window, MouseEvent::kMousePointerId, - base::flat_map<std::string, std::vector<uint8_t>>(), drag_operations); - - // It would be nice if we could just let the observer method fire, but it - // fires during the constructor when we haven't assigned the unique_ptr - // yet. - cursor_ = drag_operation_->current_cursor().cursor_type(); - } - - void DispatchDrag(DragTestWindow* window, - bool mouse_released, - uint32_t flags, - const gfx::Point& position) { - ui::PointerEvent event( - ui::MouseEvent(mouse_released ? ET_MOUSE_RELEASED : ET_MOUSE_PRESSED, - position, position, ui::EventTimeForNow(), flags, 0)); - drag_operation_->DispatchPointerEvent(event, - window ? window->window() : nullptr); - } - - void DispatchDragWithPointer(DragTestWindow* window, - int32_t drag_pointer, - bool mouse_released, - uint32_t flags, - const gfx::Point& position) { - ui::PointerEvent event( - ET_POINTER_DOWN, position, position, flags, 0, - PointerDetails(ui::EventPointerType::POINTER_TYPE_MOUSE, drag_pointer), - base::TimeTicks()); - drag_operation_->DispatchPointerEvent(event, - window ? window->window() : nullptr); - } - - void OnTestWindowDestroyed(DragTestWindow* test_window) { - drag_operation_->OnWillDestroyDragTargetConnection(test_window); - connection_by_window_.erase(test_window->window()); - } - - DragController* drag_operation() const { return drag_operation_.get(); } - - const base::Optional<uint32_t>& drag_completed_action() { - return drag_completed_action_; - } - const base::Optional<bool>& drag_completed_value() { - return drag_completed_value_; - } - - ui::CursorType cursor_type() const { return cursor_; } - - private: - // Overridden from testing::Test: - void SetUp() override { - testing::Test::SetUp(); - - window_delegate_ = std::make_unique<TestServerWindowDelegate>( - ws_test_helper_.window_server()->GetVizHostProxy()); - root_window_ = std::make_unique<ServerWindow>(window_delegate_.get(), - viz::FrameSinkId(1, 2)); - window_delegate_->set_root_window(root_window_.get()); - root_window_->SetVisible(true); - } - - void TearDown() override { - drag_operation_.reset(); - root_window_.reset(); - window_delegate_.reset(); - - DCHECK(connection_by_window_.empty()); - - testing::Test::TearDown(); - } - - // Overridden from DragCursorUpdater: - void OnDragCursorUpdated() override { - if (drag_operation_) - cursor_ = drag_operation_->current_cursor().cursor_type(); - } - - // Overridden from DragControllerSource: - void OnDragMoved(const gfx::Point& location) override {} - - void OnDragCompleted(bool success, uint32_t action_taken) override { - drag_completed_action_ = action_taken; - drag_completed_value_ = success; - } - - DragTargetConnection* GetDragTargetForWindow( - const ServerWindow* window) override { - auto it = connection_by_window_.find(const_cast<ServerWindow*>(window)); - if (it == connection_by_window_.end()) - return nullptr; - return it->second; - } - - int window_id_ = 3; - - test::WindowServerTestHelper ws_test_helper_; - - ui::CursorType cursor_; - - std::map<ServerWindow*, DragTargetConnection*> connection_by_window_; - - std::unique_ptr<TestServerWindowDelegate> window_delegate_; - std::unique_ptr<ServerWindow> root_window_; - - std::unique_ptr<DragController> drag_operation_; - - base::Optional<uint32_t> drag_completed_action_; - base::Optional<bool> drag_completed_value_; -}; - -DragTestWindow::~DragTestWindow() { - parent_->OnTestWindowDestroyed(this); -} - -TEST_F(DragControllerTest, SimpleDragDrop) { - std::unique_ptr<DragTestWindow> window = BuildWindow(); - StartDragOperation(window.get(), ui::mojom::kDropEffectMove); - - EXPECT_EQ(ui::CursorType::kNoDrop, cursor_type()); - - DispatchDrag(window.get(), false, ui::EF_LEFT_MOUSE_BUTTON, gfx::Point(1, 1)); - EXPECT_EQ(QueuedType::ENTER, window->queue_response_type()); - window->Respond(true); - - // (Even though we're doing a move, the cursor name is COPY.) - EXPECT_EQ(ui::CursorType::kCopy, cursor_type()); - - DispatchDrag(window.get(), false, ui::EF_LEFT_MOUSE_BUTTON, gfx::Point(2, 2)); - EXPECT_EQ(QueuedType::OVER, window->queue_response_type()); - window->Respond(true); - - DispatchDrag(window.get(), true, 0, gfx::Point(2, 2)); - EXPECT_EQ(QueuedType::DROP, window->queue_response_type()); - window->Respond(true); - - EXPECT_EQ(ui::mojom::kDropEffectMove, - drag_completed_action().value_or(ui::mojom::kDropEffectNone)); - EXPECT_TRUE(drag_completed_value().value_or(false)); -} - -TEST_F(DragControllerTest, FailsOnWindowSayingNo) { - std::unique_ptr<DragTestWindow> window = BuildWindow(); - StartDragOperation(window.get(), ui::mojom::kDropEffectMove); - - DispatchDrag(window.get(), false, ui::EF_LEFT_MOUSE_BUTTON, gfx::Point(1, 1)); - EXPECT_EQ(QueuedType::ENTER, window->queue_response_type()); - window->Respond(true); - - DispatchDrag(window.get(), false, ui::EF_LEFT_MOUSE_BUTTON, gfx::Point(2, 2)); - EXPECT_EQ(QueuedType::OVER, window->queue_response_type()); - window->Respond(true); - - DispatchDrag(window.get(), true, 0, gfx::Point(2, 2)); - EXPECT_EQ(QueuedType::DROP, window->queue_response_type()); - - // Unlike SimpleDragDrop, respond with kDropEffectNone, which should make the - // drag fail. - window->Respond(false); - - EXPECT_EQ(ui::mojom::kDropEffectNone, - drag_completed_action().value_or(ui::mojom::kDropEffectCopy)); - EXPECT_FALSE(drag_completed_value().value_or(true)); -} - -TEST_F(DragControllerTest, OnlyDeliverMimeDataOnce) { - std::unique_ptr<DragTestWindow> window1 = BuildWindow(); - std::unique_ptr<DragTestWindow> window2 = BuildWindow(); - - // The client lib is responsible for sending the data to the window that's - // the drag source to minimize IPC. - EXPECT_EQ(0u, window1->times_received_drag_drop_start()); - StartDragOperation(window1.get(), ui::mojom::kDropEffectMove); - EXPECT_EQ(1u, window1->times_received_drag_drop_start()); - DispatchDrag(window1.get(), false, ui::EF_LEFT_MOUSE_BUTTON, - gfx::Point(1, 1)); - EXPECT_EQ(1u, window1->times_received_drag_drop_start()); - window1->Respond(true); - - // Window2 doesn't receive the drag data until mouse is over it. - EXPECT_EQ(0u, window2->times_received_drag_drop_start()); - DispatchDrag(window2.get(), false, ui::EF_LEFT_MOUSE_BUTTON, - gfx::Point(2, 2)); - EXPECT_EQ(1u, window2->times_received_drag_drop_start()); - - // Moving back to the source window doesn't send an additional start message. - DispatchDrag(window1.get(), false, ui::EF_LEFT_MOUSE_BUTTON, - gfx::Point(1, 1)); - EXPECT_EQ(1u, window1->times_received_drag_drop_start()); - - // Moving back to window2 doesn't send an additional start message. - DispatchDrag(window2.get(), false, ui::EF_LEFT_MOUSE_BUTTON, - gfx::Point(1, 1)); - EXPECT_EQ(1u, window2->times_received_drag_drop_start()); -} - -TEST_F(DragControllerTest, DeliverMessageToParent) { - std::unique_ptr<DragTestWindow> window1 = BuildWindow(); - std::unique_ptr<DragTestWindow> window2 = BuildWindow(); - std::unique_ptr<DragTestWindow> window3 = BuildWindow(); - - window3->SetParent(window2.get()); - window3->OptOutOfDrag(); - - StartDragOperation(window1.get(), ui::mojom::kDropEffectMove); - - // Dispatching a drag to window3 (which has can accept drags off) redirects - // to window2, which is its parent. - DispatchDrag(window3.get(), false, ui::EF_LEFT_MOUSE_BUTTON, - gfx::Point(1, 1)); - EXPECT_EQ(1u, window2->times_received_drag_drop_start()); -} - -TEST_F(DragControllerTest, FailWhenDropOverNoWindow) { - std::unique_ptr<DragTestWindow> window = BuildWindow(); - StartDragOperation(window.get(), ui::mojom::kDropEffectMove); - - DispatchDrag(window.get(), false, ui::EF_LEFT_MOUSE_BUTTON, gfx::Point(1, 1)); - EXPECT_EQ(QueuedType::ENTER, window->queue_response_type()); - window->Respond(true); - - DispatchDrag(window.get(), false, ui::EF_LEFT_MOUSE_BUTTON, gfx::Point(2, 2)); - EXPECT_EQ(QueuedType::OVER, window->queue_response_type()); - window->Respond(true); - - DispatchDrag(nullptr, true, 0, gfx::Point(2, 2)); - // Moving outside of |window| should result in |window| getting a leave. - EXPECT_EQ(QueuedType::LEAVE, window->queue_response_type()); - window->Respond(true); - - EXPECT_FALSE(drag_completed_value().value_or(true)); -} - -TEST_F(DragControllerTest, EnterLeaveWhenMovingBetweenTwoWindows) { - std::unique_ptr<DragTestWindow> window1 = BuildWindow(); - std::unique_ptr<DragTestWindow> window2 = BuildWindow(); - StartDragOperation(window1.get(), ui::mojom::kDropEffectMove); - - DispatchDrag(window1.get(), false, ui::EF_LEFT_MOUSE_BUTTON, - gfx::Point(1, 1)); - EXPECT_EQ(QueuedType::ENTER, window1->queue_response_type()); - window1->Respond(true); - - DispatchDrag(window2.get(), false, ui::EF_LEFT_MOUSE_BUTTON, - gfx::Point(2, 2)); - EXPECT_EQ(QueuedType::ENTER, window2->queue_response_type()); - EXPECT_EQ(QueuedType::LEAVE, window1->queue_response_type()); - window1->Respond(true); - window2->Respond(true); -} - -TEST_F(DragControllerTest, DeadWindowDoesntBlock) { - std::unique_ptr<DragTestWindow> window1 = BuildWindow(); - std::unique_ptr<DragTestWindow> window2 = BuildWindow(); - StartDragOperation(window1.get(), ui::mojom::kDropEffectMove); - - test::DragControllerTestApi api(drag_operation()); - - // Simulate a dead window by giving it a few messages, but don't respond to - // them. - DispatchDrag(window1.get(), false, ui::EF_LEFT_MOUSE_BUTTON, - gfx::Point(1, 1)); - DispatchDrag(window1.get(), false, ui::EF_LEFT_MOUSE_BUTTON, - gfx::Point(2, 2)); - EXPECT_EQ(1u, window1->queue_size()); - EXPECT_EQ(2u, api.GetSizeOfQueueForWindow(window1->window())); - - // Moving to window2 should dispatch the enter event to it immediately. - DispatchDrag(window2.get(), false, ui::EF_LEFT_MOUSE_BUTTON, - gfx::Point(3, 3)); - EXPECT_EQ(QueuedType::ENTER, window2->queue_response_type()); - EXPECT_EQ(1u, window1->queue_size()); -} - -TEST_F(DragControllerTest, EnterToOverQueued) { - std::unique_ptr<DragTestWindow> window = BuildWindow(); - StartDragOperation(window.get(), ui::mojom::kDropEffectMove); - - DispatchDrag(window.get(), false, ui::EF_LEFT_MOUSE_BUTTON, gfx::Point(1, 1)); - ASSERT_EQ(1u, window->queue_size()); - EXPECT_EQ(QueuedType::ENTER, window->queue_response_type()); - // Don't respond. - - // We don't receive another message since we haven't acknowledged the first. - DispatchDrag(window.get(), false, ui::EF_LEFT_MOUSE_BUTTON, gfx::Point(1, 2)); - ASSERT_EQ(1u, window->queue_size()); - - // Responding causes us to receive our next event. - window->Respond(true); - ASSERT_EQ(1u, window->queue_size()); - EXPECT_EQ(QueuedType::OVER, window->queue_response_type()); -} - -TEST_F(DragControllerTest, CoalesceMouseOverEvents) { - std::unique_ptr<DragTestWindow> window = BuildWindow(); - StartDragOperation(window.get(), ui::mojom::kDropEffectMove); - - DispatchDrag(window.get(), false, ui::EF_LEFT_MOUSE_BUTTON, gfx::Point(1, 1)); - EXPECT_EQ(QueuedType::ENTER, window->queue_response_type()); - - DispatchDrag(window.get(), false, ui::EF_LEFT_MOUSE_BUTTON, gfx::Point(1, 2)); - DispatchDrag(window.get(), false, ui::EF_LEFT_MOUSE_BUTTON, gfx::Point(2, 2)); - DispatchDrag(window.get(), false, ui::EF_LEFT_MOUSE_BUTTON, gfx::Point(2, 3)); - - // Responding to the first delivers us the last mouse over event's position. - window->Respond(true); - ASSERT_EQ(1u, window->queue_size()); - EXPECT_EQ(QueuedType::OVER, window->queue_response_type()); - EXPECT_EQ(gfx::Point(2, 3), window->queue_front().cursor_offset); - - // There are no queued events because they were coalesced. - window->Respond(true); - EXPECT_EQ(0u, window->queue_size()); -} - -TEST_F(DragControllerTest, RemovePendingMouseOversOnLeave) { - std::unique_ptr<DragTestWindow> window1 = BuildWindow(); - std::unique_ptr<DragTestWindow> window2 = BuildWindow(); - StartDragOperation(window1.get(), ui::mojom::kDropEffectMove); - - // Enter - DispatchDrag(window1.get(), false, ui::EF_LEFT_MOUSE_BUTTON, - gfx::Point(1, 1)); - EXPECT_EQ(QueuedType::ENTER, window1->queue_response_type()); - - // Over - DispatchDrag(window1.get(), false, ui::EF_LEFT_MOUSE_BUTTON, - gfx::Point(1, 1)); - - // Leave - DispatchDrag(window2.get(), false, ui::EF_LEFT_MOUSE_BUTTON, - gfx::Point(1, 1)); - - // The window finally responds to the enter message; we should not receive - // any over messages since we didn't respond to the enter message in time. - window1->Respond(true); - ASSERT_EQ(1u, window1->queue_size()); - EXPECT_EQ(QueuedType::LEAVE, window1->queue_response_type()); -} - -TEST_F(DragControllerTest, TargetWindowClosedWhileDrag) { - std::unique_ptr<DragTestWindow> window1 = BuildWindow(); - std::unique_ptr<DragTestWindow> window2 = BuildWindow(); - StartDragOperation(window1.get(), ui::mojom::kDropEffectMove); - - test::DragControllerTestApi api(drag_operation()); - - // Send some events to |window|. - DispatchDrag(window2.get(), false, ui::EF_LEFT_MOUSE_BUTTON, - gfx::Point(1, 1)); - EXPECT_EQ(QueuedType::ENTER, window2->queue_response_type()); - DispatchDrag(window2.get(), false, ui::EF_LEFT_MOUSE_BUTTON, - gfx::Point(1, 1)); - - ServerWindow* server_window = window2->window(); - - // Ensure that DragController is waiting for a response from |window|. - EXPECT_EQ(2u, api.GetSizeOfQueueForWindow(server_window)); - EXPECT_EQ(server_window, api.GetCurrentTarget()); - - // Force the destruction of |window.window|. - window2.reset(); - - // DragController doesn't know anything about the server window now. - EXPECT_EQ(0u, api.GetSizeOfQueueForWindow(server_window)); - EXPECT_EQ(nullptr, api.GetCurrentTarget()); - - // But a target window closing out from under us doesn't fail the drag. - EXPECT_FALSE(drag_completed_value().has_value()); -} - -TEST_F(DragControllerTest, TargetWindowClosedResetsCursor) { - std::unique_ptr<DragTestWindow> window1 = BuildWindow(); - std::unique_ptr<DragTestWindow> window2 = BuildWindow(); - StartDragOperation(window1.get(), ui::mojom::kDropEffectMove); - EXPECT_EQ(ui::CursorType::kNoDrop, cursor_type()); - - // Send some events to |window|. - DispatchDrag(window2.get(), false, ui::EF_LEFT_MOUSE_BUTTON, - gfx::Point(1, 1)); - EXPECT_EQ(QueuedType::ENTER, window2->queue_response_type()); - window2->Respond(true); - DispatchDrag(window2.get(), false, ui::EF_LEFT_MOUSE_BUTTON, - gfx::Point(1, 1)); - window2->Respond(true); - EXPECT_EQ(ui::CursorType::kCopy, cursor_type()); - - // Force the destruction of |window.window|. - window2.reset(); - - // The cursor no loner indicates that it can drop on |window2|. - EXPECT_EQ(ui::CursorType::kNoDrop, cursor_type()); -} - -TEST_F(DragControllerTest, SourceWindowClosedWhileDrag) { - std::unique_ptr<DragTestWindow> window1 = BuildWindow(); - std::unique_ptr<DragTestWindow> window2 = BuildWindow(); - StartDragOperation(window1.get(), ui::mojom::kDropEffectMove); - - test::DragControllerTestApi api(drag_operation()); - - // Send some events to |windoww|. - DispatchDrag(window2.get(), false, ui::EF_LEFT_MOUSE_BUTTON, - gfx::Point(1, 1)); - EXPECT_EQ(QueuedType::ENTER, window2->queue_response_type()); - DispatchDrag(window2.get(), false, ui::EF_LEFT_MOUSE_BUTTON, - gfx::Point(1, 1)); - - ServerWindow* server_window = window2->window(); - - // Ensure that DragController is waiting for a response from |window2|. - EXPECT_EQ(2u, api.GetSizeOfQueueForWindow(server_window)); - EXPECT_EQ(server_window, api.GetCurrentTarget()); - - // Force the destruction of the source window. - window1.reset(); - - // The source window going away fails the drag. - EXPECT_FALSE(drag_completed_value().value_or(true)); -} - -TEST_F(DragControllerTest, DontQueueEventsAfterDrop) { - // The DragController needs to stick around to coordinate the drop, but - // it should ignore further mouse events during this time. - std::unique_ptr<DragTestWindow> window = BuildWindow(); - StartDragOperation(window.get(), ui::mojom::kDropEffectMove); - - test::DragControllerTestApi api(drag_operation()); - - DispatchDrag(window.get(), false, ui::EF_LEFT_MOUSE_BUTTON, gfx::Point(1, 1)); - EXPECT_EQ(QueuedType::ENTER, window->queue_response_type()); - window->Respond(true); - - DispatchDrag(window.get(), false, ui::EF_LEFT_MOUSE_BUTTON, gfx::Point(2, 2)); - EXPECT_EQ(QueuedType::OVER, window->queue_response_type()); - window->Respond(true); - - DispatchDrag(window.get(), true, 0, gfx::Point(2, 2)); - EXPECT_EQ(QueuedType::DROP, window->queue_response_type()); - EXPECT_EQ(1u, api.GetSizeOfQueueForWindow(window->window())); - - // Further located events don't result in additional drag messages. - DispatchDrag(window.get(), false, ui::EF_LEFT_MOUSE_BUTTON, gfx::Point(2, 2)); - DispatchDrag(window.get(), false, ui::EF_LEFT_MOUSE_BUTTON, gfx::Point(2, 2)); - EXPECT_EQ(1u, api.GetSizeOfQueueForWindow(window->window())); -} - -TEST_F(DragControllerTest, CancelDrag) { - // The DragController needs to stick around to coordinate the drop, but - // it should ignore further mouse events during this time. - std::unique_ptr<DragTestWindow> window = BuildWindow(); - StartDragOperation(window.get(), ui::mojom::kDropEffectMove); - - DispatchDrag(window.get(), false, ui::EF_LEFT_MOUSE_BUTTON, gfx::Point(1, 1)); - EXPECT_EQ(QueuedType::ENTER, window->queue_response_type()); - window->Respond(true); - - drag_operation()->Cancel(); - - EXPECT_FALSE(drag_completed_value().value_or(true)); -} - -TEST_F(DragControllerTest, IgnoreEventsFromOtherPointers) { - std::unique_ptr<DragTestWindow> window = BuildWindow(); - // This starts the operation with MouseEvent::kMousePointerId. - StartDragOperation(window.get(), ui::mojom::kDropEffectMove); - - // Ignore events from pointer 5. - DispatchDragWithPointer(window.get(), 5, false, ui::EF_LEFT_MOUSE_BUTTON, - gfx::Point(1, 1)); - ASSERT_EQ(0u, window->queue_size()); -} - -TEST_F(DragControllerTest, RejectingWindowHasProperCursor) { - std::unique_ptr<DragTestWindow> window = BuildWindow(); - StartDragOperation(window.get(), ui::mojom::kDropEffectMove); - - EXPECT_EQ(ui::CursorType::kNoDrop, cursor_type()); - - DispatchDrag(window.get(), false, ui::EF_LEFT_MOUSE_BUTTON, gfx::Point(1, 1)); - EXPECT_EQ(QueuedType::ENTER, window->queue_response_type()); - window->Respond(true); - - EXPECT_EQ(ui::CursorType::kCopy, cursor_type()); - - DispatchDrag(window.get(), false, ui::EF_LEFT_MOUSE_BUTTON, gfx::Point(2, 2)); - EXPECT_EQ(QueuedType::OVER, window->queue_response_type()); - - // At this point, we respond with no available drag actions at this pixel. - window->Respond(false); - EXPECT_EQ(ui::CursorType::kNoDrop, cursor_type()); -} - -TEST_F(DragControllerTest, ResopnseFromOtherWindowDoesntChangeCursor) { - std::unique_ptr<DragTestWindow> window1 = BuildWindow(); - std::unique_ptr<DragTestWindow> window2 = BuildWindow(); - StartDragOperation(window1.get(), ui::mojom::kDropEffectMove); - - // Send some events to |window2|. - DispatchDrag(window2.get(), false, ui::EF_LEFT_MOUSE_BUTTON, - gfx::Point(1, 1)); - EXPECT_EQ(QueuedType::ENTER, window2->queue_response_type()); - DispatchDrag(window2.get(), false, ui::EF_LEFT_MOUSE_BUTTON, - gfx::Point(1, 1)); - - EXPECT_EQ(ui::CursorType::kNoDrop, cursor_type()); - - // Now enter |window1|, and respond. - DispatchDrag(window1.get(), false, ui::EF_LEFT_MOUSE_BUTTON, - gfx::Point(5, 5)); - EXPECT_EQ(QueuedType::ENTER, window1->queue_response_type()); - window1->Respond(true); - - EXPECT_EQ(ui::CursorType::kCopy, cursor_type()); - - // Window 2 responding negatively to its queued messages shouldn't change the - // cursor. - window2->Respond(false); - - EXPECT_EQ(ui::CursorType::kCopy, cursor_type()); -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/drag_cursor_updater.h b/services/ui/ws/drag_cursor_updater.h deleted file mode 100644 index dcc945a..0000000 --- a/services/ui/ws/drag_cursor_updater.h +++ /dev/null
@@ -1,23 +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. - -#ifndef SERVICES_UI_WS_DRAG_CURSOR_UPDATER_H_ -#define SERVICES_UI_WS_DRAG_CURSOR_UPDATER_H_ - -namespace ui { -namespace ws { - -// An interface for the DragController to signal that the cursor has changed. -class DragCursorUpdater { - public: - virtual void OnDragCursorUpdated() = 0; - - protected: - virtual ~DragCursorUpdater() {} -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_DRAG_CURSOR_UPDATER_H_
diff --git a/services/ui/ws/drag_source.h b/services/ui/ws/drag_source.h deleted file mode 100644 index cb45039..0000000 --- a/services/ui/ws/drag_source.h +++ /dev/null
@@ -1,37 +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. - -#ifndef SERVICES_UI_WS_DRAG_SOURCE_H_ -#define SERVICES_UI_WS_DRAG_SOURCE_H_ - -namespace ui { -namespace ws { - -class DragTargetConnection; -class ServerWindow; - -// An interface implemented by the object that caused a DragController to -// exist, and which acts as a delegate to it. -class DragSource { - public: - virtual ~DragSource() {} - - // Called during a drag operation when the mouse cursor moves. - virtual void OnDragMoved(const gfx::Point& location) = 0; - - // Called when a drag operation is completed. |success| is true when a target - // window signaled the successful completion of the drag, false in all other - // cases where a drag was aborted at any step in the process. |action_taken| - // is one of the kDropEffect constants in window_tree_constants.mojom. - virtual void OnDragCompleted(bool success, uint32_t action_taken) = 0; - - // Returns the client connection that created |window|. - virtual DragTargetConnection* GetDragTargetForWindow( - const ServerWindow* window) = 0; -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_DRAG_SOURCE_H_
diff --git a/services/ui/ws/drag_target_connection.h b/services/ui/ws/drag_target_connection.h deleted file mode 100644 index 06d3887..0000000 --- a/services/ui/ws/drag_target_connection.h +++ /dev/null
@@ -1,90 +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. - -#ifndef SERVICES_UI_WS_DRAG_TARGET_CONNECTION_H_ -#define SERVICES_UI_WS_DRAG_TARGET_CONNECTION_H_ - -#include <string> - -#include "base/bind.h" -#include "base/containers/flat_map.h" -#include "ui/gfx/geometry/point.h" - -namespace ui { -namespace ws { - -class ServerWindow; - -// An abstract connection which can respond to drag/drop target requests. -// -// The methods in this class send drag and drop messages to the client and -// return their results through the passed in callback. From the point of view -// of the client, the lifecycle of receiving messages are in the following -// order: -class DragTargetConnection { - public: - virtual ~DragTargetConnection() {} - - // On the first time that the pointer enters a window offered by this - // connection, we send this start message with the |mime_data| of the - // drag so that we only send this data over the connection once. We send the - // mime data first because clients may read the payload at any time, - // including during the enter message. - // - // (As an optimization, on the server side, we don't send this message to the - // source window of the drag; the client library has already done the - // equivalent in ui::WindowDropTarget to minimize the load of inter-process - // communication.) - virtual void PerformOnDragDropStart( - const base::flat_map<std::string, std::vector<uint8_t>>& mime_data) = 0; - - // Next, on each time that the mouse cursor moves from one |window| to - // another, we send a DragEnter message. The value returned by |callback| is - // a bitmask of drop operations that can be performed at this location, in - // terms of the ui::mojom::kDropEffect{None,Move,Copy,Link} constants. - virtual void PerformOnDragEnter( - const ServerWindow* window, - uint32_t key_state, - const gfx::Point& cursor_offset, - uint32_t effect_bitmask, - const base::Callback<void(uint32_t)>& callback) = 0; - - // For each mouse move after the initial DragEnter message, we call DragOver - // to change the mouse location and to update what drop operations can be - // performed. - virtual void PerformOnDragOver( - const ServerWindow* window, - uint32_t key_state, - const gfx::Point& cursor_offset, - uint32_t effect_bitmask, - const base::Callback<void(uint32_t)>& callback) = 0; - - // If the mouse cursor leaves |window|, send an DragLeave message. - virtual void PerformOnDragLeave(const ServerWindow* window) = 0; - - // If the user releases the pointer over a window, send a DragDrop message, - // which signals that the client should complete the drag. The return value - // is which operation was performed; a non-zero callback value means the drag - // was accepted and completed. - virtual void PerformOnCompleteDrop( - const ServerWindow* window, - uint32_t key_state, - const gfx::Point& cursor_offset, - uint32_t effect_bitmask, - const base::Callback<void(uint32_t)>& callback) = 0; - - // Finally, regardless of which window accepted (or rejected) the drop, we - // send a done message to each connection that we sent a start message - // to. This message is used to clear cached data from the drag. - // - // (Again, we don't send this message to the source window as we didn't send - // a DragStart message; the client library handles the equivalent at its - // layer.) - virtual void PerformOnDragDropDone() = 0; -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_DRAG_TARGET_CONNECTION_H_
diff --git a/services/ui/ws/event_dispatcher.h b/services/ui/ws/event_dispatcher.h deleted file mode 100644 index 200a81cc..0000000 --- a/services/ui/ws/event_dispatcher.h +++ /dev/null
@@ -1,60 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SERVICES_UI_WS_EVENT_DISPATCHER_H_ -#define SERVICES_UI_WS_EVENT_DISPATCHER_H_ - -#include <stdint.h> - -#include "services/ui/common/types.h" - -namespace ui { - -class Event; - -namespace ws { - -class Accelerator; -class ServerWindow; - -struct EventLocation; - -// EventDispatcher is called from EventProcessor once it determines the target -// for events as well as accelerators. -class EventDispatcher { - public: - enum class AcceleratorPhase { - kPre, - kPost, - }; - - // Called when the target Window is found for |event|. - // |post_target_accelerator| is the accelerator to run if the target doesn't - // handle the event. See EventProcessor for details on event processing - // phases. |client_id| is the id of tree the event should be sent to. See - // EventLocation for details on |event_location|. |event_location| is only - // useful for located events. - virtual void DispatchInputEventToWindow( - ServerWindow* target, - ClientSpecificId client_id, - const EventLocation& event_location, - const ui::Event& event, - Accelerator* post_target_accelerator) = 0; - - // A matching accelerator was found for the specified phase of processing. - // |event| is the event that the accelerator matches and |display_id| - // identifies the display the event came in on. - virtual void OnAccelerator(uint32_t accelerator, - int64_t display_id, - const ui::Event& event, - AcceleratorPhase phase) = 0; - - protected: - virtual ~EventDispatcher() {} -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_EVENT_DISPATCHER_H_
diff --git a/services/ui/ws/event_dispatcher_delegate.h b/services/ui/ws/event_dispatcher_delegate.h deleted file mode 100644 index 2eea409..0000000 --- a/services/ui/ws/event_dispatcher_delegate.h +++ /dev/null
@@ -1,57 +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 SERVICES_UI_WS_EVENT_DISPATCHER_DELEGATE_H_ -#define SERVICES_UI_WS_EVENT_DISPATCHER_DELEGATE_H_ - -#include <stdint.h> - -#include "services/ui/ws/ids.h" - -namespace ui { - -class Event; - -namespace ws { - -class AsyncEventDispatcher; -class ServerWindow; - -struct EventLocation; - -// Called at interesting stages during event dispatch. -class EventDispatcherDelegate { - public: - // Called immediately before |event| is handed to EventProcessor for - // processing - virtual void OnWillProcessEvent(const ui::Event& event, - const EventLocation& event_location) = 0; - - // Called before dispatching an event to an AsyncEventDispatcher. The delegate - // may return a different ServerWindow to send the event to. Typically the - // delegate will return |target|. - virtual ServerWindow* OnWillDispatchInputEvent( - ServerWindow* target, - ClientSpecificId client_id, - const EventLocation& event_location, - const Event& event) = 0; - - // Called when |async_event_dispatcher| did not complete processing in a - // reasonable amount of time. - virtual void OnEventDispatchTimedOut( - AsyncEventDispatcher* async_event_dispatcher) = 0; - - // Called when an AsyncEventDispatcher handles an event that mapped to an - // accelerator. - virtual void OnAsyncEventDispatcherHandledAccelerator(const Event& event, - int64_t display_id) = 0; - - protected: - virtual ~EventDispatcherDelegate() {} -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_EVENT_DISPATCHER_DELEGATE_H_
diff --git a/services/ui/ws/event_dispatcher_impl.cc b/services/ui/ws/event_dispatcher_impl.cc deleted file mode 100644 index dd7ddd0..0000000 --- a/services/ui/ws/event_dispatcher_impl.cc +++ /dev/null
@@ -1,411 +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 "services/ui/ws/event_dispatcher_impl.h" - -#include "base/debug/debugger.h" -#include "services/ui/public/interfaces/window_tree_constants.mojom.h" -#include "services/ui/ws/accelerator.h" -#include "services/ui/ws/async_event_dispatcher.h" -#include "services/ui/ws/async_event_dispatcher_lookup.h" -#include "services/ui/ws/event_dispatcher_delegate.h" -#include "services/ui/ws/event_location.h" -#include "services/ui/ws/event_processor.h" -#include "services/ui/ws/server_window.h" -#include "services/ui/ws/server_window_tracker.h" -#include "ui/events/event.h" - -namespace ui { -namespace ws { -namespace { - -bool CanEventsBeCoalesced(const ui::Event& one, const ui::Event& two) { - if (one.type() != two.type() || one.flags() != two.flags()) - return false; - - // TODO(sad): wheel events can also be merged. - if (one.type() != ui::ET_POINTER_MOVED) - return false; - - return one.AsPointerEvent()->pointer_details().id == - two.AsPointerEvent()->pointer_details().id; -} - -std::unique_ptr<ui::Event> CoalesceEvents(std::unique_ptr<ui::Event> first, - std::unique_ptr<ui::Event> second) { - DCHECK(first->type() == ui::ET_POINTER_MOVED) - << " Non-move events cannot be merged yet."; - // For mouse moves, the new event just replaces the old event, but we need to - // use the latency from the old event. - second->set_latency(*first->latency()); - second->latency()->set_coalesced(); - return second; -} - -base::TimeDelta GetDefaultAckTimerDelay() { -#if defined(NDEBUG) - return base::TimeDelta::FromMilliseconds(100); -#else - return base::TimeDelta::FromMilliseconds(1000); -#endif -} - -} // namespace - -// See EventDispatcherImpl::EventTask::Type::kProcessedEvent for details on -// this. -class EventDispatcherImpl::ProcessedEventTarget { - public: - ProcessedEventTarget( - AsyncEventDispatcherLookup* async_event_dispatcher_lookup, - ServerWindow* window, - ClientSpecificId client_id, - Accelerator* accelerator) - : async_event_dispatcher_lookup_(async_event_dispatcher_lookup), - client_id_(client_id) { - DCHECK(async_event_dispatcher_lookup_); - DCHECK(window); - tracker_.Add(window); - if (accelerator) - accelerator_ = accelerator->GetWeakPtr(); - } - - ~ProcessedEventTarget() {} - - // Return true if the event is still valid. The event becomes invalid if - // the window is destroyed while waiting to dispatch. - bool IsValid() { - return window() && - async_event_dispatcher_lookup_->GetAsyncEventDispatcherById( - client_id_); - } - - ServerWindow* window() { - return tracker_.windows().empty() ? nullptr : tracker_.windows().front(); - } - - ClientSpecificId client_id() const { return client_id_; } - - base::WeakPtr<Accelerator> accelerator() { return accelerator_; } - - private: - AsyncEventDispatcherLookup* async_event_dispatcher_lookup_; - ServerWindowTracker tracker_; - const ClientSpecificId client_id_; - base::WeakPtr<Accelerator> accelerator_; - - DISALLOW_COPY_AND_ASSIGN(ProcessedEventTarget); -}; - -EventDispatcherImpl::InFlightEventDispatchDetails::InFlightEventDispatchDetails( - EventDispatcherImpl* event_dispatcher, - AsyncEventDispatcher* async_event_dispatcher, - int64_t display_id, - const Event& event, - EventDispatchPhase phase) - : async_event_dispatcher(async_event_dispatcher), - display_id(display_id), - event(Event::Clone(event)), - phase(phase), - weak_factory_(event_dispatcher) {} - -EventDispatcherImpl::InFlightEventDispatchDetails:: - ~InFlightEventDispatchDetails() {} - -// Contains data used for event processing that needs to happen. See enum for -// details. -struct EventDispatcherImpl::EventTask { - enum class Type { - // ProcessEvent() was called while waiting on a client or EventProcessor - // to complete processing. |event| is non-null and |processed_target| is - // null. - kEvent, - - // In certain situations EventProcessor::ProcessEvent() generates more than - // one event. When that happens, |kProcessedEvent| is used for all events - // after the first. For example, a move may result in an exit for one - // Window and and an enter for another Window. The event generated for the - // enter results in an EventTask of type |kProcessedEvent|. In this case - // both |event| and |processed_target| are valid. - kProcessedEvent, - - // ScheduleCallbackWhenDoneProcessingEvents() is called while waiting on - // a client or EventProcessor. |event| and |processed_target| are null. - kClosure - }; - - EventTask() = default; - ~EventTask() = default; - - Type type() const { - if (done_closure) - return Type::kClosure; - if (processed_target) { - DCHECK(event); - return Type::kProcessedEvent; - } - DCHECK(event); - return Type::kEvent; - } - - std::unique_ptr<Event> event; - std::unique_ptr<ProcessedEventTarget> processed_target; - EventLocation event_location; - base::OnceClosure done_closure; -}; - -EventDispatcherImpl::EventDispatcherImpl( - AsyncEventDispatcherLookup* async_event_dispatcher_lookup, - AsyncEventDispatcher* accelerator_dispatcher, - EventDispatcherDelegate* delegate) - : async_event_dispatcher_lookup_(async_event_dispatcher_lookup), - accelerator_dispatcher_(accelerator_dispatcher), - delegate_(delegate) { - DCHECK(async_event_dispatcher_lookup_); -} - -EventDispatcherImpl::~EventDispatcherImpl() = default; - -void EventDispatcherImpl::Init(EventProcessor* event_processor) { - DCHECK(event_processor); - DCHECK(!event_processor_); - event_processor_ = event_processor; -} - -void EventDispatcherImpl::ProcessEvent(ui::Event* event, - const EventLocation& event_location) { - // If this is still waiting for an ack from a previously sent event, then - // queue the event so it's dispatched once the ack is received. - if (IsProcessingEvent()) { - if (!event_tasks_.empty() && - event_tasks_.back()->type() == EventTask::Type::kEvent && - CanEventsBeCoalesced(*event_tasks_.back()->event, *event)) { - event_tasks_.back()->event = CoalesceEvents( - std::move(event_tasks_.back()->event), ui::Event::Clone(*event)); - event_tasks_.back()->event_location = event_location; - return; - } - QueueEvent(*event, nullptr, event_location); - return; - } - - QueueEvent(*event, nullptr, event_location); - ProcessEventTasks(); -} - -bool EventDispatcherImpl::IsProcessingEvent() const { - return in_flight_event_dispatch_details_ || - event_processor_->IsProcessingEvent(); -} - -const ui::Event* EventDispatcherImpl::GetInFlightEvent() const { - return in_flight_event_dispatch_details_ - ? in_flight_event_dispatch_details_->event.get() - : nullptr; -} - -void EventDispatcherImpl::ScheduleCallbackWhenDoneProcessingEvents( - base::OnceClosure closure) { - DCHECK(closure); - if (!IsProcessingEvent()) { - std::move(closure).Run(); - return; - } - - // TODO(sky): use make_unique (presubmit check fails on make_unique). - std::unique_ptr<EventTask> event_task(new EventTask()); - event_task->done_closure = std::move(closure); - event_tasks_.push(std::move(event_task)); -} - -void EventDispatcherImpl::OnWillDestroyAsyncEventDispatcher( - AsyncEventDispatcher* target) { - if (!in_flight_event_dispatch_details_ || - in_flight_event_dispatch_details_->async_event_dispatcher != target) { - return; - } - - // The target is going to be deleted and won't ack the event, simulate an ack - // so we don't wait for the timer to fire. - OnDispatchInputEventDone(mojom::EventResult::UNHANDLED); -} - -void EventDispatcherImpl::ScheduleInputEventTimeout( - AsyncEventDispatcher* async_event_dispatcher, - int64_t display_id, - const Event& event, - EventDispatchPhase phase) { - DCHECK(!in_flight_event_dispatch_details_); - std::unique_ptr<InFlightEventDispatchDetails> details = - std::make_unique<InFlightEventDispatchDetails>( - this, async_event_dispatcher, display_id, event, phase); - - // TODO(sad): Adjust this delay, possibly make this dynamic. - const base::TimeDelta max_delay = base::debug::BeingDebugged() - ? base::TimeDelta::FromDays(1) - : GetDefaultAckTimerDelay(); - details->timer.Start( - FROM_HERE, max_delay, - base::Bind(&EventDispatcherImpl::OnDispatchInputEventTimeout, - details->weak_factory_.GetWeakPtr())); - in_flight_event_dispatch_details_ = std::move(details); -} - -void EventDispatcherImpl::ProcessEventTasks() { - // Loop through |event_tasks_| stopping after dispatching the first valid - // event. - while (!event_tasks_.empty() && !IsProcessingEvent()) { - std::unique_ptr<EventTask> task = std::move(event_tasks_.front()); - event_tasks_.pop(); - - switch (task->type()) { - case EventTask::Type::kClosure: - std::move(task->done_closure).Run(); - break; - case EventTask::Type::kEvent: - delegate_->OnWillProcessEvent(*task->event, task->event_location); - event_processor_->ProcessEvent( - *task->event, task->event_location, - EventProcessor::AcceleratorMatchPhase::ANY); - break; - case EventTask::Type::kProcessedEvent: - if (task->processed_target->IsValid()) { - DispatchInputEventToWindowImpl(task->processed_target->window(), - task->processed_target->client_id(), - task->event_location, *task->event, - task->processed_target->accelerator()); - } - break; - } - } -} - -// TODO(riajiang): We might want to do event targeting for the next event while -// waiting for the current event to be dispatched. https://crbug.com/724521 -void EventDispatcherImpl::DispatchInputEventToWindowImpl( - ServerWindow* target, - ClientSpecificId client_id, - const EventLocation& event_location, - const ui::Event& event, - base::WeakPtr<Accelerator> accelerator) { - DCHECK(!in_flight_event_dispatch_details_); - DCHECK(target); - target = delegate_->OnWillDispatchInputEvent(target, client_id, - event_location, event); - AsyncEventDispatcher* async_event_dispatcher = - async_event_dispatcher_lookup_->GetAsyncEventDispatcherById(client_id); - DCHECK(async_event_dispatcher); - ScheduleInputEventTimeout(async_event_dispatcher, event_location.display_id, - event, EventDispatchPhase::TARGET); - in_flight_event_dispatch_details_->post_target_accelerator = accelerator; - - async_event_dispatcher->DispatchEvent( - target, event, event_location, - base::BindOnce( - &EventDispatcherImpl::OnDispatchInputEventDone, - in_flight_event_dispatch_details_->weak_factory_.GetWeakPtr())); -} - -void EventDispatcherImpl::OnDispatchInputEventTimeout() { - DCHECK(in_flight_event_dispatch_details_); - delegate_->OnEventDispatchTimedOut( - in_flight_event_dispatch_details_->async_event_dispatcher); - if (in_flight_event_dispatch_details_->phase == - EventDispatchPhase::PRE_TARGET_ACCELERATOR) { - OnAcceleratorDone(mojom::EventResult::UNHANDLED, {}); - } else { - OnDispatchInputEventDone(mojom::EventResult::UNHANDLED); - } -} - -void EventDispatcherImpl::OnDispatchInputEventDone(mojom::EventResult result) { - DCHECK(in_flight_event_dispatch_details_); - std::unique_ptr<InFlightEventDispatchDetails> details = - std::move(in_flight_event_dispatch_details_); - - if (result == mojom::EventResult::UNHANDLED && - details->post_target_accelerator) { - OnAccelerator(details->post_target_accelerator->id(), details->display_id, - *details->event, AcceleratorPhase::kPost); - } - - ProcessEventTasks(); -} - -void EventDispatcherImpl::OnAcceleratorDone( - mojom::EventResult result, - const base::flat_map<std::string, std::vector<uint8_t>>& properties) { - DCHECK(in_flight_event_dispatch_details_); - DCHECK_EQ(EventDispatchPhase::PRE_TARGET_ACCELERATOR, - in_flight_event_dispatch_details_->phase); - - std::unique_ptr<InFlightEventDispatchDetails> details = - std::move(in_flight_event_dispatch_details_); - - if (result == mojom::EventResult::UNHANDLED) { - DCHECK(details->event->IsKeyEvent()); - if (!properties.empty()) - details->event->AsKeyEvent()->SetProperties(properties); - event_processor_->ProcessEvent( - *details->event, EventLocation(details->display_id), - EventProcessor::AcceleratorMatchPhase::POST_ONLY); - } else { - // We're not going to process the event any further, notify the delegate. - delegate_->OnAsyncEventDispatcherHandledAccelerator(*details->event, - details->display_id); - ProcessEventTasks(); - } -} - -void EventDispatcherImpl::QueueEvent( - const ui::Event& event, - std::unique_ptr<ProcessedEventTarget> processed_event_target, - const EventLocation& event_location) { - std::unique_ptr<EventTask> queued_event(new EventTask); - queued_event->event = ui::Event::Clone(event); - queued_event->processed_target = std::move(processed_event_target); - queued_event->event_location = event_location; - event_tasks_.push(std::move(queued_event)); -} - -void EventDispatcherImpl::DispatchInputEventToWindow( - ServerWindow* target, - ClientSpecificId client_id, - const EventLocation& event_location, - const Event& event, - Accelerator* accelerator) { - if (in_flight_event_dispatch_details_) { - std::unique_ptr<ProcessedEventTarget> processed_event_target = - std::make_unique<ProcessedEventTarget>(async_event_dispatcher_lookup_, - target, client_id, accelerator); - QueueEvent(event, std::move(processed_event_target), event_location); - return; - } - - base::WeakPtr<Accelerator> weak_accelerator; - if (accelerator) - weak_accelerator = accelerator->GetWeakPtr(); - DispatchInputEventToWindowImpl(target, client_id, event_location, event, - weak_accelerator); -} - -void EventDispatcherImpl::OnAccelerator(uint32_t accelerator_id, - int64_t display_id, - const ui::Event& event, - AcceleratorPhase phase) { - const bool needs_ack = phase == AcceleratorPhase::kPre; - AsyncEventDispatcher::AcceleratorCallback ack_callback; - if (needs_ack) { - ScheduleInputEventTimeout(accelerator_dispatcher_, display_id, event, - EventDispatchPhase::PRE_TARGET_ACCELERATOR); - ack_callback = base::BindOnce( - &EventDispatcherImpl::OnAcceleratorDone, - in_flight_event_dispatch_details_->weak_factory_.GetWeakPtr()); - } - accelerator_dispatcher_->DispatchAccelerator(accelerator_id, event, - std::move(ack_callback)); -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/event_dispatcher_impl.h b/services/ui/ws/event_dispatcher_impl.h deleted file mode 100644 index 26ec81fd..0000000 --- a/services/ui/ws/event_dispatcher_impl.h +++ /dev/null
@@ -1,195 +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 SERVICES_UI_WS_EVENT_DISPATCHER_IMPL_H_ -#define SERVICES_UI_WS_EVENT_DISPATCHER_IMPL_H_ - -#include <stdint.h> - -#include <string> -#include <vector> - -#include "base/containers/flat_map.h" -#include "base/containers/queue.h" -#include "base/macros.h" -#include "base/memory/weak_ptr.h" -#include "base/timer/timer.h" -#include "services/ui/ws/event_dispatcher.h" -#include "services/ui/ws/event_processor_delegate.h" - -namespace ui { - -class Event; - -namespace mojom { -enum class EventResult; -} - -namespace ws { - -class EventDispatcherDelegate; -class EventProcessor; -class AsyncEventDispatcher; -class AsyncEventDispatcherLookup; - -struct EventLocation; - -// EventDispatcherImpl is the entry point for event related processing done by -// the Window Service. Events received from the platform are forwarded to -// ProcessEvent(). ProcessEvent() may queue the event for later processing (if -// waiting for an event to be dispatched, or waiting on EventProcessor to -// complete processing). EventDispatcherImpl ultimately calls to EventProcessor -// for processing. EventDispatcherImpl uses AsyncEventDispatcher for dispatch -// to clients. -class EventDispatcherImpl : public EventDispatcher { - public: - // |accelerator_dispatcher| must outlive this class. - EventDispatcherImpl(AsyncEventDispatcherLookup* async_event_dispatcher_lookup, - AsyncEventDispatcher* accelerator_dispatcher, - EventDispatcherDelegate* delegate); - ~EventDispatcherImpl() override; - - void Init(EventProcessor* processor); - - // Processes an event. If IsProcessingEvent() is true, this queues up the - // event for later processing. This doesn't take ownership of |event|, but it - // may modify it. - void ProcessEvent(ui::Event* event, const EventLocation& event_location); - - // Returns true if actively processing an event. This includes waiting for an - // AsyncEventDispatcher to respond to an event. - bool IsProcessingEvent() const; - - // Returns the event this EventDispatcherImpl is waiting on a response for, or - // null if not waiting on an AsyncEventDispatcher. - const ui::Event* GetInFlightEvent() const; - - // Notifies |closure| once done processing currently queued events. This - // notifies |closure| immediately if IsProcessingEvent() returns false. - void ScheduleCallbackWhenDoneProcessingEvents(base::OnceClosure closure); - - // Called when an AsyncEventDispatcher is destroyed. - // TODO(sky): AsyncEventDispatcher should support observers. - void OnWillDestroyAsyncEventDispatcher(AsyncEventDispatcher* target); - - private: - friend class EventDispatcherImplTestApi; - class ProcessedEventTarget; - struct EventTask; - - enum class EventDispatchPhase { - // Not actively dispatching. - NONE, - - // A PRE_TARGET accelerator has been encountered and we're awaiting the ack. - PRE_TARGET_ACCELERATOR, - - // Dispatching to the target, awaiting the ack. - TARGET, - }; - - // Tracks state associated with an event being dispatched to an - // AsyncEventDispatcher. - struct InFlightEventDispatchDetails { - InFlightEventDispatchDetails(EventDispatcherImpl* dispatcher, - AsyncEventDispatcher* async_event_dispatcher, - int64_t display_id, - const Event& event, - EventDispatchPhase phase); - ~InFlightEventDispatchDetails(); - - // Timer used to know when the AsyncEventDispatcher has taken too long. - base::OneShotTimer timer; - AsyncEventDispatcher* async_event_dispatcher; - int64_t display_id; - std::unique_ptr<Event> event; - EventDispatchPhase phase; - base::WeakPtr<Accelerator> post_target_accelerator; - - // Used for callbacks associated with the processing (such as |timer|). This - // is used rather than a WeakPtrFactory on EventDispatcherImpl itself so - // that it's scoped to the life of waiting for the AsyncEventDispatcher to - // respond. - base::WeakPtrFactory<EventDispatcherImpl> weak_factory_; - }; - - // Creates an InFlightEventDispatchDetails and schedules a timer that calls - // OnDispatchInputEventTimeout() when done. This is used prior to asking - // an AsyncEventDispatcher to dispatch an event or accelerator. - void ScheduleInputEventTimeout(AsyncEventDispatcher* async_event_dispatcher, - int64_t display_id, - const Event& event, - EventDispatchPhase phase); - - // Processes all pending events until there are no more, or this class is - // waiting on on a result from either EventProcessor of AsyncEventDispatcher. - void ProcessEventTasks(); - - // Actual implementation of DispatchInputEventToWindow(). Schedules a timeout - // and calls DispatchEvent() on the appropriate AsyncEventDispatcher. - void DispatchInputEventToWindowImpl(ServerWindow* target, - ClientSpecificId client_id, - const EventLocation& event_location, - const ui::Event& event, - base::WeakPtr<Accelerator> accelerator); - - // The AsyncEventDispatcher has not completed processing in an appropriate - // amount of time. - void OnDispatchInputEventTimeout(); - - // The AsyncEventDispatcher has completed processing the current event. - void OnDispatchInputEventDone(mojom::EventResult result); - - // Called when |accelerator_dispatcher_| has completed processing the - // accelerator. - void OnAcceleratorDone( - mojom::EventResult result, - const base::flat_map<std::string, std::vector<uint8_t>>& properties); - - // Schedules an event to be processed later. - void QueueEvent(const Event& event, - std::unique_ptr<ProcessedEventTarget> processed_event_target, - const EventLocation& event_location); - - // EventDispatcher: - void DispatchInputEventToWindow(ServerWindow* target, - ClientSpecificId client_id, - const EventLocation& event_location, - const Event& event, - Accelerator* accelerator) override; - void OnAccelerator(uint32_t accelerator_id, - int64_t display_id, - const ui::Event& event, - AcceleratorPhase phase) override; - - EventProcessor* event_processor_ = nullptr; - - // Used to map a ClientId to an AsyncEventDispatcher. - AsyncEventDispatcherLookup* const async_event_dispatcher_lookup_; - - // Processes accelerators. This AsyncEventDispatcher corresponds to the - // AsyncEventDispatcher accelerators originate from, which is typically the - // WindowManager. - AsyncEventDispatcher* const accelerator_dispatcher_; - - EventDispatcherDelegate* delegate_; - - // Used for any event related tasks that need to be processed. Tasks are added - // to the queue anytime work comes in while waiting for an - // AsyncEventDispatcher to respond, or waiting for async hit-testing - // processing to complete. - base::queue<std::unique_ptr<EventTask>> event_tasks_; - - // If non-null we're actively waiting for a response from an - // AsyncEventDispatcher. - std::unique_ptr<InFlightEventDispatchDetails> - in_flight_event_dispatch_details_; - - DISALLOW_COPY_AND_ASSIGN(EventDispatcherImpl); -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_EVENT_DISPATCHER_IMPL_H_
diff --git a/services/ui/ws/event_dispatcher_impl_test_api.cc b/services/ui/ws/event_dispatcher_impl_test_api.cc deleted file mode 100644 index 8f64e70..0000000 --- a/services/ui/ws/event_dispatcher_impl_test_api.cc +++ /dev/null
@@ -1,55 +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 "services/ui/ws/event_dispatcher_impl_test_api.h" - -#include "services/ui/ws/event_dispatcher_impl.h" -#include "services/ui/ws/window_tree.h" - -namespace ui { -namespace ws { - -EventDispatcherImplTestApi::EventDispatcherImplTestApi( - EventDispatcherImpl* event_dispatcher) - : event_dispatcher_(event_dispatcher) {} - -EventDispatcherImplTestApi::~EventDispatcherImplTestApi() = default; - -void EventDispatcherImplTestApi::DispatchInputEventToWindow( - ServerWindow* target, - ClientSpecificId client_id, - const EventLocation& event_location, - const Event& event, - Accelerator* accelerator) { - event_dispatcher_->DispatchInputEventToWindow( - target, client_id, event_location, event, accelerator); -} - -WindowTree* EventDispatcherImplTestApi::GetTreeThatWillAckEvent() { - return event_dispatcher_->in_flight_event_dispatch_details_ - ? static_cast<WindowTree*>( - event_dispatcher_->in_flight_event_dispatch_details_ - ->async_event_dispatcher) - : nullptr; -} - -bool EventDispatcherImplTestApi::is_event_tasks_empty() { - return event_dispatcher_->event_tasks_.empty(); -} - -bool EventDispatcherImplTestApi::OnDispatchInputEventDone( - mojom::EventResult result) { - if (!event_dispatcher_->GetInFlightEvent()) - return false; - event_dispatcher_->OnDispatchInputEventDone(result); - return true; -} - -void EventDispatcherImplTestApi::OnDispatchInputEventTimeout() { - if (event_dispatcher_->GetInFlightEvent()) - event_dispatcher_->OnDispatchInputEventTimeout(); -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/event_dispatcher_impl_test_api.h b/services/ui/ws/event_dispatcher_impl_test_api.h deleted file mode 100644 index bdd0b4fc..0000000 --- a/services/ui/ws/event_dispatcher_impl_test_api.h +++ /dev/null
@@ -1,62 +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 SERVICES_UI_WS_EVENT_DISPATCHER_IMPL_TEST_API_H_ -#define SERVICES_UI_WS_EVENT_DISPATCHER_IMPL_TEST_API_H_ - -#include "base/macros.h" -#include "services/ui/common/types.h" - -namespace ui { - -class Event; - -namespace mojom { -enum class EventResult; -} - -namespace ws { - -class Accelerator; -class EventDispatcherImpl; -class ServerWindow; -class WindowTree; - -struct EventLocation; - -// Allows accessing internal functions of EventDispatcherImpl for testing. Most -// functions call through to a function of the same name on EventDispatcherImpl, -// see EventDispatcherImpl for details. -class EventDispatcherImplTestApi { - public: - explicit EventDispatcherImplTestApi(EventDispatcherImpl* event_dispatcher); - ~EventDispatcherImplTestApi(); - - void DispatchInputEventToWindow(ServerWindow* target, - ClientSpecificId client_id, - const EventLocation& event_location, - const Event& event, - Accelerator* accelerator); - - // Convenience for returning - // |in_flight_event_dispatch_details_->async_event_dispatcher_| as a - // WindowTree. - WindowTree* GetTreeThatWillAckEvent(); - - bool is_event_tasks_empty(); - - bool OnDispatchInputEventDone(mojom::EventResult result); - - void OnDispatchInputEventTimeout(); - - private: - EventDispatcherImpl* event_dispatcher_; - - DISALLOW_COPY_AND_ASSIGN(EventDispatcherImplTestApi); -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_EVENT_DISPATCHER_IMPL_TEST_API_H_
diff --git a/services/ui/ws/event_injector.cc b/services/ui/ws/event_injector.cc deleted file mode 100644 index faad73cc..0000000 --- a/services/ui/ws/event_injector.cc +++ /dev/null
@@ -1,88 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "services/ui/ws/event_injector.h" - -#include "services/ui/ws/display.h" -#include "services/ui/ws/display_manager.h" -#include "services/ui/ws/platform_display.h" -#include "services/ui/ws/window_manager_state.h" -#include "services/ui/ws/window_server.h" - -namespace ui { -namespace ws { - -EventInjector::EventInjector(WindowServer* server) : window_server_(server) {} - -EventInjector::~EventInjector() {} - -void EventInjector::AdjustEventLocationForPixelLayout(Display* display, - ui::LocatedEvent* event) { - WindowManagerState* window_manager_state = - window_server_->GetWindowManagerState(); - if (!window_manager_state) - return; - - // Only need to adjust the location of events when there is capture. - PlatformDisplay* platform_display_with_capture = - window_manager_state->platform_display_with_capture(); - if (!platform_display_with_capture || - display->platform_display() == platform_display_with_capture) { - return; - } - - // The event is from a display other than the display with capture. On device - // events originate from the display with capture and are in terms of the - // pixel layout (see comments in EventLocation). Convert the location to be - // relative to the display with capture in terms of the pixel layout to match - // what happens on device. - gfx::PointF capture_relative_location = event->location_f(); - capture_relative_location += display->GetViewportMetrics() - .bounds_in_pixels.origin() - .OffsetFromOrigin(); - capture_relative_location -= - platform_display_with_capture->GetViewportMetrics() - .bounds_in_pixels.origin() - .OffsetFromOrigin(); - event->set_location_f(capture_relative_location); - event->set_root_location_f(capture_relative_location); -} - -void EventInjector::InjectEvent(int64_t display_id, - std::unique_ptr<ui::Event> event, - InjectEventCallback cb) { - DisplayManager* manager = window_server_->display_manager(); - if (!manager) { - DVLOG(1) << "No display manager in InjectEvent."; - std::move(cb).Run(false); - return; - } - - Display* display = manager->GetDisplayById(display_id); - if (!display) { - DVLOG(1) << "Invalid display_id in InjectEvent."; - std::move(cb).Run(false); - return; - } - - if (event->IsLocatedEvent()) { - LocatedEvent* located_event = event->AsLocatedEvent(); - if (located_event->root_location_f() != located_event->location_f()) { - DVLOG(1) << "EventInjector::InjectEvent locations must match"; - std::move(cb).Run(false); - return; - } - - AdjustEventLocationForPixelLayout(display, located_event); - - // If this is a mouse pointer event, then we have to also update the - // location of the cursor on the screen. - if (event->IsMousePointerEvent()) - display->platform_display()->MoveCursorTo(located_event->location()); - } - display->ProcessEvent(event.get(), base::BindOnce(std::move(cb), true)); -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/event_injector.h b/services/ui/ws/event_injector.h deleted file mode 100644 index f8108db9..0000000 --- a/services/ui/ws/event_injector.h +++ /dev/null
@@ -1,41 +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 SERVICES_UI_WS_EVENT_INJECTOR_H_ -#define SERVICES_UI_WS_EVENT_INJECTOR_H_ - -#include "services/ui/public/interfaces/event_injector.mojom.h" - -namespace ui { -namespace ws { - -class Display; -class WindowServer; - -// See description in mojom for details on this. -class EventInjector : public mojom::EventInjector { - public: - explicit EventInjector(WindowServer* server); - ~EventInjector() override; - - private: - // Adjusts the location as necessary of |event|. |display| is the display - // the event is targetted at. - void AdjustEventLocationForPixelLayout(Display* display, - ui::LocatedEvent* event); - - // mojom::EventInjector: - void InjectEvent(int64_t display_id, - std::unique_ptr<ui::Event> event, - InjectEventCallback cb) override; - - WindowServer* window_server_; - - DISALLOW_COPY_AND_ASSIGN(EventInjector); -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_EVENT_INJECTOR_H_
diff --git a/services/ui/ws/event_location.h b/services/ui/ws/event_location.h deleted file mode 100644 index f51d7f0..0000000 --- a/services/ui/ws/event_location.h +++ /dev/null
@@ -1,59 +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 SERVICES_UI_WS_EVENT_LOCATION_H_ -#define SERVICES_UI_WS_EVENT_LOCATION_H_ - -#include <stdint.h> - -#include "ui/display/types/display_constants.h" -#include "ui/gfx/geometry/point_f.h" - -namespace ui { -namespace ws { - -// Contains a location relative to a particular display in two different -// coordinate systems. The location the event is received at is |raw_location|. -// |raw_location| is in terms of the pixel display layout. |location| is derived -// from |raw_location| and in terms of the DIP display layout (but in pixels). -// Typically |raw_location| is on a single display, in which case |location| is -// exactly the same value. If there is a grab then the events are still -// generated for the display the grab was initiated on, even if the mouse moves -// to another display. As the pixel layout of displays differs from the DIP -// layout |location| is converted to follow the DIP layout (but in pixels). -// -// For example, two displays might have pixels bounds of: -// 0,0 1000x1000 and 0,1060 1000x1000 -// where as the DIP bounds might be: -// 0,0 500x500 and 500,0 1000x1000 -// Notice the pixel bounds are staggered along the y-axis and the DIP bounds -// along the x-axis. -// If there is a grab on the first display and the mouse moves into the second -// display then |raw_location| would be 0,1060 which is converted to a -// |location| of 1000,0 (|display_id| remains the same regardless of the display -// the mouse is on. -struct EventLocation { - EventLocation() : display_id(display::kInvalidDisplayId) {} - explicit EventLocation(int64_t display_id) : display_id(display_id) {} - EventLocation(const gfx::PointF& raw_location, - const gfx::PointF& location, - int64_t display_id) - : raw_location(raw_location), - location(location), - display_id(display_id) {} - - // Location of event in terms of pixel display layout. - gfx::PointF raw_location; - - // Location of event in terms of DIP display layout (but in pixels). - gfx::PointF location; - - // Id of the display the event was generated from. - int64_t display_id; -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_EVENT_LOCATION_H_
diff --git a/services/ui/ws/event_matcher.cc b/services/ui/ws/event_matcher.cc deleted file mode 100644 index f1f14c1..0000000 --- a/services/ui/ws/event_matcher.cc +++ /dev/null
@@ -1,99 +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 "services/ui/ws/event_matcher.h" - -#include "ui/events/mojo/event_struct_traits.h" - -namespace ui { -namespace ws { - -EventMatcher::EventMatcher(const mojom::EventMatcher& matcher) - : fields_to_match_(NONE), - event_type_(ui::ET_UNKNOWN), - event_flags_(ui::EF_NONE), - ignore_event_flags_(ui::EF_NONE), - keyboard_code_(ui::VKEY_UNKNOWN), - pointer_type_(ui::EventPointerType::POINTER_TYPE_UNKNOWN) { - if (matcher.type_matcher) { - fields_to_match_ |= TYPE; - event_type_ = mojo::ConvertTo<ui::EventType>(matcher.type_matcher->type); - } - if (matcher.flags_matcher) { - fields_to_match_ |= FLAGS; - event_flags_ = matcher.flags_matcher->flags; - if (matcher.ignore_flags_matcher) - ignore_event_flags_ = matcher.ignore_flags_matcher->flags; - } - if (matcher.key_matcher) { - fields_to_match_ |= KEYBOARD_CODE; - keyboard_code_ = static_cast<uint16_t>(matcher.key_matcher->keyboard_code); - } - if (matcher.pointer_kind_matcher) { - fields_to_match_ |= POINTER_KIND; - switch (matcher.pointer_kind_matcher->pointer_kind) { - case ui::mojom::PointerKind::MOUSE: - pointer_type_ = ui::EventPointerType::POINTER_TYPE_MOUSE; - break; - case ui::mojom::PointerKind::TOUCH: - pointer_type_ = ui::EventPointerType::POINTER_TYPE_TOUCH; - break; - default: - NOTREACHED(); - } - } - if (matcher.pointer_location_matcher) { - fields_to_match_ |= POINTER_LOCATION; - pointer_region_ = matcher.pointer_location_matcher->region; - } -} - -EventMatcher::EventMatcher(EventMatcher&& rhs) = default; - -EventMatcher::~EventMatcher() {} - -bool EventMatcher::HasFields(int fields) { - return (fields_to_match_ & fields) != 0; -} - -bool EventMatcher::MatchesEvent(const ui::Event& event) const { - if ((fields_to_match_ & TYPE) && event.type() != event_type_) - return false; - // Synthetic flags should never be matched against. - constexpr int kSyntheticFlags = EF_IS_SYNTHESIZED | EF_IS_REPEAT; - int flags = event.flags() & ~(ignore_event_flags_ | kSyntheticFlags); - if ((fields_to_match_ & FLAGS) && flags != event_flags_) - return false; - if (fields_to_match_ & KEYBOARD_CODE) { - if (!event.IsKeyEvent()) - return false; - if (keyboard_code_ != event.AsKeyEvent()->GetConflatedWindowsKeyCode()) - return false; - } - if (fields_to_match_ & POINTER_KIND) { - if (!event.IsPointerEvent() || - pointer_type_ != event.AsPointerEvent()->pointer_details().pointer_type) - return false; - } - if (fields_to_match_ & POINTER_LOCATION) { - // TODO(sad): The tricky part here is to make sure the same coord-space is - // used for the location-region and the event-location. - NOTIMPLEMENTED(); - return false; - } - return true; -} - -bool EventMatcher::Equals(const EventMatcher& other) const { - return fields_to_match_ == other.fields_to_match_ && - event_type_ == other.event_type_ && - event_flags_ == other.event_flags_ && - ignore_event_flags_ == other.ignore_event_flags_ && - keyboard_code_ == other.keyboard_code_ && - pointer_type_ == other.pointer_type_ && - pointer_region_ == other.pointer_region_; -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/event_matcher.h b/services/ui/ws/event_matcher.h deleted file mode 100644 index d0bb7e7..0000000 --- a/services/ui/ws/event_matcher.h +++ /dev/null
@@ -1,61 +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. - -#ifndef SERVICES_UI_WS_EVENT_MATCHER_H_ -#define SERVICES_UI_WS_EVENT_MATCHER_H_ - -#include <stdint.h> - -#include "base/macros.h" -#include "services/ui/public/interfaces/event_matcher.mojom.h" -#include "ui/events/event.h" -#include "ui/events/mojo/event_constants.mojom.h" -#include "ui/events/mojo/keyboard_codes.mojom.h" -#include "ui/gfx/geometry/rect_f.h" - -namespace ui { -namespace ws { - -// Wraps a mojom::EventMatcher and allows events to be tested against it. -class EventMatcher { - public: - enum MatchFields { - NONE = 0, - TYPE = 1 << 0, - FLAGS = 1 << 1, - KEYBOARD_CODE = 1 << 2, - POINTER_KIND = 1 << 3, - POINTER_LOCATION = 1 << 4, - }; - - explicit EventMatcher(const mojom::EventMatcher& matcher); - EventMatcher(EventMatcher&& rhs); - ~EventMatcher(); - - // Returns true if this matcher would match any of types in the |fields| - // bitarray. - bool HasFields(int fields); - - bool MatchesEvent(const ui::Event& event) const; - - bool Equals(const EventMatcher& other) const; - - private: - uint32_t fields_to_match_; - ui::EventType event_type_; - // Bitfields of kEventFlag* and kMouseEventFlag* values in - // input_event_constants.mojom. - int event_flags_; - int ignore_event_flags_; - uint16_t keyboard_code_; - ui::EventPointerType pointer_type_; - gfx::RectF pointer_region_; - - DISALLOW_COPY_AND_ASSIGN(EventMatcher); -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_EVENT_MATCHER_H_
diff --git a/services/ui/ws/event_matcher_unittest.cc b/services/ui/ws/event_matcher_unittest.cc deleted file mode 100644 index 29db65b..0000000 --- a/services/ui/ws/event_matcher_unittest.cc +++ /dev/null
@@ -1,73 +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 "services/ui/ws/event_matcher.h" - -#include "base/time/time.h" -#include "services/ui/public/interfaces/event_matcher.mojom.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/events/event.h" -#include "ui/events/mojo/event_constants.mojom.h" -#include "ui/gfx/geometry/point.h" - -namespace ui { -namespace ws { - -// NOTE: Most of the matching functionality is exercised by tests of Accelerator -// handling in the EventDispatcher and WindowTree tests. These are just basic -// sanity checks. - -using EventTesterTest = testing::Test; - -TEST_F(EventTesterTest, MatchesEventByType) { - mojom::EventMatcherPtr matcher = mojom::EventMatcher::New(); - matcher->type_matcher = mojom::EventTypeMatcher::New(); - matcher->type_matcher->type = ui::mojom::EventType::POINTER_DOWN; - EventMatcher pointer_down_matcher(*matcher); - - ui::PointerEvent pointer_down(ui::TouchEvent( - ui::ET_TOUCH_PRESSED, gfx::Point(), base::TimeTicks(), - ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 1))); - EXPECT_TRUE(pointer_down_matcher.MatchesEvent(pointer_down)); - - ui::PointerEvent pointer_up(ui::TouchEvent( - ui::ET_TOUCH_RELEASED, gfx::Point(), base::TimeTicks(), - ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 1))); - EXPECT_FALSE(pointer_down_matcher.MatchesEvent(pointer_up)); -} - -TEST_F(EventTesterTest, MatchesEventByKeyCode) { - mojom::EventMatcherPtr matcher(mojom::EventMatcher::New()); - matcher->type_matcher = mojom::EventTypeMatcher::New(); - matcher->type_matcher->type = ui::mojom::EventType::KEY_PRESSED; - matcher->key_matcher = mojom::KeyEventMatcher::New(); - matcher->key_matcher->keyboard_code = ui::mojom::KeyboardCode::Z; - EventMatcher z_matcher(*matcher); - - ui::KeyEvent z_key(ui::ET_KEY_PRESSED, ui::VKEY_Z, ui::EF_NONE); - EXPECT_TRUE(z_matcher.MatchesEvent(z_key)); - - ui::KeyEvent y_key(ui::ET_KEY_PRESSED, ui::VKEY_Y, ui::EF_NONE); - EXPECT_FALSE(z_matcher.MatchesEvent(y_key)); -} - -TEST_F(EventTesterTest, MatchesEventByKeyFlags) { - mojom::EventMatcherPtr matcher(mojom::EventMatcher::New()); - matcher->type_matcher = mojom::EventTypeMatcher::New(); - matcher->type_matcher->type = ui::mojom::EventType::KEY_PRESSED; - matcher->flags_matcher = mojom::EventFlagsMatcher::New(); - matcher->flags_matcher->flags = ui::mojom::kEventFlagControlDown; - matcher->key_matcher = mojom::KeyEventMatcher::New(); - matcher->key_matcher->keyboard_code = ui::mojom::KeyboardCode::N; - EventMatcher control_n_matcher(*matcher); - - ui::KeyEvent control_n(ui::ET_KEY_PRESSED, ui::VKEY_N, ui::EF_CONTROL_DOWN); - EXPECT_TRUE(control_n_matcher.MatchesEvent(control_n)); - - ui::KeyEvent shift_n(ui::ET_KEY_PRESSED, ui::VKEY_N, ui::EF_SHIFT_DOWN); - EXPECT_FALSE(control_n_matcher.MatchesEvent(shift_n)); -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/event_processor.cc b/services/ui/ws/event_processor.cc deleted file mode 100644 index 144b09ce..0000000 --- a/services/ui/ws/event_processor.cc +++ /dev/null
@@ -1,859 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "services/ui/ws/event_processor.h" - -#include <algorithm> - -#include "base/time/time.h" -#include "services/ui/ws/accelerator.h" -#include "services/ui/ws/drag_controller.h" -#include "services/ui/ws/drag_source.h" -#include "services/ui/ws/event_dispatcher.h" -#include "services/ui/ws/event_location.h" -#include "services/ui/ws/event_processor_delegate.h" -#include "services/ui/ws/server_window.h" -#include "services/ui/ws/server_window_delegate.h" -#include "services/ui/ws/server_window_drawn_tracker.h" -#include "services/ui/ws/window_coordinate_conversions.h" -#include "services/ui/ws/window_finder.h" -#include "ui/base/cursor/cursor.h" -#include "ui/events/event_utils.h" -#include "ui/gfx/geometry/point.h" -#include "ui/gfx/geometry/point_conversions.h" - -namespace ui { -namespace ws { - -using Entry = std::pair<uint32_t, std::unique_ptr<Accelerator>>; - -namespace { - -bool IsOnlyOneMouseButtonDown(int flags) { - const uint32_t button_only_flags = - flags & (ui::EF_LEFT_MOUSE_BUTTON | ui::EF_MIDDLE_MOUSE_BUTTON | - ui::EF_RIGHT_MOUSE_BUTTON); - return button_only_flags == ui::EF_LEFT_MOUSE_BUTTON || - button_only_flags == ui::EF_MIDDLE_MOUSE_BUTTON || - button_only_flags == ui::EF_RIGHT_MOUSE_BUTTON; -} - -// This is meant to mirror when implicit capture stops. Specifically non-mouse -// pointer up, or mouse and no more buttons down. -bool IsPointerGoingUp(const Event& event) { - return event.IsPointerEvent() && - (event.type() == ui::ET_POINTER_UP || - event.type() == ui::ET_POINTER_CANCELLED) && - (!event.IsMousePointerEvent() || - IsOnlyOneMouseButtonDown(event.flags())); -} - -// Get the pointer id from an event, only supports PointerEvents for now. -int32_t GetPointerId(const Event& event) { - if (event.IsPointerEvent()) - return event.AsPointerEvent()->pointer_details().id; - return PointerDetails::kUnknownPointerId; -} - -} // namespace - -//////////////////////////////////////////////////////////////////////////////// - -EventProcessor::ObservedWindow::ObservedWindow() = default; -EventProcessor::ObservedWindow::~ObservedWindow() = default; - -EventProcessor::EventProcessor(EventProcessorDelegate* delegate, - EventDispatcher* event_dispatcher) - : delegate_(delegate), - event_dispatcher_(event_dispatcher), - capture_window_(nullptr), - capture_window_client_id_(kInvalidClientId), - event_targeter_(std::make_unique<EventTargeter>(this)), - mouse_button_down_(false), - mouse_cursor_source_window_(nullptr), - mouse_cursor_in_non_client_area_(false) {} - -EventProcessor::~EventProcessor() { - SetMouseCursorSourceWindow(nullptr); - if (capture_window_) { - UnobserveWindow(capture_window_); - capture_window_ = nullptr; - capture_window_client_id_ = kInvalidClientId; - } - for (const auto& pair : pointer_targets_) { - if (pair.second.window) - UnobserveWindow(pair.second.window); - } - pointer_targets_.clear(); -} - -void EventProcessor::Reset() { - if (capture_window_) { - CancelPointerEventsToTarget(capture_window_); - DCHECK(capture_window_ == nullptr); - } - - while (!pointer_targets_.empty()) - StopTrackingPointer(pointer_targets_.begin()->first); - - mouse_button_down_ = false; -} - -ui::CursorData EventProcessor::GetCurrentMouseCursor() const { - if (drag_controller_) - return drag_controller_->current_cursor(); - - if (!mouse_cursor_source_window_) - return ui::CursorData(ui::CursorType::kPointer); - - if (mouse_cursor_in_non_client_area_) - return mouse_cursor_source_window_->non_client_cursor(); - - const ServerWindow* window = GetWindowForMouseCursor(); - return window ? window->cursor() : ui::CursorData(ui::CursorType::kPointer); -} - -bool EventProcessor::SetCaptureWindow(ServerWindow* window, - ClientSpecificId client_id) { - if (!window) - client_id = kInvalidClientId; - - if (window == capture_window_ && client_id == capture_window_client_id_) - return true; - - // A window that is blocked by a modal window cannot gain capture. - if (window && modal_window_controller_.IsWindowBlocked(window)) - return false; - - // If we're currently performing a drag and drop, reject setting the capture - // window. - if (drag_controller_) - return false; - - if (capture_window_) { - // Stop observing old capture window. |pointer_targets_| are cleared on - // initial setting of a capture window. - UnobserveWindow(capture_window_); - } else { - CancelImplicitCaptureExcept(window, client_id); - } - - // Set the capture before changing native capture; otherwise, the callback - // from native platform might try to set the capture again. - const bool had_capture_window = capture_window_ != nullptr; - ServerWindow* old_capture_window = capture_window_; - capture_window_ = window; - capture_window_client_id_ = client_id; - - delegate_->OnCaptureChanged(capture_window_, old_capture_window); - - // Begin tracking the capture window if it is not yet being observed. - if (window) { - ObserveWindow(window); - // TODO(sky): this conditional is problematic for the case of capture moving - // to a different display. - if (!had_capture_window) - delegate_->SetNativeCapture(window); - } else { - delegate_->ReleaseNativeCapture(); - if (!mouse_button_down_) - UpdateCursorProviderByLastKnownLocation(); - } - return true; -} - -void EventProcessor::SetDragDropSourceWindow( - DragSource* drag_source, - ServerWindow* window, - DragTargetConnection* source_connection, - int32_t drag_pointer, - const base::flat_map<std::string, std::vector<uint8_t>>& mime_data, - uint32_t drag_operations) { - CancelImplicitCaptureExcept(nullptr, kInvalidClientId); - drag_controller_ = std::make_unique<DragController>( - this, drag_source, window, source_connection, drag_pointer, mime_data, - drag_operations); -} - -void EventProcessor::CancelDragDrop() { - if (drag_controller_) - drag_controller_->Cancel(); -} - -void EventProcessor::EndDragDrop() { - drag_controller_.reset(); -} - -void EventProcessor::OnWillDestroyDragTargetConnection( - DragTargetConnection* connection) { - if (drag_controller_) - drag_controller_->OnWillDestroyDragTargetConnection(connection); -} - -void EventProcessor::AddSystemModalWindow(ServerWindow* window) { - modal_window_controller_.AddSystemModalWindow(window); - ReleaseCaptureBlockedByAnyModalWindow(); -} - -void EventProcessor::ReleaseCaptureBlockedByAnyModalWindow() { - if (!capture_window_) - return; - - if (modal_window_controller_.IsWindowBlocked(capture_window_)) - SetCaptureWindow(nullptr, kInvalidClientId); -} - -const ServerWindow* EventProcessor::GetWindowForMouseCursor() const { - if (mouse_cursor_in_non_client_area_ || !mouse_cursor_source_window_) - return mouse_cursor_source_window_; - - // Return the ancestor (starting at |mouse_cursor_source_window_|) whose - // client id differs. In other words, return the first window ancestor that is - // an embed root. This is done to match the behavior of aura, which sets the - // cursor on the root. - const ClientSpecificId target_client_id = delegate_->GetEventTargetClientId( - mouse_cursor_source_window_, mouse_cursor_in_non_client_area_); - const ServerWindow* window = mouse_cursor_source_window_; - while (window && window->owning_tree_id() == target_client_id) - window = window->parent(); - return window; -} - -void EventProcessor::UpdateNonClientAreaForCurrentWindow() { - if (!mouse_button_down_ && mouse_cursor_source_window_) { - event_targeter_->FindTargetForLocation( - EventSource::MOUSE, - {mouse_pointer_last_location_, mouse_pointer_last_location_, - mouse_pointer_display_id_}, - base::BindOnce( - &EventProcessor::UpdateNonClientAreaForCurrentWindowOnFoundWindow, - base::Unretained(this))); - } -} - -void EventProcessor::UpdateCursorProviderByLastKnownLocation() { - if (!mouse_button_down_) { - event_targeter_->FindTargetForLocation( - EventSource::MOUSE, - {mouse_pointer_last_location_, mouse_pointer_last_location_, - mouse_pointer_display_id_}, - base::BindOnce(&EventProcessor:: - UpdateCursorProviderByLastKnownLocationOnFoundWindow, - base::Unretained(this))); - } -} - -bool EventProcessor::AddAccelerator(uint32_t id, - mojom::EventMatcherPtr event_matcher) { - std::unique_ptr<Accelerator> accelerator(new Accelerator(id, *event_matcher)); - // If an accelerator with the same id or matcher already exists, then abort. - for (const auto& pair : accelerators_) { - if (pair.first == id) { - DVLOG(1) << "duplicate accelerator. Accelerator id=" << accelerator->id() - << " type=" << event_matcher->type_matcher->type - << " flags=" << event_matcher->flags_matcher->flags; - return false; - } else if (accelerator->EqualEventMatcher(pair.second.get())) { - DVLOG(1) << "duplicate matcher. Accelerator id=" << accelerator->id() - << " type=" << event_matcher->type_matcher->type - << " flags=" << event_matcher->flags_matcher->flags; - return false; - } - } - accelerators_.insert(Entry(id, std::move(accelerator))); - return true; -} - -void EventProcessor::RemoveAccelerator(uint32_t id) { - auto it = accelerators_.find(id); - // Clients may pass bogus ids. - if (it != accelerators_.end()) - accelerators_.erase(it); -} - -void EventProcessor::SetKeyEventsThatDontHideCursor( - std::vector<::ui::mojom::EventMatcherPtr> dont_hide_cursor_list) { - dont_hide_cursor_matchers_.clear(); - for (auto& matcher_ptr : dont_hide_cursor_list) { - EventMatcher matcher(*matcher_ptr); - // Ensure we don't have pointer matchers in our key only list. - DCHECK(!matcher.HasFields(EventMatcher::POINTER_KIND | - EventMatcher::POINTER_LOCATION)); - dont_hide_cursor_matchers_.push_back(std::move(matcher)); - } -} - -bool EventProcessor::IsProcessingEvent() const { - return waiting_on_event_targeter_; -} - -void EventProcessor::ProcessEvent(const ui::Event& event, - const EventLocation& event_location, - AcceleratorMatchPhase match_phase) { -#if !defined(NDEBUG) - if (match_phase == AcceleratorMatchPhase::POST_ONLY) { - // POST_ONLY should always be preceeded by ANY with the same event. - DCHECK(previous_event_); - // Event doesn't define ==, so this compares the key fields. - DCHECK(event.type() == previous_event_->type() && - event.time_stamp() == previous_event_->time_stamp() && - event.flags() == previous_event_->flags()); - DCHECK_EQ(previous_accelerator_match_phase_, AcceleratorMatchPhase::ANY); - } - previous_event_ = Event::Clone(event); - previous_accelerator_match_phase_ = match_phase; -#endif - - if (event.IsKeyEvent()) { - const ui::KeyEvent* key_event = event.AsKeyEvent(); - if (!key_event->is_char() && match_phase == AcceleratorMatchPhase::ANY) { - Accelerator* pre_target = - FindAccelerator(*key_event, ui::mojom::AcceleratorPhase::PRE_TARGET); - if (pre_target) { - event_dispatcher_->OnAccelerator( - pre_target->id(), event_location.display_id, event, - EventDispatcher::AcceleratorPhase::kPre); - return; - } - } - ProcessKeyEvent(*key_event, event_location.display_id, match_phase); - return; - } - - DCHECK(event.IsPointerEvent() || event.IsScrollEvent()); - DCHECK(event_location.location == event.AsLocatedEvent()->root_location_f()); - DCHECK(event_location.location == event.AsLocatedEvent()->location_f()); - DCHECK(!waiting_on_event_targeter_); - if (ShouldUseEventTargeter(event)) { - waiting_on_event_targeter_ = true; - const EventSource event_source = - event.IsMousePointerEvent() ? EventSource::MOUSE : EventSource::TOUCH; - event_targeter_->FindTargetForLocation( - event_source, event_location, - base::BindOnce(&EventProcessor::ProcessEventOnFoundTarget, - base::Unretained(this), ui::Event::Clone(event))); - } else { - ProcessEventOnFoundTargetImpl(ui::Event::Clone(event), event_location, - nullptr); - } -} - -ServerWindow* EventProcessor::GetRootWindowForDisplay(int64_t display_id) { - return delegate_->GetRootWindowForDisplay(display_id); -} - -viz::HitTestQuery* EventProcessor::GetHitTestQueryForDisplay( - int64_t display_id) { - return delegate_->GetHitTestQueryForDisplay(display_id); -} - -ServerWindow* EventProcessor::GetWindowFromFrameSinkId( - const viz::FrameSinkId& frame_sink_id) { - return delegate_->GetWindowFromFrameSinkId(frame_sink_id); -} - -DeepestWindow EventProcessor::AdjustTargetForModal( - const DeepestWindow& target) const { - const ServerWindow* modal_transient = - modal_window_controller_.GetModalTransient(target.window); - if (!modal_transient && - !modal_window_controller_.IsWindowBlocked(target.window)) { - return target; - } - - DeepestWindow updated_target = target; - updated_target.in_non_client_area = true; - updated_target.window = - target.window ? delegate_->GetFallbackTargetForEventBlockedByModal( - target.window->GetRootForDrawn()) - : nullptr; - return updated_target; -} - -void EventProcessor::SetMouseCursorSourceWindow(ServerWindow* window) { - if (mouse_cursor_source_window_ == window) - return; - - if (mouse_cursor_source_window_) - UnobserveWindow(mouse_cursor_source_window_); - mouse_cursor_source_window_ = window; - if (mouse_cursor_source_window_) - ObserveWindow(mouse_cursor_source_window_); -} - -void EventProcessor::SetMousePointerLocation( - const gfx::PointF& new_mouse_location, - int64_t new_mouse_display_id) { - // TODO: this needs to account for grab and a different display. By that I - // mean during a grab |mouse_pointer_last_location_| may actually be in a - // different display. - mouse_pointer_last_location_ = new_mouse_location; - mouse_pointer_display_id_ = new_mouse_display_id; -} - -void EventProcessor::ProcessKeyEvent(const ui::KeyEvent& event, - int64_t display_id, - AcceleratorMatchPhase match_phase) { - Accelerator* post_target = - FindAccelerator(event, ui::mojom::AcceleratorPhase::POST_TARGET); - if (drag_controller_ && event.type() == ui::ET_KEY_PRESSED && - event.key_code() == ui::VKEY_ESCAPE) { - drag_controller_->Cancel(); - return; - } - ServerWindow* focused_window = - delegate_->GetFocusedWindowForEventProcessor(display_id); - if (focused_window) { - // We only hide the cursor when there's a window to receive the key - // event. We want to hide the cursor when the user is entering text - // somewhere so if the user is at the desktop with no window to react to - // the key press, there's no reason to hide the cursor. - HideCursorOnMatchedKeyEvent(event); - - // Assume key events are for the client area. - const bool in_nonclient_area = false; - const ClientSpecificId client_id = - delegate_->GetEventTargetClientId(focused_window, in_nonclient_area); - event_dispatcher_->DispatchInputEventToWindow(focused_window, client_id, - EventLocation(display_id), - event, post_target); - return; - } - delegate_->OnEventTargetNotFound(event, display_id); - if (post_target) - event_dispatcher_->OnAccelerator(post_target->id(), display_id, event, - EventDispatcher::AcceleratorPhase::kPost); -} - -void EventProcessor::HideCursorOnMatchedKeyEvent(const ui::KeyEvent& event) { - if (event.IsSynthesized()) { - // Don't bother performing the matching; it will be rejected anyway. - return; - } - - bool hide_cursor = !dont_hide_cursor_matchers_.empty(); - for (auto& matcher : dont_hide_cursor_matchers_) { - if (matcher.MatchesEvent(event)) { - hide_cursor = false; - break; - } - } - - if (hide_cursor) - delegate_->OnEventChangesCursorVisibility(event, false); -} - -bool EventProcessor::ShouldUseEventTargeter(const Event& event) const { - if (drag_controller_) - return true; - - if (capture_window_) - return false; - - auto iter = pointer_targets_.find(GetPointerId(event)); - if (iter == pointer_targets_.end() || !iter->second.is_pointer_down) - return true; - - return (event.IsMousePointerEvent() && IsPointerGoingUp(event)) || - event.type() == ET_POINTER_DOWN; -} - -void EventProcessor::ProcessEventOnFoundTarget( - std::unique_ptr<ui::Event> event, - const EventLocation& event_location, - const DeepestWindow& target) { - DCHECK(waiting_on_event_targeter_); - waiting_on_event_targeter_ = false; - ProcessEventOnFoundTargetImpl(std::move(event), event_location, &target); -} - -void EventProcessor::ProcessEventOnFoundTargetImpl( - std::unique_ptr<ui::Event> event, - const EventLocation& event_location, - const DeepestWindow* found_target) { - // WARNING: |found_target| may be null! - DCHECK(!waiting_on_event_targeter_); - - UpdateCursorRelatedProperties(*event, event_location); - - const bool is_mouse_event = event->IsMousePointerEvent(); - const bool is_pointer_going_up = IsPointerGoingUp(*event); - - // Update mouse down state upon events which change it. - if (is_mouse_event) { - if (event->type() == ui::ET_POINTER_DOWN) - mouse_button_down_ = true; - else if (is_pointer_going_up) - mouse_button_down_ = false; - } - - if (drag_controller_ && event->IsPointerEvent()) { - DCHECK(found_target); - if (drag_controller_->DispatchPointerEvent( - *event->AsPointerEvent(), - AdjustTargetForModal(*found_target).window)) { - return; - } - } - - if (capture_window_) { - SetMouseCursorSourceWindow(capture_window_); - DispatchToClient(capture_window_, capture_window_client_id_, - *event->AsLocatedEvent(), event_location); - return; - } - - std::unique_ptr<DeepestWindowAndTarget> result; - if (found_target) { - result = std::make_unique<DeepestWindowAndTarget>(); - result->deepest_window = AdjustTargetForModal(*found_target); - result->pointer_target.is_mouse_event = is_mouse_event; - result->pointer_target.window = result->deepest_window.window; - result->pointer_target.in_nonclient_area = - result->deepest_window.in_non_client_area; - result->pointer_target.is_pointer_down = - event->type() == ui::ET_POINTER_DOWN; - result->pointer_target.display_id = event_location.display_id; - } - - const int32_t pointer_id = GetPointerId(*event); - if (!IsTrackingPointer(pointer_id) || - !pointer_targets_[pointer_id].is_pointer_down) { - DCHECK(result); - const bool any_pointers_down = AreAnyPointersDown(); - UpdateTargetForPointer(pointer_id, *event->AsLocatedEvent(), - result->pointer_target, event_location); - if (is_mouse_event) - SetMouseCursorSourceWindow(pointer_targets_[pointer_id].window); - - PointerTarget& pointer_target = pointer_targets_[pointer_id]; - if (pointer_target.is_pointer_down) { - if (!any_pointers_down) { - // Don't attempt to change focus on pointer down. We assume client code - // will do that. - ServerWindow* capture_window = pointer_target.window; - if (!capture_window) { - capture_window = - delegate_->GetRootWindowForDisplay(event_location.display_id); - } - delegate_->SetNativeCapture(capture_window); - } - } - } - - // When we release the mouse button, we want the cursor to be sourced from - // the window under the mouse pointer, even though we're sending the button - // up event to the window that had implicit capture. We have to set this - // before we perform dispatch because the Delegate is going to read this - // information from us. - if (is_pointer_going_up && is_mouse_event) { - DCHECK(result); - UpdateCursorProvider(result->deepest_window); - } - - DispatchToPointerTarget(pointer_targets_[pointer_id], - *event->AsLocatedEvent(), event_location); - - if (is_pointer_going_up) { - if (is_mouse_event) - pointer_targets_[pointer_id].is_pointer_down = false; - else - StopTrackingPointer(pointer_id); - if (!AreAnyPointersDown()) - delegate_->ReleaseNativeCapture(); - } - - if (event->type() == ET_POINTER_DOWN) { - // Use |found_target| as |result| has already been adjusted for the - // modal window. - DCHECK(found_target); - if (found_target->window) - HandleClickOnBlockedWindow(*found_target); - } -} - -void EventProcessor::UpdateCursorRelatedProperties( - const ui::Event& event, - const EventLocation& event_location) { - if (event.IsMousePointerEvent()) { - // This corresponds to the code in CompoundEventFilter which updates - // visibility on each mouse event. Here, we're sure that we're a non-exit - // mouse event and FROM_TOUCH doesn't exist in mus so we shouldn't need - // further filtering. - delegate_->OnEventChangesCursorTouchVisibility(event, true); - delegate_->OnEventChangesCursorVisibility(event, true); - - SetMousePointerLocation(event_location.raw_location, - event_location.display_id); - delegate_->OnMouseCursorLocationChanged(event_location.raw_location, - event_location.display_id); - } else if (event.IsPointerEvent()) { - // When we have a non-touch event that wasn't synthesized, hide the mouse - // cursor until the next non-synthesized mouse event. - delegate_->OnEventChangesCursorTouchVisibility(event, false); - } -} - -void EventProcessor::UpdateNonClientAreaForCurrentWindowOnFoundWindow( - const EventLocation& event_location, - const DeepestWindow& target) { - if (!mouse_cursor_source_window_) - return; - - const DeepestWindow updated_target = AdjustTargetForModal(target); - if (updated_target.window == mouse_cursor_source_window_) { - mouse_cursor_in_non_client_area_ = - mouse_cursor_source_window_ ? updated_target.in_non_client_area : false; - } - delegate_->UpdateNativeCursorFromEventProcessor(); -} - -void EventProcessor::UpdateCursorProviderByLastKnownLocationOnFoundWindow( - const EventLocation& event_location, - const DeepestWindow& target) { - UpdateCursorProvider(AdjustTargetForModal(target)); -} - -void EventProcessor::UpdateCursorProvider(const DeepestWindow& target) { - if (mouse_button_down_) - return; - - SetMouseCursorSourceWindow(target.window); - if (mouse_cursor_source_window_) { - mouse_cursor_in_non_client_area_ = target.in_non_client_area; - } else { - SetMouseCursorSourceWindow( - delegate_->GetRootWindowForDisplay(mouse_pointer_display_id_)); - mouse_cursor_in_non_client_area_ = true; - } - delegate_->UpdateNativeCursorFromEventProcessor(); -} - -void EventProcessor::HandleClickOnBlockedWindow(const DeepestWindow& target) { - ServerWindow* modal_transient = - modal_window_controller_.GetModalTransient(target.window); - if (modal_transient) { - ServerWindow* toplevel = - modal_window_controller_.GetToplevelWindow(target.window); - DCHECK(toplevel); - delegate_->SetFocusedWindowFromEventProcessor(toplevel); - delegate_->OnEventOccurredOutsideOfModalWindow(modal_transient); - } else if (target.window->IsDrawn() && - modal_window_controller_.IsWindowBlocked(target.window) && - modal_window_controller_.GetActiveSystemModalWindow()) { - delegate_->OnEventOccurredOutsideOfModalWindow( - modal_window_controller_.GetActiveSystemModalWindow()); - } -} - -void EventProcessor::StartTrackingPointer(int32_t pointer_id, - const PointerTarget& pointer_target) { - DCHECK(!IsTrackingPointer(pointer_id)); - if (pointer_target.window) - ObserveWindow(pointer_target.window); - pointer_targets_[pointer_id] = pointer_target; -} - -void EventProcessor::StopTrackingPointer(int32_t pointer_id) { - DCHECK(IsTrackingPointer(pointer_id)); - ServerWindow* window = pointer_targets_[pointer_id].window; - pointer_targets_.erase(pointer_id); - if (window) - UnobserveWindow(window); -} - -void EventProcessor::UpdateTargetForPointer( - int32_t pointer_id, - const ui::LocatedEvent& event, - const PointerTarget& pointer_target, - const EventLocation& event_location) { - if (!IsTrackingPointer(pointer_id)) { - StartTrackingPointer(pointer_id, pointer_target); - return; - } - - if (pointer_target.window == pointer_targets_[pointer_id].window && - pointer_target.in_nonclient_area == - pointer_targets_[pointer_id].in_nonclient_area) { - // The targets are the same, only set the down state to true if necessary. - // Down going to up is handled by ProcessLocatedEvent(). - if (pointer_target.is_pointer_down) - pointer_targets_[pointer_id].is_pointer_down = true; - return; - } - - // The targets are changing. Send an exit if appropriate. - if (event.IsMousePointerEvent()) { - ui::PointerEvent exit_event( - ui::ET_POINTER_EXITED, event.location(), event.root_location(), - event.flags(), 0 /* changed_button_flags */, - ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_MOUSE, - ui::MouseEvent::kMousePointerId), - event.time_stamp()); - DispatchToPointerTarget(pointer_targets_[pointer_id], exit_event, - event_location); - } - - // Technically we're updating in place, but calling start then stop makes for - // simpler code. - StopTrackingPointer(pointer_id); - StartTrackingPointer(pointer_id, pointer_target); -} - -bool EventProcessor::AreAnyPointersDown() const { - for (const auto& pair : pointer_targets_) { - if (pair.second.is_pointer_down) - return true; - } - return false; -} - -void EventProcessor::DispatchToPointerTarget( - const PointerTarget& target, - const ui::LocatedEvent& event, - const EventLocation& event_location) { - if (!target.window) { - delegate_->OnEventTargetNotFound(event, target.display_id); - return; - } - - if (target.is_mouse_event) - mouse_cursor_in_non_client_area_ = target.in_nonclient_area; - - DispatchToClient(target.window, - delegate_->GetEventTargetClientId(target.window, - target.in_nonclient_area), - event, event_location); -} - -void EventProcessor::DispatchToClient(ServerWindow* window, - ClientSpecificId client_id, - const ui::LocatedEvent& event, - const EventLocation& event_location) { - gfx::Point location = ConvertPointFromRootForEventDispatch( - delegate_->GetRootWindowForEventDispatch(window), window, - event.location()); - std::unique_ptr<ui::Event> clone = ui::Event::Clone(event); - clone->AsLocatedEvent()->set_location(location); - // TODO(jonross): add post-target accelerator support once accelerators - // support pointer events. - event_dispatcher_->DispatchInputEventToWindow( - window, client_id, event_location, *clone, nullptr); -} - -void EventProcessor::CancelPointerEventsToTarget(ServerWindow* window) { - if (capture_window_ == window) { - UnobserveWindow(window); - capture_window_ = nullptr; - capture_window_client_id_ = kInvalidClientId; - mouse_button_down_ = false; - // A window only cares to be informed that it lost capture if it explicitly - // requested capture. A window can lose capture if another window gains - // explicit capture. - delegate_->OnCaptureChanged(nullptr, window); - delegate_->ReleaseNativeCapture(); - UpdateCursorProviderByLastKnownLocation(); - return; - } - - for (auto& pair : pointer_targets_) { - if (pair.second.window == window) { - UnobserveWindow(window); - pair.second.window = nullptr; - } - } -} - -void EventProcessor::ObserveWindow(ServerWindow* window) { - auto iter = observed_windows_.find(window); - if (iter != observed_windows_.end()) { - iter->second->num_observers++; - return; - } - std::unique_ptr<ObservedWindow> observed_window = - std::make_unique<ObservedWindow>(); - observed_window->num_observers = 1; - observed_window->drawn_tracker = - std::make_unique<ServerWindowDrawnTracker>(window, this); - observed_windows_[window] = std::move(observed_window); -} - -void EventProcessor::UnobserveWindow(ServerWindow* window) { - auto it = observed_windows_.find(window); - DCHECK(it != observed_windows_.end()); - DCHECK_LT(0u, it->second->num_observers); - if (--it->second->num_observers == 0u) - observed_windows_.erase(it); -} - -Accelerator* EventProcessor::FindAccelerator( - const ui::KeyEvent& event, - const ui::mojom::AcceleratorPhase phase) { - for (const auto& pair : accelerators_) { - if (pair.second->MatchesEvent(event, phase)) - return pair.second.get(); - } - return nullptr; -} - -void EventProcessor::CancelImplicitCaptureExcept(ServerWindow* window, - ClientSpecificId client_id) { - for (const auto& pair : pointer_targets_) { - ServerWindow* target = pair.second.window; - if (!target) - continue; - UnobserveWindow(target); - if (target == window) - continue; - - // Don't send cancel events to the same client requesting capture, - // otherwise the client can easily get confused. - if (window && client_id == delegate_->GetEventTargetClientId( - target, pair.second.in_nonclient_area)) { - continue; - } - - ui::EventType event_type = pair.second.is_mouse_event - ? ui::ET_POINTER_EXITED - : ui::ET_POINTER_CANCELLED; - ui::EventPointerType pointer_type = - pair.second.is_mouse_event ? ui::EventPointerType::POINTER_TYPE_MOUSE - : ui::EventPointerType::POINTER_TYPE_TOUCH; - // TODO(jonross): Track previous location in PointerTarget for sending - // cancels. - ui::PointerEvent event(event_type, gfx::Point(), gfx::Point(), ui::EF_NONE, - 0 /* changed_button_flags */, - ui::PointerDetails(pointer_type, pair.first), - ui::EventTimeForNow()); - DispatchToPointerTarget(pair.second, event, - EventLocation(pair.second.display_id)); - } - pointer_targets_.clear(); -} - -void EventProcessor::WindowNoLongerValidTarget(ServerWindow* window) { - CancelPointerEventsToTarget(window); - if (mouse_cursor_source_window_ == window) - SetMouseCursorSourceWindow(nullptr); -} - -void EventProcessor::OnDrawnStateChanged(ServerWindow* ancestor, - ServerWindow* window, - bool is_drawn) { - if (!is_drawn) - WindowNoLongerValidTarget(window); -} - -void EventProcessor::OnRootDidChange(ServerWindow* ancestor, - ServerWindow* window) { - if (!delegate_->GetRootWindowForEventDispatch(window)) - WindowNoLongerValidTarget(window); -} - -void EventProcessor::OnDragCursorUpdated() { - delegate_->UpdateNativeCursorFromEventProcessor(); -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/event_processor.h b/services/ui/ws/event_processor.h deleted file mode 100644 index df6269e..0000000 --- a/services/ui/ws/event_processor.h +++ /dev/null
@@ -1,421 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SERVICES_UI_WS_EVENT_PROCESSOR_H_ -#define SERVICES_UI_WS_EVENT_PROCESSOR_H_ - -#include <stdint.h> - -#include <map> -#include <memory> -#include <utility> - -#include "base/containers/flat_map.h" -#include "base/macros.h" -#include "services/ui/common/types.h" -#include "services/ui/public/interfaces/cursor/cursor.mojom.h" -#include "services/ui/public/interfaces/window_manager.mojom.h" -#include "services/ui/ws/drag_cursor_updater.h" -#include "services/ui/ws/event_matcher.h" -#include "services/ui/ws/event_targeter.h" -#include "services/ui/ws/event_targeter_delegate.h" -#include "services/ui/ws/modal_window_controller.h" -#include "services/ui/ws/server_window_drawn_tracker_observer.h" -#include "ui/display/types/display_constants.h" -#include "ui/gfx/geometry/point_f.h" -#include "ui/gfx/geometry/rect_f.h" - -namespace viz { -class HitTestQuery; -} - -namespace ui { -class Event; -class KeyEvent; -class LocatedEvent; - -namespace ws { - -class Accelerator; -class DragController; -class DragSource; -class DragTargetConnection; -class EventDispatcher; -class EventProcessorDelegate; -class ServerWindow; -class ServerWindowDrawnTracker; - -struct EventLocation; - -namespace test { -class EventProcessorTestApi; -} - -// EventProcessor is responsible for processing events and maintaining event -// related state: capture, cursor, last mouse location... EventProcessor informs -// EventProcessorDelegate of interesting state changes and uses an -// EventDispatcher for the actual dispatch. EventProcessor uses EventTargeter -// to determine the actual target. EventProcessor handles a single event at a -// time, and it may asynchronously process the event (EventTargeter may work -// asynchronously). A single event may result in multiple calls to -// EventDispatcher::DispatchEvent(). -class EventProcessor : public ServerWindowDrawnTrackerObserver, - public DragCursorUpdater, - public EventTargeterDelegate { - public: - enum class AcceleratorMatchPhase { - // Both pre and post should be considered. - ANY, - - // PRE_TARGETs are not considered, only the actual target and any - // accelerators registered with POST_TARGET. - POST_ONLY, - }; - - EventProcessor(EventProcessorDelegate* delegate, - EventDispatcher* event_dispatcher); - ~EventProcessor() override; - - ModalWindowController* modal_window_controller() { - return &modal_window_controller_; - } - - // Cancels capture and stops tracking any pointer events. This does not send - // any events to the delegate. - void Reset(); - - const gfx::PointF& mouse_pointer_last_location() const { - return mouse_pointer_last_location_; - } - int64_t mouse_pointer_display_id() const { return mouse_pointer_display_id_; } - - // Returns the cursor for the current target, or POINTER if the mouse is not - // over a valid target. - ui::CursorData GetCurrentMouseCursor() const; - - // |capture_window_| will receive all input. See window_tree.mojom for - // details. - ServerWindow* capture_window() { return capture_window_; } - const ServerWindow* capture_window() const { return capture_window_; } - // Setting capture can fail if the window is blocked by a modal window - // (indicated by returning |false|). - bool SetCaptureWindow(ServerWindow* capture_window, - ClientSpecificId client_id); - - // Id of the client that capture events are sent to. - ClientSpecificId capture_window_client_id() const { - return capture_window_client_id_; - } - - void SetDragDropSourceWindow( - DragSource* drag_source, - ServerWindow* window, - DragTargetConnection* source_connection, - int32_t drag_pointer, - const base::flat_map<std::string, std::vector<uint8_t>>& mime_data, - uint32_t drag_operations); - void CancelDragDrop(); - void EndDragDrop(); - - void OnWillDestroyDragTargetConnection(DragTargetConnection* connection); - - // Adds a system modal window. The window remains modal to system until it is - // destroyed. There can exist multiple system modal windows, in which case the - // one that is visible and added most recently or shown most recently would be - // the active one. - void AddSystemModalWindow(ServerWindow* window); - - // Checks if the current capture window is blocked by any visible modal window - // and if that's the case, releases the capture. - void ReleaseCaptureBlockedByAnyModalWindow(); - - // Retrieves the ServerWindow of the last mouse move. If there is no valid - // window event target this falls back to the root of the display. In general - // this is not null, but may be null during shutdown. - ServerWindow* mouse_cursor_source_window() const { - return mouse_cursor_source_window_; - } - - // Returns the window the mouse cursor is taken from. This does not take - // into account drags. In other words if there is a drag on going the mouse - // comes comes from a different window. - const ServerWindow* GetWindowForMouseCursor() const; - - // If the mouse cursor is still over |mouse_cursor_source_window_|, updates - // whether we are in the non-client area. Used when - // |mouse_cursor_source_window_| has changed its properties. - void UpdateNonClientAreaForCurrentWindow(); - - // Possibly updates the cursor. If we aren't in an implicit capture, we take - // the last known location of the mouse pointer, and look for the - // ServerWindow* under it. - void UpdateCursorProviderByLastKnownLocation(); - - // Adds an accelerator with the given id and event-matcher. If an accelerator - // already exists with the same id or the same matcher, then the accelerator - // is not added. Returns whether adding the accelerator was successful or not. - bool AddAccelerator(uint32_t id, mojom::EventMatcherPtr event_matcher); - - void RemoveAccelerator(uint32_t id); - - void SetKeyEventsThatDontHideCursor( - std::vector<::ui::mojom::EventMatcherPtr> dont_hide_cursor_list); - - // True if we are actively finding a target for an event, false otherwise. - bool IsProcessingEvent() const; - - // Processes the supplied event, informing the delegate as approriate. This - // may result in generating any number of events. If |match_phase| is - // ANY and there is a matching accelerator with PRE_TARGET found, than only - // OnAccelerator() is called. The expectation is after the PRE_TARGET has been - // handled this is again called with an AcceleratorMatchPhase of POST_ONLY. - // This may be asynchronous if we need to find the target window for |event| - // asynchronously. - // NOTE: if |event| is a LocatedEvent, then |event_location.location| is the - // same as the location (and root_location) of |event|. - void ProcessEvent(const ui::Event& event, - const EventLocation& event_location, - AcceleratorMatchPhase match_phase); - - // EventTargeterDelegate: - ServerWindow* GetRootWindowForDisplay(int64_t display_id) override; - viz::HitTestQuery* GetHitTestQueryForDisplay(int64_t display_id) override; - ServerWindow* GetWindowFromFrameSinkId( - const viz::FrameSinkId& frame_sink_id) override; - - private: - friend class test::EventProcessorTestApi; - - // Keeps track of state associated with an active pointer. - struct PointerTarget { - // The target window, which may be null. null is used in two situations: - // when there is no valid window target, or there was a target but the - // window is destroyed before a corresponding release/cancel. - ServerWindow* window = nullptr; - - bool is_mouse_event = false; - - // Did the pointer event start in the non-client area. - bool in_nonclient_area = false; - - bool is_pointer_down = false; - - int64_t display_id = display::kInvalidDisplayId; - }; - - struct DeepestWindowAndTarget { - PointerTarget pointer_target; - DeepestWindow deepest_window; - }; - - struct ObservedWindow { - ObservedWindow(); - ~ObservedWindow(); - - // Number of times ObserveWindow() has been called. - uint8_t num_observers = 0; - - std::unique_ptr<ServerWindowDrawnTracker> drawn_tracker; - }; - - // EventTargeter returns the deepest window based on hit-test data. If the - // target is blocked by a modal window this returns a different target, - // otherwise the supplied target is returned. - DeepestWindow AdjustTargetForModal(const DeepestWindow& target) const; - - void SetMouseCursorSourceWindow(ServerWindow* window); - - // Called after we found the target for the current mouse cursor to see if - // |mouse_pointer_last_location_| and |mouse_pointer_display_id_| need to be - // updated based on the new target we found. No need to call delegate's - // OnMouseCursorLocationChanged since mouse location is the same in - // screen-coord. - // TODO(riajiang): No need to update mouse location after ozone drm can tell - // us the right display the cursor is on for drag-n-drop events. - // crbug.com/726470 - void SetMousePointerLocation(const gfx::PointF& new_mouse_location, - int64_t new_mouse_display_id); - - void ProcessKeyEvent(const ui::KeyEvent& event, - int64_t display_id, - AcceleratorMatchPhase match_phase); - - // When the user presses a key, we want to hide the cursor if it doesn't - // match a list of window manager supplied keys. - void HideCursorOnMatchedKeyEvent(const ui::KeyEvent& event); - - bool IsTrackingPointer(int32_t pointer_id) const { - return pointer_targets_.count(pointer_id) > 0; - } - - // Returns true if EventTargeter needs to be queried for the specified event. - bool ShouldUseEventTargeter(const Event& event) const; - - // Callback from EventTargeter once the target has been found. Calls - // ProcessEventOnFoundTargetImpl(). - void ProcessEventOnFoundTarget(std::unique_ptr<ui::Event> event, - const EventLocation& event_location, - const DeepestWindow& target); - - // EventProcessor provides the following logic for events: - // . wheel events go to the current target of the associated pointer. If - // there is no target, they go to the deepest window. - // . move (not drag) events go to the deepest window. - // . when a pointer goes down all events until the corresponding up or - // cancel go to the deepest target. For mouse events the up only occurs - // when no buttons on the mouse are down. - // This also generates exit events as appropriate. For example, if the mouse - // moves between one window to another an exit is generated on the first. - // - // NOTE: |found_target| is null if ShouldUseEventTargeter() returned false. - // If ShouldUseEventTargeter() returned false it means this function should - // not need |found_target| and has enough information to process the event - // without a DeepestWindow. - void ProcessEventOnFoundTargetImpl(std::unique_ptr<ui::Event> event, - const EventLocation& event_location, - const DeepestWindow* found_target); - - // Called when processing a event to updated cursor related properties. - void UpdateCursorRelatedProperties(const ui::Event& event, - const EventLocation& event_location); - - void UpdateNonClientAreaForCurrentWindowOnFoundWindow( - const EventLocation& event_location, - const DeepestWindow& target); - - // This callback is triggered by UpdateCursorProviderByLastKnownLocation(). - // It calls UpdateCursorProvider() as appropriate. - void UpdateCursorProviderByLastKnownLocationOnFoundWindow( - const EventLocation& event_location, - const DeepestWindow& target); - - // Immediatley updates the cursor provider (|mouse_cursor_source_window_|) - // as appropriate. - void UpdateCursorProvider(const DeepestWindow& target); - - // Called during a click to nodify if the click was blocked by a modal. - void HandleClickOnBlockedWindow(const DeepestWindow& target); - - // Adds |pointer_target| to |pointer_targets_|. - void StartTrackingPointer(int32_t pointer_id, - const PointerTarget& pointer_target); - - // Removes a PointerTarget from |pointer_targets_|. - void StopTrackingPointer(int32_t pointer_id); - - // Starts tracking the pointer for |event|, or if already tracking the - // pointer sends the appropriate event to the delegate and updates the - // currently tracked PointerTarget appropriately. - void UpdateTargetForPointer(int32_t pointer_id, - const ui::LocatedEvent& event, - const PointerTarget& pointer_target, - const EventLocation& event_location); - - // Returns true if any pointers are in the pressed/down state. - bool AreAnyPointersDown() const; - - // If |target->window| is valid, then passes the event to the delegate. - void DispatchToPointerTarget(const PointerTarget& target, - const ui::LocatedEvent& event, - const EventLocation& event_location); - - // Dispatch |event| to the delegate. - void DispatchToClient(ServerWindow* window, - ClientSpecificId client_id, - const ui::LocatedEvent& event, - const EventLocation& event_location); - - // Stops sending pointer events to |window|. This does not remove the entry - // for |window| from |pointer_targets_|, rather it nulls out the window. This - // way we continue to eat events until the up/cancel is received. - void CancelPointerEventsToTarget(ServerWindow* window); - - // Used to observe a window. Can be called multiple times on a window. To - // unobserve a window, UnobserveWindow() should be called the same number of - // times. - void ObserveWindow(ServerWindow* winodw); - void UnobserveWindow(ServerWindow* winodw); - - // Returns an Accelerator bound to the specified code/flags, and of the - // matching |phase|. Otherwise returns null. - Accelerator* FindAccelerator(const ui::KeyEvent& event, - const ui::mojom::AcceleratorPhase phase); - - // Clears the implicit captures in |pointer_targets_|, with the exception of - // |window|. |window| may be null. |client_id| is the target client of - // |window|. - void CancelImplicitCaptureExcept(ServerWindow* window, - ClientSpecificId client_id); - - // Called when |window| is no longer a valid target for events, for example, - // the window was removed from the hierarchy. - void WindowNoLongerValidTarget(ServerWindow* window); - - // ServerWindowDrawnTrackerObserver: - void OnDrawnStateChanged(ServerWindow* ancestor, - ServerWindow* window, - bool is_drawn) override; - void OnRootDidChange(ServerWindow* ancestor, ServerWindow* window) override; - - // DragCursorUpdater: - void OnDragCursorUpdated() override; - - EventProcessorDelegate* delegate_; - EventDispatcher* event_dispatcher_; - - ServerWindow* capture_window_; - ClientSpecificId capture_window_client_id_; - - std::unique_ptr<DragController> drag_controller_; - - ModalWindowController modal_window_controller_; - - std::unique_ptr<EventTargeter> event_targeter_; - - bool mouse_button_down_; - ServerWindow* mouse_cursor_source_window_; - bool mouse_cursor_in_non_client_area_; - - // The location of the mouse pointer in display coordinates. This can be - // outside the bounds of |mouse_cursor_source_window_|, which can capture the - // cursor. - gfx::PointF mouse_pointer_last_location_; - // Id of the display |mouse_pointer_last_location_| is on. - int64_t mouse_pointer_display_id_ = display::kInvalidDisplayId; - - std::map<uint32_t, std::unique_ptr<Accelerator>> accelerators_; - - // A list of EventMatchers provided by the window manager. When this list is - // empty, we perform no processing. When it contains EventMatchers, we run - // each post-targeted key event through this list and if there's a match, we - // don't hide the cursor (otherwise we hide the cursor). - std::vector<EventMatcher> dont_hide_cursor_matchers_; - - using PointerIdToTargetMap = std::map<int32_t, PointerTarget>; - // |pointer_targets_| contains the active pointers. For a mouse based pointer - // a PointerTarget is always active (and present in |pointer_targets_|). For - // touch based pointers the pointer is active while down and removed on - // cancel or up. - PointerIdToTargetMap pointer_targets_; - - // Keeps track of number of observe requests for each observed window. - std::map<const ServerWindow*, std::unique_ptr<ObservedWindow>> - observed_windows_; - - // Set to true when querying EventTargeter for the target. - bool waiting_on_event_targeter_ = false; - -#if !defined(NDEBUG) - std::unique_ptr<ui::Event> previous_event_; - AcceleratorMatchPhase previous_accelerator_match_phase_ = - AcceleratorMatchPhase::ANY; -#endif - - DISALLOW_COPY_AND_ASSIGN(EventProcessor); -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_EVENT_PROCESSOR_H_
diff --git a/services/ui/ws/event_processor_delegate.h b/services/ui/ws/event_processor_delegate.h deleted file mode 100644 index f0408f7..0000000 --- a/services/ui/ws/event_processor_delegate.h +++ /dev/null
@@ -1,116 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SERVICES_UI_WS_EVENT_PROCESSOR_DELEGATE_H_ -#define SERVICES_UI_WS_EVENT_PROCESSOR_DELEGATE_H_ - -#include <stdint.h> - -#include "services/ui/common/types.h" - -namespace gfx { -class PointF; -} - -namespace viz { -class FrameSinkId; -class HitTestQuery; -} - -namespace ui { - -class Event; - -namespace ws { - -class ServerWindow; - -// Notified of various state changes to EventProcessor. This is also used to -// obtain ServerWindows matching certain criteria (such as the ServerWindow for -// a display). -class EventProcessorDelegate { - public: - virtual void SetFocusedWindowFromEventProcessor(ServerWindow* window) = 0; - virtual ServerWindow* GetFocusedWindowForEventProcessor( - int64_t display_id) = 0; - - // Called when capture should be set on the native display. |window| is the - // window capture is being set on. - virtual void SetNativeCapture(ServerWindow* window) = 0; - - // Called when the native display is having capture released. There is no - // longer a ServerWindow holding capture. - virtual void ReleaseNativeCapture() = 0; - - // Called when EventProcessor has a new value for the cursor and our - // delegate should perform the native updates. - virtual void UpdateNativeCursorFromEventProcessor() = 0; - - // Called when |window| has lost capture. The native display may still be - // holding capture. The delegate should not change native display capture. - // ReleaseNativeCapture() is invoked if appropriate. - virtual void OnCaptureChanged(ServerWindow* new_capture, - ServerWindow* old_capture) = 0; - - virtual void OnMouseCursorLocationChanged(const gfx::PointF& point, - int64_t display_id) = 0; - - virtual void OnEventChangesCursorVisibility(const ui::Event& event, - bool visible) = 0; - - virtual void OnEventChangesCursorTouchVisibility(const ui::Event& event, - bool visible) = 0; - - // Returns the id of the client to send events to. |in_nonclient_area| is - // true if the event occurred in the non-client area of the window. - virtual ClientSpecificId GetEventTargetClientId(const ServerWindow* window, - bool in_nonclient_area) = 0; - - // Returns the window to start searching from at the specified location, or - // null if there is a no window containing |location_in_display|. - // |location_in_display| is in display coordinates and in pixels. - // |location_in_display| and |display_id| are updated if the window we - // found is on a different display than the originated display. - // TODO(riajiang): No need to update |location_in_display| and |display_id| - // after ozone drm can tell us the right display the cursor is on for - // drag-n-drop events. crbug.com/726470 - virtual ServerWindow* GetRootWindowForDisplay(int64_t display_id) = 0; - - // Returns the root of |window| that is used for event dispatch. The returned - // value is used for coordinate conversion. Returns null if |window| is not - // in a hierarchy that events should be dispatched to (typically not - // associated with a display). - virtual ServerWindow* GetRootWindowForEventDispatch(ServerWindow* window) = 0; - - // Called when event dispatch could not find a target. OnAccelerator may still - // be called. - virtual void OnEventTargetNotFound(const ui::Event& event, - int64_t display_id) = 0; - - // If an event is blocked by a modal window this function is used to determine - // which window the event should be dispatched to. Return null to indicate no - // window. |window| is the window the event would be targetted at if there was - // no modal window open. - virtual ServerWindow* GetFallbackTargetForEventBlockedByModal( - ServerWindow* window) = 0; - - // Called when an event occurs that targets a window that should be blocked - // by a modal window. |modal_window| is the modal window that blocked the - // event. - virtual void OnEventOccurredOutsideOfModalWindow( - ServerWindow* modal_window) = 0; - - virtual viz::HitTestQuery* GetHitTestQueryForDisplay(int64_t display_id) = 0; - - virtual ServerWindow* GetWindowFromFrameSinkId( - const viz::FrameSinkId& frame_sink_id) = 0; - - protected: - virtual ~EventProcessorDelegate() {} -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_EVENT_PROCESSOR_DELEGATE_H_
diff --git a/services/ui/ws/event_processor_unittest.cc b/services/ui/ws/event_processor_unittest.cc deleted file mode 100644 index 135ddea..0000000 --- a/services/ui/ws/event_processor_unittest.cc +++ /dev/null
@@ -1,2337 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "services/ui/ws/event_processor.h" - -#include <stddef.h> -#include <stdint.h> - -#include "base/command_line.h" -#include "base/containers/queue.h" -#include "base/macros.h" -#include "base/memory/weak_ptr.h" -#include "base/run_loop.h" -#include "base/test/scoped_feature_list.h" -#include "base/test/scoped_task_environment.h" -#include "components/viz/common/features.h" -#include "components/viz/host/hit_test/hit_test_query.h" -#include "services/ui/common/accelerator_util.h" -#include "services/ui/common/switches.h" -#include "services/ui/public/interfaces/window_tree_constants.mojom.h" -#include "services/ui/ws/accelerator.h" -#include "services/ui/ws/event_dispatcher.h" -#include "services/ui/ws/event_location.h" -#include "services/ui/ws/event_processor_delegate.h" -#include "services/ui/ws/server_window.h" -#include "services/ui/ws/test_server_window_delegate.h" -#include "services/ui/ws/test_utils.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/events/event.h" - -namespace ui { -namespace ws { -namespace test { -namespace { - -// Client ids used to indicate the client area and non-client area. -const ClientSpecificId kClientAreaId = 11; -const ClientSpecificId kNonclientAreaId = 111; - -// Identifies a generated event. -struct DispatchedEventDetails { - DispatchedEventDetails() - : window(nullptr), client_id(kInvalidClientId), accelerator(nullptr) {} - - bool IsNonclientArea() const { return client_id == kNonclientAreaId; } - bool IsClientArea() const { return client_id == kClientAreaId; } - - ServerWindow* window; - ClientSpecificId client_id; - std::unique_ptr<ui::Event> event; - Accelerator* accelerator; -}; - -// Serves as both the EventProcessorDelegate and EventDispatcher -// implementation. Records interesting calls for various assertions. -class TestEventProcessorDelegate : public EventProcessorDelegate, - public EventDispatcher { - public: - // Delegate interface used by this class to release capture on event - // dispatcher. - class Delegate { - public: - virtual void ReleaseCapture() = 0; - }; - - explicit TestEventProcessorDelegate(Delegate* delegate) - : delegate_(delegate), - focused_window_(nullptr), - lost_capture_window_(nullptr), - last_accelerator_(0) {} - ~TestEventProcessorDelegate() override {} - - void EnableFallbackToRoot() { fallback_to_root_ = true; } - - void set_is_window_in_display_root(bool value) { - is_window_in_display_root_ = value; - } - - ui::Event* last_event_target_not_found() { - return last_event_target_not_found_.get(); - } - - uint32_t GetAndClearLastAccelerator() { - uint32_t return_value = last_accelerator_; - last_accelerator_ = 0; - last_accelerator_phase_ = AcceleratorPhase::kPost; - return return_value; - } - - AcceleratorPhase last_accelerator_phase() const { - return last_accelerator_phase_; - } - - void set_root(ServerWindow* root) { root_ = root; } - - ServerWindow* window_that_blocked_event() { - return window_that_blocked_event_; - } - void ClearWindowThatBlockedEvent() { window_that_blocked_event_ = nullptr; } - - // Returns the last dispatched event, or null if there are no more. - std::unique_ptr<DispatchedEventDetails> - GetAndAdvanceDispatchedEventDetails() { - if (dispatched_event_queue_.empty()) - return nullptr; - - std::unique_ptr<DispatchedEventDetails> details = - std::move(dispatched_event_queue_.front()); - dispatched_event_queue_.pop(); - return details; - } - - ServerWindow* GetAndClearLastFocusedWindow() { - ServerWindow* result = focused_window_; - focused_window_ = nullptr; - return result; - } - - bool has_queued_events() const { return !dispatched_event_queue_.empty(); } - ServerWindow* lost_capture_window() { return lost_capture_window_; } - - base::Optional<bool> last_cursor_visibility() { - return last_cursor_visibility_; - } - - viz::HitTestQuery* hit_test_query() { return &hit_test_query_; } - - void AddWindow(ServerWindow* window) { windows_.push_back(window); } - - // EventProcessorDelegate: - void SetFocusedWindowFromEventProcessor(ServerWindow* window) override { - focused_window_ = window; - } - - private: - // EventDispatcher: - void DispatchInputEventToWindow(ServerWindow* target, - ClientSpecificId client_id, - const EventLocation& event_location, - const ui::Event& event, - Accelerator* accelerator) override { - std::unique_ptr<DispatchedEventDetails> details(new DispatchedEventDetails); - details->window = target; - details->client_id = client_id; - details->event = ui::Event::Clone(event); - details->accelerator = accelerator; - dispatched_event_queue_.push(std::move(details)); - } - void OnAccelerator(uint32_t accelerator, - int64_t display_id, - const ui::Event& event, - AcceleratorPhase phase) override { - EXPECT_EQ(0u, last_accelerator_); - last_accelerator_ = accelerator; - last_accelerator_phase_ = phase; - } - - // EventProcessorDelegate: - ServerWindow* GetFocusedWindowForEventProcessor(int64_t display_id) override { - return focused_window_; - } - void SetNativeCapture(ServerWindow* window) override {} - void ReleaseNativeCapture() override { - if (delegate_) - delegate_->ReleaseCapture(); - } - void UpdateNativeCursorFromEventProcessor() override {} - void OnCaptureChanged(ServerWindow* new_capture_window, - ServerWindow* old_capture_window) override { - lost_capture_window_ = old_capture_window; - } - void OnMouseCursorLocationChanged(const gfx::PointF& point, - int64_t display_id) override {} - void OnEventChangesCursorVisibility(const ui::Event& event, - bool visible) override { - last_cursor_visibility_ = visible; - } - void OnEventChangesCursorTouchVisibility(const ui::Event& event, - bool visible) override {} - ClientSpecificId GetEventTargetClientId(const ServerWindow* window, - bool in_nonclient_area) override { - return in_nonclient_area ? kNonclientAreaId : kClientAreaId; - } - ServerWindow* GetRootWindowForDisplay(int64_t display_id) override { - return root_; - } - void OnEventTargetNotFound(const ui::Event& event, - int64_t display_id) override { - last_event_target_not_found_ = ui::Event::Clone(event); - } - ServerWindow* GetFallbackTargetForEventBlockedByModal( - ServerWindow* window) override { - return fallback_to_root_ ? root_ : nullptr; - } - void OnEventOccurredOutsideOfModalWindow( - ServerWindow* modal_transient) override { - window_that_blocked_event_ = modal_transient; - } - viz::HitTestQuery* GetHitTestQueryForDisplay(int64_t display_id) override { - return &hit_test_query_; - } - ServerWindow* GetWindowFromFrameSinkId( - const viz::FrameSinkId& frame_sink_id) override { - for (ServerWindow* window : windows_) { - if (window->frame_sink_id() == frame_sink_id) - return window; - } - return nullptr; - } - ServerWindow* GetRootWindowForEventDispatch(ServerWindow* window) override { - return is_window_in_display_root_ ? window->GetRootForDrawn() : nullptr; - } - - Delegate* delegate_; - ServerWindow* focused_window_; - ServerWindow* lost_capture_window_; - uint32_t last_accelerator_; - AcceleratorPhase last_accelerator_phase_ = AcceleratorPhase::kPost; - base::queue<std::unique_ptr<DispatchedEventDetails>> dispatched_event_queue_; - ServerWindow* root_ = nullptr; - std::unique_ptr<ui::Event> last_event_target_not_found_; - base::Optional<bool> last_cursor_visibility_; - ServerWindow* window_that_blocked_event_ = nullptr; - viz::HitTestQuery hit_test_query_; - std::vector<ServerWindow*> windows_; - - // If true events blocked by a modal window are sent to |root_|. - bool fallback_to_root_ = false; - - bool is_window_in_display_root_ = true; - - DISALLOW_COPY_AND_ASSIGN(TestEventProcessorDelegate); -}; - -// Used by RunMouseEventTests(). Can identify up to two generated events. The -// first ServerWindow and two points identify the first event, the second -// ServerWindow and points identify the second event. If only one event is -// generated set the second window to null. -struct MouseEventTest { - std::unique_ptr<ui::MouseEvent> input_event; - ServerWindow* expected_target_window1; - gfx::Point expected_root_location1; - gfx::Point expected_location1; - ServerWindow* expected_target_window2; - gfx::Point expected_root_location2; - gfx::Point expected_location2; -}; - -// Verifies |details| matches the supplied ServerWindow and points. -void ExpectDispatchedEventDetailsMatches(const DispatchedEventDetails* details, - ServerWindow* target, - const gfx::Point& root_location, - const gfx::Point& location) { - if (!target) { - ASSERT_FALSE(details); - return; - } - ASSERT_TRUE(details); - ASSERT_EQ(target, details->window); - ASSERT_TRUE(details->event); - ASSERT_TRUE(details->event->IsLocatedEvent()); - ASSERT_TRUE(details->IsClientArea()); - ASSERT_EQ(root_location, details->event->AsLocatedEvent()->root_location()); - ASSERT_EQ(location, details->event->AsLocatedEvent()->location()); -} - -ui::mojom::EventMatcherPtr BuildKeyMatcher(ui::mojom::KeyboardCode code) { - ui::mojom::EventMatcherPtr matcher(ui::mojom::EventMatcher::New()); - matcher->key_matcher = ui::mojom::KeyEventMatcher::New(); - matcher->key_matcher->keyboard_code = code; - return matcher; -} - -EventLocation EventLocationFromEvent(const Event& event) { - EventLocation event_location(0); - if (event.IsLocatedEvent()) { - event_location.raw_location = event_location.location = - event.AsLocatedEvent()->root_location_f(); - } - return event_location; -} - -} // namespace - -// Test fixture for EventProcessor with friend access to verify the internal -// state. Setup creates a TestServerWindowDelegate, a visible root ServerWindow, -// a TestEventProcessor and the EventProcessor for testing. -class EventProcessorTest : public testing::TestWithParam<bool>, - public TestEventProcessorDelegate::Delegate { - public: - EventProcessorTest() {} - ~EventProcessorTest() override {} - - ServerWindow* root_window() { return root_window_.get(); } - TestEventProcessorDelegate* test_event_dispatcher_delegate() { - return test_event_dispatcher_delegate_.get(); - } - EventProcessor* event_dispatcher() { return event_dispatcher_.get(); } - VizHostProxy* viz_host_proxy() { - return ws_test_helper_.window_server()->GetVizHostProxy(); - } - TestServerWindowDelegate* window_delegate() { return window_delegate_.get(); } - - void DispatchEvent(EventProcessor* dispatcher, - const ui::Event& event, - EventProcessor::AcceleratorMatchPhase match_phase); - void RunMouseEventTests(EventProcessor* dispatcher, - TestEventProcessorDelegate* dispatcher_delegate, - MouseEventTest* tests, - size_t test_count); - bool AreAnyPointersDown() const; - // Deletes everything created during SetUp() - void ClearSetup(); - std::unique_ptr<ServerWindow> CreateChildWindowWithParent( - const viz::FrameSinkId& id, - ServerWindow* parent); - // Creates a window which is a child of |root_window_|. - std::unique_ptr<ServerWindow> CreateChildWindow(const viz::FrameSinkId& id); - bool IsMouseButtonDown() const; - bool IsWindowPointerTarget(const ServerWindow* window) const; - int NumberPointerTargetsForWindow(ServerWindow* window) const; - const ServerWindow* GetActiveSystemModalWindow() const; - - protected: - bool is_event_processing_async() const { return GetParam(); } - - // testing::TestWithParam<bool>: - void SetUp() override; - - void RunTasks(); - - private: - // TestEventProcessorDelegate::Delegate: - void ReleaseCapture() override { - event_dispatcher_->SetCaptureWindow(nullptr, kInvalidClientId); - } - - WindowServerTestHelper ws_test_helper_; - - std::unique_ptr<TestServerWindowDelegate> window_delegate_; - std::unique_ptr<ServerWindow> root_window_; - std::unique_ptr<TestEventProcessorDelegate> test_event_dispatcher_delegate_; - std::unique_ptr<EventProcessor> event_dispatcher_; - - DISALLOW_COPY_AND_ASSIGN(EventProcessorTest); -}; - -void EventProcessorTest::DispatchEvent( - EventProcessor* dispatcher, - const ui::Event& event, - EventProcessor::AcceleratorMatchPhase match_phase) { - dispatcher->ProcessEvent(event, EventLocationFromEvent(event), match_phase); - RunTasks(); -} - -void EventProcessorTest::RunMouseEventTests( - EventProcessor* dispatcher, - TestEventProcessorDelegate* dispatcher_delegate, - MouseEventTest* tests, - size_t test_count) { - for (size_t i = 0; i < test_count; ++i) { - const MouseEventTest& test = tests[i]; - ASSERT_FALSE(dispatcher_delegate->has_queued_events()) - << " unexpected queued events before running " << i; - DispatchEvent(dispatcher, ui::PointerEvent(*test.input_event), - EventProcessor::AcceleratorMatchPhase::ANY); - - std::unique_ptr<DispatchedEventDetails> details = - dispatcher_delegate->GetAndAdvanceDispatchedEventDetails(); - ASSERT_NO_FATAL_FAILURE(ExpectDispatchedEventDetailsMatches( - details.get(), test.expected_target_window1, - test.expected_root_location1, test.expected_location1)) - << " details don't match " << i; - details = dispatcher_delegate->GetAndAdvanceDispatchedEventDetails(); - ASSERT_NO_FATAL_FAILURE(ExpectDispatchedEventDetailsMatches( - details.get(), test.expected_target_window2, - test.expected_root_location2, test.expected_location2)) - << " details2 don't match " << i; - ASSERT_FALSE(dispatcher_delegate->has_queued_events()) - << " unexpected queued events after running " << i; - } -} - -bool EventProcessorTest::AreAnyPointersDown() const { - return EventProcessorTestApi(event_dispatcher_.get()).AreAnyPointersDown(); -} - -void EventProcessorTest::ClearSetup() { - // ServerWindowDelegate should outlive ServerWindow. - root_window_.reset(); - window_delegate_.reset(); - test_event_dispatcher_delegate_.reset(); - event_dispatcher_.reset(); -} - -std::unique_ptr<ServerWindow> EventProcessorTest::CreateChildWindowWithParent( - const viz::FrameSinkId& id, - ServerWindow* parent) { - std::unique_ptr<ServerWindow> child( - new ServerWindow(window_delegate_.get(), id)); - parent->Add(child.get()); - child->SetVisible(true); - return child; -} - -std::unique_ptr<ServerWindow> EventProcessorTest::CreateChildWindow( - const viz::FrameSinkId& id) { - return CreateChildWindowWithParent(id, root_window_.get()); -} - -bool EventProcessorTest::IsMouseButtonDown() const { - return EventProcessorTestApi(event_dispatcher_.get()).is_mouse_button_down(); -} - -bool EventProcessorTest::IsWindowPointerTarget( - const ServerWindow* window) const { - return EventProcessorTestApi(event_dispatcher_.get()) - .IsWindowPointerTarget(window); -} - -int EventProcessorTest::NumberPointerTargetsForWindow( - ServerWindow* window) const { - return EventProcessorTestApi(event_dispatcher_.get()) - .NumberPointerTargetsForWindow(window); -} - -const ServerWindow* EventProcessorTest::GetActiveSystemModalWindow() const { - ModalWindowController* mwc = - EventProcessorTestApi(event_dispatcher_.get()).modal_window_controller(); - return ModalWindowControllerTestApi(mwc).GetActiveSystemModalWindow(); -} - -void EventProcessorTest::RunTasks() { - if (!is_event_processing_async()) - return; - - base::RunLoop runloop; - runloop.RunUntilIdle(); -} - -void EventProcessorTest::SetUp() { - if (is_event_processing_async()) { - base::CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kUseAsyncEventTargeting); - } - testing::TestWithParam<bool>::SetUp(); - - window_delegate_ = - std::make_unique<TestServerWindowDelegate>(viz_host_proxy()); - root_window_ = std::make_unique<ServerWindow>(window_delegate_.get(), - viz::FrameSinkId(1, 2)); - root_window_->set_is_activation_parent(true); - window_delegate_->set_root_window(root_window_.get()); - root_window_->SetVisible(true); - - test_event_dispatcher_delegate_ = - std::make_unique<TestEventProcessorDelegate>(this); - event_dispatcher_ = - std::make_unique<EventProcessor>(test_event_dispatcher_delegate_.get(), - test_event_dispatcher_delegate_.get()); - test_event_dispatcher_delegate_->set_root(root_window_.get()); -} - -TEST_P(EventProcessorTest, ProcessEvent) { - std::unique_ptr<ServerWindow> child = - CreateChildWindow(viz::FrameSinkId(1, 3)); - - root_window()->SetBounds(gfx::Rect(0, 0, 100, 100)); - child->SetBounds(gfx::Rect(10, 10, 20, 20)); - - // Send event that is over child. - const ui::PointerEvent ui_event(ui::MouseEvent( - ui::ET_MOUSE_PRESSED, gfx::Point(20, 25), gfx::Point(20, 25), - base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON)); - DispatchEvent(event_dispatcher(), ui_event, - EventProcessor::AcceleratorMatchPhase::ANY); - - std::unique_ptr<DispatchedEventDetails> details = - test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails(); - ASSERT_TRUE(details); - ASSERT_EQ(child.get(), details->window); - - ASSERT_TRUE(details->event); - ASSERT_TRUE(details->event->IsPointerEvent()); - - ui::PointerEvent* dispatched_event = details->event->AsPointerEvent(); - EXPECT_EQ(gfx::Point(20, 25), dispatched_event->root_location()); - EXPECT_EQ(gfx::Point(10, 15), dispatched_event->location()); -} - -TEST_P(EventProcessorTest, ProcessEventNoTarget) { - // Send event without a target. - ui::KeyEvent key(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE); - DispatchEvent(event_dispatcher(), key, - EventProcessor::AcceleratorMatchPhase::ANY); - - // Event wasn't dispatched to a target. - std::unique_ptr<DispatchedEventDetails> details = - test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails(); - EXPECT_FALSE(details); - - // Delegate was informed that there wasn't a target. - ui::Event* event_out = - test_event_dispatcher_delegate()->last_event_target_not_found(); - ASSERT_TRUE(event_out); - EXPECT_TRUE(event_out->IsKeyEvent()); - EXPECT_EQ(ui::VKEY_A, event_out->AsKeyEvent()->key_code()); -} - -TEST_P(EventProcessorTest, AcceleratorBasic) { - ClearSetup(); - TestEventProcessorDelegate event_dispatcher_delegate(nullptr); - EventProcessor dispatcher(&event_dispatcher_delegate, - &event_dispatcher_delegate); - - uint32_t accelerator_1 = 1; - mojom::EventMatcherPtr matcher = ui::CreateKeyMatcher( - ui::mojom::KeyboardCode::W, ui::mojom::kEventFlagControlDown); - EXPECT_TRUE(dispatcher.AddAccelerator(accelerator_1, std::move(matcher))); - - uint32_t accelerator_2 = 2; - matcher = ui::CreateKeyMatcher(ui::mojom::KeyboardCode::N, - ui::mojom::kEventFlagNone); - EXPECT_TRUE(dispatcher.AddAccelerator(accelerator_2, std::move(matcher))); - - // Attempting to add a new accelerator with the same id should fail. - matcher = ui::CreateKeyMatcher(ui::mojom::KeyboardCode::T, - ui::mojom::kEventFlagNone); - EXPECT_FALSE(dispatcher.AddAccelerator(accelerator_2, std::move(matcher))); - - // Adding the accelerator with the same id should succeed once the existing - // accelerator is removed. - dispatcher.RemoveAccelerator(accelerator_2); - matcher = ui::CreateKeyMatcher(ui::mojom::KeyboardCode::T, - ui::mojom::kEventFlagNone); - EXPECT_TRUE(dispatcher.AddAccelerator(accelerator_2, std::move(matcher))); - - // Attempting to add an accelerator with the same matcher should fail. - uint32_t accelerator_3 = 3; - matcher = ui::CreateKeyMatcher(ui::mojom::KeyboardCode::T, - ui::mojom::kEventFlagNone); - EXPECT_FALSE(dispatcher.AddAccelerator(accelerator_3, std::move(matcher))); - - matcher = ui::CreateKeyMatcher(ui::mojom::KeyboardCode::T, - ui::mojom::kEventFlagControlDown); - EXPECT_TRUE(dispatcher.AddAccelerator(accelerator_3, std::move(matcher))); -} - -TEST_P(EventProcessorTest, EventMatching) { - TestEventProcessorDelegate* event_dispatcher_delegate = - test_event_dispatcher_delegate(); - EventProcessor* dispatcher = event_dispatcher(); - - mojom::EventMatcherPtr matcher = ui::CreateKeyMatcher( - ui::mojom::KeyboardCode::W, ui::mojom::kEventFlagControlDown); - uint32_t accelerator_1 = 1; - dispatcher->AddAccelerator(accelerator_1, std::move(matcher)); - - ui::KeyEvent key(ui::ET_KEY_PRESSED, ui::VKEY_W, ui::EF_CONTROL_DOWN); - DispatchEvent(dispatcher, key, EventProcessor::AcceleratorMatchPhase::ANY); - EXPECT_EQ(accelerator_1, - event_dispatcher_delegate->GetAndClearLastAccelerator()); - - // EF_NUM_LOCK_ON should be ignored since CreateKeyMatcher defaults to - // ignoring. - key = ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_W, - ui::EF_CONTROL_DOWN | ui::EF_NUM_LOCK_ON); - DispatchEvent(dispatcher, key, EventProcessor::AcceleratorMatchPhase::ANY); - EXPECT_EQ(accelerator_1, - event_dispatcher_delegate->GetAndClearLastAccelerator()); - - key = ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_W, ui::EF_NONE); - DispatchEvent(dispatcher, key, EventProcessor::AcceleratorMatchPhase::ANY); - EXPECT_EQ(0u, event_dispatcher_delegate->GetAndClearLastAccelerator()); - - uint32_t accelerator_2 = 2; - matcher = ui::CreateKeyMatcher(ui::mojom::KeyboardCode::W, - ui::mojom::kEventFlagNone); - dispatcher->AddAccelerator(accelerator_2, std::move(matcher)); - DispatchEvent(dispatcher, key, EventProcessor::AcceleratorMatchPhase::ANY); - EXPECT_EQ(accelerator_2, - event_dispatcher_delegate->GetAndClearLastAccelerator()); - - dispatcher->RemoveAccelerator(accelerator_2); - DispatchEvent(dispatcher, key, EventProcessor::AcceleratorMatchPhase::ANY); - EXPECT_EQ(0u, event_dispatcher_delegate->GetAndClearLastAccelerator()); -} - -// Tests that a post-target accelerator is not triggered by ProcessEvent. -TEST_P(EventProcessorTest, PostTargetAccelerator) { - TestEventProcessorDelegate* event_dispatcher_delegate = - test_event_dispatcher_delegate(); - EventProcessor* dispatcher = event_dispatcher(); - - mojom::EventMatcherPtr matcher = ui::CreateKeyMatcher( - ui::mojom::KeyboardCode::W, ui::mojom::kEventFlagControlDown); - matcher->accelerator_phase = ui::mojom::AcceleratorPhase::POST_TARGET; - uint32_t accelerator_1 = 1; - dispatcher->AddAccelerator(accelerator_1, std::move(matcher)); - - ui::KeyEvent key(ui::ET_KEY_PRESSED, ui::VKEY_W, ui::EF_CONTROL_DOWN); - // The post-target accelerator should be fired if there is no focused window. - DispatchEvent(dispatcher, key, EventProcessor::AcceleratorMatchPhase::ANY); - EXPECT_EQ(accelerator_1, - event_dispatcher_delegate->GetAndClearLastAccelerator()); - std::unique_ptr<DispatchedEventDetails> details = - event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails(); - EXPECT_FALSE(details); - - // Set focused window for EventProcessor dispatches key events. - std::unique_ptr<ServerWindow> child = - CreateChildWindow(viz::FrameSinkId(1, 3)); - event_dispatcher_delegate->SetFocusedWindowFromEventProcessor(child.get()); - - // With a focused window the event should be dispatched. - DispatchEvent(dispatcher, key, EventProcessor::AcceleratorMatchPhase::ANY); - EXPECT_EQ(0u, event_dispatcher_delegate->GetAndClearLastAccelerator()); - details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails(); - EXPECT_TRUE(details); - EXPECT_TRUE(details->accelerator); - - base::WeakPtr<Accelerator> accelerator_weak_ptr = - details->accelerator->GetWeakPtr(); - dispatcher->RemoveAccelerator(accelerator_1); - EXPECT_FALSE(accelerator_weak_ptr); - - // Post deletion there should be no accelerator - DispatchEvent(dispatcher, key, EventProcessor::AcceleratorMatchPhase::ANY); - EXPECT_EQ(0u, event_dispatcher_delegate->GetAndClearLastAccelerator()); - details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails(); - EXPECT_TRUE(details); - EXPECT_FALSE(details->accelerator); -} - -TEST_P(EventProcessorTest, ProcessPost) { - TestEventProcessorDelegate* event_dispatcher_delegate = - test_event_dispatcher_delegate(); - EventProcessor* dispatcher = event_dispatcher(); - - uint32_t pre_id = 1; - { - mojom::EventMatcherPtr matcher = ui::CreateKeyMatcher( - ui::mojom::KeyboardCode::W, ui::mojom::kEventFlagControlDown); - matcher->accelerator_phase = ui::mojom::AcceleratorPhase::PRE_TARGET; - dispatcher->AddAccelerator(pre_id, std::move(matcher)); - } - - uint32_t post_id = 2; - { - mojom::EventMatcherPtr matcher = ui::CreateKeyMatcher( - ui::mojom::KeyboardCode::W, ui::mojom::kEventFlagControlDown); - matcher->accelerator_phase = ui::mojom::AcceleratorPhase::POST_TARGET; - dispatcher->AddAccelerator(post_id, std::move(matcher)); - } - - // Set focused window for EventProcessor dispatches key events. - std::unique_ptr<ServerWindow> child = - CreateChildWindow(viz::FrameSinkId(1, 3)); - event_dispatcher_delegate->SetFocusedWindowFromEventProcessor(child.get()); - - // Dispatch for ANY, which should trigger PRE and not call - // DispatchInputEventToWindow(). - ui::KeyEvent key(ui::ET_KEY_PRESSED, ui::VKEY_W, ui::EF_CONTROL_DOWN); - DispatchEvent(dispatcher, key, EventProcessor::AcceleratorMatchPhase::ANY); - EXPECT_EQ(EventDispatcher::AcceleratorPhase::kPre, - event_dispatcher_delegate->last_accelerator_phase()); - EXPECT_EQ(pre_id, event_dispatcher_delegate->GetAndClearLastAccelerator()); - EXPECT_FALSE(event_dispatcher_delegate->has_queued_events()); - - // Dispatch for POST, which should trigger POST. - DispatchEvent(dispatcher, key, - EventProcessor::AcceleratorMatchPhase::POST_ONLY); - std::unique_ptr<DispatchedEventDetails> details = - event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails(); - ASSERT_TRUE(details); - ASSERT_TRUE(details->accelerator); - EXPECT_EQ(post_id, details->accelerator->id()); -} - -TEST_P(EventProcessorTest, Capture) { - ServerWindow* root = root_window(); - std::unique_ptr<ServerWindow> child = - CreateChildWindow(viz::FrameSinkId(1, 3)); - - root->SetBounds(gfx::Rect(0, 0, 100, 100)); - child->SetBounds(gfx::Rect(10, 10, 20, 20)); - - MouseEventTest tests[] = { - // Send a mouse down event over child. - {std::make_unique<ui::MouseEvent>( - ui::ET_MOUSE_PRESSED, gfx::Point(20, 25), gfx::Point(20, 25), - base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, - ui::EF_LEFT_MOUSE_BUTTON), - child.get(), gfx::Point(20, 25), gfx::Point(10, 15), nullptr, - gfx::Point(), gfx::Point()}, - - // Capture should be activated. Let's send a mouse move outside the bounds - // of the child. - {std::make_unique<ui::MouseEvent>(ui::ET_MOUSE_MOVED, gfx::Point(50, 50), - gfx::Point(50, 50), base::TimeTicks(), - ui::EF_LEFT_MOUSE_BUTTON, - ui::EF_LEFT_MOUSE_BUTTON), - child.get(), gfx::Point(50, 50), gfx::Point(40, 40), nullptr, - gfx::Point(), gfx::Point()}, - // Release the mouse and verify that the mouse up event goes to the child. - {std::make_unique<ui::MouseEvent>( - ui::ET_MOUSE_RELEASED, gfx::Point(50, 50), gfx::Point(50, 50), - base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, - ui::EF_LEFT_MOUSE_BUTTON), - child.get(), gfx::Point(50, 50), gfx::Point(40, 40), nullptr, - gfx::Point(), gfx::Point()}, - - // A mouse move at (50, 50) should now go to the root window. As the - // move crosses between |child| and |root| |child| gets an exit, and - // |root| the move. - {std::make_unique<ui::MouseEvent>(ui::ET_MOUSE_MOVED, gfx::Point(50, 50), - gfx::Point(50, 50), base::TimeTicks(), - ui::EF_LEFT_MOUSE_BUTTON, - ui::EF_LEFT_MOUSE_BUTTON), - child.get(), gfx::Point(50, 50), gfx::Point(40, 40), root, - gfx::Point(50, 50), gfx::Point(50, 50)}, - - }; - RunMouseEventTests(event_dispatcher(), test_event_dispatcher_delegate(), - tests, arraysize(tests)); -} - -TEST_P(EventProcessorTest, CaptureMultipleMouseButtons) { - std::unique_ptr<ServerWindow> child = - CreateChildWindow(viz::FrameSinkId(1, 3)); - - root_window()->SetBounds(gfx::Rect(0, 0, 100, 100)); - child->SetBounds(gfx::Rect(10, 10, 20, 20)); - - MouseEventTest tests[] = { - // Send a mouse down event over child with a left mouse button - {std::make_unique<ui::MouseEvent>( - ui::ET_MOUSE_PRESSED, gfx::Point(20, 25), gfx::Point(20, 25), - base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, - ui::EF_LEFT_MOUSE_BUTTON), - child.get(), gfx::Point(20, 25), gfx::Point(10, 15), nullptr, - gfx::Point(), gfx::Point()}, - - // Capture should be activated. Let's send a mouse move outside the bounds - // of the child and press the right mouse button too. - {std::make_unique<ui::MouseEvent>( - ui::ET_MOUSE_MOVED, gfx::Point(50, 50), gfx::Point(50, 50), - base::TimeTicks(), - ui::EF_LEFT_MOUSE_BUTTON | ui::EF_RIGHT_MOUSE_BUTTON, 0), - child.get(), gfx::Point(50, 50), gfx::Point(40, 40), nullptr, - gfx::Point(), gfx::Point()}, - - // Release the left mouse button and verify that the mouse up event goes - // to the child. - {std::make_unique<ui::MouseEvent>( - ui::ET_MOUSE_RELEASED, gfx::Point(50, 50), gfx::Point(50, 50), - base::TimeTicks(), - ui::EF_LEFT_MOUSE_BUTTON | ui::EF_RIGHT_MOUSE_BUTTON, - ui::EF_RIGHT_MOUSE_BUTTON), - child.get(), gfx::Point(50, 50), gfx::Point(40, 40), nullptr, - gfx::Point(), gfx::Point()}, - - // A mouse move at (50, 50) should still go to the child. - {std::make_unique<ui::MouseEvent>(ui::ET_MOUSE_MOVED, gfx::Point(50, 50), - gfx::Point(50, 50), base::TimeTicks(), - ui::EF_LEFT_MOUSE_BUTTON, 0), - child.get(), gfx::Point(50, 50), gfx::Point(40, 40), nullptr, - gfx::Point(), gfx::Point()}, - - }; - RunMouseEventTests(event_dispatcher(), test_event_dispatcher_delegate(), - tests, arraysize(tests)); -} - -TEST_P(EventProcessorTest, ClientAreaGoesToOwner) { - std::unique_ptr<ServerWindow> child = - CreateChildWindow(viz::FrameSinkId(1, 3)); - - root_window()->SetBounds(gfx::Rect(0, 0, 100, 100)); - child->SetBounds(gfx::Rect(10, 10, 20, 20)); - - child->SetClientArea(gfx::Insets(5, 5, 5, 5), std::vector<gfx::Rect>()); - - TestEventProcessorDelegate* event_dispatcher_delegate = - test_event_dispatcher_delegate(); - EventProcessor* dispatcher = event_dispatcher(); - - // Start move loop by sending mouse event over non-client area. - const ui::PointerEvent press_event(ui::MouseEvent( - ui::ET_MOUSE_PRESSED, gfx::Point(12, 12), gfx::Point(12, 12), - base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON)); - DispatchEvent(dispatcher, press_event, - EventProcessor::AcceleratorMatchPhase::ANY); - - // Events should target child and be in the non-client area. - std::unique_ptr<DispatchedEventDetails> details = - event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails(); - EXPECT_FALSE(event_dispatcher_delegate->has_queued_events()); - ASSERT_TRUE(details); - ASSERT_EQ(child.get(), details->window); - EXPECT_TRUE(details->IsNonclientArea()); - - // Move the mouse 5,6 pixels and target is the same. - const ui::PointerEvent move_event( - ui::MouseEvent(ui::ET_MOUSE_MOVED, gfx::Point(17, 18), gfx::Point(17, 18), - base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, 0)); - DispatchEvent(dispatcher, move_event, - EventProcessor::AcceleratorMatchPhase::ANY); - - // Still same target. - details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails(); - EXPECT_FALSE(event_dispatcher_delegate->has_queued_events()); - ASSERT_EQ(child.get(), details->window); - EXPECT_TRUE(details->IsNonclientArea()); - - // Release the mouse. - const ui::PointerEvent release_event(ui::MouseEvent( - ui::ET_MOUSE_RELEASED, gfx::Point(17, 18), gfx::Point(17, 18), - base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON)); - DispatchEvent(dispatcher, release_event, - EventProcessor::AcceleratorMatchPhase::ANY); - - // The event should not have been dispatched to the delegate. - details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails(); - EXPECT_FALSE(event_dispatcher_delegate->has_queued_events()); - ASSERT_EQ(child.get(), details->window); - EXPECT_TRUE(details->IsNonclientArea()); - - // Press in the client area and verify target/client area. The non-client area - // should get an exit first. - const ui::PointerEvent press_event2(ui::MouseEvent( - ui::ET_MOUSE_PRESSED, gfx::Point(21, 22), gfx::Point(21, 22), - base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON)); - DispatchEvent(dispatcher, press_event2, - EventProcessor::AcceleratorMatchPhase::ANY); - details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails(); - EXPECT_TRUE(event_dispatcher_delegate->has_queued_events()); - ASSERT_EQ(child.get(), details->window); - EXPECT_TRUE(details->IsNonclientArea()); - EXPECT_EQ(ui::ET_POINTER_EXITED, details->event->type()); - - details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails(); - EXPECT_FALSE(event_dispatcher_delegate->has_queued_events()); - ASSERT_EQ(child.get(), details->window); - EXPECT_TRUE(details->IsClientArea()); - EXPECT_EQ(ui::ET_POINTER_DOWN, details->event->type()); -} - -TEST_P(EventProcessorTest, AdditionalClientArea) { - std::unique_ptr<ServerWindow> child = - CreateChildWindow(viz::FrameSinkId(1, 3)); - - root_window()->SetBounds(gfx::Rect(0, 0, 100, 100)); - child->SetBounds(gfx::Rect(10, 10, 20, 20)); - - std::vector<gfx::Rect> additional_client_areas; - additional_client_areas.push_back(gfx::Rect(18, 0, 2, 2)); - child->SetClientArea(gfx::Insets(5, 5, 5, 5), additional_client_areas); - - TestEventProcessorDelegate* event_dispatcher_delegate = - test_event_dispatcher_delegate(); - // Press in the additional client area, it should go to the child. - const ui::PointerEvent press_event(ui::MouseEvent( - ui::ET_MOUSE_PRESSED, gfx::Point(28, 11), gfx::Point(28, 11), - base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON)); - DispatchEvent(event_dispatcher(), press_event, - EventProcessor::AcceleratorMatchPhase::ANY); - - // Events should target child and be in the client area. - std::unique_ptr<DispatchedEventDetails> details = - event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails(); - EXPECT_FALSE(event_dispatcher_delegate->has_queued_events()); - ASSERT_EQ(child.get(), details->window); - EXPECT_TRUE(details->IsClientArea()); -} - -TEST_P(EventProcessorTest, HitTestMask) { - std::unique_ptr<ServerWindow> child = - CreateChildWindow(viz::FrameSinkId(1, 3)); - - root_window()->SetBounds(gfx::Rect(0, 0, 100, 100)); - child->SetBounds(gfx::Rect(10, 10, 20, 20)); - child->SetHitTestMask(gfx::Rect(2, 2, 16, 16)); - - // Move in the masked area. - const ui::PointerEvent move1( - ui::MouseEvent(ui::ET_MOUSE_MOVED, gfx::Point(11, 11), gfx::Point(11, 11), - base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, 0)); - DispatchEvent(event_dispatcher(), move1, - EventProcessor::AcceleratorMatchPhase::ANY); - - // Event went through the child window and hit the root. - std::unique_ptr<DispatchedEventDetails> details1 = - test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails(); - EXPECT_EQ(root_window(), details1->window); - EXPECT_TRUE(details1->IsClientArea()); - - child->ClearHitTestMask(); - - // Move right in the same part of the window. - const ui::PointerEvent move2( - ui::MouseEvent(ui::ET_MOUSE_MOVED, gfx::Point(11, 12), gfx::Point(11, 12), - base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, 0)); - DispatchEvent(event_dispatcher(), move2, - EventProcessor::AcceleratorMatchPhase::ANY); - - // Mouse exits the root. - std::unique_ptr<DispatchedEventDetails> details2 = - test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails(); - EXPECT_EQ(ui::ET_POINTER_EXITED, details2->event->type()); - - // Mouse hits the child. - std::unique_ptr<DispatchedEventDetails> details3 = - test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails(); - EXPECT_EQ(child.get(), details3->window); - EXPECT_TRUE(details3->IsClientArea()); -} - -TEST_P(EventProcessorTest, DontFocusOnSecondDown) { - std::unique_ptr<ServerWindow> child = - CreateChildWindow(viz::FrameSinkId(1, 3)); - - root_window()->SetBounds(gfx::Rect(0, 0, 100, 100)); - child->SetBounds(gfx::Rect(10, 10, 20, 20)); - - TestEventProcessorDelegate* event_dispatcher_delegate = - test_event_dispatcher_delegate(); - EventProcessor* dispatcher = event_dispatcher(); - - // Press on |child|. Press should not change focus. - const ui::PointerEvent press_event(ui::MouseEvent( - ui::ET_MOUSE_PRESSED, gfx::Point(12, 12), gfx::Point(12, 12), - base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON)); - DispatchEvent(dispatcher, press_event, - EventProcessor::AcceleratorMatchPhase::ANY); - std::unique_ptr<DispatchedEventDetails> details = - event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails(); - EXPECT_FALSE(event_dispatcher_delegate->has_queued_events()); - EXPECT_EQ(child.get(), details->window); - EXPECT_EQ(nullptr, event_dispatcher_delegate->GetAndClearLastFocusedWindow()); -} - -TEST_P(EventProcessorTest, TwoPointersActive) { - std::unique_ptr<ServerWindow> child1 = - CreateChildWindow(viz::FrameSinkId(1, 3)); - std::unique_ptr<ServerWindow> child2 = - CreateChildWindow(viz::FrameSinkId(1, 4)); - - root_window()->SetBounds(gfx::Rect(0, 0, 100, 100)); - child1->SetBounds(gfx::Rect(10, 10, 20, 20)); - child2->SetBounds(gfx::Rect(50, 51, 11, 12)); - - TestEventProcessorDelegate* event_dispatcher_delegate = - test_event_dispatcher_delegate(); - EventProcessor* dispatcher = event_dispatcher(); - - // Press on child1. - const ui::PointerEvent touch_event1(ui::TouchEvent( - ui::ET_TOUCH_PRESSED, gfx::Point(12, 13), base::TimeTicks(), - ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 1))); - DispatchEvent(dispatcher, touch_event1, - EventProcessor::AcceleratorMatchPhase::ANY); - std::unique_ptr<DispatchedEventDetails> details = - event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails(); - EXPECT_EQ(child1.get(), details->window); - - // Drag over child2, child1 should get the drag. - const ui::PointerEvent drag_event1(ui::TouchEvent( - ui::ET_TOUCH_MOVED, gfx::Point(53, 54), base::TimeTicks(), - ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 1))); - DispatchEvent(dispatcher, drag_event1, - EventProcessor::AcceleratorMatchPhase::ANY); - details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails(); - EXPECT_EQ(child1.get(), details->window); - - // Press on child2 with a different touch id. - const ui::PointerEvent touch_event2(ui::TouchEvent( - ui::ET_TOUCH_PRESSED, gfx::Point(54, 55), base::TimeTicks(), - ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 2))); - DispatchEvent(dispatcher, touch_event2, - EventProcessor::AcceleratorMatchPhase::ANY); - details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails(); - EXPECT_EQ(child2.get(), details->window); - - // Drag over child1 with id 2, child2 should continue to get the drag. - const ui::PointerEvent drag_event2(ui::TouchEvent( - ui::ET_TOUCH_MOVED, gfx::Point(13, 14), base::TimeTicks(), - ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 2))); - DispatchEvent(dispatcher, drag_event2, - EventProcessor::AcceleratorMatchPhase::ANY); - details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails(); - EXPECT_EQ(child2.get(), details->window); - - // Drag again with id 1, child1 should continue to get it. - DispatchEvent(dispatcher, drag_event1, - EventProcessor::AcceleratorMatchPhase::ANY); - details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails(); - EXPECT_EQ(child1.get(), details->window); - - // Release touch id 1, and click on 2. 2 should get it. - const ui::PointerEvent touch_release(ui::TouchEvent( - ui::ET_TOUCH_RELEASED, gfx::Point(54, 55), base::TimeTicks(), - ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 1))); - DispatchEvent(dispatcher, touch_release, - EventProcessor::AcceleratorMatchPhase::ANY); - details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails(); - EXPECT_EQ(child1.get(), details->window); - const ui::PointerEvent touch_event3(ui::TouchEvent( - ui::ET_TOUCH_PRESSED, gfx::Point(54, 55), base::TimeTicks(), - ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 2))); - DispatchEvent(dispatcher, touch_event3, - EventProcessor::AcceleratorMatchPhase::ANY); - details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails(); - EXPECT_EQ(child2.get(), details->window); -} - -TEST_P(EventProcessorTest, DestroyWindowWhileGettingEvents) { - std::unique_ptr<ServerWindow> child = - CreateChildWindow(viz::FrameSinkId(1, 3)); - - root_window()->SetBounds(gfx::Rect(0, 0, 100, 100)); - child->SetBounds(gfx::Rect(10, 10, 20, 20)); - - TestEventProcessorDelegate* event_dispatcher_delegate = - test_event_dispatcher_delegate(); - EventProcessor* dispatcher = event_dispatcher(); - - // Press on child. - const ui::PointerEvent touch_event1(ui::TouchEvent( - ui::ET_TOUCH_PRESSED, gfx::Point(12, 13), base::TimeTicks(), - ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 1))); - DispatchEvent(dispatcher, touch_event1, - EventProcessor::AcceleratorMatchPhase::ANY); - std::unique_ptr<DispatchedEventDetails> details = - event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails(); - EXPECT_FALSE(event_dispatcher_delegate->has_queued_events()); - EXPECT_EQ(child.get(), details->window); - - // Delete child, and continue the drag. Event should not be dispatched. - child.reset(); - - const ui::PointerEvent drag_event1(ui::TouchEvent( - ui::ET_TOUCH_MOVED, gfx::Point(53, 54), base::TimeTicks(), - ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 1))); - DispatchEvent(dispatcher, drag_event1, - EventProcessor::AcceleratorMatchPhase::ANY); - details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails(); - EXPECT_EQ(nullptr, details.get()); -} - -TEST_P(EventProcessorTest, MouseInExtendedHitTestRegion) { - ServerWindow* root = root_window(); - std::unique_ptr<ServerWindow> child = - CreateChildWindow(viz::FrameSinkId(1, 3)); - - root->SetBounds(gfx::Rect(0, 0, 100, 100)); - child->SetBounds(gfx::Rect(10, 10, 20, 20)); - - TestEventProcessorDelegate* event_dispatcher_delegate = - test_event_dispatcher_delegate(); - EventProcessor* dispatcher = event_dispatcher(); - - // Send event that is not over child. - const ui::PointerEvent ui_event(ui::MouseEvent( - ui::ET_MOUSE_PRESSED, gfx::Point(8, 9), gfx::Point(8, 9), - base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON)); - DispatchEvent(dispatcher, ui_event, - EventProcessor::AcceleratorMatchPhase::ANY); - std::unique_ptr<DispatchedEventDetails> details = - event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails(); - ASSERT_EQ(root, details->window); - - // Release the mouse. - const ui::PointerEvent release_event(ui::MouseEvent( - ui::ET_MOUSE_RELEASED, gfx::Point(8, 9), gfx::Point(8, 9), - base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON)); - DispatchEvent(dispatcher, release_event, - EventProcessor::AcceleratorMatchPhase::ANY); - details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails(); - EXPECT_FALSE(event_dispatcher_delegate->has_queued_events()); - ASSERT_EQ(root, details->window); - EXPECT_TRUE(details->IsClientArea()); - - // Change the extended hit test region and send event in extended hit test - // region. Should result in exit for root, followed by press for child. - root->set_extended_hit_test_regions_for_children(gfx::Insets(-5, -5, -5, -5), - gfx::Insets(-5, -5, -5, -5)); - DispatchEvent(dispatcher, ui_event, - EventProcessor::AcceleratorMatchPhase::ANY); - details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails(); - EXPECT_EQ(root, details->window); - EXPECT_EQ(ui::ET_POINTER_EXITED, details->event->type()); - details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails(); - ASSERT_TRUE(details); - - EXPECT_FALSE(event_dispatcher_delegate->has_queued_events()); - EXPECT_TRUE(details->IsNonclientArea()); - ASSERT_EQ(child.get(), details->window); - EXPECT_EQ(ui::ET_POINTER_DOWN, details->event->type()); - ASSERT_TRUE(details->event.get()); - ASSERT_TRUE(details->event->IsPointerEvent()); - EXPECT_EQ(gfx::Point(-2, -1), details->event->AsPointerEvent()->location()); -} - -TEST_P(EventProcessorTest, WheelWhileDown) { - std::unique_ptr<ServerWindow> child1 = - CreateChildWindow(viz::FrameSinkId(1, 3)); - std::unique_ptr<ServerWindow> child2 = - CreateChildWindow(viz::FrameSinkId(1, 4)); - - root_window()->SetBounds(gfx::Rect(0, 0, 100, 100)); - child1->SetBounds(gfx::Rect(10, 10, 20, 20)); - child2->SetBounds(gfx::Rect(50, 51, 11, 12)); - - MouseEventTest tests[] = { - // Send a mouse down event over child1. - {std::make_unique<ui::MouseEvent>( - ui::ET_MOUSE_PRESSED, gfx::Point(15, 15), gfx::Point(15, 15), - base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, - ui::EF_LEFT_MOUSE_BUTTON), - child1.get(), gfx::Point(15, 15), gfx::Point(5, 5), nullptr, - gfx::Point(), gfx::Point()}, - // Send mouse wheel over child2, should go to child1 as it has capture. - {std::make_unique<ui::MouseWheelEvent>( - gfx::Vector2d(1, 0), gfx::Point(53, 54), gfx::Point(53, 54), - base::TimeTicks(), ui::EF_NONE, ui::EF_NONE), - child1.get(), gfx::Point(53, 54), gfx::Point(43, 44), nullptr, - gfx::Point(), gfx::Point()}, - }; - RunMouseEventTests(event_dispatcher(), test_event_dispatcher_delegate(), - tests, arraysize(tests)); -} - -// Tests that when explicit capture has been set that all events go to the -// designated window, and that when capture is cleared, events find the -// appropriate target window. -TEST_P(EventProcessorTest, SetExplicitCapture) { - ServerWindow* root = root_window(); - std::unique_ptr<ServerWindow> child = - CreateChildWindow(viz::FrameSinkId(1, 3)); - - root->SetBounds(gfx::Rect(0, 0, 100, 100)); - child->SetBounds(gfx::Rect(10, 10, 20, 20)); - - TestEventProcessorDelegate* event_dispatcher_delegate = - test_event_dispatcher_delegate(); - EventProcessor* dispatcher = event_dispatcher(); - - { - // Send all pointer events to the child. - dispatcher->SetCaptureWindow(child.get(), kClientAreaId); - - // The mouse press should go to the child even though its outside its - // bounds. - const ui::PointerEvent left_press_event(ui::MouseEvent( - ui::ET_MOUSE_PRESSED, gfx::Point(5, 5), gfx::Point(5, 5), - base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON)); - DispatchEvent(dispatcher, left_press_event, - EventProcessor::AcceleratorMatchPhase::ANY); - - // Events should target child. - std::unique_ptr<DispatchedEventDetails> details = - event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails(); - - ASSERT_TRUE(details); - ASSERT_EQ(child.get(), details->window); - EXPECT_TRUE(details->IsClientArea()); - EXPECT_TRUE(IsMouseButtonDown()); - - // The mouse down state should update while capture is set. - const ui::PointerEvent right_press_event(ui::MouseEvent( - ui::ET_MOUSE_PRESSED, gfx::Point(5, 5), gfx::Point(5, 5), - base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON | ui::EF_RIGHT_MOUSE_BUTTON, - ui::EF_RIGHT_MOUSE_BUTTON)); - DispatchEvent(dispatcher, right_press_event, - EventProcessor::AcceleratorMatchPhase::ANY); - details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails(); - EXPECT_TRUE(IsMouseButtonDown()); - - // One button released should not clear mouse down - const ui::PointerEvent left_release_event(ui::MouseEvent( - ui::ET_MOUSE_RELEASED, gfx::Point(5, 5), gfx::Point(5, 5), - base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON | ui::EF_RIGHT_MOUSE_BUTTON, - ui::EF_LEFT_MOUSE_BUTTON)); - DispatchEvent(dispatcher, left_release_event, - EventProcessor::AcceleratorMatchPhase::ANY); - details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails(); - EXPECT_TRUE(IsMouseButtonDown()); - - // Touch Event while mouse is down should not affect state. - const ui::PointerEvent touch_event(ui::TouchEvent( - ui::ET_TOUCH_PRESSED, gfx::Point(15, 15), base::TimeTicks(), - ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 2))); - DispatchEvent(dispatcher, touch_event, - EventProcessor::AcceleratorMatchPhase::ANY); - details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails(); - EXPECT_TRUE(IsMouseButtonDown()); - - // Move event should not affect down - const ui::PointerEvent move_event( - ui::MouseEvent(ui::ET_MOUSE_MOVED, gfx::Point(15, 5), gfx::Point(15, 5), - base::TimeTicks(), ui::EF_RIGHT_MOUSE_BUTTON, - ui::EF_RIGHT_MOUSE_BUTTON)); - DispatchEvent(dispatcher, move_event, - EventProcessor::AcceleratorMatchPhase::ANY); - details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails(); - EXPECT_TRUE(IsMouseButtonDown()); - - // All mouse buttons up should clear mouse down. - const ui::PointerEvent right_release_event( - ui::MouseEvent(ui::ET_MOUSE_RELEASED, gfx::Point(5, 5), - gfx::Point(5, 5), base::TimeTicks(), - ui::EF_RIGHT_MOUSE_BUTTON, ui::EF_RIGHT_MOUSE_BUTTON)); - DispatchEvent(dispatcher, right_release_event, - EventProcessor::AcceleratorMatchPhase::ANY); - details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails(); - EXPECT_FALSE(IsMouseButtonDown()); - } - - { - // Releasing capture and sending the same event will go to the root. - dispatcher->SetCaptureWindow(nullptr, kClientAreaId); - const ui::PointerEvent press_event(ui::MouseEvent( - ui::ET_MOUSE_PRESSED, gfx::Point(5, 5), gfx::Point(5, 5), - base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON)); - DispatchEvent(dispatcher, press_event, - EventProcessor::AcceleratorMatchPhase::ANY); - - // Events should target the root. - std::unique_ptr<DispatchedEventDetails> details = - event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails(); - - ASSERT_TRUE(details); - ASSERT_EQ(root, details->window); - } -} - -// This test verifies that explicit capture overrides and resets implicit -// capture. -TEST_P(EventProcessorTest, ExplicitCaptureOverridesImplicitCapture) { - ServerWindow* root = root_window(); - std::unique_ptr<ServerWindow> child = - CreateChildWindow(viz::FrameSinkId(1, 3)); - - root->SetBounds(gfx::Rect(0, 0, 100, 100)); - child->SetBounds(gfx::Rect(10, 10, 20, 20)); - - TestEventProcessorDelegate* event_dispatcher_delegate = - test_event_dispatcher_delegate(); - EventProcessor* dispatcher = event_dispatcher(); - - // Run some implicit capture tests. - MouseEventTest tests[] = { - // Send a mouse down event over child with a left mouse button - {std::make_unique<ui::MouseEvent>( - ui::ET_MOUSE_PRESSED, gfx::Point(20, 25), gfx::Point(20, 25), - base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, - ui::EF_LEFT_MOUSE_BUTTON), - child.get(), gfx::Point(20, 25), gfx::Point(10, 15)}, - // Capture should be activated. Let's send a mouse move outside the bounds - // of the child and press the right mouse button too. - {std::make_unique<ui::MouseEvent>( - ui::ET_MOUSE_MOVED, gfx::Point(50, 50), gfx::Point(50, 50), - base::TimeTicks(), - ui::EF_LEFT_MOUSE_BUTTON | ui::EF_RIGHT_MOUSE_BUTTON, 0), - child.get(), gfx::Point(50, 50), gfx::Point(40, 40)}, - // Release the left mouse button and verify that the mouse up event goes - // to the child. - {std::make_unique<ui::MouseEvent>( - ui::ET_MOUSE_RELEASED, gfx::Point(50, 50), gfx::Point(50, 50), - base::TimeTicks(), - ui::EF_LEFT_MOUSE_BUTTON | ui::EF_RIGHT_MOUSE_BUTTON, - ui::EF_RIGHT_MOUSE_BUTTON), - child.get(), gfx::Point(50, 50), gfx::Point(40, 40)}, - // A mouse move at (50, 50) should still go to the child. - {std::make_unique<ui::MouseEvent>(ui::ET_MOUSE_MOVED, gfx::Point(50, 50), - gfx::Point(50, 50), base::TimeTicks(), - ui::EF_LEFT_MOUSE_BUTTON, 0), - child.get(), gfx::Point(50, 50), gfx::Point(40, 40)}, - - }; - RunMouseEventTests(dispatcher, event_dispatcher_delegate, tests, - arraysize(tests)); - - // Add a second pointer target to the child. - { - const ui::PointerEvent touch_event(ui::TouchEvent( - ui::ET_TOUCH_PRESSED, gfx::Point(12, 13), base::TimeTicks(), - ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 1))); - DispatchEvent(dispatcher, touch_event, - EventProcessor::AcceleratorMatchPhase::ANY); - } - - std::unique_ptr<DispatchedEventDetails> details = - event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails(); - EXPECT_FALSE(event_dispatcher_delegate->has_queued_events()); - EXPECT_EQ(child.get(), details->window); - - // Verify that no window has explicit capture and hence we did indeed do - // implicit capture. - ASSERT_EQ(nullptr, dispatcher->capture_window()); - - // Give the root window explicit capture and verify input events over the - // child go to the root instead. - dispatcher->SetCaptureWindow(root, kNonclientAreaId); - - // The implicit target should receive a cancel event for each pointer target. - details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails(); - ASSERT_TRUE(details); - EXPECT_TRUE(event_dispatcher_delegate->has_queued_events()); - EXPECT_EQ(child.get(), details->window); - EXPECT_EQ(ui::ET_POINTER_CANCELLED, details->event->type()); - - details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails(); - ASSERT_TRUE(details); - EXPECT_FALSE(event_dispatcher_delegate->has_queued_events()); - EXPECT_EQ(child.get(), details->window); - EXPECT_EQ(ui::ET_POINTER_EXITED, details->event->type()); - - const ui::PointerEvent press_event(ui::MouseEvent( - ui::ET_MOUSE_PRESSED, gfx::Point(15, 15), gfx::Point(15, 15), - base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON)); - DispatchEvent(dispatcher, press_event, - EventProcessor::AcceleratorMatchPhase::ANY); - - // Events should target the root. - details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails(); - ASSERT_TRUE(details); - ASSERT_EQ(root, details->window); - ASSERT_TRUE(details->IsNonclientArea()); -} - -// Tests that setting capture does delete active pointer targets for the capture -// window. -TEST_P(EventProcessorTest, CaptureUpdatesActivePointerTargets) { - ServerWindow* root = root_window(); - root->SetBounds(gfx::Rect(0, 0, 100, 100)); - - EventProcessor* dispatcher = event_dispatcher(); - { - const ui::PointerEvent press_event(ui::MouseEvent( - ui::ET_MOUSE_PRESSED, gfx::Point(5, 5), gfx::Point(5, 5), - base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON)); - DispatchEvent(dispatcher, press_event, - EventProcessor::AcceleratorMatchPhase::ANY); - - std::unique_ptr<DispatchedEventDetails> details = - test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails(); - ASSERT_TRUE(details); - ASSERT_EQ(root, details->window); - } - { - const ui::PointerEvent touch_event(ui::TouchEvent( - ui::ET_TOUCH_PRESSED, gfx::Point(12, 13), base::TimeTicks(), - ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 1))); - DispatchEvent(dispatcher, touch_event, - EventProcessor::AcceleratorMatchPhase::ANY); - } - - ASSERT_TRUE(AreAnyPointersDown()); - ASSERT_TRUE(IsWindowPointerTarget(root)); - EXPECT_EQ(2, NumberPointerTargetsForWindow(root)); - - // Setting the capture should clear the implicit pointers for the specified - // window. - dispatcher->SetCaptureWindow(root, kNonclientAreaId); - EXPECT_FALSE(AreAnyPointersDown()); - EXPECT_FALSE(IsWindowPointerTarget(root)); -} - -// Tests that when explicit capture is changed, that the previous window with -// capture is no longer being observed. -TEST_P(EventProcessorTest, UpdatingCaptureStopsObservingPreviousCapture) { - std::unique_ptr<ServerWindow> child1 = - CreateChildWindow(viz::FrameSinkId(1, 3)); - std::unique_ptr<ServerWindow> child2 = - CreateChildWindow(viz::FrameSinkId(1, 4)); - - root_window()->SetBounds(gfx::Rect(0, 0, 100, 100)); - child1->SetBounds(gfx::Rect(10, 10, 20, 20)); - child2->SetBounds(gfx::Rect(50, 51, 11, 12)); - - EventProcessor* dispatcher = event_dispatcher(); - ASSERT_FALSE(AreAnyPointersDown()); - ASSERT_FALSE(IsWindowPointerTarget(child1.get())); - ASSERT_FALSE(IsWindowPointerTarget(child2.get())); - dispatcher->SetCaptureWindow(child1.get(), kClientAreaId); - dispatcher->SetCaptureWindow(child2.get(), kClientAreaId); - EXPECT_EQ(child1.get(), - test_event_dispatcher_delegate()->lost_capture_window()); - - EXPECT_FALSE( - EventProcessorTestApi(dispatcher).IsObservingWindow(child1.get())); -} - -// Tests that destroying a window with explicit capture clears the capture -// state. -TEST_P(EventProcessorTest, DestroyingCaptureWindowRemovesExplicitCapture) { - std::unique_ptr<ServerWindow> child = - CreateChildWindow(viz::FrameSinkId(1, 3)); - child->SetBounds(gfx::Rect(10, 10, 20, 20)); - - EventProcessor* dispatcher = event_dispatcher(); - dispatcher->SetCaptureWindow(child.get(), kClientAreaId); - EXPECT_EQ(child.get(), dispatcher->capture_window()); - - ServerWindow* lost_capture_window = child.get(); - child.reset(); - EXPECT_EQ(nullptr, dispatcher->capture_window()); - EXPECT_EQ(lost_capture_window, - test_event_dispatcher_delegate()->lost_capture_window()); -} - -// Tests that when |client_id| is set for a window performing capture, that this -// preference is used regardless of whether an event targets the client region. -TEST_P(EventProcessorTest, CaptureInNonClientAreaOverridesActualPoint) { - ServerWindow* root = root_window(); - root->SetBounds(gfx::Rect(0, 0, 100, 100)); - - root->SetClientArea(gfx::Insets(5, 5, 5, 5), std::vector<gfx::Rect>()); - EventProcessor* dispatcher = event_dispatcher(); - dispatcher->SetCaptureWindow(root, kNonclientAreaId); - - TestEventProcessorDelegate* event_dispatcher_delegate = - test_event_dispatcher_delegate(); - // Press in the client area, it should be marked as non client. - const ui::PointerEvent press_event(ui::MouseEvent( - ui::ET_MOUSE_PRESSED, gfx::Point(6, 6), gfx::Point(6, 6), - base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON)); - DispatchEvent(event_dispatcher(), press_event, - EventProcessor::AcceleratorMatchPhase::ANY); - - // Events should target child and be in the client area. - std::unique_ptr<DispatchedEventDetails> details = - event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails(); - EXPECT_FALSE(event_dispatcher_delegate->has_queued_events()); - ASSERT_EQ(root, details->window); - EXPECT_TRUE(details->IsNonclientArea()); -} - -TEST_P(EventProcessorTest, ProcessPointerEvents) { - std::unique_ptr<ServerWindow> child = - CreateChildWindow(viz::FrameSinkId(1, 3)); - - root_window()->SetBounds(gfx::Rect(0, 0, 100, 100)); - child->SetBounds(gfx::Rect(10, 10, 20, 20)); - - { - const ui::PointerEvent pointer_event(ui::MouseEvent( - ui::ET_MOUSE_PRESSED, gfx::Point(20, 25), gfx::Point(20, 25), - base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON)); - DispatchEvent(event_dispatcher(), pointer_event, - EventProcessor::AcceleratorMatchPhase::ANY); - - std::unique_ptr<DispatchedEventDetails> details = - test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails(); - ASSERT_TRUE(details); - ASSERT_EQ(child.get(), details->window); - - ASSERT_TRUE(details->event); - ASSERT_TRUE(details->event->IsPointerEvent()); - - ui::PointerEvent* dispatched_event = details->event->AsPointerEvent(); - EXPECT_EQ(gfx::Point(20, 25), dispatched_event->root_location()); - EXPECT_EQ(gfx::Point(10, 15), dispatched_event->location()); - } - - { - const int touch_id = 3; - const ui::PointerEvent pointer_event(ui::TouchEvent( - ui::ET_TOUCH_RELEASED, gfx::Point(25, 20), base::TimeTicks(), - ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, - touch_id))); - DispatchEvent(event_dispatcher(), pointer_event, - EventProcessor::AcceleratorMatchPhase::ANY); - - std::unique_ptr<DispatchedEventDetails> details = - test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails(); - ASSERT_TRUE(details); - ASSERT_EQ(child.get(), details->window); - - ASSERT_TRUE(details->event); - ASSERT_TRUE(details->event->IsPointerEvent()); - - ui::PointerEvent* dispatched_event = details->event->AsPointerEvent(); - EXPECT_EQ(gfx::Point(25, 20), dispatched_event->root_location()); - EXPECT_EQ(gfx::Point(15, 10), dispatched_event->location()); - EXPECT_EQ(touch_id, dispatched_event->pointer_details().id); - } -} - -TEST_P(EventProcessorTest, ResetClearsPointerDown) { - std::unique_ptr<ServerWindow> child = - CreateChildWindow(viz::FrameSinkId(1, 3)); - - root_window()->SetBounds(gfx::Rect(0, 0, 100, 100)); - child->SetBounds(gfx::Rect(10, 10, 20, 20)); - - // Send event that is over child. - const ui::PointerEvent ui_event(ui::MouseEvent( - ui::ET_MOUSE_PRESSED, gfx::Point(20, 25), gfx::Point(20, 25), - base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON)); - DispatchEvent(event_dispatcher(), ui_event, - EventProcessor::AcceleratorMatchPhase::ANY); - - std::unique_ptr<DispatchedEventDetails> details = - test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails(); - ASSERT_TRUE(details); - ASSERT_EQ(child.get(), details->window); - - EXPECT_TRUE(AreAnyPointersDown()); - - event_dispatcher()->Reset(); - EXPECT_FALSE(test_event_dispatcher_delegate()->has_queued_events()); - EXPECT_FALSE(AreAnyPointersDown()); -} - -TEST_P(EventProcessorTest, ResetClearsCapture) { - ServerWindow* root = root_window(); - root->SetBounds(gfx::Rect(0, 0, 100, 100)); - - root->SetClientArea(gfx::Insets(5, 5, 5, 5), std::vector<gfx::Rect>()); - EventProcessor* dispatcher = event_dispatcher(); - dispatcher->SetCaptureWindow(root, kNonclientAreaId); - - event_dispatcher()->Reset(); - EXPECT_FALSE(test_event_dispatcher_delegate()->has_queued_events()); - EXPECT_EQ(nullptr, event_dispatcher()->capture_window()); -} - -// Tests that events on a parent of a modal window are blocked. -TEST_P(EventProcessorTest, ModalWindowEventOnModalParent) { - std::unique_ptr<ServerWindow> w1 = CreateChildWindow(viz::FrameSinkId(1, 3)); - std::unique_ptr<ServerWindow> w2 = CreateChildWindow(viz::FrameSinkId(1, 5)); - - root_window()->SetBounds(gfx::Rect(0, 0, 100, 100)); - w1->SetBounds(gfx::Rect(10, 10, 30, 30)); - w2->SetBounds(gfx::Rect(50, 10, 10, 10)); - - w1->AddTransientWindow(w2.get()); - w2->SetModalType(MODAL_TYPE_WINDOW); - - // Send event that is over |w1|. - const ui::PointerEvent mouse_pressed(ui::MouseEvent( - ui::ET_MOUSE_PRESSED, gfx::Point(15, 15), gfx::Point(15, 15), - base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON)); - DispatchEvent(event_dispatcher(), mouse_pressed, - EventProcessor::AcceleratorMatchPhase::ANY); - // As |w2| is modal and the event is over |w1|, no events should be queued, - // and the delegate should be informed of this. - ASSERT_FALSE(test_event_dispatcher_delegate()->has_queued_events()); - EXPECT_EQ(w2.get(), - test_event_dispatcher_delegate()->window_that_blocked_event()); - test_event_dispatcher_delegate()->ClearWindowThatBlockedEvent(); - - const ui::PointerEvent mouse_released(ui::MouseEvent( - ui::ET_MOUSE_RELEASED, gfx::Point(15, 15), gfx::Point(15, 15), - base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON)); - DispatchEvent(event_dispatcher(), mouse_released, - EventProcessor::AcceleratorMatchPhase::ANY); - ASSERT_FALSE(test_event_dispatcher_delegate()->has_queued_events()); - EXPECT_FALSE(test_event_dispatcher_delegate()->window_that_blocked_event()); - - // Send event over |w2|. - const ui::PointerEvent mouse_pressed2(ui::MouseEvent( - ui::ET_MOUSE_PRESSED, gfx::Point(55, 15), gfx::Point(55, 15), - base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON)); - DispatchEvent(event_dispatcher(), mouse_pressed2, - EventProcessor::AcceleratorMatchPhase::ANY); - std::unique_ptr<DispatchedEventDetails> details = - test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails(); - ASSERT_TRUE(details); - EXPECT_EQ(w2.get(), details->window); - - ASSERT_TRUE(details->event); - ASSERT_TRUE(details->event->IsPointerEvent()); - - ui::PointerEvent* dispatched_event = details->event->AsPointerEvent(); - EXPECT_EQ(gfx::Point(55, 15), dispatched_event->root_location()); - EXPECT_EQ(gfx::Point(5, 5), dispatched_event->location()); - EXPECT_FALSE(test_event_dispatcher_delegate()->window_that_blocked_event()); -} - -// Tests that events on a modal child target the modal child itself. -TEST_P(EventProcessorTest, ModalWindowEventOnModalChild) { - std::unique_ptr<ServerWindow> w1 = CreateChildWindow(viz::FrameSinkId(1, 3)); - std::unique_ptr<ServerWindow> w2 = CreateChildWindow(viz::FrameSinkId(1, 5)); - - root_window()->SetBounds(gfx::Rect(0, 0, 100, 100)); - w1->SetBounds(gfx::Rect(10, 10, 30, 30)); - w2->SetBounds(gfx::Rect(50, 10, 10, 10)); - - w1->AddTransientWindow(w2.get()); - w2->SetModalType(MODAL_TYPE_WINDOW); - - // Send event that is over |w2|. - const ui::PointerEvent mouse_pressed(ui::MouseEvent( - ui::ET_MOUSE_PRESSED, gfx::Point(55, 15), gfx::Point(55, 15), - base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON)); - DispatchEvent(event_dispatcher(), mouse_pressed, - EventProcessor::AcceleratorMatchPhase::ANY); - - std::unique_ptr<DispatchedEventDetails> details = - test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails(); - ASSERT_TRUE(details); - EXPECT_EQ(w2.get(), details->window); - EXPECT_TRUE(details->IsClientArea()); - - ASSERT_TRUE(details->event); - ASSERT_TRUE(details->event->IsPointerEvent()); - - ui::PointerEvent* dispatched_event = details->event->AsPointerEvent(); - EXPECT_EQ(gfx::Point(55, 15), dispatched_event->root_location()); - EXPECT_EQ(gfx::Point(5, 5), dispatched_event->location()); -} - -// Tests that events on an unrelated window are not affected by the modal -// window. -TEST_P(EventProcessorTest, ModalWindowEventOnUnrelatedWindow) { - std::unique_ptr<ServerWindow> w1 = CreateChildWindow(viz::FrameSinkId(1, 3)); - std::unique_ptr<ServerWindow> w2 = CreateChildWindow(viz::FrameSinkId(1, 5)); - std::unique_ptr<ServerWindow> w3 = CreateChildWindow(viz::FrameSinkId(1, 6)); - - root_window()->SetBounds(gfx::Rect(0, 0, 100, 100)); - w1->SetBounds(gfx::Rect(10, 10, 30, 30)); - w2->SetBounds(gfx::Rect(50, 10, 10, 10)); - w3->SetBounds(gfx::Rect(70, 10, 10, 10)); - - w1->AddTransientWindow(w2.get()); - w2->SetModalType(MODAL_TYPE_WINDOW); - - // Send event that is over |w3|. - const ui::PointerEvent mouse_pressed(ui::MouseEvent( - ui::ET_MOUSE_PRESSED, gfx::Point(75, 15), gfx::Point(75, 15), - base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON)); - DispatchEvent(event_dispatcher(), mouse_pressed, - EventProcessor::AcceleratorMatchPhase::ANY); - - std::unique_ptr<DispatchedEventDetails> details = - test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails(); - ASSERT_TRUE(details); - EXPECT_EQ(w3.get(), details->window); - EXPECT_TRUE(details->IsClientArea()); - - ASSERT_TRUE(details->event); - ASSERT_TRUE(details->event->IsPointerEvent()); - - ui::PointerEvent* dispatched_event = details->event->AsPointerEvent(); - EXPECT_EQ(gfx::Point(75, 15), dispatched_event->root_location()); - EXPECT_EQ(gfx::Point(5, 5), dispatched_event->location()); -} - -// Tests that events on a descendant of a modal parent target the modal child. -TEST_P(EventProcessorTest, ModalWindowEventOnDescendantOfModalParent) { - std::unique_ptr<ServerWindow> w1 = CreateChildWindow(viz::FrameSinkId(1, 3)); - std::unique_ptr<ServerWindow> w11 = - CreateChildWindowWithParent(viz::FrameSinkId(1, 4), w1.get()); - std::unique_ptr<ServerWindow> w2 = CreateChildWindow(viz::FrameSinkId(1, 5)); - - root_window()->SetBounds(gfx::Rect(0, 0, 100, 100)); - w1->SetBounds(gfx::Rect(10, 10, 30, 30)); - w11->SetBounds(gfx::Rect(10, 10, 10, 10)); - w2->SetBounds(gfx::Rect(50, 10, 10, 10)); - - w1->AddTransientWindow(w2.get()); - w2->SetModalType(MODAL_TYPE_WINDOW); - - // Send event that is over |w11|. - const ui::PointerEvent mouse_pressed(ui::MouseEvent( - ui::ET_MOUSE_PRESSED, gfx::Point(25, 25), gfx::Point(25, 25), - base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON)); - DispatchEvent(event_dispatcher(), mouse_pressed, - EventProcessor::AcceleratorMatchPhase::ANY); - - // The event is targeted at |w11|, but is blocked by the modal window |w2|. - ASSERT_TRUE(test_event_dispatcher_delegate()->last_event_target_not_found()); - ASSERT_FALSE(test_event_dispatcher_delegate()->has_queued_events()); -} - -// Same as ModalWindowEventOnDescendantOfModalParent but with fallback to root -// enabled. -TEST_P(EventProcessorTest, - ModalWindowEventOnDescendantOfModalParentWithFallback) { - test_event_dispatcher_delegate()->EnableFallbackToRoot(); - - std::unique_ptr<ServerWindow> w1 = CreateChildWindow(viz::FrameSinkId(1, 3)); - std::unique_ptr<ServerWindow> w11 = - CreateChildWindowWithParent(viz::FrameSinkId(1, 4), w1.get()); - std::unique_ptr<ServerWindow> w2 = CreateChildWindow(viz::FrameSinkId(1, 5)); - - root_window()->SetBounds(gfx::Rect(0, 0, 100, 100)); - w1->SetBounds(gfx::Rect(10, 10, 30, 30)); - w11->SetBounds(gfx::Rect(10, 10, 10, 10)); - w2->SetBounds(gfx::Rect(50, 10, 10, 10)); - - w1->AddTransientWindow(w2.get()); - w2->SetModalType(MODAL_TYPE_WINDOW); - - // Send event that is over |w11|. - const ui::PointerEvent mouse_pressed(ui::MouseEvent( - ui::ET_MOUSE_PRESSED, gfx::Point(25, 25), gfx::Point(25, 25), - base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON)); - DispatchEvent(event_dispatcher(), mouse_pressed, - EventProcessor::AcceleratorMatchPhase::ANY); - - std::unique_ptr<DispatchedEventDetails> details = - test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails(); - ASSERT_TRUE(details); - EXPECT_EQ(root_window(), details->window); - EXPECT_TRUE(details->IsNonclientArea()); - - ASSERT_TRUE(details->event); - ASSERT_TRUE(details->event->IsPointerEvent()); - - ui::PointerEvent* dispatched_event = details->event->AsPointerEvent(); - EXPECT_EQ(gfx::Point(25, 25), dispatched_event->root_location()); - EXPECT_EQ(gfx::Point(25, 25), dispatched_event->location()); -} - -// Tests that events on a system modal window target the modal window itself. -TEST_P(EventProcessorTest, ModalWindowEventOnSystemModal) { - std::unique_ptr<ServerWindow> w1 = CreateChildWindow(viz::FrameSinkId(1, 3)); - - root_window()->SetBounds(gfx::Rect(0, 0, 100, 100)); - w1->SetBounds(gfx::Rect(10, 10, 30, 30)); - w1->SetModalType(MODAL_TYPE_SYSTEM); - - // Send event that is over |w1|. - const ui::PointerEvent mouse_pressed(ui::MouseEvent( - ui::ET_MOUSE_PRESSED, gfx::Point(15, 15), gfx::Point(15, 15), - base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON)); - DispatchEvent(event_dispatcher(), mouse_pressed, - EventProcessor::AcceleratorMatchPhase::ANY); - - std::unique_ptr<DispatchedEventDetails> details = - test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails(); - ASSERT_TRUE(details); - EXPECT_EQ(w1.get(), details->window); - EXPECT_TRUE(details->IsClientArea()); - - ASSERT_TRUE(details->event); - ASSERT_TRUE(details->event->IsPointerEvent()); - - ui::PointerEvent* dispatched_event = details->event->AsPointerEvent(); - EXPECT_EQ(gfx::Point(15, 15), dispatched_event->root_location()); - EXPECT_EQ(gfx::Point(5, 5), dispatched_event->location()); -} - -// Tests that events outside of system modal window target the modal window. -TEST_P(EventProcessorTest, ModalWindowEventOutsideSystemModal) { - std::unique_ptr<ServerWindow> w1 = CreateChildWindow(viz::FrameSinkId(1, 3)); - - root_window()->SetBounds(gfx::Rect(0, 0, 100, 100)); - w1->SetBounds(gfx::Rect(10, 10, 30, 30)); - w1->SetModalType(MODAL_TYPE_SYSTEM); - event_dispatcher()->AddSystemModalWindow(w1.get()); - - // Send event that is outside of |w1|. - const ui::PointerEvent mouse_pressed(ui::MouseEvent( - ui::ET_MOUSE_PRESSED, gfx::Point(45, 15), gfx::Point(45, 15), - base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON)); - DispatchEvent(event_dispatcher(), mouse_pressed, - EventProcessor::AcceleratorMatchPhase::ANY); - - ASSERT_TRUE(test_event_dispatcher_delegate()->last_event_target_not_found()); - ASSERT_FALSE(test_event_dispatcher_delegate()->has_queued_events()); - EXPECT_EQ(w1.get(), - test_event_dispatcher_delegate()->window_that_blocked_event()); -} - -// Variant of ModalWindowEventOutsideSystemModal with -// EnableFallbackToRoot(). -TEST_P(EventProcessorTest, ModalWindowEventOutsideSystemModalWithFallback) { - test_event_dispatcher_delegate()->EnableFallbackToRoot(); - - std::unique_ptr<ServerWindow> w1 = CreateChildWindow(viz::FrameSinkId(1, 3)); - - root_window()->SetBounds(gfx::Rect(0, 0, 100, 100)); - w1->SetBounds(gfx::Rect(10, 10, 30, 30)); - w1->SetModalType(MODAL_TYPE_SYSTEM); - event_dispatcher()->AddSystemModalWindow(w1.get()); - - // Send event that is outside of |w1|. - const ui::PointerEvent mouse_pressed(ui::MouseEvent( - ui::ET_MOUSE_PRESSED, gfx::Point(45, 15), gfx::Point(45, 15), - base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON)); - DispatchEvent(event_dispatcher(), mouse_pressed, - EventProcessor::AcceleratorMatchPhase::ANY); - - std::unique_ptr<DispatchedEventDetails> details = - test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails(); - ASSERT_TRUE(details); - EXPECT_EQ(root_window(), details->window); - EXPECT_TRUE(details->IsNonclientArea()); - - ASSERT_TRUE(details->event); - ASSERT_TRUE(details->event->IsPointerEvent()); - - ui::PointerEvent* dispatched_event = details->event->AsPointerEvent(); - EXPECT_EQ(gfx::Point(45, 15), dispatched_event->root_location()); - EXPECT_EQ(gfx::Point(45, 15), dispatched_event->location()); -} - -// Tests events on a sub-window of system modal window target the window itself. -TEST_P(EventProcessorTest, ModalWindowEventSubWindowSystemModal) { - std::unique_ptr<ServerWindow> w1 = CreateChildWindow(viz::FrameSinkId(1, 3)); - w1->SetModalType(MODAL_TYPE_SYSTEM); - event_dispatcher()->AddSystemModalWindow(w1.get()); - - std::unique_ptr<ServerWindow> w2 = - CreateChildWindowWithParent(viz::FrameSinkId(1, 4), w1.get()); - std::unique_ptr<ServerWindow> w3 = CreateChildWindow(viz::FrameSinkId(1, 5)); - - root_window()->SetBounds(gfx::Rect(0, 0, 100, 100)); - w1->SetBounds(gfx::Rect(10, 10, 30, 30)); - w2->SetBounds(gfx::Rect(10, 10, 10, 10)); - w3->SetBounds(gfx::Rect(50, 10, 10, 10)); - - struct { - gfx::Point location; - ServerWindow* expected_target; - } kTouchData[] = { - // Touch on |w1| should go to |w1|. - {gfx::Point(11, 11), w1.get()}, - // Touch on |w2| should go to |w2|. - {gfx::Point(25, 25), w2.get()}, - // Touch on |w3| should go to |w1|. - {gfx::Point(11, 31), w1.get()}, - }; - - for (size_t i = 0; i < arraysize(kTouchData); i++) { - // Send touch press and check that the expected target receives it. - DispatchEvent( - event_dispatcher(), - ui::PointerEvent(ui::TouchEvent( - ui::ET_TOUCH_PRESSED, kTouchData[i].location, base::TimeTicks(), - ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0))), - EventProcessor::AcceleratorMatchPhase::ANY); - std::unique_ptr<DispatchedEventDetails> details = - test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails(); - ASSERT_TRUE(details) << " details is nullptr " << i; - EXPECT_EQ(kTouchData[i].expected_target, details->window) << i; - - // Release touch. - DispatchEvent( - event_dispatcher(), - ui::PointerEvent(ui::TouchEvent( - ui::ET_TOUCH_RELEASED, kTouchData[i].location, base::TimeTicks(), - ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0))), - EventProcessor::AcceleratorMatchPhase::ANY); - test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails(); - } -} - -// Tests that setting capture to a descendant of a modal parent fails. -TEST_P(EventProcessorTest, ModalWindowSetCaptureDescendantOfModalParent) { - std::unique_ptr<ServerWindow> w1 = CreateChildWindow(viz::FrameSinkId(1, 3)); - std::unique_ptr<ServerWindow> w11 = - CreateChildWindowWithParent(viz::FrameSinkId(1, 4), w1.get()); - std::unique_ptr<ServerWindow> w2 = CreateChildWindow(viz::FrameSinkId(1, 5)); - - root_window()->SetBounds(gfx::Rect(0, 0, 100, 100)); - w1->SetBounds(gfx::Rect(10, 10, 30, 30)); - w11->SetBounds(gfx::Rect(10, 10, 10, 10)); - w2->SetBounds(gfx::Rect(50, 10, 10, 10)); - - w1->AddTransientWindow(w2.get()); - w2->SetModalType(MODAL_TYPE_WINDOW); - - EXPECT_FALSE(event_dispatcher()->SetCaptureWindow(w11.get(), kClientAreaId)); - EXPECT_EQ(nullptr, event_dispatcher()->capture_window()); -} - -// Tests that setting capture to a window unrelated to a modal parent works. -TEST_P(EventProcessorTest, ModalWindowSetCaptureUnrelatedWindow) { - std::unique_ptr<ServerWindow> w1 = CreateChildWindow(viz::FrameSinkId(1, 3)); - std::unique_ptr<ServerWindow> w2 = CreateChildWindow(viz::FrameSinkId(1, 4)); - std::unique_ptr<ServerWindow> w3 = CreateChildWindow(viz::FrameSinkId(1, 5)); - - root_window()->SetBounds(gfx::Rect(0, 0, 100, 100)); - w1->SetBounds(gfx::Rect(10, 10, 30, 30)); - w2->SetBounds(gfx::Rect(50, 10, 10, 10)); - w3->SetBounds(gfx::Rect(70, 10, 10, 10)); - - w1->AddTransientWindow(w2.get()); - w2->SetModalType(MODAL_TYPE_WINDOW); - - EXPECT_TRUE(event_dispatcher()->SetCaptureWindow(w3.get(), kClientAreaId)); - EXPECT_EQ(w3.get(), event_dispatcher()->capture_window()); -} - -// Tests that setting capture fails when there is a system modal window. -TEST_P(EventProcessorTest, ModalWindowSystemSetCapture) { - std::unique_ptr<ServerWindow> w1 = CreateChildWindow(viz::FrameSinkId(1, 3)); - std::unique_ptr<ServerWindow> w2 = CreateChildWindow(viz::FrameSinkId(1, 4)); - - root_window()->SetBounds(gfx::Rect(0, 0, 100, 100)); - w1->SetBounds(gfx::Rect(10, 10, 30, 30)); - w2->SetBounds(gfx::Rect(50, 10, 10, 10)); - - w2->SetModalType(MODAL_TYPE_SYSTEM); - event_dispatcher()->AddSystemModalWindow(w2.get()); - - EXPECT_FALSE(event_dispatcher()->SetCaptureWindow(w1.get(), kClientAreaId)); - EXPECT_EQ(nullptr, event_dispatcher()->capture_window()); -} - -// Tests having multiple system modal windows. -TEST_P(EventProcessorTest, ModalWindowMultipleSystemModals) { - std::unique_ptr<ServerWindow> w1 = CreateChildWindow(viz::FrameSinkId(1, 3)); - std::unique_ptr<ServerWindow> w2 = CreateChildWindow(viz::FrameSinkId(1, 4)); - std::unique_ptr<ServerWindow> w3 = CreateChildWindow(viz::FrameSinkId(1, 5)); - - w2->SetVisible(false); - - // In the beginning, there should be no active system modal window. - EXPECT_EQ(nullptr, GetActiveSystemModalWindow()); - - // Add a visible system modal window. It should become the active one. - w1->SetModalType(MODAL_TYPE_SYSTEM); - event_dispatcher()->AddSystemModalWindow(w1.get()); - EXPECT_EQ(w1.get(), GetActiveSystemModalWindow()); - - // Add an invisible system modal window. It should not change the active one. - w2->SetModalType(MODAL_TYPE_SYSTEM); - event_dispatcher()->AddSystemModalWindow(w2.get()); - EXPECT_EQ(w1.get(), GetActiveSystemModalWindow()); - - // Add another visible system modal window. It should become the active one. - w3->SetModalType(MODAL_TYPE_SYSTEM); - event_dispatcher()->AddSystemModalWindow(w3.get()); - EXPECT_EQ(w3.get(), GetActiveSystemModalWindow()); - - // Make an existing system modal window visible. It should become the active - // one. - w2->SetVisible(true); - EXPECT_EQ(w2.get(), GetActiveSystemModalWindow()); - - // Remove the active system modal window. Next one should become active. - w2.reset(); - EXPECT_EQ(w3.get(), GetActiveSystemModalWindow()); - - // Remove an inactive system modal window. It should not change the active - // one. - w1.reset(); - EXPECT_EQ(w3.get(), GetActiveSystemModalWindow()); - - // Remove the last remaining system modal window. There should be no active - // one anymore. - w3.reset(); - EXPECT_EQ(nullptr, GetActiveSystemModalWindow()); -} - -TEST_P(EventProcessorTest, CaptureNotResetOnParentChange) { - std::unique_ptr<ServerWindow> w1 = CreateChildWindow(viz::FrameSinkId(1, 3)); - w1->set_event_targeting_policy(mojom::EventTargetingPolicy::DESCENDANTS_ONLY); - std::unique_ptr<ServerWindow> w11 = - CreateChildWindowWithParent(viz::FrameSinkId(1, 4), w1.get()); - std::unique_ptr<ServerWindow> w2 = CreateChildWindow(viz::FrameSinkId(1, 5)); - w2->set_event_targeting_policy(mojom::EventTargetingPolicy::DESCENDANTS_ONLY); - - root_window()->SetBounds(gfx::Rect(0, 0, 100, 100)); - w1->SetBounds(gfx::Rect(0, 0, 100, 100)); - w11->SetBounds(gfx::Rect(10, 10, 10, 10)); - w2->SetBounds(gfx::Rect(0, 0, 100, 100)); - - // Send event that is over |w11|. - const ui::PointerEvent mouse_pressed(ui::MouseEvent( - ui::ET_MOUSE_PRESSED, gfx::Point(15, 15), gfx::Point(15, 15), - base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON)); - DispatchEvent(event_dispatcher(), mouse_pressed, - EventProcessor::AcceleratorMatchPhase::ANY); - event_dispatcher()->SetCaptureWindow(w11.get(), kClientAreaId); - - std::unique_ptr<DispatchedEventDetails> details = - test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails(); - ASSERT_TRUE(details); - EXPECT_EQ(w11.get(), details->window); - EXPECT_TRUE(details->IsClientArea()); - - // Move |w11| to |w2| and verify the mouse is still down, and |w11| has - // capture. - w2->Add(w11.get()); - EXPECT_TRUE(IsMouseButtonDown()); - EXPECT_EQ(w11.get(), - EventProcessorTestApi(event_dispatcher()).capture_window()); -} - -TEST_P(EventProcessorTest, ChangeCaptureFromClientToNonclient) { - std::unique_ptr<ServerWindow> child = - CreateChildWindow(viz::FrameSinkId(1, 3)); - event_dispatcher()->SetCaptureWindow(child.get(), kNonclientAreaId); - EXPECT_EQ(kNonclientAreaId, event_dispatcher()->capture_window_client_id()); - EXPECT_EQ(nullptr, test_event_dispatcher_delegate()->lost_capture_window()); - event_dispatcher()->SetCaptureWindow(child.get(), kClientAreaId); - // Changing capture from client to non-client should notify the delegate. - // The delegate can decide if it really wants to forward the event or not. - EXPECT_EQ(child.get(), - test_event_dispatcher_delegate()->lost_capture_window()); - EXPECT_EQ(child.get(), event_dispatcher()->capture_window()); - EXPECT_EQ(kClientAreaId, event_dispatcher()->capture_window_client_id()); -} - -TEST_P(EventProcessorTest, MoveMouseFromNoTargetToValidTarget) { - ServerWindow* root = root_window(); - root->set_event_targeting_policy( - mojom::EventTargetingPolicy::DESCENDANTS_ONLY); - std::unique_ptr<ServerWindow> child = - CreateChildWindow(viz::FrameSinkId(1, 3)); - - root->SetBounds(gfx::Rect(0, 0, 100, 100)); - child->SetBounds(gfx::Rect(10, 10, 20, 20)); - - MouseEventTest tests[] = { - // Send a mouse down over the root, but not the child. No event should - // be generated. - {std::make_unique<ui::MouseEvent>(ui::ET_MOUSE_MOVED, gfx::Point(5, 5), - gfx::Point(5, 5), base::TimeTicks(), 0, - 0), - nullptr, gfx::Point(), gfx::Point(), nullptr, gfx::Point(), - gfx::Point()}, - - // Move into child. - {std::make_unique<ui::MouseEvent>(ui::ET_MOUSE_MOVED, gfx::Point(12, 12), - gfx::Point(12, 12), base::TimeTicks(), - 0, 0), - child.get(), gfx::Point(12, 12), gfx::Point(2, 2), nullptr, gfx::Point(), - gfx::Point()}}; - RunMouseEventTests(event_dispatcher(), test_event_dispatcher_delegate(), - tests, arraysize(tests)); -} - -TEST_P(EventProcessorTest, NoTargetToTargetWithMouseDown) { - ServerWindow* root = root_window(); - root->set_event_targeting_policy( - mojom::EventTargetingPolicy::DESCENDANTS_ONLY); - std::unique_ptr<ServerWindow> child = - CreateChildWindow(viz::FrameSinkId(1, 3)); - - root->SetBounds(gfx::Rect(0, 0, 100, 100)); - child->SetBounds(gfx::Rect(10, 10, 20, 20)); - - MouseEventTest tests[] = { - // Mouse over the root, but not the child. No event should be generated. - {std::make_unique<ui::MouseEvent>(ui::ET_MOUSE_MOVED, gfx::Point(5, 5), - gfx::Point(5, 5), base::TimeTicks(), 0, - 0), - nullptr, gfx::Point(), gfx::Point(), nullptr, gfx::Point(), - gfx::Point()}, - - // Press in same location, still no target. - {std::make_unique<ui::MouseEvent>(ui::ET_MOUSE_PRESSED, gfx::Point(5, 5), - gfx::Point(5, 5), base::TimeTicks(), - ui::EF_LEFT_MOUSE_BUTTON, - ui::EF_LEFT_MOUSE_BUTTON), - nullptr, gfx::Point(), gfx::Point(), nullptr, gfx::Point(), - gfx::Point()}, - - // Move into child, still no target. - {std::make_unique<ui::MouseEvent>(ui::ET_MOUSE_MOVED, gfx::Point(12, 12), - gfx::Point(12, 12), base::TimeTicks(), - ui::EF_LEFT_MOUSE_BUTTON, 0), - nullptr, gfx::Point(), gfx::Point(), nullptr, gfx::Point(), - gfx::Point()}}; - RunMouseEventTests(event_dispatcher(), test_event_dispatcher_delegate(), - tests, arraysize(tests)); -} - -TEST_P(EventProcessorTest, DontSendExitToSameClientWhenCaptureChanges) { - ServerWindow* root = root_window(); - root->set_event_targeting_policy( - mojom::EventTargetingPolicy::DESCENDANTS_ONLY); - std::unique_ptr<ServerWindow> c1 = CreateChildWindow(viz::FrameSinkId(1, 3)); - std::unique_ptr<ServerWindow> c2 = CreateChildWindow(viz::FrameSinkId(1, 4)); - - root->SetBounds(gfx::Rect(0, 0, 100, 100)); - c1->SetBounds(gfx::Rect(10, 10, 20, 20)); - c2->SetBounds(gfx::Rect(15, 15, 20, 20)); - - MouseEventTest tests[] = { - // Mouse over |c2|. - {std::make_unique<ui::MouseEvent>(ui::ET_MOUSE_MOVED, gfx::Point(16, 16), - gfx::Point(16, 16), base::TimeTicks(), - 0, 0), - c2.get(), gfx::Point(16, 16), gfx::Point(1, 1), nullptr, gfx::Point(), - gfx::Point()}, - - // Press in same location. - {std::make_unique<ui::MouseEvent>( - ui::ET_MOUSE_PRESSED, gfx::Point(16, 16), gfx::Point(16, 16), - base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, - ui::EF_LEFT_MOUSE_BUTTON), - c2.get(), gfx::Point(16, 16), gfx::Point(1, 1), nullptr, gfx::Point(), - gfx::Point()}}; - RunMouseEventTests(event_dispatcher(), test_event_dispatcher_delegate(), - tests, arraysize(tests)); - - // Set capture on |c1|. No events should be sent as |c1| is in the same - // client. - event_dispatcher()->SetCaptureWindow(c1.get(), kClientAreaId); - EXPECT_FALSE(test_event_dispatcher_delegate()->has_queued_events()); -} - -TEST_P(EventProcessorTest, MousePointerClearedOnDestroy) { - root_window()->set_event_targeting_policy( - mojom::EventTargetingPolicy::DESCENDANTS_ONLY); - std::unique_ptr<ServerWindow> c1 = CreateChildWindow(viz::FrameSinkId(1, 3)); - - root_window()->SetBounds(gfx::Rect(0, 0, 100, 100)); - c1->SetBounds(gfx::Rect(10, 10, 20, 20)); - - const ui::PointerEvent move_event( - ui::MouseEvent(ui::ET_MOUSE_MOVED, gfx::Point(15, 15), gfx::Point(15, 15), - base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, 0)); - DispatchEvent(event_dispatcher(), move_event, - EventProcessor::AcceleratorMatchPhase::ANY); - - EXPECT_EQ(c1.get(), event_dispatcher()->mouse_cursor_source_window()); - c1.reset(); - EXPECT_EQ(nullptr, event_dispatcher()->mouse_cursor_source_window()); -} - -TEST_P(EventProcessorTest, LocationHonorsTransform) { - std::unique_ptr<ServerWindow> child = - CreateChildWindow(viz::FrameSinkId(1, 3)); - - gfx::Transform transform; - transform.Scale(SkIntToMScalar(2), SkIntToMScalar(2)); - child->SetTransform(transform); - - root_window()->SetBounds(gfx::Rect(0, 0, 100, 100)); - child->SetBounds(gfx::Rect(10, 10, 20, 20)); - - // Send event that is over child. - const ui::PointerEvent ui_event(ui::MouseEvent( - ui::ET_MOUSE_PRESSED, gfx::Point(20, 25), gfx::Point(20, 25), - base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON)); - DispatchEvent(event_dispatcher(), ui_event, - EventProcessor::AcceleratorMatchPhase::ANY); - - std::unique_ptr<DispatchedEventDetails> details = - test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails(); - ASSERT_TRUE(details); - ASSERT_EQ(child.get(), details->window); - - ASSERT_TRUE(details->event); - ASSERT_TRUE(details->event->IsPointerEvent()); - - ui::PointerEvent* dispatched_event = details->event->AsPointerEvent(); - EXPECT_EQ(gfx::Point(20, 25), dispatched_event->root_location()); - EXPECT_EQ(gfx::Point(5, 7), dispatched_event->location()); -} - -TEST_P(EventProcessorTest, MouseMovementsShowCursor) { - EXPECT_EQ(base::Optional<bool>(), - test_event_dispatcher_delegate()->last_cursor_visibility()); - - const ui::PointerEvent move1( - ui::MouseEvent(ui::ET_MOUSE_MOVED, gfx::Point(11, 11), gfx::Point(11, 11), - base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, 0)); - DispatchEvent(event_dispatcher(), move1, - EventProcessor::AcceleratorMatchPhase::ANY); - - EXPECT_EQ(base::Optional<bool>(true), - test_event_dispatcher_delegate()->last_cursor_visibility()); -} - -TEST_P(EventProcessorTest, KeyDoesntHideCursorWithNoList) { - // In the case of mus, we don't send a list to the window server so ensure we - // don't hide the cursor in this mode. - TestEventProcessorDelegate* event_dispatcher_delegate = - test_event_dispatcher_delegate(); - EXPECT_EQ(base::Optional<bool>(), - event_dispatcher_delegate->last_cursor_visibility()); - - // Set focused window for EventProcessor dispatches key events. - std::unique_ptr<ServerWindow> child = - CreateChildWindow(viz::FrameSinkId(1, 3)); - event_dispatcher_delegate->SetFocusedWindowFromEventProcessor(child.get()); - - ui::KeyEvent key(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE); - DispatchEvent(event_dispatcher(), key, - EventProcessor::AcceleratorMatchPhase::ANY); - - EXPECT_EQ(base::Optional<bool>(), - event_dispatcher_delegate->last_cursor_visibility()); -} - -TEST_P(EventProcessorTest, KeyDoesntHideCursorOnMatch) { - // In the case of mash, we send a list of keys which don't hide the cursor. - std::vector<ui::mojom::EventMatcherPtr> matchers; - matchers.push_back(BuildKeyMatcher(ui::mojom::KeyboardCode::A)); - event_dispatcher()->SetKeyEventsThatDontHideCursor(std::move(matchers)); - - // Set focused window for EventProcessor dispatches key events. - TestEventProcessorDelegate* event_dispatcher_delegate = - test_event_dispatcher_delegate(); - std::unique_ptr<ServerWindow> child = - CreateChildWindow(viz::FrameSinkId(1, 3)); - event_dispatcher_delegate->SetFocusedWindowFromEventProcessor(child.get()); - - ui::KeyEvent key(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE); - DispatchEvent(event_dispatcher(), key, - EventProcessor::AcceleratorMatchPhase::ANY); - - EXPECT_EQ(base::Optional<bool>(), - event_dispatcher_delegate->last_cursor_visibility()); -} - -TEST_P(EventProcessorTest, KeyHidesCursorOnNoMatch) { - // In the case of mash, we send a list of keys which don't hide the cursor. - std::vector<ui::mojom::EventMatcherPtr> matchers; - matchers.push_back(BuildKeyMatcher(ui::mojom::KeyboardCode::B)); - event_dispatcher()->SetKeyEventsThatDontHideCursor(std::move(matchers)); - - // Set focused window for EventProcessor dispatches key events. - TestEventProcessorDelegate* event_dispatcher_delegate = - test_event_dispatcher_delegate(); - std::unique_ptr<ServerWindow> child = - CreateChildWindow(viz::FrameSinkId(1, 3)); - event_dispatcher_delegate->SetFocusedWindowFromEventProcessor(child.get()); - - ui::KeyEvent key(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE); - DispatchEvent(event_dispatcher(), key, - EventProcessor::AcceleratorMatchPhase::ANY); - - EXPECT_EQ(base::Optional<bool>(false), - event_dispatcher_delegate->last_cursor_visibility()); -} - -TEST_P(EventProcessorTest, ChildModal) { - std::unique_ptr<ServerWindow> modal_parent = - CreateChildWindow(viz::FrameSinkId(1, 3)); - std::unique_ptr<ServerWindow> child_modal_window = - CreateChildWindow(viz::FrameSinkId(1, 4)); - - root_window()->SetBounds(gfx::Rect(0, 0, 100, 100)); - modal_parent->SetBounds(gfx::Rect(10, 10, 30, 30)); - child_modal_window->SetBounds(gfx::Rect(50, 10, 10, 10)); - modal_parent->AddTransientWindow(child_modal_window.get()); - child_modal_window->SetModalType(MODAL_TYPE_CHILD); - child_modal_window->SetChildModalParent(modal_parent.get()); - - const ui::PointerEvent press_event(ui::MouseEvent( - ui::ET_MOUSE_PRESSED, gfx::Point(20, 25), gfx::Point(20, 25), - base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON)); - DispatchEvent(event_dispatcher(), press_event, - EventProcessor::AcceleratorMatchPhase::ANY); - - // As the event falls over |modal_parent|, but there is a CHILD_MODAL window, - // the event is blocked and the delegate notified. - EXPECT_FALSE(test_event_dispatcher_delegate()->has_queued_events()); - EXPECT_EQ(child_modal_window.get(), - test_event_dispatcher_delegate()->window_that_blocked_event()); -} - -TEST_P(EventProcessorTest, DontCancelWhenMovedToSeparateDisplay) { - TestServerWindowDelegate window_delegate2(viz_host_proxy()); - ServerWindow root2(&window_delegate2, viz::FrameSinkId(1, 100)); - root2.set_is_activation_parent(true); - window_delegate2.set_root_window(&root2); - root2.SetVisible(true); - - std::unique_ptr<ServerWindow> w1 = CreateChildWindow(viz::FrameSinkId(1, 3)); - event_dispatcher()->SetCaptureWindow(w1.get(), kClientAreaId); - ASSERT_EQ(w1.get(), event_dispatcher()->capture_window()); - test_event_dispatcher_delegate()->set_root(&root2); - window_delegate()->AddRootWindow(&root2); - root2.Add(w1.get()); - EXPECT_EQ(w1.get(), event_dispatcher()->capture_window()); -} - -// Tests that setting capture to a window unrelated to a modal parent works. -TEST_P(EventProcessorTest, MouseCursorSourceWindowChangesWithSystemModal) { - BlockingContainers blocking_containers; - blocking_containers.system_modal_container = root_window(); - event_dispatcher()->modal_window_controller()->SetBlockingContainers( - {blocking_containers}); - - std::unique_ptr<ServerWindow> w1 = CreateChildWindow(viz::FrameSinkId(1, 3)); - std::unique_ptr<ServerWindow> w2 = CreateChildWindow(viz::FrameSinkId(1, 4)); - - root_window()->SetBounds(gfx::Rect(0, 0, 100, 100)); - root_window()->set_is_activation_parent(true); - w1->SetBounds(gfx::Rect(10, 10, 30, 30)); - w2->SetBounds(gfx::Rect(50, 10, 10, 10)); - w2->SetModalType(MODAL_TYPE_SYSTEM); - event_dispatcher()->modal_window_controller()->AddSystemModalWindow(w2.get()); - - // Move the mouse over |w1|. - const ui::PointerEvent move( - ui::MouseEvent(ui::ET_MOUSE_MOVED, gfx::Point(11, 11), gfx::Point(11, 11), - base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, 0)); - DispatchEvent(event_dispatcher(), move, - EventProcessor::AcceleratorMatchPhase::ANY); - - EXPECT_EQ(nullptr, event_dispatcher()->mouse_cursor_source_window()); - - event_dispatcher()->UpdateCursorProviderByLastKnownLocation(); - RunTasks(); - // EventProcessor fallsback to the root incase of invalid window. - EXPECT_EQ(root_window(), event_dispatcher()->mouse_cursor_source_window()); -} - -TEST_P(EventProcessorTest, DontQueryWhileMouseIsDown) { - // This test is easier to write with async event processing. - if (!is_event_processing_async()) - return; - - std::unique_ptr<ServerWindow> child = - CreateChildWindow(viz::FrameSinkId(1, 3)); - - root_window()->SetBounds(gfx::Rect(0, 0, 100, 100)); - child->SetBounds(gfx::Rect(10, 10, 20, 20)); - - const ui::PointerEvent press_event(ui::MouseEvent( - ui::ET_MOUSE_PRESSED, gfx::Point(20, 25), gfx::Point(20, 25), - base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON)); - DispatchEvent(event_dispatcher(), press_event, - EventProcessor::AcceleratorMatchPhase::ANY); - ASSERT_FALSE(event_dispatcher()->IsProcessingEvent()); - - const ui::PointerEvent move_event(ui::MouseEvent( - ui::ET_MOUSE_MOVED, gfx::Point(20, 25), gfx::Point(20, 25), - base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON)); - event_dispatcher()->ProcessEvent(move_event, - EventLocationFromEvent(move_event), - EventProcessor::AcceleratorMatchPhase::ANY); - EXPECT_FALSE(event_dispatcher()->IsProcessingEvent()); -} - -INSTANTIATE_TEST_CASE_P(/* no prefix */, EventProcessorTest, testing::Bool()); - -} // namespace test -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/event_targeter.cc b/services/ui/ws/event_targeter.cc deleted file mode 100644 index 789c315..0000000 --- a/services/ui/ws/event_targeter.cc +++ /dev/null
@@ -1,58 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "services/ui/ws/event_targeter.h" - -#include "base/command_line.h" -#include "base/metrics/user_metrics.h" -#include "base/task_scheduler/post_task.h" -#include "base/threading/thread_task_runner_handle.h" -#include "components/viz/common/features.h" -#include "components/viz/host/hit_test/hit_test_query.h" -#include "services/ui/common/switches.h" -#include "services/ui/ws/event_location.h" -#include "services/ui/ws/event_targeter_delegate.h" -#include "ui/gfx/geometry/point_conversions.h" - -namespace ui { -namespace ws { - -EventTargeter::EventTargeter(EventTargeterDelegate* event_targeter_delegate) - : event_targeter_delegate_(event_targeter_delegate), - weak_ptr_factory_(this) {} - -EventTargeter::~EventTargeter() {} - -void EventTargeter::FindTargetForLocation(EventSource event_source, - const EventLocation& event_location, - HitTestCallback callback) { - // TODO(riajiang): After the async ask-client part is implemented, the async - // part should be moved to after sync viz-hit-test call. - if (base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kUseAsyncEventTargeting)) { - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(&EventTargeter::FindTargetForLocationNow, - weak_ptr_factory_.GetWeakPtr(), event_source, - event_location, base::Passed(&callback))); - } else { - FindTargetForLocationNow(event_source, event_location, std::move(callback)); - } -} - -void EventTargeter::FindTargetForLocationNow( - EventSource event_source, - const EventLocation& event_location, - HitTestCallback callback) { - ServerWindow* root = event_targeter_delegate_->GetRootWindowForDisplay( - event_location.display_id); - DeepestWindow deepest_window; - if (root) { - deepest_window = ui::ws::FindDeepestVisibleWindowForLocation( - root, event_source, gfx::ToFlooredPoint(event_location.raw_location)); - } - std::move(callback).Run(event_location, deepest_window); -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/event_targeter.h b/services/ui/ws/event_targeter.h deleted file mode 100644 index 56935f9..0000000 --- a/services/ui/ws/event_targeter.h +++ /dev/null
@@ -1,58 +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 SERVICES_UI_WS_EVENT_TARGETER_H_ -#define SERVICES_UI_WS_EVENT_TARGETER_H_ - -#include <stdint.h> - -#include "base/callback_forward.h" -#include "base/macros.h" -#include "base/memory/weak_ptr.h" -#include "services/ui/ws/window_finder.h" -#include "ui/gfx/geometry/point.h" - -namespace ui { -namespace ws { - -class EventTargeterDelegate; -struct EventLocation; - -namespace test { -class EventTargeterTestApi; -} - -using HitTestCallback = - base::OnceCallback<void(const EventLocation&, const DeepestWindow&)>; - -// Finds the target window for a location. -class EventTargeter { - public: - explicit EventTargeter(EventTargeterDelegate* event_targeter_delegate); - ~EventTargeter(); - - // Calls WindowFinder to find the target for |display_location|. |callback| is - // called with the found target. - void FindTargetForLocation(EventSource event_source, - const EventLocation& event_location, - HitTestCallback callback); - - private: - friend class test::EventTargeterTestApi; - - void FindTargetForLocationNow(EventSource event_source, - const EventLocation& display_location, - HitTestCallback callback); - - EventTargeterDelegate* event_targeter_delegate_; - - base::WeakPtrFactory<EventTargeter> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(EventTargeter); -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_EVENT_TARGETER_H_
diff --git a/services/ui/ws/event_targeter_delegate.h b/services/ui/ws/event_targeter_delegate.h deleted file mode 100644 index f37627f..0000000 --- a/services/ui/ws/event_targeter_delegate.h +++ /dev/null
@@ -1,40 +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 SERVICES_UI_WS_EVENT_TARGETER_DELEGATE_H_ -#define SERVICES_UI_WS_EVENT_TARGETER_DELEGATE_H_ - -#include <stdint.h> - -namespace viz { -class HitTestQuery; -} - -namespace ui { -namespace ws { -class ServerWindow; - -// Used by EventTargeter to talk to WindowManagerState. -class EventTargeterDelegate { - public: - // Calls EventDispatcherDelegate::GetRootWindowForDisplay(), see - // event_dispatcher_delegate.h for details. - virtual ServerWindow* GetRootWindowForDisplay(int64_t display_id) = 0; - - // Returns null if there's no display with |display_id|. - virtual viz::HitTestQuery* GetHitTestQueryForDisplay(int64_t display_id) = 0; - - // |frame_sink_id| must be valid. Returns null if there's no window - // associated with |frame_sink_id|. - virtual ServerWindow* GetWindowFromFrameSinkId( - const viz::FrameSinkId& frame_sink_id) = 0; - - protected: - virtual ~EventTargeterDelegate() {} -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_EVENT_TARGETER_DELEGATE_H_
diff --git a/services/ui/ws/focus_controller.cc b/services/ui/ws/focus_controller.cc deleted file mode 100644 index 06a862c..0000000 --- a/services/ui/ws/focus_controller.cc +++ /dev/null
@@ -1,261 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "services/ui/ws/focus_controller.h" - -#include "base/macros.h" -#include "services/ui/public/interfaces/window_manager.mojom.h" -#include "services/ui/ws/focus_controller_observer.h" -#include "services/ui/ws/server_window.h" -#include "services/ui/ws/server_window_drawn_tracker.h" - -namespace ui { -namespace ws { - -namespace { - -ServerWindow* GetDeepestLastDescendant(ServerWindow* window) { - while (!window->children().empty()) - window = window->children().back(); - return window; -} - -// This can be used to iterate over each node in a rooted tree for the purpose -// of shifting focus/activation. -class WindowTreeIterator { - public: - explicit WindowTreeIterator(ServerWindow* root) : root_(root) {} - ~WindowTreeIterator() {} - - ServerWindow* GetNext(ServerWindow* window) const { - if (window == root_ || window == nullptr) - return GetDeepestLastDescendant(root_); - - // Return the next sibling. - ServerWindow* parent = window->parent(); - if (parent) { - const ServerWindow::Windows& siblings = parent->children(); - ServerWindow::Windows::const_reverse_iterator iter = - std::find(siblings.rbegin(), siblings.rend(), window); - DCHECK(iter != siblings.rend()); - ++iter; - if (iter != siblings.rend()) - return GetDeepestLastDescendant(*iter); - } - - // All children and siblings have been explored. Next is the parent. - return parent; - } - - private: - ServerWindow* root_; - - DISALLOW_COPY_AND_ASSIGN(WindowTreeIterator); -}; - -} // namespace - -FocusController::FocusController(ServerWindow* root) - : root_(root), - focused_window_(nullptr), - active_window_(nullptr), - activation_reason_(ActivationChangeReason::UNKNOWN) { - DCHECK(root_); -} - -FocusController::~FocusController() { -} - -bool FocusController::SetFocusedWindow(ServerWindow* window) { - if (GetFocusedWindow() == window) - return true; - - return SetFocusedWindowImpl(FocusControllerChangeSource::EXPLICIT, window); -} - -ServerWindow* FocusController::GetFocusedWindow() { - return focused_window_; -} - -void FocusController::AddObserver(FocusControllerObserver* observer) { - observers_.AddObserver(observer); -} - -void FocusController::RemoveObserver(FocusControllerObserver* observer) { - observers_.RemoveObserver(observer); -} - -void FocusController::SetActiveWindow(ServerWindow* window, - ActivationChangeReason reason) { - DCHECK(!window || CanBeActivated(window)); - if (active_window_ == window) - return; - - ServerWindow* old_active = active_window_; - active_window_ = window; - activation_reason_ = reason; - for (auto& observer : observers_) - observer.OnActivationChanged(old_active, active_window_); -} - -bool FocusController::CanBeFocused(ServerWindow* window) const { - // All ancestors of |window| must be drawn, and be focusable. - for (ServerWindow* w = window; w; w = w->parent()) { - if (!w->IsDrawn()) - return false; - if (!w->can_focus()) - return false; - } - - // |window| must be a descendent of an activatable window. - return GetActivatableAncestorOf(window) != nullptr; -} - -bool FocusController::CanBeActivated(ServerWindow* window) const { - DCHECK(window); - // A detached window cannot be activated. - if (!root_->Contains(window)) - return false; - - // The parent window must be allowed to have active children. - if (!window->parent() || !window->parent()->is_activation_parent()) - return false; - - if (!window->can_focus()) - return false; - - // The window must be drawn, or if it's not drawn, it must be minimized. - if (!window->IsDrawn() && - window->GetShowState() != mojom::ShowState::MINIMIZED) { - return false; - } - - // TODO(sad): If there's a transient modal window, then this cannot be - // activated. - return true; -} - -ServerWindow* FocusController::GetActivatableAncestorOf( - ServerWindow* window) const { - for (ServerWindow* w = window; w; w = w->parent()) { - if (CanBeActivated(w)) - return w; - } - return nullptr; -} - -bool FocusController::SetFocusedWindowImpl( - FocusControllerChangeSource change_source, - ServerWindow* window) { - if (window && !CanBeFocused(window)) - return false; - - ServerWindow* old_focused = GetFocusedWindow(); - - DCHECK(!window || window->IsDrawn()); - - // Activate the closest activatable ancestor window. - // TODO(sad): The window to activate doesn't necessarily have to be a direct - // ancestor (e.g. could be a transient parent). - SetActiveWindow(GetActivatableAncestorOf(window), - ActivationChangeReason::FOCUS); - - for (auto& observer : observers_) - observer.OnFocusChanged(change_source, old_focused, window); - - focused_window_ = window; - // We can currently use only a single ServerWindowDrawnTracker since focused - // window is expected to be a direct descendant of the active window. - if (focused_window_ && active_window_) { - DCHECK(active_window_->Contains(focused_window_)); - } - ServerWindow* track_window = focused_window_; - if (!track_window) - track_window = active_window_; - if (track_window) { - drawn_tracker_ = - std::make_unique<ServerWindowDrawnTracker>(track_window, this); - } else { - drawn_tracker_.reset(); - } - return true; -} - -void FocusController::ProcessDrawnOrRootChange(ServerWindow* ancestor, - ServerWindow* window) { - drawn_tracker_.reset(); - - // Find the window that triggered this state-change notification. - ServerWindow* trigger = window; - while (trigger->parent() != ancestor) - trigger = trigger->parent(); - DCHECK(trigger); - auto will_be_hidden = [trigger](ServerWindow* w) { - return trigger->Contains(w); - }; - - // If |window| is |active_window_|, then activate the next activatable window - // that does not belong to the subtree which is getting hidden. - if (window == active_window_) { - WindowTreeIterator iter(root_); - ServerWindow* activate = active_window_; - do { - activate = iter.GetNext(activate); - } while (activate != active_window_ && - (will_be_hidden(activate) || !CanBeActivated(activate))); - if (activate == window) - activate = nullptr; - SetActiveWindow(activate, ActivationChangeReason::DRAWN_STATE_CHANGED); - - // Now make sure focus is in the active window. - ServerWindow* focus = nullptr; - if (active_window_) { - WindowTreeIterator iter(active_window_); - focus = nullptr; - do { - focus = iter.GetNext(focus); - } while (focus != active_window_ && - (will_be_hidden(focus) || !CanBeFocused(focus))); - DCHECK(focus && CanBeFocused(focus)); - } - SetFocusedWindowImpl(FocusControllerChangeSource::DRAWN_STATE_CHANGED, - focus); - return; - } - - // Move focus to the next focusable window in |active_window_|. - DCHECK_EQ(focused_window_, window); - WindowTreeIterator iter(active_window_); - ServerWindow* focus = focused_window_; - do { - focus = iter.GetNext(focus); - } while (focus != focused_window_ && - (will_be_hidden(focus) || !CanBeFocused(focus))); - if (focus == window) - focus = nullptr; - SetFocusedWindowImpl(FocusControllerChangeSource::DRAWN_STATE_CHANGED, focus); -} - -void FocusController::OnDrawnStateWillChange(ServerWindow* ancestor, - ServerWindow* window, - bool is_drawn) { - DCHECK(!is_drawn); - DCHECK_NE(ancestor, window); - DCHECK(root_->Contains(window)); - ProcessDrawnOrRootChange(ancestor, window); -} - -void FocusController::OnDrawnStateChanged(ServerWindow* ancestor, - ServerWindow* window, - bool is_drawn) { - // DCHECK(false); TODO(sadrul): -} - -void FocusController::OnRootWillChange(ServerWindow* ancestor, - ServerWindow* window) { - ProcessDrawnOrRootChange(ancestor, window); -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/focus_controller.h b/services/ui/ws/focus_controller.h deleted file mode 100644 index 80e5beb..0000000 --- a/services/ui/ws/focus_controller.h +++ /dev/null
@@ -1,96 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SERVICES_UI_WS_FOCUS_CONTROLLER_H_ -#define SERVICES_UI_WS_FOCUS_CONTROLLER_H_ - -#include <memory> - -#include "base/macros.h" -#include "base/observer_list.h" -#include "services/ui/ws/server_window_drawn_tracker_observer.h" -#include "services/ui/ws/server_window_tracker.h" - -namespace ui { - -namespace ws { - -class FocusControllerObserver; -class ServerWindow; -class ServerWindowDrawnTracker; - -// Describes the source of the change. -enum class FocusControllerChangeSource { - EXPLICIT, - DRAWN_STATE_CHANGED, -}; - -// Tracks the focused window. Focus is moved to another window when the drawn -// state of the focused window changes. -class FocusController : public ServerWindowDrawnTrackerObserver { - public: - explicit FocusController(ServerWindow* root); - ~FocusController() override; - - // Sets the focused window. Does nothing if |window| is currently focused. - // This does not notify the delegate. See ServerWindow::SetFocusedWindow() - // for details on return value. - bool SetFocusedWindow(ServerWindow* window); - ServerWindow* GetFocusedWindow(); - - void AddObserver(FocusControllerObserver* observer); - void RemoveObserver(FocusControllerObserver* observer); - - private: - enum class ActivationChangeReason { - UNKNOWN, - FOCUS, // Focus change required a different window to be activated. - DRAWN_STATE_CHANGED, // Active window was hidden or destroyed. - }; - void SetActiveWindow(ServerWindow* window, ActivationChangeReason reason); - - // Returns whether |window| can be focused or activated. - bool CanBeFocused(ServerWindow* window) const; - bool CanBeActivated(ServerWindow* window) const; - - // Returns the closest activatable ancestor of |window|. Returns nullptr if - // there is no such ancestor. - ServerWindow* GetActivatableAncestorOf(ServerWindow* window) const; - - // Implementation of SetFocusedWindow(). - bool SetFocusedWindowImpl(FocusControllerChangeSource change_source, - ServerWindow* window); - - // Called internally when the drawn state or root changes. |ancestor| is - // the |ancestor| argument from those two functions, see them for details. - void ProcessDrawnOrRootChange(ServerWindow* ancestor, ServerWindow* window); - - // ServerWindowDrawnTrackerObserver: - void OnDrawnStateWillChange(ServerWindow* ancestor, - ServerWindow* window, - bool is_drawn) override; - void OnDrawnStateChanged(ServerWindow* ancestor, - ServerWindow* window, - bool is_drawn) override; - void OnRootWillChange(ServerWindow* ancestor, ServerWindow* window) override; - - ServerWindow* root_; - ServerWindow* focused_window_; - ServerWindow* active_window_; - // Tracks what caused |active_window_| to be activated. - ActivationChangeReason activation_reason_; - - base::ObserverList<FocusControllerObserver> observers_; - - // Keeps track of the visibility of the focused and active window. - std::unique_ptr<ServerWindowDrawnTracker> drawn_tracker_; - - DISALLOW_COPY_AND_ASSIGN(FocusController); -}; - -} // namespace ws - -} // namespace ui - -#endif // SERVICES_UI_WS_FOCUS_CONTROLLER_H_
diff --git a/services/ui/ws/focus_controller_observer.h b/services/ui/ws/focus_controller_observer.h deleted file mode 100644 index ab49b42..0000000 --- a/services/ui/ws/focus_controller_observer.h +++ /dev/null
@@ -1,29 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SERVICES_UI_WS_FOCUS_CONTROLLER_OBSERVER_H_ -#define SERVICES_UI_WS_FOCUS_CONTROLLER_OBSERVER_H_ - -namespace ui { -namespace ws { - -enum class FocusControllerChangeSource; -class ServerWindow; - -class FocusControllerObserver { - public: - virtual void OnActivationChanged(ServerWindow* old_active_window, - ServerWindow* new_active_window) = 0; - virtual void OnFocusChanged(FocusControllerChangeSource change_source, - ServerWindow* old_focused_window, - ServerWindow* new_focused_window) = 0; - - protected: - ~FocusControllerObserver() {} -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_FOCUS_CONTROLLER_OBSERVER_H_
diff --git a/services/ui/ws/focus_controller_unittest.cc b/services/ui/ws/focus_controller_unittest.cc deleted file mode 100644 index 4b8498f..0000000 --- a/services/ui/ws/focus_controller_unittest.cc +++ /dev/null
@@ -1,225 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "services/ui/ws/focus_controller.h" - -#include <stddef.h> -#include <stdint.h> - -#include "base/macros.h" -#include "services/ui/ws/focus_controller_observer.h" -#include "services/ui/ws/server_window.h" -#include "services/ui/ws/test_server_window_delegate.h" -#include "services/ui/ws/test_utils.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace ui { - -namespace ws { -namespace { - -class TestFocusControllerObserver : public FocusControllerObserver { - public: - TestFocusControllerObserver() - : ignore_explicit_(true), - focus_change_count_(0u), - old_focused_window_(nullptr), - new_focused_window_(nullptr), - old_active_window_(nullptr), - new_active_window_(nullptr) {} - - void ClearAll() { - focus_change_count_ = 0u; - old_focused_window_ = nullptr; - new_focused_window_ = nullptr; - old_active_window_ = nullptr; - new_active_window_ = nullptr; - } - size_t focus_change_count() const { return focus_change_count_; } - ServerWindow* old_focused_window() { return old_focused_window_; } - ServerWindow* new_focused_window() { return new_focused_window_; } - - ServerWindow* old_active_window() { return old_active_window_; } - ServerWindow* new_active_window() { return new_active_window_; } - - void set_ignore_explicit(bool ignore) { ignore_explicit_ = ignore; } - - private: - // FocusControllerObserver: - void OnActivationChanged(ServerWindow* old_active_window, - ServerWindow* new_active_window) override { - old_active_window_ = old_active_window; - new_active_window_ = new_active_window; - } - void OnFocusChanged(FocusControllerChangeSource source, - ServerWindow* old_focused_window, - ServerWindow* new_focused_window) override { - if (ignore_explicit_ && source == FocusControllerChangeSource::EXPLICIT) - return; - - focus_change_count_++; - old_focused_window_ = old_focused_window; - new_focused_window_ = new_focused_window; - } - - bool ignore_explicit_; - size_t focus_change_count_; - ServerWindow* old_focused_window_; - ServerWindow* new_focused_window_; - ServerWindow* old_active_window_; - ServerWindow* new_active_window_; - - DISALLOW_COPY_AND_ASSIGN(TestFocusControllerObserver); -}; - -} // namespace - -class FocusControllerTest : public testing::Test { - public: - FocusControllerTest() {} - ~FocusControllerTest() override {} - - VizHostProxy* viz_host_proxy() { - return ws_test_helper_.window_server()->GetVizHostProxy(); - } - - private: - test::WindowServerTestHelper ws_test_helper_; - - DISALLOW_COPY_AND_ASSIGN(FocusControllerTest); -}; - -TEST_F(FocusControllerTest, Basic) { - TestServerWindowDelegate server_window_delegate(viz_host_proxy()); - ServerWindow root(&server_window_delegate, viz::FrameSinkId(1, 1)); - server_window_delegate.set_root_window(&root); - root.SetVisible(true); - root.set_is_activation_parent(true); - ServerWindow child(&server_window_delegate, viz::FrameSinkId(1, 2)); - child.SetVisible(true); - child.set_is_activation_parent(true); - root.Add(&child); - ServerWindow child_child(&server_window_delegate, viz::FrameSinkId(1, 3)); - child_child.SetVisible(true); - child.Add(&child_child); - child_child.set_is_activation_parent(true); - - // Sibling of |child|. - ServerWindow child2(&server_window_delegate, viz::FrameSinkId(1, 4)); - child2.SetVisible(true); - root.Add(&child2); - - TestFocusControllerObserver focus_observer; - FocusController focus_controller(&root); - focus_controller.AddObserver(&focus_observer); - - focus_controller.SetFocusedWindow(&child_child); - EXPECT_EQ(0u, focus_observer.focus_change_count()); - - // Remove the ancestor of the focused window, focus should go to |child2|. - root.Remove(&child); - EXPECT_EQ(1u, focus_observer.focus_change_count()); - EXPECT_EQ(&child2, focus_observer.new_focused_window()); - EXPECT_EQ(&child_child, focus_observer.old_focused_window()); - focus_observer.ClearAll(); - - // Make the focused window invisible. Focus is lost in this case (as no one - // to give focus to). - child2.SetVisible(false); - EXPECT_EQ(1u, focus_observer.focus_change_count()); - EXPECT_EQ(nullptr, focus_observer.new_focused_window()); - EXPECT_EQ(&child2, focus_observer.old_focused_window()); - focus_observer.ClearAll(); - - // Go back to initial state and focus |child_child|. - child2.SetVisible(false); - root.Add(&child); - focus_controller.SetFocusedWindow(&child_child); - EXPECT_EQ(0u, focus_observer.focus_change_count()); - - // Hide the focused window, focus should go to parent. - child_child.SetVisible(false); - EXPECT_EQ(1u, focus_observer.focus_change_count()); - EXPECT_EQ(&child, focus_observer.new_focused_window()); - EXPECT_EQ(&child_child, focus_observer.old_focused_window()); - focus_observer.ClearAll(); - - child_child.SetVisible(true); - focus_controller.SetFocusedWindow(&child_child); - EXPECT_EQ(0u, focus_observer.focus_change_count()); - - // Hide the parent of the focused window, focus is lost as there no visible - // windows to move focus to. - child.SetVisible(false); - EXPECT_EQ(1u, focus_observer.focus_change_count()); - EXPECT_EQ(nullptr, focus_observer.new_focused_window()); - EXPECT_EQ(&child_child, focus_observer.old_focused_window()); - focus_observer.ClearAll(); - focus_controller.RemoveObserver(&focus_observer); -} - -namespace { - -// ServerWindowDelegate implementation whose GetRootWindow() implementation -// returns the last ancestor as the root of a window. -class TestServerWindowDelegate2 : public ServerWindowDelegate { - public: - explicit TestServerWindowDelegate2(VizHostProxy* viz_host_proxy) - : viz_host_proxy_(viz_host_proxy) {} - ~TestServerWindowDelegate2() override = default; - - // ServerWindowDelegate: - VizHostProxy* GetVizHostProxy() override { return viz_host_proxy_; } - ServerWindow* GetRootWindowForDrawn(const ServerWindow* window) override { - const ServerWindow* root = window; - while (root && root->parent()) - root = root->parent(); - // TODO(sky): this cast shouldn't be necessary! - return const_cast<ServerWindow*>(root); - } - void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info, - ServerWindow* window) override {} - - private: - VizHostProxy* viz_host_proxy_ = nullptr; - - DISALLOW_COPY_AND_ASSIGN(TestServerWindowDelegate2); -}; - -} // namespace - -TEST_F(FocusControllerTest, ActiveWindowMovesToDifferentDisplay) { - TestServerWindowDelegate2 server_window_delegate(viz_host_proxy()); - ServerWindow root1(&server_window_delegate, viz::FrameSinkId(1, 1)); - root1.SetVisible(true); - root1.set_is_activation_parent(true); - ServerWindow root2(&server_window_delegate, viz::FrameSinkId(1, 2)); - root2.SetVisible(true); - root2.set_is_activation_parent(true); - - ServerWindow child(&server_window_delegate, viz::FrameSinkId(1, 3)); - root1.Add(&child); - child.SetVisible(true); - child.set_is_activation_parent(true); - - ServerWindow child_child(&server_window_delegate, viz::FrameSinkId(1, 4)); - child.Add(&child_child); - child_child.SetVisible(true); - - TestFocusControllerObserver focus_observer; - focus_observer.set_ignore_explicit(false); - FocusController focus_controller(&root1); - focus_controller.AddObserver(&focus_observer); - - focus_controller.SetFocusedWindow(&child_child); - EXPECT_EQ(&child_child, focus_controller.GetFocusedWindow()); - - root2.Add(&child_child); - // As the focused window is moving to a different root focus should move - // to the parent of the old focused window. - EXPECT_EQ(&child, focus_controller.GetFocusedWindow()); -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/frame_generator.cc b/services/ui/ws/frame_generator.cc deleted file mode 100644 index bf0bee4..0000000 --- a/services/ui/ws/frame_generator.cc +++ /dev/null
@@ -1,247 +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 "services/ui/ws/frame_generator.h" - -#include <utility> -#include <vector> - -#include "components/viz/common/quads/compositor_frame.h" -#include "components/viz/common/quads/render_pass.h" -#include "components/viz/common/quads/render_pass_draw_quad.h" -#include "components/viz/common/quads/shared_quad_state.h" -#include "components/viz/common/quads/surface_draw_quad.h" -#include "ui/gfx/geometry/size_f.h" - -namespace ui { -namespace ws { - -FrameGenerator::FrameGenerator() = default; - -FrameGenerator::~FrameGenerator() = default; - -void FrameGenerator::SetDeviceScaleFactor(float device_scale_factor) { - if (device_scale_factor_ == device_scale_factor) - return; - device_scale_factor_ = device_scale_factor; - SetNeedsBeginFrame(true); -} - -void FrameGenerator::SetHighContrastMode(bool enabled) { - if (high_contrast_mode_enabled_ == enabled) - return; - - high_contrast_mode_enabled_ = enabled; - SetNeedsBeginFrame(true); -} - -void FrameGenerator::SetEmbeddedSurface(const viz::SurfaceInfo& surface_info) { - DCHECK(surface_info.is_valid()); - - // Only handle embedded surfaces changing here. The display root surface - // changing is handled immediately after the CompositorFrame is submitted. - if (surface_info != window_manager_surface_info_) { - window_manager_surface_info_ = surface_info; - SetNeedsBeginFrame(true); - } -} - -void FrameGenerator::SwapSurfaceWith(FrameGenerator* other) { - viz::SurfaceInfo window_manager_surface_info = window_manager_surface_info_; - window_manager_surface_info_ = other->window_manager_surface_info_; - other->window_manager_surface_info_ = window_manager_surface_info; - if (window_manager_surface_info_.is_valid()) - SetNeedsBeginFrame(true); - if (other->window_manager_surface_info_.is_valid()) - other->SetNeedsBeginFrame(true); -} - -void FrameGenerator::OnWindowDamaged() { - SetNeedsBeginFrame(true); -} - -void FrameGenerator::OnWindowSizeChanged(const gfx::Size& pixel_size) { - if (pixel_size_ == pixel_size) - return; - - pixel_size_ = pixel_size; - SetNeedsBeginFrame(true); - display_private_->Resize(pixel_size); -} - -void FrameGenerator::Bind( - std::unique_ptr<viz::mojom::CompositorFrameSink> compositor_frame_sink, - viz::mojom::DisplayPrivateAssociatedPtr display_private) { - DCHECK(!compositor_frame_sink_); - compositor_frame_sink_ = std::move(compositor_frame_sink); - display_private_ = std::move(display_private); -} - -void FrameGenerator::ReclaimResources( - const std::vector<viz::ReturnedResource>& resources) { - // Nothing to do here because FrameGenerator CompositorFrames don't reference - // any resources. - DCHECK(resources.empty()); -} - -void FrameGenerator::DidReceiveCompositorFrameAck( - const std::vector<viz::ReturnedResource>& resources) {} - -void FrameGenerator::DidPresentCompositorFrame( - uint32_t presentation_token, - const gfx::PresentationFeedback& feedback) { - NOTIMPLEMENTED(); -} - -void FrameGenerator::OnBeginFrame(const viz::BeginFrameArgs& begin_frame_args) { - DCHECK(compositor_frame_sink_); - current_begin_frame_ack_ = viz::BeginFrameAck(begin_frame_args, false); - if (begin_frame_args.type == viz::BeginFrameArgs::MISSED) { - compositor_frame_sink_->DidNotProduceFrame(current_begin_frame_ack_); - return; - } - - current_begin_frame_ack_.has_damage = true; - last_begin_frame_args_ = begin_frame_args; - - // TODO(fsamuel): We should add a trace for generating a top level frame. - viz::CompositorFrame frame(GenerateCompositorFrame()); - if (!id_allocator_.GetCurrentLocalSurfaceId().is_valid() || - frame.size_in_pixels() != last_submitted_frame_size_ || - frame.device_scale_factor() != last_device_scale_factor_) { - last_device_scale_factor_ = frame.device_scale_factor(); - last_submitted_frame_size_ = frame.size_in_pixels(); - id_allocator_.GenerateId(); - } - - compositor_frame_sink_->SubmitCompositorFrame( - id_allocator_.GetCurrentLocalSurfaceId(), std::move(frame), - GenerateHitTestRegionList(), 0); - - SetNeedsBeginFrame(false); -} - -viz::CompositorFrame FrameGenerator::GenerateCompositorFrame() { - const int render_pass_id = 1; - const gfx::Rect bounds(pixel_size_); - std::unique_ptr<viz::RenderPass> render_pass = viz::RenderPass::Create(); - render_pass->SetNew(render_pass_id, bounds, bounds, gfx::Transform()); - - DrawWindow(render_pass.get()); - - viz::CompositorFrame frame; - frame.render_pass_list.push_back(std::move(render_pass)); - if (high_contrast_mode_enabled_) { - std::unique_ptr<viz::RenderPass> invert_pass = viz::RenderPass::Create(); - invert_pass->SetNew(2, bounds, bounds, gfx::Transform()); - viz::SharedQuadState* shared_state = - invert_pass->CreateAndAppendSharedQuadState(); - gfx::Size scaled_bounds = gfx::ScaleToCeiledSize( - pixel_size_, window_manager_surface_info_.device_scale_factor(), - window_manager_surface_info_.device_scale_factor()); - bool is_clipped = false; - bool are_contents_opaque = false; - shared_state->SetAll(gfx::Transform(), gfx::Rect(scaled_bounds), bounds, - bounds, is_clipped, are_contents_opaque, 1.f, - SkBlendMode::kSrcOver, 0); - auto* quad = - invert_pass->CreateAndAppendDrawQuad<viz::RenderPassDrawQuad>(); - frame.render_pass_list.back()->filters.Append( - cc::FilterOperation::CreateInvertFilter(1.f)); - quad->SetNew( - shared_state, bounds, bounds, render_pass_id, 0 /* mask_resource_id */, - gfx::RectF() /* mask_uv_rect */, gfx::Size() /* mask_texture_size */, - gfx::Vector2dF() /* filters_scale */, - gfx::PointF() /* filters_origin */, gfx::RectF() /* tex_coord_rect */, - false /* force_anti_aliasing_off */); - frame.render_pass_list.push_back(std::move(invert_pass)); - } - frame.metadata.device_scale_factor = device_scale_factor_; - frame.metadata.begin_frame_ack = current_begin_frame_ack_; - - if (window_manager_surface_info_.is_valid()) { - frame.metadata.referenced_surfaces.push_back( - viz::SurfaceRange(window_manager_surface_info_.id())); - } - - return frame; -} - -viz::HitTestRegionList FrameGenerator::GenerateHitTestRegionList() const { - viz::HitTestRegionList hit_test_region_list; - hit_test_region_list.flags = viz::HitTestRegionFlags::kHitTestMine; - hit_test_region_list.bounds.set_size(pixel_size_); - - viz::HitTestRegion hit_test_region; - hit_test_region.frame_sink_id = - window_manager_surface_info_.id().frame_sink_id(); - hit_test_region.flags = viz::HitTestRegionFlags::kHitTestChildSurface; - hit_test_region.rect = gfx::Rect(pixel_size_); - - hit_test_region_list.regions.push_back(std::move(hit_test_region)); - - return hit_test_region_list; -} - -void FrameGenerator::DrawWindow(viz::RenderPass* pass) { - DCHECK(window_manager_surface_info_.is_valid()); - - const gfx::Rect bounds_at_origin( - window_manager_surface_info_.size_in_pixels()); - - gfx::Transform quad_to_target_transform; - - if (scale_and_center_) { - // Determine the scaling to fit the source within the target. - gfx::SizeF source(window_manager_surface_info_.size_in_pixels()); - const gfx::SizeF target(pixel_size_); - const float scale = std::min(target.width() / source.width(), - target.height() / source.height()); - - // Apply the transform to center the source within the output. - source.Scale(scale); - DCHECK(source.width() <= target.width() || - source.height() <= target.height()); - if (source.width() < target.width()) { - quad_to_target_transform.Translate( - (target.width() - source.width()) / 2.0f, 0); - } else if (source.height() < target.height()) { - quad_to_target_transform.Translate( - 0, (target.height() - source.height()) / 2.0f); - } - - // Apply the scaling after the transform. - quad_to_target_transform.Scale(scale, scale); - } - - viz::SharedQuadState* sqs = pass->CreateAndAppendSharedQuadState(); - - gfx::Size scaled_bounds = gfx::ScaleToCeiledSize( - bounds_at_origin.size(), - window_manager_surface_info_.device_scale_factor(), - window_manager_surface_info_.device_scale_factor()); - - // TODO(fsamuel): These clipping and visible rects are incorrect. They need - // to be populated from CompositorFrame structs. - sqs->SetAll(quad_to_target_transform, - gfx::Rect(scaled_bounds) /* layer_rect */, - bounds_at_origin /* visible_layer_bounds */, - bounds_at_origin /* clip_rect */, false /* is_clipped */, - false /* are_contents_opaque */, 1.0f /* opacity */, - SkBlendMode::kSrcOver, 0 /* sorting-context_id */); - auto* quad = pass->CreateAndAppendDrawQuad<viz::SurfaceDrawQuad>(); - quad->SetAll(sqs, bounds_at_origin /* rect */, - bounds_at_origin /* visible_rect */, true /* needs_blending*/, - viz::SurfaceRange(window_manager_surface_info_.id()), - SK_ColorWHITE /* default_background_color */, - false /* stretch_content_to_fill_bounds */); -} - -void FrameGenerator::SetNeedsBeginFrame(bool needs_begin_frame) { - needs_begin_frame &= window_manager_surface_info_.is_valid(); - compositor_frame_sink_->SetNeedsBeginFrame(needs_begin_frame); -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/frame_generator.h b/services/ui/ws/frame_generator.h deleted file mode 100644 index 998f2a3..0000000 --- a/services/ui/ws/frame_generator.h +++ /dev/null
@@ -1,100 +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. - -#ifndef SERVICES_UI_WS_FRAME_GENERATOR_H_ -#define SERVICES_UI_WS_FRAME_GENERATOR_H_ - -#include <memory> - -#include "base/macros.h" -#include "components/viz/common/frame_sinks/begin_frame_source.h" -#include "components/viz/common/hit_test/hit_test_region_list.h" -#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h" -#include "components/viz/common/surfaces/surface_id.h" -#include "components/viz/common/surfaces/surface_info.h" -#include "services/ui/ws/compositor_frame_sink_client_binding.h" -#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h" -#include "ui/gfx/geometry/rect.h" - -namespace cc { -class RenderPass; -} - -namespace ui { -namespace ws { - -// Responsible for redrawing the display in response to the redraw requests by -// submitting CompositorFrames to the owned CompositorFrameSink. -class FrameGenerator : public viz::mojom::CompositorFrameSinkClient { - public: - FrameGenerator(); - ~FrameGenerator() override; - - void SetDeviceScaleFactor(float device_scale_factor); - void SetHighContrastMode(bool enabled); - - // Updates the WindowManager's SurfaceInfo. - void SetEmbeddedSurface(const viz::SurfaceInfo& surface_info); - - // Swaps the |window_manager_surface_info_| with that of |other|. - void SwapSurfaceWith(FrameGenerator* other); - - void OnWindowDamaged(); - void OnWindowSizeChanged(const gfx::Size& pixel_size); - void Bind( - std::unique_ptr<viz::mojom::CompositorFrameSink> compositor_frame_sink, - viz::mojom::DisplayPrivateAssociatedPtr display_private); - - const viz::SurfaceInfo& window_manager_surface_info() const { - return window_manager_surface_info_; - } - - void set_scale_and_center(bool value) { scale_and_center_ = value; } - - private: - // viz::mojom::CompositorFrameSinkClient implementation: - void DidReceiveCompositorFrameAck( - const std::vector<viz::ReturnedResource>& resources) override; - void DidPresentCompositorFrame( - uint32_t presentation_token, - const gfx::PresentationFeedback& feedback) override; - void OnBeginFrame(const viz::BeginFrameArgs& args) override; - void OnBeginFramePausedChanged(bool paused) override {} - void ReclaimResources( - const std::vector<viz::ReturnedResource>& resources) override; - - viz::CompositorFrame GenerateCompositorFrame(); - - viz::HitTestRegionList GenerateHitTestRegionList() const; - - // DrawWindow creates SurfaceDrawQuad for the window manager and appends it to - // the provided viz::RenderPass. - void DrawWindow(viz::RenderPass* pass); - - void SetNeedsBeginFrame(bool needs_begin_frame); - - float device_scale_factor_ = 1.f; - gfx::Size pixel_size_; - - std::unique_ptr<viz::mojom::CompositorFrameSink> compositor_frame_sink_; - viz::mojom::DisplayPrivateAssociatedPtr display_private_; - viz::BeginFrameArgs last_begin_frame_args_; - viz::BeginFrameAck current_begin_frame_ack_; - bool high_contrast_mode_enabled_ = false; - gfx::Size last_submitted_frame_size_; - viz::ParentLocalSurfaceIdAllocator id_allocator_; - float last_device_scale_factor_ = 0.0f; - - viz::SurfaceInfo window_manager_surface_info_; - - // Whether the window manager surface should be scaled and centered. - bool scale_and_center_ = false; - - DISALLOW_COPY_AND_ASSIGN(FrameGenerator); -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_FRAME_GENERATOR_H_
diff --git a/services/ui/ws/frame_generator_unittest.cc b/services/ui/ws/frame_generator_unittest.cc deleted file mode 100644 index c50f5900..0000000 --- a/services/ui/ws/frame_generator_unittest.cc +++ /dev/null
@@ -1,311 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "services/ui/ws/frame_generator.h" - -#include "base/macros.h" -#include "base/test/scoped_task_environment.h" -#include "components/viz/common/frame_sinks/begin_frame_source.h" -#include "components/viz/common/quads/render_pass.h" -#include "components/viz/test/begin_frame_args_test.h" -#include "components/viz/test/fake_external_begin_frame_source.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace ui { -namespace ws { -namespace test { - -namespace { - -constexpr float kRefreshRate = 0.f; -constexpr bool kTickAutomatically = false; -constexpr float kDefaultScaleFactor = 1.0f; -constexpr float kArbitraryScaleFactor = 0.5f; -constexpr gfx::Size kArbitrarySize(3, 4); -constexpr gfx::Size kAnotherArbitrarySize(5, 6); -const viz::SurfaceId kArbitrarySurfaceId( - viz::FrameSinkId(1, 1), - viz::LocalSurfaceId(1, base::UnguessableToken::Create())); -const viz::SurfaceInfo kArbitrarySurfaceInfo(kArbitrarySurfaceId, - 1.0f, - gfx::Size(100, 100)); -} - -// TestClientBinding Observes a BeginFrame and accepts CompositorFrame submitted -// from FrameGenerator. It provides a way to inspect CompositorFrames. -class TestClientBinding : public viz::mojom::CompositorFrameSink, - public viz::BeginFrameObserver { - public: - explicit TestClientBinding(viz::mojom::CompositorFrameSinkClient* sink_client) - : sink_client_(sink_client) {} - ~TestClientBinding() override = default; - - // viz::mojom::CompositorFrameSink implementation: - void SubmitCompositorFrame( - const viz::LocalSurfaceId& local_surface_id, - viz::CompositorFrame frame, - base::Optional<viz::HitTestRegionList> hit_test_region_list, - uint64_t submit_time) override { - ++frames_submitted_; - last_frame_ = std::move(frame); - last_begin_frame_ack_ = last_frame_.metadata.begin_frame_ack; - } - - void SubmitCompositorFrameSync( - const viz::LocalSurfaceId& local_surface_id, - viz::CompositorFrame frame, - base::Optional<viz::HitTestRegionList> hit_test_region_list, - uint64_t submit_time, - SubmitCompositorFrameSyncCallback callback) override {} - - void DidNotProduceFrame(const viz::BeginFrameAck& ack) override { - last_begin_frame_ack_ = ack; - } - - void DidAllocateSharedBitmap(mojo::ScopedSharedBufferHandle buffer, - const viz::SharedBitmapId& id) override {} - - void DidDeleteSharedBitmap(const viz::SharedBitmapId& id) override {} - - void SetNeedsBeginFrame(bool needs_begin_frame) override { - if (needs_begin_frame == observing_begin_frames_) - return; - - observing_begin_frames_ = needs_begin_frame; - if (needs_begin_frame) { - begin_frame_source_->AddObserver(this); - } else { - begin_frame_source_->RemoveObserver(this); - } - } - - void SetWantsAnimateOnlyBeginFrames() override {} - - // viz::BeginFrameObserver implementation. - void OnBeginFrame(const viz::BeginFrameArgs& args) override { - sink_client_->OnBeginFrame(args); - last_begin_frame_args_ = args; - } - - const viz::BeginFrameArgs& LastUsedBeginFrameArgs() const override { - return last_begin_frame_args_; - } - - bool WantsAnimateOnlyBeginFrames() const override { return false; } - - void OnBeginFrameSourcePausedChanged(bool paused) override {} - - void SetBeginFrameSource(viz::BeginFrameSource* begin_frame_source) { - begin_frame_source_ = begin_frame_source; - } - - const viz::RenderPassList& last_render_pass_list() const { - return last_frame_.render_pass_list; - } - - const viz::CompositorFrameMetadata& last_metadata() const { - return last_frame_.metadata; - } - - int frames_submitted() const { return frames_submitted_; } - - const viz::BeginFrameAck& last_begin_frame_ack() const { - return last_begin_frame_ack_; - } - - private: - viz::mojom::CompositorFrameSinkClient* sink_client_; - viz::BeginFrameArgs last_begin_frame_args_; - viz::CompositorFrame last_frame_; - viz::BeginFrameSource* begin_frame_source_ = nullptr; - bool observing_begin_frames_ = false; - int frames_submitted_ = 0; - viz::BeginFrameAck last_begin_frame_ack_; -}; - -class FrameGeneratorTest : public testing::Test { - public: - FrameGeneratorTest() = default; - ~FrameGeneratorTest() override = default; - - // testing::Test overrides: - void SetUp() override { - testing::Test::SetUp(); - - frame_generator_ = std::make_unique<FrameGenerator>(); - begin_frame_source_ = std::make_unique<viz::FakeExternalBeginFrameSource>( - kRefreshRate, kTickAutomatically); - - // FrameGenerator requires a valid SurfaceInfo before generating - // CompositorFrames. - std::unique_ptr<TestClientBinding> client_binding = - std::make_unique<TestClientBinding>(frame_generator_.get()); - binding_ = client_binding.get(); - IssueBeginFrame(); - - // FrameGenerator does not request BeginFrames right after creation. - EXPECT_EQ(0, NumberOfFramesReceived()); - client_binding->SetBeginFrameSource(begin_frame_source_.get()); - viz::mojom::DisplayPrivateAssociatedPtr display_private; - mojo::MakeRequestAssociatedWithDedicatedPipe(&display_private); - frame_generator_->Bind(std::move(client_binding), - std::move(display_private)); - }; - - // InitWithSurfaceInfo creates a TestClientBinding and binds it to - // |frame_generator_|. After InitWithSurfaceInfo finishes, |frame_generator_| - // has a valid SurfaceInfo and does not request BeginFrames. - void InitWithSurfaceInfo() { - frame_generator_->SetEmbeddedSurface(kArbitrarySurfaceInfo); - - // Issue a BeginFrame so that frame_generator_ stops requesting BeginFrames - // after submitting a CompositorFrame. - IssueBeginFrame(); - EXPECT_EQ(1, NumberOfFramesReceived()); - } - - void IssueBeginFrame() { - begin_frame_source_->TestOnBeginFrame(viz::CreateBeginFrameArgsForTesting( - BEGINFRAME_FROM_HERE, 0, next_sequence_number_)); - ++next_sequence_number_; - } - - int NumberOfFramesReceived() const { return binding_->frames_submitted(); } - - const viz::BeginFrameAck& LastBeginFrameAck() const { - return binding_->last_begin_frame_ack(); - } - - const viz::CompositorFrameMetadata& LastMetadata() const { - return binding_->last_metadata(); - } - - const viz::RenderPassList& LastRenderPassList() const { - return binding_->last_render_pass_list(); - } - - FrameGenerator* frame_generator() { return frame_generator_.get(); } - viz::BeginFrameSource* begin_frame_source() { - return begin_frame_source_.get(); - } - - TestClientBinding* binding() { return binding_; } - - private: - base::test::ScopedTaskEnvironment scoped_task_environment_; - std::unique_ptr<viz::FakeExternalBeginFrameSource> begin_frame_source_; - std::unique_ptr<FrameGenerator> frame_generator_; - TestClientBinding* binding_ = nullptr; - int next_sequence_number_ = 1; - - DISALLOW_COPY_AND_ASSIGN(FrameGeneratorTest); -}; - -// FrameGenerator has an invalid SurfaceInfo as default. FrameGenerator does not -// submit CompositorFrames when its SurfaceInfo is invalid. -TEST_F(FrameGeneratorTest, InvalidSurfaceInfo) { - IssueBeginFrame(); - EXPECT_EQ(0, NumberOfFramesReceived()); - EXPECT_EQ(viz::BeginFrameAck(), LastBeginFrameAck()); -} - -TEST_F(FrameGeneratorTest, OnFirstSurfaceActivation) { - InitWithSurfaceInfo(); - - // Verify that the CompositorFrame refers to the window manager's surface via - // referenced_surfaces. - const viz::CompositorFrameMetadata& last_metadata = LastMetadata(); - const std::vector<viz::SurfaceRange>& referenced_surfaces = - last_metadata.referenced_surfaces; - EXPECT_EQ(1lu, referenced_surfaces.size()); - EXPECT_EQ(viz::SurfaceRange(kArbitrarySurfaceId), - referenced_surfaces.front()); - - viz::BeginFrameAck expected_ack(0, 2, true); - EXPECT_EQ(expected_ack, LastBeginFrameAck()); - EXPECT_EQ(expected_ack, last_metadata.begin_frame_ack); - - // FrameGenerator stops requesting BeginFrames after submitting a - // CompositorFrame. - IssueBeginFrame(); - EXPECT_EQ(expected_ack, LastBeginFrameAck()); -} - -TEST_F(FrameGeneratorTest, SetDeviceScaleFactor) { - InitWithSurfaceInfo(); - - // FrameGenerator does not request BeginFrames if its device scale factor - // remains unchanged. - frame_generator()->SetDeviceScaleFactor(kDefaultScaleFactor); - IssueBeginFrame(); - EXPECT_EQ(1, NumberOfFramesReceived()); - const viz::CompositorFrameMetadata& last_metadata = LastMetadata(); - EXPECT_EQ(kDefaultScaleFactor, last_metadata.device_scale_factor); - - frame_generator()->SetDeviceScaleFactor(kArbitraryScaleFactor); - IssueBeginFrame(); - EXPECT_EQ(2, NumberOfFramesReceived()); - const viz::CompositorFrameMetadata& second_last_metadata = LastMetadata(); - EXPECT_EQ(kArbitraryScaleFactor, second_last_metadata.device_scale_factor); -} - -TEST_F(FrameGeneratorTest, SetHighContrastMode) { - InitWithSurfaceInfo(); - - // Changing high contrast mode should trigger a BeginFrame. - frame_generator()->SetHighContrastMode(true); - IssueBeginFrame(); - EXPECT_EQ(2, NumberOfFramesReceived()); - - // Verify that the last frame has an invert filter. - const viz::RenderPassList& render_pass_list = LastRenderPassList(); - const cc::FilterOperations expected_filters( - {cc::FilterOperation::CreateInvertFilter(1.f)}); - EXPECT_EQ(expected_filters, render_pass_list.front()->filters); -} - -TEST_F(FrameGeneratorTest, WindowBoundsChanged) { - InitWithSurfaceInfo(); - - // Window bounds change triggers a BeginFrame. - constexpr viz::RenderPassId expected_render_pass_id = 1u; - frame_generator()->OnWindowSizeChanged(kArbitrarySize); - IssueBeginFrame(); - EXPECT_EQ(2, NumberOfFramesReceived()); - viz::RenderPass* received_render_pass = LastRenderPassList().front().get(); - EXPECT_EQ(expected_render_pass_id, received_render_pass->id); - EXPECT_EQ(kArbitrarySize, received_render_pass->output_rect.size()); - EXPECT_EQ(kArbitrarySize, received_render_pass->damage_rect.size()); - EXPECT_EQ(gfx::Transform(), received_render_pass->transform_to_root_target); -} - -// Change window bounds twice before issuing a BeginFrame. The CompositorFrame -// submitted by frame_generator() should only has the second bounds. -TEST_F(FrameGeneratorTest, WindowBoundsChangedTwice) { - InitWithSurfaceInfo(); - - frame_generator()->OnWindowSizeChanged(kArbitrarySize); - frame_generator()->OnWindowSizeChanged(kAnotherArbitrarySize); - IssueBeginFrame(); - EXPECT_EQ(2, NumberOfFramesReceived()); - viz::RenderPass* received_render_pass = LastRenderPassList().front().get(); - EXPECT_EQ(kAnotherArbitrarySize, received_render_pass->output_rect.size()); - EXPECT_EQ(kAnotherArbitrarySize, received_render_pass->damage_rect.size()); - - // frame_generator() stops requesting BeginFrames after getting one. - IssueBeginFrame(); - EXPECT_EQ(2, NumberOfFramesReceived()); -} - -TEST_F(FrameGeneratorTest, WindowDamaged) { - InitWithSurfaceInfo(); - - frame_generator()->OnWindowDamaged(); - IssueBeginFrame(); - EXPECT_EQ(2, NumberOfFramesReceived()); -} - -} // namespace test -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/ids.h b/services/ui/ws/ids.h deleted file mode 100644 index 87a0b10..0000000 --- a/services/ui/ws/ids.h +++ /dev/null
@@ -1,35 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SERVICES_UI_WS_IDS_H_ -#define SERVICES_UI_WS_IDS_H_ - -#include <stdint.h> - -#include "components/viz/common/surfaces/frame_sink_id.h" -#include "services/ui/common/types.h" - -namespace ui { -namespace ws { - -// See comments in README.md (services/ui/ws/README.md) for details on ids. - -// A client id used to indicate no client. That is, no WindowTree ever gets this -// id. -const ClientSpecificId kInvalidClientId = 0; - -const Id kInvalidTransportId = 0; - -// Client id used to indicate the window was created by the WindowServer. -const ClientSpecificId kWindowServerClientId = 1; - -// Used for ids assigned by the client. -using ClientWindowId = viz::FrameSinkId; - -using ClientWindowIdHash = viz::FrameSinkIdHash; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_IDS_H_
diff --git a/services/ui/ws/modal_window_controller.cc b/services/ui/ws/modal_window_controller.cc deleted file mode 100644 index 5e986abe..0000000 --- a/services/ui/ws/modal_window_controller.cc +++ /dev/null
@@ -1,338 +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 "services/ui/ws/modal_window_controller.h" - -#include "base/stl_util.h" -#include "services/ui/public/interfaces/window_tree_constants.mojom.h" -#include "services/ui/ws/server_window.h" -#include "services/ui/ws/server_window_drawn_tracker.h" - -namespace ui { -namespace ws { -namespace { - -// This mirrors that of RootWindowController. -bool IsWindowAboveContainer(const ServerWindow* window, - const ServerWindow* blocking_container) { - std::vector<const ServerWindow*> target_path; - std::vector<const ServerWindow*> blocking_path; - - while (window) { - target_path.push_back(window); - window = window->parent(); - } - - while (blocking_container) { - blocking_path.push_back(blocking_container); - blocking_container = blocking_container->parent(); - } - - // The root window is put at the end so that we compare windows at - // the same depth. - while (!blocking_path.empty()) { - if (target_path.empty()) - return false; - - const ServerWindow* target = target_path.back(); - target_path.pop_back(); - const ServerWindow* blocking = blocking_path.back(); - blocking_path.pop_back(); - - // Still on the same path, continue. - if (target == blocking) - continue; - - // This can happen only if unparented window is passed because - // first element must be the same root. - if (!target->parent() || !blocking->parent()) - return false; - - const ServerWindow* common_parent = target->parent(); - DCHECK_EQ(common_parent, blocking->parent()); - const ServerWindow::Windows& windows = common_parent->children(); - auto blocking_iter = std::find(windows.begin(), windows.end(), blocking); - // If the target window is above blocking window, the window can handle - // events. - return std::find(blocking_iter, windows.end(), target) != windows.end(); - } - - return true; -} - -const ServerWindow* GetModalChildForWindowAncestor(const ServerWindow* window) { - for (const ServerWindow* ancestor = window; ancestor; - ancestor = ancestor->parent()) { - for (auto* transient_child : ancestor->transient_children()) { - if (transient_child->modal_type() != MODAL_TYPE_NONE && - transient_child->IsDrawn()) - return transient_child; - } - } - return nullptr; -} - -const ServerWindow* GetWindowModalTargetForWindow(const ServerWindow* window) { - const ServerWindow* modal_window = GetModalChildForWindowAncestor(window); - if (!modal_window) - return window; - return GetWindowModalTargetForWindow(modal_window); -} - -// Returns true if |transient| is a valid modal window. |target_window| is -// the window being considered. -bool IsModalTransientChild(const ServerWindow* transient, - const ServerWindow* target_window) { - return transient->IsDrawn() && - (transient->modal_type() == MODAL_TYPE_WINDOW || - transient->modal_type() == MODAL_TYPE_SYSTEM || - (transient->modal_type() == MODAL_TYPE_CHILD && - (transient->GetChildModalParent() && - transient->GetChildModalParent()->Contains(target_window)))); -} - -// Returns the deepest modal window starting at |activatable|. |target_window| -// is the window being considered. -const ServerWindow* GetModalTransientChild(const ServerWindow* activatable, - const ServerWindow* target_window) { - for (const ServerWindow* transient : activatable->transient_children()) { - if (IsModalTransientChild(transient, target_window)) { - if (transient->transient_children().empty()) - return transient; - - const ServerWindow* modal_child = - GetModalTransientChild(transient, target_window); - return modal_child ? modal_child : transient; - } - } - return nullptr; -} - -} // namespace - -class ModalWindowController::TrackedBlockingContainers - : public ServerWindowObserver { - public: - TrackedBlockingContainers(ModalWindowController* modal_window_controller, - ServerWindow* system_modal_container, - ServerWindow* min_container) - : modal_window_controller_(modal_window_controller), - system_modal_container_(system_modal_container), - min_container_(min_container) { - DCHECK(system_modal_container_); - system_modal_container_->AddObserver(this); - if (min_container_) - min_container_->AddObserver(this); - } - - ~TrackedBlockingContainers() override { - if (system_modal_container_) - system_modal_container_->RemoveObserver(this); - if (min_container_) - min_container_->RemoveObserver(this); - } - - bool IsInDisplayWithRoot(const ServerWindow* root) const { - return root->Contains(system_modal_container_); - } - - ServerWindow* system_modal_container() { return system_modal_container_; } - - ServerWindow* min_container() { return min_container_; } - - private: - void Destroy() { - modal_window_controller_->DestroyTrackedBlockingContainers(this); - } - - // ServerWindowObserver: - void OnWindowDestroying(ServerWindow* window) override { - if (window == min_container_) { - min_container_->RemoveObserver(this); - min_container_ = nullptr; - if (!system_modal_container_) - Destroy(); - } else if (window == system_modal_container_) { - system_modal_container_->RemoveObserver(this); - system_modal_container_ = nullptr; - // The |system_modal_container_| should always be valid. - Destroy(); - } - } - - ModalWindowController* modal_window_controller_; - ServerWindow* system_modal_container_; - ServerWindow* min_container_; - - DISALLOW_COPY_AND_ASSIGN(TrackedBlockingContainers); -}; - -ModalWindowController::ModalWindowController() {} - -ModalWindowController::~ModalWindowController() { - for (auto it = system_modal_windows_.begin(); - it != system_modal_windows_.end(); it++) { - (*it)->RemoveObserver(this); - } -} - -void ModalWindowController::SetBlockingContainers( - const std::vector<BlockingContainers>& all_blocking_containers) { - all_blocking_containers_.clear(); - - for (const BlockingContainers& containers : all_blocking_containers) { - all_blocking_containers_.push_back( - std::make_unique<TrackedBlockingContainers>( - this, containers.system_modal_container, containers.min_container)); - } -} - -void ModalWindowController::AddSystemModalWindow(ServerWindow* window) { - DCHECK(window); - DCHECK(!base::ContainsValue(system_modal_windows_, window)); - DCHECK_EQ(MODAL_TYPE_SYSTEM, window->modal_type()); - - system_modal_windows_.push_back(window); - window_drawn_trackers_.insert(make_pair( - window, std::make_unique<ServerWindowDrawnTracker>(window, this))); - window->AddObserver(this); -} - -void ModalWindowController::DestroyTrackedBlockingContainers( - TrackedBlockingContainers* containers) { - for (auto iter = all_blocking_containers_.begin(); - iter != all_blocking_containers_.end(); ++iter) { - if (iter->get() == containers) { - all_blocking_containers_.erase(iter); - return; - } - } - NOTREACHED(); -} - -bool ModalWindowController::IsWindowBlocked(const ServerWindow* window) const { - if (!window || !window->IsDrawn()) - return true; - - return GetModalTransient(window) || - IsWindowBlockedBySystemModalOrMinContainer(window); -} - -const ServerWindow* ModalWindowController::GetModalTransient( - const ServerWindow* window) const { - if (!window) - return nullptr; - - // We always want to check the for the transient child of the toplevel window. - const ServerWindow* toplevel = GetToplevelWindow(window); - if (!toplevel) - return nullptr; - - return GetModalTransientChild(toplevel, window); -} - -const ServerWindow* ModalWindowController::GetToplevelWindow( - const ServerWindow* window) const { - const ServerWindow* last = nullptr; - for (const ServerWindow *w = window; w; last = w, w = w->parent()) { - if (w->is_activation_parent()) - return last; - } - return nullptr; -} - -const ServerWindow* ModalWindowController::GetActiveSystemModalWindow() const { - for (auto it = system_modal_windows_.rbegin(); - it != system_modal_windows_.rend(); it++) { - ServerWindow* modal = *it; - if (modal->IsDrawn() && IsWindowInSystemModalContainer(modal)) - return modal; - } - return nullptr; -} - -bool ModalWindowController::IsWindowBlockedBySystemModalOrMinContainer( - const ServerWindow* window) const { - const ServerWindow* system_modal_window = GetActiveSystemModalWindow(); - const ServerWindow* min_container = nullptr; - if (system_modal_window) { - // If there is a system modal window, then |window| must be part of the - // system modal window. - const bool is_part_of_active_modal = - system_modal_window->Contains(window) || - window->HasTransientAncestor(system_modal_window); - if (!is_part_of_active_modal) - return true; - - // When there is a system modal window the |min_container| becomes the - // system modal container. - min_container = system_modal_window->parent(); - } else { - min_container = GetMinContainer(window); - } - return min_container && !IsWindowAboveContainer(window, min_container); -} - -bool ModalWindowController::IsWindowInSystemModalContainer( - const ServerWindow* window) const { - DCHECK(window->IsDrawn()); - const ServerWindow* root = window->GetRootForDrawn(); - DCHECK(root); - for (auto& blocking_containers : all_blocking_containers_) { - if (blocking_containers->IsInDisplayWithRoot(root)) - return window->parent() == blocking_containers->system_modal_container(); - } - // This means the window manager didn't set the blocking containers, assume - // the window is in a valid system modal container. - return true; -} - -const ServerWindow* ModalWindowController::GetMinContainer( - const ServerWindow* window) const { - DCHECK(window->IsDrawn()); - const ServerWindow* root = window->GetRootForDrawn(); - DCHECK(root); - for (auto& blocking_containers : all_blocking_containers_) { - if (blocking_containers->IsInDisplayWithRoot(root)) - return blocking_containers->min_container(); - } - return nullptr; -} - -void ModalWindowController::RemoveWindow(ServerWindow* window) { - window->RemoveObserver(this); - auto it = std::find(system_modal_windows_.begin(), - system_modal_windows_.end(), window); - DCHECK(it != system_modal_windows_.end()); - system_modal_windows_.erase(it); - window_drawn_trackers_.erase(window); -} - -void ModalWindowController::OnWindowDestroyed(ServerWindow* window) { - RemoveWindow(window); -} - -void ModalWindowController::OnWindowModalTypeChanged(ServerWindow* window, - ModalType old_modal_type) { - DCHECK_EQ(MODAL_TYPE_SYSTEM, old_modal_type); - DCHECK_NE(MODAL_TYPE_SYSTEM, window->modal_type()); - RemoveWindow(window); -} - -void ModalWindowController::OnDrawnStateChanged(ServerWindow* ancestor, - ServerWindow* window, - bool is_drawn) { - if (!is_drawn) - return; - - // Move the most recently shown window to the end of the list. - auto it = std::find(system_modal_windows_.begin(), - system_modal_windows_.end(), window); - DCHECK(it != system_modal_windows_.end()); - system_modal_windows_.splice(system_modal_windows_.end(), - system_modal_windows_, it); -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/modal_window_controller.h b/services/ui/ws/modal_window_controller.h deleted file mode 100644 index af2b8a20..0000000 --- a/services/ui/ws/modal_window_controller.h +++ /dev/null
@@ -1,125 +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. - -#ifndef SERVICES_UI_WS_MODAL_WINDOW_CONTROLLER_H_ -#define SERVICES_UI_WS_MODAL_WINDOW_CONTROLLER_H_ - -#include <list> -#include <map> -#include <vector> - -#include "services/ui/ws/server_window_drawn_tracker_observer.h" -#include "services/ui/ws/server_window_observer.h" - -namespace ui { -namespace ws { - -class ServerWindow; -class ServerWindowDrawnTracker; - -namespace test { -class ModalWindowControllerTestApi; -} - -// See mojom::BlockingContainers for details on this. |min_container| may -// be null. -struct BlockingContainers { - ServerWindow* system_modal_container = nullptr; - ServerWindow* min_container = nullptr; -}; - -// Used to keeps track of system modal windows and check whether windows are -// blocked by modal windows or not to do appropriate retargetting of events. -class ModalWindowController : public ServerWindowObserver, - public ServerWindowDrawnTrackerObserver { - public: - ModalWindowController(); - ~ModalWindowController() override; - - // See description in mojom::WindowManager::SetBlockingContainers() for - // details on this. - void SetBlockingContainers( - const std::vector<BlockingContainers>& all_containers); - - // Adds a system modal window. The window remains modal to system until it is - // destroyed. There can exist multiple system modal windows, in which case the - // one that is visible and added most recently or shown most recently would be - // the active one. - void AddSystemModalWindow(ServerWindow* window); - - // Checks whether |window| is blocked by any visible modal window. - bool IsWindowBlocked(const ServerWindow* window) const; - - // Returns the deepest modal window that is a transient descendants of the - // top-level window for |window|. - ServerWindow* GetModalTransient(ServerWindow* window) { - return const_cast<ServerWindow*>( - GetModalTransient(static_cast<const ServerWindow*>(window))); - } - const ServerWindow* GetModalTransient(const ServerWindow* window) const; - - ServerWindow* GetToplevelWindow(ServerWindow* window) { - return const_cast<ServerWindow*>( - GetToplevelWindow(static_cast<const ServerWindow*>(window))); - } - const ServerWindow* GetToplevelWindow(const ServerWindow* window) const; - - // Returns the system modal window that is visible and added/shown most - // recently, if any. - ServerWindow* GetActiveSystemModalWindow() { - return const_cast<ServerWindow*>( - const_cast<const ModalWindowController*>(this) - ->GetActiveSystemModalWindow()); - } - const ServerWindow* GetActiveSystemModalWindow() const; - - private: - friend class test::ModalWindowControllerTestApi; - class TrackedBlockingContainers; - - // Called when the window associated with a TrackedBlockingContainers is - // destroyed. - void DestroyTrackedBlockingContainers(TrackedBlockingContainers* containers); - - // Returns true if the there is a system modal window and |window| is not - // associated with it, or |window| is not above the minimum container (if one - // has been set). - bool IsWindowBlockedBySystemModalOrMinContainer( - const ServerWindow* window) const; - - // Returns true if |window| is in a container marked for system models. - bool IsWindowInSystemModalContainer(const ServerWindow* window) const; - - const ServerWindow* GetMinContainer(const ServerWindow* window) const; - - // Removes |window| from the data structures used by this class. - void RemoveWindow(ServerWindow* window); - - // ServerWindowObserver: - void OnWindowDestroyed(ServerWindow* window) override; - void OnWindowModalTypeChanged(ServerWindow* window, - ModalType old_modal_type) override; - - // ServerWindowDrawnTrackerObserver: - void OnDrawnStateChanged(ServerWindow* ancestor, - ServerWindow* window, - bool is_drawn) override; - - // List of system modal windows in order they are added/shown. - std::list<ServerWindow*> system_modal_windows_; - - // Drawn trackers for system modal windows. - std::map<ServerWindow*, std::unique_ptr<ServerWindowDrawnTracker>> - window_drawn_trackers_; - - std::vector<std::unique_ptr<TrackedBlockingContainers>> - all_blocking_containers_; - - DISALLOW_COPY_AND_ASSIGN(ModalWindowController); -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_MODAL_WINDOW_CONTROLLER_H_
diff --git a/services/ui/ws/modal_window_controller_unittest.cc b/services/ui/ws/modal_window_controller_unittest.cc deleted file mode 100644 index 9eb1dbe1..0000000 --- a/services/ui/ws/modal_window_controller_unittest.cc +++ /dev/null
@@ -1,140 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "services/ui/ws/modal_window_controller.h" - -#include "services/ui/ws/server_window.h" -#include "services/ui/ws/test_server_window_delegate.h" -#include "services/ui/ws/test_utils.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace ui { -namespace ws { - -class ModalWindowControllerTest : public testing::Test { - public: - ModalWindowControllerTest() {} - ~ModalWindowControllerTest() override {} - - VizHostProxy* viz_host_proxy() { - return ws_test_helper_.window_server()->GetVizHostProxy(); - } - - private: - test::WindowServerTestHelper ws_test_helper_; - - DISALLOW_COPY_AND_ASSIGN(ModalWindowControllerTest); -}; - -TEST_F(ModalWindowControllerTest, MinContainer) { - TestServerWindowDelegate window_delegate(viz_host_proxy()); - ServerWindow root_window(&window_delegate, viz::FrameSinkId(1, 1)); - window_delegate.set_root_window(&root_window); - ServerWindow container1(&window_delegate, viz::FrameSinkId(1, 2)); - ServerWindow container2(&window_delegate, viz::FrameSinkId(1, 3)); - ServerWindow container3(&window_delegate, viz::FrameSinkId(1, 4)); - - root_window.SetVisible(true); - container1.SetVisible(true); - container2.SetVisible(true); - container3.SetVisible(true); - - ModalWindowController modal_window_controller; - - std::vector<BlockingContainers> blocking_containers(1); - blocking_containers[0].system_modal_container = &container3; - blocking_containers[0].min_container = &container2; - modal_window_controller.SetBlockingContainers(blocking_containers); - - ServerWindow window(&window_delegate, viz::FrameSinkId(1, 5)); - window.SetVisible(true); - - // Window should be blocked when not attached to hierarchy. - EXPECT_TRUE(modal_window_controller.IsWindowBlocked(&window)); - - container1.Add(&window); - // Still blocked as still not drawn. - EXPECT_TRUE(modal_window_controller.IsWindowBlocked(&window)); - - root_window.Add(&container1); - root_window.Add(&container2); - root_window.Add(&container3); - - // Still blocked as window beneath min container. - EXPECT_TRUE(modal_window_controller.IsWindowBlocked(&window)); - - // container2 (and 3) are above min container, so shouldn't be blocked in - // either of them. - container2.Add(&window); - EXPECT_FALSE(modal_window_controller.IsWindowBlocked(&window)); - - container3.Add(&window); - EXPECT_FALSE(modal_window_controller.IsWindowBlocked(&window)); -} - -TEST_F(ModalWindowControllerTest, SystemModalContainer) { - TestServerWindowDelegate window_delegate(viz_host_proxy()); - ServerWindow root_window(&window_delegate, viz::FrameSinkId(1, 1)); - window_delegate.set_root_window(&root_window); - ServerWindow container1(&window_delegate, viz::FrameSinkId(1, 2)); - ServerWindow container2(&window_delegate, viz::FrameSinkId(1, 3)); - ServerWindow container3(&window_delegate, viz::FrameSinkId(1, 4)); - - root_window.SetVisible(true); - container1.SetVisible(true); - container2.SetVisible(true); - container3.SetVisible(true); - - root_window.Add(&container1); - root_window.Add(&container2); - root_window.Add(&container3); - - ModalWindowController modal_window_controller; - - std::vector<BlockingContainers> blocking_containers(1); - blocking_containers[0].system_modal_container = &container3; - blocking_containers[0].min_container = &container2; - modal_window_controller.SetBlockingContainers(blocking_containers); - - ServerWindow window(&window_delegate, viz::FrameSinkId(1, 5)); - window.SetVisible(true); - - container2.Add(&window); - EXPECT_FALSE(modal_window_controller.IsWindowBlocked(&window)); - - ServerWindow modal_window(&window_delegate, viz::FrameSinkId(1, 6)); - modal_window.SetModalType(MODAL_TYPE_SYSTEM); - modal_window_controller.AddSystemModalWindow(&modal_window); - - // |window| should still not be blocked as the system modal window isn't - // drawn. - EXPECT_FALSE(modal_window_controller.IsWindowBlocked(&window)); - - container3.Add(&modal_window); - EXPECT_FALSE(modal_window_controller.IsWindowBlocked(&window)); - - modal_window.SetVisible(true); - EXPECT_TRUE(modal_window_controller.IsWindowBlocked(&window)); - - // Move the window to container3, it should still be blocked by the sytem - // modal. - container3.Add(&window); - EXPECT_TRUE(modal_window_controller.IsWindowBlocked(&window)); - - // Make window a child of the modal window. - modal_window.Add(&window); - EXPECT_FALSE(modal_window_controller.IsWindowBlocked(&window)); - - container3.Add(&window); - modal_window.AddTransientWindow(&window); - EXPECT_FALSE(modal_window_controller.IsWindowBlocked(&window)); - - container2.Add(&window); - EXPECT_TRUE(modal_window_controller.IsWindowBlocked(&window)); - - modal_window.RemoveTransientWindow(&window); -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/operation.cc b/services/ui/ws/operation.cc deleted file mode 100644 index 34e28d4d..0000000 --- a/services/ui/ws/operation.cc +++ /dev/null
@@ -1,30 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "services/ui/ws/operation.h" - -#include "services/ui/ws/window_server.h" -#include "services/ui/ws/window_tree.h" - -namespace ui { -namespace ws { - -Operation::Operation(WindowTree* tree, - WindowServer* window_server, - OperationType operation_type) - : window_server_(window_server), - source_tree_id_(tree->id()), - operation_type_(operation_type) { - DCHECK(operation_type != OperationType::NONE); - // Tell the window server about the operation currently in flight. The window - // server uses this information to suppress certain calls out to clients. - window_server_->PrepareForOperation(this); -} - -Operation::~Operation() { - window_server_->FinishOperation(); -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/operation.h b/services/ui/ws/operation.h deleted file mode 100644 index 88fe8c1..0000000 --- a/services/ui/ws/operation.h +++ /dev/null
@@ -1,79 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SERVICES_UI_WS_OPERATION_H_ -#define SERVICES_UI_WS_OPERATION_H_ - -#include <set> - -#include "base/macros.h" -#include "services/ui/common/types.h" - -namespace ui { -namespace ws { - -class WindowServer; -class WindowTree; - -enum class OperationType { - NONE, - ADD_TRANSIENT_WINDOW, - ADD_WINDOW, - DELETE_WINDOW, - EMBED, - RELEASE_CAPTURE, - REMOVE_TRANSIENT_WINDOW_FROM_PARENT, - REMOVE_WINDOW_FROM_PARENT, - REORDER_WINDOW, - SET_CAPTURE, - SET_CLIENT_AREA, - SET_FOCUS, - SET_WINDOW_BOUNDS, - SET_WINDOW_OPACITY, - SET_WINDOW_PREDEFINED_CURSOR, - SET_WINDOW_PROPERTY, - SET_WINDOW_TRANSFORM, - SET_WINDOW_VISIBILITY, -}; - -// This class tracks the currently pending client-initiated operation. -// This is typically used to suppress superfluous notifications generated -// by suboperations in the window server. -class Operation { - public: - Operation(WindowTree* tree, - WindowServer* window_server, - OperationType operation_type); - ~Operation(); - - ClientSpecificId source_tree_id() const { return source_tree_id_; } - - const OperationType& type() const { return operation_type_; } - - // Marks the tree with the specified id as having been sent a message - // during the course of |this| operation. - void MarkTreeAsMessaged(ClientSpecificId tree_id) { - message_ids_.insert(tree_id); - } - - // Returns true if MarkTreeAsMessaged(tree_id) was invoked. - bool DidMessageTree(ClientSpecificId tree_id) const { - return message_ids_.count(tree_id) > 0; - } - - private: - WindowServer* const window_server_; - const ClientSpecificId source_tree_id_; - const OperationType operation_type_; - - // See description of MarkTreeAsMessaged/DidMessageTree. - std::set<ClientSpecificId> message_ids_; - - DISALLOW_COPY_AND_ASSIGN(Operation); -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_OPERATION_H_
diff --git a/services/ui/ws/platform_display.cc b/services/ui/ws/platform_display.cc deleted file mode 100644 index 9da4993e..0000000 --- a/services/ui/ws/platform_display.cc +++ /dev/null
@@ -1,75 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "services/ui/ws/platform_display.h" - -#include "build/build_config.h" -#include "services/ui/ws/platform_display_default.h" -#include "services/ui/ws/platform_display_factory.h" -#include "services/ui/ws/server_window.h" -#include "services/ui/ws/threaded_image_cursors.h" -#include "services/ui/ws/threaded_image_cursors_factory.h" -#include "ui/platform_window/platform_window.h" - -#if defined(OS_WIN) -#include "ui/platform_window/win/win_window.h" -#elif defined(USE_X11) -#include "ui/platform_window/x11/x11_window.h" -#elif defined(OS_ANDROID) -#include "ui/platform_window/android/platform_window_android.h" -#elif defined(USE_OZONE) -#include "ui/ozone/public/ozone_platform.h" -#include "ui/platform_window/platform_window_delegate.h" -#include "ui/platform_window/platform_window_init_properties.h" -#endif - -namespace ui { -namespace ws { - -// static -PlatformDisplayFactory* PlatformDisplay::factory_ = nullptr; - -// static -std::unique_ptr<PlatformDisplay> PlatformDisplay::Create( - ServerWindow* root, - const display::ViewportMetrics& metrics, - ThreadedImageCursorsFactory* threaded_image_cursors_factory) { - if (factory_) - return factory_->CreatePlatformDisplay(root, metrics); - -#if defined(OS_ANDROID) - return std::make_unique<PlatformDisplayDefault>(root, metrics, - nullptr /* image_cursors */); -#else - return std::make_unique<PlatformDisplayDefault>( - root, metrics, threaded_image_cursors_factory->CreateCursors()); -#endif -} - -// static -std::unique_ptr<PlatformWindow> PlatformDisplay::CreatePlatformWindow( - PlatformWindowDelegate* delegate, - const gfx::Rect& bounds) { - DCHECK(!bounds.size().IsEmpty()); - std::unique_ptr<PlatformWindow> platform_window; -#if defined(OS_WIN) - platform_window = std::make_unique<ui::WinWindow>(delegate, bounds); -#elif defined(USE_X11) - platform_window = std::make_unique<ui::X11Window>(delegate, bounds); -#elif defined(OS_ANDROID) - platform_window = std::make_unique<ui::PlatformWindowAndroid>(delegate); - platform_window->SetBounds(bounds); -#elif defined(USE_OZONE) - ui::PlatformWindowInitProperties properties; - properties.bounds = bounds; - platform_window = OzonePlatform::GetInstance()->CreatePlatformWindow( - delegate, std::move(properties)); -#else - NOTREACHED() << "Unsupported platform"; -#endif - return platform_window; -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/platform_display.h b/services/ui/ws/platform_display.h deleted file mode 100644 index b9c1210..0000000 --- a/services/ui/ws/platform_display.h +++ /dev/null
@@ -1,102 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SERVICES_UI_WS_PLATFORM_DISPLAY_H_ -#define SERVICES_UI_WS_PLATFORM_DISPLAY_H_ - -#include <stdint.h> - -#include <memory> - -#include "base/memory/ref_counted.h" -#include "base/strings/string16.h" -#include "services/ui/display/viewport_metrics.h" -#include "services/ui/public/interfaces/cursor/cursor.mojom.h" -#include "ui/display/display.h" -#include "ui/events/event_source.h" -#include "ui/gfx/native_widget_types.h" - -namespace ui { - -enum class CursorSize; -class PlatformWindow; -class PlatformWindowDelegate; -struct TextInputState; - -namespace ws { - -class FrameGenerator; -class PlatformDisplayDelegate; -class PlatformDisplayFactory; -class ServerWindow; -class ThreadedImageCursorsFactory; - -// PlatformDisplay is used to connect the root ServerWindow to a display. -class PlatformDisplay : public ui::EventSource { - public: - ~PlatformDisplay() override {} - - static std::unique_ptr<PlatformDisplay> Create( - ServerWindow* root_window, - const display::ViewportMetrics& metrics, - ThreadedImageCursorsFactory* threaded_image_cursors_factory); - - virtual void Init(PlatformDisplayDelegate* delegate) = 0; - - virtual void SetViewportSize(const gfx::Size& size) = 0; - - virtual void SetTitle(const base::string16& title) = 0; - - virtual void SetCapture() = 0; - - virtual void ReleaseCapture() = 0; - - virtual void SetCursor(const ui::CursorData& cursor) = 0; - - virtual void MoveCursorTo(const gfx::Point& window_pixel_location) = 0; - - virtual void SetCursorSize(const ui::CursorSize& cursor_size) = 0; - - virtual void ConfineCursorToBounds(const gfx::Rect& pixel_bounds) = 0; - - virtual void UpdateTextInputState(const ui::TextInputState& state) = 0; - virtual void SetImeVisibility(bool visible) = 0; - - // Updates the viewport metrics for the display. - virtual void UpdateViewportMetrics( - const display::ViewportMetrics& metrics) = 0; - - virtual const display::ViewportMetrics& GetViewportMetrics() = 0; - - // Returns the AcceleratedWidget associated with the Display. It can return - // kNullAcceleratedWidget if the accelerated widget is not available yet. - virtual gfx::AcceleratedWidget GetAcceleratedWidget() const = 0; - - virtual FrameGenerator* GetFrameGenerator() = 0; - - virtual void SetCursorConfig(display::Display::Rotation rotation, - float scale) = 0; - - // Overrides factory for testing. Default (NULL) value indicates regular - // (non-test) environment. - static void set_factory_for_testing(PlatformDisplayFactory* factory) { - PlatformDisplay::factory_ = factory; - } - - protected: - // Create a platform window with the given delegate and bounds. - static std::unique_ptr<PlatformWindow> CreatePlatformWindow( - PlatformWindowDelegate* delegate, - const gfx::Rect& bounds); - - private: - // Static factory instance (always NULL for non-test). - static PlatformDisplayFactory* factory_; -}; - - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_PLATFORM_DISPLAY_H_
diff --git a/services/ui/ws/platform_display_default.cc b/services/ui/ws/platform_display_default.cc deleted file mode 100644 index f75910d..0000000 --- a/services/ui/ws/platform_display_default.cc +++ /dev/null
@@ -1,270 +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 "services/ui/ws/platform_display_default.h" - -#include <utility> - -#include "build/build_config.h" -#include "gpu/ipc/client/gpu_channel_host.h" -#include "services/ui/display/screen_manager.h" -#include "services/ui/public/interfaces/cursor/cursor_struct_traits.h" -#include "services/ui/ws/server_window.h" -#include "services/ui/ws/threaded_image_cursors.h" -#include "services/viz/privileged/interfaces/compositing/display_private.mojom.h" -#include "ui/display/display.h" -#include "ui/events/event.h" -#include "ui/events/event_utils.h" -#include "ui/platform_window/platform_ime_controller.h" -#include "ui/platform_window/platform_window.h" -#include "ui/platform_window/stub/stub_window.h" - -#if defined(USE_OZONE) -#include "ui/events/ozone/chromeos/cursor_controller.h" -#endif - -namespace ui { -namespace ws { - -PlatformDisplayDefault::PlatformDisplayDefault( - ServerWindow* root_window, - const display::ViewportMetrics& metrics, - std::unique_ptr<ThreadedImageCursors> image_cursors) - : root_window_(root_window), - image_cursors_(std::move(image_cursors)), - metrics_(metrics), - widget_(gfx::kNullAcceleratedWidget) {} - -PlatformDisplayDefault::~PlatformDisplayDefault() { -#if defined(OS_CHROMEOS) - ui::CursorController::GetInstance()->ClearCursorConfigForWindow( - GetAcceleratedWidget()); -#endif - - // Don't notify the delegate from the destructor. - delegate_ = nullptr; - - frame_generator_.reset(); - image_cursors_.reset(); - // Destroy the PlatformWindow early on as it may call us back during - // destruction and we want to be in a known state. But destroy the surface - // and ThreadedImageCursors first because they can still be using the platform - // window. - platform_window_.reset(); -} - -EventSink* PlatformDisplayDefault::GetEventSink() { - return delegate_->GetEventSink(); -} - -void PlatformDisplayDefault::Init(PlatformDisplayDelegate* delegate) { - DCHECK(delegate); - delegate_ = delegate; - - const gfx::Rect& bounds = metrics_.bounds_in_pixels; - DCHECK(!bounds.size().IsEmpty()); - - if (delegate_->GetDisplay().id() == display::kUnifiedDisplayId) { - // Virtual unified displays use a StubWindow; see AshWindowTreeHostUnified. - platform_window_ = std::make_unique<ui::StubWindow>(this, true, bounds); - } else if (delegate_->GetDisplay().id() == display::kInvalidDisplayId) { - // Unit tests may use kInvalidDisplayId to request a StubWindow for testing. - platform_window_ = std::make_unique<ui::StubWindow>(this, false); - } else { - platform_window_ = CreatePlatformWindow(this, metrics_.bounds_in_pixels); - } - - platform_window_->Show(); - - if (image_cursors_) { - image_cursors_->SetDisplay(delegate_->GetDisplay(), - metrics_.device_scale_factor); - } -} - -void PlatformDisplayDefault::SetViewportSize(const gfx::Size& size) { - platform_window_->SetBounds(gfx::Rect(size)); -} - -void PlatformDisplayDefault::SetTitle(const base::string16& title) { - platform_window_->SetTitle(title); -} - -void PlatformDisplayDefault::SetCapture() { - platform_window_->SetCapture(); -} - -void PlatformDisplayDefault::ReleaseCapture() { - platform_window_->ReleaseCapture(); -} - -void PlatformDisplayDefault::SetCursor(const ui::CursorData& cursor_data) { - if (!image_cursors_) - return; - - image_cursors_->SetCursor(cursor_data, platform_window_.get()); -} - -void PlatformDisplayDefault::MoveCursorTo( - const gfx::Point& window_pixel_location) { - platform_window_->MoveCursorTo(window_pixel_location); -} - -void PlatformDisplayDefault::SetCursorSize(const ui::CursorSize& cursor_size) { - image_cursors_->SetCursorSize(cursor_size); -} - -void PlatformDisplayDefault::ConfineCursorToBounds( - const gfx::Rect& pixel_bounds) { - platform_window_->ConfineCursorToBounds(pixel_bounds); -} - -void PlatformDisplayDefault::UpdateTextInputState( - const ui::TextInputState& state) { - ui::PlatformImeController* ime = platform_window_->GetPlatformImeController(); - if (ime) - ime->UpdateTextInputState(state); -} - -void PlatformDisplayDefault::SetImeVisibility(bool visible) { - ui::PlatformImeController* ime = platform_window_->GetPlatformImeController(); - if (ime) - ime->SetImeVisibility(visible); -} - -FrameGenerator* PlatformDisplayDefault::GetFrameGenerator() { - return frame_generator_.get(); -} - -void PlatformDisplayDefault::UpdateViewportMetrics( - const display::ViewportMetrics& metrics) { - if (metrics_ == metrics) - return; - - gfx::Rect bounds = platform_window_->GetBounds(); - if (bounds.size() != metrics.bounds_in_pixels.size()) { - bounds.set_size(metrics.bounds_in_pixels.size()); - platform_window_->SetBounds(bounds); - } - - metrics_ = metrics; - if (frame_generator_) { - frame_generator_->SetDeviceScaleFactor(metrics_.device_scale_factor); - frame_generator_->OnWindowSizeChanged(metrics_.bounds_in_pixels.size()); - } -} - -const display::ViewportMetrics& PlatformDisplayDefault::GetViewportMetrics() { - return metrics_; -} - -gfx::AcceleratedWidget PlatformDisplayDefault::GetAcceleratedWidget() const { - return widget_; -} - -void PlatformDisplayDefault::SetCursorConfig( - display::Display::Rotation rotation, - float scale) { -#if defined(OS_CHROMEOS) - ui::CursorController::GetInstance()->SetCursorConfigForWindow( - GetAcceleratedWidget(), rotation, scale); -#endif -} - -void PlatformDisplayDefault::OnBoundsChanged(const gfx::Rect& new_bounds) { - // We only care if the window size has changed. - if (new_bounds.size() == metrics_.bounds_in_pixels.size()) - return; - - // TODO(tonikitoo): Handle the bounds changing in external window mode. The - // window should be resized by the WS and it shouldn't involve ScreenManager. -} - -void PlatformDisplayDefault::OnDamageRect(const gfx::Rect& damaged_region) { - if (frame_generator_) - frame_generator_->OnWindowDamaged(); -} - -void PlatformDisplayDefault::DispatchEvent(ui::Event* event) { - // Mojo requires conversion of mouse and touch events to pointer events. - if (event->IsMouseEvent()) { - ui::PointerEvent pointer_event(*event->AsMouseEvent()); - SendEventToSink(&pointer_event); - } else if (event->IsTouchEvent()) { - ui::PointerEvent pointer_event(*event->AsTouchEvent()); - SendEventToSink(&pointer_event); - } else { - SendEventToSink(event); - } -} - -void PlatformDisplayDefault::OnCloseRequest() { - // TODO(tonikitoo): Handle a close request in external window mode. The window - // should be closed by the WS and it shouldn't involve ScreenManager. - const int64_t display_id = delegate_->GetDisplay().id(); - display::ScreenManager::GetInstance()->RequestCloseDisplay(display_id); -} - -void PlatformDisplayDefault::OnClosed() {} - -void PlatformDisplayDefault::OnWindowStateChanged( - ui::PlatformWindowState new_state) {} - -void PlatformDisplayDefault::OnLostCapture() { - delegate_->OnNativeCaptureLost(); -} - -void PlatformDisplayDefault::OnAcceleratedWidgetAvailable( - gfx::AcceleratedWidget widget, - float device_scale_factor) { - // This will get called after Init() is called, either synchronously as part - // of the Init() callstack or async after Init() has returned, depending on - // the platform. - DCHECK_EQ(gfx::kNullAcceleratedWidget, widget_); - widget_ = widget; - delegate_->OnAcceleratedWidgetAvailable(); - - if (!delegate_->IsHostingViz()) - return; - - viz::mojom::CompositorFrameSinkAssociatedPtr compositor_frame_sink; - viz::mojom::CompositorFrameSinkClientPtr compositor_frame_sink_client; - viz::mojom::CompositorFrameSinkClientRequest - compositor_frame_sink_client_request = - mojo::MakeRequest(&compositor_frame_sink_client); - - // TODO(ccameron): |display_client| is not bound. This will need to - // change to support macOS. - viz::mojom::DisplayPrivateAssociatedPtr display_private; - viz::mojom::DisplayClientPtr display_client; - viz::mojom::DisplayClientRequest display_client_request = - mojo::MakeRequest(&display_client); - - root_window_->CreateRootCompositorFrameSink( - widget_, mojo::MakeRequest(&compositor_frame_sink), - std::move(compositor_frame_sink_client), - mojo::MakeRequest(&display_private), std::move(display_client)); - - display_private->SetDisplayVisible(true); - frame_generator_ = std::make_unique<FrameGenerator>(); - auto frame_sink_client_binding = - std::make_unique<CompositorFrameSinkClientBinding>( - frame_generator_.get(), - std::move(compositor_frame_sink_client_request), - std::move(compositor_frame_sink)); - frame_generator_->Bind(std::move(frame_sink_client_binding), - std::move(display_private)); - frame_generator_->OnWindowSizeChanged(root_window_->bounds().size()); - frame_generator_->SetDeviceScaleFactor(metrics_.device_scale_factor); -} - -void PlatformDisplayDefault::OnAcceleratedWidgetDestroying() {} - -void PlatformDisplayDefault::OnAcceleratedWidgetDestroyed() { -} - -void PlatformDisplayDefault::OnActivationChanged(bool active) {} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/platform_display_default.h b/services/ui/ws/platform_display_default.h deleted file mode 100644 index 9b5be0a..0000000 --- a/services/ui/ws/platform_display_default.h +++ /dev/null
@@ -1,92 +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. - -#ifndef SERVICES_UI_WS_PLATFORM_DISPLAY_DEFAULT_H_ -#define SERVICES_UI_WS_PLATFORM_DISPLAY_DEFAULT_H_ - -#include <memory> - -#include "base/macros.h" -#include "services/ui/display/viewport_metrics.h" -#include "services/ui/ws/frame_generator.h" -#include "services/ui/ws/platform_display.h" -#include "services/ui/ws/platform_display_delegate.h" -#include "services/ui/ws/server_window.h" -#include "ui/platform_window/platform_window_delegate.h" - -namespace ui { - -class EventSink; -class PlatformWindow; - -namespace ws { - -class ThreadedImageCursors; - -// PlatformDisplay implementation that connects to a PlatformWindow and -// FrameGenerator for Chrome OS. -class PlatformDisplayDefault : public PlatformDisplay, - public ui::PlatformWindowDelegate { - public: - // |image_cursors| may be null, for example on Android or in tests. - PlatformDisplayDefault(ServerWindow* root_window, - const display::ViewportMetrics& metrics, - std::unique_ptr<ThreadedImageCursors> image_cursors); - ~PlatformDisplayDefault() override; - - // EventSource:: - EventSink* GetEventSink() override; - - // PlatformDisplay: - void Init(PlatformDisplayDelegate* delegate) override; - void SetViewportSize(const gfx::Size& size) override; - void SetTitle(const base::string16& title) override; - void SetCapture() override; - void ReleaseCapture() override; - void SetCursor(const ui::CursorData& cursor) override; - void MoveCursorTo(const gfx::Point& window_pixel_location) override; - void SetCursorSize(const ui::CursorSize& cursor_size) override; - void ConfineCursorToBounds(const gfx::Rect& pixel_bounds) override; - void UpdateTextInputState(const ui::TextInputState& state) override; - void SetImeVisibility(bool visible) override; - void UpdateViewportMetrics(const display::ViewportMetrics& metrics) override; - const display::ViewportMetrics& GetViewportMetrics() override; - gfx::AcceleratedWidget GetAcceleratedWidget() const override; - FrameGenerator* GetFrameGenerator() override; - void SetCursorConfig(display::Display::Rotation rotation, - float scale) override; - - private: - // ui::PlatformWindowDelegate: - void OnBoundsChanged(const gfx::Rect& new_bounds) override; - void OnDamageRect(const gfx::Rect& damaged_region) override; - void DispatchEvent(ui::Event* event) override; - void OnCloseRequest() override; - void OnClosed() override; - void OnWindowStateChanged(ui::PlatformWindowState new_state) override; - void OnLostCapture() override; - void OnAcceleratedWidgetAvailable(gfx::AcceleratedWidget widget, - float device_scale_factor) override; - void OnAcceleratedWidgetDestroying() override; - void OnAcceleratedWidgetDestroyed() override; - void OnActivationChanged(bool active) override; - - ServerWindow* root_window_; - - std::unique_ptr<ThreadedImageCursors> image_cursors_; - - PlatformDisplayDelegate* delegate_ = nullptr; - std::unique_ptr<FrameGenerator> frame_generator_; - - display::ViewportMetrics metrics_; - std::unique_ptr<ui::PlatformWindow> platform_window_; - gfx::AcceleratedWidget widget_; - - DISALLOW_COPY_AND_ASSIGN(PlatformDisplayDefault); -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_PLATFORM_DISPLAY_DEFAULT_H_
diff --git a/services/ui/ws/platform_display_default_unittest.cc b/services/ui/ws/platform_display_default_unittest.cc deleted file mode 100644 index 04bac1c..0000000 --- a/services/ui/ws/platform_display_default_unittest.cc +++ /dev/null
@@ -1,129 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "services/ui/ws/platform_display_default.h" - -#include "base/message_loop/message_loop.h" -#include "base/time/time.h" -#include "services/ui/common/image_cursors_set.h" -#include "services/ui/ws/threaded_image_cursors.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/display/types/native_display_delegate.h" -#include "ui/events/event.h" -#include "ui/events/event_sink.h" -#include "ui/events/system_input_injector.h" -#include "ui/gfx/geometry/point.h" -#include "ui/ozone/public/cursor_factory_ozone.h" -#include "ui/ozone/public/ozone_platform.h" -#include "ui/platform_window/platform_window.h" -#include "ui/platform_window/stub/stub_window.h" - -namespace ui { -namespace ws { -namespace { - -// An EventSink that records events sent to it. -class TestEventSink : public EventSink { - public: - TestEventSink() { Reset(); } - ~TestEventSink() override = default; - - void Reset() { - count_ = 0; - last_event_type_ = ET_UNKNOWN; - } - - // EventSink: - EventDispatchDetails OnEventFromSource(Event* event) override { - count_++; - last_event_type_ = event->type(); - return EventDispatchDetails(); - } - - int count_; - EventType last_event_type_; -}; - -// A PlatformDisplayDelegate to connect the PlatformDisplay to a TestEventSink. -class TestPlatformDisplayDelegate : public PlatformDisplayDelegate { - public: - explicit TestPlatformDisplayDelegate(TestEventSink* sink) : sink_(sink) {} - ~TestPlatformDisplayDelegate() override = default; - - // PlatformDisplayDelegate: - const display::Display& GetDisplay() override { return stub_display_; } - ServerWindow* GetRootWindow() override { return nullptr; } - EventSink* GetEventSink() override { return sink_; } - void OnAcceleratedWidgetAvailable() override {} - void OnNativeCaptureLost() override {} - bool IsHostingViz() const override { return true; } - - private: - TestEventSink* sink_; - display::Display stub_display_; - - DISALLOW_COPY_AND_ASSIGN(TestPlatformDisplayDelegate); -}; - -TEST(PlatformDisplayDefaultTest, EventDispatch) { - // ThreadTaskRunnerHandle needed required by ThreadedImageCursors. - base::MessageLoop loop; - - // Create the display. - display::ViewportMetrics metrics; - metrics.bounds_in_pixels = gfx::Rect(1024, 768); - metrics.device_scale_factor = 1.f; - metrics.ui_scale_factor = 1.f; - scoped_refptr<base::SingleThreadTaskRunner> task_runner = - base::ThreadTaskRunnerHandle::Get(); - ImageCursorsSet image_cursors_set; - CursorFactoryOzone cursor_factory_ozone; - std::unique_ptr<ThreadedImageCursors> threaded_image_cursors = - std::make_unique<ThreadedImageCursors>(task_runner, - image_cursors_set.GetWeakPtr()); - PlatformDisplayDefault display(nullptr, metrics, - std::move(threaded_image_cursors)); - - // Initialize the display with a test EventSink so we can sense events. - TestEventSink event_sink; - TestPlatformDisplayDelegate delegate(&event_sink); - // kInvalidDisplayId causes the display to be initialized with a StubWindow. - EXPECT_EQ(display::kInvalidDisplayId, delegate.GetDisplay().id()); - display.Init(&delegate); - - // Event dispatch is handled at the PlatformWindowDelegate level. - PlatformWindowDelegate* display_for_dispatch = - static_cast<PlatformWindowDelegate*>(&display); - - // Mouse events are converted to pointer events. - MouseEvent mouse(ET_MOUSE_PRESSED, gfx::Point(1, 2), gfx::Point(1, 2), - base::TimeTicks(), EF_NONE, 0); - display_for_dispatch->DispatchEvent(&mouse); - EXPECT_EQ(ET_POINTER_DOWN, event_sink.last_event_type_); - event_sink.Reset(); - - // Touch events are converted to pointer events. - TouchEvent touch(ET_TOUCH_PRESSED, gfx::Point(3, 4), base::TimeTicks(), - PointerDetails(EventPointerType::POINTER_TYPE_TOUCH, 0)); - display_for_dispatch->DispatchEvent(&touch); - EXPECT_EQ(ET_POINTER_DOWN, event_sink.last_event_type_); - event_sink.Reset(); - - // Pressing a key dispatches exactly one event. - KeyEvent key_pressed(ET_KEY_PRESSED, VKEY_A, EF_NONE); - display_for_dispatch->DispatchEvent(&key_pressed); - EXPECT_EQ(1, event_sink.count_); - EXPECT_EQ(ET_KEY_PRESSED, event_sink.last_event_type_); - event_sink.Reset(); - - // Releasing the key dispatches exactly one event. - KeyEvent key_released(ET_KEY_RELEASED, VKEY_A, EF_NONE); - display_for_dispatch->DispatchEvent(&key_released); - EXPECT_EQ(1, event_sink.count_); - EXPECT_EQ(ET_KEY_RELEASED, event_sink.last_event_type_); -} - -} // namespace -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/platform_display_delegate.h b/services/ui/ws/platform_display_delegate.h deleted file mode 100644 index 41bbb95..0000000 --- a/services/ui/ws/platform_display_delegate.h +++ /dev/null
@@ -1,50 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SERVICES_UI_WS_PLATFORM_DISPLAY_DELEGATE_H_ -#define SERVICES_UI_WS_PLATFORM_DISPLAY_DELEGATE_H_ - -namespace display { -class Display; -} - -namespace ui { - -class EventSink; - -namespace ws { - -class ServerWindow; - -// PlatformDisplayDelegate is implemented by an object that manages the -// lifetime of a PlatformDisplay, forwards events to the appropriate windows, -/// and responses to changes in viewport size. -class PlatformDisplayDelegate { - public: - // Returns a display::Display for this display. - virtual const display::Display& GetDisplay() = 0; - - // Returns the root window of this display. - virtual ServerWindow* GetRootWindow() = 0; - - // Returns the event sink of this display; - virtual EventSink* GetEventSink() = 0; - - // Called once when the AcceleratedWidget is available for drawing. - virtual void OnAcceleratedWidgetAvailable() = 0; - - // Called when the Display loses capture. - virtual void OnNativeCaptureLost() = 0; - - virtual bool IsHostingViz() const = 0; - - protected: - virtual ~PlatformDisplayDelegate() {} -}; - -} // namespace ws - -} // namespace ui - -#endif // SERVICES_UI_WS_PLATFORM_DISPLAY_DELEGATE_H_
diff --git a/services/ui/ws/platform_display_factory.h b/services/ui/ws/platform_display_factory.h deleted file mode 100644 index 99e17af..0000000 --- a/services/ui/ws/platform_display_factory.h +++ /dev/null
@@ -1,32 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SERVICES_UI_WS_PLATFORM_DISPLAY_FACTORY_H_ -#define SERVICES_UI_WS_PLATFORM_DISPLAY_FACTORY_H_ - -#include <memory> - -namespace display { -struct ViewportMetrics; -} - -namespace ui { -namespace ws { - -class PlatformDisplay; -class ServerWindow; - -// Abstract factory for PlatformDisplays. Used by tests to construct test -// PlatformDisplays. -class PlatformDisplayFactory { - public: - virtual std::unique_ptr<PlatformDisplay> CreatePlatformDisplay( - ServerWindow* root_window, - const display::ViewportMetrics& metrics) = 0; -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_PLATFORM_DISPLAY_FACTORY_H_
diff --git a/services/ui/ws/platform_display_mirror.cc b/services/ui/ws/platform_display_mirror.cc deleted file mode 100644 index ef8bf65..0000000 --- a/services/ui/ws/platform_display_mirror.cc +++ /dev/null
@@ -1,170 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "services/ui/ws/platform_display_mirror.h" - -#include "components/viz/common/surfaces/surface_id.h" -#include "components/viz/common/surfaces/surface_info.h" -#include "components/viz/host/renderer_settings_creation.h" -#include "services/ui/ws/display.h" -#include "services/ui/ws/display_manager.h" -#include "services/ui/ws/frame_generator.h" -#include "services/ui/ws/window_server.h" -#include "ui/platform_window/platform_window.h" - -namespace ui { -namespace ws { - -PlatformDisplayMirror::PlatformDisplayMirror( - const display::Display& display, - const display::ViewportMetrics& metrics, - WindowServer* window_server, - Display* display_to_mirror) - : display_(display), - metrics_(metrics), - window_server_(window_server), - display_to_mirror_(display_to_mirror) { - DCHECK(display_to_mirror_); - frame_sink_id_ = window_server->display_manager()->GetAndAdvanceNextRootId(); - - // Create a new platform window to display the mirror destination content. - platform_window_ = CreatePlatformWindow(this, metrics_.bounds_in_pixels); - platform_window_->Show(); -} - -PlatformDisplayMirror::~PlatformDisplayMirror() = default; - -void PlatformDisplayMirror::Init(PlatformDisplayDelegate* delegate) {} - -void PlatformDisplayMirror::SetViewportSize(const gfx::Size& size) {} - -void PlatformDisplayMirror::SetTitle(const base::string16& title) {} - -void PlatformDisplayMirror::SetCapture() {} - -void PlatformDisplayMirror::ReleaseCapture() {} - -void PlatformDisplayMirror::SetCursor(const ui::CursorData& cursor) {} - -void PlatformDisplayMirror::MoveCursorTo( - const gfx::Point& window_pixel_location) {} - -void PlatformDisplayMirror::SetCursorSize(const ui::CursorSize& cursor_size) {} - -void PlatformDisplayMirror::ConfineCursorToBounds( - const gfx::Rect& pixel_bounds) {} - -void PlatformDisplayMirror::UpdateTextInputState( - const ui::TextInputState& state) {} - -void PlatformDisplayMirror::SetImeVisibility(bool visible) {} - -void PlatformDisplayMirror::UpdateViewportMetrics( - const display::ViewportMetrics& metrics) { - metrics_ = metrics; -} - -const display::ViewportMetrics& PlatformDisplayMirror::GetViewportMetrics() { - return metrics_; -} - -gfx::AcceleratedWidget PlatformDisplayMirror::GetAcceleratedWidget() const { - return widget_; -} - -FrameGenerator* PlatformDisplayMirror::GetFrameGenerator() { - return frame_generator_.get(); -} - -EventSink* PlatformDisplayMirror::GetEventSink() { - return nullptr; -} - -void PlatformDisplayMirror::SetCursorConfig(display::Display::Rotation rotation, - float scale) {} - -void PlatformDisplayMirror::OnBoundsChanged(const gfx::Rect& new_bounds) {} - -void PlatformDisplayMirror::OnDamageRect(const gfx::Rect& damaged_region) {} - -void PlatformDisplayMirror::DispatchEvent(ui::Event* event) {} - -void PlatformDisplayMirror::OnCloseRequest() {} - -void PlatformDisplayMirror::OnClosed() {} - -void PlatformDisplayMirror::OnWindowStateChanged( - ui::PlatformWindowState new_state) {} - -void PlatformDisplayMirror::OnLostCapture() {} - -void PlatformDisplayMirror::OnAcceleratedWidgetAvailable( - gfx::AcceleratedWidget widget, - float device_scale_factor) { - DCHECK_EQ(gfx::kNullAcceleratedWidget, widget_); - widget_ = widget; - - // Create a CompositorFrameSink for this display, using the widget's surface. - viz::mojom::CompositorFrameSinkAssociatedPtr compositor_frame_sink; - viz::mojom::CompositorFrameSinkClientPtr compositor_frame_sink_client; - viz::mojom::CompositorFrameSinkClientRequest - compositor_frame_sink_client_request = - mojo::MakeRequest(&compositor_frame_sink_client); - window_server_->GetVizHostProxy()->RegisterFrameSinkId(frame_sink_id_, this); - - // TODO(ccameron): Bind |display_client| to support macOS? (maybe not needed) - viz::mojom::DisplayPrivateAssociatedPtr display_private; - viz::mojom::DisplayClientPtr display_client; - viz::mojom::DisplayClientRequest display_client_request = - mojo::MakeRequest(&display_client); - - auto params = viz::mojom::RootCompositorFrameSinkParams::New(); - params->frame_sink_id = frame_sink_id_; - params->widget = widget_; - params->renderer_settings = viz::CreateRendererSettings(); - params->compositor_frame_sink = mojo::MakeRequest(&compositor_frame_sink); - params->compositor_frame_sink_client = - compositor_frame_sink_client.PassInterface(); - params->display_private = mojo::MakeRequest(&display_private); - params->display_client = display_client.PassInterface(); - window_server_->GetVizHostProxy()->CreateRootCompositorFrameSink( - std::move(params)); - - // Make a FrameGenerator that references |display_to_mirror_|'s surface id. - display_private->SetDisplayVisible(true); - frame_generator_ = std::make_unique<FrameGenerator>(); - auto frame_sink_client_binding = - std::make_unique<CompositorFrameSinkClientBinding>( - frame_generator_.get(), - std::move(compositor_frame_sink_client_request), - std::move(compositor_frame_sink)); - frame_generator_->Bind(std::move(frame_sink_client_binding), - std::move(display_private)); - - frame_generator_->OnWindowSizeChanged(metrics_.bounds_in_pixels.size()); - frame_generator_->SetDeviceScaleFactor(metrics_.device_scale_factor); - frame_generator_->set_scale_and_center(true); - - // Pass the surface info for the mirror source display to the frame generator, - // the id is not available if the source display init is not yet complete. - const viz::SurfaceInfo& info = display_to_mirror_->platform_display() - ->GetFrameGenerator() - ->window_manager_surface_info(); - if (info.id().is_valid()) - frame_generator_->SetEmbeddedSurface(info); -} - -void PlatformDisplayMirror::OnAcceleratedWidgetDestroying() {} - -void PlatformDisplayMirror::OnAcceleratedWidgetDestroyed() {} - -void PlatformDisplayMirror::OnActivationChanged(bool active) {} - -void PlatformDisplayMirror::OnFirstSurfaceActivation( - const viz::SurfaceInfo& surface_info) {} - -void PlatformDisplayMirror::OnFrameTokenChanged(uint32_t frame_token) {} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/platform_display_mirror.h b/services/ui/ws/platform_display_mirror.h deleted file mode 100644 index 7cc712b..0000000 --- a/services/ui/ws/platform_display_mirror.h +++ /dev/null
@@ -1,108 +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 SERVICES_UI_WS_PLATFORM_DISPLAY_MIRROR_H_ -#define SERVICES_UI_WS_PLATFORM_DISPLAY_MIRROR_H_ - -#include <memory> - -#include "base/macros.h" -#include "components/viz/common/surfaces/frame_sink_id.h" -#include "components/viz/host/host_frame_sink_client.h" -#include "services/ui/ws/platform_display.h" -#include "ui/display/display.h" -#include "ui/platform_window/platform_window.h" -#include "ui/platform_window/platform_window_delegate.h" - -namespace ui { -namespace ws { - -class Display; -class WindowServer; - -// PlatformDisplay implementation that mirrors another display. -class PlatformDisplayMirror : public PlatformDisplay, - public ui::PlatformWindowDelegate, - public viz::HostFrameSinkClient { - public: - PlatformDisplayMirror(const display::Display& display, - const display::ViewportMetrics& metrics, - WindowServer* window_server, - Display* display_to_mirror); - ~PlatformDisplayMirror() override; - - const display::Display& display() const { return display_; } - void set_display(const display::Display& display) { display_ = display; } - - Display* display_to_mirror() const { return display_to_mirror_; } - - // PlatformDisplay: - void Init(PlatformDisplayDelegate* delegate) override; - void SetViewportSize(const gfx::Size& size) override; - void SetTitle(const base::string16& title) override; - void SetCapture() override; - void ReleaseCapture() override; - void SetCursor(const ui::CursorData& cursor) override; - void MoveCursorTo(const gfx::Point& window_pixel_location) override; - void SetCursorSize(const ui::CursorSize& cursor_size) override; - void ConfineCursorToBounds(const gfx::Rect& pixel_bounds) override; - void UpdateTextInputState(const ui::TextInputState& state) override; - void SetImeVisibility(bool visible) override; - void UpdateViewportMetrics(const display::ViewportMetrics& metrics) override; - const display::ViewportMetrics& GetViewportMetrics() override; - gfx::AcceleratedWidget GetAcceleratedWidget() const override; - FrameGenerator* GetFrameGenerator() override; - EventSink* GetEventSink() override; - void SetCursorConfig(display::Display::Rotation rotation, - float scale) override; - - // ui::PlatformWindowDelegate: - void OnBoundsChanged(const gfx::Rect& new_bounds) override; - void OnDamageRect(const gfx::Rect& damaged_region) override; - void DispatchEvent(ui::Event* event) override; - void OnCloseRequest() override; - void OnClosed() override; - void OnWindowStateChanged(ui::PlatformWindowState new_state) override; - void OnLostCapture() override; - void OnAcceleratedWidgetAvailable(gfx::AcceleratedWidget widget, - float device_scale_factor) override; - void OnAcceleratedWidgetDestroying() override; - void OnAcceleratedWidgetDestroyed() override; - void OnActivationChanged(bool active) override; - - // viz::HostFrameSinkClient: - void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info) override; - void OnFrameTokenChanged(uint32_t frame_token) override; - - private: - // The basic info and metrics about this mirroring destination display. - display::Display display_; - display::ViewportMetrics metrics_; - - // The WindowServer that owns this object, via DisplayManager. - WindowServer* window_server_; - - // The source ws::Display that this display mirrors. - Display* display_to_mirror_; - - // The frame sink id assigned to this display. - viz::FrameSinkId frame_sink_id_; - - // The window in the underlying platform windowing system (i.e. Wayland/X11). - std::unique_ptr<ui::PlatformWindow> platform_window_; - - // The accelerated widget that provides a surface to paint pixels. - gfx::AcceleratedWidget widget_ = gfx::kNullAcceleratedWidget; - - // The generator that submits frames copied from the source display's surface - // to this destination display's frame sink. - std::unique_ptr<FrameGenerator> frame_generator_; - - DISALLOW_COPY_AND_ASSIGN(PlatformDisplayMirror); -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_PLATFORM_DISPLAY_MIRROR_H_
diff --git a/services/ui/ws/server_window.cc b/services/ui/ws/server_window.cc deleted file mode 100644 index 35c7a20d..0000000 --- a/services/ui/ws/server_window.cc +++ /dev/null
@@ -1,500 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "services/ui/ws/server_window.h" - -#include <inttypes.h> -#include <stddef.h> - -#include "base/strings/stringprintf.h" -#include "components/viz/host/host_frame_sink_manager.h" -#include "components/viz/host/renderer_settings_creation.h" -#include "services/ui/public/interfaces/window_manager.mojom.h" -#include "services/ui/ws/server_window_delegate.h" -#include "services/ui/ws/server_window_observer.h" -#include "services/ui/ws/server_window_tracker.h" -#include "ui/base/cursor/cursor.h" - -namespace ui { -namespace ws { - -ServerWindow::ServerWindow(ServerWindowDelegate* delegate, - const viz::FrameSinkId& frame_sink_id, - const Properties& properties) - : delegate_(delegate), - owning_tree_id_(frame_sink_id.client_id()), - // Default to kPointer as kNull doesn't change the cursor, it leaves - // the last non-null cursor. - cursor_(ui::CursorType::kPointer), - non_client_cursor_(ui::CursorType::kPointer), - properties_(properties), - // Don't notify newly added observers during notification. This causes - // problems for code that adds an observer as part of an observer - // notification (such as ServerWindowDrawTracker). - observers_(base::ObserverListPolicy::EXISTING_ONLY) { - DCHECK(delegate); // Must provide a delegate. - UpdateFrameSinkId(frame_sink_id); -} - -ServerWindow::~ServerWindow() { - for (auto& observer : observers_) - observer.OnWindowDestroying(this); - - if (transient_parent_) - transient_parent_->RemoveTransientWindow(this); - - // Destroy transient children, only after we've removed ourselves from our - // parent, as destroying an active transient child may otherwise attempt to - // refocus us. - Windows transient_children(transient_children_); - for (auto* window : transient_children) - delete window; - DCHECK(transient_children_.empty()); - - while (!children_.empty()) - children_.front()->parent()->Remove(children_.front()); - - if (parent_) - parent_->Remove(this); - - for (auto& observer : observers_) - observer.OnWindowDestroyed(this); - - auto* host_frame_sink_manager = delegate_->GetVizHostProxy(); - if (host_frame_sink_manager) - host_frame_sink_manager->InvalidateFrameSinkId(frame_sink_id_); -} - -void ServerWindow::AddObserver(ServerWindowObserver* observer) { - observers_.AddObserver(observer); -} - -void ServerWindow::RemoveObserver(ServerWindowObserver* observer) { - DCHECK(observers_.HasObserver(observer)); - observers_.RemoveObserver(observer); -} - -bool ServerWindow::HasObserver(ServerWindowObserver* observer) { - return observers_.HasObserver(observer); -} - -void ServerWindow::CreateRootCompositorFrameSink( - gfx::AcceleratedWidget widget, - viz::mojom::CompositorFrameSinkAssociatedRequest sink_request, - viz::mojom::CompositorFrameSinkClientPtr client, - viz::mojom::DisplayPrivateAssociatedRequest display_request, - viz::mojom::DisplayClientPtr display_client) { - has_created_compositor_frame_sink_ = true; - // TODO(fsamuel): AcceleratedWidget cannot be transported over IPC for Mac - // or Android. We should instead use GpuSurfaceTracker here on those - // platforms. - - auto params = viz::mojom::RootCompositorFrameSinkParams::New(); - params->frame_sink_id = frame_sink_id_; - params->widget = widget; - params->renderer_settings = viz::CreateRendererSettings(); - params->compositor_frame_sink = std::move(sink_request); - params->compositor_frame_sink_client = client.PassInterface(); - params->display_private = std::move(display_request); - params->display_client = display_client.PassInterface(); - - delegate_->GetVizHostProxy()->CreateRootCompositorFrameSink( - std::move(params)); -} - -void ServerWindow::CreateCompositorFrameSink( - viz::mojom::CompositorFrameSinkRequest request, - viz::mojom::CompositorFrameSinkClientPtr client) { - has_created_compositor_frame_sink_ = true; - delegate_->GetVizHostProxy()->CreateCompositorFrameSink( - frame_sink_id_, std::move(request), std::move(client)); -} - -void ServerWindow::UpdateFrameSinkId(const viz::FrameSinkId& frame_sink_id) { - DCHECK(frame_sink_id.is_valid()); - auto* host_frame_sink_manager = delegate_->GetVizHostProxy(); - DCHECK(host_frame_sink_manager); - host_frame_sink_manager->RegisterFrameSinkId(frame_sink_id, this); - host_frame_sink_manager->SetFrameSinkDebugLabel(frame_sink_id, GetName()); - if (frame_sink_id_.is_valid()) { - if (parent()) { - host_frame_sink_manager->UnregisterFrameSinkHierarchy( - parent()->frame_sink_id(), frame_sink_id_); - host_frame_sink_manager->RegisterFrameSinkHierarchy( - parent()->frame_sink_id(), frame_sink_id); - } - host_frame_sink_manager->InvalidateFrameSinkId(frame_sink_id_); - } - frame_sink_id_ = frame_sink_id; -} - -void ServerWindow::Add(ServerWindow* child) { - // We assume validation checks happened already. - DCHECK(child); - DCHECK(child != this); - DCHECK(!child->Contains(this)); - if (child->parent() == this) { - if (children_.size() == 1) - return; // Already in the right position. - child->Reorder(children_.back(), mojom::OrderDirection::ABOVE); - return; - } - - ServerWindow* old_parent = child->parent(); - for (auto& observer : child->observers_) - observer.OnWillChangeWindowHierarchy(child, this, old_parent); - - if (child->parent()) - child->parent()->RemoveImpl(child); - - child->parent_ = this; - children_.push_back(child); - - for (auto& observer : child->observers_) - observer.OnWindowHierarchyChanged(child, this, old_parent); -} - -void ServerWindow::Remove(ServerWindow* child) { - // We assume validation checks happened else where. - DCHECK(child); - DCHECK(child != this); - DCHECK(child->parent() == this); - - for (auto& observer : child->observers_) - observer.OnWillChangeWindowHierarchy(child, nullptr, this); - - RemoveImpl(child); - - for (auto& observer : child->observers_) - observer.OnWindowHierarchyChanged(child, nullptr, this); -} - -void ServerWindow::RemoveAllChildren() { - while (!children_.empty()) - Remove(children_[0]); -} - -void ServerWindow::Reorder(ServerWindow* relative, - mojom::OrderDirection direction) { - parent_->children_.erase( - std::find(parent_->children_.begin(), parent_->children_.end(), this)); - Windows::iterator i = - std::find(parent_->children_.begin(), parent_->children_.end(), relative); - if (direction == mojom::OrderDirection::ABOVE) { - DCHECK(i != parent_->children_.end()); - parent_->children_.insert(++i, this); - } else if (direction == mojom::OrderDirection::BELOW) { - DCHECK(i != parent_->children_.end()); - parent_->children_.insert(i, this); - } - for (auto& observer : observers_) - observer.OnWindowReordered(this, relative, direction); - OnStackingChanged(); -} - -void ServerWindow::StackChildAtBottom(ServerWindow* child) { - // There's nothing to do if the child is already at the bottom. - if (children_.size() <= 1 || child == children_.front()) - return; - child->Reorder(children_.front(), mojom::OrderDirection::BELOW); -} - -void ServerWindow::StackChildAtTop(ServerWindow* child) { - // There's nothing to do if the child is already at the top. - if (children_.size() <= 1 || child == children_.back()) - return; - child->Reorder(children_.back(), mojom::OrderDirection::ABOVE); -} - -void ServerWindow::SetBounds( - const gfx::Rect& bounds, - const base::Optional<viz::LocalSurfaceId>& local_surface_id) { - if (bounds_ == bounds && current_local_surface_id_ == local_surface_id) - return; - - const gfx::Rect old_bounds = bounds_; - - current_local_surface_id_ = local_surface_id; - - bounds_ = bounds; - for (auto& observer : observers_) - observer.OnWindowBoundsChanged(this, old_bounds, bounds); -} - -void ServerWindow::SetClientArea( - const gfx::Insets& insets, - const std::vector<gfx::Rect>& additional_client_areas) { - if (client_area_ == insets && - additional_client_areas == additional_client_areas_) { - return; - } - - additional_client_areas_ = additional_client_areas; - client_area_ = insets; - for (auto& observer : observers_) - observer.OnWindowClientAreaChanged(this, insets, additional_client_areas); -} - -void ServerWindow::SetHitTestMask(const gfx::Rect& mask) { - hit_test_mask_ = std::make_unique<gfx::Rect>(mask); -} - -void ServerWindow::ClearHitTestMask() { - hit_test_mask_.reset(); -} - -void ServerWindow::SetCanAcceptDrops(bool accepts_drops) { - accepts_drops_ = accepts_drops; -} - -const ServerWindow* ServerWindow::GetRootForDrawn() const { - return delegate_->GetRootWindowForDrawn(this); -} - -bool ServerWindow::AddTransientWindow(ServerWindow* child) { - if (child->transient_parent()) - child->transient_parent()->RemoveTransientWindow(child); - - DCHECK(std::find(transient_children_.begin(), transient_children_.end(), - child) == transient_children_.end()); - transient_children_.push_back(child); - child->transient_parent_ = this; - - for (auto& observer : observers_) - observer.OnTransientWindowAdded(this, child); - return true; -} - -void ServerWindow::RemoveTransientWindow(ServerWindow* child) { - Windows::iterator i = - std::find(transient_children_.begin(), transient_children_.end(), child); - DCHECK(i != transient_children_.end()); - transient_children_.erase(i); - DCHECK_EQ(this, child->transient_parent()); - child->transient_parent_ = nullptr; - - for (auto& observer : observers_) - observer.OnTransientWindowRemoved(this, child); -} - -bool ServerWindow::HasTransientAncestor(const ServerWindow* window) const { - const ServerWindow* transient_ancestor = this; - while (transient_ancestor && transient_ancestor != window) - transient_ancestor = transient_ancestor->transient_parent_; - return transient_ancestor == window; -} - -void ServerWindow::SetModalType(ModalType modal_type) { - if (modal_type_ == modal_type) - return; - - const ModalType old_modal_type = modal_type_; - modal_type_ = modal_type; - for (auto& observer : observers_) - observer.OnWindowModalTypeChanged(this, old_modal_type); -} - -void ServerWindow::SetChildModalParent(ServerWindow* modal_parent) { - if (modal_parent) { - child_modal_parent_tracker_ = std::make_unique<ServerWindowTracker>(); - child_modal_parent_tracker_->Add(modal_parent); - } else { - child_modal_parent_tracker_.reset(); - } -} - -const ServerWindow* ServerWindow::GetChildModalParent() const { - return child_modal_parent_tracker_ && - !child_modal_parent_tracker_->windows().empty() - ? *child_modal_parent_tracker_->windows().begin() - : nullptr; -} - -bool ServerWindow::Contains(const ServerWindow* window) const { - for (const ServerWindow* parent = window; parent; parent = parent->parent_) { - if (parent == this) - return true; - } - return false; -} - -void ServerWindow::SetVisible(bool value) { - if (visible_ == value) - return; - - for (auto& observer : observers_) - observer.OnWillChangeWindowVisibility(this); - visible_ = value; - for (auto& observer : observers_) - observer.OnWindowVisibilityChanged(this); -} - -void ServerWindow::SetOpacity(float value) { - if (value == opacity_) - return; - float old_opacity = opacity_; - opacity_ = value; - for (auto& observer : observers_) - observer.OnWindowOpacityChanged(this, old_opacity, opacity_); -} - -void ServerWindow::SetCursor(ui::CursorData value) { - if (cursor_.IsSameAs(value)) - return; - cursor_ = std::move(value); - for (auto& observer : observers_) - observer.OnWindowCursorChanged(this, cursor_); -} - -void ServerWindow::SetNonClientCursor(ui::CursorData value) { - if (non_client_cursor_.IsSameAs(value)) - return; - non_client_cursor_ = std::move(value); - for (auto& observer : observers_) - observer.OnWindowNonClientCursorChanged(this, non_client_cursor_); -} - -void ServerWindow::SetTransform(const gfx::Transform& transform) { - if (transform_ == transform) - return; - - const gfx::Transform old_transform = transform_; - transform_ = transform; - for (auto& observer : observers_) - observer.OnWindowTransformChanged(this, old_transform, transform); -} - -void ServerWindow::SetProperty(const std::string& name, - const std::vector<uint8_t>* value) { - auto it = properties_.find(name); - if (it != properties_.end()) { - if (value && it->second == *value) - return; - } else if (!value) { - // This property isn't set in |properties_| and |value| is nullptr, so - // there's - // no change. - return; - } - - if (value) { - properties_[name] = *value; - } else if (it != properties_.end()) { - properties_.erase(it); - } - auto* host_frame_sink_manager = delegate_->GetVizHostProxy(); - if (host_frame_sink_manager && name == mojom::WindowManager::kName_Property) - host_frame_sink_manager->SetFrameSinkDebugLabel(frame_sink_id_, GetName()); - - for (auto& observer : observers_) - observer.OnWindowSharedPropertyChanged(this, name, value); -} - -std::string ServerWindow::GetName() const { - auto it = properties_.find(mojom::WindowManager::kName_Property); - if (it == properties_.end()) - return std::string(); - return std::string(it->second.begin(), it->second.end()); -} - -void ServerWindow::SetTextInputState(const ui::TextInputState& state) { - const bool changed = !(text_input_state_ == state); - if (changed) { - text_input_state_ = state; - // keyboard even if the state is not changed. So we have to notify - // |observers_|. - for (auto& observer : observers_) - observer.OnWindowTextInputStateChanged(this, state); - } -} - -bool ServerWindow::IsDrawn() const { - const ServerWindow* root = delegate_->GetRootWindowForDrawn(this); - if (!root || !root->visible()) - return false; - const ServerWindow* window = this; - while (window && window != root && window->visible()) - window = window->parent(); - return root == window; -} - -mojom::ShowState ServerWindow::GetShowState() const { - auto iter = properties_.find(mojom::WindowManager::kShowState_Property); - if (iter == properties_.end() || iter->second.empty()) - return mojom::ShowState::DEFAULT; - - return static_cast<mojom::ShowState>(iter->second[0]); -} - -void ServerWindow::SetUnderlayOffset(const gfx::Vector2d& offset) { - if (offset == underlay_offset_) - return; - - underlay_offset_ = offset; -} - -void ServerWindow::OnEmbeddedAppDisconnected() { - for (auto& observer : observers_) - observer.OnWindowEmbeddedAppDisconnected(this); -} - -#if DCHECK_IS_ON() -std::string ServerWindow::GetDebugWindowHierarchy() const { - std::string result; - BuildDebugInfo(std::string(), &result); - return result; -} - -std::string ServerWindow::GetDebugWindowInfo() const { - std::string name = GetName(); - if (name.empty()) - name = "(no name)"; - - std::string frame_sink; - if (has_created_compositor_frame_sink_) - frame_sink = " [" + frame_sink_id_.ToString() + "]"; - - return base::StringPrintf( - "visible=%s bounds=%s name=%s%s", visible_ ? "true" : "false", - bounds_.ToString().c_str(), name.c_str(), frame_sink.c_str()); -} - -void ServerWindow::BuildDebugInfo(const std::string& depth, - std::string* result) const { - *result += - base::StringPrintf("%s%s\n", depth.c_str(), GetDebugWindowInfo().c_str()); - for (const ServerWindow* child : children_) - child->BuildDebugInfo(depth + " ", result); -} -#endif // DCHECK_IS_ON() - -void ServerWindow::OnFirstSurfaceActivation( - const viz::SurfaceInfo& surface_info) { - delegate_->OnFirstSurfaceActivation(surface_info, this); -} - -void ServerWindow::OnFrameTokenChanged(uint32_t frame_token) { - // TODO(yiyix, fsamuel): Implement frame token propagation for Mus. See - // crbug.com/771331 -} - -void ServerWindow::RemoveImpl(ServerWindow* window) { - window->parent_ = nullptr; - children_.erase(std::find(children_.begin(), children_.end(), window)); -} - -void ServerWindow::OnStackingChanged() { - if (stacking_target_) { - Windows::const_iterator window_i = std::find( - parent()->children().begin(), parent()->children().end(), this); - DCHECK(window_i != parent()->children().end()); - if (window_i != parent()->children().begin() && - (*(window_i - 1) == stacking_target_)) { - return; - } - } -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/server_window.h b/services/ui/ws/server_window.h deleted file mode 100644 index 845c7ae1..0000000 --- a/services/ui/ws/server_window.h +++ /dev/null
@@ -1,324 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SERVICES_UI_WS_SERVER_WINDOW_H_ -#define SERVICES_UI_WS_SERVER_WINDOW_H_ - -#include <stdint.h> - -#include <map> -#include <string> -#include <vector> - -#include "base/logging.h" -#include "base/macros.h" -#include "base/observer_list.h" -#include "components/viz/common/surfaces/frame_sink_id.h" -#include "components/viz/host/host_frame_sink_client.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "services/ui/public/interfaces/window_tree.mojom.h" -#include "services/ui/public/interfaces/window_tree_constants.mojom.h" -#include "services/ui/ws/ids.h" -#include "services/viz/privileged/interfaces/compositing/display_private.mojom.h" -#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h" -#include "ui/base/window_tracker_template.h" -#include "ui/gfx/geometry/insets.h" -#include "ui/gfx/geometry/rect.h" -#include "ui/gfx/geometry/vector2d.h" -#include "ui/gfx/native_widget_types.h" -#include "ui/gfx/transform.h" -#include "ui/platform_window/text_input_state.h" - -namespace ui { -namespace ws { - -class ServerWindowDelegate; -class ServerWindowObserver; - -// Server side representation of a window. Delegate is informed of interesting -// events. -// -// It is assumed that all functions that mutate the tree have validated the -// mutation is possible before hand. For example, Reorder() assumes the supplied -// window is a child and not already in position. -// -// ServerWindows do not own their children. If you delete a window that has -// children the children are implicitly removed. Similarly if a window has a -// parent and the window is deleted the deleted window is implicitly removed -// from the parent. -class ServerWindow : public viz::HostFrameSinkClient { - public: - using Properties = std::map<std::string, std::vector<uint8_t>>; - using Windows = std::vector<ServerWindow*>; - - // |frame_sink_id| needs to be an input here as we are creating frame_sink_id_ - // based on the ClientWindowId clients provided. - ServerWindow(ServerWindowDelegate* delegate, - const viz::FrameSinkId& frame_sink_id, - const Properties& properties = Properties()); - ~ServerWindow() override; - - void AddObserver(ServerWindowObserver* observer); - void RemoveObserver(ServerWindowObserver* observer); - bool HasObserver(ServerWindowObserver* observer); - - // Creates a new CompositorFrameSink of the specified type, replacing the - // existing. - void CreateRootCompositorFrameSink( - gfx::AcceleratedWidget widget, - viz::mojom::CompositorFrameSinkAssociatedRequest sink_request, - viz::mojom::CompositorFrameSinkClientPtr client, - viz::mojom::DisplayPrivateAssociatedRequest display_request, - viz::mojom::DisplayClientPtr display_client); - - void CreateCompositorFrameSink( - viz::mojom::CompositorFrameSinkRequest request, - viz::mojom::CompositorFrameSinkClientPtr client); - - // Id of the tree that owns and created this window. - ClientSpecificId owning_tree_id() const { return owning_tree_id_; } - - const viz::FrameSinkId& frame_sink_id() const { return frame_sink_id_; } - void UpdateFrameSinkId(const viz::FrameSinkId& frame_sink_id); - - const base::Optional<viz::LocalSurfaceId>& current_local_surface_id() const { - return current_local_surface_id_; - } - - // Add the child to this window. - void Add(ServerWindow* child); - - // Removes the child window, but does not delete it. - void Remove(ServerWindow* child); - - // Removes all child windows from this window, but does not delete them. - void RemoveAllChildren(); - - void Reorder(ServerWindow* relative, mojom::OrderDirection diretion); - void StackChildAtBottom(ServerWindow* child); - void StackChildAtTop(ServerWindow* child); - - const gfx::Rect& bounds() const { return bounds_; } - // Sets the bounds. If the size changes this implicitly resets the client - // area to fill the whole bounds. - void SetBounds(const gfx::Rect& bounds, - const base::Optional<viz::LocalSurfaceId>& local_surface_id = - base::nullopt); - - const std::vector<gfx::Rect>& additional_client_areas() const { - return additional_client_areas_; - } - const gfx::Insets& client_area() const { return client_area_; } - void SetClientArea(const gfx::Insets& insets, - const std::vector<gfx::Rect>& additional_client_areas); - - const gfx::Rect* hit_test_mask() const { return hit_test_mask_.get(); } - void SetHitTestMask(const gfx::Rect& mask); - void ClearHitTestMask(); - - bool can_accept_drops() const { return accepts_drops_; } - void SetCanAcceptDrops(bool accepts_drags); - - const ui::CursorData& cursor() const { return cursor_; } - const ui::CursorData& non_client_cursor() const { return non_client_cursor_; } - - const ServerWindow* parent() const { return parent_; } - ServerWindow* parent() { return parent_; } - - // Returns the root window used in checking drawn status. This is not - // necessarily the same as the root window used in event dispatch. - // NOTE: this returns null if the window does not have an ancestor associated - // with a display. - const ServerWindow* GetRootForDrawn() const; - ServerWindow* GetRootForDrawn() { - return const_cast<ServerWindow*>( - const_cast<const ServerWindow*>(this)->GetRootForDrawn()); - } - - const Windows& children() const { return children_; } - - // Transient window management. - // Adding transient child fails if the child window is modal to system. - bool AddTransientWindow(ServerWindow* child); - void RemoveTransientWindow(ServerWindow* child); - - ServerWindow* transient_parent() { return transient_parent_; } - const ServerWindow* transient_parent() const { return transient_parent_; } - - const Windows& transient_children() const { return transient_children_; } - - // Returns true if |this| is a transient descendant of |window|. - bool HasTransientAncestor(const ServerWindow* window) const; - - ModalType modal_type() const { return modal_type_; } - void SetModalType(ModalType modal_type); - - void SetChildModalParent(ServerWindow* modal_parent); - const ServerWindow* GetChildModalParent() const; - ServerWindow* GetChildModalParent() { - return const_cast<ServerWindow*>( - const_cast<const ServerWindow*>(this)->GetChildModalParent()); - } - - // Returns true if this contains |window| or is |window|. - bool Contains(const ServerWindow* window) const; - - // Returns the visibility requested by this window. IsDrawn() returns whether - // the window is actually visible on screen. - bool visible() const { return visible_; } - void SetVisible(bool value); - - float opacity() const { return opacity_; } - void SetOpacity(float value); - - void SetCursor(ui::CursorData cursor); - void SetNonClientCursor(ui::CursorData cursor); - - const gfx::Transform& transform() const { return transform_; } - void SetTransform(const gfx::Transform& transform); - - const std::map<std::string, std::vector<uint8_t>>& properties() const { - return properties_; - } - void SetProperty(const std::string& name, const std::vector<uint8_t>* value); - - std::string GetName() const; - - void SetTextInputState(const ui::TextInputState& state); - const ui::TextInputState& text_input_state() const { - return text_input_state_; - } - - void set_can_focus(bool can_focus) { can_focus_ = can_focus; } - bool can_focus() const { return can_focus_; } - - void set_is_activation_parent(bool value) { is_activation_parent_ = value; } - bool is_activation_parent() const { return is_activation_parent_; } - - bool has_created_compositor_frame_sink() const { - return has_created_compositor_frame_sink_; - } - - void set_event_targeting_policy(mojom::EventTargetingPolicy policy) { - event_targeting_policy_ = policy; - } - mojom::EventTargetingPolicy event_targeting_policy() const { - return event_targeting_policy_; - } - - // Returns true if this window is attached to a root and all ancestors are - // visible. - bool IsDrawn() const; - - mojom::ShowState GetShowState() const; - - const gfx::Insets& extended_mouse_hit_test_region() const { - return extended_mouse_hit_test_region_; - } - const gfx::Insets& extended_touch_hit_test_region() const { - return extended_touch_hit_test_region_; - } - void set_extended_hit_test_regions_for_children( - const gfx::Insets& mouse_insets, - const gfx::Insets& touch_insets) { - extended_mouse_hit_test_region_ = mouse_insets; - extended_touch_hit_test_region_ = touch_insets; - } - - // Offset of the underlay from the the window bounds (used for shadows). - const gfx::Vector2d& underlay_offset() const { return underlay_offset_; } - void SetUnderlayOffset(const gfx::Vector2d& offset); - - ServerWindowDelegate* delegate() { return delegate_; } - - // Called when the window is no longer an embed root. - void OnEmbeddedAppDisconnected(); - -#if DCHECK_IS_ON() - std::string GetDebugWindowHierarchy() const; - std::string GetDebugWindowInfo() const; - void BuildDebugInfo(const std::string& depth, std::string* result) const; -#endif - - private: - // viz::HostFrameSinkClient implementation. - void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info) override; - void OnFrameTokenChanged(uint32_t frame_token) override; - - // Implementation of removing a window. Doesn't send any notification. - void RemoveImpl(ServerWindow* window); - - // Called when this window's stacking order among its siblings is changed. - void OnStackingChanged(); - - ServerWindowDelegate* const delegate_; - // This is the client id of the WindowTree that owns this window. This is - // cached as the |frame_sink_id_| may change. - const ClientSpecificId owning_tree_id_; - // This may change for embed windows. - viz::FrameSinkId frame_sink_id_; - base::Optional<viz::LocalSurfaceId> current_local_surface_id_; - - ServerWindow* parent_ = nullptr; - Windows children_; - - // Transient window management. - // If non-null we're actively restacking transient as the result of a - // transient ancestor changing. - ServerWindow* stacking_target_ = nullptr; - ServerWindow* transient_parent_ = nullptr; - Windows transient_children_; - - ModalType modal_type_ = MODAL_TYPE_NONE; - bool visible_ = false; - gfx::Rect bounds_; - gfx::Insets client_area_; - std::vector<gfx::Rect> additional_client_areas_; - ui::CursorData cursor_; - ui::CursorData non_client_cursor_; - float opacity_ = 1.0f; - bool can_focus_ = true; - mojom::EventTargetingPolicy event_targeting_policy_ = - mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS; - gfx::Transform transform_; - ui::TextInputState text_input_state_; - - Properties properties_; - - gfx::Vector2d underlay_offset_; - - // The hit test for windows extends outside the bounds of the window by this - // amount. - gfx::Insets extended_mouse_hit_test_region_; - gfx::Insets extended_touch_hit_test_region_; - - // Mouse events outside the hit test mask don't hit the window. An empty mask - // means all events miss the window. If null there is no mask. - std::unique_ptr<gfx::Rect> hit_test_mask_; - - // Whether this window can be the target in a drag and drop - // operation. Clients must opt-in to this. - bool accepts_drops_ = false; - - base::ObserverList<ServerWindowObserver> observers_; - - // Used to track the modal parent of a child modal window. - std::unique_ptr<WindowTrackerTemplate<ServerWindow, ServerWindowObserver>> - child_modal_parent_tracker_; - - // Whether the children of this window can be active. Also used to determine - // when a window is considered top level. That is, if true the children of - // this window are considered top level windows. - bool is_activation_parent_ = false; - - // Used by tests to know whether clients have already drawn this window. - bool has_created_compositor_frame_sink_ = false; - - DISALLOW_COPY_AND_ASSIGN(ServerWindow); -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_SERVER_WINDOW_H_
diff --git a/services/ui/ws/server_window_delegate.h b/services/ui/ws/server_window_delegate.h deleted file mode 100644 index ad74d98c..0000000 --- a/services/ui/ws/server_window_delegate.h +++ /dev/null
@@ -1,84 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SERVICES_UI_WS_SERVER_WINDOW_DELEGATE_H_ -#define SERVICES_UI_WS_SERVER_WINDOW_DELEGATE_H_ - -#include <memory> - -#include "services/ui/public/interfaces/window_tree.mojom.h" -#include "services/ui/public/interfaces/window_tree_constants.mojom.h" -#include "services/viz/privileged/interfaces/compositing/frame_sink_manager.mojom.h" - -namespace viz { -class HitTestQuery; -class HostFrameSinkClient; -} - -namespace ui { - -namespace ws { - -class ServerWindow; - -// A proxy to communicate to the viz host (usually viz::HostFrameSinkManager). -// If mus is hosting viz, then it forwards all the calls to the appropriate viz -// host. If mus is not hosting viz, then it drops all calls. It is always safe -// to call any method on this proxy. See documentation in -// viz::HostFrameSinkManager for the documentation for the methods. -class VizHostProxy { - public: - virtual ~VizHostProxy() {} - - virtual void RegisterFrameSinkId(const viz::FrameSinkId& frame_sink_id, - viz::HostFrameSinkClient* client) = 0; - - virtual void SetFrameSinkDebugLabel(const viz::FrameSinkId& frame_sink_id, - const std::string& name) = 0; - - virtual void InvalidateFrameSinkId(const viz::FrameSinkId& frame_sink_id) = 0; - - virtual void RegisterFrameSinkHierarchy(const viz::FrameSinkId& new_parent, - const viz::FrameSinkId& child) = 0; - virtual void UnregisterFrameSinkHierarchy(const viz::FrameSinkId& old_parent, - const viz::FrameSinkId& child) = 0; - - virtual void CreateRootCompositorFrameSink( - viz::mojom::RootCompositorFrameSinkParamsPtr params) = 0; - - virtual void CreateCompositorFrameSink( - const viz::FrameSinkId& frame_sink_id, - viz::mojom::CompositorFrameSinkRequest request, - viz::mojom::CompositorFrameSinkClientPtr client) = 0; - - virtual viz::HitTestQuery* GetHitTestQuery( - const viz::FrameSinkId& frame_sink_id) = 0; -}; - -class ServerWindowDelegate { - public: - // Returns a proxy to communicate to the viz host. This must always return - // non-null. - virtual VizHostProxy* GetVizHostProxy() = 0; - - // Returns the root of the window tree to which this |window| is attached. - // Returns null if this window is not attached up through to a root window. - // The returned root is used for drawn checks and may differ from that used - // for event dispatch purposes. - virtual ServerWindow* GetRootWindowForDrawn(const ServerWindow* window) = 0; - - // Called when a CompositorFrame with a new SurfaceId activates for the first - // time for |window|. - virtual void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info, - ServerWindow* window) = 0; - - protected: - virtual ~ServerWindowDelegate() {} -}; - -} // namespace ws - -} // namespace ui - -#endif // SERVICES_UI_WS_SERVER_WINDOW_DELEGATE_H_
diff --git a/services/ui/ws/server_window_drawn_tracker.cc b/services/ui/ws/server_window_drawn_tracker.cc deleted file mode 100644 index 29d01c7..0000000 --- a/services/ui/ws/server_window_drawn_tracker.cc +++ /dev/null
@@ -1,159 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "services/ui/ws/server_window_drawn_tracker.h" - -#include "services/ui/ws/server_window.h" -#include "services/ui/ws/server_window_drawn_tracker_observer.h" - -namespace ui { - -namespace ws { - -ServerWindowDrawnTracker::ServerWindowDrawnTracker( - ServerWindow* window, - ServerWindowDrawnTrackerObserver* observer) - : window_(window), - observer_(observer), - drawn_(window->IsDrawn()), - weak_factory_(this) { - AddObservers(); -} - -ServerWindowDrawnTracker::~ServerWindowDrawnTracker() { - RemoveObservers(); -} - -void ServerWindowDrawnTracker::SetDrawn(ServerWindow* ancestor, bool drawn) { - // If |windows_| is empty when this code runs, that means |window_| has been - // destroyed. So set |window_| to nullptr, but make sure the right value is - // sent to OnDrawnStateChanged(). - ServerWindow* window = window_; - if (windows_.empty()) - window_ = nullptr; - - if (drawn == drawn_) - return; - - drawn_ = drawn; - observer_->OnDrawnStateChanged(ancestor, window, drawn); -} - -void ServerWindowDrawnTracker::AddObservers() { - if (!window_) { - root_ = nullptr; - return; - } - - ServerWindow* last = window_; - for (ServerWindow* v = window_; v; v = v->parent()) { - v->AddObserver(this); - windows_.insert(v); - last = v; - } - DCHECK(last); - root_ = last; -} - -void ServerWindowDrawnTracker::RemoveObservers() { - for (ServerWindow* window : windows_) - window->RemoveObserver(this); - - windows_.clear(); -} - -void ServerWindowDrawnTracker::OnWindowDestroying(ServerWindow* window) { - if (!drawn_) - return; - observer_->OnDrawnStateWillChange(window->parent(), window_, false); -} - -void ServerWindowDrawnTracker::OnWindowDestroyed(ServerWindow* window) { - // As windows are removed before being destroyed, resulting in - // OnWindowHierarchyChanged() and us removing ourself as an observer, the only - // window we should ever get notified of destruction on is |window_|. - DCHECK_EQ(window, window_); - RemoveObservers(); - SetDrawn(nullptr, false); -} - -void ServerWindowDrawnTracker::OnWillChangeWindowHierarchy( - ServerWindow* window, - ServerWindow* new_parent, - ServerWindow* old_parent) { - bool new_is_drawn = new_parent && new_parent->IsDrawn(); - if (new_is_drawn) { - for (ServerWindow* w = window_; new_is_drawn && w != old_parent; - w = w->parent()) { - new_is_drawn = w->visible(); - } - } - if (drawn_ != new_is_drawn) { - auto ref = weak_factory_.GetWeakPtr(); - observer_->OnDrawnStateWillChange(new_is_drawn ? nullptr : old_parent, - window_, new_is_drawn); - // Allow for the |observer_| to delete |this|. - if (!ref) - return; - } - - if (!root_->Contains(new_parent)) - observer_->OnRootWillChange(old_parent, window_); -} - -void ServerWindowDrawnTracker::OnWindowHierarchyChanged( - ServerWindow* window, - ServerWindow* new_parent, - ServerWindow* old_parent) { - ServerWindow* old_root = root_; - RemoveObservers(); - AddObservers(); - const bool is_drawn = window_->IsDrawn(); - auto ref = weak_factory_.GetWeakPtr(); - SetDrawn(is_drawn ? nullptr : old_parent, is_drawn); - // Allow for the |observer_| to delete |this|. - if (!ref) - return; - if (old_root != root_) - observer_->OnRootDidChange(old_parent, window); -} - -void ServerWindowDrawnTracker::OnWillChangeWindowVisibility( - ServerWindow* window) { - bool will_change = false; - if (drawn_) { - // If |window_| is currently drawn, then any change of visibility of the - // windows will toggle the drawn status. - will_change = true; - } else { - // If |window| is currently visible, then it's becoming invisible, and so - // |window_| will remain not drawn. - if (window->visible()) { - will_change = false; - } else { - bool is_drawn = (window->GetRootForDrawn() == window) || - (window->parent() && window->parent()->IsDrawn()); - if (is_drawn) { - for (ServerWindow* w = window_; is_drawn && w != window; - w = w->parent()) - is_drawn = w->visible(); - } - will_change = drawn_ != is_drawn; - } - } - if (will_change) { - bool new_is_drawn = !drawn_; - observer_->OnDrawnStateWillChange(new_is_drawn ? nullptr : window->parent(), - window_, new_is_drawn); - } -} - -void ServerWindowDrawnTracker::OnWindowVisibilityChanged(ServerWindow* window) { - const bool is_drawn = window_->IsDrawn(); - SetDrawn(is_drawn ? nullptr : window->parent(), is_drawn); -} - -} // namespace ws - -} // namespace ui
diff --git a/services/ui/ws/server_window_drawn_tracker.h b/services/ui/ws/server_window_drawn_tracker.h deleted file mode 100644 index 9ae7d07..0000000 --- a/services/ui/ws/server_window_drawn_tracker.h +++ /dev/null
@@ -1,69 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SERVICES_UI_WS_SERVER_WINDOW_DRAWN_TRACKER_H_ -#define SERVICES_UI_WS_SERVER_WINDOW_DRAWN_TRACKER_H_ - -#include <set> - -#include "base/macros.h" -#include "base/memory/weak_ptr.h" -#include "services/ui/ws/server_window_observer.h" - -namespace ui { - -namespace ws { - -class ServerWindowDrawnTrackerObserver; - -// ServerWindowDrawnTracker notifies its observer any time the drawn state of -// the supplied window changes. -// -// NOTE: you must ensure this class is destroyed before the root. -class ServerWindowDrawnTracker : public ServerWindowObserver { - public: - ServerWindowDrawnTracker(ServerWindow* window, - ServerWindowDrawnTrackerObserver* observer); - ~ServerWindowDrawnTracker() override; - - ServerWindow* window() { return window_; } - - private: - void SetDrawn(ServerWindow* ancestor, bool drawn); - - // Adds |this| as an observer to |window_| and its ancestors. - void AddObservers(); - - // Stops observerving any windows we added as an observer in AddObservers(). - void RemoveObservers(); - - // ServerWindowObserver: - void OnWindowDestroying(ServerWindow* window) override; - void OnWindowDestroyed(ServerWindow* window) override; - void OnWillChangeWindowHierarchy(ServerWindow* window, - ServerWindow* new_parent, - ServerWindow* old_parent) override; - void OnWindowHierarchyChanged(ServerWindow* window, - ServerWindow* new_parent, - ServerWindow* old_parent) override; - void OnWillChangeWindowVisibility(ServerWindow* window) override; - void OnWindowVisibilityChanged(ServerWindow* window) override; - - ServerWindow* root_ = nullptr; - ServerWindow* window_; - ServerWindowDrawnTrackerObserver* observer_; - bool drawn_; - // Set of windows we're observing. This is |window_| and all its ancestors. - std::set<ServerWindow*> windows_; - - base::WeakPtrFactory<ServerWindowDrawnTracker> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(ServerWindowDrawnTracker); -}; - -} // namespace ws - -} // namespace ui - -#endif // SERVICES_UI_WS_SERVER_WINDOW_DRAWN_TRACKER_H_
diff --git a/services/ui/ws/server_window_drawn_tracker_observer.h b/services/ui/ws/server_window_drawn_tracker_observer.h deleted file mode 100644 index 773a0de..0000000 --- a/services/ui/ws/server_window_drawn_tracker_observer.h +++ /dev/null
@@ -1,49 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SERVICES_UI_WS_SERVER_WINDOW_DRAWN_TRACKER_OBSERVER_H_ -#define SERVICES_UI_WS_SERVER_WINDOW_DRAWN_TRACKER_OBSERVER_H_ - -namespace ui { - -namespace ws { - -class ServerWindow; - -class ServerWindowDrawnTrackerObserver { - public: - // Invoked right before the drawn state changes. If |is_drawn| is false, - // |ancestor| identifies where the change will occur. In the case of a remove, - // |ancestor| is the parent of the window that will be removed (causing the - // drawn state to change). In the case of visibility change, |ancestor| is the - // parent of the window whose visibility will change. - virtual void OnDrawnStateWillChange(ServerWindow* ancestor, - ServerWindow* window, - bool is_drawn) {} - - // Invoked when the drawn state changes. If |is_drawn| is false |ancestor| - // identifies where the change occurred. In the case of a remove |ancestor| is - // the parent of the window that was removed. In the case of a visibility - // change |ancestor| is the parent of the window whose visibility changed. - virtual void OnDrawnStateChanged(ServerWindow* ancestor, - ServerWindow* window, - bool is_drawn) {} - - // Invoked if the root will change as the result of a child of |ancestor| - // being moved to a new root. - virtual void OnRootWillChange(ServerWindow* ancestor, ServerWindow* window) {} - - // Invoked after the root changed. |ancestor| is the old ancestor that was the - // old parent of the window (not necessarily |window|) that was moved. - virtual void OnRootDidChange(ServerWindow* ancestor, ServerWindow* window) {} - - protected: - virtual ~ServerWindowDrawnTrackerObserver() {} -}; - -} // namespace ws - -} // namespace ui - -#endif // SERVICES_UI_WS_SERVER_WINDOW_DRAWN_TRACKER_OBSERVER_H_
diff --git a/services/ui/ws/server_window_drawn_tracker_unittest.cc b/services/ui/ws/server_window_drawn_tracker_unittest.cc deleted file mode 100644 index 290d8111..0000000 --- a/services/ui/ws/server_window_drawn_tracker_unittest.cc +++ /dev/null
@@ -1,291 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "services/ui/ws/server_window_drawn_tracker.h" - -#include <stddef.h> - -#include "base/macros.h" -#include "services/ui/ws/server_window.h" -#include "services/ui/ws/server_window_drawn_tracker_observer.h" -#include "services/ui/ws/test_server_window_delegate.h" -#include "services/ui/ws/test_utils.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace ui { - -namespace ws { -namespace { - -class TestServerWindowDrawnTrackerObserver - : public ServerWindowDrawnTrackerObserver { - public: - TestServerWindowDrawnTrackerObserver() = default; - - void clear_change_count() { - change_count_ = 0u; - root_will_change_count_ = 0u; - root_did_change_count_ = 0u; - } - size_t change_count() const { return change_count_; } - const ServerWindow* ancestor() const { return ancestor_; } - const ServerWindow* window() const { return window_; } - bool is_drawn() const { return is_drawn_; } - size_t root_will_change_count() const { return root_will_change_count_; } - size_t root_did_change_count() const { return root_did_change_count_; } - - private: - // ServerWindowDrawnTrackerObserver: - void OnDrawnStateWillChange(ServerWindow* ancestor, - ServerWindow* window, - bool is_drawn) override { - change_count_++; - ancestor_ = ancestor; - window_ = window; - is_drawn_ = is_drawn; - } - - void OnDrawnStateChanged(ServerWindow* ancestor, - ServerWindow* window, - bool is_drawn) override { - EXPECT_EQ(ancestor_, ancestor); - EXPECT_EQ(window_, window); - EXPECT_EQ(is_drawn_, is_drawn); - } - void OnRootWillChange(ServerWindow* ancestor, ServerWindow* window) override { - root_will_change_count_++; - } - void OnRootDidChange(ServerWindow* ancestor, ServerWindow* window) override { - root_did_change_count_++; - } - - size_t change_count_ = 0u; - size_t root_will_change_count_ = 0u; - size_t root_did_change_count_ = 0u; - const ServerWindow* ancestor_ = nullptr; - const ServerWindow* window_ = nullptr; - bool is_drawn_ = false; - - DISALLOW_COPY_AND_ASSIGN(TestServerWindowDrawnTrackerObserver); -}; - -viz::FrameSinkId MakeFrameSinkId() { - constexpr int client_id = 1; - static int window_id = 0; - return viz::FrameSinkId(client_id, ++window_id); -} - -} // namespace - -class ServerWindowDrawnTrackerTest : public testing::Test { - public: - ServerWindowDrawnTrackerTest() {} - ~ServerWindowDrawnTrackerTest() override {} - - VizHostProxy* viz_host_proxy() { - return ws_test_helper_.window_server()->GetVizHostProxy(); - } - - private: - test::WindowServerTestHelper ws_test_helper_; - - DISALLOW_COPY_AND_ASSIGN(ServerWindowDrawnTrackerTest); -}; - -TEST_F(ServerWindowDrawnTrackerTest, ChangeBecauseOfDeletionAndVisibility) { - TestServerWindowDelegate server_window_delegate(viz_host_proxy()); - std::unique_ptr<ServerWindow> window( - new ServerWindow(&server_window_delegate, MakeFrameSinkId())); - server_window_delegate.set_root_window(window.get()); - TestServerWindowDrawnTrackerObserver drawn_observer; - ServerWindowDrawnTracker tracker(window.get(), &drawn_observer); - window->SetVisible(true); - EXPECT_EQ(1u, drawn_observer.change_count()); - EXPECT_EQ(0u, drawn_observer.root_will_change_count()); - EXPECT_EQ(0u, drawn_observer.root_did_change_count()); - EXPECT_EQ(window.get(), drawn_observer.window()); - EXPECT_EQ(nullptr, drawn_observer.ancestor()); - EXPECT_TRUE(drawn_observer.is_drawn()); - drawn_observer.clear_change_count(); - - window->SetVisible(false); - EXPECT_EQ(1u, drawn_observer.change_count()); - EXPECT_EQ(0u, drawn_observer.root_will_change_count()); - EXPECT_EQ(0u, drawn_observer.root_did_change_count()); - EXPECT_EQ(window.get(), drawn_observer.window()); - EXPECT_EQ(nullptr, drawn_observer.ancestor()); - EXPECT_FALSE(drawn_observer.is_drawn()); - drawn_observer.clear_change_count(); - - window->SetVisible(true); - EXPECT_EQ(1u, drawn_observer.change_count()); - EXPECT_EQ(0u, drawn_observer.root_will_change_count()); - EXPECT_EQ(0u, drawn_observer.root_did_change_count()); - EXPECT_EQ(window.get(), drawn_observer.window()); - EXPECT_EQ(nullptr, drawn_observer.ancestor()); - EXPECT_TRUE(drawn_observer.is_drawn()); - drawn_observer.clear_change_count(); - - ServerWindow* old_window = window.get(); - window.reset(); - EXPECT_EQ(1u, drawn_observer.change_count()); - EXPECT_EQ(0u, drawn_observer.root_will_change_count()); - EXPECT_EQ(0u, drawn_observer.root_did_change_count()); - EXPECT_EQ(old_window, drawn_observer.window()); - EXPECT_EQ(nullptr, drawn_observer.ancestor()); - EXPECT_FALSE(drawn_observer.is_drawn()); -} - -TEST_F(ServerWindowDrawnTrackerTest, ChangeBecauseOfRemovingFromRoot) { - TestServerWindowDelegate server_window_delegate(viz_host_proxy()); - ServerWindow root(&server_window_delegate, MakeFrameSinkId()); - server_window_delegate.set_root_window(&root); - root.SetVisible(true); - ServerWindow child(&server_window_delegate, MakeFrameSinkId()); - child.SetVisible(true); - root.Add(&child); - - TestServerWindowDrawnTrackerObserver drawn_observer; - ServerWindowDrawnTracker tracker(&child, &drawn_observer); - root.Remove(&child); - EXPECT_EQ(1u, drawn_observer.change_count()); - EXPECT_EQ(1u, drawn_observer.root_will_change_count()); - EXPECT_EQ(1u, drawn_observer.root_did_change_count()); - EXPECT_EQ(&child, drawn_observer.window()); - EXPECT_EQ(&root, drawn_observer.ancestor()); - EXPECT_FALSE(drawn_observer.is_drawn()); - drawn_observer.clear_change_count(); - - root.Add(&child); - EXPECT_EQ(1u, drawn_observer.change_count()); - EXPECT_EQ(1u, drawn_observer.root_will_change_count()); - EXPECT_EQ(1u, drawn_observer.root_did_change_count()); - EXPECT_EQ(&child, drawn_observer.window()); - EXPECT_EQ(nullptr, drawn_observer.ancestor()); - EXPECT_TRUE(drawn_observer.is_drawn()); -} - -TEST_F(ServerWindowDrawnTrackerTest, ChangeBecauseOfRemovingAncestorFromRoot) { - TestServerWindowDelegate server_window_delegate(viz_host_proxy()); - ServerWindow root(&server_window_delegate, MakeFrameSinkId()); - server_window_delegate.set_root_window(&root); - root.SetVisible(true); - ServerWindow child(&server_window_delegate, MakeFrameSinkId()); - child.SetVisible(true); - root.Add(&child); - - ServerWindow child_child(&server_window_delegate, MakeFrameSinkId()); - child_child.SetVisible(true); - child.Add(&child_child); - - TestServerWindowDrawnTrackerObserver drawn_observer; - ServerWindowDrawnTracker tracker(&child_child, &drawn_observer); - root.Remove(&child); - EXPECT_EQ(1u, drawn_observer.change_count()); - EXPECT_EQ(1u, drawn_observer.root_will_change_count()); - EXPECT_EQ(1u, drawn_observer.root_did_change_count()); - EXPECT_EQ(&child_child, drawn_observer.window()); - EXPECT_EQ(&root, drawn_observer.ancestor()); - EXPECT_FALSE(drawn_observer.is_drawn()); - drawn_observer.clear_change_count(); - - root.Add(&child_child); - EXPECT_EQ(1u, drawn_observer.change_count()); - EXPECT_EQ(1u, drawn_observer.root_will_change_count()); - EXPECT_EQ(1u, drawn_observer.root_did_change_count()); - EXPECT_EQ(&child_child, drawn_observer.window()); - EXPECT_EQ(nullptr, drawn_observer.ancestor()); - EXPECT_TRUE(drawn_observer.is_drawn()); -} - -TEST_F(ServerWindowDrawnTrackerTest, VisibilityChangeFromNonParentAncestor) { - TestServerWindowDelegate server_window_delegate(viz_host_proxy()); - ServerWindow root(&server_window_delegate, MakeFrameSinkId()); - ServerWindow child1(&server_window_delegate, MakeFrameSinkId()); - ServerWindow child2(&server_window_delegate, MakeFrameSinkId()); - ServerWindow child3(&server_window_delegate, MakeFrameSinkId()); - server_window_delegate.set_root_window(&root); - - root.Add(&child1); - child1.Add(&child2); - child2.Add(&child3); - - root.SetVisible(true); - child1.SetVisible(false); - child2.SetVisible(false); - child3.SetVisible(true); - - TestServerWindowDrawnTrackerObserver drawn_observer; - ServerWindowDrawnTracker tracker(&child3, &drawn_observer); - - EXPECT_FALSE(child3.IsDrawn()); - - // Make |child1| visible. |child3| should still be not drawn, since |child2| - // is still invisible. - child1.SetVisible(true); - EXPECT_EQ(0u, drawn_observer.change_count()); - EXPECT_EQ(0u, drawn_observer.root_will_change_count()); - EXPECT_EQ(0u, drawn_observer.root_did_change_count()); - EXPECT_EQ(nullptr, drawn_observer.window()); - EXPECT_EQ(nullptr, drawn_observer.ancestor()); - EXPECT_FALSE(drawn_observer.is_drawn()); - EXPECT_FALSE(child3.IsDrawn()); - - child2.SetVisible(true); - EXPECT_EQ(1u, drawn_observer.change_count()); - EXPECT_EQ(0u, drawn_observer.root_will_change_count()); - EXPECT_EQ(0u, drawn_observer.root_did_change_count()); - EXPECT_EQ(&child3, drawn_observer.window()); - EXPECT_EQ(nullptr, drawn_observer.ancestor()); - EXPECT_TRUE(drawn_observer.is_drawn()); - EXPECT_TRUE(child3.IsDrawn()); -} - -TEST_F(ServerWindowDrawnTrackerTest, TreeHierarchyChangeFromNonParentAncestor) { - TestServerWindowDelegate server_window_delegate(viz_host_proxy()); - ServerWindow root(&server_window_delegate, MakeFrameSinkId()); - ServerWindow child1(&server_window_delegate, MakeFrameSinkId()); - ServerWindow child2(&server_window_delegate, MakeFrameSinkId()); - ServerWindow child11(&server_window_delegate, MakeFrameSinkId()); - ServerWindow child111(&server_window_delegate, MakeFrameSinkId()); - server_window_delegate.set_root_window(&root); - - root.Add(&child1); - root.Add(&child2); - child1.Add(&child11); - child11.Add(&child111); - - root.SetVisible(true); - child1.SetVisible(false); - child2.SetVisible(true); - child11.SetVisible(false); - child111.SetVisible(true); - - TestServerWindowDrawnTrackerObserver drawn_observer; - ServerWindowDrawnTracker tracker(&child111, &drawn_observer); - EXPECT_FALSE(child111.IsDrawn()); - - // Move |child11| as a child of |child2|. |child111| should remain not drawn. - child2.Add(&child11); - EXPECT_EQ(0u, drawn_observer.change_count()); - EXPECT_EQ(0u, drawn_observer.root_will_change_count()); - EXPECT_EQ(0u, drawn_observer.root_did_change_count()); - EXPECT_EQ(nullptr, drawn_observer.window()); - EXPECT_EQ(nullptr, drawn_observer.ancestor()); - EXPECT_FALSE(drawn_observer.is_drawn()); - EXPECT_FALSE(child111.IsDrawn()); - - child11.SetVisible(true); - EXPECT_EQ(1u, drawn_observer.change_count()); - EXPECT_EQ(0u, drawn_observer.root_will_change_count()); - EXPECT_EQ(0u, drawn_observer.root_did_change_count()); - EXPECT_EQ(&child111, drawn_observer.window()); - EXPECT_EQ(nullptr, drawn_observer.ancestor()); - EXPECT_TRUE(drawn_observer.is_drawn()); - EXPECT_TRUE(child111.IsDrawn()); -} - -} // namespace ws - -} // namespace ui
diff --git a/services/ui/ws/server_window_observer.h b/services/ui/ws/server_window_observer.h deleted file mode 100644 index ac54498..0000000 --- a/services/ui/ws/server_window_observer.h +++ /dev/null
@@ -1,108 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SERVICES_UI_WS_SERVER_WINDOW_OBSERVER_H_ -#define SERVICES_UI_WS_SERVER_WINDOW_OBSERVER_H_ - -#include <stdint.h> - -#include <string> -#include <vector> - -#include "services/ui/public/interfaces/cursor/cursor.mojom.h" -#include "services/ui/public/interfaces/window_tree_constants.mojom.h" -#include "ui/base/ui_base_types.h" - -namespace gfx { -class Insets; -class Rect; -class Transform; -} - -namespace ui { - -struct TextInputState; - -namespace ws { - -class ServerWindow; - -// TODO(sky): rename to OnDid and OnWill everywhere. -class ServerWindowObserver { - public: - // Invoked when a window is about to be destroyed; before any of the children - // have been removed and before the window has been removed from its parent. - virtual void OnWindowDestroying(ServerWindow* window) {} - - // Invoked at the end of the window's destructor (after it has been removed - // from the hierarchy. - virtual void OnWindowDestroyed(ServerWindow* window) {} - - virtual void OnWillChangeWindowHierarchy(ServerWindow* window, - ServerWindow* new_parent, - ServerWindow* old_parent) {} - - virtual void OnWindowHierarchyChanged(ServerWindow* window, - ServerWindow* new_parent, - ServerWindow* old_parent) {} - - virtual void OnWindowBoundsChanged(ServerWindow* window, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds) {} - - virtual void OnWindowTransformChanged(ServerWindow* window, - const gfx::Transform& old_transform, - const gfx::Transform& new_transform) {} - - virtual void OnWindowClientAreaChanged( - ServerWindow* window, - const gfx::Insets& new_client_area, - const std::vector<gfx::Rect>& new_additional_client_areas) {} - - virtual void OnWindowReordered(ServerWindow* window, - ServerWindow* relative, - mojom::OrderDirection direction) {} - - virtual void OnWillChangeWindowVisibility(ServerWindow* window) {} - virtual void OnWindowVisibilityChanged(ServerWindow* window) {} - virtual void OnWindowOpacityChanged(ServerWindow* window, - float old_opacity, - float new_opacity) {} - - virtual void OnWindowCursorChanged(ServerWindow* window, - const ui::CursorData& cursor_data) {} - virtual void OnWindowNonClientCursorChanged( - ServerWindow* window, - const ui::CursorData& cursor_data) {} - - virtual void OnWindowTextInputStateChanged(ServerWindow* window, - const ui::TextInputState& state) {} - - virtual void OnWindowSharedPropertyChanged( - ServerWindow* window, - const std::string& name, - const std::vector<uint8_t>* new_data) {} - - // Called when the window is no longer an embed root. - virtual void OnWindowEmbeddedAppDisconnected(ServerWindow* window) {} - - // Called when a transient child is added to |window|. - virtual void OnTransientWindowAdded(ServerWindow* window, - ServerWindow* transient_child) {} - - // Called when a transient child is removed from |window|. - virtual void OnTransientWindowRemoved(ServerWindow* window, - ServerWindow* transient_child) {} - - virtual void OnWindowModalTypeChanged(ServerWindow* window, - ModalType old_modal_type) {} - - protected: - virtual ~ServerWindowObserver() {} -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_SERVER_WINDOW_OBSERVER_H_
diff --git a/services/ui/ws/server_window_tracker.h b/services/ui/ws/server_window_tracker.h deleted file mode 100644 index b611a72..0000000 --- a/services/ui/ws/server_window_tracker.h +++ /dev/null
@@ -1,25 +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. - -#ifndef SERVICES_UI_WS_SERVER_WINDOW_TRACKER_H_ -#define SERVICES_UI_WS_SERVER_WINDOW_TRACKER_H_ - -#include <stdint.h> -#include <set> - -#include "base/macros.h" -#include "services/ui/ws/server_window.h" -#include "services/ui/ws/server_window_observer.h" -#include "ui/base/window_tracker_template.h" - -namespace ui { -namespace ws { - -using ServerWindowTracker = - ui::WindowTrackerTemplate<ServerWindow, ServerWindowObserver>; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_SERVER_WINDOW_TRACKER_H_
diff --git a/services/ui/ws/test_change_tracker.cc b/services/ui/ws/test_change_tracker.cc deleted file mode 100644 index 5d110d6..0000000 --- a/services/ui/ws/test_change_tracker.cc +++ /dev/null
@@ -1,504 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "services/ui/ws/test_change_tracker.h" - -#include <stddef.h> - -#include "base/strings/string_util.h" -#include "base/strings/stringprintf.h" -#include "mojo/public/cpp/bindings/map.h" -#include "services/ui/common/util.h" -#include "ui/base/cursor/cursor.h" -#include "ui/gfx/geometry/point_conversions.h" - -namespace ui { - -namespace ws { - -std::string WindowIdToString(Id id) { - return (id == 0) ? "null" - : base::StringPrintf("%d,%d", ClientIdFromTransportId(id), - ClientWindowIdFromTransportId(id)); -} - -namespace { - -std::string DirectionToString(mojom::OrderDirection direction) { - return direction == mojom::OrderDirection::ABOVE ? "above" : "below"; -} - -enum class ChangeDescriptionType { - ONE, - TWO, - // Includes display id and location of events. - THREE, -}; - -std::string ChangeToDescription(const Change& change, - ChangeDescriptionType type) { - switch (change.type) { - case CHANGE_TYPE_EMBED: - if (type == ChangeDescriptionType::ONE) - return "OnEmbed"; - return base::StringPrintf("OnEmbed drawn=%s", - change.bool_value ? "true" : "false"); - - case CHANGE_TYPE_EMBEDDED_APP_DISCONNECTED: - return base::StringPrintf("OnEmbeddedAppDisconnected window=%s", - WindowIdToString(change.window_id).c_str()); - - case CHANGE_TYPE_UNEMBED: - return base::StringPrintf("OnUnembed window=%s", - WindowIdToString(change.window_id).c_str()); - - case CHANGE_TYPE_CAPTURE_CHANGED: - return base::StringPrintf("OnCaptureChanged new_window=%s old_window=%s", - WindowIdToString(change.window_id).c_str(), - WindowIdToString(change.window_id2).c_str()); - - case CHANGE_TYPE_FRAME_SINK_ID_ALLOCATED: - return base::StringPrintf("OnFrameSinkIdAllocated window=%s %s", - WindowIdToString(change.window_id).c_str(), - change.frame_sink_id.ToString().c_str()); - - case CHANGE_TYPE_NODE_ADD_TRANSIENT_WINDOW: - return base::StringPrintf("AddTransientWindow parent = %s child = %s", - WindowIdToString(change.window_id).c_str(), - WindowIdToString(change.window_id2).c_str()); - - case CHANGE_TYPE_NODE_BOUNDS_CHANGED: - return base::StringPrintf( - "BoundsChanged window=%s old_bounds=%s new_bounds=%s " - "local_surface_id=%s", - WindowIdToString(change.window_id).c_str(), - change.bounds.ToString().c_str(), change.bounds2.ToString().c_str(), - change.local_surface_id ? change.local_surface_id->ToString().c_str() - : "(none)"); - - case CHANGE_TYPE_NODE_HIERARCHY_CHANGED: - return base::StringPrintf( - "HierarchyChanged window=%s old_parent=%s new_parent=%s", - WindowIdToString(change.window_id).c_str(), - WindowIdToString(change.window_id2).c_str(), - WindowIdToString(change.window_id3).c_str()); - - case CHANGE_TYPE_NODE_REMOVE_TRANSIENT_WINDOW_FROM_PARENT: - return base::StringPrintf( - "RemoveTransientWindowFromParent parent = %s child = %s", - WindowIdToString(change.window_id).c_str(), - WindowIdToString(change.window_id2).c_str()); - - case CHANGE_TYPE_NODE_REORDERED: - return base::StringPrintf("Reordered window=%s relative=%s direction=%s", - WindowIdToString(change.window_id).c_str(), - WindowIdToString(change.window_id2).c_str(), - DirectionToString(change.direction).c_str()); - - case CHANGE_TYPE_NODE_DELETED: - return base::StringPrintf("WindowDeleted window=%s", - WindowIdToString(change.window_id).c_str()); - - case CHANGE_TYPE_NODE_VISIBILITY_CHANGED: - return base::StringPrintf("VisibilityChanged window=%s visible=%s", - WindowIdToString(change.window_id).c_str(), - change.bool_value ? "true" : "false"); - - case CHANGE_TYPE_NODE_DRAWN_STATE_CHANGED: - return base::StringPrintf("DrawnStateChanged window=%s drawn=%s", - WindowIdToString(change.window_id).c_str(), - change.bool_value ? "true" : "false"); - - case CHANGE_TYPE_INPUT_EVENT: { - std::string result = base::StringPrintf( - "InputEvent window=%s event_action=%d", - WindowIdToString(change.window_id).c_str(), change.event_action); - if (change.matches_pointer_watcher) - result += " matches_pointer_watcher"; - return result; - } - - case CHANGE_TYPE_POINTER_WATCHER_EVENT: - return base::StringPrintf("PointerWatcherEvent event_action=%d window=%s", - change.event_action, - WindowIdToString(change.window_id).c_str()); - - case CHANGE_TYPE_PROPERTY_CHANGED: - return base::StringPrintf("PropertyChanged window=%s key=%s value=%s", - WindowIdToString(change.window_id).c_str(), - change.property_key.c_str(), - change.property_value.c_str()); - - case CHANGE_TYPE_FOCUSED: - return base::StringPrintf("Focused id=%s", - WindowIdToString(change.window_id).c_str()); - - case CHANGE_TYPE_CURSOR_CHANGED: - return base::StringPrintf("CursorChanged id=%s cursor_type=%d", - WindowIdToString(change.window_id).c_str(), - static_cast<int>(change.cursor_type)); - case CHANGE_TYPE_ON_CHANGE_COMPLETED: - return base::StringPrintf("ChangeCompleted id=%d sucess=%s", - change.change_id, - change.bool_value ? "true" : "false"); - - case CHANGE_TYPE_ON_TOP_LEVEL_CREATED: - return base::StringPrintf("TopLevelCreated id=%d window_id=%s drawn=%s", - change.change_id, - WindowIdToString(change.window_id).c_str(), - change.bool_value ? "true" : "false"); - case CHANGE_TYPE_OPACITY: - return base::StringPrintf("OpacityChanged window_id=%s opacity=%.2f", - WindowIdToString(change.window_id).c_str(), - change.float_value); - case CHANGE_TYPE_SURFACE_CHANGED: - return base::StringPrintf("SurfaceCreated window_id=%s surface_id=%s", - WindowIdToString(change.window_id).c_str(), - change.surface_id.ToString().c_str()); - case CHANGE_TYPE_TRANSFORM_CHANGED: - return base::StringPrintf("TransformChanged window_id=%s", - WindowIdToString(change.window_id).c_str()); - } - return std::string(); -} - -std::string SingleChangeToDescriptionImpl(const std::vector<Change>& changes, - ChangeDescriptionType change_type) { - std::string result; - for (auto& change : changes) { - if (!result.empty()) - result += "\n"; - result += ChangeToDescription(change, change_type); - } - return result; -} - -} // namespace - -std::vector<std::string> ChangesToDescription1( - const std::vector<Change>& changes) { - std::vector<std::string> strings(changes.size()); - for (size_t i = 0; i < changes.size(); ++i) - strings[i] = ChangeToDescription(changes[i], ChangeDescriptionType::ONE); - return strings; -} - -std::string SingleChangeToDescription(const std::vector<Change>& changes) { - return SingleChangeToDescriptionImpl(changes, ChangeDescriptionType::ONE); -} - -std::string SingleChangeToDescription2(const std::vector<Change>& changes) { - return SingleChangeToDescriptionImpl(changes, ChangeDescriptionType::TWO); -} - -std::string SingleWindowDescription(const std::vector<TestWindow>& windows) { - if (windows.empty()) - return "no windows"; - std::string result; - for (const TestWindow& window : windows) - result += window.ToString(); - return result; -} - -std::string ChangeWindowDescription(const std::vector<Change>& changes) { - if (changes.size() != 1) - return std::string(); - std::vector<std::string> window_strings(changes[0].windows.size()); - for (size_t i = 0; i < changes[0].windows.size(); ++i) - window_strings[i] = "[" + changes[0].windows[i].ToString() + "]"; - return base::JoinString(window_strings, ","); -} - -TestWindow WindowDataToTestWindow(const mojom::WindowDataPtr& data) { - TestWindow window; - window.parent_id = data->parent_id; - window.window_id = data->window_id; - window.visible = data->visible; - window.properties = mojo::FlatMapToMap(data->properties); - return window; -} - -void WindowDatasToTestWindows(const std::vector<mojom::WindowDataPtr>& data, - std::vector<TestWindow>* test_windows) { - for (size_t i = 0; i < data.size(); ++i) - test_windows->push_back(WindowDataToTestWindow(data[i])); -} - -Change::Change() - : type(CHANGE_TYPE_EMBED), - window_id(0), - window_id2(0), - window_id3(0), - event_action(0), - matches_pointer_watcher(false), - direction(mojom::OrderDirection::ABOVE), - bool_value(false), - float_value(0.f), - cursor_type(ui::CursorType::kNull), - change_id(0u), - display_id(0) {} - -Change::Change(const Change& other) = default; - -Change::~Change() {} - -TestChangeTracker::TestChangeTracker() : delegate_(NULL) {} - -TestChangeTracker::~TestChangeTracker() {} - -void TestChangeTracker::OnEmbed(mojom::WindowDataPtr root, bool drawn) { - Change change; - change.type = CHANGE_TYPE_EMBED; - change.bool_value = drawn; - change.windows.push_back(WindowDataToTestWindow(root)); - AddChange(change); -} - -void TestChangeTracker::OnEmbeddedAppDisconnected(Id window_id) { - Change change; - change.type = CHANGE_TYPE_EMBEDDED_APP_DISCONNECTED; - change.window_id = window_id; - AddChange(change); -} - -void TestChangeTracker::OnWindowBoundsChanged( - Id window_id, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds, - const base::Optional<viz::LocalSurfaceId>& local_surface_id) { - Change change; - change.type = CHANGE_TYPE_NODE_BOUNDS_CHANGED; - change.window_id = window_id; - change.bounds = old_bounds; - change.bounds2 = new_bounds; - change.local_surface_id = local_surface_id; - AddChange(change); -} - -void TestChangeTracker::OnWindowTransformChanged(Id window_id) { - Change change; - change.type = CHANGE_TYPE_TRANSFORM_CHANGED; - change.window_id = window_id; - AddChange(change); -} - -void TestChangeTracker::OnUnembed(Id window_id) { - Change change; - change.type = CHANGE_TYPE_UNEMBED; - change.window_id = window_id; - AddChange(change); -} - -void TestChangeTracker::OnTransientWindowAdded(Id window_id, - Id transient_window_id) { - Change change; - change.type = CHANGE_TYPE_NODE_ADD_TRANSIENT_WINDOW; - change.window_id = window_id; - change.window_id2 = transient_window_id; - AddChange(change); -} - -void TestChangeTracker::OnTransientWindowRemoved(Id window_id, - Id transient_window_id) { - Change change; - change.type = CHANGE_TYPE_NODE_REMOVE_TRANSIENT_WINDOW_FROM_PARENT; - change.window_id = window_id; - change.window_id2 = transient_window_id; - AddChange(change); -} - -void TestChangeTracker::OnCaptureChanged(Id new_capture_window_id, - Id old_capture_window_id) { - Change change; - change.type = CHANGE_TYPE_CAPTURE_CHANGED; - change.window_id = new_capture_window_id; - change.window_id2 = old_capture_window_id; - AddChange(change); -} - -void TestChangeTracker::OnFrameSinkIdAllocated( - Id window_id, - const viz::FrameSinkId& frame_sink_id) { - Change change; - change.type = CHANGE_TYPE_FRAME_SINK_ID_ALLOCATED; - change.window_id = window_id; - change.frame_sink_id = frame_sink_id; - AddChange(change); -} - -void TestChangeTracker::OnWindowHierarchyChanged( - Id window_id, - Id old_parent_id, - Id new_parent_id, - std::vector<mojom::WindowDataPtr> windows) { - Change change; - change.type = CHANGE_TYPE_NODE_HIERARCHY_CHANGED; - change.window_id = window_id; - change.window_id2 = old_parent_id; - change.window_id3 = new_parent_id; - WindowDatasToTestWindows(windows, &change.windows); - AddChange(change); -} - -void TestChangeTracker::OnWindowReordered(Id window_id, - Id relative_window_id, - mojom::OrderDirection direction) { - Change change; - change.type = CHANGE_TYPE_NODE_REORDERED; - change.window_id = window_id; - change.window_id2 = relative_window_id; - change.direction = direction; - AddChange(change); -} - -void TestChangeTracker::OnWindowDeleted(Id window_id) { - Change change; - change.type = CHANGE_TYPE_NODE_DELETED; - change.window_id = window_id; - AddChange(change); -} - -void TestChangeTracker::OnWindowVisibilityChanged(Id window_id, bool visible) { - Change change; - change.type = CHANGE_TYPE_NODE_VISIBILITY_CHANGED; - change.window_id = window_id; - change.bool_value = visible; - AddChange(change); -} - -void TestChangeTracker::OnWindowOpacityChanged(Id window_id, float opacity) { - Change change; - change.type = CHANGE_TYPE_OPACITY; - change.window_id = window_id; - change.float_value = opacity; - AddChange(change); -} - -void TestChangeTracker::OnWindowParentDrawnStateChanged(Id window_id, - bool drawn) { - Change change; - change.type = CHANGE_TYPE_NODE_DRAWN_STATE_CHANGED; - change.window_id = window_id; - change.bool_value = drawn; - AddChange(change); -} - -void TestChangeTracker::OnWindowInputEvent( - Id window_id, - const ui::Event& event, - int64_t display_id, - const gfx::PointF& event_location_in_screen_pixel_layout, - bool matches_pointer_watcher) { - Change change; - change.type = CHANGE_TYPE_INPUT_EVENT; - change.window_id = window_id; - change.event_action = static_cast<int32_t>(event.type()); - change.matches_pointer_watcher = matches_pointer_watcher; - change.display_id = display_id; - if (event.IsLocatedEvent()) - change.location1 = event.AsLocatedEvent()->root_location(); - change.location2 = event_location_in_screen_pixel_layout; - if (event.IsKeyEvent() && event.AsKeyEvent()->properties()) - change.key_event_properties = *event.AsKeyEvent()->properties(); - AddChange(change); -} - -void TestChangeTracker::OnPointerEventObserved(const ui::Event& event, - Id window_id) { - Change change; - change.type = CHANGE_TYPE_POINTER_WATCHER_EVENT; - change.event_action = static_cast<int32_t>(event.type()); - change.window_id = window_id; - AddChange(change); -} - -void TestChangeTracker::OnWindowSharedPropertyChanged( - Id window_id, - const std::string& name, - const base::Optional<std::vector<uint8_t>>& data) { - Change change; - change.type = CHANGE_TYPE_PROPERTY_CHANGED; - change.window_id = window_id; - change.property_key = name; - if (!data) - change.property_value = "NULL"; - else - change.property_value.assign(data->begin(), data->end()); - AddChange(change); -} - -void TestChangeTracker::OnWindowFocused(Id window_id) { - Change change; - change.type = CHANGE_TYPE_FOCUSED; - change.window_id = window_id; - AddChange(change); -} - -void TestChangeTracker::OnWindowCursorChanged(Id window_id, - const ui::CursorData& cursor) { - Change change; - change.type = CHANGE_TYPE_CURSOR_CHANGED; - change.window_id = window_id; - change.cursor_type = cursor.cursor_type(); - AddChange(change); -} - -void TestChangeTracker::OnChangeCompleted(uint32_t change_id, bool success) { - Change change; - change.type = CHANGE_TYPE_ON_CHANGE_COMPLETED; - change.change_id = change_id; - change.bool_value = success; - AddChange(change); -} - -void TestChangeTracker::OnTopLevelCreated(uint32_t change_id, - mojom::WindowDataPtr window_data, - bool drawn) { - Change change; - change.type = CHANGE_TYPE_ON_TOP_LEVEL_CREATED; - change.change_id = change_id; - change.window_id = window_data->window_id; - change.bool_value = drawn; - AddChange(change); -} - -void TestChangeTracker::OnWindowSurfaceChanged( - Id window_id, - const viz::SurfaceInfo& surface_info) { - Change change; - change.type = CHANGE_TYPE_SURFACE_CHANGED; - change.window_id = window_id; - change.surface_id = surface_info.id(); - change.frame_size = surface_info.size_in_pixels(); - change.device_scale_factor = surface_info.device_scale_factor(); - AddChange(change); -} - -void TestChangeTracker::AddChange(const Change& change) { - changes_.push_back(change); - if (delegate_) - delegate_->OnChangeAdded(); -} - -TestWindow::TestWindow() {} - -TestWindow::TestWindow(const TestWindow& other) = default; - -TestWindow::~TestWindow() {} - -std::string TestWindow::ToString() const { - return base::StringPrintf("window=%s parent=%s", - WindowIdToString(window_id).c_str(), - WindowIdToString(parent_id).c_str()); -} - -std::string TestWindow::ToString2() const { - return base::StringPrintf( - "window=%s parent=%s visible=%s", WindowIdToString(window_id).c_str(), - WindowIdToString(parent_id).c_str(), visible ? "true" : "false"); -} - -} // namespace ws - -} // namespace ui
diff --git a/services/ui/ws/test_change_tracker.h b/services/ui/ws/test_change_tracker.h deleted file mode 100644 index 8bf9f1d..0000000 --- a/services/ui/ws/test_change_tracker.h +++ /dev/null
@@ -1,210 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SERVICES_UI_WS_TEST_CHANGE_TRACKER_H_ -#define SERVICES_UI_WS_TEST_CHANGE_TRACKER_H_ - -#include <stdint.h> - -#include <string> -#include <vector> - -#include "base/containers/flat_map.h" -#include "base/macros.h" -#include "services/ui/common/types.h" -#include "services/ui/public/interfaces/window_tree.mojom.h" -#include "ui/gfx/geometry/mojo/geometry.mojom.h" -#include "ui/gfx/geometry/point.h" -#include "ui/gfx/geometry/point_f.h" - -namespace ui { - -namespace ws { - -enum ChangeType { - CHANGE_TYPE_CAPTURE_CHANGED, - CHANGE_TYPE_FRAME_SINK_ID_ALLOCATED, - CHANGE_TYPE_EMBED, - CHANGE_TYPE_EMBEDDED_APP_DISCONNECTED, - CHANGE_TYPE_UNEMBED, - // TODO(sky): nuke NODE. - CHANGE_TYPE_NODE_ADD_TRANSIENT_WINDOW, - CHANGE_TYPE_NODE_BOUNDS_CHANGED, - CHANGE_TYPE_NODE_HIERARCHY_CHANGED, - CHANGE_TYPE_NODE_REMOVE_TRANSIENT_WINDOW_FROM_PARENT, - CHANGE_TYPE_NODE_REORDERED, - CHANGE_TYPE_NODE_VISIBILITY_CHANGED, - CHANGE_TYPE_NODE_DRAWN_STATE_CHANGED, - CHANGE_TYPE_NODE_DELETED, - CHANGE_TYPE_INPUT_EVENT, - CHANGE_TYPE_POINTER_WATCHER_EVENT, - CHANGE_TYPE_PROPERTY_CHANGED, - CHANGE_TYPE_FOCUSED, - CHANGE_TYPE_CURSOR_CHANGED, - CHANGE_TYPE_ON_CHANGE_COMPLETED, - CHANGE_TYPE_ON_TOP_LEVEL_CREATED, - CHANGE_TYPE_OPACITY, - CHANGE_TYPE_SURFACE_CHANGED, - CHANGE_TYPE_TRANSFORM_CHANGED, -}; - -// TODO(sky): consider nuking and converting directly to WindowData. -struct TestWindow { - TestWindow(); - TestWindow(const TestWindow& other); - ~TestWindow(); - - // Returns a string description of this. - std::string ToString() const; - - // Returns a string description that includes visible and drawn. - std::string ToString2() const; - - Id parent_id; - Id window_id; - bool visible; - std::map<std::string, std::vector<uint8_t>> properties; -}; - -// Tracks a call to WindowTreeClient. See the individual functions for the -// fields that are used. -struct Change { - Change(); - Change(const Change& other); - ~Change(); - - ChangeType type; - std::vector<TestWindow> windows; - Id window_id; - Id window_id2; - Id window_id3; - gfx::Rect bounds; - gfx::Rect bounds2; - viz::FrameSinkId frame_sink_id; - base::Optional<viz::LocalSurfaceId> local_surface_id; - // TODO(sky): rename, this is Event::event_type. - int32_t event_action; - bool matches_pointer_watcher; - std::string embed_url; - mojom::OrderDirection direction; - bool bool_value; - float float_value; - std::string property_key; - std::string property_value; - ui::CursorType cursor_type; - uint32_t change_id; - viz::SurfaceId surface_id; - gfx::Size frame_size; - float device_scale_factor; - gfx::Transform transform; - // Set in OnWindowInputEvent() if the event is a KeyEvent. - base::flat_map<std::string, std::vector<uint8_t>> key_event_properties; - int64_t display_id; - gfx::Point location1; - gfx::PointF location2; -}; - -// Converts Changes to string descriptions. -std::vector<std::string> ChangesToDescription1( - const std::vector<Change>& changes); - -// Convenience for returning the description of the first item in |changes|. -// Returns an empty string if |changes| has something other than one entry. -std::string SingleChangeToDescription(const std::vector<Change>& changes); -std::string SingleChangeToDescription2(const std::vector<Change>& changes); - -// Convenience for returning the description of the first item in |windows|. -// Returns an empty string if |windows| has something other than one entry. -std::string SingleWindowDescription(const std::vector<TestWindow>& windows); - -// Returns a string description of |changes[0].windows|. Returns an empty string -// if change.size() != 1. -std::string ChangeWindowDescription(const std::vector<Change>& changes); - -// Converts WindowDatas to TestWindows. -void WindowDatasToTestWindows(const std::vector<mojom::WindowDataPtr>& data, - std::vector<TestWindow>* test_windows); - -// TestChangeTracker is used to record WindowTreeClient functions. It notifies -// a delegate any time a change is added. -class TestChangeTracker { - public: - // Used to notify the delegate when a change is added. A change corresponds to - // a single WindowTreeClient function. - class Delegate { - public: - virtual void OnChangeAdded() = 0; - - protected: - virtual ~Delegate() {} - }; - - TestChangeTracker(); - ~TestChangeTracker(); - - void set_delegate(Delegate* delegate) { delegate_ = delegate; } - - std::vector<Change>* changes() { return &changes_; } - - // Each of these functions generate a Change. There is one per - // WindowTreeClient function. - void OnEmbed(mojom::WindowDataPtr root, bool drawn); - void OnEmbeddedAppDisconnected(Id window_id); - void OnUnembed(Id window_id); - void OnCaptureChanged(Id new_capture_window_id, Id old_capture_window_id); - void OnFrameSinkIdAllocated(Id window_id, - const viz::FrameSinkId& frame_sink_id); - void OnTransientWindowAdded(Id window_id, Id transient_window_id); - void OnTransientWindowRemoved(Id window_id, Id transient_window_id); - void OnWindowBoundsChanged( - Id window_id, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds, - const base::Optional<viz::LocalSurfaceId>& local_surface_id); - void OnWindowTransformChanged(Id window_id); - void OnWindowHierarchyChanged(Id window_id, - Id old_parent_id, - Id new_parent_id, - std::vector<mojom::WindowDataPtr> windows); - void OnWindowReordered(Id window_id, - Id relative_window_id, - mojom::OrderDirection direction); - void OnWindowDeleted(Id window_id); - void OnWindowVisibilityChanged(Id window_id, bool visible); - void OnWindowOpacityChanged(Id window_id, float opacity); - void OnWindowParentDrawnStateChanged(Id window_id, bool drawn); - void OnWindowInputEvent( - Id window_id, - const ui::Event& event, - int64_t display_id, - const gfx::PointF& event_location_in_screen_pixel_layout, - bool matches_pointer_watcher); - void OnPointerEventObserved(const ui::Event& event, Id window_id); - void OnWindowSharedPropertyChanged( - Id window_id, - const std::string& name, - const base::Optional<std::vector<uint8_t>>& data); - void OnWindowFocused(Id window_id); - void OnWindowCursorChanged(Id window_id, const ui::CursorData& cursor); - void OnChangeCompleted(uint32_t change_id, bool success); - void OnTopLevelCreated(uint32_t change_id, - mojom::WindowDataPtr window_data, - bool drawn); - void OnWindowSurfaceChanged(Id window_id, - const viz::SurfaceInfo& surface_info); - - private: - void AddChange(const Change& change); - - Delegate* delegate_; - std::vector<Change> changes_; - - DISALLOW_COPY_AND_ASSIGN(TestChangeTracker); -}; - -} // namespace ws - -} // namespace ui - -#endif // SERVICES_UI_WS_TEST_CHANGE_TRACKER_H_
diff --git a/services/ui/ws/test_manifest.json b/services/ui/ws/test_manifest.json deleted file mode 100644 index ae155484..0000000 --- a/services/ui/ws/test_manifest.json +++ /dev/null
@@ -1,22 +0,0 @@ -{ - "name": "ui_service_unittests", - "display_name": "Mus Window Server Unittests", - "interface_provider_specs": { - "service_manager:connector": { - "provides": { - "ui:window_tree_client": [ - "ui.mojom.WindowTreeClient" - ] - }, - "requires": { - "*": [ "app" ], - "ui_service_unittests": [ "ui:window_tree_client" ], - "ui": [ - "window_manager", - "window_tree_host_factory" - ], - "viz": [ "viz_host" ] - } - } - } -}
diff --git a/services/ui/ws/test_server_window_delegate.cc b/services/ui/ws/test_server_window_delegate.cc deleted file mode 100644 index 87a8ae3..0000000 --- a/services/ui/ws/test_server_window_delegate.cc +++ /dev/null
@@ -1,39 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "services/ui/ws/test_server_window_delegate.h" - -#include "services/ui/ws/server_window.h" - -namespace ui { -namespace ws { - -TestServerWindowDelegate::TestServerWindowDelegate(VizHostProxy* viz_host_proxy) - : viz_host_proxy_(viz_host_proxy) {} - -TestServerWindowDelegate::~TestServerWindowDelegate() {} - -void TestServerWindowDelegate::AddRootWindow(ServerWindow* window) { - roots_.insert(window); -} - -VizHostProxy* TestServerWindowDelegate::GetVizHostProxy() { - return viz_host_proxy_; -} - -ServerWindow* TestServerWindowDelegate::GetRootWindowForDrawn( - const ServerWindow* window) { - for (ServerWindow* root : roots_) { - if (root->Contains(window)) - return root; - } - return root_window_; -} - -void TestServerWindowDelegate::OnFirstSurfaceActivation( - const viz::SurfaceInfo& surface_info, - ServerWindow* window) {} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/test_server_window_delegate.h b/services/ui/ws/test_server_window_delegate.h deleted file mode 100644 index f0e6fc2..0000000 --- a/services/ui/ws/test_server_window_delegate.h +++ /dev/null
@@ -1,45 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SERVICES_UI_WS_TEST_SERVER_WINDOW_DELEGATE_H_ -#define SERVICES_UI_WS_TEST_SERVER_WINDOW_DELEGATE_H_ - -#include <set> - -#include "base/macros.h" -#include "services/ui/ws/server_window_delegate.h" - -namespace ui { -namespace ws { - -class TestServerWindowDelegate : public ServerWindowDelegate { - public: - explicit TestServerWindowDelegate(VizHostProxy* viz_host_proxy); - ~TestServerWindowDelegate() override; - - // GetRootWindowForDrawn() returns the first ServerWindow added by way of - // AddRootWindow() that contains the supplied window. If none of the - // ServerWindows added by way of AddRootWindow() contain the supplied window, - // then the value passed to set_root_window() is returned. - void set_root_window(ServerWindow* window) { root_window_ = window; } - void AddRootWindow(ServerWindow* window); - - private: - // ServerWindowDelegate: - VizHostProxy* GetVizHostProxy() override; - ServerWindow* GetRootWindowForDrawn(const ServerWindow* window) override; - void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info, - ServerWindow* window) override; - - ServerWindow* root_window_ = nullptr; - VizHostProxy* viz_host_proxy_ = nullptr; - std::set<ServerWindow*> roots_; - - DISALLOW_COPY_AND_ASSIGN(TestServerWindowDelegate); -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_TEST_SERVER_WINDOW_DELEGATE_H_
diff --git a/services/ui/ws/test_utils.cc b/services/ui/ws/test_utils.cc deleted file mode 100644 index 93ec69d..0000000 --- a/services/ui/ws/test_utils.cc +++ /dev/null
@@ -1,859 +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 "services/ui/ws/test_utils.h" - -#include <utility> - -#include "base/memory/ptr_util.h" -#include "base/message_loop/message_loop_current.h" -#include "base/strings/string_number_conversions.h" -#include "components/viz/common/frame_sinks/copy_output_request.h" -#include "gpu/ipc/client/gpu_channel_host.h" -#include "services/service_manager/public/mojom/connector.mojom.h" -#include "services/ui/common/image_cursors_set.h" -#include "services/ui/gpu_host/test_gpu_host.h" -#include "services/ui/public/interfaces/cursor/cursor.mojom.h" -#include "services/ui/ws/cursor_location_manager.h" -#include "services/ui/ws/display_binding.h" -#include "services/ui/ws/display_creation_config.h" -#include "services/ui/ws/display_manager.h" -#include "services/ui/ws/threaded_image_cursors.h" -#include "services/ui/ws/threaded_image_cursors_factory.h" -#include "services/ui/ws/window_manager_access_policy.h" -#include "services/ui/ws/window_manager_window_tree_factory.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/base/cursor/cursor.h" -#include "ui/gfx/geometry/dip_util.h" - -namespace ui { -namespace ws { -namespace test { -namespace { - -ClientWindowId NextUnusedClientWindowId(WindowTree* tree) { - for (ClientSpecificId id = kEmbedTreeWindowId;; ++id) { - // Used the id of the client in the upper bits to simplify things. - const ClientWindowId client_id = ClientWindowId(tree->id(), id); - if (!tree->GetWindowByClientId(client_id)) - return client_id; - } -} - -display::ViewportMetrics MakeViewportMetrics(const display::Display& display) { - gfx::Size pixel_size = gfx::ConvertSizeToPixel(display.device_scale_factor(), - display.bounds().size()); - - display::ViewportMetrics metrics; - metrics.bounds_in_pixels.set_size(pixel_size); - metrics.device_scale_factor = display.device_scale_factor(); - metrics.ui_scale_factor = 1; - return metrics; -} - -class TestThreadedImageCursorsFactory : public ThreadedImageCursorsFactory { - public: - TestThreadedImageCursorsFactory() {} - ~TestThreadedImageCursorsFactory() override {} - - // ThreadedImageCursorsFactory: - std::unique_ptr<ThreadedImageCursors> CreateCursors() override { - if (!resource_runner_) { - resource_runner_ = base::ThreadTaskRunnerHandle::Get(); - image_cursors_set_ = std::make_unique<ui::ImageCursorsSet>(); - } - return std::make_unique<ws::ThreadedImageCursors>( - resource_runner_, image_cursors_set_->GetWeakPtr()); - } - - private: - scoped_refptr<base::SingleThreadTaskRunner> resource_runner_; - std::unique_ptr<ui::ImageCursorsSet> image_cursors_set_; - - DISALLOW_COPY_AND_ASSIGN(TestThreadedImageCursorsFactory); -}; - -} // namespace - -// TestScreenManager ------------------------------------------------- - -TestScreenManager::TestScreenManager() {} - -TestScreenManager::~TestScreenManager() { - display::Screen::SetScreenInstance(nullptr); -} - -int64_t TestScreenManager::AddDisplay() { - return AddDisplay( - display::Display(display::kInvalidDisplayId, gfx::Rect(100, 100))); -} - -int64_t TestScreenManager::AddDisplay(const display::Display& input_display) { - // Generate a unique display id. - int64_t display_id = display_ids_.empty() ? 1 : *display_ids_.rbegin() + 1; - display_ids_.insert(display_id); - - display::Display display = input_display; - display.set_id(display_id); - - // First display added will be the primary display. - display::DisplayList::Type type = display::DisplayList::Type::NOT_PRIMARY; - if (display_ids_.size() == 1) - type = display::DisplayList::Type::PRIMARY; - - screen_->display_list().AddDisplay(display, type); - delegate_->OnDisplayAdded(display, MakeViewportMetrics(display)); - - if (type == display::DisplayList::Type::PRIMARY) - delegate_->OnPrimaryDisplayChanged(display_id); - - return display_id; -} - -void TestScreenManager::ModifyDisplay( - const display::Display& display, - const base::Optional<display::ViewportMetrics>& metrics) { - DCHECK(display_ids_.count(display.id()) == 1); - screen_->display_list().UpdateDisplay(display); - if (metrics) - delegate_->OnDisplayModified(display, *metrics); - else - delegate_->OnDisplayModified(display, MakeViewportMetrics(display)); -} - -void TestScreenManager::RemoveDisplay(int64_t display_id) { - DCHECK(display_ids_.count(display_id) == 1); - screen_->display_list().RemoveDisplay(display_id); - delegate_->OnDisplayRemoved(display_id); - display_ids_.erase(display_id); -} - -void TestScreenManager::Init(display::ScreenManagerDelegate* delegate) { - delegate_ = delegate; - - // Reset everything. - display_ids_.clear(); - display::Screen::SetScreenInstance(nullptr); - screen_ = std::make_unique<display::ScreenBase>(); - display::Screen::SetScreenInstance(screen_.get()); -} - -display::ScreenBase* TestScreenManager::GetScreen() { - return screen_.get(); -} - -// TestPlatformDisplayFactory ------------------------------------------------- - -TestPlatformDisplayFactory::TestPlatformDisplayFactory( - ui::CursorData* cursor_storage) - : cursor_storage_(cursor_storage) {} - -TestPlatformDisplayFactory::~TestPlatformDisplayFactory() {} - -std::unique_ptr<PlatformDisplay> -TestPlatformDisplayFactory::CreatePlatformDisplay( - ServerWindow* root_window, - const display::ViewportMetrics& metrics) { - return std::make_unique<TestPlatformDisplay>(metrics, cursor_storage_); -} - -// WindowTreeTestApi --------------------------------------------------------- - -WindowTreeTestApi::WindowTreeTestApi(WindowTree* tree) : tree_(tree) {} -WindowTreeTestApi::~WindowTreeTestApi() {} - -void WindowTreeTestApi::StartPointerWatcher(bool want_moves) { - tree_->StartPointerWatcher(want_moves); -} - -void WindowTreeTestApi::StopPointerWatcher() { - tree_->StopPointerWatcher(); -} - -// EventProcessorTestApi ---------------------------------------------------- - -bool EventProcessorTestApi::IsWindowPointerTarget( - const ServerWindow* window) const { - for (const auto& pair : ep_->pointer_targets_) { - if (pair.second.window == window) - return true; - } - return false; -} - -int EventProcessorTestApi::NumberPointerTargetsForWindow(ServerWindow* window) { - int count = 0; - for (const auto& pair : ep_->pointer_targets_) - if (pair.second.window == window) - count++; - return count; -} - -bool EventProcessorTestApi::IsObservingWindow(ServerWindow* window) { - return ep_->observed_windows_.count(window) > 0; -} - -// TestDisplayBinding --------------------------------------------------------- - -WindowTree* TestDisplayBinding::CreateWindowTree(ServerWindow* root) { - const uint32_t embed_flags = 0; - WindowTree* tree = window_server_->EmbedAtWindow( - root, ui::mojom::WindowTreeClientPtr(), embed_flags, - base::WrapUnique(new WindowManagerAccessPolicy)); - WindowTreeTestApi(tree).set_is_for_embedding(false); - tree->ConfigureWindowManager(automatically_create_display_roots_); - return tree; -} - -// TestWindowManager ---------------------------------------------------------- - -TestWindowManager::TestWindowManager() {} - -TestWindowManager::~TestWindowManager() {} - -void TestWindowManager::OnConnect() { - connect_count_++; -} - -void TestWindowManager::WmOnAcceleratedWidgetForDisplay( - int64_t display, - gpu::SurfaceHandle surface_handle) {} - -void TestWindowManager::WmNewDisplayAdded( - const display::Display& display, - ui::mojom::WindowDataPtr root, - bool drawn, - const base::Optional<viz::LocalSurfaceId>& local_surface_id) { - display_added_count_++; -} - -void TestWindowManager::WmDisplayRemoved(int64_t display_id) { - got_display_removed_ = true; - display_removed_id_ = display_id; -} - -void TestWindowManager::WmSetModalType(Id window_id, ui::ModalType type) { - on_set_modal_type_called_ = true; -} - -void TestWindowManager::WmCreateTopLevelWindow( - uint32_t change_id, - const viz::FrameSinkId& frame_sink_id, - const base::flat_map<std::string, std::vector<uint8_t>>& properties) { - got_create_top_level_window_ = true; - change_id_ = change_id; -} - -void TestWindowManager::WmClientJankinessChanged(ClientSpecificId client_id, - bool janky) {} - -void TestWindowManager::WmBuildDragImage(const gfx::Point& screen_location, - const gfx::ImageSkia& drag_image, - const gfx::Vector2d& drag_image_offset, - ui::mojom::PointerKind source) {} - -void TestWindowManager::WmMoveDragImage(const gfx::Point& screen_location, - WmMoveDragImageCallback callback) { - std::move(callback).Run(); -} - -void TestWindowManager::WmDestroyDragImage() {} - -void TestWindowManager::WmPerformMoveLoop(uint32_t change_id, - Id window_id, - mojom::MoveLoopSource source, - const gfx::Point& cursor_location) { - on_perform_move_loop_called_ = true; -} - -void TestWindowManager::WmCancelMoveLoop(uint32_t change_id) {} - -void TestWindowManager::WmDeactivateWindow(Id window_id) {} - -void TestWindowManager::WmStackAbove(uint32_t change_id, - Id above_id, - Id below_id) {} - -void TestWindowManager::WmStackAtTop(uint32_t change_id, Id window_id) {} - -void TestWindowManager::WmPerformWmAction(Id window_id, - const std::string& action) { - last_wm_action_ = action; -} - -void TestWindowManager::OnAccelerator(uint32_t ack_id, - uint32_t accelerator_id, - std::unique_ptr<ui::Event> event) { - on_accelerator_called_ = true; - on_accelerator_id_ = accelerator_id; -} - -void TestWindowManager::OnCursorTouchVisibleChanged(bool enabled) {} - -void TestWindowManager::OnEventBlockedByModalWindow(Id window_id) {} - -// TestWindowTreeClient ------------------------------------------------------- - -TestWindowTreeClient::TestWindowTreeClient() - : binding_(this), record_on_change_completed_(false) {} -TestWindowTreeClient::~TestWindowTreeClient() {} - -void TestWindowTreeClient::Bind( - mojo::InterfaceRequest<mojom::WindowTreeClient> request) { - binding_.Bind(std::move(request)); -} - -void TestWindowTreeClient::OnEmbed( - mojom::WindowDataPtr root, - ui::mojom::WindowTreePtr tree, - int64_t display_id, - Id focused_window_id, - bool drawn, - const base::Optional<viz::LocalSurfaceId>& local_surface_id) { - // TODO(sky): add test coverage of |focused_window_id|. - tracker_.OnEmbed(std::move(root), drawn); -} - -void TestWindowTreeClient::OnEmbedFromToken( - const base::UnguessableToken& token, - ::ui::mojom::WindowDataPtr root, - int64_t display_id, - const base::Optional<viz::LocalSurfaceId>& local_surface_id) {} - -void TestWindowTreeClient::OnEmbeddedAppDisconnected(Id window) { - tracker_.OnEmbeddedAppDisconnected(window); -} - -void TestWindowTreeClient::OnUnembed(Id window_id) { - tracker_.OnUnembed(window_id); -} - -void TestWindowTreeClient::OnCaptureChanged(Id new_capture_window_id, - Id old_capture_window_id) { - tracker_.OnCaptureChanged(new_capture_window_id, old_capture_window_id); -} - -void TestWindowTreeClient::OnFrameSinkIdAllocated( - Id window_id, - const viz::FrameSinkId& frame_sink_id) { - tracker_.OnFrameSinkIdAllocated(window_id, frame_sink_id); -} - -void TestWindowTreeClient::OnTopLevelCreated( - uint32_t change_id, - mojom::WindowDataPtr data, - int64_t display_id, - bool drawn, - const base::Optional<viz::LocalSurfaceId>& local_surface_id) { - tracker_.OnTopLevelCreated(change_id, std::move(data), drawn); -} - -void TestWindowTreeClient::OnWindowBoundsChanged( - Id window, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds, - const base::Optional<viz::LocalSurfaceId>& local_surface_id) { - tracker_.OnWindowBoundsChanged(window, std::move(old_bounds), - std::move(new_bounds), local_surface_id); -} - -void TestWindowTreeClient::OnWindowTransformChanged( - Id window, - const gfx::Transform& old_transform, - const gfx::Transform& new_transform) {} - -void TestWindowTreeClient::OnClientAreaChanged( - Id window_id, - const gfx::Insets& new_client_area, - const std::vector<gfx::Rect>& new_additional_client_areas) {} - -void TestWindowTreeClient::OnTransientWindowAdded(Id window_id, - Id transient_window_id) {} - -void TestWindowTreeClient::OnTransientWindowRemoved(Id window_id, - Id transient_window_id) {} - -void TestWindowTreeClient::OnWindowHierarchyChanged( - Id window, - Id old_parent, - Id new_parent, - std::vector<mojom::WindowDataPtr> windows) { - tracker_.OnWindowHierarchyChanged(window, old_parent, new_parent, - std::move(windows)); -} - -void TestWindowTreeClient::OnWindowReordered(Id window_id, - Id relative_window_id, - mojom::OrderDirection direction) { - tracker_.OnWindowReordered(window_id, relative_window_id, direction); -} - -void TestWindowTreeClient::OnWindowDeleted(Id window) { - tracker_.OnWindowDeleted(window); -} - -void TestWindowTreeClient::OnWindowVisibilityChanged(Id window, bool visible) { - tracker_.OnWindowVisibilityChanged(window, visible); -} - -void TestWindowTreeClient::OnWindowOpacityChanged(Id window, - float old_opacity, - float new_opacity) { - tracker_.OnWindowOpacityChanged(window, new_opacity); -} - -void TestWindowTreeClient::OnWindowParentDrawnStateChanged(Id window, - bool drawn) { - tracker_.OnWindowParentDrawnStateChanged(window, drawn); -} - -void TestWindowTreeClient::OnWindowSharedPropertyChanged( - Id window, - const std::string& name, - const base::Optional<std::vector<uint8_t>>& new_data) { - tracker_.OnWindowSharedPropertyChanged(window, name, new_data); -} - -void TestWindowTreeClient::OnWindowInputEvent( - uint32_t event_id, - Id window, - int64_t display_id, - Id display_root_window, - const gfx::PointF& event_location_in_screen_pixel_layout, - std::unique_ptr<ui::Event> event, - bool matches_pointer_watcher) { - tracker_.OnWindowInputEvent(window, *event.get(), display_id, - event_location_in_screen_pixel_layout, - matches_pointer_watcher); -} - -void TestWindowTreeClient::OnPointerEventObserved( - std::unique_ptr<ui::Event> event, - Id window_id, - int64_t display_id) { - tracker_.OnPointerEventObserved(*event.get(), window_id); -} - -void TestWindowTreeClient::OnWindowFocused(Id focused_window_id) { - tracker_.OnWindowFocused(focused_window_id); -} - -void TestWindowTreeClient::OnWindowCursorChanged(Id window_id, - ui::CursorData cursor) { - tracker_.OnWindowCursorChanged(window_id, cursor); -} - -void TestWindowTreeClient::OnWindowSurfaceChanged( - Id window_id, - const viz::SurfaceInfo& surface_info) {} - -void TestWindowTreeClient::OnDragDropStart( - const base::flat_map<std::string, std::vector<uint8_t>>& mime_data) {} - -void TestWindowTreeClient::OnDragEnter(Id window, - uint32_t key_state, - const gfx::Point& position, - uint32_t effect_bitmask, - OnDragEnterCallback callback) {} - -void TestWindowTreeClient::OnDragOver(Id window, - uint32_t key_state, - const gfx::Point& position, - uint32_t effect_bitmask, - OnDragOverCallback callback) {} - -void TestWindowTreeClient::OnDragLeave(Id window) {} - -void TestWindowTreeClient::OnCompleteDrop(Id window, - uint32_t key_state, - const gfx::Point& position, - uint32_t effect_bitmask, - OnCompleteDropCallback callback) {} - -void TestWindowTreeClient::OnPerformDragDropCompleted(uint32_t change_id, - bool success, - uint32_t action_taken) {} - -void TestWindowTreeClient::OnDragDropDone() {} - -void TestWindowTreeClient::OnChangeCompleted(uint32_t change_id, bool success) { - if (record_on_change_completed_) - tracker_.OnChangeCompleted(change_id, success); -} - -void TestWindowTreeClient::RequestClose(Id window_id) {} - -void TestWindowTreeClient::GetWindowManager( - mojo::AssociatedInterfaceRequest<mojom::WindowManager> internal) {} - -void TestWindowTreeClient::GetScreenProviderObserver( - mojom::ScreenProviderObserverAssociatedRequest observer) {} - -// TestWindowTreeBinding ------------------------------------------------------ - -TestWindowTreeBinding::TestWindowTreeBinding( - WindowTree* tree, - std::unique_ptr<TestWindowTreeClient> client) - : WindowTreeBinding(client.get()), - tree_(tree), - client_(std::move(client)) {} - -TestWindowTreeBinding::~TestWindowTreeBinding() {} - -mojom::WindowManager* TestWindowTreeBinding::GetWindowManager() { - if (!window_manager_.get()) - window_manager_ = std::make_unique<TestWindowManager>(); - return window_manager_.get(); -} -void TestWindowTreeBinding::SetIncomingMethodCallProcessingPaused(bool paused) { - is_paused_ = paused; -} - -mojom::WindowTreeClient* TestWindowTreeBinding::CreateClientForShutdown() { - DCHECK(!client_after_reset_); - client_after_reset_ = std::make_unique<TestWindowTreeClient>(); - return client_after_reset_.get(); -} - -// TestWindowServerDelegate ---------------------------------------------- - -TestWindowServerDelegate::TestWindowServerDelegate() - : threaded_image_cursors_factory_( - std::make_unique<TestThreadedImageCursorsFactory>()) {} -TestWindowServerDelegate::~TestWindowServerDelegate() {} - -TestWindowTreeBinding* TestWindowServerDelegate::Embed(WindowTree* tree, - ServerWindow* window, - int flags) { - mojom::WindowTreeClientPtr client; - mojom::WindowTreeClientRequest client_request = mojo::MakeRequest(&client); - ClientWindowId client_window_id; - if (!tree->IsWindowKnown(window, &client_window_id)) - return nullptr; - - tree->Embed(client_window_id, std::move(client), flags); - last_client()->Bind(std::move(client_request)); - return last_binding(); -} - -void TestWindowServerDelegate::StartDisplayInit() {} - -void TestWindowServerDelegate::OnNoMoreDisplays() { - got_on_no_more_displays_ = true; -} - -std::unique_ptr<WindowTreeBinding> -TestWindowServerDelegate::CreateWindowTreeBinding( - BindingType type, - ws::WindowServer* window_server, - ws::WindowTree* tree, - mojom::WindowTreeRequest* tree_request, - mojom::WindowTreeClientPtr* client) { - std::unique_ptr<TestWindowTreeBinding> binding = - std::make_unique<TestWindowTreeBinding>(tree); - bindings_.push_back(binding.get()); - return std::move(binding); -} - -bool TestWindowServerDelegate::IsTestConfig() const { - return true; -} - -void TestWindowServerDelegate::OnWillCreateTreeForWindowManager( - bool automatically_create_display_roots) { - if (window_server_->display_creation_config() != - DisplayCreationConfig::UNKNOWN) { - return; - } - window_server_->SetDisplayCreationConfig( - automatically_create_display_roots ? DisplayCreationConfig::AUTOMATIC - : DisplayCreationConfig::MANUAL); -} - -ThreadedImageCursorsFactory* -TestWindowServerDelegate::GetThreadedImageCursorsFactory() { - return threaded_image_cursors_factory_.get(); -} - -// WindowServerTestHelper --------------------------------------------------- - -WindowServerTestHelper::WindowServerTestHelper() - : cursor_(ui::CursorType::kNull), platform_display_factory_(&cursor_) { - // Some tests create their own message loop, for example to add a task runner. - if (!base::MessageLoopCurrent::Get()) - message_loop_ = std::make_unique<base::MessageLoop>(); - PlatformDisplay::set_factory_for_testing(&platform_display_factory_); - window_server_ = std::make_unique<WindowServer>(&window_server_delegate_, - true /* should_host_viz */); - std::unique_ptr<gpu_host::GpuHost> gpu_host = - std::make_unique<gpu_host::TestGpuHost>(); - window_server_->SetGpuHost(std::move(gpu_host)); - window_server_delegate_.set_window_server(window_server_.get()); -} - -WindowServerTestHelper::~WindowServerTestHelper() { - // Destroy |window_server_| while the message-loop is still alive. - window_server_.reset(); -} - -// WindowEventTargetingHelper ------------------------------------------------ - -WindowEventTargetingHelper::WindowEventTargetingHelper( - bool automatically_create_display_roots) { - display_ = new Display(window_server()); - display_binding_ = new TestDisplayBinding(window_server(), - automatically_create_display_roots); - display_->Init(display::ViewportMetrics(), - base::WrapUnique(display_binding_)); - wm_client_ = ws_test_helper_.window_server_delegate()->last_client(); - wm_client_->tracker()->changes()->clear(); -} - -WindowEventTargetingHelper::~WindowEventTargetingHelper() {} - -ServerWindow* WindowEventTargetingHelper::CreatePrimaryTree( - const gfx::Rect& root_window_bounds, - const gfx::Rect& window_bounds) { - WindowTree* wm_tree = window_server()->GetTreeWithId(kWindowManagerClientId); - const ClientWindowId embed_window_id(wm_tree->id(), - next_primary_tree_window_id_++); - EXPECT_TRUE(wm_tree->NewWindow(embed_window_id, ServerWindow::Properties())); - EXPECT_TRUE(wm_tree->SetWindowVisibility(embed_window_id, true)); - EXPECT_TRUE(wm_tree->AddWindow(FirstRootId(wm_tree), embed_window_id)); - display_->root_window()->SetBounds(root_window_bounds, base::nullopt); - mojom::WindowTreeClientPtr client; - ws_test_helper_.window_server_delegate()->last_client()->Bind( - mojo::MakeRequest(&client)); - const uint32_t embed_flags = 0; - wm_tree->Embed(embed_window_id, std::move(client), embed_flags); - ServerWindow* embed_window = wm_tree->GetWindowByClientId(embed_window_id); - embed_window->set_event_targeting_policy( - mojom::EventTargetingPolicy::DESCENDANTS_ONLY); - WindowTree* tree1 = window_server()->GetTreeWithRoot(embed_window); - WindowTreeTestApi(tree1).set_is_for_embedding(false); - EXPECT_NE(nullptr, tree1); - EXPECT_NE(tree1, wm_tree); - - embed_window->SetBounds(window_bounds, base::nullopt); - - return embed_window; -} - -void WindowEventTargetingHelper::CreateSecondaryTree( - ServerWindow* embed_window, - const gfx::Rect& window_bounds, - TestWindowTreeClient** out_client, - WindowTree** window_tree, - ServerWindow** window) { - WindowTree* tree1 = window_server()->GetTreeWithRoot(embed_window); - ASSERT_TRUE(tree1 != nullptr); - const ClientWindowId child1_id(tree1->id(), kEmbedTreeWindowId); - ASSERT_TRUE(tree1->NewWindow(child1_id, ServerWindow::Properties())); - ServerWindow* child1 = tree1->GetWindowByClientId(child1_id); - ASSERT_TRUE(child1); - EXPECT_TRUE(tree1->AddWindow(ClientWindowIdForWindow(tree1, embed_window), - child1_id)); - embed_window->set_is_activation_parent(true); - - child1->SetVisible(true); - child1->SetBounds(window_bounds, base::nullopt); - - TestWindowTreeClient* embed_client = - ws_test_helper_.window_server_delegate()->last_client(); - embed_client->tracker()->changes()->clear(); - wm_client_->tracker()->changes()->clear(); - - *out_client = embed_client; - *window_tree = tree1; - *window = child1; -} - -void WindowEventTargetingHelper::SetTaskRunner( - scoped_refptr<base::SingleThreadTaskRunner> task_runner) { - base::MessageLoopCurrent::Get()->SetTaskRunner(task_runner); -} - -// ---------------------------------------------------------------------------- - -TestScreenProviderObserver::TestScreenProviderObserver() : binding_(this) {} - -TestScreenProviderObserver::~TestScreenProviderObserver() = default; - -mojom::ScreenProviderObserverPtr TestScreenProviderObserver::GetPtr() { - mojom::ScreenProviderObserverPtr ptr; - binding_.Bind(mojo::MakeRequest(&ptr)); - return ptr; -} - -std::string TestScreenProviderObserver::GetAndClearObserverCalls() { - std::string result; - std::swap(observer_calls_, result); - return result; -} - -std::string TestScreenProviderObserver::DisplayIdsToString( - const std::vector<mojom::WsDisplayPtr>& wm_displays) { - std::string display_ids; - for (const auto& wm_display : wm_displays) { - if (!display_ids.empty()) - display_ids += " "; - display_ids += base::Int64ToString(wm_display->display.id()); - } - return display_ids; -} - -void TestScreenProviderObserver::OnDisplaysChanged( - std::vector<mojom::WsDisplayPtr> displays, - int64_t primary_display_id, - int64_t internal_display_id) { - if (!observer_calls_.empty()) - observer_calls_ += "\n"; - observer_calls_ += "OnDisplaysChanged " + DisplayIdsToString(displays); - observer_calls_ += " " + base::Int64ToString(internal_display_id); -} - -// ----------------------------------------------------------------------------- -TestPlatformDisplay::TestPlatformDisplay( - const display::ViewportMetrics& metrics, - ui::CursorData* cursor_storage) - : metrics_(metrics), cursor_storage_(cursor_storage) {} - -TestPlatformDisplay::~TestPlatformDisplay() = default; - -// PlatformDisplay: -void TestPlatformDisplay::Init(PlatformDisplayDelegate* delegate) { - delegate->OnAcceleratedWidgetAvailable(); -} -void TestPlatformDisplay::SetViewportSize(const gfx::Size& size) {} -void TestPlatformDisplay::SetTitle(const base::string16& title) {} -void TestPlatformDisplay::SetCapture() { - has_capture_ = true; -} -void TestPlatformDisplay::ReleaseCapture() { - has_capture_ = false; -} -void TestPlatformDisplay::SetCursor(const ui::CursorData& cursor) { - *cursor_storage_ = cursor; -} -void TestPlatformDisplay::SetCursorSize(const ui::CursorSize& cursor_size) {} -void TestPlatformDisplay::ConfineCursorToBounds(const gfx::Rect& pixel_bounds) { - confine_cursor_bounds_ = pixel_bounds; -} -void TestPlatformDisplay::MoveCursorTo( - const gfx::Point& window_pixel_location) {} -void TestPlatformDisplay::UpdateTextInputState( - const ui::TextInputState& state) {} -void TestPlatformDisplay::SetImeVisibility(bool visible) {} -void TestPlatformDisplay::UpdateViewportMetrics( - const display::ViewportMetrics& metrics) { - metrics_ = metrics; -} -const display::ViewportMetrics& TestPlatformDisplay::GetViewportMetrics() { - return metrics_; -} -gfx::AcceleratedWidget TestPlatformDisplay::GetAcceleratedWidget() const { - return gfx::kNullAcceleratedWidget; -} -FrameGenerator* TestPlatformDisplay::GetFrameGenerator() { - return nullptr; -} -EventSink* TestPlatformDisplay::GetEventSink() { - return nullptr; -} -void TestPlatformDisplay::SetCursorConfig(display::Display::Rotation rotation, - float scale) { - cursor_scale_ = scale; -} - -// ----------------------------------------------------------------------------- - -CursorLocationManagerTestApi::CursorLocationManagerTestApi( - CursorLocationManager* cursor_location_manager) - : cursor_location_manager_(cursor_location_manager) {} - -CursorLocationManagerTestApi::~CursorLocationManagerTestApi() = default; - -base::subtle::Atomic32 CursorLocationManagerTestApi::current_cursor_location() { - return cursor_location_manager_->current_cursor_location_; -} - -// ----------------------------------------------------------------------------- - -void AddWindowManager(WindowServer* window_server, - bool automatically_create_display_roots) { - window_server->window_manager_window_tree_factory()->CreateWindowTree( - nullptr, nullptr, automatically_create_display_roots); -} - -display::Display MakeDisplay(int origin_x, - int origin_y, - int width_pixels, - int height_pixels, - float scale_factor) { - gfx::Size scaled_size = gfx::ConvertSizeToDIP( - scale_factor, gfx::Size(width_pixels, height_pixels)); - gfx::Rect bounds(gfx::Point(origin_x, origin_y), scaled_size); - - display::Display display; - display.set_bounds(bounds); - display.set_work_area(bounds); - display.set_device_scale_factor(scale_factor); - return display; -} - -ServerWindow* FirstRoot(WindowTree* tree) { - return tree->roots().size() == 1u - ? const_cast<ServerWindow*>(*(tree->roots().begin())) - : nullptr; -} - -ClientWindowId FirstRootId(WindowTree* tree) { - ServerWindow* first_root = FirstRoot(tree); - return first_root ? ClientWindowIdForWindow(tree, first_root) - : ClientWindowId(); -} - -ClientWindowId ClientWindowIdForWindow(WindowTree* tree, - const ServerWindow* window) { - ClientWindowId client_window_id; - // If window isn't known we'll return 0, which should then error out. - tree->IsWindowKnown(window, &client_window_id); - return client_window_id; -} - -ServerWindow* NewWindowInTree(WindowTree* tree, ClientWindowId* client_id) { - return NewWindowInTreeWithParent(tree, FirstRoot(tree), client_id); -} - -ServerWindow* NewWindowInTreeWithParent(WindowTree* tree, - ServerWindow* parent, - ClientWindowId* client_id, - const gfx::Rect& bounds) { - if (!parent) - return nullptr; - ClientWindowId parent_client_id; - if (!tree->IsWindowKnown(parent, &parent_client_id)) - return nullptr; - ClientWindowId client_window_id = NextUnusedClientWindowId(tree); - if (!tree->NewWindow(client_window_id, ServerWindow::Properties())) - return nullptr; - if (!tree->SetWindowVisibility(client_window_id, true)) - return nullptr; - if (!tree->AddWindow(parent_client_id, client_window_id)) - return nullptr; - ServerWindow* window = tree->GetWindowByClientId(client_window_id); - window->SetBounds(bounds); - if (client_id) - *client_id = client_window_id; - return window; -} - -gfx::Point Atomic32ToPoint(base::subtle::Atomic32 atomic) { - return gfx::Point(static_cast<int16_t>(atomic >> 16), - static_cast<int16_t>(atomic & 0xFFFF)); -} - -} // namespace test -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/test_utils.h b/services/ui/ws/test_utils.h deleted file mode 100644 index 846fd73..0000000 --- a/services/ui/ws/test_utils.h +++ /dev/null
@@ -1,891 +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. - -#ifndef SERVICES_UI_WS_TEST_UTILS_H_ -#define SERVICES_UI_WS_TEST_UTILS_H_ - -#include <stdint.h> - -#include <memory> -#include <set> -#include <vector> - -#include "base/atomicops.h" -#include "base/containers/flat_map.h" -#include "base/message_loop/message_loop.h" -#include "base/optional.h" -#include "base/single_thread_task_runner.h" -#include "services/service_manager/public/cpp/bind_source_info.h" -#include "services/ui/display/screen_manager.h" -#include "services/ui/display/viewport_metrics.h" -#include "services/ui/gpu_host/gpu_host.h" -#include "services/ui/public/interfaces/screen_provider.mojom.h" -#include "services/ui/public/interfaces/window_tree.mojom.h" -#include "services/ui/ws/display.h" -#include "services/ui/ws/display_binding.h" -#include "services/ui/ws/drag_controller.h" -#include "services/ui/ws/event_dispatcher_impl_test_api.h" -#include "services/ui/ws/event_processor.h" -#include "services/ui/ws/event_targeter.h" -#include "services/ui/ws/platform_display.h" -#include "services/ui/ws/platform_display_factory.h" -#include "services/ui/ws/test_change_tracker.h" -#include "services/ui/ws/user_activity_monitor.h" -#include "services/ui/ws/window_manager_state.h" -#include "services/ui/ws/window_server_delegate.h" -#include "services/ui/ws/window_tree.h" -#include "services/ui/ws/window_tree_binding.h" -#include "ui/display/display.h" -#include "ui/display/screen_base.h" -#include "ui/display/types/display_constants.h" - -namespace ui { -namespace ws { - -class CursorLocationManager; - -namespace test { - -const ClientSpecificId kWindowManagerClientId = kWindowServerClientId + 1; -const std::string kWindowManagerClientIdString = - std::to_string(kWindowManagerClientId); -const ClientSpecificId kEmbedTreeWindowId = 1; - -// Collection of utilities useful in creating mus tests. - -// Test ScreenManager instance that allows adding/modifying/removing displays. -// Tracks display ids to perform some basic verification that no duplicates are -// added and display was added before being modified or removed. Display ids -// reset when Init() is called. -class TestScreenManager : public display::ScreenManager { - public: - TestScreenManager(); - ~TestScreenManager() override; - - // Adds a new display with default metrics, generates a unique display id and - // returns it. Calls OnDisplayAdded() on delegate. - int64_t AddDisplay(); - - // Adds a new display with provided |display|, generates a unique display id - // and returns it. Calls OnDisplayAdded() on delegate. - int64_t AddDisplay(const display::Display& display); - - // Calls OnDisplayModified() on delegate. - void ModifyDisplay(const display::Display& display, - const base::Optional<display::ViewportMetrics>& metrics = - base::Optional<display::ViewportMetrics>()); - - // Calls OnDisplayRemoved() on delegate. - void RemoveDisplay(int64_t id); - - // display::ScreenManager: - void AddInterfaces( - service_manager::BinderRegistryWithArgs< - const service_manager::BindSourceInfo&>* registry) override {} - void Init(display::ScreenManagerDelegate* delegate) override; - void RequestCloseDisplay(int64_t display_id) override {} - display::ScreenBase* GetScreen() override; - - private: - display::ScreenManagerDelegate* delegate_ = nullptr; - std::unique_ptr<display::ScreenBase> screen_; - std::set<int64_t> display_ids_; - - DISALLOW_COPY_AND_ASSIGN(TestScreenManager); -}; - -// ----------------------------------------------------------------------------- - -class UserActivityMonitorTestApi { - public: - explicit UserActivityMonitorTestApi(UserActivityMonitor* monitor) - : monitor_(monitor) {} - - void SetTimerTaskRunner( - scoped_refptr<base::SingleThreadTaskRunner> task_runner) { - monitor_->idle_timer_.SetTaskRunner(task_runner); - } - - private: - UserActivityMonitor* monitor_; - DISALLOW_COPY_AND_ASSIGN(UserActivityMonitorTestApi); -}; - -// ----------------------------------------------------------------------------- - -class WindowTreeTestApi { - public: - explicit WindowTreeTestApi(WindowTree* tree); - ~WindowTreeTestApi(); - - void set_is_for_embedding(bool value) { tree_->is_for_embedding_ = value; } - void set_window_manager_internal(mojom::WindowManager* wm_internal) { - tree_->window_manager_internal_ = wm_internal; - } - void SetEventTargetingPolicy(Id transport_window_id, - mojom::EventTargetingPolicy policy) { - tree_->SetEventTargetingPolicy(transport_window_id, policy); - } - void AckOldestEvent( - mojom::EventResult result = mojom::EventResult::UNHANDLED) { - tree_->OnWindowInputEventAck(tree_->event_ack_id_, result); - } - void EnableCapture() { tree_->event_ack_id_ = 1u; } - void AckLastEvent(mojom::EventResult result) { - tree_->OnWindowInputEventAck(tree_->event_ack_id_, result); - } - void AckLastAccelerator( - mojom::EventResult result, - const base::flat_map<std::string, std::vector<uint8_t>>& properties = - base::flat_map<std::string, std::vector<uint8_t>>()) { - tree_->OnAcceleratorAck(tree_->event_ack_id_, result, properties); - } - - void StartPointerWatcher(bool want_moves); - void StopPointerWatcher(); - - bool ProcessSetDisplayRoot(const display::Display& display_to_create, - const display::ViewportMetrics& viewport_metrics, - bool is_primary_display, - const ClientWindowId& client_window_id) { - return tree_->ProcessSetDisplayRoot(display_to_create, viewport_metrics, - is_primary_display, client_window_id, - std::vector<display::Display>()); - } - - bool ProcessSwapDisplayRoots(int64_t display_id1, int64_t display_id2) { - return tree_->ProcessSwapDisplayRoots(display_id1, display_id2); - } - size_t event_queue_size() const { return tree_->event_queue_.size(); } - bool HasEventInFlight() const { return tree_->event_ack_id_ != 0u; } - - private: - WindowTree* tree_; - - DISALLOW_COPY_AND_ASSIGN(WindowTreeTestApi); -}; - -// ----------------------------------------------------------------------------- - -class EventProcessorTestApi { - public: - explicit EventProcessorTestApi(EventProcessor* ep) : ep_(ep) {} - ~EventProcessorTestApi() {} - - bool AreAnyPointersDown() const { return ep_->AreAnyPointersDown(); } - bool is_mouse_button_down() const { return ep_->mouse_button_down_; } - bool IsWindowPointerTarget(const ServerWindow* window) const; - int NumberPointerTargetsForWindow(ServerWindow* window); - ModalWindowController* modal_window_controller() const { - return &ep_->modal_window_controller_; - } - ServerWindow* capture_window() { return ep_->capture_window_; } - EventTargeter* event_targeter() { return ep_->event_targeter_.get(); } - bool IsObservingWindow(ServerWindow* window); - - private: - EventProcessor* ep_; - - DISALLOW_COPY_AND_ASSIGN(EventProcessorTestApi); -}; - -// ----------------------------------------------------------------------------- - -class EventTargeterTestApi { - public: - explicit EventTargeterTestApi(EventTargeter* event_targeter) - : event_targeter_(event_targeter) {} - ~EventTargeterTestApi() {} - - bool HasPendingQueries() const { - return event_targeter_->weak_ptr_factory_.HasWeakPtrs(); - } - - private: - EventTargeter* event_targeter_; - - DISALLOW_COPY_AND_ASSIGN(EventTargeterTestApi); -}; - -// ----------------------------------------------------------------------------- - -class ModalWindowControllerTestApi { - public: - explicit ModalWindowControllerTestApi(ModalWindowController* mwc) - : mwc_(mwc) {} - ~ModalWindowControllerTestApi() {} - - const ServerWindow* GetActiveSystemModalWindow() const { - return mwc_->GetActiveSystemModalWindow(); - } - - private: - ModalWindowController* mwc_; - - DISALLOW_COPY_AND_ASSIGN(ModalWindowControllerTestApi); -}; - -// ----------------------------------------------------------------------------- - -class WindowManagerStateTestApi { - public: - explicit WindowManagerStateTestApi(WindowManagerState* wms) : wms_(wms) {} - ~WindowManagerStateTestApi() {} - - ClientSpecificId GetEventTargetClientId(ServerWindow* window, - bool in_nonclient_area) { - return wms_->GetEventTargetClientId(window, in_nonclient_area); - } - - void ProcessEvent(ui::Event* event, int64_t display_id = 0) { - wms_->ProcessEvent(event, display_id); - } - - ClientSpecificId GetEventTargetClientId(const ServerWindow* window, - bool in_nonclient_area) { - return wms_->GetEventTargetClientId(window, in_nonclient_area); - } - - void OnEventAckTimeout(ClientSpecificId client_id) { - EventDispatcherImplTestApi(&wms_->event_dispatcher_) - .OnDispatchInputEventTimeout(); - } - - const std::vector<std::unique_ptr<WindowManagerDisplayRoot>>& - window_manager_display_roots() const { - return wms_->window_manager_display_roots_; - } - - // TODO(sky): convert calling code to use EventDispatcherImplTestApi directly. - void DispatchInputEventToWindow(ServerWindow* target, - ClientSpecificId client_id, - const EventLocation& event_location, - const ui::Event& event, - Accelerator* accelerator) { - EventDispatcherImplTestApi(&wms_->event_dispatcher_) - .DispatchInputEventToWindow(target, client_id, event_location, event, - accelerator); - } - WindowTree* tree_awaiting_input_ack() { - return EventDispatcherImplTestApi(&wms_->event_dispatcher_) - .GetTreeThatWillAckEvent(); - } - bool is_event_tasks_empty() const { - return EventDispatcherImplTestApi(&wms_->event_dispatcher_) - .is_event_tasks_empty(); - } - bool AckInFlightEvent(mojom::EventResult result) { - return EventDispatcherImplTestApi(&wms_->event_dispatcher_) - .OnDispatchInputEventDone(result); - } - - private: - WindowManagerState* wms_; - - DISALLOW_COPY_AND_ASSIGN(WindowManagerStateTestApi); -}; - -// ----------------------------------------------------------------------------- - -class DragControllerTestApi { - public: - explicit DragControllerTestApi(DragController* op) : op_(op) {} - ~DragControllerTestApi() {} - - size_t GetSizeOfQueueForWindow(ServerWindow* window) { - return op_->GetSizeOfQueueForWindow(window); - } - - ServerWindow* GetCurrentTarget() { return op_->current_target_window_; } - - private: - DragController* op_; - - DISALLOW_COPY_AND_ASSIGN(DragControllerTestApi); -}; - -// ----------------------------------------------------------------------------- - -// Factory that always embeds the new WindowTree as the root user id. -class TestDisplayBinding : public DisplayBinding { - public: - explicit TestDisplayBinding(WindowServer* window_server, - bool automatically_create_display_roots = true) - : window_server_(window_server), - automatically_create_display_roots_( - automatically_create_display_roots) {} - ~TestDisplayBinding() override {} - - private: - // DisplayBinding: - WindowTree* CreateWindowTree(ServerWindow* root) override; - - WindowServer* window_server_; - const bool automatically_create_display_roots_; - - DISALLOW_COPY_AND_ASSIGN(TestDisplayBinding); -}; - -// ----------------------------------------------------------------------------- - -// Factory that dispenses TestPlatformDisplays. -class TestPlatformDisplayFactory : public PlatformDisplayFactory { - public: - explicit TestPlatformDisplayFactory(ui::CursorData* cursor_storage); - ~TestPlatformDisplayFactory(); - - // PlatformDisplayFactory: - std::unique_ptr<PlatformDisplay> CreatePlatformDisplay( - ServerWindow* root_window, - const display::ViewportMetrics& metrics) override; - - private: - ui::CursorData* cursor_storage_; - - DISALLOW_COPY_AND_ASSIGN(TestPlatformDisplayFactory); -}; - -// ----------------------------------------------------------------------------- - -class TestWindowManager : public mojom::WindowManager { - public: - TestWindowManager(); - ~TestWindowManager() override; - - bool did_call_create_top_level_window(uint32_t* change_id) { - if (!got_create_top_level_window_) - return false; - - got_create_top_level_window_ = false; - *change_id = change_id_; - return true; - } - - void ClearAcceleratorCalled() { - on_accelerator_id_ = 0u; - on_accelerator_called_ = false; - } - - const std::string& last_wm_action() const { return last_wm_action_; } - bool on_perform_move_loop_called() { return on_perform_move_loop_called_; } - bool on_accelerator_called() { return on_accelerator_called_; } - uint32_t on_accelerator_id() { return on_accelerator_id_; } - bool got_display_removed() const { return got_display_removed_; } - int64_t display_removed_id() const { return display_removed_id_; } - bool on_set_modal_type_called() { return on_set_modal_type_called_; } - int connect_count() const { return connect_count_; } - int display_added_count() const { return display_added_count_; } - - private: - // WindowManager: - void OnConnect() override; - void WmOnAcceleratedWidgetForDisplay( - int64_t display, - gpu::SurfaceHandle surface_handle) override; - void WmNewDisplayAdded( - const display::Display& display, - ui::mojom::WindowDataPtr root, - bool drawn, - const base::Optional<viz::LocalSurfaceId>& local_surface_id) override; - void WmDisplayRemoved(int64_t display_id) override; - void WmDisplayModified(const display::Display& display) override {} - void WmSetBounds(uint32_t change_id, - Id window_id, - const gfx::Rect& bounds) override {} - void WmSetProperty( - uint32_t change_id, - Id window_id, - const std::string& name, - const base::Optional<std::vector<uint8_t>>& value) override {} - void WmSetModalType(Id window_id, ui::ModalType type) override; - void WmSetCanFocus(Id window_id, bool can_focus) override {} - void WmCreateTopLevelWindow( - uint32_t change_id, - const viz::FrameSinkId& frame_sink_id, - const base::flat_map<std::string, std::vector<uint8_t>>& properties) - override; - void WmClientJankinessChanged(ClientSpecificId client_id, - bool janky) override; - void WmBuildDragImage(const gfx::Point& screen_location, - const gfx::ImageSkia& drag_image, - const gfx::Vector2d& drag_image_offset, - ui::mojom::PointerKind source) override; - void WmMoveDragImage(const gfx::Point& screen_location, - WmMoveDragImageCallback callback) override; - void WmDestroyDragImage() override; - void WmPerformMoveLoop(uint32_t change_id, - Id window_id, - mojom::MoveLoopSource source, - const gfx::Point& cursor_location) override; - void WmCancelMoveLoop(uint32_t change_id) override; - void WmDeactivateWindow(Id window_id) override; - void WmStackAbove(uint32_t change_id, Id above_id, Id below_id) override; - void WmStackAtTop(uint32_t change_id, Id window_id) override; - void WmPerformWmAction(Id window_id, const std::string& action) override; - void OnAccelerator(uint32_t ack_id, - uint32_t accelerator_id, - std::unique_ptr<ui::Event> event) override; - void OnCursorTouchVisibleChanged(bool enabled) override; - void OnEventBlockedByModalWindow(Id window_id) override; - - std::string last_wm_action_; - - bool on_perform_move_loop_called_ = false; - bool on_set_modal_type_called_ = false; - - bool got_create_top_level_window_ = false; - uint32_t change_id_ = 0u; - - bool on_accelerator_called_ = false; - uint32_t on_accelerator_id_ = 0u; - - bool got_display_removed_ = false; - int64_t display_removed_id_ = 0; - - int connect_count_ = 0; - int display_added_count_ = 0; - - DISALLOW_COPY_AND_ASSIGN(TestWindowManager); -}; - -// ----------------------------------------------------------------------------- - -// WindowTreeClient implementation that logs all calls to a TestChangeTracker. -class TestWindowTreeClient : public ui::mojom::WindowTreeClient { - public: - TestWindowTreeClient(); - ~TestWindowTreeClient() override; - - TestChangeTracker* tracker() { return &tracker_; } - - void Bind(mojo::InterfaceRequest<mojom::WindowTreeClient> request); - - void set_record_on_change_completed(bool value) { - record_on_change_completed_ = value; - } - - private: - // WindowTreeClient: - void OnEmbed( - mojom::WindowDataPtr root, - ui::mojom::WindowTreePtr tree, - int64_t display_id, - Id focused_window_id, - bool drawn, - const base::Optional<viz::LocalSurfaceId>& local_surface_id) override; - void OnEmbedFromToken( - const base::UnguessableToken& token, - mojom::WindowDataPtr root, - int64_t display_id, - const base::Optional<viz::LocalSurfaceId>& local_surface_id) override; - void OnEmbeddedAppDisconnected(Id window) override; - void OnUnembed(Id window_id) override; - void OnCaptureChanged(Id new_capture_window_id, - Id old_capture_window_id) override; - void OnFrameSinkIdAllocated(Id window_id, - const viz::FrameSinkId& frame_sink_id) override; - void OnTopLevelCreated( - uint32_t change_id, - mojom::WindowDataPtr data, - int64_t display_id, - bool drawn, - const base::Optional<viz::LocalSurfaceId>& local_surface_id) override; - void OnWindowBoundsChanged( - Id window, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds, - const base::Optional<viz::LocalSurfaceId>& local_surface_id) override; - void OnWindowTransformChanged(Id window, - const gfx::Transform& old_transform, - const gfx::Transform& new_transform) override; - void OnClientAreaChanged( - Id window_id, - const gfx::Insets& new_client_area, - const std::vector<gfx::Rect>& new_additional_client_areas) override; - void OnTransientWindowAdded(Id window_id, Id transient_window_id) override; - void OnTransientWindowRemoved(Id window_id, Id transient_window_id) override; - void OnWindowHierarchyChanged( - Id window, - Id old_parent, - Id new_parent, - std::vector<mojom::WindowDataPtr> windows) override; - void OnWindowReordered(Id window_id, - Id relative_window_id, - mojom::OrderDirection direction) override; - void OnWindowDeleted(Id window) override; - void OnWindowVisibilityChanged(Id window, bool visible) override; - void OnWindowOpacityChanged(Id window, - float old_opacity, - float new_opacity) override; - void OnWindowParentDrawnStateChanged(Id window, bool drawn) override; - void OnWindowSharedPropertyChanged( - Id window, - const std::string& name, - const base::Optional<std::vector<uint8_t>>& new_data) override; - void OnWindowInputEvent( - uint32_t event_id, - Id window, - int64_t display_id, - Id display_root_window, - const gfx::PointF& event_location_in_screen_pixel_layout, - std::unique_ptr<ui::Event> event, - bool matches_pointer_watcher) override; - void OnPointerEventObserved(std::unique_ptr<ui::Event> event, - Id window_id, - int64_t display_id) override; - void OnWindowFocused(Id focused_window_id) override; - void OnWindowCursorChanged(Id window_id, ui::CursorData cursor) override; - void OnWindowSurfaceChanged(Id window_id, - const viz::SurfaceInfo& surface_info) override; - void OnDragDropStart(const base::flat_map<std::string, std::vector<uint8_t>>& - mime_data) override; - void OnDragEnter(Id window, - uint32_t key_state, - const gfx::Point& position, - uint32_t effect_bitmask, - OnDragEnterCallback callback) override; - void OnDragOver(Id window, - uint32_t key_state, - const gfx::Point& position, - uint32_t effect_bitmask, - OnDragOverCallback callback) override; - void OnDragLeave(Id window) override; - void OnCompleteDrop(Id window, - uint32_t key_state, - const gfx::Point& position, - uint32_t effect_bitmask, - OnCompleteDropCallback callback) override; - void OnPerformDragDropCompleted(uint32_t change_id, - bool success, - uint32_t action_taken) override; - void OnDragDropDone() override; - void OnChangeCompleted(uint32_t change_id, bool success) override; - void RequestClose(Id window_id) override; - void GetWindowManager( - mojo::AssociatedInterfaceRequest<mojom::WindowManager> internal) override; - void GetScreenProviderObserver( - mojom::ScreenProviderObserverAssociatedRequest observer) override; - - TestChangeTracker tracker_; - mojo::Binding<mojom::WindowTreeClient> binding_; - bool record_on_change_completed_ = false; - - DISALLOW_COPY_AND_ASSIGN(TestWindowTreeClient); -}; - -// ----------------------------------------------------------------------------- - -// WindowTreeBinding implementation that vends TestWindowTreeBinding. -class TestWindowTreeBinding : public WindowTreeBinding { - public: - TestWindowTreeBinding(WindowTree* tree, - std::unique_ptr<TestWindowTreeClient> client = - std::make_unique<TestWindowTreeClient>()); - ~TestWindowTreeBinding() override; - - std::unique_ptr<TestWindowTreeClient> ReleaseClient() { - return std::move(client_); - } - - WindowTree* tree() { return tree_; } - TestWindowTreeClient* client() { return client_.get(); } - TestWindowManager* window_manager() { return window_manager_.get(); } - - bool is_paused() const { return is_paused_; } - - // WindowTreeBinding: - mojom::WindowManager* GetWindowManager() override; - void SetIncomingMethodCallProcessingPaused(bool paused) override; - - protected: - // WindowTreeBinding: - mojom::WindowTreeClient* CreateClientForShutdown() override; - - private: - WindowTree* tree_; - std::unique_ptr<TestWindowTreeClient> client_; - // This is the client created once ResetClientForShutdown() is called. - std::unique_ptr<TestWindowTreeClient> client_after_reset_; - bool is_paused_ = false; - std::unique_ptr<TestWindowManager> window_manager_; - - DISALLOW_COPY_AND_ASSIGN(TestWindowTreeBinding); -}; - -// ----------------------------------------------------------------------------- - -// WindowServerDelegate that creates TestWindowTreeClients. -class TestWindowServerDelegate : public WindowServerDelegate { - public: - TestWindowServerDelegate(); - ~TestWindowServerDelegate() override; - - void set_window_server(WindowServer* window_server) { - window_server_ = window_server; - } - - TestWindowTreeClient* last_client() { - return last_binding() ? last_binding()->client() : nullptr; - } - TestWindowTreeBinding* last_binding() { - return bindings_.empty() ? nullptr : bindings_.back(); - } - - std::vector<TestWindowTreeBinding*>* bindings() { return &bindings_; } - - bool got_on_no_more_displays() const { return got_on_no_more_displays_; } - - // Does an Embed() in |tree| at |window| returning the TestWindowTreeBinding - // that resulred (null on failure). - TestWindowTreeBinding* Embed(WindowTree* tree, - ServerWindow* window, - int flags = 0); - - // WindowServerDelegate: - void StartDisplayInit() override; - void OnNoMoreDisplays() override; - std::unique_ptr<WindowTreeBinding> CreateWindowTreeBinding( - BindingType type, - ws::WindowServer* window_server, - ws::WindowTree* tree, - mojom::WindowTreeRequest* tree_request, - mojom::WindowTreeClientPtr* client) override; - bool IsTestConfig() const override; - void OnWillCreateTreeForWindowManager( - bool automatically_create_display_roots) override; - ThreadedImageCursorsFactory* GetThreadedImageCursorsFactory() override; - - private: - WindowServer* window_server_ = nullptr; - bool got_on_no_more_displays_ = false; - // All TestWindowTreeBinding objects created via CreateWindowTreeBinding. - // These are owned by the corresponding WindowTree. - std::vector<TestWindowTreeBinding*> bindings_; - std::unique_ptr<ThreadedImageCursorsFactory> threaded_image_cursors_factory_; - - DISALLOW_COPY_AND_ASSIGN(TestWindowServerDelegate); -}; - -// ----------------------------------------------------------------------------- - -// Helper class which creates and sets up the necessary objects for tests that -// use the WindowServer. -class WindowServerTestHelper { - public: - WindowServerTestHelper(); - ~WindowServerTestHelper(); - - WindowServer* window_server() { return window_server_.get(); } - const ui::CursorData& cursor() const { return cursor_; } - - TestWindowServerDelegate* window_server_delegate() { - return &window_server_delegate_; - } - - private: - ui::CursorData cursor_; - TestPlatformDisplayFactory platform_display_factory_; - TestWindowServerDelegate window_server_delegate_; - std::unique_ptr<WindowServer> window_server_; - std::unique_ptr<base::MessageLoop> message_loop_; - - DISALLOW_COPY_AND_ASSIGN(WindowServerTestHelper); -}; - -// ----------------------------------------------------------------------------- - -// Helper class which owns all of the necessary objects to test event targeting -// of ServerWindow objects. -class WindowEventTargetingHelper { - public: - explicit WindowEventTargetingHelper( - bool automatically_create_display_roots = true); - ~WindowEventTargetingHelper(); - - // Creates |window| as an embeded window of the primary tree. This window is a - // root window of its own tree, with bounds |window_bounds|. The bounds of the - // root window of |display_| are defined by |root_window_bounds|. - ServerWindow* CreatePrimaryTree(const gfx::Rect& root_window_bounds, - const gfx::Rect& window_bounds); - // Creates a secondary tree, embedded as a child of |embed_window|. The - // resulting |window| is setup for event targeting, with bounds - // |window_bounds|. - // TODO(sky): rename and cleanup. This doesn't really create a new tree. - void CreateSecondaryTree(ServerWindow* embed_window, - const gfx::Rect& window_bounds, - TestWindowTreeClient** out_client, - WindowTree** window_tree, - ServerWindow** window); - // Sets the task runner for |message_loop_| - void SetTaskRunner(scoped_refptr<base::SingleThreadTaskRunner> task_runner); - - ui::CursorType cursor_type() const { - return ws_test_helper_.cursor().cursor_type(); - } - Display* display() { return display_; } - TestWindowTreeBinding* last_binding() { - return ws_test_helper_.window_server_delegate()->last_binding(); - } - TestWindowTreeClient* last_window_tree_client() { - return ws_test_helper_.window_server_delegate()->last_client(); - } - TestWindowTreeClient* wm_client() { return wm_client_; } - WindowServer* window_server() { return ws_test_helper_.window_server(); } - - TestWindowServerDelegate* test_window_server_delegate() { - return ws_test_helper_.window_server_delegate(); - } - - private: - WindowServerTestHelper ws_test_helper_; - // TestWindowTreeClient that is used for the WM client. Owned by - // |window_server_delegate_| - TestWindowTreeClient* wm_client_ = nullptr; - // Owned by WindowServer - TestDisplayBinding* display_binding_ = nullptr; - // Owned by WindowServer's DisplayManager. - Display* display_ = nullptr; - ClientSpecificId next_primary_tree_window_id_ = kEmbedTreeWindowId; - - DISALLOW_COPY_AND_ASSIGN(WindowEventTargetingHelper); -}; - -// ----------------------------------------------------------------------------- - -class TestScreenProviderObserver : public mojom::ScreenProviderObserver { - public: - TestScreenProviderObserver(); - ~TestScreenProviderObserver() override; - - mojom::ScreenProviderObserverPtr GetPtr(); - - std::string GetAndClearObserverCalls(); - - private: - std::string DisplayIdsToString( - const std::vector<mojom::WsDisplayPtr>& wm_displays); - - // mojom::ScreenProviderObserver: - void OnDisplaysChanged(std::vector<mojom::WsDisplayPtr> displays, - int64_t primary_display_id, - int64_t internal_display_id) override; - - mojo::Binding<mojom::ScreenProviderObserver> binding_; - std::string observer_calls_; - - DISALLOW_COPY_AND_ASSIGN(TestScreenProviderObserver); -}; - -// ----------------------------------------------------------------------------- -// Empty implementation of PlatformDisplay. -class TestPlatformDisplay : public PlatformDisplay { - public: - TestPlatformDisplay(const display::ViewportMetrics& metrics, - ui::CursorData* cursor_storage); - ~TestPlatformDisplay() override; - - display::Display::Rotation cursor_rotation() const { - return cursor_rotation_; - } - float cursor_scale() const { return cursor_scale_; } - - gfx::Rect confine_cursor_bounds() const { return confine_cursor_bounds_; } - - const display::ViewportMetrics& metrics() const { return metrics_; } - - bool has_capture() const { return has_capture_; } - - // PlatformDisplay: - void Init(PlatformDisplayDelegate* delegate) override; - void SetViewportSize(const gfx::Size& size) override; - void SetTitle(const base::string16& title) override; - void SetCapture() override; - void ReleaseCapture() override; - void SetCursor(const ui::CursorData& cursor) override; - void SetCursorSize(const ui::CursorSize& cursor_size) override; - void ConfineCursorToBounds(const gfx::Rect& pixel_bounds) override; - void MoveCursorTo(const gfx::Point& window_pixel_location) override; - void UpdateTextInputState(const ui::TextInputState& state) override; - void SetImeVisibility(bool visible) override; - void UpdateViewportMetrics(const display::ViewportMetrics& metrics) override; - const display::ViewportMetrics& GetViewportMetrics() override; - gfx::AcceleratedWidget GetAcceleratedWidget() const override; - FrameGenerator* GetFrameGenerator() override; - EventSink* GetEventSink() override; - void SetCursorConfig(display::Display::Rotation rotation, - float scale) override; - - private: - display::ViewportMetrics metrics_; - ui::CursorData* cursor_storage_; - display::Display::Rotation cursor_rotation_ = - display::Display::Rotation::ROTATE_0; - float cursor_scale_ = 1.0f; - gfx::Rect confine_cursor_bounds_; - bool has_capture_ = false; - - DISALLOW_COPY_AND_ASSIGN(TestPlatformDisplay); -}; - -// ----------------------------------------------------------------------------- - -class CursorLocationManagerTestApi { - public: - CursorLocationManagerTestApi(CursorLocationManager* cursor_location_manager); - ~CursorLocationManagerTestApi(); - - base::subtle::Atomic32 current_cursor_location(); - - private: - CursorLocationManager* cursor_location_manager_; - - DISALLOW_COPY_AND_ASSIGN(CursorLocationManagerTestApi); -}; - -// ----------------------------------------------------------------------------- - -// Adds a WM to |window_server|. Creates WindowManagerWindowTreeFactory and -// associated WindowTree for the WM. -void AddWindowManager(WindowServer* window_server, - bool automatically_create_display_roots = true); - -// Create a new Display object with specified origin, pixel size and device -// scale factor. The bounds size is computed based on the pixel size and device -// scale factor. -display::Display MakeDisplay(int origin_x, - int origin_y, - int width_pixels, - int height_pixels, - float scale_factor); - -// Returns the first and only root of |tree|. If |tree| has zero or more than -// one root returns null. -ServerWindow* FirstRoot(WindowTree* tree); - -// Returns the ClientWindowId of the first root of |tree|, or an empty -// ClientWindowId if |tree| has zero or more than one root. -ClientWindowId FirstRootId(WindowTree* tree); - -// Returns |tree|s ClientWindowId for |window|. -ClientWindowId ClientWindowIdForWindow(WindowTree* tree, - const ServerWindow* window); - -// Creates a new visible window as a child of the single root of |tree|. -// |client_id| is set to the ClientWindowId of the new window. -ServerWindow* NewWindowInTree(WindowTree* tree, - ClientWindowId* client_id = nullptr); -ServerWindow* NewWindowInTreeWithParent(WindowTree* tree, - ServerWindow* parent, - ClientWindowId* client_id = nullptr, - const gfx::Rect& bounds = gfx::Rect()); - -// Converts an atomic 32 to a point. The cursor location is represented as an -// atomic 32. -gfx::Point Atomic32ToPoint(base::subtle::Atomic32 atomic); - -} // namespace test -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_TEST_UTILS_H_
diff --git a/services/ui/ws/threaded_image_cursors.cc b/services/ui/ws/threaded_image_cursors.cc deleted file mode 100644 index f5178d7..0000000 --- a/services/ui/ws/threaded_image_cursors.cc +++ /dev/null
@@ -1,230 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "services/ui/ws/threaded_image_cursors.h" - -#include "base/bind.h" -#include "base/single_thread_task_runner.h" -#include "base/threading/thread_task_runner_handle.h" -#include "services/ui/common/image_cursors_set.h" -#include "ui/base/cursor/cursor_data.h" -#include "ui/base/cursor/image_cursors.h" -#include "ui/platform_window/platform_window.h" - -#if defined(USE_OZONE) -#include "ui/ozone/public/cursor_factory_ozone.h" -#include "ui/ozone/public/ozone_platform.h" -#endif - -namespace ui { -namespace ws { -namespace { - -void AddImageCursorsOnResourceThread( - base::WeakPtr<ui::ImageCursorsSet> image_cursors_set_weak_ptr, - std::unique_ptr<ui::ImageCursors> image_cursors) { - if (image_cursors_set_weak_ptr) - image_cursors_set_weak_ptr->AddImageCursors(std::move(image_cursors)); -} - -void RemoveImageCursorsOnResourceThread( - base::WeakPtr<ui::ImageCursorsSet> image_cursors_set_weak_ptr, - base::WeakPtr<ui::ImageCursors> image_cursors_weak_ptr) { - if (image_cursors_set_weak_ptr && image_cursors_weak_ptr) { - image_cursors_set_weak_ptr->DeleteImageCursors( - image_cursors_weak_ptr.get()); - } -} - -void SetDisplayOnResourceThread( - base::WeakPtr<ui::ImageCursors> image_cursors_weak_ptr, - const display::Display& display, - float scale_factor) { - if (image_cursors_weak_ptr) - image_cursors_weak_ptr->SetDisplay(display, scale_factor); -} - -void SetCursorSizeOnResourceThread( - base::WeakPtr<ui::ImageCursors> image_cursors_weak_ptr, - CursorSize cursor_size) { - if (image_cursors_weak_ptr) - image_cursors_weak_ptr->SetCursorSize(cursor_size); -} - -// Executed on |resource_task_runner_|. Sets cursor type on -// |image_cursors_set_weak_ptr_|, and then schedules a task on -// |ui_service_task_runner_| to set the corresponding PlatformCursor on the -// provided |platform_window|. -// |platform_window| pointer needs to be valid while -// |threaded_image_cursors_weak_ptr| is not invalidated. -void SetCursorOnResourceThread( - base::WeakPtr<ui::ImageCursors> image_cursors_weak_ptr, - ui::CursorType cursor_type, - ui::PlatformWindow* platform_window, - scoped_refptr<base::SingleThreadTaskRunner> ui_service_task_runner_, - base::WeakPtr<ThreadedImageCursors> threaded_image_cursors_weak_ptr) { - if (image_cursors_weak_ptr) { - ui::Cursor native_cursor(cursor_type); - image_cursors_weak_ptr->SetPlatformCursor(&native_cursor); - // |platform_window| is owned by the UI Service thread, so setting the - // cursor on it also needs to happen on that thread. - ui_service_task_runner_->PostTask( - FROM_HERE, base::Bind(&ThreadedImageCursors::SetCursorOnPlatformWindow, - threaded_image_cursors_weak_ptr, - native_cursor.platform(), platform_window)); - } -} - -#if defined(USE_OZONE) -// Executed on |resource_task_runner_|. Creates a PlatformCursor using the -// Ozone |cursor_factory| passed to it, and then schedules a task on -// |ui_service_task_runner_| to set that cursor on the provided -// |platform_window|. -// |platform_window| pointer needs to be valid while -// |threaded_image_cursors_weak_ptr| is not invalidated. -void SetCustomCursorOnResourceThread( - base::WeakPtr<ui::ImageCursors> image_cursors_weak_ptr, - std::unique_ptr<ui::CursorData> cursor_data, - ui::CursorFactoryOzone* cursor_factory, - ui::PlatformWindow* platform_window, - scoped_refptr<base::SingleThreadTaskRunner> ui_service_task_runner_, - base::WeakPtr<ThreadedImageCursors> threaded_image_cursors_weak_ptr) { - if (image_cursors_weak_ptr) { - ui::PlatformCursor platform_cursor = - cursor_data->ToNativeCursor().platform(); - // |platform_window| is owned by the UI Service thread, so setting the - // cursor on it also needs to happen on that thread. - ui_service_task_runner_->PostTask( - FROM_HERE, - base::Bind(&ThreadedImageCursors::SetCursorOnPlatformWindowAndUnref, - threaded_image_cursors_weak_ptr, platform_cursor, - platform_window)); - } -} -#endif // defined(USE_OZONE) - -} // namespace - -ThreadedImageCursors::ThreadedImageCursors( - scoped_refptr<base::SingleThreadTaskRunner>& resource_task_runner, - base::WeakPtr<ui::ImageCursorsSet> image_cursors_set_weak_ptr) - : resource_task_runner_(resource_task_runner), - image_cursors_set_weak_ptr_(image_cursors_set_weak_ptr), - weak_ptr_factory_(this) { - DCHECK(resource_task_runner_); - ui_service_task_runner_ = base::ThreadTaskRunnerHandle::Get(); - - // Create and initialize the ImageCursors object here and then set it on - // |image_cursors_set_weak_ptr_|. Note that it is essential to initialize - // the ImageCursors object on the UI Service's thread if we are using Ozone, - // so that it uses the right (thread-local) CursorFactoryOzone instance. - std::unique_ptr<ui::ImageCursors> image_cursors = - std::make_unique<ui::ImageCursors>(); - image_cursors->Initialize(); - image_cursors_weak_ptr_ = image_cursors->GetWeakPtr(); - resource_task_runner_->PostTask( - FROM_HERE, - base::Bind(&AddImageCursorsOnResourceThread, image_cursors_set_weak_ptr_, - base::Passed(std::move(image_cursors)))); -} - -ThreadedImageCursors::~ThreadedImageCursors() { - resource_task_runner_->PostTask( - FROM_HERE, - base::Bind(&RemoveImageCursorsOnResourceThread, - image_cursors_set_weak_ptr_, image_cursors_weak_ptr_)); -} - -void ThreadedImageCursors::SetDisplay(const display::Display& display, - float scale_factor) { - resource_task_runner_->PostTask( - FROM_HERE, base::Bind(&SetDisplayOnResourceThread, - image_cursors_weak_ptr_, display, scale_factor)); -} - -void ThreadedImageCursors::SetCursorSize(CursorSize cursor_size) { - resource_task_runner_->PostTask( - FROM_HERE, base::Bind(&SetCursorSizeOnResourceThread, - image_cursors_weak_ptr_, cursor_size)); -} - -void ThreadedImageCursors::SetCursor(const ui::CursorData& cursor_data, - ui::PlatformWindow* platform_window) { - ui::CursorType cursor_type = cursor_data.cursor_type(); - -#if !defined(USE_OZONE) - // Outside of ozone builds, there isn't a single interface for creating - // PlatformCursors. The closest thing to one is in //content/ instead of - // //ui/ which means we can't use it from here. For now, just don't handle - // custom image cursors. - // - // TODO(erg): Once blink speaks directly to mus, make blink perform its own - // cursor management on its own mus windows so we can remove Webcursor from - // //content/ and do this in way that's safe cross-platform, instead of as an - // ozone-specific hack. - if (cursor_type == ui::CursorType::kCustom) { - NOTIMPLEMENTED() << "No custom cursor support on non-ozone yet."; - cursor_type = ui::CursorType::kPointer; - } -#else - // In Ozone builds, we have an interface available which turns bitmap data - // into platform cursors. - if (cursor_type == ui::CursorType::kCustom) { - std::unique_ptr<ui::CursorData> cursor_data_copy = - std::make_unique<ui::CursorData>(cursor_data); - ui::CursorFactoryOzone* cursor_factory = - ui::CursorFactoryOzone::GetInstance(); - // CursorFactoryOzone is a thread-local singleton (crbug.com/741106). - // However the instance that belongs to the UI Service thread is used - // on the resource thread. (This happens via ImageCursors when we call - // SetCursorOnResourceThread.) Since CursorFactoryOzone is not thread-safe, - // we should only use it on the UI Service thread, which is why this - // PostTask is needed. - resource_task_runner_->PostTask( - FROM_HERE, - base::Bind(&SetCustomCursorOnResourceThread, image_cursors_weak_ptr_, - base::Passed(&cursor_data_copy), - base::Unretained(cursor_factory), platform_window, - ui_service_task_runner_, weak_ptr_factory_.GetWeakPtr())); - } -#endif // !defined(USE_OZONE) - - // Handle the non-custom cursor case for both Ozone and non-Ozone builds. - if (cursor_type != ui::CursorType::kCustom) { - resource_task_runner_->PostTask( - FROM_HERE, - base::Bind(&SetCursorOnResourceThread, image_cursors_weak_ptr_, - cursor_type, platform_window, ui_service_task_runner_, - weak_ptr_factory_.GetWeakPtr())); - } -} - -void ThreadedImageCursors::SetCursorOnPlatformWindow( - ui::PlatformCursor platform_cursor, - ui::PlatformWindow* platform_window) { - platform_window->SetCursor(platform_cursor); -} - -#if defined(USE_OZONE) -void ThreadedImageCursors::SetCursorOnPlatformWindowAndUnref( - ui::PlatformCursor platform_cursor, - ui::PlatformWindow* platform_window) { - SetCursorOnPlatformWindow(platform_cursor, platform_window); - - // The PlatformCursor returned by CreateAnimatedCursor() has a single - // refcount which is owned by the caller. If we were returned a valid - // |platform_cursor|, we must unref it here. All implementations of - // PlatformWindow::SetCursor() which need to keep the PlatformCursor have - // increased the refcount for their self. - // - // Note: Cursors returned by SetPlatformCursor() do not return custom bitmap - // cursors. The refcount of such a cursor is owned by the caller and - // shouldn't be refed/unrefed by the caller. - if (platform_cursor) - ui::CursorFactoryOzone::GetInstance()->UnrefImageCursor(platform_cursor); -} -#endif - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/threaded_image_cursors.h b/services/ui/ws/threaded_image_cursors.h deleted file mode 100644 index b9ce89f..0000000 --- a/services/ui/ws/threaded_image_cursors.h +++ /dev/null
@@ -1,101 +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 SERVICES_UI_WS_THREADED_IMAGE_CURSORS_H_ -#define SERVICES_UI_WS_THREADED_IMAGE_CURSORS_H_ - -#include "base/memory/weak_ptr.h" -#include "ui/base/cursor/cursor.h" - -namespace base { -class SingleThreadTaskRunner; -} - -namespace display { -class Display; -} - -namespace ui { -class CursorData; -class ImageCursors; -class ImageCursorsSet; -class PlatformWindow; - -namespace ws { - -// Wrapper around ui::ImageCursors, which executes its methods asynchronously -// via the provided task runner. This is needed because ui::ImageCursors needs -// to load resources when executing some of its methods, which cannot happen on -// the UI Service's thread when it runs inside the Window Manager process. -// -// Unlike ImageCursors, this class can also handle CursorType::kCustom cursors, -// which is also done asynchronously. -// -// Note: We could execute the methods synchronously when UI Service runs in its -// own process (and thus the provided task runner matches the task runner of the -// UI Service's thread), but we don't do that in the interest of sharing code. -class ThreadedImageCursors { - public: - // |resource_runner| is the task runner for the thread which can be used to - // load resources; |image_cursors_set_weak_ptr_| points to an object that - // lives on |resource_runner|'s thread. - // We create an ImageCursors object here and then pass the ownership to - // |image_cursors_set_weak_ptr_|. All operations on the ImageCursors object - // happen on |resource_runner|, which is why we need the owner to live on - // |resource_runner|'s thread. - ThreadedImageCursors( - scoped_refptr<base::SingleThreadTaskRunner>& resource_task_runner, - base::WeakPtr<ui::ImageCursorsSet> image_cursors_set_weak_ptr_); - ~ThreadedImageCursors(); - - // Executes ui::ImageCursors::SetDisplay asynchronously. - // Sets the display the cursors are loaded for. |scale_factor| determines the - // size of the image to load. Returns true if the cursor image is reloaded. - void SetDisplay(const display::Display& display, float scale_factor); - - // Asynchronously sets the size of the mouse cursor icon. - void SetCursorSize(CursorSize cursor_size); - - // Asynchronously loads the cursor and then sets the corresponding - // PlatformCursor on the provided |platform_window|. - // |platform_window| pointer needs to be valid while this object is alive. - void SetCursor(const ui::CursorData& cursor_data, - ui::PlatformWindow* platform_window); - - // Helper method. Sets |platform_cursor| on the |platform_window|. - void SetCursorOnPlatformWindow(ui::PlatformCursor platform_cursor, - ui::PlatformWindow* platform_window); -#if defined(USE_OZONE) - void SetCursorOnPlatformWindowAndUnref(ui::PlatformCursor platform_cursor, - ui::PlatformWindow* platform_window); -#endif - - private: - // The object used for performing the actual cursor operations. - // Created on UI Service's thread, but is used on the - // |resource_task_runner_|'s thread, because it needs to load resources. - base::WeakPtr<ui::ImageCursors> image_cursors_weak_ptr_; - - // Task runner for the thread which owns the cursor resources. - // |image_cursors_set_weak_ptr__| and |image_cursors_weak_ptr_| should only - // be dereferenced on this task runner. - scoped_refptr<base::SingleThreadTaskRunner> resource_task_runner_; - - // Task runner of the UI Service thread (where this object is created and - // destroyed). - scoped_refptr<base::SingleThreadTaskRunner> ui_service_task_runner_; - - // Lives on |resource_runner_|'s thread, used to own the object behind - // |image_cursors_weak_ptr_|. - base::WeakPtr<ui::ImageCursorsSet> image_cursors_set_weak_ptr_; - - base::WeakPtrFactory<ThreadedImageCursors> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(ThreadedImageCursors); -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_THREADED_IMAGE_CURSORS_H_
diff --git a/services/ui/ws/threaded_image_cursors_factory.h b/services/ui/ws/threaded_image_cursors_factory.h deleted file mode 100644 index 1deab54..0000000 --- a/services/ui/ws/threaded_image_cursors_factory.h +++ /dev/null
@@ -1,23 +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 SERVICES_UI_WS_THREADED_IMAGE_CURSORS_FACTORY_H_ -#define SERVICES_UI_WS_THREADED_IMAGE_CURSORS_FACTORY_H_ - -#include <memory> - -namespace ui { -namespace ws { -class ThreadedImageCursors; - -class ThreadedImageCursorsFactory { - public: - virtual ~ThreadedImageCursorsFactory() {} - virtual std::unique_ptr<ThreadedImageCursors> CreateCursors() = 0; -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_THREADED_IMAGE_CURSORS_FACTORY_H_
diff --git a/services/ui/ws/transient_windows_unittest.cc b/services/ui/ws/transient_windows_unittest.cc deleted file mode 100644 index 19dca6b..0000000 --- a/services/ui/ws/transient_windows_unittest.cc +++ /dev/null
@@ -1,191 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/macros.h" -#include "base/strings/string_number_conversions.h" -#include "services/ui/ws/server_window.h" -#include "services/ui/ws/server_window_observer.h" -#include "services/ui/ws/test_server_window_delegate.h" -#include "services/ui/ws/test_utils.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace ui { -namespace ws { - -namespace { - -class TestTransientWindowObserver : public ServerWindowObserver { - public: - TestTransientWindowObserver() : add_count_(0), remove_count_(0) {} - - ~TestTransientWindowObserver() override {} - - int add_count() const { return add_count_; } - int remove_count() const { return remove_count_; } - - // TransientWindowObserver overrides: - void OnTransientWindowAdded(ServerWindow* window, - ServerWindow* transient) override { - add_count_++; - } - void OnTransientWindowRemoved(ServerWindow* window, - ServerWindow* transient) override { - remove_count_++; - } - - private: - int add_count_; - int remove_count_; - - DISALLOW_COPY_AND_ASSIGN(TestTransientWindowObserver); -}; - -ServerWindow* CreateTestWindow(TestServerWindowDelegate* delegate, - const viz::FrameSinkId& frame_sink_id, - ServerWindow* parent) { - ServerWindow* window = new ServerWindow(delegate, frame_sink_id); - window->SetVisible(true); - if (parent) - parent->Add(window); - else - delegate->set_root_window(window); - return window; -} - -std::string ChildWindowIDsAsString(ServerWindow* parent) { - std::string result; - for (auto i = parent->children().begin(); i != parent->children().end(); - ++i) { - if (!result.empty()) - result += " "; - const viz::FrameSinkId& id = (*i)->frame_sink_id(); - if (id.client_id() != 0) { - // All use cases of this expect the client_id to be 0. - return "unexpected-client-id"; - } - result += base::IntToString(id.sink_id()); - } - return result; -} - -} // namespace - -class TransientWindowsTest : public testing::Test { - public: - TransientWindowsTest() {} - ~TransientWindowsTest() override {} - - VizHostProxy* viz_host_proxy() { - return ws_test_helper_.window_server()->GetVizHostProxy(); - } - - private: - test::WindowServerTestHelper ws_test_helper_; - - DISALLOW_COPY_AND_ASSIGN(TransientWindowsTest); -}; - -TEST_F(TransientWindowsTest, TransientChildren) { - TestServerWindowDelegate server_window_delegate(viz_host_proxy()); - - std::unique_ptr<ServerWindow> parent(CreateTestWindow( - &server_window_delegate, viz::FrameSinkId(1, 0), nullptr)); - std::unique_ptr<ServerWindow> w1(CreateTestWindow( - &server_window_delegate, viz::FrameSinkId(1, 1), parent.get())); - std::unique_ptr<ServerWindow> w3(CreateTestWindow( - &server_window_delegate, viz::FrameSinkId(1, 2), parent.get())); - - ServerWindow* w2 = CreateTestWindow(&server_window_delegate, - viz::FrameSinkId(1, 3), parent.get()); - - // w2 is now owned by w1. - w1->AddTransientWindow(w2); - // Stack w1 at the top (end), this should force w2 to be last (on top of w1). - parent->StackChildAtTop(w1.get()); - - // Destroy w1, which should also destroy w3 (since it's a transient child). - w1.reset(); - w2 = nullptr; - ASSERT_EQ(1u, parent->children().size()); - EXPECT_EQ(w3.get(), parent->children()[0]); -} - -// Verifies adding doesn't restack at all. -TEST_F(TransientWindowsTest, DontStackUponCreation) { - TestServerWindowDelegate delegate(viz_host_proxy()); - std::unique_ptr<ServerWindow> parent( - CreateTestWindow(&delegate, viz::FrameSinkId(0, 1), nullptr)); - std::unique_ptr<ServerWindow> window0( - CreateTestWindow(&delegate, viz::FrameSinkId(0, 2), parent.get())); - std::unique_ptr<ServerWindow> window1( - CreateTestWindow(&delegate, viz::FrameSinkId(0, 3), parent.get())); - - ServerWindow* window2 = - CreateTestWindow(&delegate, viz::FrameSinkId(0, 4), parent.get()); - window0->AddTransientWindow(window2); - EXPECT_EQ("2 3 4", ChildWindowIDsAsString(parent.get())); -} - -// More variations around verifying ordering doesn't change when -// adding/removing transients. -TEST_F(TransientWindowsTest, RestackUponAddOrRemoveTransientWindow) { - TestServerWindowDelegate delegate(viz_host_proxy()); - std::unique_ptr<ServerWindow> parent( - CreateTestWindow(&delegate, viz::FrameSinkId(0, 1), nullptr)); - std::unique_ptr<ServerWindow> windows[4]; - for (int i = 0; i < 4; i++) - windows[i].reset( - CreateTestWindow(&delegate, viz::FrameSinkId(0, i + 2), parent.get())); - - EXPECT_EQ("2 3 4 5", ChildWindowIDsAsString(parent.get())); - - windows[0]->AddTransientWindow(windows[2].get()); - EXPECT_EQ(windows[0].get(), windows[2]->transient_parent()); - ASSERT_EQ(1u, windows[0]->transient_children().size()); - EXPECT_EQ(windows[2].get(), windows[0]->transient_children()[0]); - EXPECT_EQ("2 3 4 5", ChildWindowIDsAsString(parent.get())); - - windows[0]->AddTransientWindow(windows[3].get()); - EXPECT_EQ(windows[0].get(), windows[3]->transient_parent()); - ASSERT_EQ(2u, windows[0]->transient_children().size()); - EXPECT_EQ(windows[2].get(), windows[0]->transient_children()[0]); - EXPECT_EQ(windows[3].get(), windows[0]->transient_children()[1]); - EXPECT_EQ("2 3 4 5", ChildWindowIDsAsString(parent.get())); - - windows[0]->RemoveTransientWindow(windows[2].get()); - EXPECT_EQ(nullptr, windows[2]->transient_parent()); - ASSERT_EQ(1u, windows[0]->transient_children().size()); - EXPECT_EQ(windows[3].get(), windows[0]->transient_children()[0]); - EXPECT_EQ("2 3 4 5", ChildWindowIDsAsString(parent.get())); - - windows[0]->RemoveTransientWindow(windows[3].get()); - EXPECT_EQ(nullptr, windows[3]->transient_parent()); - ASSERT_EQ(0u, windows[0]->transient_children().size()); - EXPECT_EQ("2 3 4 5", ChildWindowIDsAsString(parent.get())); -} - -// Verifies TransientWindowObserver is notified appropriately. -TEST_F(TransientWindowsTest, TransientWindowObserverNotified) { - TestServerWindowDelegate delegate(viz_host_proxy()); - std::unique_ptr<ServerWindow> parent( - CreateTestWindow(&delegate, viz::FrameSinkId(0, 1), nullptr)); - std::unique_ptr<ServerWindow> w1( - CreateTestWindow(&delegate, viz::FrameSinkId(0, 2), parent.get())); - - TestTransientWindowObserver test_observer; - parent->AddObserver(&test_observer); - - parent->AddTransientWindow(w1.get()); - EXPECT_EQ(1, test_observer.add_count()); - EXPECT_EQ(0, test_observer.remove_count()); - - parent->RemoveTransientWindow(w1.get()); - EXPECT_EQ(1, test_observer.add_count()); - EXPECT_EQ(1, test_observer.remove_count()); - - parent->RemoveObserver(&test_observer); -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/user_activity_monitor.cc b/services/ui/ws/user_activity_monitor.cc deleted file mode 100644 index 8e22d445..0000000 --- a/services/ui/ws/user_activity_monitor.cc +++ /dev/null
@@ -1,136 +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 "services/ui/ws/user_activity_monitor.h" - -#include "base/bind.h" -#include "base/memory/ptr_util.h" -#include "base/time/default_tick_clock.h" - -namespace ui { -namespace ws { - -UserActivityMonitor::UserActivityMonitor( - std::unique_ptr<const base::TickClock> clock) - : now_clock_(std::move(clock)) { - if (!now_clock_) - now_clock_ = base::WrapUnique(new base::DefaultTickClock); - last_activity_ = now_clock_->NowTicks(); -} - -UserActivityMonitor::~UserActivityMonitor() {} - -void UserActivityMonitor::OnUserActivity() { - base::TimeTicks now = now_clock_->NowTicks(); - for (auto& pair : activity_observers_) { - ActivityObserverInfo* info = &(pair.first); - if (info->last_activity_notification.is_null() || - (now - info->last_activity_notification) > info->delay) { - pair.second->OnUserActivity(); - info->last_activity_notification = now; - } - } - - // Wake up all the 'idle' observers. - for (auto& pair : idle_observers_) { - IdleObserverInfo* info = &(pair.first); - if (info->idle_state == mojom::UserIdleObserver::IdleState::ACTIVE) - continue; - info->last_idle_state_notification = now; - info->idle_state = mojom::UserIdleObserver::IdleState::ACTIVE; - pair.second->OnUserIdleStateChanged(info->idle_state); - } - - last_activity_ = now; - - // Start the timer if there are some idle observers. - if (idle_timer_.IsRunning()) - idle_timer_.Reset(); -} - -void UserActivityMonitor::Add(mojom::UserActivityMonitorRequest request) { - bindings_.AddBinding(this, std::move(request)); -} - -void UserActivityMonitor::AddUserActivityObserver( - uint32_t delay_between_notify_secs, - mojom::UserActivityObserverPtr observer) { - ActivityObserverInfo info; - info.delay = base::TimeDelta::FromSeconds(delay_between_notify_secs); - observer.set_connection_error_handler( - base::Bind(&UserActivityMonitor::OnActivityObserverDisconnected, - base::Unretained(this), observer.get())); - activity_observers_.push_back(std::make_pair(info, std::move(observer))); -} - -void UserActivityMonitor::AddUserIdleObserver( - uint32_t idleness_in_minutes, - mojom::UserIdleObserverPtr observer) { - IdleObserverInfo info; - info.idle_duration = base::TimeDelta::FromMinutes(idleness_in_minutes); - base::TimeTicks now = now_clock_->NowTicks(); - DCHECK(!last_activity_.is_null()); - bool user_is_active = (now - last_activity_ < info.idle_duration); - info.idle_state = user_is_active ? mojom::UserIdleObserver::IdleState::ACTIVE - : mojom::UserIdleObserver::IdleState::IDLE; - info.last_idle_state_notification = now; - observer->OnUserIdleStateChanged(info.idle_state); - observer.set_connection_error_handler( - base::Bind(&UserActivityMonitor::OnIdleObserverDisconnected, - base::Unretained(this), observer.get())); - idle_observers_.push_back(std::make_pair(info, std::move(observer))); - if (user_is_active) - ActivateIdleTimer(); -} - -void UserActivityMonitor::ActivateIdleTimer() { - if (idle_timer_.IsRunning()) - return; - idle_timer_.Start(FROM_HERE, base::TimeDelta::FromMinutes(1), this, - &UserActivityMonitor::OnMinuteTimer); -} - -void UserActivityMonitor::OnMinuteTimer() { - base::TimeTicks now = now_clock_->NowTicks(); - bool active_observer = false; - for (auto& pair : idle_observers_) { - IdleObserverInfo* info = &(pair.first); - if (info->idle_state == mojom::UserIdleObserver::IdleState::IDLE) - continue; - if (now - info->last_idle_state_notification < info->idle_duration) { - active_observer = true; - continue; - } - info->last_idle_state_notification = now; - info->idle_state = mojom::UserIdleObserver::IdleState::IDLE; - pair.second->OnUserIdleStateChanged(info->idle_state); - } - // All observers are already notified of IDLE. No point running the timer - // anymore. - if (!active_observer) - idle_timer_.Stop(); -} - -void UserActivityMonitor::OnActivityObserverDisconnected( - mojom::UserActivityObserver* observer) { - activity_observers_.erase(std::remove_if( - activity_observers_.begin(), activity_observers_.end(), - [observer](const std::pair<ActivityObserverInfo, - mojom::UserActivityObserverPtr>& pair) { - return pair.second.get() == observer; - })); -} - -void UserActivityMonitor::OnIdleObserverDisconnected( - mojom::UserIdleObserver* observer) { - idle_observers_.erase(std::remove_if( - idle_observers_.begin(), idle_observers_.end(), - [observer]( - const std::pair<IdleObserverInfo, mojom::UserIdleObserverPtr>& pair) { - return pair.second.get() == observer; - })); -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/user_activity_monitor.h b/services/ui/ws/user_activity_monitor.h deleted file mode 100644 index c892af2..0000000 --- a/services/ui/ws/user_activity_monitor.h +++ /dev/null
@@ -1,83 +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. - -#ifndef SERVICES_UI_WS_USER_ACTIVITY_MONITOR_H_ -#define SERVICES_UI_WS_USER_ACTIVITY_MONITOR_H_ - -#include "base/time/tick_clock.h" -#include "base/time/time.h" -#include "base/timer/timer.h" -#include "mojo/public/cpp/bindings/binding_set.h" -#include "mojo/public/cpp/bindings/interface_ptr_set.h" -#include "services/ui/public/interfaces/user_activity_monitor.mojom.h" - -namespace ui { -namespace ws { - -namespace test { -class UserActivityMonitorTestApi; -} - -class UserActivityMonitor : public mojom::UserActivityMonitor { - public: - // |now_clock| is used to get the timestamp. If |now_clock| is nullptr, then - // DefaultTickClock is used. - explicit UserActivityMonitor( - std::unique_ptr<const base::TickClock> now_clock); - ~UserActivityMonitor() override; - - // Should be called whenever some input event is received from the user. - void OnUserActivity(); - - // Provides an implementation for the remote request. - void Add(mojom::UserActivityMonitorRequest request); - - // mojom::UserActivityMonitor: - void AddUserActivityObserver( - uint32_t delay_between_notify_secs, - mojom::UserActivityObserverPtr observer) override; - void AddUserIdleObserver(uint32_t idleness_in_minutes, - mojom::UserIdleObserverPtr observer) override; - - private: - friend class test::UserActivityMonitorTestApi; - - // Makes sure the idle timer is running. - void ActivateIdleTimer(); - - // Called every minute when |idle_timer_| is active. - void OnMinuteTimer(); - - void OnActivityObserverDisconnected(mojom::UserActivityObserver* observer); - void OnIdleObserverDisconnected(mojom::UserIdleObserver* observer); - - mojo::BindingSet<mojom::UserActivityMonitor> bindings_; - std::unique_ptr<const base::TickClock> now_clock_; - - struct ActivityObserverInfo { - base::TimeTicks last_activity_notification; - base::TimeDelta delay; - }; - std::vector<std::pair<ActivityObserverInfo, mojom::UserActivityObserverPtr>> - activity_observers_; - - struct IdleObserverInfo { - base::TimeTicks last_idle_state_notification; - base::TimeDelta idle_duration; - mojom::UserIdleObserver::IdleState idle_state; - }; - std::vector<std::pair<IdleObserverInfo, mojom::UserIdleObserverPtr>> - idle_observers_; - // Timer used to determine user's idleness. The timer is run only when at - // least one of the idle-observers are notified ACTIVE. - base::RepeatingTimer idle_timer_; - base::TimeTicks last_activity_; - - DISALLOW_COPY_AND_ASSIGN(UserActivityMonitor); -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_USER_ACTIVITY_MONITOR_H_
diff --git a/services/ui/ws/user_activity_monitor_unittest.cc b/services/ui/ws/user_activity_monitor_unittest.cc deleted file mode 100644 index 6ef67baa..0000000 --- a/services/ui/ws/user_activity_monitor_unittest.cc +++ /dev/null
@@ -1,214 +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 "services/ui/ws/user_activity_monitor.h" - -#include "base/run_loop.h" -#include "base/test/simple_test_tick_clock.h" -#include "base/test/test_mock_time_task_runner.h" -#include "mojo/public/cpp/bindings/interface_request.h" -#include "services/ui/common/task_runner_test_base.h" -#include "services/ui/ws/test_utils.h" -#include "testing/gtest/include/gtest/gtest.h" - -using ui::mojom::UserIdleObserver; - -namespace ui { -namespace ws { -namespace test { - -class TestUserActivityObserver : public mojom::UserActivityObserver { - public: - TestUserActivityObserver() : binding_(this) {} - ~TestUserActivityObserver() override {} - - mojom::UserActivityObserverPtr GetPtr() { - mojom::UserActivityObserverPtr ptr; - binding_.Bind(mojo::MakeRequest(&ptr)); - return ptr; - } - - bool GetAndResetReceivedUserActivity() { - bool val = received_user_activity_; - received_user_activity_ = false; - return val; - } - - private: - // mojom::UserActivityObserver: - void OnUserActivity() override { received_user_activity_ = true; } - - mojo::Binding<mojom::UserActivityObserver> binding_; - bool received_user_activity_ = false; - - DISALLOW_COPY_AND_ASSIGN(TestUserActivityObserver); -}; - -class TestUserIdleObserver : public mojom::UserIdleObserver { - public: - TestUserIdleObserver() : binding_(this) {} - ~TestUserIdleObserver() override {} - - mojom::UserIdleObserverPtr GetPtr() { - mojom::UserIdleObserverPtr ptr; - binding_.Bind(mojo::MakeRequest(&ptr)); - return ptr; - } - - bool GetAndResetIdleState(UserIdleObserver::IdleState* state) { - if (!received_idle_state_) - return false; - received_idle_state_ = false; - *state = idle_state_; - return true; - } - - private: - // mojom::UserIdleObserver: - void OnUserIdleStateChanged(UserIdleObserver::IdleState new_state) override { - received_idle_state_ = true; - idle_state_ = new_state; - } - - mojo::Binding<mojom::UserIdleObserver> binding_; - bool received_idle_state_ = false; - UserIdleObserver::IdleState idle_state_ = UserIdleObserver::IdleState::ACTIVE; - - DISALLOW_COPY_AND_ASSIGN(TestUserIdleObserver); -}; - -class UserActivityMonitorTest : public TaskRunnerTestBase { - public: - UserActivityMonitorTest() {} - ~UserActivityMonitorTest() override {} - - UserActivityMonitor* monitor() { return monitor_.get(); } - - private: - // testing::Test: - void SetUp() override { - TaskRunnerTestBase::SetUp(); - monitor_ = std::make_unique<UserActivityMonitor>( - task_runner()->DeprecatedGetMockTickClock()); - } - - std::unique_ptr<UserActivityMonitor> monitor_; - - DISALLOW_COPY_AND_ASSIGN(UserActivityMonitorTest); -}; - -TEST_F(UserActivityMonitorTest, UserActivityObserver) { - TestUserActivityObserver first_observer, second_observer; - monitor()->AddUserActivityObserver(3, first_observer.GetPtr()); - monitor()->AddUserActivityObserver(4, second_observer.GetPtr()); - - // The first activity should notify both observers. - monitor()->OnUserActivity(); - RunUntilIdle(); - EXPECT_TRUE(first_observer.GetAndResetReceivedUserActivity()); - EXPECT_TRUE(second_observer.GetAndResetReceivedUserActivity()); - - // The next activity after just one second should not notify either observer. - RunTasksForNext(base::TimeDelta::FromSeconds(1)); - monitor()->OnUserActivity(); - RunUntilIdle(); - EXPECT_FALSE(first_observer.GetAndResetReceivedUserActivity()); - EXPECT_FALSE(second_observer.GetAndResetReceivedUserActivity()); - - RunTasksForNext(base::TimeDelta::FromMilliseconds(2001)); - monitor()->OnUserActivity(); - RunUntilIdle(); - EXPECT_TRUE(first_observer.GetAndResetReceivedUserActivity()); - EXPECT_FALSE(second_observer.GetAndResetReceivedUserActivity()); - - RunTasksForNext(base::TimeDelta::FromSeconds(1)); - monitor()->OnUserActivity(); - RunUntilIdle(); - EXPECT_FALSE(first_observer.GetAndResetReceivedUserActivity()); - EXPECT_TRUE(second_observer.GetAndResetReceivedUserActivity()); -} - -// Tests that idleness observers receive the correct notification upon -// connection. -TEST_F(UserActivityMonitorTest, UserIdleObserverConnectNotification) { - UserIdleObserver::IdleState idle_state; - - // If an observer is added without any user activity, then it still receives - // an ACTIVE notification immediately. - TestUserIdleObserver first_observer; - monitor()->AddUserIdleObserver(1, first_observer.GetPtr()); - RunUntilIdle(); - EXPECT_TRUE(first_observer.GetAndResetIdleState(&idle_state)); - EXPECT_EQ(UserIdleObserver::IdleState::ACTIVE, idle_state); - - // If an observer is added without any user activity and the system has been - // idle, then the observer receives an IDLE notification immediately. - RunTasksForNext(base::TimeDelta::FromMinutes(5)); - TestUserIdleObserver second_observer; - monitor()->AddUserIdleObserver(4, second_observer.GetPtr()); - RunUntilIdle(); - EXPECT_TRUE(second_observer.GetAndResetIdleState(&idle_state)); - EXPECT_EQ(UserIdleObserver::IdleState::IDLE, idle_state); - EXPECT_TRUE(first_observer.GetAndResetIdleState(&idle_state)); - EXPECT_EQ(UserIdleObserver::IdleState::IDLE, idle_state); - - // If an observer is added after some user activity, then it receives an - // immediate ACTIVE notification. - monitor()->OnUserActivity(); - TestUserIdleObserver third_observer; - monitor()->AddUserIdleObserver(1, third_observer.GetPtr()); - RunUntilIdle(); - EXPECT_TRUE(third_observer.GetAndResetIdleState(&idle_state)); - EXPECT_EQ(UserIdleObserver::IdleState::ACTIVE, idle_state); - EXPECT_TRUE(second_observer.GetAndResetIdleState(&idle_state)); - EXPECT_EQ(UserIdleObserver::IdleState::ACTIVE, idle_state); - EXPECT_TRUE(first_observer.GetAndResetIdleState(&idle_state)); - EXPECT_EQ(UserIdleObserver::IdleState::ACTIVE, idle_state); - - RunTasksForNext(base::TimeDelta::FromMinutes(10)); - TestUserIdleObserver fourth_observer; - monitor()->AddUserIdleObserver(1, fourth_observer.GetPtr()); - RunUntilIdle(); - EXPECT_TRUE(fourth_observer.GetAndResetIdleState(&idle_state)); - EXPECT_EQ(UserIdleObserver::IdleState::IDLE, idle_state); - EXPECT_TRUE(third_observer.GetAndResetIdleState(&idle_state)); - EXPECT_EQ(UserIdleObserver::IdleState::IDLE, idle_state); - EXPECT_TRUE(second_observer.GetAndResetIdleState(&idle_state)); - EXPECT_EQ(UserIdleObserver::IdleState::IDLE, idle_state); - EXPECT_TRUE(first_observer.GetAndResetIdleState(&idle_state)); - EXPECT_EQ(UserIdleObserver::IdleState::IDLE, idle_state); - - // All observers are idle. These should not receive any IDLE notifications as - // more time passes by. - RunTasksForNext(base::TimeDelta::FromMinutes(100)); - RunUntilIdle(); - EXPECT_FALSE(first_observer.GetAndResetIdleState(&idle_state)); - EXPECT_FALSE(second_observer.GetAndResetIdleState(&idle_state)); - EXPECT_FALSE(third_observer.GetAndResetIdleState(&idle_state)); - EXPECT_FALSE(fourth_observer.GetAndResetIdleState(&idle_state)); - - // Some activity would notify ACTIVE to all observers. - monitor()->OnUserActivity(); - RunUntilIdle(); - EXPECT_TRUE(fourth_observer.GetAndResetIdleState(&idle_state)); - EXPECT_EQ(UserIdleObserver::IdleState::ACTIVE, idle_state); - EXPECT_TRUE(third_observer.GetAndResetIdleState(&idle_state)); - EXPECT_EQ(UserIdleObserver::IdleState::ACTIVE, idle_state); - EXPECT_TRUE(second_observer.GetAndResetIdleState(&idle_state)); - EXPECT_EQ(UserIdleObserver::IdleState::ACTIVE, idle_state); - EXPECT_TRUE(first_observer.GetAndResetIdleState(&idle_state)); - EXPECT_EQ(UserIdleObserver::IdleState::ACTIVE, idle_state); - - // Yet more activity should not send any notifications. - monitor()->OnUserActivity(); - RunUntilIdle(); - EXPECT_FALSE(first_observer.GetAndResetIdleState(&idle_state)); - EXPECT_FALSE(second_observer.GetAndResetIdleState(&idle_state)); - EXPECT_FALSE(third_observer.GetAndResetIdleState(&idle_state)); - EXPECT_FALSE(fourth_observer.GetAndResetIdleState(&idle_state)); -} - -} // namespace test -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/user_display_manager.cc b/services/ui/ws/user_display_manager.cc deleted file mode 100644 index 1fb692d..0000000 --- a/services/ui/ws/user_display_manager.cc +++ /dev/null
@@ -1,121 +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 "services/ui/ws/user_display_manager.h" - -#include <utility> - -#include "services/ui/display/screen_manager.h" -#include "services/ui/ws/user_display_manager_delegate.h" -#include "ui/display/display.h" -#include "ui/display/screen_base.h" -#include "ui/display/types/display_constants.h" - -namespace ui { -namespace ws { - -UserDisplayManager::UserDisplayManager(UserDisplayManagerDelegate* delegate) - : delegate_(delegate), - got_valid_frame_decorations_(delegate->GetFrameDecorations(nullptr)) {} - -UserDisplayManager::~UserDisplayManager() {} - -void UserDisplayManager::DisableAutomaticNotification() { - DCHECK(notify_automatically_); - notify_automatically_ = false; -} - -void UserDisplayManager::CallOnDisplaysChanged() { - observers_.ForAllPtrs([this](mojom::ScreenProviderObserver* observer) { - CallOnDisplaysChanged(observer); - }); -} - -void UserDisplayManager::OnFrameDecorationValuesChanged() { - got_valid_frame_decorations_ = true; - CallOnDisplaysChangedIfNecessary(); -} - -void UserDisplayManager::AddDisplayManagerBinding( - mojo::InterfaceRequest<mojom::ScreenProvider> request) { - bindings_.AddBinding(this, std::move(request)); -} - -void UserDisplayManager::OnDisplayUpdated(const display::Display& display) { - CallOnDisplaysChangedIfNecessary(); -} - -void UserDisplayManager::OnDisplayDestroyed(int64_t display_id) { - CallOnDisplaysChangedIfNecessary(); -} - -void UserDisplayManager::OnPrimaryDisplayChanged(int64_t primary_display_id) { - CallOnDisplaysChangedIfNecessary(); -} - -void UserDisplayManager::AddObserver( - mojom::ScreenProviderObserverPtr observer) { - mojom::ScreenProviderObserver* observer_impl = observer.get(); - observers_.AddPtr(std::move(observer)); - OnObserverAdded(observer_impl); -} - -void UserDisplayManager::OnObserverAdded( - mojom::ScreenProviderObserver* observer) { - // Many clients key off the frame decorations to size widgets. Wait for frame - // decorations before notifying so that we don't have to worry about clients - // resizing appropriately. - if (!ShouldCallOnDisplaysChanged()) - return; - - CallOnDisplaysChanged(observer); -} - -mojom::WsDisplayPtr UserDisplayManager::ToWsDisplayPtr( - const display::Display& display) { - mojom::WsDisplayPtr ws_display = mojom::WsDisplay::New(); - ws_display->display = display; - delegate_->GetFrameDecorations(&ws_display->frame_decoration_values); - return ws_display; -} - -std::vector<mojom::WsDisplayPtr> UserDisplayManager::GetAllDisplays() { - const auto& displays = - display::ScreenManager::GetInstance()->GetScreen()->GetAllDisplays(); - - std::vector<mojom::WsDisplayPtr> ws_display; - ws_display.reserve(displays.size()); - - for (const auto& display : displays) - ws_display.push_back(ToWsDisplayPtr(display)); - - return ws_display; -} - -bool UserDisplayManager::ShouldCallOnDisplaysChanged() const { - return got_valid_frame_decorations_ && !display::ScreenManager::GetInstance() - ->GetScreen() - ->GetAllDisplays() - .empty(); -} - -void UserDisplayManager::CallOnDisplaysChangedIfNecessary() { - if (!notify_automatically_ || !ShouldCallOnDisplaysChanged()) - return; - - CallOnDisplaysChanged(); -} - -void UserDisplayManager::CallOnDisplaysChanged( - mojom::ScreenProviderObserver* observer) { - observer->OnDisplaysChanged(GetAllDisplays(), - display::ScreenManager::GetInstance() - ->GetScreen() - ->GetPrimaryDisplay() - .id(), - delegate_->GetInternalDisplayId()); -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/user_display_manager.h b/services/ui/ws/user_display_manager.h deleted file mode 100644 index e0205466..0000000 --- a/services/ui/ws/user_display_manager.h +++ /dev/null
@@ -1,94 +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. - -#ifndef SERVICES_UI_WS_USER_DISPLAY_MANAGER_H_ -#define SERVICES_UI_WS_USER_DISPLAY_MANAGER_H_ - -#include <vector> - -#include "base/macros.h" -#include "mojo/public/cpp/bindings/binding_set.h" -#include "mojo/public/cpp/bindings/interface_ptr_set.h" -#include "services/ui/public/interfaces/screen_provider.mojom.h" - -namespace display { -class Display; -} - -namespace ui { -namespace ws { - -class UserDisplayManagerDelegate; - -// Provides per user display state. -// TODO(sky): merge this with ui::ws::DisplayManager (and rename). -class UserDisplayManager : public mojom::ScreenProvider { - public: - UserDisplayManager(UserDisplayManagerDelegate* delegate); - ~UserDisplayManager() override; - - void DisableAutomaticNotification(); - - // Unconditionally calls OnDisplayChanged() on observers. - void CallOnDisplaysChanged(); - - // Called when the frame decorations for this user change. - void OnFrameDecorationValuesChanged(); - - void AddDisplayManagerBinding( - mojo::InterfaceRequest<mojom::ScreenProvider> request); - - // Called when something about the display (e.g. pixel-ratio, size) changes. - void OnDisplayUpdated(const display::Display& display); - - // Called when the display with |display_id| was removed. - void OnDisplayDestroyed(int64_t display_id); - - // Called when the primary display changes. - void OnPrimaryDisplayChanged(int64_t primary_display_id); - - // mojom::ScreenProvider: - void AddObserver(mojom::ScreenProviderObserverPtr observer) override; - - private: - // Called when a new observer is added. If frame decorations are available - // notifies the observer immediately. - void OnObserverAdded(mojom::ScreenProviderObserver* observer); - - // Fills in a WsDisplayPtr for |display|. - mojom::WsDisplayPtr ToWsDisplayPtr(const display::Display& display); - - std::vector<mojom::WsDisplayPtr> GetAllDisplays(); - - bool ShouldCallOnDisplaysChanged() const; - - // Calls OnDisplaysChanged() on all observers. - void CallOnDisplaysChangedIfNecessary(); - - // Calls OnDisplaysChanged() on |observer|. - void CallOnDisplaysChanged(mojom::ScreenProviderObserver* observer); - - UserDisplayManagerDelegate* delegate_; - - // Set to true the first time at least one Display has valid frame values. - bool got_valid_frame_decorations_; - - mojo::BindingSet<mojom::ScreenProvider> bindings_; - - // WARNING: only use these once |got_valid_frame_decorations_| is true. - mojo::InterfacePtrSet<mojom::ScreenProviderObserver> observers_; - - // If true DisplayManagerObservers are notified any time there is a display - // change. If false, observers are only notified when CallOnDisplaysChanged() - // is explicitly called. This value is true in automatic display creation and - // false when in manual mode. - bool notify_automatically_ = true; - - DISALLOW_COPY_AND_ASSIGN(UserDisplayManager); -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_USER_DISPLAY_MANAGER_H_
diff --git a/services/ui/ws/user_display_manager_delegate.h b/services/ui/ws/user_display_manager_delegate.h deleted file mode 100644 index 70bb641..0000000 --- a/services/ui/ws/user_display_manager_delegate.h +++ /dev/null
@@ -1,30 +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. - -#ifndef SERVICES_UI_WS_USER_DISPLAY_MANAGER_DELEGATE_H_ -#define SERVICES_UI_WS_USER_DISPLAY_MANAGER_DELEGATE_H_ - -#include <stdint.h> - -#include "services/ui/public/interfaces/window_tree_constants.mojom.h" - -namespace ui { -namespace ws { - -class UserDisplayManagerDelegate { - public: - // Gets the frame decorations. Returns true if the decorations have been set, - // false otherwise. |values| may be null. - virtual bool GetFrameDecorations(mojom::FrameDecorationValuesPtr* values) = 0; - - virtual int64_t GetInternalDisplayId() = 0; - - protected: - virtual ~UserDisplayManagerDelegate() {} -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_USER_DISPLAY_MANAGER_DELEGATE_H_
diff --git a/services/ui/ws/user_display_manager_unittest.cc b/services/ui/ws/user_display_manager_unittest.cc deleted file mode 100644 index b57f11dd..0000000 --- a/services/ui/ws/user_display_manager_unittest.cc +++ /dev/null
@@ -1,149 +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 "services/ui/ws/user_display_manager.h" - -#include <stdint.h> - -#include <string> - -#include "base/macros.h" -#include "base/strings/string_number_conversions.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "mojo/public/cpp/bindings/interface_request.h" -#include "services/ui/common/task_runner_test_base.h" -#include "services/ui/common/types.h" -#include "services/ui/common/util.h" -#include "services/ui/display/screen_manager.h" -#include "services/ui/ws/display_manager.h" -#include "services/ui/ws/ids.h" -#include "services/ui/ws/server_window.h" -#include "services/ui/ws/test_utils.h" -#include "services/ui/ws/window_manager_state.h" -#include "services/ui/ws/window_manager_window_tree_factory.h" -#include "services/ui/ws/window_server.h" -#include "services/ui/ws/window_server_delegate.h" -#include "services/ui/ws/window_tree.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/gfx/geometry/rect.h" - -namespace ui { -namespace ws { -namespace test { -namespace { - -mojom::FrameDecorationValuesPtr CreateDefaultFrameDecorationValues() { - return mojom::FrameDecorationValues::New(); -} - -} // namespace - -// ----------------------------------------------------------------------------- - -class UserDisplayManagerTest : public TaskRunnerTestBase { - public: - UserDisplayManagerTest() {} - ~UserDisplayManagerTest() override {} - - WindowServer* window_server() { return ws_test_helper_.window_server(); } - TestWindowServerDelegate* window_server_delegate() { - return ws_test_helper_.window_server_delegate(); - } - - TestScreenManager& screen_manager() { return screen_manager_; } - - private: - // testing::Test: - void SetUp() override { - TaskRunnerTestBase::SetUp(); - screen_manager_.Init(window_server()->display_manager()); - } - - WindowServerTestHelper ws_test_helper_; - TestScreenManager screen_manager_; - DISALLOW_COPY_AND_ASSIGN(UserDisplayManagerTest); -}; - -TEST_F(UserDisplayManagerTest, OnlyNotifyWhenFrameDecorationsSet) { - screen_manager().AddDisplay(); - - TestScreenProviderObserver screen_provider_observer; - DisplayManager* display_manager = window_server()->display_manager(); - AddWindowManager(window_server()); - UserDisplayManager* user_display_manager = - display_manager->GetUserDisplayManager(); - ASSERT_TRUE(user_display_manager); - user_display_manager->AddObserver(screen_provider_observer.GetPtr()); - RunUntilIdle(); - - // Observer should not have been notified yet. - EXPECT_EQ(std::string(), screen_provider_observer.GetAndClearObserverCalls()); - - // Set the frame decoration values, which should trigger sending immediately. - ASSERT_EQ(1u, display_manager->displays().size()); - window_server()->GetWindowManagerState()->SetFrameDecorationValues( - CreateDefaultFrameDecorationValues()); - RunUntilIdle(); - - EXPECT_EQ("OnDisplaysChanged 1 -1", - screen_provider_observer.GetAndClearObserverCalls()); -} - -TEST_F(UserDisplayManagerTest, AddObserverAfterFrameDecorationsSet) { - screen_manager().AddDisplay(); - - TestScreenProviderObserver screen_provider_observer; - DisplayManager* display_manager = window_server()->display_manager(); - AddWindowManager(window_server()); - UserDisplayManager* user_display_manager = - display_manager->GetUserDisplayManager(); - ASSERT_TRUE(user_display_manager); - ASSERT_EQ(1u, display_manager->displays().size()); - window_server()->GetWindowManagerState()->SetFrameDecorationValues( - CreateDefaultFrameDecorationValues()); - - user_display_manager->AddObserver(screen_provider_observer.GetPtr()); - RunUntilIdle(); - - EXPECT_EQ("OnDisplaysChanged 1 -1", - screen_provider_observer.GetAndClearObserverCalls()); -} - -TEST_F(UserDisplayManagerTest, AddRemoveDisplay) { - screen_manager().AddDisplay(); - - TestScreenProviderObserver screen_provider_observer; - DisplayManager* display_manager = window_server()->display_manager(); - AddWindowManager(window_server()); - UserDisplayManager* user_display_manager = - display_manager->GetUserDisplayManager(); - ASSERT_TRUE(user_display_manager); - ASSERT_EQ(1u, display_manager->displays().size()); - window_server()->GetWindowManagerState()->SetFrameDecorationValues( - CreateDefaultFrameDecorationValues()); - user_display_manager->AddObserver(screen_provider_observer.GetPtr()); - RunUntilIdle(); - - EXPECT_EQ("OnDisplaysChanged 1 -1", - screen_provider_observer.GetAndClearObserverCalls()); - - // Add another display. - const int64_t second_display_id = screen_manager().AddDisplay(); - RunUntilIdle(); - - // Observer should be notified immediately as frame decorations were set. - EXPECT_EQ("OnDisplaysChanged 1 2 -1", - screen_provider_observer.GetAndClearObserverCalls()); - - // Remove the display and verify observer is notified. - screen_manager().RemoveDisplay(second_display_id); - RunUntilIdle(); - - EXPECT_EQ("OnDisplaysChanged 1 -1", - screen_provider_observer.GetAndClearObserverCalls()); -} - -} // namespace test -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/video_detector_impl.cc b/services/ui/ws/video_detector_impl.cc deleted file mode 100644 index e74d2e1..0000000 --- a/services/ui/ws/video_detector_impl.cc +++ /dev/null
@@ -1,28 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "services/ui/ws/video_detector_impl.h" - -#include "components/viz/host/host_frame_sink_manager.h" - -namespace ui { -namespace ws { - -VideoDetectorImpl::VideoDetectorImpl( - viz::HostFrameSinkManager* host_frame_sink_manager) - : host_frame_sink_manager_(host_frame_sink_manager) {} - -VideoDetectorImpl::~VideoDetectorImpl() = default; - -void VideoDetectorImpl::AddBinding(mojom::VideoDetectorRequest request) { - binding_set_.AddBinding(this, std::move(request)); -} - -void VideoDetectorImpl::AddObserver( - viz::mojom::VideoDetectorObserverPtr observer) { - host_frame_sink_manager_->AddVideoDetectorObserver(std::move(observer)); -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/video_detector_impl.h b/services/ui/ws/video_detector_impl.h deleted file mode 100644 index 77170fd71..0000000 --- a/services/ui/ws/video_detector_impl.h +++ /dev/null
@@ -1,44 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SERVICES_UI_WS_VIDEO_DETECTOR_IMPL_H_ -#define SERVICES_UI_WS_VIDEO_DETECTOR_IMPL_H_ - -#include "mojo/public/cpp/bindings/binding_set.h" -#include "services/ui/public/interfaces/video_detector.mojom.h" -#include "services/viz/public/interfaces/compositing/video_detector_observer.mojom.h" - -namespace viz { -class HostFrameSinkManager; -} - -namespace ui { -namespace ws { - -// WS-side representation of viz::VideoDetector. Internally forwards observer -// requests to viz. -// TODO(crbug.com/780514): If we restart viz the observers won't receive -// notifications anymore. This needs to be fixed. -class VideoDetectorImpl : public mojom::VideoDetector { - public: - explicit VideoDetectorImpl( - viz::HostFrameSinkManager* host_frame_sink_manager); - ~VideoDetectorImpl() override; - - void AddBinding(mojom::VideoDetectorRequest request); - - // mojom::VideoDetector implementation. - void AddObserver(viz::mojom::VideoDetectorObserverPtr observer) override; - - private: - viz::HostFrameSinkManager* host_frame_sink_manager_; - mojo::BindingSet<mojom::VideoDetector> binding_set_; - - DISALLOW_COPY_AND_ASSIGN(VideoDetectorImpl); -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_VIDEO_DETECTOR_IMPL_H_
diff --git a/services/ui/ws/window_coordinate_conversions.cc b/services/ui/ws/window_coordinate_conversions.cc deleted file mode 100644 index 264b7c1..0000000 --- a/services/ui/ws/window_coordinate_conversions.cc +++ /dev/null
@@ -1,57 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "services/ui/ws/window_coordinate_conversions.h" - -#include "services/ui/ws/server_window.h" -#include "ui/gfx/geometry/point.h" -#include "ui/gfx/geometry/point3_f.h" -#include "ui/gfx/geometry/point_f.h" -#include "ui/gfx/transform.h" - -namespace ui { -namespace ws { -namespace { - -gfx::Transform GetTransformToRoot(const ServerWindow* root, - const ServerWindow* window) { - gfx::Transform transform; - const ServerWindow* w = window; - for (; w && w != root; w = w->parent()) { - gfx::Transform translation; - translation.Translate(static_cast<float>(w->bounds().x()), - static_cast<float>(w->bounds().y())); - if (!w->transform().IsIdentity()) - transform.ConcatTransform(w->transform()); - transform.ConcatTransform(translation); - } - // Allow the root to also have a transform. This mirrors how - // WindowManagerDisplayRoot works. Ash sets the transform for rotation as well - // as ui scale. - if (w == root && !w->transform().IsIdentity()) - transform.ConcatTransform(w->transform()); - return transform; -} - -} // namespace - -gfx::Point ConvertPointFromRootForEventDispatch( - const ServerWindow* root, - const ServerWindow* window, - const gfx::Point& location_in_root) { - // This code should only be called when |window| is connected to a display. - DCHECK(root); - - if (root == window) - return location_in_root; - - const gfx::Transform transform = GetTransformToRoot(root, window); - gfx::Point3F location_in_root3(gfx::PointF{location_in_root}); - transform.TransformPointReverse(&location_in_root3); - - return gfx::ToFlooredPoint(location_in_root3.AsPointF()); -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/window_coordinate_conversions.h b/services/ui/ws/window_coordinate_conversions.h deleted file mode 100644 index f871bb6..0000000 --- a/services/ui/ws/window_coordinate_conversions.h +++ /dev/null
@@ -1,25 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SERVICES_UI_WS_WINDOW_COORDINATE_CONVERSIONS_H_ -#define SERVICES_UI_WS_WINDOW_COORDINATE_CONVERSIONS_H_ - -namespace gfx { -class Point; -} - -namespace ui { -namespace ws { - -class ServerWindow; - -// Converts |point|, in the coordinates of the root, to that of |window|. -gfx::Point ConvertPointFromRootForEventDispatch(const ServerWindow* root, - const ServerWindow* window, - const gfx::Point& point); - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_WINDOW_COORDINATE_CONVERSIONS_H_
diff --git a/services/ui/ws/window_coordinate_conversions_unittest.cc b/services/ui/ws/window_coordinate_conversions_unittest.cc deleted file mode 100644 index 5e25ec80..0000000 --- a/services/ui/ws/window_coordinate_conversions_unittest.cc +++ /dev/null
@@ -1,59 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "services/ui/ws/window_coordinate_conversions.h" - -#include "services/ui/ws/server_window.h" -#include "services/ui/ws/test_server_window_delegate.h" -#include "services/ui/ws/test_utils.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace ui { -namespace ws { - -class WindowCoordinateConversions : public testing::Test { - public: - WindowCoordinateConversions() {} - ~WindowCoordinateConversions() override {} - - VizHostProxy* viz_host_proxy() { - return ws_test_helper_.window_server()->GetVizHostProxy(); - } - - private: - test::WindowServerTestHelper ws_test_helper_; - - DISALLOW_COPY_AND_ASSIGN(WindowCoordinateConversions); -}; - -TEST_F(WindowCoordinateConversions, Transform) { - TestServerWindowDelegate window_delegate(viz_host_proxy()); - ServerWindow root(&window_delegate, viz::FrameSinkId(1, 2)); - root.set_event_targeting_policy( - mojom::EventTargetingPolicy::DESCENDANTS_ONLY); - root.SetVisible(true); - root.SetBounds(gfx::Rect(0, 0, 100, 100), base::nullopt); - ServerWindow child(&window_delegate, viz::FrameSinkId(1, 3)); - root.Add(&child); - child.SetVisible(true); - child.SetBounds(gfx::Rect(0, 0, 20, 20), base::nullopt); - // Make the root |child|, and set a transform on |child|, which mirrors - // how WindowManagerState and EventDispatcher work together. - window_delegate.set_root_window(&child); - gfx::Transform transform; - transform.Scale(SkIntToMScalar(2), SkIntToMScalar(2)); - child.SetTransform(transform); - - ServerWindow child_child(&window_delegate, viz::FrameSinkId(1, 4)); - child.Add(&child_child); - child_child.SetVisible(true); - child_child.SetBounds(gfx::Rect(4, 6, 12, 24), base::nullopt); - - const gfx::Point converted_point = ConvertPointFromRootForEventDispatch( - &child, &child_child, gfx::Point(14, 20)); - EXPECT_EQ(gfx::Point(3, 4), converted_point); -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/window_finder.cc b/services/ui/ws/window_finder.cc deleted file mode 100644 index 1f99e99..0000000 --- a/services/ui/ws/window_finder.cc +++ /dev/null
@@ -1,180 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "services/ui/ws/window_finder.h" - -#include "base/containers/adapters.h" -#include "services/ui/ws/server_window.h" -#include "ui/gfx/geometry/point.h" -#include "ui/gfx/geometry/point3_f.h" -#include "ui/gfx/geometry/point_f.h" -#include "ui/gfx/transform.h" - -namespace ui { -namespace ws { -namespace { - -bool IsLocationInNonclientArea(const ServerWindow* target, - const gfx::Point& location) { - if (!target->parent() || target->bounds().size().IsEmpty()) - return false; - - gfx::Rect client_area(target->bounds().size()); - client_area.Inset(target->client_area()); - if (client_area.Contains(location)) - return false; - - for (const auto& rect : target->additional_client_areas()) { - if (rect.Contains(location)) - return false; - } - - return true; -} - -bool ShouldUseExtendedHitRegion(const ServerWindow* window) { - if (!window->parent()) - return false; - - const mojom::ShowState show_state = window->GetShowState(); - if (show_state == mojom::ShowState::MAXIMIZED || - show_state == mojom::ShowState::FULLSCREEN) { - return false; - } - // This matches the logic of EasyResizeWindowTargeter. - return !window->transient_parent() || - window->transient_parent() == window->parent(); -} - -// Returns true if |location_in_window| is in the extended hit region and not -// in the normal bounds of |window|. -bool IsLocationInExtendedHitRegion(EventSource event_source, - const ServerWindow* window, - const gfx::Point& location_in_window) { - if (!ShouldUseExtendedHitRegion(window)) - return false; - - const gfx::Insets& extended_hit_insets = - event_source == EventSource::MOUSE - ? window->parent()->extended_mouse_hit_test_region() - : window->parent()->extended_touch_hit_test_region(); - if (extended_hit_insets.IsEmpty()) - return false; - - gfx::Rect child_bounds(window->bounds().size()); - if (child_bounds.Contains(location_in_window)) - return false; - - child_bounds.Inset(extended_hit_insets); - return child_bounds.Contains(location_in_window); -} - -gfx::Transform TransformFromParent(const ServerWindow* window, - const gfx::Transform& current_transform) { - gfx::Transform result = current_transform; - if (window->bounds().origin() != gfx::Point()) { - gfx::Transform translation; - translation.Translate(static_cast<float>(window->bounds().x()), - static_cast<float>(window->bounds().y())); - result.PreconcatTransform(translation); - } - if (!window->transform().IsIdentity()) - result.PreconcatTransform(window->transform()); - return result; -} - -bool FindDeepestVisibleWindowForLocationImpl( - ServerWindow* window, - bool is_root_window, - EventSource event_source, - const gfx::Point& location_in_root, - const gfx::Point& location_in_window, - const gfx::Transform& transform_from_parent, - DeepestWindow* deepest_window) { - // The non-client area takes precedence over descendants, as otherwise the - // user would likely not be able to hit the non-client area as it's common - // for descendants to go into the non-client area. - // - // Display roots aren't allowed to have non-client areas. This is important - // as roots may have a transform, which causes problem in comparing sizes. - if (!is_root_window && - IsLocationInNonclientArea(window, location_in_window)) { - deepest_window->window = window; - deepest_window->in_non_client_area = true; - return true; - } - const mojom::EventTargetingPolicy event_targeting_policy = - window->event_targeting_policy(); - - if (event_targeting_policy == ui::mojom::EventTargetingPolicy::NONE) - return false; - - if (event_targeting_policy == - mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS || - event_targeting_policy == mojom::EventTargetingPolicy::DESCENDANTS_ONLY) { - const ServerWindow::Windows& children = window->children(); - for (ServerWindow* child : base::Reversed(children)) { - if (!child->visible()) - continue; - - const gfx::Transform child_transform = - TransformFromParent(child, transform_from_parent); - gfx::Point3F location_in_child3(gfx::PointF{location_in_root}); - child_transform.TransformPointReverse(&location_in_child3); - const gfx::Point location_in_child = - gfx::ToFlooredPoint(location_in_child3.AsPointF()); - if (IsLocationInExtendedHitRegion(event_source, child, - location_in_child)) { - deepest_window->window = child; - deepest_window->in_non_client_area = true; - return true; - } - gfx::Rect child_bounds(child->bounds().size()); - if (!child_bounds.Contains(location_in_child) || - (child->hit_test_mask() && - !child->hit_test_mask()->Contains(location_in_child))) { - continue; - } - - const bool child_is_root = false; - if (FindDeepestVisibleWindowForLocationImpl( - child, child_is_root, event_source, location_in_root, - location_in_child, child_transform, deepest_window)) { - return true; - } - } - } - - if (event_targeting_policy == mojom::EventTargetingPolicy::DESCENDANTS_ONLY) - return false; - - deepest_window->window = window; - deepest_window->in_non_client_area = false; - return true; -} - -} // namespace - -DeepestWindow FindDeepestVisibleWindowForLocation(ServerWindow* root_window, - EventSource event_source, - const gfx::Point& location) { - gfx::Point initial_location = location; - gfx::Transform root_transform = root_window->transform(); - if (!root_transform.IsIdentity()) { - gfx::Point3F transformed_location(gfx::PointF{initial_location}); - root_transform.TransformPointReverse(&transformed_location); - initial_location = gfx::ToFlooredPoint(transformed_location.AsPointF()); - } - DeepestWindow result; - // Allow the root to have a transform, which mirrors what happens with - // WindowManagerDisplayRoot. - const bool is_root_window = true; - FindDeepestVisibleWindowForLocationImpl( - root_window, is_root_window, event_source, location, initial_location, - root_transform, &result); - return result; -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/window_finder.h b/services/ui/ws/window_finder.h deleted file mode 100644 index 5a461d22..0000000 --- a/services/ui/ws/window_finder.h +++ /dev/null
@@ -1,37 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SERVICES_UI_WS_WINDOW_FINDER_H_ -#define SERVICES_UI_WS_WINDOW_FINDER_H_ - -#include "components/viz/host/hit_test/hit_test_query.h" - -namespace gfx { -class Point; -} - -namespace ui { -namespace ws { - -class ServerWindow; - -struct DeepestWindow { - ServerWindow* window = nullptr; - bool in_non_client_area = false; -}; - -using EventSource = viz::EventSource; - -// Finds the deepest visible child of |root| that should receive an event at -// |location|. |location| is in the coordinate space of |root_window|. The -// |window| field in the returned structure is set to the child window. If no -// valid child window is found |window| is set to null. -DeepestWindow FindDeepestVisibleWindowForLocation(ServerWindow* root_window, - EventSource event_source, - const gfx::Point& location); - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_WINDOW_FINDER_H_
diff --git a/services/ui/ws/window_finder_unittest.cc b/services/ui/ws/window_finder_unittest.cc deleted file mode 100644 index f6a28af..0000000 --- a/services/ui/ws/window_finder_unittest.cc +++ /dev/null
@@ -1,319 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "services/ui/ws/window_finder.h" - -#include "services/ui/ws/server_window.h" -#include "services/ui/ws/test_server_window_delegate.h" -#include "services/ui/ws/test_utils.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace ui { -namespace ws { - -class WindowFinderTest : public testing::Test { - public: - WindowFinderTest() {} - ~WindowFinderTest() override {} - - VizHostProxy* viz_host_proxy() { - return ws_test_helper_.window_server()->GetVizHostProxy(); - } - - private: - test::WindowServerTestHelper ws_test_helper_; - - DISALLOW_COPY_AND_ASSIGN(WindowFinderTest); -}; - -TEST_F(WindowFinderTest, FindDeepestVisibleWindow) { - TestServerWindowDelegate window_delegate(viz_host_proxy()); - ServerWindow root(&window_delegate, viz::FrameSinkId(1, 2)); - root.set_event_targeting_policy( - mojom::EventTargetingPolicy::DESCENDANTS_ONLY); - window_delegate.set_root_window(&root); - root.SetVisible(true); - root.SetBounds(gfx::Rect(0, 0, 100, 100), base::nullopt); - - ServerWindow child1(&window_delegate, viz::FrameSinkId(1, 3)); - root.Add(&child1); - child1.SetVisible(true); - child1.SetBounds(gfx::Rect(10, 10, 20, 20), base::nullopt); - - ServerWindow child2(&window_delegate, viz::FrameSinkId(1, 4)); - root.Add(&child2); - child2.SetVisible(true); - child2.SetBounds(gfx::Rect(15, 15, 20, 20), base::nullopt); - - EXPECT_EQ(&child2, FindDeepestVisibleWindowForLocation( - &root, EventSource::MOUSE, gfx::Point(16, 16)) - .window); - - EXPECT_EQ(&child1, FindDeepestVisibleWindowForLocation( - &root, EventSource::MOUSE, gfx::Point(13, 14)) - .window); - - child1.set_event_targeting_policy(mojom::EventTargetingPolicy::NONE); - EXPECT_EQ(nullptr, FindDeepestVisibleWindowForLocation( - &root, EventSource::MOUSE, gfx::Point(13, 14)) - .window); - - root.set_extended_hit_test_regions_for_children(gfx::Insets(-1, -1, -1, -1), - gfx::Insets(-2, -2, -2, -2)); - EXPECT_EQ(&child2, FindDeepestVisibleWindowForLocation( - &root, EventSource::MOUSE, gfx::Point(14, 14)) - .window); - EXPECT_EQ(nullptr, FindDeepestVisibleWindowForLocation( - &root, EventSource::MOUSE, gfx::Point(13, 13)) - .window); - EXPECT_EQ(&child2, FindDeepestVisibleWindowForLocation( - &root, EventSource::TOUCH, gfx::Point(13, 13)) - .window); -} - -TEST_F(WindowFinderTest, FindDeepestVisibleWindowNonClientArea) { - TestServerWindowDelegate window_delegate(viz_host_proxy()); - ServerWindow root(&window_delegate, viz::FrameSinkId(1, 2)); - window_delegate.set_root_window(&root); - root.SetVisible(true); - root.SetBounds(gfx::Rect(0, 0, 100, 100), base::nullopt); - - ServerWindow child1(&window_delegate, viz::FrameSinkId(1, 3)); - root.Add(&child1); - child1.SetVisible(true); - child1.SetBounds(gfx::Rect(10, 10, 20, 20), base::nullopt); - - DeepestWindow result = FindDeepestVisibleWindowForLocation( - &root, EventSource::MOUSE, gfx::Point(13, 14)); - EXPECT_EQ(&child1, result.window); - EXPECT_FALSE(result.in_non_client_area); - - result = FindDeepestVisibleWindowForLocation(&root, EventSource::MOUSE, - gfx::Point(11, 11)); - EXPECT_EQ(&child1, result.window); - EXPECT_FALSE(result.in_non_client_area); - - // 11, 11 is over the non-client area. - child1.SetClientArea(gfx::Insets(2, 3, 4, 5), std::vector<gfx::Rect>()); - result = FindDeepestVisibleWindowForLocation(&root, EventSource::MOUSE, - gfx::Point(11, 11)); - EXPECT_EQ(&child1, result.window); - EXPECT_TRUE(result.in_non_client_area); - - // 15, 15 is over the client area. - result = FindDeepestVisibleWindowForLocation(&root, EventSource::MOUSE, - gfx::Point(15, 15)); - EXPECT_EQ(&child1, result.window); - EXPECT_FALSE(result.in_non_client_area); - - // EventTargetingPolicy::NONE should not impact the result for the - // non-client area. - child1.set_event_targeting_policy(mojom::EventTargetingPolicy::NONE); - result = FindDeepestVisibleWindowForLocation(&root, EventSource::MOUSE, - gfx::Point(11, 11)); - child1.SetClientArea(gfx::Insets(2, 3, 4, 5), std::vector<gfx::Rect>()); - EXPECT_EQ(&child1, result.window); - EXPECT_TRUE(result.in_non_client_area); - - // EventTargetingPolicy::NONE means the client area won't be matched though. - result = FindDeepestVisibleWindowForLocation(&root, EventSource::MOUSE, - gfx::Point(15, 15)); - EXPECT_EQ(&root, result.window); - EXPECT_FALSE(result.in_non_client_area); -} - -TEST_F(WindowFinderTest, FindDeepestVisibleWindowHitTestMask) { - TestServerWindowDelegate window_delegate(viz_host_proxy()); - ServerWindow root(&window_delegate, viz::FrameSinkId(1, 2)); - window_delegate.set_root_window(&root); - root.SetVisible(true); - root.SetBounds(gfx::Rect(0, 0, 100, 100), base::nullopt); - - ServerWindow child_with_mask(&window_delegate, viz::FrameSinkId(1, 4)); - root.Add(&child_with_mask); - child_with_mask.SetVisible(true); - child_with_mask.SetBounds(gfx::Rect(10, 10, 20, 20), base::nullopt); - child_with_mask.SetHitTestMask(gfx::Rect(2, 2, 16, 16)); - - // Test a point inside the window but outside the mask. - EXPECT_EQ(&root, FindDeepestVisibleWindowForLocation( - &root, EventSource::MOUSE, gfx::Point(11, 11)) - .window); - - // Test a point inside the window and inside the mask. - EXPECT_EQ(&child_with_mask, FindDeepestVisibleWindowForLocation( - &root, EventSource::MOUSE, gfx::Point(15, 15)) - .window); -} - -TEST_F(WindowFinderTest, FindDeepestVisibleWindowOverNonTarget) { - TestServerWindowDelegate window_delegate(viz_host_proxy()); - ServerWindow root(&window_delegate, viz::FrameSinkId(1, 2)); - window_delegate.set_root_window(&root); - root.SetVisible(true); - root.SetBounds(gfx::Rect(0, 0, 100, 100), base::nullopt); - - // Create two windows, |child1| and |child2|. The two overlap but |child2| is - // not a valid event target. - ServerWindow child1(&window_delegate, viz::FrameSinkId(1, 3)); - root.Add(&child1); - child1.SetVisible(true); - child1.SetBounds(gfx::Rect(10, 10, 20, 20), base::nullopt); - - ServerWindow child2(&window_delegate, viz::FrameSinkId(1, 4)); - root.Add(&child2); - child2.set_event_targeting_policy(mojom::EventTargetingPolicy::NONE); - child2.SetVisible(true); - child2.SetBounds(gfx::Rect(15, 15, 20, 20), base::nullopt); - - // 16, 16 is over |child2| and |child1|, but as |child2| isn't a valid event - // target |child1| should be picked. - EXPECT_EQ(&child1, FindDeepestVisibleWindowForLocation( - &root, EventSource::MOUSE, gfx::Point(16, 16)) - .window); -} - -TEST_F(WindowFinderTest, NonClientPreferredOverChild) { - TestServerWindowDelegate window_delegate(viz_host_proxy()); - ServerWindow root(&window_delegate, viz::FrameSinkId(1, 2)); - window_delegate.set_root_window(&root); - root.SetVisible(true); - root.SetBounds(gfx::Rect(0, 0, 100, 100), base::nullopt); - - // Create two windows, |child| and |child_child|; |child| is a child of the - // root and |child_child| and child of |child|. All share the same size with - // |child| having a non-client area. - ServerWindow child(&window_delegate, viz::FrameSinkId(1, 3)); - root.Add(&child); - child.SetVisible(true); - child.SetBounds(gfx::Rect(0, 0, 100, 100), base::nullopt); - child.SetClientArea(gfx::Insets(2, 3, 4, 5), std::vector<gfx::Rect>()); - - ServerWindow child_child(&window_delegate, viz::FrameSinkId(1, 4)); - child.Add(&child_child); - child_child.SetVisible(true); - child_child.SetBounds(gfx::Rect(0, 0, 100, 100), base::nullopt); - - // |child| was should be returned as the event is over the non-client area. - EXPECT_EQ(&child, FindDeepestVisibleWindowForLocation( - &root, EventSource::MOUSE, gfx::Point(1, 1)) - .window); -} - -TEST_F(WindowFinderTest, FindDeepestVisibleWindowWithTransform) { - TestServerWindowDelegate window_delegate(viz_host_proxy()); - ServerWindow root(&window_delegate, viz::FrameSinkId(1, 2)); - root.set_event_targeting_policy( - mojom::EventTargetingPolicy::DESCENDANTS_ONLY); - window_delegate.set_root_window(&root); - root.SetVisible(true); - root.SetBounds(gfx::Rect(0, 0, 100, 100), base::nullopt); - ServerWindow child(&window_delegate, viz::FrameSinkId(1, 3)); - root.Add(&child); - child.SetVisible(true); - child.SetBounds(gfx::Rect(10, 10, 20, 20), base::nullopt); - gfx::Transform transform; - transform.Scale(SkIntToMScalar(2), SkIntToMScalar(2)); - child.SetTransform(transform); - - EXPECT_EQ(&child, FindDeepestVisibleWindowForLocation( - &root, EventSource::MOUSE, gfx::Point(49, 49)) - .window); - EXPECT_EQ(nullptr, FindDeepestVisibleWindowForLocation( - &root, EventSource::MOUSE, gfx::Point(9, 9)) - .window); - - ServerWindow child_child(&window_delegate, viz::FrameSinkId(1, 4)); - child.Add(&child_child); - child_child.SetVisible(true); - child_child.SetBounds(gfx::Rect(12, 12, 4, 4), base::nullopt); - - EXPECT_EQ(&child, FindDeepestVisibleWindowForLocation( - &root, EventSource::MOUSE, gfx::Point(30, 30)) - .window); - EXPECT_EQ(&child_child, FindDeepestVisibleWindowForLocation( - &root, EventSource::MOUSE, gfx::Point(35, 35)) - .window); - - // Verify extended hit test with transform is picked up. - root.set_extended_hit_test_regions_for_children(gfx::Insets(-2, -2, -2, -2), - gfx::Insets(-2, -2, -2, -2)); - EXPECT_EQ(&child, FindDeepestVisibleWindowForLocation( - &root, EventSource::MOUSE, gfx::Point(7, 7)) - .window); - EXPECT_EQ(nullptr, FindDeepestVisibleWindowForLocation( - &root, EventSource::MOUSE, gfx::Point(4, 4)) - .window); -} - -TEST_F(WindowFinderTest, FindDeepestVisibleWindowWithTransformOnParent) { - TestServerWindowDelegate window_delegate(viz_host_proxy()); - ServerWindow root(&window_delegate, viz::FrameSinkId(1, 2)); - root.set_event_targeting_policy( - mojom::EventTargetingPolicy::DESCENDANTS_ONLY); - root.SetVisible(true); - root.SetBounds(gfx::Rect(0, 0, 100, 100), base::nullopt); - ServerWindow child(&window_delegate, viz::FrameSinkId(1, 3)); - root.Add(&child); - child.SetVisible(true); - child.SetBounds(gfx::Rect(10, 10, 10, 10), base::nullopt); - // Make the root child, but the transform is set on the parent. This mirrors - // how WindowManagerState and EventDispatcher work together. - window_delegate.set_root_window(&child); - gfx::Transform transform; - transform.Scale(SkIntToMScalar(2), SkIntToMScalar(2)); - root.SetTransform(transform); - - EXPECT_EQ(&child, FindDeepestVisibleWindowForLocation( - &root, EventSource::MOUSE, gfx::Point(25, 25)) - .window); - EXPECT_EQ(nullptr, FindDeepestVisibleWindowForLocation( - &root, EventSource::MOUSE, gfx::Point(52, 52)) - .window); -} - -// Creates the following window hierarchy: -// root -// |- c1 (has .5x transform, and is used as the root in -// FindDeepestVisibleWindowForLocation). -// |- c2 -// |- c3 -// With various assertions around hit testing. -TEST_F(WindowFinderTest, - FindDeepestVisibleWindowWithTransformOnParentMagnified) { - TestServerWindowDelegate window_delegate(viz_host_proxy()); - ServerWindow root(&window_delegate, viz::FrameSinkId(1, 2)); - root.set_event_targeting_policy( - mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS); - root.SetVisible(true); - root.SetBounds(gfx::Rect(0, 0, 100, 100), base::nullopt); - window_delegate.set_root_window(&root); - ServerWindow c1(&window_delegate, viz::FrameSinkId(1, 3)); - root.Add(&c1); - c1.SetVisible(true); - c1.SetBounds(gfx::Rect(0, 0, 100, 100), base::nullopt); - gfx::Transform transform; - transform.Scale(SkFloatToMScalar(.5f), SkFloatToMScalar(.5f)); - c1.SetTransform(transform); - - ServerWindow c2(&window_delegate, viz::FrameSinkId(1, 4)); - c1.Add(&c2); - c2.SetVisible(true); - c2.SetBounds(gfx::Rect(0, 0, 200, 200), base::nullopt); - - ServerWindow c3(&window_delegate, viz::FrameSinkId(1, 5)); - c2.Add(&c3); - c3.SetVisible(true); - c3.SetBounds(gfx::Rect(0, 190, 200, 10), base::nullopt); - - EXPECT_EQ(&c2, FindDeepestVisibleWindowForLocation(&c1, EventSource::MOUSE, - gfx::Point(55, 55)) - .window); - EXPECT_EQ(&c3, FindDeepestVisibleWindowForLocation(&c1, EventSource::MOUSE, - gfx::Point(0, 99)) - .window); -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/window_manager_access_policy.cc b/services/ui/ws/window_manager_access_policy.cc deleted file mode 100644 index fe53b8e..0000000 --- a/services/ui/ws/window_manager_access_policy.cc +++ /dev/null
@@ -1,238 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "services/ui/ws/window_manager_access_policy.h" - -#include "services/ui/ws/access_policy_delegate.h" -#include "services/ui/ws/server_window.h" - -namespace ui { -namespace ws { - -WindowManagerAccessPolicy::WindowManagerAccessPolicy() {} - -WindowManagerAccessPolicy::~WindowManagerAccessPolicy() {} - -void WindowManagerAccessPolicy::Init(ClientSpecificId client_id, - AccessPolicyDelegate* delegate) { - client_id_ = client_id; - delegate_ = delegate; -} - -bool WindowManagerAccessPolicy::CanRemoveWindowFromParent( - const ServerWindow* window) const { - return true; -} - -bool WindowManagerAccessPolicy::CanAddWindow(const ServerWindow* parent, - const ServerWindow* child) const { - return true; -} - -bool WindowManagerAccessPolicy::CanAddTransientWindow( - const ServerWindow* parent, - const ServerWindow* child) const { - return true; -} - -bool WindowManagerAccessPolicy::CanRemoveTransientWindowFromParent( - const ServerWindow* window) const { - return true; -} - -bool WindowManagerAccessPolicy::CanSetModal( - const ServerWindow* window) const { - return true; -} - -bool WindowManagerAccessPolicy::CanSetChildModalParent( - const ServerWindow* window, - const ServerWindow* modal_parent) const { - return true; -} - -bool WindowManagerAccessPolicy::CanReorderWindow( - const ServerWindow* window, - const ServerWindow* relative_window, - mojom::OrderDirection direction) const { - return true; -} - -bool WindowManagerAccessPolicy::CanDeleteWindow( - const ServerWindow* window) const { - return WasCreatedByThisClient(window); -} - -bool WindowManagerAccessPolicy::CanGetWindowTree( - const ServerWindow* window) const { - return true; -} - -bool WindowManagerAccessPolicy::CanDescendIntoWindowForWindowTree( - const ServerWindow* window) const { - return true; -} - -bool WindowManagerAccessPolicy::CanEmbed(const ServerWindow* window) const { - return !delegate_->HasRootForAccessPolicy(window); -} - -bool WindowManagerAccessPolicy::CanChangeWindowVisibility( - const ServerWindow* window) const { - if (WasCreatedByThisClient(window)) - return true; - // The WindowManager can change the visibility of the WindowManager root. - const ServerWindow* root = window->GetRootForDrawn(); - return root && window->parent() == root; -} - -bool WindowManagerAccessPolicy::CanChangeWindowOpacity( - const ServerWindow* window) const { - return WasCreatedByThisClient(window); -} - -bool WindowManagerAccessPolicy::CanSetWindowCompositorFrameSink( - const ServerWindow* window) const { - if (delegate_->IsWindowRootOfAnotherTreeForAccessPolicy(window)) - return false; - - return WasCreatedByThisClient(window) || - (delegate_->HasRootForAccessPolicy(window)); -} - -bool WindowManagerAccessPolicy::CanSetWindowBounds( - const ServerWindow* window) const { - return WasCreatedByThisClient(window); -} - -bool WindowManagerAccessPolicy::CanSetWindowTransform( - const ServerWindow* window) const { - return WasCreatedByThisClient(window); -} - -bool WindowManagerAccessPolicy::CanSetWindowProperties( - const ServerWindow* window) const { - return WasCreatedByThisClient(window); -} - -bool WindowManagerAccessPolicy::CanSetWindowTextInputState( - const ServerWindow* window) const { - return WasCreatedByThisClient(window); -} - -bool WindowManagerAccessPolicy::CanSetCapture( - const ServerWindow* window) const { - return WasCreatedByThisClient(window); -} - -bool WindowManagerAccessPolicy::CanSetFocus(const ServerWindow* window) const { - return true; -} - -bool WindowManagerAccessPolicy::CanSetClientArea( - const ServerWindow* window) const { - return WasCreatedByThisClient(window) || - delegate_->HasRootForAccessPolicy(window); -} - -bool WindowManagerAccessPolicy::CanSetHitTestMask( - const ServerWindow* window) const { - return WasCreatedByThisClient(window) || - delegate_->HasRootForAccessPolicy(window); -} - -bool WindowManagerAccessPolicy::CanSetAcceptDrops( - const ServerWindow* window) const { - return true; -} - -bool WindowManagerAccessPolicy::CanSetEventTargetingPolicy( - const ServerWindow* window) const { - return WasCreatedByThisClient(window) || - delegate_->HasRootForAccessPolicy(window); -} - -bool WindowManagerAccessPolicy::CanStackAbove( - const ServerWindow* above, - const ServerWindow* below) const { - // This API is for clients. Window managers can perform any arbitrary - // reordering of the windows and don't need to go through this constrained - // API. - return false; -} - -bool WindowManagerAccessPolicy::CanStackAtTop( - const ServerWindow* window) const { - // This API is for clients. Window managers can perform any arbitrary - // reordering of the windows and don't need to go through this constrained - // API. - return false; -} - -bool WindowManagerAccessPolicy::CanPerformWmAction( - const ServerWindow* window) const { - // This API is for clients. Window managers don't need to tell themselves to - // do things. - return false; -} - -bool WindowManagerAccessPolicy::CanSetCursorProperties( - const ServerWindow* window) const { - return WasCreatedByThisClient(window) || - delegate_->HasRootForAccessPolicy(window); -} - -bool WindowManagerAccessPolicy::CanInitiateDragLoop( - const ServerWindow* window) const { - return WasCreatedByThisClient(window) || - delegate_->HasRootForAccessPolicy(window); -} - -bool WindowManagerAccessPolicy::CanInitiateMoveLoop( - const ServerWindow* window) const { - return false; -} - -bool WindowManagerAccessPolicy::ShouldNotifyOnHierarchyChange( - const ServerWindow* window, - const ServerWindow** new_parent, - const ServerWindow** old_parent) const { - // Notify if we've already told the window manager about the window, or if - // we've - // already told the window manager about the parent. The later handles the - // case of a window that wasn't parented to the root getting added to the - // root. - return IsWindowKnown(window) || (*new_parent && IsWindowKnown(*new_parent)); -} - -bool WindowManagerAccessPolicy::CanSetWindowManager() const { - return true; -} - -const ServerWindow* WindowManagerAccessPolicy::GetWindowForFocusChange( - const ServerWindow* focused) { - return focused; -} - -bool WindowManagerAccessPolicy::IsWindowKnown( - const ServerWindow* window) const { - return delegate_->IsWindowKnownForAccessPolicy(window); -} - -bool WindowManagerAccessPolicy::IsValidIdForNewWindow( - const ClientWindowId& id) const { - // The WindowManager see windows created from other clients. If the WM doesn't - // use the client id when creating windows the WM could end up with two - // windows with the same id. Because of this the wm must use the same - // client id for all windows it creates. - return base::checked_cast<ClientSpecificId>(id.client_id()) == client_id_; -} - -bool WindowManagerAccessPolicy::WasCreatedByThisClient( - const ServerWindow* window) const { - return window->owning_tree_id() == client_id_; -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/window_manager_access_policy.h b/services/ui/ws/window_manager_access_policy.h deleted file mode 100644 index ab2d475..0000000 --- a/services/ui/ws/window_manager_access_policy.h +++ /dev/null
@@ -1,87 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SERVICES_UI_WS_WINDOW_MANAGER_ACCESS_POLICY_H_ -#define SERVICES_UI_WS_WINDOW_MANAGER_ACCESS_POLICY_H_ - -#include <stdint.h> - -#include "base/macros.h" -#include "services/ui/ws/access_policy.h" - -namespace ui { -namespace ws { - -class AccessPolicyDelegate; - -class WindowManagerAccessPolicy : public AccessPolicy { - public: - WindowManagerAccessPolicy(); - ~WindowManagerAccessPolicy() override; - - // AccessPolicy: - void Init(ClientSpecificId client_id, - AccessPolicyDelegate* delegate) override; - bool CanRemoveWindowFromParent(const ServerWindow* window) const override; - bool CanAddWindow(const ServerWindow* parent, - const ServerWindow* child) const override; - bool CanAddTransientWindow(const ServerWindow* parent, - const ServerWindow* child) const override; - bool CanRemoveTransientWindowFromParent( - const ServerWindow* window) const override; - bool CanSetModal(const ServerWindow* window) const override; - bool CanSetChildModalParent(const ServerWindow* window, - const ServerWindow* modal_parent) const override; - bool CanReorderWindow(const ServerWindow* window, - const ServerWindow* relative_window, - mojom::OrderDirection direction) const override; - bool CanDeleteWindow(const ServerWindow* window) const override; - bool CanGetWindowTree(const ServerWindow* window) const override; - bool CanDescendIntoWindowForWindowTree( - const ServerWindow* window) const override; - bool CanEmbed(const ServerWindow* window) const override; - bool CanChangeWindowVisibility(const ServerWindow* window) const override; - bool CanChangeWindowOpacity(const ServerWindow* window) const override; - bool CanSetWindowCompositorFrameSink( - const ServerWindow* window) const override; - bool CanSetWindowBounds(const ServerWindow* window) const override; - bool CanSetWindowTransform(const ServerWindow* window) const override; - bool CanSetWindowProperties(const ServerWindow* window) const override; - bool CanSetWindowTextInputState(const ServerWindow* window) const override; - bool CanSetCapture(const ServerWindow* window) const override; - bool CanSetFocus(const ServerWindow* window) const override; - bool CanSetClientArea(const ServerWindow* window) const override; - bool CanSetHitTestMask(const ServerWindow* window) const override; - bool CanSetAcceptDrops(const ServerWindow* window) const override; - bool CanSetEventTargetingPolicy(const ServerWindow* window) const override; - bool CanStackAbove(const ServerWindow* above, - const ServerWindow* below) const override; - bool CanStackAtTop(const ServerWindow* window) const override; - bool CanPerformWmAction(const ServerWindow* window) const override; - bool CanSetCursorProperties(const ServerWindow* window) const override; - bool CanInitiateDragLoop(const ServerWindow* window) const override; - bool CanInitiateMoveLoop(const ServerWindow* window) const override; - bool ShouldNotifyOnHierarchyChange( - const ServerWindow* window, - const ServerWindow** new_parent, - const ServerWindow** old_parent) const override; - const ServerWindow* GetWindowForFocusChange( - const ServerWindow* focused) override; - bool CanSetWindowManager() const override; - bool IsValidIdForNewWindow(const ClientWindowId& id) const override; - - private: - bool IsWindowKnown(const ServerWindow* window) const; - bool WasCreatedByThisClient(const ServerWindow* window) const; - - ClientSpecificId client_id_ = 0u; - AccessPolicyDelegate* delegate_ = nullptr; - - DISALLOW_COPY_AND_ASSIGN(WindowManagerAccessPolicy); -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_WINDOW_MANAGER_ACCESS_POLICY_H_
diff --git a/services/ui/ws/window_manager_client_unittest.cc b/services/ui/ws/window_manager_client_unittest.cc deleted file mode 100644 index b0c0217..0000000 --- a/services/ui/ws/window_manager_client_unittest.cc +++ /dev/null
@@ -1,874 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stddef.h> -#include <stdint.h> - -#include "base/bind.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/run_loop.h" -#include "services/ui/common/util.h" -#include "services/ui/ws/test_utils.h" -#include "services/ui/ws/window_server_test_base.h" -#include "ui/aura/client/transient_window_client.h" -#include "ui/aura/env.h" -#include "ui/aura/mus/embed_root.h" -#include "ui/aura/mus/embed_root_delegate.h" -#include "ui/aura/mus/window_port_mus.h" -#include "ui/aura/mus/window_tree_client.h" -#include "ui/aura/mus/window_tree_client_delegate.h" -#include "ui/aura/mus/window_tree_host_mus.h" -#include "ui/aura/mus/window_tree_host_mus_init_params.h" -#include "ui/aura/test/mus/change_completion_waiter.h" -#include "ui/aura/test/mus/test_window_manager_delegate.h" -#include "ui/aura/test/mus/window_tree_client_private.h" -#include "ui/aura/window.h" -#include "ui/aura/window_observer.h" -#include "ui/aura/window_tracker.h" -#include "ui/gfx/geometry/rect.h" - -namespace ui { -namespace ws { - -namespace { - -Id server_id(aura::Window* window) { - return aura::WindowMus::Get(window)->server_id(); -} - -aura::Window* GetChildWindowByServerId(aura::WindowTreeClient* client, Id id) { - return aura::WindowTreeClientPrivate(client).GetWindowByServerId(id); -} - -class BoundsChangeObserver : public aura::WindowObserver { - public: - explicit BoundsChangeObserver(aura::Window* window) : window_(window) { - window_->AddObserver(this); - } - ~BoundsChangeObserver() override { window_->RemoveObserver(this); } - - private: - // Overridden from WindowObserver: - void OnWindowBoundsChanged(aura::Window* window, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds, - ui::PropertyChangeReason reason) override { - DCHECK_EQ(window, window_); - EXPECT_TRUE(WindowServerTestBase::QuitRunLoop()); - } - - aura::Window* window_; - - DISALLOW_COPY_AND_ASSIGN(BoundsChangeObserver); -}; - -// Wait until the bounds of the supplied window change; returns false on -// timeout. -bool WaitForBoundsToChange(aura::Window* window) { - BoundsChangeObserver observer(window); - return WindowServerTestBase::DoRunLoopWithTimeout(); -} - -// Spins a run loop until the tree beginning at |root| has |tree_size| windows -// (including |root|). -class TreeSizeMatchesObserver : public aura::WindowObserver { - public: - TreeSizeMatchesObserver(aura::Window* tree, size_t tree_size) - : tree_(tree), tree_size_(tree_size) { - tree_->AddObserver(this); - } - ~TreeSizeMatchesObserver() override { tree_->RemoveObserver(this); } - - bool IsTreeCorrectSize() { return CountWindows(tree_) == tree_size_; } - - private: - // Overridden from WindowObserver: - void OnWindowHierarchyChanged(const HierarchyChangeParams& params) override { - if (IsTreeCorrectSize()) - EXPECT_TRUE(WindowServerTestBase::QuitRunLoop()); - } - - size_t CountWindows(const aura::Window* window) const { - size_t count = 1; - for (const aura::Window* child : window->children()) - count += CountWindows(child); - return count; - } - - aura::Window* tree_; - size_t tree_size_; - - DISALLOW_COPY_AND_ASSIGN(TreeSizeMatchesObserver); -}; - -// Wait until |window| has |tree_size| descendants; returns false on timeout. -// The count includes |window|. For example, if you want to wait for |window| to -// have a single child, use a |tree_size| of 2. -bool WaitForTreeSizeToMatch(aura::Window* window, size_t tree_size) { - TreeSizeMatchesObserver observer(window, tree_size); - return observer.IsTreeCorrectSize() || - WindowServerTestBase::DoRunLoopWithTimeout(); -} - -class StackingOrderChangeObserver : public aura::WindowObserver { - public: - StackingOrderChangeObserver(aura::Window* window) : window_(window) { - window_->AddObserver(this); - } - ~StackingOrderChangeObserver() override { window_->RemoveObserver(this); } - - private: - // Overridden from aura::WindowObserver: - void OnWindowStackingChanged(aura::Window* window) override { - DCHECK_EQ(window, window_); - EXPECT_TRUE(WindowServerTestBase::QuitRunLoop()); - } - - aura::Window* window_; - - DISALLOW_COPY_AND_ASSIGN(StackingOrderChangeObserver); -}; - -// Wait until |window|'s tree size matches |tree_size|; returns false on -// timeout. -bool WaitForStackingOrderChange(aura::Window* window) { - StackingOrderChangeObserver observer(window); - return WindowServerTestBase::DoRunLoopWithTimeout(); -} - -// Tracks a window's destruction. Query is_valid() for current state. -class WindowTracker : public aura::WindowObserver { - public: - explicit WindowTracker(aura::Window* window) : window_(window) { - window_->AddObserver(this); - } - ~WindowTracker() override { - if (window_) - window_->RemoveObserver(this); - } - - bool is_valid() const { return !!window_; } - - private: - // Overridden from WindowObserver: - void OnWindowDestroyed(aura::Window* window) override { - DCHECK_EQ(window, window_); - window_ = nullptr; - } - - aura::Window* window_; - - DISALLOW_COPY_AND_ASSIGN(WindowTracker); -}; - -// Creates a new visible Window. If |parent| is non-null the newly created -// window is added to it. -aura::Window* NewVisibleWindow( - aura::Window* parent, - aura::WindowTreeClient* client, - aura::WindowMusType type = aura::WindowMusType::LOCAL) { - std::unique_ptr<aura::WindowPortMus> window_port_mus = - std::make_unique<aura::WindowPortMus>(client, type); - aura::Window* window = new aura::Window(nullptr, std::move(window_port_mus)); - window->Init(ui::LAYER_NOT_DRAWN); - window->Show(); - if (parent) - parent->AddChild(window); - return window; -} - -} // namespace - -// WindowServer -// ----------------------------------------------------------------- - -struct EmbedResult { - bool IsValid() const { - return window_tree_client.get() != nullptr && - window_tree_host.get() != nullptr; - } - - std::unique_ptr<aura::WindowTreeClient> window_tree_client; - std::unique_ptr<aura::WindowTreeHostMus> window_tree_host; -}; - -aura::Window* GetFirstRoot(aura::WindowTreeClient* client) { - return client->GetRoots().empty() ? nullptr : *client->GetRoots().begin(); -} - -// These tests model synchronization of two peer clients of the window server, -// that are given access to some root window. - -class WindowServerTest : public WindowServerTestBase { - public: - struct ClientAreaChange { - aura::Window* window = nullptr; - gfx::Insets insets; - }; - - WindowServerTest() {} - - aura::Window* GetFirstWMRoot() { return GetFirstRoot(window_manager()); } - - // Embeds another version of the test app @ window. This runs a run loop until - // a response is received, or a timeout. The return value is always non-null, - // but if there is an error there is no WindowTreeClient. Always use - // ASSERT_EQ(result->IsValid()) on the return value. - std::unique_ptr<EmbedResult> Embed(aura::WindowTreeClient* window_tree_client, - aura::Window* window) { - DCHECK(!embed_details_); - embed_details_ = std::make_unique<EmbedDetails>(); - window_tree_client->Embed(window, ConnectAndGetWindowServerClient(), 0, - base::Bind(&WindowServerTest::EmbedCallbackImpl, - base::Unretained(this))); - if (embed_details_->callback_run) { - // The callback was run immediately, this indicates an immediate failure, - // such as |window| has children. - EXPECT_FALSE(embed_details_->embed_result); - embed_details_.reset(); - return std::make_unique<EmbedResult>(); - } - // Wait for EmbedCallbackImpl() to be called with the result. - embed_details_->waiting = true; - if (!WindowServerTestBase::DoRunLoopWithTimeout()) { - embed_details_.reset(); - return std::make_unique<EmbedResult>(); - } - std::unique_ptr<EmbedResult> result = std::move(embed_details_->result); - embed_details_.reset(); - return result; - } - - // Establishes a connection to this application and asks for a - // WindowTreeClient. - ui::mojom::WindowTreeClientPtr ConnectAndGetWindowServerClient() { - ui::mojom::WindowTreeClientPtr client; - connector()->BindInterface(test_name(), &client); - return client; - } - - std::unique_ptr<ClientAreaChange> WaitForClientAreaToChange() { - client_area_change_ = std::make_unique<ClientAreaChange>(); - // The nested run loop is quit in OnWmSetClientArea(). Client area - // changes don't route through the window, only the WindowManagerDelegate. - if (!WindowServerTestBase::DoRunLoopWithTimeout()) { - client_area_change_.reset(); - return nullptr; - } - return std::move(client_area_change_); - } - - // WindowServerTestBase: - void OnEmbed( - std::unique_ptr<aura::WindowTreeHostMus> window_tree_host) override { - if (!embed_details_) { - WindowServerTestBase::OnEmbed(std::move(window_tree_host)); - return; - } - - embed_details_->result->window_tree_host = std::move(window_tree_host); - embed_details_->result->window_tree_client = ReleaseMostRecentClient(); - if (embed_details_->callback_run) - EXPECT_TRUE(WindowServerTestBase::QuitRunLoop()); - } - void OnWmSetClientArea( - aura::Window* window, - const gfx::Insets& insets, - const std::vector<gfx::Rect>& additional_client_areas) override { - if (!client_area_change_.get()) - return; - - client_area_change_->window = window; - client_area_change_->insets = insets; - EXPECT_TRUE(WindowServerTestBase::QuitRunLoop()); - } - - private: - // Used to track the state of a call to window->Embed(). - struct EmbedDetails { - EmbedDetails() : result(std::make_unique<EmbedResult>()) {} - - // The callback function supplied to Embed() was called. - bool callback_run = false; - - // The boolean supplied to the Embed() callback. - bool embed_result = false; - - // Whether a MessageLoop is running. - bool waiting = false; - - std::unique_ptr<EmbedResult> result; - }; - - void EmbedCallbackImpl(bool result) { - embed_details_->callback_run = true; - embed_details_->embed_result = result; - if (embed_details_->waiting && - (!result || embed_details_->result->window_tree_client)) - EXPECT_TRUE(WindowServerTestBase::QuitRunLoop()); - } - - std::unique_ptr<EmbedDetails> embed_details_; - - std::unique_ptr<ClientAreaChange> client_area_change_; - - DISALLOW_COPY_AND_ASSIGN(WindowServerTest); -}; - -TEST_F(WindowServerTest, RootWindow) { - ASSERT_NE(nullptr, window_manager()); - EXPECT_EQ(1u, window_manager()->GetRoots().size()); -} - -TEST_F(WindowServerTest, Embed) { - aura::Window* window = NewVisibleWindow(GetFirstWMRoot(), window_manager(), - aura::WindowMusType::EMBED_IN_OWNER); - std::unique_ptr<EmbedResult> embed_result = Embed(window_manager(), window); - ASSERT_TRUE(embed_result->IsValid()); - - aura::Window* embed_root = embed_result->window_tree_host->window(); - // WindowTreeHost::window() is the single root of the embed. - EXPECT_EQ(1u, embed_result->window_tree_client->GetRoots().size()); - EXPECT_EQ(embed_root, GetFirstRoot(embed_result->window_tree_client.get())); - EXPECT_EQ(ClientWindowIdFromTransportId(server_id(window)), - ClientWindowIdFromTransportId(server_id(embed_root))); - EXPECT_NE(0u, ClientIdFromTransportId(server_id(embed_root))); - EXPECT_EQ(nullptr, embed_root->parent()); - EXPECT_TRUE(embed_root->children().empty()); -} - -// Window manager has two windows, N1 and N11. Embeds A at N1. A should not see -// N11. -TEST_F(WindowServerTest, EmbeddedDoesntSeeChild) { - aura::Window* window = NewVisibleWindow(GetFirstWMRoot(), window_manager(), - aura::WindowMusType::EMBED_IN_OWNER); - std::unique_ptr<EmbedResult> embed_result = Embed(window_manager(), window); - ASSERT_TRUE(embed_result->IsValid()); - aura::Window* embed_root = embed_result->window_tree_host->window(); - EXPECT_EQ(ClientWindowIdFromTransportId(server_id(window)), - ClientWindowIdFromTransportId(server_id(embed_root))); - EXPECT_NE(0u, ClientIdFromTransportId(server_id(embed_root))); - EXPECT_EQ(nullptr, embed_root->parent()); - EXPECT_TRUE(embed_root->children().empty()); -} - -// TODO(beng): write a replacement test for the one that once existed here: -// This test validates the following scenario: -// - a window originating from one client -// - a window originating from a second client -// + the client originating the window is destroyed -// -> the window should still exist (since the second client is live) but -// should be disconnected from any windows. -// http://crbug.com/396300 -// -// TODO(beng): The new test should validate the scenario as described above -// except that the second client still has a valid tree. - -// Verifies that bounds changes applied to a window hierarchy in one client -// are reflected to another. -TEST_F(WindowServerTest, SetBounds) { - aura::Window* window = NewVisibleWindow(GetFirstWMRoot(), window_manager(), - aura::WindowMusType::EMBED_IN_OWNER); - - std::unique_ptr<EmbedResult> embed_result = Embed(window_manager(), window); - ASSERT_TRUE(embed_result->IsValid()); - aura::Window* embed_root = embed_result->window_tree_host->window(); - EXPECT_EQ(window->bounds(), embed_root->bounds()); - - window->SetBounds(gfx::Rect(0, 0, 100, 100)); - ASSERT_TRUE(WaitForBoundsToChange(embed_root)); - EXPECT_EQ(window->bounds(), embed_root->bounds()); -} - -// Verifies that bounds changes applied to a window owned by a different -// client can be refused. -TEST_F(WindowServerTest, SetBoundsSecurity) { - aura::TestWindowManagerDelegate wm_delegate; - set_window_manager_delegate(&wm_delegate); - - aura::Window* window = NewVisibleWindow(GetFirstWMRoot(), window_manager(), - aura::WindowMusType::EMBED_IN_OWNER); - - std::unique_ptr<EmbedResult> embed_result = Embed(window_manager(), window); - ASSERT_TRUE(embed_result->IsValid()); - aura::Window* embed_root = embed_result->window_tree_host->window(); - window->SetBounds(gfx::Rect(0, 0, 800, 600)); - ASSERT_TRUE(WaitForBoundsToChange(embed_root)); - - embed_result->window_tree_host->SetBoundsInPixels(gfx::Rect(0, 0, 1024, 768)); - // Bounds change is initially accepted, but the server declines the request. - EXPECT_NE(window->bounds(), embed_root->bounds()); - - // The client is notified when the requested is declined, and updates the - // local bounds accordingly. - ASSERT_TRUE(WaitForBoundsToChange(embed_root)); - EXPECT_EQ(window->bounds(), embed_root->bounds()); - set_window_manager_delegate(nullptr); -} - -// Verifies that a root window can always be destroyed. -TEST_F(WindowServerTest, DestroySecurity) { - aura::Window* window = NewVisibleWindow(GetFirstWMRoot(), window_manager(), - aura::WindowMusType::EMBED_IN_OWNER); - - std::unique_ptr<EmbedResult> embed_result = Embed(window_manager(), window); - ASSERT_TRUE(embed_result->IsValid()); - aura::Window* embed_root = embed_result->window_tree_host->window(); - - // The root can be destroyed, even though it was not created by the client. - aura::WindowTracker tracker; - tracker.Add(window); - tracker.Add(embed_root); - embed_result->window_tree_host.reset(); - EXPECT_FALSE(tracker.Contains(embed_root)); - EXPECT_TRUE(tracker.Contains(window)); - - delete window; - EXPECT_FALSE(tracker.Contains(window)); -} - -TEST_F(WindowServerTest, MultiRoots) { - aura::Window* window1 = NewVisibleWindow(GetFirstWMRoot(), window_manager(), - aura::WindowMusType::EMBED_IN_OWNER); - aura::Window* window2 = NewVisibleWindow(GetFirstWMRoot(), window_manager(), - aura::WindowMusType::EMBED_IN_OWNER); - std::unique_ptr<EmbedResult> embed_result1 = Embed(window_manager(), window1); - ASSERT_TRUE(embed_result1->IsValid()); - std::unique_ptr<EmbedResult> embed_result2 = Embed(window_manager(), window2); - ASSERT_TRUE(embed_result2->IsValid()); -} - -TEST_F(WindowServerTest, Reorder) { - aura::Window* window1 = NewVisibleWindow(GetFirstWMRoot(), window_manager(), - aura::WindowMusType::EMBED_IN_OWNER); - - std::unique_ptr<EmbedResult> embed_result = Embed(window_manager(), window1); - ASSERT_TRUE(embed_result->IsValid()); - aura::WindowTreeClient* embedded = embed_result->window_tree_client.get(); - aura::Window* embed_root = embed_result->window_tree_host->window(); - - aura::Window* window11 = NewVisibleWindow(embed_root, embedded); - aura::Window* window12 = NewVisibleWindow(embed_root, embedded); - ASSERT_TRUE(WaitForTreeSizeToMatch(window1, 3u)); - - // |embedded|'s WindowTree has an id_ of embedded_client_id, so window11's - // client_id part should be embedded_client_id in the WindowTree for - // window_manager(). Similar for window12. - Id embedded_client_id = test::kWindowManagerClientId + 1; - Id window11_in_wm = embedded_client_id << 32 | - ClientWindowIdFromTransportId(server_id(window11)); - Id window12_in_wm = embedded_client_id << 32 | - ClientWindowIdFromTransportId(server_id(window12)); - - { - window11->parent()->StackChildAtTop(window11); - // The |embedded| tree should be updated immediately. - EXPECT_EQ(embed_root->children().front(), - GetChildWindowByServerId(embedded, server_id(window12))); - EXPECT_EQ(embed_root->children().back(), - GetChildWindowByServerId(embedded, server_id(window11))); - - // The window_manager() tree is still not updated. - EXPECT_EQ(window1->children().back(), - GetChildWindowByServerId(window_manager(), window12_in_wm)); - - // Wait until window_manager() tree is updated. - ASSERT_TRUE(WaitForStackingOrderChange( - GetChildWindowByServerId(window_manager(), window11_in_wm))); - EXPECT_EQ(window1->children().front(), - GetChildWindowByServerId(window_manager(), window12_in_wm)); - EXPECT_EQ(window1->children().back(), - GetChildWindowByServerId(window_manager(), window11_in_wm)); - } - - { - window11->parent()->StackChildAtBottom(window11); - // |embedded| should be updated immediately. - EXPECT_EQ(embed_root->children().front(), - GetChildWindowByServerId(embedded, server_id(window11))); - EXPECT_EQ(embed_root->children().back(), - GetChildWindowByServerId(embedded, server_id(window12))); - - // |window_manager()| is also eventually updated. - EXPECT_EQ(window1->children().back(), - GetChildWindowByServerId(window_manager(), window11_in_wm)); - ASSERT_TRUE(WaitForStackingOrderChange( - GetChildWindowByServerId(window_manager(), window11_in_wm))); - EXPECT_EQ(window1->children().front(), - GetChildWindowByServerId(window_manager(), window11_in_wm)); - EXPECT_EQ(window1->children().back(), - GetChildWindowByServerId(window_manager(), window12_in_wm)); - } -} - -namespace { - -class VisibilityChangeObserver : public aura::WindowObserver { - public: - explicit VisibilityChangeObserver(aura::Window* window) : window_(window) { - window_->AddObserver(this); - } - ~VisibilityChangeObserver() override { window_->RemoveObserver(this); } - - private: - // Overridden from WindowObserver: - void OnWindowVisibilityChanged(aura::Window* window, bool visible) override { - EXPECT_EQ(window, window_); - EXPECT_TRUE(WindowServerTestBase::QuitRunLoop()); - } - - aura::Window* window_; - - DISALLOW_COPY_AND_ASSIGN(VisibilityChangeObserver); -}; - -} // namespace - -TEST_F(WindowServerTest, Visible) { - aura::Window* window1 = NewVisibleWindow(GetFirstWMRoot(), window_manager(), - aura::WindowMusType::EMBED_IN_OWNER); - - // Embed another app and verify initial state. - std::unique_ptr<EmbedResult> embed_result = Embed(window_manager(), window1); - ASSERT_TRUE(embed_result->IsValid()); - aura::Window* embed_root = embed_result->window_tree_host->window(); - EXPECT_TRUE(embed_root->TargetVisibility()); - EXPECT_TRUE(embed_root->IsVisible()); - - // Change the visible state from the first client and verify its mirrored - // correctly to the embedded app. - { - VisibilityChangeObserver observer(embed_root); - window1->Hide(); - ASSERT_TRUE(WindowServerTestBase::DoRunLoopWithTimeout()); - } - - EXPECT_FALSE(window1->TargetVisibility()); - EXPECT_FALSE(window1->IsVisible()); - - EXPECT_FALSE(embed_root->TargetVisibility()); - EXPECT_FALSE(embed_root->IsVisible()); - - // Make the node visible again. - { - VisibilityChangeObserver observer(embed_root); - window1->Show(); - ASSERT_TRUE(WindowServerTestBase::DoRunLoopWithTimeout()); - } - - EXPECT_TRUE(window1->TargetVisibility()); - EXPECT_TRUE(window1->IsVisible()); - - EXPECT_TRUE(embed_root->TargetVisibility()); - EXPECT_TRUE(embed_root->IsVisible()); -} - -// TODO(beng): tests for window event dispatcher. -// - verify that we see events for all windows. - -TEST_F(WindowServerTest, EmbedFailsWithChildren) { - aura::Window* window1 = NewVisibleWindow(GetFirstWMRoot(), window_manager(), - aura::WindowMusType::EMBED_IN_OWNER); - ASSERT_TRUE(NewVisibleWindow(window1, window_manager())); - std::unique_ptr<EmbedResult> embed_result = Embed(window_manager(), window1); - // Embed() should fail as |window1| has a child. - EXPECT_FALSE(embed_result->IsValid()); -} - -namespace { - -class DestroyObserver : public aura::WindowObserver { - public: - DestroyObserver(aura::WindowTreeClient* client, bool* got_destroy) - : got_destroy_(got_destroy) { - GetFirstRoot(client)->AddObserver(this); - } - ~DestroyObserver() override {} - - private: - // Overridden from aura::WindowObserver: - void OnWindowDestroyed(aura::Window* window) override { - *got_destroy_ = true; - window->RemoveObserver(this); - - EXPECT_TRUE(WindowServerTestBase::QuitRunLoop()); - } - - bool* got_destroy_; - - DISALLOW_COPY_AND_ASSIGN(DestroyObserver); -}; - -} // namespace - -// Verifies deleting a Window that is the root of another client notifies -// observers in the right order (OnWindowDestroyed() before -// OnWindowManagerDestroyed()). -TEST_F(WindowServerTest, WindowServerDestroyedAfterRootObserver) { - aura::Window* window = NewVisibleWindow(GetFirstWMRoot(), window_manager(), - aura::WindowMusType::EMBED_IN_OWNER); - - std::unique_ptr<EmbedResult> embed_result = Embed(window_manager(), window); - ASSERT_TRUE(embed_result->IsValid()); - aura::WindowTreeClient* embedded_client = - embed_result->window_tree_client.get(); - - bool got_destroy = false; - DestroyObserver observer(embedded_client, &got_destroy); - // Delete the window |embedded_client| is embedded in. |embedded_client| is - // asynchronously notified and cleans up. - delete window; - EXPECT_TRUE(DoRunLoopWithTimeout()); - ASSERT_TRUE(got_destroy); - // The WindowTreeHost was destroyed as well (by - // WindowServerTestBase::OnEmbedRootDestroyed()). - embed_result->window_tree_host.release(); - EXPECT_EQ(0u, embed_result->window_tree_client->GetRoots().size()); -} - -TEST_F(WindowServerTest, ClientAreaChanged) { - aura::Window* window = NewVisibleWindow(GetFirstWMRoot(), window_manager(), - aura::WindowMusType::EMBED_IN_OWNER); - - std::unique_ptr<EmbedResult> embed_result = Embed(window_manager(), window); - ASSERT_TRUE(embed_result->IsValid()); - - // Verify change from embedded makes it to parent. - const gfx::Insets insets(1, 2, 3, 4); - embed_result->window_tree_host->SetClientArea(insets, - std::vector<gfx::Rect>()); - std::unique_ptr<ClientAreaChange> client_area_change = - WaitForClientAreaToChange(); - ASSERT_TRUE(client_area_change); - EXPECT_EQ(window, client_area_change->window); - EXPECT_EQ(insets, client_area_change->insets); -} - -class EstablishConnectionViaFactoryDelegate - : public aura::TestWindowManagerDelegate { - public: - explicit EstablishConnectionViaFactoryDelegate(aura::WindowTreeClient* client) - : client_(client), run_loop_(nullptr), created_window_(nullptr) {} - ~EstablishConnectionViaFactoryDelegate() override {} - - bool QuitOnCreate() { - if (run_loop_) - return false; - - created_window_ = nullptr; - run_loop_ = std::make_unique<base::RunLoop>(); - run_loop_->Run(); - run_loop_.reset(); - return created_window_ != nullptr; - } - - aura::Window* created_window() { return created_window_; } - - // WindowManagerDelegate: - aura::Window* OnWmCreateTopLevelWindow( - ui::mojom::WindowType window_type, - std::map<std::string, std::vector<uint8_t>>* properties) override { - created_window_ = NewVisibleWindow((*client_->GetRoots().begin()), client_, - aura::WindowMusType::TOP_LEVEL_IN_WM); - if (run_loop_) - run_loop_->Quit(); - return created_window_; - } - - private: - aura::WindowTreeClient* client_; - std::unique_ptr<base::RunLoop> run_loop_; - aura::Window* created_window_; - - DISALLOW_COPY_AND_ASSIGN(EstablishConnectionViaFactoryDelegate); -}; - -TEST_F(WindowServerTest, EstablishConnectionViaFactory) { - EstablishConnectionViaFactoryDelegate delegate(window_manager()); - set_window_manager_delegate(&delegate); - std::unique_ptr<aura::WindowTreeClient> second_client = - aura::WindowTreeClient::CreateForWindowTreeFactory(connector(), this, - false); - aura::WindowTreeHostMus window_tree_host_in_second_client( - aura::CreateInitParamsForTopLevel(second_client.get())); - window_tree_host_in_second_client.InitHost(); - window_tree_host_in_second_client.window()->Show(); - ASSERT_TRUE(second_client->GetRoots().count( - window_tree_host_in_second_client.window()) > 0); - // Wait for the window to appear in the wm. - ASSERT_TRUE(delegate.QuitOnCreate()); - - aura::Window* window_in_wm = delegate.created_window(); - ASSERT_TRUE(window_in_wm); - - // Change the bounds in the wm, and make sure the child sees it. - const gfx::Rect window_bounds(1, 11, 12, 101); - window_in_wm->SetBounds(window_bounds); - ASSERT_TRUE( - WaitForBoundsToChange(window_tree_host_in_second_client.window())); - EXPECT_EQ(window_bounds, - window_tree_host_in_second_client.GetBoundsInPixels()); -} - -TEST_F(WindowServerTest, OnWindowHierarchyChangedIncludesTransientParent) { - // Create a second connection. In the second connection create a window, - // parent it to the root, create another window, mark it as a transient parent - // of the first window and then add it. - EstablishConnectionViaFactoryDelegate delegate(window_manager()); - set_window_manager_delegate(&delegate); - std::unique_ptr<aura::WindowTreeClient> second_client = - aura::WindowTreeClient::CreateForWindowTreeFactory(connector(), this, - false); - aura::WindowTreeHostMus window_tree_host_in_second_client( - aura::CreateInitParamsForTopLevel(second_client.get())); - window_tree_host_in_second_client.InitHost(); - window_tree_host_in_second_client.window()->Show(); - aura::Window* second_client_child = NewVisibleWindow( - window_tree_host_in_second_client.window(), second_client.get()); - // Create the transient without a parent, set transient parent, then add. - aura::Window* transient = NewVisibleWindow(nullptr, second_client.get()); - aura::client::TransientWindowClient* transient_window_client = - aura::client::GetTransientWindowClient(); - transient_window_client->AddTransientChild(second_client_child, transient); - second_client_child->AddChild(transient); - - // Wait for the top-level to appear in the window manager. - ASSERT_TRUE(delegate.QuitOnCreate()); - aura::Window* top_level_in_wm = delegate.created_window(); - - // Makes sure the window manager sees the same structure and the transient - // parent is connected correctly. - ASSERT_TRUE(WaitForTreeSizeToMatch(top_level_in_wm, 3u)); - ASSERT_EQ(1u, top_level_in_wm->children().size()); - aura::Window* second_client_child_in_wm = top_level_in_wm->children()[0]; - ASSERT_EQ(1u, second_client_child_in_wm->children().size()); - aura::Window* transient_in_wm = second_client_child_in_wm->children()[0]; - ASSERT_EQ(second_client_child_in_wm, - transient_window_client->GetTransientParent(transient_in_wm)); -} - -class TestEmbedRootDelegate : public aura::EmbedRootDelegate { - public: - TestEmbedRootDelegate() {} - - void SetQuitClosure(base::Closure closure) { quit_closure_ = closure; } - - const base::UnguessableToken& token() const { return token_; } - aura::Window* embed_window() { return embed_window_; } - bool got_unembed() const { return got_unembed_; } - - // EmbedRootDelegate: - void OnEmbedTokenAvailable(const base::UnguessableToken& token) override { - token_ = token; - quit_closure_.Run(); - } - void OnEmbed(aura::Window* window) override { - embed_window_ = window; - quit_closure_.Run(); - } - void OnUnembed() override { - got_unembed_ = true; - quit_closure_.Run(); - } - - private: - base::Closure quit_closure_; - aura::Window* embed_window_ = nullptr; - bool got_unembed_ = false; - - base::UnguessableToken token_; - - DISALLOW_COPY_AND_ASSIGN(TestEmbedRootDelegate); -}; - -// This test exercises multiple EmbedRoots for a single client. -TEST_F(WindowServerTest, EmbedRoot) { - EstablishConnectionViaFactoryDelegate delegate(window_manager()); - set_window_manager_delegate(&delegate); - std::unique_ptr<aura::WindowTreeClient> second_client = - aura::WindowTreeClient::CreateForWindowTreeFactory(connector(), this, - false); - - // Create a visible window so that the window-manager has a different number - // of initial windows than the client. - NewVisibleWindow(GetFirstWMRoot(), window_manager(), - aura::WindowMusType::EMBED_IN_OWNER); - std::vector<std::unique_ptr<aura::EmbedRoot>> embed_roots; - for (int i = 0; i < 2; ++i) { - // Create a new EmbedRoot and wait for the token from the server. - TestEmbedRootDelegate test_embed_root_delegate; - std::unique_ptr<aura::EmbedRoot> embed_root = - second_client->CreateEmbedRoot(&test_embed_root_delegate); - base::RunLoop run_loop1; - test_embed_root_delegate.SetQuitClosure(run_loop1.QuitClosure()); - run_loop1.Run(); - ASSERT_TRUE(test_embed_root_delegate.token()); - - // Embed the token from the window manager's connection and wait for - // OnEmbed(). - aura::Window* embed_window_in_wm = - NewVisibleWindow(GetFirstWMRoot(), window_manager(), - aura::WindowMusType::EMBED_IN_OWNER); - window_manager()->EmbedUsingToken(embed_window_in_wm, - test_embed_root_delegate.token(), 0u, - base::DoNothing()); - - base::RunLoop run_loop2; - test_embed_root_delegate.SetQuitClosure(run_loop2.QuitClosure()); - run_loop2.Run(); - ASSERT_TRUE(test_embed_root_delegate.embed_window()); - EXPECT_NE(test_embed_root_delegate.embed_window(), embed_window_in_wm); - // Create a child of the embed root's window in |second_client|. Then wait - // for completion to ensure all is well. - NewVisibleWindow(test_embed_root_delegate.embed_window(), - second_client.get()); - aura::test::WaitForAllChangesToComplete(second_client.get()); - embed_roots.push_back(std::move(embed_root)); - } -} - -TEST_F(WindowServerTest, DeleteEmbedRoot) { - EstablishConnectionViaFactoryDelegate delegate(window_manager()); - set_window_manager_delegate(&delegate); - std::unique_ptr<aura::WindowTreeClient> second_client = - aura::WindowTreeClient::CreateForWindowTreeFactory(connector(), this, - false); - - // Create a new EmbedRoot and wait for the token from the server. - TestEmbedRootDelegate test_embed_root_delegate; - std::unique_ptr<aura::EmbedRoot> embed_root = - second_client->CreateEmbedRoot(&test_embed_root_delegate); - base::RunLoop run_loop1; - test_embed_root_delegate.SetQuitClosure(run_loop1.QuitClosure()); - run_loop1.Run(); - ASSERT_TRUE(test_embed_root_delegate.token()); - - // Embed the token from the window manager's connection and wait for - // OnEmbed(). - aura::Window* embed_window_in_wm = NewVisibleWindow( - GetFirstWMRoot(), window_manager(), aura::WindowMusType::EMBED_IN_OWNER); - window_manager()->EmbedUsingToken(embed_window_in_wm, - test_embed_root_delegate.token(), 0u, - base::DoNothing()); - - base::RunLoop run_loop2; - test_embed_root_delegate.SetQuitClosure(run_loop2.QuitClosure()); - run_loop2.Run(); - ASSERT_TRUE(test_embed_root_delegate.embed_window()); - aura::WindowTracker embed_root_window_tracker; - embed_root_window_tracker.Add(test_embed_root_delegate.embed_window()); - - // Delete the embed root (from the window-manager). - delete embed_window_in_wm; - base::RunLoop run_loop3; - test_embed_root_delegate.SetQuitClosure(run_loop3.QuitClosure()); - run_loop3.Run(); - EXPECT_TRUE(test_embed_root_delegate.got_unembed()); - // The EmbedRoot's window should still exist in the embedded client. - EXPECT_FALSE(embed_root_window_tracker.windows().empty()); -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/window_manager_display_root.cc b/services/ui/ws/window_manager_display_root.cc deleted file mode 100644 index 0e41987..0000000 --- a/services/ui/ws/window_manager_display_root.cc +++ /dev/null
@@ -1,59 +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 "services/ui/ws/window_manager_display_root.h" - -#include <string> -#include <vector> - -#include "services/ui/public/interfaces/window_manager.mojom.h" -#include "services/ui/ws/display.h" -#include "services/ui/ws/display_manager.h" -#include "services/ui/ws/server_window.h" -#include "services/ui/ws/window_manager_state.h" -#include "services/ui/ws/window_server.h" -#include "services/ui/ws/window_tree.h" - -namespace ui { -namespace ws { - -WindowManagerDisplayRoot::WindowManagerDisplayRoot(Display* display) - : display_(display) { - std::string name = "WindowManagerRoot"; - ServerWindow::Properties properties; - properties[mojom::WindowManager::kName_Property] = - std::vector<uint8_t>(name.begin(), name.end()); - - const ClientWindowId client_window_id = - window_server()->display_manager()->GetAndAdvanceNextRootId(); - root_.reset( - window_server()->CreateServerWindow(client_window_id, properties)); - root_->set_event_targeting_policy( - mojom::EventTargetingPolicy::DESCENDANTS_ONLY); - // Our root is always a child of the Display's root. Do this - // before the WindowTree has been created so that the client doesn't get - // notified of the add, bounds change and visibility change. - root_->SetBounds(gfx::Rect(display->root_window()->bounds().size()), - allocator_.GenerateId()); - root_->SetVisible(true); - display->root_window()->Add(root_.get()); -} - -WindowManagerDisplayRoot::~WindowManagerDisplayRoot() {} - -const ServerWindow* WindowManagerDisplayRoot::GetClientVisibleRoot() const { - if (window_manager_state_->window_tree() - ->automatically_create_display_roots()) { - return root_.get(); - } - - return root_->children().empty() ? nullptr : root_->children()[0]; -} - -WindowServer* WindowManagerDisplayRoot::window_server() { - return display_->window_server(); -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/window_manager_display_root.h b/services/ui/ws/window_manager_display_root.h deleted file mode 100644 index c6962e42..0000000 --- a/services/ui/ws/window_manager_display_root.h +++ /dev/null
@@ -1,75 +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. - -#ifndef SERVICES_UI_WS_WINDOW_MANAGER_DISPLAY_ROOT_H_ -#define SERVICES_UI_WS_WINDOW_MANAGER_DISPLAY_ROOT_H_ - -#include <stdint.h> - -#include <memory> - -#include "base/macros.h" -#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h" - -namespace ui { -namespace ws { - -class Display; -class ServerWindow; -class WindowManagerState; -class WindowServer; - -// Owns the root window of a window manager for one display. Each window manager -// has one WindowManagerDisplayRoot for each Display. The root window is -// parented to the root of a Display. -class WindowManagerDisplayRoot { - public: - explicit WindowManagerDisplayRoot(Display* display); - ~WindowManagerDisplayRoot(); - - // NOTE: this window is not necessarily visible to the window manager. When - // the display roots are automatically created this root is visible to the - // window manager. When the display roots are not automatically created this - // root has a single child that is created by the client. Use - // GetClientVisibleRoot() to get the root that is visible to the client. - ServerWindow* root() { return root_.get(); } - const ServerWindow* root() const { return root_.get(); } - - // See root() for details of this. This returns null until the client creates - // the root. - ServerWindow* GetClientVisibleRoot() { - return const_cast<ServerWindow*>( - const_cast<const WindowManagerDisplayRoot*>(this) - ->GetClientVisibleRoot()); - } - const ServerWindow* GetClientVisibleRoot() const; - - Display* display() { return display_; } - const Display* display() const { return display_; } - - WindowManagerState* window_manager_state() { return window_manager_state_; } - const WindowManagerState* window_manager_state() const { - return window_manager_state_; - } - - private: - friend class Display; - friend class WindowManagerState; - - WindowServer* window_server(); - - Display* display_; - // Root ServerWindow of this WindowManagerDisplayRoot. |root_| has a parent, - // the root ServerWindow of the Display. - std::unique_ptr<ServerWindow> root_; - WindowManagerState* window_manager_state_ = nullptr; - viz::ParentLocalSurfaceIdAllocator allocator_; - - DISALLOW_COPY_AND_ASSIGN(WindowManagerDisplayRoot); -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_WINDOW_MANAGER_DISPLAY_ROOT_H_
diff --git a/services/ui/ws/window_manager_state.cc b/services/ui/ws/window_manager_state.cc deleted file mode 100644 index fcf2b00f..0000000 --- a/services/ui/ws/window_manager_state.cc +++ /dev/null
@@ -1,642 +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 "services/ui/ws/window_manager_state.h" - -#include <utility> - -#include "base/containers/queue.h" -#include "base/logging.h" -#include "base/memory/weak_ptr.h" -#include "components/viz/host/host_frame_sink_manager.h" -#include "services/service_manager/public/mojom/connector.mojom.h" -#include "services/ui/common/accelerator_util.h" -#include "services/ui/ws/accelerator.h" -#include "services/ui/ws/cursor_location_manager.h" -#include "services/ui/ws/display.h" -#include "services/ui/ws/display_creation_config.h" -#include "services/ui/ws/display_manager.h" -#include "services/ui/ws/event_location.h" -#include "services/ui/ws/event_targeter.h" -#include "services/ui/ws/platform_display.h" -#include "services/ui/ws/server_window.h" -#include "services/ui/ws/server_window_tracker.h" -#include "services/ui/ws/user_display_manager.h" -#include "services/ui/ws/window_manager_display_root.h" -#include "services/ui/ws/window_server.h" -#include "services/ui/ws/window_tree.h" -#include "ui/events/event.h" -#include "ui/gfx/geometry/dip_util.h" -#include "ui/gfx/geometry/point3_f.h" -#include "ui/gfx/geometry/point_conversions.h" - -namespace ui { -namespace ws { -namespace { - -// Flags that matter when checking if a key event matches an accelerator. -const int kAcceleratorEventFlags = - EF_SHIFT_DOWN | EF_CONTROL_DOWN | EF_ALT_DOWN | EF_COMMAND_DOWN; - -const ServerWindow* GetEmbedRoot(const ServerWindow* window) { - DCHECK(window); - const ServerWindow* embed_root = window->parent(); - while (embed_root && - embed_root->owning_tree_id() == window->owning_tree_id()) { - embed_root = embed_root->parent(); - } - return embed_root; -} - -const gfx::Rect& GetDisplayBoundsInPixels(Display* display) { - return display->GetViewportMetrics().bounds_in_pixels; -} - -gfx::Point PixelsToDips(Display* display, const gfx::Point& location) { - return gfx::ConvertPointToDIP( - display->GetDisplay().device_scale_factor() / - display->GetViewportMetrics().ui_scale_factor, - location); -} - -gfx::Point DipsToPixels(Display* display, const gfx::Point& location) { - return gfx::ConvertPointToPixel( - display->GetDisplay().device_scale_factor() / - display->GetViewportMetrics().ui_scale_factor, - location); -} - -} // namespace - -bool WindowManagerState::DebugAccelerator::Matches( - const ui::KeyEvent& event) const { - return key_code == event.key_code() && - event_flags == (kAcceleratorEventFlags & event.flags()) && - !event.is_char(); -} - -WindowManagerState::WindowManagerState(WindowTree* window_tree) - : window_tree_(window_tree), - event_dispatcher_(window_server(), window_tree_, this), - event_processor_(this, &event_dispatcher_), - cursor_state_(window_tree_->display_manager(), this) { - event_dispatcher_.Init(&event_processor_); - frame_decoration_values_ = mojom::FrameDecorationValues::New(); - frame_decoration_values_->max_title_bar_button_width = 0u; - - AddDebugAccelerators(); -} - -WindowManagerState::~WindowManagerState() { - for (auto& display_root : window_manager_display_roots_) - display_root->display()->OnWillDestroyTree(window_tree_); - - if (window_tree_->automatically_create_display_roots()) { - for (auto& display_root : orphaned_window_manager_display_roots_) - display_root->root()->RemoveObserver(this); - } -} - -void WindowManagerState::SetFrameDecorationValues( - mojom::FrameDecorationValuesPtr values) { - got_frame_decoration_values_ = true; - frame_decoration_values_ = values.Clone(); - UserDisplayManager* user_display_manager = - display_manager()->GetUserDisplayManager(); - user_display_manager->OnFrameDecorationValuesChanged(); - if (window_server()->display_creation_config() == - DisplayCreationConfig::MANUAL && - display_manager()->got_initial_config_from_window_manager()) { - user_display_manager->CallOnDisplaysChanged(); - } -} - -bool WindowManagerState::SetCapture(ServerWindow* window, - ClientSpecificId client_id) { - if (capture_window() == window && - client_id == event_processor_.capture_window_client_id()) { - return true; - } -#if DCHECK_IS_ON() - if (window) { - WindowManagerDisplayRoot* display_root = - display_manager()->GetWindowManagerDisplayRoot(window); - DCHECK(display_root && display_root->window_manager_state() == this); - } -#endif - return event_processor_.SetCaptureWindow(window, client_id); -} - -void WindowManagerState::ReleaseCaptureBlockedByAnyModalWindow() { - event_processor_.ReleaseCaptureBlockedByAnyModalWindow(); -} - -void WindowManagerState::SetCursorLocation(const gfx::Point& display_pixels, - int64_t display_id) { - Display* display = display_manager()->GetDisplayById(display_id); - if (!display) { - NOTIMPLEMENTED() << "Window manager sent invalid display_id!"; - return; - } - - // MoveCursorTo() implicitly generates a mouse event. - display->platform_display()->MoveCursorTo(display_pixels); -} - -void WindowManagerState::SetKeyEventsThatDontHideCursor( - std::vector<::ui::mojom::EventMatcherPtr> dont_hide_cursor_list) { - event_processor()->SetKeyEventsThatDontHideCursor( - std::move(dont_hide_cursor_list)); -} - -void WindowManagerState::SetCursorTouchVisible(bool enabled) { - cursor_state_.SetCursorTouchVisible(enabled); -} - -void WindowManagerState::SetDragDropSourceWindow( - DragSource* drag_source, - ServerWindow* window, - DragTargetConnection* source_connection, - const base::flat_map<std::string, std::vector<uint8_t>>& drag_data, - uint32_t drag_operation) { - PointerId drag_pointer = MouseEvent::kMousePointerId; - const ui::Event* in_flight_event = event_dispatcher_.GetInFlightEvent(); - if (in_flight_event && in_flight_event->IsPointerEvent()) { - drag_pointer = in_flight_event->AsPointerEvent()->pointer_details().id; - } else { - NOTIMPLEMENTED() << "Set drag drop set up during something other than a " - << "pointer event; rejecting drag."; - drag_source->OnDragCompleted(false, ui::mojom::kDropEffectNone); - return; - } - - event_processor_.SetDragDropSourceWindow(drag_source, window, - source_connection, drag_pointer, - drag_data, drag_operation); -} - -void WindowManagerState::CancelDragDrop() { - event_processor_.CancelDragDrop(); -} - -void WindowManagerState::EndDragDrop() { - event_processor_.EndDragDrop(); - UpdateNativeCursorFromEventProcessor(); -} - -void WindowManagerState::AddSystemModalWindow(ServerWindow* window) { - event_processor_.AddSystemModalWindow(window); -} - -void WindowManagerState::DeleteWindowManagerDisplayRoot( - ServerWindow* display_root) { - for (auto iter = orphaned_window_manager_display_roots_.begin(); - iter != orphaned_window_manager_display_roots_.end(); ++iter) { - if ((*iter)->root() == display_root) { - orphaned_window_manager_display_roots_.erase(iter); - return; - } - } - - for (auto iter = window_manager_display_roots_.begin(); - iter != window_manager_display_roots_.end(); ++iter) { - if ((*iter)->root() == display_root) { - (*iter)->display()->RemoveWindowManagerDisplayRoot((*iter).get()); - window_manager_display_roots_.erase(iter); - return; - } - } -} - -void WindowManagerState::OnWillDestroyTree(WindowTree* tree) { - event_processor_.OnWillDestroyDragTargetConnection(tree); - - event_dispatcher_.OnWillDestroyAsyncEventDispatcher(tree); -} - -void WindowManagerState::ProcessEvent(ui::Event* event, int64_t display_id) { - EventLocation event_location(display_id); - if (event->IsLocatedEvent()) { - event_location.raw_location = event->AsLocatedEvent()->location_f(); - AdjustEventLocation(display_id, event->AsLocatedEvent()); - event_location.location = event->AsLocatedEvent()->root_location_f(); - } - event_dispatcher_.ProcessEvent(event, event_location); -} - -void WindowManagerState::ScheduleCallbackWhenDoneProcessingEvents( - base::OnceClosure closure) { - event_dispatcher_.ScheduleCallbackWhenDoneProcessingEvents( - std::move(closure)); -} - -const WindowServer* WindowManagerState::window_server() const { - return window_tree_->window_server(); -} - -WindowServer* WindowManagerState::window_server() { - return window_tree_->window_server(); -} - -DisplayManager* WindowManagerState::display_manager() { - return window_tree_->display_manager(); -} - -const DisplayManager* WindowManagerState::display_manager() const { - return window_tree_->display_manager(); -} - -void WindowManagerState::AddWindowManagerDisplayRoot( - std::unique_ptr<WindowManagerDisplayRoot> display_root) { - window_manager_display_roots_.push_back(std::move(display_root)); -} - -void WindowManagerState::OnDisplayDestroying(Display* display) { - if (display->platform_display() == platform_display_with_capture_) - platform_display_with_capture_ = nullptr; - - for (auto iter = window_manager_display_roots_.begin(); - iter != window_manager_display_roots_.end(); ++iter) { - if ((*iter)->display() == display) { - if (window_tree_->automatically_create_display_roots()) - (*iter)->root()->AddObserver(this); - orphaned_window_manager_display_roots_.push_back(std::move(*iter)); - window_manager_display_roots_.erase(iter); - window_tree_->OnDisplayDestroying(display->GetId()); - orphaned_window_manager_display_roots_.back()->display_ = nullptr; - return; - } - } -} - -ServerWindow* WindowManagerState::GetWindowManagerRootForDisplayRoot( - ServerWindow* window) { - for (auto& display_root_ptr : window_manager_display_roots_) { - if (display_root_ptr->root()->parent() == window) - return display_root_ptr->GetClientVisibleRoot(); - } - NOTREACHED(); - return nullptr; -} - -void WindowManagerState::AddDebugAccelerators() { - const DebugAccelerator accelerator = { - DebugAcceleratorType::PRINT_WINDOWS, ui::VKEY_S, - ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN | ui::EF_SHIFT_DOWN}; - debug_accelerators_.push_back(accelerator); -} - -void WindowManagerState::ProcessDebugAccelerator(const ui::Event& event, - int64_t display_id) { - if (event.type() != ui::ET_KEY_PRESSED) - return; - - const ui::KeyEvent& key_event = *event.AsKeyEvent(); - for (const DebugAccelerator& accelerator : debug_accelerators_) { - if (accelerator.Matches(key_event)) { - HandleDebugAccelerator(accelerator.type, display_id); - break; - } - } -} - -void WindowManagerState::HandleDebugAccelerator(DebugAcceleratorType type, - int64_t display_id) { -#if DCHECK_IS_ON() - // Error so it will be collected in system logs. - for (Display* display : display_manager()->displays()) { - WindowManagerDisplayRoot* display_root = - display->window_manager_display_root(); - if (display_root) { - LOG(ERROR) << "ServerWindow hierarchy:\n" - << display_root->root()->GetDebugWindowHierarchy(); - } - } - ServerWindow* focused_window = GetFocusedWindowForEventProcessor(display_id); - LOG(ERROR) << "Focused window: " - << (focused_window ? focused_window->frame_sink_id().ToString() - : "(null)"); -#endif -} - -bool WindowManagerState::ConvertPointToScreen(int64_t display_id, - gfx::Point* point) { - Display* display = display_manager()->GetDisplayById(display_id); - if (!display) - return false; - - WindowManagerDisplayRoot* root = display->window_manager_display_root(); - if (!root) - return false; - - const display::Display& originated_display = display->GetDisplay(); - gfx::Transform transform; - transform.Scale(originated_display.device_scale_factor(), - originated_display.device_scale_factor()); - transform *= display->window_manager_display_root() - ->GetClientVisibleRoot() - ->transform(); - gfx::Transform invert; - if (!transform.GetInverse(&invert)) - invert = transform; - auto point_3f = gfx::Point3F(gfx::PointF(*point)); - invert.TransformPoint(&point_3f); - *point = gfx::ToFlooredPoint(point_3f.AsPointF()) + - originated_display.bounds().origin().OffsetFromOrigin(); - return true; -} - -Display* WindowManagerState::FindDisplayContainingPixelLocation( - const gfx::Point& screen_pixels) { - for (auto& display_root_ptr : window_manager_display_roots_) { - if (GetDisplayBoundsInPixels(display_root_ptr->display()) - .Contains(screen_pixels)) { - return display_root_ptr->display(); - } - } - return nullptr; -} - -void WindowManagerState::AdjustEventLocation(int64_t display_id, - LocatedEvent* event) { - if (window_manager_display_roots_.empty()) - return; - - Display* display = display_manager()->GetDisplayById(display_id); - if (!display) - return; - - const gfx::Rect& display_bounds_in_pixels = GetDisplayBoundsInPixels(display); - // Typical case is the display contains the location. - if (gfx::Rect(display_bounds_in_pixels.size()).Contains(event->location())) - return; - - // The location is outside the bounds of the specified display. This generally - // happens when there is a grab and the mouse is moved to another display. - // When this happens the location of the event is in terms of the pixel - // display layout. Find the display using the pixel display layout. - const gfx::Point screen_pixels = - event->location() + display_bounds_in_pixels.origin().OffsetFromOrigin(); - Display* containing_display = - FindDisplayContainingPixelLocation(screen_pixels); - if (!containing_display) { - DVLOG(1) << "Invalid event location " << event->location().ToString() - << " / display id " << display_id; - return; - } - - // Adjust the location of the event to be in terms of the DIP display layout - // (but in pixels). See EventLocation for details on this. - const gfx::Point location_in_containing_display = - screen_pixels - - GetDisplayBoundsInPixels(containing_display).origin().OffsetFromOrigin(); - const gfx::Point screen_dip_location = - containing_display->GetDisplay().bounds().origin() + - PixelsToDips(containing_display, location_in_containing_display) - .OffsetFromOrigin(); - const gfx::Point pixel_relative_location = DipsToPixels( - display, screen_dip_location - - display->GetDisplay().bounds().origin().OffsetFromOrigin()); - event->set_location(pixel_relative_location); - event->set_root_location(pixel_relative_location); -} - -//////////////////////////////////////////////////////////////////////////////// -// EventProcessorDelegate: - -void WindowManagerState::SetFocusedWindowFromEventProcessor( - ServerWindow* new_focused_window) { - window_server()->SetFocusedWindow(new_focused_window); -} - -ServerWindow* WindowManagerState::GetFocusedWindowForEventProcessor( - int64_t display_id) { - ServerWindow* focused_window = window_server()->GetFocusedWindow(); - if (focused_window) - return focused_window; - - // When none of the windows have focus return the window manager's root. - for (auto& display_root_ptr : window_manager_display_roots_) { - if (display_root_ptr->display()->GetId() == display_id) - return display_root_ptr->GetClientVisibleRoot(); - } - if (!window_manager_display_roots_.empty()) - return (*window_manager_display_roots_.begin())->GetClientVisibleRoot(); - return nullptr; -} - -void WindowManagerState::SetNativeCapture(ServerWindow* window) { - DCHECK(window); - - // Classic ash expects no native grab when in unified display. - // See http://crbug.com/773348 for details. - if (display_manager()->InUnifiedDisplayMode()) - return; - - WindowManagerDisplayRoot* display_root = - display_manager()->GetWindowManagerDisplayRoot(window); - DCHECK(display_root); - platform_display_with_capture_ = display_root->display()->platform_display(); - platform_display_with_capture_->SetCapture(); -} - -void WindowManagerState::ReleaseNativeCapture() { - // Classic ash expects no native grab when in unified display. - // See http://crbug.com/773348 for details. - if (display_manager()->InUnifiedDisplayMode()) - return; - - // Tests trigger calling this without a corresponding SetNativeCapture(). - // TODO(sky): maybe abstract this away so that DCHECK can be added? - if (!platform_display_with_capture_) - return; - - platform_display_with_capture_->ReleaseCapture(); - platform_display_with_capture_ = nullptr; -} - -void WindowManagerState::UpdateNativeCursorFromEventProcessor() { - const ui::CursorData cursor = event_processor_.GetCurrentMouseCursor(); - cursor_state_.SetCurrentWindowCursor(cursor); -} - -void WindowManagerState::OnCaptureChanged(ServerWindow* new_capture, - ServerWindow* old_capture) { - window_server()->ProcessCaptureChanged(new_capture, old_capture); -} - -void WindowManagerState::OnMouseCursorLocationChanged( - const gfx::PointF& point_in_display, - int64_t display_id) { - gfx::Point point_in_screen = gfx::ToFlooredPoint(point_in_display); - if (ConvertPointToScreen(display_id, &point_in_screen)) { - window_server() - ->display_manager() - ->cursor_location_manager() - ->OnMouseCursorLocationChanged(point_in_screen); - } - // If the display the |point_in_display| is on has been deleted, keep the old - // cursor location. -} - -void WindowManagerState::OnEventChangesCursorVisibility(const ui::Event& event, - bool visible) { - if (event.IsSynthesized()) - return; - cursor_state_.SetCursorVisible(visible); -} - -void WindowManagerState::OnEventChangesCursorTouchVisibility( - const ui::Event& event, - bool visible) { - if (event.IsSynthesized()) - return; - - // Setting cursor touch visibility needs to cause a callback which notifies a - // caller so we can dispatch the state change to the window manager. - cursor_state_.SetCursorTouchVisible(visible); -} - -ClientSpecificId WindowManagerState::GetEventTargetClientId( - const ServerWindow* window, - bool in_nonclient_area) { - if (in_nonclient_area) { - // Events in the non-client area always go to the window manager. - return window_tree_->id(); - } - - // If the window is an embed root, it goes to the tree embedded in the window. - WindowTree* tree = window_server()->GetTreeWithRoot(window); - if (!tree) { - // Window is not an embed root, event goes to owner of the window. - tree = window_server()->GetTreeWithId(window->owning_tree_id()); - } - DCHECK(tree); - - // Ascend to the first tree marked as not embedder_intercepts_events(). - const ServerWindow* embed_root = - tree->HasRoot(window) ? window : GetEmbedRoot(window); - while (tree && tree->embedder_intercepts_events()) { - DCHECK(tree->HasRoot(embed_root)); - tree = window_server()->GetTreeWithId(embed_root->owning_tree_id()); - embed_root = GetEmbedRoot(embed_root); - } - DCHECK(tree); - return tree->id(); -} - -ServerWindow* WindowManagerState::GetRootWindowForDisplay(int64_t display_id) { - Display* display = display_manager()->GetDisplayById(display_id); - if (!display) - return nullptr; - - return display->window_manager_display_root()->GetClientVisibleRoot(); -} - -ServerWindow* WindowManagerState::GetRootWindowForEventDispatch( - ServerWindow* window) { - for (auto& display_root_ptr : window_manager_display_roots_) { - ServerWindow* client_visible_root = - display_root_ptr->GetClientVisibleRoot(); - if (client_visible_root->Contains(window)) - return client_visible_root; - } - return nullptr; -} - -void WindowManagerState::OnEventTargetNotFound(const ui::Event& event, - int64_t display_id) { - window_server()->SendToPointerWatchers(event, nullptr, /* window */ - nullptr /* ignore_tree */, display_id); - if (event.IsMousePointerEvent()) - UpdateNativeCursorFromEventProcessor(); -} - -ServerWindow* WindowManagerState::GetFallbackTargetForEventBlockedByModal( - ServerWindow* window) { - DCHECK(window); - // TODO(sky): reevaluate when http://crbug.com/646998 is fixed. - return GetWindowManagerRootForDisplayRoot(window); -} - -void WindowManagerState::OnEventOccurredOutsideOfModalWindow( - ServerWindow* modal_window) { - window_tree_->OnEventOccurredOutsideOfModalWindow(modal_window); -} - -viz::HitTestQuery* WindowManagerState::GetHitTestQueryForDisplay( - int64_t display_id) { - Display* display = display_manager()->GetDisplayById(display_id); - if (!display) - return nullptr; - - return window_server()->GetVizHostProxy()->GetHitTestQuery( - display->root_window()->frame_sink_id()); -} - -ServerWindow* WindowManagerState::GetWindowFromFrameSinkId( - const viz::FrameSinkId& frame_sink_id) { - DCHECK(frame_sink_id.is_valid()); - return window_tree()->GetWindowByClientId(frame_sink_id); -} - -void WindowManagerState::OnWindowEmbeddedAppDisconnected(ServerWindow* window) { - for (auto iter = orphaned_window_manager_display_roots_.begin(); - iter != orphaned_window_manager_display_roots_.end(); ++iter) { - if ((*iter)->root() == window) { - window->RemoveObserver(this); - orphaned_window_manager_display_roots_.erase(iter); - return; - } - } - NOTREACHED(); -} - -void WindowManagerState::OnCursorTouchVisibleChanged(bool enabled) { - window_tree_->OnCursorTouchVisibleChanged(enabled); -} - -ServerWindow* WindowManagerState::OnWillDispatchInputEvent( - ServerWindow* target, - ClientSpecificId client_id, - const EventLocation& event_location, - const Event& event) { - if (target->parent() == nullptr) { - // The target is a display root, redirect to the WindowManager's root so - // that the WindowManager is passed a window it knows. - target = GetWindowManagerRootForDisplayRoot(target); - } - if (event.IsMousePointerEvent()) - UpdateNativeCursorFromEventProcessor(); - WindowTree* tree = window_server()->GetTreeWithId(client_id); - DCHECK(tree); - // Ignore |tree| because it will receive the event via normal dispatch. - window_server()->SendToPointerWatchers(event, target, tree, - event_location.display_id); - return target; -} - -void WindowManagerState::OnEventDispatchTimedOut( - AsyncEventDispatcher* async_event_dispatcher) { - DCHECK(async_event_dispatcher); - WindowTree* hung_tree = static_cast<WindowTree*>(async_event_dispatcher); - if (!hung_tree->janky()) - window_tree_->ClientJankinessChanged(hung_tree); -} - -void WindowManagerState::OnAsyncEventDispatcherHandledAccelerator( - const Event& event, - int64_t display_id) { - window_server()->SendToPointerWatchers(event, nullptr, nullptr, display_id); -} - -void WindowManagerState::OnWillProcessEvent( - const ui::Event& event, - const EventLocation& event_location) { - // Debug accelerators are always checked and don't interfere with processing. - ProcessDebugAccelerator(event, event_location.display_id); -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/window_manager_state.h b/services/ui/ws/window_manager_state.h deleted file mode 100644 index b012826..0000000 --- a/services/ui/ws/window_manager_state.h +++ /dev/null
@@ -1,275 +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. - -#ifndef SERVICES_UI_WS_WINDOW_MANAGER_STATE_H_ -#define SERVICES_UI_WS_WINDOW_MANAGER_STATE_H_ - -#include <stdint.h> - -#include <memory> -#include <string> -#include <vector> - -#include "base/containers/flat_map.h" -#include "base/memory/weak_ptr.h" -#include "base/timer/timer.h" -#include "services/ui/public/interfaces/screen_provider.mojom.h" -#include "services/ui/ws/cursor_state.h" -#include "services/ui/ws/cursor_state_delegate.h" -#include "services/ui/ws/event_dispatcher_delegate.h" -#include "services/ui/ws/event_dispatcher_impl.h" -#include "services/ui/ws/event_processor.h" -#include "services/ui/ws/event_processor_delegate.h" -#include "services/ui/ws/server_window_observer.h" -#include "services/ui/ws/window_server.h" - -namespace viz { -class HitTestQuery; -} - -namespace ui { -namespace ws { - -class DisplayManager; -class EventDispatcherImpl; -class PlatformDisplay; -class WindowManagerDisplayRoot; -class WindowTree; - -namespace test { -class WindowManagerStateTestApi; -} - -// Manages state specific to a WindowManager that is shared across displays. -// WindowManagerState is owned by the WindowTree the window manager is -// associated with. -class WindowManagerState : public EventProcessorDelegate, - public ServerWindowObserver, - public CursorStateDelegate, - public EventDispatcherDelegate { - public: - explicit WindowManagerState(WindowTree* window_tree); - ~WindowManagerState() override; - - WindowTree* window_tree() { return window_tree_; } - const WindowTree* window_tree() const { return window_tree_; } - - void OnWillDestroyTree(WindowTree* tree); - - void SetFrameDecorationValues(mojom::FrameDecorationValuesPtr values); - const mojom::FrameDecorationValues& frame_decoration_values() const { - return *frame_decoration_values_; - } - bool got_frame_decoration_values() const { - return got_frame_decoration_values_; - } - - bool SetCapture(ServerWindow* window, ClientSpecificId client_id); - ServerWindow* capture_window() { return event_processor_.capture_window(); } - const ServerWindow* capture_window() const { - return event_processor_.capture_window(); - } - - void ReleaseCaptureBlockedByAnyModalWindow(); - - // Sets the location of the cursor to a location on display |display_id|. - void SetCursorLocation(const gfx::Point& display_pixels, int64_t display_id); - - void SetKeyEventsThatDontHideCursor( - std::vector<::ui::mojom::EventMatcherPtr> dont_hide_cursor_list); - - void SetCursorTouchVisible(bool enabled); - - void SetDragDropSourceWindow( - DragSource* drag_source, - ServerWindow* window, - DragTargetConnection* source_connection, - const base::flat_map<std::string, std::vector<uint8_t>>& drag_data, - uint32_t drag_operation); - void CancelDragDrop(); - void EndDragDrop(); - - void AddSystemModalWindow(ServerWindow* window); - - // Deletes the WindowManagerDisplayRoot whose root is |display_root|. - void DeleteWindowManagerDisplayRoot(ServerWindow* display_root); - - // TODO(sky): EventProcessor is really an implementation detail and should - // not be exposed. - EventProcessor* event_processor() { return &event_processor_; } - - CursorState& cursor_state() { return cursor_state_; } - - // Processes an event from PlatformDisplay. This doesn't take ownership of - // |event|, but it may modify it. - void ProcessEvent(ui::Event* event, int64_t display_id); - - // Notifies |closure| once done processing currently queued events. This - // notifies |closure| immediately if IsProcessingEvent() returns false. - void ScheduleCallbackWhenDoneProcessingEvents(base::OnceClosure closure); - - PlatformDisplay* platform_display_with_capture() { - return platform_display_with_capture_; - } - - private: - friend class Display; - friend class test::WindowManagerStateTestApi; - - // Set of display roots. This is a vector rather than a set to support removal - // without deleting. - using WindowManagerDisplayRoots = - std::vector<std::unique_ptr<WindowManagerDisplayRoot>>; - - enum class DebugAcceleratorType { - PRINT_WINDOWS, - }; - - struct DebugAccelerator { - bool Matches(const KeyEvent& event) const; - - DebugAcceleratorType type; - KeyboardCode key_code; - int event_flags; - }; - - const WindowServer* window_server() const; - WindowServer* window_server(); - - DisplayManager* display_manager(); - const DisplayManager* display_manager() const; - - // Adds |display_root| to the set of WindowManagerDisplayRoots owned by this - // WindowManagerState. - void AddWindowManagerDisplayRoot( - std::unique_ptr<WindowManagerDisplayRoot> display_root); - - // Called when a Display is deleted. - void OnDisplayDestroying(Display* display); - - // Returns the ServerWindow that is the root of the WindowManager for - // |window|. |window| corresponds to the root of a Display. - ServerWindow* GetWindowManagerRootForDisplayRoot(ServerWindow* window); - - // Called if the client doesn't ack an event in the appropriate amount of - // time. - void OnEventAckTimeout(ClientSpecificId client_id); - - // Implemenation of processing an event with a match phase of all. This - // handles debug accelerators and forwards to EventProcessor. - void ProcessEventImpl(const Event& event, - const EventLocation& event_location); - - // Dispatches the event to the appropriate client and starts the ack timer. - void DispatchInputEventToWindowImpl(ServerWindow* target, - ClientSpecificId client_id, - const EventLocation& event_location, - const Event& event, - base::WeakPtr<Accelerator> accelerator); - - // Registers accelerators used internally for debugging. - void AddDebugAccelerators(); - - // Finds the debug accelerator for |event| and if one is found calls - // HandleDebugAccelerator(). - void ProcessDebugAccelerator(const Event& event, int64_t display_id); - - // Runs the specified debug accelerator. - void HandleDebugAccelerator(DebugAcceleratorType type, int64_t display_id); - - // Processes queued event tasks until there are no more, or we're waiting on - // a client or the EventDisptacher to complete processing. - void ProcessEventTasks(); - - // Helper function to convert |point| to be in screen coordinates. |point| as - // the input should be in display-physical-pixel space, and the output is in - // screen-dip space. Returns true if the |point| is successfully converted, - // false otherwise. - bool ConvertPointToScreen(int64_t display_id, gfx::Point* point); - - Display* FindDisplayContainingPixelLocation(const gfx::Point& screen_pixels); - - void AdjustEventLocation(int64_t display_id, LocatedEvent* event); - - // EventProcessorDelegate: - void SetFocusedWindowFromEventProcessor(ServerWindow* window) override; - ServerWindow* GetFocusedWindowForEventProcessor(int64_t display_id) override; - void SetNativeCapture(ServerWindow* window) override; - void ReleaseNativeCapture() override; - void UpdateNativeCursorFromEventProcessor() override; - void OnCaptureChanged(ServerWindow* new_capture, - ServerWindow* old_capture) override; - void OnMouseCursorLocationChanged(const gfx::PointF& point, - int64_t display_id) override; - void OnEventChangesCursorVisibility(const ui::Event& event, - bool visible) override; - void OnEventChangesCursorTouchVisibility(const ui::Event& event, - bool visible) override; - ClientSpecificId GetEventTargetClientId(const ServerWindow* window, - bool in_nonclient_area) override; - ServerWindow* GetRootWindowForDisplay(int64_t display_id) override; - ServerWindow* GetRootWindowForEventDispatch(ServerWindow* window) override; - void OnEventTargetNotFound(const Event& event, int64_t display_id) override; - ServerWindow* GetFallbackTargetForEventBlockedByModal( - ServerWindow* window) override; - void OnEventOccurredOutsideOfModalWindow(ServerWindow* modal_window) override; - viz::HitTestQuery* GetHitTestQueryForDisplay(int64_t display_id) override; - ServerWindow* GetWindowFromFrameSinkId( - const viz::FrameSinkId& frame_sink_id) override; - - // ServerWindowObserver: - void OnWindowEmbeddedAppDisconnected(ServerWindow* window) override; - - // CursorStateDelegate: - void OnCursorTouchVisibleChanged(bool enabled) override; - - // EventDispatcherDelegate: - ServerWindow* OnWillDispatchInputEvent(ServerWindow* target, - ClientSpecificId client_id, - const EventLocation& event_location, - const Event& event) override; - void OnEventDispatchTimedOut( - AsyncEventDispatcher* async_event_dipsatcher) override; - void OnAsyncEventDispatcherHandledAccelerator(const Event& event, - int64_t display_id) override; - void OnWillProcessEvent(const ui::Event& event, - const EventLocation& event_location) override; - - // The single WindowTree this WindowManagerState is associated with. - // |window_tree_| owns this. - WindowTree* window_tree_; - - // Set to true the first time SetFrameDecorationValues() is called. - bool got_frame_decoration_values_ = false; - mojom::FrameDecorationValuesPtr frame_decoration_values_; - - std::vector<DebugAccelerator> debug_accelerators_; - - EventDispatcherImpl event_dispatcher_; - - EventProcessor event_processor_; - - // PlatformDisplay that currently has capture. - PlatformDisplay* platform_display_with_capture_ = nullptr; - - // All the active WindowManagerDisplayRoots. - WindowManagerDisplayRoots window_manager_display_roots_; - - // Set of WindowManagerDisplayRoots corresponding to Displays that have been - // destroyed. WindowManagerDisplayRoots are not destroyed immediately when - // the Display is destroyed to allow the client to destroy the window when it - // wants to. Once the client destroys the window WindowManagerDisplayRoots is - // destroyed. - WindowManagerDisplayRoots orphaned_window_manager_display_roots_; - - // All state regarding what the current cursor is. - CursorState cursor_state_; - - DISALLOW_COPY_AND_ASSIGN(WindowManagerState); -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_WINDOW_MANAGER_STATE_H_
diff --git a/services/ui/ws/window_manager_state_unittest.cc b/services/ui/ws/window_manager_state_unittest.cc deleted file mode 100644 index 0ba2715..0000000 --- a/services/ui/ws/window_manager_state_unittest.cc +++ /dev/null
@@ -1,1004 +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 "services/ui/ws/window_manager_state.h" - -#include <memory> - -#include "base/command_line.h" -#include "base/containers/flat_map.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/test/test_simple_task_runner.h" -#include "base/threading/thread_task_runner_handle.h" -#include "services/service_manager/public/mojom/connector.mojom.h" -#include "services/ui/common/accelerator_util.h" -#include "services/ui/common/switches.h" -#include "services/ui/ws/accelerator.h" -#include "services/ui/ws/cursor_location_manager.h" -#include "services/ui/ws/display.h" -#include "services/ui/ws/display_manager.h" -#include "services/ui/ws/event_location.h" -#include "services/ui/ws/platform_display.h" -#include "services/ui/ws/test_change_tracker.h" -#include "services/ui/ws/test_server_window_delegate.h" -#include "services/ui/ws/test_utils.h" -#include "services/ui/ws/window_manager_access_policy.h" -#include "services/ui/ws/window_manager_display_root.h" -#include "services/ui/ws/window_manager_state.h" -#include "services/ui/ws/window_server.h" -#include "services/ui/ws/window_tree.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/base/cursor/cursor.h" -#include "ui/events/event.h" - -namespace ui { -namespace ws { -namespace test { - -// Used in checking if an event was processed. See usage for examples. -void SetBoolToTrue(bool* value) { - *value = true; -} - -class WindowManagerStateTest : public testing::Test { - public: - WindowManagerStateTest(); - ~WindowManagerStateTest() override {} - - std::unique_ptr<Accelerator> CreateAccelerator(); - - // Creates a child |server_window| with associataed |window_tree| and - // |test_client|. The window is setup for processing input. - void CreateSecondaryTree(TestWindowTreeClient** test_client, - WindowTree** window_tree, - ServerWindow** server_window); - - void DispatchInputEventToWindow(ServerWindow* target, - const EventLocation& event_location, - const ui::Event& event, - Accelerator* accelerator); - void OnEventAckTimeout(ClientSpecificId client_id); - - // This is the tree associated with the WindowManagerState. That is, this is - // the WindowTree of the WindowManager. - WindowTree* tree() { - return window_event_targeting_helper_.window_server()->GetTreeWithId( - kWindowManagerClientId); - } - // This is *not* the tree associated with the WindowManagerState, use tree() - // if you need the window manager tree. - WindowTree* window_tree() { return window_tree_; } - TestWindowTreeClient* window_tree_client() { return window_tree_client_; } - ServerWindow* window() { return window_; } - TestWindowManager* window_manager() { return &window_manager_; } - TestWindowTreeClient* wm_client() { - return window_event_targeting_helper_.wm_client(); - } - WindowManagerState* window_manager_state() { return window_manager_state_; } - WindowServer* window_server() { - return window_event_targeting_helper_.window_server(); - } - ui::CursorType cursor_type() const { - return window_event_targeting_helper_.cursor_type(); - } - - void EmbedAt(WindowTree* tree, - const ClientWindowId& embed_window_id, - uint32_t embed_flags, - WindowTree** embed_tree, - TestWindowTreeClient** embed_client_proxy) { - mojom::WindowTreeClientPtr embed_client; - auto client_request = mojo::MakeRequest(&embed_client); - ASSERT_TRUE( - tree->Embed(embed_window_id, std::move(embed_client), embed_flags)); - TestWindowTreeClient* client = - window_event_targeting_helper_.last_window_tree_client(); - ASSERT_EQ(1u, client->tracker()->changes()->size()); - EXPECT_EQ(CHANGE_TYPE_EMBED, (*client->tracker()->changes())[0].type); - client->tracker()->changes()->clear(); - *embed_client_proxy = client; - *embed_tree = window_event_targeting_helper_.last_binding()->tree(); - } - - void DestroyWindowTree() { - window_event_targeting_helper_.window_server()->DestroyTree(window_tree_); - window_tree_ = nullptr; - } - - // testing::Test: - void SetUp() override; - - protected: - // Handles WindowStateManager ack timeouts. - scoped_refptr<base::TestSimpleTaskRunner> task_runner_; - - private: - WindowEventTargetingHelper window_event_targeting_helper_; - - WindowManagerState* window_manager_state_; - - TestWindowManager window_manager_; - ServerWindow* window_ = nullptr; - WindowTree* window_tree_ = nullptr; - TestWindowTreeClient* window_tree_client_ = nullptr; - - DISALLOW_COPY_AND_ASSIGN(WindowManagerStateTest); -}; - -WindowManagerStateTest::WindowManagerStateTest() - : task_runner_(new base::TestSimpleTaskRunner) {} - -std::unique_ptr<Accelerator> WindowManagerStateTest::CreateAccelerator() { - mojom::EventMatcherPtr matcher = ui::CreateKeyMatcher( - ui::mojom::KeyboardCode::W, ui::mojom::kEventFlagControlDown); - matcher->accelerator_phase = ui::mojom::AcceleratorPhase::POST_TARGET; - uint32_t accelerator_id = 1; - std::unique_ptr<Accelerator> accelerator( - new Accelerator(accelerator_id, *matcher)); - return accelerator; -} - -void WindowManagerStateTest::CreateSecondaryTree( - TestWindowTreeClient** test_client, - WindowTree** window_tree, - ServerWindow** server_window) { - window_event_targeting_helper_.CreateSecondaryTree( - window_, gfx::Rect(20, 20, 20, 20), test_client, window_tree, - server_window); -} - -void WindowManagerStateTest::DispatchInputEventToWindow( - ServerWindow* target, - const EventLocation& event_location, - const ui::Event& event, - Accelerator* accelerator) { - WindowManagerStateTestApi test_api(window_manager_state_); - ClientSpecificId client_id = test_api.GetEventTargetClientId(target, false); - test_api.DispatchInputEventToWindow(target, client_id, event_location, event, - accelerator); -} - -void WindowManagerStateTest::OnEventAckTimeout( - ClientSpecificId client_id) { - WindowManagerStateTestApi test_api(window_manager_state_); - test_api.OnEventAckTimeout(client_id); -} - -void WindowManagerStateTest::SetUp() { - window_event_targeting_helper_.SetTaskRunner(task_runner_); - window_manager_state_ = window_event_targeting_helper_.display() - ->window_manager_display_root() - ->window_manager_state(); - window_ = window_event_targeting_helper_.CreatePrimaryTree( - gfx::Rect(0, 0, 100, 100), gfx::Rect(0, 0, 50, 50)); - window_tree_ = window_event_targeting_helper_.last_binding()->tree(); - window_tree_client_ = - window_event_targeting_helper_.last_window_tree_client(); - ASSERT_TRUE(window_tree_->HasRoot(window_)); - - WindowTreeTestApi(tree()).set_window_manager_internal(&window_manager_); - wm_client()->tracker()->changes()->clear(); - window_tree_client_->tracker()->changes()->clear(); -} - -void SetCanFocusUp(ServerWindow* window) { - while (window) { - window->set_can_focus(true); - window = window->parent(); - } -} - -class WindowManagerStateTestAsync : public WindowManagerStateTest { - public: - WindowManagerStateTestAsync() {} - ~WindowManagerStateTestAsync() override {} - - // WindowManagerStateTest: - void SetUp() override { - base::CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kUseAsyncEventTargeting); - WindowManagerStateTest::SetUp(); - } - - private: - DISALLOW_COPY_AND_ASSIGN(WindowManagerStateTestAsync); -}; - -EventLocation EventLocationFromEvent(const Event& event, - const Display& display) { - EventLocation event_location(display.GetId()); - if (event.IsLocatedEvent()) { - event_location.raw_location = event_location.location = - event.AsLocatedEvent()->root_location_f(); - } - return event_location; -} - -// Tests that when an event is dispatched with no accelerator, that post target -// accelerator is not triggered. -TEST_F(WindowManagerStateTest, NullAccelerator) { - WindowManagerState* state = window_manager_state(); - EXPECT_TRUE(state); - - ServerWindow* target = window(); - const Display* display = window_tree()->GetDisplay(target); - ASSERT_TRUE(display); - ui::KeyEvent key(ui::ET_KEY_PRESSED, ui::VKEY_W, ui::EF_CONTROL_DOWN); - DispatchInputEventToWindow(target, EventLocationFromEvent(key, *display), key, - nullptr); - WindowTree* target_tree = window_tree(); - TestChangeTracker* tracker = window_tree_client()->tracker(); - ASSERT_EQ(1u, tracker->changes()->size()); - EXPECT_EQ( - "InputEvent window=" + kWindowManagerClientIdString + ",1 event_action=7", - ChangesToDescription1(*tracker->changes())[0]); - - WindowTreeTestApi(target_tree).AckOldestEvent(); - EXPECT_FALSE(window_manager()->on_accelerator_called()); -} - -// Tests that when a post target accelerator is provided on an event, that it is -// called on ack. -TEST_F(WindowManagerStateTest, PostTargetAccelerator) { - ui::KeyEvent key(ui::ET_KEY_PRESSED, ui::VKEY_W, ui::EF_CONTROL_DOWN); - std::unique_ptr<Accelerator> accelerator = CreateAccelerator(); - - ServerWindow* target = window(); - const Display* display = window_tree()->GetDisplay(target); - ASSERT_TRUE(display); - DispatchInputEventToWindow(target, EventLocationFromEvent(key, *display), key, - accelerator.get()); - TestChangeTracker* tracker = window_tree_client()->tracker(); - ASSERT_EQ(1u, tracker->changes()->size()); - EXPECT_EQ( - "InputEvent window=" + kWindowManagerClientIdString + ",1 event_action=7", - ChangesToDescription1(*tracker->changes())[0]); - - WindowTreeTestApi(window_tree()).AckOldestEvent(); - EXPECT_TRUE(window_manager()->on_accelerator_called()); - EXPECT_EQ(accelerator->id(), window_manager()->on_accelerator_id()); -} - -// Tests that if a pre target accelerator consumes the event no other processing -// is done. -TEST_F(WindowManagerStateTest, PreTargetConsumed) { - // Set up two trees with focus on a child in the second. - const ClientWindowId child_window_id(window_tree()->id(), 11); - window_tree()->NewWindow(child_window_id, ServerWindow::Properties()); - ServerWindow* child_window = - window_tree()->GetWindowByClientId(child_window_id); - window_tree()->AddWindow(FirstRootId(window_tree()), child_window_id); - child_window->SetVisible(true); - SetCanFocusUp(child_window); - child_window->parent()->set_is_activation_parent(true); - ASSERT_TRUE(window_tree()->SetFocus(child_window_id)); - - // Register a pre-accelerator. - uint32_t accelerator_id = 11; - { - mojom::EventMatcherPtr matcher = ui::CreateKeyMatcher( - ui::mojom::KeyboardCode::W, ui::mojom::kEventFlagControlDown); - - ASSERT_TRUE(window_manager_state()->event_processor()->AddAccelerator( - accelerator_id, std::move(matcher))); - } - TestChangeTracker* tracker = wm_client()->tracker(); - tracker->changes()->clear(); - TestChangeTracker* tracker2 = window_tree_client()->tracker(); - tracker2->changes()->clear(); - - // Send and ensure only the pre accelerator is called. - ui::KeyEvent key(ui::ET_KEY_PRESSED, ui::VKEY_W, ui::EF_CONTROL_DOWN); - bool was_event_processed = false; - window_manager_state()->ProcessEvent(&key, 0); - window_manager_state()->ScheduleCallbackWhenDoneProcessingEvents( - base::BindOnce(&SetBoolToTrue, &was_event_processed)); - EXPECT_TRUE(window_manager()->on_accelerator_called()); - EXPECT_EQ(accelerator_id, window_manager()->on_accelerator_id()); - EXPECT_TRUE(tracker->changes()->empty()); - EXPECT_TRUE(tracker2->changes()->empty()); - EXPECT_FALSE(was_event_processed); - - // Ack the accelerator, saying we consumed it. - WindowTreeTestApi(tree()).AckLastAccelerator(mojom::EventResult::HANDLED); - EXPECT_TRUE(was_event_processed); - // Nothing should change. - EXPECT_TRUE(tracker->changes()->empty()); - EXPECT_TRUE(tracker2->changes()->empty()); - - was_event_processed = false; - window_manager()->ClearAcceleratorCalled(); - - // Repeat, but respond with UNHANDLED. - window_manager_state()->ProcessEvent(&key, 0); - window_manager_state()->ScheduleCallbackWhenDoneProcessingEvents( - base::BindOnce(&SetBoolToTrue, &was_event_processed)); - EXPECT_FALSE(was_event_processed); - EXPECT_TRUE(window_manager()->on_accelerator_called()); - EXPECT_EQ(accelerator_id, window_manager()->on_accelerator_id()); - EXPECT_TRUE(tracker->changes()->empty()); - EXPECT_TRUE(tracker2->changes()->empty()); - WindowTreeTestApi(tree()).AckLastAccelerator(mojom::EventResult::UNHANDLED); - // |was_event_processed| is false because the accelerator wasn't completely - // handled yet. - EXPECT_FALSE(was_event_processed); - - EXPECT_TRUE(tracker->changes()->empty()); - // The focused window should get the event. - EXPECT_EQ("InputEvent window=0,11 event_action=7", - SingleChangeToDescription(*tracker2->changes())); - WindowTreeTestApi(window_tree()).AckLastEvent(mojom::EventResult::HANDLED); - EXPECT_TRUE(was_event_processed); -} - -TEST_F(WindowManagerStateTest, AckWithProperties) { - // Set up two trees with focus on a child in the second. - const ClientWindowId child_window_id(window_tree()->id(), 11); - window_tree()->NewWindow(child_window_id, ServerWindow::Properties()); - ServerWindow* child_window = - window_tree()->GetWindowByClientId(child_window_id); - window_tree()->AddWindow(FirstRootId(window_tree()), child_window_id); - child_window->SetVisible(true); - SetCanFocusUp(child_window); - child_window->parent()->set_is_activation_parent(true); - ASSERT_TRUE(window_tree()->SetFocus(child_window_id)); - - // Register a pre-accelerator. - uint32_t accelerator_id = 11; - { - mojom::EventMatcherPtr matcher = ui::CreateKeyMatcher( - ui::mojom::KeyboardCode::W, ui::mojom::kEventFlagControlDown); - - ASSERT_TRUE(window_manager_state()->event_processor()->AddAccelerator( - accelerator_id, std::move(matcher))); - } - TestChangeTracker* tracker = wm_client()->tracker(); - tracker->changes()->clear(); - TestChangeTracker* tracker2 = window_tree_client()->tracker(); - tracker2->changes()->clear(); - - // Send and ensure only the pre accelerator is called. - ui::KeyEvent key(ui::ET_KEY_PRESSED, ui::VKEY_W, ui::EF_CONTROL_DOWN); - window_manager_state()->ProcessEvent(&key, 0); - EXPECT_TRUE(window_manager()->on_accelerator_called()); - EXPECT_EQ(accelerator_id, window_manager()->on_accelerator_id()); - EXPECT_TRUE(tracker->changes()->empty()); - EXPECT_TRUE(tracker2->changes()->empty()); - - // Ack the accelerator, with unhandled. - base::flat_map<std::string, std::vector<uint8_t>> event_properties; - const std::string property_key = "x"; - const std::vector<uint8_t> property_value(2, 0xAB); - event_properties[property_key] = property_value; - EXPECT_TRUE(tracker->changes()->empty()); - EXPECT_TRUE(tracker2->changes()->empty()); - WindowTreeTestApi(tree()).AckLastAccelerator(mojom::EventResult::UNHANDLED, - event_properties); - - // The focused window should get the event. - EXPECT_EQ("InputEvent window=0,11 event_action=7", - SingleChangeToDescription(*tracker2->changes())); - ASSERT_EQ(1u, tracker2->changes()->size()); - EXPECT_EQ(1u, (*tracker2->changes())[0].key_event_properties.size()); - EXPECT_EQ(event_properties, (*tracker2->changes())[0].key_event_properties); - - WindowTreeTestApi(window_tree()).AckLastEvent(mojom::EventResult::HANDLED); - tracker2->changes()->clear(); - - // Send the event again, and ack with no properties. Ensure client gets no - // properties. - window_manager()->ClearAcceleratorCalled(); - window_manager_state()->ProcessEvent(&key, 0); - EXPECT_TRUE(window_manager()->on_accelerator_called()); - EXPECT_EQ(accelerator_id, window_manager()->on_accelerator_id()); - EXPECT_TRUE(tracker->changes()->empty()); - EXPECT_TRUE(tracker2->changes()->empty()); - - // Ack the accelerator with unhandled. - WindowTreeTestApi(tree()).AckLastAccelerator(mojom::EventResult::UNHANDLED); - - // The focused window should get the event. - EXPECT_EQ("InputEvent window=0,11 event_action=7", - SingleChangeToDescription(*tracker2->changes())); - ASSERT_EQ(1u, tracker2->changes()->size()); - EXPECT_TRUE((*tracker2->changes())[0].key_event_properties.empty()); -} - -// Tests that when a client handles an event that post target accelerators are -// not called. -TEST_F(WindowManagerStateTest, ClientHandlesEvent) { - ui::KeyEvent key(ui::ET_KEY_PRESSED, ui::VKEY_W, ui::EF_CONTROL_DOWN); - std::unique_ptr<Accelerator> accelerator = CreateAccelerator(); - - ServerWindow* target = window(); - const Display* display = window_tree()->GetDisplay(target); - ASSERT_TRUE(display); - DispatchInputEventToWindow(target, EventLocationFromEvent(key, *display), key, - accelerator.get()); - TestChangeTracker* tracker = window_tree_client()->tracker(); - ASSERT_EQ(1u, tracker->changes()->size()); - EXPECT_EQ( - "InputEvent window=" + kWindowManagerClientIdString + ",1 event_action=7", - ChangesToDescription1(*tracker->changes())[0]); - - EXPECT_TRUE(WindowManagerStateTestApi(window_manager_state()) - .AckInFlightEvent(mojom::EventResult::HANDLED)); - EXPECT_FALSE(window_manager()->on_accelerator_called()); -} - -// Tests that when an accelerator is deleted before an ack, that it is not -// called. -TEST_F(WindowManagerStateTest, AcceleratorDeleted) { - ui::KeyEvent key(ui::ET_KEY_PRESSED, ui::VKEY_W, ui::EF_CONTROL_DOWN); - std::unique_ptr<Accelerator> accelerator(CreateAccelerator()); - - ServerWindow* target = window(); - const Display* display = window_tree()->GetDisplay(target); - ASSERT_TRUE(display); - DispatchInputEventToWindow(target, EventLocationFromEvent(key, *display), key, - accelerator.get()); - TestChangeTracker* tracker = window_tree_client()->tracker(); - ASSERT_EQ(1u, tracker->changes()->size()); - EXPECT_EQ( - "InputEvent window=" + kWindowManagerClientIdString + ",1 event_action=7", - ChangesToDescription1(*tracker->changes())[0]); - - accelerator.reset(); - EXPECT_TRUE(WindowManagerStateTestApi(window_manager_state()) - .AckInFlightEvent(mojom::EventResult::UNHANDLED)); - EXPECT_FALSE(window_manager()->on_accelerator_called()); -} - -// Tests that a events arriving before an ack don't notify the tree until the -// ack arrives, and that the correct accelerator is called. -TEST_F(WindowManagerStateTest, EnqueuedAccelerators) { - ui::KeyEvent key(ui::ET_KEY_PRESSED, ui::VKEY_W, ui::EF_CONTROL_DOWN); - std::unique_ptr<Accelerator> accelerator(CreateAccelerator()); - - ServerWindow* target = window(); - const Display* display = window_tree()->GetDisplay(target); - ASSERT_TRUE(display); - DispatchInputEventToWindow(target, EventLocationFromEvent(key, *display), key, - accelerator.get()); - TestChangeTracker* tracker = window_tree_client()->tracker(); - ASSERT_EQ(1u, tracker->changes()->size()); - EXPECT_EQ( - "InputEvent window=" + kWindowManagerClientIdString + ",1 event_action=7", - ChangesToDescription1(*tracker->changes())[0]); - - tracker->changes()->clear(); - ui::KeyEvent key2(ui::ET_KEY_PRESSED, ui::VKEY_Y, ui::EF_CONTROL_DOWN); - mojom::EventMatcherPtr matcher = ui::CreateKeyMatcher( - ui::mojom::KeyboardCode::Y, ui::mojom::kEventFlagControlDown); - matcher->accelerator_phase = ui::mojom::AcceleratorPhase::POST_TARGET; - uint32_t accelerator_id = 2; - std::unique_ptr<Accelerator> accelerator2( - new Accelerator(accelerator_id, *matcher)); - DispatchInputEventToWindow(target, EventLocationFromEvent(key2, *display), - key2, accelerator2.get()); - EXPECT_TRUE(tracker->changes()->empty()); - - WindowTreeTestApi(window_tree()).AckOldestEvent(); - ASSERT_EQ(1u, tracker->changes()->size()); - EXPECT_EQ( - "InputEvent window=" + kWindowManagerClientIdString + ",1 event_action=7", - ChangesToDescription1(*tracker->changes())[0]); - EXPECT_TRUE(window_manager()->on_accelerator_called()); - EXPECT_EQ(accelerator->id(), window_manager()->on_accelerator_id()); -} - -// Tests that the accelerator is not sent when the tree is dying. -TEST_F(WindowManagerStateTest, DeleteTree) { - ui::KeyEvent key(ui::ET_KEY_PRESSED, ui::VKEY_W, ui::EF_CONTROL_DOWN); - std::unique_ptr<Accelerator> accelerator = CreateAccelerator(); - - ServerWindow* target = window(); - const Display* display = window_tree()->GetDisplay(target); - ASSERT_TRUE(display); - DispatchInputEventToWindow(target, EventLocationFromEvent(key, *display), key, - accelerator.get()); - TestChangeTracker* tracker = window_tree_client()->tracker(); - ASSERT_EQ(1u, tracker->changes()->size()); - EXPECT_EQ( - "InputEvent window=" + kWindowManagerClientIdString + ",1 event_action=7", - ChangesToDescription1(*tracker->changes())[0]); - - window_manager_state()->OnWillDestroyTree(tree()); - EXPECT_FALSE(window_manager()->on_accelerator_called()); -} - -// Tests that if a tree is destroyed before acking, that the accelerator is -// still sent if it is not the root tree. -TEST_F(WindowManagerStateTest, DeleteNonRootTree) { - TestWindowTreeClient* embed_connection = nullptr; - WindowTree* target_tree = nullptr; - ServerWindow* target = nullptr; - CreateSecondaryTree(&embed_connection, &target_tree, &target); - TestWindowManager target_window_manager; - WindowTreeTestApi(target_tree) - .set_window_manager_internal(&target_window_manager); - - ui::KeyEvent key(ui::ET_KEY_PRESSED, ui::VKEY_W, ui::EF_CONTROL_DOWN); - std::unique_ptr<Accelerator> accelerator = CreateAccelerator(); - const Display* display = target_tree->GetDisplay(target); - ASSERT_TRUE(display); - DispatchInputEventToWindow(target, EventLocationFromEvent(key, *display), key, - accelerator.get()); - TestChangeTracker* tracker = embed_connection->tracker(); - ASSERT_EQ(1u, tracker->changes()->size()); - // clients that created this window is receiving the event, so client_id part - // would be reset to 0 before sending back to clients. - EXPECT_EQ("InputEvent window=0," + std::to_string(kEmbedTreeWindowId) + - " event_action=7", - ChangesToDescription1(*tracker->changes())[0]); - EXPECT_TRUE(wm_client()->tracker()->changes()->empty()); - - window_manager_state()->OnWillDestroyTree(target_tree); - EXPECT_FALSE(target_window_manager.on_accelerator_called()); - EXPECT_TRUE(window_manager()->on_accelerator_called()); -} - -// Tests that if a tree is destroyed before acking an event, that mus won't -// then try to send any queued events. -TEST_F(WindowManagerStateTest, DontSendQueuedEventsToADeadTree) { - ServerWindow* target = window(); - TestChangeTracker* tracker = window_tree_client()->tracker(); - - const Display* display = window_tree()->GetDisplay(target); - ASSERT_TRUE(display); - ui::MouseEvent press(ui::ET_MOUSE_PRESSED, gfx::Point(5, 5), gfx::Point(5, 5), - base::TimeTicks(), EF_LEFT_MOUSE_BUTTON, - EF_LEFT_MOUSE_BUTTON); - DispatchInputEventToWindow(target, EventLocationFromEvent(press, *display), - press, nullptr); - ASSERT_EQ(1u, tracker->changes()->size()); - EXPECT_EQ( - "InputEvent window=" + kWindowManagerClientIdString + ",1 event_action=1", - ChangesToDescription1(*tracker->changes())[0]); - tracker->changes()->clear(); - // The above is not setting TreeAwaitingInputAck. - - // Queue the key release event; it should not be immediately dispatched - // because there's no ACK for the last one. - ui::MouseEvent release(ui::ET_MOUSE_RELEASED, gfx::Point(5, 5), - gfx::Point(5, 5), base::TimeTicks(), - EF_LEFT_MOUSE_BUTTON, EF_LEFT_MOUSE_BUTTON); - DispatchInputEventToWindow(target, EventLocationFromEvent(release, *display), - release, nullptr); - EXPECT_EQ(0u, tracker->changes()->size()); - - // Destroying a window tree with an event in queue shouldn't crash. - DestroyWindowTree(); -} - -// Tests that when an ack times out that the accelerator is notified. -TEST_F(WindowManagerStateTest, AckTimeout) { - ui::KeyEvent key(ui::ET_KEY_PRESSED, ui::VKEY_W, ui::EF_CONTROL_DOWN); - std::unique_ptr<Accelerator> accelerator = CreateAccelerator(); - const Display* display = window_tree()->GetDisplay(window()); - ASSERT_TRUE(display); - DispatchInputEventToWindow(window(), EventLocationFromEvent(key, *display), - key, accelerator.get()); - TestChangeTracker* tracker = window_tree_client()->tracker(); - ASSERT_EQ(1u, tracker->changes()->size()); - EXPECT_EQ( - "InputEvent window=" + kWindowManagerClientIdString + ",1 event_action=7", - ChangesToDescription1(*tracker->changes())[0]); - - OnEventAckTimeout(window()->owning_tree_id()); - EXPECT_TRUE(window_manager()->on_accelerator_called()); - EXPECT_EQ(accelerator->id(), window_manager()->on_accelerator_id()); -} - -TEST_F(WindowManagerStateTest, InterceptingEmbedderReceivesEvents) { - WindowTree* embedder_tree = tree(); - const ClientWindowId embed_window_id(embedder_tree->id(), 12); - embedder_tree->NewWindow(embed_window_id, ServerWindow::Properties()); - ServerWindow* embedder_window = - embedder_tree->GetWindowByClientId(embed_window_id); - ASSERT_TRUE( - embedder_tree->AddWindow(FirstRootId(embedder_tree), embed_window_id)); - - TestWindowTreeClient* embedder_client = wm_client(); - - { - // Do a normal embed. - const uint32_t embed_flags = 0; - WindowTree* embed_tree = nullptr; - TestWindowTreeClient* embed_client_proxy = nullptr; - EmbedAt(embedder_tree, embed_window_id, embed_flags, &embed_tree, - &embed_client_proxy); - ASSERT_TRUE(embed_client_proxy); - - // Send an event to the embed window. It should go to the embedded client. - const Display* display = embed_tree->GetDisplay(embedder_window); - ASSERT_TRUE(display); - ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, gfx::Point(), gfx::Point(), - base::TimeTicks(), 0, 0); - DispatchInputEventToWindow(embedder_window, - EventLocationFromEvent(mouse, *display), mouse, - nullptr); - ASSERT_EQ(1u, embed_client_proxy->tracker()->changes()->size()); - EXPECT_EQ(CHANGE_TYPE_INPUT_EVENT, - (*embed_client_proxy->tracker()->changes())[0].type); - WindowTreeTestApi(embed_tree).AckLastEvent(mojom::EventResult::UNHANDLED); - embed_client_proxy->tracker()->changes()->clear(); - } - - { - // Do an embed where the embedder wants to intercept events to the embedded - // tree. - const uint32_t embed_flags = mojom::kEmbedFlagEmbedderInterceptsEvents; - WindowTree* embed_tree = nullptr; - TestWindowTreeClient* embed_client_proxy = nullptr; - const ClientWindowId embed_client_window_id = - embedder_window->frame_sink_id(); - EmbedAt(embedder_tree, embed_window_id, embed_flags, &embed_tree, - &embed_client_proxy); - ASSERT_TRUE(embed_client_proxy); - embedder_client->tracker()->changes()->clear(); - - // Send an event to the embed window. But this time, it should reach the - // embedder. - const Display* display = embed_tree->GetDisplay(embedder_window); - ASSERT_TRUE(display); - ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, gfx::Point(), gfx::Point(), - base::TimeTicks(), 0, 0); - DispatchInputEventToWindow(embedder_window, - EventLocationFromEvent(mouse, *display), mouse, - nullptr); - ASSERT_EQ(0u, embed_client_proxy->tracker()->changes()->size()); - ASSERT_EQ(1u, embedder_client->tracker()->changes()->size()); - EXPECT_EQ(CHANGE_TYPE_INPUT_EVENT, - (*embedder_client->tracker()->changes())[0].type); - WindowTreeTestApi(embedder_tree) - .AckLastEvent(mojom::EventResult::UNHANDLED); - embedder_client->tracker()->changes()->clear(); - - // Embed another tree in the embedded tree. - const ClientWindowId nested_embed_window_id(embed_tree->id(), 23); - embed_tree->NewWindow(nested_embed_window_id, ServerWindow::Properties()); - ASSERT_TRUE( - embed_tree->AddWindow(embed_client_window_id, nested_embed_window_id)); - - WindowTree* nested_embed_tree = nullptr; - TestWindowTreeClient* nested_embed_client_proxy = nullptr; - // Intercept events (kEmbedFlagEmbedderInterceptsEvents) is inherited, so - // even though this doesn't explicitly specify - // kEmbedFlagEmbedderInterceptsEvents it gets - // kEmbedFlagEmbedderInterceptsEvents from the parent embedding. - EmbedAt(embed_tree, nested_embed_window_id, 0, &nested_embed_tree, - &nested_embed_client_proxy); - ASSERT_TRUE(nested_embed_client_proxy); - embed_client_proxy->tracker()->changes()->clear(); - embedder_client->tracker()->changes()->clear(); - - // Send an event to the nested embed window. The event should still reach - // the outermost embedder. - ServerWindow* nested_embed_window = - embed_tree->GetWindowByClientId(nested_embed_window_id); - ASSERT_TRUE(nested_embed_window->parent()); - mouse = ui::MouseEvent(ui::ET_MOUSE_MOVED, gfx::Point(), gfx::Point(), - base::TimeTicks(), 0, 0); - DispatchInputEventToWindow(nested_embed_window, - EventLocationFromEvent(mouse, *display), mouse, - nullptr); - ASSERT_EQ(0u, nested_embed_client_proxy->tracker()->changes()->size()); - ASSERT_EQ(0u, embed_client_proxy->tracker()->changes()->size()); - - ASSERT_EQ(1u, embedder_client->tracker()->changes()->size()); - EXPECT_EQ(CHANGE_TYPE_INPUT_EVENT, - (*embedder_client->tracker()->changes())[0].type); - WindowTreeTestApi(embedder_tree) - .AckLastEvent(mojom::EventResult::UNHANDLED); - } -} - -// Ensures accelerators are forgotten between events. -TEST_F(WindowManagerStateTest, PostAcceleratorForgotten) { - // Send an event that matches the accelerator and have the target respond - // that it handled the event so that the accelerator isn't called. - ui::KeyEvent accelerator_key(ui::ET_KEY_PRESSED, ui::VKEY_W, - ui::EF_CONTROL_DOWN); - std::unique_ptr<Accelerator> accelerator = CreateAccelerator(); - ServerWindow* target = window(); - const Display* display = window_tree()->GetDisplay(target); - ASSERT_TRUE(display); - DispatchInputEventToWindow(target, - EventLocationFromEvent(accelerator_key, *display), - accelerator_key, accelerator.get()); - TestChangeTracker* tracker = window_tree_client()->tracker(); - ASSERT_EQ(1u, tracker->changes()->size()); - EXPECT_EQ( - "InputEvent window=" + kWindowManagerClientIdString + ",1 event_action=7", - ChangesToDescription1(*tracker->changes())[0]); - tracker->changes()->clear(); - WindowTreeTestApi(window_tree()).AckLastEvent(mojom::EventResult::HANDLED); - EXPECT_FALSE(window_manager()->on_accelerator_called()); - - // Send another event that doesn't match the accelerator, the accelerator - // shouldn't be called. - ui::KeyEvent non_accelerator_key(ui::ET_KEY_PRESSED, ui::VKEY_T, - ui::EF_CONTROL_DOWN); - DispatchInputEventToWindow( - target, EventLocationFromEvent(non_accelerator_key, *display), - non_accelerator_key, nullptr); - ASSERT_EQ(1u, tracker->changes()->size()); - EXPECT_EQ( - "InputEvent window=" + kWindowManagerClientIdString + ",1 event_action=7", - ChangesToDescription1(*tracker->changes())[0]); - WindowTreeTestApi(window_tree()).AckLastEvent(mojom::EventResult::UNHANDLED); - EXPECT_FALSE(window_manager()->on_accelerator_called()); -} - -// Verifies there is no crash if the WindowTree of a window manager is destroyed -// with no roots. -TEST(WindowManagerStateShutdownTest, DestroyTreeBeforeDisplay) { - WindowServerTestHelper ws_test_helper; - WindowServer* window_server = ws_test_helper.window_server(); - TestScreenManager screen_manager; - screen_manager.Init(window_server->display_manager()); - screen_manager.AddDisplay(); - AddWindowManager(window_server); - ASSERT_EQ(1u, window_server->display_manager()->displays().size()); - Display* display = *(window_server->display_manager()->displays().begin()); - WindowManagerDisplayRoot* window_manager_display_root = - display->window_manager_display_root(); - ASSERT_TRUE(window_manager_display_root); - WindowTree* tree = - window_manager_display_root->window_manager_state()->window_tree(); - ASSERT_EQ(1u, tree->roots().size()); - ClientWindowId root_client_id; - ASSERT_TRUE(tree->IsWindowKnown(*(tree->roots().begin()), &root_client_id)); - EXPECT_TRUE(tree->DeleteWindow(root_client_id)); - window_server->DestroyTree(tree); -} - -TEST_F(WindowManagerStateTest, CursorResetOverNoTarget) { - ASSERT_EQ(1u, window_server()->display_manager()->displays().size()); - const ClientWindowId child_window_id(window_tree()->id(), 11); - window_tree()->NewWindow(child_window_id, ServerWindow::Properties()); - ServerWindow* child_window = - window_tree()->GetWindowByClientId(child_window_id); - window_tree()->AddWindow(FirstRootId(window_tree()), child_window_id); - child_window->SetVisible(true); - child_window->SetBounds(gfx::Rect(0, 0, 20, 20)); - child_window->parent()->SetCursor(ui::CursorData(ui::CursorType::kCopy)); - EXPECT_EQ(ui::CursorType::kCopy, cursor_type()); - // Move the mouse outside the bounds of the child, so that the mouse is not - // over any valid windows. Cursor should change to POINTER. - ui::PointerEvent move( - ui::ET_POINTER_MOVED, gfx::Point(25, 25), gfx::Point(25, 25), 0, 0, - ui::PointerDetails(EventPointerType::POINTER_TYPE_MOUSE, 0), - base::TimeTicks()); - window_manager_state()->ProcessEvent(&move, 0); - // The event isn't over a valid target, which should trigger resetting the - // cursor to POINTER. - EXPECT_EQ(ui::CursorType::kPointer, cursor_type()); -} - -TEST(WindowManagerStateEventTest, AdjustEventLocation) { - WindowServerTestHelper ws_test_helper; - WindowServer* window_server = ws_test_helper.window_server(); - TestScreenManager screen_manager; - screen_manager.Init(window_server->display_manager()); - AddWindowManager(window_server); - const int64_t first_display_id = screen_manager.AddDisplay(); - const int64_t second_display_id = screen_manager.AddDisplay(); - Display* first_display = - window_server->display_manager()->GetDisplayById(first_display_id); - // As there are no child windows make sure the root is a valid target. - first_display->window_manager_display_root() - ->GetClientVisibleRoot() - ->set_event_targeting_policy( - mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS); - Display* second_display = - window_server->display_manager()->GetDisplayById(second_display_id); - ASSERT_TRUE(second_display); - display::Display second_display_display = second_display->GetDisplay(); - second_display_display.set_bounds(gfx::Rect(100, 0, 100, 100)); - display::ViewportMetrics second_metrics; - // The DIP display layout is horizontal and the pixel layout vertical. - second_metrics.device_scale_factor = 1.0f; - second_metrics.bounds_in_pixels = gfx::Rect(0, 200, 100, 100); - second_metrics.ui_scale_factor = 1.0f; - screen_manager.ModifyDisplay(second_display_display, second_metrics); - const gfx::Point move_location(5, 210); - ui::PointerEvent move( - ui::ET_POINTER_MOVED, move_location, move_location, 0, 0, - ui::PointerDetails(EventPointerType::POINTER_TYPE_MOUSE, 0), - base::TimeTicks()); - WindowManagerDisplayRoot* window_manager_display_root = - second_display->window_manager_display_root(); - TestChangeTracker* tracker = - ws_test_helper.window_server_delegate()->last_client()->tracker(); - tracker->changes()->clear(); - window_manager_display_root->window_manager_state()->ProcessEvent( - &move, first_display_id); - ASSERT_EQ(1u, tracker->changes()->size()); - // |location2| is the location supplied in terms of the pixel display layout. - EXPECT_EQ(gfx::PointF(move_location), (*tracker->changes())[0].location2); - // |location1| is the location in DIP display layout. - EXPECT_EQ(gfx::Point(105, 10), (*tracker->changes())[0].location1); -} - -TEST_F(WindowManagerStateTest, CursorLocationManagerUpdatedOnMouseMove) { - WindowManagerStateTestApi test_api(window_manager_state()); - ASSERT_EQ(1u, test_api.window_manager_display_roots().size()); - WindowManagerDisplayRoot* window_manager_display_root = - test_api.window_manager_display_roots().begin()->get(); - ASSERT_TRUE(window_manager_display_root->GetClientVisibleRoot()); - // Install a transform on the root, which impacts the location reported to - // clients. - gfx::Transform transform; - transform.Translate(6, 7); - window_manager_display_root->GetClientVisibleRoot()->SetTransform(transform); - ui::PointerEvent move( - ui::ET_POINTER_MOVED, gfx::Point(25, 25), gfx::Point(25, 25), 0, 0, - ui::PointerDetails(EventPointerType::POINTER_TYPE_MOUSE, 0), - base::TimeTicks()); - // Tests add display with kInvalidDisplayId. - window_manager_state()->ProcessEvent(&move, display::kInvalidDisplayId); - CursorLocationManager* cursor_location_manager = - window_server()->display_manager()->cursor_location_manager(); - // The location reported to clients is offset by the root transform. - EXPECT_EQ( - gfx::Point(19, 18), - Atomic32ToPoint(CursorLocationManagerTestApi(cursor_location_manager) - .current_cursor_location())); -} - -TEST_F(WindowManagerStateTest, SetCapture) { - ASSERT_EQ(1u, window_server()->display_manager()->displays().size()); - Display* display = *(window_server()->display_manager()->displays().begin()); - TestPlatformDisplay* platform_display = - static_cast<TestPlatformDisplay*>(display->platform_display()); - EXPECT_TRUE(window_tree()->SetCapture(FirstRootId(window_tree()))); - EXPECT_EQ(FirstRoot(window_tree()), window_manager_state()->capture_window()); - EXPECT_TRUE(platform_display->has_capture()); - EXPECT_TRUE(window_tree()->ReleaseCapture(FirstRootId(window_tree()))); - EXPECT_FALSE(platform_display->has_capture()); - - // In unified mode capture should not propagate to the PlatformDisplay. This - // is for compatibility with classic ash. See http://crbug.com/773348. - display->SetDisplay(display::Display(display::kUnifiedDisplayId)); - EXPECT_TRUE(window_tree()->SetCapture(FirstRootId(window_tree()))); - EXPECT_EQ(FirstRoot(window_tree()), window_manager_state()->capture_window()); - EXPECT_FALSE(platform_display->has_capture()); - EXPECT_TRUE(window_tree()->ReleaseCapture(FirstRootId(window_tree()))); - EXPECT_FALSE(platform_display->has_capture()); -} - -TEST_F(WindowManagerStateTestAsync, CursorResetOverNoTargetAsync) { - ASSERT_EQ(1u, window_server()->display_manager()->displays().size()); - const ClientWindowId child_window_id(window_tree()->id(), 11); - window_tree()->NewWindow(child_window_id, ServerWindow::Properties()); - ServerWindow* child_window = - window_tree()->GetWindowByClientId(child_window_id); - window_tree()->AddWindow(FirstRootId(window_tree()), child_window_id); - // Setup steps already do hit-test for mouse cursor update so this should go - // to the queue in EventTargeter. - EventTargeterTestApi event_targeter_test_api( - EventProcessorTestApi(window_manager_state()->event_processor()) - .event_targeter()); - EXPECT_TRUE(event_targeter_test_api.HasPendingQueries()); - // But no events have been generated, so IsProcessingEvent() should be false. - EXPECT_FALSE(window_manager_state()->event_processor()->IsProcessingEvent()); - child_window->SetVisible(true); - child_window->SetBounds(gfx::Rect(0, 0, 20, 20)); - child_window->parent()->SetCursor(ui::CursorData(ui::CursorType::kCopy)); - // Move the mouse outside the bounds of the child, so that the mouse is not - // over any valid windows. Cursor should change to POINTER. - ui::PointerEvent move( - ui::ET_POINTER_MOVED, gfx::Point(25, 25), gfx::Point(25, 25), 0, 0, - ui::PointerDetails(EventPointerType::POINTER_TYPE_MOUSE, 0), - base::TimeTicks()); - WindowManagerStateTestApi test_api(window_manager_state()); - EXPECT_TRUE(test_api.is_event_tasks_empty()); - window_manager_state()->ProcessEvent(&move, 0); - EXPECT_FALSE(test_api.tree_awaiting_input_ack()); - EXPECT_TRUE(window_manager_state()->event_processor()->IsProcessingEvent()); - EXPECT_TRUE(test_api.is_event_tasks_empty()); - task_runner_->RunUntilIdle(); - EXPECT_TRUE(test_api.is_event_tasks_empty()); - // The event isn't over a valid target, which should trigger resetting the - // cursor to POINTER. - EXPECT_EQ(ui::CursorType::kPointer, cursor_type()); -} - -TEST_F(WindowManagerStateTest, DeleteTreeWithPendingEventAck) { - ASSERT_EQ(1u, window_server()->display_manager()->displays().size()); - Display* display = *(window_server()->display_manager()->displays().begin()); - - TestWindowTreeClient* embed_connection = nullptr; - WindowTree* target_tree = nullptr; - ServerWindow* target = nullptr; - CreateSecondaryTree(&embed_connection, &target_tree, &target); - target->set_event_targeting_policy( - mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS); - - bool was_event_processed = false; - ui::PointerEvent move( - ui::ET_POINTER_MOVED, gfx::Point(25, 25), gfx::Point(25, 25), 0, 0, - ui::PointerDetails(EventPointerType::POINTER_TYPE_MOUSE, 0), - base::TimeTicks()); - window_manager_state()->ProcessEvent(&move, display->GetId()); - window_manager_state()->ScheduleCallbackWhenDoneProcessingEvents( - base::BindOnce(&SetBoolToTrue, &was_event_processed)); - EXPECT_FALSE(was_event_processed); - EXPECT_TRUE(WindowTreeTestApi(target_tree).HasEventInFlight()); - window_server()->DestroyTree(target_tree); - // Destroying the tree triggers the event to be considered processed. - EXPECT_TRUE(was_event_processed); -} - -TEST_F(WindowManagerStateTest, EventProcessedCallbackNotRunForGeneratedEvents) { - ASSERT_EQ(1u, window_server()->display_manager()->displays().size()); - Display* display = *(window_server()->display_manager()->displays().begin()); - - // Create two children of the root. - ServerWindow* wm_root = FirstRoot(window_tree()); - wm_root->SetBounds(gfx::Rect(0, 0, 100, 100)); - wm_root->set_event_targeting_policy( - mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS); - ServerWindow* child_window1 = NewWindowInTreeWithParent( - window_tree(), wm_root, nullptr, gfx::Rect(0, 0, 20, 20)); - child_window1->set_event_targeting_policy( - mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS); - ServerWindow* child_window2 = NewWindowInTreeWithParent( - window_tree(), wm_root, nullptr, gfx::Rect(50, 0, 20, 20)); - child_window2->set_event_targeting_policy( - mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS); - - TestChangeTracker* tracker = window_tree_client()->tracker(); - tracker->changes()->clear(); - - bool was_event_processed = false; - ui::PointerEvent move1( - ui::ET_POINTER_MOVED, gfx::Point(15, 15), gfx::Point(15, 15), 0, 0, - ui::PointerDetails(EventPointerType::POINTER_TYPE_MOUSE, 0), - base::TimeTicks()); - window_manager_state()->ProcessEvent(&move1, display->GetId()); - window_manager_state()->ScheduleCallbackWhenDoneProcessingEvents( - base::BindOnce(&SetBoolToTrue, &was_event_processed)); - EXPECT_FALSE(was_event_processed); - EXPECT_TRUE(WindowTreeTestApi(window_tree()).HasEventInFlight()); - ASSERT_EQ(1u, tracker->changes()->size()); - EXPECT_EQ(CHANGE_TYPE_INPUT_EVENT, (*tracker->changes())[0].type); - tracker->changes()->clear(); - WindowTreeTestApi(window_tree()).AckLastEvent(mojom::EventResult::HANDLED); - EXPECT_TRUE(was_event_processed); - was_event_processed = false; - - ui::PointerEvent move2( - ui::ET_POINTER_MOVED, gfx::Point(65, 15), gfx::Point(65, 15), 0, 0, - ui::PointerDetails(EventPointerType::POINTER_TYPE_MOUSE, 0), - base::TimeTicks()); - window_manager_state()->ProcessEvent(&move2, display->GetId()); - window_manager_state()->ScheduleCallbackWhenDoneProcessingEvents( - base::BindOnce(&SetBoolToTrue, &was_event_processed)); - EXPECT_FALSE(was_event_processed); - EXPECT_TRUE(WindowTreeTestApi(window_tree()).HasEventInFlight()); - ASSERT_EQ(1u, tracker->changes()->size()); - EXPECT_EQ(CHANGE_TYPE_INPUT_EVENT, (*tracker->changes())[0].type); - EXPECT_EQ(ET_POINTER_EXITED, (*tracker->changes())[0].event_action); - tracker->changes()->clear(); - - WindowTreeTestApi(window_tree()).AckLastEvent(mojom::EventResult::HANDLED); - // |was_event_processed| is false, because the exit was synthesized and will - // be followed by a move. - EXPECT_FALSE(was_event_processed); - ASSERT_EQ(1u, tracker->changes()->size()); - EXPECT_EQ(CHANGE_TYPE_INPUT_EVENT, (*tracker->changes())[0].type); - EXPECT_EQ(ET_POINTER_MOVED, (*tracker->changes())[0].event_action); - tracker->changes()->clear(); - WindowTreeTestApi(window_tree()).AckLastEvent(mojom::EventResult::HANDLED); - EXPECT_TRUE(was_event_processed); - EXPECT_TRUE(tracker->changes()->empty()); -} - -} // namespace test -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/window_manager_window_tree_factory.cc b/services/ui/ws/window_manager_window_tree_factory.cc deleted file mode 100644 index 7e279889..0000000 --- a/services/ui/ws/window_manager_window_tree_factory.cc +++ /dev/null
@@ -1,78 +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 "services/ui/ws/window_manager_window_tree_factory.h" - -#include "base/bind.h" -#include "services/ui/ws/display_creation_config.h" -#include "services/ui/ws/window_manager_window_tree_factory_observer.h" -#include "services/ui/ws/window_server.h" -#include "services/ui/ws/window_server_delegate.h" -#include "services/ui/ws/window_tree.h" - -namespace ui { -namespace ws { - -WindowManagerWindowTreeFactory::WindowManagerWindowTreeFactory( - WindowServer* window_server) - : window_server_(window_server), binding_(this) {} - -WindowManagerWindowTreeFactory::~WindowManagerWindowTreeFactory() {} - -void WindowManagerWindowTreeFactory::Bind( - mojo::InterfaceRequest<mojom::WindowManagerWindowTreeFactory> request) { - binding_.Bind(std::move(request)); -} - -void WindowManagerWindowTreeFactory::AddObserver( - WindowManagerWindowTreeFactoryObserver* observer) { - observers_.AddObserver(observer); -} - -void WindowManagerWindowTreeFactory::RemoveObserver( - WindowManagerWindowTreeFactoryObserver* observer) { - observers_.RemoveObserver(observer); -} - -void WindowManagerWindowTreeFactory::OnTreeDestroyed() { - window_tree_ = nullptr; -} - -void WindowManagerWindowTreeFactory::CreateWindowTree( - mojom::WindowTreeRequest window_tree_request, - mojom::WindowTreeClientPtr window_tree_client, - bool automatically_create_display_roots) { - if (window_tree_) { - DVLOG(1) << "CreateWindowTree() called more than once."; - return; - } - - // CreateWindowTree() can only be called once, so there is no reason to keep - // the binding around. - if (binding_.is_bound()) - binding_.Close(); - - // If the config is MANUAL, then all WindowManagers must connect as MANUAL. - if (!automatically_create_display_roots && - window_server_->display_creation_config() == - DisplayCreationConfig::AUTOMATIC) { - DVLOG(1) << "CreateWindowTree() called with manual and automatic."; - return; - } - - SetWindowTree(window_server_->CreateTreeForWindowManager( - std::move(window_tree_request), std::move(window_tree_client), - automatically_create_display_roots)); -} - -void WindowManagerWindowTreeFactory::SetWindowTree(WindowTree* window_tree) { - DCHECK(!window_tree_); - window_tree_ = window_tree; - - for (WindowManagerWindowTreeFactoryObserver& observer : observers_) - observer.OnWindowManagerWindowTreeFactoryReady(this); -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/window_manager_window_tree_factory.h b/services/ui/ws/window_manager_window_tree_factory.h deleted file mode 100644 index 7c2b2f11..0000000 --- a/services/ui/ws/window_manager_window_tree_factory.h +++ /dev/null
@@ -1,61 +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. - -#ifndef SERVICES_UI_WS_WINDOW_MANAGER_WINDOW_TREE_FACTORY_H_ -#define SERVICES_UI_WS_WINDOW_MANAGER_WINDOW_TREE_FACTORY_H_ - -#include <stdint.h> - -#include "mojo/public/cpp/bindings/binding.h" -#include "services/ui/public/interfaces/window_manager_window_tree_factory.mojom.h" - -namespace ui { -namespace ws { - -class WindowManagerWindowTreeFactoryObserver; -class WindowServer; -class WindowTree; - -// Implementation of mojom::WindowManagerWindowTreeFactory. -class WindowManagerWindowTreeFactory - : public mojom::WindowManagerWindowTreeFactory { - public: - explicit WindowManagerWindowTreeFactory(WindowServer* window_server); - ~WindowManagerWindowTreeFactory() override; - - WindowTree* window_tree() { return window_tree_; } - - bool is_bound() const { return binding_.is_bound(); } - - void Bind( - mojo::InterfaceRequest<mojom::WindowManagerWindowTreeFactory> request); - - void AddObserver(WindowManagerWindowTreeFactoryObserver* observer); - void RemoveObserver(WindowManagerWindowTreeFactoryObserver* observer); - - void OnTreeDestroyed(); - - // mojom::WindowManagerWindowTreeFactory: - void CreateWindowTree(mojom::WindowTreeRequest window_tree_request, - mojom::WindowTreeClientPtr window_tree_client, - bool window_manager_creates_roots) override; - - private: - void SetWindowTree(WindowTree* window_tree); - - WindowServer* window_server_; - mojo::Binding<mojom::WindowManagerWindowTreeFactory> binding_; - - // Owned by WindowServer. - WindowTree* window_tree_ = nullptr; - - base::ObserverList<WindowManagerWindowTreeFactoryObserver> observers_; - - DISALLOW_COPY_AND_ASSIGN(WindowManagerWindowTreeFactory); -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_WINDOW_MANAGER_WINDOW_TREE_FACTORY_H_
diff --git a/services/ui/ws/window_manager_window_tree_factory_observer.h b/services/ui/ws/window_manager_window_tree_factory_observer.h deleted file mode 100644 index 70a0ff7..0000000 --- a/services/ui/ws/window_manager_window_tree_factory_observer.h +++ /dev/null
@@ -1,26 +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 SERVICES_UI_WS_WINDOW_MANAGER_WINDOW_TREE_FACTORY_OBSERVER_H_ -#define SERVICES_UI_WS_WINDOW_MANAGER_WINDOW_TREE_FACTORY_OBSERVER_H_ - -namespace ui { -namespace ws { - -class WindowManagerWindowTreeFactory; - -class WindowManagerWindowTreeFactoryObserver { - public: - // Called when the WindowTree associated with |factory| has been set - virtual void OnWindowManagerWindowTreeFactoryReady( - WindowManagerWindowTreeFactory* factory) = 0; - - protected: - virtual ~WindowManagerWindowTreeFactoryObserver() {} -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_WINDOW_MANAGER_WINDOW_TREE_FACTORY_OBSERVER_H_
diff --git a/services/ui/ws/window_server.cc b/services/ui/ws/window_server.cc deleted file mode 100644 index a362d6f9..0000000 --- a/services/ui/ws/window_server.cc +++ /dev/null
@@ -1,1078 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "services/ui/ws/window_server.h" - -#include <set> -#include <string> - -#include "base/logging.h" -#include "base/memory/ptr_util.h" -#include "base/stl_util.h" -#include "components/viz/common/switches.h" -#include "services/ui/gpu_host/gpu_host.h" -#include "services/ui/ws/display.h" -#include "services/ui/ws/display_creation_config.h" -#include "services/ui/ws/display_manager.h" -#include "services/ui/ws/frame_generator.h" -#include "services/ui/ws/operation.h" -#include "services/ui/ws/server_window.h" -#include "services/ui/ws/user_activity_monitor.h" -#include "services/ui/ws/window_manager_access_policy.h" -#include "services/ui/ws/window_manager_display_root.h" -#include "services/ui/ws/window_manager_state.h" -#include "services/ui/ws/window_manager_window_tree_factory.h" -#include "services/ui/ws/window_server_delegate.h" -#include "services/ui/ws/window_tree.h" -#include "services/ui/ws/window_tree_binding.h" -#include "ui/gfx/geometry/size_conversions.h" - -namespace ui { -namespace ws { - -namespace { - -// Returns true if |window| is considered the active window manager for -// |display|. -bool IsWindowConsideredWindowManagerRoot(const Display* display, - const ServerWindow* window) { - if (!display) - return false; - - const WindowManagerDisplayRoot* display_root = - display->window_manager_display_root(); - return display_root && display_root->GetClientVisibleRoot() == window; -} - -class VizHostProxyImpl : public VizHostProxy { - public: - explicit VizHostProxyImpl(viz::HostFrameSinkManager* manager) - : manager_(manager) {} - - ~VizHostProxyImpl() override = default; - - // VizHostProxy: - void RegisterFrameSinkId(const viz::FrameSinkId& frame_sink_id, - viz::HostFrameSinkClient* client) override { - if (manager_) - manager_->RegisterFrameSinkId(frame_sink_id, client); - } - - void SetFrameSinkDebugLabel(const viz::FrameSinkId& frame_sink_id, - const std::string& name) override { - if (manager_) - manager_->SetFrameSinkDebugLabel(frame_sink_id, name); - } - - void InvalidateFrameSinkId(const viz::FrameSinkId& frame_sink_id) override { - if (manager_) - manager_->InvalidateFrameSinkId(frame_sink_id); - } - - void RegisterFrameSinkHierarchy(const viz::FrameSinkId& new_parent, - const viz::FrameSinkId& child) override { - if (manager_) - manager_->RegisterFrameSinkHierarchy(new_parent, child); - } - - void UnregisterFrameSinkHierarchy(const viz::FrameSinkId& old_parent, - const viz::FrameSinkId& child) override { - if (manager_) - manager_->UnregisterFrameSinkHierarchy(old_parent, child); - } - - void CreateRootCompositorFrameSink( - viz::mojom::RootCompositorFrameSinkParamsPtr params) override { - // No software compositing on ChromeOS. - params->gpu_compositing = true; - - if (manager_) - manager_->CreateRootCompositorFrameSink(std::move(params)); - } - - void CreateCompositorFrameSink( - const viz::FrameSinkId& frame_sink_id, - viz::mojom::CompositorFrameSinkRequest request, - viz::mojom::CompositorFrameSinkClientPtr client) override { - if (manager_) { - manager_->CreateCompositorFrameSink(frame_sink_id, std::move(request), - std::move(client)); - } - } - - viz::HitTestQuery* GetHitTestQuery( - const viz::FrameSinkId& frame_sink_id) override { - if (!manager_) - return nullptr; - const auto& display_hit_test_query_map = manager_->display_hit_test_query(); - const auto iter = display_hit_test_query_map.find(frame_sink_id); - return (iter != display_hit_test_query_map.end()) ? iter->second.get() - : nullptr; - } - - private: - viz::HostFrameSinkManager* const manager_; - - DISALLOW_COPY_AND_ASSIGN(VizHostProxyImpl); -}; - -} // namespace - -struct WindowServer::CurrentMoveLoopState { - uint32_t change_id; - ServerWindow* window; - WindowTree* initiator; - gfx::Rect revert_bounds; -}; - -struct WindowServer::CurrentDragLoopState { - uint32_t change_id; - ServerWindow* window; - WindowTree* initiator; -}; - -WindowServer::WindowServer(WindowServerDelegate* delegate, bool should_host_viz) - : delegate_(delegate), - next_client_id_(kWindowServerClientId + 1), - display_manager_(std::make_unique<DisplayManager>(this, should_host_viz)), - current_operation_(nullptr), - in_destructor_(false), - next_wm_change_id_(0), - window_manager_window_tree_factory_( - std::make_unique<WindowManagerWindowTreeFactory>(this)), - host_frame_sink_manager_( - should_host_viz ? std::make_unique<viz::HostFrameSinkManager>() - : nullptr), - viz_host_proxy_( - std::make_unique<VizHostProxyImpl>(host_frame_sink_manager_.get())), - video_detector_(host_frame_sink_manager_.get()), - display_creation_config_(DisplayCreationConfig::UNKNOWN) { - if (host_frame_sink_manager_) - host_frame_sink_manager_->WillAssignTemporaryReferencesExternally(); - user_activity_monitor_ = std::make_unique<UserActivityMonitor>(nullptr); -} - -WindowServer::~WindowServer() { - in_destructor_ = true; - - for (auto& pair : tree_map_) - pair.second->PrepareForWindowServerShutdown(); - - // Destroys the window trees results in querying for the display. Tear down - // the displays first so that the trees are notified of the display going - // away while the display is still valid. - display_manager_->DestroyAllDisplays(); - - while (!tree_map_.empty()) - DestroyTree(tree_map_.begin()->second.get()); - - display_manager_.reset(); -} - -void WindowServer::SetDisplayCreationConfig(DisplayCreationConfig config) { - DCHECK(tree_map_.empty()); - DCHECK_EQ(DisplayCreationConfig::UNKNOWN, display_creation_config_); - display_creation_config_ = config; - display_manager_->OnDisplayCreationConfigSet(); -} - -void WindowServer::SetGpuHost(std::unique_ptr<gpu_host::GpuHost> gpu_host) { - DCHECK(host_frame_sink_manager_); - gpu_host_ = std::move(gpu_host); - CreateFrameSinkManager(); -} - -ThreadedImageCursorsFactory* WindowServer::GetThreadedImageCursorsFactory() { - return delegate()->GetThreadedImageCursorsFactory(); -} - -ServerWindow* WindowServer::CreateServerWindow( - const viz::FrameSinkId& frame_sink_id, - const std::map<std::string, std::vector<uint8_t>>& properties) { - ServerWindow* window = new ServerWindow(this, frame_sink_id, properties); - window->AddObserver(this); - return window; -} - -ClientSpecificId WindowServer::GetAndAdvanceNextClientId() { - const ClientSpecificId id = next_client_id_++; - CHECK_NE(0u, next_client_id_); - return id; -} - -WindowTree* WindowServer::EmbedAtWindow( - ServerWindow* root, - mojom::WindowTreeClientPtr client, - uint32_t flags, - std::unique_ptr<AccessPolicy> access_policy) { - // TODO(sky): I suspect this code needs to reset the FrameSinkId to the - // ClientWindowId that was used at the time the window was created. As - // currently if there is a reembed the FrameSinkId from the last embedding - // is incorrectly used. - const bool is_for_embedding = true; - std::unique_ptr<WindowTree> tree_ptr = std::make_unique<WindowTree>( - this, is_for_embedding, root, std::move(access_policy)); - WindowTree* tree = tree_ptr.get(); - if (flags & mojom::kEmbedFlagEmbedderInterceptsEvents) - tree->set_embedder_intercepts_events(); - - if (flags & mojom::kEmbedFlagEmbedderControlsVisibility) - tree->set_can_change_root_window_visibility(false); - - mojom::WindowTreePtr window_tree_ptr; - auto window_tree_request = mojo::MakeRequest(&window_tree_ptr); - std::unique_ptr<WindowTreeBinding> binding = - delegate_->CreateWindowTreeBinding( - WindowServerDelegate::BindingType::EMBED, this, tree, - &window_tree_request, &client); - if (!binding) { - binding = std::make_unique<ws::DefaultWindowTreeBinding>( - tree, this, std::move(window_tree_request), std::move(client)); - } - - AddTree(std::move(tree_ptr), std::move(binding), std::move(window_tree_ptr)); - OnTreeMessagedClient(tree->id()); - root->UpdateFrameSinkId(viz::FrameSinkId(tree->id(), 0)); - return tree; -} - -void WindowServer::AddTree(std::unique_ptr<WindowTree> tree_impl_ptr, - std::unique_ptr<WindowTreeBinding> binding, - mojom::WindowTreePtr tree_ptr) { - CHECK_EQ(0u, tree_map_.count(tree_impl_ptr->id())); - WindowTree* tree = tree_impl_ptr.get(); - tree_map_[tree->id()] = std::move(tree_impl_ptr); - tree->Init(std::move(binding), std::move(tree_ptr)); -} - -WindowTree* WindowServer::CreateTreeForWindowManager( - mojom::WindowTreeRequest window_tree_request, - mojom::WindowTreeClientPtr window_tree_client, - bool automatically_create_display_roots) { - delegate_->OnWillCreateTreeForWindowManager( - automatically_create_display_roots); - - const bool is_for_embedding = false; - std::unique_ptr<WindowTree> window_tree = std::make_unique<WindowTree>( - this, is_for_embedding, nullptr, - base::WrapUnique(new WindowManagerAccessPolicy)); - std::unique_ptr<WindowTreeBinding> window_tree_binding = - delegate_->CreateWindowTreeBinding( - WindowServerDelegate::BindingType::WINDOW_MANAGER, this, - window_tree.get(), &window_tree_request, &window_tree_client); - if (!window_tree_binding) { - window_tree_binding = std::make_unique<DefaultWindowTreeBinding>( - window_tree.get(), this, std::move(window_tree_request), - std::move(window_tree_client)); - } - WindowTree* window_tree_ptr = window_tree.get(); - AddTree(std::move(window_tree), std::move(window_tree_binding), nullptr); - window_tree_ptr->ConfigureWindowManager(automatically_create_display_roots); - return window_tree_ptr; -} - -void WindowServer::DestroyTree(WindowTree* tree) { - std::unique_ptr<WindowTree> tree_ptr; - { - auto iter = tree_map_.find(tree->id()); - DCHECK(iter != tree_map_.end()); - tree_ptr = std::move(iter->second); - tree_map_.erase(iter); - } - - base::EraseIf(scheduled_embeds_, - [&tree](const std::pair<base::UnguessableToken, - const WindowTreeAndWindowId&>& pair) { - return (tree == pair.second.tree); - }); - - // Notify remaining connections so that they can cleanup. - for (auto& pair : tree_map_) - pair.second->OnWillDestroyTree(tree); - - if (window_manager_window_tree_factory_->window_tree() == tree) - window_manager_window_tree_factory_->OnTreeDestroyed(); - - // Remove any requests from the client that resulted in a call to the window - // manager and we haven't gotten a response back yet. - std::set<uint32_t> to_remove; - for (auto& pair : in_flight_wm_change_map_) { - if (pair.second.client_id == tree->id()) - to_remove.insert(pair.first); - } - for (uint32_t id : to_remove) - in_flight_wm_change_map_.erase(id); -} - -WindowTree* WindowServer::GetTreeWithId(ClientSpecificId client_id) { - auto iter = tree_map_.find(client_id); - return iter == tree_map_.end() ? nullptr : iter->second.get(); -} - -WindowTree* WindowServer::GetTreeWithClientName( - const std::string& client_name) { - for (const auto& entry : tree_map_) { - if (entry.second->name() == client_name) - return entry.second.get(); - } - return nullptr; -} - -base::UnguessableToken WindowServer::RegisterEmbedToken( - WindowTree* tree, - ClientSpecificId window_id) { - const base::UnguessableToken token = base::UnguessableToken::Create(); - DCHECK(!scheduled_embeds_.count(token)); - scheduled_embeds_[token] = {tree, window_id}; - return token; -} - -WindowTreeAndWindowId WindowServer::UnregisterEmbedToken( - const base::UnguessableToken& token) { - auto iter = scheduled_embeds_.find(token); - if (iter == scheduled_embeds_.end()) - return {}; - WindowTreeAndWindowId result = iter->second; - scheduled_embeds_.erase(iter); - return result; -} - -void WindowServer::OnTreeMessagedClient(ClientSpecificId id) { - if (current_operation_) - current_operation_->MarkTreeAsMessaged(id); -} - -bool WindowServer::DidTreeMessageClient(ClientSpecificId id) const { - return current_operation_ && current_operation_->DidMessageTree(id); -} - -const WindowTree* WindowServer::GetTreeWithRoot( - const ServerWindow* window) const { - if (!window) - return nullptr; - for (auto& pair : tree_map_) { - if (pair.second->HasRoot(window)) - return pair.second.get(); - } - return nullptr; -} - -void WindowServer::BindWindowManagerWindowTreeFactory( - mojo::InterfaceRequest<mojom::WindowManagerWindowTreeFactory> request) { - if (window_manager_window_tree_factory_->is_bound()) { - DVLOG(1) << "Can only have one WindowManagerWindowTreeFactory"; - return; - } - window_manager_window_tree_factory_->Bind(std::move(request)); -} - -bool WindowServer::SetFocusedWindow(ServerWindow* window) { - // TODO(sky): this should fail if there is modal dialog active and |window| - // is outside that. - ServerWindow* currently_focused = GetFocusedWindow(); - Display* focused_display = - currently_focused - ? display_manager_->GetDisplayContaining(currently_focused) - : nullptr; - if (!window) - return focused_display ? focused_display->SetFocusedWindow(nullptr) : true; - - Display* display = display_manager_->GetDisplayContaining(window); - DCHECK(display); // It's assumed callers do validation before calling this. - const bool result = display->SetFocusedWindow(window); - // If the focus actually changed, and focus was in another display, then we - // need to notify the previously focused display so that it cleans up state - // and notifies appropriately. - if (result && display->GetFocusedWindow() && display != focused_display && - focused_display) { - const bool cleared_focus = focused_display->SetFocusedWindow(nullptr); - DCHECK(cleared_focus); - } - return result; -} - -ServerWindow* WindowServer::GetFocusedWindow() { - for (Display* display : display_manager_->displays()) { - ServerWindow* focused_window = display->GetFocusedWindow(); - if (focused_window) - return focused_window; - } - return nullptr; -} - -void WindowServer::SetHighContrastMode(bool enabled) { - // TODO(fsamuel): This doesn't really seem like it's a window server concept? - if (high_contrast_mode_ == enabled) - return; - high_contrast_mode_ = enabled; - - // Propagate the change to all Displays so that FrameGenerators start - // requesting BeginFrames. - display_manager_->SetHighContrastMode(enabled); -} - -uint32_t WindowServer::GenerateWindowManagerChangeId( - WindowTree* source, - uint32_t client_change_id) { - const uint32_t wm_change_id = next_wm_change_id_++; - in_flight_wm_change_map_[wm_change_id] = {source->id(), client_change_id}; - return wm_change_id; -} - -void WindowServer::WindowManagerChangeCompleted( - uint32_t window_manager_change_id, - bool success) { - InFlightWindowManagerChange change; - if (!GetAndClearInFlightWindowManagerChange(window_manager_change_id, - &change)) { - return; - } - - WindowTree* tree = GetTreeWithId(change.client_id); - tree->OnChangeCompleted(change.client_change_id, success); -} - -void WindowServer::WindowManagerCreatedTopLevelWindow( - WindowTree* wm_tree, - uint32_t window_manager_change_id, - ServerWindow* window) { - InFlightWindowManagerChange change; - if (!GetAndClearInFlightWindowManagerChange(window_manager_change_id, - &change)) { - DVLOG(1) << "WindowManager responded with invalid change id; most " - << "likely bug in WindowManager processing WmCreateTopLevelWindow " - << "change_id=" << window_manager_change_id; - return; - } - - WindowTree* tree = GetTreeWithId(change.client_id); - // The window manager should have created the window already, and it should - // be ready for embedding. - if (!tree->IsWaitingForNewTopLevelWindow(window_manager_change_id)) { - DVLOG(1) << "WindowManager responded with valid change id, but client " - << "is not waiting for top-level; possible bug in mus, change_id=" - << window_manager_change_id; - WindowManagerSentBogusMessage(); - return; - } - if (window && (window->owning_tree_id() != wm_tree->id() || - !window->children().empty() || GetTreeWithRoot(window))) { - DVLOG(1) - << "WindowManager responded with invalid window; window should " - << "not have any children, not be the root of a client and should be " - << "created by the WindowManager, window_manager_change_id=" - << window_manager_change_id; - WindowManagerSentBogusMessage(); - return; - } - - viz::FrameSinkId updated_frame_sink_id = - tree->OnWindowManagerCreatedTopLevelWindow( - window_manager_change_id, change.client_change_id, window); - if (window) - window->UpdateFrameSinkId(updated_frame_sink_id); -} - -void WindowServer::ProcessWindowBoundsChanged( - const ServerWindow* window, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds, - const base::Optional<viz::LocalSurfaceId>& local_surface_id) { - for (auto& pair : tree_map_) { - pair.second->ProcessWindowBoundsChanged(window, old_bounds, new_bounds, - IsOperationSource(pair.first), - local_surface_id); - } -} - -void WindowServer::ProcessWindowTransformChanged( - const ServerWindow* window, - const gfx::Transform& old_transform, - const gfx::Transform& new_transform) { - for (auto& pair : tree_map_) { - pair.second->ProcessWindowTransformChanged( - window, old_transform, new_transform, IsOperationSource(pair.first)); - } -} - -void WindowServer::ProcessClientAreaChanged( - const ServerWindow* window, - const gfx::Insets& new_client_area, - const std::vector<gfx::Rect>& new_additional_client_areas) { - for (auto& pair : tree_map_) { - pair.second->ProcessClientAreaChanged(window, new_client_area, - new_additional_client_areas, - IsOperationSource(pair.first)); - } -} - -void WindowServer::ProcessCaptureChanged(const ServerWindow* new_capture, - const ServerWindow* old_capture) { - for (auto& pair : tree_map_) { - pair.second->ProcessCaptureChanged(new_capture, old_capture, - IsOperationSource(pair.first)); - } -} - -void WindowServer::ProcessWillChangeWindowHierarchy( - const ServerWindow* window, - const ServerWindow* new_parent, - const ServerWindow* old_parent) { - for (auto& pair : tree_map_) { - pair.second->ProcessWillChangeWindowHierarchy( - window, new_parent, old_parent, IsOperationSource(pair.first)); - } -} - -void WindowServer::ProcessWindowHierarchyChanged( - const ServerWindow* window, - const ServerWindow* new_parent, - const ServerWindow* old_parent) { - for (auto& pair : tree_map_) { - pair.second->ProcessWindowHierarchyChanged(window, new_parent, old_parent, - IsOperationSource(pair.first)); - } -} - -void WindowServer::ProcessWindowReorder(const ServerWindow* window, - const ServerWindow* relative_window, - const mojom::OrderDirection direction) { - // We'll probably do a bit of reshuffling when we add a transient window. - if ((current_operation_type() == OperationType::ADD_TRANSIENT_WINDOW) || - (current_operation_type() == - OperationType::REMOVE_TRANSIENT_WINDOW_FROM_PARENT)) { - return; - } - for (auto& pair : tree_map_) { - pair.second->ProcessWindowReorder(window, relative_window, direction, - IsOperationSource(pair.first)); - } -} - -void WindowServer::ProcessWindowDeleted(ServerWindow* window) { - for (auto& pair : tree_map_) - pair.second->ProcessWindowDeleted(window, IsOperationSource(pair.first)); -} - -void WindowServer::ProcessWillChangeWindowCursor(ServerWindow* window, - const ui::CursorData& cursor) { - for (auto& pair : tree_map_) { - pair.second->ProcessCursorChanged(window, cursor, - IsOperationSource(pair.first)); - } -} - -void WindowServer::SendToPointerWatchers(const ui::Event& event, - ServerWindow* target_window, - WindowTree* ignore_tree, - int64_t display_id) { - for (auto& pair : tree_map_) { - WindowTree* tree = pair.second.get(); - if (tree != ignore_tree) - tree->SendToPointerWatcher(event, target_window, display_id); - } -} - -void WindowServer::SetSurfaceActivationCallback( - base::OnceCallback<void(ServerWindow*)> callback) { - DCHECK(delegate_->IsTestConfig()) << "Surface activation callbacks are " - << "expensive, and allowed only in tests."; - DCHECK(surface_activation_callback_.is_null() || callback.is_null()); - surface_activation_callback_ = std::move(callback); -} - -void WindowServer::StartMoveLoop(uint32_t change_id, - ServerWindow* window, - WindowTree* initiator, - const gfx::Rect& revert_bounds) { - current_move_loop_.reset( - new CurrentMoveLoopState{change_id, window, initiator, revert_bounds}); -} - -void WindowServer::EndMoveLoop() { - current_move_loop_.reset(); -} - -uint32_t WindowServer::GetCurrentMoveLoopChangeId() { - if (current_move_loop_) - return current_move_loop_->change_id; - return 0; -} - -ServerWindow* WindowServer::GetCurrentMoveLoopWindow() { - if (current_move_loop_) - return current_move_loop_->window; - return nullptr; -} - -WindowTree* WindowServer::GetCurrentMoveLoopInitiator() { - if (current_move_loop_) - return current_move_loop_->initiator; - return nullptr; -} - -gfx::Rect WindowServer::GetCurrentMoveLoopRevertBounds() { - if (current_move_loop_) - return current_move_loop_->revert_bounds; - return gfx::Rect(); -} - -void WindowServer::StartDragLoop(uint32_t change_id, - ServerWindow* window, - WindowTree* initiator) { - current_drag_loop_.reset( - new CurrentDragLoopState{change_id, window, initiator}); -} - -void WindowServer::EndDragLoop() { - current_drag_loop_.reset(); -} - -uint32_t WindowServer::GetCurrentDragLoopChangeId() { - if (current_drag_loop_) - return current_drag_loop_->change_id; - return 0u; -} - -ServerWindow* WindowServer::GetCurrentDragLoopWindow() { - if (current_drag_loop_) - return current_drag_loop_->window; - return nullptr; -} - -WindowTree* WindowServer::GetCurrentDragLoopInitiator() { - if (current_drag_loop_) - return current_drag_loop_->initiator; - return nullptr; -} - -void WindowServer::OnDisplayReady(Display* display, bool is_first) { - if (is_first) - delegate_->OnFirstDisplayReady(); - bool wm_is_hosting_viz = !gpu_host_; - if (wm_is_hosting_viz) { - // Notify WM about the AcceleratedWidget if it is hosting viz. - for (auto& pair : tree_map_) { - if (pair.second->window_manager_state()) { - auto& wm_tree = pair.second; - wm_tree->OnAcceleratedWidgetAvailableForDisplay(display); - } - } - } else { - gpu_host_->OnAcceleratedWidgetAvailable( - display->platform_display()->GetAcceleratedWidget()); - } -} - -void WindowServer::OnDisplayDestroyed(Display* display) { - if (gpu_host_) { - gpu_host_->OnAcceleratedWidgetDestroyed( - display->platform_display()->GetAcceleratedWidget()); - } -} - -void WindowServer::OnNoMoreDisplays() { - delegate_->OnNoMoreDisplays(); -} - -WindowManagerState* WindowServer::GetWindowManagerState() { - return window_manager_window_tree_factory_->window_tree() - ? window_manager_window_tree_factory_->window_tree() - ->window_manager_state() - : nullptr; -} - -VizHostProxy* WindowServer::GetVizHostProxy() { - return viz_host_proxy_.get(); -} - -void WindowServer::OnFirstSurfaceActivation( - const viz::SurfaceInfo& surface_info, - ServerWindow* window) { - DCHECK(host_frame_sink_manager_); - // This is only used for testing to observe that a window has a - // CompositorFrame. - if (surface_activation_callback_) - std::move(surface_activation_callback_).Run(window); - - Display* display = display_manager_->GetDisplayContaining(window); - if (IsWindowConsideredWindowManagerRoot(display, window)) { - // A new surface for a WindowManager root has been created. This is a - // special case because ServerWindows created by the WindowServer are not - // part of a WindowTree. Send the SurfaceId directly to FrameGenerator and - // claim the temporary reference for the display root. - display_manager_->OnWindowManagerSurfaceActivation(display, surface_info); - host_frame_sink_manager_->AssignTemporaryReference( - surface_info.id(), display->root_window()->frame_sink_id()); - return; - } - - HandleTemporaryReferenceForNewSurface(surface_info.id(), window); - - // We always use the owner of the window's id (even for an embedded window), - // because an embedded window's id is allocated by the parent's window tree. - WindowTree* window_tree = GetTreeWithId(window->owning_tree_id()); - if (window_tree) - window_tree->ProcessWindowSurfaceChanged(window, surface_info); -} - -bool WindowServer::GetFrameDecorations( - mojom::FrameDecorationValuesPtr* values) { - WindowManagerState* window_manager_state = GetWindowManagerState(); - if (!window_manager_state) - return false; - if (values && window_manager_state->got_frame_decoration_values()) - *values = window_manager_state->frame_decoration_values().Clone(); - return window_manager_state->got_frame_decoration_values(); -} - -int64_t WindowServer::GetInternalDisplayId() { - return display_manager_->GetInternalDisplayId(); -} - -bool WindowServer::GetAndClearInFlightWindowManagerChange( - uint32_t window_manager_change_id, - InFlightWindowManagerChange* change) { - // There are valid reasons as to why we wouldn't know about the id. The - // most likely is the client disconnected before the response from the window - // manager came back. - auto iter = in_flight_wm_change_map_.find(window_manager_change_id); - if (iter == in_flight_wm_change_map_.end()) - return false; - - *change = iter->second; - in_flight_wm_change_map_.erase(iter); - return true; -} - -void WindowServer::PrepareForOperation(Operation* op) { - // Should only ever have one change in flight. - CHECK(!current_operation_); - current_operation_ = op; -} - -void WindowServer::FinishOperation() { - // PrepareForOperation/FinishOperation should be balanced. - CHECK(current_operation_); - current_operation_ = nullptr; -} - -void WindowServer::UpdateNativeCursorFromMouseLocation(ServerWindow* window) { - UpdateNativeCursorFromMouseLocation( - display_manager_->GetWindowManagerDisplayRoot(window)); -} - -void WindowServer::UpdateNativeCursorFromMouseLocation( - WindowManagerDisplayRoot* display_root) { - if (!display_root) - return; - - EventProcessor* event_processor = - display_root->window_manager_state()->event_processor(); - event_processor->UpdateCursorProviderByLastKnownLocation(); -} - -void WindowServer::UpdateNativeCursorIfOver(ServerWindow* window) { - WindowManagerDisplayRoot* display_root = - display_manager_->GetWindowManagerDisplayRoot(window); - if (!display_root) - return; - - EventProcessor* event_processor = - display_root->window_manager_state()->event_processor(); - if (window != event_processor->GetWindowForMouseCursor()) - return; - - event_processor->UpdateNonClientAreaForCurrentWindow(); -} - -void WindowServer::HandleTemporaryReferenceForNewSurface( - const viz::SurfaceId& surface_id, - ServerWindow* window) { - DCHECK(host_frame_sink_manager_); - // TODO(kylechar): Investigate adding tests for this. - const ClientSpecificId window_client_id = window->owning_tree_id(); - - // Find the root ServerWindow for the client that embeds |window|, which is - // the root of the client that embeds |surface_id|. The client that embeds - // |surface_id| created |window|, so |window| will have the client id of the - // embedder. The root window of the embedder will have been created by it's - // embedder, so the first ServerWindow with a different client id will be the - // root of the embedder. - ServerWindow* current = window->parent(); - while (current && current->owning_tree_id() == window_client_id) - current = current->parent(); - - // The client that embeds |window| is expected to submit a CompositorFrame - // that references |surface_id|. Have the parent claim ownership of the - // temporary reference to |surface_id|. If the parent client crashes before it - // adds a surface reference then the GPU can cleanup temporary references. If - // no parent client embeds |window| then tell the GPU to drop the temporary - // reference immediately. - if (current) { - host_frame_sink_manager_->AssignTemporaryReference( - surface_id, current->frame_sink_id()); - } else { - host_frame_sink_manager_->DropTemporaryReference(surface_id); - } -} - -void WindowServer::CreateFrameSinkManager() { - DCHECK(host_frame_sink_manager_); - viz::mojom::FrameSinkManagerPtr frame_sink_manager; - viz::mojom::FrameSinkManagerRequest frame_sink_manager_request = - mojo::MakeRequest(&frame_sink_manager); - viz::mojom::FrameSinkManagerClientPtr frame_sink_manager_client; - viz::mojom::FrameSinkManagerClientRequest frame_sink_manager_client_request = - mojo::MakeRequest(&frame_sink_manager_client); - - viz::mojom::FrameSinkManagerParamsPtr params = - viz::mojom::FrameSinkManagerParams::New(); - params->restart_id = viz_restart_id_++; - base::Optional<uint32_t> activation_deadline_in_frames = - switches::GetDeadlineToSynchronizeSurfaces(); - params->use_activation_deadline = activation_deadline_in_frames.has_value(); - params->activation_deadline_in_frames = - activation_deadline_in_frames.value_or(0u); - params->frame_sink_manager = std::move(frame_sink_manager_request); - params->frame_sink_manager_client = frame_sink_manager_client.PassInterface(); - gpu_host_->CreateFrameSinkManager(std::move(params)); - - host_frame_sink_manager_->BindAndSetManager( - std::move(frame_sink_manager_client_request), nullptr /* task_runner */, - std::move(frame_sink_manager)); -} - -AsyncEventDispatcher* WindowServer::GetAsyncEventDispatcherById( - ClientSpecificId id) { - return GetTreeWithId(id); -} - -ServerWindow* WindowServer::GetRootWindowForDrawn(const ServerWindow* window) { - Display* display = display_manager_->GetDisplayContaining(window); - return display ? display->root_window() : nullptr; -} - -void WindowServer::OnWindowDestroyed(ServerWindow* window) { - ProcessWindowDeleted(window); -} - -void WindowServer::OnWillChangeWindowHierarchy(ServerWindow* window, - ServerWindow* new_parent, - ServerWindow* old_parent) { - if (in_destructor_) - return; - - ProcessWillChangeWindowHierarchy(window, new_parent, old_parent); -} - -void WindowServer::OnWindowHierarchyChanged(ServerWindow* window, - ServerWindow* new_parent, - ServerWindow* old_parent) { - if (in_destructor_) - return; - - WindowManagerDisplayRoot* display_root = - display_manager_->GetWindowManagerDisplayRoot(window); - if (display_root) { - display_root->window_manager_state() - ->ReleaseCaptureBlockedByAnyModalWindow(); - } - - ProcessWindowHierarchyChanged(window, new_parent, old_parent); - - if (old_parent) { - viz_host_proxy_->UnregisterFrameSinkHierarchy(old_parent->frame_sink_id(), - window->frame_sink_id()); - } - if (new_parent) { - viz_host_proxy_->RegisterFrameSinkHierarchy(new_parent->frame_sink_id(), - window->frame_sink_id()); - } - - if (!pending_system_modal_windows_.windows().empty()) { - // Windows that are now in a display are put here, then removed. We do this - // in two passes to avoid removing from a list we're iterating over. - std::set<ServerWindow*> no_longer_pending; - for (ServerWindow* system_modal_window : - pending_system_modal_windows_.windows()) { - DCHECK_EQ(MODAL_TYPE_SYSTEM, system_modal_window->modal_type()); - WindowManagerDisplayRoot* display_root = - display_manager_->GetWindowManagerDisplayRoot(system_modal_window); - if (display_root) { - no_longer_pending.insert(system_modal_window); - display_root->window_manager_state()->AddSystemModalWindow(window); - } - } - - for (ServerWindow* system_modal_window : no_longer_pending) - pending_system_modal_windows_.Remove(system_modal_window); - } - - WindowManagerDisplayRoot* old_display_root = - old_parent ? display_manager_->GetWindowManagerDisplayRoot(old_parent) - : nullptr; - WindowManagerDisplayRoot* new_display_root = - new_parent ? display_manager_->GetWindowManagerDisplayRoot(new_parent) - : nullptr; - UpdateNativeCursorFromMouseLocation(new_display_root); - if (old_display_root != new_display_root) - UpdateNativeCursorFromMouseLocation(old_display_root); -} - -void WindowServer::OnWindowBoundsChanged(ServerWindow* window, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds) { - if (in_destructor_) - return; - - ProcessWindowBoundsChanged(window, old_bounds, new_bounds, - window->current_local_surface_id()); - UpdateNativeCursorFromMouseLocation(window); -} - -void WindowServer::OnWindowTransformChanged( - ServerWindow* window, - const gfx::Transform& old_transform, - const gfx::Transform& new_transform) { - if (in_destructor_) - return; - - ProcessWindowTransformChanged(window, old_transform, new_transform); - UpdateNativeCursorFromMouseLocation(window); -} - -void WindowServer::OnWindowClientAreaChanged( - ServerWindow* window, - const gfx::Insets& new_client_area, - const std::vector<gfx::Rect>& new_additional_client_areas) { - if (in_destructor_) - return; - - ProcessClientAreaChanged(window, new_client_area, - new_additional_client_areas); - - UpdateNativeCursorIfOver(window); -} - -void WindowServer::OnWindowReordered(ServerWindow* window, - ServerWindow* relative, - mojom::OrderDirection direction) { - ProcessWindowReorder(window, relative, direction); - UpdateNativeCursorFromMouseLocation(window); -} - -void WindowServer::OnWillChangeWindowVisibility(ServerWindow* window) { - if (in_destructor_) - return; - - for (auto& pair : tree_map_) { - pair.second->ProcessWillChangeWindowVisibility( - window, IsOperationSource(pair.first)); - } -} - -void WindowServer::OnWindowOpacityChanged(ServerWindow* window, - float old_opacity, - float new_opacity) { - DCHECK(!in_destructor_); - - for (auto& pair : tree_map_) { - pair.second->ProcessWindowOpacityChanged(window, old_opacity, new_opacity, - IsOperationSource(pair.first)); - } -} - -void WindowServer::OnWindowVisibilityChanged(ServerWindow* window) { - if (in_destructor_) - return; - - WindowManagerDisplayRoot* display_root = - display_manager_->GetWindowManagerDisplayRoot(window); - if (display_root) { - display_root->window_manager_state() - ->ReleaseCaptureBlockedByAnyModalWindow(); - } -} - -void WindowServer::OnWindowCursorChanged(ServerWindow* window, - const ui::CursorData& cursor) { - if (in_destructor_) - return; - - ProcessWillChangeWindowCursor(window, cursor); - - UpdateNativeCursorIfOver(window); -} - -void WindowServer::OnWindowNonClientCursorChanged( - ServerWindow* window, - const ui::CursorData& cursor) { - if (in_destructor_) - return; - - UpdateNativeCursorIfOver(window); -} - -void WindowServer::OnWindowSharedPropertyChanged( - ServerWindow* window, - const std::string& name, - const std::vector<uint8_t>* new_data) { - for (auto& pair : tree_map_) { - pair.second->ProcessWindowPropertyChanged(window, name, new_data, - IsOperationSource(pair.first)); - } -} - -void WindowServer::OnWindowTextInputStateChanged( - ServerWindow* window, - const ui::TextInputState& state) { - Display* display = display_manager_->GetDisplayContaining(window); - display->UpdateTextInputState(window, state); -} - -void WindowServer::OnTransientWindowAdded(ServerWindow* window, - ServerWindow* transient_child) { - for (auto& pair : tree_map_) { - pair.second->ProcessTransientWindowAdded(window, transient_child, - IsOperationSource(pair.first)); - } -} - -void WindowServer::OnTransientWindowRemoved(ServerWindow* window, - ServerWindow* transient_child) { - // If we're deleting a window, then this is a superfluous message. - if (current_operation_type() == OperationType::DELETE_WINDOW) - return; - for (auto& pair : tree_map_) { - pair.second->ProcessTransientWindowRemoved(window, transient_child, - IsOperationSource(pair.first)); - } -} - -void WindowServer::OnWindowModalTypeChanged(ServerWindow* window, - ModalType old_modal_type) { - WindowManagerDisplayRoot* display_root = - display_manager_->GetWindowManagerDisplayRoot(window); - if (window->modal_type() == MODAL_TYPE_SYSTEM) { - if (display_root) - display_root->window_manager_state()->AddSystemModalWindow(window); - else - pending_system_modal_windows_.Add(window); - } else { - pending_system_modal_windows_.Remove(window); - } - - if (display_root && window->modal_type() != MODAL_TYPE_NONE) { - display_root->window_manager_state() - ->ReleaseCaptureBlockedByAnyModalWindow(); - } -} - -void WindowServer::OnGpuServiceInitialized() { - delegate_->StartDisplayInit(); -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/window_server.h b/services/ui/ws/window_server.h deleted file mode 100644 index 80643d9..0000000 --- a/services/ui/ws/window_server.h +++ /dev/null
@@ -1,452 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SERVICES_UI_WS_WINDOW_SERVER_H_ -#define SERVICES_UI_WS_WINDOW_SERVER_H_ - -#include <stdint.h> - -#include <map> -#include <memory> -#include <string> -#include <vector> - -#include "base/containers/flat_map.h" -#include "base/macros.h" -#include "base/optional.h" -#include "components/viz/common/frame_sinks/begin_frame_source.h" -#include "components/viz/common/surfaces/frame_sink_id.h" -#include "components/viz/host/host_frame_sink_manager.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "services/ui/gpu_host/gpu_host_delegate.h" -#include "services/ui/public/interfaces/window_manager_window_tree_factory.mojom.h" -#include "services/ui/public/interfaces/window_tree.mojom.h" -#include "services/ui/ws/async_event_dispatcher_lookup.h" -#include "services/ui/ws/ids.h" -#include "services/ui/ws/operation.h" -#include "services/ui/ws/server_window_delegate.h" -#include "services/ui/ws/server_window_observer.h" -#include "services/ui/ws/server_window_tracker.h" -#include "services/ui/ws/user_display_manager_delegate.h" -#include "services/ui/ws/video_detector_impl.h" - -namespace ui { - -namespace gpu_host { -class GpuHost; -} - -namespace ws { - -class AccessPolicy; -class Display; -class DisplayManager; -class ServerWindow; -class ThreadedImageCursorsFactory; -class UserActivityMonitor; -class WindowManagerDisplayRoot; -class WindowManagerState; -class WindowManagerWindowTreeFactory; -class WindowServerDelegate; -class WindowTree; -class WindowTreeBinding; - -enum class DisplayCreationConfig; - -struct WindowTreeAndWindowId { - WindowTree* tree = nullptr; - ClientSpecificId window_id = 0u; -}; - -// WindowServer manages the set of clients of the window server (all the -// WindowTrees) as well as providing the root of the hierarchy. -class WindowServer : public ServerWindowDelegate, - public ServerWindowObserver, - public gpu_host::GpuHostDelegate, - public UserDisplayManagerDelegate, - public AsyncEventDispatcherLookup { - public: - WindowServer(WindowServerDelegate* delegate, bool should_host_viz); - ~WindowServer() override; - - WindowServerDelegate* delegate() { return delegate_; } - - DisplayManager* display_manager() { return display_manager_.get(); } - const DisplayManager* display_manager() const { - return display_manager_.get(); - } - - void SetDisplayCreationConfig(DisplayCreationConfig config); - DisplayCreationConfig display_creation_config() const { - return display_creation_config_; - } - - void SetGpuHost(std::unique_ptr<gpu_host::GpuHost> gpu_host); - gpu_host::GpuHost* gpu_host() { return gpu_host_.get(); } - - bool is_hosting_viz() const { return !!host_frame_sink_manager_; } - - ThreadedImageCursorsFactory* GetThreadedImageCursorsFactory(); - - // Creates a new ServerWindow. The return value is owned by the caller, but - // must be destroyed before WindowServer. - ServerWindow* CreateServerWindow( - const viz::FrameSinkId& frame_sink_id, - const std::map<std::string, std::vector<uint8_t>>& properties); - - // Returns the id for the next WindowTree. - ClientSpecificId GetAndAdvanceNextClientId(); - - // See description of WindowTree::Embed() for details. This assumes - // |transport_window_id| is valid. - WindowTree* EmbedAtWindow(ServerWindow* root, - mojom::WindowTreeClientPtr client, - uint32_t flags, - std::unique_ptr<AccessPolicy> access_policy); - - // Adds |tree_impl_ptr| to the set of known trees. Use DestroyTree() to - // destroy the tree. - void AddTree(std::unique_ptr<WindowTree> tree_impl_ptr, - std::unique_ptr<WindowTreeBinding> binding, - mojom::WindowTreePtr tree_ptr); - WindowTree* CreateTreeForWindowManager( - mojom::WindowTreeRequest window_tree_request, - mojom::WindowTreeClientPtr window_tree_client, - bool automatically_create_display_roots); - // Invoked when a WindowTree's connection encounters an error. - void DestroyTree(WindowTree* tree); - - // Returns the tree by client id. - WindowTree* GetTreeWithId(ClientSpecificId client_id); - - WindowTree* GetTreeWithClientName(const std::string& client_name); - - size_t num_trees() const { return tree_map_.size(); } - - // Creates and registers a token for use in a future embedding. |window_id| - // is the window_id portion of the ClientWindowId to use for the window in - // |tree|. |window_id| is validated during actual embed. - base::UnguessableToken RegisterEmbedToken(WindowTree* tree, - ClientSpecificId window_id); - - // Unregisters the WindowTree associated with |token| and returns it. Returns - // null if RegisterEmbedToken() was not previously called for |token|. - WindowTreeAndWindowId UnregisterEmbedToken( - const base::UnguessableToken& token); - - OperationType current_operation_type() const { - return current_operation_ ? current_operation_->type() - : OperationType::NONE; - } - - // Returns true if the specified client issued the current operation. - bool IsOperationSource(ClientSpecificId client_id) const { - return current_operation_ && - current_operation_->source_tree_id() == client_id; - } - - // Invoked when a client messages a client about the change. This is used - // to avoid sending ServerChangeIdAdvanced() unnecessarily. - void OnTreeMessagedClient(ClientSpecificId id); - - // Returns true if OnTreeMessagedClient() was invoked for id. - bool DidTreeMessageClient(ClientSpecificId id) const; - - // Returns the WindowTree that has |window| as a root. - WindowTree* GetTreeWithRoot(const ServerWindow* window) { - return const_cast<WindowTree*>( - const_cast<const WindowServer*>(this)->GetTreeWithRoot(window)); - } - const WindowTree* GetTreeWithRoot(const ServerWindow* window) const; - - UserActivityMonitor* user_activity_monitor() { - return user_activity_monitor_.get(); - } - - WindowManagerWindowTreeFactory* window_manager_window_tree_factory() { - return window_manager_window_tree_factory_.get(); - } - void BindWindowManagerWindowTreeFactory( - mojo::InterfaceRequest<mojom::WindowManagerWindowTreeFactory> request); - - // Sets focus to |window|. Returns true if |window| already has focus, or - // focus was successfully changed. Returns |false| if |window| is not a valid - // window to receive focus. - bool SetFocusedWindow(ServerWindow* window); - ServerWindow* GetFocusedWindow(); - - void SetHighContrastMode(bool enabled); - - // Returns a change id for the window manager that is associated with - // |source| and |client_change_id|. When the window manager replies - // WindowManagerChangeCompleted() is called to obtain the original source - // and client supplied change_id that initiated the called. - uint32_t GenerateWindowManagerChangeId(WindowTree* source, - uint32_t client_change_id); - - // Called when a response from the window manager is obtained. Calls to - // the client that initiated the change with the change id originally - // supplied by the client. - void WindowManagerChangeCompleted(uint32_t window_manager_change_id, - bool success); - void WindowManagerCreatedTopLevelWindow(WindowTree* wm_tree, - uint32_t window_manager_change_id, - ServerWindow* window); - - // Called when we get an unexpected message from the WindowManager. - // TODO(sky): decide what we want to do here. - void WindowManagerSentBogusMessage() {} - - // These functions trivially delegate to all WindowTrees, which in - // term notify their clients. - void ProcessWindowBoundsChanged( - const ServerWindow* window, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds, - const base::Optional<viz::LocalSurfaceId>& local_surface_id); - void ProcessWindowTransformChanged(const ServerWindow* window, - const gfx::Transform& old_transform, - const gfx::Transform& new_transform); - void ProcessClientAreaChanged( - const ServerWindow* window, - const gfx::Insets& new_client_area, - const std::vector<gfx::Rect>& new_additional_client_areas); - void ProcessCaptureChanged(const ServerWindow* new_capture, - const ServerWindow* old_capture); - void ProcessWillChangeWindowHierarchy(const ServerWindow* window, - const ServerWindow* new_parent, - const ServerWindow* old_parent); - void ProcessWindowHierarchyChanged(const ServerWindow* window, - const ServerWindow* new_parent, - const ServerWindow* old_parent); - void ProcessWindowReorder(const ServerWindow* window, - const ServerWindow* relative_window, - const mojom::OrderDirection direction); - void ProcessWindowDeleted(ServerWindow* window); - void ProcessWillChangeWindowCursor(ServerWindow* window, - const ui::CursorData& cursor); - - // Sends an |event| to all WindowTrees that might be observing events. Skips - // |ignore_tree| if it is non-null. |target_window| is the target of the - // event. - void SendToPointerWatchers(const ui::Event& event, - ServerWindow* target_window, - WindowTree* ignore_tree, - int64_t display_id); - - // Sets a callback to be called whenever a surface is activated. This - // corresponds a client submitting a new CompositorFrame for a Window. This - // should only be called in a test configuration. - void SetSurfaceActivationCallback( - base::OnceCallback<void(ServerWindow*)> callback); - - void StartMoveLoop(uint32_t change_id, - ServerWindow* window, - WindowTree* initiator, - const gfx::Rect& revert_bounds); - void EndMoveLoop(); - uint32_t GetCurrentMoveLoopChangeId(); - ServerWindow* GetCurrentMoveLoopWindow(); - WindowTree* GetCurrentMoveLoopInitiator(); - gfx::Rect GetCurrentMoveLoopRevertBounds(); - bool in_move_loop() const { return !!current_move_loop_; } - - void StartDragLoop(uint32_t change_id, - ServerWindow* window, - WindowTree* initiator); - void EndDragLoop(); - uint32_t GetCurrentDragLoopChangeId(); - ServerWindow* GetCurrentDragLoopWindow(); - WindowTree* GetCurrentDragLoopInitiator(); - bool in_drag_loop() const { return !!current_drag_loop_; } - - void OnDisplayReady(Display* display, bool is_first); - void OnDisplayDestroyed(Display* display); - void OnNoMoreDisplays(); - WindowManagerState* GetWindowManagerState(); - - VideoDetectorImpl* video_detector() { return &video_detector_; } - - // ServerWindowDelegate: - VizHostProxy* GetVizHostProxy() override; - void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info, - ServerWindow* window) override; - - // UserDisplayManagerDelegate: - bool GetFrameDecorations(mojom::FrameDecorationValuesPtr* values) override; - int64_t GetInternalDisplayId() override; - - private: - struct CurrentMoveLoopState; - struct CurrentDragLoopState; - friend class Operation; - - using WindowTreeMap = - std::map<ClientSpecificId, std::unique_ptr<WindowTree>>; - - struct InFlightWindowManagerChange { - // Identifies the client that initiated the change. - ClientSpecificId client_id; - - // Change id supplied by the client. - uint32_t client_change_id; - }; - - using InFlightWindowManagerChangeMap = - std::map<uint32_t, InFlightWindowManagerChange>; - - bool GetAndClearInFlightWindowManagerChange( - uint32_t window_manager_change_id, - InFlightWindowManagerChange* change); - - // Invoked when a client is about to execute a window server operation. - // Subsequently followed by FinishOperation() once the change is done. - // - // Changes should never nest, meaning each PrepareForOperation() must be - // balanced with a call to FinishOperation() with no PrepareForOperation() - // in between. - void PrepareForOperation(Operation* op); - - // Balances a call to PrepareForOperation(). - void FinishOperation(); - - // Updates the native cursor by figuring out what window is under the mouse - // cursor. This is run in response to events that change the bounds or window - // hierarchy. - void UpdateNativeCursorFromMouseLocation(ServerWindow* window); - void UpdateNativeCursorFromMouseLocation( - WindowManagerDisplayRoot* display_root); - - // Updates the native cursor if the cursor is currently inside |window|. This - // is run in response to events that change the mouse cursor properties of - // |window|. - void UpdateNativeCursorIfOver(ServerWindow* window); - - // Finds the parent client that will embed |surface_id| and claims ownership - // of the temporary reference. If no parent client is found then tell GPU to - // immediately drop the temporary reference. |window| is the ServerWindow - // that corresponds to |surface_id|. - void HandleTemporaryReferenceForNewSurface(const viz::SurfaceId& surface_id, - ServerWindow* window); - - void CreateFrameSinkManager(); - - // AsyncEventDispatcherLookup: - AsyncEventDispatcher* GetAsyncEventDispatcherById( - ClientSpecificId id) override; - - // Overridden from ServerWindowDelegate: - ServerWindow* GetRootWindowForDrawn(const ServerWindow* window) override; - - // Overridden from ServerWindowObserver: - void OnWindowDestroyed(ServerWindow* window) override; - void OnWillChangeWindowHierarchy(ServerWindow* window, - ServerWindow* new_parent, - ServerWindow* old_parent) override; - void OnWindowHierarchyChanged(ServerWindow* window, - ServerWindow* new_parent, - ServerWindow* old_parent) override; - void OnWindowBoundsChanged(ServerWindow* window, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds) override; - void OnWindowTransformChanged(ServerWindow* window, - const gfx::Transform& old_transform, - const gfx::Transform& new_transform) override; - void OnWindowClientAreaChanged( - ServerWindow* window, - const gfx::Insets& new_client_area, - const std::vector<gfx::Rect>& new_additional_client_areas) override; - void OnWindowReordered(ServerWindow* window, - ServerWindow* relative, - mojom::OrderDirection direction) override; - void OnWillChangeWindowVisibility(ServerWindow* window) override; - void OnWindowVisibilityChanged(ServerWindow* window) override; - void OnWindowOpacityChanged(ServerWindow* window, - float old_opacity, - float new_opacity) override; - void OnWindowSharedPropertyChanged( - ServerWindow* window, - const std::string& name, - const std::vector<uint8_t>* new_data) override; - void OnWindowCursorChanged(ServerWindow* window, - const ui::CursorData& cursor) override; - void OnWindowNonClientCursorChanged(ServerWindow* window, - const ui::CursorData& cursor) override; - void OnWindowTextInputStateChanged(ServerWindow* window, - const ui::TextInputState& state) override; - void OnTransientWindowAdded(ServerWindow* window, - ServerWindow* transient_child) override; - void OnTransientWindowRemoved(ServerWindow* window, - ServerWindow* transient_child) override; - void OnWindowModalTypeChanged(ServerWindow* window, - ModalType old_modal_type) override; - - // GpuHostDelegate: - void OnGpuServiceInitialized() override; - - WindowServerDelegate* delegate_; - - // ID to use for next WindowTree. - ClientSpecificId next_client_id_; - - std::unique_ptr<DisplayManager> display_manager_; - - std::unique_ptr<CurrentDragLoopState> current_drag_loop_; - std::unique_ptr<CurrentMoveLoopState> current_move_loop_; - - // Set of WindowTrees. - WindowTreeMap tree_map_; - - // If non-null then we're processing a client operation. The Operation is - // not owned by us (it's created on the stack by WindowTree). - Operation* current_operation_; - - bool in_destructor_; - bool high_contrast_mode_ = false; - - // Maps from window manager change id to the client that initiated the - // request. - InFlightWindowManagerChangeMap in_flight_wm_change_map_; - - // Next id supplied to the window manager. - uint32_t next_wm_change_id_; - - std::unique_ptr<gpu_host::GpuHost> gpu_host_; - base::OnceCallback<void(ServerWindow*)> surface_activation_callback_; - - std::unique_ptr<UserActivityMonitor> user_activity_monitor_; - - std::unique_ptr<WindowManagerWindowTreeFactory> - window_manager_window_tree_factory_; - - viz::SurfaceId root_surface_id_; - - // Incremented when the viz process is restarted. - uint32_t viz_restart_id_ = viz::BeginFrameSource::kNotRestartableId + 1; - - // Provides interfaces to create and manage FrameSinks. - std::unique_ptr<viz::HostFrameSinkManager> host_frame_sink_manager_; - std::unique_ptr<VizHostProxy> viz_host_proxy_; - - VideoDetectorImpl video_detector_; - - // System modal windows not attached to a display are added here. Once - // attached to a display they are removed. - ServerWindowTracker pending_system_modal_windows_; - - DisplayCreationConfig display_creation_config_; - - // Tokens registered by ScheduleEmbedForExistingClient() that are removed when - // EmbedUsingToken() is called. - using ScheduledEmbeds = - base::flat_map<base::UnguessableToken, WindowTreeAndWindowId>; - ScheduledEmbeds scheduled_embeds_; - - DISALLOW_COPY_AND_ASSIGN(WindowServer); -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_WINDOW_SERVER_H_
diff --git a/services/ui/ws/window_server_delegate.cc b/services/ui/ws/window_server_delegate.cc deleted file mode 100644 index 6d1194b..0000000 --- a/services/ui/ws/window_server_delegate.cc +++ /dev/null
@@ -1,25 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "services/ui/ws/window_server_delegate.h" - -#include "services/ui/ws/window_tree_binding.h" - -namespace ui { -namespace ws { - -void WindowServerDelegate::OnFirstDisplayReady() {} - -std::unique_ptr<WindowTreeBinding> -WindowServerDelegate::CreateWindowTreeBinding( - BindingType type, - ws::WindowServer* window_server, - ws::WindowTree* tree, - mojom::WindowTreeRequest* tree_request, - mojom::WindowTreeClientPtr* client) { - return nullptr; -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/window_server_delegate.h b/services/ui/ws/window_server_delegate.h deleted file mode 100644 index 1539856..0000000 --- a/services/ui/ws/window_server_delegate.h +++ /dev/null
@@ -1,72 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SERVICES_UI_WS_WINDOW_SERVER_DELEGATE_H_ -#define SERVICES_UI_WS_WINDOW_SERVER_DELEGATE_H_ - -#include <stdint.h> - -#include <memory> -#include <string> - -#include "mojo/public/cpp/bindings/interface_request.h" -#include "services/ui/common/types.h" -#include "services/ui/public/interfaces/window_tree.mojom.h" - -namespace ui { - -namespace mojom { -class WindowTree; -} - -namespace ws { - -class Display; -class ThreadedImageCursorsFactory; -class WindowServer; -class WindowTree; -class WindowTreeBinding; - -class WindowServerDelegate { - public: - enum BindingType { - EMBED, - WINDOW_MANAGER, - }; - - // WindowServer signal that display initialization can start. - virtual void StartDisplayInit() = 0; - - // Called once when the AcceleratedWidget of a Display is available. - virtual void OnFirstDisplayReady(); - - virtual void OnNoMoreDisplays() = 0; - - virtual bool IsTestConfig() const = 0; - - // Creates a WindowTreeBinding. Default implementation returns null, which - // creates DefaultBinding. - virtual std::unique_ptr<WindowTreeBinding> CreateWindowTreeBinding( - BindingType type, - ws::WindowServer* window_server, - ws::WindowTree* tree, - mojom::WindowTreeRequest* tree_request, - mojom::WindowTreeClientPtr* client); - - // Called prior to a new WindowTree being created for a - // WindowManagerWindowTreeFactory. |automatically_create_display_roots| - // mirrors that of CreateWindowTree(). See it for details. - virtual void OnWillCreateTreeForWindowManager( - bool automatically_create_display_roots) = 0; - - virtual ThreadedImageCursorsFactory* GetThreadedImageCursorsFactory() = 0; - - protected: - virtual ~WindowServerDelegate() {} -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_WINDOW_SERVER_DELEGATE_H_
diff --git a/services/ui/ws/window_server_service_test_base.cc b/services/ui/ws/window_server_service_test_base.cc deleted file mode 100644 index 5dfd12d..0000000 --- a/services/ui/ws/window_server_service_test_base.cc +++ /dev/null
@@ -1,64 +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 "services/ui/ws/window_server_service_test_base.h" - -#include <memory> - -#include "base/command_line.h" -#include "base/macros.h" -#include "services/service_manager/public/cpp/service.h" -#include "services/service_manager/public/cpp/service_test.h" -#include "services/ui/common/switches.h" -#include "ui/gl/gl_switches.h" - -namespace ui { - -namespace { - -const char kTestAppName[] = "ui_service_unittests"; - -class WindowServerServiceTestClient - : public service_manager::test::ServiceTestClient { - public: - explicit WindowServerServiceTestClient(WindowServerServiceTestBase* test) - : ServiceTestClient(test), test_(test) {} - ~WindowServerServiceTestClient() override {} - - private: - // service_manager::test::ServiceTestClient: - void OnBindInterface(const service_manager::BindSourceInfo& source_info, - const std::string& interface_name, - mojo::ScopedMessagePipeHandle interface_pipe) override { - test_->OnBindInterface(source_info, interface_name, - std::move(interface_pipe)); - } - - WindowServerServiceTestBase* test_; - - DISALLOW_COPY_AND_ASSIGN(WindowServerServiceTestClient); -}; - -void EnsureCommandLineSwitch(const std::string& name) { - base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); - if (!cmd_line->HasSwitch(name)) - cmd_line->AppendSwitch(name); -} - -} // namespace - -WindowServerServiceTestBase::WindowServerServiceTestBase() - : ServiceTest(kTestAppName) { - EnsureCommandLineSwitch(switches::kUseTestConfig); - EnsureCommandLineSwitch(::switches::kOverrideUseSoftwareGLForTests); -} - -WindowServerServiceTestBase::~WindowServerServiceTestBase() {} - -std::unique_ptr<service_manager::Service> -WindowServerServiceTestBase::CreateService() { - return std::make_unique<WindowServerServiceTestClient>(this); -} - -} // namespace ui
diff --git a/services/ui/ws/window_server_service_test_base.h b/services/ui/ws/window_server_service_test_base.h deleted file mode 100644 index 882fb07..0000000 --- a/services/ui/ws/window_server_service_test_base.h +++ /dev/null
@@ -1,33 +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. - -#ifndef SERVICES_UI_WS_WINDOW_SERVER_SERVICE_TEST_BASE_H_ -#define SERVICES_UI_WS_WINDOW_SERVER_SERVICE_TEST_BASE_H_ - -#include "base/macros.h" -#include "services/service_manager/public/cpp/service_test.h" - -namespace ui { - -// Base class for all window manager ServiceTests to perform some common setup. -class WindowServerServiceTestBase : public service_manager::test::ServiceTest { - public: - WindowServerServiceTestBase(); - ~WindowServerServiceTestBase() override; - - virtual void OnBindInterface( - const service_manager::BindSourceInfo& source_info, - const std::string& interface_name, - mojo::ScopedMessagePipeHandle interface_pipe) = 0; - - private: - // service_manager::test::ServiceTest: - std::unique_ptr<service_manager::Service> CreateService() override; - - DISALLOW_COPY_AND_ASSIGN(WindowServerServiceTestBase); -}; - -} // namespace ui - -#endif // SERVICES_UI_WS_WINDOW_SERVER_SERVICE_TEST_BASE_H_
diff --git a/services/ui/ws/window_server_test_base.cc b/services/ui/ws/window_server_test_base.cc deleted file mode 100644 index 241f8f38..0000000 --- a/services/ui/ws/window_server_test_base.cc +++ /dev/null
@@ -1,310 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "services/ui/ws/window_server_test_base.h" - -#include "base/bind.h" -#include "base/command_line.h" -#include "base/location.h" -#include "base/run_loop.h" -#include "base/single_thread_task_runner.h" -#include "base/test/test_timeouts.h" -#include "base/threading/thread_task_runner_handle.h" -#include "services/service_manager/public/cpp/connector.h" -#include "ui/aura/env.h" -#include "ui/aura/mus/window_tree_client.h" -#include "ui/aura/mus/window_tree_host_mus.h" -#include "ui/base/ui_base_features.h" -#include "ui/base/ui_base_switches.h" -#include "ui/display/display.h" -#include "ui/display/display_list.h" -#include "ui/wm/core/capture_controller.h" - -namespace ui { -namespace { - -base::RunLoop* current_run_loop = nullptr; - -void TimeoutRunLoop(const base::Closure& timeout_task, bool* timeout) { - CHECK(current_run_loop); - *timeout = true; - timeout_task.Run(); -} - -} // namespace - -WindowServerTestBase::WindowServerTestBase() { - registry_.AddInterface<mojom::WindowTreeClient>( - base::Bind(&WindowServerTestBase::BindWindowTreeClientRequest, - base::Unretained(this))); -} - -WindowServerTestBase::~WindowServerTestBase() {} - -// static -bool WindowServerTestBase::DoRunLoopWithTimeout() { - if (current_run_loop != nullptr) - return false; - - bool timeout = false; - base::RunLoop run_loop; - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, base::Bind(&TimeoutRunLoop, run_loop.QuitClosure(), &timeout), - TestTimeouts::action_timeout()); - - current_run_loop = &run_loop; - current_run_loop->Run(); - current_run_loop = nullptr; - return !timeout; -} - -// static -bool WindowServerTestBase::QuitRunLoop() { - if (!current_run_loop) - return false; - - current_run_loop->Quit(); - current_run_loop = nullptr; - return true; -} - -void WindowServerTestBase::DeleteWindowTreeClient( - aura::WindowTreeClient* client) { - for (auto iter = window_tree_clients_.begin(); - iter != window_tree_clients_.end(); ++iter) { - if (iter->get() == client) { - window_tree_clients_.erase(iter); - return; - } - } - NOTREACHED(); -} - -std::unique_ptr<aura::WindowTreeClient> -WindowServerTestBase::ReleaseMostRecentClient() { - if (window_tree_clients_.empty()) - return nullptr; - - std::unique_ptr<aura::WindowTreeClient> result = - std::move(window_tree_clients_.back()); - window_tree_clients_.pop_back(); - return result; -} - -void WindowServerTestBase::SetUp() { - feature_list_.InitAndEnableFeature(features::kMashDeprecated); - WindowServerServiceTestBase::SetUp(); - - env_ = aura::Env::CreateInstance(aura::Env::Mode::MUS); - display::Screen::SetScreenInstance(&screen_); - std::unique_ptr<aura::WindowTreeClient> window_manager_window_tree_client = - aura::WindowTreeClient::CreateForWindowManager(connector(), this, this); - window_manager_ = window_manager_window_tree_client.get(); - window_tree_clients_.push_back(std::move(window_manager_window_tree_client)); - - // Connecting as the WindowManager results in OnWmNewDisplay() being called - // with the display (and root). Wait for it to be called so we have display - // and root window information (otherwise we can't really do anything). - ASSERT_TRUE(DoRunLoopWithTimeout()); -} - -void WindowServerTestBase::TearDown() { - // WindowTreeHost depends on WindowTreeClient. - window_tree_hosts_.clear(); - window_tree_clients_.clear(); - env_.reset(); - display::Screen::SetScreenInstance(nullptr); - - WindowServerServiceTestBase::TearDown(); -} - -void WindowServerTestBase::OnBindInterface( - const service_manager::BindSourceInfo& source_info, - const std::string& interface_name, - mojo::ScopedMessagePipeHandle interface_pipe) { - registry_.BindInterface(interface_name, std::move(interface_pipe)); -} - -void WindowServerTestBase::OnEmbed( - std::unique_ptr<aura::WindowTreeHostMus> window_tree_host) { - EXPECT_TRUE(QuitRunLoop()); - window_tree_hosts_.push_back(std::move(window_tree_host)); -} - -void WindowServerTestBase::OnLostConnection(aura::WindowTreeClient* client) { - window_tree_client_lost_connection_ = true; - DeleteWindowTreeClient(client); -} - -void WindowServerTestBase::OnEmbedRootDestroyed( - aura::WindowTreeHostMus* window_tree_host) { - if (!DeleteWindowTreeHost(window_tree_host)) { - // Assume a subclass called Embed() and wants us to destroy it. - delete window_tree_host; - } -} - -void WindowServerTestBase::OnPointerEventObserved(const ui::PointerEvent& event, - int64_t display_id, - aura::Window* target) {} - -aura::PropertyConverter* WindowServerTestBase::GetPropertyConverter() { - return &property_converter_; -} - -void WindowServerTestBase::SetWindowManagerClient( - aura::WindowManagerClient* client) { - window_manager_client_ = client; -} - -void WindowServerTestBase::OnWmConnected() {} - -void WindowServerTestBase::OnWmSetBounds(aura::Window* window, - const gfx::Rect& bounds) { - if (!window_manager_delegate_) - return; - window_manager_delegate_->OnWmSetBounds(window, bounds); -} - -bool WindowServerTestBase::OnWmSetProperty( - aura::Window* window, - const std::string& name, - std::unique_ptr<std::vector<uint8_t>>* new_data) { - return window_manager_delegate_ - ? window_manager_delegate_->OnWmSetProperty(window, name, new_data) - : true; -} - -void WindowServerTestBase::OnWmSetModalType(aura::Window* window, - ui::ModalType type) { - if (window_manager_delegate_) - window_manager_delegate_->OnWmSetModalType(window, type); -} - -void WindowServerTestBase::OnWmSetCanFocus(aura::Window* window, - bool can_focus) { - if (window_manager_delegate_) - window_manager_delegate_->OnWmSetCanFocus(window, can_focus); -} - -aura::Window* WindowServerTestBase::OnWmCreateTopLevelWindow( - ui::mojom::WindowType window_type, - std::map<std::string, std::vector<uint8_t>>* properties) { - return window_manager_delegate_ - ? window_manager_delegate_->OnWmCreateTopLevelWindow(window_type, - properties) - : nullptr; -} - -void WindowServerTestBase::OnWmClientJankinessChanged( - const std::set<aura::Window*>& client_windows, - bool janky) { - if (window_manager_delegate_) - window_manager_delegate_->OnWmClientJankinessChanged(client_windows, janky); -} - -void WindowServerTestBase::OnWmWillCreateDisplay( - const display::Display& display) { - screen_.display_list().AddDisplay(display, - display::DisplayList::Type::PRIMARY); - if (window_manager_delegate_) - window_manager_delegate_->OnWmWillCreateDisplay(display); -} - -void WindowServerTestBase::OnWmNewDisplay( - std::unique_ptr<aura::WindowTreeHostMus> window_tree_host, - const display::Display& display) { - EXPECT_TRUE(QuitRunLoop()); - ASSERT_TRUE(window_manager_client_); - window_manager_client_->AddActivationParent(window_tree_host->window()); - window_tree_hosts_.push_back(std::move(window_tree_host)); - - if (window_manager_delegate_) - window_manager_delegate_->OnWmNewDisplay(nullptr, display); -} - -void WindowServerTestBase::OnWmDisplayRemoved( - aura::WindowTreeHostMus* window_tree_host) { - if (window_manager_delegate_) - window_manager_delegate_->OnWmDisplayRemoved(window_tree_host); - ASSERT_TRUE(DeleteWindowTreeHost(window_tree_host)); -} - -void WindowServerTestBase::OnWmDisplayModified( - const display::Display& display) { - if (window_manager_delegate_) - window_manager_delegate_->OnWmDisplayModified(display); -} - -ui::mojom::EventResult WindowServerTestBase::OnAccelerator( - uint32_t accelerator_id, - const ui::Event& event, - base::flat_map<std::string, std::vector<uint8_t>>* properties) { - return window_manager_delegate_ ? window_manager_delegate_->OnAccelerator( - accelerator_id, event, properties) - : ui::mojom::EventResult::UNHANDLED; -} - -void WindowServerTestBase::OnCursorTouchVisibleChanged(bool enabled) { - if (window_manager_delegate_) - window_manager_delegate_->OnCursorTouchVisibleChanged(enabled); -} - -void WindowServerTestBase::OnWmPerformMoveLoop( - aura::Window* window, - ui::mojom::MoveLoopSource source, - const gfx::Point& cursor_location, - const base::Callback<void(bool)>& on_done) { - if (window_manager_delegate_) { - window_manager_delegate_->OnWmPerformMoveLoop(window, source, - cursor_location, on_done); - } -} - -void WindowServerTestBase::OnWmCancelMoveLoop(aura::Window* window) { - if (window_manager_delegate_) - window_manager_delegate_->OnWmCancelMoveLoop(window); -} - -void WindowServerTestBase::OnWmSetClientArea( - aura::Window* window, - const gfx::Insets& insets, - const std::vector<gfx::Rect>& additional_client_areas) { - if (window_manager_delegate_) { - window_manager_delegate_->OnWmSetClientArea(window, insets, - additional_client_areas); - } -} - -bool WindowServerTestBase::IsWindowActive(aura::Window* window) { - if (window_manager_delegate_) - window_manager_delegate_->IsWindowActive(window); - return false; -} - -void WindowServerTestBase::OnWmDeactivateWindow(aura::Window* window) { - if (window_manager_delegate_) - window_manager_delegate_->OnWmDeactivateWindow(window); -} - -void WindowServerTestBase::BindWindowTreeClientRequest( - ui::mojom::WindowTreeClientRequest request) { - const bool create_discardable_memory = false; - window_tree_clients_.push_back(aura::WindowTreeClient::CreateForEmbedding( - connector(), this, std::move(request), create_discardable_memory)); -} - -bool WindowServerTestBase::DeleteWindowTreeHost( - aura::WindowTreeHostMus* window_tree_host) { - for (auto iter = window_tree_hosts_.begin(); iter != window_tree_hosts_.end(); - ++iter) { - if ((*iter).get() == window_tree_host) { - window_tree_hosts_.erase(iter); - return true; - } - } - return false; -} - -} // namespace ui
diff --git a/services/ui/ws/window_server_test_base.h b/services/ui/ws/window_server_test_base.h deleted file mode 100644 index 0d92c21a..0000000 --- a/services/ui/ws/window_server_test_base.h +++ /dev/null
@@ -1,175 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SERVICES_UI_WS_WINDOW_SERVER_TEST_BASE_H_ -#define SERVICES_UI_WS_WINDOW_SERVER_TEST_BASE_H_ - -#include <memory> -#include <set> - -#include "base/macros.h" -#include "base/test/scoped_feature_list.h" -#include "services/service_manager/public/cpp/binder_registry.h" -#include "services/ui/public/interfaces/window_tree.mojom.h" -#include "services/ui/ws/window_server_service_test_base.h" -#include "ui/aura/mus/property_converter.h" -#include "ui/aura/mus/window_manager_delegate.h" -#include "ui/aura/mus/window_tree_client_delegate.h" -#include "ui/display/screen_base.h" -#include "ui/wm/core/wm_state.h" - -namespace aura { -class Env; -} - -namespace ui { - -// WindowServerTestBase is a base class for use with shell tests that use -// WindowServer. SetUp() connects to the WindowServer and blocks until OnEmbed() -// has been invoked. window_manager() can be used to access the WindowServer -// established as part of SetUp(). -class WindowServerTestBase : public WindowServerServiceTestBase, - public aura::WindowTreeClientDelegate, - public aura::WindowManagerDelegate { - public: - WindowServerTestBase(); - ~WindowServerTestBase() override; - - // True if WindowTreeClientDelegate::OnLostConnection() was called. - bool window_tree_client_lost_connection() const { - return window_tree_client_lost_connection_; - } - - // Runs the MessageLoop until QuitRunLoop() is called, or a timeout occurs. - // Returns true on success. Generally prefer running a RunLoop and - // explicitly quiting that, but use this for times when that is not possible. - static bool DoRunLoopWithTimeout() WARN_UNUSED_RESULT; - - // Quits a run loop started by DoRunLoopWithTimeout(). Returns true on - // success, false if a RunLoop isn't running. - static bool QuitRunLoop() WARN_UNUSED_RESULT; - - aura::WindowTreeClient* window_manager() { return window_manager_; } - aura::WindowManagerClient* window_manager_client() { - return window_manager_client_; - } - - protected: - void set_window_manager_delegate(aura::WindowManagerDelegate* delegate) { - window_manager_delegate_ = delegate; - } - - // Cleans up internal state then deletes |client|. - void DeleteWindowTreeClient(aura::WindowTreeClient* client); - - // Returns the most recent WindowTreeClient that was created as the result of - // InterfaceFactory<WindowTreeClient> being called. In other words the most - // recent WindowTreeClient created as the result of a client embedding. - std::unique_ptr<aura::WindowTreeClient> ReleaseMostRecentClient(); - - // testing::Test: - void SetUp() override; - void TearDown() override; - - // WindowServerServiceTestBase: - void OnBindInterface(const service_manager::BindSourceInfo& source_info, - const std::string& interface_name, - mojo::ScopedMessagePipeHandle interface_pipe) override; - - // WindowTreeClientDelegate: - void OnEmbed( - std::unique_ptr<aura::WindowTreeHostMus> window_tree_host) override; - void OnLostConnection(aura::WindowTreeClient* client) override; - void OnEmbedRootDestroyed(aura::WindowTreeHostMus* window_tree_host) override; - void OnPointerEventObserved(const ui::PointerEvent& event, - int64_t display_id, - aura::Window* target) override; - aura::PropertyConverter* GetPropertyConverter() override; - - // WindowManagerDelegate: - void SetWindowManagerClient(aura::WindowManagerClient* client) override; - void OnWmConnected() override; - void OnWmAcceleratedWidgetAvailableForDisplay( - int64_t display_id, - gfx::AcceleratedWidget widget) override {} - void OnWmSetBounds(aura::Window* window, const gfx::Rect& bounds) override; - bool OnWmSetProperty( - aura::Window* window, - const std::string& name, - std::unique_ptr<std::vector<uint8_t>>* new_data) override; - void OnWmSetModalType(aura::Window* window, ui::ModalType type) override; - void OnWmSetCanFocus(aura::Window* window, bool can_focus) override; - aura::Window* OnWmCreateTopLevelWindow( - ui::mojom::WindowType window_type, - std::map<std::string, std::vector<uint8_t>>* properties) override; - void OnWmClientJankinessChanged(const std::set<aura::Window*>& client_windows, - bool not_responding) override; - void OnWmBuildDragImage(const gfx::Point& screen_location, - const gfx::ImageSkia& drag_image, - const gfx::Vector2d& drag_image_offset, - ui::mojom::PointerKind source) override {} - void OnWmMoveDragImage(const gfx::Point& screen_location) override {} - void OnWmDestroyDragImage() override {} - void OnWmWillCreateDisplay(const display::Display& display) override; - void OnWmNewDisplay(std::unique_ptr<aura::WindowTreeHostMus> window_tree_host, - const display::Display& display) override; - void OnWmDisplayRemoved(aura::WindowTreeHostMus* window_tree_host) override; - void OnWmDisplayModified(const display::Display& display) override; - mojom::EventResult OnAccelerator( - uint32_t accelerator_id, - const ui::Event& event, - base::flat_map<std::string, std::vector<uint8_t>>* properties) override; - void OnCursorTouchVisibleChanged(bool enabled) override; - void OnWmPerformMoveLoop(aura::Window* window, - mojom::MoveLoopSource source, - const gfx::Point& cursor_location, - const base::Callback<void(bool)>& on_done) override; - void OnWmCancelMoveLoop(aura::Window* window) override; - void OnWmSetClientArea( - aura::Window* window, - const gfx::Insets& insets, - const std::vector<gfx::Rect>& additional_client_areas) override; - bool IsWindowActive(aura::Window* window) override; - void OnWmDeactivateWindow(aura::Window* window) override; - - void BindWindowTreeClientRequest( - mojom::WindowTreeClientRequest request); - - private: - // Removes |window_tree_host| from |window_tree_hosts_| and deletes it. - // Returns true on success, and false if not found, in which case - // |window_tree_host| is not deleted. - bool DeleteWindowTreeHost(aura::WindowTreeHostMus* window_tree_host); - - base::test::ScopedFeatureList feature_list_; - - std::unique_ptr<aura::Env> env_; - ::wm::WMState wm_state_; - display::ScreenBase screen_; - aura::PropertyConverter property_converter_; - - std::vector<std::unique_ptr<aura::WindowTreeClient>> window_tree_clients_; - - std::vector<std::unique_ptr<aura::WindowTreeHostMus>> window_tree_hosts_; - - // The window server connection held by the window manager (app running at - // the root window). - aura::WindowTreeClient* window_manager_ = nullptr; - - // A test can override the WM-related behaviour by installing its own - // WindowManagerDelegate during the test. - aura::WindowManagerDelegate* window_manager_delegate_ = nullptr; - - aura::WindowManagerClient* window_manager_client_ = nullptr; - - bool window_tree_client_lost_connection_ = false; - - service_manager::BinderRegistry registry_; - - DISALLOW_COPY_AND_ASSIGN(WindowServerTestBase); -}; - -} // namespace ui - -#endif // SERVICES_UI_WS_WINDOW_SERVER_TEST_BASE_H_
diff --git a/services/ui/ws/window_server_test_impl.cc b/services/ui/ws/window_server_test_impl.cc deleted file mode 100644 index 56028334..0000000 --- a/services/ui/ws/window_server_test_impl.cc +++ /dev/null
@@ -1,61 +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 "services/ui/ws/window_server_test_impl.h" - -#include "services/ui/public/interfaces/window_tree.mojom.h" -#include "services/ui/ws/server_window.h" -#include "services/ui/ws/window_server.h" -#include "services/ui/ws/window_tree.h" - -namespace ui { -namespace ws { - -WindowServerTestImpl::WindowServerTestImpl(WindowServer* window_server) - : window_server_(window_server) {} - -WindowServerTestImpl::~WindowServerTestImpl() {} - -void WindowServerTestImpl::OnSurfaceActivated( - const std::string& name, - EnsureClientHasDrawnWindowCallback cb, - ServerWindow* window) { - // This api is used to detect when a client has painted once, which is - // dictated by whether there is a CompositorFrameSink. - WindowTree* tree = window_server_->GetTreeWithClientName(name); - if (tree && tree->HasRoot(window) && - window->has_created_compositor_frame_sink()) { - std::move(cb).Run(true); - } else { - // No tree with the given name, or it hasn't painted yet. Install a callback - // for the next time a client creates a CompositorFramesink. - InstallCallback(name, std::move(cb)); - } -} - -void WindowServerTestImpl::InstallCallback( - const std::string& client_name, - EnsureClientHasDrawnWindowCallback cb) { - window_server_->SetSurfaceActivationCallback( - base::BindOnce(&WindowServerTestImpl::OnSurfaceActivated, - base::Unretained(this), client_name, std::move(cb))); -} - -void WindowServerTestImpl::EnsureClientHasDrawnWindow( - const std::string& client_name, - EnsureClientHasDrawnWindowCallback callback) { - WindowTree* tree = window_server_->GetTreeWithClientName(client_name); - if (tree) { - for (const ServerWindow* window : tree->roots()) { - if (window->has_created_compositor_frame_sink()) { - std::move(callback).Run(true); - return; - } - } - } - InstallCallback(client_name, std::move(callback)); -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/window_server_test_impl.h b/services/ui/ws/window_server_test_impl.h deleted file mode 100644 index 43c4d361..0000000 --- a/services/ui/ws/window_server_test_impl.h +++ /dev/null
@@ -1,46 +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. - -#ifndef SERVICES_UI_WS_WINDOW_SERVER_TEST_IMPL_H_ -#define SERVICES_UI_WS_WINDOW_SERVER_TEST_IMPL_H_ - -#include "services/ui/public/interfaces/window_server_test.mojom.h" - -namespace ui { -namespace ws { - -class ServerWindow; -class WindowServer; - -// Used to detect when a client (as identified by a name) has drawn at least -// once to screen. -class WindowServerTestImpl : public mojom::WindowServerTest { - public: - explicit WindowServerTestImpl(WindowServer* server); - ~WindowServerTestImpl() override; - - private: - void OnSurfaceActivated(const std::string& name, - EnsureClientHasDrawnWindowCallback cb, - ServerWindow* window); - - // Installs a callback that calls OnSurfaceActivated() the next time a client - // creates a compositor frame. - void InstallCallback(const std::string& name, - EnsureClientHasDrawnWindowCallback cb); - - // mojom::WindowServerTest: - void EnsureClientHasDrawnWindow( - const std::string& client_name, - EnsureClientHasDrawnWindowCallback callback) override; - - WindowServer* window_server_; - - DISALLOW_COPY_AND_ASSIGN(WindowServerTestImpl); -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_WINDOW_SERVER_TEST_IMPL_H_
diff --git a/services/ui/ws/window_tree.cc b/services/ui/ws/window_tree.cc deleted file mode 100644 index 0b48d0a..0000000 --- a/services/ui/ws/window_tree.cc +++ /dev/null
@@ -1,2898 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "services/ui/ws/window_tree.h" - -#include <stddef.h> - -#include <utility> - -#include "base/bind.h" -#include "base/callback_helpers.h" -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "build/build_config.h" -#include "mojo/public/cpp/bindings/map.h" -#include "services/ui/common/util.h" -#include "services/ui/display/screen_manager.h" -#include "services/ui/ws/cursor_location_manager.h" -#include "services/ui/ws/debug_utils.h" -#include "services/ui/ws/default_access_policy.h" -#include "services/ui/ws/display.h" -#include "services/ui/ws/display_manager.h" -#include "services/ui/ws/event_location.h" -#include "services/ui/ws/event_matcher.h" -#include "services/ui/ws/event_processor.h" -#include "services/ui/ws/focus_controller.h" -#include "services/ui/ws/frame_generator.h" -#include "services/ui/ws/modal_window_controller.h" -#include "services/ui/ws/operation.h" -#include "services/ui/ws/platform_display.h" -#include "services/ui/ws/server_window.h" -#include "services/ui/ws/server_window_observer.h" -#include "services/ui/ws/user_display_manager.h" -#include "services/ui/ws/window_manager_display_root.h" -#include "services/ui/ws/window_manager_state.h" -#include "services/ui/ws/window_server.h" -#include "services/ui/ws/window_tree_binding.h" -#include "ui/base/cursor/cursor.h" -#include "ui/display/display.h" -#include "ui/display/display_list.h" -#include "ui/display/screen_base.h" -#include "ui/display/types/display_constants.h" -#include "ui/platform_window/mojo/ime_type_converters.h" -#include "ui/platform_window/text_input_state.h" - -using mojo::InterfaceRequest; - -using EventProperties = base::flat_map<std::string, std::vector<uint8_t>>; - -namespace ui { -namespace ws { -namespace { - -bool HasPositiveInset(const gfx::Insets& insets) { - return insets.width() > 0 || insets.height() > 0 || insets.left() > 0 || - insets.right() > 0; -} - -FrameGenerator* GetFrameGenerator(WindowManagerDisplayRoot* display_root) { - return display_root->display()->platform_display() - ? display_root->display()->platform_display()->GetFrameGenerator() - : nullptr; -} - -display::ViewportMetrics TransportMetricsToDisplayMetrics( - const ui::mojom::WmViewportMetrics& transport_metrics) { - display::ViewportMetrics viewport_metrics; - viewport_metrics.bounds_in_pixels = transport_metrics.bounds_in_pixels; - viewport_metrics.device_scale_factor = transport_metrics.device_scale_factor; - viewport_metrics.ui_scale_factor = transport_metrics.ui_scale_factor; - return viewport_metrics; -} - -} // namespace - -class TargetedEvent : public ServerWindowObserver { - public: - TargetedEvent(ServerWindow* target, - const ui::Event& event, - const EventLocation& event_location, - WindowTree::DispatchEventCallback callback) - : target_(target), - event_(ui::Event::Clone(event)), - event_location_(event_location), - callback_(std::move(callback)) { - target_->AddObserver(this); - } - ~TargetedEvent() override { - if (target_) - target_->RemoveObserver(this); - } - - ServerWindow* target() { return target_; } - std::unique_ptr<ui::Event> TakeEvent() { return std::move(event_); } - const EventLocation& event_location() const { return event_location_; } - WindowTree::DispatchEventCallback TakeCallback() { - return std::move(callback_); - } - - private: - // ServerWindowObserver: - void OnWindowDestroyed(ServerWindow* window) override { - DCHECK_EQ(target_, window); - target_->RemoveObserver(this); - target_ = nullptr; - } - - ServerWindow* target_; - std::unique_ptr<ui::Event> event_; - const EventLocation event_location_; - WindowTree::DispatchEventCallback callback_; - - DISALLOW_COPY_AND_ASSIGN(TargetedEvent); -}; - -struct WindowTree::DragMoveState { - // Whether we've queued a move to |queued_cursor_location_| when we get an - // ack from WmMoveDragImage. - bool has_queued_drag_window_move = false; - - // When |has_queued_drag_window_move_| is true, this is a location which - // should be sent to the window manager as soon as it acked the last one. - gfx::Point queued_cursor_location; -}; - -WindowTree::WindowTree(WindowServer* window_server, - bool is_for_embedding, - ServerWindow* root, - std::unique_ptr<AccessPolicy> access_policy) - : window_server_(window_server), - is_for_embedding_(is_for_embedding), - id_(window_server_->GetAndAdvanceNextClientId()), - access_policy_(std::move(access_policy)), - event_ack_id_(0), - window_manager_internal_(nullptr), - drag_weak_factory_(this) { - if (root) - roots_.insert(root); - access_policy_->Init(id_, this); -} - -WindowTree::~WindowTree() { - DestroyWindows(); - - // We alert the WindowManagerState that we're destroying this state here - // because WindowManagerState would attempt to use things that wouldn't have - // been cleaned up by OnWindowDestroyingTreeImpl(). - if (window_manager_state_) { - window_manager_state_->OnWillDestroyTree(this); - window_manager_state_.reset(); - } -} - -void WindowTree::Init(std::unique_ptr<WindowTreeBinding> binding, - mojom::WindowTreePtr tree) { - DCHECK(!binding_); - binding_ = std::move(binding); - - if (roots_.empty()) - return; - - std::vector<const ServerWindow*> to_send; - CHECK_EQ(1u, roots_.size()); - const ServerWindow* root = *roots_.begin(); - GetUnknownWindowsFrom(root, &to_send, nullptr); - - Display* display = GetDisplay(root); - int64_t display_id = display ? display->GetId() : display::kInvalidDisplayId; - const ServerWindow* focused_window = - display ? display->GetFocusedWindow() : nullptr; - if (focused_window) - focused_window = access_policy_->GetWindowForFocusChange(focused_window); - ClientWindowId focused_window_id; - if (focused_window) - IsWindowKnown(focused_window, &focused_window_id); - - const bool drawn = root->parent() && root->parent()->IsDrawn(); - client()->OnEmbed(WindowToWindowData(to_send.front()), std::move(tree), - display_id, ClientWindowIdToTransportId(focused_window_id), - drawn, root->current_local_surface_id()); -} - -void WindowTree::OnAcceleratedWidgetAvailableForDisplay(Display* display) { - DCHECK(window_manager_internal_); - // TODO(sad): Use GpuSurfaceTracker on platforms where a gpu::SurfaceHandle is - // not the same as a gfx::AcceleratedWidget. - window_manager_internal_->WmOnAcceleratedWidgetForDisplay( - display->GetId(), display->platform_display()->GetAcceleratedWidget()); -} - -void WindowTree::ConfigureWindowManager( - bool automatically_create_display_roots) { - // ConfigureWindowManager() should be called early on, before anything - // else. |waiting_for_top_level_window_info_| must be null as if - // |waiting_for_top_level_window_info_| is non-null it means we're about to - // create an associated interface, which doesn't work with pause/resume. - // TODO(sky): DCHECK temporary until 626869 is sorted out. - DCHECK(!waiting_for_top_level_window_info_); - DCHECK(!window_manager_internal_); - automatically_create_display_roots_ = automatically_create_display_roots; - window_manager_internal_ = binding_->GetWindowManager(); - window_manager_internal_->OnConnect(); - window_manager_state_ = std::make_unique<WindowManagerState>(this); -} - -bool WindowTree::IsWindowKnown(const ServerWindow* window, - ClientWindowId* id) const { - if (!window) - return false; - auto iter = window_to_client_id_map_.find(window); - if (iter == window_to_client_id_map_.end()) - return false; - if (id) - *id = iter->second; - return true; -} - -bool WindowTree::HasRoot(const ServerWindow* window) const { - return roots_.count(window) > 0; -} - -const ServerWindow* WindowTree::GetWindowByClientId( - const ClientWindowId& id) const { - auto iter = client_id_to_window_map_.find(id); - return iter == client_id_to_window_map_.end() ? nullptr : iter->second; -} - -const Display* WindowTree::GetDisplay(const ServerWindow* window) const { - return window ? display_manager()->GetDisplayContaining(window) : nullptr; -} - -const WindowManagerDisplayRoot* WindowTree::GetWindowManagerDisplayRoot( - const ServerWindow* window) const { - return window ? display_manager()->GetWindowManagerDisplayRoot(window) - : nullptr; -} - -DisplayManager* WindowTree::display_manager() { - return window_server_->display_manager(); -} - -const DisplayManager* WindowTree::display_manager() const { - return window_server_->display_manager(); -} - -void WindowTree::PrepareForWindowServerShutdown() { - window_manager_internal_client_binding_.reset(); - binding_->ResetClientForShutdown(); - if (window_manager_internal_) - window_manager_internal_ = binding_->GetWindowManager(); -} - -void WindowTree::AddRootForWindowManager(const ServerWindow* root) { - if (!automatically_create_display_roots_) - return; - - DCHECK(automatically_create_display_roots_); - DCHECK(window_manager_internal_); - const ClientWindowId client_window_id = root->frame_sink_id(); - AddToMaps(root, client_window_id); - roots_.insert(root); - - Display* ws_display = GetDisplay(root); - DCHECK(ws_display); - - window_manager_internal_->WmNewDisplayAdded( - ws_display->GetDisplay(), WindowToWindowData(root), - root->parent()->IsDrawn(), root->current_local_surface_id()); -} - -void WindowTree::OnWillDestroyTree(WindowTree* tree) { - DCHECK_NE(tree, this); // This function is not called for |this|. - - if (event_source_wms_ && event_source_wms_->window_tree() == tree) - event_source_wms_ = nullptr; - - // Notify our client if |tree| was embedded in any of our windows. - for (const auto* tree_root : tree->roots_) { - const bool owns_tree_root = tree_root->owning_tree_id() == id_; - if (owns_tree_root) - client()->OnEmbeddedAppDisconnected(TransportIdForWindow(tree_root)); - } - - if (window_manager_state_) - window_manager_state_->OnWillDestroyTree(tree); -} - -void WindowTree::OnWmDisplayModified(const display::Display& display) { - window_manager_internal_->WmDisplayModified(display); -} - -void WindowTree::NotifyChangeCompleted( - uint32_t change_id, - mojom::WindowManagerErrorCode error_code) { - client()->OnChangeCompleted( - change_id, error_code == mojom::WindowManagerErrorCode::SUCCESS); -} - -void WindowTree::OnWmMoveDragImageAck() { - if (drag_move_state_->has_queued_drag_window_move) { - gfx::Point queued_location = drag_move_state_->queued_cursor_location; - drag_move_state_.reset(); - OnDragMoved(queued_location); - } else { - drag_move_state_.reset(); - } -} - -ServerWindow* WindowTree::ProcessSetDisplayRoot( - const display::Display& display_to_create, - const display::ViewportMetrics& viewport_metrics, - bool is_primary_display, - const ClientWindowId& client_window_id, - const std::vector<display::Display>& mirrors) { - DCHECK(window_manager_state_); // Only called for window manager. - DVLOG(3) << "SetDisplayRoot client=" << id_ - << " global window_id=" << client_window_id.ToString(); - - if (automatically_create_display_roots_) { - DVLOG(1) << "SetDisplayRoot is only applicable when " - << "automatically_create_display_roots is false"; - return nullptr; - } - - ServerWindow* window = GetWindowByClientId(client_window_id); - const bool is_moving_to_new_display = - window && window->parent() && base::ContainsKey(roots_, window); - if (!window || (window->parent() && !is_moving_to_new_display)) { - DVLOG(1) << "SetDisplayRoot called with invalid window id " - << client_window_id.ToString(); - return nullptr; - } - - if (base::ContainsKey(roots_, window) && !is_moving_to_new_display) { - DVLOG(1) << "SetDisplayRoot called with existing root"; - return nullptr; - } - - Display* display = display_manager()->GetDisplayById(display_to_create.id()); - const bool display_already_existed = display != nullptr; - if (!display) { - // Create a display if the window manager is extending onto a new display. - display = display_manager()->AddDisplayForWindowManager( - is_primary_display, display_to_create, viewport_metrics); - } else if (!display->window_manager_display_root()) { - // Init the root if the display already existed as a mirroring destination. - display->InitWindowManagerDisplayRoots(); - } - - if (!mirrors.empty()) - NOTIMPLEMENTED() << "TODO(crbug.com/806318): Mus+Viz mirroring/unified"; - - DCHECK(display); - WindowManagerDisplayRoot* display_root = - display->window_manager_display_root(); - DCHECK(display_root); - display_root->root()->RemoveAllChildren(); - - // NOTE: this doesn't resize the window in any way. We assume the client takes - // care of any modifications it needs to do. - roots_.insert(window); - Operation op(this, window_server_, OperationType::ADD_WINDOW); - ServerWindow* old_parent = - is_moving_to_new_display ? window->parent() : nullptr; - display_root->root()->Add(window); - if (is_moving_to_new_display) { - DCHECK(old_parent); - window_manager_state_->DeleteWindowManagerDisplayRoot(old_parent); - } - if (display_already_existed && - display->platform_display()->GetAcceleratedWidget()) { - // Notify the window manager that the dispay's accelerated widget is already - // available, if the display is being reused for a new window tree host. - window_manager_internal_->WmOnAcceleratedWidgetForDisplay( - display->GetId(), display->platform_display()->GetAcceleratedWidget()); - } - return window; -} - -bool WindowTree::ProcessSwapDisplayRoots(int64_t display_id1, - int64_t display_id2) { - DCHECK(window_manager_state_); // Can only be called by the window manager. - DVLOG(3) << "SwapDisplayRoots display_id1=" << display_id2 - << " display_id2=" << display_id2; - if (automatically_create_display_roots_) { - DVLOG(1) << "SwapDisplayRoots only applicable when window-manager creates " - << "display roots"; - return false; - } - Display* display1 = display_manager()->GetDisplayById(display_id1); - Display* display2 = display_manager()->GetDisplayById(display_id2); - if (!display1 || !display2) { - DVLOG(1) << "SwapDisplayRoots called with unknown display ids"; - return false; - } - - WindowManagerDisplayRoot* display_root1 = - display1->window_manager_display_root(); - WindowManagerDisplayRoot* display_root2 = - display2->window_manager_display_root(); - - if (!display_root1->GetClientVisibleRoot() || - !display_root2->GetClientVisibleRoot()) { - DVLOG(1) << "SetDisplayRoot called with displays that have not been " - << "configured"; - return false; - } - - display_root1->root()->Add(display_root2->GetClientVisibleRoot()); - display_root2->root()->Add(display_root1->GetClientVisibleRoot()); - - // TODO(sky): this is race condition here if one is valid and one null. - FrameGenerator* frame_generator1 = GetFrameGenerator(display_root1); - FrameGenerator* frame_generator2 = GetFrameGenerator(display_root2); - if (frame_generator1 && frame_generator2) - frame_generator1->SwapSurfaceWith(frame_generator2); - - return true; -} - -bool WindowTree::ProcessSetBlockingContainers( - std::vector<mojom::BlockingContainersPtr> - transport_all_blocking_containers) { - DCHECK(window_manager_state_); // Can only be called by the window manager. - - std::vector<BlockingContainers> all_containers; - for (auto& transport_container : transport_all_blocking_containers) { - BlockingContainers blocking_containers; - blocking_containers.system_modal_container = GetWindowByClientId( - MakeClientWindowId(transport_container->system_modal_container_id)); - if (!blocking_containers.system_modal_container) { - DVLOG(1) << "SetBlockingContainers called with unknown modal container"; - return false; - } - blocking_containers.min_container = GetWindowByClientId( - MakeClientWindowId(transport_container->min_container_id)); - all_containers.push_back(blocking_containers); - } - window_manager_state_->event_processor() - ->modal_window_controller() - ->SetBlockingContainers(all_containers); - return true; -} - -bool WindowTree::SetCapture(const ClientWindowId& client_window_id) { - ServerWindow* window = GetWindowByClientId(client_window_id); - WindowManagerDisplayRoot* display_root = GetWindowManagerDisplayRoot(window); - ServerWindow* current_capture_window = - display_root ? display_root->window_manager_state()->capture_window() - : nullptr; - if (window && window->IsDrawn() && display_root && - access_policy_->CanSetCapture(window) && - (!current_capture_window || - access_policy_->CanSetCapture(current_capture_window))) { - Operation op(this, window_server_, OperationType::SET_CAPTURE); - return display_root->window_manager_state()->SetCapture(window, id_); - } - return false; -} - -bool WindowTree::ReleaseCapture(const ClientWindowId& client_window_id) { - ServerWindow* window = GetWindowByClientId(client_window_id); - WindowManagerDisplayRoot* display_root = GetWindowManagerDisplayRoot(window); - ServerWindow* current_capture_window = - display_root ? display_root->window_manager_state()->capture_window() - : nullptr; - if (!window || !display_root || - (current_capture_window && - !access_policy_->CanSetCapture(current_capture_window)) || - window != current_capture_window) { - return false; - } - Operation op(this, window_server_, OperationType::RELEASE_CAPTURE); - return display_root->window_manager_state()->SetCapture(nullptr, - kInvalidClientId); -} - -void WindowTree::DispatchEvent(ServerWindow* target, - const ui::Event& event, - const EventLocation& event_location, - DispatchEventCallback callback) { - if (event_ack_id_ || !event_queue_.empty()) { - // Either awaiting an ack, or there are events in the queue. Store the event - // for processing when the ack is received. - event_queue_.push(std::make_unique<TargetedEvent>( - target, event, event_location, std::move(callback))); - // TODO(sad): If the |event_queue_| grows too large, then this should notify - // Display, so that it can stop sending events. - return; - } - - DispatchEventImpl(target, event, event_location, std::move(callback)); -} - -void WindowTree::DispatchAccelerator(uint32_t accelerator_id, - const ui::Event& event, - AcceleratorCallback callback) { - DVLOG(3) << "OnAccelerator client=" << id_; - DCHECK(window_manager_internal_); // Only valid for the window manager. - if (callback) { - GenerateEventAckId(); - accelerator_ack_callback_ = std::move(callback); - } else { - DCHECK_EQ(0u, event_ack_id_); - DCHECK(!accelerator_ack_callback_); - } - // TODO: https://crbug.com/617167. Don't clone event once we map mojom::Event - // directly to ui::Event. - window_manager_internal_->OnAccelerator(event_ack_id_, accelerator_id, - ui::Event::Clone(event)); -} - -bool WindowTree::NewWindow( - const ClientWindowId& client_window_id, - const std::map<std::string, std::vector<uint8_t>>& properties) { - DVLOG(3) << "new window client=" << id_ - << " window_id=" << client_window_id.ToString(); - if (!IsValidIdForNewWindow(client_window_id)) { - DVLOG(1) << "NewWindow failed (id is not valid for client)"; - return false; - } - DCHECK(!GetWindowByClientId(client_window_id)); - DCHECK_EQ(id_, client_window_id.client_id()); - ServerWindow* window = - window_server_->CreateServerWindow(client_window_id, properties); - created_windows_.insert(window); - AddToMaps(window, client_window_id); - return true; -} - -bool WindowTree::AddWindow(const ClientWindowId& parent_id, - const ClientWindowId& child_id) { - ServerWindow* parent = GetWindowByClientId(parent_id); - ServerWindow* child = GetWindowByClientId(child_id); - DVLOG(3) << "add window client=" << id_ - << " client parent window_id=" << parent_id.ToString() - << " global window_id=" << DebugWindowId(parent) - << " client child window_id= " << child_id.ToString() - << " global window_id=" << DebugWindowId(child); - if (!parent) { - DVLOG(1) << "AddWindow failed (no parent)"; - return false; - } - if (!child) { - DVLOG(1) << "AddWindow failed (no child)"; - return false; - } - if (child->parent() == parent) { - DVLOG(1) << "AddWindow failed (already has parent)"; - return false; - } - if (child->Contains(parent)) { - DVLOG(1) << "AddWindow failed (child contains parent)"; - return false; - } - if (!access_policy_->CanAddWindow(parent, child)) { - DVLOG(1) << "AddWindow failed (access denied)"; - return false; - } - Operation op(this, window_server_, OperationType::ADD_WINDOW); - parent->Add(child); - return true; -} - -bool WindowTree::AddTransientWindow(const ClientWindowId& window_id, - const ClientWindowId& transient_window_id) { - ServerWindow* window = GetWindowByClientId(window_id); - ServerWindow* transient_window = GetWindowByClientId(transient_window_id); - if (window && transient_window && !transient_window->Contains(window) && - access_policy_->CanAddTransientWindow(window, transient_window)) { - Operation op(this, window_server_, OperationType::ADD_TRANSIENT_WINDOW); - return window->AddTransientWindow(transient_window); - } - return false; -} - -bool WindowTree::DeleteWindow(const ClientWindowId& window_id) { - ServerWindow* window = GetWindowByClientId(window_id); - DVLOG(3) << "removing window from parent client=" << id_ - << " client window_id= " << window_id.ToString() - << " global window_id=" << DebugWindowId(window); - if (!window) - return false; - - if (roots_.count(window) > 0) { - // Deleting a root behaves as an unembed. - window_server_->OnTreeMessagedClient(id_); - RemoveRoot(window, RemoveRootReason::UNEMBED); - return true; - } - - if (!access_policy_->CanDeleteWindow(window) && - !ShouldRouteToWindowManager(window)) { - return false; - } - - // Have the owner of the tree service the actual delete. - WindowTree* tree = window_server_->GetTreeWithId(window->owning_tree_id()); - return tree && tree->DeleteWindowImpl(this, window); -} - -bool WindowTree::SetModalType(const ClientWindowId& window_id, - ModalType modal_type) { - ServerWindow* window = GetWindowByClientId(window_id); - if (!window) { - DVLOG(1) << "SetModalType failed (invalid id)"; - return false; - } - - if (is_for_embedding_ && modal_type == MODAL_TYPE_SYSTEM) { - DVLOG(1) << "SetModalType failed (not allowed for embedded clients)"; - return false; - } - - if (ShouldRouteToWindowManager(window)) { - WindowTree* wm_tree = GetWindowManagerDisplayRoot(window) - ->window_manager_state() - ->window_tree(); - wm_tree->window_manager_internal_->WmSetModalType( - wm_tree->TransportIdForWindow(window), modal_type); - return true; - } - - if (!access_policy_->CanSetModal(window)) { - DVLOG(1) << "SetModalType failed (access denied)"; - return false; - } - - if (window->modal_type() == modal_type) - return true; - - window->SetModalType(modal_type); - return true; -} - -bool WindowTree::SetChildModalParent( - const ClientWindowId& window_id, - const ClientWindowId& modal_parent_window_id) { - ServerWindow* window = GetWindowByClientId(window_id); - ServerWindow* modal_parent_window = - GetWindowByClientId(modal_parent_window_id); - // A value of null for |modal_parent_window| resets the modal parent. - if (!window) { - DVLOG(1) << "SetChildModalParent failed (invalid id)"; - return false; - } - - if (!access_policy_->CanSetChildModalParent(window, modal_parent_window)) { - DVLOG(1) << "SetChildModalParent failed (access denied)"; - return false; - } - - window->SetChildModalParent(modal_parent_window); - return true; -} - -std::vector<const ServerWindow*> WindowTree::GetWindowTree( - const ClientWindowId& window_id) const { - const ServerWindow* window = GetWindowByClientId(window_id); - std::vector<const ServerWindow*> windows; - if (window) - GetWindowTreeImpl(window, &windows); - return windows; -} - -bool WindowTree::SetWindowVisibility(const ClientWindowId& window_id, - bool visible) { - ServerWindow* window = GetWindowByClientId(window_id); - DVLOG(3) << "SetWindowVisibility client=" << id_ - << " client window_id= " << window_id.ToString() - << " global window_id=" << DebugWindowId(window); - if (!window) { - DVLOG(1) << "SetWindowVisibility failed (no window)"; - return false; - } - if (!access_policy_->CanChangeWindowVisibility(window) || - (!can_change_root_window_visibility_ && HasRoot(window))) { - DVLOG(1) << "SetWindowVisibility failed (access policy denied change)"; - return false; - } - if (window->visible() == visible) - return true; - Operation op(this, window_server_, OperationType::SET_WINDOW_VISIBILITY); - window->SetVisible(visible); - return true; -} - -bool WindowTree::SetWindowOpacity(const ClientWindowId& window_id, - float opacity) { - ServerWindow* window = GetWindowByClientId(window_id); - if (!window || !access_policy_->CanChangeWindowOpacity(window)) - return false; - if (window->opacity() == opacity) - return true; - Operation op(this, window_server_, OperationType::SET_WINDOW_OPACITY); - window->SetOpacity(opacity); - return true; -} - -bool WindowTree::SetFocus(const ClientWindowId& window_id) { - ServerWindow* window = GetWindowByClientId(window_id); - ServerWindow* currently_focused = window_server_->GetFocusedWindow(); - DVLOG(3) << "SetFocusedWindow client=" << id_ - << " client window_id=" << window_id.ToString() - << " window=" << DebugWindowId(window); - if (currently_focused == window) - return true; - - Display* display = GetDisplay(window); - if (window && (!display || !window->can_focus() || !window->IsDrawn())) { - DVLOG(1) << "SetFocus failed (window cannot be focused)"; - return false; - } - - if (!access_policy_->CanSetFocus(window)) { - DVLOG(1) << "SetFocus failed (blocked by access policy)"; - return false; - } - - Operation op(this, window_server_, OperationType::SET_FOCUS); - bool success = window_server_->SetFocusedWindow(window); - if (!success) - DVLOG(1) << "SetFocus failed (could not SetFocusedWindow)"; - return success; -} - -bool WindowTree::Embed(const ClientWindowId& window_id, - mojom::WindowTreeClientPtr window_tree_client, - uint32_t flags) { - if (!window_tree_client || !CanEmbed(window_id)) - return false; - ServerWindow* window = GetWindowByClientId(window_id); - DCHECK(window); // CanEmbed() returns false if no window. - PrepareForEmbed(window); - // mojom::kEmbedFlagEmbedderInterceptsEvents is inherited, otherwise an - // embedder could effectively circumvent it by embedding itself. - if (embedder_intercepts_events_) - flags = mojom::kEmbedFlagEmbedderInterceptsEvents; - window_server_->EmbedAtWindow(window, std::move(window_tree_client), flags, - base::WrapUnique(new DefaultAccessPolicy)); - client()->OnFrameSinkIdAllocated(ClientWindowIdToTransportId(window_id), - window->frame_sink_id()); - return true; -} - -bool WindowTree::EmbedExistingTree( - const ClientWindowId& window_id, - const WindowTreeAndWindowId& tree_and_window_id, - const base::UnguessableToken& token) { - const ClientWindowId window_id_in_embedded(tree_and_window_id.tree->id(), - tree_and_window_id.window_id); - if (!CanEmbed(window_id) || - !tree_and_window_id.tree->IsValidIdForNewWindow(window_id_in_embedded)) { - return false; - } - ServerWindow* window = GetWindowByClientId(window_id); - DCHECK(window); // CanEmbed() returns false if no window. - PrepareForEmbed(window); - tree_and_window_id.tree->AddRootForToken(token, window, - window_id_in_embedded); - window->UpdateFrameSinkId(window_id_in_embedded); - client()->OnFrameSinkIdAllocated(ClientWindowIdToTransportId(window_id), - window->frame_sink_id()); - return true; -} - -bool WindowTree::IsWaitingForNewTopLevelWindow(uint32_t wm_change_id) { - return waiting_for_top_level_window_info_ && - waiting_for_top_level_window_info_->wm_change_id == wm_change_id; -} - -viz::FrameSinkId WindowTree::OnWindowManagerCreatedTopLevelWindow( - uint32_t wm_change_id, - uint32_t client_change_id, - const ServerWindow* window) { - DCHECK(IsWaitingForNewTopLevelWindow(wm_change_id)); - std::unique_ptr<WaitingForTopLevelWindowInfo> - waiting_for_top_level_window_info( - std::move(waiting_for_top_level_window_info_)); - binding_->SetIncomingMethodCallProcessingPaused(false); - // We were paused, so the id should still be valid. - DCHECK(IsValidIdForNewWindow( - waiting_for_top_level_window_info->client_window_id)); - if (!window) { - client()->OnChangeCompleted(client_change_id, false); - return viz::FrameSinkId(); - } - AddToMaps(window, waiting_for_top_level_window_info->client_window_id); - roots_.insert(window); - Display* display = GetDisplay(window); - int64_t display_id = display ? display->GetId() : display::kInvalidDisplayId; - const bool drawn = window->parent() && window->parent()->IsDrawn(); - client()->OnTopLevelCreated(client_change_id, WindowToWindowData(window), - display_id, drawn, - window->current_local_surface_id()); - return waiting_for_top_level_window_info->client_window_id; -} - -void WindowTree::AddActivationParent(const ClientWindowId& window_id) { - ServerWindow* window = GetWindowByClientId(window_id); - if (window) - window->set_is_activation_parent(true); - else - DVLOG(1) << "AddActivationParent failed (invalid window id)"; -} - -void WindowTree::OnChangeCompleted(uint32_t change_id, bool success) { - client()->OnChangeCompleted(change_id, success); -} - -void WindowTree::OnEventOccurredOutsideOfModalWindow( - const ServerWindow* modal_window) { - DCHECK(window_manager_internal_); - // Only tell the window manager about windows it created. - if (modal_window->owning_tree_id() != id_) - return; - - ClientWindowId client_window_id; - const bool is_known = IsWindowKnown(modal_window, &client_window_id); - // The window manager knows all windows. - DCHECK(is_known); - window_manager_internal_->OnEventBlockedByModalWindow( - ClientWindowIdToTransportId(client_window_id)); -} - -void WindowTree::OnCursorTouchVisibleChanged(bool enabled) { - DCHECK(window_manager_internal_); - window_manager_internal_->OnCursorTouchVisibleChanged(enabled); -} - -void WindowTree::OnDisplayDestroying(int64_t display_id) { - DCHECK(window_manager_internal_); - if (automatically_create_display_roots_) - window_manager_internal_->WmDisplayRemoved(display_id); - // For the else case the client should detect removal directly. -} - -void WindowTree::ClientJankinessChanged(WindowTree* tree) { - tree->janky_ = !tree->janky_; - // Don't inform the client if it is the source of jank (which generally only - // happens while debugging). - if (window_manager_internal_ && tree != this) { - window_manager_internal_->WmClientJankinessChanged( - tree->id(), tree->janky()); - } -} - -void WindowTree::ProcessWindowBoundsChanged( - const ServerWindow* window, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds, - bool originated_change, - const base::Optional<viz::LocalSurfaceId>& local_surface_id) { - ClientWindowId client_window_id; - if (originated_change || !IsWindowKnown(window, &client_window_id)) - return; - client()->OnWindowBoundsChanged(ClientWindowIdToTransportId(client_window_id), - old_bounds, new_bounds, local_surface_id); -} - -void WindowTree::ProcessWindowTransformChanged( - const ServerWindow* window, - const gfx::Transform& old_transform, - const gfx::Transform& new_transform, - bool originated_change) { - ClientWindowId client_window_id; - if (originated_change || !IsWindowKnown(window, &client_window_id)) - return; - client()->OnWindowTransformChanged( - ClientWindowIdToTransportId(client_window_id), old_transform, - new_transform); -} - -void WindowTree::ProcessClientAreaChanged( - const ServerWindow* window, - const gfx::Insets& new_client_area, - const std::vector<gfx::Rect>& new_additional_client_areas, - bool originated_change) { - ClientWindowId client_window_id; - if (originated_change || !IsWindowKnown(window, &client_window_id)) - return; - client()->OnClientAreaChanged( - ClientWindowIdToTransportId(client_window_id), new_client_area, - std::vector<gfx::Rect>(new_additional_client_areas)); -} - -void WindowTree::ProcessWillChangeWindowHierarchy( - const ServerWindow* window, - const ServerWindow* new_parent, - const ServerWindow* old_parent, - bool originated_change) { - if (originated_change) - return; - - const bool old_drawn = window->IsDrawn(); - const bool new_drawn = - window->visible() && new_parent && new_parent->IsDrawn(); - if (old_drawn == new_drawn) - return; - - NotifyDrawnStateChanged(window, new_drawn); -} - -void WindowTree::ProcessWindowPropertyChanged( - const ServerWindow* window, - const std::string& name, - const std::vector<uint8_t>* new_data, - bool originated_change) { - if (originated_change) - return; - - ClientWindowId client_window_id; - if (!IsWindowKnown(window, &client_window_id)) - return; - - base::Optional<std::vector<uint8_t>> data; - if (new_data) - data.emplace(*new_data); - - client()->OnWindowSharedPropertyChanged( - ClientWindowIdToTransportId(client_window_id), name, data); -} - -void WindowTree::ProcessWindowHierarchyChanged(const ServerWindow* window, - const ServerWindow* new_parent, - const ServerWindow* old_parent, - bool originated_change) { - const bool knows_new = new_parent && IsWindowKnown(new_parent); - if (originated_change || (window_server_->current_operation_type() == - OperationType::DELETE_WINDOW) || - (window_server_->current_operation_type() == OperationType::EMBED) || - window_server_->DidTreeMessageClient(id_)) { - return; - } - - if (!access_policy_->ShouldNotifyOnHierarchyChange(window, &new_parent, - &old_parent)) { - return; - } - // Inform the client of any new windows and update the set of windows we know - // about. - std::vector<const ServerWindow*> to_send; - if (!IsWindowKnown(window)) - GetUnknownWindowsFrom(window, &to_send, nullptr); - const bool knows_old = old_parent && IsWindowKnown(old_parent); - if (!knows_old && !knows_new) - return; - - const Id new_parent_client_window_id = - knows_new ? TransportIdForWindow(new_parent) : kInvalidTransportId; - const Id old_parent_client_window_id = - knows_old ? TransportIdForWindow(old_parent) : kInvalidTransportId; - const Id client_window_id = - window ? TransportIdForWindow(window) : kInvalidTransportId; - client()->OnWindowHierarchyChanged( - client_window_id, old_parent_client_window_id, - new_parent_client_window_id, WindowsToWindowDatas(to_send)); - window_server_->OnTreeMessagedClient(id_); -} - -void WindowTree::ProcessWindowReorder(const ServerWindow* window, - const ServerWindow* relative_window, - mojom::OrderDirection direction, - bool originated_change) { - DCHECK_EQ(window->parent(), relative_window->parent()); - ClientWindowId client_window_id, relative_client_window_id; - if (originated_change || !IsWindowKnown(window, &client_window_id) || - !IsWindowKnown(relative_window, &relative_client_window_id) || - window_server_->DidTreeMessageClient(id_)) - return; - - // Do not notify ordering changes of the root windows, since the client - // doesn't know about the ancestors of the roots, and so can't do anything - // about this ordering change of the root. - if (HasRoot(window) || HasRoot(relative_window)) - return; - - client()->OnWindowReordered( - ClientWindowIdToTransportId(client_window_id), - ClientWindowIdToTransportId(relative_client_window_id), direction); - window_server_->OnTreeMessagedClient(id_); -} - -void WindowTree::ProcessWindowDeleted(ServerWindow* window, - bool originated_change) { - created_windows_.erase(window); - - ClientWindowId client_window_id; - if (!IsWindowKnown(window, &client_window_id)) - return; - - if (HasRoot(window)) - RemoveRoot(window, RemoveRootReason::DELETED); - else - RemoveFromMaps(window); - - if (originated_change) - return; - - client()->OnWindowDeleted(ClientWindowIdToTransportId(client_window_id)); - window_server_->OnTreeMessagedClient(id_); -} - -void WindowTree::ProcessWillChangeWindowVisibility(const ServerWindow* window, - bool originated_change) { - if (originated_change) - return; - - ClientWindowId client_window_id; - if (IsWindowKnown(window, &client_window_id)) { - client()->OnWindowVisibilityChanged( - ClientWindowIdToTransportId(client_window_id), !window->visible()); - return; - } - - bool window_target_drawn_state; - if (window->visible()) { - // Window is being hidden, won't be drawn. - window_target_drawn_state = false; - } else { - // Window is being shown. Window will be drawn if its parent is drawn. - window_target_drawn_state = window->parent() && window->parent()->IsDrawn(); - } - - NotifyDrawnStateChanged(window, window_target_drawn_state); -} - -void WindowTree::ProcessWindowOpacityChanged(const ServerWindow* window, - float old_opacity, - float new_opacity, - bool originated_change) { - if (originated_change) - return; - - ClientWindowId client_window_id; - if (IsWindowKnown(window, &client_window_id)) { - client()->OnWindowOpacityChanged( - ClientWindowIdToTransportId(client_window_id), old_opacity, - new_opacity); - } -} - -void WindowTree::ProcessCursorChanged(const ServerWindow* window, - const ui::CursorData& cursor, - bool originated_change) { - if (originated_change) - return; - ClientWindowId client_window_id; - if (!IsWindowKnown(window, &client_window_id)) - return; - - client()->OnWindowCursorChanged(ClientWindowIdToTransportId(client_window_id), - cursor); -} - -void WindowTree::ProcessFocusChanged(const ServerWindow* old_focused_window, - const ServerWindow* new_focused_window) { - if (window_server_->current_operation_type() == OperationType::SET_FOCUS && - window_server_->IsOperationSource(id_)) { - return; - } - const ServerWindow* window = - new_focused_window - ? access_policy_->GetWindowForFocusChange(new_focused_window) - : nullptr; - ClientWindowId client_window_id; - // If the window isn't known we'll supply null, which is ok. - IsWindowKnown(window, &client_window_id); - client()->OnWindowFocused(ClientWindowIdToTransportId(client_window_id)); -} - -void WindowTree::ProcessTransientWindowAdded( - const ServerWindow* window, - const ServerWindow* transient_window, - bool originated_change) { - if (originated_change) - return; - - ClientWindowId client_window_id, transient_client_window_id; - if (!IsWindowKnown(window, &client_window_id) || - !IsWindowKnown(transient_window, &transient_client_window_id)) { - return; - } - client()->OnTransientWindowAdded( - ClientWindowIdToTransportId(client_window_id), - ClientWindowIdToTransportId(transient_client_window_id)); -} - -void WindowTree::ProcessTransientWindowRemoved( - const ServerWindow* window, - const ServerWindow* transient_window, - bool originated_change) { - if (originated_change) - return; - ClientWindowId client_window_id, transient_client_window_id; - if (!IsWindowKnown(window, &client_window_id) || - !IsWindowKnown(transient_window, &transient_client_window_id)) { - return; - } - client()->OnTransientWindowRemoved( - ClientWindowIdToTransportId(client_window_id), - ClientWindowIdToTransportId(transient_client_window_id)); -} - -void WindowTree::ProcessWindowSurfaceChanged( - ServerWindow* window, - const viz::SurfaceInfo& surface_info) { - ClientWindowId client_window_id; - if (!IsWindowKnown(window, &client_window_id)) - return; - client()->OnWindowSurfaceChanged( - ClientWindowIdToTransportId(client_window_id), surface_info); -} - -void WindowTree::SendToPointerWatcher(const ui::Event& event, - ServerWindow* target_window, - int64_t display_id) { - if (!EventMatchesPointerWatcher(event)) - return; - - ClientWindowId client_window_id; - // Ignore the return value from IsWindowKnown() as in the case of the client - // not knowing the window we'll send 0, which corresponds to no window. - IsWindowKnown(target_window, &client_window_id); - client()->OnPointerEventObserved( - ui::Event::Clone(event), ClientWindowIdToTransportId(client_window_id), - display_id); -} - -Id WindowTree::ClientWindowIdToTransportId( - const ClientWindowId& client_window_id) const { - if (client_window_id.client_id() == id_) - return client_window_id.sink_id(); - const Id client_id = client_window_id.client_id(); - return (client_id << 32) | client_window_id.sink_id(); -} - -bool WindowTree::ShouldRouteToWindowManager(const ServerWindow* window) const { - if (window_manager_state_) - return false; // We are the window manager, don't route to ourself. - - // If the client created this window, then do not route it through the WM. - if (window->owning_tree_id() == id_) - return false; - - // If the client did not create the window, then it must be the root of the - // client. If not, that means the client should not know about this window, - // and so do not route the request to the WM. - if (roots_.count(window) == 0) - return false; - - return IsWindowCreatedByWindowManager(window); -} - -void WindowTree::ProcessCaptureChanged(const ServerWindow* new_capture, - const ServerWindow* old_capture, - bool originated_change) { - ClientWindowId new_capture_window_client_id; - ClientWindowId old_capture_window_client_id; - const bool new_capture_window_known = - IsWindowKnown(new_capture, &new_capture_window_client_id); - const bool old_capture_window_known = - IsWindowKnown(old_capture, &old_capture_window_client_id); - if (!new_capture_window_known && !old_capture_window_known) - return; - - if (originated_change && ((window_server_->current_operation_type() == - OperationType::RELEASE_CAPTURE) || - (window_server_->current_operation_type() == - OperationType::SET_CAPTURE))) { - return; - } - - client()->OnCaptureChanged( - ClientWindowIdToTransportId(new_capture_window_client_id), - ClientWindowIdToTransportId(old_capture_window_client_id)); -} - -Id WindowTree::TransportIdForWindow(const ServerWindow* window) const { - auto iter = window_to_client_id_map_.find(window); - DCHECK(iter != window_to_client_id_map_.end()); - return ClientWindowIdToTransportId(iter->second); -} - -bool WindowTree::IsValidIdForNewWindow(const ClientWindowId& id) const { - // Reserve 0 (ClientWindowId() and sink_id) to indicate a null window. - return client_id_to_window_map_.count(id) == 0u && - access_policy_->IsValidIdForNewWindow(id) && id != ClientWindowId() && - id.sink_id() != 0; -} - -bool WindowTree::CanReorderWindow(const ServerWindow* window, - const ServerWindow* relative_window, - mojom::OrderDirection direction) const { - if (!window) { - DVLOG(1) << "CanReorderWindow failed (invalid window)"; - return false; - } - if (!relative_window) { - DVLOG(1) << "CanReorderWindow failed (invalid relative window)"; - return false; - } - - if (!window->parent()) { - DVLOG(1) << "CanReorderWindow failed (no parent)"; - return false; - } - - if (window->parent() != relative_window->parent()) { - DVLOG(1) << "CanReorderWindow failed (parents differ)"; - return false; - } - - if (!access_policy_->CanReorderWindow(window, relative_window, direction)) { - DVLOG(1) << "CanReorderWindow failed (access policy denied)"; - return false; - } - - const ServerWindow::Windows& children = window->parent()->children(); - const size_t child_i = - std::find(children.begin(), children.end(), window) - children.begin(); - const size_t target_i = - std::find(children.begin(), children.end(), relative_window) - - children.begin(); - if ((direction == mojom::OrderDirection::ABOVE && child_i == target_i + 1) || - (direction == mojom::OrderDirection::BELOW && child_i + 1 == target_i)) { - DVLOG(1) << "CanReorderWindow failed (already in position)"; - return false; - } - - return true; -} - -bool WindowTree::RemoveWindowFromParent( - const ClientWindowId& client_window_id) { - ServerWindow* window = GetWindowByClientId(client_window_id); - DVLOG(3) << "removing window from parent client=" << id_ - << " client window_id= " << client_window_id - << " global window_id=" << DebugWindowId(window); - if (!window) { - DVLOG(1) << "RemoveWindowFromParent failed (invalid window id=" - << client_window_id.ToString() << ")"; - return false; - } - if (!window->parent()) { - DVLOG(1) << "RemoveWindowFromParent failed (no parent id=" - << client_window_id.ToString() << ")"; - return false; - } - if (!access_policy_->CanRemoveWindowFromParent(window)) { - DVLOG(1) << "RemoveWindowFromParent failed (access policy disallowed id=" - << client_window_id.ToString() << ")"; - return false; - } - Operation op(this, window_server_, OperationType::REMOVE_WINDOW_FROM_PARENT); - window->parent()->Remove(window); - return true; -} - -bool WindowTree::DeleteWindowImpl(WindowTree* source, ServerWindow* window) { - DCHECK(window); - DCHECK_EQ(window->owning_tree_id(), id_); - Operation op(source, window_server_, OperationType::DELETE_WINDOW); - delete window; - return true; -} - -void WindowTree::GetUnknownWindowsFrom( - const ServerWindow* window, - std::vector<const ServerWindow*>* windows, - const ClientWindowId* id_for_window) { - if (!access_policy_->CanGetWindowTree(window)) - return; - - // This function is called in the context of a hierarchy change when the - // parent wasn't known. We need to tell the client about the window so that - // it can set the parent correctly. - if (windows) - windows->push_back(window); - if (IsWindowKnown(window)) - return; - - const ClientWindowId client_window_id = - id_for_window ? *id_for_window : window->frame_sink_id(); - AddToMaps(window, client_window_id); - if (!access_policy_->CanDescendIntoWindowForWindowTree(window)) - return; - const ServerWindow::Windows& children = window->children(); - for (ServerWindow* child : children) - GetUnknownWindowsFrom(child, windows, nullptr); -} - -void WindowTree::AddToMaps(const ServerWindow* window, - const ClientWindowId& client_window_id) { - DCHECK_EQ(0u, client_id_to_window_map_.count(client_window_id)); - client_id_to_window_map_[client_window_id] = window; - window_to_client_id_map_[window] = client_window_id; -} - -void WindowTree::AddRootForToken(const base::UnguessableToken& token, - ServerWindow* window, - const ClientWindowId& client_window_id) { - roots_.insert(window); - Display* display = GetDisplay(window); - int64_t display_id = display ? display->GetId() : display::kInvalidDisplayId; - // Caller should have verified there is no window already registered for - // |client_window_id|. - DCHECK(!GetWindowByClientId(client_window_id)); - GetUnknownWindowsFrom(window, nullptr, &client_window_id); - client()->OnEmbedFromToken(token, WindowToWindowData(window), display_id, - window->current_local_surface_id()); -} - -bool WindowTree::RemoveFromMaps(const ServerWindow* window) { - auto iter = window_to_client_id_map_.find(window); - if (iter == window_to_client_id_map_.end()) - return false; - - client_id_to_window_map_.erase(iter->second); - window_to_client_id_map_.erase(iter); - return true; -} - -void WindowTree::RemoveFromKnown(const ServerWindow* window, - std::vector<ServerWindow*>* created_windows) { - // TODO(sky): const_cast here is a bit ick. - if (created_windows_.count(const_cast<ServerWindow*>(window))) { - if (created_windows) - created_windows->push_back(const_cast<ServerWindow*>(window)); - return; - } - - RemoveFromMaps(window); - - for (ServerWindow* child : window->children()) - RemoveFromKnown(child, created_windows); -} - -void WindowTree::RemoveRoot(ServerWindow* window, RemoveRootReason reason) { - DCHECK(roots_.count(window) > 0); - roots_.erase(window); - - if (window->owning_tree_id() == id_) { - // This client created the window. If this client is the window manager and - // display roots are manually created, then |window| is a display root and - // needs be cleaned. - if (window_manager_state_ && !automatically_create_display_roots_) { - // The window manager is asking to delete the root it created. - window_manager_state_->DeleteWindowManagerDisplayRoot(window->parent()); - DeleteWindowImpl(this, window); - } - return; - } - - const Id client_window_id = TransportIdForWindow(window); - - if (reason == RemoveRootReason::EMBED) { - client()->OnUnembed(client_window_id); - client()->OnWindowDeleted(client_window_id); - window_server_->OnTreeMessagedClient(id_); - } - - // This client no longer knows about |window|. Unparent any windows created - // by this client that were parented to descendants of |window|. - std::vector<ServerWindow*> created_windows; - RemoveFromKnown(window, &created_windows); - for (ServerWindow* created_window : created_windows) - created_window->parent()->Remove(created_window); - - if (reason == RemoveRootReason::UNEMBED) { - // Notify the owner of the window it no longer has a client embedded in it. - // Owner is null in the case of the windowmanager unembedding itself from - // a root. - WindowTree* owning_tree = - window_server_->GetTreeWithId(window->owning_tree_id()); - if (owning_tree) { - DCHECK(owning_tree && owning_tree != this); - owning_tree->client()->OnEmbeddedAppDisconnected( - owning_tree->TransportIdForWindow(window)); - } - - window->OnEmbeddedAppDisconnected(); - } -} - -std::vector<mojom::WindowDataPtr> WindowTree::WindowsToWindowDatas( - const std::vector<const ServerWindow*>& windows) { - std::vector<mojom::WindowDataPtr> array(windows.size()); - for (size_t i = 0; i < windows.size(); ++i) - array[i] = WindowToWindowData(windows[i]); - return array; -} - -mojom::WindowDataPtr WindowTree::WindowToWindowData( - const ServerWindow* window) { - DCHECK(IsWindowKnown(window)); - const ServerWindow* parent = window->parent(); - const ServerWindow* transient_parent = window->transient_parent(); - // If the parent or transient parent isn't known, it means it is not visible - // to the client and should not be sent over. - if (!IsWindowKnown(parent)) - parent = nullptr; - if (!IsWindowKnown(transient_parent)) - transient_parent = nullptr; - mojom::WindowDataPtr window_data(mojom::WindowData::New()); - window_data->parent_id = - parent ? TransportIdForWindow(parent) : kInvalidTransportId; - window_data->window_id = - window ? TransportIdForWindow(window) : kInvalidTransportId; - window_data->transient_parent_id = - transient_parent ? TransportIdForWindow(transient_parent) - : kInvalidTransportId; - window_data->bounds = window->bounds(); - window_data->properties = mojo::MapToFlatMap(window->properties()); - window_data->visible = window->visible(); - return window_data; -} - -void WindowTree::GetWindowTreeImpl( - const ServerWindow* window, - std::vector<const ServerWindow*>* windows) const { - DCHECK(window); - - if (!access_policy_->CanGetWindowTree(window)) - return; - - windows->push_back(window); - - if (!access_policy_->CanDescendIntoWindowForWindowTree(window)) - return; - - const ServerWindow::Windows& children = window->children(); - for (ServerWindow* child : children) - GetWindowTreeImpl(child, windows); -} - -void WindowTree::NotifyDrawnStateChanged(const ServerWindow* window, - bool new_drawn_value) { - // Even though we don't know about window, it may be an ancestor of our root, - // in which case the change may effect our roots drawn state. - if (roots_.empty()) - return; - - for (auto* root : roots_) { - if (window->Contains(root) && (new_drawn_value != root->IsDrawn())) { - client()->OnWindowParentDrawnStateChanged(TransportIdForWindow(root), - new_drawn_value); - } - } -} - -void WindowTree::DestroyWindows() { - if (created_windows_.empty()) - return; - - Operation op(this, window_server_, OperationType::DELETE_WINDOW); - // If we get here from the destructor we're not going to get - // ProcessWindowDeleted(). Copy the map and delete from the copy so that we - // don't have to worry about whether |created_windows_| changes or not. - std::set<ServerWindow*> created_windows_copy; - created_windows_.swap(created_windows_copy); - // A sibling can be a transient parent of another window so we detach windows - // from their transient parents to avoid double deletes. - for (ServerWindow* window : created_windows_copy) { - ServerWindow* transient_parent = window->transient_parent(); - if (transient_parent) - transient_parent->RemoveTransientWindow(window); - } - - for (ServerWindow* window : created_windows_copy) - delete window; -} - -bool WindowTree::CanEmbed(const ClientWindowId& window_id) const { - const ServerWindow* window = GetWindowByClientId(window_id); - return window && access_policy_->CanEmbed(window); -} - -void WindowTree::PrepareForEmbed(ServerWindow* window) { - DCHECK(window); - - // Only allow a node to be the root for one client. - WindowTree* existing_owner = window_server_->GetTreeWithRoot(window); - - Operation op(this, window_server_, OperationType::EMBED); - RemoveChildrenAsPartOfEmbed(window); - if (existing_owner) { - // Never message the originating client. - window_server_->OnTreeMessagedClient(id_); - existing_owner->RemoveRoot(window, RemoveRootReason::EMBED); - } -} - -void WindowTree::RemoveChildrenAsPartOfEmbed(ServerWindow* window) { - CHECK(window); - while (!window->children().empty()) - window->Remove(window->children().front()); -} - -uint32_t WindowTree::GenerateEventAckId() { - DCHECK(!event_ack_id_); - // We do not want to create a sequential id for each event, because that can - // leak some information to the client. So instead, manufacture the id - // randomly. - event_ack_id_ = 0x1000000 | (rand() & 0xffffff); - return event_ack_id_; -} - -void WindowTree::DispatchEventImpl(ServerWindow* target, - const ui::Event& event, - const EventLocation& event_location, - DispatchEventCallback callback) { - // DispatchEventImpl() is called so often that log level 4 is used. - DVLOG(4) << "DispatchEventImpl client=" << id_; - GenerateEventAckId(); - event_ack_callback_ = std::move(callback); - WindowManagerDisplayRoot* display_root = GetWindowManagerDisplayRoot(target); - DCHECK(display_root); - event_source_wms_ = display_root->window_manager_state(); - // Should only get events from windows attached to a host. - DCHECK(event_source_wms_); - bool matched_pointer_watcher = EventMatchesPointerWatcher(event); - - // Pass the root window of the display supplying the event. This is necessary - // for Ash to determine the event position in the unified desktop mode, where - // each physical display mirrors part of a single virtual display. - Display* display = window_server_->display_manager()->GetDisplayById( - event_location.display_id); - WindowManagerDisplayRoot* event_display_root = nullptr; - if (display && window_manager_state_) { - event_display_root = display->window_manager_display_root(); - } - ServerWindow* display_root_window = - event_display_root ? event_display_root->GetClientVisibleRoot() : nullptr; - - client()->OnWindowInputEvent( - event_ack_id_, TransportIdForWindow(target), event_location.display_id, - display_root_window ? TransportIdForWindow(display_root_window) : Id(), - event_location.raw_location, ui::Event::Clone(event), - matched_pointer_watcher); -} - -bool WindowTree::EventMatchesPointerWatcher(const ui::Event& event) const { - if (!has_pointer_watcher_) - return false; - if (!event.IsPointerEvent()) - return false; - if (pointer_watcher_want_moves_ && event.type() == ui::ET_POINTER_MOVED) - return true; - return event.type() == ui::ET_POINTER_DOWN || - event.type() == ui::ET_POINTER_UP || - event.type() == ui::ET_POINTER_WHEEL_CHANGED; -} - -ClientWindowId WindowTree::MakeClientWindowId(Id transport_window_id) const { - // If the client didn't specify the id portion of the window_id use the id of - // the client. - if (!ClientIdFromTransportId(transport_window_id)) - return ClientWindowId(id_, transport_window_id); - return ClientWindowId(ClientIdFromTransportId(transport_window_id), - ClientWindowIdFromTransportId(transport_window_id)); -} - -mojom::WindowTreeClientPtr -WindowTree::GetAndRemoveScheduledEmbedWindowTreeClient( - const base::UnguessableToken& token) { - auto iter = scheduled_embeds_.find(token); - if (iter != scheduled_embeds_.end()) { - mojom::WindowTreeClientPtr client = std::move(iter->second); - scheduled_embeds_.erase(iter); - return client; - } - - // There are no clients above the window manager. - if (window_manager_internal_) - return nullptr; - - // Use the root to find the client that embedded this. For non-window manager - // connections there should be only one root (a WindowTreeClient can only be - // embedded once). During shutdown there may be no roots. - if (roots_.size() != 1) - return nullptr; - const ServerWindow* root = *roots_.begin(); - WindowTree* owning_tree = - window_server_->GetTreeWithId(root->owning_tree_id()); - if (!owning_tree) - return nullptr; - DCHECK_NE(this, owning_tree); - return owning_tree->GetAndRemoveScheduledEmbedWindowTreeClient(token); -} - -void WindowTree::NewWindow( - uint32_t change_id, - Id transport_window_id, - const base::Optional<base::flat_map<std::string, std::vector<uint8_t>>>& - transport_properties) { - std::map<std::string, std::vector<uint8_t>> properties; - if (transport_properties.has_value()) - properties = mojo::FlatMapToMap(transport_properties.value()); - - client()->OnChangeCompleted( - change_id, - NewWindow(MakeClientWindowId(transport_window_id), properties)); -} - -void WindowTree::NewTopLevelWindow( - uint32_t change_id, - Id transport_window_id, - const base::flat_map<std::string, std::vector<uint8_t>>& - transport_properties) { - // TODO(sky): rather than DCHECK, have this kill connection. - DCHECK(!window_manager_internal_); // Not valid for the windowmanager. - DCHECK(!waiting_for_top_level_window_info_); - const ClientWindowId client_window_id = - MakeClientWindowId(transport_window_id); - // TODO(sky): need a way for client to provide context to figure out display. - Display* display = display_manager()->displays().empty() - ? nullptr - : *(display_manager()->displays().begin()); - // TODO(sky): move checks to accesspolicy. - WindowManagerDisplayRoot* display_root = - display && !is_for_embedding_ ? display->window_manager_display_root() - : nullptr; - if (!display_root || - display_root->window_manager_state()->window_tree() == this || - !IsValidIdForNewWindow(client_window_id)) { - client()->OnChangeCompleted(change_id, false); - return; - } - - // The server creates the real window. Any further messages from the client - // may try to alter the window. Pause incoming messages so that we know we - // can't get a message for a window before the window is created. Once the - // window is created we'll resume processing. - binding_->SetIncomingMethodCallProcessingPaused(true); - - const uint32_t wm_change_id = - window_server_->GenerateWindowManagerChangeId(this, change_id); - - waiting_for_top_level_window_info_.reset( - new WaitingForTopLevelWindowInfo(client_window_id, wm_change_id)); - - display_root->window_manager_state() - ->window_tree() - ->window_manager_internal_->WmCreateTopLevelWindow( - wm_change_id, client_window_id, transport_properties); -} - -void WindowTree::DeleteWindow(uint32_t change_id, Id transport_window_id) { - client()->OnChangeCompleted( - change_id, DeleteWindow(MakeClientWindowId(transport_window_id))); -} - -void WindowTree::AddWindow(uint32_t change_id, Id parent_id, Id child_id) { - client()->OnChangeCompleted( - change_id, - AddWindow(MakeClientWindowId(parent_id), MakeClientWindowId(child_id))); -} - -void WindowTree::RemoveWindowFromParent(uint32_t change_id, Id window_id) { - client()->OnChangeCompleted( - change_id, RemoveWindowFromParent(MakeClientWindowId(window_id))); -} - -void WindowTree::AddTransientWindow(uint32_t change_id, - Id window, - Id transient_window) { - client()->OnChangeCompleted( - change_id, AddTransientWindow(MakeClientWindowId(window), - MakeClientWindowId(transient_window))); -} - -void WindowTree::RemoveTransientWindowFromParent(uint32_t change_id, - Id transient_window_id) { - bool success = false; - ServerWindow* transient_window = - GetWindowByClientId(MakeClientWindowId(transient_window_id)); - if (transient_window && transient_window->transient_parent() && - access_policy_->CanRemoveTransientWindowFromParent(transient_window)) { - success = true; - Operation op(this, window_server_, - OperationType::REMOVE_TRANSIENT_WINDOW_FROM_PARENT); - transient_window->transient_parent()->RemoveTransientWindow( - transient_window); - } - client()->OnChangeCompleted(change_id, success); -} - -void WindowTree::SetModalType(uint32_t change_id, - Id window_id, - ModalType modal_type) { - client()->OnChangeCompleted( - change_id, SetModalType(MakeClientWindowId(window_id), modal_type)); -} - -void WindowTree::SetChildModalParent(uint32_t change_id, - Id window_id, - Id parent_window_id) { - client()->OnChangeCompleted( - change_id, SetChildModalParent(MakeClientWindowId(window_id), - MakeClientWindowId(parent_window_id))); -} - -void WindowTree::ReorderWindow(uint32_t change_id, - Id window_id, - Id relative_window_id, - mojom::OrderDirection direction) { - // TODO(erg): This implementation allows reordering two windows that are - // children of a parent window which the two implementations can't see. There - // should be a security check to prevent this. - bool success = false; - ServerWindow* window = GetWindowByClientId(MakeClientWindowId(window_id)); - ServerWindow* relative_window = - GetWindowByClientId(MakeClientWindowId(relative_window_id)); - DVLOG(3) << "reorder client=" << id_ << " client window_id=" << window_id - << " global window_id=" << DebugWindowId(window) - << " relative client window_id=" << relative_window_id - << " relative global window_id=" << DebugWindowId(relative_window); - if (CanReorderWindow(window, relative_window, direction)) { - success = true; - Operation op(this, window_server_, OperationType::REORDER_WINDOW); - window->Reorder(relative_window, direction); - window_server_->ProcessWindowReorder(window, relative_window, direction); - } - client()->OnChangeCompleted(change_id, success); -} - -void WindowTree::GetWindowTree(Id window_id, GetWindowTreeCallback callback) { - std::vector<const ServerWindow*> windows( - GetWindowTree(MakeClientWindowId(window_id))); - std::move(callback).Run(WindowsToWindowDatas(windows)); -} - -void WindowTree::SetCapture(uint32_t change_id, Id window_id) { - client()->OnChangeCompleted(change_id, - SetCapture(MakeClientWindowId(window_id))); -} - -void WindowTree::ReleaseCapture(uint32_t change_id, Id window_id) { - client()->OnChangeCompleted(change_id, - ReleaseCapture(MakeClientWindowId(window_id))); -} - -void WindowTree::StartPointerWatcher(bool want_moves) { - has_pointer_watcher_ = true; - pointer_watcher_want_moves_ = want_moves; -} - -void WindowTree::StopPointerWatcher() { - has_pointer_watcher_ = false; - pointer_watcher_want_moves_ = false; -} - -void WindowTree::SetWindowBounds( - uint32_t change_id, - Id window_id, - const gfx::Rect& bounds, - const base::Optional<viz::LocalSurfaceId>& local_surface_id) { - ServerWindow* window = GetWindowByClientId(MakeClientWindowId(window_id)); - if (window && ShouldRouteToWindowManager(window)) { - DVLOG(3) << "Redirecting request to change bounds for " - << DebugWindowId(window) << " to window manager..."; - const uint32_t wm_change_id = - window_server_->GenerateWindowManagerChangeId(this, change_id); - // |window_id| may be a client id, use the id from the window to ensure - // the windowmanager doesn't get an id it doesn't know about. - WindowManagerDisplayRoot* display_root = - GetWindowManagerDisplayRoot(window); - WindowTree* wm_tree = display_root->window_manager_state()->window_tree(); - wm_tree->window_manager_internal_->WmSetBounds( - wm_change_id, wm_tree->TransportIdForWindow(window), std::move(bounds)); - return; - } - - DVLOG(3) << "SetWindowBounds window_id=" << window_id - << " global window_id=" << DebugWindowId(window) - << " bounds=" << bounds.ToString() << " local_surface_id=" - << (local_surface_id ? local_surface_id->ToString() : "null"); - - if (!window) { - DVLOG(1) << "SetWindowBounds failed (invalid window id)"; - client()->OnChangeCompleted(change_id, false); - return; - } - - // Only the owner of the window can change the bounds. - bool success = access_policy_->CanSetWindowBounds(window); - if (success) { - Operation op(this, window_server_, OperationType::SET_WINDOW_BOUNDS); - window->SetBounds(bounds, local_surface_id); - } else { - DVLOG(1) << "SetWindowBounds failed (access denied)"; - } - client()->OnChangeCompleted(change_id, success); -} - -void WindowTree::SetWindowTransform(uint32_t change_id, - Id window_id, - const gfx::Transform& transform) { - // Clients shouldn't have a need to set the transform of the embed root, so - // we don't bother routing it to the window-manager. - - ServerWindow* window = GetWindowByClientId(MakeClientWindowId(window_id)); - DVLOG(3) << "SetWindowTransform client window_id=" << window_id - << " global window_id=" << DebugWindowId(window) - << " transform=" << transform.ToString(); - - if (!window) { - DVLOG(1) << "SetWindowTransform failed (invalid window id)"; - client()->OnChangeCompleted(change_id, false); - return; - } - - // Only the owner of the window can change the bounds. - const bool success = access_policy_->CanSetWindowTransform(window); - if (success) { - Operation op(this, window_server_, OperationType::SET_WINDOW_TRANSFORM); - window->SetTransform(transform); - } else { - DVLOG(1) << "SetWindowTransform failed (access denied)"; - } - client()->OnChangeCompleted(change_id, success); -} - -void WindowTree::SetWindowVisibility(uint32_t change_id, - Id transport_window_id, - bool visible) { - client()->OnChangeCompleted( - change_id, - SetWindowVisibility(MakeClientWindowId(transport_window_id), visible)); -} - -void WindowTree::SetWindowProperty( - uint32_t change_id, - Id transport_window_id, - const std::string& name, - const base::Optional<std::vector<uint8_t>>& value) { - ServerWindow* window = - GetWindowByClientId(MakeClientWindowId(transport_window_id)); - if (window && ShouldRouteToWindowManager(window)) { - const uint32_t wm_change_id = - window_server_->GenerateWindowManagerChangeId(this, change_id); - WindowManagerDisplayRoot* display_root = - GetWindowManagerDisplayRoot(window); - WindowTree* wm_tree = display_root->window_manager_state()->window_tree(); - wm_tree->window_manager_internal_->WmSetProperty( - wm_change_id, wm_tree->TransportIdForWindow(window), name, value); - return; - } - const bool success = window && access_policy_->CanSetWindowProperties(window); - if (success) { - Operation op(this, window_server_, OperationType::SET_WINDOW_PROPERTY); - if (!value.has_value()) { - window->SetProperty(name, nullptr); - } else { - window->SetProperty(name, &value.value()); - } - } - client()->OnChangeCompleted(change_id, success); -} - -void WindowTree::SetWindowOpacity(uint32_t change_id, - Id window_id, - float opacity) { - client()->OnChangeCompleted( - change_id, SetWindowOpacity(MakeClientWindowId(window_id), opacity)); -} - -void WindowTree::AttachCompositorFrameSink( - Id transport_window_id, - viz::mojom::CompositorFrameSinkRequest compositor_frame_sink, - viz::mojom::CompositorFrameSinkClientPtr client) { - ServerWindow* window = - GetWindowByClientId(MakeClientWindowId(transport_window_id)); - if (!window) { - DVLOG(1) << "AttachCompositorFrameSink failed (invalid window id)"; - return; - } - - const bool success = access_policy_->CanSetWindowCompositorFrameSink(window); - if (!success) { - DVLOG(1) << "AttachCompositorFrameSink failed (access denied)"; - return; - } - window->CreateCompositorFrameSink(std::move(compositor_frame_sink), - std::move(client)); -} - -void WindowTree::SetWindowTextInputState(Id transport_window_id, - ui::mojom::TextInputStatePtr state) { - ServerWindow* window = - GetWindowByClientId(MakeClientWindowId(transport_window_id)); - bool success = window && access_policy_->CanSetWindowTextInputState(window); - if (success) - window->SetTextInputState(state.To<ui::TextInputState>()); -} - -void WindowTree::SetImeVisibility(Id transport_window_id, - bool visible, - ui::mojom::TextInputStatePtr state) { - ServerWindow* window = - GetWindowByClientId(MakeClientWindowId(transport_window_id)); - bool success = window && access_policy_->CanSetWindowTextInputState(window); - if (success) { - if (!state.is_null()) - window->SetTextInputState(state.To<ui::TextInputState>()); - - Display* display = GetDisplay(window); - if (display) - display->SetImeVisibility(window, visible); - } -} - -void WindowTree::OnWindowInputEventAck(uint32_t event_id, - mojom::EventResult result) { - // DispatchEventImpl() is called so often that log level 4 is used. - DVLOG(4) << "OnWindowInputEventAck client=" << id_; - if (event_ack_id_ == 0 || event_id != event_ack_id_ || !event_ack_callback_) { - // TODO(sad): Something bad happened. Kill the client? - NOTIMPLEMENTED() << ": Wrong event acked. event_id=" << event_id - << ", event_ack_id_=" << event_ack_id_; - DVLOG(1) << "OnWindowInputEventAck supplied unexpected event_id"; - return; - } - - event_ack_id_ = 0; - - if (janky_) - event_source_wms_->window_tree()->ClientJankinessChanged(this); - - event_source_wms_ = nullptr; - base::ResetAndReturn(&event_ack_callback_).Run(result); - - if (!event_queue_.empty()) { - DCHECK(!event_ack_id_); - ServerWindow* target = nullptr; - std::unique_ptr<ui::Event> event; - DispatchEventCallback callback; - EventLocation event_location; - do { - std::unique_ptr<TargetedEvent> targeted_event = - std::move(event_queue_.front()); - event_queue_.pop(); - target = targeted_event->target(); - event = targeted_event->TakeEvent(); - event_location = targeted_event->event_location(); - callback = targeted_event->TakeCallback(); - } while (!event_queue_.empty() && !GetDisplay(target)); - if (GetDisplay(target)) { - DispatchEventImpl(target, *event, event_location, std::move(callback)); - } else { - // If the window is no longer valid (or not in a display), then there is - // no point in dispatching to the client, but we need to run the callback - // so that WindowManagerState isn't still waiting for an ack. We only - // need run the last callback as they should all target the same - // WindowManagerState and WindowManagerState is at most waiting on one - // ack. - std::move(callback).Run(mojom::EventResult::UNHANDLED); - } - } -} - -void WindowTree::SetClientArea(Id transport_window_id, - const gfx::Insets& insets, - const base::Optional<std::vector<gfx::Rect>>& - transport_additional_client_areas) { - ServerWindow* window = - GetWindowByClientId(MakeClientWindowId(transport_window_id)); - DVLOG(3) << "SetClientArea client window_id=" << transport_window_id - << " global window_id=" << DebugWindowId(window) - << " insets=" << insets.top() << " " << insets.left() << " " - << insets.bottom() << " " << insets.right(); - if (!window) { - DVLOG(1) << "SetClientArea failed (invalid window id)"; - return; - } - if (!access_policy_->CanSetClientArea(window)) { - DVLOG(1) << "SetClientArea failed (access denied)"; - return; - } - - Operation op(this, window_server_, OperationType::SET_CLIENT_AREA); - window->SetClientArea(insets, transport_additional_client_areas.value_or( - std::vector<gfx::Rect>())); -} - -void WindowTree::SetHitTestMask(Id transport_window_id, - const base::Optional<gfx::Rect>& mask) { - ServerWindow* window = - GetWindowByClientId(MakeClientWindowId(transport_window_id)); - if (!window) { - DVLOG(1) << "SetHitTestMask failed (invalid window id)"; - return; - } - - if (!access_policy_->CanSetHitTestMask(window)) { - DVLOG(1) << "SetHitTestMask failed (access denied)"; - return; - } - - if (mask) - window->SetHitTestMask(*mask); - else - window->ClearHitTestMask(); -} - -void WindowTree::SetCanAcceptDrops(Id window_id, bool accepts_drops) { - ServerWindow* window = GetWindowByClientId(MakeClientWindowId(window_id)); - if (!window) { - DVLOG(1) << "SetCanAcceptDrops failed (invalid window id)"; - return; - } - - if (!access_policy_->CanSetAcceptDrops(window)) { - DVLOG(1) << "SetAcceptsDrops failed (access denied)"; - return; - } - - window->SetCanAcceptDrops(accepts_drops); -} - -void WindowTree::Embed(Id transport_window_id, - mojom::WindowTreeClientPtr client, - uint32_t flags, - EmbedCallback callback) { - std::move(callback).Run( - Embed(MakeClientWindowId(transport_window_id), std::move(client), flags)); -} - -void WindowTree::ScheduleEmbed(mojom::WindowTreeClientPtr client, - ScheduleEmbedCallback callback) { - const base::UnguessableToken token = base::UnguessableToken::Create(); - scheduled_embeds_[token] = std::move(client); - std::move(callback).Run(token); -} - -void WindowTree::EmbedUsingToken(Id transport_window_id, - const base::UnguessableToken& token, - uint32_t flags, - EmbedUsingTokenCallback callback) { - mojom::WindowTreeClientPtr client = - GetAndRemoveScheduledEmbedWindowTreeClient(token); - if (client) { - Embed(transport_window_id, std::move(client), flags, std::move(callback)); - return; - } - - WindowTreeAndWindowId tree_and_id = - window_server()->UnregisterEmbedToken(token); - if (!tree_and_id.tree) { - DVLOG(1) << "EmbedUsingToken failed, no ScheduleEmbed(), token=" - << token.ToString(); - std::move(callback).Run(false); - return; - } - if (tree_and_id.tree == this) { - DVLOG(1) << "EmbedUsingToken failed, attempt to embed self, token=" - << token.ToString(); - std::move(callback).Run(false); - return; - } - std::move(callback).Run(EmbedExistingTree( - MakeClientWindowId(transport_window_id), tree_and_id, token)); -} - -void WindowTree::ScheduleEmbedForExistingClient( - uint32_t window_id, - ScheduleEmbedForExistingClientCallback callback) { - std::move(callback).Run(window_server()->RegisterEmbedToken(this, window_id)); -} - -void WindowTree::SetFocus(uint32_t change_id, Id transport_window_id) { - client()->OnChangeCompleted( - change_id, SetFocus(MakeClientWindowId(transport_window_id))); -} - -void WindowTree::SetCanFocus(Id transport_window_id, bool can_focus) { - ServerWindow* window = - GetWindowByClientId(MakeClientWindowId(transport_window_id)); - if (!window) { - DVLOG(1) << "SetCanFocus failed (invalid window id)"; - return; - } - - if (ShouldRouteToWindowManager(window)) { - WindowManagerDisplayRoot* display_root = - GetWindowManagerDisplayRoot(window); - WindowTree* wm_tree = display_root->window_manager_state()->window_tree(); - wm_tree->window_manager_internal_->WmSetCanFocus(transport_window_id, - can_focus); - } else if (access_policy_->CanSetFocus(window)) { - window->set_can_focus(can_focus); - } else { - DVLOG(1) << "SetCanFocus failed (access denied)"; - } -} - -void WindowTree::SetEventTargetingPolicy(Id transport_window_id, - mojom::EventTargetingPolicy policy) { - ServerWindow* window = - GetWindowByClientId(MakeClientWindowId(transport_window_id)); - // TODO(riajiang): check |event_queue_| is empty for |window|. - if (window && access_policy_->CanSetEventTargetingPolicy(window)) - window->set_event_targeting_policy(policy); -} - -void WindowTree::SetCursor(uint32_t change_id, - Id transport_window_id, - ui::CursorData cursor) { - ServerWindow* window = - GetWindowByClientId(MakeClientWindowId(transport_window_id)); - if (!window) { - DVLOG(1) << "SetCursor failed (invalid id)"; - client()->OnChangeCompleted(change_id, false); - return; - } - - // Only the owner of the window can change the bounds. - bool success = access_policy_->CanSetCursorProperties(window); - if (!success) { - DVLOG(1) << "SetCursor failed (access denied)"; - client()->OnChangeCompleted(change_id, false); - return; - } - - // If the cursor is custom, it must have valid frames. - if (cursor.cursor_type() == ui::CursorType::kCustom) { - if (cursor.cursor_frames().empty()) { - DVLOG(1) << "SetCursor failed (no frames with custom cursor)"; - client()->OnChangeCompleted(change_id, false); - return; - } - - for (const SkBitmap& bitmap : cursor.cursor_frames()) { - if (bitmap.drawsNothing()) { - DVLOG(1) << "SetCursor failed (cursor frame draws nothing)"; - client()->OnChangeCompleted(change_id, false); - return; - } - } - } - - Operation op(this, window_server_, - OperationType::SET_WINDOW_PREDEFINED_CURSOR); - window->SetCursor(std::move(cursor)); - client()->OnChangeCompleted(change_id, success); -} - -void WindowTree::DeactivateWindow(Id window_id) { - ServerWindow* window = GetWindowByClientId(MakeClientWindowId(window_id)); - if (!window) { - DVLOG(1) << "DeactivateWindow failed (invalid id)"; - return; - } - - WindowManagerDisplayRoot* display_root = GetWindowManagerDisplayRoot(window); - if (!display_root) { - // The window isn't parented. There's nothing to do. - DVLOG(1) << "DeactivateWindow failed (window unparented)"; - return; - } - - WindowTree* wm_tree = display_root->window_manager_state()->window_tree(); - wm_tree->window_manager_internal_->WmDeactivateWindow( - wm_tree->TransportIdForWindow(window)); -} - -void WindowTree::StackAbove(uint32_t change_id, Id above_id, Id below_id) { - ServerWindow* above = GetWindowByClientId(MakeClientWindowId(above_id)); - if (!above) { - DVLOG(1) << "StackAbove failed (invalid above id)"; - client()->OnChangeCompleted(change_id, false); - return; - } - - ServerWindow* below = GetWindowByClientId(MakeClientWindowId(below_id)); - if (!below) { - DVLOG(1) << "StackAbove failed (invalid below id)"; - client()->OnChangeCompleted(change_id, false); - return; - } - - if (!access_policy_->CanStackAbove(above, below)) { - DVLOG(1) << "StackAbove failed (access denied)"; - client()->OnChangeCompleted(change_id, false); - return; - } - - ServerWindow* parent = above->parent(); - ServerWindow* below_parent = below->parent(); - if (!parent) { - DVLOG(1) << "StackAbove failed (above unparented)"; - client()->OnChangeCompleted(change_id, false); - return; - } - if (!below_parent) { - DVLOG(1) << "StackAbove failed (below unparented)"; - client()->OnChangeCompleted(change_id, false); - return; - } - if (parent != below_parent) { - DVLOG(1) << "StackAbove failed (windows have different parents)"; - client()->OnChangeCompleted(change_id, false); - return; - } - - WindowManagerDisplayRoot* display_root = GetWindowManagerDisplayRoot(above); - if (!display_root) { - DVLOG(1) << "StackAbove (no display root)"; - client()->OnChangeCompleted(change_id, false); - return; - } - - // Window reordering assumes that it is the owner of parent who is sending - // the message, and does not deal gracefully with other clients reordering - // their windows. So tell the window manager to send us a reorder message. - WindowTree* wm_tree = display_root->window_manager_state()->window_tree(); - const uint32_t wm_change_id = - window_server_->GenerateWindowManagerChangeId(this, change_id); - wm_tree->window_manager_internal_->WmStackAbove( - wm_change_id, wm_tree->TransportIdForWindow(above), - wm_tree->TransportIdForWindow(below)); -} - -void WindowTree::StackAtTop(uint32_t change_id, Id window_id) { - ServerWindow* window = GetWindowByClientId(MakeClientWindowId(window_id)); - if (!window) { - DVLOG(1) << "StackAtTop failed (invalid id)"; - client()->OnChangeCompleted(change_id, false); - return; - } - - if (!access_policy_->CanStackAtTop(window)) { - DVLOG(1) << "StackAtTop failed (access denied)"; - client()->OnChangeCompleted(change_id, false); - return; - } - - ServerWindow* parent = window->parent(); - if (!parent) { - DVLOG(1) << "StackAtTop failed (window unparented)"; - client()->OnChangeCompleted(change_id, false); - return; - } - - DCHECK(!parent->children().empty()); - if (parent->children().back() == window) { - // Ignore this call; the client didn't know they were already at the top. - DVLOG(3) << "StackAtTop ignored (already at top)"; - client()->OnChangeCompleted(change_id, true); - return; - } - - WindowManagerDisplayRoot* display_root = GetWindowManagerDisplayRoot(window); - if (!display_root) { - DVLOG(1) << "StackAtTop (no display root)"; - client()->OnChangeCompleted(change_id, false); - return; - } - - // Window reordering assumes that it is the owner of parent who is sending - // the message, and does not deal gracefully with other clients reordering - // their windows. So tell the window manager to send us a reorder message. - WindowTree* wm_tree = display_root->window_manager_state()->window_tree(); - const uint32_t wm_change_id = - window_server_->GenerateWindowManagerChangeId(this, change_id); - wm_tree->window_manager_internal_->WmStackAtTop( - wm_change_id, wm_tree->TransportIdForWindow(window)); -} - -void WindowTree::PerformWmAction(Id window_id, const std::string& action) { - ServerWindow* window = GetWindowByClientId(MakeClientWindowId(window_id)); - if (!window) { - DVLOG(1) << "PerformWmAction(" << action << ") failed (invalid id)"; - return; - } - - if (!access_policy_->CanPerformWmAction(window)) { - DVLOG(1) << "PerformWmAction(" << action << ") failed (access denied)"; - return; - } - - WindowManagerDisplayRoot* display_root = GetWindowManagerDisplayRoot(window); - if (!display_root) { - DVLOG(1) << "PerformWmAction(" << action << ") failed (no display root)"; - return; - } - - WindowTree* wm_tree = display_root->window_manager_state()->window_tree(); - wm_tree->window_manager_internal_->WmPerformWmAction( - wm_tree->TransportIdForWindow(window), action); -} - -void WindowTree::GetWindowManagerClient( - mojo::AssociatedInterfaceRequest<mojom::WindowManagerClient> internal) { - if (!access_policy_->CanSetWindowManager() || !window_manager_internal_ || - window_manager_internal_client_binding_) { - return; - } - window_manager_internal_client_binding_.reset( - new mojo::AssociatedBinding<mojom::WindowManagerClient>( - this, std::move(internal))); -} - -void WindowTree::GetCursorLocationMemory( - GetCursorLocationMemoryCallback callback) { - std::move(callback).Run( - display_manager()->cursor_location_manager()->GetCursorLocationMemory()); -} - -void WindowTree::PerformDragDrop( - uint32_t change_id, - Id source_window_id, - const gfx::Point& screen_location, - const base::flat_map<std::string, std::vector<uint8_t>>& drag_data, - const gfx::ImageSkia& drag_image, - const gfx::Vector2d& drag_image_offset, - uint32_t drag_operation, - ui::mojom::PointerKind source) { - ServerWindow* window = - GetWindowByClientId(MakeClientWindowId(source_window_id)); - bool success = window && access_policy_->CanInitiateDragLoop(window); - if (!success || !ShouldRouteToWindowManager(window)) { - // We need to fail this move loop change, otherwise the client will just be - // waiting for |change_id|. - DVLOG(1) << "PerformDragDrop failed (access denied)"; - client()->OnPerformDragDropCompleted(change_id, false, - mojom::kDropEffectNone); - return; - } - - WindowManagerDisplayRoot* display_root = GetWindowManagerDisplayRoot(window); - if (!display_root) { - // The window isn't parented. There's nothing to do. - DVLOG(1) << "PerformDragDrop failed (window unparented)"; - client()->OnPerformDragDropCompleted(change_id, false, - mojom::kDropEffectNone); - return; - } - - if (window_server_->in_move_loop() || window_server_->in_drag_loop()) { - // Either the window manager is servicing a window drag or we're servicing - // a drag and drop operation. We can't start a second drag. - DVLOG(1) << "PerformDragDrop failed (already performing a drag)"; - client()->OnPerformDragDropCompleted(change_id, false, - mojom::kDropEffectNone); - return; - } - - WindowManagerState* wms = display_root->window_manager_state(); - - // Send the drag representation to the window manager. - wms->window_tree()->window_manager_internal_->WmBuildDragImage( - screen_location, drag_image, drag_image_offset, source); - - // Here, we need to dramatically change how the mouse pointer works. Once - // we've started a drag drop operation, cursor events don't go to windows as - // normal. - window_server_->StartDragLoop(change_id, window, this); - wms->SetDragDropSourceWindow(this, window, this, drag_data, drag_operation); -} - -void WindowTree::CancelDragDrop(Id window_id) { - ServerWindow* window = GetWindowByClientId(MakeClientWindowId(window_id)); - if (!window) { - DVLOG(1) << "CancelDragDrop failed (no window)"; - return; - } - - if (window != window_server_->GetCurrentDragLoopWindow()) { - DVLOG(1) << "CancelDragDrop failed (not the drag loop window)"; - return; - } - - if (window_server_->GetCurrentDragLoopInitiator() != this) { - DVLOG(1) << "CancelDragDrop failed (not the drag initiator)"; - return; - } - - WindowManagerDisplayRoot* display_root = GetWindowManagerDisplayRoot(window); - if (!display_root) { - DVLOG(1) << "CancelDragDrop failed (no such window manager display root)"; - return; - } - - WindowManagerState* wms = display_root->window_manager_state(); - wms->CancelDragDrop(); -} - -void WindowTree::PerformWindowMove(uint32_t change_id, - Id window_id, - ui::mojom::MoveLoopSource source, - const gfx::Point& cursor) { - ServerWindow* window = GetWindowByClientId(MakeClientWindowId(window_id)); - bool success = window && access_policy_->CanInitiateMoveLoop(window); - if (!success || !ShouldRouteToWindowManager(window)) { - // We need to fail this move loop change, otherwise the client will just be - // waiting for |change_id|. - DVLOG(1) << "PerformWindowMove failed (access denied)"; - OnChangeCompleted(change_id, false); - return; - } - - WindowManagerDisplayRoot* display_root = GetWindowManagerDisplayRoot(window); - if (!display_root) { - // The window isn't parented. There's nothing to do. - DVLOG(1) << "PerformWindowMove failed (window unparented)"; - OnChangeCompleted(change_id, false); - return; - } - - if (window_server_->in_move_loop() || window_server_->in_drag_loop()) { - // Either the window manager is servicing a window drag or we're servicing - // a drag and drop operation. We can't start a second drag. - DVLOG(1) << "PerformWindowMove failed (already performing a drag)"; - OnChangeCompleted(change_id, false); - return; - } - - // When we perform a window move loop, we give the window manager non client - // capture. Because of how the capture public interface currently works, - // SetCapture() will check whether the mouse cursor is currently in the - // non-client area and if so, will redirect messages to the window - // manager. (And normal window movement relies on this behaviour.) - WindowManagerState* wms = display_root->window_manager_state(); - wms->SetCapture(window, wms->window_tree()->id()); - - const uint32_t wm_change_id = - window_server_->GenerateWindowManagerChangeId(this, change_id); - window_server_->StartMoveLoop(wm_change_id, window, this, window->bounds()); - wms->window_tree()->window_manager_internal_->WmPerformMoveLoop( - wm_change_id, wms->window_tree()->TransportIdForWindow(window), source, - cursor); -} - -void WindowTree::CancelWindowMove(Id window_id) { - ServerWindow* window = GetWindowByClientId(MakeClientWindowId(window_id)); - if (!window) { - DVLOG(1) << "CancelWindowMove failed (invalid window id)"; - return; - } - - bool success = access_policy_->CanInitiateMoveLoop(window); - if (!success) { - DVLOG(1) << "CancelWindowMove failed (access denied)"; - return; - } - - if (window != window_server_->GetCurrentMoveLoopWindow()) { - DVLOG(1) << "CancelWindowMove failed (not the move loop window)"; - return; - } - - if (window_server_->GetCurrentMoveLoopInitiator() != this) { - DVLOG(1) << "CancelWindowMove failed (not the move loop initiator)"; - return; - } - - WindowManagerDisplayRoot* display_root = GetWindowManagerDisplayRoot(window); - if (!display_root) { - DVLOG(1) << "CancelWindowMove failed (no such window manager display root)"; - return; - } - - WindowManagerState* wms = display_root->window_manager_state(); - wms->window_tree()->window_manager_internal_->WmCancelMoveLoop( - window_server_->GetCurrentMoveLoopChangeId()); -} - -void WindowTree::AddAccelerators( - std::vector<mojom::WmAcceleratorPtr> accelerators, - AddAcceleratorsCallback callback) { - DCHECK(window_manager_state_); - - bool success = true; - for (auto iter = accelerators.begin(); iter != accelerators.end(); ++iter) { - if (!window_manager_state_->event_processor()->AddAccelerator( - iter->get()->id, std::move(iter->get()->event_matcher))) - success = false; - } - std::move(callback).Run(success); -} - -void WindowTree::RemoveAccelerator(uint32_t id) { - window_manager_state_->event_processor()->RemoveAccelerator(id); -} - -void WindowTree::AddActivationParent(Id transport_window_id) { - AddActivationParent(MakeClientWindowId(transport_window_id)); -} - -void WindowTree::RemoveActivationParent(Id transport_window_id) { - ServerWindow* window = - GetWindowByClientId(MakeClientWindowId(transport_window_id)); - if (!window) { - DVLOG(1) << "RemoveActivationParent failed (invalid window id)"; - return; - } - window->set_is_activation_parent(false); -} - -void WindowTree::SetExtendedHitRegionForChildren( - Id window_id, - const gfx::Insets& mouse_insets, - const gfx::Insets& touch_insets) { - ServerWindow* window = GetWindowByClientId(MakeClientWindowId(window_id)); - // Extended hit test region should only be set by the owner of the window. - if (!window) { - DVLOG(1) << "SetExtendedHitRegionForChildren failed (invalid window id)"; - return; - } - if (window->owning_tree_id() != id_) { - DVLOG(1) << "SetExtendedHitRegionForChildren failed (supplied window that " - << "client does not own)"; - return; - } - if (HasPositiveInset(mouse_insets) || HasPositiveInset(touch_insets)) { - DVLOG(1) << "SetExtendedHitRegionForChildren failed (insets must be " - << "negative)"; - return; - } - window->set_extended_hit_test_regions_for_children(mouse_insets, - touch_insets); -} - -void WindowTree::SetKeyEventsThatDontHideCursor( - std::vector<::ui::mojom::EventMatcherPtr> dont_hide_cursor_list) { - DCHECK(window_manager_state_); - window_manager_state_->SetKeyEventsThatDontHideCursor( - std::move(dont_hide_cursor_list)); -} - -void WindowTree::SetDisplayRoot(const display::Display& display, - mojom::WmViewportMetricsPtr viewport_metrics, - bool is_primary_display, - Id window_id, - const std::vector<display::Display>& mirrors, - SetDisplayRootCallback callback) { - ServerWindow* display_root = ProcessSetDisplayRoot( - display, TransportMetricsToDisplayMetrics(*viewport_metrics), - is_primary_display, MakeClientWindowId(window_id), mirrors); - if (!display_root) { - std::move(callback).Run(false); - return; - } - display_root->parent()->SetVisible(true); - std::move(callback).Run(true); -} - -void WindowTree::SetDisplayConfiguration( - const std::vector<display::Display>& displays, - std::vector<ui::mojom::WmViewportMetricsPtr> transport_metrics, - int64_t primary_display_id, - int64_t internal_display_id, - const std::vector<display::Display>& mirrors, - SetDisplayConfigurationCallback callback) { - std::vector<display::ViewportMetrics> metrics; - for (auto& transport_ptr : transport_metrics) - metrics.push_back(TransportMetricsToDisplayMetrics(*transport_ptr)); - std::move(callback).Run(display_manager()->SetDisplayConfiguration( - displays, metrics, primary_display_id, internal_display_id, mirrors)); -} - -void WindowTree::SwapDisplayRoots(int64_t display_id1, - int64_t display_id2, - SwapDisplayRootsCallback callback) { - DCHECK(window_manager_state_); // Only applicable to the window manager. - std::move(callback).Run(ProcessSwapDisplayRoots(display_id1, display_id2)); -} - -void WindowTree::SetBlockingContainers( - std::vector<::ui::mojom::BlockingContainersPtr> blocking_containers, - SetBlockingContainersCallback callback) { - DCHECK(window_manager_state_); // Only applicable to the window manager. - std::move(callback).Run( - ProcessSetBlockingContainers(std::move(blocking_containers))); -} - -void WindowTree::WmResponse(uint32_t change_id, bool response) { - if (window_server_->in_move_loop() && - window_server_->GetCurrentMoveLoopChangeId() == change_id) { - ServerWindow* window = window_server_->GetCurrentMoveLoopWindow(); - - if (window->owning_tree_id() != id_) { - window_server_->WindowManagerSentBogusMessage(); - window = nullptr; - } else { - WindowManagerDisplayRoot* display_root = - GetWindowManagerDisplayRoot(window); - if (display_root) { - WindowManagerState* wms = display_root->window_manager_state(); - // Clear the implicit capture. - wms->SetCapture(nullptr, false); - } - } - - if (!response && window) { - // Our move loop didn't succeed, which means that we must restore the - // original bounds of the window. - window->SetBounds(window_server_->GetCurrentMoveLoopRevertBounds(), - base::nullopt); - } - - window_server_->EndMoveLoop(); - } - - window_server_->WindowManagerChangeCompleted(change_id, response); -} - -void WindowTree::WmSetBoundsResponse(uint32_t change_id) { - // The window manager will always give a response of false to the client - // because it will always update the bounds of the top level window itself - // which will overwrite the request made by the client. - WmResponse(change_id, false); -} - -void WindowTree::WmRequestClose(Id transport_window_id) { - ServerWindow* window = - GetWindowByClientId(MakeClientWindowId(transport_window_id)); - WindowTree* tree = window_server_->GetTreeWithRoot(window); - if (tree && tree != this) { - tree->client()->RequestClose(tree->TransportIdForWindow(window)); - } - // TODO(sky): think about what else case means. -} - -void WindowTree::WmSetFrameDecorationValues( - mojom::FrameDecorationValuesPtr values) { - DCHECK(window_manager_state_); - window_manager_state_->SetFrameDecorationValues(std::move(values)); -} - -void WindowTree::WmSetNonClientCursor(Id window_id, ui::CursorData cursor) { - DCHECK(window_manager_state_); - ServerWindow* window = GetWindowByClientId(MakeClientWindowId(window_id)); - if (!window) { - DVLOG(1) << "WmSetNonClientCursor failed (invalid window id)"; - return; - } - - window->SetNonClientCursor(std::move(cursor)); -} - -void WindowTree::WmLockCursor() { - DCHECK(window_manager_state_); - window_manager_state_->cursor_state().LockCursor(); -} - -void WindowTree::WmUnlockCursor() { - DCHECK(window_manager_state_); - window_manager_state_->cursor_state().UnlockCursor(); -} - -void WindowTree::WmSetCursorVisible(bool visible) { - DCHECK(window_manager_state_); - window_manager_state_->cursor_state().SetCursorVisible(visible); -} - -void WindowTree::WmSetCursorSize(ui::CursorSize cursor_size) { - DCHECK(window_manager_state_); - window_manager_state_->cursor_state().SetCursorSize(cursor_size); -} - -void WindowTree::WmSetGlobalOverrideCursor( - base::Optional<ui::CursorData> cursor) { - DCHECK(window_manager_state_); - window_manager_state_->cursor_state().SetGlobalOverrideCursor(cursor); -} - -void WindowTree::WmMoveCursorToDisplayLocation(const gfx::Point& display_pixels, - int64_t display_id) { - DCHECK(window_manager_state_); - window_manager_state_->SetCursorLocation(display_pixels, display_id); -} - -void WindowTree::WmConfineCursorToBounds(const gfx::Rect& bounds_in_pixels, - int64_t display_id) { - DCHECK(window_manager_state_); - Display* display = display_manager()->GetDisplayById(display_id); - if (!display) { - DVLOG(1) << "WmConfineCursorToBounds failed (invalid display id)"; - return; - } - - PlatformDisplay* platform_display = display->platform_display(); - if (!platform_display) { - DVLOG(1) << "WmConfineCursorToBounds failed (no platform display)"; - return; - } - - platform_display->ConfineCursorToBounds(bounds_in_pixels); -} - -void WindowTree::WmSetCursorTouchVisible(bool enabled) { - DCHECK(window_manager_state_); - window_manager_state_->SetCursorTouchVisible(enabled); -} - -void WindowTree::OnWmCreatedTopLevelWindow(uint32_t change_id, - Id transport_window_id) { - ServerWindow* window = - GetWindowByClientId(MakeClientWindowId(transport_window_id)); - if (window && window->owning_tree_id() != id_) { - DVLOG(1) << "OnWmCreatedTopLevelWindow failed (invalid window id)"; - window_server_->WindowManagerSentBogusMessage(); - window = nullptr; - } - window_server_->WindowManagerCreatedTopLevelWindow(this, change_id, window); -} - -void WindowTree::OnAcceleratorAck(uint32_t event_id, - mojom::EventResult result, - const EventProperties& properties) { - DVLOG(3) << "OnAcceleratorAck client=" << id_; - if (event_ack_id_ == 0 || event_id != event_ack_id_ || - !accelerator_ack_callback_) { - DVLOG(1) << "OnAcceleratorAck failed (invalid event id)"; - window_server_->WindowManagerSentBogusMessage(); - return; - } - event_ack_id_ = 0; - DCHECK(window_manager_state_); - base::ResetAndReturn(&accelerator_ack_callback_).Run(result, properties); -} - -bool WindowTree::HasRootForAccessPolicy(const ServerWindow* window) const { - return HasRoot(window); -} - -bool WindowTree::IsWindowKnownForAccessPolicy( - const ServerWindow* window) const { - return IsWindowKnown(window); -} - -bool WindowTree::IsWindowRootOfAnotherTreeForAccessPolicy( - const ServerWindow* window) const { - WindowTree* tree = window_server_->GetTreeWithRoot(window); - return tree && tree != this; -} - -bool WindowTree::IsWindowCreatedByWindowManager( - const ServerWindow* window) const { - // The WindowManager is attached to the root of the Display, if there isn't a - // WindowManager attached, the window manager didn't create this window. - const WindowManagerDisplayRoot* display_root = - GetWindowManagerDisplayRoot(window); - if (!display_root) - return false; - - return display_root->window_manager_state()->window_tree()->id() == - window->owning_tree_id(); -} - -bool WindowTree::ShouldInterceptEventsForAccessPolicy( - const ServerWindow* window) const { - if (is_for_embedding_) - return false; - - while (window) { - // Find the first window created by this client. If there is an embedding, - // it'll be here. - if (window->owning_tree_id() == id_) { - // embedded_tree->embedder_intercepts_events() indicates Embed() was - // called with kEmbedFlagEmbedderInterceptsEvents. In this case the - // embedder needs to see the window so that it knows the event is - // targetted at it. - WindowTree* embedded_tree = window_server_->GetTreeWithRoot(window); - if (embedded_tree && embedded_tree->embedder_intercepts_events()) - return true; - return false; - } - window = window->parent(); - } - return false; -} - -void WindowTree::OnDragMoved(const gfx::Point& location) { - DCHECK(window_server_->in_drag_loop()); - DCHECK_EQ(this, window_server_->GetCurrentDragLoopInitiator()); - - ServerWindow* window = window_server_->GetCurrentDragLoopWindow(); - WindowManagerDisplayRoot* display_root = GetWindowManagerDisplayRoot(window); - if (!display_root) - return; - - if (drag_move_state_) { - drag_move_state_->has_queued_drag_window_move = true; - drag_move_state_->queued_cursor_location = location; - } else { - WindowManagerState* wms = display_root->window_manager_state(); - drag_move_state_ = std::make_unique<DragMoveState>(); - wms->window_tree()->window_manager_internal_->WmMoveDragImage( - location, base::Bind(&WindowTree::OnWmMoveDragImageAck, - drag_weak_factory_.GetWeakPtr())); - } -} - -void WindowTree::OnDragCompleted(bool success, uint32_t action_taken) { - DCHECK(window_server_->in_drag_loop()); - - if (window_server_->GetCurrentDragLoopInitiator() != this) - return; - - uint32_t change_id = window_server_->GetCurrentDragLoopChangeId(); - ServerWindow* window = window_server_->GetCurrentDragLoopWindow(); - WindowManagerDisplayRoot* display_root = GetWindowManagerDisplayRoot(window); - if (!display_root) - return; - - window_server_->EndDragLoop(); - WindowManagerState* wms = display_root->window_manager_state(); - wms->EndDragDrop(); - wms->window_tree()->window_manager_internal_->WmDestroyDragImage(); - drag_weak_factory_.InvalidateWeakPtrs(); - - client()->OnPerformDragDropCompleted(change_id, success, action_taken); -} - -DragTargetConnection* WindowTree::GetDragTargetForWindow( - const ServerWindow* window) { - if (!window) - return nullptr; - DragTargetConnection* connection = window_server_->GetTreeWithRoot(window); - if (connection) - return connection; - return window_server_->GetTreeWithId(window->owning_tree_id()); -} - -void WindowTree::PerformOnDragDropStart( - const base::flat_map<std::string, std::vector<uint8_t>>& mime_data) { - client()->OnDragDropStart(mime_data); -} - -void WindowTree::PerformOnDragEnter( - const ServerWindow* window, - uint32_t event_flags, - const gfx::Point& cursor_offset, - uint32_t effect_bitmask, - const base::Callback<void(uint32_t)>& callback) { - ClientWindowId client_window_id; - if (!IsWindowKnown(window, &client_window_id)) { - NOTREACHED(); - callback.Run(0); - return; - } - client()->OnDragEnter(ClientWindowIdToTransportId(client_window_id), - event_flags, cursor_offset, effect_bitmask, callback); -} - -void WindowTree::PerformOnDragOver( - const ServerWindow* window, - uint32_t event_flags, - const gfx::Point& cursor_offset, - uint32_t effect_bitmask, - const base::Callback<void(uint32_t)>& callback) { - ClientWindowId client_window_id; - if (!IsWindowKnown(window, &client_window_id)) { - NOTREACHED(); - callback.Run(0); - return; - } - client()->OnDragOver(ClientWindowIdToTransportId(client_window_id), - event_flags, cursor_offset, effect_bitmask, callback); -} - -void WindowTree::PerformOnDragLeave(const ServerWindow* window) { - ClientWindowId client_window_id; - if (!IsWindowKnown(window, &client_window_id)) { - NOTREACHED(); - return; - } - client()->OnDragLeave(ClientWindowIdToTransportId(client_window_id)); -} - -void WindowTree::PerformOnCompleteDrop( - const ServerWindow* window, - uint32_t event_flags, - const gfx::Point& cursor_offset, - uint32_t effect_bitmask, - const base::Callback<void(uint32_t)>& callback) { - ClientWindowId client_window_id; - if (!IsWindowKnown(window, &client_window_id)) { - NOTREACHED(); - callback.Run(0); - return; - } - client()->OnCompleteDrop(ClientWindowIdToTransportId(client_window_id), - event_flags, cursor_offset, effect_bitmask, - callback); -} - -void WindowTree::PerformOnDragDropDone() { - client()->OnDragDropDone(); -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/window_tree.h b/services/ui/ws/window_tree.h deleted file mode 100644 index ae920d3..0000000 --- a/services/ui/ws/window_tree.h +++ /dev/null
@@ -1,765 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SERVICES_UI_WS_WINDOW_TREE_H_ -#define SERVICES_UI_WS_WINDOW_TREE_H_ - -#include <stdint.h> - -#include <map> -#include <memory> -#include <set> -#include <string> -#include <unordered_map> -#include <vector> - -#include "base/callback.h" -#include "base/containers/flat_map.h" -#include "base/containers/queue.h" -#include "base/macros.h" -#include "base/memory/weak_ptr.h" -#include "mojo/public/cpp/bindings/associated_binding.h" -#include "services/ui/public/interfaces/window_tree.mojom.h" -#include "services/ui/ws/access_policy_delegate.h" -#include "services/ui/ws/async_event_dispatcher.h" -#include "services/ui/ws/drag_source.h" -#include "services/ui/ws/drag_target_connection.h" -#include "services/ui/ws/ids.h" -#include "services/ui/ws/window_tree_binding.h" -#include "services/viz/public/interfaces/compositing/surface_id.mojom.h" -#include "ui/gfx/native_widget_types.h" - -namespace display { -struct ViewportMetrics; -} -namespace gfx { -class Insets; -class Rect; -} - -namespace ui { -class Event; -} - -namespace ui { -namespace ws { - -class AccessPolicy; -class DisplayManager; -class Display; -class DragTargetConnection; -class ServerWindow; -class TargetedEvent; -class WindowManagerDisplayRoot; -class WindowManagerState; -class WindowServer; - -struct EventLocation; -struct WindowTreeAndWindowId; - -namespace test { -class WindowTreeTestApi; -} - -// WindowTree represents a view onto portions of the window tree. The parts of -// the tree exposed to the client start at the root windows. A WindowTree may -// have any number of roots (including none). A WindowTree may not have -// visibility of all the descendants of its roots. -// -// WindowTree notifies its client as changes happen to windows exposed to the -// the client. -// -// See ids.h for details on how WindowTree handles identity of windows. -class WindowTree : public mojom::WindowTree, - public AccessPolicyDelegate, - public mojom::WindowManagerClient, - public DragSource, - public DragTargetConnection, - public AsyncEventDispatcher { - public: - WindowTree(WindowServer* window_server, - bool is_for_embedding, - ServerWindow* root, - std::unique_ptr<AccessPolicy> access_policy); - ~WindowTree() override; - - void Init(std::unique_ptr<WindowTreeBinding> binding, - mojom::WindowTreePtr tree); - - // Called if this WindowTree hosts a WindowManager. See mojom for details - // on |automatically_create_display_roots|. - void ConfigureWindowManager(bool automatically_create_display_roots); - - bool automatically_create_display_roots() const { - return automatically_create_display_roots_; - } - - void OnAcceleratedWidgetAvailableForDisplay(Display* display); - - ClientSpecificId id() const { return id_; } - - void set_embedder_intercepts_events() { embedder_intercepts_events_ = true; } - bool embedder_intercepts_events() const { - return embedder_intercepts_events_; - } - - void set_can_change_root_window_visibility(bool value) { - can_change_root_window_visibility_ = value; - } - - bool is_for_embedding() const { return is_for_embedding_; } - - mojom::WindowTreeClient* client() { return binding_->client(); } - - // Returns the Window with the specified client id *only* if known to this - // client, returns null if not known. - ServerWindow* GetWindowByClientId(const ClientWindowId& id) { - return const_cast<ServerWindow*>( - const_cast<const WindowTree*>(this)->GetWindowByClientId(id)); - } - const ServerWindow* GetWindowByClientId(const ClientWindowId& id) const; - - bool IsWindowKnown(const ServerWindow* window) const { - return IsWindowKnown(window, nullptr); - } - // Returns whether |window| is known to this tree. If |window| is known and - // |client_window_id| is non-null |client_window_id| is set to the - // ClientWindowId of the window. - bool IsWindowKnown(const ServerWindow* window, - ClientWindowId* client_window_id) const; - - // Returns true if |window| is one of this trees roots. - bool HasRoot(const ServerWindow* window) const; - - std::set<const ServerWindow*> roots() { return roots_; } - - void set_name(const std::string& name) { name_ = name; } - const std::string& name() const { return name_; } - - bool janky() const { return janky_; } - - const Display* GetDisplay(const ServerWindow* window) const; - Display* GetDisplay(const ServerWindow* window) { - return const_cast<Display*>( - const_cast<const WindowTree*>(this)->GetDisplay(window)); - } - - const WindowManagerDisplayRoot* GetWindowManagerDisplayRoot( - const ServerWindow* window) const; - WindowManagerDisplayRoot* GetWindowManagerDisplayRoot( - const ServerWindow* window) { - return const_cast<WindowManagerDisplayRoot*>( - const_cast<const WindowTree*>(this)->GetWindowManagerDisplayRoot( - window)); - } - WindowManagerState* window_manager_state() { - return window_manager_state_.get(); - } - - DisplayManager* display_manager(); - const DisplayManager* display_manager() const; - - WindowServer* window_server() { return window_server_; } - const WindowServer* window_server() const { return window_server_; } - - // Called from ~WindowServer. Reset WindowTreeClient so that it no longer gets - // any messages. - void PrepareForWindowServerShutdown(); - - // Adds a new root to this tree. This is only valid for window managers. - void AddRootForWindowManager(const ServerWindow* root); - - // Invoked when a tree is about to be destroyed. - void OnWillDestroyTree(WindowTree* tree); - - // Sends updated display information. - void OnWmDisplayModified(const display::Display& display); - - // These functions are synchronous variants of those defined in the mojom. The - // WindowTree implementations all call into these. See the mojom for details. - bool SetCapture(const ClientWindowId& client_window_id); - bool ReleaseCapture(const ClientWindowId& client_window_id); - bool NewWindow(const ClientWindowId& client_window_id, - const std::map<std::string, std::vector<uint8_t>>& properties); - bool AddWindow(const ClientWindowId& parent_id, - const ClientWindowId& child_id); - bool AddTransientWindow(const ClientWindowId& window_id, - const ClientWindowId& transient_window_id); - bool RemoveWindowFromParent(const ClientWindowId& window_id); - bool DeleteWindow(const ClientWindowId& window_id); - bool SetModalType(const ClientWindowId& window_id, ModalType modal_type); - bool SetChildModalParent(const ClientWindowId& window_id, - const ClientWindowId& modal_parent_window_id); - std::vector<const ServerWindow*> GetWindowTree( - const ClientWindowId& window_id) const; - bool SetWindowVisibility(const ClientWindowId& window_id, bool visible); - bool SetWindowOpacity(const ClientWindowId& window_id, float opacity); - bool SetFocus(const ClientWindowId& window_id); - bool Embed(const ClientWindowId& window_id, - mojom::WindowTreeClientPtr window_tree_client, - uint32_t flags); - - // Called from EmbedUsingToken() to embed an existing client that previously - // called ScheduleEmbedForExistingClient(). |tree_and_window_id.tree| is the - // client that previously called ScheduleEmbedForExistingClient() and - // |token| is the token returned to the client. - bool EmbedExistingTree(const ClientWindowId& window_id, - const WindowTreeAndWindowId& tree_and_window_id, - const base::UnguessableToken& token); - - bool IsWaitingForNewTopLevelWindow(uint32_t wm_change_id); - viz::FrameSinkId OnWindowManagerCreatedTopLevelWindow( - uint32_t wm_change_id, - uint32_t client_change_id, - const ServerWindow* window); - void AddActivationParent(const ClientWindowId& window_id); - - // Calls through to the client. - void OnChangeCompleted(uint32_t change_id, bool success); - - // If |callback| is valid then an ack is expected from the client. When the - // ack from the client is received |callback| is Run(). - using AcceleratorCallback = base::OnceCallback<void( - mojom::EventResult, - const base::flat_map<std::string, std::vector<uint8_t>>&)>; - void OnEventOccurredOutsideOfModalWindow(const ServerWindow* modal_window); - - // Called when the cursor touch visibility bit changes. This is only called - // on the WindowTree associated with a WindowManager. - void OnCursorTouchVisibleChanged(bool enabled); - - // Called when a display has been removed. This is only called on the - // WindowTree associated with a WindowManager. - void OnDisplayDestroying(int64_t display_id); - - // Called when |tree|'s jankiness changes (see janky_ for definition). - // Notifies the window manager client so it can update UI for the affected - // window(s). - void ClientJankinessChanged(WindowTree* tree); - - // The following methods are invoked after the corresponding change has been - // processed. They do the appropriate bookkeeping and update the client as - // necessary. - void ProcessWindowBoundsChanged( - const ServerWindow* window, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds, - bool originated_change, - const base::Optional<viz::LocalSurfaceId>& local_surface_id); - void ProcessWindowTransformChanged(const ServerWindow* window, - const gfx::Transform& old_transform, - const gfx::Transform& new_transform, - bool originated_change); - void ProcessClientAreaChanged( - const ServerWindow* window, - const gfx::Insets& new_client_area, - const std::vector<gfx::Rect>& new_additional_client_areas, - bool originated_change); - void ProcessWillChangeWindowHierarchy(const ServerWindow* window, - const ServerWindow* new_parent, - const ServerWindow* old_parent, - bool originated_change); - void ProcessWindowPropertyChanged(const ServerWindow* window, - const std::string& name, - const std::vector<uint8_t>* new_data, - bool originated_change); - void ProcessWindowHierarchyChanged(const ServerWindow* window, - const ServerWindow* new_parent, - const ServerWindow* old_parent, - bool originated_change); - void ProcessWindowReorder(const ServerWindow* window, - const ServerWindow* relative_window, - mojom::OrderDirection direction, - bool originated_change); - void ProcessWindowDeleted(ServerWindow* window, bool originated_change); - void ProcessWillChangeWindowVisibility(const ServerWindow* window, - bool originated_change); - void ProcessWindowOpacityChanged(const ServerWindow* window, - float old_opacity, - float new_opacity, - bool originated_change); - void ProcessCursorChanged(const ServerWindow* window, - const ui::CursorData& cursor, - bool originated_change); - void ProcessFocusChanged(const ServerWindow* old_focused_window, - const ServerWindow* new_focused_window); - void ProcessCaptureChanged(const ServerWindow* new_capture, - const ServerWindow* old_capture, - bool originated_change); - void ProcessTransientWindowAdded(const ServerWindow* window, - const ServerWindow* transient_window, - bool originated_change); - void ProcessTransientWindowRemoved(const ServerWindow* window, - const ServerWindow* transient_window, - bool originated_change); - void ProcessWindowSurfaceChanged(ServerWindow* window, - const viz::SurfaceInfo& surface_info); - - // Sends this event to the client if it matches an active pointer watcher. - // |target_window| is the target of the event, and may be null or not known - // to this tree. - void SendToPointerWatcher(const ui::Event& event, - ServerWindow* target_window, - int64_t display_id); - - // Before the ClientWindowId gets sent back to the client, making sure we - // reset the high 16 bits back to 0 if it's being sent back to the client - // that created the window. - Id ClientWindowIdToTransportId(const ClientWindowId& client_window_id) const; - - private: - friend class test::WindowTreeTestApi; - - struct WaitingForTopLevelWindowInfo { - WaitingForTopLevelWindowInfo(const ClientWindowId& client_window_id, - uint32_t wm_change_id) - : client_window_id(client_window_id), wm_change_id(wm_change_id) {} - ~WaitingForTopLevelWindowInfo() {} - - // Id supplied from the client. - ClientWindowId client_window_id; - - // Change id we created for the window manager. - uint32_t wm_change_id; - }; - - enum class RemoveRootReason { - // The window is being removed. - DELETED, - - // Another client is being embedded in the window. - EMBED, - - // The embedded client explicitly asked to be unembedded. - UNEMBED, - }; - - bool ShouldRouteToWindowManager(const ServerWindow* window) const; - - Id TransportIdForWindow(const ServerWindow* window) const; - - // Returns true if |id| is a valid WindowId for a new window. - bool IsValidIdForNewWindow(const ClientWindowId& id) const; - - // These functions return true if the corresponding mojom function is allowed - // for this tree. - bool CanReorderWindow(const ServerWindow* window, - const ServerWindow* relative_window, - mojom::OrderDirection direction) const; - - // Deletes a window owned by this tree. Returns true on success. |source| is - // the tree that originated the change. - bool DeleteWindowImpl(WindowTree* source, ServerWindow* window); - - // If |window| is known does nothing. Otherwise adds |window| to |windows| (if - // non-null) and marks |window| as known and recurses. If |window| is not - // known it assigned the ClientWindowId |id_for_window|, if |id_for_window| - // is null, then the FrameSinkId of |window| is used. - void GetUnknownWindowsFrom(const ServerWindow* window, - std::vector<const ServerWindow*>* windows, - const ClientWindowId* id_for_window); - - // Called to add |window| as an embed root. This matches a call from the - // client to ScheduleEmbedForExistingClient(). |client_window_id| is the - // ClientWindowId to use for |window|. - void AddRootForToken(const base::UnguessableToken& token, - ServerWindow* window, - const ClientWindowId& client_window_id); - - void AddToMaps(const ServerWindow* window, - const ClientWindowId& client_window_id); - - // Removes |window| from the appropriate maps. If |window| is known to this - // client true is returned. - bool RemoveFromMaps(const ServerWindow* window); - - // Removes |window| and all its descendants from the necessary maps. This - // does not recurse through windows that were created by this tree. All - // windows created by this tree are added to |created_windows|. - void RemoveFromKnown(const ServerWindow* window, - std::vector<ServerWindow*>* created_windows); - - // Removes a root from set of roots of this tree. This does not remove - // the window from the window tree, only from the set of roots. - void RemoveRoot(ServerWindow* window, RemoveRootReason reason); - - // Converts Window(s) to WindowData(s) for transport. This assumes all the - // windows are valid for the client. The parent of windows the client is not - // allowed to see are set to NULL (in the returned WindowData(s)). - std::vector<mojom::WindowDataPtr> WindowsToWindowDatas( - const std::vector<const ServerWindow*>& windows); - mojom::WindowDataPtr WindowToWindowData(const ServerWindow* window); - - // Implementation of GetWindowTree(). Adds |window| to |windows| and recurses - // if CanDescendIntoWindowForWindowTree() returns true. - void GetWindowTreeImpl(const ServerWindow* window, - std::vector<const ServerWindow*>* windows) const; - - // Notify the client if the drawn state of any of the roots changes. - // |window| is the window that is changing to the drawn state - // |new_drawn_value|. - void NotifyDrawnStateChanged(const ServerWindow* window, - bool new_drawn_value); - - // Deletes all Windows we own. - void DestroyWindows(); - - bool CanEmbed(const ClientWindowId& window_id) const; - void PrepareForEmbed(ServerWindow* window); - void RemoveChildrenAsPartOfEmbed(ServerWindow* window); - - // Generates a new event id for an accelerator or event ack, sets it in - // |event_ack_id_| and returns it. - uint32_t GenerateEventAckId(); - - void DispatchEventImpl(ServerWindow* target, - const ui::Event& event, - const EventLocation& event_location, - DispatchEventCallback callback); - - // Returns true if the client has a pointer watcher and this event matches. - bool EventMatchesPointerWatcher(const ui::Event& event) const; - - // Calls OnChangeCompleted() on the client. - void NotifyChangeCompleted(uint32_t change_id, - mojom::WindowManagerErrorCode error_code); - - // Callback for when WmMoveDragImage completes. This sends off the next - // queued move under the image if the mouse had further moves while we were - // waiting for the last move to be acknowledged. - void OnWmMoveDragImageAck(); - - // Called from SetDisplayRoot(), see mojom for details. Returns the root - // of the display if successful, otherwise null. - ServerWindow* ProcessSetDisplayRoot( - const display::Display& display_to_create, - const display::ViewportMetrics& transport_viewport_metrics, - bool is_primary_display, - const ClientWindowId& client_window_id, - const std::vector<display::Display>& mirrors); - - bool ProcessSwapDisplayRoots(int64_t display_id1, int64_t display_id2); - bool ProcessSetBlockingContainers(std::vector<mojom::BlockingContainersPtr> - transport_all_blocking_containers); - - // Returns the ClientWindowId from a transport id. Uses id_ as the - // ClientWindowId::client_id part if it was invalid. This function - // do a straight mapping, there may not be a window with the returned id. - ClientWindowId MakeClientWindowId(Id transport_window_id) const; - - // Returns the WindowTreeClient previously scheduled for an embed with the - // given |token| from ScheduleEmbed(). If this client is the result of an - // Embed() and ScheduleEmbed() was not called on this client, then this - // recurses to the parent WindowTree. Recursing enables an acestor to call - // ScheduleEmbed() and the ancestor to communicate the token with the client. - mojom::WindowTreeClientPtr GetAndRemoveScheduledEmbedWindowTreeClient( - const base::UnguessableToken& token); - - // AsyncEventDispatcher: - void DispatchEvent(ServerWindow* target, - const ui::Event& event, - const EventLocation& event_location, - DispatchEventCallback callback) override; - void DispatchAccelerator(uint32_t accelerator_id, - const ui::Event& event, - AcceleratorCallback callback) override; - - // WindowTree: - void NewWindow( - uint32_t change_id, - Id transport_window_id, - const base::Optional<base::flat_map<std::string, std::vector<uint8_t>>>& - transport_properties) override; - void NewTopLevelWindow( - uint32_t change_id, - Id transport_window_id, - const base::flat_map<std::string, std::vector<uint8_t>>& - transport_properties) override; - void DeleteWindow(uint32_t change_id, Id transport_window_id) override; - void AddWindow(uint32_t change_id, Id parent_id, Id child_id) override; - void RemoveWindowFromParent(uint32_t change_id, Id window_id) override; - void AddTransientWindow(uint32_t change_id, - Id window, - Id transient_window) override; - void RemoveTransientWindowFromParent(uint32_t change_id, - Id transient_window_id) override; - void SetModalType(uint32_t change_id, Id window_id, ModalType type) override; - void SetChildModalParent(uint32_t change_id, - Id window_id, - Id parent_window_id) override; - void ReorderWindow(uint32_t change_Id, - Id window_id, - Id relative_window_id, - mojom::OrderDirection direction) override; - void GetWindowTree(Id window_id, GetWindowTreeCallback callback) override; - void SetCapture(uint32_t change_id, Id window_id) override; - void ReleaseCapture(uint32_t change_id, Id window_id) override; - void StartPointerWatcher(bool want_moves) override; - void StopPointerWatcher() override; - void SetWindowBounds( - uint32_t change_id, - Id window_id, - const gfx::Rect& bounds, - const base::Optional<viz::LocalSurfaceId>& local_surface_id) override; - void SetWindowTransform(uint32_t change_id, - Id window_id, - const gfx::Transform& transform) override; - void SetWindowVisibility(uint32_t change_id, - Id window_id, - bool visible) override; - void SetWindowProperty( - uint32_t change_id, - Id transport_window_id, - const std::string& name, - const base::Optional<std::vector<uint8_t>>& value) override; - void SetWindowOpacity(uint32_t change_id, - Id window_id, - float opacity) override; - void AttachCompositorFrameSink( - Id transport_window_id, - viz::mojom::CompositorFrameSinkRequest compositor_frame_sink, - viz::mojom::CompositorFrameSinkClientPtr client) override; - void Embed(Id transport_window_id, - mojom::WindowTreeClientPtr client, - uint32_t flags, - EmbedCallback callback) override; - void ScheduleEmbed(mojom::WindowTreeClientPtr client, - ScheduleEmbedCallback callback) override; - void EmbedUsingToken(Id transport_window_id, - const base::UnguessableToken& token, - uint32_t flags, - EmbedUsingTokenCallback callback) override; - void ScheduleEmbedForExistingClient( - ClientSpecificId window_id, - ScheduleEmbedForExistingClientCallback callback) override; - void SetFocus(uint32_t change_id, Id transport_window_id) override; - void SetCanFocus(Id transport_window_id, bool can_focus) override; - void SetEventTargetingPolicy(Id transport_window_id, - mojom::EventTargetingPolicy policy) override; - void SetCursor(uint32_t change_id, - Id transport_window_id, - ui::CursorData cursor) override; - void SetWindowTextInputState(Id transport_window_id, - ui::mojom::TextInputStatePtr state) override; - void SetImeVisibility(Id transport_window_id, - bool visible, - ui::mojom::TextInputStatePtr state) override; - void OnWindowInputEventAck(uint32_t event_id, - mojom::EventResult result) override; - void DeactivateWindow(Id window_id) override; - void SetClientArea(Id transport_window_id, - const gfx::Insets& insets, - const base::Optional<std::vector<gfx::Rect>>& - transport_additional_client_areas) override; - void SetCanAcceptDrops(Id window_id, bool accepts_drops) override; - void SetHitTestMask(Id transport_window_id, - const base::Optional<gfx::Rect>& mask) override; - void StackAbove(uint32_t change_id, Id above_id, Id below_id) override; - void StackAtTop(uint32_t change_id, Id window_id) override; - void PerformWmAction(Id window_id, const std::string& action) override; - void GetWindowManagerClient( - mojo::AssociatedInterfaceRequest<mojom::WindowManagerClient> internal) - override; - void GetCursorLocationMemory( - GetCursorLocationMemoryCallback callback) override; - void PerformDragDrop( - uint32_t change_id, - Id source_window_id, - const gfx::Point& screen_location, - const base::flat_map<std::string, std::vector<uint8_t>>& drag_data, - const gfx::ImageSkia& drag_image, - const gfx::Vector2d& drag_image_offset, - uint32_t drag_operation, - ui::mojom::PointerKind source) override; - void CancelDragDrop(Id window_id) override; - void PerformWindowMove(uint32_t change_id, - Id window_id, - ui::mojom::MoveLoopSource source, - const gfx::Point& cursor) override; - void CancelWindowMove(Id window_id) override; - - // mojom::WindowManagerClient: - void AddAccelerators(std::vector<mojom::WmAcceleratorPtr> accelerators, - AddAcceleratorsCallback callback) override; - void RemoveAccelerator(uint32_t id) override; - void AddActivationParent(Id transport_window_id) override; - void RemoveActivationParent(Id transport_window_id) override; - void SetExtendedHitRegionForChildren( - Id window_id, - const gfx::Insets& mouse_insets, - const gfx::Insets& touch_insets) override; - void SetKeyEventsThatDontHideCursor( - std::vector<::ui::mojom::EventMatcherPtr> dont_hide_cursor_list) override; - void SetDisplayRoot(const display::Display& display, - mojom::WmViewportMetricsPtr viewport_metrics, - bool is_primary_display, - Id window_id, - const std::vector<display::Display>& mirrors, - SetDisplayRootCallback callback) override; - void SetDisplayConfiguration( - const std::vector<display::Display>& displays, - std::vector<ui::mojom::WmViewportMetricsPtr> transport_metrics, - int64_t primary_display_id, - int64_t internal_display_id, - const std::vector<display::Display>& mirrors, - SetDisplayConfigurationCallback callback) override; - void SwapDisplayRoots(int64_t display_id1, - int64_t display_id2, - SwapDisplayRootsCallback callback) override; - void SetBlockingContainers( - std::vector<mojom::BlockingContainersPtr> blocking_containers, - SetBlockingContainersCallback callback) override; - void WmResponse(uint32_t change_id, bool response) override; - void WmSetBoundsResponse(uint32_t change_id) override; - void WmRequestClose(Id transport_window_id) override; - void WmSetFrameDecorationValues( - mojom::FrameDecorationValuesPtr values) override; - void WmSetNonClientCursor(Id window_id, ui::CursorData cursor) override; - void WmLockCursor() override; - void WmUnlockCursor() override; - void WmSetCursorVisible(bool visible) override; - void WmSetCursorSize(ui::CursorSize cursor_size) override; - void WmSetGlobalOverrideCursor( - base::Optional<ui::CursorData> cursor) override; - void WmMoveCursorToDisplayLocation(const gfx::Point& display_pixels, - int64_t display_id) override; - void WmConfineCursorToBounds(const gfx::Rect& bounds_in_pixles, - int64_t display_id) override; - void WmSetCursorTouchVisible(bool enabled) override; - void OnWmCreatedTopLevelWindow(uint32_t change_id, - Id transport_window_id) override; - void OnAcceleratorAck(uint32_t event_id, - mojom::EventResult result, - const base::flat_map<std::string, std::vector<uint8_t>>& - properties) override; - - // AccessPolicyDelegate: - bool HasRootForAccessPolicy(const ServerWindow* window) const override; - bool IsWindowKnownForAccessPolicy(const ServerWindow* window) const override; - bool IsWindowRootOfAnotherTreeForAccessPolicy( - const ServerWindow* window) const override; - bool IsWindowCreatedByWindowManager( - const ServerWindow* window) const override; - bool ShouldInterceptEventsForAccessPolicy( - const ServerWindow* window) const override; - - // DragSource: - void OnDragMoved(const gfx::Point& location) override; - void OnDragCompleted(bool success, uint32_t action_taken) override; - DragTargetConnection* GetDragTargetForWindow( - const ServerWindow* window) override; - - // DragTargetConnection: - void PerformOnDragDropStart( - const base::flat_map<std::string, std::vector<uint8_t>>& mime_data) - override; - void PerformOnDragEnter( - const ServerWindow* window, - uint32_t event_flags, - const gfx::Point& cursor_offset, - uint32_t effect_bitmask, - const base::Callback<void(uint32_t)>& callback) override; - void PerformOnDragOver( - const ServerWindow* window, - uint32_t event_flags, - const gfx::Point& cursor_offset, - uint32_t effect_bitmask, - const base::Callback<void(uint32_t)>& callback) override; - void PerformOnDragLeave(const ServerWindow* window) override; - void PerformOnCompleteDrop( - const ServerWindow* window, - uint32_t event_flags, - const gfx::Point& cursor_offset, - uint32_t effect_bitmask, - const base::Callback<void(uint32_t)>& callback) override; - void PerformOnDragDropDone() override; - - WindowServer* window_server_; - - // True if this WindowTree was created by way of Embed(). - bool is_for_embedding_; - - // Id of this tree as assigned by WindowServer. - const ClientSpecificId id_; - std::string name_; - - std::unique_ptr<WindowTreeBinding> binding_; - - std::unique_ptr<ui::ws::AccessPolicy> access_policy_; - - // The roots, or embed points, of this tree. A WindowTree may have any - // number of roots, including 0. - std::set<const ServerWindow*> roots_; - - // The windows created by this tree. This tree owns these objects. - std::set<ServerWindow*> created_windows_; - - // The client is allowed to assign ids. - std::unordered_map<ClientWindowId, const ServerWindow*, ClientWindowIdHash> - client_id_to_window_map_; - std::unordered_map<const ServerWindow*, ClientWindowId> - window_to_client_id_map_; - - // Id passed to the client and expected to be supplied back to - // OnWindowInputEventAck() or OnAcceleratorAck(). - uint32_t event_ack_id_; - - DispatchEventCallback event_ack_callback_; - - AcceleratorCallback accelerator_ack_callback_; - - // A client is considered janky if it hasn't ACK'ed input events within a - // reasonable timeframe. - bool janky_ = false; - - // For performance reasons, only send move events if the client explicitly - // requests them. - bool pointer_watcher_want_moves_ = false; - - // True if StartPointerWatcher() was called. - bool has_pointer_watcher_ = false; - - // WindowManager the current event came from. - WindowManagerState* event_source_wms_ = nullptr; - - base::queue<std::unique_ptr<TargetedEvent>> event_queue_; - - // TODO(sky): move all window manager specific state into struct to make it - // clear what applies only to the window manager. - std::unique_ptr<mojo::AssociatedBinding<mojom::WindowManagerClient>> - window_manager_internal_client_binding_; - mojom::WindowManager* window_manager_internal_; - std::unique_ptr<WindowManagerState> window_manager_state_; - // See mojom for details. - bool automatically_create_display_roots_ = true; - - std::unique_ptr<WaitingForTopLevelWindowInfo> - waiting_for_top_level_window_info_; - bool embedder_intercepts_events_ = false; - - // State kept while we're waiting for the window manager to ack a - // WmMoveDragImage. Non-null while we're waiting for a response. - struct DragMoveState; - std::unique_ptr<DragMoveState> drag_move_state_; - - // Holds WindowTreeClients passed to ScheduleEmbed(). Entries are removed - // when EmbedUsingToken() is called. - using ScheduledEmbeds = - base::flat_map<base::UnguessableToken, mojom::WindowTreeClientPtr>; - ScheduledEmbeds scheduled_embeds_; - - // Controls whether the client can change the visibility of the roots. - bool can_change_root_window_visibility_ = true; - - // A weak ptr factory for callbacks from the window manager for when we send - // a image move. All weak ptrs are invalidated when a drag is completed. - base::WeakPtrFactory<WindowTree> drag_weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(WindowTree); -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_WINDOW_TREE_H_
diff --git a/services/ui/ws/window_tree_binding.cc b/services/ui/ws/window_tree_binding.cc deleted file mode 100644 index 124ff4b7..0000000 --- a/services/ui/ws/window_tree_binding.cc +++ /dev/null
@@ -1,73 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "services/ui/ws/window_tree_binding.h" - -#include "base/bind.h" -#include "services/ui/ws/window_server.h" -#include "services/ui/ws/window_tree.h" - -namespace ui { -namespace ws { - -WindowTreeBinding::WindowTreeBinding(mojom::WindowTreeClient* client) - : client_(client) {} - -WindowTreeBinding::~WindowTreeBinding() {} - -void WindowTreeBinding::ResetClientForShutdown() { - client_ = CreateClientForShutdown(); -} - -DefaultWindowTreeBinding::DefaultWindowTreeBinding( - WindowTree* tree, - WindowServer* window_server, - mojom::WindowTreeRequest service_request, - mojom::WindowTreeClientPtr client) - : WindowTreeBinding(client.get()), - binding_(tree, std::move(service_request)), - client_(std::move(client)) { - // Both |window_server| and |tree| outlive us. - binding_.set_connection_error_handler( - base::Bind(&WindowServer::DestroyTree, base::Unretained(window_server), - base::Unretained(tree))); -} - -DefaultWindowTreeBinding::DefaultWindowTreeBinding( - WindowTree* tree, - mojom::WindowTreeClientPtr client) - : WindowTreeBinding(client.get()), - binding_(tree), - client_(std::move(client)) {} - -DefaultWindowTreeBinding::~DefaultWindowTreeBinding() {} - -mojom::WindowTreePtr DefaultWindowTreeBinding::CreateInterfacePtrAndBind() { - DCHECK(!binding_.is_bound()); - mojom::WindowTreePtr ptr; - binding_.Bind(mojo::MakeRequest(&ptr)); - return ptr; -} - -mojom::WindowManager* DefaultWindowTreeBinding::GetWindowManager() { - client_->GetWindowManager(MakeRequest(&window_manager_internal_)); - return window_manager_internal_.get(); -} - -void DefaultWindowTreeBinding::SetIncomingMethodCallProcessingPaused( - bool paused) { - if (paused) - binding_.PauseIncomingMethodCallProcessing(); - else - binding_.ResumeIncomingMethodCallProcessing(); -} - -mojom::WindowTreeClient* DefaultWindowTreeBinding::CreateClientForShutdown() { - client_.reset(); - MakeRequest(&client_); - return client_.get(); -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/window_tree_binding.h b/services/ui/ws/window_tree_binding.h deleted file mode 100644 index 4b9b884..0000000 --- a/services/ui/ws/window_tree_binding.h +++ /dev/null
@@ -1,83 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SERVICES_UI_WS_WINDOW_TREE_BINDING_H_ -#define SERVICES_UI_WS_WINDOW_TREE_BINDING_H_ - -#include <memory> - -#include "base/macros.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "services/ui/public/interfaces/window_tree.mojom.h" - -namespace ui { -namespace ws { - -class WindowServer; -class WindowTree; - -// WindowTreeBinding manages the binding between a WindowTree and its -// WindowTreeClient. WindowTreeBinding exists so that a mock implementation -// of WindowTreeClient can be injected for tests. WindowTree owns its -// associated WindowTreeBinding. -class WindowTreeBinding { - public: - explicit WindowTreeBinding(mojom::WindowTreeClient* client); - virtual ~WindowTreeBinding(); - - mojom::WindowTreeClient* client() { return client_; } - - // Obtains a new WindowManager. This should only be called once. - virtual mojom::WindowManager* GetWindowManager() = 0; - - virtual void SetIncomingMethodCallProcessingPaused(bool paused) = 0; - - // Called when the WindowServer is destroyed. Sets |client_| to - // CreateClientForShutdown(). - void ResetClientForShutdown(); - - protected: - virtual mojom::WindowTreeClient* CreateClientForShutdown() = 0; - - private: - mojom::WindowTreeClient* client_; - - DISALLOW_COPY_AND_ASSIGN(WindowTreeBinding); -}; - -// Bindings implementation of WindowTreeBinding. -class DefaultWindowTreeBinding : public WindowTreeBinding { - public: - DefaultWindowTreeBinding(WindowTree* tree, - WindowServer* window_server, - mojom::WindowTreeRequest service_request, - mojom::WindowTreeClientPtr client); - DefaultWindowTreeBinding(WindowTree* tree, - mojom::WindowTreeClientPtr client); - ~DefaultWindowTreeBinding() override; - - // Use when created with the constructor that does not take a - // WindowTreeRequest. - mojom::WindowTreePtr CreateInterfacePtrAndBind(); - - // WindowTreeBinding: - mojom::WindowManager* GetWindowManager() override; - void SetIncomingMethodCallProcessingPaused(bool paused) override; - - protected: - // WindowTreeBinding: - mojom::WindowTreeClient* CreateClientForShutdown() override; - - private: - mojo::Binding<mojom::WindowTree> binding_; - mojom::WindowTreeClientPtr client_; - mojom::WindowManagerAssociatedPtr window_manager_internal_; - - DISALLOW_COPY_AND_ASSIGN(DefaultWindowTreeBinding); -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_WINDOW_TREE_BINDING_H_
diff --git a/services/ui/ws/window_tree_client_unittest.cc b/services/ui/ws/window_tree_client_unittest.cc deleted file mode 100644 index 30542aa9..0000000 --- a/services/ui/ws/window_tree_client_unittest.cc +++ /dev/null
@@ -1,2564 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stddef.h> -#include <stdint.h> - -#include "base/bind.h" -#include "base/containers/flat_map.h" -#include "base/macros.h" -#include "base/run_loop.h" -#include "base/strings/stringprintf.h" -#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h" -#include "mojo/public/cpp/bindings/associated_binding.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "services/service_manager/public/cpp/binder_registry.h" -#include "services/service_manager/public/cpp/service_test.h" -#include "services/ui/common/util.h" -#include "services/ui/public/interfaces/constants.mojom.h" -#include "services/ui/public/interfaces/window_tree.mojom.h" -#include "services/ui/public/interfaces/window_tree_host_factory.mojom.h" -#include "services/ui/ws/ids.h" -#include "services/ui/ws/test_change_tracker.h" -#include "services/ui/ws/window_server_service_test_base.h" -#include "ui/base/cursor/cursor.h" - -using mojo::InterfaceRequest; -using service_manager::Service; -using ui::mojom::WindowDataPtr; -using ui::mojom::WindowTree; -using ui::mojom::WindowTreeClient; - -namespace ui { -namespace ws { -namespace test { - -namespace { - -// Creates an id used for transport from the specified parameters. -Id BuildWindowId(ClientSpecificId client_id, - ClientSpecificId window_id) { - const Id tmp = client_id; - return (tmp << 32) | window_id; -} - -// Callback function from WindowTree functions. -// ---------------------------------- - -void WindowTreeResultCallback(base::RunLoop* run_loop, - std::vector<TestWindow>* windows, - std::vector<WindowDataPtr> results) { - WindowDatasToTestWindows(results, windows); - run_loop->Quit(); -} - -void EmbedCallbackImpl(base::RunLoop* run_loop, - bool* result_cache, - bool result) { - *result_cache = result; - run_loop->Quit(); -} - -void ScheduleEmbedCallbackImpl(base::RunLoop* run_loop, - base::UnguessableToken* resulting_token, - const base::UnguessableToken& token) { - *resulting_token = token; - run_loop->Quit(); -} - -// ----------------------------------------------------------------------------- - -bool EmbedUrl(service_manager::Connector* connector, - WindowTree* tree, - const std::string& url, - Id root_id) { - bool result = false; - base::RunLoop run_loop; - { - mojom::WindowTreeClientPtr client; - connector->BindInterface(url, &client); - const uint32_t embed_flags = 0; - tree->Embed(root_id, std::move(client), embed_flags, - base::Bind(&EmbedCallbackImpl, &run_loop, &result)); - } - run_loop.Run(); - return result; -} - -bool Embed(WindowTree* tree, Id root_id, mojom::WindowTreeClientPtr client) { - bool result = false; - base::RunLoop run_loop; - { - const uint32_t embed_flags = 0; - tree->Embed(root_id, std::move(client), embed_flags, - base::Bind(&EmbedCallbackImpl, &run_loop, &result)); - } - run_loop.Run(); - return result; -} - -bool EmbedUsingToken(WindowTree* tree, - Id root_id, - const base::UnguessableToken& token) { - bool result = false; - base::RunLoop run_loop; - const uint32_t embed_flags = 0; - tree->EmbedUsingToken(root_id, token, embed_flags, - base::Bind(&EmbedCallbackImpl, &run_loop, &result)); - run_loop.Run(); - return result; -} - -void ScheduleEmbed(WindowTree* tree, - mojom::WindowTreeClientPtr client, - base::UnguessableToken* token) { - base::RunLoop run_loop; - tree->ScheduleEmbed(std::move(client), - base::Bind(&ScheduleEmbedCallbackImpl, &run_loop, token)); - run_loop.Run(); -} - -void GetWindowTree(WindowTree* tree, - Id window_id, - std::vector<TestWindow>* windows) { - base::RunLoop run_loop; - tree->GetWindowTree( - window_id, base::Bind(&WindowTreeResultCallback, &run_loop, windows)); - run_loop.Run(); -} - -// Utility functions ----------------------------------------------------------- - -const Id kNullParentId = 0; -std::string IdToString(Id id) { - return (id == kNullParentId) - ? "null" - : base::StringPrintf("%d,%d", ClientIdFromTransportId(id), - ClientWindowIdFromTransportId(id)); -} - -std::string WindowParentToString(Id window, Id parent) { - return base::StringPrintf("window=%s parent=%s", IdToString(window).c_str(), - IdToString(parent).c_str()); -} - -// ----------------------------------------------------------------------------- - -// A WindowTreeClient implementation that logs all changes to a tracker. -class TestWindowTreeClient : public mojom::WindowTreeClient, - public TestChangeTracker::Delegate, - public mojom::WindowManager { - public: - TestWindowTreeClient() - : binding_(this), - root_window_id_(0), - // Start with a random large number so tests can use lower ids if they - // want. - next_change_id_(10000), - waiting_change_id_(0), - on_change_completed_result_(false), - track_root_bounds_changes_(false) { - tracker_.set_delegate(this); - } - - void Bind(mojo::InterfaceRequest<mojom::WindowTreeClient> request) { - binding_.Bind(std::move(request)); - } - - mojom::WindowTree* tree() { return tree_.get(); } - TestChangeTracker* tracker() { return &tracker_; } - Id root_window_id() const { return root_window_id_; } - - // Sets whether changes to the bounds of the root should be tracked. Normally - // they are ignored (as during startup we often times get random size - // changes). - void set_track_root_bounds_changes(bool value) { - track_root_bounds_changes_ = value; - } - - // Runs a nested MessageLoop until |count| changes (calls to - // WindowTreeClient functions) have been received. - void WaitForChangeCount(size_t count) { - if (tracker_.changes()->size() >= count) - return; - - ASSERT_TRUE(wait_state_.get() == nullptr); - wait_state_ = std::make_unique<WaitState>(); - wait_state_->change_count = count; - wait_state_->run_loop.Run(); - wait_state_.reset(); - } - - uint32_t GetAndAdvanceChangeId() { return next_change_id_++; } - - // Runs a nested MessageLoop until OnEmbed() has been encountered. - void WaitForOnEmbed() { - if (tree_) - return; - embed_run_loop_ = std::make_unique<base::RunLoop>(); - embed_run_loop_->Run(); - embed_run_loop_.reset(); - } - - bool WaitForChangeCompleted(uint32_t id) { - waiting_change_id_ = id; - change_completed_run_loop_ = std::make_unique<base::RunLoop>(); - change_completed_run_loop_->Run(); - return on_change_completed_result_; - } - - bool DeleteWindow(Id id) { - const uint32_t change_id = GetAndAdvanceChangeId(); - tree()->DeleteWindow(change_id, id); - return WaitForChangeCompleted(change_id); - } - - bool AddWindow(Id parent, Id child) { - const uint32_t change_id = GetAndAdvanceChangeId(); - tree()->AddWindow(change_id, parent, child); - return WaitForChangeCompleted(change_id); - } - - bool RemoveWindowFromParent(Id window_id) { - const uint32_t change_id = GetAndAdvanceChangeId(); - tree()->RemoveWindowFromParent(change_id, window_id); - return WaitForChangeCompleted(change_id); - } - - bool ReorderWindow(Id window_id, - Id relative_window_id, - mojom::OrderDirection direction) { - const uint32_t change_id = GetAndAdvanceChangeId(); - tree()->ReorderWindow(change_id, window_id, relative_window_id, direction); - return WaitForChangeCompleted(change_id); - } - - // Waits for all messages to be received by |ws|. This is done by attempting - // to set opacity on an embed/invalid window. 1.0f is the default opacity - // value. When we get the response we know all messages have been processed. - bool WaitForAllMessages() { return !SetWindowOpacity(0, 1.0f); } - - Id NewWindow(ClientSpecificId window_id) { - return NewWindowWithCompleteId(window_id); - } - - // Generally you want NewWindow(), but use this if you need to test given - // a complete window id (NewWindow() ors with the client id). - Id NewWindowWithCompleteId(Id id) { - base::flat_map<std::string, std::vector<uint8_t>> properties; - const uint32_t change_id = GetAndAdvanceChangeId(); - tree()->NewWindow(change_id, id, std::move(properties)); - return WaitForChangeCompleted(change_id) ? id : 0; - } - - bool SetWindowProperty(Id window_id, - const std::string& name, - const std::vector<uint8_t>* data) { - base::Optional<std::vector<uint8_t>> mojo_data; - if (data) - mojo_data.emplace(*data); - const uint32_t change_id = GetAndAdvanceChangeId(); - tree()->SetWindowProperty(change_id, window_id, name, mojo_data); - return WaitForChangeCompleted(change_id); - } - - bool SetCursor(Id window_id, const ui::CursorData& cursor) { - const uint32_t change_id = GetAndAdvanceChangeId(); - tree()->SetCursor(change_id, window_id, cursor); - return WaitForChangeCompleted(change_id); - } - - bool SetWindowVisibility(Id window_id, bool visible) { - const uint32_t change_id = GetAndAdvanceChangeId(); - tree()->SetWindowVisibility(change_id, window_id, visible); - return WaitForChangeCompleted(change_id); - } - - bool SetWindowOpacity(Id window_id, float opacity) { - const uint32_t change_id = GetAndAdvanceChangeId(); - tree()->SetWindowOpacity(change_id, window_id, opacity); - return WaitForChangeCompleted(change_id); - } - - private: - // Used when running a nested MessageLoop. - struct WaitState { - WaitState() : change_count(0) {} - - // Number of changes waiting for. - size_t change_count; - base::RunLoop run_loop; - }; - - // TestChangeTracker::Delegate: - void OnChangeAdded() override { - if (wait_state_.get() && - tracker_.changes()->size() >= wait_state_->change_count) { - wait_state_->run_loop.Quit(); - } - } - - // WindowTreeClient: - void OnEmbed( - WindowDataPtr root, - mojom::WindowTreePtr tree, - int64_t display_id, - Id focused_window_id, - bool drawn, - const base::Optional<viz::LocalSurfaceId>& local_surface_id) override { - // TODO(sky): add coverage of |focused_window_id|. - ASSERT_TRUE(root); - root_window_id_ = root->window_id; - tree_ = std::move(tree); - tracker()->OnEmbed(std::move(root), drawn); - if (embed_run_loop_) - embed_run_loop_->Quit(); - } - void OnEmbedFromToken( - const base::UnguessableToken& token, - mojom::WindowDataPtr root, - int64_t display_id, - const base::Optional<viz::LocalSurfaceId>& local_surface_id) override {} - void OnEmbeddedAppDisconnected(Id window_id) override { - tracker()->OnEmbeddedAppDisconnected(window_id); - } - void OnUnembed(Id window_id) override { tracker()->OnUnembed(window_id); } - void OnCaptureChanged(Id new_capture_window_id, - Id old_capture_window_id) override { - tracker()->OnCaptureChanged(new_capture_window_id, old_capture_window_id); - } - void OnFrameSinkIdAllocated(Id window_id, - const viz::FrameSinkId& frame_sink_id) override {} - void OnTopLevelCreated( - uint32_t change_id, - mojom::WindowDataPtr data, - int64_t display_id, - bool drawn, - const base::Optional<viz::LocalSurfaceId>& local_surface_id) override { - tracker()->OnTopLevelCreated(change_id, std::move(data), drawn); - } - void OnWindowBoundsChanged( - Id window_id, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds, - const base::Optional<viz::LocalSurfaceId>& local_surface_id) override { - // The bounds of the root may change during startup on Android at random - // times. As this doesn't matter, and shouldn't impact test exepctations, - // it is ignored. - if (window_id == root_window_id_ && !track_root_bounds_changes_) - return; - tracker()->OnWindowBoundsChanged(window_id, old_bounds, new_bounds, - local_surface_id); - } - void OnWindowTransformChanged(Id window_id, - const gfx::Transform& old_transform, - const gfx::Transform& new_transform) override { - tracker()->OnWindowTransformChanged(window_id); - } - void OnClientAreaChanged( - Id window_id, - const gfx::Insets& new_client_area, - const std::vector<gfx::Rect>& new_additional_client_areas) override {} - void OnTransientWindowAdded(Id window_id, Id transient_window_id) override { - tracker()->OnTransientWindowAdded(window_id, transient_window_id); - } - void OnTransientWindowRemoved(Id window_id, Id transient_window_id) override { - tracker()->OnTransientWindowRemoved(window_id, transient_window_id); - } - void OnWindowHierarchyChanged(Id window, - Id old_parent, - Id new_parent, - std::vector<WindowDataPtr> windows) override { - tracker()->OnWindowHierarchyChanged(window, old_parent, new_parent, - std::move(windows)); - } - void OnWindowReordered(Id window_id, - Id relative_window_id, - mojom::OrderDirection direction) override { - tracker()->OnWindowReordered(window_id, relative_window_id, direction); - } - void OnWindowDeleted(Id window) override { - tracker()->OnWindowDeleted(window); - } - void OnWindowVisibilityChanged(Id window, bool visible) override { - tracker()->OnWindowVisibilityChanged(window, visible); - } - void OnWindowOpacityChanged(Id window, - float old_opacity, - float new_opacity) override { - tracker()->OnWindowOpacityChanged(window, new_opacity); - } - void OnWindowParentDrawnStateChanged(Id window, bool drawn) override { - tracker()->OnWindowParentDrawnStateChanged(window, drawn); - } - void OnWindowInputEvent( - uint32_t event_id, - Id window_id, - int64_t display_id, - Id display_root_window_id, - const gfx::PointF& event_location_in_screen_pixel_layout, - std::unique_ptr<ui::Event> event, - bool matches_pointer_watcher) override { - // Ack input events to clear the state on the server. These can be received - // during test startup. X11Window::DispatchEvent sends a synthetic move - // event to notify of entry. - tree()->OnWindowInputEventAck(event_id, mojom::EventResult::HANDLED); - // Don't log input events as none of the tests care about them and they - // may come in at random points. - } - void OnPointerEventObserved(std::unique_ptr<ui::Event>, - Id window_id, - int64_t display_id) override {} - void OnWindowSharedPropertyChanged( - Id window, - const std::string& name, - const base::Optional<std::vector<uint8_t>>& new_data) override { - tracker_.OnWindowSharedPropertyChanged(window, name, new_data); - } - // TODO(sky): add testing coverage. - void OnWindowFocused(Id focused_window_id) override {} - void OnWindowCursorChanged(Id window_id, ui::CursorData cursor) override { - tracker_.OnWindowCursorChanged(window_id, cursor); - } - - void OnDragDropStart(const base::flat_map<std::string, std::vector<uint8_t>>& - drag_data) override { - NOTIMPLEMENTED(); - } - - void OnWindowSurfaceChanged(Id window_id, - const viz::SurfaceInfo& surface_info) override { - tracker_.OnWindowSurfaceChanged(window_id, surface_info); - } - - void OnDragEnter(Id window, - uint32_t key_state, - const gfx::Point& position, - uint32_t effect_bitmask, - OnDragEnterCallback callback) override { - NOTIMPLEMENTED(); - } - void OnDragOver(Id window, - uint32_t key_state, - const gfx::Point& position, - uint32_t effect_bitmask, - OnDragOverCallback callback) override { - NOTIMPLEMENTED(); - } - void OnDragLeave(Id window) override { NOTIMPLEMENTED(); } - void OnCompleteDrop(Id window, - uint32_t key_state, - const gfx::Point& position, - uint32_t effect_bitmask, - OnCompleteDropCallback callback) override { - NOTIMPLEMENTED(); - } - - void OnPerformDragDropCompleted(uint32_t change_id, - bool success, - uint32_t action_taken) override { - NOTIMPLEMENTED(); - } - - void OnDragDropDone() override { NOTIMPLEMENTED(); } - - void OnChangeCompleted(uint32_t change_id, bool success) override { - if (waiting_change_id_ == change_id && change_completed_run_loop_) { - on_change_completed_result_ = success; - change_completed_run_loop_->Quit(); - } - } - void RequestClose(Id window_id) override {} - void GetWindowManager(mojo::AssociatedInterfaceRequest<mojom::WindowManager> - internal) override { - window_manager_binding_ = - std::make_unique<mojo::AssociatedBinding<mojom::WindowManager>>( - this, std::move(internal)); - tree_->GetWindowManagerClient(MakeRequest(&window_manager_client_)); - } - void GetScreenProviderObserver( - mojom::ScreenProviderObserverAssociatedRequest observer) override { - // GetScreenProviderObserver() is only called in ws2. - NOTREACHED(); - } - - // mojom::WindowManager: - void OnConnect() override {} - void WmOnAcceleratedWidgetForDisplay( - int64_t display, - gpu::SurfaceHandle surface_handle) override {} - void WmNewDisplayAdded( - const display::Display& display, - mojom::WindowDataPtr root_data, - bool drawn, - const base::Optional<viz::LocalSurfaceId>& local_surface_id) override { - NOTIMPLEMENTED(); - } - void WmDisplayRemoved(int64_t display_id) override { NOTIMPLEMENTED(); } - void WmDisplayModified(const display::Display& display) override { - NOTIMPLEMENTED(); - } - void WmSetBounds(uint32_t change_id, - Id window_id, - const gfx::Rect& bounds) override { - window_manager_client_->WmResponse(change_id, false); - } - void WmSetProperty( - uint32_t change_id, - Id window_id, - const std::string& name, - const base::Optional<std::vector<uint8_t>>& value) override { - window_manager_client_->WmResponse(change_id, false); - } - void WmSetModalType(Id window_id, ui::ModalType type) override {} - void WmSetCanFocus(Id window_id, bool can_focus) override {} - void WmCreateTopLevelWindow( - uint32_t change_id, - const viz::FrameSinkId& frame_sink_id, - const base::flat_map<std::string, std::vector<uint8_t>>& properties) - override { - NOTIMPLEMENTED(); - } - void WmClientJankinessChanged(ClientSpecificId client_id, - bool janky) override { - NOTIMPLEMENTED(); - } - void WmBuildDragImage(const gfx::Point& screen_location, - const gfx::ImageSkia& drag_image, - const gfx::Vector2d& drag_image_offset, - ui::mojom::PointerKind source) override {} - void WmMoveDragImage(const gfx::Point& screen_location, - WmMoveDragImageCallback callback) override { - std::move(callback).Run(); - } - void WmDestroyDragImage() override {} - void WmPerformMoveLoop(uint32_t change_id, - Id window_id, - mojom::MoveLoopSource source, - const gfx::Point& cursor_location) override { - NOTIMPLEMENTED(); - } - void WmCancelMoveLoop(uint32_t change_id) override { NOTIMPLEMENTED(); } - void WmDeactivateWindow(Id window_id) override { NOTIMPLEMENTED(); } - void WmStackAbove(uint32_t change_id, Id above_id, Id below_id) override { - NOTIMPLEMENTED(); - } - void WmStackAtTop(uint32_t change_id, Id window_id) override { - NOTIMPLEMENTED(); - } - void WmPerformWmAction(Id window_id, const std::string& action) override { - NOTIMPLEMENTED(); - } - void OnAccelerator(uint32_t ack_id, - uint32_t accelerator_id, - std::unique_ptr<ui::Event> event) override { - NOTIMPLEMENTED(); - } - void OnCursorTouchVisibleChanged(bool enabled) override { NOTIMPLEMENTED(); } - void OnEventBlockedByModalWindow(Id window_id) override { NOTIMPLEMENTED(); } - - TestChangeTracker tracker_; - - mojom::WindowTreePtr tree_; - - // If non-null we're waiting for OnEmbed() using this RunLoop. - std::unique_ptr<base::RunLoop> embed_run_loop_; - - // If non-null we're waiting for a certain number of change notifications to - // be encountered. - std::unique_ptr<WaitState> wait_state_; - - mojo::Binding<WindowTreeClient> binding_; - Id root_window_id_; - uint32_t next_change_id_; - uint32_t waiting_change_id_; - bool on_change_completed_result_; - bool track_root_bounds_changes_; - std::unique_ptr<base::RunLoop> change_completed_run_loop_; - - std::unique_ptr<mojo::AssociatedBinding<mojom::WindowManager>> - window_manager_binding_; - mojom::WindowManagerClientAssociatedPtr window_manager_client_; - - DISALLOW_COPY_AND_ASSIGN(TestWindowTreeClient); -}; - -// ----------------------------------------------------------------------------- - -// InterfaceFactory for vending TestWindowTreeClients. -class WindowTreeClientFactory { - public: - WindowTreeClientFactory() {} - ~WindowTreeClientFactory() {} - - // Runs a nested MessageLoop until a new instance has been created. - std::unique_ptr<TestWindowTreeClient> WaitForInstance() { - if (!client_impl_.get()) { - DCHECK(!run_loop_); - run_loop_ = std::make_unique<base::RunLoop>(); - run_loop_->Run(); - run_loop_.reset(); - } - return std::move(client_impl_); - } - - void BindWindowTreeClientRequest( - mojom::WindowTreeClientRequest request) { - client_impl_ = std::make_unique<TestWindowTreeClient>(); - client_impl_->Bind(std::move(request)); - if (run_loop_.get()) - run_loop_->Quit(); - } - - private: - std::unique_ptr<TestWindowTreeClient> client_impl_; - std::unique_ptr<base::RunLoop> run_loop_; - - DISALLOW_COPY_AND_ASSIGN(WindowTreeClientFactory); -}; - -} // namespace - -class WindowTreeClientTest : public WindowServerServiceTestBase { - public: - WindowTreeClientTest() : root_window_id_(0) {} - - ~WindowTreeClientTest() override {} - - protected: - // Returns the changes from the various clients. - std::vector<Change>* changes1() { return wt_client1_->tracker()->changes(); } - std::vector<Change>* changes2() { return wt_client2_->tracker()->changes(); } - std::vector<Change>* changes3() { return wt_client3_->tracker()->changes(); } - - // Various clients. |wt1()|, being the first client, has special permissions - // (it's treated as the window manager). - WindowTree* wt1() { return wt_client1_->tree(); } - WindowTree* wt2() { return wt_client2_->tree(); } - WindowTree* wt3() { return wt_client3_->tree(); } - - TestWindowTreeClient* wt_client1() { return wt_client1_.get(); } - TestWindowTreeClient* wt_client2() { return wt_client2_.get(); } - TestWindowTreeClient* wt_client3() { return wt_client3_.get(); } - - Id root_window_id() const { return root_window_id_; } - - int client_id_1() const { return client_id_1_; } - int client_id_2() const { return client_id_2_; } - int client_id_3() const { return client_id_3_; } - - void EstablishSecondClientWithRoot(Id root_id) { - ASSERT_TRUE(wt_client2_.get() == nullptr); - wt_client2_ = EstablishClientViaEmbed(wt1(), root_id); - ASSERT_GT(client_id_2_, 0); - ASSERT_TRUE(wt_client2_.get() != nullptr); - } - - void EstablishSecondClient(bool create_initial_window) { - Id window_1_1 = 0; - if (create_initial_window) { - window_1_1 = wt_client1()->NewWindow(1); - ASSERT_TRUE(window_1_1); - } - ASSERT_NO_FATAL_FAILURE( - EstablishSecondClientWithRoot(BuildWindowId(client_id_1(), 1))); - - if (create_initial_window) { - // window_1_1 is created by wt_client1() so its client_id part should be - // client_id_1() in wt_client2. - EXPECT_EQ( - "[" + - WindowParentToString( - BuildWindowId(client_id_1(), - ClientWindowIdFromTransportId(window_1_1)), - kNullParentId) + - "]", - ChangeWindowDescription(*changes2())); - } - } - - void EstablishThirdClient(WindowTree* owner, Id root_id) { - ASSERT_TRUE(wt_client3_.get() == nullptr); - wt_client3_ = EstablishClientViaEmbed(owner, root_id); - ASSERT_TRUE(wt_client3_.get() != nullptr); - } - - std::unique_ptr<TestWindowTreeClient> WaitForWindowTreeClient() { - return client_factory_->WaitForInstance(); - } - - // Establishes a new client by way of Embed() on the specified WindowTree. - std::unique_ptr<TestWindowTreeClient> EstablishClientViaEmbed( - WindowTree* owner, - Id root_id) { - return EstablishClientViaEmbedWithPolicyBitmask(owner, root_id); - } - - std::unique_ptr<TestWindowTreeClient> - EstablishClientViaEmbedWithPolicyBitmask(WindowTree* owner, Id root_id) { - if (!EmbedUrl(connector(), owner, test_name(), root_id)) { - ADD_FAILURE() << "Embed() failed"; - return nullptr; - } - std::unique_ptr<TestWindowTreeClient> client = - client_factory_->WaitForInstance(); - if (!client.get()) { - ADD_FAILURE() << "WaitForInstance failed"; - return nullptr; - } - client->WaitForOnEmbed(); - - // TODO(fsamuel): Currently the FrameSinkId maps directly to the server's - // window ID. This is likely bad from a security perspective and should be - // fixed. - EXPECT_EQ("OnEmbed", - SingleChangeToDescription(*client->tracker()->changes())); - return client; - } - - // WindowServerServiceTestBase: - void OnBindInterface(const service_manager::BindSourceInfo& source_info, - const std::string& interface_name, - mojo::ScopedMessagePipeHandle interface_pipe) override { - registry_.BindInterface(interface_name, std::move(interface_pipe)); - } - - void SetUp() override { - client_factory_ = std::make_unique<WindowTreeClientFactory>(); - registry_.AddInterface( - base::Bind(&WindowTreeClientFactory::BindWindowTreeClientRequest, - base::Unretained(client_factory_.get()))); - - WindowServerServiceTestBase::SetUp(); - - mojom::WindowTreeHostFactoryPtr factory; - connector()->BindInterface(ui::mojom::kServiceName, &factory); - - mojom::WindowTreeClientPtr tree_client_ptr; - wt_client1_ = std::make_unique<TestWindowTreeClient>(); - wt_client1_->Bind(MakeRequest(&tree_client_ptr)); - - factory->CreateWindowTreeHost(MakeRequest(&host_), - std::move(tree_client_ptr)); - - // Next we should get an embed call on the "window manager" client. - wt_client1_->WaitForOnEmbed(); - - ASSERT_EQ(1u, changes1()->size()); - EXPECT_EQ(CHANGE_TYPE_EMBED, (*changes1())[0].type); - ASSERT_FALSE((*changes1())[0].windows.empty()); - root_window_id_ = (*changes1())[0].windows[0].window_id; - ASSERT_EQ(root_window_id_, wt_client1_->root_window_id()); - changes1()->clear(); - } - - void TearDown() override { - // Destroy these before the message loop is destroyed (happens in - // WindowServerServiceTestBase::TearDown). - wt_client1_.reset(); - wt_client2_.reset(); - wt_client3_.reset(); - client_factory_.reset(); - WindowServerServiceTestBase::TearDown(); - } - - std::unique_ptr<TestWindowTreeClient> wt_client1_; - std::unique_ptr<TestWindowTreeClient> wt_client2_; - std::unique_ptr<TestWindowTreeClient> wt_client3_; - - mojom::WindowTreeHostPtr host_; - - private: - std::unique_ptr<WindowTreeClientFactory> client_factory_; - int client_id_1_ = kWindowServerClientId + 1; - int client_id_2_ = client_id_1_ + 1; - int client_id_3_ = client_id_2_ + 1; - Id root_window_id_; - service_manager::BinderRegistry registry_; - - DISALLOW_COPY_AND_ASSIGN(WindowTreeClientTest); -}; - -// Verifies two clients get different ids. -TEST_F(WindowTreeClientTest, TwoClientsGetDifferentClientIds) { - ASSERT_NO_FATAL_FAILURE(EstablishSecondClient(true)); - - ASSERT_EQ(1u, changes2()->size()); - ASSERT_NE(client_id_1(), client_id_2()); -} - -// Verifies when Embed() is invoked any child windows are removed. -TEST_F(WindowTreeClientTest, WindowsRemovedWhenEmbedding) { - // Two windows 1 and 2. 2 is parented to 1. - Id window_1_1 = wt_client1()->NewWindow(1); - ASSERT_TRUE(window_1_1); - ASSERT_TRUE(wt_client1()->AddWindow(root_window_id(), window_1_1)); - - Id window_1_2 = wt_client1()->NewWindow(2); - ASSERT_TRUE(window_1_2); - ASSERT_TRUE(wt_client1()->AddWindow(window_1_1, window_1_2)); - - ASSERT_NO_FATAL_FAILURE(EstablishSecondClient(false)); - ASSERT_EQ(1u, changes2()->size()); - ASSERT_EQ(1u, (*changes2())[0].windows.size()); - // window_1_1 has a client_id part of client_id_1 in wt2. - Id window11_in_wt2 = - BuildWindowId(client_id_1(), ClientWindowIdFromTransportId(window_1_1)); - EXPECT_EQ("[" + WindowParentToString(window11_in_wt2, kNullParentId) + "]", - ChangeWindowDescription(*changes2())); - - // Embed() removed window 2. - { - std::vector<TestWindow> windows; - GetWindowTree(wt1(), window_1_2, &windows); - EXPECT_EQ(WindowParentToString(window_1_2, kNullParentId), - SingleWindowDescription(windows)); - } - - // ws2 should not see window 2. - { - std::vector<TestWindow> windows; - GetWindowTree(wt2(), window11_in_wt2, &windows); - EXPECT_EQ(WindowParentToString(window11_in_wt2, kNullParentId), - SingleWindowDescription(windows)); - } - { - std::vector<TestWindow> windows; - GetWindowTree(wt2(), window_1_2, &windows); - EXPECT_TRUE(windows.empty()); - } - - // Windows 3 and 4 in client 2. - Id window_2_3 = wt_client2()->NewWindow(3); - Id window_2_4 = wt_client2()->NewWindow(4); - ASSERT_TRUE(window_2_3); - ASSERT_TRUE(window_2_4); - ASSERT_TRUE(wt_client2()->AddWindow(window_2_3, window_2_4)); - - // Client 3 rooted at 2. - ASSERT_NO_FATAL_FAILURE(EstablishThirdClient(wt2(), window_2_3)); - - // Window 4 should no longer have a parent. - { - std::vector<TestWindow> windows; - GetWindowTree(wt2(), window_2_3, &windows); - EXPECT_EQ(WindowParentToString(window_2_3, kNullParentId), - SingleWindowDescription(windows)); - - windows.clear(); - GetWindowTree(wt2(), window_2_4, &windows); - EXPECT_EQ(WindowParentToString(window_2_4, kNullParentId), - SingleWindowDescription(windows)); - } - - // And window 4 should not be visible to client 3. - { - std::vector<TestWindow> windows; - GetWindowTree(wt3(), window_2_3, &windows); - EXPECT_EQ("no windows", SingleWindowDescription(windows)); - } -} - -// Verifies once Embed() has been invoked the parent client can't see any -// children. -TEST_F(WindowTreeClientTest, CantAccessChildrenOfEmbeddedWindow) { - ASSERT_NO_FATAL_FAILURE(EstablishSecondClient(true)); - - Id window_1_1 = BuildWindowId(client_id_1(), 1); - Id window_2_2 = wt_client2()->NewWindow(2); - ASSERT_TRUE(window_2_2); - ASSERT_TRUE(wt_client2()->AddWindow(window_1_1, window_2_2)); - - ASSERT_NO_FATAL_FAILURE(EstablishThirdClient(wt2(), window_2_2)); - - Id window_3_3 = wt_client3()->NewWindow(3); - ASSERT_TRUE(window_3_3); - ASSERT_TRUE( - wt_client3()->AddWindow(wt_client3()->root_window_id(), window_3_3)); - - // Even though 3 is a child of 2 client 2 can't see 3 as it's from a - // different client. - { - std::vector<TestWindow> windows; - GetWindowTree(wt2(), window_2_2, &windows); - EXPECT_EQ(WindowParentToString(window_2_2, window_1_1), - SingleWindowDescription(windows)); - } - - // Client 2 shouldn't be able to get window 3 at all. - { - std::vector<TestWindow> windows; - GetWindowTree(wt2(), window_3_3, &windows); - EXPECT_TRUE(windows.empty()); - } - - // Client 1 should be able to see it all (its the root). - { - std::vector<TestWindow> windows; - GetWindowTree(wt1(), window_1_1, &windows); - ASSERT_EQ(3u, windows.size()); - // window_1_1 is created by wt1() so client_id part would be 0 in wt1(). - EXPECT_EQ(WindowParentToString(ClientWindowIdFromTransportId(window_1_1), - kNullParentId), - windows[0].ToString()); - // NOTE: we expect a match of WindowParentToString(window_2_2, window_1_1), - // but the ids are in the id space of client2, which is not the same as - // the id space of wt1(). - EXPECT_EQ("window=" + std::to_string(client_id_2()) + ",2 parent=0,1", - windows[1].ToString()); - // Same thing here, we really want to test for - // WindowParentToString(window_3_3, window_2_2). - EXPECT_EQ("window=" + std::to_string(client_id_3()) + - ",3 parent=" + std::to_string(client_id_2()) + ",2", - windows[2].ToString()); - } -} - -// Verifies once Embed() has been invoked the parent can't mutate the children. -TEST_F(WindowTreeClientTest, CantModifyChildrenOfEmbeddedWindow) { - ASSERT_NO_FATAL_FAILURE(EstablishSecondClient(true)); - - Id window_1_1 = BuildWindowId(client_id_1(), 1); - Id window_2_1 = wt_client2()->NewWindow(1); - ASSERT_TRUE(window_2_1); - ASSERT_TRUE(wt_client2()->AddWindow(window_1_1, window_2_1)); - - ASSERT_NO_FATAL_FAILURE(EstablishThirdClient(wt2(), window_2_1)); - - Id window_2_2 = wt_client2()->NewWindow(2); - ASSERT_TRUE(window_2_2); - // Client 2 shouldn't be able to add anything to the window anymore. - ASSERT_FALSE(wt_client2()->AddWindow(window_2_1, window_2_2)); - - // Create window 3 in client 3 and add it to window 3. - Id window_3_1 = wt_client3()->NewWindow(1); - ASSERT_TRUE(window_3_1); - // window_2_1 should have a client_id of client_id_2 in wt_client3. - ASSERT_TRUE(wt_client3()->AddWindow( - BuildWindowId(client_id_2(), ClientWindowIdFromTransportId(window_2_1)), - window_3_1)); - - // Client 2 shouldn't be able to remove window 3. - ASSERT_FALSE(wt_client2()->RemoveWindowFromParent( - BuildWindowId(client_id_3(), ClientWindowIdFromTransportId(window_3_1)))); -} - -// Verifies client gets a valid id. -TEST_F(WindowTreeClientTest, NewWindow) { - Id window_1_1 = wt_client1()->NewWindow(1); - ASSERT_TRUE(window_1_1); - EXPECT_TRUE(changes1()->empty()); - - // Can't create a window with the same id. - ASSERT_EQ(0u, wt_client1()->NewWindowWithCompleteId(window_1_1)); - EXPECT_TRUE(changes1()->empty()); - - // Can't create a window with a bogus client id. - ASSERT_EQ(0u, wt_client1()->NewWindowWithCompleteId( - BuildWindowId(client_id_1() + 1, 1))); - EXPECT_TRUE(changes1()->empty()); -} - -// Verifies AddWindow fails when window is already in position. -TEST_F(WindowTreeClientTest, AddWindowWithNoChange) { - // Create the embed point now so that the ids line up. - ASSERT_TRUE(wt_client1()->NewWindow(1)); - Id window_1_21 = wt_client1()->NewWindow(21); - Id window_1_31 = wt_client1()->NewWindow(31); - ASSERT_TRUE(window_1_21); - ASSERT_TRUE(window_1_31); - - ASSERT_NO_FATAL_FAILURE(EstablishSecondClient(false)); - - // Make 3 a child of 2. - ASSERT_TRUE(wt_client1()->AddWindow(window_1_21, window_1_31)); - - // Try again, this should fail. - EXPECT_FALSE(wt_client1()->AddWindow(window_1_21, window_1_31)); -} - -// Verifies AddWindow fails when window is already in position. -TEST_F(WindowTreeClientTest, AddAncestorFails) { - // Create the embed point now so that the ids line up. - ASSERT_TRUE(wt_client1()->NewWindow(1)); - Id window_1_21 = wt_client1()->NewWindow(21); - Id window_1_31 = wt_client1()->NewWindow(31); - ASSERT_TRUE(window_1_21); - ASSERT_TRUE(window_1_31); - - ASSERT_NO_FATAL_FAILURE(EstablishSecondClient(false)); - - // Make 3 a child of 2. - ASSERT_TRUE(wt_client1()->AddWindow(window_1_21, window_1_31)); - - // Try to make 2 a child of 3, this should fail since 2 is an ancestor of 3. - EXPECT_FALSE(wt_client1()->AddWindow(window_1_31, window_1_21)); -} - -// Verifies adding to root sends right notifications. -TEST_F(WindowTreeClientTest, AddToRoot) { - // Create the embed point now so that the ids line up. - Id window_1_1 = wt_client1()->NewWindow(1); - ASSERT_TRUE(window_1_1); - Id window_1_21 = wt_client1()->NewWindow(21); - Id window_1_31 = wt_client1()->NewWindow(31); - ASSERT_TRUE(window_1_21); - ASSERT_TRUE(window_1_31); - - ASSERT_NO_FATAL_FAILURE(EstablishSecondClient(false)); - changes2()->clear(); - - // Make 3 a child of 21. - ASSERT_TRUE(wt_client1()->AddWindow(window_1_21, window_1_31)); - - // Make 21 a child of 1. - ASSERT_TRUE(wt_client1()->AddWindow(window_1_1, window_1_21)); - - // Client 2 should not be told anything (because the window is from a - // different client). Create a window to ensure we got a response from - // the server. - ASSERT_TRUE(wt_client2()->NewWindow(100)); - EXPECT_TRUE(changes2()->empty()); -} - -// Verifies HierarchyChanged is correctly sent for various adds/removes. -TEST_F(WindowTreeClientTest, WindowHierarchyChangedWindows) { - // Create the embed point now so that the ids line up. - Id window_1_1 = wt_client1()->NewWindow(1); - // client_id_1(),2->client_id_1(),11. - Id window_1_2 = wt_client1()->NewWindow(2); - ASSERT_TRUE(window_1_2); - ASSERT_TRUE(wt_client1()->SetWindowVisibility(window_1_2, true)); - Id window_1_11 = wt_client1()->NewWindow(11); - ASSERT_TRUE(window_1_11); - ASSERT_TRUE(wt_client1()->SetWindowVisibility(window_1_11, true)); - ASSERT_TRUE(wt_client1()->AddWindow(window_1_2, window_1_11)); - - ASSERT_NO_FATAL_FAILURE(EstablishSecondClient(false)); - ASSERT_TRUE(wt_client1()->SetWindowVisibility(window_1_1, true)); - - ASSERT_TRUE(wt_client2()->WaitForAllMessages()); - changes2()->clear(); - - // window_1_1 has a client_id part of client_id_1 in wt2. - Id window11_in_wt2 = - BuildWindowId(client_id_1(), ClientWindowIdFromTransportId(window_1_1)); - - // client_id_1(),1->client_id_1(),2->client_id_1(),11 - { - // Client 2 should not get anything (client_id_1(),2 is from another - // client). - ASSERT_TRUE(wt_client1()->AddWindow(window_1_1, window_1_2)); - ASSERT_TRUE(wt_client2()->WaitForAllMessages()); - EXPECT_TRUE(changes2()->empty()); - } - - // 0,1->client_id_1(),1->client_id_1(),2->client_id_1(),11. - { - // Client 2 is now connected to the root, so it should have gotten a drawn - // notification. - ASSERT_TRUE(wt_client1()->AddWindow(root_window_id(), window_1_1)); - wt_client2_->WaitForChangeCount(1u); - EXPECT_EQ("DrawnStateChanged window=" + IdToString(window11_in_wt2) + - " drawn=true", - SingleChangeToDescription(*changes2())); - } - - // client_id_1(),1->client_id_1(),2->client_id_1(),11. - { - // Client 2 is no longer connected to the root, should get drawn state - // changed. - changes2()->clear(); - ASSERT_TRUE(wt_client1()->RemoveWindowFromParent(window_1_1)); - wt_client2_->WaitForChangeCount(1); - EXPECT_EQ("DrawnStateChanged window=" + IdToString(window11_in_wt2) + - " drawn=false", - SingleChangeToDescription(*changes2())); - } - - // client_id_1(),1->client_id_1(),2->client_id_1(),11->client_id_1(),111. - Id window_1_111 = wt_client1()->NewWindow(111); - ASSERT_TRUE(window_1_111); - ASSERT_TRUE(wt_client1()->SetWindowVisibility(window_1_111, true)); - { - changes2()->clear(); - ASSERT_TRUE(wt_client1()->AddWindow(window_1_11, window_1_111)); - ASSERT_TRUE(wt_client2()->WaitForAllMessages()); - EXPECT_TRUE(changes2()->empty()); - } - - // 0,1->client_id_1(),1->client_id_1(),2->client_id_1(),11->client_id_1(),111 - { - changes2()->clear(); - ASSERT_TRUE(wt_client1()->AddWindow(root_window_id(), window_1_1)); - wt_client2_->WaitForChangeCount(1); - EXPECT_EQ("DrawnStateChanged window=" + IdToString(window11_in_wt2) + - " drawn=true", - SingleChangeToDescription(*changes2())); - } -} - -TEST_F(WindowTreeClientTest, WindowHierarchyChangedAddingKnownToUnknown) { - // Create the following structure: root -> 1 -> 11 and 2->21 (2 has no - // parent). - ASSERT_NO_FATAL_FAILURE(EstablishSecondClient(true)); - Id window_1_1 = BuildWindowId(client_id_1(), 1); - - Id window_2_11 = wt_client2()->NewWindow(11); - Id window_2_2 = wt_client2()->NewWindow(2); - Id window_2_21 = wt_client2()->NewWindow(21); - ASSERT_TRUE(window_2_11); - ASSERT_TRUE(window_2_2); - ASSERT_TRUE(window_2_21); - // window_1_1 has a client_id part of 0 in wt1, while window_2_2 has that of - // client_id_2. - Id window11_in_wt1 = ClientWindowIdFromTransportId(window_1_1); - Id window22_in_wt1 = - BuildWindowId(client_id_2(), ClientWindowIdFromTransportId(window_2_2)); - - // Set up the hierarchy. - ASSERT_TRUE(wt_client1()->AddWindow(root_window_id(), window_1_1)); - ASSERT_TRUE(wt_client2()->AddWindow(window_1_1, window_2_11)); - ASSERT_TRUE(wt_client2()->AddWindow(window_2_2, window_2_21)); - - // Remove 11, should result in a hierarchy change for the root. - { - changes1()->clear(); - ASSERT_TRUE(wt_client2()->RemoveWindowFromParent(window_2_11)); - - wt_client1_->WaitForChangeCount(1); - // client_id_2(),1 should be IdToString(window_2_11), but window_2_11 is in - // the id space of client2, not client1. - EXPECT_EQ("HierarchyChanged window=" + std::to_string(client_id_2()) + - ",11 old_parent=" + IdToString(window11_in_wt1) + - " new_parent=null", - SingleChangeToDescription(*changes1())); - } - - // Add 2 to 1. - { - changes1()->clear(); - ASSERT_TRUE(wt_client2()->AddWindow(window_1_1, window_2_2)); - wt_client1_->WaitForChangeCount(1); - EXPECT_EQ("HierarchyChanged window=" + IdToString(window22_in_wt1) + - " old_parent=null new_parent=" + IdToString(window11_in_wt1), - SingleChangeToDescription(*changes1())); - // "window=client_id_2(),3 parent=client_id_2(),2]" should be, - // WindowParentToString(window_2_21, window_2_2), but isn't because of - // differing id spaces. - EXPECT_EQ("[" + WindowParentToString(window22_in_wt1, window11_in_wt1) + - "],[window=" + std::to_string(client_id_2()) + - ",21 parent=" + std::to_string(client_id_2()) + ",2]", - ChangeWindowDescription(*changes1())); - } -} - -TEST_F(WindowTreeClientTest, ReorderWindow) { - ASSERT_NO_FATAL_FAILURE(EstablishSecondClient(true)); - - Id window_2_1 = wt_client2()->NewWindow(1); - Id window_2_2 = wt_client2()->NewWindow(2); - Id window_2_3 = wt_client2()->NewWindow(3); - Id window_1_4 = wt_client1()->NewWindow(4); // Peer to client_id_1(),1 - Id window_1_5 = wt_client1()->NewWindow(5); // Peer to client_id_1(),1 - Id window_2_6 = wt_client2()->NewWindow(6); // Child of client_id_1(),2. - Id window_2_7 = wt_client2()->NewWindow(7); // Unparented. - Id window_2_8 = wt_client2()->NewWindow(8); // Unparented. - ASSERT_TRUE(window_2_1); - ASSERT_TRUE(window_2_2); - ASSERT_TRUE(window_2_3); - ASSERT_TRUE(window_1_4); - ASSERT_TRUE(window_1_5); - ASSERT_TRUE(window_2_6); - ASSERT_TRUE(window_2_7); - ASSERT_TRUE(window_2_8); - - ASSERT_TRUE(wt_client2()->AddWindow(window_2_1, window_2_2)); - ASSERT_TRUE(wt_client2()->AddWindow(window_2_2, window_2_6)); - ASSERT_TRUE(wt_client2()->AddWindow(window_2_1, window_2_3)); - ASSERT_TRUE(wt_client1()->AddWindow(root_window_id(), window_1_4)); - ASSERT_TRUE(wt_client1()->AddWindow(root_window_id(), window_1_5)); - ASSERT_TRUE( - wt_client2()->AddWindow(BuildWindowId(client_id_1(), 1), window_2_1)); - - // window_2_* has client_id part of client_id_2 in wt1. - Id window22_in_wt1 = - BuildWindowId(client_id_2(), ClientWindowIdFromTransportId(window_2_2)); - Id window23_in_wt1 = - BuildWindowId(client_id_2(), ClientWindowIdFromTransportId(window_2_3)); - Id window26_in_wt1 = - BuildWindowId(client_id_2(), ClientWindowIdFromTransportId(window_2_6)); - Id window27_in_wt1 = - BuildWindowId(client_id_2(), ClientWindowIdFromTransportId(window_2_7)); - Id window28_in_wt1 = - BuildWindowId(client_id_2(), ClientWindowIdFromTransportId(window_2_8)); - - { - changes1()->clear(); - ASSERT_TRUE(wt_client2()->ReorderWindow(window_2_2, window_2_3, - mojom::OrderDirection::ABOVE)); - - wt_client1_->WaitForChangeCount(1); - EXPECT_EQ("Reordered window=" + IdToString(window22_in_wt1) + " relative=" + - IdToString(window23_in_wt1) + " direction=above", - SingleChangeToDescription(*changes1())); - } - - { - changes1()->clear(); - ASSERT_TRUE(wt_client2()->ReorderWindow(window_2_2, window_2_3, - mojom::OrderDirection::BELOW)); - - wt_client1_->WaitForChangeCount(1); - EXPECT_EQ("Reordered window=" + IdToString(window22_in_wt1) + " relative=" + - IdToString(window23_in_wt1) + " direction=below", - SingleChangeToDescription(*changes1())); - } - - // view2 is already below view3. - EXPECT_FALSE(wt_client2()->ReorderWindow(window_2_2, window_2_3, - mojom::OrderDirection::BELOW)); - - // view4 & 5 are unknown to client 2. - EXPECT_FALSE(wt_client2()->ReorderWindow(window_1_4, window_1_5, - mojom::OrderDirection::ABOVE)); - - // view6 & view3 have different parents. - EXPECT_FALSE(wt_client1()->ReorderWindow(window23_in_wt1, window26_in_wt1, - mojom::OrderDirection::ABOVE)); - - // Non-existent window-ids - EXPECT_FALSE(wt_client1()->ReorderWindow(BuildWindowId(client_id_1(), 27), - BuildWindowId(client_id_1(), 28), - mojom::OrderDirection::ABOVE)); - - // view7 & view8 are un-parented. - EXPECT_FALSE(wt_client1()->ReorderWindow(window27_in_wt1, window28_in_wt1, - mojom::OrderDirection::ABOVE)); -} - -// Verifies DeleteWindow works. -TEST_F(WindowTreeClientTest, DeleteWindow) { - ASSERT_NO_FATAL_FAILURE(EstablishSecondClient(true)); - Id window_1_1 = BuildWindowId(client_id_1(), 1); - Id window_2_1 = wt_client2()->NewWindow(1); - ASSERT_TRUE(window_2_1); - // window_2_1 is not created by wt1 so its client_id part is client_id_2, - // while window_1_1 would have 0 for the client_id part. - Id window21_in_wt1 = - BuildWindowId(client_id_2(), ClientWindowIdFromTransportId(window_2_1)); - - // Make 2 a child of 1. - { - changes1()->clear(); - ASSERT_TRUE(wt_client2()->AddWindow(window_1_1, window_2_1)); - wt_client1_->WaitForChangeCount(1); - EXPECT_EQ("HierarchyChanged window=" + IdToString(window21_in_wt1) + - " old_parent=null new_parent=" + - IdToString(ClientWindowIdFromTransportId(window_1_1)), - SingleChangeToDescription(*changes1())); - } - - // Delete 2. - { - changes1()->clear(); - changes2()->clear(); - ASSERT_TRUE(wt_client2()->DeleteWindow(window_2_1)); - EXPECT_TRUE(changes2()->empty()); - - wt_client1_->WaitForChangeCount(1); - EXPECT_EQ("WindowDeleted window=" + IdToString(window21_in_wt1), - SingleChangeToDescription(*changes1())); - } -} - -// Verifies DeleteWindow() on the root suceeds. -TEST_F(WindowTreeClientTest, DeleteRoot) { - ASSERT_NO_FATAL_FAILURE(EstablishSecondClient(true)); - Id window_1_1 = BuildWindowId(client_id_1(), 1); - EXPECT_TRUE(wt_client2()->DeleteWindow(window_1_1)); - // Client1 should get OnEmbeddedAppDisconnected(). - wt_client1_->WaitForChangeCount(1); - // window_1_1 should have client_id of 0 in wt_client1 because it's created - // by wt_client1. - EXPECT_EQ("OnEmbeddedAppDisconnected window=" + - IdToString(ClientWindowIdFromTransportId(window_1_1)), - SingleChangeToDescription(*changes1())); - - // Create a new window and try adding to |window_1_1| from client 2, should - // fail as client 2 no longer knows about |window_1_1|. - Id window_2_1 = wt_client2()->NewWindow(1); - ASSERT_TRUE(window_2_1); - EXPECT_FALSE(wt_client2()->AddWindow(window_1_1, window_2_1)); -} - -// Verifies DeleteWindow() on the root suceeds. -TEST_F(WindowTreeClientTest, DeleteRootWithChildren) { - ASSERT_NO_FATAL_FAILURE(EstablishSecondClient(true)); - Id window_1_1 = BuildWindowId(client_id_1(), 1); - Id window_2_1 = wt_client2()->NewWindow(1); - ASSERT_TRUE(window_2_1); - ASSERT_TRUE(wt_client2()->AddWindow(window_1_1, window_2_1)); - changes2()->clear(); - EXPECT_TRUE(wt_client2()->DeleteWindow(window_1_1)); - // DeleteWindow() should not result in any calls to client 2. - EXPECT_TRUE(changes2()->empty()); - - // Create a new window parented to 2_1. Should work as 2_1 is still valid. - Id window_2_2 = wt_client2()->NewWindow(2); - ASSERT_TRUE(window_2_2); - ASSERT_TRUE(wt_client2()->AddWindow(window_2_1, window_2_2)); -} - -// Verifies DeleteWindow isn't allowed from a separate client. -TEST_F(WindowTreeClientTest, DeleteWindowFromAnotherClientDisallowed) { - ASSERT_NO_FATAL_FAILURE(EstablishSecondClient(true)); - // This id is unknown, so deletion should fail. - EXPECT_FALSE(wt_client2()->DeleteWindow(BuildWindowId(client_id_1(), 2))); -} - -// Verifies if a window was deleted and then reused that other clients are -// properly notified. -TEST_F(WindowTreeClientTest, ReuseDeletedWindowId) { - ASSERT_NO_FATAL_FAILURE(EstablishSecondClient(true)); - Id window_1_1 = BuildWindowId(client_id_1(), 1); - Id window_2_1 = wt_client2()->NewWindow(1); - ASSERT_TRUE(window_2_1); - - // wt1 created window_1_1 but not window_2_1. - Id window11_in_wt1 = ClientWindowIdFromTransportId(window_1_1); - Id window21_in_wt1 = - BuildWindowId(client_id_2(), ClientWindowIdFromTransportId(window_2_1)); - - // Add 2 to 1. - { - changes1()->clear(); - ASSERT_TRUE(wt_client2()->AddWindow(window_1_1, window_2_1)); - wt_client1_->WaitForChangeCount(1); - EXPECT_EQ("HierarchyChanged window=" + IdToString(window21_in_wt1) + - " old_parent=null new_parent=" + IdToString(window11_in_wt1), - SingleChangeToDescription(*changes1())); - EXPECT_EQ( - "[" + WindowParentToString(window21_in_wt1, window11_in_wt1) + "]", - ChangeWindowDescription(*changes1())); - } - - // Delete 2. - { - changes1()->clear(); - ASSERT_TRUE(wt_client2()->DeleteWindow(window_2_1)); - - wt_client1_->WaitForChangeCount(1); - EXPECT_EQ("WindowDeleted window=" + IdToString(window21_in_wt1), - SingleChangeToDescription(*changes1())); - } - - // Create 2 again, and add it back to 1. Should get the same notification. - window_2_1 = wt_client2()->NewWindow(2); - window21_in_wt1 = BuildWindowId(ClientIdFromTransportId(window21_in_wt1), - ClientWindowIdFromTransportId(window_2_1)); - ASSERT_TRUE(window_2_1); - { - changes1()->clear(); - ASSERT_TRUE(wt_client2()->AddWindow(window_1_1, window_2_1)); - - wt_client1_->WaitForChangeCount(1); - EXPECT_EQ("HierarchyChanged window=" + IdToString(window21_in_wt1) + - " old_parent=null new_parent=" + IdToString(window11_in_wt1), - SingleChangeToDescription(*changes1())); - EXPECT_EQ( - "[" + WindowParentToString(window21_in_wt1, window11_in_wt1) + "]", - ChangeWindowDescription(*changes1())); - } -} - -// Assertions for GetWindowTree. -TEST_F(WindowTreeClientTest, GetWindowTree) { - ASSERT_NO_FATAL_FAILURE(EstablishSecondClient(true)); - Id window_1_1 = BuildWindowId(client_id_1(), 1); - - // Create 11 in first client and make it a child of 1. - Id window_1_11 = wt_client1()->NewWindow(11); - ASSERT_TRUE(window_1_11); - ASSERT_TRUE(wt_client1()->AddWindow(root_window_id(), window_1_1)); - ASSERT_TRUE(wt_client1()->AddWindow(window_1_1, window_1_11)); - - // Create two windows in second client, 2 and 3, both children of 1. - Id window_2_1 = wt_client2()->NewWindow(1); - Id window_2_2 = wt_client2()->NewWindow(2); - ASSERT_TRUE(window_2_1); - ASSERT_TRUE(window_2_2); - ASSERT_TRUE(wt_client2()->AddWindow(window_1_1, window_2_1)); - ASSERT_TRUE(wt_client2()->AddWindow(window_1_1, window_2_2)); - - // wt1 created window_1_1 and window_1_11, but not window_2_1 and window_2_2. - Id window11_in_wt1 = ClientWindowIdFromTransportId(window_1_1); - Id window111_in_wt1 = ClientWindowIdFromTransportId(window_1_11); - Id window21_in_wt1 = - BuildWindowId(client_id_2(), ClientWindowIdFromTransportId(window_2_1)); - Id window22_in_wt1 = - BuildWindowId(client_id_2(), ClientWindowIdFromTransportId(window_2_2)); - - // Verifies GetWindowTree() on the root. The root client sees all. - { - std::vector<TestWindow> windows; - GetWindowTree(wt1(), root_window_id(), &windows); - ASSERT_EQ(5u, windows.size()); - EXPECT_EQ(WindowParentToString(root_window_id(), kNullParentId), - windows[0].ToString()); - EXPECT_EQ(WindowParentToString(window11_in_wt1, root_window_id()), - windows[1].ToString()); - EXPECT_EQ(WindowParentToString(window111_in_wt1, window11_in_wt1), - windows[2].ToString()); - EXPECT_EQ(WindowParentToString(window21_in_wt1, window11_in_wt1), - windows[3].ToString()); - EXPECT_EQ(WindowParentToString(window22_in_wt1, window11_in_wt1), - windows[4].ToString()); - } - - // Verifies GetWindowTree() on the window client_id_1(),1 from wt2(). wt2() - // sees client_id_1(),1 as client_id_1(),1 is wt2()'s root and wt2() sees all - // the windows it created. - { - std::vector<TestWindow> windows; - GetWindowTree(wt2(), window_1_1, &windows); - ASSERT_EQ(3u, windows.size()); - EXPECT_EQ(WindowParentToString(window_1_1, kNullParentId), - windows[0].ToString()); - EXPECT_EQ(WindowParentToString(window_2_1, window_1_1), - windows[1].ToString()); - EXPECT_EQ(WindowParentToString(window_2_2, window_1_1), - windows[2].ToString()); - } - - // Client 2 shouldn't be able to get the root tree. - { - std::vector<TestWindow> windows; - GetWindowTree(wt2(), root_window_id(), &windows); - ASSERT_EQ(0u, windows.size()); - } -} - -TEST_F(WindowTreeClientTest, SetWindowBounds) { - Id window_1_1 = wt_client1()->NewWindow(1); - ASSERT_TRUE(window_1_1); - ASSERT_TRUE(wt_client1()->AddWindow(root_window_id(), window_1_1)); - - ASSERT_NO_FATAL_FAILURE(EstablishSecondClient(false)); - - changes2()->clear(); - - wt_client2_->set_track_root_bounds_changes(true); - - viz::ParentLocalSurfaceIdAllocator allocator; - viz::LocalSurfaceId local_surface_id = allocator.GenerateId(); - wt1()->SetWindowBounds(10, window_1_1, gfx::Rect(0, 0, 100, 100), - local_surface_id); - ASSERT_TRUE(wt_client1()->WaitForChangeCompleted(10)); - - wt_client2_->WaitForChangeCount(1); - // window_1_1 has a client_id part of client_id_1 in wt2. - Id window11_in_wt2 = - BuildWindowId(client_id_1(), ClientWindowIdFromTransportId(window_1_1)); - EXPECT_EQ("BoundsChanged window=" + IdToString(window11_in_wt2) + - " old_bounds=0,0 0x0 new_bounds=0,0 100x100 local_surface_id=" + - local_surface_id.ToString(), - SingleChangeToDescription(*changes2())); - - // Should not be possible to change the bounds of a window created by another - // client. - wt2()->SetWindowBounds(11, window11_in_wt2, gfx::Rect(0, 0, 0, 0), - base::nullopt); - ASSERT_FALSE(wt_client2()->WaitForChangeCompleted(11)); -} - -// Verify AddWindow fails when trying to manipulate windows in other roots. -TEST_F(WindowTreeClientTest, CantMoveWindowsFromOtherRoot) { - // Create 1 and 2 in the first client. - Id window_1_1 = wt_client1()->NewWindow(1); - Id window_1_2 = wt_client1()->NewWindow(2); - ASSERT_TRUE(window_1_1); - ASSERT_TRUE(window_1_2); - - ASSERT_NO_FATAL_FAILURE(EstablishSecondClient(false)); - - // Try to move 2 to be a child of 1 from client 2. This should fail as 2 - // should not be able to access 1. - ASSERT_FALSE(wt_client2()->AddWindow(window_1_1, window_1_2)); - - // Try to reparent 1 to the root. A client is not allowed to reparent its - // roots. - ASSERT_FALSE(wt_client2()->AddWindow(root_window_id(), window_1_1)); -} - -// Verify RemoveWindowFromParent fails for windows that are descendants of the -// roots. -TEST_F(WindowTreeClientTest, CantRemoveWindowsInOtherRoots) { - // Create 1 and 2 in the first client and parent both to the root. - Id window_1_1 = wt_client1()->NewWindow(1); - Id window_1_2 = wt_client1()->NewWindow(2); - ASSERT_TRUE(window_1_1); - ASSERT_TRUE(window_1_2); - - ASSERT_TRUE(wt_client1()->AddWindow(root_window_id(), window_1_1)); - ASSERT_TRUE(wt_client1()->AddWindow(root_window_id(), window_1_2)); - - // Establish the second client and give it the root 1. - ASSERT_NO_FATAL_FAILURE(EstablishSecondClient(false)); - - // Client 2 should not be able to remove window 2 or 1 from its parent. - ASSERT_FALSE(wt_client2()->RemoveWindowFromParent(window_1_2)); - ASSERT_FALSE(wt_client2()->RemoveWindowFromParent(window_1_1)); - - // Create windows 10 and 11 in 2. - Id window_2_10 = wt_client2()->NewWindow(10); - Id window_2_11 = wt_client2()->NewWindow(11); - ASSERT_TRUE(window_2_10); - ASSERT_TRUE(window_2_11); - - // Parent 11 to 10. - ASSERT_TRUE(wt_client2()->AddWindow(window_2_10, window_2_11)); - // Remove 11 from 10. - ASSERT_TRUE(wt_client2()->RemoveWindowFromParent(window_2_11)); - - // Verify nothing was actually removed. - { - std::vector<TestWindow> windows; - GetWindowTree(wt1(), root_window_id(), &windows); - ASSERT_EQ(3u, windows.size()); - EXPECT_EQ(WindowParentToString(root_window_id(), kNullParentId), - windows[0].ToString()); - EXPECT_EQ(WindowParentToString(window_1_1, root_window_id()), - windows[1].ToString()); - EXPECT_EQ(WindowParentToString(window_1_2, root_window_id()), - windows[2].ToString()); - } -} - -// Verify GetWindowTree fails for windows that are not descendants of the roots. -TEST_F(WindowTreeClientTest, CantGetWindowTreeOfOtherRoots) { - // Create 1 and 2 in the first client and parent both to the root. - Id window_1_1 = wt_client1()->NewWindow(1); - Id window_1_2 = wt_client1()->NewWindow(2); - ASSERT_TRUE(window_1_1); - ASSERT_TRUE(window_1_2); - - ASSERT_TRUE(wt_client1()->AddWindow(root_window_id(), window_1_1)); - ASSERT_TRUE(wt_client1()->AddWindow(root_window_id(), window_1_2)); - - ASSERT_NO_FATAL_FAILURE(EstablishSecondClient(false)); - - std::vector<TestWindow> windows; - - // Should get nothing for the root. - GetWindowTree(wt2(), root_window_id(), &windows); - ASSERT_TRUE(windows.empty()); - - // Should get nothing for window 2. - GetWindowTree(wt2(), window_1_2, &windows); - ASSERT_TRUE(windows.empty()); - - // Should get window 1 if asked for. - Id window11_in_wt2 = - BuildWindowId(client_id_1(), ClientWindowIdFromTransportId(window_1_1)); - GetWindowTree(wt2(), window11_in_wt2, &windows); - ASSERT_EQ(1u, windows.size()); - EXPECT_EQ(WindowParentToString(window11_in_wt2, kNullParentId), - windows[0].ToString()); -} - -TEST_F(WindowTreeClientTest, EmbedWithSameWindowId) { - ASSERT_NO_FATAL_FAILURE(EstablishSecondClient(true)); - changes2()->clear(); - - Id window_1_1 = BuildWindowId(client_id_1(), 1); - ASSERT_NO_FATAL_FAILURE(EstablishThirdClient(wt1(), window_1_1)); - - // Client 2 should have been told of the unembed and delete. - { - wt_client2_->WaitForChangeCount(2); - EXPECT_EQ("OnUnembed window=" + IdToString(window_1_1), - ChangesToDescription1(*changes2())[0]); - EXPECT_EQ("WindowDeleted window=" + IdToString(window_1_1), - ChangesToDescription1(*changes2())[1]); - } - - // Client 2 has no root. Verify it can't see window client_id_1(),1 anymore. - { - std::vector<TestWindow> windows; - GetWindowTree(wt2(), window_1_1, &windows); - EXPECT_TRUE(windows.empty()); - } -} - -TEST_F(WindowTreeClientTest, EmbedWithSameWindowId2) { - ASSERT_NO_FATAL_FAILURE(EstablishSecondClient(true)); - Id window_1_1 = BuildWindowId(client_id_1(), 1); - changes2()->clear(); - - ASSERT_NO_FATAL_FAILURE(EstablishThirdClient(wt1(), window_1_1)); - - // Client 2 should have been told about the unembed and delete. - wt_client2_->WaitForChangeCount(2); - changes2()->clear(); - - // Create a window in the third client and parent it to the root. - Id window_3_1 = wt_client3()->NewWindow(1); - ASSERT_TRUE(window_3_1); - // After EstablishThirdClient, window_1_1 should have a ClientWindowId of - // (client_id_2, 0). - Id embedded_window_1_1_wt3 = BuildWindowId(client_id_2(), 0); - ASSERT_TRUE(wt_client3()->AddWindow(embedded_window_1_1_wt3, window_3_1)); - - // wt1 created window_1_1 but not window_3_1. - Id window11_in_wt1 = ClientWindowIdFromTransportId(window_1_1); - Id window31_in_wt1 = - BuildWindowId(client_id_3(), ClientWindowIdFromTransportId(window_3_1)); - - // Client 1 should have been told about the add (it owns the window). - { - wt_client1_->WaitForChangeCount(1); - EXPECT_EQ("HierarchyChanged window=" + IdToString(window31_in_wt1) + - " old_parent=null new_parent=" + IdToString(window11_in_wt1), - SingleChangeToDescription(*changes1())); - } - - // Embed client_id_1(),1 again. - { - changes3()->clear(); - - // We should get a new client for the new embedding. - std::unique_ptr<TestWindowTreeClient> client4( - EstablishClientViaEmbed(wt1(), window_1_1)); - Id embedded_window_1_1_wt4 = BuildWindowId(client_id_3(), 0); - ASSERT_TRUE(client4.get()); - EXPECT_EQ("[" + - WindowParentToString(embedded_window_1_1_wt4, kNullParentId) + - "]", - ChangeWindowDescription(*client4->tracker()->changes())); - - // And 3 should get an unembed and delete. - wt_client3_->WaitForChangeCount(2); - EXPECT_EQ("OnUnembed window=" + IdToString(embedded_window_1_1_wt3), - ChangesToDescription1(*changes3())[0]); - EXPECT_EQ("WindowDeleted window=" + IdToString(embedded_window_1_1_wt3), - ChangesToDescription1(*changes3())[1]); - } - - // wt3() has no root. Verify it can't see window client_id_1(),1 anymore. - { - std::vector<TestWindow> windows; - GetWindowTree(wt3(), window_1_1, &windows); - EXPECT_TRUE(windows.empty()); - } - - // Verify client_id_3(),1 is no longer parented to client_id_1(),1. We have to - // do this from client_id_1(),1 as wt3() can no longer see client_id_1(),1. - { - std::vector<TestWindow> windows; - GetWindowTree(wt1(), window_1_1, &windows); - ASSERT_EQ(1u, windows.size()); - EXPECT_EQ(WindowParentToString(window11_in_wt1, kNullParentId), - windows[0].ToString()); - } - - // Verify wt3() can still see the window it created client_id_3(),1. - { - std::vector<TestWindow> windows; - GetWindowTree(wt3(), window_3_1, &windows); - ASSERT_EQ(1u, windows.size()); - EXPECT_EQ(WindowParentToString(window_3_1, kNullParentId), - windows[0].ToString()); - } -} - -// Assertions for SetWindowVisibility. -TEST_F(WindowTreeClientTest, SetWindowVisibility) { - // Create 1 and 2 in the first client and parent both to the root. - Id window_1_1 = wt_client1()->NewWindow(1); - Id window_1_2 = wt_client1()->NewWindow(2); - ASSERT_TRUE(window_1_1); - ASSERT_TRUE(window_1_2); - - ASSERT_TRUE(wt_client1()->AddWindow(root_window_id(), window_1_1)); - { - std::vector<TestWindow> windows; - GetWindowTree(wt1(), root_window_id(), &windows); - ASSERT_EQ(2u, windows.size()); - EXPECT_EQ( - WindowParentToString(root_window_id(), kNullParentId) + " visible=true", - windows[0].ToString2()); - EXPECT_EQ( - WindowParentToString(window_1_1, root_window_id()) + " visible=false", - windows[1].ToString2()); - } - - // Show all the windows. - ASSERT_TRUE(wt_client1()->SetWindowVisibility(window_1_1, true)); - ASSERT_TRUE(wt_client1()->SetWindowVisibility(window_1_2, true)); - { - std::vector<TestWindow> windows; - GetWindowTree(wt1(), root_window_id(), &windows); - ASSERT_EQ(2u, windows.size()); - EXPECT_EQ( - WindowParentToString(root_window_id(), kNullParentId) + " visible=true", - windows[0].ToString2()); - EXPECT_EQ( - WindowParentToString(window_1_1, root_window_id()) + " visible=true", - windows[1].ToString2()); - } - - // Hide 1. - ASSERT_TRUE(wt_client1()->SetWindowVisibility(window_1_1, false)); - { - std::vector<TestWindow> windows; - GetWindowTree(wt1(), window_1_1, &windows); - ASSERT_EQ(1u, windows.size()); - EXPECT_EQ( - WindowParentToString(window_1_1, root_window_id()) + " visible=false", - windows[0].ToString2()); - } - - // Attach 2 to 1. - ASSERT_TRUE(wt_client1()->AddWindow(window_1_1, window_1_2)); - { - std::vector<TestWindow> windows; - GetWindowTree(wt1(), window_1_1, &windows); - ASSERT_EQ(2u, windows.size()); - EXPECT_EQ( - WindowParentToString(window_1_1, root_window_id()) + " visible=false", - windows[0].ToString2()); - EXPECT_EQ(WindowParentToString(window_1_2, window_1_1) + " visible=true", - windows[1].ToString2()); - } - - // Show 1. - ASSERT_TRUE(wt_client1()->SetWindowVisibility(window_1_1, true)); - { - std::vector<TestWindow> windows; - GetWindowTree(wt1(), window_1_1, &windows); - ASSERT_EQ(2u, windows.size()); - EXPECT_EQ( - WindowParentToString(window_1_1, root_window_id()) + " visible=true", - windows[0].ToString2()); - EXPECT_EQ(WindowParentToString(window_1_2, window_1_1) + " visible=true", - windows[1].ToString2()); - } -} - -// Test that we hear the cursor change in other clients. -TEST_F(WindowTreeClientTest, SetCursor) { - // Get a second client to listen in. - ASSERT_NO_FATAL_FAILURE(EstablishSecondClient(true)); - Id window_1_1 = BuildWindowId(client_id_1(), 1); - changes2()->clear(); - - ASSERT_TRUE(wt_client1()->SetCursor(window_1_1, - ui::CursorData(ui::CursorType::kIBeam))); - wt_client2_->WaitForChangeCount(1u); - - EXPECT_EQ("CursorChanged id=" + IdToString(window_1_1) + " cursor_type=4", - SingleChangeToDescription(*changes2())); -} - -// Assertions for SetWindowVisibility sending notifications. -TEST_F(WindowTreeClientTest, SetWindowVisibilityNotifications) { - // Create client_id_1(),1 and client_id_1(),2. client_id_1(),2 is made a child - // of client_id_1(),1 and client_id_1(),1 a child of the root. - Id window_1_1 = wt_client1()->NewWindow(1); - ASSERT_TRUE(window_1_1); - ASSERT_TRUE(wt_client1()->SetWindowVisibility(window_1_1, true)); - // Setting to the same value should return true. - EXPECT_TRUE(wt_client1()->SetWindowVisibility(window_1_1, true)); - - Id window_1_2 = wt_client1()->NewWindow(2); - ASSERT_TRUE(window_1_2); - ASSERT_TRUE(wt_client1()->SetWindowVisibility(window_1_2, true)); - ASSERT_TRUE(wt_client1()->AddWindow(root_window_id(), window_1_1)); - ASSERT_TRUE(wt_client1()->AddWindow(window_1_1, window_1_2)); - - // Establish the second client at client_id_1(),2. - ASSERT_NO_FATAL_FAILURE(EstablishSecondClientWithRoot(window_1_2)); - - // Add client_id_2(),3 as a child of client_id_1(),2. - Id window_2_1 = wt_client2()->NewWindow(1); - ASSERT_TRUE(window_2_1); - ASSERT_TRUE(wt_client2()->SetWindowVisibility(window_2_1, true)); - // window_1_2 has a client_id part of client_id_1 in wt2. - Id window12_in_wt2 = - BuildWindowId(client_id_1(), ClientWindowIdFromTransportId(window_1_2)); - ASSERT_TRUE(wt_client2()->AddWindow(window12_in_wt2, window_2_1)); - ASSERT_TRUE(wt_client1()->WaitForAllMessages()); - - changes2()->clear(); - // Hide client_id_1(),2 from client 1. Client 2 should see this. - ASSERT_TRUE(wt_client1()->SetWindowVisibility(window_1_2, false)); - { - wt_client2_->WaitForChangeCount(1); - EXPECT_EQ("VisibilityChanged window=" + IdToString(window12_in_wt2) + - " visible=false", - SingleChangeToDescription(*changes2())); - } - - changes1()->clear(); - // Show client_id_1(),2 from client 2, client 1 should be notified. - ASSERT_TRUE(wt_client2()->SetWindowVisibility(window12_in_wt2, true)); - { - wt_client1_->WaitForChangeCount(1); - EXPECT_EQ( - "VisibilityChanged window=" + IdToString(window_1_2) + " visible=true", - SingleChangeToDescription(*changes1())); - } - - changes2()->clear(); - // Hide client_id_1(),1, client 2 should be told the draw state changed. - ASSERT_TRUE(wt_client1()->SetWindowVisibility(window_1_1, false)); - { - wt_client2_->WaitForChangeCount(1); - EXPECT_EQ("DrawnStateChanged window=" + IdToString(window12_in_wt2) + - " drawn=false", - SingleChangeToDescription(*changes2())); - } - - changes2()->clear(); - // Show client_id_1(),1 from client 1. Client 2 should see this. - ASSERT_TRUE(wt_client1()->SetWindowVisibility(window_1_1, true)); - { - wt_client2_->WaitForChangeCount(1); - EXPECT_EQ("DrawnStateChanged window=" + IdToString(window12_in_wt2) + - " drawn=true", - SingleChangeToDescription(*changes2())); - } - - // Change visibility of client_id_2(),3, client 1 should see this. - changes1()->clear(); - ASSERT_TRUE(wt_client2()->SetWindowVisibility(window_2_1, false)); - { - wt_client1_->WaitForChangeCount(1); - EXPECT_EQ( - "VisibilityChanged window=" + - IdToString(BuildWindowId( - client_id_2(), ClientWindowIdFromTransportId(window_2_1))) + - " visible=false", - SingleChangeToDescription(*changes1())); - } - - changes2()->clear(); - // Remove client_id_1(),1 from the root, client 2 should see drawn state - // changed. - ASSERT_TRUE(wt_client1()->RemoveWindowFromParent(window_1_1)); - { - wt_client2_->WaitForChangeCount(1); - EXPECT_EQ("DrawnStateChanged window=" + IdToString(window12_in_wt2) + - " drawn=false", - SingleChangeToDescription(*changes2())); - } - - changes2()->clear(); - // Add client_id_1(),1 back to the root, client 2 should see drawn state - // changed. - ASSERT_TRUE(wt_client1()->AddWindow(root_window_id(), window_1_1)); - { - wt_client2_->WaitForChangeCount(1); - EXPECT_EQ("DrawnStateChanged window=" + IdToString(window12_in_wt2) + - " drawn=true", - SingleChangeToDescription(*changes2())); - } -} - -// Assertions for SetWindowVisibility sending notifications. -TEST_F(WindowTreeClientTest, SetWindowVisibilityNotifications2) { - // Create client_id_1(),1 and client_id_1(),2. client_id_1(),2 is made a child - // of client_id_1(),1 and client_id_1(),1 a child of the root. - Id window_1_1 = wt_client1()->NewWindow(1); - ASSERT_TRUE(window_1_1); - ASSERT_TRUE(wt_client1()->SetWindowVisibility(window_1_1, true)); - Id window_1_2 = wt_client1()->NewWindow(2); - ASSERT_TRUE(window_1_2); - ASSERT_TRUE(wt_client1()->AddWindow(root_window_id(), window_1_1)); - ASSERT_TRUE(wt_client1()->AddWindow(window_1_1, window_1_2)); - - // Establish the second client at client_id_1(),2. - ASSERT_NO_FATAL_FAILURE(EstablishSecondClientWithRoot(window_1_2)); - // window_1_2 has a client_id part of client_id_1 in wt2. - Id window12_in_wt2 = - BuildWindowId(client_id_1(), ClientWindowIdFromTransportId(window_1_2)); - EXPECT_EQ("OnEmbed drawn=true", SingleChangeToDescription2(*changes2())); - changes2()->clear(); - - // Show client_id_1(),2 from client 1. Client 2 should see this. - ASSERT_TRUE(wt_client1()->SetWindowVisibility(window_1_2, true)); - { - wt_client2_->WaitForChangeCount(1); - EXPECT_EQ("VisibilityChanged window=" + IdToString(window12_in_wt2) + - " visible=true", - SingleChangeToDescription(*changes2())); - } -} - -// Assertions for SetWindowVisibility sending notifications. -TEST_F(WindowTreeClientTest, SetWindowVisibilityNotifications3) { - // Create client_id_1(),1 and client_id_1(),2. client_id_1(),2 is made a child - // of client_id_1(),1 and client_id_1(),1 a child of the root. - Id window_1_1 = wt_client1()->NewWindow(1); - ASSERT_TRUE(window_1_1); - Id window_1_2 = wt_client1()->NewWindow(2); - ASSERT_TRUE(window_1_2); - ASSERT_TRUE(wt_client1()->AddWindow(root_window_id(), window_1_1)); - ASSERT_TRUE(wt_client1()->AddWindow(window_1_1, window_1_2)); - - // Establish the second client at client_id_1(),2. - // TODO(fsamuel): Currently the FrameSinkId maps directly to the server's - // window ID. This is likely bad from a security perspective and should be - // fixed. - ASSERT_NO_FATAL_FAILURE(EstablishSecondClientWithRoot(window_1_2)); - // window_1_2 has a client_id part of client_id_1 in wt2. - Id window12_in_wt2 = - BuildWindowId(client_id_1(), ClientWindowIdFromTransportId(window_1_2)); - EXPECT_EQ("OnEmbed drawn=false", SingleChangeToDescription2(*changes2())); - changes2()->clear(); - - // Show client_id_1(),1, drawn should be true for client_id_1(),2 (as that is - // all the child sees). - ASSERT_TRUE(wt_client1()->SetWindowVisibility(window_1_1, true)); - { - wt_client2_->WaitForChangeCount(1); - EXPECT_EQ("DrawnStateChanged window=" + IdToString(window12_in_wt2) + - " drawn=true", - SingleChangeToDescription(*changes2())); - } - changes2()->clear(); - - // Show client_id_1(),2, visible should be true. - ASSERT_TRUE(wt_client1()->SetWindowVisibility(window_1_2, true)); - { - wt_client2_->WaitForChangeCount(1); - EXPECT_EQ("VisibilityChanged window=" + IdToString(window12_in_wt2) + - " visible=true", - SingleChangeToDescription(*changes2())); - } -} - -// Tests that when opacity is set on a window, that the calling client is not -// notified, however children are. Also that setting the same opacity is -// rejected and no one is notified. -TEST_F(WindowTreeClientTest, SetOpacityNotifications) { - Id window_1_1 = wt_client1()->NewWindow(1); - ASSERT_TRUE(window_1_1); - - ASSERT_NO_FATAL_FAILURE(EstablishSecondClientWithRoot(window_1_1)); - Id window_2_1 = wt_client2()->NewWindow(1); - ASSERT_TRUE(window_2_1); - // window_1_1 has a client_id part of client_id_1 in wt2. - Id window11_in_wt2 = - BuildWindowId(client_id_1(), ClientWindowIdFromTransportId(window_1_1)); - ASSERT_TRUE(wt_client2()->AddWindow(window11_in_wt2, window_2_1)); - ASSERT_TRUE(wt_client1()->WaitForAllMessages()); - - changes1()->clear(); - changes2()->clear(); - // Change opacity, no notification for calling client. - ASSERT_TRUE(wt_client1()->SetWindowOpacity(window_1_1, 0.5f)); - EXPECT_TRUE(changes1()->empty()); - wt_client2()->WaitForChangeCount(1); - EXPECT_EQ("OpacityChanged window_id=" + IdToString(window11_in_wt2) + - " opacity=0.50", - SingleChangeToDescription(*changes2())); - - changes2()->clear(); - // Attempting to set the same opacity should succeed, but no notification as - // there was no actual change. - ASSERT_TRUE(wt_client1()->SetWindowOpacity(window_1_1, 0.5f)); - EXPECT_TRUE(changes1()->empty()); - wt_client2()->WaitForAllMessages(); - EXPECT_TRUE(changes2()->empty()); -} - -TEST_F(WindowTreeClientTest, SetWindowProperty) { - Id window_1_1 = wt_client1()->NewWindow(1); - ASSERT_TRUE(window_1_1); - - ASSERT_NO_FATAL_FAILURE(EstablishSecondClient(false)); - changes2()->clear(); - - ASSERT_TRUE(wt_client1()->AddWindow(root_window_id(), window_1_1)); - { - std::vector<TestWindow> windows; - GetWindowTree(wt1(), root_window_id(), &windows); - ASSERT_EQ(2u, windows.size()); - EXPECT_EQ(root_window_id(), windows[0].window_id); - EXPECT_EQ(window_1_1, windows[1].window_id); - ASSERT_EQ(0u, windows[1].properties.size()); - } - - // Set properties on 1. - changes2()->clear(); - std::vector<uint8_t> one(1, '1'); - ASSERT_TRUE(wt_client1()->SetWindowProperty(window_1_1, "one", &one)); - // window_1_1 has a client_id part of client_id_1 in wt2. - Id window11_in_wt2 = - BuildWindowId(client_id_1(), ClientWindowIdFromTransportId(window_1_1)); - { - wt_client2_->WaitForChangeCount(1); - EXPECT_EQ("PropertyChanged window=" + IdToString(window11_in_wt2) + - " key=one value=1", - SingleChangeToDescription(*changes2())); - } - - // Test that our properties exist in the window tree - { - std::vector<TestWindow> windows; - GetWindowTree(wt1(), window_1_1, &windows); - ASSERT_EQ(1u, windows.size()); - ASSERT_EQ(1u, windows[0].properties.size()); - EXPECT_EQ(one, windows[0].properties["one"]); - } - - changes2()->clear(); - // Set back to null. - ASSERT_TRUE(wt_client1()->SetWindowProperty(window_1_1, "one", NULL)); - { - wt_client2_->WaitForChangeCount(1); - EXPECT_EQ("PropertyChanged window=" + IdToString(window11_in_wt2) + - " key=one value=NULL", - SingleChangeToDescription(*changes2())); - } -} - -TEST_F(WindowTreeClientTest, OnEmbeddedAppDisconnected) { - // Create client 2 and 3. - ASSERT_NO_FATAL_FAILURE(EstablishSecondClient(true)); - Id window_1_1 = BuildWindowId(client_id_1(), 1); - Id window_2_1 = wt_client2()->NewWindow(1); - ASSERT_TRUE(window_2_1); - ASSERT_TRUE(wt_client2()->AddWindow(window_1_1, window_2_1)); - changes2()->clear(); - ASSERT_NO_FATAL_FAILURE(EstablishThirdClient(wt2(), window_2_1)); - - // Client 1 should get a hierarchy change for window_2_1. - wt_client1_->WaitForChangeCount(1); - changes1()->clear(); - - // Close client 3. Client 2 (which had previously embedded 3) should - // be notified of this. - wt_client3_.reset(); - wt_client2_->WaitForChangeCount(1); - EXPECT_EQ("OnEmbeddedAppDisconnected window=" + IdToString(window_2_1), - SingleChangeToDescription(*changes2())); - - // The closing is only interesting to the root that did the embedding. Other - // clients should not be notified of this. - wt_client1_->WaitForAllMessages(); - EXPECT_TRUE(changes1()->empty()); -} - -// Verifies when the parent of an Embed() is destroyed the embedded app gets -// a WindowDeleted (and doesn't trigger a DCHECK). -TEST_F(WindowTreeClientTest, OnParentOfEmbedDisconnects) { - // Create client 2 and 3. - ASSERT_NO_FATAL_FAILURE(EstablishSecondClient(true)); - Id window_1_1 = BuildWindowId(client_id_1(), 1); - ASSERT_TRUE(wt_client1()->AddWindow(root_window_id(), window_1_1)); - Id window_2_1 = wt_client2()->NewWindow(1); - Id window_2_2 = wt_client2()->NewWindow(2); - ASSERT_TRUE(window_2_1); - ASSERT_TRUE(window_2_2); - ASSERT_TRUE(wt_client2()->AddWindow(window_1_1, window_2_1)); - ASSERT_TRUE(wt_client2()->AddWindow(window_2_1, window_2_2)); - changes2()->clear(); - ASSERT_NO_FATAL_FAILURE(EstablishThirdClient(wt2(), window_2_2)); - changes3()->clear(); - - // Close client 2. Client 3 should get a delete (for its root). - wt_client2_.reset(); - wt_client3_->WaitForChangeCount(1); - // window_2_2 has a client_id part of client_id_2 in wt3. - EXPECT_EQ("WindowDeleted window=" + - IdToString(BuildWindowId( - client_id_2(), ClientWindowIdFromTransportId(window_2_2))), - SingleChangeToDescription(*changes3())); -} - -// Verifies WindowTreeImpl doesn't incorrectly erase from its internal -// map when a window from another client with the same window_id is removed. -TEST_F(WindowTreeClientTest, DontCleanMapOnDestroy) { - ASSERT_NO_FATAL_FAILURE(EstablishSecondClient(true)); - Id window_1_1 = BuildWindowId(client_id_1(), 1); - ASSERT_TRUE(wt_client2()->NewWindow(1)); - changes1()->clear(); - wt_client2_.reset(); - wt_client1_->WaitForChangeCount(1); - // window_1_1 is created by wt1 so client_id part would be 0. - EXPECT_EQ("OnEmbeddedAppDisconnected window=" + - IdToString(ClientWindowIdFromTransportId(window_1_1)), - SingleChangeToDescription(*changes1())); - std::vector<TestWindow> windows; - GetWindowTree(wt1(), window_1_1, &windows); - EXPECT_FALSE(windows.empty()); -} - -// Verifies Embed() works when supplying a WindowTreeClient. -TEST_F(WindowTreeClientTest, EmbedSupplyingWindowTreeClient) { - ASSERT_TRUE(wt_client1()->NewWindow(1)); - - TestWindowTreeClient client2; - mojom::WindowTreeClientPtr client2_ptr; - mojo::Binding<WindowTreeClient> client2_binding( - &client2, mojo::MakeRequest(&client2_ptr)); - ASSERT_TRUE(Embed(wt1(), BuildWindowId(client_id_1(), 1), - std::move(client2_ptr))); - client2.WaitForOnEmbed(); - EXPECT_EQ("OnEmbed", - SingleChangeToDescription(*client2.tracker()->changes())); -} - -TEST_F(WindowTreeClientTest, EmbedUsingToken) { - // Embed client2. - ASSERT_TRUE(wt_client1()->NewWindow(1)); - TestWindowTreeClient client2; - mojom::WindowTreeClientPtr client2_ptr; - mojo::Binding<WindowTreeClient> client2_binding( - &client2, mojo::MakeRequest(&client2_ptr)); - ASSERT_TRUE( - Embed(wt1(), BuildWindowId(client_id_1(), 1), std::move(client2_ptr))); - client2.WaitForOnEmbed(); - EXPECT_EQ("OnEmbed", - SingleChangeToDescription(*client2.tracker()->changes())); - - // Schedule an embed of |client3| from wt1(). - TestWindowTreeClient client3; - mojom::WindowTreeClientPtr client3_ptr; - mojo::Binding<WindowTreeClient> client3_binding( - &client3, mojo::MakeRequest(&client3_ptr)); - base::UnguessableToken token; - ScheduleEmbed(wt1(), std::move(client3_ptr), &token); - - // Have |client2| embed using the token scheduled above. - const Id window_id = client2.NewWindow(121); - ASSERT_TRUE(window_id); - ASSERT_TRUE(EmbedUsingToken(client2.tree(), BuildWindowId(client_id_2(), 121), - token)); - client3.WaitForOnEmbed(); - EXPECT_EQ("OnEmbed", - SingleChangeToDescription(*client3.tracker()->changes())); - - // EmbedUsingToken() should fail when passed a token that was already used. - EXPECT_FALSE(EmbedUsingToken(client2.tree(), - BuildWindowId(client_id_2(), 121), token)); - - // EmbedUsingToken() should fail when passed a locally generated token. - EXPECT_FALSE(EmbedUsingToken(client2.tree(), - BuildWindowId(client_id_2(), 121), - base::UnguessableToken::Create())); -} - -TEST_F(WindowTreeClientTest, EmbedUsingTokenFailsWithInvalidWindow) { - // Embed client2. - ASSERT_TRUE(wt_client1()->NewWindow(1)); - TestWindowTreeClient client2; - mojom::WindowTreeClientPtr client2_ptr; - mojo::Binding<WindowTreeClient> client2_binding( - &client2, mojo::MakeRequest(&client2_ptr)); - ASSERT_TRUE( - Embed(wt1(), BuildWindowId(client_id_1(), 1), std::move(client2_ptr))); - client2.WaitForOnEmbed(); - EXPECT_EQ("OnEmbed", - SingleChangeToDescription(*client2.tracker()->changes())); - - // Schedule an embed of |client3| from wt1(). - TestWindowTreeClient client3; - mojom::WindowTreeClientPtr client3_ptr; - mojo::Binding<WindowTreeClient> client3_binding( - &client3, mojo::MakeRequest(&client3_ptr)); - base::UnguessableToken token; - ScheduleEmbed(wt1(), std::move(client3_ptr), &token); - - // This should fail as the window id does not identify a valid window. - EXPECT_FALSE(EmbedUsingToken(client2.tree(), - BuildWindowId(client_id_2(), 121), token)); -} - -TEST_F(WindowTreeClientTest, EmbedFailsFromOtherClient) { - ASSERT_NO_FATAL_FAILURE(EstablishSecondClient(true)); - - Id window_1_1 = BuildWindowId(client_id_1(), 1); - Id window_2_1 = wt_client2()->NewWindow(1); - ASSERT_TRUE(window_2_1); - ASSERT_TRUE(wt_client2()->AddWindow(window_1_1, window_2_1)); - ASSERT_NO_FATAL_FAILURE(EstablishThirdClient(wt2(), window_2_1)); - - Id window_3_3 = wt_client3()->NewWindow(3); - ASSERT_TRUE(window_3_3); - // window_2_1 should have client_id of client_id_2 in wt_client3. - ASSERT_TRUE(wt_client3()->AddWindow( - BuildWindowId(client_id_2(), ClientWindowIdFromTransportId(window_2_1)), - window_3_3)); - - // 2 should not be able to embed in window_3_3 as window_3_3 was not created - // by - // 2. - EXPECT_FALSE(EmbedUrl(connector(), wt2(), test_name(), window_3_3)); -} - -// Verifies Embed() from window manager on another clients window works. -TEST_F(WindowTreeClientTest, EmbedFromOtherClient) { - ASSERT_NO_FATAL_FAILURE(EstablishSecondClient(true)); - - Id window_1_1 = BuildWindowId(client_id_1(), 1); - Id window_2_1 = wt_client2()->NewWindow(1); - ASSERT_TRUE(window_2_1); - ASSERT_TRUE(wt_client2()->AddWindow(window_1_1, window_2_1)); - - changes2()->clear(); - - // Establish a third client in window_2_1. window_2_1 has a client_id of - // client_id_2 for other clients. - ASSERT_NO_FATAL_FAILURE(EstablishThirdClient( - wt1(), - BuildWindowId(client_id_2(), ClientWindowIdFromTransportId(window_2_1)))); - - ASSERT_TRUE(wt_client2()->WaitForAllMessages()); - EXPECT_EQ(std::string(), SingleChangeToDescription(*changes2())); -} - -TEST_F(WindowTreeClientTest, CantEmbedFromClientRoot) { - // Shouldn't be able to embed into the root. - ASSERT_FALSE(EmbedUrl(connector(), wt1(), test_name(), root_window_id())); - - // Even though the call above failed a WindowTreeClient was obtained. We need - // to - // wait for it else we throw off the next connect. - WaitForWindowTreeClient(); - - // Don't allow a client to embed into its own root. - ASSERT_NO_FATAL_FAILURE(EstablishSecondClient(true)); - EXPECT_FALSE(EmbedUrl(connector(), wt2(), test_name(), - BuildWindowId(client_id_1(), 1))); - - // Need to wait for a WindowTreeClient for same reason as above. - WaitForWindowTreeClient(); - - Id window_1_2 = wt_client1()->NewWindow(2); - ASSERT_TRUE(window_1_2); - ASSERT_TRUE( - wt_client1()->AddWindow(BuildWindowId(client_id_1(), 1), window_1_2)); - ASSERT_TRUE(wt_client3_.get() == nullptr); - wt_client3_ = EstablishClientViaEmbedWithPolicyBitmask(wt1(), window_1_2); - ASSERT_TRUE(wt_client3_.get() != nullptr); - - // window_1_2 is ws3's root, so even though v3 is an embed root it should not - // be able to Embed into itself. - ASSERT_FALSE(EmbedUrl(connector(), wt3(), test_name(), window_1_2)); -} - -// Verifies that a transient window tracks its parent's lifetime. -TEST_F(WindowTreeClientTest, TransientWindowTracksTransientParentLifetime) { - ASSERT_NO_FATAL_FAILURE(EstablishSecondClient(true)); - Id window_1_1 = BuildWindowId(client_id_1(), 1); - - Id window_2_1 = wt_client2()->NewWindow(1); - Id window_2_2 = wt_client2()->NewWindow(2); - Id window_2_3 = wt_client2()->NewWindow(3); - ASSERT_TRUE(window_2_1); - // window_2_* has a client_id part of client_id_2 in wt1. - Id window21_in_wt1 = - BuildWindowId(client_id_2(), ClientWindowIdFromTransportId(window_2_1)); - Id window22_in_wt1 = - BuildWindowId(client_id_2(), ClientWindowIdFromTransportId(window_2_2)); - Id window23_in_wt1 = - BuildWindowId(client_id_2(), ClientWindowIdFromTransportId(window_2_3)); - - // root -> window_1_1 -> window_2_1 - // root -> window_1_1 -> window_2_2 - // root -> window_1_1 -> window_2_3 - ASSERT_TRUE(wt_client1()->AddWindow(root_window_id(), window_1_1)); - ASSERT_TRUE(wt_client2()->AddWindow(window_1_1, window_2_1)); - ASSERT_TRUE(wt_client2()->AddWindow(window_1_1, window_2_2)); - ASSERT_TRUE(wt_client2()->AddWindow(window_1_1, window_2_3)); - - // window_2_2 and window_2_3 now track the lifetime of window_2_1. - changes1()->clear(); - wt2()->AddTransientWindow(10, window_2_1, window_2_2); - wt2()->AddTransientWindow(11, window_2_1, window_2_3); - wt_client1()->WaitForChangeCount(2); - EXPECT_EQ("AddTransientWindow parent = " + IdToString(window21_in_wt1) + - " child = " + IdToString(window22_in_wt1), - ChangesToDescription1(*changes1())[0]); - EXPECT_EQ("AddTransientWindow parent = " + IdToString(window21_in_wt1) + - " child = " + IdToString(window23_in_wt1), - ChangesToDescription1(*changes1())[1]); - - changes1()->clear(); - wt2()->RemoveTransientWindowFromParent(12, window_2_3); - wt_client1()->WaitForChangeCount(1); - EXPECT_EQ("RemoveTransientWindowFromParent parent = " + - IdToString(window21_in_wt1) + - " child = " + IdToString(window23_in_wt1), - SingleChangeToDescription(*changes1())); - - changes1()->clear(); - ASSERT_TRUE(wt_client2()->DeleteWindow(window_2_1)); - wt_client1()->WaitForChangeCount(2); - EXPECT_EQ("WindowDeleted window=" + IdToString(window22_in_wt1), - ChangesToDescription1(*changes1())[0]); - EXPECT_EQ("WindowDeleted window=" + IdToString(window21_in_wt1), - ChangesToDescription1(*changes1())[1]); -} - -TEST_F(WindowTreeClientTest, Ids) { - const Id window_1_100 = wt_client1()->NewWindow(100); - ASSERT_TRUE(window_1_100); - ASSERT_TRUE(wt_client1()->AddWindow(root_window_id(), window_1_100)); - - // Establish the second client at client_id_1(),100. - ASSERT_NO_FATAL_FAILURE(EstablishSecondClientWithRoot(window_1_100)); - - // client_id_1(),100 is the id in the wt_client1's id space. The new client - // should see client_id_2(),1 (the server id). - const Id window_1_100_in_ws2 = BuildWindowId(client_id_1(), 100); - EXPECT_EQ(window_1_100_in_ws2, wt_client2()->root_window_id()); - - // The first window created in the second client gets a server id of - // client_id_2(),1 regardless of the id the client uses. - const Id window_2_101 = wt_client2()->NewWindow(101); - ASSERT_TRUE(wt_client2()->AddWindow(window_1_100_in_ws2, window_2_101)); - const Id window_2_101_in_ws1 = BuildWindowId(client_id_2(), 101); - wt_client1()->WaitForChangeCount(1); - EXPECT_EQ("HierarchyChanged window=" + IdToString(window_2_101_in_ws1) + - " old_parent=null new_parent=" + IdToString(window_1_100), - SingleChangeToDescription(*changes1())); - changes1()->clear(); - - // Change the bounds of window_2_101 and make sure server gets it. - wt2()->SetWindowBounds(11, window_2_101, gfx::Rect(1, 2, 3, 4), - base::nullopt); - ASSERT_TRUE(wt_client2()->WaitForChangeCompleted(11)); - wt_client1()->WaitForChangeCount(1); - EXPECT_EQ( - "BoundsChanged window=" + IdToString(window_2_101_in_ws1) + - " old_bounds=0,0 0x0 new_bounds=1,2 3x4 local_surface_id=(none)", - SingleChangeToDescription(*changes1())); - changes2()->clear(); - - // Remove 2_101 from wm, client1 should see the change. - wt1()->RemoveWindowFromParent(12, window_2_101_in_ws1); - ASSERT_TRUE(wt_client1()->WaitForChangeCompleted(12)); - wt_client2()->WaitForChangeCount(1); - EXPECT_EQ("HierarchyChanged window=" + IdToString(window_2_101) + - " old_parent=" + IdToString(window_1_100_in_ws2) + - " new_parent=null", - SingleChangeToDescription(*changes2())); -} - -// Tests that setting capture fails when no input event has occurred, and there -// is no notification of lost capture. -TEST_F(WindowTreeClientTest, ExplicitCaptureWithoutInput) { - Id window_1_1 = wt_client1()->NewWindow(1); - - // Add the window to the root, so that they have a Display to handle input - // capture. - ASSERT_TRUE(wt_client1()->AddWindow(root_window_id(), window_1_1)); - changes1()->clear(); - - // Since there has been no input, capture should not succeed. No lost capture - // message is expected. - wt1()->SetCapture(1, window_1_1); - wt_client1_->WaitForAllMessages(); - EXPECT_TRUE(changes1()->empty()); - - // Since there is no window with capture, lost capture should not be notified. - wt1()->ReleaseCapture(3, window_1_1); - wt_client1_->WaitForAllMessages(); - EXPECT_TRUE(changes1()->empty()); -} - -// TODO(jonross): Enable this once apptests can send input events to the server. -// Enabling capture requires that the client be processing events. -TEST_F(WindowTreeClientTest, DISABLED_ExplicitCapturePropagation) { - Id window_1_1 = wt_client1()->NewWindow(1); - Id window_1_2 = wt_client1()->NewWindow(2); - - // Add the windows to the root, so that they have a Display to handle input - // capture. - ASSERT_TRUE(wt_client1()->AddWindow(root_window_id(), window_1_1)); - ASSERT_TRUE(wt_client1()->AddWindow(root_window_id(), window_1_2)); - - changes1()->clear(); - // Window 1 takes capture then Window 2 takes capture. - // Verify that window 1 has lost capture. - wt1()->SetCapture(1, window_1_1); - wt1()->SetCapture(2, window_1_2); - wt_client1_->WaitForChangeCount(1); - - EXPECT_EQ("OnLostCapture window=" + IdToString(window_1_1), - SingleChangeToDescription(*changes1())); - - changes1()->clear(); - // Explicitly releasing capture should not notify of lost capture. - wt1()->ReleaseCapture(3, window_1_2); - wt_client1_->WaitForAllMessages(); - - EXPECT_TRUE(changes1()->empty()); -} - -TEST_F(WindowTreeClientTest, SurfaceIdPropagation) { - const Id window_1_100 = wt_client1()->NewWindow(100); - ASSERT_TRUE(window_1_100); - ASSERT_TRUE(wt_client1()->AddWindow(root_window_id(), window_1_100)); - - // Establish the second client at client_id_1(),100. - ASSERT_NO_FATAL_FAILURE(EstablishSecondClientWithRoot(window_1_100)); - changes2()->clear(); - - // client_id_1(),100 is the id in the wt_client1's id space. The new client - // should see client_id_2(),1 (the server id). - const Id window_1_100_in_ws2 = BuildWindowId(client_id_1(), 100); - EXPECT_EQ(window_1_100_in_ws2, wt_client2()->root_window_id()); - - // Submit a CompositorFrame to window_1_100_in_ws2 (the embedded window in - // wt2) and make sure the server gets it. - { - viz::mojom::CompositorFrameSinkPtr surface_ptr; - viz::mojom::CompositorFrameSinkClientRequest client_request; - viz::mojom::CompositorFrameSinkClientPtr surface_client_ptr; - client_request = mojo::MakeRequest(&surface_client_ptr); - wt2()->AttachCompositorFrameSink(window_1_100_in_ws2, - mojo::MakeRequest(&surface_ptr), - std::move(surface_client_ptr)); - viz::CompositorFrame compositor_frame; - std::unique_ptr<viz::RenderPass> render_pass = viz::RenderPass::Create(); - gfx::Rect frame_rect(0, 0, 100, 100); - render_pass->SetNew(1, frame_rect, frame_rect, gfx::Transform()); - compositor_frame.render_pass_list.push_back(std::move(render_pass)); - compositor_frame.metadata.device_scale_factor = 1.f; - compositor_frame.metadata.begin_frame_ack = viz::BeginFrameAck(0, 1, true); - viz::LocalSurfaceId local_surface_id(1, base::UnguessableToken::Create()); - surface_ptr->SubmitCompositorFrame( - local_surface_id, std::move(compositor_frame), base::nullopt, 0); - } - // Make sure the parent connection gets the surface ID. - wt_client1()->WaitForChangeCount(1); - // Verify that the submitted frame is for |window_2_101|. - viz::FrameSinkId frame_sink_id = - changes1()->back().surface_id.frame_sink_id(); - // FrameSinkId is based on window's ClientWindowId. - EXPECT_EQ(static_cast<size_t>(client_id_2()), frame_sink_id.client_id()); - EXPECT_EQ(0u, frame_sink_id.sink_id()); - changes1()->clear(); - - // The first window created in the second client gets a server id of - // client_id_2(),1 regardless of the id the client uses. - const Id window_2_101 = wt_client2()->NewWindow(101); - ASSERT_TRUE(wt_client2()->AddWindow(window_1_100_in_ws2, window_2_101)); - const Id window_2_101_in_ws2 = BuildWindowId(client_id_2(), 101); - wt_client1()->WaitForChangeCount(1); - EXPECT_EQ("HierarchyChanged window=" + IdToString(window_2_101_in_ws2) + - " old_parent=null new_parent=" + IdToString(window_1_100), - SingleChangeToDescription(*changes1())); - // Submit a CompositorFrame to window_2_101_in_ws2 (a regular window in - // wt2) and make sure client gets it. - { - viz::mojom::CompositorFrameSinkPtr surface_ptr; - viz::mojom::CompositorFrameSinkClientRequest client_request; - viz::mojom::CompositorFrameSinkClientPtr surface_client_ptr; - client_request = mojo::MakeRequest(&surface_client_ptr); - wt2()->AttachCompositorFrameSink(window_2_101, - mojo::MakeRequest(&surface_ptr), - std::move(surface_client_ptr)); - viz::CompositorFrame compositor_frame; - std::unique_ptr<viz::RenderPass> render_pass = viz::RenderPass::Create(); - gfx::Rect frame_rect(0, 0, 100, 100); - render_pass->SetNew(1, frame_rect, frame_rect, gfx::Transform()); - compositor_frame.render_pass_list.push_back(std::move(render_pass)); - compositor_frame.metadata.device_scale_factor = 1.f; - compositor_frame.metadata.begin_frame_ack = viz::BeginFrameAck(0, 1, true); - viz::LocalSurfaceId local_surface_id(2, base::UnguessableToken::Create()); - surface_ptr->SubmitCompositorFrame( - local_surface_id, std::move(compositor_frame), base::nullopt, 0); - } - // Make sure the parent connection gets the surface ID. - wt_client2()->WaitForChangeCount(1); - // Verify that the submitted frame is for |window_2_101|. - viz::FrameSinkId frame_sink_id2 = - changes2()->back().surface_id.frame_sink_id(); - // FrameSinkId is based on window's ClientWindowId. - EXPECT_NE(0u, frame_sink_id2.client_id()); - EXPECT_EQ(ClientWindowIdFromTransportId(window_2_101), - frame_sink_id2.sink_id()); -} - -// Verifies when an unknown window with a known child is added to a hierarchy -// the known child is identified in the WindowData. -TEST_F(WindowTreeClientTest, AddUnknownWindowKnownParent) { - const Id window_1_100 = wt_client1()->NewWindow(100); - ASSERT_TRUE(window_1_100); - ASSERT_TRUE(wt_client1()->AddWindow(root_window_id(), window_1_100)); - - // Establish the second client at client_id_1(),100. - ASSERT_NO_FATAL_FAILURE(EstablishSecondClientWithRoot(window_1_100)); - const Id window_2_1 = wt_client2()->NewWindow(1000); - const Id window_2_2 = wt_client2()->NewWindow(2000); - // Add 2_1 to the root, remove 2_1, add 2_1 to 2_2 and then 2_2 to the parent. - ASSERT_TRUE( - wt_client2()->AddWindow(wt_client2()->root_window_id(), window_2_1)); - ASSERT_TRUE(wt_client2()->RemoveWindowFromParent(window_2_1)); - ASSERT_TRUE(wt_client2()->AddWindow(window_2_2, window_2_1)); - wt_client1()->WaitForChangeCount(2); - changes1()->clear(); - ASSERT_TRUE( - wt_client2()->AddWindow(wt_client2()->root_window_id(), window_2_2)); - wt_client1()->WaitForChangeCount(1); - const Id window_2_1_in_wm = BuildWindowId(client_id_2(), 1000); - const Id window_2_2_in_wm = BuildWindowId(client_id_2(), 2000); - EXPECT_EQ("HierarchyChanged window=" + IdToString(window_2_2_in_wm) + - " old_parent=null new_parent=" + IdToString(window_1_100), - SingleChangeToDescription(*changes1())); - EXPECT_EQ("[window=" + IdToString(window_2_2_in_wm) + " parent=" + - IdToString(window_1_100) + "],[window=" + - IdToString(window_2_1_in_wm) + " parent=" + - IdToString(window_2_2_in_wm) + "]", - ChangeWindowDescription(*changes1())); -} - -TEST_F(WindowTreeClientTest, Transform) { - const Id window1 = wt_client1()->NewWindow(100); - ASSERT_TRUE(window1); - ASSERT_TRUE(wt_client1()->AddWindow(root_window_id(), window1)); - - // Establish the second client at |window1|. - ASSERT_NO_FATAL_FAILURE(EstablishSecondClientWithRoot(window1)); - - // The first window created in the second client gets a server id of - // client_id_2(),1 regardless of the id the client uses. - const Id window1_in_client2 = BuildWindowId(client_id_1(), 100); - const Id window2 = wt_client2()->NewWindow(11); - ASSERT_TRUE(wt_client2()->AddWindow(window1_in_client2, window2)); - const Id window2_in_client1 = BuildWindowId(client_id_2(), 11); - wt_client1()->WaitForChangeCount(1); - changes1()->clear(); - - // Change the transform of |window2| and make sure server gets it. - gfx::Transform transform; - transform.Scale(SkIntToMScalar(2), SkIntToMScalar(2)); - const uint32_t transform_change_id = 12; - wt2()->SetWindowTransform(transform_change_id, window2, transform); - ASSERT_TRUE(wt_client2()->WaitForChangeCompleted(transform_change_id)); - wt_client1()->WaitForChangeCount(1); - EXPECT_EQ("TransformChanged window_id=" + IdToString(window2_in_client1), - SingleChangeToDescription(*changes1())); -} - -// TODO(sky): need to better track changes to initial client. For example, -// that SetBounsdWindows/AddWindow and the like don't result in messages to the -// originating client. - -// TODO(sky): make sure coverage of what was -// WindowManagerTest.SecondEmbedRoot_InitService and -// WindowManagerTest.MultipleEmbedRootsBeforeWTHReady gets added to window -// manager -// tests. - -} // namespace test -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/window_tree_factory.cc b/services/ui/ws/window_tree_factory.cc deleted file mode 100644 index 0021fe46..0000000 --- a/services/ui/ws/window_tree_factory.cc +++ /dev/null
@@ -1,39 +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 "services/ui/ws/window_tree_factory.h" - -#include "base/memory/ptr_util.h" -#include "services/ui/ws/default_access_policy.h" -#include "services/ui/ws/window_server.h" -#include "services/ui/ws/window_tree.h" -#include "services/ui/ws/window_tree_binding.h" - -namespace ui { -namespace ws { - -WindowTreeFactory::WindowTreeFactory(WindowServer* window_server, - const std::string& client_name) - : window_server_(window_server), - client_name_(client_name) {} - -WindowTreeFactory::~WindowTreeFactory() {} - -void WindowTreeFactory::CreateWindowTree( - mojo::InterfaceRequest<mojom::WindowTree> tree_request, - mojom::WindowTreeClientPtr client) { - const bool is_for_embedding = false; - std::unique_ptr<ws::WindowTree> service( - new ws::WindowTree(window_server_, is_for_embedding, nullptr, - base::WrapUnique(new DefaultAccessPolicy))); - std::unique_ptr<ws::DefaultWindowTreeBinding> binding( - new ws::DefaultWindowTreeBinding(service.get(), window_server_, - std::move(tree_request), - std::move(client))); - service->set_name(client_name_); - window_server_->AddTree(std::move(service), std::move(binding), nullptr); -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/window_tree_factory.h b/services/ui/ws/window_tree_factory.h deleted file mode 100644 index 66f114fd..0000000 --- a/services/ui/ws/window_tree_factory.h +++ /dev/null
@@ -1,36 +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. - -#ifndef SERVICES_UI_WS_WINDOW_TREE_FACTORY_H_ -#define SERVICES_UI_WS_WINDOW_TREE_FACTORY_H_ - -#include "base/macros.h" -#include "services/ui/public/interfaces/window_tree.mojom.h" - -namespace ui { -namespace ws { - -class WindowServer; - -class WindowTreeFactory : public ui::mojom::WindowTreeFactory { - public: - WindowTreeFactory(WindowServer* window_server, - const std::string& client_name); - ~WindowTreeFactory() override; - - private: - // ui::mojom::WindowTreeFactory: - void CreateWindowTree(mojo::InterfaceRequest<mojom::WindowTree> tree_request, - mojom::WindowTreeClientPtr client) override; - - WindowServer* window_server_; - const std::string client_name_; - - DISALLOW_COPY_AND_ASSIGN(WindowTreeFactory); -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_WINDOW_TREE_FACTORY_H_
diff --git a/services/ui/ws/window_tree_host_factory.cc b/services/ui/ws/window_tree_host_factory.cc deleted file mode 100644 index 4675098..0000000 --- a/services/ui/ws/window_tree_host_factory.cc +++ /dev/null
@@ -1,46 +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 "services/ui/ws/window_tree_host_factory.h" - -#include "services/ui/display/viewport_metrics.h" -#include "services/ui/ws/display.h" -#include "services/ui/ws/display_binding.h" -#include "services/ui/ws/window_server.h" - -namespace ui { -namespace ws { - -WindowTreeHostFactory::WindowTreeHostFactory(WindowServer* window_server) - : window_server_(window_server) {} - -WindowTreeHostFactory::~WindowTreeHostFactory() {} - -void WindowTreeHostFactory::AddBinding( - mojom::WindowTreeHostFactoryRequest request) { - bindings_.AddBinding(this, std::move(request)); -} - -void WindowTreeHostFactory::CreateWindowTreeHost( - mojom::WindowTreeHostRequest host, - mojom::WindowTreeClientPtr tree_client) { - Display* ws_display = new Display(window_server_); - - std::unique_ptr<DisplayBindingImpl> display_binding(new DisplayBindingImpl( - std::move(host), ws_display, std::move(tree_client), window_server_)); - - // Provide an initial size for the WindowTreeHost. - display::ViewportMetrics metrics; - metrics.bounds_in_pixels = gfx::Rect(1024, 768); - metrics.device_scale_factor = 1.0f; - metrics.ui_scale_factor = 1.0f; - - display::Display display(1, metrics.bounds_in_pixels); - ws_display->SetDisplay(display); - - ws_display->Init(metrics, std::move(display_binding)); -} - -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws/window_tree_host_factory.h b/services/ui/ws/window_tree_host_factory.h deleted file mode 100644 index de23bde..0000000 --- a/services/ui/ws/window_tree_host_factory.h +++ /dev/null
@@ -1,39 +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. - -#ifndef SERVICES_UI_WS_WINDOW_TREE_HOST_FACTORY_H_ -#define SERVICES_UI_WS_WINDOW_TREE_HOST_FACTORY_H_ - -#include <stdint.h> - -#include "mojo/public/cpp/bindings/binding_set.h" -#include "services/ui/public/interfaces/window_tree_host_factory.mojom.h" - -namespace ui { -namespace ws { - -class WindowServer; - -class WindowTreeHostFactory : public mojom::WindowTreeHostFactory { - public: - explicit WindowTreeHostFactory(WindowServer* window_server); - ~WindowTreeHostFactory() override; - - void AddBinding(mojom::WindowTreeHostFactoryRequest request); - - private: - // mojom::WindowTreeHostFactory implementation. - void CreateWindowTreeHost(mojom::WindowTreeHostRequest host, - mojom::WindowTreeClientPtr tree_client) override; - - WindowServer* window_server_; - mojo::BindingSet<mojom::WindowTreeHostFactory> bindings_; - - DISALLOW_COPY_AND_ASSIGN(WindowTreeHostFactory); -}; - -} // namespace ws -} // namespace ui - -#endif // SERVICES_UI_WS_WINDOW_TREE_HOST_FACTORY_H_
diff --git a/services/ui/ws/window_tree_unittest.cc b/services/ui/ws/window_tree_unittest.cc deleted file mode 100644 index e38542a..0000000 --- a/services/ui/ws/window_tree_unittest.cc +++ /dev/null
@@ -1,2212 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "services/ui/ws/window_tree.h" - -#include <stdint.h> - -#include <string> -#include <vector> - -#include "base/containers/flat_map.h" -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "base/strings/stringprintf.h" -#include "services/service_manager/public/mojom/connector.mojom.h" -#include "services/ui/common/task_runner_test_base.h" -#include "services/ui/common/types.h" -#include "services/ui/common/util.h" -#include "services/ui/public/interfaces/window_tree.mojom.h" -#include "services/ui/public/interfaces/window_tree_constants.mojom.h" -#include "services/ui/ws/default_access_policy.h" -#include "services/ui/ws/display_manager.h" -#include "services/ui/ws/ids.h" -#include "services/ui/ws/platform_display.h" -#include "services/ui/ws/platform_display_factory.h" -#include "services/ui/ws/server_window.h" -#include "services/ui/ws/test_change_tracker.h" -#include "services/ui/ws/test_server_window_delegate.h" -#include "services/ui/ws/test_utils.h" -#include "services/ui/ws/user_display_manager.h" -#include "services/ui/ws/window_manager_access_policy.h" -#include "services/ui/ws/window_manager_display_root.h" -#include "services/ui/ws/window_server.h" -#include "services/ui/ws/window_server_delegate.h" -#include "services/ui/ws/window_tree_binding.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/base/cursor/cursor.h" -#include "ui/events/event.h" -#include "ui/events/event_utils.h" -#include "ui/gfx/geometry/rect.h" - -namespace ui { -namespace ws { -namespace test { -namespace { - -const std::string kNextWindowClientIdString = - std::to_string(kWindowManagerClientId + 1); - -std::string ClientWindowIdToString(const ClientWindowId& id) { - return base::StringPrintf("%d,%d", id.client_id(), id.sink_id()); -} - -ClientWindowId BuildClientWindowId(WindowTree* tree, - ClientSpecificId window_id) { - return ClientWindowId(tree->id(), window_id); -} - -// ----------------------------------------------------------------------------- - -ui::PointerEvent CreatePointerDownEvent(int x, int y) { - return ui::PointerEvent(ui::TouchEvent( - ui::ET_TOUCH_PRESSED, gfx::Point(x, y), ui::EventTimeForNow(), - ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 1))); -} - -ui::PointerEvent CreatePointerUpEvent(int x, int y) { - return ui::PointerEvent(ui::TouchEvent( - ui::ET_TOUCH_RELEASED, gfx::Point(x, y), ui::EventTimeForNow(), - ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 1))); -} - -ui::PointerEvent CreatePointerWheelEvent(int x, int y) { - return ui::PointerEvent( - ui::MouseWheelEvent(gfx::Vector2d(), gfx::Point(x, y), gfx::Point(x, y), - ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE)); -} - -ui::PointerEvent CreateMouseMoveEvent(int x, int y) { - return ui::PointerEvent( - ui::MouseEvent(ui::ET_MOUSE_MOVED, gfx::Point(x, y), gfx::Point(x, y), - ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE)); -} - -ui::PointerEvent CreateMouseDownEvent(int x, int y) { - return ui::PointerEvent( - ui::MouseEvent(ui::ET_MOUSE_PRESSED, gfx::Point(x, y), gfx::Point(x, y), - ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, - ui::EF_LEFT_MOUSE_BUTTON)); -} - -ui::PointerEvent CreateMouseUpEvent(int x, int y) { - return ui::PointerEvent( - ui::MouseEvent(ui::ET_MOUSE_RELEASED, gfx::Point(x, y), gfx::Point(x, y), - ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, - ui::EF_LEFT_MOUSE_BUTTON)); -} - -ServerWindow* GetCaptureWindow(Display* display) { - return display->window_manager_display_root() - ->window_manager_state() - ->capture_window(); -} - -class TestMoveLoopWindowManager : public TestWindowManager { - public: - TestMoveLoopWindowManager(WindowTree* tree) : tree_(tree) {} - ~TestMoveLoopWindowManager() override {} - - void WmPerformMoveLoop(uint32_t change_id, - Id window_id, - mojom::MoveLoopSource source, - const gfx::Point& cursor_location) override { - static_cast<mojom::WindowManagerClient*>(tree_)->WmResponse( - change_id, true); - } - - private: - WindowTree* tree_; - - DISALLOW_COPY_AND_ASSIGN(TestMoveLoopWindowManager); -}; - -// This creates a WindowTree similar to how connecting via WindowTreeFactory -// creates a tree. -WindowTree* CreateTreeViaFactory(WindowServer* window_server, - TestWindowTreeBinding** binding) { - const bool is_for_embedding = false; - WindowTree* tree = new WindowTree(window_server, is_for_embedding, nullptr, - std::make_unique<DefaultAccessPolicy>()); - *binding = new TestWindowTreeBinding(tree); - window_server->AddTree(base::WrapUnique(tree), base::WrapUnique(*binding), - nullptr); - return tree; -} - -} // namespace - -// ----------------------------------------------------------------------------- - -class WindowTreeTest : public testing::Test { - public: - WindowTreeTest() {} - ~WindowTreeTest() override {} - - ui::CursorType cursor_type() { - return window_event_targeting_helper_.cursor_type(); - } - Display* display() { return window_event_targeting_helper_.display(); } - TestWindowTreeClient* last_window_tree_client() { - return window_event_targeting_helper_.last_window_tree_client(); - } - TestWindowTreeClient* wm_client() { - return window_event_targeting_helper_.wm_client(); - } - WindowServer* window_server() { - return window_event_targeting_helper_.window_server(); - } - WindowTree* wm_tree() { - return window_event_targeting_helper_.window_server()->GetTreeWithId( - kWindowManagerClientId); - } - WindowTree* last_tree() { - return window_event_targeting_helper_.last_binding() - ? window_event_targeting_helper_.last_binding()->tree() - : nullptr; - } - - // Simulates an event coming from the system. The event is not acked - // immediately, use AckPreviousEvent() to do that. - void DispatchEventWithoutAck(const ui::Event& event) { - std::unique_ptr<Event> tmp = ui::Event::Clone(event); - display()->ProcessEvent(tmp.get()); - } - - void set_window_manager_internal(WindowTree* tree, - mojom::WindowManager* wm_internal) { - WindowTreeTestApi(tree).set_window_manager_internal(wm_internal); - } - - void AckPreviousEvent() { - WindowManagerStateTestApi test_api( - display()->window_manager_display_root()->window_manager_state()); - while (test_api.tree_awaiting_input_ack()) { - WindowTreeTestApi(test_api.tree_awaiting_input_ack()) - .AckOldestEvent(mojom::EventResult::HANDLED); - } - } - - void DispatchEventAndAckImmediately(const ui::Event& event) { - DispatchEventWithoutAck(event); - AckPreviousEvent(); - } - - // Creates a new window from wm_tree() and embeds a new client in it. - void SetupEventTargeting(TestWindowTreeClient** out_client, - WindowTree** window_tree, - ServerWindow** window); - - // Creates a new tree as the specified user. This does what creation via - // a WindowTreeFactory does. - WindowTree* CreateNewTree(TestWindowTreeBinding** binding) { - return CreateTreeViaFactory(window_server(), binding); - } - - TestWindowServerDelegate* test_window_server_delegate() { - return window_event_targeting_helper_.test_window_server_delegate(); - } - - protected: - WindowEventTargetingHelper window_event_targeting_helper_; - - private: - DISALLOW_COPY_AND_ASSIGN(WindowTreeTest); -}; - -// Creates a new window in wm_tree(), adds it to the root, embeds a -// new client in the window and creates a child of said window. |window| is -// set to the child of |window_tree| that is created. -void WindowTreeTest::SetupEventTargeting(TestWindowTreeClient** out_client, - WindowTree** window_tree, - ServerWindow** window) { - ServerWindow* embed_window = window_event_targeting_helper_.CreatePrimaryTree( - gfx::Rect(0, 0, 100, 100), gfx::Rect(0, 0, 50, 50)); - window_event_targeting_helper_.CreateSecondaryTree( - embed_window, gfx::Rect(20, 20, 20, 20), out_client, window_tree, window); - FirstRoot(*window_tree)->set_is_activation_parent(true); -} - -// Verifies focus does not change on pointer events. -TEST_F(WindowTreeTest, DontFocusOnPointer) { - const ClientWindowId embed_window_id = - BuildClientWindowId(wm_tree(), kEmbedTreeWindowId); - EXPECT_TRUE( - wm_tree()->NewWindow(embed_window_id, ServerWindow::Properties())); - ServerWindow* embed_window = wm_tree()->GetWindowByClientId(embed_window_id); - ASSERT_TRUE(embed_window); - EXPECT_TRUE(wm_tree()->SetWindowVisibility(embed_window_id, true)); - ASSERT_TRUE(FirstRoot(wm_tree())); - const ClientWindowId wm_root_id = FirstRootId(wm_tree()); - EXPECT_TRUE(wm_tree()->AddWindow(wm_root_id, embed_window_id)); - ServerWindow* wm_root = FirstRoot(wm_tree()); - ASSERT_TRUE(wm_root); - wm_root->SetBounds(gfx::Rect(0, 0, 100, 100)); - // This tests expects |wm_root| to be a possible target. - wm_root->set_event_targeting_policy( - mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS); - display()->root_window()->SetBounds(gfx::Rect(0, 0, 100, 100)); - mojom::WindowTreeClientPtr client; - wm_client()->Bind(mojo::MakeRequest(&client)); - const uint32_t embed_flags = 0; - wm_tree()->Embed(embed_window_id, std::move(client), embed_flags); - WindowTree* tree1 = window_server()->GetTreeWithRoot(embed_window); - ASSERT_TRUE(tree1 != nullptr); - ASSERT_NE(tree1, wm_tree()); - - embed_window->SetBounds(gfx::Rect(0, 0, 50, 50)); - - const ClientWindowId child1_id( - BuildClientWindowId(tree1, kEmbedTreeWindowId)); - EXPECT_TRUE(tree1->NewWindow(child1_id, ServerWindow::Properties())); - EXPECT_TRUE(tree1->AddWindow(ClientWindowIdForWindow(tree1, embed_window), - child1_id)); - ServerWindow* child1 = tree1->GetWindowByClientId(child1_id); - ASSERT_TRUE(child1); - child1->SetVisible(true); - child1->SetBounds(gfx::Rect(20, 20, 20, 20)); - - embed_window->set_is_activation_parent(true); - - // Dispatch a pointer event to the child1, focus should be null. - DispatchEventAndAckImmediately(CreatePointerDownEvent(21, 22)); - Display* display1 = tree1->GetDisplay(embed_window); - EXPECT_EQ(nullptr, display1->GetFocusedWindow()); -} - -TEST_F(WindowTreeTest, BasicInputEventTarget) { - TestWindowTreeClient* embed_client = nullptr; - WindowTree* tree = nullptr; - ServerWindow* window = nullptr; - EXPECT_NO_FATAL_FAILURE( - SetupEventTargeting(&embed_client, &tree, &window)); - - // Send an event to |v1|. |embed_client| should get the event, not - // |wm_client|, since |v1| lives inside an embedded window. - DispatchEventAndAckImmediately(CreatePointerDownEvent(21, 22)); - ASSERT_EQ(0u, wm_client()->tracker()->changes()->size()); - ASSERT_EQ(1u, embed_client->tracker()->changes()->size()); - // embed_client created this window that is receiving the event, so client_id - // part would be reset to 0 before sending back to clients. - EXPECT_EQ("InputEvent window=0," + std::to_string(kEmbedTreeWindowId) + - " event_action=" + std::to_string(ui::ET_POINTER_DOWN), - ChangesToDescription1(*embed_client->tracker()->changes())[0]); -} - -TEST_F(WindowTreeTest, EventDispatcherMouseCursorSourceWindowResetOnRemove) { - TestWindowTreeClient* embed_client = nullptr; - WindowTree* tree = nullptr; - ServerWindow* window = nullptr; - EXPECT_NO_FATAL_FAILURE(SetupEventTargeting(&embed_client, &tree, &window)); - - window->SetBounds(gfx::Rect(0, 0, 100, 100)); - - DispatchEventAndAckImmediately(CreatePointerDownEvent(21, 22)); - - WindowManagerState* wms = - display()->window_manager_display_root()->window_manager_state(); - EXPECT_EQ(window, wms->event_processor()->mouse_cursor_source_window()); - - window->parent()->Remove(window); - // The remove should reset the mouse_cursor_source_window(). The important - // thing is it changes to something other than |window|. - EXPECT_NE(window, wms->event_processor()->mouse_cursor_source_window()); -} - -// Verifies SetChildModalParent() works correctly. -TEST_F(WindowTreeTest, SetChildModalParent) { - TestWindowTreeClient* embed_client = nullptr; - WindowTree* tree = nullptr; - ServerWindow* window = nullptr; - EXPECT_NO_FATAL_FAILURE(SetupEventTargeting(&embed_client, &tree, &window)); - - ClientWindowId w1_id; - ServerWindow* w1 = NewWindowInTreeWithParent(tree, window, &w1_id); - ASSERT_TRUE(w1); - ClientWindowId w2_id; - ServerWindow* w2 = NewWindowInTreeWithParent(tree, window, &w2_id); - ASSERT_TRUE(w2); - ASSERT_TRUE(tree->SetChildModalParent(w1_id, w2_id)); - EXPECT_EQ(w2, w1->GetChildModalParent()); - ASSERT_TRUE(tree->SetChildModalParent(w1_id, ClientWindowId())); - EXPECT_EQ(nullptr, w1->GetChildModalParent()); -} - -// Tests that a client can watch for events outside its bounds. -TEST_F(WindowTreeTest, StartPointerWatcher) { - // Create an embedded client. - TestWindowTreeClient* client = nullptr; - WindowTree* tree = nullptr; - ServerWindow* window = nullptr; - EXPECT_NO_FATAL_FAILURE(SetupEventTargeting(&client, &tree, &window)); - - // Create an event outside the bounds of the client. - ui::PointerEvent pointer_down = CreatePointerDownEvent(5, 5); - - // Events are not watched before starting a watcher. - DispatchEventAndAckImmediately(pointer_down); - ASSERT_EQ(0u, client->tracker()->changes()->size()); - - // Create a watcher for all events excluding move events. - WindowTreeTestApi(tree).StartPointerWatcher(false); - - // Pointer-down events are sent to the client. - DispatchEventAndAckImmediately(pointer_down); - ASSERT_EQ(1u, client->tracker()->changes()->size()); - EXPECT_EQ("PointerWatcherEvent event_action=" + - std::to_string(ui::ET_POINTER_DOWN) + " window=null", - ChangesToDescription1(*client->tracker()->changes())[0]); - client->tracker()->changes()->clear(); - - // Create a pointer wheel event outside the bounds of the client. - ui::PointerEvent pointer_wheel = CreatePointerWheelEvent(5, 5); - - // Pointer-wheel events are sent to the client. - DispatchEventAndAckImmediately(pointer_wheel); - ASSERT_EQ(1u, client->tracker()->changes()->size()); - EXPECT_EQ("PointerWatcherEvent event_action=" + - std::to_string(ui::ET_POINTER_WHEEL_CHANGED) + " window=null", - ChangesToDescription1(*client->tracker()->changes())[0]); - client->tracker()->changes()->clear(); - - // Stopping the watcher stops sending events to the client. - WindowTreeTestApi(tree).StopPointerWatcher(); - DispatchEventAndAckImmediately(pointer_down); - ASSERT_EQ(0u, client->tracker()->changes()->size()); - DispatchEventAndAckImmediately(pointer_wheel); - ASSERT_EQ(0u, client->tracker()->changes()->size()); - - // Create a watcher for all events including move events. - WindowTreeTestApi(tree).StartPointerWatcher(true); - - // Pointer-wheel events are sent to the client. - DispatchEventAndAckImmediately(pointer_wheel); - ASSERT_EQ(1u, client->tracker()->changes()->size()); - EXPECT_EQ("PointerWatcherEvent event_action=" + - std::to_string(ui::ET_POINTER_WHEEL_CHANGED) + " window=null", - ChangesToDescription1(*client->tracker()->changes())[0]); -} - -// Verifies PointerWatcher sees windows known to it. -TEST_F(WindowTreeTest, PointerWatcherGetsWindow) { - // Create an embedded client. - TestWindowTreeClient* client = nullptr; - WindowTree* tree = nullptr; - ServerWindow* window = nullptr; - EXPECT_NO_FATAL_FAILURE(SetupEventTargeting(&client, &tree, &window)); - - WindowTreeTestApi(wm_tree()).StartPointerWatcher(false); - - // Create and dispatch an event that targets the embedded window. - ui::PointerEvent pointer_down = CreatePointerDownEvent(25, 25); - DispatchEventAndAckImmediately(pointer_down); - - ASSERT_EQ(1u, wm_client()->tracker()->changes()->size()); - EXPECT_EQ( - "PointerWatcherEvent event_action=" + - std::to_string(ui::ET_POINTER_DOWN) + " window=" + - ClientWindowIdToString(ClientWindowIdForWindow(wm_tree(), window)), - ChangesToDescription1(*wm_client()->tracker()->changes())[0]); -} - -// Tests that a client using a pointer watcher does not receive events that -// don't match the |want_moves| setting. -TEST_F(WindowTreeTest, StartPointerWatcherNonMatching) { - // Create an embedded client. - TestWindowTreeClient* client = nullptr; - WindowTree* tree = nullptr; - ServerWindow* window = nullptr; - EXPECT_NO_FATAL_FAILURE(SetupEventTargeting(&client, &tree, &window)); - - // Create a watcher for all events excluding move events. - WindowTreeTestApi(tree).StartPointerWatcher(false); - - // Pointer-move events are not sent to the client, since they don't match. - DispatchEventAndAckImmediately(CreateMouseMoveEvent(5, 5)); - ASSERT_EQ(0u, client->tracker()->changes()->size()); -} - -// Tests that an event that both hits a client window and matches a pointer -// watcher is sent only once to the client. -TEST_F(WindowTreeTest, StartPointerWatcherSendsOnce) { - // Create an embedded client. - TestWindowTreeClient* client = nullptr; - WindowTree* tree = nullptr; - ServerWindow* window = nullptr; - EXPECT_NO_FATAL_FAILURE(SetupEventTargeting(&client, &tree, &window)); - - // Create a watcher for all events excluding move events (which do not - // cause focus changes). - WindowTreeTestApi(tree).StartPointerWatcher(false); - - // Create an event inside the bounds of the client. - ui::PointerEvent pointer_up = CreatePointerUpEvent(25, 25); - - // The event is dispatched once, with a flag set that it matched the pointer - // watcher. - DispatchEventAndAckImmediately(pointer_up); - ASSERT_EQ(1u, client->tracker()->changes()->size()); - // clients that created this window is receiving the event, so client_id part - // would be reset to 0 before sending back to clients. - EXPECT_EQ("InputEvent window=0," + std::to_string(kEmbedTreeWindowId) + - " event_action=" + std::to_string(ui::ET_POINTER_UP) + - " matches_pointer_watcher", - SingleChangeToDescription(*client->tracker()->changes())); -} - -// Tests that a pointer watcher cannot watch keystrokes. -TEST_F(WindowTreeTest, StartPointerWatcherKeyEventsDisallowed) { - TestWindowTreeBinding* other_binding; - WindowTree* other_tree = CreateNewTree(&other_binding); - other_binding->client()->tracker()->changes()->clear(); - - WindowTreeTestApi(other_tree).StartPointerWatcher(false); - ui::KeyEvent key_pressed(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE); - DispatchEventAndAckImmediately(key_pressed); - EXPECT_EQ(0u, other_binding->client()->tracker()->changes()->size()); - EXPECT_EQ("InputEvent window=" + std::to_string(kWindowServerClientId) + - ",3 event_action=" + std::to_string(ui::ET_KEY_PRESSED), - SingleChangeToDescription(*wm_client()->tracker()->changes())); - - WindowTreeTestApi(wm_tree()).StartPointerWatcher(false); - ui::KeyEvent key_released(ui::ET_KEY_RELEASED, ui::VKEY_A, ui::EF_NONE); - DispatchEventAndAckImmediately(key_released); - EXPECT_EQ(0u, other_binding->client()->tracker()->changes()->size()); -} - -TEST_F(WindowTreeTest, KeyEventSentToWindowManagerWhenNothingFocused) { - ui::KeyEvent key_pressed(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE); - DispatchEventAndAckImmediately(key_pressed); - EXPECT_EQ("InputEvent window=" + std::to_string(kWindowServerClientId) + - ",3 event_action=" + std::to_string(ui::ET_KEY_PRESSED), - SingleChangeToDescription(*wm_client()->tracker()->changes())); -} - -TEST_F(WindowTreeTest, CursorChangesWhenMouseOverWindowAndWindowSetsCursor) { - TestWindowTreeClient* embed_client = nullptr; - WindowTree* tree = nullptr; - ServerWindow* window = nullptr; - EXPECT_NO_FATAL_FAILURE(SetupEventTargeting(&embed_client, &tree, &window)); - - // Like in BasicInputEventTarget, we send a pointer down event to be - // dispatched. This is only to place the mouse cursor over that window though. - DispatchEventAndAckImmediately(CreateMouseMoveEvent(21, 22)); - - // Set the cursor on the parent as that is where the cursor is picked up from. - window->parent()->SetCursor(ui::CursorData(ui::CursorType::kIBeam)); - - // Because the cursor is over the window when SetCursor was called, we should - // have immediately changed the cursor. - EXPECT_EQ(ui::CursorType::kIBeam, cursor_type()); -} - -TEST_F(WindowTreeTest, CursorChangesWhenEnteringWindowWithDifferentCursor) { - TestWindowTreeClient* embed_client = nullptr; - WindowTree* tree = nullptr; - ServerWindow* window = nullptr; - EXPECT_NO_FATAL_FAILURE(SetupEventTargeting(&embed_client, &tree, &window)); - - // Let's create a pointer event outside the window and then move the pointer - // inside. - DispatchEventAndAckImmediately(CreateMouseMoveEvent(5, 5)); - // Set the cursor on the parent as that is where the cursor is picked up from. - window->parent()->SetCursor(ui::CursorData(ui::CursorType::kIBeam)); - EXPECT_EQ(ui::CursorType::kPointer, cursor_type()); - - DispatchEventAndAckImmediately(CreateMouseMoveEvent(21, 22)); - EXPECT_EQ(ui::CursorType::kIBeam, cursor_type()); -} - -TEST_F(WindowTreeTest, DragOutsideWindow) { - TestWindowTreeClient* embed_client = nullptr; - WindowTree* tree = nullptr; - ServerWindow* window = nullptr; - EXPECT_NO_FATAL_FAILURE(SetupEventTargeting(&embed_client, &tree, &window)); - - // Start with the cursor outside the window. Setting the cursor shouldn't - // change the cursor. - DispatchEventAndAckImmediately(CreateMouseMoveEvent(5, 5)); - // Set the cursor on the parent as that is where the cursor is picked up from. - window->parent()->SetCursor(ui::CursorData(ui::CursorType::kIBeam)); - EXPECT_EQ(ui::CursorType::kPointer, cursor_type()); - - // Move the pointer to the inside of the window - DispatchEventAndAckImmediately(CreateMouseMoveEvent(21, 22)); - EXPECT_EQ(ui::CursorType::kIBeam, cursor_type()); - - // Start the drag. - DispatchEventAndAckImmediately(CreateMouseDownEvent(21, 22)); - EXPECT_EQ(ui::CursorType::kIBeam, cursor_type()); - - // Move the cursor (mouse is still down) outside the window. - DispatchEventAndAckImmediately(CreateMouseMoveEvent(5, 5)); - EXPECT_EQ(ui::CursorType::kIBeam, cursor_type()); - - // Release the cursor. We should now adapt the cursor of the window - // underneath the pointer. - DispatchEventAndAckImmediately(CreateMouseUpEvent(5, 5)); - EXPECT_EQ(ui::CursorType::kPointer, cursor_type()); -} - -TEST_F(WindowTreeTest, ChangingWindowBoundsChangesCursor) { - TestWindowTreeClient* embed_client = nullptr; - WindowTree* tree = nullptr; - ServerWindow* window = nullptr; - EXPECT_NO_FATAL_FAILURE(SetupEventTargeting(&embed_client, &tree, &window)); - - // Put the cursor just outside the bounds of the window. - DispatchEventAndAckImmediately(CreateMouseMoveEvent(41, 41)); - // Sets the cursor on the root as that is where the cursor is picked up from. - window->parent()->SetCursor(ui::CursorData(ui::CursorType::kIBeam)); - EXPECT_EQ(ui::CursorType::kPointer, cursor_type()); - - // Expand the bounds of the window so they now include where the cursor now - // is. - window->SetBounds(gfx::Rect(20, 20, 25, 25)); - EXPECT_EQ(ui::CursorType::kIBeam, cursor_type()); - - // Contract the bounds again. - window->SetBounds(gfx::Rect(20, 20, 20, 20)); - EXPECT_EQ(ui::CursorType::kPointer, cursor_type()); -} - -TEST_F(WindowTreeTest, WindowReorderingChangesCursor) { - // Setup two trees parented to the root with the same bounds. - ServerWindow* embed_window1 = - window_event_targeting_helper_.CreatePrimaryTree( - gfx::Rect(0, 0, 200, 200), gfx::Rect(0, 0, 50, 50)); - ServerWindow* embed_window2 = - window_event_targeting_helper_.CreatePrimaryTree( - gfx::Rect(0, 0, 200, 200), gfx::Rect(0, 0, 50, 50)); - - ASSERT_EQ(embed_window1->parent(), embed_window2->parent()); - embed_window1->set_event_targeting_policy( - mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS); - embed_window2->set_event_targeting_policy( - mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS); - embed_window1->SetCursor(ui::CursorData(ui::CursorType::kIBeam)); - embed_window2->SetCursor(ui::CursorData(ui::CursorType::kCross)); - DispatchEventAndAckImmediately(CreateMouseMoveEvent(5, 5)); - // Cursor should match that of top-most window, which is |embed_window2|. - EXPECT_EQ(ui::CursorType::kCross, cursor_type()); - // Move |embed_window1| on top, cursor should now match it. - embed_window1->parent()->StackChildAtTop(embed_window1); - EXPECT_EQ(ui::CursorType::kIBeam, cursor_type()); -} - -// Assertions around moving cursor between trees with roots. -TEST_F(WindowTreeTest, CursorMultipleTrees) { - // Setup two trees parented to the root with the same bounds. - ServerWindow* embed_window1 = - window_event_targeting_helper_.CreatePrimaryTree( - gfx::Rect(0, 0, 200, 200), gfx::Rect(0, 0, 10, 10)); - ServerWindow* embed_window2 = - window_event_targeting_helper_.CreatePrimaryTree( - gfx::Rect(0, 0, 200, 200), gfx::Rect(20, 20, 20, 20)); - embed_window1->set_event_targeting_policy( - mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS); - embed_window2->set_event_targeting_policy( - mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS); - embed_window2->parent()->set_event_targeting_policy( - mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS); - embed_window1->SetCursor(ui::CursorData(ui::CursorType::kIBeam)); - embed_window2->SetCursor(ui::CursorData(ui::CursorType::kCross)); - embed_window1->parent()->SetCursor(ui::CursorData(ui::CursorType::kCopy)); - - // Create a child of |embed_window1|. - ServerWindow* embed_window1_child = NewWindowInTreeWithParent( - window_server()->GetTreeWithRoot(embed_window1), embed_window1); - ASSERT_TRUE(embed_window1_child); - embed_window1_child->SetBounds(gfx::Rect(0, 0, 10, 10)); - embed_window1_child->SetVisible(true); - - // Move mouse into |embed_window1|. - DispatchEventAndAckImmediately(CreateMouseMoveEvent(5, 5)); - EXPECT_EQ(ui::CursorType::kIBeam, cursor_type()); - - // Move mouse into |embed_window2|. - DispatchEventAndAckImmediately(CreateMouseMoveEvent(25, 25)); - EXPECT_EQ(ui::CursorType::kCross, cursor_type()); - - // Move mouse into area between, which should use cursor set on parent. - DispatchEventAndAckImmediately(CreateMouseMoveEvent(15, 15)); - EXPECT_EQ(ui::CursorType::kCopy, cursor_type()); -} - -TEST_F(WindowTreeTest, EventAck) { - const ClientWindowId embed_window_id = - BuildClientWindowId(wm_tree(), kEmbedTreeWindowId); - EXPECT_TRUE( - wm_tree()->NewWindow(embed_window_id, ServerWindow::Properties())); - EXPECT_TRUE(wm_tree()->SetWindowVisibility(embed_window_id, true)); - ASSERT_TRUE(FirstRoot(wm_tree())); - EXPECT_TRUE(wm_tree()->AddWindow(FirstRootId(wm_tree()), embed_window_id)); - ASSERT_EQ(1u, display()->root_window()->children().size()); - ServerWindow* wm_root = FirstRoot(wm_tree()); - ASSERT_TRUE(wm_root); - wm_root->SetBounds(gfx::Rect(0, 0, 100, 100)); - // This tests expects |wm_root| to be a possible target. - wm_root->set_event_targeting_policy( - mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS); - - wm_client()->tracker()->changes()->clear(); - DispatchEventWithoutAck(CreateMouseMoveEvent(21, 22)); - ASSERT_EQ(1u, wm_client()->tracker()->changes()->size()); - EXPECT_EQ("InputEvent window=" + std::to_string(kWindowServerClientId) + - ",3 event_action=" + std::to_string(ui::ET_POINTER_MOVED), - ChangesToDescription1(*wm_client()->tracker()->changes())[0]); - wm_client()->tracker()->changes()->clear(); - - // Send another event. This event shouldn't reach the client. - DispatchEventWithoutAck(CreateMouseMoveEvent(21, 22)); - ASSERT_EQ(0u, wm_client()->tracker()->changes()->size()); - - // Ack the first event. That should trigger the dispatch of the second event. - AckPreviousEvent(); - ASSERT_EQ(1u, wm_client()->tracker()->changes()->size()); - EXPECT_EQ("InputEvent window=" + std::to_string(kWindowServerClientId) + - ",3 event_action=" + std::to_string(ui::ET_POINTER_MOVED), - ChangesToDescription1(*wm_client()->tracker()->changes())[0]); -} - -TEST_F(WindowTreeTest, RemoveWindowFromParentWithQueuedEvent) { - TestWindowTreeClient* embed_client = nullptr; - WindowTree* tree = nullptr; - ServerWindow* window = nullptr; - EXPECT_NO_FATAL_FAILURE(SetupEventTargeting(&embed_client, &tree, &window)); - - window->SetBounds(gfx::Rect(0, 0, 100, 100)); - window->set_is_activation_parent(true); - ClientWindowId w1_id; - ServerWindow* w1 = - NewWindowInTreeWithParent(tree, window, &w1_id, gfx::Rect(0, 0, 20, 20)); - ASSERT_TRUE(w1); - ClientWindowId w2_id; - ServerWindow* w2 = - NewWindowInTreeWithParent(tree, window, &w2_id, gfx::Rect(25, 0, 20, 20)); - ASSERT_TRUE(w2); - - DispatchEventAndAckImmediately(CreateMouseMoveEvent(5, 5)); - - // This moves between |w1| and |w2|, which results in two events (move and - // enter). - DispatchEventWithoutAck(CreateMouseMoveEvent(27, 5)); - - // There should be an event in flight for the move. - EXPECT_TRUE(WindowTreeTestApi(tree).HasEventInFlight()); - - // Simulate the client taking too long. - WindowManagerStateTestApi wm_state_test_api( - wm_tree()->window_manager_state()); - wm_state_test_api.OnEventAckTimeout(tree->id()); - - // There should be an event queued (for the enter). - EXPECT_EQ(1u, WindowTreeTestApi(tree).event_queue_size()); - - // Remove the window from the hierarchy, which should make it so the client - // doesn't get the queued event. - w2->parent()->Remove(w2); - - // Ack the in flight event, which should trigger processing the queued event. - // Because |w2| was removed, the event should not be dispatched to the client - // and WindowManagerState should no longer be waiting (because there are no - // inflight events). - WindowTreeTestApi(tree).AckOldestEvent(); - EXPECT_FALSE(WindowTreeTestApi(tree).HasEventInFlight()); - EXPECT_EQ(nullptr, wm_state_test_api.tree_awaiting_input_ack()); -} - -// Establish client, call Embed() in WM, make sure to get FrameSinkId. -TEST_F(WindowTreeTest, Embed) { - const ClientWindowId embed_window_id = - BuildClientWindowId(wm_tree(), kEmbedTreeWindowId); - EXPECT_TRUE( - wm_tree()->NewWindow(embed_window_id, ServerWindow::Properties())); - ServerWindow* embed_window = wm_tree()->GetWindowByClientId(embed_window_id); - ASSERT_TRUE(embed_window); - const ClientWindowId wm_root_id = FirstRootId(wm_tree()); - EXPECT_TRUE(wm_tree()->AddWindow(wm_root_id, embed_window_id)); - ServerWindow* wm_root = FirstRoot(wm_tree()); - ASSERT_TRUE(wm_root); - mojom::WindowTreeClientPtr client; - wm_client()->Bind(mojo::MakeRequest(&client)); - const uint32_t embed_flags = 0; - wm_tree()->Embed(embed_window_id, std::move(client), embed_flags); - ASSERT_EQ(1u, wm_client()->tracker()->changes()->size()) - << SingleChangeToDescription(*wm_client()->tracker()->changes()); - // The window manager should be told about the FrameSinkId of the embedded - // window. Clients that created this window is receiving the event, so - // client_id part would be reset to 0 before sending back to clients. - EXPECT_EQ( - base::StringPrintf( - "OnFrameSinkIdAllocated window=%s %s", - ClientWindowIdToString(ClientWindowId(0, embed_window_id.sink_id())) - .c_str(), - embed_window->frame_sink_id().ToString().c_str()), - SingleChangeToDescription(*wm_client()->tracker()->changes())); -} - -TEST_F(WindowTreeTest, DisallowSetSystemModalForEmbedded) { - const ClientWindowId embed_window_id = - BuildClientWindowId(wm_tree(), kEmbedTreeWindowId); - EXPECT_TRUE( - wm_tree()->NewWindow(embed_window_id, ServerWindow::Properties())); - ServerWindow* embed_window = wm_tree()->GetWindowByClientId(embed_window_id); - ASSERT_TRUE(embed_window); - const ClientWindowId wm_root_id = FirstRootId(wm_tree()); - EXPECT_TRUE(wm_tree()->AddWindow(wm_root_id, embed_window_id)); - ServerWindow* wm_root = FirstRoot(wm_tree()); - ASSERT_TRUE(wm_root); - mojom::WindowTreeClientPtr client; - wm_client()->Bind(mojo::MakeRequest(&client)); - const uint32_t embed_flags = 0; - ASSERT_TRUE( - wm_tree()->Embed(embed_window_id, std::move(client), embed_flags)); - ASSERT_TRUE(last_tree()); - EXPECT_FALSE(last_tree()->SetModalType( - ClientWindowIdForWindow(last_tree(), embed_window), MODAL_TYPE_SYSTEM)); -} - -TEST_F(WindowTreeTest, ModalTypeSystemToModalTypeNone) { - const ClientWindowId test_window_id = BuildClientWindowId(wm_tree(), 21); - EXPECT_TRUE(wm_tree()->NewWindow(test_window_id, ServerWindow::Properties())); - ServerWindow* test_window = wm_tree()->GetWindowByClientId(test_window_id); - ASSERT_TRUE(test_window); - test_window->SetVisible(true); - const ClientWindowId wm_root_id = FirstRootId(wm_tree()); - EXPECT_TRUE(wm_tree()->AddWindow(wm_root_id, test_window_id)); - EXPECT_TRUE(wm_tree()->SetModalType(test_window_id, MODAL_TYPE_SYSTEM)); - WindowManagerState* wms = - display()->window_manager_display_root()->window_manager_state(); - ModalWindowControllerTestApi modal_window_controller_test_api( - EventProcessorTestApi(wms->event_processor()).modal_window_controller()); - EXPECT_EQ(test_window, - modal_window_controller_test_api.GetActiveSystemModalWindow()); - EXPECT_TRUE(wm_tree()->SetModalType(test_window_id, MODAL_TYPE_NONE)); - EXPECT_EQ(nullptr, - modal_window_controller_test_api.GetActiveSystemModalWindow()); -} - -TEST_F(WindowTreeTest, ModalTypeSystemUnparentedThenParented) { - const ClientWindowId test_window_id = BuildClientWindowId(wm_tree(), 21); - EXPECT_TRUE(wm_tree()->NewWindow(test_window_id, ServerWindow::Properties())); - ServerWindow* test_window = wm_tree()->GetWindowByClientId(test_window_id); - ASSERT_TRUE(test_window); - test_window->SetVisible(true); - const ClientWindowId wm_root_id = FirstRootId(wm_tree()); - EXPECT_TRUE(wm_tree()->SetModalType(test_window_id, MODAL_TYPE_SYSTEM)); - WindowManagerState* wms = - display()->window_manager_display_root()->window_manager_state(); - ModalWindowControllerTestApi modal_window_controller_test_api( - EventProcessorTestApi(wms->event_processor()).modal_window_controller()); - EXPECT_EQ(nullptr, - modal_window_controller_test_api.GetActiveSystemModalWindow()); - EXPECT_TRUE(wm_tree()->AddWindow(wm_root_id, test_window_id)); - EXPECT_EQ(test_window, - modal_window_controller_test_api.GetActiveSystemModalWindow()); - EXPECT_TRUE(wm_tree()->SetModalType(test_window_id, MODAL_TYPE_NONE)); - EXPECT_EQ(nullptr, - modal_window_controller_test_api.GetActiveSystemModalWindow()); -} - -// Establish client, call NewTopLevelWindow(), make sure get id, and make -// sure client paused. -TEST_F(WindowTreeTest, NewTopLevelWindow) { - TestWindowManager wm_internal; - set_window_manager_internal(wm_tree(), &wm_internal); - - TestWindowTreeBinding* child_binding; - WindowTree* child_tree = CreateNewTree(&child_binding); - child_binding->client()->tracker()->changes()->clear(); - child_binding->client()->set_record_on_change_completed(true); - - // Create a new top level window. - base::flat_map<std::string, std::vector<uint8_t>> properties; - const uint32_t initial_change_id = 17; - // Explicitly use an id that does not contain the client id. - const ClientWindowId embed_window_id2_in_child(child_tree->id(), 27); - static_cast<mojom::WindowTree*>(child_tree) - ->NewTopLevelWindow( - initial_change_id, - child_tree->ClientWindowIdToTransportId(embed_window_id2_in_child), - properties); - - // The binding should be paused until the wm acks the change. - uint32_t wm_change_id = 0u; - ASSERT_TRUE(wm_internal.did_call_create_top_level_window(&wm_change_id)); - EXPECT_TRUE(child_binding->is_paused()); - - // Create the window for |embed_window_id2_in_child|. - const ClientWindowId embed_window_id2 = BuildClientWindowId(wm_tree(), 2); - EXPECT_TRUE( - wm_tree()->NewWindow(embed_window_id2, ServerWindow::Properties())); - EXPECT_TRUE(wm_tree()->SetWindowVisibility(embed_window_id2, true)); - EXPECT_TRUE(wm_tree()->AddWindow(FirstRootId(wm_tree()), embed_window_id2)); - - // Ack the change, which should resume the binding. - child_binding->client()->tracker()->changes()->clear(); - static_cast<mojom::WindowManagerClient*>(wm_tree()) - ->OnWmCreatedTopLevelWindow( - wm_change_id, - wm_tree()->ClientWindowIdToTransportId(embed_window_id2)); - - ServerWindow* embed_window = wm_tree()->GetWindowByClientId(embed_window_id2); - ASSERT_TRUE(embed_window); - EXPECT_EQ(embed_window_id2_in_child, embed_window->frame_sink_id()); - EXPECT_FALSE(child_binding->is_paused()); - // TODO(fsamuel): Currently the FrameSinkId maps directly to the server's - // window ID. This is likely bad from a security perspective and should be - // fixed. - EXPECT_EQ(base::StringPrintf( - "TopLevelCreated id=17 window_id=%s drawn=true", - ClientWindowIdToString( - ClientWindowId(0, embed_window_id2_in_child.sink_id())) - .c_str()), - SingleChangeToDescription( - *child_binding->client()->tracker()->changes())); - child_binding->client()->tracker()->changes()->clear(); - - // Change the visibility of the window from the owner and make sure the - // client sees the right id. - EXPECT_TRUE(embed_window->visible()); - ASSERT_TRUE(wm_tree()->SetWindowVisibility( - ClientWindowIdForWindow(wm_tree(), embed_window), false)); - EXPECT_FALSE(embed_window->visible()); - EXPECT_EQ("VisibilityChanged window=" + - ClientWindowIdToString( - ClientWindowId(0, embed_window_id2_in_child.sink_id())) + - " visible=false", - SingleChangeToDescription( - *child_binding->client()->tracker()->changes())); - - // Set the visibility from the child using the client assigned id. - ASSERT_TRUE(child_tree->SetWindowVisibility(embed_window_id2_in_child, true)); - EXPECT_TRUE(embed_window->visible()); -} - -// Tests that only the capture window can release capture. -TEST_F(WindowTreeTest, ExplicitSetCapture) { - TestWindowTreeClient* embed_client = nullptr; - WindowTree* tree = nullptr; - ServerWindow* window = nullptr; - EXPECT_NO_FATAL_FAILURE(SetupEventTargeting(&embed_client, &tree, &window)); - const ServerWindow* root_window = *tree->roots().begin(); - tree->AddWindow(FirstRootId(tree), ClientWindowIdForWindow(tree, window)); - window->SetBounds(gfx::Rect(0, 0, 100, 100)); - ASSERT_TRUE(tree->GetDisplay(window)); - - // Set capture. - mojom::WindowTree* mojom_window_tree = static_cast<mojom::WindowTree*>(tree); - uint32_t change_id = 42; - mojom_window_tree->SetCapture( - change_id, tree->ClientWindowIdToTransportId(window->frame_sink_id())); - Display* display = tree->GetDisplay(window); - EXPECT_EQ(window, GetCaptureWindow(display)); - - // Only the capture window should be able to release capture - mojom_window_tree->ReleaseCapture( - ++change_id, - tree->ClientWindowIdToTransportId(root_window->frame_sink_id())); - EXPECT_EQ(window, GetCaptureWindow(display)); - - mojom_window_tree->ReleaseCapture( - ++change_id, tree->ClientWindowIdToTransportId(window->frame_sink_id())); - EXPECT_EQ(nullptr, GetCaptureWindow(display)); -} - -// Tests that while a client is interacting with input, that capture is not -// allowed for invisible windows. -TEST_F(WindowTreeTest, CaptureWindowMustBeVisible) { - TestWindowTreeClient* embed_client = nullptr; - WindowTree* tree = nullptr; - ServerWindow* window = nullptr; - EXPECT_NO_FATAL_FAILURE(SetupEventTargeting(&embed_client, &tree, &window)); - tree->AddWindow(FirstRootId(tree), ClientWindowIdForWindow(tree, window)); - window->SetBounds(gfx::Rect(0, 0, 100, 100)); - ASSERT_TRUE(tree->GetDisplay(window)); - - DispatchEventWithoutAck(CreatePointerDownEvent(10, 10)); - window->SetVisible(false); - EXPECT_FALSE(tree->SetCapture(ClientWindowIdForWindow(tree, window))); - EXPECT_NE(window, GetCaptureWindow(tree->GetDisplay(window))); -} - -// Tests that showing a modal window releases the capture if the capture is on a -// descendant of the modal parent. -TEST_F(WindowTreeTest, ShowModalWindowWithDescendantCapture) { - TestWindowTreeClient* embed_client = nullptr; - WindowTree* tree = nullptr; - ServerWindow* w1 = nullptr; - EXPECT_NO_FATAL_FAILURE(SetupEventTargeting(&embed_client, &tree, &w1)); - - w1->SetBounds(gfx::Rect(10, 10, 30, 30)); - const ServerWindow* root_window = *tree->roots().begin(); - ClientWindowId root_window_id = ClientWindowIdForWindow(tree, root_window); - ClientWindowId w1_id = ClientWindowIdForWindow(tree, w1); - Display* display = tree->GetDisplay(w1); - - // Create |w11| as a child of |w1| and make it visible. - ClientWindowId w11_id = BuildClientWindowId(tree, 11); - ASSERT_TRUE(tree->NewWindow(w11_id, ServerWindow::Properties())); - ServerWindow* w11 = tree->GetWindowByClientId(w11_id); - w11->SetBounds(gfx::Rect(10, 10, 10, 10)); - ASSERT_TRUE(tree->AddWindow(w1_id, w11_id)); - ASSERT_TRUE(tree->SetWindowVisibility(w11_id, true)); - - // Create |w2| as a child of |root_window| and modal to |w1| and leave it - // hidden. - ClientWindowId w2_id = BuildClientWindowId(tree, 3); - ASSERT_TRUE(tree->NewWindow(w2_id, ServerWindow::Properties())); - ServerWindow* w2 = tree->GetWindowByClientId(w2_id); - w2->SetBounds(gfx::Rect(50, 10, 10, 10)); - ASSERT_TRUE(tree->AddWindow(root_window_id, w2_id)); - ASSERT_TRUE(tree->AddTransientWindow(w1_id, w2_id)); - ASSERT_TRUE(tree->SetModalType(w2_id, MODAL_TYPE_WINDOW)); - - // Set capture to |w11|. - DispatchEventWithoutAck(CreatePointerDownEvent(25, 25)); - ASSERT_TRUE(tree->SetCapture(w11_id)); - EXPECT_EQ(w11, GetCaptureWindow(display)); - AckPreviousEvent(); - - // Make |w2| visible. This should release capture as capture is set to a - // descendant of the modal parent. - ASSERT_TRUE(tree->SetWindowVisibility(w2_id, true)); - EXPECT_EQ(nullptr, GetCaptureWindow(display)); -} - -// Tests that setting a visible window as modal releases the capture if the -// capture is on a descendant of the modal parent. -TEST_F(WindowTreeTest, VisibleWindowToModalWithDescendantCapture) { - TestWindowTreeClient* embed_client = nullptr; - WindowTree* tree = nullptr; - ServerWindow* w1 = nullptr; - EXPECT_NO_FATAL_FAILURE(SetupEventTargeting(&embed_client, &tree, &w1)); - - w1->SetBounds(gfx::Rect(10, 10, 30, 30)); - const ServerWindow* root_window = *tree->roots().begin(); - ClientWindowId root_window_id = ClientWindowIdForWindow(tree, root_window); - ClientWindowId w1_id = ClientWindowIdForWindow(tree, w1); - Display* display = tree->GetDisplay(w1); - - // Create |w11| as a child of |w1| and make it visible. - ClientWindowId w11_id = BuildClientWindowId(tree, 11); - ASSERT_TRUE(tree->NewWindow(w11_id, ServerWindow::Properties())); - ServerWindow* w11 = tree->GetWindowByClientId(w11_id); - w11->SetBounds(gfx::Rect(10, 10, 10, 10)); - ASSERT_TRUE(tree->AddWindow(w1_id, w11_id)); - ASSERT_TRUE(tree->SetWindowVisibility(w11_id, true)); - - // Create |w2| as a child of |root_window| and make it visible. - ClientWindowId w2_id = BuildClientWindowId(tree, 3); - ASSERT_TRUE(tree->NewWindow(w2_id, ServerWindow::Properties())); - ServerWindow* w2 = tree->GetWindowByClientId(w2_id); - w2->SetBounds(gfx::Rect(50, 10, 10, 10)); - ASSERT_TRUE(tree->AddWindow(root_window_id, w2_id)); - ASSERT_TRUE(tree->SetWindowVisibility(w2_id, true)); - - // Set capture to |w11|. - DispatchEventWithoutAck(CreatePointerDownEvent(25, 25)); - ASSERT_TRUE(tree->SetCapture(w11_id)); - EXPECT_EQ(w11, GetCaptureWindow(display)); - AckPreviousEvent(); - - // Set |w2| modal to |w1|. This should release the capture as the capture is - // set to a descendant of the modal parent. - ASSERT_TRUE(tree->AddTransientWindow(w1_id, w2_id)); - ASSERT_TRUE(tree->SetModalType(w2_id, MODAL_TYPE_WINDOW)); - EXPECT_EQ(nullptr, GetCaptureWindow(display)); -} - -// Tests that showing a modal window does not change capture if the capture is -// not on a descendant of the modal parent. -TEST_F(WindowTreeTest, ShowModalWindowWithNonDescendantCapture) { - TestWindowTreeClient* embed_client = nullptr; - WindowTree* tree = nullptr; - ServerWindow* w1 = nullptr; - EXPECT_NO_FATAL_FAILURE(SetupEventTargeting(&embed_client, &tree, &w1)); - - w1->SetBounds(gfx::Rect(10, 10, 30, 30)); - const ServerWindow* root_window = *tree->roots().begin(); - ClientWindowId root_window_id = ClientWindowIdForWindow(tree, root_window); - ClientWindowId w1_id = ClientWindowIdForWindow(tree, w1); - Display* display = tree->GetDisplay(w1); - - // Create |w2| as a child of |root_window| and modal to |w1| and leave it - // hidden. - ClientWindowId w2_id = BuildClientWindowId(tree, kEmbedTreeWindowId + 1); - ASSERT_TRUE(tree->NewWindow(w2_id, ServerWindow::Properties())); - ServerWindow* w2 = tree->GetWindowByClientId(w2_id); - w2->SetBounds(gfx::Rect(50, 10, 10, 10)); - ASSERT_TRUE(tree->AddWindow(root_window_id, w2_id)); - ASSERT_TRUE(tree->AddTransientWindow(w1_id, w2_id)); - ASSERT_TRUE(tree->SetModalType(w2_id, MODAL_TYPE_WINDOW)); - - // Create |w3| as a child of |root_window| and make it visible. - ClientWindowId w3_id = BuildClientWindowId(tree, kEmbedTreeWindowId + 2); - ASSERT_TRUE(tree->NewWindow(w3_id, ServerWindow::Properties())); - ServerWindow* w3 = tree->GetWindowByClientId(w3_id); - w3->SetBounds(gfx::Rect(70, 10, 10, 10)); - ASSERT_TRUE(tree->AddWindow(root_window_id, w3_id)); - ASSERT_TRUE(tree->SetWindowVisibility(w3_id, true)); - - // Set capture to |w3|. - DispatchEventWithoutAck(CreatePointerDownEvent(25, 25)); - ASSERT_TRUE(tree->SetCapture(w3_id)); - EXPECT_EQ(w3, GetCaptureWindow(display)); - AckPreviousEvent(); - - // Make |w2| visible. This should not change the capture as the capture is not - // set to a descendant of the modal parent. - ASSERT_TRUE(tree->SetWindowVisibility(w2_id, true)); - EXPECT_EQ(w3, GetCaptureWindow(display)); -} - -// Tests that setting a visible window as modal does not change the capture if -// the capture is not set to a descendant of the modal parent. -TEST_F(WindowTreeTest, VisibleWindowToModalWithNonDescendantCapture) { - TestWindowTreeClient* embed_client = nullptr; - WindowTree* tree = nullptr; - ServerWindow* w1 = nullptr; - EXPECT_NO_FATAL_FAILURE(SetupEventTargeting(&embed_client, &tree, &w1)); - - w1->SetBounds(gfx::Rect(10, 10, 30, 30)); - const ServerWindow* root_window = *tree->roots().begin(); - ClientWindowId root_window_id = ClientWindowIdForWindow(tree, root_window); - ClientWindowId w1_id = ClientWindowIdForWindow(tree, w1); - Display* display = tree->GetDisplay(w1); - - // Create |w2| and |w3| as children of |root_window| and make them visible. - ClientWindowId w2_id = BuildClientWindowId(tree, kEmbedTreeWindowId + 1); - ASSERT_TRUE(tree->NewWindow(w2_id, ServerWindow::Properties())); - ServerWindow* w2 = tree->GetWindowByClientId(w2_id); - w2->SetBounds(gfx::Rect(50, 10, 10, 10)); - ASSERT_TRUE(tree->AddWindow(root_window_id, w2_id)); - ASSERT_TRUE(tree->SetWindowVisibility(w2_id, true)); - - ClientWindowId w3_id = BuildClientWindowId(tree, kEmbedTreeWindowId + 2); - ASSERT_TRUE(tree->NewWindow(w3_id, ServerWindow::Properties())); - ServerWindow* w3 = tree->GetWindowByClientId(w3_id); - w3->SetBounds(gfx::Rect(70, 10, 10, 10)); - ASSERT_TRUE(tree->AddWindow(root_window_id, w3_id)); - ASSERT_TRUE(tree->SetWindowVisibility(w3_id, true)); - - // Set capture to |w3|. - DispatchEventWithoutAck(CreatePointerDownEvent(25, 25)); - ASSERT_TRUE(tree->SetCapture(w3_id)); - EXPECT_EQ(w3, GetCaptureWindow(display)); - AckPreviousEvent(); - - // Set |w2| modal to |w1|. This should not release the capture as the capture - // is not set to a descendant of the modal parent. - ASSERT_TRUE(tree->AddTransientWindow(w1_id, w2_id)); - ASSERT_TRUE(tree->SetModalType(w2_id, MODAL_TYPE_WINDOW)); - EXPECT_EQ(w3, GetCaptureWindow(display)); -} - -// Tests that showing a system modal window releases the capture. -TEST_F(WindowTreeTest, ShowSystemModalWindowWithCapture) { - TestWindowTreeClient* embed_client = nullptr; - WindowTree* tree = nullptr; - ServerWindow* w1 = nullptr; - EXPECT_NO_FATAL_FAILURE(SetupEventTargeting(&embed_client, &tree, &w1)); - - w1->SetBounds(gfx::Rect(10, 10, 10, 10)); - const ServerWindow* root_window = *tree->roots().begin(); - ClientWindowId root_window_id = ClientWindowIdForWindow(tree, root_window); - ClientWindowId w1_id = ClientWindowIdForWindow(tree, w1); - Display* display = tree->GetDisplay(w1); - - // Create a system modal window |w2| as a child of |root_window| and leave it - // hidden. - ClientWindowId w2_id = BuildClientWindowId(tree, kEmbedTreeWindowId + 1); - ASSERT_TRUE(tree->NewWindow(w2_id, ServerWindow::Properties())); - ServerWindow* w2 = tree->GetWindowByClientId(w2_id); - w2->SetBounds(gfx::Rect(30, 10, 10, 10)); - ASSERT_TRUE(tree->AddWindow(root_window_id, w2_id)); - ASSERT_TRUE(tree->SetModalType(w2_id, MODAL_TYPE_SYSTEM)); - - // Set capture to |w1|. - DispatchEventWithoutAck(CreatePointerDownEvent(15, 15)); - ASSERT_TRUE(tree->SetCapture(w1_id)); - EXPECT_EQ(w1, GetCaptureWindow(display)); - AckPreviousEvent(); - - // Make |w2| visible. This should release capture as it is system modal - // window. - ASSERT_TRUE(tree->SetWindowVisibility(w2_id, true)); - EXPECT_EQ(nullptr, GetCaptureWindow(display)); -} - -// Tests that setting a visible window as modal to system releases the capture. -TEST_F(WindowTreeTest, VisibleWindowToSystemModalWithCapture) { - TestWindowTreeClient* embed_client = nullptr; - WindowTree* tree = nullptr; - ServerWindow* w1 = nullptr; - EXPECT_NO_FATAL_FAILURE(SetupEventTargeting(&embed_client, &tree, &w1)); - - w1->SetBounds(gfx::Rect(10, 10, 10, 10)); - const ServerWindow* root_window = *tree->roots().begin(); - ClientWindowId root_window_id = ClientWindowIdForWindow(tree, root_window); - ClientWindowId w1_id = ClientWindowIdForWindow(tree, w1); - Display* display = tree->GetDisplay(w1); - - // Create |w2| as a child of |root_window| and make it visible. - ClientWindowId w2_id = BuildClientWindowId(tree, kEmbedTreeWindowId + 1); - ASSERT_TRUE(tree->NewWindow(w2_id, ServerWindow::Properties())); - ServerWindow* w2 = tree->GetWindowByClientId(w2_id); - w2->SetBounds(gfx::Rect(30, 10, 10, 10)); - ASSERT_TRUE(tree->AddWindow(root_window_id, w2_id)); - ASSERT_TRUE(tree->SetWindowVisibility(w2_id, true)); - - // Set capture to |w1|. - DispatchEventWithoutAck(CreatePointerDownEvent(15, 15)); - ASSERT_TRUE(tree->SetCapture(w1_id)); - EXPECT_EQ(w1, GetCaptureWindow(display)); - AckPreviousEvent(); - - // Make |w2| modal to system. This should release capture. - ASSERT_TRUE(tree->SetModalType(w2_id, MODAL_TYPE_SYSTEM)); - EXPECT_EQ(nullptr, GetCaptureWindow(display)); -} - -// Tests that moving the capture window to a modal parent releases the capture -// as capture cannot be blocked by a modal window. -TEST_F(WindowTreeTest, MoveCaptureWindowToModalParent) { - TestWindowTreeClient* embed_client = nullptr; - WindowTree* tree = nullptr; - ServerWindow* w1 = nullptr; - EXPECT_NO_FATAL_FAILURE(SetupEventTargeting(&embed_client, &tree, &w1)); - - w1->SetBounds(gfx::Rect(10, 10, 30, 30)); - ServerWindow* root_window = FirstRoot(tree); - ClientWindowId root_window_id = ClientWindowIdForWindow(tree, root_window); - ClientWindowId w1_id = ClientWindowIdForWindow(tree, w1); - Display* display = tree->GetDisplay(w1); - - // Create |w2| and |w3| as children of |root_window| and make them visible. - ClientWindowId w2_id = BuildClientWindowId(tree, kEmbedTreeWindowId + 1); - ASSERT_TRUE(tree->NewWindow(w2_id, ServerWindow::Properties())); - ServerWindow* w2 = tree->GetWindowByClientId(w2_id); - w2->SetBounds(gfx::Rect(50, 10, 10, 10)); - ASSERT_TRUE(tree->AddWindow(root_window_id, w2_id)); - ASSERT_TRUE(tree->SetWindowVisibility(w2_id, true)); - - ClientWindowId w3_id = BuildClientWindowId(tree, kEmbedTreeWindowId + 2); - ASSERT_TRUE(tree->NewWindow(w3_id, ServerWindow::Properties())); - ServerWindow* w3 = tree->GetWindowByClientId(w3_id); - w3->SetBounds(gfx::Rect(70, 10, 10, 10)); - ASSERT_TRUE(tree->AddWindow(root_window_id, w3_id)); - ASSERT_TRUE(tree->SetWindowVisibility(w3_id, true)); - - // Set |w2| modal to |w1|. - ASSERT_TRUE(tree->AddTransientWindow(w1_id, w2_id)); - ASSERT_TRUE(tree->SetModalType(w2_id, MODAL_TYPE_WINDOW)); - - // Set capture to |w3|. - DispatchEventWithoutAck(CreatePointerDownEvent(25, 25)); - ASSERT_TRUE(tree->SetCapture(w3_id)); - EXPECT_EQ(w3, GetCaptureWindow(display)); - AckPreviousEvent(); - - // Make |w3| child of |w1|. This should release capture as |w3| is now blocked - // by a modal window. - ASSERT_TRUE(tree->AddWindow(w1_id, w3_id)); - EXPECT_EQ(nullptr, GetCaptureWindow(display)); -} - -// Tests that opacity can be set on a known window. -TEST_F(WindowTreeTest, SetOpacity) { - TestWindowTreeClient* embed_client = nullptr; - WindowTree* tree = nullptr; - ServerWindow* window = nullptr; - EXPECT_NO_FATAL_FAILURE(SetupEventTargeting(&embed_client, &tree, &window)); - - const float new_opacity = 0.5f; - EXPECT_NE(new_opacity, window->opacity()); - ASSERT_TRUE(tree->SetWindowOpacity(ClientWindowIdForWindow(tree, window), - new_opacity)); - EXPECT_EQ(new_opacity, window->opacity()); - - // Re-applying the same opacity will succeed. - EXPECT_TRUE(tree->SetWindowOpacity(ClientWindowIdForWindow(tree, window), - new_opacity)); -} - -// Tests that opacity requests for unknown windows are rejected. -TEST_F(WindowTreeTest, SetOpacityFailsOnUnknownWindow) { - TestWindowTreeClient* embed_client = nullptr; - WindowTree* tree = nullptr; - ServerWindow* window = nullptr; - EXPECT_NO_FATAL_FAILURE(SetupEventTargeting(&embed_client, &tree, &window)); - - const ClientWindowId root_id = FirstRootId(tree); - - EXPECT_FALSE(tree->SetWindowOpacity( - ClientWindowId(root_id.client_id(), root_id.sink_id() + 10), .5f)); -} - -TEST_F(WindowTreeTest, SetCaptureTargetsRightConnection) { - ServerWindow* window = window_event_targeting_helper_.CreatePrimaryTree( - gfx::Rect(0, 0, 100, 100), gfx::Rect(0, 0, 50, 50)); - WindowTree* owning_tree = - window_server()->GetTreeWithId(window->owning_tree_id()); - WindowTree* embed_tree = window_server()->GetTreeWithRoot(window); - ASSERT_NE(owning_tree, embed_tree); - ASSERT_TRUE( - owning_tree->SetCapture(ClientWindowIdForWindow(owning_tree, window))); - DispatchEventWithoutAck(CreateMouseMoveEvent(21, 22)); - WindowManagerStateTestApi wm_state_test_api( - display()->window_manager_display_root()->window_manager_state()); - EXPECT_EQ(owning_tree, wm_state_test_api.tree_awaiting_input_ack()); - AckPreviousEvent(); - - // Set capture from the embedded client and make sure it gets the event. - ASSERT_TRUE( - embed_tree->SetCapture(ClientWindowIdForWindow(embed_tree, window))); - DispatchEventWithoutAck(CreateMouseMoveEvent(22, 23)); - EXPECT_EQ(embed_tree, wm_state_test_api.tree_awaiting_input_ack()); -} - -TEST_F(WindowTreeTest, ValidMoveLoopWithWM) { - TestWindowManager wm_internal; - set_window_manager_internal(wm_tree(), &wm_internal); - - TestWindowTreeBinding* child_binding; - WindowTree* child_tree = CreateNewTree(&child_binding); - child_binding->client()->tracker()->changes()->clear(); - child_binding->client()->set_record_on_change_completed(true); - - // Create a new top level window. - base::flat_map<std::string, std::vector<uint8_t>> properties; - const uint32_t initial_change_id = 17; - // Explicitly use an id that does not contain the client id. - const ClientWindowId embed_window_id2_in_child(child_tree->id(), 27); - static_cast<mojom::WindowTree*>(child_tree) - ->NewTopLevelWindow( - initial_change_id, - child_tree->ClientWindowIdToTransportId(embed_window_id2_in_child), - properties); - - // The binding should be paused until the wm acks the change. - uint32_t wm_change_id = 0u; - ASSERT_TRUE(wm_internal.did_call_create_top_level_window(&wm_change_id)); - EXPECT_TRUE(child_binding->is_paused()); - - // Create the window for |embed_window_id2_in_child|. - const ClientWindowId embed_window_id2 = BuildClientWindowId(wm_tree(), 2); - EXPECT_TRUE( - wm_tree()->NewWindow(embed_window_id2, ServerWindow::Properties())); - EXPECT_TRUE(wm_tree()->SetWindowVisibility(embed_window_id2, true)); - EXPECT_TRUE(wm_tree()->AddWindow(FirstRootId(wm_tree()), embed_window_id2)); - - // Ack the change, which should resume the binding. - child_binding->client()->tracker()->changes()->clear(); - static_cast<mojom::WindowManagerClient*>(wm_tree()) - ->OnWmCreatedTopLevelWindow( - wm_change_id, - wm_tree()->ClientWindowIdToTransportId(embed_window_id2)); - EXPECT_FALSE(child_binding->is_paused()); - - // The child_tree is the one that has to make this call; the - const uint32_t change_id = 7; - static_cast<mojom::WindowTree*>(child_tree) - ->PerformWindowMove( - change_id, - child_tree->ClientWindowIdToTransportId(embed_window_id2_in_child), - mojom::MoveLoopSource::MOUSE, gfx::Point(0, 0)); - - EXPECT_TRUE(wm_internal.on_perform_move_loop_called()); -} - -TEST_F(WindowTreeTest, MoveLoopAckOKByWM) { - TestMoveLoopWindowManager wm_internal(wm_tree()); - set_window_manager_internal(wm_tree(), &wm_internal); - - TestWindowTreeBinding* child_binding; - WindowTree* child_tree = CreateNewTree(&child_binding); - child_binding->client()->tracker()->changes()->clear(); - child_binding->client()->set_record_on_change_completed(true); - - // Create a new top level window. - base::flat_map<std::string, std::vector<uint8_t>> properties; - const uint32_t initial_change_id = 17; - // Explicitly use an id that does not contain the client id. - const ClientWindowId embed_window_id2_in_child(child_tree->id(), 27); - static_cast<mojom::WindowTree*>(child_tree) - ->NewTopLevelWindow( - initial_change_id, - child_tree->ClientWindowIdToTransportId(embed_window_id2_in_child), - properties); - - // The binding should be paused until the wm acks the change. - uint32_t wm_change_id = 0u; - ASSERT_TRUE(wm_internal.did_call_create_top_level_window(&wm_change_id)); - EXPECT_TRUE(child_binding->is_paused()); - - // Create the window for |embed_window_id2_in_child|. - const ClientWindowId embed_window_id2 = BuildClientWindowId(wm_tree(), 2); - EXPECT_TRUE( - wm_tree()->NewWindow(embed_window_id2, ServerWindow::Properties())); - EXPECT_TRUE(wm_tree()->SetWindowVisibility(embed_window_id2, true)); - EXPECT_TRUE(wm_tree()->AddWindow(FirstRootId(wm_tree()), embed_window_id2)); - - // Ack the change, which should resume the binding. - child_binding->client()->tracker()->changes()->clear(); - static_cast<mojom::WindowManagerClient*>(wm_tree()) - ->OnWmCreatedTopLevelWindow( - wm_change_id, - wm_tree()->ClientWindowIdToTransportId(embed_window_id2)); - EXPECT_FALSE(child_binding->is_paused()); - - // The child_tree is the one that has to make this call; the - const uint32_t change_id = 7; - child_binding->client()->tracker()->changes()->clear(); - static_cast<mojom::WindowTree*>(child_tree) - ->PerformWindowMove( - change_id, - child_tree->ClientWindowIdToTransportId(embed_window_id2_in_child), - mojom::MoveLoopSource::MOUSE, gfx::Point(0, 0)); - - // There should be three changes, the first two relating to capture changing, - // the last for the completion. - std::vector<Change>* child_changes = - child_binding->client()->tracker()->changes(); - ASSERT_EQ(3u, child_changes->size()); - EXPECT_EQ(CHANGE_TYPE_CAPTURE_CHANGED, (*child_changes)[0].type); - EXPECT_EQ(CHANGE_TYPE_CAPTURE_CHANGED, (*child_changes)[1].type); - child_changes->erase(child_changes->begin(), child_changes->begin() + 2); - EXPECT_EQ("ChangeCompleted id=7 sucess=true", - SingleChangeToDescription(*child_changes)); -} - -TEST_F(WindowTreeTest, WindowManagerCantMoveLoop) { - TestWindowManager wm_internal; - set_window_manager_internal(wm_tree(), &wm_internal); - - TestWindowTreeBinding* child_binding; - WindowTree* child_tree = CreateNewTree(&child_binding); - child_binding->client()->tracker()->changes()->clear(); - child_binding->client()->set_record_on_change_completed(true); - - // Create a new top level window. - base::flat_map<std::string, std::vector<uint8_t>> properties; - const uint32_t initial_change_id = 17; - // Explicitly use an id that does not contain the client id. - const ClientWindowId embed_window_id2_in_child(child_tree->id(), 27); - static_cast<mojom::WindowTree*>(child_tree) - ->NewTopLevelWindow( - initial_change_id, - child_tree->ClientWindowIdToTransportId(embed_window_id2_in_child), - properties); - - // The binding should be paused until the wm acks the change. - uint32_t wm_change_id = 0u; - ASSERT_TRUE(wm_internal.did_call_create_top_level_window(&wm_change_id)); - EXPECT_TRUE(child_binding->is_paused()); - - // Create the window for |embed_window_id2_in_child|. - const ClientWindowId embed_window_id2 = BuildClientWindowId(wm_tree(), 2); - EXPECT_TRUE( - wm_tree()->NewWindow(embed_window_id2, ServerWindow::Properties())); - EXPECT_TRUE(wm_tree()->SetWindowVisibility(embed_window_id2, true)); - EXPECT_TRUE(wm_tree()->AddWindow(FirstRootId(wm_tree()), embed_window_id2)); - - // Ack the change, which should resume the binding. - child_binding->client()->tracker()->changes()->clear(); - static_cast<mojom::WindowManagerClient*>(wm_tree()) - ->OnWmCreatedTopLevelWindow( - wm_change_id, - wm_tree()->ClientWindowIdToTransportId(embed_window_id2)); - EXPECT_FALSE(child_binding->is_paused()); - - // Making this call from the wm_tree() must be invalid. - const uint32_t change_id = 7; - static_cast<mojom::WindowTree*>(wm_tree())->PerformWindowMove( - change_id, wm_tree()->ClientWindowIdToTransportId(embed_window_id2), - mojom::MoveLoopSource::MOUSE, gfx::Point(0, 0)); - - EXPECT_FALSE(wm_internal.on_perform_move_loop_called()); -} - -TEST_F(WindowTreeTest, RevertWindowBoundsOnMoveLoopFailure) { - TestWindowManager wm_internal; - set_window_manager_internal(wm_tree(), &wm_internal); - - TestWindowTreeBinding* child_binding; - WindowTree* child_tree = CreateNewTree(&child_binding); - child_binding->client()->tracker()->changes()->clear(); - child_binding->client()->set_record_on_change_completed(true); - - // Create a new top level window. - base::flat_map<std::string, std::vector<uint8_t>> properties; - const uint32_t initial_change_id = 17; - // Explicitly use an id that does not contain the client id. - const ClientWindowId embed_window_id2_in_child(child_tree->id(), 27); - static_cast<mojom::WindowTree*>(child_tree) - ->NewTopLevelWindow( - initial_change_id, - child_tree->ClientWindowIdToTransportId(embed_window_id2_in_child), - properties); - - // The binding should be paused until the wm acks the change. - uint32_t wm_change_id = 0u; - ASSERT_TRUE(wm_internal.did_call_create_top_level_window(&wm_change_id)); - EXPECT_TRUE(child_binding->is_paused()); - - // Create the window for |embed_window_id2_in_child|. - const ClientWindowId embed_window_id2 = BuildClientWindowId(wm_tree(), 2); - EXPECT_TRUE( - wm_tree()->NewWindow(embed_window_id2, ServerWindow::Properties())); - EXPECT_TRUE(wm_tree()->SetWindowVisibility(embed_window_id2, true)); - EXPECT_TRUE(wm_tree()->AddWindow(FirstRootId(wm_tree()), embed_window_id2)); - - // Ack the change, which should resume the binding. - child_binding->client()->tracker()->changes()->clear(); - static_cast<mojom::WindowManagerClient*>(wm_tree()) - ->OnWmCreatedTopLevelWindow( - wm_change_id, - wm_tree()->ClientWindowIdToTransportId(embed_window_id2)); - EXPECT_FALSE(child_binding->is_paused()); - - // The child_tree is the one that has to make this call; the - const uint32_t change_id = 7; - static_cast<mojom::WindowTree*>(child_tree) - ->PerformWindowMove( - change_id, - child_tree->ClientWindowIdToTransportId(embed_window_id2_in_child), - mojom::MoveLoopSource::MOUSE, gfx::Point(0, 0)); - - ServerWindow* server_window = - wm_tree()->GetWindowByClientId(embed_window_id2); - gfx::Rect old_bounds = server_window->bounds(); - server_window->SetBounds(gfx::Rect(10, 10, 20, 20)); - - // Cancel the move loop. - const uint32_t kFirstWMChange = 1; - static_cast<mojom::WindowManagerClient*>(wm_tree())->WmResponse( - kFirstWMChange, false); - - // Canceling the move loop should have reverted the bounds. - EXPECT_EQ(old_bounds, server_window->bounds()); -} - -TEST_F(WindowTreeTest, InvalidMoveLoopStillAcksAttempt) { - // We send a PerformWindowMove for an invalid window. We expect to receive a - // non-success OnMoveLoopCompleted() event. - TestWindowTreeClient* embed_client = nullptr; - WindowTree* tree = nullptr; - ServerWindow* window = nullptr; - EXPECT_NO_FATAL_FAILURE(SetupEventTargeting(&embed_client, &tree, &window)); - - embed_client->set_record_on_change_completed(true); - - const uint32_t kChangeId = 8; - const Id kInvalidWindowId = 1234567890; - static_cast<mojom::WindowTree*>(tree)->PerformWindowMove( - kChangeId, kInvalidWindowId, mojom::MoveLoopSource::MOUSE, - gfx::Point(0, 0)); - - EXPECT_EQ("ChangeCompleted id=8 sucess=false", - SingleChangeToDescription(*embed_client->tracker()->changes())); -} - -TEST_F(WindowTreeTest, SetCanAcceptEvents) { - TestWindowTreeClient* embed_client = nullptr; - WindowTree* tree = nullptr; - ServerWindow* window = nullptr; - EXPECT_NO_FATAL_FAILURE(SetupEventTargeting(&embed_client, &tree, &window)); - - EXPECT_EQ(mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS, - window->event_targeting_policy()); - WindowTreeTestApi(tree).SetEventTargetingPolicy( - tree->ClientWindowIdToTransportId(ClientWindowIdForWindow(tree, window)), - mojom::EventTargetingPolicy::NONE); - EXPECT_EQ(mojom::EventTargetingPolicy::NONE, - window->event_targeting_policy()); -} - -// Verifies wm observers capture changes in client. -TEST_F(WindowTreeTest, CaptureNotifiesWm) { - ServerWindow* window = window_event_targeting_helper_.CreatePrimaryTree( - gfx::Rect(0, 0, 100, 100), gfx::Rect(0, 0, 50, 50)); - TestWindowTreeClient* embed_client = last_window_tree_client(); - WindowTree* owning_tree = - window_server()->GetTreeWithId(window->owning_tree_id()); - WindowTree* embed_tree = window_server()->GetTreeWithRoot(window); - ASSERT_NE(owning_tree, embed_tree); - - const ClientWindowId embed_child_window_id = - BuildClientWindowId(embed_tree, kEmbedTreeWindowId + 1); - ASSERT_TRUE( - embed_tree->NewWindow(embed_child_window_id, ServerWindow::Properties())); - EXPECT_TRUE(embed_tree->SetWindowVisibility(embed_child_window_id, true)); - EXPECT_TRUE( - embed_tree->AddWindow(FirstRootId(embed_tree), embed_child_window_id)); - wm_client()->tracker()->changes()->clear(); - embed_client->tracker()->changes()->clear(); - EXPECT_TRUE(embed_tree->SetCapture(embed_child_window_id)); - ASSERT_TRUE(!wm_client()->tracker()->changes()->empty()); - EXPECT_EQ("OnCaptureChanged new_window=" + kNextWindowClientIdString + "," + - std::to_string(embed_child_window_id.sink_id()) + - " old_window=null", - ChangesToDescription1(*wm_client()->tracker()->changes())[0]); - EXPECT_TRUE(embed_client->tracker()->changes()->empty()); - - // Set capture to embed window, and ensure notified as well. - wm_client()->tracker()->changes()->clear(); - EXPECT_TRUE(embed_tree->SetCapture(FirstRootId(embed_tree))); - ASSERT_TRUE(!wm_client()->tracker()->changes()->empty()); - // clients that created this window is receiving the event, so client_id part - // would be reset to 0 before sending back to clients. - EXPECT_EQ("OnCaptureChanged new_window=0," + - std::to_string(kEmbedTreeWindowId) + - " old_window=" + kNextWindowClientIdString + "," + - std::to_string(embed_child_window_id.sink_id()), - ChangesToDescription1(*wm_client()->tracker()->changes())[0]); - EXPECT_TRUE(embed_client->tracker()->changes()->empty()); - wm_client()->tracker()->changes()->clear(); - - // Set capture from server and ensure embedded tree notified. - EXPECT_TRUE(owning_tree->ReleaseCapture( - ClientWindowIdForWindow(owning_tree, FirstRoot(embed_tree)))); - EXPECT_TRUE(wm_client()->tracker()->changes()->empty()); - ASSERT_TRUE(!embed_client->tracker()->changes()->empty()); - EXPECT_EQ("OnCaptureChanged new_window=null old_window=" + - kWindowManagerClientIdString + ",1", - ChangesToDescription1(*embed_client->tracker()->changes())[0]); -} - -TEST_F(WindowTreeTest, SetModalTypeForwardedToWindowManager) { - TestWindowManager wm_internal; - set_window_manager_internal(wm_tree(), &wm_internal); - - TestWindowTreeBinding* child_binding = nullptr; - WindowTree* child_tree = CreateNewTree(&child_binding); - - // Create a new top level window. - base::flat_map<std::string, std::vector<uint8_t>> properties; - const uint32_t initial_change_id = 17; - // Explicitly use an id that does not contain the client id. - const ClientWindowId embed_window_id2_in_child(child_tree->id(), 27); - static_cast<mojom::WindowTree*>(child_tree) - ->NewTopLevelWindow( - initial_change_id, - child_tree->ClientWindowIdToTransportId(embed_window_id2_in_child), - properties); - - // Create the window for |embed_window_id2_in_child|. - const ClientWindowId embed_window_id2 = BuildClientWindowId(wm_tree(), 2); - EXPECT_TRUE( - wm_tree()->NewWindow(embed_window_id2, ServerWindow::Properties())); - EXPECT_TRUE(wm_tree()->SetWindowVisibility(embed_window_id2, true)); - EXPECT_TRUE(wm_tree()->AddWindow(FirstRootId(wm_tree()), embed_window_id2)); - - // Ack the change, which should resume the binding. - static_cast<mojom::WindowManagerClient*>(wm_tree()) - ->OnWmCreatedTopLevelWindow( - 0u, wm_tree()->ClientWindowIdToTransportId(embed_window_id2)); - - // Change modal type to MODAL_TYPE_SYSTEM and check that it is forwarded to - // the window manager. - child_tree->SetModalType(embed_window_id2_in_child, MODAL_TYPE_SYSTEM); - EXPECT_TRUE(wm_internal.on_set_modal_type_called()); -} - -TEST_F(WindowTreeTest, TestWindowManagerSettingCursorLocation) { - const ClientWindowId embed_window_id = - BuildClientWindowId(wm_tree(), kEmbedTreeWindowId); - EXPECT_TRUE( - wm_tree()->NewWindow(embed_window_id, ServerWindow::Properties())); - ServerWindow* embed_window = wm_tree()->GetWindowByClientId(embed_window_id); - ASSERT_TRUE(embed_window); - EXPECT_TRUE(wm_tree()->SetWindowVisibility(embed_window_id, true)); - ASSERT_TRUE(FirstRoot(wm_tree())); - const ClientWindowId wm_root_id = FirstRootId(wm_tree()); - EXPECT_TRUE(wm_tree()->AddWindow(wm_root_id, embed_window_id)); - ServerWindow* wm_root = FirstRoot(wm_tree()); - ASSERT_TRUE(wm_root); - wm_root->SetBounds(gfx::Rect(0, 0, 100, 100)); - // This tests expects |wm_root| to be a possible target. - wm_root->set_event_targeting_policy( - mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS); - display()->root_window()->SetBounds(gfx::Rect(0, 0, 100, 100)); - mojom::WindowTreeClientPtr client; - wm_client()->Bind(mojo::MakeRequest(&client)); - const uint32_t embed_flags = 0; - wm_tree()->Embed(embed_window_id, std::move(client), embed_flags); - WindowTree* tree1 = window_server()->GetTreeWithRoot(embed_window); - ASSERT_TRUE(tree1 != nullptr); - ASSERT_NE(tree1, wm_tree()); - - embed_window->SetBounds(gfx::Rect(20, 20, 20, 20)); - embed_window->SetCursor(ui::CursorData(ui::CursorType::kIBeam)); - - // Because the cursor is still at the origin, changing the cursor shouldn't - // have switched to ibeam. - EXPECT_EQ(ui::CursorType::kPointer, cursor_type()); - - // Have the window manager move the cursor within the embed window. - static_cast<mojom::WindowManagerClient*>(wm_tree()) - ->WmMoveCursorToDisplayLocation(gfx::Point(21, 21), -1); -} - -TEST_F(WindowTreeTest, TestWindowManagerConfineCursor) { - const gfx::Rect bounds(10, 10, 100, 100); - const int64_t display_id = display()->GetId(); - static_cast<mojom::WindowManagerClient*>(wm_tree())->WmConfineCursorToBounds( - bounds, display_id); - - PlatformDisplay* platform_display = display()->platform_display(); - EXPECT_EQ(bounds, static_cast<TestPlatformDisplay*>(platform_display) - ->confine_cursor_bounds()); -} - -using WindowTreeShutdownTest = testing::Test; - -// Makes sure WindowTreeClient doesn't get any messages during shutdown. -TEST_F(WindowTreeShutdownTest, DontSendMessagesDuringShutdown) { - std::unique_ptr<TestWindowTreeClient> client; - { - // Create a tree with one window. - WindowServerTestHelper ws_test_helper; - WindowServer* window_server = ws_test_helper.window_server(); - TestScreenManager screen_manager; - screen_manager.Init(window_server->display_manager()); - screen_manager.AddDisplay(); - - AddWindowManager(window_server); - TestWindowTreeBinding* test_binding = - ws_test_helper.window_server_delegate()->last_binding(); - ASSERT_TRUE(test_binding); - WindowTree* tree = test_binding->tree(); - const ClientWindowId window_id = BuildClientWindowId(tree, 2); - ASSERT_TRUE(tree->NewWindow(window_id, ServerWindow::Properties())); - - // Release the client so that it survices shutdown. - client = test_binding->ReleaseClient(); - client->tracker()->changes()->clear(); - } - - // Client should not have got any messages after shutdown. - EXPECT_TRUE(client->tracker()->changes()->empty()); -} - -// Used to test the window manager configured to manually create displays roots. -class WindowTreeManualDisplayTest : public TaskRunnerTestBase { - public: - WindowTreeManualDisplayTest() {} - ~WindowTreeManualDisplayTest() override {} - - WindowServer* window_server() { return ws_test_helper_.window_server(); } - DisplayManager* display_manager() { - return window_server()->display_manager(); - } - TestWindowServerDelegate* window_server_delegate() { - return ws_test_helper_.window_server_delegate(); - } - TestScreenManager& screen_manager() { return screen_manager_; } - - protected: - // testing::Test: - void SetUp() override { - TaskRunnerTestBase::SetUp(); - screen_manager_.Init(window_server()->display_manager()); - } - - private: - WindowServerTestHelper ws_test_helper_; - TestScreenManager screen_manager_; - - DISALLOW_COPY_AND_ASSIGN(WindowTreeManualDisplayTest); -}; - -TEST_F(WindowTreeManualDisplayTest, ClientCreatesDisplayRoot) { - const bool automatically_create_display_roots = false; - AddWindowManager(window_server(), automatically_create_display_roots); - - WindowManagerState* window_manager_state = - window_server()->GetWindowManagerState(); - ASSERT_TRUE(window_manager_state); - WindowTree* window_manager_tree = window_manager_state->window_tree(); - EXPECT_TRUE(window_manager_tree->roots().empty()); - TestWindowManager* test_window_manager = - window_server_delegate()->last_binding()->window_manager(); - EXPECT_EQ(1, test_window_manager->connect_count()); - EXPECT_EQ(0, test_window_manager->display_added_count()); - - // Create a window for the windowmanager and set it as the root. - ClientWindowId display_root_id = BuildClientWindowId(window_manager_tree, 10); - ASSERT_TRUE(window_manager_tree->NewWindow(display_root_id, - ServerWindow::Properties())); - ServerWindow* display_root = - window_manager_tree->GetWindowByClientId(display_root_id); - ASSERT_TRUE(display_root); - display::Display display1 = MakeDisplay(0, 0, 1024, 768, 1.0f); - display1.set_id(101); - - display::ViewportMetrics metrics; - metrics.bounds_in_pixels = display1.bounds(); - metrics.device_scale_factor = 1.5; - metrics.ui_scale_factor = 2.5; - const bool is_primary_display = true; - ASSERT_TRUE(WindowTreeTestApi(window_manager_tree) - .ProcessSetDisplayRoot(display1, metrics, is_primary_display, - display_root_id)); - EXPECT_TRUE(display_root->parent()); - EXPECT_TRUE(window_server_delegate() - ->last_binding() - ->client() - ->tracker() - ->changes() - ->empty()); - EXPECT_EQ(1u, window_manager_tree->roots().size()); - - // Delete the root, which should delete the WindowManagerDisplayRoot. - EXPECT_TRUE(window_manager_tree->DeleteWindow(display_root_id)); - EXPECT_TRUE(window_manager_tree->roots().empty()); - EXPECT_TRUE(WindowManagerStateTestApi(window_manager_state) - .window_manager_display_roots() - .empty()); -} - -TEST_F(WindowTreeManualDisplayTest, MoveDisplayRootToNewDisplay) { - const bool automatically_create_display_roots = false; - AddWindowManager(window_server(), automatically_create_display_roots); - - WindowManagerState* window_manager_state = - window_server()->GetWindowManagerState(); - ASSERT_TRUE(window_manager_state); - WindowTree* window_manager_tree = window_manager_state->window_tree(); - EXPECT_TRUE(window_manager_tree->roots().empty()); - TestWindowManager* test_window_manager = - window_server_delegate()->last_binding()->window_manager(); - EXPECT_EQ(1, test_window_manager->connect_count()); - EXPECT_EQ(0, test_window_manager->display_added_count()); - - // Create a window for the windowmanager and set it as the root. - ClientWindowId display_root_id = BuildClientWindowId(window_manager_tree, 10); - ASSERT_TRUE(window_manager_tree->NewWindow(display_root_id, - ServerWindow::Properties())); - ServerWindow* display_root = - window_manager_tree->GetWindowByClientId(display_root_id); - ASSERT_TRUE(display_root); - display::Display display1 = MakeDisplay(0, 0, 1024, 768, 1.0f); - constexpr int64_t display1_id = 101; - display1.set_id(display1_id); - - display::ViewportMetrics metrics; - metrics.bounds_in_pixels = display1.bounds(); - metrics.device_scale_factor = 1.5; - metrics.ui_scale_factor = 2.5; - const bool is_primary_display = true; - ASSERT_TRUE(WindowTreeTestApi(window_manager_tree) - .ProcessSetDisplayRoot(display1, metrics, is_primary_display, - display_root_id)); - ASSERT_TRUE(display_root->parent()); - const viz::FrameSinkId display1_parent_id = - display_root->parent()->frame_sink_id(); - EXPECT_TRUE(window_server_delegate() - ->last_binding() - ->client() - ->tracker() - ->changes() - ->empty()); - EXPECT_EQ(1u, window_manager_tree->roots().size()); - - // Call ProcessSetDisplayRoot() again, with a different display. - display::Display display2 = MakeDisplay(0, 0, 1024, 768, 1.0f); - constexpr int64_t display2_id = 102; - display2.set_id(display2_id); - ASSERT_TRUE(WindowTreeTestApi(window_manager_tree) - .ProcessSetDisplayRoot(display2, metrics, is_primary_display, - display_root_id)); - ASSERT_TRUE(display_root->parent()); - EXPECT_NE(display1_parent_id, display_root->parent()->frame_sink_id()); - EXPECT_TRUE(window_server_delegate() - ->last_binding() - ->client() - ->tracker() - ->changes() - ->empty()); - EXPECT_EQ(1u, window_manager_tree->roots().size()); - // The WindowManagerDisplayRoot for |display1| should have been deleted. - EXPECT_EQ(1u, WindowManagerStateTestApi(window_manager_state) - .window_manager_display_roots() - .size()); - EXPECT_FALSE(window_server()->display_manager()->GetDisplayById(display1_id)); - EXPECT_TRUE(window_server()->display_manager()->GetDisplayById(display2_id)); - - // Delete the root, which should delete the WindowManagerDisplayRoot. - EXPECT_TRUE(window_manager_tree->DeleteWindow(display_root_id)); - EXPECT_TRUE(window_manager_tree->roots().empty()); - EXPECT_TRUE(WindowManagerStateTestApi(window_manager_state) - .window_manager_display_roots() - .empty()); -} - -TEST_F(WindowTreeManualDisplayTest, - DisplayManagerObserverNotifiedWithManualRoots) { - const bool automatically_create_display_roots = false; - AddWindowManager(window_server(), automatically_create_display_roots); - - TestScreenProviderObserver screen_provider_observer; - DisplayManager* display_manager = window_server()->display_manager(); - UserDisplayManager* user_display_manager = - display_manager->GetUserDisplayManager(); - ASSERT_TRUE(user_display_manager); - user_display_manager->AddObserver(screen_provider_observer.GetPtr()); - - // Observer should not have been notified yet. - // - // NOTE: the RunUntilIdle() calls are necessary anytime the calls are checked - // as the observer is called via mojo, which is async. - RunUntilIdle(); - EXPECT_TRUE(screen_provider_observer.GetAndClearObserverCalls().empty()); - - // Set frame decorations, again observer should not be notified. - WindowManagerState* window_manager_state = - window_server()->GetWindowManagerState(); - ASSERT_TRUE(window_manager_state); - WindowTree* window_manager_tree = window_manager_state->window_tree(); - window_manager_state->SetFrameDecorationValues( - mojom::FrameDecorationValues::New()); - RunUntilIdle(); - EXPECT_TRUE(screen_provider_observer.GetAndClearObserverCalls().empty()); - - // Create a window for the windowmanager and set it as the root. - ClientWindowId display_root_id = BuildClientWindowId(window_manager_tree, 10); - ASSERT_TRUE(window_manager_tree->NewWindow(display_root_id, - ServerWindow::Properties())); - ServerWindow* display_root = - window_manager_tree->GetWindowByClientId(display_root_id); - ASSERT_TRUE(display_root); - RunUntilIdle(); - EXPECT_TRUE(screen_provider_observer.GetAndClearObserverCalls().empty()); - - // Add a new display. - // The value for the scale factor doesn't matter, just choosing something - // other than 1 to ensure values other than 1 correctly take. - const float kDisplay1ScaleFactor = 2.25; - display::Display display1 = - MakeDisplay(0, 0, 1024, 768, kDisplay1ScaleFactor); - const int64_t display_id1 = 101; - display1.set_id(display_id1); - display::ViewportMetrics metrics1; - metrics1.bounds_in_pixels = display1.bounds(); - metrics1.device_scale_factor = kDisplay1ScaleFactor; - metrics1.ui_scale_factor = 2.5; - const bool is_primary_display = true; - ASSERT_TRUE(WindowTreeTestApi(window_manager_tree) - .ProcessSetDisplayRoot(display1, metrics1, is_primary_display, - display_root_id)); - RunUntilIdle(); - EXPECT_TRUE(screen_provider_observer.GetAndClearObserverCalls().empty()); - - // Configure the displays, updating the bounds of the first display. - std::vector<display::Display> displays; - displays.push_back(display1); - std::vector<display::ViewportMetrics> viewport_metrics; - viewport_metrics.push_back(metrics1); - const gfx::Rect updated_bounds(1, 2, 3, 4); - viewport_metrics[0].bounds_in_pixels = updated_bounds; - std::vector<display::Display> mirrors; - ASSERT_TRUE(display_manager->SetDisplayConfiguration( - displays, viewport_metrics, display_id1, display::kInvalidDisplayId, - mirrors)); - RunUntilIdle(); - EXPECT_EQ("OnDisplaysChanged " + std::to_string(display_id1) + " " + - std::to_string(display::kInvalidDisplayId), - screen_provider_observer.GetAndClearObserverCalls()); - PlatformDisplay* platform_display1 = - display_manager->GetDisplayById(display_id1)->platform_display(); - ASSERT_TRUE(platform_display1); - EXPECT_EQ( - kDisplay1ScaleFactor * ui::mojom::kCursorMultiplierForExternalDisplays, - static_cast<TestPlatformDisplay*>(platform_display1)->cursor_scale()); - EXPECT_EQ(updated_bounds, static_cast<TestPlatformDisplay*>(platform_display1) - ->metrics() - .bounds_in_pixels); - - // Create a window for the windowmanager and set it as the root. - ClientWindowId display_root_id2 = - BuildClientWindowId(window_manager_tree, 11); - ASSERT_TRUE(window_manager_tree->NewWindow(display_root_id2, - ServerWindow::Properties())); - ServerWindow* display_root2 = - window_manager_tree->GetWindowByClientId(display_root_id); - ASSERT_TRUE(display_root2); - RunUntilIdle(); - EXPECT_TRUE(screen_provider_observer.GetAndClearObserverCalls().empty()); - - // Add another display. - const float kDisplay2ScaleFactor = 1.75; - display::Display display2 = - MakeDisplay(0, 0, 1024, 768, kDisplay2ScaleFactor); - const int64_t display_id2 = 102; - display2.set_id(display_id2); - display::ViewportMetrics metrics2; - metrics2.bounds_in_pixels = display2.bounds(); - metrics2.device_scale_factor = kDisplay2ScaleFactor; - metrics2.ui_scale_factor = 2.5; - ASSERT_TRUE( - WindowTreeTestApi(window_manager_tree) - .ProcessSetDisplayRoot(display2, metrics2, false, display_root_id2)); - RunUntilIdle(); - EXPECT_TRUE(screen_provider_observer.GetAndClearObserverCalls().empty()); - - // Make |display2| the default, and resize both displays. - display1.set_bounds(gfx::Rect(0, 0, 1024, 1280)); - metrics1.bounds_in_pixels = display1.bounds(); - displays.clear(); - displays.push_back(display1); - - display2.set_bounds(gfx::Rect(0, 0, 500, 600)); - metrics2.bounds_in_pixels = display2.bounds(); - displays.push_back(display2); - - viewport_metrics.clear(); - viewport_metrics.push_back(metrics1); - viewport_metrics.push_back(metrics2); - ASSERT_TRUE(display_manager->SetDisplayConfiguration( - displays, viewport_metrics, display_id2, display_id2, mirrors)); - RunUntilIdle(); - EXPECT_EQ("OnDisplaysChanged " + std::to_string(display_id1) + " " + - std::to_string(display_id2) + " " + std::to_string(display_id2), - screen_provider_observer.GetAndClearObserverCalls()); - EXPECT_EQ( - kDisplay1ScaleFactor * ui::mojom::kCursorMultiplierForExternalDisplays, - static_cast<TestPlatformDisplay*>(platform_display1)->cursor_scale()); - PlatformDisplay* platform_display2 = - display_manager->GetDisplayById(display_id2)->platform_display(); - ASSERT_TRUE(platform_display2); - EXPECT_EQ( - kDisplay2ScaleFactor, - static_cast<TestPlatformDisplay*>(platform_display2)->cursor_scale()); - - // Delete the second display, no notification should be sent. - EXPECT_TRUE(window_manager_tree->DeleteWindow(display_root_id2)); - RunUntilIdle(); - EXPECT_TRUE(screen_provider_observer.GetAndClearObserverCalls().empty()); - EXPECT_FALSE(display_manager->GetDisplayById(display_id2)); - - // Set the config back to only the first. - displays.clear(); - displays.push_back(display1); - - viewport_metrics.clear(); - viewport_metrics.push_back(metrics1); - ASSERT_TRUE(display_manager->SetDisplayConfiguration( - displays, viewport_metrics, display_id1, display_id1, mirrors)); - RunUntilIdle(); - EXPECT_EQ("OnDisplaysChanged " + std::to_string(display_id1) + " " + - std::to_string(display_id1), - screen_provider_observer.GetAndClearObserverCalls()); - - // The display list should not have display2. - display::DisplayList& display_list = - display::ScreenManager::GetInstance()->GetScreen()->display_list(); - EXPECT_TRUE(display_list.FindDisplayById(display_id2) == - display_list.displays().end()); - ASSERT_TRUE(display_list.GetPrimaryDisplayIterator() != - display_list.displays().end()); - EXPECT_EQ(display_id1, display_list.GetPrimaryDisplayIterator()->id()); -} - -TEST_F(WindowTreeManualDisplayTest, SwapDisplayRoots) { - const bool automatically_create_display_roots = false; - AddWindowManager(window_server(), automatically_create_display_roots); - - WindowManagerState* window_manager_state = - window_server()->GetWindowManagerState(); - ASSERT_TRUE(window_manager_state); - WindowTree* window_manager_tree = window_manager_state->window_tree(); - window_manager_state->SetFrameDecorationValues( - mojom::FrameDecorationValues::New()); - - // Add two windows for the two displays. - ClientWindowId display_root_id1 = - BuildClientWindowId(window_manager_tree, 10); - ASSERT_TRUE(window_manager_tree->NewWindow(display_root_id1, - ServerWindow::Properties())); - ServerWindow* display_root1 = - window_manager_tree->GetWindowByClientId(display_root_id1); - ASSERT_TRUE(display_root1); - - ClientWindowId display_root_id2 = - BuildClientWindowId(window_manager_tree, 20); - ASSERT_TRUE(window_manager_tree->NewWindow(display_root_id2, - ServerWindow::Properties())); - ServerWindow* display_root2 = - window_manager_tree->GetWindowByClientId(display_root_id2); - ASSERT_TRUE(display_root2); - EXPECT_NE(display_root1, display_root2); - - // Add two displays. - const int64_t display_id1 = 101; - display::Display display1 = MakeDisplay(0, 0, 1024, 768, 1.0f); - display1.set_id(display_id1); - display::ViewportMetrics metrics; - metrics.bounds_in_pixels = display1.bounds(); - metrics.device_scale_factor = 1.5; - metrics.ui_scale_factor = 2.5; - const bool is_primary_display = true; - ASSERT_TRUE(WindowTreeTestApi(window_manager_tree) - .ProcessSetDisplayRoot(display1, metrics, is_primary_display, - display_root_id1)); - - display::Display display2 = MakeDisplay(0, 0, 1024, 768, 1.0f); - const int64_t display_id2 = 102; - display2.set_id(display_id2); - ASSERT_TRUE(WindowTreeTestApi(window_manager_tree) - .ProcessSetDisplayRoot(display2, metrics, is_primary_display, - display_root_id2)); - - ServerWindow* display_root1_parent = display_root1->parent(); - ServerWindow* display_root2_parent = display_root2->parent(); - ASSERT_TRUE(WindowTreeTestApi(window_manager_tree) - .ProcessSwapDisplayRoots(display_id1, display_id2)); - EXPECT_EQ(display_root1_parent, display_root2->parent()); - EXPECT_EQ(display_root2_parent, display_root1->parent()); -} - -TEST_F(WindowTreeTest, EmbedFlagEmbedderControlsVisibility) { - const ClientWindowId embed_window_id = - BuildClientWindowId(wm_tree(), kEmbedTreeWindowId); - EXPECT_TRUE( - wm_tree()->NewWindow(embed_window_id, ServerWindow::Properties())); - ServerWindow* embed_window = wm_tree()->GetWindowByClientId(embed_window_id); - ASSERT_TRUE(embed_window); - EXPECT_TRUE(wm_tree()->AddWindow(FirstRootId(wm_tree()), embed_window_id)); - mojom::WindowTreeClientPtr client; - wm_client()->Bind(mojo::MakeRequest(&client)); - const uint32_t embed_flags = mojom::kEmbedFlagEmbedderControlsVisibility; - wm_tree()->Embed(embed_window_id, std::move(client), embed_flags); - WindowTree* tree1 = window_server()->GetTreeWithRoot(embed_window); - ASSERT_TRUE(tree1); - // |tree1| should not be able to control the visibility of its root because - // |kEmbedFlagEmbedderControlsVisibility| was specified. - EXPECT_FALSE(tree1->SetWindowVisibility( - ClientWindowIdForWindow(tree1, embed_window), false)); - const ClientWindowId child_window_id = BuildClientWindowId(tree1, 101); - // But |tree1| can control the visibility of any windows it creates. - EXPECT_TRUE(tree1->NewWindow(child_window_id, ServerWindow::Properties())); - EXPECT_TRUE(tree1->SetWindowVisibility(child_window_id, true)); -} - -TEST_F(WindowTreeTest, PerformWmAction) { - TestWindowManager wm_internal; - set_window_manager_internal(wm_tree(), &wm_internal); - - TestWindowTreeBinding* child_binding = nullptr; - WindowTree* child_tree = CreateNewTree(&child_binding); - - // Create a new top level window. - base::flat_map<std::string, std::vector<uint8_t>> properties; - const uint32_t initial_change_id = 17; - // Explicitly use an id that does not contain the client id. - const ClientWindowId embed_window_id2_in_child(child_tree->id(), 27); - static_cast<mojom::WindowTree*>(child_tree) - ->NewTopLevelWindow( - initial_change_id, - child_tree->ClientWindowIdToTransportId(embed_window_id2_in_child), - properties); - - // Create the window for |embed_window_id2_in_child|. - const ClientWindowId embed_window_id2 = BuildClientWindowId(wm_tree(), 2); - EXPECT_TRUE( - wm_tree()->NewWindow(embed_window_id2, ServerWindow::Properties())); - EXPECT_TRUE(wm_tree()->SetWindowVisibility(embed_window_id2, true)); - EXPECT_TRUE(wm_tree()->AddWindow(FirstRootId(wm_tree()), embed_window_id2)); - - // Ack the change, which should resume the binding. - static_cast<mojom::WindowManagerClient*>(wm_tree()) - ->OnWmCreatedTopLevelWindow( - 0u, wm_tree()->ClientWindowIdToTransportId(embed_window_id2)); - - static_cast<mojom::WindowTree*>(child_tree) - ->PerformWmAction( - child_tree->ClientWindowIdToTransportId(embed_window_id2_in_child), - "test-action"); - EXPECT_EQ("test-action", wm_internal.last_wm_action()); -} - -TEST_F(WindowTreeTest, EmbedderInterceptsEventsSeesWindowsInEmbeddedClients) { - // Make the root visible and give it bounds. - ServerWindow* wm_root = FirstRoot(wm_tree()); - ASSERT_TRUE(wm_root); - const gfx::Rect bounds(0, 0, 20, 20); - wm_root->SetBounds(bounds); - wm_root->SetVisible(true); - - // Create window for embedded (|w1|). - ClientWindowId w1_id; - ServerWindow* w1 = - NewWindowInTreeWithParent(wm_tree(), wm_root, &w1_id, bounds); - ASSERT_TRUE(w1); - - // Embed a new client in |w1|. - TestWindowTreeBinding* embed_binding1 = - test_window_server_delegate()->Embed(wm_tree(), w1); - // Set the |is_for_embedding| to false, otherwise - // kEmbedFlagEmbedderInterceptsEvents is ignored - WindowTreeTestApi(embed_binding1->tree()).set_is_for_embedding(false); - ASSERT_TRUE(embed_binding1); - - // Create |w2| (in the embedded tree). - ClientWindowId w2_id; - ServerWindow* w2 = - NewWindowInTreeWithParent(embed_binding1->tree(), w1, &w2_id, bounds); - ASSERT_TRUE(w2); - - // Embed a new client in |w2|. - TestWindowTreeBinding* embed_binding2 = test_window_server_delegate()->Embed( - embed_binding1->tree(), w2, mojom::kEmbedFlagEmbedderInterceptsEvents); - ASSERT_TRUE(embed_binding2); - - // Create |w3| as a child of |w2|. - ClientWindowId w3_id; - ServerWindow* w3 = - NewWindowInTreeWithParent(embed_binding2->tree(), w2, &w3_id, bounds); - ASSERT_TRUE(w3); - - // Embed a new client in |w3|. - TestWindowTreeBinding* embed_binding3 = - test_window_server_delegate()->Embed(embed_binding2->tree(), w3); - ASSERT_TRUE(embed_binding3); - - // Create |w4| as a child of |w3|. - ClientWindowId w4_id; - ServerWindow* w4 = - NewWindowInTreeWithParent(embed_binding3->tree(), w3, &w4_id, bounds); - ASSERT_TRUE(w4); - - // |w4| and |w3| should be known to embed_binding1->tree() because of - // kEmbedFlagEmbedderInterceptsEvents. |w3| should not be known to - // embed_binding2->tree(), because it has an invalid user id. - EXPECT_TRUE(embed_binding1->tree()->IsWindowKnown(w3, nullptr)); - ClientWindowId w4_in_tree1_id; - EXPECT_TRUE(embed_binding1->tree()->IsWindowKnown(w4, &w4_in_tree1_id)); - EXPECT_FALSE(embed_binding2->tree()->IsWindowKnown(w4, nullptr)); - - // Verify an event targetting |w4| goes to embed_binding1->tree(). - embed_binding1->client()->tracker()->changes()->clear(); - AckPreviousEvent(); - DispatchEventWithoutAck(CreatePointerDownEvent(5, 5)); - WindowManagerStateTestApi wm_state_test_api( - wm_tree()->window_manager_state()); - EXPECT_EQ(embed_binding1->tree(), - wm_state_test_api.tree_awaiting_input_ack()); - // Event targets |w4|, but goes to embed_binding1->tree() (because of - // kEmbedFlagEmbedderInterceptsEvents). - EXPECT_EQ(1u, embed_binding1->client()->tracker()->changes()->size()); - EXPECT_EQ("InputEvent window=" + ClientWindowIdToString(w4_in_tree1_id) + - " event_action=" + std::to_string(ui::ET_POINTER_DOWN), - SingleChangeToDescription( - *embed_binding1->client()->tracker()->changes())); -} - -} // namespace test -} // namespace ws -} // namespace ui
diff --git a/services/ui/ws2/README.md b/services/ui/ws2/README.md index 6b4e03e..4db4a1ac 100644 --- a/services/ui/ws2/README.md +++ b/services/ui/ws2/README.md
@@ -23,3 +23,83 @@ draw to the screen (using Viz). This is mostly seamless to the tap_visualizer. The tap_visualizer configures Views to use Mus, which results in Views and Aura, using the WindowService. + +## Ids + +Each client connected to the Window Service is assigned a unique id inside the +Window Service. This id is a monotonically increasing uint32_t. This is often +referred to as the client_id. + +As clients do not know their id, they always supply 0 as the client id in the +mojom related functions. Internally the Window Service maps 0 to the real client +id. + +Windows have a couple of different (related) ids. + +### ClientWindowId + +ClientWindowId is a uint64_t pairing of a client_id and a window_id. The +window_id is a uint32_t assigned by the client, and should be unique within that +client's scope. When communicating with the Window Service, clients may use 0 as +the client_id to refer to their own windows. The Window Service maps 0 to the +real client_id. In Window Service code the id from the client is typically +referred to as the transport_window_id. Mojom functions that receive the +transport_window_id map it to a ClientWindowId. ClientWindowId is a real class +that provides type safety. + +When a client is embedded in an existing window, the embedded client is given +visibility to a Window created by the embedder. In this case the Window Service +supplies the ClientWindowId to the embedded client and uses the ClientWindowId +at the time the Window was created (the ClientWindowId actually comes from the +FrameSinkId, see below for details on FrameSinkId). In other words, both the +embedder and embedded client use the same ClientWindowId for the Window. See +discussion on FrameSinkId for more details. + +For a client to establish an embed root, it first calls +ScheduleEmbedForExistingClient(), so it can provide a window_id that is unique +within its own scope. That client then passes the returned token to what will +become its embedder to call EmbedUsingToken(). In this case, the embedder and +embedded client do not use the same ClientWindowId for the Window. + +ClientWindowId is globally unique, but a Window may have multiple +ClientWindowIds associated with it. + +### FrameSinkId + +Each Window has a FrameSinkId that is needed for both hit-testing and +embedding. The FrameSinkId is initialized to the ClientWindowId of the client +creating the Window, but it changes during an embedding. In particular, when a +client calls Embed() the FrameSinkId of the Window changes such that the +client_id of the FrameSinkId matches the client_id of the client being +embedded and the sink_id is set to 0. The embedder is informed of this by way of +OnFrameSinkIdAllocated(). The embedded client is informed of the original +FrameSinkId (the client_id of the FrameSinkId matches the embedder's client_id). +In client code the embedded client ends up *always* using a client_id of 0 for +the FrameSinkId. This works because Viz knows the real client_id and handles +mapping 0 to the real client_id. + +The FrameSinkId of top-level windows is set to the ClientWindowId from the +client requesting the top-level (top-levels are created and owned by the Window +Manager). The Window Manager is told the updated FrameSinkId when it is asked +to create the top-level (WmCreateTopLevelWindow()). + +The FrameSinkId of an embed root's Window is set to the ClientWindowId of the +embed root's Window from the embedded client. + +### LocalSurfaceId + +The LocalSurfaceId (which contains unguessable) is necessary if the client wants +to submit a compositor-frame for the Window (it wants to show something on +screen), and not needed if the client only wants to submit a hit-test region. +The LocalSurfaceId may be assigned when the bounds and/or device-scale-factor +changes. The LocalSurfaceId can change at other times as well (perhaps to +synchronize an effect with the embedded client). The LocalSurfaceId is intended +to allow for smooth resizes and ensures at embed points the CompositorFrame from +both clients match. Client code supplies a LocalSurfaceId for windows that have +another client embedded in them as well as windows with a LayerTreeFrameSink. +The LocalSurfaceId comes from the owner of the window. The embedded client is +told of changes to the LocalSurfaceId by way of OnWindowBoundsChanged(). This is +still very much a work in progress. + +FrameSinkId is derived from the embedded client, where as LocalSurfaceId +comes from the embedder.
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index 843086b..95d1709 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -2693,6 +2693,151 @@ "libANGLE" ] }, + "android-mojo-webview-rel": { + "gtest_tests": [ + { + "args": [ + "--enable-features=NetworkService", + "--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter", + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "network_service_content_browsertests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "name": "network_service_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "MMB29Q", + "device_type": "bullhead", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "shards": 5 + }, + "test": "content_browsertests" + }, + { + "args": [ + "--enable-surface-synchronization", + "--test-launcher-filter-file=../../testing/buildbot/filters/surface_sync.content_browsertests.filter", + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "surface_sync_content_browsertests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "name": "surface_sync_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "MMB29Q", + "device_type": "bullhead", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "shards": 2 + }, + "test": "content_browsertests" + }, + { + "args": [ + "--enable-features=VizDisplayCompositor", + "--test-launcher-filter-file=../../testing/buildbot/filters/viz.android.content_browsertests.filter", + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "viz_content_browsertests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "name": "viz_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "MMB29Q", + "device_type": "bullhead", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "shards": 2 + }, + "test": "content_browsertests" + } + ] + }, "chromeos-amd64-generic-rel-goma-canary": { "additional_compile_targets": [ "chromiumos_preflight" @@ -2704,6 +2849,24 @@ ], "gtest_tests": [ { + "args": [ + "--ozone-platform=headless" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "kvm": "1", + "os": "Ubuntu-14.04", + "pool": "Chrome-CrOS-VM" + } + ], + "hard_timeout": 3600, + "io_timeout": 3600 + }, + "test": "aura_unittests" + }, + { "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [
diff --git a/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter b/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter index 6c2e0d08..29edda3 100644 --- a/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter +++ b/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter
@@ -212,15 +212,6 @@ # Note WebRequestUnloadImmediately is disabled on Linux -ExtensionWebRequestApiTest.WebRequestUnloadImmediately -# WebRequest implementation needs to handle extension -# installation/uninstallation events. -# http://crbug.com/857577 --BackgroundXhrTest.HttpAuth --BackgroundXhrTest.TlsClientAuth - -# http://crbug.com/853733 --DeclarativeNetRequestBrowserTest.PageAllowingAPI_BrowserRequests/0 - # http://crbug.com/705114 # Remove streams concept from code and replace with data pipe passing. -MimeHandlerViewTests/MimeHandlerViewTest.Abort/0
diff --git a/testing/buildbot/filters/viz.android.content_browsertests.filter b/testing/buildbot/filters/viz.android.content_browsertests.filter index ec4ec9d..6b5a0e2 100644 --- a/testing/buildbot/filters/viz.android.content_browsertests.filter +++ b/testing/buildbot/filters/viz.android.content_browsertests.filter
@@ -1,16 +1,4 @@ # Android Failures # Flaky failures with incorrect Input event acks. https://crbug.com/855532 -TouchInputBrowserTest.TouchHandlerConsume --TouchInputBrowserTest.TouchHandlerNoConsume - -## Base viz.content_browsertests.filter since we cannot chain filter files -#### Hit Testing -# Test failure: https://crbug.com/848325 --SitePerProcessHitTestBrowserTest.RootConsumesScrollDuringOverscrollGesture* - -# InputEventAckWaiter never receives the event: https://crbug.com/848348 --SitePerProcessHitTestBrowserTest.CrossProcessMouseEnterAndLeaveTest* --SitePerProcessHitTestBrowserTest.CrossProcessMouseCapture* - -# /2 Variant does not handle overlapping surfaces: https://crbug.com/846798 --SitePerProcessHitTestBrowserTest.HitTestStaleDataDeletedView* +-TouchInputBrowserTest.TouchHandlerNoConsume \ No newline at end of file
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index 41a695a..6d75618 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -352,6 +352,11 @@ }, 'chromeos_gtests_experimental': { + 'aura_unittests': { + 'args': [ + '--ozone-platform=headless', + ], + }, 'base_unittests': {}, 'chromeos_unittests': { 'args': [
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl index 1112a6f..99028e3 100644 --- a/testing/buildbot/waterfalls.pyl +++ b/testing/buildbot/waterfalls.pyl
@@ -2427,6 +2427,21 @@ '--enable-features=ViewsBrowserWindows', ], }, + 'android-mojo-webview-rel': { + 'swarming': { + 'dimension_sets': [ + { + 'device_os': 'MMB29Q', + 'device_type': 'bullhead', + 'os': 'Android', + }, + ], + }, + 'os_type': 'android', + 'test_suites': { + 'gtest_tests': 'mojo_android_gtests', + }, + }, 'Mojo Android': { 'swarming': { 'dimension_sets': [
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 be44df14..b92d190 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-gen-property-trees +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-gen-property-trees
@@ -36,7 +36,6 @@ Bug(none) imagecapture/ [ Skip ] Bug(none) inspector-protocol/ [ Skip ] Bug(none) installedapp/ [ Skip ] -Bug(none) intersection-observer/ [ Skip ] Bug(none) jquery/ [ Skip ] Bug(none) loader/ [ Skip ] Bug(none) mathml/ [ Skip ] @@ -48,7 +47,6 @@ Bug(none) navigator_webdriver/ [ Skip ] Bug(none) netinfo/ [ Skip ] Bug(none) nfc/ [ Skip ] -Bug(none) overflow/ [ Skip ] Bug(none) payments/ [ Skip ] Bug(none) performance/ [ Skip ] Bug(none) permissionclient/ [ Skip ] @@ -61,7 +59,6 @@ Bug(none) resize-observer/ [ Skip ] Bug(none) resources/ [ Skip ] Bug(none) screen_orientation/ [ Skip ] -Bug(none) scrollingcoordinator/ [ Skip ] Bug(none) security/ [ Skip ] Bug(none) sensor/ [ Skip ] Bug(none) shadow-dom/ [ Skip ] @@ -69,7 +66,6 @@ Bug(none) storage/ [ Skip ] Bug(none) tables/ [ Skip ] Bug(none) third_party/ [ Skip ] -Bug(none) touchadjustment/ [ Skip ] Bug(none) transforms/ [ Skip ] Bug(none) traversal/ [ Skip ] Bug(none) typedcssom/ [ Skip ] @@ -86,8 +82,6 @@ Bug(none) virtual/gpu-rasterization/ [ Skip ] Bug(none) virtual/gpu/ [ Skip ] Bug(none) virtual/high-contrast-mode/ [ Skip ] -Bug(none) virtual/sxg-with-network-service/ [ Skip ] -Bug(none) virtual/sxg/ [ Skip ] Bug(none) virtual/import-meta-url/ [ Skip ] Bug(none) virtual/layout_ng/ [ Skip ] Bug(none) virtual/layout_ng_experimental/ [ Skip ] @@ -115,6 +109,8 @@ Bug(none) virtual/single-renderer-process/ [ Skip ] Bug(none) virtual/spv2/ [ Skip ] Bug(none) virtual/stable/ [ Skip ] +Bug(none) virtual/sxg-with-network-service/ [ Skip ] +Bug(none) virtual/sxg/ [ Skip ] Bug(none) virtual/targetedstylerecalc/ [ Skip ] Bug(none) virtual/unified-autoplay/ [ Skip ] Bug(none) virtual/video-surface-layer/ [ Skip ] @@ -131,10 +127,6 @@ Bug(none) xmlviewer/ [ Skip ] Bug(none) xr/ [ Skip ] -# These tests should also pass. TODO(pdr): Enable these tests. -Bug(none) virtual/scroll_customization/ [ Skip ] -Bug(none) virtual/threaded/ [ Skip ] - # These tests failed in normal mode but are fixed with BlinkGenPropertyTrees. Bug(none) compositing/overflow/clip-escaping-reverse-order-should-not-crash.html [ Pass ] Bug(none) compositing/overflow/composited-scroll-with-fractional-translation.html [ Pass ] @@ -143,9 +135,6 @@ # These animation/transition tests should pass. Bug(none) animations/ [ Pass ] Bug(none) transitions/ [ Pass ] -Bug(none) virtual/threaded/animations/ [ Pass ] -Bug(none) virtual/threaded/transitions/ [ Pass ] -Bug(none) virtual/threaded/fast/animationworklet/ [ Pass ] # crbug.com/836897 - covers 855688,855691,855702,855718 crbug.com/855688 transitions/opacity-transform-transitions-inside-iframe.html [ Timeout ] @@ -175,10 +164,10 @@ crbug.com/836912 paint/overflow/composited-scroll-vertical-rl.html [ Failure ] # These scrolling tests should pass. -Bug(none) virtual/threaded/fast/scrolling [ Pass ] -Bug(none) virtual/threaded/fast/events [ Pass ] +Bug(none) virtual/threaded/ [ Pass ] Bug(none) fast/scrolling [ Pass ] Bug(none) fast/events [ Pass ] +Bug(none) virtual/scroll_customization/ [ Pass ] crbug.com/840017 virtual/threaded/fast/events/pinch/gesture-pinch-zoom-prevent-in-handler.html [ Failure ] crbug.com/840017 virtual/threaded/fast/events/pinch/gesture-pinch-zoom-scroll-bubble.html [ Failure Crash ] crbug.com/836913 virtual/threaded/fast/scrolling/background-paint-scrolled.html [ Failure Pass Crash ] @@ -187,6 +176,9 @@ crbug.com/836913 virtual/threaded/fast/scrolling/overflow-scrollability.html [ Failure Pass ] crbug.com/836913 virtual/threaded/fast/scrolling/overlay-scrollbars.html [ Failure Crash ] crbug.com/845635 virtual/threaded/fast/events/pinch/scroll-visual-viewport-send-boundary-events.html [ Failure ] +crbug.com/866051 virtual/threaded/fast/scroll-behavior/overscroll-behavior.html [ Failure ] +crbug.com/836913 virtual/threaded/fast/scroll-behavior/smooth-scroll-overflow-hidden.html [ Crash ] +crbug.com/836913 virtual/threaded/external/wpt/css/css-scroll-snap/snap-at-user-scroll-end-manual.html [ Timeout ] # These visual viewport tests should pass. Bug(none) external/wpt/visual-viewport [ Pass ] @@ -387,7 +379,6 @@ Bug(none) compositing/gestures/gesture-tapHighlight-with-squashing.html [ Failure ] Bug(none) compositing/masks/mask-with-removed-filters.html [ Failure ] Bug(none) compositing/video/video-controls-layer-creation.html [ Failure Pass ] -Bug(none) compositing/visibility/visibility-image-layers.html [ Failure ] # Rounded borders have slightly different antialiasing Bug(none) compositing/composited-scaled-child-with-border-radius-parent-clip.html [ Failure ] @@ -487,6 +478,8 @@ # Image layers are not scaled. crbug.com/854195 images/color-profile-layer.html [ Failure ] crbug.com/854195 images/pixelated-composited.html [ Failure ] +crbug.com/854195 compositing/visibility/visibility-image-layers.html [ Failure ] +crbug.com/854195 virtual/threaded/compositing/visibility/visibility-image-layers.html [ Failure ] # Paint invalidation test failures. Needs investigation. crbug.com/857322 paint/invalidation/background/obscured-background-no-repaint.html [ Failure Crash ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index 0c44bd4..0bff540 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -282,10 +282,6 @@ # [css-contain] -crbug.com/785212 external/wpt/css/css-contain/contain-layout-006.html [ Failure ] -crbug.com/785212 external/wpt/css/css-contain/contain-layout-007.html [ Failure ] -crbug.com/785212 external/wpt/css/css-contain/contain-layout-013.html [ Failure ] -crbug.com/785212 external/wpt/css/css-contain/contain-layout-014.html [ Failure ] crbug.com/847274 external/wpt/css/css-contain/contain-paint-005.html [ Failure ] crbug.com/847274 external/wpt/css/css-contain/contain-paint-006.html [ Failure ] @@ -2609,7 +2605,6 @@ crbug.com/808834 [ Linux Win ] external/wpt/css/css-pseudo/first-letter-001.html [ Failure ] -crbug.com/655458 crbug.com/721814 external/wpt/mediacapture-image/idlharness.html [ Skip ] crbug.com/723741 virtual/threaded/http/tests/devtools/tracing/idle-callback.js [ Failure Pass Timeout ] @@ -4625,7 +4620,6 @@ # Sheriff 2018-07-11 # Test timeouts following wpt-import@89ccb892... crbug.com/862588 [ Linux ] external/wpt/cookie-store/idlharness.tentative.https.html [ Timeout Pass ] -crbug.com/862588 [ Linux ] external/wpt/gamepad/idlharness.html [ Timeout Pass ] crbug.com/862588 [ Linux ] external/wpt/push-api/idlharness.https.any.sharedworker.html [ Timeout Pass ] crbug.com/862588 [ Linux ] external/wpt/push-api/idlharness.https.any.worker.html [ Timeout Pass ] crbug.com/862588 [ Linux ] external/wpt/resource-timing/idlharness.any.html [ Timeout Pass ]
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json index 28efc88..5a010e31 100644 --- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json +++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
@@ -35344,7 +35344,7 @@ "/css/css-contain/contain-layout-001.html", [ [ - "/css/css-contain/reference/contain-size-001-ref.html", + "/css/reference/pass_if_pass_below.html", "==" ] ], @@ -35356,7 +35356,7 @@ "/css/css-contain/contain-layout-002.html", [ [ - "/css/css-contain/reference/contain-layout-002-ref.html", + "/css/reference/ref-filled-green-100px-square.xht", "==" ] ], @@ -35368,7 +35368,7 @@ "/css/css-contain/contain-layout-003.html", [ [ - "/css/css-contain/reference/contain-layout-002-ref.html", + "/css/reference/ref-filled-green-100px-square.xht", "==" ] ], @@ -35380,7 +35380,7 @@ "/css/css-contain/contain-layout-004.html", [ [ - "/css/css-contain/reference/contain-layout-004-ref.html", + "/css/reference/ref-filled-green-100px-square.xht", "==" ] ], @@ -35392,7 +35392,7 @@ "/css/css-contain/contain-layout-005.html", [ [ - "/css/css-contain/reference/contain-layout-005-ref.html", + "/css/reference/ref-filled-green-100px-square.xht", "==" ] ], @@ -35560,7 +35560,7 @@ "/css/css-contain/contain-paint-002.html", [ [ - "/css/css-contain/reference/contain-size-001-ref.html", + "/css/reference/pass_if_pass_below.html", "==" ] ], @@ -35572,7 +35572,7 @@ "/css/css-contain/contain-paint-003.html", [ [ - "/css/css-contain/reference/contain-size-001-ref.html", + "/css/reference/pass_if_pass_below.html", "==" ] ], @@ -35584,7 +35584,7 @@ "/css/css-contain/contain-paint-004.html", [ [ - "/css/css-contain/reference/contain-paint-004-ref.html", + "/css/reference/nothing.html", "==" ] ], @@ -35596,7 +35596,7 @@ "/css/css-contain/contain-paint-005.html", [ [ - "/css/css-contain/reference/contain-size-001-ref.html", + "/css/reference/pass_if_pass_below.html", "==" ] ], @@ -35608,7 +35608,7 @@ "/css/css-contain/contain-paint-006.html", [ [ - "/css/css-contain/reference/contain-size-001-ref.html", + "/css/reference/pass_if_pass_below.html", "==" ] ], @@ -35704,7 +35704,7 @@ "/css/css-contain/contain-paint-014.html", [ [ - "/css/css-contain/reference/contain-paint-014-ref.html", + "/css/reference/nothing.html", "==" ] ], @@ -35716,7 +35716,7 @@ "/css/css-contain/contain-paint-015.html", [ [ - "/css/css-contain/reference/contain-size-001-ref.html", + "/css/reference/pass_if_pass_below.html", "==" ] ], @@ -35728,7 +35728,7 @@ "/css/css-contain/contain-paint-016.html", [ [ - "/css/css-contain/reference/contain-size-001-ref.html", + "/css/reference/pass_if_pass_below.html", "==" ] ], @@ -35740,7 +35740,7 @@ "/css/css-contain/contain-paint-017.html", [ [ - "/css/css-contain/reference/contain-size-001-ref.html", + "/css/reference/pass_if_pass_below.html", "==" ] ], @@ -35752,7 +35752,7 @@ "/css/css-contain/contain-paint-018.html", [ [ - "/css/css-contain/reference/contain-size-001-ref.html", + "/css/reference/pass_if_pass_below.html", "==" ] ], @@ -35764,7 +35764,7 @@ "/css/css-contain/contain-paint-019.html", [ [ - "/css/css-contain/reference/contain-paint-014-ref.html", + "/css/reference/nothing.html", "==" ] ], @@ -35776,7 +35776,7 @@ "/css/css-contain/contain-size-001.html", [ [ - "/css/css-contain/reference/contain-size-001-ref.html", + "/css/reference/pass_if_pass_below.html", "==" ] ], @@ -35788,7 +35788,7 @@ "/css/css-contain/contain-size-002.html", [ [ - "/css/css-contain/reference/contain-size-001-ref.html", + "/css/reference/pass_if_pass_below.html", "==" ] ], @@ -35800,7 +35800,7 @@ "/css/css-contain/contain-size-003.html", [ [ - "/css/css-contain/reference/contain-size-001-ref.html", + "/css/reference/pass_if_pass_below.html", "==" ] ], @@ -35836,7 +35836,7 @@ "/css/css-contain/contain-size-006.html", [ [ - "/css/css-contain/reference/contain-size-001-ref.html", + "/css/reference/pass_if_pass_below.html", "==" ] ], @@ -35848,7 +35848,7 @@ "/css/css-contain/contain-size-007.html", [ [ - "/css/css-contain/reference/contain-size-001-ref.html", + "/css/reference/pass_if_pass_below.html", "==" ] ], @@ -35860,7 +35860,7 @@ "/css/css-contain/contain-size-008.html", [ [ - "/css/css-contain/reference/contain-size-001-ref.html", + "/css/reference/pass_if_pass_below.html", "==" ] ], @@ -35872,7 +35872,7 @@ "/css/css-contain/contain-size-009.html", [ [ - "/css/css-contain/reference/contain-size-001-ref.html", + "/css/reference/pass_if_pass_below.html", "==" ] ], @@ -35884,7 +35884,7 @@ "/css/css-contain/contain-size-010.html", [ [ - "/css/css-contain/reference/contain-size-001-ref.html", + "/css/reference/pass_if_pass_below.html", "==" ] ], @@ -35896,7 +35896,7 @@ "/css/css-contain/contain-size-011.html", [ [ - "/css/css-contain/reference/contain-paint-014-ref.html", + "/css/reference/nothing.html", "==" ] ], @@ -35908,7 +35908,7 @@ "/css/css-contain/contain-size-012.html", [ [ - "/css/css-contain/reference/contain-size-001-ref.html", + "/css/reference/pass_if_pass_below.html", "==" ] ], @@ -103519,6 +103519,11 @@ {} ] ], + "battery-status/battery-interface-idlharness.https.window-expected.txt": [ + [ + {} + ] + ], "battery-status/support-iframe.html": [ [ {} @@ -112554,21 +112559,6 @@ {} ] ], - "css/css-contain/reference/contain-layout-002-ref.html": [ - [ - {} - ] - ], - "css/css-contain/reference/contain-layout-004-ref.html": [ - [ - {} - ] - ], - "css/css-contain/reference/contain-layout-005-ref.html": [ - [ - {} - ] - ], "css/css-contain/reference/contain-layout-breaks-002-ref.html": [ [ {} @@ -112579,11 +112569,6 @@ {} ] ], - "css/css-contain/reference/contain-paint-004-ref.html": [ - [ - {} - ] - ], "css/css-contain/reference/contain-paint-007-ref.html": [ [ {} @@ -112599,16 +112584,6 @@ {} ] ], - "css/css-contain/reference/contain-paint-014-ref.html": [ - [ - {} - ] - ], - "css/css-contain/reference/contain-size-001-ref.html": [ - [ - {} - ] - ], "css/css-contain/reference/contain-size-004-ref.html": [ [ {} @@ -144474,6 +144449,11 @@ {} ] ], + "gamepad/idlharness.window-expected.txt": [ + [ + {} + ] + ], "generic-sensor/META.yml": [ [ {} @@ -144599,6 +144579,11 @@ {} ] ], + "geolocation-sensor/idlharness.https.window-expected.txt": [ + [ + {} + ] + ], "graphics-aam/META.yml": [ [ {} @@ -159149,6 +159134,11 @@ {} ] ], + "magnetometer/idlharness.https.window-expected.txt": [ + [ + {} + ] + ], "media-capabilities/META.yml": [ [ {} @@ -161254,6 +161244,11 @@ {} ] ], + "pointerevents/extension/idlharness.window-expected.txt": [ + [ + {} + ] + ], "pointerevents/extension/pointerevent_coalesced_events_attributes-manual-expected.txt": [ [ {} @@ -171204,6 +171199,11 @@ {} ] ], + "webrtc/RTCPeerConnection-transceivers.https-expected.txt": [ + [ + {} + ] + ], "webrtc/RTCPeerConnectionIceEvent-constructor-expected.txt": [ [ {} @@ -184013,9 +184013,9 @@ {} ] ], - "battery-status/battery-interface-idlharness.https.html": [ + "battery-status/battery-interface-idlharness.https.window.js": [ [ - "/battery-status/battery-interface-idlharness.https.html", + "/battery-status/battery-interface-idlharness.https.window.html", {} ] ], @@ -212703,9 +212703,9 @@ {} ] ], - "gamepad/idlharness.html": [ + "gamepad/idlharness.window.js": [ [ - "/gamepad/idlharness.html", + "/gamepad/idlharness.window.html", {} ] ], @@ -212829,9 +212829,9 @@ {} ] ], - "geolocation-sensor/idlharness.https.html": [ + "geolocation-sensor/idlharness.https.window.js": [ [ - "/geolocation-sensor/idlharness.https.html", + "/geolocation-sensor/idlharness.https.window.html", {} ] ], @@ -212883,9 +212883,9 @@ {} ] ], - "gyroscope/idlharness.https.html": [ + "gyroscope/idlharness.https.window.js": [ [ - "/gyroscope/idlharness.https.html", + "/gyroscope/idlharness.https.window.html", {} ] ], @@ -225631,9 +225631,9 @@ {} ] ], - "keyboard-lock/idlharness.https.html": [ + "keyboard-lock/idlharness.https.window.js": [ [ - "/keyboard-lock/idlharness.https.html", + "/keyboard-lock/idlharness.https.window.html", {} ] ], @@ -225673,9 +225673,9 @@ {} ] ], - "keyboard-map/idlharness.https.html": [ + "keyboard-map/idlharness.https.window.js": [ [ - "/keyboard-map/idlharness.https.html", + "/keyboard-map/idlharness.https.window.html", {} ] ], @@ -225829,9 +225829,9 @@ {} ] ], - "magnetometer/idlharness.https.html": [ + "magnetometer/idlharness.https.window.js": [ [ - "/magnetometer/idlharness.https.html", + "/magnetometer/idlharness.https.window.html", {} ] ], @@ -226259,9 +226259,9 @@ {} ] ], - "mediacapture-image/idlharness.html": [ + "mediacapture-image/idlharness.window.js": [ [ - "/mediacapture-image/idlharness.html", + "/mediacapture-image/idlharness.window.html", {} ] ], @@ -226451,9 +226451,9 @@ {} ] ], - "mediasession/idlharness.html": [ + "mediasession/idlharness.window.js": [ [ - "/mediasession/idlharness.html", + "/mediasession/idlharness.window.html", {} ] ], @@ -237737,9 +237737,9 @@ {} ] ], - "orientation-sensor/idlharness.https.html": [ + "orientation-sensor/idlharness.https.window.js": [ [ - "/orientation-sensor/idlharness.https.html", + "/orientation-sensor/idlharness.https.window.html", {} ] ], @@ -238413,9 +238413,9 @@ } ] ], - "pointerevents/extension/idlharness.html": [ + "pointerevents/extension/idlharness.window.js": [ [ - "/pointerevents/extension/idlharness.html", + "/pointerevents/extension/idlharness.window.html", {} ] ], @@ -238777,6 +238777,12 @@ {} ] ], + "quirks/unitless-length/excluded-properties.html": [ + [ + "/quirks/unitless-length/excluded-properties.html", + {} + ] + ], "quirks/unitless-length/limited-quirks.html": [ [ "/quirks/unitless-length/limited-quirks.html", @@ -255899,6 +255905,12 @@ {} ] ], + "webrtc/RTCPeerConnection-transceivers.https.html": [ + [ + "/webrtc/RTCPeerConnection-transceivers.https.html", + {} + ] + ], "webrtc/RTCPeerConnectionIceEvent-constructor.html": [ [ "/webrtc/RTCPeerConnectionIceEvent-constructor.html", @@ -259069,6 +259081,12 @@ {} ] ], + "webxr/xrSession_exclusive_requestAnimationFrame.https.html": [ + [ + "/webxr/xrSession_exclusive_requestAnimationFrame.https.html", + {} + ] + ], "workers/SharedWorkerPerformanceNow.html": [ [ "/workers/SharedWorkerPerformanceNow.html", @@ -275446,8 +275464,12 @@ "39639373d161846186cbcb7eb33466493bcc77ad", "testharness" ], - "battery-status/battery-interface-idlharness.https.html": [ - "ded64d71b16ef29ee44ef2337642d551f8b557fe", + "battery-status/battery-interface-idlharness.https.window-expected.txt": [ + "2a2009d89f98be6e16fbd0cab3f0f370a32a65e4", + "support" + ], + "battery-status/battery-interface-idlharness.https.window.js": [ + "a95b16677ae52391ccd2d92b40eba679664c83bd", "testharness" ], "battery-status/battery-plugging-in-manual.https.html": [ @@ -300083,23 +300105,23 @@ "support" ], "css/css-contain/contain-layout-001.html": [ - "325039fe561cd040fe680c42155a53d59eaf114e", + "d7e8b61bd8a7f5a2e212861f8ece100ce2d5bf49", "reftest" ], "css/css-contain/contain-layout-002.html": [ - "950f95e3be4bfa0b7458699e1f34e6f0567b9a35", + "be7015089e1e8e8fe25890734862cf703b790d48", "reftest" ], "css/css-contain/contain-layout-003.html": [ - "ab1c4fa31dd731e4b0993c4a2a2ba8d82ec3d524", + "ee83742ffee11bdb5d892b8513cc4b5ac08c691a", "reftest" ], "css/css-contain/contain-layout-004.html": [ - "bb9d7c13fa5745171c5e3319e04e7dc1c4007807", + "b42792df963aa8a6295df498ba9ace7770660cbe", "reftest" ], "css/css-contain/contain-layout-005.html": [ - "26160f813c0b3e5c963d4aae7bb23f90e9956941", + "33af5800bb2bc8cff3a5e6a2979cb9224aada355", "reftest" ], "css/css-contain/contain-layout-006.html": [ @@ -300155,23 +300177,23 @@ "reftest" ], "css/css-contain/contain-paint-002.html": [ - "50adc0e83ba0d3bffd957dbf8acdf7474f6350f5", + "fdf31fdc298da8545f125406bc6b7d679bbe3132", "reftest" ], "css/css-contain/contain-paint-003.html": [ - "7eb703232b2a448b3b49394ed0102b65aa37e647", + "cb8c27b18abe50d15c0dc80520cc3e920aff2160", "reftest" ], "css/css-contain/contain-paint-004.html": [ - "2db5aaea054ed4b3a2c2db1786f29fc44515cdd4", + "7b4b39e623ee8e4845cde4eb51a9f81a2993cec2", "reftest" ], "css/css-contain/contain-paint-005.html": [ - "68c7155386ef96ba8fe22ce55d996634f928b703", + "18716da09c82bb564ad29628ff83d3ce914bc2b2", "reftest" ], "css/css-contain/contain-paint-006.html": [ - "935d160de8000eb1f83ac6a987b6c7047ca80e93", + "e95dfaad34be2427cab57f0320872b5481ff7a25", "reftest" ], "css/css-contain/contain-paint-007.html": [ @@ -300203,39 +300225,39 @@ "reftest" ], "css/css-contain/contain-paint-014.html": [ - "c22ee90cf05992dab4188cc86c255bd040babe26", + "272e9031acbe072e8daab8a6b034e93395dee933", "reftest" ], "css/css-contain/contain-paint-015.html": [ - "3941644b7fffc11a2786e55dc28d6fcfe55c57dc", + "8de03ed418d767537b000ba317897aa4faa5f0da", "reftest" ], "css/css-contain/contain-paint-016.html": [ - "fbedca7cd40c2e5a6aea020de403d81ea334f2c1", + "f413eba1117e883daa04e734c414a66f891753af", "reftest" ], "css/css-contain/contain-paint-017.html": [ - "40a82207bac0728925609faf19e0aa896f956009", + "cbd018f0c83662866b216cb3828a97f9ddb847f0", "reftest" ], "css/css-contain/contain-paint-018.html": [ - "74f65ae0e2f8c4ceb77c54fa8bf9b1d364f55c38", + "f1a438d882f622974276d52dc737e1daa8b04b91", "reftest" ], "css/css-contain/contain-paint-019.html": [ - "75b780b1b791b6c3c06cddbd9462103b88bbd603", + "a0c12cdb221a1bb1e73c81b982ba78f87a63b93c", "reftest" ], "css/css-contain/contain-size-001.html": [ - "089c4fd7352f91a85d5d8f6bf8c5f261c868cd37", + "05060bb62063edcc4b7d7ad095e73f703c68eb01", "reftest" ], "css/css-contain/contain-size-002.html": [ - "ea16d90e56729c1678b327412cd945a0dea6b762", + "235ec0441285890c93dffb4ff2bd0872f3f95dd7", "reftest" ], "css/css-contain/contain-size-003.html": [ - "4b1fd16d90f0eebd7ce97a82a5ef55806f92060e", + "a49f582fbed96fab59ab3bce4295ff86c3032c22", "reftest" ], "css/css-contain/contain-size-004.html": [ @@ -300247,31 +300269,31 @@ "reftest" ], "css/css-contain/contain-size-006.html": [ - "2952e1bfc74d784dd2d16867ad95199d78c08efa", + "bd204b37cafa98d3d3eb1796896c893c55c3e028", "reftest" ], "css/css-contain/contain-size-007.html": [ - "54d0f08274e3bb380d098fb5dbf9edeee67780f3", + "8c75bee5e46d80563532d441f6195a1e5bf455f8", "reftest" ], "css/css-contain/contain-size-008.html": [ - "eaff3d8150332dffa1c70fc75efd66929f8adc79", + "cbe3b7b06287b828b49e992f247a4a6e00cfcc80", "reftest" ], "css/css-contain/contain-size-009.html": [ - "727fa2cfad094c1a4e4785fb71cdc3c09a5d7f1b", + "14b67af417b6c662fbb38f6875ebb2a625923063", "reftest" ], "css/css-contain/contain-size-010.html": [ - "1bfca9e97f9135b4f4b1b456f017a641c8b85a1c", + "efe7acae5fc908a049275c407acc26843dc89552", "reftest" ], "css/css-contain/contain-size-011.html": [ - "c4b06e89428d47d9777610bb949714f70685dac5", + "de95aef6aef63dc6cfa71bdc6ca749feeca9d575", "reftest" ], "css/css-contain/contain-size-012.html": [ - "51cc7a37659688af3830dbca89b9a515e22b2551", + "b85a20c31a5b0c33f2f4f459c6507e3eb40958f0", "reftest" ], "css/css-contain/contain-size-013.html": [ @@ -300354,18 +300376,6 @@ "5067c9308951cae6deb33f4383398f96d859428f", "reftest" ], - "css/css-contain/reference/contain-layout-002-ref.html": [ - "cb077e2b280d7200c33e945fb175ffdbb536651a", - "support" - ], - "css/css-contain/reference/contain-layout-004-ref.html": [ - "6a591187b27feb07fa982059850e06ae65f80e32", - "support" - ], - "css/css-contain/reference/contain-layout-005-ref.html": [ - "6320656dc24c5377756d0895edcc2134a4ba1da1", - "support" - ], "css/css-contain/reference/contain-layout-breaks-002-ref.html": [ "f5804830fd9d22117b027135bf5b9191f0f3f15e", "support" @@ -300374,10 +300384,6 @@ "be57e942110661fd32f0342bbe2870e4e3280d86", "support" ], - "css/css-contain/reference/contain-paint-004-ref.html": [ - "eecbc6d0ea1638e8c853458ed59cfbd67d096ef0", - "support" - ], "css/css-contain/reference/contain-paint-007-ref.html": [ "c34cc4f333edcc4949ae8418ca736154632dc5eb", "support" @@ -300390,14 +300396,6 @@ "c3d8d642f2b4b25df84170669222b61866ab3057", "support" ], - "css/css-contain/reference/contain-paint-014-ref.html": [ - "1f281c10ae1bf7dd0f1c9119458b3698077a8e60", - "support" - ], - "css/css-contain/reference/contain-size-001-ref.html": [ - "6f68316c3e9647eb6f71d299bb1d43e286899a7d", - "support" - ], "css/css-contain/reference/contain-size-004-ref.html": [ "090aba85ddcf927a33de227157ac8e411fd5c268", "support" @@ -304119,7 +304117,7 @@ "support" ], "css/css-font-loading/idlharness.https.html": [ - "93c01c16bf27adc0789dda15dd2e704b96715415", + "3284f427d0cecb3337b83a6fbfd60b16e5db0600", "testharness" ], "css/css-fonts/META.yml": [ @@ -352183,7 +352181,7 @@ "testharness" ], "encoding/idlharness.any.js": [ - "d37d060ee1ab2b54cf4dccc2cb80796771324ef7", + "60a9348e7608a10af6091b0a157943ffc31a2e8a", "testharness" ], "encoding/iso-2022-jp-decoder-expected.txt": [ @@ -357214,8 +357212,12 @@ "a1a489005f90621c5a421ecb5fb94ffafe824694", "support" ], - "gamepad/idlharness.html": [ - "0cb95e9fda86db8327efdd3a05c3b2a99d480255", + "gamepad/idlharness.window-expected.txt": [ + "60497677badfd7edb9f7caa49f5a713b2cacd433", + "support" + ], + "gamepad/idlharness.window.js": [ + "30bf94fe8e091d9c0245d071c42c19e96936b4a0", "testharness" ], "generic-sensor/META.yml": [ @@ -357418,8 +357420,12 @@ "43637ddb585aa1671f2beec30ba973a719953041", "support" ], - "geolocation-sensor/idlharness.https.html": [ - "38c75b8946de5be961435045007b8af9a4627cd2", + "geolocation-sensor/idlharness.https.window-expected.txt": [ + "045a6314a335c5baf9744d4588410f88499ba64d", + "support" + ], + "geolocation-sensor/idlharness.https.window.js": [ + "c29a81848d39576fc68ad145216ab17c27a1f213", "testharness" ], "graphics-aam/META.yml": [ @@ -357534,8 +357540,8 @@ "c8644c83d04efcf453284309917a4fd64b3f20c2", "support" ], - "gyroscope/idlharness.https.html": [ - "8b9b8fcdc6d33fb20c174b67306a182bdbb707fd", + "gyroscope/idlharness.https.window.js": [ + "5d74b2071370ce6232e7ea541ca984f9b9fbf95d", "testharness" ], "hr-time/META.yml": [ @@ -378211,7 +378217,7 @@ "support" ], "interfaces/geolocation-API.idl": [ - "87be830712d8d40ec01b200935a41422e72ab7c4", + "ae1b33281c8833971cabe9ffb3ab37c065251fc0", "support" ], "interfaces/geolocation-sensor.idl": [ @@ -378287,7 +378293,7 @@ "support" ], "interfaces/netinfo.idl": [ - "357a99c1a5cb73265ee63d1ab1a0e413c6ced458", + "c40e777040b92c90591f40a02a66440ecc228c5a", "support" ], "interfaces/orientation-event.idl": [ @@ -378315,7 +378321,7 @@ "support" ], "interfaces/payment-request.idl": [ - "1523f682dd32680417a5e45d9201743685549fe6", + "8e5193372ad6f38d36fc20c454ea7b55e21b6379", "support" ], "interfaces/performance-timeline.idl": [ @@ -378327,11 +378333,11 @@ "support" ], "interfaces/picture-in-picture.idl": [ - "4051a7f0ba28e984294ca32a5a2aef73b7f9a6bb", + "6feee4b6ea8d50e9ec572a6786c8fd9b4b8f80da", "support" ], "interfaces/pointerevents-extension.idl": [ - "26055736a27852501eba7da7f0cab7c57eceb652", + "e3f284d2a59f53f6127f7d146b8759918431d859", "support" ], "interfaces/pointerevents.idl": [ @@ -378363,7 +378369,7 @@ "support" ], "interfaces/requestidlecallback.idl": [ - "e49a6aad4ba17b797516f397096703690bcbecd9", + "72a32cc188200761e80bb1b35f21f3a86b0839fe", "support" ], "interfaces/resource-timing.idl": [ @@ -378419,7 +378425,7 @@ "support" ], "interfaces/user-timing.idl": [ - "41c00eec8e9c1b2137bd05e85bdc029b7a87c349", + "e91a31115b596326e55da3c9ccd141b2b5e7275a", "support" ], "interfaces/vibration.idl": [ @@ -378451,7 +378457,7 @@ "support" ], "interfaces/webaudio.idl": [ - "a2adb319de88d1d33080a837972caefa5c5c1946", + "1750df8547db73ffe06d1c3e87f34fbcc7c49dcb", "support" ], "interfaces/webauthn.idl": [ @@ -378626,8 +378632,8 @@ "6374a5c8d059bb62d557b9d1b20bd855eaab90fa", "support" ], - "keyboard-lock/idlharness.https.html": [ - "d196b06e8606572e1e6c1a9e81e2f0920641c069", + "keyboard-lock/idlharness.https.window.js": [ + "70fb3044f9154dd97ca82c5b3f76a4e383252ff3", "testharness" ], "keyboard-lock/navigator-keyboard-lock-blocked-from-cross-origin-iframe.https.html": [ @@ -378666,8 +378672,8 @@ "8ac2e74fd9fc5406af7a663d393fdd6f789effdf", "support" ], - "keyboard-map/idlharness.https.html": [ - "3215b6729d83ca2841baf6eb33445eb07e0a7c25", + "keyboard-map/idlharness.https.window.js": [ + "30317f694273b15b2b1b6fea2fddc88c806a3303", "testharness" ], "keyboard-map/navigator-keyboard-map-blocked-from-cross-origin-iframe.https.html": [ @@ -378870,8 +378876,12 @@ "5284b1f1712ee3349f296f51984548f24bd15710", "support" ], - "magnetometer/idlharness.https.html": [ - "d5ba7fe95ed2740eec56757dfe3b0a900f3ea4c4", + "magnetometer/idlharness.https.window-expected.txt": [ + "e62d6f25b87e79312b361661560541a2e11f5453", + "support" + ], + "magnetometer/idlharness.https.window.js": [ + "2d163a0c50467e06311dfff5c0c3b60420e6150b", "testharness" ], "media-capabilities/META.yml": [ @@ -379594,8 +379604,8 @@ "7e12f1328b97f124aafb2944ea846bc6fc9007bb", "support" ], - "mediacapture-image/idlharness.html": [ - "ad2c957734eb67577ef3e50f95984eeb999f4743", + "mediacapture-image/idlharness.window.js": [ + "2a422e686bd462ea9cf1d8718becac291e3da2e9", "testharness" ], "mediacapture-record/BlobEvent-constructor.html": [ @@ -379818,8 +379828,8 @@ "5ceecb2611837e6c52a303cec32d8cb9fabe93a6", "support" ], - "mediasession/idlharness.html": [ - "e5b4267255f62b4505b3c656d2b377380f8dfab5", + "mediasession/idlharness.window.js": [ + "5ab75d11ae3fcb7dc19971865df170cdf4e706ee", "testharness" ], "mediasession/mediametadata.html": [ @@ -388330,8 +388340,8 @@ "87d5e9ad1fa7a7f976e5f9f6d353fac2b5efbf91", "support" ], - "orientation-sensor/idlharness.https.html": [ - "1f94329cb330a1a904d409a6e158a5fe9f8dd709", + "orientation-sensor/idlharness.https.window.js": [ + "0be5ccc874864dd3f1a0aeb9a79f0ddfe601b30e", "testharness" ], "orientation-sensor/orientation-sensor-tests.js": [ @@ -389103,7 +389113,7 @@ "testharness" ], "picture-in-picture/idlharness.window-expected.txt": [ - "448975f233f81cff22313e9ab78f0acc337a6672", + "a048d5c50c8e843efdfb66389f95f16b3e1bca6a", "support" ], "picture-in-picture/idlharness.window.js": [ @@ -389154,8 +389164,12 @@ "cba44e2dd2a3c54106bfecc6cdd407643e2ba995", "manual" ], - "pointerevents/extension/idlharness.html": [ - "70f3fc4fce01d7acb4611aa870d7f95a1d734dbc", + "pointerevents/extension/idlharness.window-expected.txt": [ + "dd0c631efa409399a06df707e99224303a7bb61b", + "support" + ], + "pointerevents/extension/idlharness.window.js": [ + "ec3860925d71afeda168b89025e5ee6085e67d3e", "testharness" ], "pointerevents/extension/pointerevent_coalesced_events_attributes-manual-expected.txt": [ @@ -390078,6 +390092,10 @@ "b7a8466a3842237ddf9446bd3ab49de043001526", "testharness" ], + "quirks/unitless-length/excluded-properties.html": [ + "d1214dc257034cf6a844289039ffd8a2e736193c", + "testharness" + ], "quirks/unitless-length/limited-quirks.html": [ "5d34a17086a2f3abb58b0e3e3f0599bc39f8486e", "testharness" @@ -406395,19 +406413,19 @@ "testharness" ], "user-timing/idlharness.any.js": [ - "6a0dcd26b5ff16b18603c50b9257d55e6e25f0ce", + "62a3040dfb0508df0ef9d572a33e750cdd2b0d18", "testharness" ], "user-timing/idlharness.any.sharedworker-expected.txt": [ - "52a0c5d8d5120e0f5134fa1deafb6d7ea7461386", + "ed987d6e53a057a2c38bd124065663fe12621032", "support" ], "user-timing/idlharness.any.worker-expected.txt": [ - "52a0c5d8d5120e0f5134fa1deafb6d7ea7461386", + "ed987d6e53a057a2c38bd124065663fe12621032", "support" ], "user-timing/idlharness.https.any.serviceworker-expected.txt": [ - "52a0c5d8d5120e0f5134fa1deafb6d7ea7461386", + "ed987d6e53a057a2c38bd124065663fe12621032", "support" ], "user-timing/invoke_with_timing_attributes.html": [ @@ -408523,7 +408541,7 @@ "testharness" ], "webaudio/the-audio-api/the-pannernode-interface/panner-distance-clamping.html": [ - "820c902b9bcfeed9611ec9c3cba3ee2179a8cee7", + "7ea63964142ab76e3883bef9e73c2e8e0b28ea96", "testharness" ], "webaudio/the-audio-api/the-pannernode-interface/panner-equalpower-stereo.html": [ @@ -409327,7 +409345,7 @@ "support" ], "webrtc/RTCDTMFSender-insertDTMF.https-expected.txt": [ - "066417349e23523916fe52a07d70759ac9b9d88f", + "3016fba4cde425a3e9e2f48ab71ad53f8565b628", "support" ], "webrtc/RTCDTMFSender-insertDTMF.https.html": [ @@ -409339,7 +409357,7 @@ "testharness" ], "webrtc/RTCDTMFSender-ontonechange.https-expected.txt": [ - "5f5dd477a4ce9b1cd4e0cf83eb3938443554d807", + "a7f7a0895850be9bebb17947f4c3176bf157c515", "support" ], "webrtc/RTCDTMFSender-ontonechange.https.html": [ @@ -409407,7 +409425,7 @@ "testharness" ], "webrtc/RTCPeerConnection-addTrack.https-expected.txt": [ - "525e696aea18da56f97605eb6d555a36f2c114d9", + "719fd07bffe6801720297e0e5632cdcdc7ff96e7", "support" ], "webrtc/RTCPeerConnection-addTrack.https.html": [ @@ -409415,11 +409433,11 @@ "testharness" ], "webrtc/RTCPeerConnection-addTransceiver-expected.txt": [ - "96f621b10b54b8fc676e63bb65ca8592f53a863f", + "f081cfd4da18191f04c211a70735b7142907e61f", "support" ], "webrtc/RTCPeerConnection-addTransceiver.html": [ - "c2d5766daa3ea4050ccb2777d7c08af1a1bd176f", + "3d1531048c244d0f3391d6fe30e7c8bc7e13ef35", "testharness" ], "webrtc/RTCPeerConnection-canTrickleIceCandidates-expected.txt": [ @@ -409463,11 +409481,11 @@ "testharness" ], "webrtc/RTCPeerConnection-createOffer-expected.txt": [ - "55cad561ac704efe1ad6a2df164d4320fe4622fe", + "8732e22ecb750cf9887fa7e84017c397b503e0a7", "support" ], "webrtc/RTCPeerConnection-createOffer-offerToReceive-expected.txt": [ - "2435b4d6afc9ccb9c793c67d10486926fc8ed1f5", + "65c7f80a62213b18a6303f0f7a9494a6334f0f39", "support" ], "webrtc/RTCPeerConnection-createOffer-offerToReceive.html": [ @@ -409507,7 +409525,7 @@ "testharness" ], "webrtc/RTCPeerConnection-getStats.https-expected.txt": [ - "724a22ab2b75e30b57c3fcad9309cf89d0fda0a9", + "3f4bb2c4462d759c99441a4afd2447c1e04f33d0", "support" ], "webrtc/RTCPeerConnection-getStats.https.html": [ @@ -409547,7 +409565,7 @@ "testharness" ], "webrtc/RTCPeerConnection-onnegotiationneeded-expected.txt": [ - "30dae56636019ba40caa9dc5428469dcced0895f", + "54366bc2f11cf5d9585c44ffc39641548dece432", "support" ], "webrtc/RTCPeerConnection-onnegotiationneeded.html": [ @@ -409555,7 +409573,7 @@ "testharness" ], "webrtc/RTCPeerConnection-ontrack.https-expected.txt": [ - "df68d12770ca3d1a359b1b8172ffbd31b49f3e79", + "7484d81e73d8b3bb7da9dbb529f3aa651031ae79", "support" ], "webrtc/RTCPeerConnection-ontrack.https.html": [ @@ -409571,7 +409589,7 @@ "testharness" ], "webrtc/RTCPeerConnection-removeTrack.https-expected.txt": [ - "8f528eae3d527bece8107ebc0452a493bc5de290", + "287a1df978aa75674908e69f88e40e5d7ab640eb", "support" ], "webrtc/RTCPeerConnection-removeTrack.https.html": [ @@ -409579,7 +409597,7 @@ "testharness" ], "webrtc/RTCPeerConnection-setDescription-transceiver-expected.txt": [ - "7b041be1aa700a20e0e3904541f3f56011fd26b6", + "536e96502f864806d56c069591c131e94e182996", "support" ], "webrtc/RTCPeerConnection-setDescription-transceiver.html": [ @@ -409587,7 +409605,7 @@ "testharness" ], "webrtc/RTCPeerConnection-setLocalDescription-answer-expected.txt": [ - "23395c4322aebdcfb39359e9f33d3ec433ee8f3d", + "54aebf1d129aeac2fb59939cc1ba0910a1733929", "support" ], "webrtc/RTCPeerConnection-setLocalDescription-answer.html": [ @@ -409635,7 +409653,7 @@ "testharness" ], "webrtc/RTCPeerConnection-setRemoteDescription-expected.txt": [ - "0ddd700cf8b0f417c42f6d8148a2b984fb49b840", + "910f4d9f878a79e5a45098c3f065f9ce4fb291e7", "support" ], "webrtc/RTCPeerConnection-setRemoteDescription-offer-expected.txt": [ @@ -409690,6 +409708,14 @@ "d40ed4a64f9e769c21060b0ba9b593938d8f8403", "testharness" ], + "webrtc/RTCPeerConnection-transceivers.https-expected.txt": [ + "86459c6218ef168369b2445eddcc58cbea405f2c", + "support" + ], + "webrtc/RTCPeerConnection-transceivers.https.html": [ + "a7eee2ccff5db0c393346cfcb842b0b6d9e3b966", + "testharness" + ], "webrtc/RTCPeerConnectionIceEvent-constructor-expected.txt": [ "b69971c474359a4d07ed7f13cd0c1c19d62f84f6", "support" @@ -409703,7 +409729,7 @@ "support" ], "webrtc/RTCRtpParameters-codecs-expected.txt": [ - "2961e1c2d3071811a65c71f317e84ddfd7bf9f74", + "5bd6aafe90b69ff786798ddca45e70ae6e972eb2", "support" ], "webrtc/RTCRtpParameters-codecs.html": [ @@ -409711,7 +409737,7 @@ "testharness" ], "webrtc/RTCRtpParameters-degradationPreference-expected.txt": [ - "cef821b6e5eddb9af9c76bf8aca3119861e240f2", + "14326c63c154458221696a080389f150114d941a", "support" ], "webrtc/RTCRtpParameters-degradationPreference.html": [ @@ -409719,7 +409745,7 @@ "testharness" ], "webrtc/RTCRtpParameters-encodings-expected.txt": [ - "f5426bbd105d41715002586ff4f7f0914eeffecf", + "d1a0908d90ff13bf84cb10091251408268af5871", "support" ], "webrtc/RTCRtpParameters-encodings.html": [ @@ -409727,7 +409753,7 @@ "testharness" ], "webrtc/RTCRtpParameters-headerExtensions-expected.txt": [ - "b237cecc6d8b2cfa6bc1330f7ab8aaf391be880e", + "f0d8cd67814b9b7079caafad08e8ef8b58624f0c", "support" ], "webrtc/RTCRtpParameters-headerExtensions.html": [ @@ -409739,7 +409765,7 @@ "support" ], "webrtc/RTCRtpParameters-rtcp-expected.txt": [ - "62790bf5e1a64c52ee00752656ba5514ada17138", + "e19718d23d800db427eae0395003e82d8e5a01d3", "support" ], "webrtc/RTCRtpParameters-rtcp.html": [ @@ -409747,7 +409773,7 @@ "testharness" ], "webrtc/RTCRtpParameters-transactionId-expected.txt": [ - "58bcc0d36d8914797813c0c55d57b0686acf2338", + "a870299433debbcbad921bf9ae29f0115ccc14fa", "support" ], "webrtc/RTCRtpParameters-transactionId.html": [ @@ -409767,7 +409793,7 @@ "testharness" ], "webrtc/RTCRtpReceiver-getParameters-expected.txt": [ - "35dc13cb626b75667ae1e0a50b7e36c26a90d018", + "67893493a79511bd8d9b0283b2a2cbc61a1bc16c", "support" ], "webrtc/RTCRtpReceiver-getParameters.html": [ @@ -409775,7 +409801,7 @@ "testharness" ], "webrtc/RTCRtpReceiver-getStats.https-expected.txt": [ - "0010ed8df781c7e073669bba0552e325812a6d80", + "6dcca15dea5acb9ee7cb189e5dba340145459aa9", "support" ], "webrtc/RTCRtpReceiver-getStats.https.html": [ @@ -409795,7 +409821,7 @@ "testharness" ], "webrtc/RTCRtpSender-getStats.https-expected.txt": [ - "c8fcb6afd6d9a6e5f08ec8ebc3ad350bc397f4ae", + "bd6fc71e2d62dd9d5ad1c7916b194e0bf201145b", "support" ], "webrtc/RTCRtpSender-getStats.https.html": [ @@ -409803,7 +409829,7 @@ "testharness" ], "webrtc/RTCRtpSender-replaceTrack.https-expected.txt": [ - "5cc966da1ef624e5766cbf231ee67b5451ebd976", + "a6b5ff94414685af0bb1f94f914c47270f26f7b5", "support" ], "webrtc/RTCRtpSender-replaceTrack.https.html": [ @@ -409811,7 +409837,7 @@ "testharness" ], "webrtc/RTCRtpSender-setParameters-expected.txt": [ - "67b1fe5b9245c28de02a0c4433772965663c6e4e", + "1b3a085503d4ef2a59b0d3168039348bca46a14c", "support" ], "webrtc/RTCRtpSender-setParameters.html": [ @@ -409819,7 +409845,7 @@ "testharness" ], "webrtc/RTCRtpTransceiver-setCodecPreferences-expected.txt": [ - "4dc85a6d4b4e1101a474855af05cb3e91f4a3659", + "014777b6d47ced70e804b1436d3db4de10ef0525", "support" ], "webrtc/RTCRtpTransceiver-setCodecPreferences.html": [ @@ -409827,7 +409853,7 @@ "testharness" ], "webrtc/RTCRtpTransceiver-setDirection-expected.txt": [ - "ef8e1a07245c4387dcb2f15217b0fb2c3e8801a2", + "7a866c7f840dee21306a0eb8c7bf85f7130a632c", "support" ], "webrtc/RTCRtpTransceiver-setDirection.html": [ @@ -409855,7 +409881,7 @@ "support" ], "webrtc/RTCTrackEvent-constructor-expected.txt": [ - "f8a6e385de501fba2b96fb72c4c4c15cc1e62c05", + "fc06d177c57188ca1140d5d39336659bffa3d321", "support" ], "webrtc/RTCTrackEvent-constructor.html": [ @@ -409903,7 +409929,7 @@ "support" ], "webrtc/interfaces.https-expected.txt": [ - "31fd6cb35abfe55e6db83f072e28fd8c599de714", + "475facb1a5d7dd1bd9d37e2a02a5c9d2c3d9778f", "support" ], "webrtc/interfaces.https.html": [ @@ -414359,13 +414385,17 @@ "support" ], "webxr/resources/webxr_util.js": [ - "e8e9631d39b75b8e01a583636de765bc9c81dcd1", + "e145f999bb691a4d19067c75adc0f1206a63835d", "support" ], "webxr/webxr_availability.http.sub.html": [ "d8aa0ef8b7b3363fd23af2700dc6d9186201c408", "testharness" ], + "webxr/xrSession_exclusive_requestAnimationFrame.https.html": [ + "e75f95ee7d2751f7cbeadda9d6219bb29dbedfdc", + "testharness" + ], "workers/META.yml": [ "e10618bcfad6f80d5d983b9f4da878560b644108", "support"
diff --git a/third_party/WebKit/LayoutTests/external/wpt/battery-status/battery-interface-idlharness.https.html b/third_party/WebKit/LayoutTests/external/wpt/battery-status/battery-interface-idlharness.https.html deleted file mode 100644 index 888ad95..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/battery-status/battery-interface-idlharness.https.html +++ /dev/null
@@ -1,36 +0,0 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<title>Battery test: IDL</title> -<link rel="author" title="Intel" href="http://www.intel.com"> -<link rel="help" href="https://www.w3.org/TR/battery-status/"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script src="/resources/WebIDLParser.js"></script> -<script src="/resources/idlharness.js"></script> -<script> -'use strict'; - -promise_test(async () => { - const battery = await fetch('/interfaces/battery-status.idl').then(r => r.text()); - const dom = await fetch('/interfaces/dom.idl').then(r => r.text()); - const html = await fetch('/interfaces/html.idl').then(r => r.text()); - - const idl_array = new IdlArray(); - idl_array.add_idls(battery); - idl_array.add_dependency_idls(dom); - idl_array.add_dependency_idls(html); - - let manager; - try { - manager = await navigator.getBattery(); - } catch (e) { - // Will surface in idlharness.js's test_objects. - } - - idl_array.add_objects({ - Navigator: ['navigator'], - BatteryManager: [manager], - }); - idl_array.test(); -}, 'Test IDL implementation of Battery Status API'); -</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/battery-status/battery-interface-idlharness.https.window-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/battery-status/battery-interface-idlharness.https.window-expected.txt new file mode 100644 index 0000000..0d7b7da3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/battery-status/battery-interface-idlharness.https.window-expected.txt
@@ -0,0 +1,31 @@ +This is a testharness.js-based test. +FAIL Test IDL implementation of Battery Status API promise_test: Unhandled rejection with value: object "Got an error before parsing any named definition: Unrecognised tokens, line 1 (tokens: "{\"error\": {\"message\"") +[ + { + "type": "{", + "value": "{", + "trivia": "" + }, + { + "type": "string", + "value": "\"error\"", + "trivia": "" + }, + { + "type": ":", + "value": ":", + "trivia": "" + }, + { + "type": "{", + "value": "{", + "trivia": " " + }, + { + "type": "string", + "value": "\"message\"", + "trivia": "" + } +]" +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/battery-status/battery-interface-idlharness.https.window.js b/third_party/WebKit/LayoutTests/external/wpt/battery-status/battery-interface-idlharness.https.window.js new file mode 100644 index 0000000..3db3e16e --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/battery-status/battery-interface-idlharness.https.window.js
@@ -0,0 +1,20 @@ +// META: script=/resources/WebIDLParser.js +// META: script=/resources/idlharness.js + +// https://w3c.github.io/battery/ + +'use strict'; + +idl_test( + ['battery'], + ['dom', 'html'], + async idl_array => { + idl_array.add_objects({ + Navigator: ['navigator'], + BatteryManager: ['manager'], + }) + + self.manager = await navigator.getBattery(); + }, + 'Test IDL implementation of Battery Status API' +);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-layout-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-layout-001.html index 3a49cb9..c8895b9 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-layout-001.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-layout-001.html
@@ -5,7 +5,7 @@ <link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net"> <meta name=flags content=""> <meta name=assert content="layout containment does not apply to non atomic inlines"> - <link rel="match" href="reference/contain-size-001-ref.html"> + <link rel="match" href="../reference/pass_if_pass_below.html"> <link rel=help href="https://drafts.csswg.org/css-contain-1/#containment-layout"> <style> @@ -15,5 +15,5 @@ } </style> -<p>This test passes if you can see the word PASS below. +<p>Test passes if there is the word "PASS" below.</p> <div><span>PA</span>SS</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-layout-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-layout-002.html index c39d759..1ae149f 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-layout-002.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-layout-002.html
@@ -5,28 +5,32 @@ <link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net"> <meta name=flags content="ahem"> <meta name=assert content="layout containment does not apply to ruby-base"> - <link rel="match" href="reference/contain-layout-002-ref.html"> + <link rel="match" href="../reference/ref-filled-green-100px-square.xht"> <link rel=help href="https://drafts.csswg.org/css-contain-1/#containment-layout"> <style> +div { + position: relative; + background: red; + width: 100px; + height: 100px; + padding: 25px; + box-sizing: border-box; +} rb { contain: layout; display: ruby-base; - font-family: ahem; - font-size: 20px; + font-family: Ahem; + font-size: 100px; line-height: 1; } -rb::before { - content: "X"; - color: green; -} rb::after { content: "X"; - color: white; + color: green; position: absolute; top:0; left: 0; } </style> -<p>This test passes if you can see a green box below. +<p>Test passes if there is a filled green square and <strong>no red</strong>.</p> <div><ruby><rb></rb></ruby></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-layout-003.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-layout-003.html index b1bc241..1b063f1 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-layout-003.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-layout-003.html
@@ -5,28 +5,32 @@ <link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net"> <meta name=flags content="ahem"> <meta name=assert content="layout containment does not apply to ruby-base-container"> - <link rel="match" href="reference/contain-layout-002-ref.html"> + <link rel="match" href="../reference/ref-filled-green-100px-square.xht"> <link rel=help href="https://drafts.csswg.org/css-contain-1/#containment-layout"> <style> +div { + position: relative; + background: red; + width: 100px; + height: 100px; + padding: 25px; + box-sizing: border-box; +} rbc { contain: layout; display: ruby-base-container; - font-family: ahem; - font-size: 20px; + font-family: Ahem; + font-size: 100px; line-height: 1; } -rbc::before { - content: "X"; - color: green; -} rbc::after { content: "X"; - color: white; + color: green; position: absolute; top:0; left: 0; } </style> -<p>This test passes if you can see a green box below. +<p>Test passes if there is a filled green square and <strong>no red</strong>.</p> <div><ruby><rbc></rbc></ruby></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-layout-004.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-layout-004.html index 93af6ee..483aeae 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-layout-004.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-layout-004.html
@@ -5,28 +5,32 @@ <link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net"> <meta name=flags content="ahem"> <meta name=assert content="layout containment does not apply to ruby-text-container"> - <link rel="match" href="reference/contain-layout-004-ref.html"> + <link rel="match" href="../reference/ref-filled-green-100px-square.xht"> <link rel=help href="https://drafts.csswg.org/css-contain-1/#containment-layout"> <style> +div { + position: relative; + background: red; + width: 100px; + height: 100px; + padding: 25px; + box-sizing: border-box; +} rtc { contain: layout; display: ruby-text-container; - font-family: ahem; - font-size: 20px; + font-family: Ahem; + font-size: 100px; line-height: 1; } -rtc::before { - content: "X"; - color: green; -} rtc::after { content: "X"; - color: white; + color: green; position: absolute; top:0; left: 0; } </style> -<p>This test passes if you can see a green box below. +<p>Test passes if there is a filled green square and <strong>no red</strong>.</p> <div><ruby><rtc></rtc></ruby></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-layout-005.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-layout-005.html index f348359..39ef209 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-layout-005.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-layout-005.html
@@ -5,28 +5,32 @@ <link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net"> <meta name=flags content="ahem"> <meta name=assert content="layout containment does not apply to ruby-text"> - <link rel="match" href="reference/contain-layout-005-ref.html"> + <link rel="match" href="../reference/ref-filled-green-100px-square.xht"> <link rel=help href="https://drafts.csswg.org/css-contain-1/#containment-layout"> <style> +div { + position: relative; + background: red; + width: 100px; + height: 100px; + padding: 25px; + box-sizing: border-box; +} rt { contain: layout; display: ruby-text; - font-family: ahem; - font-size: 20px; + font-family: Ahem; + font-size: 100px; line-height: 1; } -rt::before { - content: "X"; - color: green; -} rt::after { content: "X"; - color: white; + color: green; position: absolute; top:0; left: 0; } </style> -<p>This test passes if you can see a green box below. +<p>Test passes if there is a filled green square and <strong>no red</strong>.</p> <div><ruby><rt></rt></ruby></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-002.html index ff59a234..6f495f56 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-002.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-002.html
@@ -5,7 +5,7 @@ <link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net"> <meta name=flags content=""> <meta name=assert content="paint containment does not apply to non atomic inlines"> - <link rel="match" href="reference/contain-size-001-ref.html"> + <link rel="match" href="../reference/pass_if_pass_below.html"> <link rel=help href="https://drafts.csswg.org/css-contain-1/#containment-paint"> <style> @@ -19,5 +19,5 @@ } </style> -<p>This test passes if you can see the word PASS below. +<p>Test passes if there is the word "PASS" below.</p> <div><span></span></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-003.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-003.html index 7db9c20..ae9238d 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-003.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-003.html
@@ -5,14 +5,14 @@ <link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net"> <meta name=flags content=""> <meta name=assert content="paint containment applies to the principal box, which is the table wrapper box for tables"> - <link rel="match" href="reference/contain-size-001-ref.html"> + <link rel="match" href="../reference/pass_if_pass_below.html"> <link rel=help href="https://drafts.csswg.org/css-contain-1/#containment-paint"> <style> table { contain: paint; } </style> -<p>This test passes if you can see the word PASS below. +<p>Test passes if there is the word "PASS" below.</p> <table> <caption>PASS</caption> </table>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-004.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-004.html index a3941b3..d37676d 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-004.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-004.html
@@ -5,14 +5,14 @@ <link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net"> <meta name=flags content=""> <meta name=assert content="paint containment applies to the principal box, which for list items excludes the list marker"> - <link rel="match" href="reference/contain-paint-004-ref.html"> + <link rel="match" href="../reference/nothing.html"> <link rel=help href="https://drafts.csswg.org/css-contain-1/#containment-paint"> <style> li { contain: paint; } </style> -<p>This test passes if you can see no number below. +<p>There should be nothing below.</p> <ol> <li> <li>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-005.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-005.html index 71ceae4f..a6817be 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-005.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-005.html
@@ -5,7 +5,7 @@ <link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net"> <meta name=flags content=""> <meta name=assert content="paint containment does not apply to ruby-base"> - <link rel="match" href="reference/contain-size-001-ref.html"> + <link rel="match" href="../reference/pass_if_pass_below.html"> <link rel=help href="https://drafts.csswg.org/css-contain-1/#containment-paint"> <style> @@ -20,5 +20,5 @@ } </style> -<p>This test passes if you can see the word PASS below. +<p>Test passes if there is the word "PASS" below.</p> <div><ruby><rb></rb></ruby></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-006.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-006.html index 1349c186..b04a78f 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-006.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-006.html
@@ -5,7 +5,7 @@ <link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net"> <meta name=flags content=""> <meta name=assert content="paint containment does not apply to ruby-base-container"> - <link rel="match" href="reference/contain-size-001-ref.html"> + <link rel="match" href="../reference/pass_if_pass_below.html"> <link rel=help href="https://drafts.csswg.org/css-contain-1/#containment-paint"> <style> @@ -20,5 +20,5 @@ } </style> -<p>This test passes if you can see the word PASS below. +<p>Test passes if there is the word "PASS" below.</p> <div><ruby><rbc></rbc></ruby></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-014.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-014.html index d1eb4ec8..ee6bc787 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-014.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-014.html
@@ -3,7 +3,7 @@ <title>CSS Containment Test: Paint containment on table-cell</title> <link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com"> <link rel="help" href="https://drafts.csswg.org/css-contain-1/#containment-paint"> -<link rel="match" href="reference/contain-paint-014-ref.html"> +<link rel="match" href="../reference/nothing.html"> <meta name=assert content="Paint containment does apply to table-cell elements."> <style> div { @@ -15,5 +15,5 @@ } </style> -<p>This test passes if you can NOT see the word FAIL below.</p> +<p>There should be nothing below.</p> <div><span>FAIL</span></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-015.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-015.html index 0e50bea..702bfb62 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-015.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-015.html
@@ -3,7 +3,7 @@ <title>CSS Containment Test: Paint containment on table-row-group</title> <link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com"> <link rel="help" href="https://drafts.csswg.org/css-contain-1/#containment-paint"> -<link rel="match" href="reference/contain-size-001-ref.html"> +<link rel="match" href="../reference/pass_if_pass_below.html"> <meta name=assert content="Paint containment doesn't apply to table-row-group elements."> <style> div { @@ -15,5 +15,5 @@ } </style> -<p>This test passes if you can see the word PASS below.</p> +<p>Test passes if there is the word "PASS" below.</p> <div><span>PASS</span></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-016.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-016.html index 309b5a08..cb16009e 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-016.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-016.html
@@ -3,7 +3,7 @@ <title>CSS Containment Test: Paint containment on table-header-group</title> <link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com"> <link rel="help" href="https://drafts.csswg.org/css-contain-1/#containment-paint"> -<link rel="match" href="reference/contain-size-001-ref.html"> +<link rel="match" href="../reference/pass_if_pass_below.html"> <meta name=assert content="Paint containment doesn't apply to table-header-group elements."> <style> div { @@ -15,5 +15,5 @@ } </style> -<p>This test passes if you can see the word PASS below.</p> +<p>Test passes if there is the word "PASS" below.</p> <div><span>PASS</span></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-017.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-017.html index 578f382..d1e57d4 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-017.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-017.html
@@ -3,7 +3,7 @@ <title>CSS Containment Test: Paint containment on table-footer-group</title> <link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com"> <link rel="help" href="https://drafts.csswg.org/css-contain-1/#containment-paint"> -<link rel="match" href="reference/contain-size-001-ref.html"> +<link rel="match" href="../reference/pass_if_pass_below.html"> <meta name=assert content="Paint containment doesn't apply to table-footer-group elements."> <style> div { @@ -15,5 +15,5 @@ } </style> -<p>This test passes if you can see the word PASS below.</p> +<p>Test passes if there is the word "PASS" below.</p> <div><span>PASS</span></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-018.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-018.html index bf19131..f4b92da 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-018.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-018.html
@@ -3,7 +3,7 @@ <title>CSS Containment Test: Paint containment on table-row</title> <link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com"> <link rel="help" href="https://drafts.csswg.org/css-contain-1/#containment-paint"> -<link rel="match" href="reference/contain-size-001-ref.html"> +<link rel="match" href="../reference/pass_if_pass_below.html"> <meta name=assert content="Paint containment doesn't apply to table-row elements."> <style> div { @@ -15,5 +15,5 @@ } </style> -<p>This test passes if you can see the word PASS below.</p> +<p>Test passes if there is the word "PASS" below.</p> <div><span>PASS</span></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-019.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-019.html index 131463c4..90c5a8f0 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-019.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-paint-019.html
@@ -3,7 +3,7 @@ <title>CSS Containment Test: Paint containment on table-caption</title> <link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com"> <link rel="help" href="https://drafts.csswg.org/css-contain-1/#containment-paint"> -<link rel="match" href="reference/contain-paint-014-ref.html"> +<link rel="match" href="../reference/nothing.html"> <meta name=assert content="Paint containment does apply to table-caption elements."> <style> div { @@ -15,5 +15,5 @@ } </style> -<p>This test passes if you can NOT see the word FAIL below.</p> +<p>There should be nothing below.</p> <div><span>FAIL</span></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-001.html index 5ed871b..85bc4f4 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-001.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-001.html
@@ -5,7 +5,7 @@ <link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net"> <meta name=flags content=""> <meta name=assert content="size containment does not apply to non atomic inlines"> - <link rel="match" href="reference/contain-size-001-ref.html"> + <link rel="match" href="../reference/pass_if_pass_below.html"> <link rel=help href="https://drafts.csswg.org/css-contain-1/#containment-size"> <style> @@ -13,5 +13,5 @@ span { contain: size; } </style> -<p>This test passes if you can see the word PASS below. +<p>Test passes if there is the word "PASS" below.</p> <div><span>PASS</span></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-002.html index e844c67f..490fd6a 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-002.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-002.html
@@ -5,7 +5,7 @@ <link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net"> <meta name=flags content=""> <meta name=assert content="size containment does not to apply ruby-base, which is an internatl ruby element"> - <link rel="match" href="reference/contain-size-001-ref.html"> + <link rel="match" href="../reference/pass_if_pass_below.html"> <link rel=help href="https://drafts.csswg.org/css-contain-1/#containment-size"> <link rel=help href="https://drafts.csswg.org/css-display-3/#internal-ruby-element"> @@ -20,5 +20,5 @@ } </style> -<p>This test passes if you can see the word PASS below. +<p>Test passes if there is the word "PASS" below.</p> <div><ruby><rb>PASS</rb></ruby></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-003.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-003.html index 95827dc..e767e2148 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-003.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-003.html
@@ -5,7 +5,7 @@ <link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net"> <meta name=flags content=""> <meta name=assert content="size containment does not to apply ruby-base-container, which is an internatl ruby element"> - <link rel="match" href="reference/contain-size-001-ref.html"> + <link rel="match" href="../reference/pass_if_pass_below.html"> <link rel=help href="https://drafts.csswg.org/css-contain-1/#containment-size"> <link rel=help href="https://drafts.csswg.org/css-display-3/#internal-ruby-element"> @@ -20,5 +20,5 @@ } </style> -<p>This test passes if you can see the word PASS below. +<p>Test passes if there is the word "PASS" below.</p> <div><ruby><rbc>PASS</rbc></ruby></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-006.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-006.html index dc1773e..f5c17152d 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-006.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-006.html
@@ -3,7 +3,7 @@ <title>CSS Containment Test: Size containment on table-cell</title> <link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com"> <link rel="help" href="https://drafts.csswg.org/css-contain-1/#containment-size"> -<link rel="match" href="reference/contain-size-001-ref.html"> +<link rel="match" href="../reference/pass_if_pass_below.html"> <meta name=assert content="Size containment doesn't apply to table-cell elements."> <style> div { @@ -13,5 +13,5 @@ } </style> -<p>This test passes if you can see the word PASS below.</p> +<p>Test passes if there is the word "PASS" below.</p> <div>PASS</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-007.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-007.html index 9cf6d91..71e61af 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-007.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-007.html
@@ -3,7 +3,7 @@ <title>CSS Containment Test: Size containment on table-row-group</title> <link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com"> <link rel="help" href="https://drafts.csswg.org/css-contain-1/#containment-size"> -<link rel="match" href="reference/contain-size-001-ref.html"> +<link rel="match" href="../reference/pass_if_pass_below.html"> <meta name=assert content="Size containment doesn't apply to table-row-group elements."> <style> div { @@ -13,5 +13,5 @@ } </style> -<p>This test passes if you can see the word PASS below.</p> +<p>Test passes if there is the word "PASS" below.</p> <div>PASS</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-008.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-008.html index 07ba0e2..fb7b525 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-008.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-008.html
@@ -3,7 +3,7 @@ <title>CSS Containment Test: Size containment on table-header-group</title> <link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com"> <link rel="help" href="https://drafts.csswg.org/css-contain-1/#containment-size"> -<link rel="match" href="reference/contain-size-001-ref.html"> +<link rel="match" href="../reference/pass_if_pass_below.html"> <meta name=assert content="Size containment doesn't apply to table-header-group elements."> <style> div { @@ -13,5 +13,5 @@ } </style> -<p>This test passes if you can see the word PASS below.</p> +<p>Test passes if there is the word "PASS" below.</p> <div>PASS</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-009.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-009.html index a3ca43c2..4b080c4 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-009.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-009.html
@@ -3,7 +3,7 @@ <title>CSS Containment Test: Size containment on table-footer-group</title> <link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com"> <link rel="help" href="https://drafts.csswg.org/css-contain-1/#containment-size"> -<link rel="match" href="reference/contain-size-001-ref.html"> +<link rel="match" href="../reference/pass_if_pass_below.html"> <meta name=assert content="Size containment doesn't apply to table-footer-group elements."> <style> div { @@ -13,5 +13,5 @@ } </style> -<p>This test passes if you can see the word PASS below.</p> +<p>Test passes if there is the word "PASS" below.</p> <div>PASS</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-010.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-010.html index a28110d0..59fdb8b 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-010.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-010.html
@@ -3,7 +3,7 @@ <title>CSS Containment Test: Size containment on table-row</title> <link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com"> <link rel="help" href="https://drafts.csswg.org/css-contain-1/#containment-size"> -<link rel="match" href="reference/contain-size-001-ref.html"> +<link rel="match" href="../reference/pass_if_pass_below.html"> <meta name=assert content="Size containment doesn't apply to table-row elements."> <style> div { @@ -13,5 +13,5 @@ } </style> -<p>This test passes if you can see the word PASS below.</p> +<p>Test passes if there is the word "PASS" below.</p> <div>PASS</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-011.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-011.html index 0d8e3670..f2a14693 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-011.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-011.html
@@ -3,7 +3,7 @@ <title>CSS Containment Test: Size containment on table-caption</title> <link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com"> <link rel="help" href="https://drafts.csswg.org/css-contain-1/#containment-size"> -<link rel="match" href="reference/contain-paint-014-ref.html"> +<link rel="match" href="../reference/nothing.html"> <meta name=assert content="Size containment does apply to table-caption elements."> <style> div { @@ -13,5 +13,5 @@ } </style> -<p>This test passes if you can NOT see the word FAIL below.</p> +<p>There should be nothing below.</p> <div>FAIL</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-012.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-012.html index 73a79e0..6823292 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-012.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/contain-size-012.html
@@ -3,7 +3,7 @@ <title>CSS Containment Test: Size containment on table</title> <link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com"> <link rel="help" href="https://drafts.csswg.org/css-contain-1/#containment-size"> -<link rel="match" href="reference/contain-size-001-ref.html"> +<link rel="match" href="../reference/pass_if_pass_below.html"> <meta name=assert content="Size containment doesn't apply to table elements."> <style> div { @@ -13,5 +13,5 @@ } </style> -<p>This test passes if you can see the word PASS below.</p> +<p>Test passes if there is the word "PASS" below.</p> <div>PASS</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/reference/contain-layout-002-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/reference/contain-layout-002-ref.html deleted file mode 100644 index 5fbeb3a7..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/reference/contain-layout-002-ref.html +++ /dev/null
@@ -1,27 +0,0 @@ -<!doctype html> -<html lang=en> - <meta charset=utf-8> - <title>CSS-contain test referene</title> - <link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net"> - <meta name=flags content="ahem"> - -<style> -rb { - font-family: ahem; - font-size: 20px; - line-height: 1; -} -rb::before { - content: "X"; - color: green; -} -rb::after { - content: "X"; - color: white; - position: absolute; - top:0; left: 0; -} -</style> - -<p>This test passes if you can see a green box below. -<div><ruby><rb></rb></ruby></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/reference/contain-layout-004-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/reference/contain-layout-004-ref.html deleted file mode 100644 index f3279e9b..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/reference/contain-layout-004-ref.html +++ /dev/null
@@ -1,28 +0,0 @@ -<!doctype html> -<html lang=en> - <meta charset=utf-8> - <title>CSS-contain test reference</title> - <link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net"> - <meta name=flags content="ahem"> - -<style> -rtc { - display: ruby-text-container; - font-family: ahem; - font-size: 20px; - line-height: 1; -} -rtc::before { - content: "X"; - color: green; -} -rtc::after { - content: "X"; - color: white; - position: absolute; - top:0; left: 0; -} -</style> - -<p>This test passes if you can see a green box below. -<div><ruby><rtc></rtc></ruby></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/reference/contain-layout-005-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/reference/contain-layout-005-ref.html deleted file mode 100644 index 0b2792f..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/reference/contain-layout-005-ref.html +++ /dev/null
@@ -1,28 +0,0 @@ -<!doctype html> -<html lang=en> - <meta charset=utf-8> - <title>CSS-contain test reference</title> - <link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net"> - <meta name=flags content="ahem"> - -<style> -rt { - display: ruby-text; - font-family: ahem; - font-size: 20px; - line-height: 1; -} -rt::before { - content: "X"; - color: green; -} -rt::after { - content: "X"; - color: white; - position: absolute; - top:0; left: 0; -} -</style> - -<p>This test passes if you can see a green box below. -<div><ruby><rt></rt></ruby></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/reference/contain-paint-004-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/reference/contain-paint-004-ref.html deleted file mode 100644 index c03b4c8..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/reference/contain-paint-004-ref.html +++ /dev/null
@@ -1,7 +0,0 @@ -<!doctype html> -<html lang=en> - <meta charset=utf-8> - <title>CSS-contain test reference</title> - <link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net"> - -<p>This test passes if you can see no number below.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/reference/contain-paint-014-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/reference/contain-paint-014-ref.html deleted file mode 100644 index 6617f777..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/reference/contain-paint-014-ref.html +++ /dev/null
@@ -1,5 +0,0 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<title>CSS Containment Test: Reference file</title> -<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com"> -<p>This test passes if you can NOT see the word FAIL below.</p>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/reference/contain-size-001-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/reference/contain-size-001-ref.html deleted file mode 100644 index 9b669db1..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-contain/reference/contain-size-001-ref.html +++ /dev/null
@@ -1,8 +0,0 @@ -<!doctype html> -<html lang=en> - <meta charset=utf-8> - <title>CSS-contain test reference</title> - <link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net"> - -<p>This test passes if you can see the word PASS below. -<div>PASS</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-font-loading/idlharness.https.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-font-loading/idlharness.https.html index d507a61..9e3d45fb 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-font-loading/idlharness.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-font-loading/idlharness.https.html
@@ -8,22 +8,17 @@ <script> 'use strict'; -promise_test(async () => { - const srcs = ['css-font-loading', 'dom', 'html', 'cssom']; - const [cssfontloading, dom, html, cssom] = await Promise.all( - srcs.map(i => fetch(`/interfaces/${i}.idl`).then(r => r.text()))); - - const idl_array = new IdlArray(); - idl_array.add_idls(cssfontloading); - idl_array.add_dependency_idls(dom); - idl_array.add_dependency_idls(html); - idl_array.add_dependency_idls(cssom); - idl_array.add_objects({ - Document: ['document'], - FontFace: ['new FontFace("family", "src")'], - FontFaceSetLoadEvent: ['new FontFaceSetLoadEvent("type")'], - FontFaceSet: ['document.fonts'], - }); - idl_array.test(); -}, 'css-font-loading interfaces'); +idl_test( + ['css-font-loading'], + ['dom', 'html', 'cssom'], + idl_array => { + idl_array.add_objects({ + Document: ['document'], + FontFace: ['new FontFace("family", "src")'], + FontFaceSetLoadEvent: ['new FontFaceSetLoadEvent("type")'], + FontFaceSet: ['document.fonts'], + }); + }, + 'css-font-loading interfaces' +); </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encoding/idlharness.any.js b/third_party/WebKit/LayoutTests/external/wpt/encoding/idlharness.any.js index 25ec97a5..14335ba2 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/encoding/idlharness.any.js +++ b/third_party/WebKit/LayoutTests/external/wpt/encoding/idlharness.any.js
@@ -2,13 +2,14 @@ // META: script=/resources/WebIDLParser.js // META: script=/resources/idlharness.js -promise_test(async() => { - const text = await (await fetch('/interfaces/encoding.idl')).text(); - const idl_array = new IdlArray(); - idl_array.add_idls(text); - idl_array.add_objects({ - TextEncoder: ['new TextEncoder()'], - TextDecoder: ['new TextDecoder()'] - }); - idl_array.test(); -}, 'Encoding Standard IDL'); +idl_test( + ['encoding'], + [], // No deps + idl_array => { + idl_array.add_objects({ + TextEncoder: ['new TextEncoder()'], + TextDecoder: ['new TextDecoder()'] + }); + }, + 'Encoding Standard IDL' +);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/gamepad/idlharness.html b/third_party/WebKit/LayoutTests/external/wpt/gamepad/idlharness.html deleted file mode 100644 index 6a27e47..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/gamepad/idlharness.html +++ /dev/null
@@ -1,30 +0,0 @@ -<!doctype html> -<title>Gamepad IDL tests</title> -<link rel="help" href="https://w3c.github.io/gamepad/#gamepad-interface"> -<link rel="help" href="https://w3c.github.io/gamepad/#gamepadbutton-interface"> -<link rel="help" href="https://w3c.github.io/gamepad/#gamepadevent-interface"> -<link rel="help" href="https://w3c.github.io/gamepad/#navigator-interface-extension"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script src="/resources/WebIDLParser.js"></script> -<script src="/resources/idlharness.js"></script> -<script> - "use strict"; - - promise_test(async () => { - const srcs = ['gamepad', 'dom', 'html']; - const [idl, dom, html] = await Promise.all( - srcs.map(i => fetch(`/interfaces/${i}.idl`).then(r => r.text()))); - - const idl_array = new IdlArray(); - idl_array.add_idls(idl); - idl_array.add_dependency_idls(dom); - idl_array.add_dependency_idls(html); - - idl_array.add_objects({ - GamepadEvent: [new GamepadEvent("something")], - Navigator: ["navigator"] - }); - idl_array.test(); - }, "Test IDL implementation of Gamepad API"); -</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/gamepad/idlharness.window-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/gamepad/idlharness.window-expected.txt new file mode 100644 index 0000000..1c52378 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/gamepad/idlharness.window-expected.txt
@@ -0,0 +1,52 @@ +This is a testharness.js-based test. +PASS Test IDL implementation of Gamepad API +PASS Partial interface Navigator: original interface defined +PASS Partial interface Navigator: valid exposure set +PASS Gamepad interface: existence and properties of interface object +PASS Gamepad interface object length +PASS Gamepad interface object name +PASS Gamepad interface: existence and properties of interface prototype object +PASS Gamepad interface: existence and properties of interface prototype object's "constructor" property +PASS Gamepad interface: existence and properties of interface prototype object's @@unscopables property +PASS Gamepad interface: attribute id +PASS Unscopable handled correctly for id property on Gamepad +PASS Gamepad interface: attribute index +PASS Unscopable handled correctly for index property on Gamepad +PASS Gamepad interface: attribute connected +PASS Unscopable handled correctly for connected property on Gamepad +PASS Gamepad interface: attribute timestamp +PASS Unscopable handled correctly for timestamp property on Gamepad +PASS Gamepad interface: attribute mapping +PASS Unscopable handled correctly for mapping property on Gamepad +PASS Gamepad interface: attribute axes +PASS Unscopable handled correctly for axes property on Gamepad +PASS Gamepad interface: attribute buttons +PASS Unscopable handled correctly for buttons property on Gamepad +PASS GamepadButton interface: existence and properties of interface object +PASS GamepadButton interface object length +PASS GamepadButton interface object name +PASS GamepadButton interface: existence and properties of interface prototype object +PASS GamepadButton interface: existence and properties of interface prototype object's "constructor" property +PASS GamepadButton interface: existence and properties of interface prototype object's @@unscopables property +PASS GamepadButton interface: attribute pressed +PASS Unscopable handled correctly for pressed property on GamepadButton +PASS GamepadButton interface: attribute touched +PASS Unscopable handled correctly for touched property on GamepadButton +PASS GamepadButton interface: attribute value +PASS Unscopable handled correctly for value property on GamepadButton +PASS GamepadEvent interface: existence and properties of interface object +FAIL GamepadEvent interface object length assert_equals: wrong value for GamepadEvent.length expected 2 but got 1 +PASS GamepadEvent interface object name +PASS GamepadEvent interface: existence and properties of interface prototype object +PASS GamepadEvent interface: existence and properties of interface prototype object's "constructor" property +PASS GamepadEvent interface: existence and properties of interface prototype object's @@unscopables property +PASS GamepadEvent interface: attribute gamepad +PASS Unscopable handled correctly for gamepad property on GamepadEvent +PASS GamepadEvent must be primary interface of new GamepadEvent("gamepad") +PASS Stringification of new GamepadEvent("gamepad") +PASS GamepadEvent interface: new GamepadEvent("gamepad") must inherit property "gamepad" with the proper type +PASS Navigator interface: operation getGamepads() +PASS Unscopable handled correctly for getGamepads() on Navigator +PASS Navigator interface: navigator must inherit property "getGamepads()" with the proper type +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/gamepad/idlharness.window.js b/third_party/WebKit/LayoutTests/external/wpt/gamepad/idlharness.window.js new file mode 100644 index 0000000..e2c0e2b --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/gamepad/idlharness.window.js
@@ -0,0 +1,18 @@ +// META: script=/resources/WebIDLParser.js +// META: script=/resources/idlharness.js + +// https://w3c.github.io/gamepad/ + +'use strict'; + +idl_test( + ['gamepad'], + ['dom', 'html'], + idl_array => { + idl_array.add_objects({ + GamepadEvent: ['new GamepadEvent("gamepad")'], + Navigator: ['navigator'] + }); + }, + 'Test IDL implementation of Gamepad API' +);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/geolocation-sensor/idlharness.https.html b/third_party/WebKit/LayoutTests/external/wpt/geolocation-sensor/idlharness.https.html deleted file mode 100644 index 75d29eb..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/geolocation-sensor/idlharness.https.html +++ /dev/null
@@ -1,35 +0,0 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<title>Geolocation Sensor IDL tests</title> -<link rel="help" href="https://wicg.github.io/geolocation-sensor/"> -<link rel="help" href="https://w3c.github.io/sensors/"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script src="/resources/WebIDLParser.js"></script> -<script src="/resources/idlharness.js"></script> -<script> -"use strict"; - -function doTest([generic_sensor, geolocation_sensor]) { - const idl_array = new IdlArray(); - idl_array.add_untested_idls('interface EventTarget {};'); - idl_array.add_untested_idls('interface EventHandler {};'); - idl_array.add_idls(generic_sensor, { only: ['Sensor', 'SensorOptions'] }); - idl_array.add_idls(geolocation_sensor); - idl_array.add_objects({ - GeolocationSensor: ['new GeolocationSensor'], - }); - idl_array.test(); -} - -function fetchText(url) { - return fetch(url).then((response) => response.text()); -} - -promise_test(() => { - return Promise.all([ - "/interfaces/sensors.idl", - "/interfaces/geolocation-sensor.idl" - ].map(fetchText)).then(doTest); -}, "Test IDL implementation of Geolocation Sensor"); -</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/geolocation-sensor/idlharness.https.window-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/geolocation-sensor/idlharness.https.window-expected.txt new file mode 100644 index 0000000..26853bc --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/geolocation-sensor/idlharness.https.window-expected.txt
@@ -0,0 +1,37 @@ +This is a testharness.js-based test. +PASS Test IDL implementation of Geolocation Sensor +FAIL GeolocationSensor interface: existence and properties of interface object assert_own_property: self does not have own property "GeolocationSensor" expected property "GeolocationSensor" missing +FAIL GeolocationSensor interface object length assert_own_property: self does not have own property "GeolocationSensor" expected property "GeolocationSensor" missing +FAIL GeolocationSensor interface object name assert_own_property: self does not have own property "GeolocationSensor" expected property "GeolocationSensor" missing +FAIL GeolocationSensor interface: existence and properties of interface prototype object assert_own_property: self does not have own property "GeolocationSensor" expected property "GeolocationSensor" missing +FAIL GeolocationSensor interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "GeolocationSensor" expected property "GeolocationSensor" missing +FAIL GeolocationSensor interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "GeolocationSensor" expected property "GeolocationSensor" missing +FAIL GeolocationSensor interface: operation read(ReadOptions) assert_own_property: self does not have own property "GeolocationSensor" expected property "GeolocationSensor" missing +PASS Unscopable handled correctly for read(ReadOptions) on GeolocationSensor +FAIL GeolocationSensor interface: attribute latitude assert_own_property: self does not have own property "GeolocationSensor" expected property "GeolocationSensor" missing +PASS Unscopable handled correctly for latitude property on GeolocationSensor +FAIL GeolocationSensor interface: attribute longitude assert_own_property: self does not have own property "GeolocationSensor" expected property "GeolocationSensor" missing +PASS Unscopable handled correctly for longitude property on GeolocationSensor +FAIL GeolocationSensor interface: attribute altitude assert_own_property: self does not have own property "GeolocationSensor" expected property "GeolocationSensor" missing +PASS Unscopable handled correctly for altitude property on GeolocationSensor +FAIL GeolocationSensor interface: attribute accuracy assert_own_property: self does not have own property "GeolocationSensor" expected property "GeolocationSensor" missing +PASS Unscopable handled correctly for accuracy property on GeolocationSensor +FAIL GeolocationSensor interface: attribute altitudeAccuracy assert_own_property: self does not have own property "GeolocationSensor" expected property "GeolocationSensor" missing +PASS Unscopable handled correctly for altitudeAccuracy property on GeolocationSensor +FAIL GeolocationSensor interface: attribute heading assert_own_property: self does not have own property "GeolocationSensor" expected property "GeolocationSensor" missing +PASS Unscopable handled correctly for heading property on GeolocationSensor +FAIL GeolocationSensor interface: attribute speed assert_own_property: self does not have own property "GeolocationSensor" expected property "GeolocationSensor" missing +PASS Unscopable handled correctly for speed property on GeolocationSensor +FAIL GeolocationSensor must be primary interface of new GeolocationSensor assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: GeolocationSensor is not defined" +FAIL Stringification of new GeolocationSensor assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: GeolocationSensor is not defined" +FAIL GeolocationSensor interface: new GeolocationSensor must inherit property "read(ReadOptions)" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: GeolocationSensor is not defined" +FAIL GeolocationSensor interface: calling read(ReadOptions) on new GeolocationSensor with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: GeolocationSensor is not defined" +FAIL GeolocationSensor interface: new GeolocationSensor must inherit property "latitude" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: GeolocationSensor is not defined" +FAIL GeolocationSensor interface: new GeolocationSensor must inherit property "longitude" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: GeolocationSensor is not defined" +FAIL GeolocationSensor interface: new GeolocationSensor must inherit property "altitude" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: GeolocationSensor is not defined" +FAIL GeolocationSensor interface: new GeolocationSensor must inherit property "accuracy" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: GeolocationSensor is not defined" +FAIL GeolocationSensor interface: new GeolocationSensor must inherit property "altitudeAccuracy" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: GeolocationSensor is not defined" +FAIL GeolocationSensor interface: new GeolocationSensor must inherit property "heading" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: GeolocationSensor is not defined" +FAIL GeolocationSensor interface: new GeolocationSensor must inherit property "speed" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: GeolocationSensor is not defined" +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/geolocation-sensor/idlharness.https.window.js b/third_party/WebKit/LayoutTests/external/wpt/geolocation-sensor/idlharness.https.window.js new file mode 100644 index 0000000..eb3da34f --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/geolocation-sensor/idlharness.https.window.js
@@ -0,0 +1,17 @@ +// META: script=/resources/WebIDLParser.js +// META: script=/resources/idlharness.js + +// https://wicg.github.io/geolocation-sensor/ + +'use strict'; + +idl_test( + ['geolocation-sensor'], + ['generic-sensor', 'dom'], + idl_array => { + idl_array.add_objects({ + GeolocationSensor: ['new GeolocationSensor'], + }); + }, + 'Test IDL implementation of Geolocation Sensor' +);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/gyroscope/idlharness.https.html b/third_party/WebKit/LayoutTests/external/wpt/gyroscope/idlharness.https.html deleted file mode 100644 index 4b3ed48..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/gyroscope/idlharness.https.html +++ /dev/null
@@ -1,37 +0,0 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<title>Gyroscope Sensor IDL tests</title> -<link rel="author" title="Intel" href="http://www.intel.com"> -<link rel="help" href="https://w3c.github.io/gyroscope/"> -<link rel="help" href="https://w3c.github.io/sensors/"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script src="/resources/WebIDLParser.js"></script> -<script src="/resources/idlharness.js"></script> -<script> -"use strict"; - -function doTest([dom, generic_sensor, gyroscope]) { - const idl_array = new IdlArray(); - idl_array.add_untested_idls(dom); - idl_array.add_untested_idls('interface EventHandler {};'); - idl_array.add_idls(generic_sensor, { only: ['Sensor', 'SensorOptions'] }); - idl_array.add_idls(gyroscope); - idl_array.add_objects({ - Gyroscope: ['new Gyroscope();'] - }); - idl_array.test(); -} - -function fetchText(url) { - return fetch(url).then((response) => response.text()); -} - -promise_test(() => { - return Promise.all([ - "/interfaces/dom.idl", - "/interfaces/sensors.idl", - "/interfaces/gyroscope.idl", - ].map(fetchText)).then(doTest); -}, "Test IDL implementation of Gyroscope Sensor"); -</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/gyroscope/idlharness.https.window.js b/third_party/WebKit/LayoutTests/external/wpt/gyroscope/idlharness.https.window.js new file mode 100644 index 0000000..dfdac4e1 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/gyroscope/idlharness.https.window.js
@@ -0,0 +1,17 @@ +// META: script=/resources/WebIDLParser.js +// META: script=/resources/idlharness.js + +// https://w3c.github.io/gyroscope/ + +'use strict'; + +idl_test( + ['gyroscope'], + ['generic-sensor', 'dom'], + idl_array => { + idl_array.add_objects({ + Gyroscope: ['new Gyroscope();'] + }); + }, + 'Test IDL implementation of Gyroscope Sensor' +);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/embedded-content/the-img-element/decode/image-decode-with-quick-attach.html b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/embedded-content/the-img-element/decode/image-decode-with-quick-attach.html new file mode 100644 index 0000000..be680da --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/embedded-content/the-img-element/decode/image-decode-with-quick-attach.html
@@ -0,0 +1,26 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<meta name="timeout" content="long"> +<title>HTMLImageElement.prototype.decode(), attach to DOM before promise resolves.</title> +<link rel="author" title="Vladimir Levin" href="mailto:vmpstr@chromium.org"> +<link rel=help href="https://html.spec.whatwg.org/multipage/embedded-content.html#dom-img-decode"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<body></body> + +<script> +"use strict"; + +promise_test(function() { + const img = new Image(); + img.src = "/images/green.png"; + const promise = img.decode().then(function(arg) { + assert_equals(arg, undefined); + }); + // Don't wait for the promise to resolve before attaching the image. + // The promise should still resolve successfully. + document.body.appendChild(img); + return promise; +}, document.title); +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/interfaces/geolocation-API.idl b/third_party/WebKit/LayoutTests/external/wpt/interfaces/geolocation-API.idl index 2972539e..c36fb8b 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/interfaces/geolocation-API.idl +++ b/third_party/WebKit/LayoutTests/external/wpt/interfaces/geolocation-API.idl
@@ -7,9 +7,9 @@ readonly attribute Geolocation geolocation; }; - - [NoInterfaceObject] +[NoInterfaceObject] interface Geolocation { + void getCurrentPosition(PositionCallback successCallback, optional PositionErrorCallback errorCallback, optional PositionOptions options); @@ -25,20 +25,19 @@ callback PositionErrorCallback = void (PositionError positionError); - dictionary PositionOptions { +dictionary PositionOptions { boolean enableHighAccuracy = false; [Clamp] unsigned long timeout = 0xFFFFFFFF; [Clamp] unsigned long maximumAge = 0; }; - - [NoInterfaceObject] +[NoInterfaceObject] interface Position { readonly attribute Coordinates coords; readonly attribute DOMTimeStamp timestamp; }; - [NoInterfaceObject] +[NoInterfaceObject] interface Coordinates { readonly attribute double latitude; readonly attribute double longitude; @@ -49,7 +48,7 @@ readonly attribute double? speed; }; - [NoInterfaceObject] +[NoInterfaceObject] interface PositionError { const unsigned short PERMISSION_DENIED = 1; const unsigned short POSITION_UNAVAILABLE = 2;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/interfaces/netinfo.idl b/third_party/WebKit/LayoutTests/external/wpt/interfaces/netinfo.idl index 75edd350..3e6212c 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/interfaces/netinfo.idl +++ b/third_party/WebKit/LayoutTests/external/wpt/interfaces/netinfo.idl
@@ -4,42 +4,39 @@ // See: https://wicg.github.io/netinfo/ enum ConnectionType { - "bluetooth", - "cellular", - "ethernet", - "mixed", - "none", - "other", - "unknown", - "wifi", - "wimax" + "bluetooth", + "cellular", + "ethernet", + "mixed", + "none", + "other", + "unknown", + "wifi", + "wimax" }; + enum EffectiveConnectionType { - "2g", - "3g", - "4g", - "slow-2g" + "2g", + "3g", + "4g", + "slow-2g" }; -[NoInterfaceObject, - Exposed=(Window,Worker)] + +[NoInterfaceObject, Exposed=(Window,Worker)] interface NavigatorNetworkInformation { - readonly attribute NetworkInformation connection; + readonly attribute NetworkInformation connection; }; Navigator implements NavigatorNetworkInformation; - WorkerNavigator implements NavigatorNetworkInformation; + [Exposed=(Window,Worker)] interface NetworkInformation : EventTarget { - readonly attribute ConnectionType type; - readonly attribute EffectiveConnectionType effectiveType; - readonly attribute Megabit downlinkMax; - readonly attribute Megabit downlink; - readonly attribute Millisecond rtt; - readonly attribute boolean saveData; - attribute EventHandler onchange; -}; - -typedef unrestricted double Megabit; - -typedef unsigned long long Millisecond; + readonly attribute ConnectionType type; + readonly attribute EffectiveConnectionType effectiveType; + readonly attribute Megabit downlinkMax; + readonly attribute Megabit downlink; + readonly attribute Millisecond rtt; + readonly attribute boolean saveData; + attribute EventHandler onchange; +};typedef unrestricted double Megabit;typedef unsigned long long Millisecond;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/interfaces/payment-request.idl b/third_party/WebKit/LayoutTests/external/wpt/interfaces/payment-request.idl index 6e42524..1018ecc 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/interfaces/payment-request.idl +++ b/third_party/WebKit/LayoutTests/external/wpt/interfaces/payment-request.idl
@@ -166,7 +166,7 @@ dictionary PaymentValidationErrors { PayerErrorFields payer; - AddressErrorFields shippingAddress; + AddressErrors shippingAddress; }; dictionary PayerErrorFields {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/interfaces/picture-in-picture.idl b/third_party/WebKit/LayoutTests/external/wpt/interfaces/picture-in-picture.idl index cafcae1..78a5ae7 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/interfaces/picture-in-picture.idl +++ b/third_party/WebKit/LayoutTests/external/wpt/interfaces/picture-in-picture.idl
@@ -22,7 +22,7 @@ readonly attribute Element? pictureInPictureElement; }; -interface PictureInPictureWindow { +interface PictureInPictureWindow : EventTarget { readonly attribute long width; readonly attribute long height;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/interfaces/pointerevents-extension.idl b/third_party/WebKit/LayoutTests/external/wpt/interfaces/pointerevents-extension.idl index 63a05a5..f4f2de3 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/interfaces/pointerevents-extension.idl +++ b/third_party/WebKit/LayoutTests/external/wpt/interfaces/pointerevents-extension.idl
@@ -1,8 +1,14 @@ -dictionary PointerEventInit : MouseEventInit { - sequence<PointerEvent> coalescedEvents; +// GENERATED CONTENT - DO NOT EDIT +// Content of this file was automatically extracted from the +// "PointerEvents - Level 2 - Extensions" spec. +// See: https://w3c.github.io/pointerevents/extension.html + +partial dictionary PointerEventInit { + sequence<PointerEvent> coalescedEvents = []; + sequence<PointerEvent> predictedEvents = []; }; -[Constructor(DOMString type, optional PointerEventInit eventInitDict)] -interface PointerEvent : MouseEvent { +partial interface PointerEvent { sequence<PointerEvent> getCoalescedEvents(); + sequence<PointerEvent> getPredictedEvents(); };
diff --git a/third_party/WebKit/LayoutTests/external/wpt/interfaces/requestidlecallback.idl b/third_party/WebKit/LayoutTests/external/wpt/interfaces/requestidlecallback.idl index 195f3767..6144781 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/interfaces/requestidlecallback.idl +++ b/third_party/WebKit/LayoutTests/external/wpt/interfaces/requestidlecallback.idl
@@ -4,19 +4,17 @@ // See: https://w3c.github.io/requestidlecallback/ partial interface Window { - unsigned long requestIdleCallback(IdleRequestCallback callback, - optional IdleRequestOptions options); - void cancelIdleCallback(unsigned long handle); + unsigned long requestIdleCallback(IdleRequestCallback callback, optional IdleRequestOptions options); + void cancelIdleCallback(unsigned long handle); }; dictionary IdleRequestOptions { - unsigned long timeout; + unsigned long timeout; }; -[Exposed=Window] -interface IdleDeadline { - DOMHighResTimeStamp timeRemaining(); - readonly attribute boolean didTimeout; +[Exposed=Window] interface IdleDeadline { + DOMHighResTimeStamp timeRemaining(); + readonly attribute boolean didTimeout; }; callback IdleRequestCallback = void (IdleDeadline deadline);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/interfaces/user-timing.idl b/third_party/WebKit/LayoutTests/external/wpt/interfaces/user-timing.idl index 576ee53..74139c6 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/interfaces/user-timing.idl +++ b/third_party/WebKit/LayoutTests/external/wpt/interfaces/user-timing.idl
@@ -6,14 +6,14 @@ partial interface Performance { void mark(DOMString markName); void clearMarks(optional DOMString markName); - void measure(DOMString measureName, - optional DOMString startMark, - optional DOMString endMark); + void measure(DOMString measureName, optional DOMString startMark, optional DOMString endMark); void clearMeasures(optional DOMString measureName); }; + [Exposed=(Window,Worker)] interface PerformanceMark : PerformanceEntry { }; + [Exposed=(Window,Worker)] interface PerformanceMeasure : PerformanceEntry { };
diff --git a/third_party/WebKit/LayoutTests/external/wpt/interfaces/webaudio.idl b/third_party/WebKit/LayoutTests/external/wpt/interfaces/webaudio.idl index 5f3085d..0ea32e50 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/interfaces/webaudio.idl +++ b/third_party/WebKit/LayoutTests/external/wpt/interfaces/webaudio.idl
@@ -46,8 +46,8 @@ WaveShaperNode createWaveShaper (); Promise<AudioBuffer> decodeAudioData (ArrayBuffer audioData, - optional DecodeSuccessCallback successCallback, - optional DecodeErrorCallback errorCallback); + optional DecodeSuccessCallback? successCallback, + optional DecodeErrorCallback? errorCallback); Promise<void> resume (); };
diff --git a/third_party/WebKit/LayoutTests/external/wpt/keyboard-lock/idlharness.https.html b/third_party/WebKit/LayoutTests/external/wpt/keyboard-lock/idlharness.https.html deleted file mode 100644 index a63e387..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/keyboard-lock/idlharness.https.html +++ /dev/null
@@ -1,34 +0,0 @@ -<!doctype html> -<html> -<head> -<title>Keyboard Lock IDL tests</title> -<link rel="help" href="https://w3c.github.io/keyboard-lock/"/> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script src="/resources/WebIDLParser.js"></script> -<script src="/resources/idlharness.js"></script> -<script> -'use strict'; - -function doTest(idls) { - var idl_array = new IdlArray(); - idl_array.add_untested_idls('interface Navigator {};'); - for (let idl of idls) { - idl_array.add_idls(idl); - } - idl_array.add_objects({ - Navigator: ['navigator'], - Keyboard: ['navigator.keyboard'], - }); - idl_array.test(); -}; - -function fetchText(url) { - return fetch(url).then((response) => response.text()); -} - -promise_test(() => { - return Promise.all(["/interfaces/keyboard-lock.idl"].map(fetchText)) - .then(doTest); -}, "Test driver"); -</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/keyboard-lock/idlharness.https.window.js b/third_party/WebKit/LayoutTests/external/wpt/keyboard-lock/idlharness.https.window.js new file mode 100644 index 0000000..27573bd --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/keyboard-lock/idlharness.https.window.js
@@ -0,0 +1,18 @@ +// META: script=/resources/WebIDLParser.js +// META: script=/resources/idlharness.js + +// https://w3c.github.io/keyboard-lock/ + +'use strict'; + +idl_test( + ['keyboard-lock'], + ['html'], + idl_array => { + idl_array.add_objects({ + Navigator: ['navigator'], + Keyboard: ['navigator.keyboard'], + }); + }, + 'keyboard-lock interfaces' +);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/keyboard-map/idlharness.https.html b/third_party/WebKit/LayoutTests/external/wpt/keyboard-map/idlharness.https.html deleted file mode 100644 index 05d687d..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/keyboard-map/idlharness.https.html +++ /dev/null
@@ -1,31 +0,0 @@ -<!doctype html> -<html> -<head> -<title>Keyboard Map IDL tests</title> -<link rel="help" href="https://wicg.github.io/keyboard-map/"/> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script src="/resources/WebIDLParser.js"></script> -<script src="/resources/idlharness.js"></script> -<script> -'use strict'; - -promise_test(async () => { - var idl_array = new IdlArray(); - const keyboard_map_idl = await fetch("/interfaces/keyboard-map.idl") - .then(r => r.text()); - const layout_map = await navigator.keyboard.getLayoutMap(); - - idl_array.add_untested_idls('interface Navigator {};'); - idl_array.add_idls(keyboard_map_idl); - - window.layout_map = layout_map; - - idl_array.add_objects({ - Navigator: ['navigator'], - Keyboard: ['navigator.keyboard'], - KeyboardLayoutMap: ['layout_map'], - }); - idl_array.test(); -}, "Test IDL implementation of Keyboard Map API"); -</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/keyboard-map/idlharness.https.window.js b/third_party/WebKit/LayoutTests/external/wpt/keyboard-map/idlharness.https.window.js new file mode 100644 index 0000000..d800166 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/keyboard-map/idlharness.https.window.js
@@ -0,0 +1,21 @@ +// META: script=/resources/WebIDLParser.js +// META: script=/resources/idlharness.js + +// https://wicg.github.io/keyboard-map/ + +'use strict'; + +idl_test( + ['keyboard-map'], + ['html'], + async idl_array => { + idl_array.add_objects({ + Navigator: ['navigator'], + Keyboard: ['navigator.keyboard'], + KeyboardLayoutMap: ['layout_map'], + }); + + self.layout_map = await navigator.keyboard.getLayoutMap(); + }, + 'Test IDL implementation of Keyboard Map API' +);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/magnetometer/idlharness.https.html b/third_party/WebKit/LayoutTests/external/wpt/magnetometer/idlharness.https.html deleted file mode 100644 index 904869eb..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/magnetometer/idlharness.https.html +++ /dev/null
@@ -1,38 +0,0 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<title>Magnetometer Sensor IDL tests</title> -<link rel="author" title="Intel" href="http://www.intel.com"> -<link rel="help" href="https://w3c.github.io/magnetometer/"> -<link rel="help" href="https://w3c.github.io/sensors/"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script src="/resources/WebIDLParser.js"></script> -<script src="/resources/idlharness.js"></script> -<script> -"use strict"; - -function doTest([dom, generic_sensor, magnetometer]) { - const idl_array = new IdlArray(); - idl_array.add_untested_idls(dom); - idl_array.add_untested_idls('interface EventHandler {};'); - idl_array.add_idls(generic_sensor, { only: ['Sensor', 'SensorOptions'] }); - idl_array.add_idls(magnetometer); - idl_array.add_objects({ - Magnetometer: ['new Magnetometer();'], - UncalibratedMagnetometer: ['new UncalibratedMagnetometer();'] - }); - idl_array.test(); -} - -function fetchText(url) { - return fetch(url).then((response) => response.text()); -} - -promise_test(() => { - return Promise.all([ - "/interfaces/dom.idl", - "/interfaces/sensors.idl", - "/interfaces/magnetometer.idl", - ].map(fetchText)).then(doTest); -}, "Test IDL implementation of Magnetometer Sensor"); -</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/magnetometer/idlharness.https.window-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/magnetometer/idlharness.https.window-expected.txt new file mode 100644 index 0000000..2f049ba1 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/magnetometer/idlharness.https.window-expected.txt
@@ -0,0 +1,47 @@ +This is a testharness.js-based test. +PASS Test IDL implementation of Magnetometer Sensor +PASS Magnetometer interface: existence and properties of interface object +PASS Magnetometer interface object length +PASS Magnetometer interface object name +PASS Magnetometer interface: existence and properties of interface prototype object +PASS Magnetometer interface: existence and properties of interface prototype object's "constructor" property +PASS Magnetometer interface: existence and properties of interface prototype object's @@unscopables property +PASS Magnetometer interface: attribute x +PASS Unscopable handled correctly for x property on Magnetometer +PASS Magnetometer interface: attribute y +PASS Unscopable handled correctly for y property on Magnetometer +PASS Magnetometer interface: attribute z +PASS Unscopable handled correctly for z property on Magnetometer +PASS Magnetometer must be primary interface of new Magnetometer(); +PASS Stringification of new Magnetometer(); +PASS Magnetometer interface: new Magnetometer(); must inherit property "x" with the proper type +PASS Magnetometer interface: new Magnetometer(); must inherit property "y" with the proper type +PASS Magnetometer interface: new Magnetometer(); must inherit property "z" with the proper type +FAIL UncalibratedMagnetometer interface: existence and properties of interface object assert_own_property: self does not have own property "UncalibratedMagnetometer" expected property "UncalibratedMagnetometer" missing +FAIL UncalibratedMagnetometer interface object length assert_own_property: self does not have own property "UncalibratedMagnetometer" expected property "UncalibratedMagnetometer" missing +FAIL UncalibratedMagnetometer interface object name assert_own_property: self does not have own property "UncalibratedMagnetometer" expected property "UncalibratedMagnetometer" missing +FAIL UncalibratedMagnetometer interface: existence and properties of interface prototype object assert_own_property: self does not have own property "UncalibratedMagnetometer" expected property "UncalibratedMagnetometer" missing +FAIL UncalibratedMagnetometer interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "UncalibratedMagnetometer" expected property "UncalibratedMagnetometer" missing +FAIL UncalibratedMagnetometer interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "UncalibratedMagnetometer" expected property "UncalibratedMagnetometer" missing +FAIL UncalibratedMagnetometer interface: attribute x assert_own_property: self does not have own property "UncalibratedMagnetometer" expected property "UncalibratedMagnetometer" missing +PASS Unscopable handled correctly for x property on UncalibratedMagnetometer +FAIL UncalibratedMagnetometer interface: attribute y assert_own_property: self does not have own property "UncalibratedMagnetometer" expected property "UncalibratedMagnetometer" missing +PASS Unscopable handled correctly for y property on UncalibratedMagnetometer +FAIL UncalibratedMagnetometer interface: attribute z assert_own_property: self does not have own property "UncalibratedMagnetometer" expected property "UncalibratedMagnetometer" missing +PASS Unscopable handled correctly for z property on UncalibratedMagnetometer +FAIL UncalibratedMagnetometer interface: attribute xBias assert_own_property: self does not have own property "UncalibratedMagnetometer" expected property "UncalibratedMagnetometer" missing +PASS Unscopable handled correctly for xBias property on UncalibratedMagnetometer +FAIL UncalibratedMagnetometer interface: attribute yBias assert_own_property: self does not have own property "UncalibratedMagnetometer" expected property "UncalibratedMagnetometer" missing +PASS Unscopable handled correctly for yBias property on UncalibratedMagnetometer +FAIL UncalibratedMagnetometer interface: attribute zBias assert_own_property: self does not have own property "UncalibratedMagnetometer" expected property "UncalibratedMagnetometer" missing +PASS Unscopable handled correctly for zBias property on UncalibratedMagnetometer +FAIL UncalibratedMagnetometer must be primary interface of new UncalibratedMagnetometer(); assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: UncalibratedMagnetometer is not defined" +FAIL Stringification of new UncalibratedMagnetometer(); assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: UncalibratedMagnetometer is not defined" +FAIL UncalibratedMagnetometer interface: new UncalibratedMagnetometer(); must inherit property "x" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: UncalibratedMagnetometer is not defined" +FAIL UncalibratedMagnetometer interface: new UncalibratedMagnetometer(); must inherit property "y" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: UncalibratedMagnetometer is not defined" +FAIL UncalibratedMagnetometer interface: new UncalibratedMagnetometer(); must inherit property "z" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: UncalibratedMagnetometer is not defined" +FAIL UncalibratedMagnetometer interface: new UncalibratedMagnetometer(); must inherit property "xBias" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: UncalibratedMagnetometer is not defined" +FAIL UncalibratedMagnetometer interface: new UncalibratedMagnetometer(); must inherit property "yBias" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: UncalibratedMagnetometer is not defined" +FAIL UncalibratedMagnetometer interface: new UncalibratedMagnetometer(); must inherit property "zBias" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: UncalibratedMagnetometer is not defined" +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/magnetometer/idlharness.https.window.js b/third_party/WebKit/LayoutTests/external/wpt/magnetometer/idlharness.https.window.js new file mode 100644 index 0000000..97a3c85e --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/magnetometer/idlharness.https.window.js
@@ -0,0 +1,18 @@ +// META: script=/resources/WebIDLParser.js +// META: script=/resources/idlharness.js + +// https://w3c.github.io/magnetometer/ + +'use strict'; + +idl_test( + ['magnetometer'], + ['generic-sensor', 'dom'], + idl_array => { + idl_array.add_objects({ + Magnetometer: ['new Magnetometer();'], + UncalibratedMagnetometer: ['new UncalibratedMagnetometer();'] + }); + }, + 'Test IDL implementation of Magnetometer Sensor' +);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-image/idlharness.html b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-image/idlharness.html deleted file mode 100644 index 40888f0b..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-image/idlharness.html +++ /dev/null
@@ -1,49 +0,0 @@ -<!DOCTYPE html> -<html> -<head> - <meta charset=utf-8> - <title>Image Capture IDL test</title> - <link rel="help" href="https://w3c.github.io/mediacapture-image"> - <link rel="idl" href="https://w3c.github.io/mediacapture-image/#idl-index"> - <script src="/resources/testharness.js"></script> - <script src="/resources/testharnessreport.js"></script> - <script src="/resources/WebIDLParser.js"></script> - <script src="/resources/idlharness.js"></script> -</head> -<body> - <canvas id='canvas' width=10 height=10/> - -<script> - 'use strict'; - - promise_test(async () => { - const srcs = ['image-capture', 'mediacapture-streams', 'html', 'dom']; - const [idl, main, html, dom] = await Promise.all( - srcs.map(i => fetch(`/interfaces/${i}.idl`).then(r => r.text()))); - - let capture; - try { - var canvas = document.getElementById('canvas'); - var context = canvas.getContext("2d"); - context.fillStyle = "red"; - context.fillRect(0, 0, 10, 10); - var track = canvas.captureStream().getVideoTracks()[0]; - capture = new ImageCapture(track); - } catch (e) { - // Will be surfaced in idlharness.js's test_object below. - } - - var idl_array = new IdlArray(); - idl_array.add_idls(idl); - idl_array.add_dependency_idls(main); - idl_array.add_dependency_idls(html); - idl_array.add_dependency_idls(dom); - idl_array.add_objects({ - ImageCapture : [capture] - }); - idl_array.test(); - }, 'Test mediacapture-image IDL interfaces'); - </script> - <div id="log"></div> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-image/idlharness.window.js b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-image/idlharness.window.js new file mode 100644 index 0000000..0c06405a --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-image/idlharness.window.js
@@ -0,0 +1,27 @@ +// META: script=/resources/WebIDLParser.js +// META: script=/resources/idlharness.js + +// https://w3c.github.io/mediacapture-image/ + +'use strict'; + +idl_test( + ['image-capture'], + ['mediacapture-streams', 'html', 'dom'], + async idl_array => { + idl_array.add_objects({ + ImageCapture : ['capture'], + PhotoCapabilities: ['capabilities'], + }); + + const canvas = document.createElement('canvas'); + document.body.appendChild(canvas); + const context = canvas.getContext("2d"); + context.fillStyle = "red"; + context.fillRect(0, 0, 10, 10); + const track = canvas.captureStream().getVideoTracks()[0]; + self.capture = new ImageCapture(track); + self.capabilities = await capture.getPhotoCapabilities(); + }, + 'Test mediacapture-image IDL interfaces' +);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mediasession/idlharness.html b/third_party/WebKit/LayoutTests/external/wpt/mediasession/idlharness.html deleted file mode 100644 index d732c03..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/mediasession/idlharness.html +++ /dev/null
@@ -1,32 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"> -<title>Media Session IDL tests</title> -<link rel="help" href="https://wicg.github.io/mediasession/"/> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script src="/resources/WebIDLParser.js"></script> -<script src="/resources/idlharness.js"></script> -</head> -<body> -<h1>Media Session IDL tests</h1> -<script> -'use strict'; - -promise_test(async () => { - var idl_array = new IdlArray(); - const idl = await fetch('/interfaces/mediasession.idl').then(r => r.text()); - const html = await fetch('/interfaces/html.idl').then(r => r.text()); - idl_array.add_idls(idl); - idl_array.add_dependency_idls(html); - idl_array.add_objects({ - MediaMetadata: ['new MediaMetadata()'], - Navigator: ['navigator'] - }); - idl_array.test(); -}, 'Test IDL implementation of Media Session'); -</script> -<div id="log"></div> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mediasession/idlharness.window.js b/third_party/WebKit/LayoutTests/external/wpt/mediasession/idlharness.window.js new file mode 100644 index 0000000..f9ac62d --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/mediasession/idlharness.window.js
@@ -0,0 +1,19 @@ +// META: script=/resources/WebIDLParser.js +// META: script=/resources/idlharness.js + +// https://wicg.github.io/mediasession/ + +'use strict'; + +idl_test( + ['mediasession'], + ['html'], + idl_array => { + idl_array.add_objects({ + MediaMetadata: ['new MediaMetadata()'], + MediaSession: ['navigator.mediaSession'], + Navigator: ['navigator'] + }); + }, + 'Test IDL implementation of Media Session' +);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/idlharness.https.html b/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/idlharness.https.html deleted file mode 100644 index c87d99f..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/idlharness.https.html +++ /dev/null
@@ -1,38 +0,0 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<title>Orientation Sensor IDL tests</title> -<link rel="author" title="Intel" href="http://www.intel.com"> -<link rel="help" href="https://w3c.github.io/orientation-sensor/"> -<link rel="help" href="https://w3c.github.io/sensors/"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script src="/resources/WebIDLParser.js"></script> -<script src="/resources/idlharness.js"></script> -<script> -"use strict"; - -function doTest([dom, generic_sensor, orientation_sensor]) { - const idl_array = new IdlArray(); - idl_array.add_untested_idls(dom); - idl_array.add_untested_idls('interface EventHandler {};'); - idl_array.add_idls(generic_sensor, { only: ['Sensor', 'SensorOptions'] }); - idl_array.add_idls(orientation_sensor); - idl_array.add_objects({ - AbsoluteOrientationSensor: ['new AbsoluteOrientationSensor();'], - RelativeOrientationSensor: ['new RelativeOrientationSensor();'] - }); - idl_array.test(); -} - -function fetchText(url) { - return fetch(url).then((response) => response.text()); -} - -promise_test(() => { - return Promise.all([ - "/interfaces/dom.idl", - "/interfaces/sensors.idl", - "/interfaces/orientation-sensor.idl", - ].map(fetchText)).then(doTest); -}, "Test IDL implementation of Orientation Sensor"); -</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/idlharness.https.window.js b/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/idlharness.https.window.js new file mode 100644 index 0000000..39217fc --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/idlharness.https.window.js
@@ -0,0 +1,19 @@ +// META: script=/resources/WebIDLParser.js +// META: script=/resources/idlharness.js + +// https://w3c.github.io/orientation-sensor/"> + +'use strict'; + +idl_test( + ['orientation-sensor'], + ['generic-sensor', 'dom'], + idl_array => { + idl_array.add_objects({ + AbsoluteOrientationSensor: ['new AbsoluteOrientationSensor();'], + RelativeOrientationSensor: ['new RelativeOrientationSensor();'] + }); + idl_array.prevent_multiple_testing('OrientationSensor'); + }, + 'Test IDL implementation of Orientation Sensor' +);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/picture-in-picture/idlharness.window-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/picture-in-picture/idlharness.window-expected.txt index bfbb0c6..5f0cb84 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/picture-in-picture/idlharness.window-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/picture-in-picture/idlharness.window-expected.txt
@@ -4,10 +4,10 @@ PASS Partial interface HTMLVideoElement: original interface defined PASS Partial interface Document: original interface defined PASS Partial interface DocumentOrShadowRoot: original interface defined -FAIL PictureInPictureWindow interface: existence and properties of interface object assert_equals: prototype of self's property "PictureInPictureWindow" is not Function.prototype expected function "function () { [native code] }" but got function "function EventTarget() { [native code] }" +PASS PictureInPictureWindow interface: existence and properties of interface object PASS PictureInPictureWindow interface object length PASS PictureInPictureWindow interface object name -FAIL PictureInPictureWindow interface: existence and properties of interface prototype object assert_equals: prototype of PictureInPictureWindow.prototype is not Object.prototype expected object "[object Object]" but got object "[object EventTarget]" +PASS PictureInPictureWindow interface: existence and properties of interface prototype object PASS PictureInPictureWindow interface: existence and properties of interface prototype object's "constructor" property PASS PictureInPictureWindow interface: existence and properties of interface prototype object's @@unscopables property PASS PictureInPictureWindow interface: attribute width
diff --git a/third_party/WebKit/LayoutTests/external/wpt/pointerevents/extension/idlharness.html b/third_party/WebKit/LayoutTests/external/wpt/pointerevents/extension/idlharness.html deleted file mode 100644 index 40a441cf..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/pointerevents/extension/idlharness.html +++ /dev/null
@@ -1,56 +0,0 @@ -<!doctype html> -<meta charset=utf-8> -<title>idlharness test</title> -<script src=/resources/testharness.js></script> -<script src=/resources/testharnessreport.js></script> -<script src="/resources/WebIDLParser.js"></script> -<script src="/resources/idlharness.js"></script> - -<pre id='untested_idl' style='display:none'> -[Global=Window, Exposed=Window] -interface Window { -}; - -[TreatNonObjectAsNull] -callback EventHandlerNonNull = any (Event event); -typedef EventHandlerNonNull? EventHandler; - -[NoInterfaceObject] -interface GlobalEventHandlers { -}; -Window implements GlobalEventHandlers; - -interface Element { -}; - -interface HTMLElement : Element { -}; -HTMLElement implements GlobalEventHandlers; - -interface Document { -}; -Document implements GlobalEventHandlers; - -interface MouseEvent { -}; - -</pre> -<script> -promise_test(async function () { - const dom = await fetch('/interfaces/dom.idl').then(r => r.text()); - const uievents = await fetch('/interfaces/uievents.idl').then(r => r.text()); - const idl = await fetch('/interfaces/pointerevents-extension.idl').then(r => r.text()); - - const idl_array = new IdlArray(); - idl_array.add_untested_idls(dom, { only: ['EventInit'] }); - idl_array.add_untested_idls(uievents, { only: [ - 'UIEventInit', - 'MouseEventInit', - 'EventModifierInit'] - }); - idl_array.add_untested_idls( - document.getElementById("untested_idl").textContent); - idl_array.add_idls(idl); - idl_array.test(); -}, 'pointerevents extension interfaces'); -</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/pointerevents/extension/idlharness.window-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/pointerevents/extension/idlharness.window-expected.txt new file mode 100644 index 0000000..b22590a --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/pointerevents/extension/idlharness.window-expected.txt
@@ -0,0 +1,12 @@ +This is a testharness.js-based test. +PASS pointerevents extension interfaces +PASS Partial dictionary PointerEventInit: original dictionary defined +PASS Partial interface PointerEvent: original interface defined +PASS PointerEvent interface: operation getCoalescedEvents() +PASS Unscopable handled correctly for getCoalescedEvents() on PointerEvent +FAIL PointerEvent interface: operation getPredictedEvents() assert_own_property: interface prototype object missing non-static operation expected property "getPredictedEvents" missing +PASS Unscopable handled correctly for getPredictedEvents() on PointerEvent +PASS PointerEvent interface: new PointerEvent("pointer") must inherit property "getCoalescedEvents()" with the proper type +FAIL PointerEvent interface: new PointerEvent("pointer") must inherit property "getPredictedEvents()" with the proper type assert_inherits: property "getPredictedEvents" not found in prototype chain +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/pointerevents/extension/idlharness.window.js b/third_party/WebKit/LayoutTests/external/wpt/pointerevents/extension/idlharness.window.js new file mode 100644 index 0000000..703e1c4 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/pointerevents/extension/idlharness.window.js
@@ -0,0 +1,15 @@ +// META: script=/resources/WebIDLParser.js +// META: script=/resources/idlharness.js + +// https://w3c.github.io/pointerevents/extension.html + +idl_test( + ['pointerevents-extension'], + ['pointerevents', 'uievents', 'dom'], + idl_array => { + idl_array.add_objects({ + PointerEvent: ['new PointerEvent("pointer")'], + }) + }, + 'pointerevents extension interfaces' +);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/user-timing/idlharness.any.js b/third_party/WebKit/LayoutTests/external/wpt/user-timing/idlharness.any.js index 47300bd..6c60cb55 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/user-timing/idlharness.any.js +++ b/third_party/WebKit/LayoutTests/external/wpt/user-timing/idlharness.any.js
@@ -6,19 +6,27 @@ 'use strict'; -promise_test(async () => { - const idl_array = new IdlArray(); - const idl = await fetch("/interfaces/user-timing.idl").then(r => r.text()); - const hrtime = await fetch("/interfaces/hr-time.idl").then(r => r.text()); - const perf = await fetch("/interfaces/performance-timeline.idl").then(r => r.text()); - const dom = await fetch("/interfaces/dom.idl").then(r => r.text()); +idl_test( + ['user-timing'], + ['hr-time', 'performance-timeline', 'dom'], + idl_array => { + try { + performance.mark('test'); + performance.measure('test'); + for (const m of performance.getEntriesByType('mark')) { + self.mark = m; + } + for (const m of performance.getEntriesByType('measure')) { + self.measure = m; + } + } catch (e) { + // Will be surfaced when mark is undefined below. + } - idl_array.add_idls(idl); - idl_array.add_dependency_idls(hrtime); - idl_array.add_dependency_idls(perf); - idl_array.add_dependency_idls(dom); - idl_array.add_objects({ - Performance: ["performance"] - }); - idl_array.test(); -}, "Test IDL implementation of user-timing API"); + idl_array.add_objects({ + Performance: ['performance'], + PerformanceMark: ['mark'], + PerformanceMeasure: ['measure'], + }); + }, + 'Test IDL implementation of user-timing API');
diff --git a/third_party/WebKit/LayoutTests/external/wpt/user-timing/idlharness.any.sharedworker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/user-timing/idlharness.any.sharedworker-expected.txt index aead771b..42eb8e7 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/user-timing/idlharness.any.sharedworker-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/user-timing/idlharness.any.sharedworker-expected.txt
@@ -7,12 +7,16 @@ FAIL PerformanceMark interface: existence and properties of interface prototype object assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing FAIL PerformanceMark interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing FAIL PerformanceMark interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing +FAIL PerformanceMark must be primary interface of mark assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing +PASS Stringification of mark FAIL PerformanceMeasure interface: existence and properties of interface object assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing FAIL PerformanceMeasure interface object length assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing FAIL PerformanceMeasure interface object name assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing FAIL PerformanceMeasure interface: existence and properties of interface prototype object assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing FAIL PerformanceMeasure interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing FAIL PerformanceMeasure interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing +FAIL PerformanceMeasure must be primary interface of measure assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing +PASS Stringification of measure PASS Performance interface: operation mark(DOMString) PASS Unscopable handled correctly for mark(DOMString) on Performance PASS Performance interface: operation clearMarks(DOMString)
diff --git a/third_party/WebKit/LayoutTests/external/wpt/user-timing/idlharness.any.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/user-timing/idlharness.any.worker-expected.txt index aead771b..42eb8e7 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/user-timing/idlharness.any.worker-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/user-timing/idlharness.any.worker-expected.txt
@@ -7,12 +7,16 @@ FAIL PerformanceMark interface: existence and properties of interface prototype object assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing FAIL PerformanceMark interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing FAIL PerformanceMark interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing +FAIL PerformanceMark must be primary interface of mark assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing +PASS Stringification of mark FAIL PerformanceMeasure interface: existence and properties of interface object assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing FAIL PerformanceMeasure interface object length assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing FAIL PerformanceMeasure interface object name assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing FAIL PerformanceMeasure interface: existence and properties of interface prototype object assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing FAIL PerformanceMeasure interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing FAIL PerformanceMeasure interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing +FAIL PerformanceMeasure must be primary interface of measure assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing +PASS Stringification of measure PASS Performance interface: operation mark(DOMString) PASS Unscopable handled correctly for mark(DOMString) on Performance PASS Performance interface: operation clearMarks(DOMString)
diff --git a/third_party/WebKit/LayoutTests/external/wpt/user-timing/idlharness.https.any.serviceworker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/user-timing/idlharness.https.any.serviceworker-expected.txt index aead771b..42eb8e7 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/user-timing/idlharness.https.any.serviceworker-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/user-timing/idlharness.https.any.serviceworker-expected.txt
@@ -7,12 +7,16 @@ FAIL PerformanceMark interface: existence and properties of interface prototype object assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing FAIL PerformanceMark interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing FAIL PerformanceMark interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing +FAIL PerformanceMark must be primary interface of mark assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing +PASS Stringification of mark FAIL PerformanceMeasure interface: existence and properties of interface object assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing FAIL PerformanceMeasure interface object length assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing FAIL PerformanceMeasure interface object name assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing FAIL PerformanceMeasure interface: existence and properties of interface prototype object assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing FAIL PerformanceMeasure interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing FAIL PerformanceMeasure interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing +FAIL PerformanceMeasure must be primary interface of measure assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing +PASS Stringification of measure PASS Performance interface: operation mark(DOMString) PASS Unscopable handled correctly for mark(DOMString) on Performance PASS Performance interface: operation clearMarks(DOMString)
diff --git a/third_party/WebKit/LayoutTests/fast/dom/Element/offset-parent-contain-expected.txt b/third_party/WebKit/LayoutTests/fast/dom/Element/offset-parent-contain-expected.txt deleted file mode 100644 index b977cad..0000000 --- a/third_party/WebKit/LayoutTests/fast/dom/Element/offset-parent-contain-expected.txt +++ /dev/null
@@ -1,9 +0,0 @@ -This is a testharness.js-based test. -PASS inside contain:paint -FAIL inside contain:layout assert_equals: expected Element node <div id="containLayout" style="contain:layout;"> - <div... but got Element node <body><div id="containPaint" style="contain:paint;"> - ... -PASS inside contain:style -PASS inside contain:size -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/sources/debugger/async-callstack-network-initiator-image.js b/third_party/WebKit/LayoutTests/http/tests/devtools/sources/debugger/async-callstack-network-initiator-image.js index 0b2f640..db8e6272 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/sources/debugger/async-callstack-network-initiator-image.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/sources/debugger/async-callstack-network-initiator-image.js
@@ -25,7 +25,7 @@ var initiatorInfo = BrowserSDK.networkLog.initiatorInfoForRequest(event.data); var element = new Components.Linkifier().linkifyScriptLocation( - TestRunner.mainTarget, initiatorInfo.scriptId, initiatorInfo.url, initiatorInfo.lineNumber - 1, + TestRunner.mainTarget, initiatorInfo.scriptId, initiatorInfo.url, initiatorInfo.lineNumber, initiatorInfo.columnNumber - 1); TestRunner.addResult(element.textContent); TestRunner.completeTest();
diff --git a/third_party/WebKit/LayoutTests/virtual/video-surface-layer/external/wpt/picture-in-picture/idlharness.window-expected.txt b/third_party/WebKit/LayoutTests/virtual/video-surface-layer/external/wpt/picture-in-picture/idlharness.window-expected.txt index f7f27aa..43a7519 100644 --- a/third_party/WebKit/LayoutTests/virtual/video-surface-layer/external/wpt/picture-in-picture/idlharness.window-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/video-surface-layer/external/wpt/picture-in-picture/idlharness.window-expected.txt
@@ -4,10 +4,10 @@ PASS Partial interface HTMLVideoElement: original interface defined PASS Partial interface Document: original interface defined PASS Partial interface DocumentOrShadowRoot: original interface defined -FAIL PictureInPictureWindow interface: existence and properties of interface object assert_equals: prototype of self's property "PictureInPictureWindow" is not Function.prototype expected function "function () { [native code] }" but got function "function EventTarget() { [native code] }" +PASS PictureInPictureWindow interface: existence and properties of interface object PASS PictureInPictureWindow interface object length PASS PictureInPictureWindow interface object name -FAIL PictureInPictureWindow interface: existence and properties of interface prototype object assert_equals: prototype of PictureInPictureWindow.prototype is not Object.prototype expected object "[object Object]" but got object "[object EventTarget]" +PASS PictureInPictureWindow interface: existence and properties of interface prototype object PASS PictureInPictureWindow interface: existence and properties of interface prototype object's "constructor" property PASS PictureInPictureWindow interface: existence and properties of interface prototype object's @@unscopables property PASS PictureInPictureWindow interface: attribute width
diff --git a/third_party/blink/public/platform/web_feature.mojom b/third_party/blink/public/platform/web_feature.mojom index 304541b..331f8ec18 100644 --- a/third_party/blink/public/platform/web_feature.mojom +++ b/third_party/blink/public/platform/web_feature.mojom
@@ -1969,6 +1969,7 @@ kCSSFillAvailableLogicalHeight = 2508, kPopupOpenWhileFileChooserOpened = 2509, kCookieStoreAPI = 2510, + kFeaturePolicyJSAPI = 2511, // Add new features immediately above this line. Don't change assigned // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/blink/renderer/bindings/core/v8/array_value.cc b/third_party/blink/renderer/bindings/core/v8/array_value.cc index f87b143..5a02a8150 100644 --- a/third_party/blink/renderer/bindings/core/v8/array_value.cc +++ b/third_party/blink/renderer/bindings/core/v8/array_value.cc
@@ -36,7 +36,7 @@ return blink::IsUndefinedOrNull(array_); } -bool ArrayValue::length(size_t& length) const { +bool ArrayValue::length(uint32_t& length) const { if (IsUndefinedOrNull()) return false; @@ -44,7 +44,7 @@ return true; } -bool ArrayValue::Get(size_t index, Dictionary& value) const { +bool ArrayValue::Get(uint32_t index, Dictionary& value) const { if (IsUndefinedOrNull()) return false;
diff --git a/third_party/blink/renderer/bindings/core/v8/array_value.h b/third_party/blink/renderer/bindings/core/v8/array_value.h index 2526e61..2b7dc71 100644 --- a/third_party/blink/renderer/bindings/core/v8/array_value.h +++ b/third_party/blink/renderer/bindings/core/v8/array_value.h
@@ -49,8 +49,8 @@ bool IsUndefinedOrNull() const; - bool length(size_t&) const; - bool Get(size_t index, Dictionary&) const; + bool length(uint32_t&) const; + bool Get(uint32_t index, Dictionary&) const; private: v8::Local<v8::Array> array_;
diff --git a/third_party/blink/renderer/core/dom/document.idl b/third_party/blink/renderer/core/dom/document.idl index 7d88ef1..7f86ca1 100644 --- a/third_party/blink/renderer/core/dom/document.idl +++ b/third_party/blink/renderer/core/dom/document.idl
@@ -196,7 +196,7 @@ // TODO(iclelland): add spec for JS exposure in the spec for Feature Policy. // Please refer to this doc for more details for now: // https://docs.google.com/a/chromium.org/document/d/1wvk3cXkblNnbkMcsKayseK-k0SMGiP9b9fQFgfpqQpc/edit?usp=sharing - [RuntimeEnabled=FeaturePolicyJavaScriptInterface] readonly attribute Policy policy; + [OriginTrialEnabled=FeaturePolicyJavaScriptInterface] readonly attribute Policy policy; // Deprecated prefixed page visibility API. // TODO(davidben): This is a property so attaching a deprecation warning results in false positives when outputting
diff --git a/third_party/blink/renderer/core/frame/deprecation_report_body.idl b/third_party/blink/renderer/core/frame/deprecation_report_body.idl index 780cc3c..8ac1919f 100644 --- a/third_party/blink/renderer/core/frame/deprecation_report_body.idl +++ b/third_party/blink/renderer/core/frame/deprecation_report_body.idl
@@ -12,6 +12,6 @@ readonly attribute Date? anticipatedRemoval; readonly attribute DOMString message; readonly attribute DOMString? sourceFile; - readonly attribute long? lineNumber; - readonly attribute long? columnNumber; + readonly attribute unsigned long? lineNumber; + readonly attribute unsigned long? columnNumber; };
diff --git a/third_party/blink/renderer/core/frame/intervention_report_body.idl b/third_party/blink/renderer/core/frame/intervention_report_body.idl index e85429a..303945b 100644 --- a/third_party/blink/renderer/core/frame/intervention_report_body.idl +++ b/third_party/blink/renderer/core/frame/intervention_report_body.idl
@@ -11,6 +11,6 @@ readonly attribute DOMString id; readonly attribute DOMString message; readonly attribute DOMString? sourceFile; - readonly attribute long? lineNumber; - readonly attribute long? columnNumber; + readonly attribute unsigned long? lineNumber; + readonly attribute unsigned long? columnNumber; };
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.cc b/third_party/blink/renderer/core/frame/local_frame_view.cc index 1a81188..1a661a7 100644 --- a/third_party/blink/renderer/core/frame/local_frame_view.cc +++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -234,7 +234,7 @@ past_layout_lifecycle_update_(false), suppress_adjust_view_size_(false), allows_layout_invalidation_after_layout_clean_(true), - needs_intersection_observation_(false), + intersection_observation_state_(kNotNeeded), needs_forced_compositing_update_(false), needs_focus_on_fragment_(false), main_thread_scrolling_reasons_(0), @@ -2516,7 +2516,7 @@ } } - { + if (intersection_observation_state_ != kNotNeeded) { TRACE_EVENT0("blink,benchmark", "LocalFrameView::UpdateViewportIntersectionsForSubtree"); SCOPED_UMA_AND_UKM_TIMER("Blink.IntersectionObservation.UpdateTime", @@ -3899,7 +3899,7 @@ child->View()->UpdateViewportIntersectionsForSubtree(); } - needs_intersection_observation_ = false; + intersection_observation_state_ = kNotNeeded; } void LocalFrameView::UpdateThrottlingStatusForSubtree() { @@ -4088,10 +4088,13 @@ parent->SetNeedsForcedCompositingUpdate(); } -void LocalFrameView::SetNeedsIntersectionObservation() { - needs_intersection_observation_ = true; +void LocalFrameView::SetNeedsIntersectionObservation( + IntersectionObservationState state) { + if (intersection_observation_state_ >= state) + return; + intersection_observation_state_ = state; if (LocalFrameView* parent = ParentFrameView()) - parent->SetNeedsIntersectionObservation(); + parent->SetNeedsIntersectionObservation(state); } bool LocalFrameView::ShouldThrottleRendering() const { @@ -4103,7 +4106,7 @@ // Only lifecycle phases up to layout are needed to generate an // intersection observation. - return !needs_intersection_observation_ || + return intersection_observation_state_ != kRequired || GetFrame().LocalFrameRoot().View()->past_layout_lifecycle_update_; }
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.h b/third_party/blink/renderer/core/frame/local_frame_view.h index 30519b5..9e54670 100644 --- a/third_party/blink/renderer/core/frame/local_frame_view.h +++ b/third_party/blink/renderer/core/frame/local_frame_view.h
@@ -167,8 +167,22 @@ // Marks this frame, and ancestor frames, as needing one intersection // observervation. This overrides throttling for one frame, up to - // kLayoutClean. - void SetNeedsIntersectionObservation(); + // kLayoutClean. The order of these enums is important - they must proceed + // from "least required to most required". + enum IntersectionObservationState { + // The next painting frame does not need an intersection observation. + kNotNeeded = 0, + // The next painting frame needs an intersection observation. + kDesired = 1, + // The next painting frame must be generated up to intersection observation + // (even if frame is throttled). + kRequired = 2 + }; + + // Sets the internal IntersectionObservationState to the max of the + // current value and the provided one. + void SetNeedsIntersectionObservation(IntersectionObservationState); + // Marks this frame, and ancestor frames, as needing a mandatory compositing // update. This overrides throttling for one frame, up to kCompositingClean. void SetNeedsForcedCompositingUpdate(); @@ -853,7 +867,8 @@ bool suppress_adjust_view_size_; bool allows_layout_invalidation_after_layout_clean_; - bool needs_intersection_observation_; + + IntersectionObservationState intersection_observation_state_; bool needs_forced_compositing_update_; bool needs_focus_on_fragment_;
diff --git a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc index 71b6440..473c6a7 100644 --- a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc +++ b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
@@ -415,20 +415,23 @@ if (!LowLatencyEnabled()) canvas2d_bridge_->FinalizeFrame(); + } - if (LowLatencyEnabled() && !dirty_rect_.IsEmpty() && - GetOrCreateCanvasResourceProvider(kPreferAcceleration)) { + if (LowLatencyEnabled() && !dirty_rect_.IsEmpty()) { + AccelerationHint hint = + Is2d() ? kPreferNoAcceleration : kPreferAcceleration; + if (GetOrCreateCanvasResourceProvider(hint)) { + ResourceProvider()->TryEnableSingleBuffering(); // Push a frame base::TimeTicks start_time = WTF::CurrentTimeTicks(); - scoped_refptr<CanvasResource> canvas_resource = - ResourceProvider()->ProduceFrame(); + scoped_refptr<StaticBitmapImage> image = + canvas2d_bridge_->NewImageSnapshot(kPreferAcceleration); FloatRect src_rect(0, 0, Size().Width(), Size().Height()); dirty_rect_.Intersect(src_rect); IntRect int_dirty = EnclosingIntRect(dirty_rect_); SkIRect damage_rect = SkIRect::MakeXYWH( int_dirty.X(), int_dirty.Y(), int_dirty.Width(), int_dirty.Height()); - frame_dispatcher_->DispatchFrameSync(std::move(canvas_resource), - start_time, damage_rect); + frame_dispatcher_->DispatchFrameSync(image, start_time, damage_rect); (void)start_time; (void)damage_rect; dirty_rect_ = FloatRect(); @@ -1138,9 +1141,8 @@ scoped_refptr<Image> HTMLCanvasElement::CopiedImage( SourceDrawingBuffer source_buffer, AccelerationHint hint) { - if (SurfaceLayerBridge()) { + if (PlaceholderFrame()) return PlaceholderFrame()->Bitmap(); - } if (!IsPaintable()) return nullptr;
diff --git a/third_party/blink/renderer/core/html/html_iframe_element.idl b/third_party/blink/renderer/core/html/html_iframe_element.idl index c1ff20c..c0d5a9c0 100644 --- a/third_party/blink/renderer/core/html/html_iframe_element.idl +++ b/third_party/blink/renderer/core/html/html_iframe_element.idl
@@ -47,7 +47,7 @@ // TODO(iclelland): add spec for JS exposure in the spec for Feature Policy. // Please refer to this doc for more details for now: // https://docs.google.com/a/chromium.org/document/d/1wvk3cXkblNnbkMcsKayseK-k0SMGiP9b9fQFgfpqQpc/edit?usp=sharing - [RuntimeEnabled=FeaturePolicyJavaScriptInterface] readonly attribute Policy policy; + [OriginTrialEnabled=FeaturePolicyJavaScriptInterface] readonly attribute Policy policy; // obsolete members // https://html.spec.whatwg.org/#HTMLIFrameElement-partial
diff --git a/third_party/blink/renderer/core/html/html_image_element.cc b/third_party/blink/renderer/core/html/html_image_element.cc index 8c29fcd..8e157267 100644 --- a/third_party/blink/renderer/core/html/html_image_element.cc +++ b/third_party/blink/renderer/core/html/html_image_element.cc
@@ -412,10 +412,12 @@ // If we have been inserted from a layoutObject-less document, // our loader may have not fetched the image, so do it now. - if ((insertion_point->isConnected() && !GetImageLoader().GetContent()) || - image_was_modified) + if ((insertion_point->isConnected() && !GetImageLoader().GetContent() && + !GetImageLoader().HasPendingActivity()) || + image_was_modified) { GetImageLoader().UpdateFromElement(ImageLoader::kUpdateNormal, referrer_policy_); + } return HTMLElement::InsertedInto(insertion_point); }
diff --git a/third_party/blink/renderer/core/intersection_observer/intersection_observer.cc b/third_party/blink/renderer/core/intersection_observer/intersection_observer.cc index c930a51..2fba8dc 100644 --- a/third_party/blink/renderer/core/intersection_observer/intersection_observer.cc +++ b/third_party/blink/renderer/core/intersection_observer/intersection_observer.cc
@@ -274,7 +274,7 @@ if (LocalFrameView* frame_view = target_frame->View()) { // The IntersectionObsever spec requires that at least one observation // be recorded afer observe() is called, even if the frame is throttled. - frame_view->SetNeedsIntersectionObservation(); + frame_view->SetNeedsIntersectionObservation(LocalFrameView::kRequired); frame_view->ScheduleAnimation(); } }
diff --git a/third_party/blink/renderer/core/intersection_observer/intersection_observer_test.cc b/third_party/blink/renderer/core/intersection_observer/intersection_observer_test.cc index 4c32ad4..c867a3d 100644 --- a/third_party/blink/renderer/core/intersection_observer/intersection_observer_test.cc +++ b/third_party/blink/renderer/core/intersection_observer/intersection_observer_test.cc
@@ -9,6 +9,7 @@ #include "third_party/blink/renderer/core/frame/local_frame_view.h" #include "third_party/blink/renderer/core/intersection_observer/intersection_observer_delegate.h" #include "third_party/blink/renderer/core/intersection_observer/intersection_observer_init.h" +#include "third_party/blink/renderer/core/layout/layout_view.h" #include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h" #include "third_party/blink/renderer/core/testing/sim/sim_compositor.h" #include "third_party/blink/renderer/core/testing/sim/sim_request.h" @@ -152,6 +153,53 @@ EXPECT_EQ(observer_delegate->CallCount(), 3); } +TEST_F(IntersectionObserverTest, HitTestAfterMutation) { + WebView().Resize(WebSize(800, 600)); + SimRequest main_resource("https://example.com/", "text/html"); + LoadURL("https://example.com/"); + main_resource.Complete(R"HTML( + <div id='leading-space' style='height: 700px;'></div> + <div id='target'></div> + <div id='trailing-space' style='height: 700px;'></div> + )HTML"); + + IntersectionObserverInit observer_init; + DummyExceptionStateForTesting exception_state; + TestIntersectionObserverDelegate* observer_delegate = + new TestIntersectionObserverDelegate(GetDocument()); + IntersectionObserver* observer = IntersectionObserver::Create( + observer_init, *observer_delegate, exception_state); + ASSERT_FALSE(exception_state.HadException()); + + Element* target = GetDocument().getElementById("target"); + ASSERT_TRUE(target); + observer->observe(target, exception_state); + + Compositor().BeginFrame(); + test::RunPendingTasks(); + EXPECT_EQ(observer_delegate->CallCount(), 1); + + GetDocument().View()->ScheduleAnimation(); + + Compositor().BeginFrame(); + test::RunPendingTasks(); + EXPECT_EQ(observer_delegate->CallCount(), 1); + + GetDocument().View()->LayoutViewport()->SetScrollOffset(ScrollOffset(0, 300), + kProgrammaticScroll); + + HitTestLocation location(LayoutPoint(0, 0)); + HitTestResult result( + HitTestRequest(HitTestRequest::kReadOnly | HitTestRequest::kActive | + HitTestRequest::kAllowChildFrameContent), + location); + GetDocument().View()->GetLayoutView()->HitTest(location, result); + + Compositor().BeginFrame(); + test::RunPendingTasks(); + EXPECT_EQ(observer_delegate->CallCount(), 2); +} + TEST_F(IntersectionObserverTest, DisconnectClearsNotifications) { WebView().Resize(WebSize(800, 600)); SimRequest main_resource("https://example.com/", "text/html");
diff --git a/third_party/blink/renderer/core/layout/layout_block.cc b/third_party/blink/renderer/core/layout/layout_block.cc index 3ea1d5c..db10a7f 100644 --- a/third_party/blink/renderer/core/layout/layout_block.cc +++ b/third_party/blink/renderer/core/layout/layout_block.cc
@@ -161,13 +161,13 @@ if (old_style && Parent()) { bool old_style_contains_fixed_position = old_style->CanContainFixedPositionObjects(IsDocumentElement()) || - ShouldApplyPaintContainment(); + ShouldApplyPaintContainment() || ShouldApplyLayoutContainment(); bool old_style_contains_absolute_position = old_style_contains_fixed_position || old_style->CanContainAbsolutePositionObjects(); bool new_style_contains_fixed_position = new_style.CanContainFixedPositionObjects(IsDocumentElement()) || - ShouldApplyPaintContainment(); + ShouldApplyPaintContainment() || ShouldApplyLayoutContainment(); bool new_style_contains_absolute_position = new_style_contains_fixed_position || new_style.CanContainAbsolutePositionObjects(); @@ -264,7 +264,7 @@ SetCanContainFixedPositionObjects( IsLayoutView() || IsSVGForeignObject() || IsTextControl() || new_style.CanContainFixedPositionObjects(IsDocumentElement()) || - ShouldApplyPaintContainment()); + ShouldApplyPaintContainment() || ShouldApplyLayoutContainment()); // It's possible for our border/padding to change, but for the overall logical // width or height of the block to end up being the same. We keep track of
diff --git a/third_party/blink/renderer/core/layout/layout_object.cc b/third_party/blink/renderer/core/layout/layout_object.cc index f9d4f7c..3e0f3535 100644 --- a/third_party/blink/renderer/core/layout/layout_object.cc +++ b/third_party/blink/renderer/core/layout/layout_object.cc
@@ -987,7 +987,7 @@ LayoutObject* LayoutObject::ContainerForAbsolutePosition( AncestorSkipInfo* skip_info) const { return FindAncestorByPredicate(this, skip_info, [](LayoutObject* candidate) { - if (!candidate->CanContainAbsolutePositionObjects() && + if (!candidate->StyleRef().CanContainAbsolutePositionObjects() && candidate->ShouldApplyLayoutContainment()) { UseCounter::Count(candidate->GetDocument(), WebFeature::kCSSContainLayoutPositionedDescendants); @@ -1000,7 +1000,8 @@ AncestorSkipInfo* skip_info) const { DCHECK(!IsText()); return FindAncestorByPredicate(this, skip_info, [](LayoutObject* candidate) { - if (!candidate->CanContainFixedPositionObjects() && + if (!candidate->StyleRef().CanContainFixedPositionObjects( + candidate->IsDocumentElement()) && candidate->ShouldApplyLayoutContainment()) { UseCounter::Count(candidate->GetDocument(), WebFeature::kCSSContainLayoutPositionedDescendants); @@ -3182,6 +3183,9 @@ bitfields_.SetNeedsPaintPropertyUpdate(true); LayoutObject* ancestor = ParentCrossingFrames(); + + GetFrameView()->SetNeedsIntersectionObservation(LocalFrameView::kDesired); + while (ancestor && !ancestor->DescendantNeedsPaintPropertyUpdate()) { ancestor->bitfields_.SetDescendantNeedsPaintPropertyUpdate(true); ancestor = ancestor->ParentCrossingFrames();
diff --git a/third_party/blink/renderer/core/layout/layout_table_box_component.cc b/third_party/blink/renderer/core/layout/layout_table_box_component.cc index 03a3cc2c..4b09846b 100644 --- a/third_party/blink/renderer/core/layout/layout_table_box_component.cc +++ b/third_party/blink/renderer/core/layout/layout_table_box_component.cc
@@ -62,7 +62,7 @@ LayoutBox::StyleDidChange(diff, old_style); SetCanContainFixedPositionObjects( Style()->CanContainFixedPositionObjects(false) || - ShouldApplyPaintContainment()); + ShouldApplyPaintContainment() || ShouldApplyLayoutContainment()); } } // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.cc index 4ae097b..da17cbb 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.cc
@@ -126,6 +126,8 @@ style_->CanContainFixedPositionObjects(false) || ToLayoutBoxModelObject(layout_object_) ->ShouldApplyPaintContainment() || + ToLayoutBoxModelObject(layout_object_) + ->ShouldApplyLayoutContainment() || CanBeHitTestTargetPseudoNodeStyle(*style_); } return;
diff --git a/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc b/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc index 004f9ff4..bb38c588 100644 --- a/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc +++ b/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc
@@ -51,8 +51,7 @@ base::TimeTicks commit_start_time = WTF::CurrentTimeTicks(); current_frame_damage_rect_.join(damage_rect); GetOrCreateResourceDispatcher()->DispatchFrameSync( - std::move(canvas_resource), commit_start_time, - current_frame_damage_rect_); + canvas_resource->Bitmap(), commit_start_time, current_frame_damage_rect_); current_frame_damage_rect_ = SkIRect::MakeEmpty(); } @@ -391,9 +390,8 @@ if (current_frame_damage_rect_.isEmpty()) return; base::TimeTicks commit_start_time = WTF::CurrentTimeTicks(); - GetOrCreateResourceDispatcher()->DispatchFrame(std::move(canvas_resource), - commit_start_time, - current_frame_damage_rect_); + GetOrCreateResourceDispatcher()->DispatchFrame( + canvas_resource->Bitmap(), commit_start_time, current_frame_damage_rect_); current_frame_damage_rect_ = SkIRect::MakeEmpty(); }
diff --git a/third_party/blink/renderer/core/paint/paint_layer_fragment.h b/third_party/blink/renderer/core/paint/paint_layer_fragment.h index 170a7d0..30b9d07 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_fragment.h +++ b/third_party/blink/renderer/core/paint/paint_layer_fragment.h
@@ -49,14 +49,6 @@ DISALLOW_NEW_EXCEPT_PLACEMENT_NEW(); public: - void SetRects(const LayoutRect& bounds, - const ClipRect& background, - const ClipRect& foreground) { - layer_bounds = bounds; - background_rect = background; - foreground_rect = foreground; - } - void MoveBy(const LayoutPoint& offset) { layer_bounds.MoveBy(offset); background_rect.MoveBy(offset);
diff --git a/third_party/blink/renderer/core/policy/policy.idl b/third_party/blink/renderer/core/policy/policy.idl index ab6fda8d..d2d5ad31 100644 --- a/third_party/blink/renderer/core/policy/policy.idl +++ b/third_party/blink/renderer/core/policy/policy.idl
@@ -8,9 +8,9 @@ // https://docs.google.com/a/chromium.org/document/d/1wvk3cXkblNnbkMcsKayseK-k0SMGiP9b9fQFgfpqQpc/edit?usp=sharing [ NoInterfaceObject, - RuntimeEnabled=FeaturePolicyJavaScriptInterface + OriginTrialEnabled=FeaturePolicyJavaScriptInterface ] interface Policy { - boolean allowsFeature(DOMString feature, optional DOMString url); - sequence<DOMString> allowedFeatures(); - sequence<DOMString> getAllowlistForFeature(DOMString feature); + [MeasureAs=FeaturePolicyJSAPI] boolean allowsFeature(DOMString feature, optional DOMString url); + [MeasureAs=FeaturePolicyJSAPI] sequence<DOMString> allowedFeatures(); + [MeasureAs=FeaturePolicyJSAPI] sequence<DOMString> getAllowlistForFeature(DOMString feature); };
diff --git a/third_party/blink/renderer/core/scheduler/frame_throttling_test.cc b/third_party/blink/renderer/core/scheduler/frame_throttling_test.cc index d4c09dc..f739924 100644 --- a/third_party/blink/renderer/core/scheduler/frame_throttling_test.cc +++ b/third_party/blink/renderer/core/scheduler/frame_throttling_test.cc
@@ -191,7 +191,8 @@ EXPECT_TRUE(inner_frame_document->View()->ShouldThrottleRendering()); // An intersection observation overrides... - inner_frame_document->View()->SetNeedsIntersectionObservation(); + inner_frame_document->View()->SetNeedsIntersectionObservation( + LocalFrameView::kRequired); EXPECT_FALSE(inner_frame_document->View()->ShouldThrottleRendering()); inner_frame_document->View()->ScheduleAnimation();
diff --git a/third_party/blink/renderer/core/testing/type_conversions.h b/third_party/blink/renderer/core/testing/type_conversions.h index 7e798b1..a9632d1 100644 --- a/third_party/blink/renderer/core/testing/type_conversions.h +++ b/third_party/blink/renderer/core/testing/type_conversions.h
@@ -37,17 +37,15 @@ public: static TypeConversions* Create() { return new TypeConversions(); } - long testLong() { return long_; } - void setTestLong(long value) { long_ = value; } - unsigned long testUnsignedLong() { return unsigned_long_; } - void setTestUnsignedLong(unsigned long value) { unsigned_long_ = value; } + int32_t testLong() { return long_; } + void setTestLong(int32_t value) { long_ = value; } + uint32_t testUnsignedLong() { return unsigned_long_; } + void setTestUnsignedLong(uint32_t value) { unsigned_long_ = value; } - long long testLongLong() { return long_long_; } - void setTestLongLong(long long value) { long_long_ = value; } - unsigned long long testUnsignedLongLong() { return unsigned_long_long_; } - void setTestUnsignedLongLong(unsigned long long value) { - unsigned_long_long_ = value; - } + int64_t testLongLong() { return long_long_; } + void setTestLongLong(int64_t value) { long_long_ = value; } + uint64_t testUnsignedLongLong() { return unsigned_long_long_; } + void setTestUnsignedLongLong(uint64_t value) { unsigned_long_long_ = value; } int8_t testByte() { return byte_; } void setTestByte(int8_t value) { byte_ = value; } @@ -81,10 +79,10 @@ short_(0), unsigned_short_(0) {} - long long_; - unsigned long unsigned_long_; - long long long_long_; - unsigned long long unsigned_long_long_; + int32_t long_; + uint32_t unsigned_long_; + int64_t long_long_; + uint64_t unsigned_long_long_; int8_t byte_; uint8_t octet_; int16_t short_;
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_test.cc b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_test.cc index 5c679f9..208ff8c 100644 --- a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_test.cc +++ b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_test.cc
@@ -120,16 +120,15 @@ return CanvasElement().GetGPUMemoryUsage(); } void DrawSomething() { - Canvas2DLayerBridge* bridge = CanvasElement().GetCanvas2DLayerBridge(); - bridge->DidDraw(FloatRect(0, 0, 1, 1)); - bridge->FinalizeFrame(); + CanvasElement().DidDraw(); + CanvasElement().FinalizeFrame(); // Grabbing an image forces a flush - bridge->NewImageSnapshot(kPreferAcceleration); + CanvasElement().CopiedImage(kBackBuffer, kPreferAcceleration); } - void CreateContext(OpacityMode, - String color_space = String(), - LinearPixelMathState = kLinearPixelMathDisabled); + enum LatencyMode { kNormalLatency, kLowLatency }; + + void CreateContext(OpacityMode, LatencyMode = kNormalLatency); ScriptState* GetScriptState() { return ToScriptStateForMainWorld(canvas_element_->GetFrame()); } @@ -185,19 +184,12 @@ opaque_bitmap_(IntSize(10, 10), kOpaqueBitmap), alpha_bitmap_(IntSize(10, 10), kTransparentBitmap) {} -void CanvasRenderingContext2DTest::CreateContext( - OpacityMode opacity_mode, - String color_space, - LinearPixelMathState LinearPixelMath_state) { +void CanvasRenderingContext2DTest::CreateContext(OpacityMode opacity_mode, + LatencyMode latency_mode) { String canvas_type("2d"); CanvasContextCreationAttributesCore attributes; attributes.alpha = opacity_mode == kNonOpaque; - if (!color_space.IsEmpty()) { - attributes.color_space = color_space; - if (LinearPixelMath_state == kLinearPixelMathEnabled) { - attributes.pixel_format = "float16"; - } - } + attributes.low_latency = latency_mode == kLowLatency; canvas_element_->GetCanvasRenderingContext(canvas_type, attributes); } @@ -1209,4 +1201,22 @@ EXPECT_FALSE(layer->NeedsCompositingInputsUpdate()); } +TEST_F(CanvasRenderingContext2DTest, LowLatencyIsSingleBuffered) { + CreateContext(kNonOpaque, kLowLatency); + // No need to set-up the layer bridge when testing low latency mode. + DrawSomething(); + auto frame1_resource = + CanvasElement() + .GetOrCreateCanvasResourceProvider(kPreferNoAcceleration) + ->ProduceFrame(); + EXPECT_TRUE(!!frame1_resource); + DrawSomething(); + auto frame2_resource = + CanvasElement() + .GetOrCreateCanvasResourceProvider(kPreferNoAcceleration) + ->ProduceFrame(); + EXPECT_TRUE(!!frame2_resource); + EXPECT_EQ(frame1_resource.get(), frame2_resource.get()); +} + } // namespace blink
diff --git a/third_party/blink/renderer/modules/mediastream/media_constraints_impl.cc b/third_party/blink/renderer/modules/mediastream/media_constraints_impl.cc index dc8304c..64d65a3c 100644 --- a/third_party/blink/renderer/modules/mediastream/media_constraints_impl.cc +++ b/third_party/blink/renderer/modules/mediastream/media_constraints_impl.cc
@@ -231,12 +231,12 @@ if (!ok || optional_constraints.IsUndefinedOrNull()) return false; - size_t number_of_constraints; + uint32_t number_of_constraints; ok = optional_constraints.length(number_of_constraints); if (!ok) return false; - for (size_t i = 0; i < number_of_constraints; ++i) { + for (uint32_t i = 0; i < number_of_constraints; ++i) { Dictionary constraint; ok = optional_constraints.Get(i, constraint); if (!ok || constraint.IsUndefinedOrNull())
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.cc b/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.cc index 70f352861..829faff 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.cc +++ b/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.cc
@@ -127,9 +127,14 @@ } void CanvasResourceDispatcher::DispatchFrameSync( - scoped_refptr<CanvasResource> canvas_resource, + scoped_refptr<StaticBitmapImage> image, base::TimeTicks commit_start_time, const SkIRect& damage_rect) { + scoped_refptr<CanvasResource> canvas_resource = CanvasResourceBitmap::Create( + std::move(image), + nullptr, // Resource provider not specified -> recycling will not work + kLow_SkFilterQuality, CanvasColorParams()); + viz::CompositorFrame frame; if (!PrepareFrame(std::move(canvas_resource), commit_start_time, damage_rect, &frame)) @@ -144,9 +149,14 @@ } void CanvasResourceDispatcher::DispatchFrame( - scoped_refptr<CanvasResource> canvas_resource, + scoped_refptr<StaticBitmapImage> image, base::TimeTicks commit_start_time, const SkIRect& damage_rect) { + scoped_refptr<CanvasResource> canvas_resource = CanvasResourceBitmap::Create( + std::move(image), + nullptr, // Resource provider not specified -> recycling will not work + kLow_SkFilterQuality, CanvasColorParams()); + viz::CompositorFrame frame; if (!PrepareFrame(std::move(canvas_resource), commit_start_time, damage_rect, &frame)) @@ -219,24 +229,38 @@ if (SharedGpuContext::IsGpuCompositingEnabled()) { // Case 1: both canvas and compositor are gpu accelerated. commit_type = kCommitGPUCanvasGPUCompositing; + offscreen_canvas_resource_provider_ + ->SetTransferableResourceToStaticBitmapImage(&resource, + canvas_resource); yflipped = true; } else { // Case 2: canvas is accelerated but gpu compositing is disabled. commit_type = kCommitGPUCanvasSoftwareCompositing; + offscreen_canvas_resource_provider_ + ->SetTransferableResourceToSharedBitmap(resource, + canvas_resource->Bitmap()); } } else { if (SharedGpuContext::IsGpuCompositingEnabled()) { // Case 3: canvas is not gpu-accelerated, but compositor is. commit_type = kCommitSoftwareCanvasGPUCompositing; + scoped_refptr<CanvasResource> accelerated_resource = + canvas_resource->MakeAccelerated( + SharedGpuContext::ContextProviderWrapper()); + if (!accelerated_resource) + return false; + offscreen_canvas_resource_provider_ + ->SetTransferableResourceToStaticBitmapImage(&resource, + accelerated_resource); } else { // Case 4: both canvas and compositor are not gpu accelerated. commit_type = kCommitSoftwareCanvasSoftwareCompositing; + offscreen_canvas_resource_provider_ + ->SetTransferableResourceToSharedBitmap(resource, + canvas_resource->Bitmap()); } } - offscreen_canvas_resource_provider_->SetTransferableResource(&resource, - canvas_resource); - commit_type_histogram.Count(commit_type); PostImageToPlaceholderIfNotBlocked( @@ -453,14 +477,12 @@ void CanvasResourceDispatcher::DidAllocateSharedBitmap( mojo::ScopedSharedBufferHandle buffer, ::gpu::mojom::blink::MailboxPtr id) { - if (sink_) - sink_->DidAllocateSharedBitmap(std::move(buffer), std::move(id)); + sink_->DidAllocateSharedBitmap(std::move(buffer), std::move(id)); } void CanvasResourceDispatcher::DidDeleteSharedBitmap( ::gpu::mojom::blink::MailboxPtr id) { - if (sink_) - sink_->DidDeleteSharedBitmap(std::move(id)); + sink_->DidDeleteSharedBitmap(std::move(id)); } } // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.h b/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.h index 0de60f33..d2afb6a 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.h +++ b/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.h
@@ -47,11 +47,11 @@ void SetSuspendAnimation(bool); bool NeedsBeginFrame() const { return needs_begin_frame_; } bool IsAnimationSuspended() const { return suspend_animation_; } - void DispatchFrame(scoped_refptr<CanvasResource>, + void DispatchFrame(scoped_refptr<StaticBitmapImage>, base::TimeTicks commit_start_time, const SkIRect& damage_rect); void ReclaimResource(viz::ResourceId); - void DispatchFrameSync(scoped_refptr<CanvasResource>, + void DispatchFrameSync(scoped_refptr<StaticBitmapImage>, base::TimeTicks commit_start_time, const SkIRect& damage_rect);
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc index 4685fcd2..8d951cd 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc +++ b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
@@ -152,6 +152,7 @@ ~CanvasResourceProviderTextureGpuMemoryBuffer() override = default; bool SupportsDirectCompositing() const override { return true; } + bool SupportsSingleBuffering() const override { return true; } private: scoped_refptr<CanvasResource> CreateResource() final { @@ -263,6 +264,7 @@ ~CanvasResourceProviderRamGpuMemoryBuffer() override = default; bool SupportsDirectCompositing() const override { return true; } + bool SupportsSingleBuffering() const override { return true; } private: scoped_refptr<CanvasResource> CreateResource() final { @@ -318,6 +320,7 @@ } ~CanvasResourceProviderSharedBitmap() override = default; bool SupportsDirectCompositing() const override { return true; } + bool SupportsSingleBuffering() const override { return true; } private: scoped_refptr<CanvasResource> CreateResource() final { @@ -684,6 +687,7 @@ canvas_image_provider_.reset(); xform_canvas_ = nullptr; surface_ = nullptr; + single_buffer_ = nullptr; } uint32_t CanvasResourceProvider::ContentUniqueID() const { @@ -721,6 +725,11 @@ } scoped_refptr<CanvasResource> CanvasResourceProvider::NewOrRecycledResource() { + if (IsSingleBuffered()) { + if (!single_buffer_) + single_buffer_ = CreateResource(); + return single_buffer_; + } if (recycled_resources_.size()) { scoped_refptr<CanvasResource> resource = std::move(recycled_resources_.back()); @@ -730,4 +739,11 @@ return CreateResource(); } +void CanvasResourceProvider::TryEnableSingleBuffering() { + if (IsSingleBuffered() || !SupportsSingleBuffering()) + return; + SetResourceRecyclingEnabled(false); + is_single_buffered_ = true; +} + } // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.h b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.h index cfa543e5..cf0325b 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.h +++ b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.h
@@ -100,11 +100,26 @@ virtual bool IsValid() const = 0; virtual bool IsAccelerated() const = 0; virtual bool SupportsDirectCompositing() const = 0; + virtual bool SupportsSingleBuffering() const { return false; } uint32_t ContentUniqueID() const; CanvasResourceDispatcher* ResourceDispatcher() { return resource_dispatcher_.get(); } + // Indicates that the compositing path is single buffered, meaning that + // ProduceFrame() return a reference to the same resource each time, which + // implies that Producing an animation frame may overwrite the resource used + // by the previous frame. This results in graphics updates skipping the + // queue, thus reducing latency, but with the possible side effects of + // tearring (in cases where the resource is scanned out directly) and + // irregular frame rate. + bool IsSingleBuffered() { return is_single_buffered_; } + + // Attempt to enable single buffering mode on this resource provider. May + // fail if the CanvasResourcePRovider subclass does not support this mode of + // operation. + void TryEnableSingleBuffering(); + void RecycleResource(scoped_refptr<CanvasResource>); void SetResourceRecyclingEnabled(bool); void ClearRecycledResources(); @@ -189,6 +204,9 @@ WTF::Vector<scoped_refptr<CanvasResource>> recycled_resources_; bool resource_recycling_enabled_ = true; + bool is_single_buffered_ = false; + scoped_refptr<CanvasResource> single_buffer_; + base::WeakPtrFactory<CanvasResourceProvider> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(CanvasResourceProvider);
diff --git a/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.cc b/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.cc index 10739aa..2db3ef5 100644 --- a/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.cc +++ b/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.cc
@@ -134,8 +134,7 @@ // We decompose the cloned handle, and use it to create a // mojo::ScopedHandle which will own cleanup of the handle, and will be // passed over IPC. - gfx::GpuMemoryBufferHandle gpu_handle = - CloneHandleForIPC(gpu_memory_buffer->GetHandle()); + gfx::GpuMemoryBufferHandle gpu_handle = gpu_memory_buffer->CloneHandle(); vr_presentation_provider->SubmitFrameWithTextureHandle( vr_frame_id, mojo::WrapPlatformFile(gpu_handle.dxgi_handle.GetHandle()));
diff --git a/third_party/blink/renderer/platform/graphics/offscreen_canvas_frame_dispatcher_test.cc b/third_party/blink/renderer/platform/graphics/offscreen_canvas_frame_dispatcher_test.cc index eea63df..86812fc 100644 --- a/third_party/blink/renderer/platform/graphics/offscreen_canvas_frame_dispatcher_test.cc +++ b/third_party/blink/renderer/platform/graphics/offscreen_canvas_frame_dispatcher_test.cc
@@ -10,7 +10,6 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/renderer/platform/graphics/canvas_resource.h" -#include "third_party/blink/renderer/platform/graphics/canvas_resource_provider.h" #include "third_party/skia/include/core/SkSurface.h" using testing::_; @@ -49,13 +48,6 @@ protected: CanvasResourceDispatcherTest() { dispatcher_ = std::make_unique<MockCanvasResourceDispatcher>(); - resource_provider_ = CanvasResourceProvider::Create( - IntSize(10, 10), - CanvasResourceProvider::kSoftwareCompositedResourceUsage, - nullptr, // context_provider_wrapper - 0, // msaa_sample_count - CanvasColorParams(), CanvasResourceProvider::kDefaultPresentationMode, - dispatcher_->GetWeakPtr()); } MockCanvasResourceDispatcher* Dispatcher() { return dispatcher_.get(); } @@ -63,12 +55,13 @@ private: scoped_refptr<StaticBitmapImage> PrepareStaticBitmapImage(); std::unique_ptr<MockCanvasResourceDispatcher> dispatcher_; - std::unique_ptr<CanvasResourceProvider> resource_provider_; }; void CanvasResourceDispatcherTest::DispatchOneFrame() { - dispatcher_->DispatchFrame(resource_provider_->ProduceFrame(), - base::TimeTicks(), SkIRect::MakeEmpty()); + sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(10, 10); + dispatcher_->DispatchFrame( + StaticBitmapImage::Create(surface->makeImageSnapshot()), + base::TimeTicks(), SkIRect::MakeEmpty()); } TEST_F(CanvasResourceDispatcherTest, PlaceholderRunsNormally) {
diff --git a/third_party/blink/renderer/platform/graphics/offscreen_canvas_resource_provider.cc b/third_party/blink/renderer/platform/graphics/offscreen_canvas_resource_provider.cc index 6ad642b..a99595fb 100644 --- a/third_party/blink/renderer/platform/graphics/offscreen_canvas_resource_provider.cc +++ b/third_party/blink/renderer/platform/graphics/offscreen_canvas_resource_provider.cc
@@ -4,9 +4,28 @@ #include "third_party/blink/renderer/platform/graphics/offscreen_canvas_resource_provider.h" +#include "base/memory/shared_memory.h" +#include "base/numerics/checked_math.h" +#include "components/viz/common/resources/bitmap_allocation.h" +#include "components/viz/common/resources/shared_bitmap.h" #include "components/viz/common/resources/single_release_callback.h" +#include "gpu/command_buffer/client/gles2_interface.h" +#include "gpu/command_buffer/common/capabilities.h" +#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom-blink.h" +#include "third_party/blink/public/platform/platform.h" +#include "third_party/blink/public/platform/web_graphics_context_3d_provider.h" #include "third_party/blink/renderer/platform/graphics/canvas_resource.h" #include "third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.h" +#include "third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.h" +#include "third_party/blink/renderer/platform/runtime_enabled_features.h" +#include "third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer.h" +#include "third_party/blink/renderer/platform/wtf/typed_arrays/uint8_array.h" +#include "third_party/khronos/GLES2/gl2.h" +#include "third_party/khronos/GLES2/gl2ext.h" +#include "third_party/skia/include/core/SkColor.h" +#include "third_party/skia/include/core/SkImage.h" +#include "third_party/skia/include/core/SkSwizzle.h" +#include "third_party/skia/include/gpu/GrContext.h" namespace blink { @@ -27,9 +46,68 @@ return std::make_unique<FrameResource>(); } -void OffscreenCanvasResourceProvider::SetTransferableResource( - viz::TransferableResource* out_resource, - scoped_refptr<CanvasResource> image) { +void OffscreenCanvasResourceProvider::SetTransferableResourceToSharedBitmap( + viz::TransferableResource& resource, + scoped_refptr<StaticBitmapImage> image) { + std::unique_ptr<FrameResource> frame_resource = + CreateOrRecycleFrameResource(); + if (!frame_resource->shared_memory) { + frame_resource->provider = this; + frame_resource->shared_bitmap_id = viz::SharedBitmap::GenerateId(); + frame_resource->shared_memory = + viz::bitmap_allocation::AllocateMappedBitmap(gfx::Size(width_, height_), + resource.format); + frame_dispatcher_->DidAllocateSharedBitmap( + viz::bitmap_allocation::DuplicateAndCloseMappedBitmap( + frame_resource->shared_memory.get(), gfx::Size(width_, height_), + resource.format), + SharedBitmapIdToGpuMailboxPtr(frame_resource->shared_bitmap_id)); + } + void* pixels = frame_resource->shared_memory->memory(); + DCHECK(pixels); + // When |image| is texture backed, this function does a GPU readback which is + // required. + sk_sp<SkImage> sk_image = image->PaintImageForCurrentFrame().GetSkImage(); + if (sk_image->bounds().isEmpty()) + return; + SkImageInfo image_info = SkImageInfo::Make( + width_, height_, kN32_SkColorType, + image->IsPremultiplied() ? kPremul_SkAlphaType : kUnpremul_SkAlphaType, + sk_image->refColorSpace()); + if (image_info.isEmpty()) + return; + + if (RuntimeEnabledFeatures::CanvasColorManagementEnabled()) { + image_info = image_info.makeColorType(sk_image->colorType()); + } + + // TODO(junov): Optimize to avoid copying pixels for non-texture-backed + // sk_image. See crbug.com/651456. + bool read_pixels_successful = + sk_image->readPixels(image_info, pixels, image_info.minRowBytes(), 0, 0); + DCHECK(read_pixels_successful); + if (!read_pixels_successful) + return; + resource.mailbox_holder.mailbox = frame_resource->shared_bitmap_id; + resource.mailbox_holder.texture_target = 0; + resource.is_software = true; + resource.id = next_resource_id_; + resource.format = viz::ResourceFormat::RGBA_8888; + resource.size = gfx::Size(width_, height_); + // This indicates the filtering on the resource inherently, not the desired + // filtering effect on the quad. + resource.filter = GL_NEAREST; + // TODO(crbug.com/646022): making this overlay-able. + resource.is_overlay_candidate = false; + + resources_.insert(next_resource_id_, std::move(frame_resource)); +} + +void OffscreenCanvasResourceProvider:: + SetTransferableResourceToStaticBitmapImage( + viz::TransferableResource* out_resource, + scoped_refptr<CanvasResource> image) { + DCHECK(image->IsAccelerated()); DCHECK(image->IsValid()); std::unique_ptr<FrameResource> frame_resource = @@ -88,6 +166,10 @@ OffscreenCanvasResourceProvider::FrameResource::~FrameResource() { if (release_callback) release_callback->Run(sync_token, is_lost); + if (provider && !shared_bitmap_id.IsZero()) { + provider->frame_dispatcher_->DidDeleteSharedBitmap( + SharedBitmapIdToGpuMailboxPtr(shared_bitmap_id)); + } } } // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/offscreen_canvas_resource_provider.h b/third_party/blink/renderer/platform/graphics/offscreen_canvas_resource_provider.h index 6ef51de..a1615b3 100644 --- a/third_party/blink/renderer/platform/graphics/offscreen_canvas_resource_provider.h +++ b/third_party/blink/renderer/platform/graphics/offscreen_canvas_resource_provider.h
@@ -9,6 +9,10 @@ #include "components/viz/common/resources/transferable_resource.h" #include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h" +namespace base { +class SharedMemory; +} + namespace viz { class SingleReleaseCallback; namespace mojom { @@ -34,8 +38,11 @@ ~OffscreenCanvasResourceProvider(); - void SetTransferableResource(viz::TransferableResource* out_resource, - scoped_refptr<CanvasResource>); + void SetTransferableResourceToSharedBitmap(viz::TransferableResource&, + scoped_refptr<StaticBitmapImage>); + void SetTransferableResourceToStaticBitmapImage( + viz::TransferableResource* out_resource, + scoped_refptr<CanvasResource>); void ReclaimResource(unsigned resource_id); void ReclaimResources(const WTF::Vector<viz::ReturnedResource>& resources); @@ -56,6 +63,12 @@ // TODO(junov): What does this do? bool spare_lock = true; + // Holds the backing for a software-backed resource. + std::unique_ptr<base::SharedMemory> shared_memory; + // The id given to the display compositor to display a software-backed + // resource. + viz::SharedBitmapId shared_bitmap_id; + // Back-pointer to the OffscreenCanvasResourceProvider. FrameResource does // not outlive the provider. OffscreenCanvasResourceProvider* provider = nullptr;
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index c3d68ec..5da92de 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -494,6 +494,7 @@ }, { name: "FeaturePolicyJavaScriptInterface", + origin_trial_feature_name: "FeaturePolicyJSAPI", status: "experimental" }, {
diff --git a/third_party/blink/renderer/platform/time_clamper.cc b/third_party/blink/renderer/platform/time_clamper.cc index ab38f2a..5eb0653 100644 --- a/third_party/blink/renderer/platform/time_clamper.cc +++ b/third_party/blink/renderer/platform/time_clamper.cc
@@ -15,13 +15,19 @@ TimeClamper::TimeClamper() : secret_(base::RandUint64()) {} double TimeClamper::ClampTimeResolution(double time_seconds) const { - DCHECK_GE(time_seconds, 0); + bool was_negative = false; + if (time_seconds < 0) { + was_negative = true; + time_seconds = -time_seconds; + } double interval = floor(time_seconds / kResolutionSeconds); double clamped_time = interval * kResolutionSeconds; double tick_threshold = ThresholdFor(clamped_time); if (time_seconds >= tick_threshold) - return (interval + 1) * kResolutionSeconds; + clamped_time = (interval + 1) * kResolutionSeconds; + if (was_negative) + clamped_time = -clamped_time; return clamped_time; }
diff --git a/third_party/blink/renderer/platform/time_clamper_test.cc b/third_party/blink/renderer/platform/time_clamper_test.cc index f519dcfb..9a855fc 100644 --- a/third_party/blink/renderer/platform/time_clamper_test.cc +++ b/third_party/blink/renderer/platform/time_clamper_test.cc
@@ -45,6 +45,16 @@ } } +TEST(TimeClamperTest, ClampingNegativeNumbersIsConsistent) { + TimeClamper clamper; + for (double time_seconds = -kInterval * 100; time_seconds <= 0; + time_seconds += kInterval * 0.1) { + double t1 = clamper.ClampTimeResolution(time_seconds); + double t2 = clamper.ClampTimeResolution(time_seconds); + EXPECT_EQ(t1, t2); + } +} + TEST(TimeClamperTest, ClampingIsPerInstance) { const double kEpsilon = 1e-10; TimeClamper clamper1;
diff --git a/third_party/blink/renderer/platform/wtf/BUILD.gn b/third_party/blink/renderer/platform/wtf/BUILD.gn index dba0b46..95a6b538 100644 --- a/third_party/blink/renderer/platform/wtf/BUILD.gn +++ b/third_party/blink/renderer/platform/wtf/BUILD.gn
@@ -338,6 +338,7 @@ "text/text_codec_utf8_test.cc", "text/text_encoding_test.cc", "text/wtf_string_test.cc", + "threading_primitives_test.cc", "tree_node_test.cc", "type_traits_test.cc", "typed_arrays/array_buffer_builder_test.cc",
diff --git a/third_party/blink/renderer/platform/wtf/DEPS b/third_party/blink/renderer/platform/wtf/DEPS index 2576c5d9..2cff45e5 100644 --- a/third_party/blink/renderer/platform/wtf/DEPS +++ b/third_party/blink/renderer/platform/wtf/DEPS
@@ -20,8 +20,7 @@ "+base/strings", "+base/template_util.h", "+base/test/metrics/histogram_tester.h", - "+base/threading/thread_checker.h", - "+base/threading/thread_local_storage.h", + "+base/threading", "+base/time/time.h", "+base/tuple.h", # To avoid recursive dependency, we impose a blanket ban on using other @@ -30,9 +29,3 @@ "+third_party/blink/renderer/platform/wtf", "-v8", ] - -specific_include_rules = { - ".*_test\.cc": [ - "+base/threading/thread.h" - ] -}
diff --git a/third_party/blink/renderer/platform/wtf/threading_primitives_test.cc b/third_party/blink/renderer/platform/wtf/threading_primitives_test.cc new file mode 100644 index 0000000..fee226d --- /dev/null +++ b/third_party/blink/renderer/platform/wtf/threading_primitives_test.cc
@@ -0,0 +1,81 @@ +// 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/platform/wtf/threading_primitives.h" + +#include "base/bind.h" +#include "base/synchronization/waitable_event.h" +#include "base/threading/scoped_blocking_call.h" +#include "base/threading/thread.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/renderer/platform/wtf/time.h" + +namespace WTF { +namespace { + +class MockBlockingObserver : public base::internal::BlockingObserver { + public: + // base::internal::BlockingObserver + MOCK_METHOD1(BlockingStarted, void(base::BlockingType)); + MOCK_METHOD0(BlockingTypeUpgraded, void()); + MOCK_METHOD0(BlockingEnded, void()); +}; + +class ThreadConditionTest : public testing::Test { + public: + void RunOtherThreadInfiniteWait() { + base::internal::SetBlockingObserverForCurrentThread(&observer_); + MutexLocker lock(mutex_); + ready_.Signal(); + condition_.Wait(mutex_); + } + + void RunOtherThreadTimedWait() { + base::internal::SetBlockingObserverForCurrentThread(&observer_); + MutexLocker lock(mutex_); + ready_.Signal(); + condition_.TimedWait(mutex_, CurrentTime() + 10.0); + } + + protected: + base::WaitableEvent ready_; + testing::StrictMock<MockBlockingObserver> observer_; + Mutex mutex_; + ThreadCondition condition_; +}; + +TEST_F(ThreadConditionTest, WaitReportsBlockingCall) { + EXPECT_CALL(observer_, BlockingStarted(base::BlockingType::MAY_BLOCK)); + EXPECT_CALL(observer_, BlockingEnded()); + + base::Thread other_thread("other thread"); + other_thread.StartAndWaitForTesting(); + other_thread.task_runner()->PostTask( + FROM_HERE, + base::BindOnce(&ThreadConditionTest::RunOtherThreadInfiniteWait, + base::Unretained(this))); + + ready_.Wait(); + MutexLocker lock(mutex_); + condition_.Signal(); +} + +TEST_F(ThreadConditionTest, TimedWaitReportsBlockingCall) { + EXPECT_CALL(observer_, BlockingStarted(base::BlockingType::MAY_BLOCK)); + EXPECT_CALL(observer_, BlockingEnded()); + + base::Thread other_thread("other thread"); + other_thread.StartAndWaitForTesting(); + other_thread.task_runner()->PostTask( + FROM_HERE, base::BindOnce(&ThreadConditionTest::RunOtherThreadTimedWait, + base::Unretained(this))); + + ready_.Wait(); + MutexLocker lock(mutex_); + condition_.Signal(); +} + +} // namespace +} // namespace WTF
diff --git a/third_party/blink/renderer/platform/wtf/threading_pthreads.cc b/third_party/blink/renderer/platform/wtf/threading_pthreads.cc index cf4f983..5928f1f5 100644 --- a/third_party/blink/renderer/platform/wtf/threading_pthreads.cc +++ b/third_party/blink/renderer/platform/wtf/threading_pthreads.cc
@@ -38,6 +38,7 @@ #include <limits.h> #include <sched.h> #include <sys/time.h> +#include "base/threading/scoped_blocking_call.h" #include "third_party/blink/renderer/platform/wtf/date_math.h" #include "third_party/blink/renderer/platform/wtf/dtoa/double-conversion.h" #include "third_party/blink/renderer/platform/wtf/hash_map.h" @@ -206,6 +207,7 @@ } void ThreadCondition::Wait(Mutex& mutex) { + base::ScopedBlockingCall scoped_blocking_call(base::BlockingType::MAY_BLOCK); PlatformMutex& platform_mutex = mutex.Impl(); int result = pthread_cond_wait(&condition_, &platform_mutex.internal_mutex_); DCHECK_EQ(result, 0); @@ -230,6 +232,7 @@ target_time.tv_sec = time_seconds; target_time.tv_nsec = time_nanoseconds; + base::ScopedBlockingCall scoped_blocking_call(base::BlockingType::MAY_BLOCK); PlatformMutex& platform_mutex = mutex.Impl(); int result = pthread_cond_timedwait( &condition_, &platform_mutex.internal_mutex_, &target_time);
diff --git a/third_party/blink/renderer/platform/wtf/threading_win.cc b/third_party/blink/renderer/platform/wtf/threading_win.cc index 09cc847..b06ca84a 100644 --- a/third_party/blink/renderer/platform/wtf/threading_win.cc +++ b/third_party/blink/renderer/platform/wtf/threading_win.cc
@@ -105,6 +105,7 @@ #include <errno.h> #include <process.h> #include <windows.h> +#include "base/threading/scoped_blocking_call.h" #include "third_party/blink/renderer/platform/wtf/date_math.h" #include "third_party/blink/renderer/platform/wtf/dtoa/double-conversion.h" #include "third_party/blink/renderer/platform/wtf/hash_map.h" @@ -248,6 +249,7 @@ void ThreadCondition::Wait(Mutex& mutex) { PlatformMutex& platform_mutex = mutex.Impl(); + base::ScopedBlockingCall scoped_blocking_call(base::BlockingType::MAY_BLOCK); BOOL result = SleepConditionVariableCS( &condition_, &platform_mutex.internal_mutex_, INFINITE); DCHECK_NE(result, 0); @@ -271,6 +273,7 @@ ? INFINITE : ((absolute_time - current_time) * 1000.0); + base::ScopedBlockingCall scoped_blocking_call(base::BlockingType::MAY_BLOCK); PlatformMutex& platform_mutex = mutex.Impl(); BOOL result = SleepConditionVariableCS( &condition_, &platform_mutex.internal_mutex_, interval);
diff --git a/third_party/fuchsia-sdk/BUILD.gn b/third_party/fuchsia-sdk/BUILD.gn index 2446fa4..4bb91f54 100644 --- a/third_party/fuchsia-sdk/BUILD.gn +++ b/third_party/fuchsia-sdk/BUILD.gn
@@ -36,7 +36,6 @@ fuchsia_sdk_pkg("fdio") { sources = [ "include/lib/fdio/debug.h", - "include/lib/fdio/io.fidl.h", "include/lib/fdio/io.h", "include/lib/fdio/limits.h", "include/lib/fdio/module.modulemap",
diff --git a/third_party/wayland-protocols/BUILD.gn b/third_party/wayland-protocols/BUILD.gn index e62fbec..3d28796 100644 --- a/third_party/wayland-protocols/BUILD.gn +++ b/third_party/wayland-protocols/BUILD.gn
@@ -343,3 +343,24 @@ public_configs = [ ":cursor_shapes_protocol_config" ] } + +config("text_input_protocol_config") { + include_dirs = [ "include/protocol" ] +} + +source_set("text_input_protocol") { + sources = [ + "include/protocol/text-input-unstable-v1-client-protocol.h", + "include/protocol/text-input-unstable-v1-server-protocol.h", + "protocol/text-input-v1-protocol.c", + ] + + deps = [ + "//third_party/wayland:wayland_util", + ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + + public_configs = [ ":text_input_protocol_config" ] +}
diff --git a/third_party/wayland-protocols/OWNERS b/third_party/wayland-protocols/OWNERS index fe51e0c..55943c1 100644 --- a/third_party/wayland-protocols/OWNERS +++ b/third_party/wayland-protocols/OWNERS
@@ -1,2 +1,5 @@ reveman@chromium.org piman@chromium.org +oshima@chromium.org +dcastagna@chromium.org +
diff --git a/third_party/wayland-protocols/README.chromium b/third_party/wayland-protocols/README.chromium index 410f6ce..b757599 100644 --- a/third_party/wayland-protocols/README.chromium +++ b/third_party/wayland-protocols/README.chromium
@@ -70,4 +70,7 @@ wayland-scanner code < src/unstable/input-timestamps/input-timestamps-unstable-v1.xml > protocol/input-timestamps-v1-protocol.c wayland-scanner server-header < src/unstable/input-timestamps/input-timestamps-unstable-v1.xml > include/protocol/input-timestamps-unstable-v1-server-protocol.h wayland-scanner client-header < src/unstable/input-timestamps/input-timestamps-unstable-v1.xml > include/protocol/input-timestamps-unstable-v1-client-protocol.h + wayland-scanner code < src/unstable/text-input/text-input-unstable-v1.xml > protocol/text-input-v1-protocol.c + wayland-scanner server-header < src/unstable/text-input/text-input-unstable-v1.xml > include/protocol/text-input-unstable-v1-server-protocol.h + wayland-scanner client-header < src/unstable/text-input/text-input-unstable-v1.xml > include/protocol/text-input-unstable-v1-client-protocol.h - Update this README to reflect the new version number.
diff --git a/third_party/wayland-protocols/include/protocol/text-input-unstable-v1-client-protocol.h b/third_party/wayland-protocols/include/protocol/text-input-unstable-v1-client-protocol.h new file mode 100644 index 0000000..4f2df6c --- /dev/null +++ b/third_party/wayland-protocols/include/protocol/text-input-unstable-v1-client-protocol.h
@@ -0,0 +1,841 @@ +/* Generated by wayland-scanner 1.13.0 */ + +#ifndef TEXT_INPUT_UNSTABLE_V1_CLIENT_PROTOCOL_H +#define TEXT_INPUT_UNSTABLE_V1_CLIENT_PROTOCOL_H + +#include <stdint.h> +#include <stddef.h> +#include "wayland-client.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @page page_text_input_unstable_v1 The text_input_unstable_v1 protocol + * @section page_ifaces_text_input_unstable_v1 Interfaces + * - @subpage page_iface_zwp_text_input_v1 - text input + * - @subpage page_iface_zwp_text_input_manager_v1 - text input manager + * @section page_copyright_text_input_unstable_v1 Copyright + * <pre> + * + * Copyright © 2012, 2013 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * </pre> + */ +struct wl_seat; +struct wl_surface; +struct zwp_text_input_manager_v1; +struct zwp_text_input_v1; + +/** + * @page page_iface_zwp_text_input_v1 zwp_text_input_v1 + * @section page_iface_zwp_text_input_v1_desc Description + * + * An object used for text input. Adds support for text input and input + * methods to applications. A text_input object is created from a + * wl_text_input_manager and corresponds typically to a text entry in an + * application. + * + * Requests are used to activate/deactivate the text_input object and set + * state information like surrounding and selected text or the content type. + * The information about entered text is sent to the text_input object via + * the pre-edit and commit events. Using this interface removes the need + * for applications to directly process hardware key events and compose text + * out of them. + * + * Text is generally UTF-8 encoded, indices and lengths are in bytes. + * + * Serials are used to synchronize the state between the text input and + * an input method. New serials are sent by the text input in the + * commit_state request and are used by the input method to indicate + * the known text input state in events like preedit_string, commit_string, + * and keysym. The text input can then ignore events from the input method + * which are based on an outdated state (for example after a reset). + * + * Warning! The protocol described in this file is experimental and + * backward incompatible changes may be made. Backward compatible changes + * may be added together with the corresponding interface version bump. + * Backward incompatible changes are done by bumping the version number in + * the protocol and interface names and resetting the interface version. + * Once the protocol is to be declared stable, the 'z' prefix and the + * version number in the protocol and interface names are removed and the + * interface version number is reset. + * @section page_iface_zwp_text_input_v1_api API + * See @ref iface_zwp_text_input_v1. + */ +/** + * @defgroup iface_zwp_text_input_v1 The zwp_text_input_v1 interface + * + * An object used for text input. Adds support for text input and input + * methods to applications. A text_input object is created from a + * wl_text_input_manager and corresponds typically to a text entry in an + * application. + * + * Requests are used to activate/deactivate the text_input object and set + * state information like surrounding and selected text or the content type. + * The information about entered text is sent to the text_input object via + * the pre-edit and commit events. Using this interface removes the need + * for applications to directly process hardware key events and compose text + * out of them. + * + * Text is generally UTF-8 encoded, indices and lengths are in bytes. + * + * Serials are used to synchronize the state between the text input and + * an input method. New serials are sent by the text input in the + * commit_state request and are used by the input method to indicate + * the known text input state in events like preedit_string, commit_string, + * and keysym. The text input can then ignore events from the input method + * which are based on an outdated state (for example after a reset). + * + * Warning! The protocol described in this file is experimental and + * backward incompatible changes may be made. Backward compatible changes + * may be added together with the corresponding interface version bump. + * Backward incompatible changes are done by bumping the version number in + * the protocol and interface names and resetting the interface version. + * Once the protocol is to be declared stable, the 'z' prefix and the + * version number in the protocol and interface names are removed and the + * interface version number is reset. + */ +extern const struct wl_interface zwp_text_input_v1_interface; +/** + * @page page_iface_zwp_text_input_manager_v1 zwp_text_input_manager_v1 + * @section page_iface_zwp_text_input_manager_v1_desc Description + * + * A factory for text_input objects. This object is a global singleton. + * @section page_iface_zwp_text_input_manager_v1_api API + * See @ref iface_zwp_text_input_manager_v1. + */ +/** + * @defgroup iface_zwp_text_input_manager_v1 The zwp_text_input_manager_v1 interface + * + * A factory for text_input objects. This object is a global singleton. + */ +extern const struct wl_interface zwp_text_input_manager_v1_interface; + +#ifndef ZWP_TEXT_INPUT_V1_CONTENT_HINT_ENUM +#define ZWP_TEXT_INPUT_V1_CONTENT_HINT_ENUM +/** + * @ingroup iface_zwp_text_input_v1 + * content hint + * + * Content hint is a bitmask to allow to modify the behavior of the text + * input. + */ +enum zwp_text_input_v1_content_hint { + /** + * no special behaviour + */ + ZWP_TEXT_INPUT_V1_CONTENT_HINT_NONE = 0x0, + /** + * auto completion, correction and capitalization + */ + ZWP_TEXT_INPUT_V1_CONTENT_HINT_DEFAULT = 0x7, + /** + * hidden and sensitive text + */ + ZWP_TEXT_INPUT_V1_CONTENT_HINT_PASSWORD = 0xc0, + /** + * suggest word completions + */ + ZWP_TEXT_INPUT_V1_CONTENT_HINT_AUTO_COMPLETION = 0x1, + /** + * suggest word corrections + */ + ZWP_TEXT_INPUT_V1_CONTENT_HINT_AUTO_CORRECTION = 0x2, + /** + * switch to uppercase letters at the start of a sentence + */ + ZWP_TEXT_INPUT_V1_CONTENT_HINT_AUTO_CAPITALIZATION = 0x4, + /** + * prefer lowercase letters + */ + ZWP_TEXT_INPUT_V1_CONTENT_HINT_LOWERCASE = 0x8, + /** + * prefer uppercase letters + */ + ZWP_TEXT_INPUT_V1_CONTENT_HINT_UPPERCASE = 0x10, + /** + * prefer casing for titles and headings (can be language dependent) + */ + ZWP_TEXT_INPUT_V1_CONTENT_HINT_TITLECASE = 0x20, + /** + * characters should be hidden + */ + ZWP_TEXT_INPUT_V1_CONTENT_HINT_HIDDEN_TEXT = 0x40, + /** + * typed text should not be stored + */ + ZWP_TEXT_INPUT_V1_CONTENT_HINT_SENSITIVE_DATA = 0x80, + /** + * just latin characters should be entered + */ + ZWP_TEXT_INPUT_V1_CONTENT_HINT_LATIN = 0x100, + /** + * the text input is multiline + */ + ZWP_TEXT_INPUT_V1_CONTENT_HINT_MULTILINE = 0x200, +}; +#endif /* ZWP_TEXT_INPUT_V1_CONTENT_HINT_ENUM */ + +#ifndef ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_ENUM +#define ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_ENUM +/** + * @ingroup iface_zwp_text_input_v1 + * content purpose + * + * The content purpose allows to specify the primary purpose of a text + * input. + * + * This allows an input method to show special purpose input panels with + * extra characters or to disallow some characters. + */ +enum zwp_text_input_v1_content_purpose { + /** + * default input, allowing all characters + */ + ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_NORMAL = 0, + /** + * allow only alphabetic characters + */ + ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_ALPHA = 1, + /** + * allow only digits + */ + ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_DIGITS = 2, + /** + * input a number (including decimal separator and sign) + */ + ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_NUMBER = 3, + /** + * input a phone number + */ + ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_PHONE = 4, + /** + * input an URL + */ + ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_URL = 5, + /** + * input an email address + */ + ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_EMAIL = 6, + /** + * input a name of a person + */ + ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_NAME = 7, + /** + * input a password (combine with password or sensitive_data hint) + */ + ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_PASSWORD = 8, + /** + * input a date + */ + ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_DATE = 9, + /** + * input a time + */ + ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_TIME = 10, + /** + * input a date and time + */ + ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_DATETIME = 11, + /** + * input for a terminal + */ + ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_TERMINAL = 12, +}; +#endif /* ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_ENUM */ + +#ifndef ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_ENUM +#define ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_ENUM +enum zwp_text_input_v1_preedit_style { + /** + * default style for composing text + */ + ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_DEFAULT = 0, + /** + * style should be the same as in non-composing text + */ + ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_NONE = 1, + ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_ACTIVE = 2, + ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_INACTIVE = 3, + ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_HIGHLIGHT = 4, + ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_UNDERLINE = 5, + ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_SELECTION = 6, + ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_INCORRECT = 7, +}; +#endif /* ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_ENUM */ + +#ifndef ZWP_TEXT_INPUT_V1_TEXT_DIRECTION_ENUM +#define ZWP_TEXT_INPUT_V1_TEXT_DIRECTION_ENUM +enum zwp_text_input_v1_text_direction { + /** + * automatic text direction based on text and language + */ + ZWP_TEXT_INPUT_V1_TEXT_DIRECTION_AUTO = 0, + /** + * left-to-right + */ + ZWP_TEXT_INPUT_V1_TEXT_DIRECTION_LTR = 1, + /** + * right-to-left + */ + ZWP_TEXT_INPUT_V1_TEXT_DIRECTION_RTL = 2, +}; +#endif /* ZWP_TEXT_INPUT_V1_TEXT_DIRECTION_ENUM */ + +/** + * @ingroup iface_zwp_text_input_v1 + * @struct zwp_text_input_v1_listener + */ +struct zwp_text_input_v1_listener { + /** + * enter event + * + * Notify the text_input object when it received focus. Typically + * in response to an activate request. + */ + void (*enter)(void *data, + struct zwp_text_input_v1 *zwp_text_input_v1, + struct wl_surface *surface); + /** + * leave event + * + * Notify the text_input object when it lost focus. Either in + * response to a deactivate request or when the assigned surface + * lost focus or was destroyed. + */ + void (*leave)(void *data, + struct zwp_text_input_v1 *zwp_text_input_v1); + /** + * modifiers map + * + * Transfer an array of 0-terminated modifier names. The position + * in the array is the index of the modifier as used in the + * modifiers bitmask in the keysym event. + */ + void (*modifiers_map)(void *data, + struct zwp_text_input_v1 *zwp_text_input_v1, + struct wl_array *map); + /** + * state of the input panel + * + * Notify when the visibility state of the input panel changed. + */ + void (*input_panel_state)(void *data, + struct zwp_text_input_v1 *zwp_text_input_v1, + uint32_t state); + /** + * pre-edit + * + * Notify when a new composing text (pre-edit) should be set + * around the current cursor position. Any previously set composing + * text should be removed. + * + * The commit text can be used to replace the preedit text on reset + * (for example on unfocus). + * + * The text input should also handle all preedit_style and + * preedit_cursor events occurring directly before preedit_string. + * @param serial serial of the latest known text input state + */ + void (*preedit_string)(void *data, + struct zwp_text_input_v1 *zwp_text_input_v1, + uint32_t serial, + const char *text, + const char *commit); + /** + * pre-edit styling + * + * Sets styling information on composing text. The style is + * applied for length bytes from index relative to the beginning of + * the composing text (as byte offset). Multiple styles can be + * applied to a composing text by sending multiple preedit_styling + * events. + * + * This event is handled as part of a following preedit_string + * event. + */ + void (*preedit_styling)(void *data, + struct zwp_text_input_v1 *zwp_text_input_v1, + uint32_t index, + uint32_t length, + uint32_t style); + /** + * pre-edit cursor + * + * Sets the cursor position inside the composing text (as byte + * offset) relative to the start of the composing text. When index + * is a negative number no cursor is shown. + * + * This event is handled as part of a following preedit_string + * event. + */ + void (*preedit_cursor)(void *data, + struct zwp_text_input_v1 *zwp_text_input_v1, + int32_t index); + /** + * commit + * + * Notify when text should be inserted into the editor widget. + * The text to commit could be either just a single character after + * a key press or the result of some composing (pre-edit). It could + * also be an empty text when some text should be removed (see + * delete_surrounding_text) or when the input cursor should be + * moved (see cursor_position). + * + * Any previously set composing text should be removed. + * @param serial serial of the latest known text input state + */ + void (*commit_string)(void *data, + struct zwp_text_input_v1 *zwp_text_input_v1, + uint32_t serial, + const char *text); + /** + * set cursor to new position + * + * Notify when the cursor or anchor position should be modified. + * + * This event should be handled as part of a following + * commit_string event. + */ + void (*cursor_position)(void *data, + struct zwp_text_input_v1 *zwp_text_input_v1, + int32_t index, + int32_t anchor); + /** + * delete surrounding text + * + * Notify when the text around the current cursor position should + * be deleted. + * + * Index is relative to the current cursor (in bytes). Length is + * the length of deleted text (in bytes). + * + * This event should be handled as part of a following + * commit_string event. + */ + void (*delete_surrounding_text)(void *data, + struct zwp_text_input_v1 *zwp_text_input_v1, + int32_t index, + uint32_t length); + /** + * keysym + * + * Notify when a key event was sent. Key events should not be + * used for normal text input operations, which should be done with + * commit_string, delete_surrounding_text, etc. The key event + * follows the wl_keyboard key event convention. Sym is an XKB + * keysym, state a wl_keyboard key_state. Modifiers are a mask for + * effective modifiers (where the modifier indices are set by the + * modifiers_map event) + * @param serial serial of the latest known text input state + */ + void (*keysym)(void *data, + struct zwp_text_input_v1 *zwp_text_input_v1, + uint32_t serial, + uint32_t time, + uint32_t sym, + uint32_t state, + uint32_t modifiers); + /** + * language + * + * Sets the language of the input text. The "language" argument + * is an RFC-3066 format language tag. + * @param serial serial of the latest known text input state + */ + void (*language)(void *data, + struct zwp_text_input_v1 *zwp_text_input_v1, + uint32_t serial, + const char *language); + /** + * text direction + * + * Sets the text direction of input text. + * + * It is mainly needed for showing an input cursor on the correct + * side of the editor when there is no input done yet and making + * sure neutral direction text is laid out properly. + * @param serial serial of the latest known text input state + */ + void (*text_direction)(void *data, + struct zwp_text_input_v1 *zwp_text_input_v1, + uint32_t serial, + uint32_t direction); +}; + +/** + * @ingroup iface_zwp_text_input_v1 + */ +static inline int +zwp_text_input_v1_add_listener(struct zwp_text_input_v1 *zwp_text_input_v1, + const struct zwp_text_input_v1_listener *listener, void *data) +{ + return wl_proxy_add_listener((struct wl_proxy *) zwp_text_input_v1, + (void (**)(void)) listener, data); +} + +#define ZWP_TEXT_INPUT_V1_ACTIVATE 0 +#define ZWP_TEXT_INPUT_V1_DEACTIVATE 1 +#define ZWP_TEXT_INPUT_V1_SHOW_INPUT_PANEL 2 +#define ZWP_TEXT_INPUT_V1_HIDE_INPUT_PANEL 3 +#define ZWP_TEXT_INPUT_V1_RESET 4 +#define ZWP_TEXT_INPUT_V1_SET_SURROUNDING_TEXT 5 +#define ZWP_TEXT_INPUT_V1_SET_CONTENT_TYPE 6 +#define ZWP_TEXT_INPUT_V1_SET_CURSOR_RECTANGLE 7 +#define ZWP_TEXT_INPUT_V1_SET_PREFERRED_LANGUAGE 8 +#define ZWP_TEXT_INPUT_V1_COMMIT_STATE 9 +#define ZWP_TEXT_INPUT_V1_INVOKE_ACTION 10 + +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_ENTER_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_LEAVE_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_MODIFIERS_MAP_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_INPUT_PANEL_STATE_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_PREEDIT_STRING_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_PREEDIT_STYLING_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_PREEDIT_CURSOR_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_COMMIT_STRING_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_CURSOR_POSITION_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_DELETE_SURROUNDING_TEXT_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_KEYSYM_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_LANGUAGE_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_TEXT_DIRECTION_SINCE_VERSION 1 + +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_ACTIVATE_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_DEACTIVATE_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_SHOW_INPUT_PANEL_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_HIDE_INPUT_PANEL_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_RESET_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_SET_SURROUNDING_TEXT_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_SET_CONTENT_TYPE_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_SET_CURSOR_RECTANGLE_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_SET_PREFERRED_LANGUAGE_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_COMMIT_STATE_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_INVOKE_ACTION_SINCE_VERSION 1 + +/** @ingroup iface_zwp_text_input_v1 */ +static inline void +zwp_text_input_v1_set_user_data(struct zwp_text_input_v1 *zwp_text_input_v1, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) zwp_text_input_v1, user_data); +} + +/** @ingroup iface_zwp_text_input_v1 */ +static inline void * +zwp_text_input_v1_get_user_data(struct zwp_text_input_v1 *zwp_text_input_v1) +{ + return wl_proxy_get_user_data((struct wl_proxy *) zwp_text_input_v1); +} + +static inline uint32_t +zwp_text_input_v1_get_version(struct zwp_text_input_v1 *zwp_text_input_v1) +{ + return wl_proxy_get_version((struct wl_proxy *) zwp_text_input_v1); +} + +/** @ingroup iface_zwp_text_input_v1 */ +static inline void +zwp_text_input_v1_destroy(struct zwp_text_input_v1 *zwp_text_input_v1) +{ + wl_proxy_destroy((struct wl_proxy *) zwp_text_input_v1); +} + +/** + * @ingroup iface_zwp_text_input_v1 + * + * Requests the text_input object to be activated (typically when the + * text entry gets focus). + * + * The seat argument is a wl_seat which maintains the focus for this + * activation. The surface argument is a wl_surface assigned to the + * text_input object and tracked for focus lost. The enter event + * is emitted on successful activation. + */ +static inline void +zwp_text_input_v1_activate(struct zwp_text_input_v1 *zwp_text_input_v1, struct wl_seat *seat, struct wl_surface *surface) +{ + wl_proxy_marshal((struct wl_proxy *) zwp_text_input_v1, + ZWP_TEXT_INPUT_V1_ACTIVATE, seat, surface); +} + +/** + * @ingroup iface_zwp_text_input_v1 + * + * Requests the text_input object to be deactivated (typically when the + * text entry lost focus). The seat argument is a wl_seat which was used + * for activation. + */ +static inline void +zwp_text_input_v1_deactivate(struct zwp_text_input_v1 *zwp_text_input_v1, struct wl_seat *seat) +{ + wl_proxy_marshal((struct wl_proxy *) zwp_text_input_v1, + ZWP_TEXT_INPUT_V1_DEACTIVATE, seat); +} + +/** + * @ingroup iface_zwp_text_input_v1 + * + * Requests input panels (virtual keyboard) to show. + */ +static inline void +zwp_text_input_v1_show_input_panel(struct zwp_text_input_v1 *zwp_text_input_v1) +{ + wl_proxy_marshal((struct wl_proxy *) zwp_text_input_v1, + ZWP_TEXT_INPUT_V1_SHOW_INPUT_PANEL); +} + +/** + * @ingroup iface_zwp_text_input_v1 + * + * Requests input panels (virtual keyboard) to hide. + */ +static inline void +zwp_text_input_v1_hide_input_panel(struct zwp_text_input_v1 *zwp_text_input_v1) +{ + wl_proxy_marshal((struct wl_proxy *) zwp_text_input_v1, + ZWP_TEXT_INPUT_V1_HIDE_INPUT_PANEL); +} + +/** + * @ingroup iface_zwp_text_input_v1 + * + * Should be called by an editor widget when the input state should be + * reset, for example after the text was changed outside of the normal + * input method flow. + */ +static inline void +zwp_text_input_v1_reset(struct zwp_text_input_v1 *zwp_text_input_v1) +{ + wl_proxy_marshal((struct wl_proxy *) zwp_text_input_v1, + ZWP_TEXT_INPUT_V1_RESET); +} + +/** + * @ingroup iface_zwp_text_input_v1 + * + * Sets the plain surrounding text around the input position. Text is + * UTF-8 encoded. Cursor is the byte offset within the + * surrounding text. Anchor is the byte offset of the + * selection anchor within the surrounding text. If there is no selected + * text anchor, then it is the same as cursor. + */ +static inline void +zwp_text_input_v1_set_surrounding_text(struct zwp_text_input_v1 *zwp_text_input_v1, const char *text, uint32_t cursor, uint32_t anchor) +{ + wl_proxy_marshal((struct wl_proxy *) zwp_text_input_v1, + ZWP_TEXT_INPUT_V1_SET_SURROUNDING_TEXT, text, cursor, anchor); +} + +/** + * @ingroup iface_zwp_text_input_v1 + * + * Sets the content purpose and content hint. While the purpose is the + * basic purpose of an input field, the hint flags allow to modify some + * of the behavior. + * + * When no content type is explicitly set, a normal content purpose with + * default hints (auto completion, auto correction, auto capitalization) + * should be assumed. + */ +static inline void +zwp_text_input_v1_set_content_type(struct zwp_text_input_v1 *zwp_text_input_v1, uint32_t hint, uint32_t purpose) +{ + wl_proxy_marshal((struct wl_proxy *) zwp_text_input_v1, + ZWP_TEXT_INPUT_V1_SET_CONTENT_TYPE, hint, purpose); +} + +/** + * @ingroup iface_zwp_text_input_v1 + */ +static inline void +zwp_text_input_v1_set_cursor_rectangle(struct zwp_text_input_v1 *zwp_text_input_v1, int32_t x, int32_t y, int32_t width, int32_t height) +{ + wl_proxy_marshal((struct wl_proxy *) zwp_text_input_v1, + ZWP_TEXT_INPUT_V1_SET_CURSOR_RECTANGLE, x, y, width, height); +} + +/** + * @ingroup iface_zwp_text_input_v1 + * + * Sets a specific language. This allows for example a virtual keyboard to + * show a language specific layout. The "language" argument is an RFC-3066 + * format language tag. + * + * It could be used for example in a word processor to indicate the + * language of the currently edited document or in an instant message + * application which tracks languages of contacts. + */ +static inline void +zwp_text_input_v1_set_preferred_language(struct zwp_text_input_v1 *zwp_text_input_v1, const char *language) +{ + wl_proxy_marshal((struct wl_proxy *) zwp_text_input_v1, + ZWP_TEXT_INPUT_V1_SET_PREFERRED_LANGUAGE, language); +} + +/** + * @ingroup iface_zwp_text_input_v1 + */ +static inline void +zwp_text_input_v1_commit_state(struct zwp_text_input_v1 *zwp_text_input_v1, uint32_t serial) +{ + wl_proxy_marshal((struct wl_proxy *) zwp_text_input_v1, + ZWP_TEXT_INPUT_V1_COMMIT_STATE, serial); +} + +/** + * @ingroup iface_zwp_text_input_v1 + */ +static inline void +zwp_text_input_v1_invoke_action(struct zwp_text_input_v1 *zwp_text_input_v1, uint32_t button, uint32_t index) +{ + wl_proxy_marshal((struct wl_proxy *) zwp_text_input_v1, + ZWP_TEXT_INPUT_V1_INVOKE_ACTION, button, index); +} + +#define ZWP_TEXT_INPUT_MANAGER_V1_CREATE_TEXT_INPUT 0 + + +/** + * @ingroup iface_zwp_text_input_manager_v1 + */ +#define ZWP_TEXT_INPUT_MANAGER_V1_CREATE_TEXT_INPUT_SINCE_VERSION 1 + +/** @ingroup iface_zwp_text_input_manager_v1 */ +static inline void +zwp_text_input_manager_v1_set_user_data(struct zwp_text_input_manager_v1 *zwp_text_input_manager_v1, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) zwp_text_input_manager_v1, user_data); +} + +/** @ingroup iface_zwp_text_input_manager_v1 */ +static inline void * +zwp_text_input_manager_v1_get_user_data(struct zwp_text_input_manager_v1 *zwp_text_input_manager_v1) +{ + return wl_proxy_get_user_data((struct wl_proxy *) zwp_text_input_manager_v1); +} + +static inline uint32_t +zwp_text_input_manager_v1_get_version(struct zwp_text_input_manager_v1 *zwp_text_input_manager_v1) +{ + return wl_proxy_get_version((struct wl_proxy *) zwp_text_input_manager_v1); +} + +/** @ingroup iface_zwp_text_input_manager_v1 */ +static inline void +zwp_text_input_manager_v1_destroy(struct zwp_text_input_manager_v1 *zwp_text_input_manager_v1) +{ + wl_proxy_destroy((struct wl_proxy *) zwp_text_input_manager_v1); +} + +/** + * @ingroup iface_zwp_text_input_manager_v1 + * + * Creates a new text_input object. + */ +static inline struct zwp_text_input_v1 * +zwp_text_input_manager_v1_create_text_input(struct zwp_text_input_manager_v1 *zwp_text_input_manager_v1) +{ + struct wl_proxy *id; + + id = wl_proxy_marshal_constructor((struct wl_proxy *) zwp_text_input_manager_v1, + ZWP_TEXT_INPUT_MANAGER_V1_CREATE_TEXT_INPUT, &zwp_text_input_v1_interface, NULL); + + return (struct zwp_text_input_v1 *) id; +} + +#ifdef __cplusplus +} +#endif + +#endif
diff --git a/third_party/wayland-protocols/include/protocol/text-input-unstable-v1-server-protocol.h b/third_party/wayland-protocols/include/protocol/text-input-unstable-v1-server-protocol.h new file mode 100644 index 0000000..524b223 --- /dev/null +++ b/third_party/wayland-protocols/include/protocol/text-input-unstable-v1-server-protocol.h
@@ -0,0 +1,711 @@ +/* Generated by wayland-scanner 1.13.0 */ + +#ifndef TEXT_INPUT_UNSTABLE_V1_SERVER_PROTOCOL_H +#define TEXT_INPUT_UNSTABLE_V1_SERVER_PROTOCOL_H + +#include <stdint.h> +#include <stddef.h> +#include "wayland-server.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct wl_client; +struct wl_resource; + +/** + * @page page_text_input_unstable_v1 The text_input_unstable_v1 protocol + * @section page_ifaces_text_input_unstable_v1 Interfaces + * - @subpage page_iface_zwp_text_input_v1 - text input + * - @subpage page_iface_zwp_text_input_manager_v1 - text input manager + * @section page_copyright_text_input_unstable_v1 Copyright + * <pre> + * + * Copyright © 2012, 2013 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * </pre> + */ +struct wl_seat; +struct wl_surface; +struct zwp_text_input_manager_v1; +struct zwp_text_input_v1; + +/** + * @page page_iface_zwp_text_input_v1 zwp_text_input_v1 + * @section page_iface_zwp_text_input_v1_desc Description + * + * An object used for text input. Adds support for text input and input + * methods to applications. A text_input object is created from a + * wl_text_input_manager and corresponds typically to a text entry in an + * application. + * + * Requests are used to activate/deactivate the text_input object and set + * state information like surrounding and selected text or the content type. + * The information about entered text is sent to the text_input object via + * the pre-edit and commit events. Using this interface removes the need + * for applications to directly process hardware key events and compose text + * out of them. + * + * Text is generally UTF-8 encoded, indices and lengths are in bytes. + * + * Serials are used to synchronize the state between the text input and + * an input method. New serials are sent by the text input in the + * commit_state request and are used by the input method to indicate + * the known text input state in events like preedit_string, commit_string, + * and keysym. The text input can then ignore events from the input method + * which are based on an outdated state (for example after a reset). + * + * Warning! The protocol described in this file is experimental and + * backward incompatible changes may be made. Backward compatible changes + * may be added together with the corresponding interface version bump. + * Backward incompatible changes are done by bumping the version number in + * the protocol and interface names and resetting the interface version. + * Once the protocol is to be declared stable, the 'z' prefix and the + * version number in the protocol and interface names are removed and the + * interface version number is reset. + * @section page_iface_zwp_text_input_v1_api API + * See @ref iface_zwp_text_input_v1. + */ +/** + * @defgroup iface_zwp_text_input_v1 The zwp_text_input_v1 interface + * + * An object used for text input. Adds support for text input and input + * methods to applications. A text_input object is created from a + * wl_text_input_manager and corresponds typically to a text entry in an + * application. + * + * Requests are used to activate/deactivate the text_input object and set + * state information like surrounding and selected text or the content type. + * The information about entered text is sent to the text_input object via + * the pre-edit and commit events. Using this interface removes the need + * for applications to directly process hardware key events and compose text + * out of them. + * + * Text is generally UTF-8 encoded, indices and lengths are in bytes. + * + * Serials are used to synchronize the state between the text input and + * an input method. New serials are sent by the text input in the + * commit_state request and are used by the input method to indicate + * the known text input state in events like preedit_string, commit_string, + * and keysym. The text input can then ignore events from the input method + * which are based on an outdated state (for example after a reset). + * + * Warning! The protocol described in this file is experimental and + * backward incompatible changes may be made. Backward compatible changes + * may be added together with the corresponding interface version bump. + * Backward incompatible changes are done by bumping the version number in + * the protocol and interface names and resetting the interface version. + * Once the protocol is to be declared stable, the 'z' prefix and the + * version number in the protocol and interface names are removed and the + * interface version number is reset. + */ +extern const struct wl_interface zwp_text_input_v1_interface; +/** + * @page page_iface_zwp_text_input_manager_v1 zwp_text_input_manager_v1 + * @section page_iface_zwp_text_input_manager_v1_desc Description + * + * A factory for text_input objects. This object is a global singleton. + * @section page_iface_zwp_text_input_manager_v1_api API + * See @ref iface_zwp_text_input_manager_v1. + */ +/** + * @defgroup iface_zwp_text_input_manager_v1 The zwp_text_input_manager_v1 interface + * + * A factory for text_input objects. This object is a global singleton. + */ +extern const struct wl_interface zwp_text_input_manager_v1_interface; + +#ifndef ZWP_TEXT_INPUT_V1_CONTENT_HINT_ENUM +#define ZWP_TEXT_INPUT_V1_CONTENT_HINT_ENUM +/** + * @ingroup iface_zwp_text_input_v1 + * content hint + * + * Content hint is a bitmask to allow to modify the behavior of the text + * input. + */ +enum zwp_text_input_v1_content_hint { + /** + * no special behaviour + */ + ZWP_TEXT_INPUT_V1_CONTENT_HINT_NONE = 0x0, + /** + * auto completion, correction and capitalization + */ + ZWP_TEXT_INPUT_V1_CONTENT_HINT_DEFAULT = 0x7, + /** + * hidden and sensitive text + */ + ZWP_TEXT_INPUT_V1_CONTENT_HINT_PASSWORD = 0xc0, + /** + * suggest word completions + */ + ZWP_TEXT_INPUT_V1_CONTENT_HINT_AUTO_COMPLETION = 0x1, + /** + * suggest word corrections + */ + ZWP_TEXT_INPUT_V1_CONTENT_HINT_AUTO_CORRECTION = 0x2, + /** + * switch to uppercase letters at the start of a sentence + */ + ZWP_TEXT_INPUT_V1_CONTENT_HINT_AUTO_CAPITALIZATION = 0x4, + /** + * prefer lowercase letters + */ + ZWP_TEXT_INPUT_V1_CONTENT_HINT_LOWERCASE = 0x8, + /** + * prefer uppercase letters + */ + ZWP_TEXT_INPUT_V1_CONTENT_HINT_UPPERCASE = 0x10, + /** + * prefer casing for titles and headings (can be language dependent) + */ + ZWP_TEXT_INPUT_V1_CONTENT_HINT_TITLECASE = 0x20, + /** + * characters should be hidden + */ + ZWP_TEXT_INPUT_V1_CONTENT_HINT_HIDDEN_TEXT = 0x40, + /** + * typed text should not be stored + */ + ZWP_TEXT_INPUT_V1_CONTENT_HINT_SENSITIVE_DATA = 0x80, + /** + * just latin characters should be entered + */ + ZWP_TEXT_INPUT_V1_CONTENT_HINT_LATIN = 0x100, + /** + * the text input is multiline + */ + ZWP_TEXT_INPUT_V1_CONTENT_HINT_MULTILINE = 0x200, +}; +#endif /* ZWP_TEXT_INPUT_V1_CONTENT_HINT_ENUM */ + +#ifndef ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_ENUM +#define ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_ENUM +/** + * @ingroup iface_zwp_text_input_v1 + * content purpose + * + * The content purpose allows to specify the primary purpose of a text + * input. + * + * This allows an input method to show special purpose input panels with + * extra characters or to disallow some characters. + */ +enum zwp_text_input_v1_content_purpose { + /** + * default input, allowing all characters + */ + ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_NORMAL = 0, + /** + * allow only alphabetic characters + */ + ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_ALPHA = 1, + /** + * allow only digits + */ + ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_DIGITS = 2, + /** + * input a number (including decimal separator and sign) + */ + ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_NUMBER = 3, + /** + * input a phone number + */ + ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_PHONE = 4, + /** + * input an URL + */ + ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_URL = 5, + /** + * input an email address + */ + ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_EMAIL = 6, + /** + * input a name of a person + */ + ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_NAME = 7, + /** + * input a password (combine with password or sensitive_data hint) + */ + ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_PASSWORD = 8, + /** + * input a date + */ + ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_DATE = 9, + /** + * input a time + */ + ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_TIME = 10, + /** + * input a date and time + */ + ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_DATETIME = 11, + /** + * input for a terminal + */ + ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_TERMINAL = 12, +}; +#endif /* ZWP_TEXT_INPUT_V1_CONTENT_PURPOSE_ENUM */ + +#ifndef ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_ENUM +#define ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_ENUM +enum zwp_text_input_v1_preedit_style { + /** + * default style for composing text + */ + ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_DEFAULT = 0, + /** + * style should be the same as in non-composing text + */ + ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_NONE = 1, + ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_ACTIVE = 2, + ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_INACTIVE = 3, + ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_HIGHLIGHT = 4, + ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_UNDERLINE = 5, + ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_SELECTION = 6, + ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_INCORRECT = 7, +}; +#endif /* ZWP_TEXT_INPUT_V1_PREEDIT_STYLE_ENUM */ + +#ifndef ZWP_TEXT_INPUT_V1_TEXT_DIRECTION_ENUM +#define ZWP_TEXT_INPUT_V1_TEXT_DIRECTION_ENUM +enum zwp_text_input_v1_text_direction { + /** + * automatic text direction based on text and language + */ + ZWP_TEXT_INPUT_V1_TEXT_DIRECTION_AUTO = 0, + /** + * left-to-right + */ + ZWP_TEXT_INPUT_V1_TEXT_DIRECTION_LTR = 1, + /** + * right-to-left + */ + ZWP_TEXT_INPUT_V1_TEXT_DIRECTION_RTL = 2, +}; +#endif /* ZWP_TEXT_INPUT_V1_TEXT_DIRECTION_ENUM */ + +/** + * @ingroup iface_zwp_text_input_v1 + * @struct zwp_text_input_v1_interface + */ +struct zwp_text_input_v1_interface { + /** + * request activation + * + * Requests the text_input object to be activated (typically when + * the text entry gets focus). + * + * The seat argument is a wl_seat which maintains the focus for + * this activation. The surface argument is a wl_surface assigned + * to the text_input object and tracked for focus lost. The enter + * event is emitted on successful activation. + */ + void (*activate)(struct wl_client *client, + struct wl_resource *resource, + struct wl_resource *seat, + struct wl_resource *surface); + /** + * request deactivation + * + * Requests the text_input object to be deactivated (typically + * when the text entry lost focus). The seat argument is a wl_seat + * which was used for activation. + */ + void (*deactivate)(struct wl_client *client, + struct wl_resource *resource, + struct wl_resource *seat); + /** + * show input panels + * + * Requests input panels (virtual keyboard) to show. + */ + void (*show_input_panel)(struct wl_client *client, + struct wl_resource *resource); + /** + * hide input panels + * + * Requests input panels (virtual keyboard) to hide. + */ + void (*hide_input_panel)(struct wl_client *client, + struct wl_resource *resource); + /** + * reset + * + * Should be called by an editor widget when the input state + * should be reset, for example after the text was changed outside + * of the normal input method flow. + */ + void (*reset)(struct wl_client *client, + struct wl_resource *resource); + /** + * sets the surrounding text + * + * Sets the plain surrounding text around the input position. + * Text is UTF-8 encoded. Cursor is the byte offset within the + * surrounding text. Anchor is the byte offset of the selection + * anchor within the surrounding text. If there is no selected text + * anchor, then it is the same as cursor. + */ + void (*set_surrounding_text)(struct wl_client *client, + struct wl_resource *resource, + const char *text, + uint32_t cursor, + uint32_t anchor); + /** + * set content purpose and hint + * + * Sets the content purpose and content hint. While the purpose + * is the basic purpose of an input field, the hint flags allow to + * modify some of the behavior. + * + * When no content type is explicitly set, a normal content purpose + * with default hints (auto completion, auto correction, auto + * capitalization) should be assumed. + */ + void (*set_content_type)(struct wl_client *client, + struct wl_resource *resource, + uint32_t hint, + uint32_t purpose); + /** + */ + void (*set_cursor_rectangle)(struct wl_client *client, + struct wl_resource *resource, + int32_t x, + int32_t y, + int32_t width, + int32_t height); + /** + * sets preferred language + * + * Sets a specific language. This allows for example a virtual + * keyboard to show a language specific layout. The "language" + * argument is an RFC-3066 format language tag. + * + * It could be used for example in a word processor to indicate the + * language of the currently edited document or in an instant + * message application which tracks languages of contacts. + */ + void (*set_preferred_language)(struct wl_client *client, + struct wl_resource *resource, + const char *language); + /** + * @param serial used to identify the known state + */ + void (*commit_state)(struct wl_client *client, + struct wl_resource *resource, + uint32_t serial); + /** + */ + void (*invoke_action)(struct wl_client *client, + struct wl_resource *resource, + uint32_t button, + uint32_t index); +}; + +#define ZWP_TEXT_INPUT_V1_ENTER 0 +#define ZWP_TEXT_INPUT_V1_LEAVE 1 +#define ZWP_TEXT_INPUT_V1_MODIFIERS_MAP 2 +#define ZWP_TEXT_INPUT_V1_INPUT_PANEL_STATE 3 +#define ZWP_TEXT_INPUT_V1_PREEDIT_STRING 4 +#define ZWP_TEXT_INPUT_V1_PREEDIT_STYLING 5 +#define ZWP_TEXT_INPUT_V1_PREEDIT_CURSOR 6 +#define ZWP_TEXT_INPUT_V1_COMMIT_STRING 7 +#define ZWP_TEXT_INPUT_V1_CURSOR_POSITION 8 +#define ZWP_TEXT_INPUT_V1_DELETE_SURROUNDING_TEXT 9 +#define ZWP_TEXT_INPUT_V1_KEYSYM 10 +#define ZWP_TEXT_INPUT_V1_LANGUAGE 11 +#define ZWP_TEXT_INPUT_V1_TEXT_DIRECTION 12 + +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_ENTER_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_LEAVE_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_MODIFIERS_MAP_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_INPUT_PANEL_STATE_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_PREEDIT_STRING_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_PREEDIT_STYLING_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_PREEDIT_CURSOR_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_COMMIT_STRING_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_CURSOR_POSITION_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_DELETE_SURROUNDING_TEXT_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_KEYSYM_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_LANGUAGE_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_TEXT_DIRECTION_SINCE_VERSION 1 + +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_ACTIVATE_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_DEACTIVATE_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_SHOW_INPUT_PANEL_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_HIDE_INPUT_PANEL_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_RESET_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_SET_SURROUNDING_TEXT_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_SET_CONTENT_TYPE_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_SET_CURSOR_RECTANGLE_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_SET_PREFERRED_LANGUAGE_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_COMMIT_STATE_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_text_input_v1 + */ +#define ZWP_TEXT_INPUT_V1_INVOKE_ACTION_SINCE_VERSION 1 + +/** + * @ingroup iface_zwp_text_input_v1 + * Sends an enter event to the client owning the resource. + * @param resource_ The client's resource + */ +static inline void +zwp_text_input_v1_send_enter(struct wl_resource *resource_, struct wl_resource *surface) +{ + wl_resource_post_event(resource_, ZWP_TEXT_INPUT_V1_ENTER, surface); +} + +/** + * @ingroup iface_zwp_text_input_v1 + * Sends an leave event to the client owning the resource. + * @param resource_ The client's resource + */ +static inline void +zwp_text_input_v1_send_leave(struct wl_resource *resource_) +{ + wl_resource_post_event(resource_, ZWP_TEXT_INPUT_V1_LEAVE); +} + +/** + * @ingroup iface_zwp_text_input_v1 + * Sends an modifiers_map event to the client owning the resource. + * @param resource_ The client's resource + */ +static inline void +zwp_text_input_v1_send_modifiers_map(struct wl_resource *resource_, struct wl_array *map) +{ + wl_resource_post_event(resource_, ZWP_TEXT_INPUT_V1_MODIFIERS_MAP, map); +} + +/** + * @ingroup iface_zwp_text_input_v1 + * Sends an input_panel_state event to the client owning the resource. + * @param resource_ The client's resource + */ +static inline void +zwp_text_input_v1_send_input_panel_state(struct wl_resource *resource_, uint32_t state) +{ + wl_resource_post_event(resource_, ZWP_TEXT_INPUT_V1_INPUT_PANEL_STATE, state); +} + +/** + * @ingroup iface_zwp_text_input_v1 + * Sends an preedit_string event to the client owning the resource. + * @param resource_ The client's resource + * @param serial serial of the latest known text input state + */ +static inline void +zwp_text_input_v1_send_preedit_string(struct wl_resource *resource_, uint32_t serial, const char *text, const char *commit) +{ + wl_resource_post_event(resource_, ZWP_TEXT_INPUT_V1_PREEDIT_STRING, serial, text, commit); +} + +/** + * @ingroup iface_zwp_text_input_v1 + * Sends an preedit_styling event to the client owning the resource. + * @param resource_ The client's resource + */ +static inline void +zwp_text_input_v1_send_preedit_styling(struct wl_resource *resource_, uint32_t index, uint32_t length, uint32_t style) +{ + wl_resource_post_event(resource_, ZWP_TEXT_INPUT_V1_PREEDIT_STYLING, index, length, style); +} + +/** + * @ingroup iface_zwp_text_input_v1 + * Sends an preedit_cursor event to the client owning the resource. + * @param resource_ The client's resource + */ +static inline void +zwp_text_input_v1_send_preedit_cursor(struct wl_resource *resource_, int32_t index) +{ + wl_resource_post_event(resource_, ZWP_TEXT_INPUT_V1_PREEDIT_CURSOR, index); +} + +/** + * @ingroup iface_zwp_text_input_v1 + * Sends an commit_string event to the client owning the resource. + * @param resource_ The client's resource + * @param serial serial of the latest known text input state + */ +static inline void +zwp_text_input_v1_send_commit_string(struct wl_resource *resource_, uint32_t serial, const char *text) +{ + wl_resource_post_event(resource_, ZWP_TEXT_INPUT_V1_COMMIT_STRING, serial, text); +} + +/** + * @ingroup iface_zwp_text_input_v1 + * Sends an cursor_position event to the client owning the resource. + * @param resource_ The client's resource + */ +static inline void +zwp_text_input_v1_send_cursor_position(struct wl_resource *resource_, int32_t index, int32_t anchor) +{ + wl_resource_post_event(resource_, ZWP_TEXT_INPUT_V1_CURSOR_POSITION, index, anchor); +} + +/** + * @ingroup iface_zwp_text_input_v1 + * Sends an delete_surrounding_text event to the client owning the resource. + * @param resource_ The client's resource + */ +static inline void +zwp_text_input_v1_send_delete_surrounding_text(struct wl_resource *resource_, int32_t index, uint32_t length) +{ + wl_resource_post_event(resource_, ZWP_TEXT_INPUT_V1_DELETE_SURROUNDING_TEXT, index, length); +} + +/** + * @ingroup iface_zwp_text_input_v1 + * Sends an keysym event to the client owning the resource. + * @param resource_ The client's resource + * @param serial serial of the latest known text input state + */ +static inline void +zwp_text_input_v1_send_keysym(struct wl_resource *resource_, uint32_t serial, uint32_t time, uint32_t sym, uint32_t state, uint32_t modifiers) +{ + wl_resource_post_event(resource_, ZWP_TEXT_INPUT_V1_KEYSYM, serial, time, sym, state, modifiers); +} + +/** + * @ingroup iface_zwp_text_input_v1 + * Sends an language event to the client owning the resource. + * @param resource_ The client's resource + * @param serial serial of the latest known text input state + */ +static inline void +zwp_text_input_v1_send_language(struct wl_resource *resource_, uint32_t serial, const char *language) +{ + wl_resource_post_event(resource_, ZWP_TEXT_INPUT_V1_LANGUAGE, serial, language); +} + +/** + * @ingroup iface_zwp_text_input_v1 + * Sends an text_direction event to the client owning the resource. + * @param resource_ The client's resource + * @param serial serial of the latest known text input state + */ +static inline void +zwp_text_input_v1_send_text_direction(struct wl_resource *resource_, uint32_t serial, uint32_t direction) +{ + wl_resource_post_event(resource_, ZWP_TEXT_INPUT_V1_TEXT_DIRECTION, serial, direction); +} + +/** + * @ingroup iface_zwp_text_input_manager_v1 + * @struct zwp_text_input_manager_v1_interface + */ +struct zwp_text_input_manager_v1_interface { + /** + * create text input + * + * Creates a new text_input object. + */ + void (*create_text_input)(struct wl_client *client, + struct wl_resource *resource, + uint32_t id); +}; + + +/** + * @ingroup iface_zwp_text_input_manager_v1 + */ +#define ZWP_TEXT_INPUT_MANAGER_V1_CREATE_TEXT_INPUT_SINCE_VERSION 1 + +#ifdef __cplusplus +} +#endif + +#endif
diff --git a/third_party/wayland-protocols/protocol/text-input-v1-protocol.c b/third_party/wayland-protocols/protocol/text-input-v1-protocol.c new file mode 100644 index 0000000..937d874 --- /dev/null +++ b/third_party/wayland-protocols/protocol/text-input-v1-protocol.c
@@ -0,0 +1,92 @@ +/* Generated by wayland-scanner 1.13.0 */ + +/* + * Copyright © 2012, 2013 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include <stdlib.h> +#include <stdint.h> +#include "wayland-util.h" + +extern const struct wl_interface wl_seat_interface; +extern const struct wl_interface wl_surface_interface; +extern const struct wl_interface zwp_text_input_v1_interface; + +static const struct wl_interface *types[] = { + NULL, + NULL, + NULL, + NULL, + NULL, + &wl_seat_interface, + &wl_surface_interface, + &wl_seat_interface, + &wl_surface_interface, + &zwp_text_input_v1_interface, +}; + +static const struct wl_message zwp_text_input_v1_requests[] = { + { "activate", "oo", types + 5 }, + { "deactivate", "o", types + 7 }, + { "show_input_panel", "", types + 0 }, + { "hide_input_panel", "", types + 0 }, + { "reset", "", types + 0 }, + { "set_surrounding_text", "suu", types + 0 }, + { "set_content_type", "uu", types + 0 }, + { "set_cursor_rectangle", "iiii", types + 0 }, + { "set_preferred_language", "s", types + 0 }, + { "commit_state", "u", types + 0 }, + { "invoke_action", "uu", types + 0 }, +}; + +static const struct wl_message zwp_text_input_v1_events[] = { + { "enter", "o", types + 8 }, + { "leave", "", types + 0 }, + { "modifiers_map", "a", types + 0 }, + { "input_panel_state", "u", types + 0 }, + { "preedit_string", "uss", types + 0 }, + { "preedit_styling", "uuu", types + 0 }, + { "preedit_cursor", "i", types + 0 }, + { "commit_string", "us", types + 0 }, + { "cursor_position", "ii", types + 0 }, + { "delete_surrounding_text", "iu", types + 0 }, + { "keysym", "uuuuu", types + 0 }, + { "language", "us", types + 0 }, + { "text_direction", "uu", types + 0 }, +}; + +WL_EXPORT const struct wl_interface zwp_text_input_v1_interface = { + "zwp_text_input_v1", 1, + 11, zwp_text_input_v1_requests, + 13, zwp_text_input_v1_events, +}; + +static const struct wl_message zwp_text_input_manager_v1_requests[] = { + { "create_text_input", "n", types + 9 }, +}; + +WL_EXPORT const struct wl_interface zwp_text_input_manager_v1_interface = { + "zwp_text_input_manager_v1", 1, + 1, zwp_text_input_manager_v1_requests, + 0, NULL, +}; +
diff --git a/tools/binary_size/libsupersize/models.py b/tools/binary_size/libsupersize/models.py index 9f27e2ad..3126088d 100644 --- a/tools/binary_size/libsupersize/models.py +++ b/tools/binary_size/libsupersize/models.py
@@ -110,13 +110,33 @@ )) +# Relevant for native symbols. All anonymous:: namespaces are removed during +# name normalization. This flag means that the name had one or more anonymous:: +# namespaces stripped from it. FLAG_ANONYMOUS = 1 +# Relevant for .text symbols. The actual symbol name had a "startup." prefix on +# it, which was removed by name normalization. FLAG_STARTUP = 2 +# Relevant for .text symbols. The actual symbol name had a "unlikely." prefix on +# it, which was removed by name normalization. FLAG_UNLIKELY = 4 +# Relevant to .data & .rodata symbols. The actual symbol name had a "rel." +# prefix on it, which was removed by name normalization. FLAG_REL = 8 +# Relevant to .data & .rodata symbols. The actual symbol name had a "rel.local." +# prefix on it, which was removed by name normalization. FLAG_REL_LOCAL = 16 +# The source path did not have the usual "../.." prefix, but instead had a +# prefix of "gen", meaning that the symbol is from a source file that was +# generated during the build (the "gen" prefix is removed during normalization). FLAG_GENERATED_SOURCE = 32 +# Relevant for .text symbols. The actual symbol name had a " [clone .####]" +# suffix, which was removed by name normalization. Cloned symbols are created by +# compiler optimizations (e.g. partial inlining). FLAG_CLONE = 64 +# Relevant for .text symbols. The actual symbol name had a "hot." prefix on it, +# which was removed by name normalization. Occurs when an AFDO profile is +# supplied to the linker. FLAG_HOT = 128
diff --git a/tools/json_schema_compiler/cc_generator.py b/tools/json_schema_compiler/cc_generator.py index ba0a0a8..52df07f 100644 --- a/tools/json_schema_compiler/cc_generator.py +++ b/tools/json_schema_compiler/cc_generator.py
@@ -895,8 +895,8 @@ .Sblock('else {') ) if is_ptr: - c.Append( - '%(dst_var)s.reset(new std::vector<char>(%(src_var)s->GetBlob()));') + c.Append('%(dst_var)s.reset(new std::vector<uint8_t>(' + '%(src_var)s->GetBlob()));') else: c.Append('%(dst_var)s = %(src_var)s->GetBlob();') c.Eblock('}')
diff --git a/tools/json_schema_compiler/cpp_type_generator.py b/tools/json_schema_compiler/cpp_type_generator.py index 4db77507..888f1a7 100644 --- a/tools/json_schema_compiler/cpp_type_generator.py +++ b/tools/json_schema_compiler/cpp_type_generator.py
@@ -112,7 +112,7 @@ item_cpp_type = self.GetCppType(type_.item_type, is_in_container=True) cpp_type = 'std::vector<%s>' % item_cpp_type elif type_.property_type == PropertyType.BINARY: - cpp_type = 'std::vector<char>' + cpp_type = 'std::vector<uint8_t>' else: raise NotImplementedError('Cannot get type of %s' % type_.property_type)
diff --git a/tools/json_schema_compiler/util.cc b/tools/json_schema_compiler/util.cc index 227ad3b..bda985c 100644 --- a/tools/json_schema_compiler/util.cc +++ b/tools/json_schema_compiler/util.cc
@@ -68,7 +68,7 @@ return true; } -bool PopulateItem(const base::Value& from, std::vector<char>* out) { +bool PopulateItem(const base::Value& from, std::vector<uint8_t>* out) { if (!from.is_blob()) return false; *out = from.GetBlob(); @@ -76,7 +76,7 @@ } bool PopulateItem(const base::Value& from, - std::vector<char>* out, + std::vector<uint8_t>* out, base::string16* error) { if (!from.is_blob()) return ReportError(from, base::Value::Type::BINARY, error); @@ -131,8 +131,8 @@ out->AppendString(from); } -void AddItemToList(const std::vector<char>& from, base::ListValue* out) { - out->Append(base::Value::CreateWithCopiedBuffer(from.data(), from.size())); +void AddItemToList(const std::vector<uint8_t>& from, base::ListValue* out) { + out->GetList().emplace_back(from); } void AddItemToList(const std::unique_ptr<base::Value>& from,
diff --git a/tools/json_schema_compiler/util.h b/tools/json_schema_compiler/util.h index 8d206a66..9bee95e 100644 --- a/tools/json_schema_compiler/util.h +++ b/tools/json_schema_compiler/util.h
@@ -30,9 +30,9 @@ bool PopulateItem(const base::Value& from, std::string* out, base::string16* error); -bool PopulateItem(const base::Value& from, std::vector<char>* out); +bool PopulateItem(const base::Value& from, std::vector<uint8_t>* out); bool PopulateItem(const base::Value& from, - std::vector<char>* out, + std::vector<uint8_t>* out, base::string16* error); bool PopulateItem(const base::Value& from, std::unique_ptr<base::Value>* out, @@ -161,7 +161,7 @@ void AddItemToList(const bool from, base::ListValue* out); void AddItemToList(const double from, base::ListValue* out); void AddItemToList(const std::string& from, base::ListValue* out); -void AddItemToList(const std::vector<char>& from, base::ListValue* out); +void AddItemToList(const std::vector<uint8_t>& from, base::ListValue* out); void AddItemToList(const std::unique_ptr<base::Value>& from, base::ListValue* out); void AddItemToList(const std::unique_ptr<base::DictionaryValue>& from,
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index 334f748..14de8d2 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -204,10 +204,13 @@ 'linux-chromium-tests-staging-builder': 'release_bot', 'Mac deterministic': 'release_bot_mac_strip', 'Mac deterministic (dbg)': 'debug_bot', + + 'android-mojo-webview-rel': 'android_release_bot_minimal_symbols_arm64', 'Mojo ChromiumOS': 'chromeos_with_codecs_release_trybot', 'Mojo Android': 'android_release_bot_minimal_symbols_arm64', 'Mojo Linux': 'release_trybot', 'Mojo Windows': 'release_bot_x86_minimal_symbols', + 'Site Isolation Android': 'android_release_bot_minimal_symbols_arm64', 'VR Linux': 'vr_release_bot', 'Win 10 Fast Ring': 'release_trybot',
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 0596c82..8bcdc083 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -19417,6 +19417,7 @@ <int value="2508" label="CSSFillAvailableLogicalHeight"/> <int value="2509" label="PopupOpenWhileFileChooserOpened"/> <int value="2510" label="CookieStoreAPI"/> + <int value="2511" label="FeaturePolicyJSAPI"/> </enum> <enum name="FeedbackSource">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index c3d9756..9c39efb7 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -10163,6 +10163,14 @@ </summary> </histogram> +<histogram name="BrowserServices.ServiceTabResolveInfoQuery" units="ms"> + <owner>peconn@chromium.org</owner> + <summary> + Triggered when an Android background service attempts to create a Tab. We + time how long the Android package manager queryIntentActivities call takes. + </summary> +</histogram> + <histogram name="BrowserServices.TwaOpenTime" units="ms"> <owner>peconn@chromium.org</owner> <summary>
diff --git a/tools/perf/expectations.config b/tools/perf/expectations.config index bdf1621..664a293e 100644 --- a/tools/perf/expectations.config +++ b/tools/perf/expectations.config
@@ -239,25 +239,23 @@ # Benchmark: system_health.common_desktop crbug.com/828917 [ Mac ] system_health.common_desktop/multitab:misc:typical24 [ Skip ] -crbug.com/853188 [ Win ] system_health.common_desktop/browse:news:cnn [ Skip ] crbug.com/649392 [ Win ] system_health.common_desktop/play:media:soundcloud [ Skip ] crbug.com/649392 [ All ] system_health.common_desktop/play:media:google_play_music [ Skip ] crbug.com/773084 [ Mac ] system_health.common_desktop/browse:tools:maps [ Skip ] crbug.com/673775 [ Win ] system_health.common_desktop/browse:search:google [ Skip ] -crbug.com/799106 [ Win ] system_health.common_desktop/browse:media:flickr_infinite_scroll [ Skip ] crbug.com/839411 [ Win ] system_health.common_desktop/browse:social:twitter_infinite_scroll [ Skip ] crbug.com/846022 [ Linux ] system_health.common_desktop/browse:social:twitter_infinite_scroll [ Skip ] # Benchmark: system_health.common_mobile -[ Android_Webview ] system_health.common_mobile/browse:chrome:omnibox [ Skip ] +crbug.com/865464 [ Android_Webview ] system_health.common_mobile/browse:chrome:omnibox [ Skip ] crbug.com/736497 [ Nexus_6 ] system_health.common_mobile/browse:shopping:avito [ Skip ] crbug.com/657433 [ Android ] system_health.common_mobile/load:tools:gmail [ Skip ] crbug.com/714650 [ Android ] system_health.common_mobile/browse:news:globo [ Skip ] crbug.com/728081 [ Android ] system_health.common_mobile/browse:news:toi [ Skip ] -[ Android_Webview ] system_health.common_mobile/long_running:tools:gmail-background [ Skip ] +crbug.com/865466 [ Android_Webview ] system_health.common_mobile/long_running:tools:gmail-background [ Skip ] crbug.com/787001 [ Android_Webview ] system_health.common_mobile/load:media:soundcloud [ Skip ] crbug.com/708300 [ Android ] system_health.common_mobile/browse:shopping:flipkart [ Skip ] -[ Android_Webview ] system_health.common_mobile/browse:chrome:newtab [ Skip ] +crbug.com/865471 [ Android_Webview ] system_health.common_mobile/browse:chrome:newtab [ Skip ] crbug.com/738854 [ Nexus_5X ] system_health.common_mobile/load:tools:drive [ Skip ] crbug.com/738854 [ Android_Webview ] system_health.common_mobile/load:tools:drive [ Skip ] crbug.com/797261 [ Android_Webview ] system_health.common_mobile/load:games:spychase [ Skip ]
diff --git a/ui/aura/mus/window_tree_client.cc b/ui/aura/mus/window_tree_client.cc index 7cc1734..55b4a9ee 100644 --- a/ui/aura/mus/window_tree_client.cc +++ b/ui/aura/mus/window_tree_client.cc
@@ -260,11 +260,10 @@ service_manager::Connector* connector, WindowTreeClientDelegate* delegate, bool create_discardable_memory, - scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, - Config config) { + scoped_refptr<base::SingleThreadTaskRunner> io_task_runner) { std::unique_ptr<WindowTreeClient> wtc( new WindowTreeClient(connector, delegate, nullptr, nullptr, nullptr, - create_discardable_memory, config)); + create_discardable_memory, Config::kMus2)); ui::mojom::WindowTreeFactoryPtr factory; connector->BindInterface(ui::mojom::kServiceName, &factory); ui::mojom::WindowTreePtr window_tree;
diff --git a/ui/aura/mus/window_tree_client.h b/ui/aura/mus/window_tree_client.h index b1cee40..e59d413 100644 --- a/ui/aura/mus/window_tree_client.h +++ b/ui/aura/mus/window_tree_client.h
@@ -141,8 +141,7 @@ service_manager::Connector* connector, WindowTreeClientDelegate* delegate, bool create_discardable_memory = true, - scoped_refptr<base::SingleThreadTaskRunner> io_task_runner = nullptr, - Config config = Config::kMashDeprecated); + scoped_refptr<base::SingleThreadTaskRunner> io_task_runner = nullptr); // Creates a WindowTreeClient such that the Window Service creates a single // WindowTreeHost. This is useful for testing and examples.
diff --git a/ui/base/material_design/material_design_controller.cc b/ui/base/material_design/material_design_controller.cc index 286542d..c698b28 100644 --- a/ui/base/material_design/material_design_controller.cc +++ b/ui/base/material_design/material_design_controller.cc
@@ -7,6 +7,7 @@ #include <string> #include "base/command_line.h" +#include "base/feature_list.h" #include "base/logging.h" #include "base/strings/string_number_conversions.h" #include "base/trace_event/trace_event.h" @@ -38,6 +39,19 @@ namespace ui { namespace { +#if defined(OS_CHROMEOS) || defined(OS_WIN) || defined(OS_LINUX) + +// Whether Material Refresh should be used by default. +// Material refresh is controlled by both --top-chrome-md and this feature. +// --top-chrome-md should take precedence over what this feature may indicate. +bool IsMaterialRefreshEnabled() { + static constexpr base::Feature kMaterialRefreshEnabledFeature = { + "MaterialRefresh", base::FEATURE_ENABLED_BY_DEFAULT}; + return base::FeatureList::IsEnabled(kMaterialRefreshEnabledFeature); +} + +#endif + #if defined(OS_CHROMEOS) // Whether to use MATERIAL_TOUCH_OPTIMIZED when a touch device is detected. @@ -46,9 +60,18 @@ base::FEATURE_ENABLED_BY_DEFAULT}; MaterialDesignController::Mode GetDefaultTouchDeviceMode() { - return base::FeatureList::IsEnabled(kTouchOptimizedUi) - ? MaterialDesignController::MATERIAL_TOUCH_REFRESH - : MaterialDesignController::MATERIAL_REFRESH; + bool material_refresh_enabled = IsMaterialRefreshEnabled(); + bool touch_optimized_ui_enabled = + base::FeatureList::IsEnabled(kTouchOptimizedUi); + if (material_refresh_enabled) { + return touch_optimized_ui_enabled + ? MaterialDesignController::MATERIAL_TOUCH_REFRESH + : MaterialDesignController::MATERIAL_REFRESH; + } + + return touch_optimized_ui_enabled + ? MaterialDesignController::MATERIAL_TOUCH_OPTIMIZED + : MaterialDesignController::MATERIAL_HYBRID; } bool HasTouchscreen() { @@ -178,11 +201,11 @@ if (HasTouchscreen()) return GetDefaultTouchDeviceMode(); - return MATERIAL_REFRESH; + return IsMaterialRefreshEnabled() ? MATERIAL_REFRESH : MATERIAL_NORMAL; #endif // defined(OS_CHROMEOS) #if defined(OS_WIN) || defined(OS_LINUX) - return MATERIAL_REFRESH; + return IsMaterialRefreshEnabled() ? MATERIAL_REFRESH : MATERIAL_NORMAL; #elif defined(OS_MACOSX) && BUILDFLAG(MAC_VIEWS_BROWSER) return features::IsViewsBrowserCocoa() ? MATERIAL_NORMAL : MATERIAL_REFRESH; #else
diff --git a/ui/gfx/color_utils.cc b/ui/gfx/color_utils.cc index ddef32a..f7cf46d 100644 --- a/ui/gfx/color_utils.cc +++ b/ui/gfx/color_utils.cc
@@ -314,6 +314,40 @@ foreground1 : foreground2; } +SkColor GetColorWithMinimumContrast(SkColor default_foreground, + SkColor background) { + DCHECK_EQ(SkColorGetA(default_foreground), SK_AlphaOPAQUE); + + const double background_luminance = GetRelativeLuminance(background); + if (GetContrastRatio(GetRelativeLuminance(default_foreground), + background_luminance) >= kMinimumReadableContrastRatio) { + return default_foreground; + } + + const SkColor blend_direction = + IsDark(background) ? SK_ColorWHITE : g_color_utils_darkest; + // Binary search to find the smallest blend that gives us acceptable contrast. + SkAlpha lower_bound_alpha = SK_AlphaTRANSPARENT; + SkAlpha upper_bound_alpha = SK_AlphaOPAQUE; + SkColor best_color = blend_direction; + constexpr int kCloseEnoughAlphaDelta = 0x04; + while (lower_bound_alpha + kCloseEnoughAlphaDelta < upper_bound_alpha) { + const SkAlpha next_alpha = + gfx::ToCeiledInt((lower_bound_alpha + upper_bound_alpha) / 2.f); + const SkColor next_foreground = + AlphaBlend(blend_direction, default_foreground, next_alpha); + if (GetContrastRatio(GetRelativeLuminance(next_foreground), + background_luminance) < + kMinimumReadableContrastRatio) { + lower_bound_alpha = next_alpha; + } else { + upper_bound_alpha = next_alpha; + best_color = next_foreground; + } + } + return best_color; +} + SkColor InvertColor(SkColor color) { return SkColorSetARGB(SkColorGetA(color), 255 - SkColorGetR(color), 255 - SkColorGetG(color), 255 - SkColorGetB(color));
diff --git a/ui/gfx/color_utils.h b/ui/gfx/color_utils.h index 771edb55..991c498 100644 --- a/ui/gfx/color_utils.h +++ b/ui/gfx/color_utils.h
@@ -23,7 +23,7 @@ // The minimum contrast between text and background that is still readable. // This value is taken from w3c accessibility guidelines. -const double kMinimumReadableContrastRatio = 4.5f; +constexpr double kMinimumReadableContrastRatio = 4.5; // Determines the contrast ratio of two colors or two relative luminance values // (as computed by RelativeLuminance()), calculated according to @@ -125,6 +125,15 @@ SkColor foreground2, SkColor background); +// This function attempts to select a color based on |default_foreground| that +// will meet the minimum contrast ratio when used as a text color on top of +// |background|. If |default_foreground| already meets the minimum contrast +// ratio, this function will simply return it. Otherwise it will blend the color +// darker/lighter until either the contrast ratio is acceptable or the color +// cannot become any more extreme. Only use with opaque colors. +GFX_EXPORT SkColor GetColorWithMinimumContrast(SkColor default_foreground, + SkColor background); + // Invert a color. GFX_EXPORT SkColor InvertColor(SkColor color);
diff --git a/ui/gfx/color_utils_unittest.cc b/ui/gfx/color_utils_unittest.cc index 2a6c9c7..9d4b8d2 100644 --- a/ui/gfx/color_utils_unittest.cc +++ b/ui/gfx/color_utils_unittest.cc
@@ -188,4 +188,37 @@ SetDarkestColor(old_black_color); } +TEST(ColorUtils, GetColorWithMinimumContrast_ForegroundAlreadyMeetsMinimum) { + EXPECT_EQ(SK_ColorBLACK, + GetColorWithMinimumContrast(SK_ColorBLACK, SK_ColorWHITE)); +} + +TEST(ColorUtils, GetColorWithMinimumContrast_BlendDarker) { + const SkColor foreground = SkColorSetRGB(0xAA, 0xAA, 0xAA); + const SkColor result = GetColorWithMinimumContrast(foreground, SK_ColorWHITE); + EXPECT_NE(foreground, result); + EXPECT_GE(GetContrastRatio(result, SK_ColorWHITE), + kMinimumReadableContrastRatio); +} + +TEST(ColorUtils, GetColorWithMinimumContrast_BlendLighter) { + const SkColor foreground = SkColorSetRGB(0x33, 0x33, 0x33); + const SkColor result = GetColorWithMinimumContrast(foreground, SK_ColorBLACK); + EXPECT_NE(foreground, result); + EXPECT_GE(GetContrastRatio(result, SK_ColorBLACK), + kMinimumReadableContrastRatio); +} + +TEST(ColorUtils, GetColorWithMinimumContrast_StopsAtDarkestColor) { + SkColor old_black_color = GetDarkestColorForTesting(); + + const SkColor darkest_color = SkColorSetRGB(0x44, 0x44, 0x44); + SetDarkestColor(darkest_color); + EXPECT_EQ(darkest_color, + GetColorWithMinimumContrast(SkColorSetRGB(0x55, 0x55, 0x55), + SkColorSetRGB(0xAA, 0xAA, 0xAA))); + + SetDarkestColor(old_black_color); +} + } // namespace color_utils
diff --git a/ui/gfx/gpu_memory_buffer.cc b/ui/gfx/gpu_memory_buffer.cc index ad32c87e..e6751d8 100644 --- a/ui/gfx/gpu_memory_buffer.cc +++ b/ui/gfx/gpu_memory_buffer.cc
@@ -4,19 +4,14 @@ #include "ui/gfx/gpu_memory_buffer.h" -#include "base/process/process_handle.h" #include "ui/gfx/generic_shared_memory_id.h" -#if defined(OS_WIN) -#include <windows.h> -#elif defined(OS_ANDROID) -#include "base/android/android_hardware_buffer_compat.h" -#endif - namespace gfx { GpuMemoryBufferHandle::GpuMemoryBufferHandle() : type(EMPTY_BUFFER), id(0) {} +// TODO(crbug.com/863011): Reset |type| and possibly the handles on the +// moved-from object. GpuMemoryBufferHandle::GpuMemoryBufferHandle(GpuMemoryBufferHandle&& other) = default; @@ -27,74 +22,4 @@ void GpuMemoryBuffer::SetColorSpace(const gfx::ColorSpace& color_space) {} -GpuMemoryBufferHandle CloneHandleForIPC( - const GpuMemoryBufferHandle& source_handle) { - switch (source_handle.type) { - case gfx::EMPTY_BUFFER: - NOTREACHED(); - return gfx::GpuMemoryBufferHandle(); - case gfx::SHARED_MEMORY_BUFFER: { - gfx::GpuMemoryBufferHandle handle; - handle.type = gfx::SHARED_MEMORY_BUFFER; - handle.id = source_handle.id; - handle.handle = base::SharedMemory::DuplicateHandle(source_handle.handle); - handle.offset = source_handle.offset; - handle.stride = source_handle.stride; - return handle; - } - case gfx::NATIVE_PIXMAP: { - gfx::GpuMemoryBufferHandle handle; - handle.type = gfx::NATIVE_PIXMAP; - handle.id = source_handle.id; -#if defined(OS_LINUX) - handle.native_pixmap_handle = - gfx::CloneHandleForIPC(source_handle.native_pixmap_handle); -#endif - return handle; - } - case gfx::ANDROID_HARDWARE_BUFFER: { - gfx::GpuMemoryBufferHandle handle; - handle.type = gfx::ANDROID_HARDWARE_BUFFER; - handle.id = source_handle.id; -#if defined(OS_ANDROID) - base::AndroidHardwareBufferCompat::GetInstance().Acquire( - source_handle.android_hardware_buffer); - handle.android_hardware_buffer = source_handle.android_hardware_buffer; -#endif - return handle; - } - case gfx::IO_SURFACE_BUFFER: { - gfx::GpuMemoryBufferHandle handle; - handle.type = gfx::IO_SURFACE_BUFFER; - handle.id = source_handle.id; -#if defined(OS_MACOSX) && !defined(OS_IOS) - handle.mach_port = source_handle.mach_port; -#endif - return handle; - } - case gfx::DXGI_SHARED_HANDLE: - gfx::GpuMemoryBufferHandle handle; - handle.type = gfx::DXGI_SHARED_HANDLE; - handle.id = source_handle.id; -#if defined(OS_WIN) - base::ProcessHandle process = ::GetCurrentProcess(); - HANDLE duplicated_handle; - BOOL result = ::DuplicateHandle( - process, source_handle.dxgi_handle.GetHandle(), process, - &duplicated_handle, 0, FALSE, DUPLICATE_SAME_ACCESS); - if (!result) - DPLOG(ERROR) << "Failed to duplicate DXGI resource handle."; - handle.dxgi_handle = IPC::PlatformFileForTransit(duplicated_handle); -#endif - return handle; - } - return gfx::GpuMemoryBufferHandle(); -} - -base::trace_event::MemoryAllocatorDumpGuid GpuMemoryBuffer::GetGUIDForTracing( - uint64_t tracing_process_id) const { - return gfx::GetGenericSharedGpuMemoryGUIDForTracing(tracing_process_id, - GetId()); -} - } // namespace gfx
diff --git a/ui/gfx/gpu_memory_buffer.h b/ui/gfx/gpu_memory_buffer.h index 4b2b1c3..9e77c08 100644 --- a/ui/gfx/gpu_memory_buffer.h +++ b/ui/gfx/gpu_memory_buffer.h
@@ -9,7 +9,6 @@ #include <stdint.h> #include "base/memory/shared_memory.h" -#include "base/trace_event/memory_allocator_dump_guid.h" #include "build/build_config.h" #include "ui/gfx/buffer_types.h" #include "ui/gfx/generic_shared_memory_id.h" @@ -22,13 +21,18 @@ #include "ui/gfx/mac/io_surface.h" #elif defined(OS_WIN) #include "ipc/ipc_platform_file.h" // nogncheck +#elif defined(OS_ANDROID) +#include "base/android/scoped_hardware_buffer_handle.h" #endif extern "C" typedef struct _ClientBuffer* ClientBuffer; -#if defined(OS_ANDROID) -extern "C" typedef struct AHardwareBuffer AHardwareBuffer; -#endif +namespace base { +namespace trace_event { +class ProcessMemoryDump; +class MemoryAllocatorDumpGuid; +} // namespace trace_event +} // namespace base namespace gfx { @@ -46,6 +50,9 @@ using GpuMemoryBufferId = GenericSharedMemoryId; +// TODO(crbug.com/863011): Convert this to a proper class to ensure the state is +// always consistent, particularly that the only one handle is set at the same +// time and it corresponds to |type|. struct GFX_EXPORT GpuMemoryBufferHandle { GpuMemoryBufferHandle(); GpuMemoryBufferHandle(GpuMemoryBufferHandle&& other); @@ -54,17 +61,20 @@ bool is_null() const { return type == EMPTY_BUFFER; } GpuMemoryBufferType type; GpuMemoryBufferId id; + // TODO(crbug.com/863011): convert this to a scoped handle. base::SharedMemoryHandle handle; uint32_t offset; int32_t stride; #if defined(OS_LINUX) + // TODO(crbug.com/863011): convert this to a scoped handle. NativePixmapHandle native_pixmap_handle; #elif defined(OS_MACOSX) && !defined(OS_IOS) ScopedRefCountedIOSurfaceMachPort mach_port; #elif defined(OS_WIN) + // TODO(crbug.com/863011): convert this to a scoped handle. IPC::PlatformFileForTransit dxgi_handle; #elif defined(OS_ANDROID) - AHardwareBuffer* android_hardware_buffer = nullptr; + base::android::ScopedHardwareBufferHandle android_hardware_buffer; #endif }; @@ -106,23 +116,29 @@ // Returns a unique identifier associated with buffer. virtual GpuMemoryBufferId GetId() const = 0; - // Returns a platform specific handle for this buffer. - virtual GpuMemoryBufferHandle GetHandle() const = 0; + // Returns the type of this buffer. + virtual GpuMemoryBufferType GetType() const = 0; + + // Returns a platform specific handle for this buffer which in particular can + // be sent over IPC. This duplicates file handles as appropriate, so that a + // caller takes ownership of the returned handle. + virtual GpuMemoryBufferHandle CloneHandle() const = 0; // Type-checking downcast routine. virtual ClientBuffer AsClientBuffer() = 0; - // Returns the GUID for tracing. - virtual base::trace_event::MemoryAllocatorDumpGuid GetGUIDForTracing( - uint64_t tracing_process_id) const; + // Dumps information about the memory backing the GpuMemoryBuffer to |pmd|. + // The memory usage is attributed to |buffer_dump_guid|. + // |tracing_process_id| uniquely identifies the process owning the memory. + // |importance| is relevant only for the cases of co-ownership, the memory + // gets attributed to the owner with the highest importance. + virtual void OnMemoryDump( + base::trace_event::ProcessMemoryDump* pmd, + const base::trace_event::MemoryAllocatorDumpGuid& buffer_dump_guid, + uint64_t tracing_process_id, + int importance) const = 0; }; -// Returns an instance of |handle| which can be sent over IPC. This duplicates -// the file-handles as appropriate, so that the IPC code take ownership of them, -// without invalidating |handle| itself. -GFX_EXPORT GpuMemoryBufferHandle -CloneHandleForIPC(const GpuMemoryBufferHandle& handle); - } // namespace gfx #endif // UI_GFX_GPU_MEMORY_BUFFER_H_
diff --git a/ui/gfx/mojo/buffer_types_struct_traits.cc b/ui/gfx/mojo/buffer_types_struct_traits.cc index ddeeee4..534c7f9 100644 --- a/ui/gfx/mojo/buffer_types_struct_traits.cc +++ b/ui/gfx/mojo/buffer_types_struct_traits.cc
@@ -108,14 +108,10 @@ gfx::mojom::AHardwareBufferHandlePtr StructTraits<gfx::mojom::GpuMemoryBufferHandleDataView, gfx::GpuMemoryBufferHandle>:: - android_hardware_buffer_handle(const gfx::GpuMemoryBufferHandle& handle) { + android_hardware_buffer_handle(gfx::GpuMemoryBufferHandle& handle) { if (handle.type != gfx::ANDROID_HARDWARE_BUFFER) return nullptr; - // Assume ownership of the input AHardwareBuffer. - auto scoped_handle = base::android::ScopedHardwareBufferHandle::Adopt( - handle.android_hardware_buffer); - // We must keep a ref to the AHardwareBuffer alive until the receiver has // acquired its own reference. We do this by sending a message pipe handle // along with the buffer. When the receiver deserializes (or even if they @@ -124,12 +120,12 @@ mojo::MessagePipe tracking_pipe; auto wrapped_handle = gfx::mojom::AHardwareBufferHandle::New( mojo::WrapPlatformFile( - scoped_handle.SerializeAsFileDescriptor().release()), + handle.android_hardware_buffer.SerializeAsFileDescriptor().release()), std::move(tracking_pipe.handle0)); // Pass ownership of the input handle to our tracking pipe to keep the AHB // alive until it's deserialized. - mojo::ScopeToMessagePipe(std::move(scoped_handle), + mojo::ScopeToMessagePipe(std::move(handle.android_hardware_buffer), std::move(tracking_pipe.handle1)); return wrapped_handle; } @@ -193,10 +189,8 @@ base::ScopedFD scoped_fd(fd); if (unwrap_result != MOJO_RESULT_OK || !scoped_fd.is_valid()) return false; - out->android_hardware_buffer = - base::android::ScopedHardwareBufferHandle :: - DeserializeFromFileDescriptor(std::move(scoped_fd)) - .Take(); + out->android_hardware_buffer = base::android::ScopedHardwareBufferHandle:: + DeserializeFromFileDescriptor(std::move(scoped_fd)); out->offset = data.offset(); out->stride = data.stride(); }
diff --git a/ui/gfx/mojo/buffer_types_struct_traits.h b/ui/gfx/mojo/buffer_types_struct_traits.h index ce615b3..33069bc2 100644 --- a/ui/gfx/mojo/buffer_types_struct_traits.h +++ b/ui/gfx/mojo/buffer_types_struct_traits.h
@@ -339,7 +339,7 @@ #if defined(OS_ANDROID) static gfx::mojom::AHardwareBufferHandlePtr android_hardware_buffer_handle( - const gfx::GpuMemoryBufferHandle& handle); + gfx::GpuMemoryBufferHandle& handle); #endif static bool Read(gfx::mojom::GpuMemoryBufferHandleDataView data,
diff --git a/ui/message_center/views/proportional_image_view.h b/ui/message_center/views/proportional_image_view.h index 1790aaa..d0d28904 100644 --- a/ui/message_center/views/proportional_image_view.h +++ b/ui/message_center/views/proportional_image_view.h
@@ -27,6 +27,8 @@ void SetImage(const gfx::ImageSkia& image, const gfx::Size& max_image_size); + const gfx::ImageSkia& image() const { return image_; } + // Overridden from views::View: void OnPaint(gfx::Canvas* canvas) override; const char* GetClassName() const override;
diff --git a/ui/views/mus/aura_init.cc b/ui/views/mus/aura_init.cc index 56b6c3c..c6c4966e 100644 --- a/ui/views/mus/aura_init.cc +++ b/ui/views/mus/aura_init.cc
@@ -46,19 +46,13 @@ bool AuraInit::Init(const InitParams& params) { env_ = aura::Env::CreateInstance(aura::Env::Mode::MUS); - if (params.mode == Mode::AURA_MUS || params.mode == Mode::AURA_MUS2) { - MusClient::InitParams mus_params; - mus_params.connector = params.connector; - mus_params.identity = params.identity; - mus_params.io_task_runner = params.io_task_runner; - mus_params.wtc_config = - params.mode == Mode::AURA_MUS2 - ? aura::WindowTreeClient::Config::kMus2 - : aura::WindowTreeClient::Config::kMashDeprecated; - mus_params.create_wm_state = true; - mus_params.use_accessibility_host = params.use_accessibility_host; - mus_client_ = std::make_unique<MusClient>(mus_params); - } + MusClient::InitParams mus_params; + mus_params.connector = params.connector; + mus_params.identity = params.identity; + mus_params.io_task_runner = params.io_task_runner; + mus_params.create_wm_state = true; + mus_params.use_accessibility_host = params.use_accessibility_host; + mus_client_ = std::make_unique<MusClient>(mus_params); // MaterialDesignController may have initialized already (such as happens // in the utility process). if (!ui::MaterialDesignController::is_mode_initialized())
diff --git a/ui/views/mus/aura_init.h b/ui/views/mus/aura_init.h index c821dea..dad4d1f 100644 --- a/ui/views/mus/aura_init.h +++ b/ui/views/mus/aura_init.h
@@ -33,20 +33,6 @@ // |resource_file| is the path to the apk file containing the resources. class VIEWS_MUS_EXPORT AuraInit { public: - // TODO(sky): remove Mode. https://crbug.com/842365. - enum class Mode { - // Indicates AuraInit should target using aura with mus. This is deprecated. - AURA_MUS, - - // Indicates AuraInit should target using aura with mus, for a Window - // Manager client. This is deprecated. - AURA_MUS_WINDOW_MANAGER, - - // Targets ws2. Mode will eventually be removed entirely and this will be - // the default. - AURA_MUS2, - }; - ~AuraInit(); struct VIEWS_MUS_EXPORT InitParams { @@ -59,7 +45,6 @@ // File for 2x icons. Can be empty. std::string resource_file_200; scoped_refptr<base::SingleThreadTaskRunner> io_task_runner = nullptr; - Mode mode = Mode::AURA_MUS; bool register_path_provider = true; // When true the client application will connect to the accessibility host // in the browser to supply AX node trees and handle AX actions (e.g. to @@ -72,7 +57,6 @@ // unusable state, and calling services should shutdown. static std::unique_ptr<AuraInit> Create(const InitParams& params); - // Only valid if Mode::AURA_MUS was passed to constructor. MusClient* mus_client() { return mus_client_.get(); } private:
diff --git a/ui/views/mus/ax_remote_host.cc b/ui/views/mus/ax_remote_host.cc index bc1d4ed..d992c37 100644 --- a/ui/views/mus/ax_remote_host.cc +++ b/ui/views/mus/ax_remote_host.cc
@@ -11,6 +11,7 @@ #include "ui/accessibility/ax_enums.mojom.h" #include "ui/accessibility/ax_event.h" #include "ui/accessibility/platform/ax_unique_id.h" +#include "ui/aura/mus/window_tree_client.h" #include "ui/aura/window.h" #include "ui/views/accessibility/ax_aura_obj_wrapper.h" #include "ui/views/mus/ax_tree_source_mus.h"
diff --git a/ui/views/mus/mus_client.cc b/ui/views/mus/mus_client.cc index 09eb2fc..f4f36ac 100644 --- a/ui/views/mus/mus_client.cc +++ b/ui/views/mus/mus_client.cc
@@ -20,6 +20,7 @@ #include "ui/aura/mus/capture_synchronizer.h" #include "ui/aura/mus/mus_context_factory.h" #include "ui/aura/mus/property_converter.h" +#include "ui/aura/mus/window_tree_client.h" #include "ui/aura/mus/window_tree_host_mus.h" #include "ui/aura/mus/window_tree_host_mus_init_params.h" #include "ui/aura/window.h" @@ -112,8 +113,7 @@ DCHECK(io_task_runner); owned_window_tree_client_ = aura::WindowTreeClient::CreateForWindowTreeFactory( - connector, this, true, std::move(io_task_runner), - params.wtc_config); + connector, this, true, std::move(io_task_runner)); window_tree_client_ = owned_window_tree_client_.get(); aura::Env::GetInstance()->SetWindowTreeClient(window_tree_client_); } else { @@ -130,10 +130,7 @@ input_device_client_->Connect(std::move(input_device_server)); screen_ = std::make_unique<ScreenMus>(this); - if (params.wtc_config == aura::WindowTreeClient::Config::kMashDeprecated) - screen_->InitDeprecated(connector); - else - window_tree_client_->WaitForDisplays(); + window_tree_client_->WaitForDisplays(); ui::mojom::ClipboardHostPtr clipboard_host_ptr; connector->BindInterface(ui::mojom::kServiceName, &clipboard_host_ptr);
diff --git a/ui/views/mus/mus_client.h b/ui/views/mus/mus_client.h index cb3d6b6..d641fcd 100644 --- a/ui/views/mus/mus_client.h +++ b/ui/views/mus/mus_client.h
@@ -15,7 +15,6 @@ #include "services/service_manager/public/cpp/identity.h" #include "services/ui/public/interfaces/event_injector.mojom.h" #include "ui/aura/client/capture_client.h" -#include "ui/aura/mus/window_tree_client.h" #include "ui/aura/mus/window_tree_client_delegate.h" #include "ui/views/mus/mus_export.h" #include "ui/views/mus/screen_mus_delegate.h" @@ -68,15 +67,13 @@ InitParams(); ~InitParams(); - // Production code should provide |connector|, |identity|, |wtc_config| - // and an |io_task_runner| if the process already has one. Test code may - // skip these parameters (e.g. a unit test that does not need to connect - // to the window service does not need to provide a connector). + // Production code should provide |connector|, |identity|, and an + // |io_task_runner| if the process already has one. Test code may skip these + // parameters (e.g. a unit test that does not need to connect to the window + // service does not need to provide a connector). service_manager::Connector* connector = nullptr; service_manager::Identity identity; scoped_refptr<base::SingleThreadTaskRunner> io_task_runner = nullptr; - aura::WindowTreeClient::Config wtc_config = - aura::WindowTreeClient::Config::kMashDeprecated; // Create a wm::WMState. Some processes (e.g. the browser) may already // have one.
diff --git a/ui/views/mus/mus_views_delegate.cc b/ui/views/mus/mus_views_delegate.cc index 927c065e..e383ac00 100644 --- a/ui/views/mus/mus_views_delegate.cc +++ b/ui/views/mus/mus_views_delegate.cc
@@ -15,8 +15,7 @@ void MusViewsDelegate::NotifyAccessibilityEvent(View* view, ax::mojom::Event event_type) { - // Null in AuraInit::Mode::AURA_MUS_WINDOW_MANAGER which is used in mash. - if (MusClient::Get() && MusClient::Get()->ax_remote_host()) + if (MusClient::Get()->ax_remote_host()) MusClient::Get()->ax_remote_host()->HandleEvent(view, event_type); }
diff --git a/ui/views/mus/screen_mus.cc b/ui/views/mus/screen_mus.cc index 1238f81a..e05c1087 100644 --- a/ui/views/mus/screen_mus.cc +++ b/ui/views/mus/screen_mus.cc
@@ -5,8 +5,6 @@ #include "ui/views/mus/screen_mus.h" #include "base/stl_util.h" -#include "services/service_manager/public/cpp/connector.h" -#include "services/ui/public/interfaces/constants.mojom.h" #include "ui/aura/env.h" #include "ui/aura/mus/window_tree_host_mus.h" #include "ui/aura/window.h" @@ -36,8 +34,7 @@ using Type = display::DisplayList::Type; -ScreenMus::ScreenMus(ScreenMusDelegate* delegate) - : delegate_(delegate), screen_provider_observer_binding_(this) { +ScreenMus::ScreenMus(ScreenMusDelegate* delegate) : delegate_(delegate) { DCHECK(delegate); display::Screen::SetScreenInstance(this); } @@ -47,31 +44,6 @@ display::Screen::SetScreenInstance(nullptr); } -void ScreenMus::InitDeprecated(service_manager::Connector* connector) { - connector->BindInterface(ui::mojom::kServiceName, &screen_provider_); - - ui::mojom::ScreenProviderObserverPtr observer; - screen_provider_observer_binding_.Bind(mojo::MakeRequest(&observer)); - screen_provider_->AddObserver(std::move(observer)); - - // We need the set of displays before we can continue. Wait for it. - // - // TODO(rockot): Do something better here. This should not have to block tasks - // from running on the calling thread. http://crbug.com/594852. - bool success = screen_provider_observer_binding_.WaitForIncomingMethodCall(); - - // The WaitForIncomingMethodCall() should have supplied the set of Displays, - // unless mus is going down, in which case encountered_error() is true, or the - // call to WaitForIncomingMethodCall() failed. - if (display_list().displays().empty()) { - DCHECK(screen_provider_.encountered_error() || !success); - // In this case we install a default display and assume the process is - // going to exit shortly so that the real value doesn't matter. - display_list().AddDisplay( - display::Display(0xFFFFFFFF, gfx::Rect(0, 0, 801, 802)), Type::PRIMARY); - } -} - void ScreenMus::OnDisplaysChanged( std::vector<ui::mojom::WsDisplayPtr> ws_displays, int64_t primary_display_id,
diff --git a/ui/views/mus/screen_mus.h b/ui/views/mus/screen_mus.h index ad94f9f1..2ab3ff95 100644 --- a/ui/views/mus/screen_mus.h +++ b/ui/views/mus/screen_mus.h
@@ -5,15 +5,10 @@ #ifndef UI_VIEWS_MUS_SCREEN_MUS_H_ #define UI_VIEWS_MUS_SCREEN_MUS_H_ -#include "mojo/public/cpp/bindings/binding.h" #include "services/ui/public/interfaces/screen_provider.mojom.h" #include "ui/display/screen_base.h" #include "ui/views/mus/mus_export.h" -namespace service_manager { -class Connector; -} - namespace views { class ScreenMusDelegate; @@ -25,9 +20,6 @@ explicit ScreenMus(ScreenMusDelegate* delegate); ~ScreenMus() override; - // TODO(sky): not used with ws2. Remove. https://crbug.com/842365. - void InitDeprecated(service_manager::Connector* connector); - // ui::mojom::ScreenProviderObserver: void OnDisplaysChanged(std::vector<ui::mojom::WsDisplayPtr> ws_displays, int64_t primary_display_id, @@ -44,9 +36,6 @@ aura::Window* GetWindowAtScreenPoint(const gfx::Point& point) override; ScreenMusDelegate* delegate_; - ui::mojom::ScreenProviderPtr screen_provider_; - mojo::Binding<ui::mojom::ScreenProviderObserver> - screen_provider_observer_binding_; DISALLOW_COPY_AND_ASSIGN(ScreenMus); };
diff --git a/ui/views/mus/views_mus_test_suite.cc b/ui/views/mus/views_mus_test_suite.cc index 959f5ad..8bc2f83 100644 --- a/ui/views/mus/views_mus_test_suite.cc +++ b/ui/views/mus/views_mus_test_suite.cc
@@ -104,7 +104,6 @@ params.connector = GetConnector(); params.identity = service_manager_identity_; params.bind_test_ws_interfaces = true; - params.wtc_config = aura::WindowTreeClient::Config::kMus2; return std::make_unique<MusClient>(params); }
diff --git a/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.js b/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.js index cb48a9f..2836da8 100644 --- a/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.js +++ b/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.js
@@ -198,6 +198,10 @@ * @private */ onNativeDialogClose_: function(e) { + // Ignore any 'close' events not fired directly by the <dialog> element. + if (e.target !== this.getNative()) + return; + // TODO(dpapad): This is necessary to make the code work both for Polymer 1 // and Polymer 2. Remove once migration to Polymer 2 is completed. e.stopPropagation();
diff --git a/ui/webui/resources/cr_elements/icons.html b/ui/webui/resources/cr_elements/icons.html index 6bb386e1..47927f9 100644 --- a/ui/webui/resources/cr_elements/icons.html +++ b/ui/webui/resources/cr_elements/icons.html
@@ -28,8 +28,10 @@ --> <g id="account-child-invert" viewBox="0 0 48 48"><path d="M24 4c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6 2.69-6 6-6z"></path><path fill="none" d="M0 0h48v48H0V0z"></path><circle fill="none" cx="24" cy="26" r="4"></circle><path d="M24 18c-6.16 0-13 3.12-13 7.23v11.54c0 2.32 2.19 4.33 5.2 5.63 2.32 1 5.12 1.59 7.8 1.59.66 0 1.33-.06 2-.14v-5.2c-.67.08-1.34.14-2 .14-2.63 0-5.39-.57-7.68-1.55.67-2.12 4.34-3.65 7.68-3.65.86 0 1.75.11 2.6.29 2.79.62 5.2 2.15 5.2 4.04v4.47c3.01-1.31 5.2-3.31 5.2-5.63V25.23C37 21.12 30.16 18 24 18zm0 12c-2.21 0-4-1.79-4-4s1.79-4 4-4 4 1.79 4 4-1.79 4-4 4z"></path></g> <g id="add"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/></g> + <g id="arrow-back"><path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z"></path></g> <g id="arrow-drop-up"><path d="M7 14l5-5 5 5z"></g> <g id="arrow-drop-down"><path d="M7 10l5 5 5-5z"></path></g> + <g id="arrow-forward"><path d="M12 4l-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8z"></path></g> <if expr="chromeos"> <g id="bluetooth"><path d="M17.71 7.71L12 2h-1v7.59L6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 11 14.41V22h1l5.71-5.71-4.3-4.29 4.3-4.29zM13 5.83l1.88 1.88L13 9.59V5.83zm1.88 10.46L13 18.17v-3.76l1.88 1.88z"></path></g> <g id="camera-alt"><circle cx="12" cy="12" r="3.2"></circle><path d="M9 2L7.17 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2h-3.17L15 2H9zm3 15c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5z"></path></g>
diff --git a/ui/webui/resources/js/cr/ui/focus_without_ink.js b/ui/webui/resources/js/cr/ui/focus_without_ink.js index 8a9f07315..ed5c00fe 100644 --- a/ui/webui/resources/js/cr/ui/focus_without_ink.js +++ b/ui/webui/resources/js/cr/ui/focus_without_ink.js
@@ -28,7 +28,8 @@ var focusWithoutInk = function(toFocus) { var innerButton = null; - if (toFocus.parentElement.tagName == 'PAPER-ICON-BUTTON-LIGHT') { + if (toFocus.parentElement && + toFocus.parentElement.tagName == 'PAPER-ICON-BUTTON-LIGHT') { innerButton = toFocus; toFocus = toFocus.parentElement; }