Cleanup/ remove unwanted duplicated option on tabs.json
[chromium-blink-merge.git] / ash / drag_drop / drag_drop_controller_unittest.cc
blob20513e1f0491adb5a6abdc5d59d75657cd7e2b3d
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ash/drag_drop/drag_drop_controller.h"
7 #include "ash/drag_drop/drag_drop_tracker.h"
8 #include "ash/drag_drop/drag_image_view.h"
9 #include "ash/shell.h"
10 #include "ash/test/ash_test_base.h"
11 #include "base/command_line.h"
12 #include "base/location.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "ui/aura/client/capture_client.h"
15 #include "ui/aura/window_event_dispatcher.h"
16 #include "ui/aura/window_tree_host.h"
17 #include "ui/base/clipboard/clipboard.h"
18 #include "ui/base/clipboard/scoped_clipboard_writer.h"
19 #include "ui/base/dragdrop/drag_drop_types.h"
20 #include "ui/base/dragdrop/drag_utils.h"
21 #include "ui/base/dragdrop/os_exchange_data.h"
22 #include "ui/base/ui_base_switches.h"
23 #include "ui/events/event.h"
24 #include "ui/events/event_utils.h"
25 #include "ui/events/gesture_detection/gesture_configuration.h"
26 #include "ui/events/gestures/gesture_types.h"
27 #include "ui/events/test/event_generator.h"
28 #include "ui/events/test/events_test_utils.h"
29 #include "ui/gfx/animation/linear_animation.h"
30 #include "ui/gfx/image/image_skia_rep.h"
31 #include "ui/views/view.h"
32 #include "ui/views/widget/native_widget_aura.h"
33 #include "ui/views/widget/native_widget_delegate.h"
34 #include "ui/views/widget/widget.h"
36 namespace ash {
37 namespace test {
39 namespace {
41 // A simple view that makes sure RunShellDrag is invoked on mouse drag.
42 class DragTestView : public views::View {
43 public:
44 DragTestView() : views::View() {
45 Reset();
48 void Reset() {
49 num_drag_enters_ = 0;
50 num_drag_exits_ = 0;
51 num_drag_updates_ = 0;
52 num_drops_ = 0;
53 drag_done_received_ = false;
54 long_tap_received_ = false;
57 int VerticalDragThreshold() {
58 return views::View::GetVerticalDragThreshold();
61 int HorizontalDragThreshold() {
62 return views::View::GetHorizontalDragThreshold();
65 int num_drag_enters_;
66 int num_drag_exits_;
67 int num_drag_updates_;
68 int num_drops_;
69 bool drag_done_received_;
70 bool long_tap_received_;
72 private:
73 // View overrides:
74 int GetDragOperations(const gfx::Point& press_pt) override {
75 return ui::DragDropTypes::DRAG_COPY;
78 void WriteDragData(const gfx::Point& p, OSExchangeData* data) override {
79 data->SetString(base::UTF8ToUTF16("I am being dragged"));
80 gfx::ImageSkiaRep image_rep(gfx::Size(10, 20), 1.0f);
81 gfx::ImageSkia image_skia(image_rep);
83 drag_utils::SetDragImageOnDataObject(image_skia, gfx::Vector2d(), data);
86 bool OnMousePressed(const ui::MouseEvent& event) override { return true; }
88 void OnGestureEvent(ui::GestureEvent* event) override {
89 if (event->type() == ui::ET_GESTURE_LONG_TAP)
90 long_tap_received_ = true;
91 return;
94 bool GetDropFormats(
95 int* formats,
96 std::set<OSExchangeData::CustomFormat>* custom_formats) override {
97 *formats = ui::OSExchangeData::STRING;
98 return true;
101 bool CanDrop(const OSExchangeData& data) override { return true; }
103 void OnDragEntered(const ui::DropTargetEvent& event) override {
104 num_drag_enters_++;
107 int OnDragUpdated(const ui::DropTargetEvent& event) override {
108 num_drag_updates_++;
109 return ui::DragDropTypes::DRAG_COPY;
112 void OnDragExited() override { num_drag_exits_++; }
114 int OnPerformDrop(const ui::DropTargetEvent& event) override {
115 num_drops_++;
116 return ui::DragDropTypes::DRAG_COPY;
119 void OnDragDone() override { drag_done_received_ = true; }
121 DISALLOW_COPY_AND_ASSIGN(DragTestView);
124 class CompletableLinearAnimation : public gfx::LinearAnimation {
125 public:
126 CompletableLinearAnimation(int duration,
127 int frame_rate,
128 gfx::AnimationDelegate* delegate)
129 : gfx::LinearAnimation(duration, frame_rate, delegate),
130 duration_(duration) {
133 void Complete() {
134 Step(start_time() + base::TimeDelta::FromMilliseconds(duration_));
137 private:
138 int duration_;
141 class TestDragDropController : public DragDropController {
142 public:
143 TestDragDropController() : DragDropController() { Reset(); }
145 void Reset() {
146 drag_start_received_ = false;
147 num_drag_updates_ = 0;
148 drop_received_ = false;
149 drag_canceled_ = false;
150 drag_string_.clear();
153 int StartDragAndDrop(const ui::OSExchangeData& data,
154 aura::Window* root_window,
155 aura::Window* source_window,
156 const gfx::Point& location,
157 int operation,
158 ui::DragDropTypes::DragEventSource source) override {
159 drag_start_received_ = true;
160 data.GetString(&drag_string_);
161 return DragDropController::StartDragAndDrop(
162 data, root_window, source_window, location, operation, source);
165 void DragUpdate(aura::Window* target,
166 const ui::LocatedEvent& event) override {
167 DragDropController::DragUpdate(target, event);
168 num_drag_updates_++;
171 void Drop(aura::Window* target, const ui::LocatedEvent& event) override {
172 DragDropController::Drop(target, event);
173 drop_received_ = true;
176 void DragCancel() override {
177 DragDropController::DragCancel();
178 drag_canceled_ = true;
181 gfx::LinearAnimation* CreateCancelAnimation(
182 int duration,
183 int frame_rate,
184 gfx::AnimationDelegate* delegate) override {
185 return new CompletableLinearAnimation(duration, frame_rate, delegate);
188 void DoDragCancel(int animation_duration_ms) override {
189 DragDropController::DoDragCancel(animation_duration_ms);
190 drag_canceled_ = true;
193 bool drag_start_received_;
194 int num_drag_updates_;
195 bool drop_received_;
196 bool drag_canceled_;
197 base::string16 drag_string_;
199 private:
200 DISALLOW_COPY_AND_ASSIGN(TestDragDropController);
203 class TestNativeWidgetAura : public views::NativeWidgetAura {
204 public:
205 explicit TestNativeWidgetAura(views::internal::NativeWidgetDelegate* delegate)
206 : NativeWidgetAura(delegate),
207 check_if_capture_lost_(false) {
210 void set_check_if_capture_lost(bool value) {
211 check_if_capture_lost_ = value;
214 void OnCaptureLost() override {
215 DCHECK(!check_if_capture_lost_);
216 views::NativeWidgetAura::OnCaptureLost();
219 private:
220 bool check_if_capture_lost_;
222 DISALLOW_COPY_AND_ASSIGN(TestNativeWidgetAura);
225 // TODO(sky): this is for debugging, remove when track down failure.
226 void SetCheckIfCaptureLost(views::Widget* widget, bool value) {
227 // On Windows, the DCHECK triggers when running on bot or locally through RDP,
228 // but not when logged in locally.
229 #if !defined(OS_WIN)
230 static_cast<TestNativeWidgetAura*>(widget->native_widget())->
231 set_check_if_capture_lost(value);
232 #endif
235 views::Widget* CreateNewWidget() {
236 views::Widget* widget = new views::Widget;
237 views::Widget::InitParams params;
238 params.type = views::Widget::InitParams::TYPE_WINDOW_FRAMELESS;
239 params.accept_events = true;
240 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
241 params.parent = Shell::GetPrimaryRootWindow();
242 params.child = true;
243 params.native_widget = new TestNativeWidgetAura(widget);
244 widget->Init(params);
245 widget->Show();
246 return widget;
249 void AddViewToWidgetAndResize(views::Widget* widget, views::View* view) {
250 if (!widget->GetContentsView()) {
251 views::View* contents_view = new views::View;
252 widget->SetContentsView(contents_view);
255 views::View* contents_view = widget->GetContentsView();
256 contents_view->AddChildView(view);
257 view->SetBounds(contents_view->width(), 0, 100, 100);
258 gfx::Rect contents_view_bounds = contents_view->bounds();
259 contents_view_bounds.Union(view->bounds());
260 contents_view->SetBoundsRect(contents_view_bounds);
261 widget->SetBounds(contents_view_bounds);
264 void DispatchGesture(ui::EventType gesture_type, gfx::Point location) {
265 ui::GestureEventDetails event_details(gesture_type);
266 event_details.set_oldest_touch_id(1);
267 ui::GestureEvent gesture_event(
268 location.x(), location.y(), 0, ui::EventTimeForNow(), event_details);
269 ui::EventSource* event_source =
270 Shell::GetPrimaryRootWindow()->GetHost()->GetEventSource();
271 ui::EventSourceTestApi event_source_test(event_source);
272 ui::EventDispatchDetails details =
273 event_source_test.SendEventToProcessor(&gesture_event);
274 CHECK(!details.dispatcher_destroyed);
277 } // namespace
279 class DragDropControllerTest : public AshTestBase {
280 public:
281 DragDropControllerTest() : AshTestBase() {}
282 ~DragDropControllerTest() override {}
284 void SetUp() override {
285 AshTestBase::SetUp();
286 drag_drop_controller_.reset(new TestDragDropController);
287 drag_drop_controller_->set_should_block_during_drag_drop(false);
288 aura::client::SetDragDropClient(Shell::GetPrimaryRootWindow(),
289 drag_drop_controller_.get());
292 void TearDown() override {
293 aura::client::SetDragDropClient(Shell::GetPrimaryRootWindow(), NULL);
294 drag_drop_controller_.reset();
295 AshTestBase::TearDown();
298 void UpdateDragData(ui::OSExchangeData* data) {
299 drag_drop_controller_->drag_data_ = data;
302 aura::Window* GetDragWindow() {
303 return drag_drop_controller_->drag_window_;
306 aura::Window* GetDragSourceWindow() {
307 return drag_drop_controller_->drag_source_window_;
310 void SetDragSourceWindow(aura::Window* drag_source_window) {
311 drag_drop_controller_->drag_source_window_ = drag_source_window;
312 drag_source_window->AddObserver(drag_drop_controller_.get());
315 aura::Window* GetDragImageWindow() {
316 return drag_drop_controller_->drag_image_.get() ?
317 drag_drop_controller_->drag_image_->GetWidget()->GetNativeWindow() :
318 NULL;
321 DragDropTracker* drag_drop_tracker() {
322 return drag_drop_controller_->drag_drop_tracker_.get();
325 void CompleteCancelAnimation() {
326 CompletableLinearAnimation* animation =
327 static_cast<CompletableLinearAnimation*>(
328 drag_drop_controller_->cancel_animation_.get());
329 animation->Complete();
332 protected:
333 scoped_ptr<TestDragDropController> drag_drop_controller_;
335 private:
336 DISALLOW_COPY_AND_ASSIGN(DragDropControllerTest);
339 // TODO(win_aura) http://crbug.com/154081
340 #if defined(OS_WIN)
341 #define MAYBE_DragDropInSingleViewTest DISABLED_DragDropInSingleViewTest
342 #else
343 #define MAYBE_DragDropInSingleViewTest DragDropInSingleViewTest
344 #endif
345 TEST_F(DragDropControllerTest, MAYBE_DragDropInSingleViewTest) {
346 scoped_ptr<views::Widget> widget(CreateNewWidget());
347 DragTestView* drag_view = new DragTestView;
348 AddViewToWidgetAndResize(widget.get(), drag_view);
349 ui::OSExchangeData data;
350 data.SetString(base::UTF8ToUTF16("I am being dragged"));
351 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
352 widget->GetNativeView());
353 generator.PressLeftButton();
355 int num_drags = 17;
356 SetCheckIfCaptureLost(widget.get(), true);
357 for (int i = 0; i < num_drags; ++i) {
358 // Because we are not doing a blocking drag and drop, the original
359 // OSDragExchangeData object is lost as soon as we return from the drag
360 // initiation in DragDropController::StartDragAndDrop(). Hence we set the
361 // drag_data_ to a fake drag data object that we created.
362 if (i > 0)
363 UpdateDragData(&data);
364 // 7 comes from views::View::GetVerticalDragThreshold()).
365 if (i >= 7)
366 SetCheckIfCaptureLost(widget.get(), false);
368 generator.MoveMouseBy(0, 1);
370 // Execute any scheduled draws to process deferred mouse events.
371 RunAllPendingInMessageLoop();
374 generator.ReleaseLeftButton();
376 EXPECT_TRUE(drag_drop_controller_->drag_start_received_);
377 EXPECT_EQ(num_drags - 1 - drag_view->VerticalDragThreshold(),
378 drag_drop_controller_->num_drag_updates_);
379 EXPECT_TRUE(drag_drop_controller_->drop_received_);
380 EXPECT_EQ(base::UTF8ToUTF16("I am being dragged"),
381 drag_drop_controller_->drag_string_);
383 EXPECT_EQ(1, drag_view->num_drag_enters_);
384 EXPECT_EQ(num_drags - 1 - drag_view->VerticalDragThreshold(),
385 drag_view->num_drag_updates_);
386 EXPECT_EQ(1, drag_view->num_drops_);
387 EXPECT_EQ(0, drag_view->num_drag_exits_);
388 EXPECT_TRUE(drag_view->drag_done_received_);
391 TEST_F(DragDropControllerTest, DragDropWithZeroDragUpdates) {
392 scoped_ptr<views::Widget> widget(CreateNewWidget());
393 DragTestView* drag_view = new DragTestView;
394 AddViewToWidgetAndResize(widget.get(), drag_view);
395 ui::OSExchangeData data;
396 data.SetString(base::UTF8ToUTF16("I am being dragged"));
397 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
398 widget->GetNativeView());
399 generator.PressLeftButton();
401 int num_drags = drag_view->VerticalDragThreshold() + 1;
402 for (int i = 0; i < num_drags; ++i) {
403 // Because we are not doing a blocking drag and drop, the original
404 // OSDragExchangeData object is lost as soon as we return from the drag
405 // initiation in DragDropController::StartDragAndDrop(). Hence we set the
406 // drag_data_ to a fake drag data object that we created.
407 if (i > 0)
408 UpdateDragData(&data);
409 generator.MoveMouseBy(0, 1);
412 UpdateDragData(&data);
414 generator.ReleaseLeftButton();
416 EXPECT_TRUE(drag_drop_controller_->drag_start_received_);
417 EXPECT_EQ(num_drags - 1 - drag_view->VerticalDragThreshold() + 1,
418 drag_drop_controller_->num_drag_updates_);
419 EXPECT_TRUE(drag_drop_controller_->drop_received_);
421 EXPECT_EQ(1, drag_view->num_drag_enters_);
422 EXPECT_EQ(num_drags - 1 - drag_view->VerticalDragThreshold() + 1,
423 drag_view->num_drag_updates_);
424 EXPECT_EQ(1, drag_view->num_drops_);
425 EXPECT_EQ(0, drag_view->num_drag_exits_);
426 EXPECT_TRUE(drag_view->drag_done_received_);
429 // TODO(win_aura) http://crbug.com/154081
430 #if defined(OS_WIN)
431 #define MAYBE_DragDropInMultipleViewsSingleWidgetTest DISABLED_DragDropInMultipleViewsSingleWidgetTest
432 #else
433 #define MAYBE_DragDropInMultipleViewsSingleWidgetTest DragDropInMultipleViewsSingleWidgetTest
434 #endif
435 TEST_F(DragDropControllerTest, MAYBE_DragDropInMultipleViewsSingleWidgetTest) {
436 scoped_ptr<views::Widget> widget(CreateNewWidget());
437 DragTestView* drag_view1 = new DragTestView;
438 AddViewToWidgetAndResize(widget.get(), drag_view1);
439 DragTestView* drag_view2 = new DragTestView;
440 AddViewToWidgetAndResize(widget.get(), drag_view2);
442 ui::OSExchangeData data;
443 data.SetString(base::UTF8ToUTF16("I am being dragged"));
445 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
446 generator.MoveMouseRelativeTo(widget->GetNativeView(),
447 drag_view1->bounds().CenterPoint());
448 generator.PressLeftButton();
450 int num_drags = drag_view1->width();
451 for (int i = 0; i < num_drags; ++i) {
452 // Because we are not doing a blocking drag and drop, the original
453 // OSDragExchangeData object is lost as soon as we return from the drag
454 // initiation in DragDropController::StartDragAndDrop(). Hence we set the
455 // drag_data_ to a fake drag data object that we created.
456 if (i > 0)
457 UpdateDragData(&data);
458 generator.MoveMouseBy(1, 0);
460 // Execute any scheduled draws to process deferred mouse events.
461 RunAllPendingInMessageLoop();
464 generator.ReleaseLeftButton();
466 EXPECT_TRUE(drag_drop_controller_->drag_start_received_);
467 EXPECT_EQ(num_drags - 1 - drag_view1->HorizontalDragThreshold(),
468 drag_drop_controller_->num_drag_updates_);
469 EXPECT_TRUE(drag_drop_controller_->drop_received_);
470 EXPECT_EQ(base::UTF8ToUTF16("I am being dragged"),
471 drag_drop_controller_->drag_string_);
473 EXPECT_EQ(1, drag_view1->num_drag_enters_);
474 int num_expected_updates = drag_view1->bounds().width() -
475 drag_view1->bounds().CenterPoint().x() - 2;
476 EXPECT_EQ(num_expected_updates - drag_view1->HorizontalDragThreshold(),
477 drag_view1->num_drag_updates_);
478 EXPECT_EQ(0, drag_view1->num_drops_);
479 EXPECT_EQ(1, drag_view1->num_drag_exits_);
480 EXPECT_TRUE(drag_view1->drag_done_received_);
482 EXPECT_EQ(1, drag_view2->num_drag_enters_);
483 num_expected_updates = num_drags - num_expected_updates - 1;
484 EXPECT_EQ(num_expected_updates, drag_view2->num_drag_updates_);
485 EXPECT_EQ(1, drag_view2->num_drops_);
486 EXPECT_EQ(0, drag_view2->num_drag_exits_);
487 EXPECT_FALSE(drag_view2->drag_done_received_);
490 // TODO(win_aura) http://crbug.com/154081
491 #if defined(OS_WIN)
492 #define MAYBE_DragDropInMultipleViewsMultipleWidgetsTest DISABLED_DragDropInMultipleViewsMultipleWidgetsTest
493 #else
494 #define MAYBE_DragDropInMultipleViewsMultipleWidgetsTest DragDropInMultipleViewsMultipleWidgetsTest
495 #endif
496 TEST_F(DragDropControllerTest, MAYBE_DragDropInMultipleViewsMultipleWidgetsTest) {
497 scoped_ptr<views::Widget> widget1(CreateNewWidget());
498 DragTestView* drag_view1 = new DragTestView;
499 AddViewToWidgetAndResize(widget1.get(), drag_view1);
500 scoped_ptr<views::Widget> widget2(CreateNewWidget());
501 DragTestView* drag_view2 = new DragTestView;
502 AddViewToWidgetAndResize(widget2.get(), drag_view2);
503 gfx::Rect widget1_bounds = widget1->GetClientAreaBoundsInScreen();
504 gfx::Rect widget2_bounds = widget2->GetClientAreaBoundsInScreen();
505 widget2->SetBounds(gfx::Rect(widget1_bounds.width(), 0,
506 widget2_bounds.width(), widget2_bounds.height()));
508 ui::OSExchangeData data;
509 data.SetString(base::UTF8ToUTF16("I am being dragged"));
511 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
512 widget1->GetNativeView());
513 generator.PressLeftButton();
515 int num_drags = drag_view1->width();
516 for (int i = 0; i < num_drags; ++i) {
517 // Because we are not doing a blocking drag and drop, the original
518 // OSDragExchangeData object is lost as soon as we return from the drag
519 // initiation in DragDropController::StartDragAndDrop(). Hence we set the
520 // drag_data_ to a fake drag data object that we created.
521 if (i > 0)
522 UpdateDragData(&data);
523 generator.MoveMouseBy(1, 0);
525 // Execute any scheduled draws to process deferred mouse events.
526 RunAllPendingInMessageLoop();
529 generator.ReleaseLeftButton();
531 EXPECT_TRUE(drag_drop_controller_->drag_start_received_);
532 EXPECT_EQ(num_drags - 1 - drag_view1->HorizontalDragThreshold(),
533 drag_drop_controller_->num_drag_updates_);
534 EXPECT_TRUE(drag_drop_controller_->drop_received_);
535 EXPECT_EQ(base::UTF8ToUTF16("I am being dragged"),
536 drag_drop_controller_->drag_string_);
538 EXPECT_EQ(1, drag_view1->num_drag_enters_);
539 int num_expected_updates = drag_view1->bounds().width() -
540 drag_view1->bounds().CenterPoint().x() - 2;
541 EXPECT_EQ(num_expected_updates - drag_view1->HorizontalDragThreshold(),
542 drag_view1->num_drag_updates_);
543 EXPECT_EQ(0, drag_view1->num_drops_);
544 EXPECT_EQ(1, drag_view1->num_drag_exits_);
545 EXPECT_TRUE(drag_view1->drag_done_received_);
547 EXPECT_EQ(1, drag_view2->num_drag_enters_);
548 num_expected_updates = num_drags - num_expected_updates - 1;
549 EXPECT_EQ(num_expected_updates, drag_view2->num_drag_updates_);
550 EXPECT_EQ(1, drag_view2->num_drops_);
551 EXPECT_EQ(0, drag_view2->num_drag_exits_);
552 EXPECT_FALSE(drag_view2->drag_done_received_);
555 // TODO(win_aura) http://crbug.com/154081
556 #if defined(OS_WIN)
557 #define MAYBE_ViewRemovedWhileInDragDropTest DISABLED_ViewRemovedWhileInDragDropTest
558 #else
559 #define MAYBE_ViewRemovedWhileInDragDropTest ViewRemovedWhileInDragDropTest
560 #endif
561 TEST_F(DragDropControllerTest, MAYBE_ViewRemovedWhileInDragDropTest) {
562 scoped_ptr<views::Widget> widget(CreateNewWidget());
563 scoped_ptr<DragTestView> drag_view(new DragTestView);
564 AddViewToWidgetAndResize(widget.get(), drag_view.get());
565 gfx::Point point = gfx::Rect(drag_view->bounds()).CenterPoint();
566 ui::OSExchangeData data;
567 data.SetString(base::UTF8ToUTF16("I am being dragged"));
569 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
570 generator.MoveMouseToCenterOf(widget->GetNativeView());
571 generator.PressLeftButton();
573 int num_drags_1 = 17;
574 for (int i = 0; i < num_drags_1; ++i) {
575 // Because we are not doing a blocking drag and drop, the original
576 // OSDragExchangeData object is lost as soon as we return from the drag
577 // initiation in DragDropController::StartDragAndDrop(). Hence we set the
578 // drag_data_ to a fake drag data object that we created.
579 if (i > 0)
580 UpdateDragData(&data);
581 generator.MoveMouseBy(0, 1);
583 // Execute any scheduled draws to process deferred mouse events.
584 RunAllPendingInMessageLoop();
587 drag_view->parent()->RemoveChildView(drag_view.get());
588 // View has been removed. We will not get any of the following drag updates.
589 int num_drags_2 = 23;
590 for (int i = 0; i < num_drags_2; ++i) {
591 UpdateDragData(&data);
592 generator.MoveMouseBy(0, 1);
594 // Execute any scheduled draws to process deferred mouse events.
595 RunAllPendingInMessageLoop();
598 generator.ReleaseLeftButton();
600 EXPECT_TRUE(drag_drop_controller_->drag_start_received_);
601 EXPECT_EQ(num_drags_1 + num_drags_2 - 1 - drag_view->VerticalDragThreshold(),
602 drag_drop_controller_->num_drag_updates_);
603 EXPECT_TRUE(drag_drop_controller_->drop_received_);
604 EXPECT_EQ(base::UTF8ToUTF16("I am being dragged"),
605 drag_drop_controller_->drag_string_);
607 EXPECT_EQ(1, drag_view->num_drag_enters_);
608 EXPECT_EQ(num_drags_1 - 1 - drag_view->VerticalDragThreshold(),
609 drag_view->num_drag_updates_);
610 EXPECT_EQ(0, drag_view->num_drops_);
611 EXPECT_EQ(0, drag_view->num_drag_exits_);
612 EXPECT_TRUE(drag_view->drag_done_received_);
615 TEST_F(DragDropControllerTest, DragLeavesClipboardAloneTest) {
616 ui::Clipboard* cb = ui::Clipboard::GetForCurrentThread();
617 std::string clip_str("I am on the clipboard");
619 // We first copy some text to the clipboard.
620 ui::ScopedClipboardWriter scw(ui::CLIPBOARD_TYPE_COPY_PASTE);
621 scw.WriteText(base::ASCIIToUTF16(clip_str));
623 EXPECT_TRUE(cb->IsFormatAvailable(ui::Clipboard::GetPlainTextFormatType(),
624 ui::CLIPBOARD_TYPE_COPY_PASTE));
626 scoped_ptr<views::Widget> widget(CreateNewWidget());
627 DragTestView* drag_view = new DragTestView;
628 AddViewToWidgetAndResize(widget.get(), drag_view);
630 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
631 widget->GetNativeView());
632 ui::OSExchangeData data;
633 std::string data_str("I am being dragged");
634 data.SetString(base::ASCIIToUTF16(data_str));
636 generator.PressLeftButton();
637 generator.MoveMouseBy(0, drag_view->VerticalDragThreshold() + 1);
639 // Execute any scheduled draws to process deferred mouse events.
640 RunAllPendingInMessageLoop();
642 // Verify the clipboard contents haven't changed
643 std::string result;
644 EXPECT_TRUE(cb->IsFormatAvailable(ui::Clipboard::GetPlainTextFormatType(),
645 ui::CLIPBOARD_TYPE_COPY_PASTE));
646 cb->ReadAsciiText(ui::CLIPBOARD_TYPE_COPY_PASTE, &result);
647 EXPECT_EQ(clip_str, result);
648 // Destory the clipboard here because ash doesn't delete it.
649 // crbug.com/158150.
650 ui::Clipboard::DestroyClipboardForCurrentThread();
653 TEST_F(DragDropControllerTest, WindowDestroyedDuringDragDrop) {
654 scoped_ptr<views::Widget> widget(CreateNewWidget());
655 DragTestView* drag_view = new DragTestView;
656 AddViewToWidgetAndResize(widget.get(), drag_view);
657 aura::Window* window = widget->GetNativeView();
659 ui::OSExchangeData data;
660 data.SetString(base::UTF8ToUTF16("I am being dragged"));
661 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
662 widget->GetNativeView());
663 generator.PressLeftButton();
665 int num_drags = 17;
666 for (int i = 0; i < num_drags; ++i) {
667 // Because we are not doing a blocking drag and drop, the original
668 // OSDragExchangeData object is lost as soon as we return from the drag
669 // initiation in DragDropController::StartDragAndDrop(). Hence we set the
670 // drag_data_ to a fake drag data object that we created.
671 if (i > 0)
672 UpdateDragData(&data);
673 generator.MoveMouseBy(0, 1);
675 // Execute any scheduled draws to process deferred mouse events.
676 RunAllPendingInMessageLoop();
678 if (i > drag_view->VerticalDragThreshold())
679 EXPECT_EQ(window, GetDragWindow());
682 widget->CloseNow();
683 EXPECT_FALSE(GetDragWindow());
685 num_drags = 23;
686 for (int i = 0; i < num_drags; ++i) {
687 if (i > 0)
688 UpdateDragData(&data);
689 generator.MoveMouseBy(0, 1);
690 // We should not crash here.
693 generator.ReleaseLeftButton();
695 EXPECT_TRUE(drag_drop_controller_->drag_start_received_);
696 EXPECT_TRUE(drag_drop_controller_->drop_received_);
699 TEST_F(DragDropControllerTest, SyntheticEventsDuringDragDrop) {
700 scoped_ptr<views::Widget> widget(CreateNewWidget());
701 DragTestView* drag_view = new DragTestView;
702 AddViewToWidgetAndResize(widget.get(), drag_view);
703 ui::OSExchangeData data;
704 data.SetString(base::UTF8ToUTF16("I am being dragged"));
705 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
706 widget->GetNativeView());
707 generator.PressLeftButton();
709 int num_drags = 17;
710 for (int i = 0; i < num_drags; ++i) {
711 // Because we are not doing a blocking drag and drop, the original
712 // OSDragExchangeData object is lost as soon as we return from the drag
713 // initiation in DragDropController::StartDragAndDrop(). Hence we set the
714 // drag_data_ to a fake drag data object that we created.
715 if (i > 0)
716 UpdateDragData(&data);
717 generator.MoveMouseBy(0, 1);
719 // We send a unexpected mouse move event. Note that we cannot use
720 // EventGenerator since it implicitly turns these into mouse drag events.
721 // The DragDropController should simply ignore these events.
722 gfx::Point mouse_move_location = drag_view->bounds().CenterPoint();
723 ui::MouseEvent mouse_move(ui::ET_MOUSE_MOVED, mouse_move_location,
724 mouse_move_location, ui::EventTimeForNow(), 0, 0);
725 ui::EventDispatchDetails details = Shell::GetPrimaryRootWindow()->
726 GetHost()->event_processor()->OnEventFromSource(&mouse_move);
727 ASSERT_FALSE(details.dispatcher_destroyed);
730 generator.ReleaseLeftButton();
732 EXPECT_TRUE(drag_drop_controller_->drag_start_received_);
733 EXPECT_EQ(num_drags - 1 - drag_view->VerticalDragThreshold(),
734 drag_drop_controller_->num_drag_updates_);
735 EXPECT_TRUE(drag_drop_controller_->drop_received_);
736 EXPECT_EQ(base::UTF8ToUTF16("I am being dragged"),
737 drag_drop_controller_->drag_string_);
739 EXPECT_EQ(1, drag_view->num_drag_enters_);
740 EXPECT_EQ(num_drags - 1 - drag_view->VerticalDragThreshold(),
741 drag_view->num_drag_updates_);
742 EXPECT_EQ(1, drag_view->num_drops_);
743 EXPECT_EQ(0, drag_view->num_drag_exits_);
744 EXPECT_TRUE(drag_view->drag_done_received_);
747 // TODO(win_aura) http://crbug.com/154081
748 #if defined(OS_WIN)
749 #define MAYBE_PressingEscapeCancelsDragDrop DISABLED_PressingEscapeCancelsDragDrop
750 #define MAYBE_CaptureLostCancelsDragDrop DISABLED_CaptureLostCancelsDragDrop
751 #else
752 #define MAYBE_PressingEscapeCancelsDragDrop PressingEscapeCancelsDragDrop
753 #define MAYBE_CaptureLostCancelsDragDrop CaptureLostCancelsDragDrop
754 #endif
755 TEST_F(DragDropControllerTest, MAYBE_PressingEscapeCancelsDragDrop) {
756 scoped_ptr<views::Widget> widget(CreateNewWidget());
757 DragTestView* drag_view = new DragTestView;
758 AddViewToWidgetAndResize(widget.get(), drag_view);
759 ui::OSExchangeData data;
760 data.SetString(base::UTF8ToUTF16("I am being dragged"));
761 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
762 widget->GetNativeView());
763 generator.PressLeftButton();
765 int num_drags = 17;
766 for (int i = 0; i < num_drags; ++i) {
767 // Because we are not doing a blocking drag and drop, the original
768 // OSDragExchangeData object is lost as soon as we return from the drag
769 // initiation in DragDropController::StartDragAndDrop(). Hence we set the
770 // drag_data_ to a fake drag data object that we created.
771 if (i > 0)
772 UpdateDragData(&data);
773 generator.MoveMouseBy(0, 1);
775 // Execute any scheduled draws to process deferred mouse events.
776 RunAllPendingInMessageLoop();
779 generator.PressKey(ui::VKEY_ESCAPE, 0);
781 EXPECT_TRUE(drag_drop_controller_->drag_start_received_);
782 EXPECT_EQ(num_drags - 1 - drag_view->VerticalDragThreshold(),
783 drag_drop_controller_->num_drag_updates_);
784 EXPECT_FALSE(drag_drop_controller_->drop_received_);
785 EXPECT_TRUE(drag_drop_controller_->drag_canceled_);
786 EXPECT_EQ(base::UTF8ToUTF16("I am being dragged"),
787 drag_drop_controller_->drag_string_);
789 EXPECT_EQ(1, drag_view->num_drag_enters_);
790 EXPECT_EQ(num_drags - 1 - drag_view->VerticalDragThreshold(),
791 drag_view->num_drag_updates_);
792 EXPECT_EQ(0, drag_view->num_drops_);
793 EXPECT_EQ(1, drag_view->num_drag_exits_);
794 EXPECT_TRUE(drag_view->drag_done_received_);
797 TEST_F(DragDropControllerTest, MAYBE_CaptureLostCancelsDragDrop) {
798 scoped_ptr<views::Widget> widget(CreateNewWidget());
799 DragTestView* drag_view = new DragTestView;
800 AddViewToWidgetAndResize(widget.get(), drag_view);
801 ui::OSExchangeData data;
802 data.SetString(base::UTF8ToUTF16("I am being dragged"));
803 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
804 widget->GetNativeView());
805 generator.PressLeftButton();
807 int num_drags = 17;
808 for (int i = 0; i < num_drags; ++i) {
809 // Because we are not doing a blocking drag and drop, the original
810 // OSDragExchangeData object is lost as soon as we return from the drag
811 // initiation in DragDropController::StartDragAndDrop(). Hence we set the
812 // drag_data_ to a fake drag data object that we created.
813 if (i > 0)
814 UpdateDragData(&data);
815 generator.MoveMouseBy(0, 1);
817 // Execute any scheduled draws to process deferred mouse events.
818 RunAllPendingInMessageLoop();
820 // Make sure the capture window won't handle mouse events.
821 aura::Window* capture_window = drag_drop_tracker()->capture_window();
822 ASSERT_TRUE(capture_window);
823 EXPECT_EQ("0x0", capture_window->bounds().size().ToString());
824 EXPECT_EQ(NULL,
825 capture_window->GetEventHandlerForPoint(gfx::Point()));
826 EXPECT_EQ(NULL,
827 capture_window->GetTopWindowContainingPoint(gfx::Point()));
829 aura::client::GetCaptureClient(widget->GetNativeView()->GetRootWindow())->
830 SetCapture(NULL);
832 EXPECT_TRUE(drag_drop_controller_->drag_start_received_);
833 EXPECT_EQ(num_drags - 1 - drag_view->VerticalDragThreshold(),
834 drag_drop_controller_->num_drag_updates_);
835 EXPECT_FALSE(drag_drop_controller_->drop_received_);
836 EXPECT_TRUE(drag_drop_controller_->drag_canceled_);
837 EXPECT_EQ(base::UTF8ToUTF16("I am being dragged"),
838 drag_drop_controller_->drag_string_);
840 EXPECT_EQ(1, drag_view->num_drag_enters_);
841 EXPECT_EQ(num_drags - 1 - drag_view->VerticalDragThreshold(),
842 drag_view->num_drag_updates_);
843 EXPECT_EQ(0, drag_view->num_drops_);
844 EXPECT_EQ(1, drag_view->num_drag_exits_);
845 EXPECT_TRUE(drag_view->drag_done_received_);
848 TEST_F(DragDropControllerTest, TouchDragDropInMultipleWindows) {
849 base::CommandLine::ForCurrentProcess()->AppendSwitch(
850 switches::kEnableTouchDragDrop);
851 scoped_ptr<views::Widget> widget1(CreateNewWidget());
852 DragTestView* drag_view1 = new DragTestView;
853 AddViewToWidgetAndResize(widget1.get(), drag_view1);
854 scoped_ptr<views::Widget> widget2(CreateNewWidget());
855 DragTestView* drag_view2 = new DragTestView;
856 AddViewToWidgetAndResize(widget2.get(), drag_view2);
857 gfx::Rect widget1_bounds = widget1->GetClientAreaBoundsInScreen();
858 gfx::Rect widget2_bounds = widget2->GetClientAreaBoundsInScreen();
859 widget2->SetBounds(gfx::Rect(widget1_bounds.width(), 0,
860 widget2_bounds.width(), widget2_bounds.height()));
862 ui::OSExchangeData data;
863 data.SetString(base::UTF8ToUTF16("I am being dragged"));
865 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
866 widget1->GetNativeView());
867 generator.PressTouch();
868 gfx::Point point = gfx::Rect(drag_view1->bounds()).CenterPoint();
869 DispatchGesture(ui::ET_GESTURE_LONG_PRESS, point);
870 // Because we are not doing a blocking drag and drop, the original
871 // OSDragExchangeData object is lost as soon as we return from the drag
872 // initiation in DragDropController::StartDragAndDrop(). Hence we set the
873 // drag_data_ to a fake drag data object that we created.
874 UpdateDragData(&data);
875 gfx::Point gesture_location = point;
876 int num_drags = drag_view1->width();
877 for (int i = 0; i < num_drags; ++i) {
878 gesture_location.Offset(1, 0);
879 DispatchGesture(ui::ET_GESTURE_SCROLL_UPDATE, gesture_location);
881 // Execute any scheduled draws to process deferred mouse events.
882 RunAllPendingInMessageLoop();
885 DispatchGesture(ui::ET_GESTURE_SCROLL_END, gesture_location);
887 EXPECT_TRUE(drag_drop_controller_->drag_start_received_);
888 EXPECT_EQ(num_drags, drag_drop_controller_->num_drag_updates_);
889 EXPECT_TRUE(drag_drop_controller_->drop_received_);
890 EXPECT_EQ(base::UTF8ToUTF16("I am being dragged"),
891 drag_drop_controller_->drag_string_);
893 EXPECT_EQ(1, drag_view1->num_drag_enters_);
894 int num_expected_updates = drag_view1->bounds().width() -
895 drag_view1->bounds().CenterPoint().x() - 1;
896 EXPECT_EQ(num_expected_updates, drag_view1->num_drag_updates_);
897 EXPECT_EQ(0, drag_view1->num_drops_);
898 EXPECT_EQ(1, drag_view1->num_drag_exits_);
899 EXPECT_TRUE(drag_view1->drag_done_received_);
901 EXPECT_EQ(1, drag_view2->num_drag_enters_);
902 num_expected_updates = num_drags - num_expected_updates;
903 EXPECT_EQ(num_expected_updates, drag_view2->num_drag_updates_);
904 EXPECT_EQ(1, drag_view2->num_drops_);
905 EXPECT_EQ(0, drag_view2->num_drag_exits_);
906 EXPECT_FALSE(drag_view2->drag_done_received_);
909 TEST_F(DragDropControllerTest, TouchDragDropCancelsOnLongTap) {
910 base::CommandLine::ForCurrentProcess()->AppendSwitch(
911 switches::kEnableTouchDragDrop);
912 scoped_ptr<views::Widget> widget(CreateNewWidget());
913 DragTestView* drag_view = new DragTestView;
914 AddViewToWidgetAndResize(widget.get(), drag_view);
915 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
916 widget->GetNativeView());
918 generator.PressTouch();
919 gfx::Point point = gfx::Rect(drag_view->bounds()).CenterPoint();
920 DispatchGesture(ui::ET_GESTURE_LONG_PRESS, point);
921 DispatchGesture(ui::ET_GESTURE_LONG_TAP, point);
923 EXPECT_TRUE(drag_drop_controller_->drag_start_received_);
924 EXPECT_TRUE(drag_drop_controller_->drag_canceled_);
925 EXPECT_EQ(0, drag_drop_controller_->num_drag_updates_);
926 EXPECT_FALSE(drag_drop_controller_->drop_received_);
927 EXPECT_EQ(base::UTF8ToUTF16("I am being dragged"),
928 drag_drop_controller_->drag_string_);
929 EXPECT_EQ(0, drag_view->num_drag_enters_);
930 EXPECT_EQ(0, drag_view->num_drops_);
931 EXPECT_EQ(0, drag_view->num_drag_exits_);
932 EXPECT_TRUE(drag_view->drag_done_received_);
935 TEST_F(DragDropControllerTest, TouchDragDropLongTapGestureIsForwarded) {
936 base::CommandLine::ForCurrentProcess()->AppendSwitch(
937 switches::kEnableTouchDragDrop);
938 scoped_ptr<views::Widget> widget(CreateNewWidget());
939 DragTestView* drag_view = new DragTestView;
940 AddViewToWidgetAndResize(widget.get(), drag_view);
941 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
942 widget->GetNativeView());
944 generator.PressTouch();
945 gfx::Point point = gfx::Rect(drag_view->bounds()).CenterPoint();
946 DispatchGesture(ui::ET_GESTURE_LONG_PRESS, point);
948 // Since we are not running inside a nested loop, the |drag_source_window_|
949 // will get destroyed immediately. Hence we reassign it.
950 EXPECT_EQ(NULL, GetDragSourceWindow());
951 SetDragSourceWindow(widget->GetNativeView());
952 EXPECT_FALSE(drag_view->long_tap_received_);
953 DispatchGesture(ui::ET_GESTURE_LONG_TAP, point);
954 CompleteCancelAnimation();
955 EXPECT_TRUE(drag_view->long_tap_received_);
958 namespace {
960 class DragImageWindowObserver : public aura::WindowObserver {
961 public:
962 void OnWindowDestroying(aura::Window* window) override {
963 window_location_on_destroying_ = window->GetBoundsInScreen().origin();
966 gfx::Point window_location_on_destroying() const {
967 return window_location_on_destroying_;
970 public:
971 gfx::Point window_location_on_destroying_;
974 } // namespace
976 // Verifies the drag image moves back to the position where drag is started
977 // across displays when drag is cancelled.
978 TEST_F(DragDropControllerTest, DragCancelAcrossDisplays) {
979 if (!SupportsMultipleDisplays())
980 return;
982 UpdateDisplay("400x400,400x400");
983 aura::Window::Windows root_windows =
984 Shell::GetInstance()->GetAllRootWindows();
985 for (aura::Window::Windows::iterator iter = root_windows.begin();
986 iter != root_windows.end(); ++iter) {
987 aura::client::SetDragDropClient(*iter, drag_drop_controller_.get());
990 ui::OSExchangeData data;
991 data.SetString(base::UTF8ToUTF16("I am being dragged"));
993 scoped_ptr<views::Widget> widget(CreateNewWidget());
994 aura::Window* window = widget->GetNativeWindow();
995 drag_drop_controller_->StartDragAndDrop(
996 data,
997 window->GetRootWindow(),
998 window,
999 gfx::Point(5, 5),
1000 ui::DragDropTypes::DRAG_MOVE,
1001 ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE);
1003 DragImageWindowObserver observer;
1004 ASSERT_TRUE(GetDragImageWindow());
1005 GetDragImageWindow()->AddObserver(&observer);
1008 ui::MouseEvent e(ui::ET_MOUSE_DRAGGED, gfx::Point(200, 0),
1009 gfx::Point(200, 0), ui::EventTimeForNow(), ui::EF_NONE,
1010 ui::EF_NONE);
1011 drag_drop_controller_->DragUpdate(window, e);
1014 ui::MouseEvent e(ui::ET_MOUSE_DRAGGED, gfx::Point(600, 0),
1015 gfx::Point(600, 0), ui::EventTimeForNow(), ui::EF_NONE,
1016 ui::EF_NONE);
1017 drag_drop_controller_->DragUpdate(window, e);
1020 drag_drop_controller_->DragCancel();
1021 CompleteCancelAnimation();
1023 EXPECT_EQ("5,5", observer.window_location_on_destroying().ToString());
1027 scoped_ptr<views::Widget> widget(CreateNewWidget());
1028 aura::Window* window = widget->GetNativeWindow();
1029 drag_drop_controller_->StartDragAndDrop(
1030 data,
1031 window->GetRootWindow(),
1032 window,
1033 gfx::Point(405, 405),
1034 ui::DragDropTypes::DRAG_MOVE,
1035 ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE);
1036 DragImageWindowObserver observer;
1037 ASSERT_TRUE(GetDragImageWindow());
1038 GetDragImageWindow()->AddObserver(&observer);
1041 ui::MouseEvent e(ui::ET_MOUSE_DRAGGED, gfx::Point(600, 0),
1042 gfx::Point(600, 0), ui::EventTimeForNow(), ui::EF_NONE,
1043 ui::EF_NONE);
1044 drag_drop_controller_->DragUpdate(window, e);
1047 ui::MouseEvent e(ui::ET_MOUSE_DRAGGED, gfx::Point(200, 0),
1048 gfx::Point(200, 0), ui::EventTimeForNow(), ui::EF_NONE,
1049 ui::EF_NONE);
1050 drag_drop_controller_->DragUpdate(window, e);
1053 drag_drop_controller_->DragCancel();
1054 CompleteCancelAnimation();
1056 EXPECT_EQ("405,405", observer.window_location_on_destroying().ToString());
1058 for (aura::Window::Windows::iterator iter = root_windows.begin();
1059 iter != root_windows.end(); ++iter) {
1060 aura::client::SetDragDropClient(*iter, NULL);
1064 TEST_F(DragDropControllerTest, TouchDragDropCompletesOnFling) {
1065 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1066 switches::kEnableTouchDragDrop);
1067 ui::GestureConfiguration::GetInstance()
1068 ->set_max_touch_move_in_pixels_for_click(1);
1069 scoped_ptr<views::Widget> widget(CreateNewWidget());
1070 DragTestView* drag_view = new DragTestView;
1071 AddViewToWidgetAndResize(widget.get(), drag_view);
1072 ui::OSExchangeData data;
1073 data.SetString(base::UTF8ToUTF16("I am being dragged"));
1074 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
1075 widget->GetNativeView());
1077 gfx::Point start = gfx::Rect(drag_view->bounds()).CenterPoint();
1078 gfx::Point mid = start + gfx::Vector2d(drag_view->bounds().width() / 6, 0);
1079 gfx::Point end = start + gfx::Vector2d(drag_view->bounds().width() / 3, 0);
1081 base::TimeDelta timestamp = ui::EventTimeForNow();
1082 ui::TouchEvent press(ui::ET_TOUCH_PRESSED, start, 0, timestamp);
1083 generator.Dispatch(&press);
1085 DispatchGesture(ui::ET_GESTURE_LONG_PRESS, start);
1086 UpdateDragData(&data);
1087 timestamp += base::TimeDelta::FromMilliseconds(10);
1088 ui::TouchEvent move1(ui::ET_TOUCH_MOVED, mid, 0, timestamp);
1089 generator.Dispatch(&move1);
1090 // Doing two moves instead of one will guarantee to generate a fling at the
1091 // end.
1092 timestamp += base::TimeDelta::FromMilliseconds(10);
1093 ui::TouchEvent move2(ui::ET_TOUCH_MOVED, end, 0, timestamp);
1094 generator.Dispatch(&move2);
1095 ui::TouchEvent release(ui::ET_TOUCH_RELEASED, end, 0, timestamp);
1096 generator.Dispatch(&release);
1098 EXPECT_TRUE(drag_drop_controller_->drag_start_received_);
1099 EXPECT_FALSE(drag_drop_controller_->drag_canceled_);
1100 EXPECT_EQ(2, drag_drop_controller_->num_drag_updates_);
1101 EXPECT_TRUE(drag_drop_controller_->drop_received_);
1102 EXPECT_EQ(base::UTF8ToUTF16("I am being dragged"),
1103 drag_drop_controller_->drag_string_);
1104 EXPECT_EQ(1, drag_view->num_drag_enters_);
1105 EXPECT_EQ(2, drag_view->num_drag_updates_);
1106 EXPECT_EQ(1, drag_view->num_drops_);
1107 EXPECT_EQ(0, drag_view->num_drag_exits_);
1108 EXPECT_TRUE(drag_view->drag_done_received_);
1111 } // namespace test
1112 } // namespace ash