Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3428)

Unified Diff: chrome/browser/ui/views/drag_and_drop_interactive_uitest.cc

Issue 2622733002: Mac Support for drag-and-drop tests that start dragging via mouse simulation.
Patch Set: . Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ui/views/drag_and_drop_interactive_uitest.cc
diff --git a/chrome/browser/ui/views/drag_and_drop_interactive_uitest.cc b/chrome/browser/ui/views/drag_and_drop_interactive_uitest.cc
index f102bd096fcb56faf03fc284bc68ef897721f221..089ebcbfd29f2c329b36cd6fbb106f315baa9e7b 100644
--- a/chrome/browser/ui/views/drag_and_drop_interactive_uitest.cc
+++ b/chrome/browser/ui/views/drag_and_drop_interactive_uitest.cc
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "chrome/browser/ui/views/drag_and_drop_interactive_uitest.h"
+
#include <algorithm>
#include <initializer_list>
#include <memory>
@@ -24,6 +26,7 @@
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
+#include "content/public/common/drop_data.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
@@ -34,13 +37,6 @@
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/aura/client/drag_drop_client.h"
-#include "ui/aura/client/drag_drop_delegate.h"
-#include "ui/aura/client/screen_position_client.h"
-#include "ui/aura/window.h"
-#include "ui/base/dragdrop/drag_drop_types.h"
-#include "ui/base/dragdrop/drop_target_event.h"
-#include "ui/base/dragdrop/os_exchange_data.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
#include "url/gurl.h"
@@ -49,150 +45,23 @@ namespace chrome {
namespace {
-// TODO(lukasza): Support testing on non-Aura platforms (i.e. Android + Mac?).
-//
-// Notes for the TODO above:
-//
-// - Why inject/simulate drag-and-drop events at the aura::Window* level.
-//
-// - It seems better to inject into UI libraries to cover code *inside* these
-// libraries. This might complicate simulation a little bit (i.e. picking
-// the right aura::Window and/or aura::client::DragDropDelegate to target),
-// but otherwise important bits of code wouldn't get test coverage (i.e.
-// directly injecting into RenderViewHost->DragTargetDragEnter seems wrong).
-//
-// - In theory, we could introduce WebContentsImpl::DragTargetDragEnter (to be
-// used by all UI platforms - so reused by web_contents_view_android.cc,
-// web_contents_view_aura.cc, web_drag_dest_mac.mm), but it feels wrong - UI
-// libraries should already know which widget is the target of the event and
-// so should be able to talk directly to the right widget (i.e. WebContents
-// should not be responsible for mapping coordinates to a widget - this is
-// the job of the UI library).
-//
-// - Unknowns:
-//
-// - Will this work for WebView and Plugin testing.
-
-// Test helper for simulating drag and drop happening in WebContents.
-class DragAndDropSimulator {
- public:
- explicit DragAndDropSimulator(content::WebContents* web_contents)
- : web_contents_(web_contents) {}
-
- // Simulates notification that |text| was dragged from outside of the browser,
- // into the specified |location| inside |web_contents|.
- // |location| is relative to |web_contents|.
- // Returns true upon success.
- bool SimulateDragEnter(gfx::Point location, const std::string& text) {
- ui::OSExchangeData data;
- data.SetString(base::UTF8ToUTF16(text));
- return SimulateDragEnter(location, data);
- }
-
- // Simulates dropping of the drag-and-dropped item.
- // SimulateDragEnter needs to be called first.
- // Returns true upon success.
- bool SimulateDrop(gfx::Point location) {
- if (!active_drag_event_) {
- ADD_FAILURE() << "Cannot drop a drag that hasn't started yet.";
- return false;
- }
-
- aura::client::DragDropDelegate* delegate = GetDragDropDelegate();
- if (!delegate)
- return false;
-
- gfx::Point event_location;
- gfx::Point event_root_location;
- CalculateEventLocations(location, &event_location, &event_root_location);
- active_drag_event_->set_location(event_location);
- active_drag_event_->set_root_location(event_root_location);
-
- delegate->OnDragUpdated(*active_drag_event_);
- delegate->OnPerformDrop(*active_drag_event_);
- return true;
- }
-
- private:
- bool SimulateDragEnter(gfx::Point location, const ui::OSExchangeData& data) {
- if (active_drag_event_) {
- ADD_FAILURE() << "Cannot start a new drag when old one hasn't ended yet.";
- return false;
- }
-
- aura::client::DragDropDelegate* delegate = GetDragDropDelegate();
- if (!delegate)
- return false;
-
- gfx::Point event_location;
- gfx::Point event_root_location;
- CalculateEventLocations(location, &event_location, &event_root_location);
- active_drag_event_.reset(new ui::DropTargetEvent(
- data, event_location, event_root_location, kDefaultSourceOperations));
-
- delegate->OnDragEntered(*active_drag_event_);
- delegate->OnDragUpdated(*active_drag_event_);
- return true;
- }
-
- aura::client::DragDropDelegate* GetDragDropDelegate() {
- gfx::NativeView view = web_contents_->GetContentNativeView();
- aura::client::DragDropDelegate* delegate =
- aura::client::GetDragDropDelegate(view);
- EXPECT_TRUE(delegate) << "Expecting WebContents to have DragDropDelegate";
- return delegate;
- }
-
- void CalculateEventLocations(gfx::Point web_contents_relative_location,
- gfx::Point* out_event_location,
- gfx::Point* out_event_root_location) {
- gfx::NativeView view = web_contents_->GetNativeView();
-
- *out_event_location = web_contents_relative_location;
-
- gfx::Point root_location = web_contents_relative_location;
- aura::Window::ConvertPointToTarget(view, view->GetRootWindow(),
- &root_location);
- *out_event_root_location = root_location;
- }
-
- // These are ui::DropTargetEvent::source_operations_ being sent when manually
- // trying out drag&drop of an image file from Nemo (Ubuntu's file explorer)
- // into a content_shell.
- static constexpr int kDefaultSourceOperations = ui::DragDropTypes::DRAG_MOVE |
- ui::DragDropTypes::DRAG_COPY |
- ui::DragDropTypes::DRAG_LINK;
-
- content::WebContents* web_contents_;
- std::unique_ptr<ui::DropTargetEvent> active_drag_event_;
-
- DISALLOW_COPY_AND_ASSIGN(DragAndDropSimulator);
-};
-
// Helper for waiting until a drag-and-drop starts (e.g. in response to a
// mouse-down + mouse-move simulated by the test).
-class DragStartWaiter : public aura::client::DragDropClient {
+class DragStartWaiter {
public:
- // Starts monitoring |web_contents| for a start of a drag-and-drop.
- explicit DragStartWaiter(content::WebContents* web_contents)
- : web_contents_(web_contents),
- message_loop_runner_(new content::MessageLoopRunner),
+ // Starts globally monitoring for a start of a drag-and-drop that originates
+ // from web contents.
+ DragStartWaiter()
+ : message_loop_runner_(new content::MessageLoopRunner),
suppress_passing_of_start_drag_further_(false),
drag_started_(false) {
- DCHECK(web_contents_);
-
- // Intercept calls to the old DragDropClient.
- gfx::NativeWindow root_window =
- web_contents_->GetContentNativeView()->GetRootWindow();
- old_client_ = aura::client::GetDragDropClient(root_window);
- aura::client::SetDragDropClient(root_window, this);
+ content::RegisterDragStartCallback(
+ base::Bind(&DragStartWaiter::StartDragAndDrop, base::Unretained(this)));
}
- ~DragStartWaiter() override {
- // Restore the original DragDropClient.
- gfx::NativeWindow root_window =
- web_contents_->GetContentNativeView()->GetRootWindow();
- aura::client::SetDragDropClient(root_window, old_client_);
+ ~DragStartWaiter() {
+ // Unregister our callback.
+ content::RegisterDragStartCallback(content::DragStartCallback());
}
// Waits until we almost report a drag-and-drop start to the OS.
@@ -208,23 +77,17 @@ class DragStartWaiter : public aura::client::DragDropClient {
// Before returning populates |text|, |html| and other parameters with data
// that would have been passed to the OS). If the caller is not interested in
// this data, then the corresponding argument can be null.
- void WaitUntilDragStart(std::string* text,
- std::string* html,
- int* operation,
- gfx::Point* location_inside_web_contents) {
+ void WaitUntilDragStart(content::DropData* drop_data,
+ blink::WebDragOperationsMask* drag_operations_mask) {
message_loop_runner_->Run();
// message_loop_runner_->Quit is only called from StartDragAndDrop.
DCHECK(drag_started_);
- if (text)
- *text = text_;
- if (html)
- *html = html_;
- if (operation)
- *operation = operation_;
- if (location_inside_web_contents)
- *location_inside_web_contents = location_inside_web_contents_;
+ if (drop_data)
+ *drop_data = drop_data_;
+ if (drag_operations_mask)
+ *drag_operations_mask = drag_operations_mask_;
}
void SuppressPassingStartDragFurther() {
@@ -235,37 +98,15 @@ class DragStartWaiter : public aura::client::DragDropClient {
callback_to_run_inside_drag_and_drop_message_loop_ = callback;
}
- // aura::client::DragDropClient overrides:
- int StartDragAndDrop(const ui::OSExchangeData& data,
- aura::Window* root_window,
- aura::Window* source_window,
- const gfx::Point& screen_location,
- int operation,
- ui::DragDropTypes::DragEventSource source) override {
+ // Implementation of DragStartCallback passed to RegisterDragStartCallback.
+ bool StartDragAndDrop(const content::DropData& drop_data,
+ blink::WebDragOperationsMask drag_operations_mask) {
DCHECK(!drag_started_);
if (!drag_started_) {
drag_started_ = true;
+ drop_data_ = drop_data;
+ drag_operations_mask_ = drag_operations_mask;
message_loop_runner_->Quit();
-
- base::string16 text;
- if (data.GetString(&text))
- text_ = base::UTF16ToUTF8(text);
- else
- text_ = "<no text>";
-
- GURL base_url;
- base::string16 html;
- if (data.GetHtml(&html, &base_url))
- html_ = base::UTF16ToUTF8(html);
- else
- html_ = "<no html>";
-
- gfx::Rect bounds =
- web_contents_->GetContentNativeView()->GetBoundsInScreen();
- location_inside_web_contents_ =
- screen_location - gfx::Vector2d(bounds.x(), bounds.y());
-
- operation_ = operation;
}
if (!callback_to_run_inside_drag_and_drop_message_loop_.is_null()) {
@@ -275,33 +116,18 @@ class DragStartWaiter : public aura::client::DragDropClient {
callback_to_run_inside_drag_and_drop_message_loop_.Reset();
}
- if (suppress_passing_of_start_drag_further_)
- return 0;
-
- // Start a nested drag-and-drop loop (might not return for a long time).
- return old_client_->StartDragAndDrop(data, root_window, source_window,
- screen_location, operation, source);
+ return suppress_passing_of_start_drag_further_;
}
- void DragCancel() override {
- ADD_FAILURE() << "Unexpected call to DragCancel";
- }
-
- bool IsDragDropInProgress() override { return drag_started_; }
-
private:
- content::WebContents* web_contents_;
scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
- aura::client::DragDropClient* old_client_;
base::Closure callback_to_run_inside_drag_and_drop_message_loop_;
bool suppress_passing_of_start_drag_further_;
// Data captured during the first intercepted StartDragAndDrop call.
bool drag_started_;
- std::string text_;
- std::string html_;
- int operation_;
- gfx::Point location_inside_web_contents_;
+ content::DropData drop_data_;
+ blink::WebDragOperationsMask drag_operations_mask_;
DISALLOW_COPY_AND_ASSIGN(DragStartWaiter);
};
@@ -526,7 +352,8 @@ class DragAndDropBrowserTest : public InProcessBrowserTest,
host_resolver()->AddRule("*", "127.0.0.1");
content::SetupCrossSiteRedirector(embedded_test_server());
ASSERT_TRUE(embedded_test_server()->Start());
- drag_simulator_.reset(new DragAndDropSimulator(web_contents()));
+
+ ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
}
bool use_cross_site_subframe() {
@@ -612,6 +439,8 @@ class DragAndDropBrowserTest : public InProcessBrowserTest,
return kMiddleOfLeftFrame + gfx::Vector2d(10, 10);
}
+ gfx::Point middle_of_right_frame() { return kMiddleOfRightFrame; }
+
bool SimulateMouseMoveToLeftFrame() {
AssertTestPageIsLoaded();
return SimulateMouseMove(kMiddleOfLeftFrame);
@@ -627,20 +456,6 @@ class DragAndDropBrowserTest : public InProcessBrowserTest,
ui_controls::UP);
}
- ////////////////////////////////////////////////////////////////////
- // Simulation of dragging from outside the browser into web contents
- // (using DragAndDropSimulator, not simulating mouse events).
-
- bool SimulateDragEnterToRightFrame(const std::string& text) {
- AssertTestPageIsLoaded();
- return drag_simulator_->SimulateDragEnter(kMiddleOfRightFrame, text);
- }
-
- bool SimulateDropInRightFrame() {
- AssertTestPageIsLoaded();
- return drag_simulator_->SimulateDrop(kMiddleOfRightFrame);
- }
-
private:
// Constants with coordinates within content/test/data/drag_and_drop/page.html
// The precise frame center is at 200,200 and 400,200 coordinates, but slight
@@ -656,9 +471,11 @@ class DragAndDropBrowserTest : public InProcessBrowserTest,
bool SimulateMouseMove(const gfx::Point& location_inside_web_contents) {
gfx::Rect bounds = web_contents()->GetContainerBounds();
- return ui_test_utils::SendMouseMoveSync(
- gfx::Point(bounds.x() + location_inside_web_contents.x(),
- bounds.y() + location_inside_web_contents.y()));
+ gfx::Point pos(bounds.x() + location_inside_web_contents.x(),
+ bounds.y() + location_inside_web_contents.y());
+ LOG(ERROR) << "SimulateMouseMove"
+ << "; pos=(" << pos.x() << "," << pos.y() << ")";
+ return ui_test_utils::SendMouseMoveSync(pos);
}
bool NavigateNamedFrame(const std::string& frame_name,
@@ -728,14 +545,18 @@ class DragAndDropBrowserTest : public InProcessBrowserTest,
ASSERT_EQ(kTestPagePath, web_contents()->GetLastCommittedURL().path());
}
- std::unique_ptr<DragAndDropSimulator> drag_simulator_;
-
DISALLOW_COPY_AND_ASSIGN(DragAndDropBrowserTest);
};
+// TODO(lukasza): Implement ExternalDragEnterSimulator for Mac.
+#if !defined(OS_MACOSX)
+
// Scenario: drag text from outside the browser and drop to the right frame.
// Test coverage: dragover, drop DOM events.
IN_PROC_BROWSER_TEST_P(DragAndDropBrowserTest, DropTextFromOutside) {
+ std::unique_ptr<ExternalDragEnterSimulator> drag_simulator =
+ ExternalDragEnterSimulator::Create(web_contents());
+
std::string frame_site = use_cross_site_subframe() ? "b.com" : "a.com";
ASSERT_TRUE(NavigateToTestPage("a.com"));
ASSERT_TRUE(NavigateRightFrame(frame_site, "drop_target.html"));
@@ -751,7 +572,8 @@ IN_PROC_BROWSER_TEST_P(DragAndDropBrowserTest, DropTextFromOutside) {
// Drag text from outside the browser into/over the right frame.
{
DOMDragEventWaiter dragover_waiter("dragover", right_frame());
- ASSERT_TRUE(SimulateDragEnterToRightFrame("Dragged test text"));
+ ASSERT_TRUE(drag_simulator->SimulateDragEnter(middle_of_right_frame(),
+ "Dragged test text"));
std::string dragover_event;
ASSERT_TRUE(dragover_waiter.WaitForNextMatchingEvent(&dragover_event));
@@ -761,7 +583,7 @@ IN_PROC_BROWSER_TEST_P(DragAndDropBrowserTest, DropTextFromOutside) {
// Drop into the right frame.
{
DOMDragEventWaiter drop_waiter("drop", right_frame());
- ASSERT_TRUE(SimulateDropInRightFrame());
+ ASSERT_TRUE(drag_simulator->SimulateDrop(middle_of_right_frame()));
std::string drop_event;
ASSERT_TRUE(drop_waiter.WaitForNextMatchingEvent(&drop_event));
@@ -769,6 +591,8 @@ IN_PROC_BROWSER_TEST_P(DragAndDropBrowserTest, DropTextFromOutside) {
}
}
+#endif
+
// Scenario: starting a drag in left frame
// Test coverage: dragstart DOM event, dragstart data passed to the OS.
IN_PROC_BROWSER_TEST_P(DragAndDropBrowserTest, DragStartInFrame) {
@@ -793,7 +617,7 @@ IN_PROC_BROWSER_TEST_P(DragAndDropBrowserTest, DragStartInFrame) {
"Files,text/html,text/uri-list");
// Start the drag in the left frame.
- DragStartWaiter drag_start_waiter(web_contents());
+ DragStartWaiter drag_start_waiter;
drag_start_waiter.SuppressPassingStartDragFurther();
DOMDragEventWaiter dragstart_event_waiter("dragstart", left_frame());
EXPECT_TRUE(SimulateMouseDownAndDragStartInLeftFrame());
@@ -808,22 +632,34 @@ IN_PROC_BROWSER_TEST_P(DragAndDropBrowserTest, DragStartInFrame) {
// Verify data being passed to the OS.
{
- std::string text;
- std::string html;
- int operation = 0;
- gfx::Point location_inside_web_contents;
- drag_start_waiter.WaitUntilDragStart(&text, &html, &operation,
- &location_inside_web_contents);
+ content::DropData drop_data;
+ blink::WebDragOperationsMask operation;
+ drag_start_waiter.WaitUntilDragStart(&drop_data, &operation);
+
+ EXPECT_EQ("Alternative image text", base::UTF16ToUTF8(drop_data.url_title));
+ EXPECT_TRUE(drop_data.text.is_null());
+
+ EXPECT_EQ("droids.jpg",
+ base::UTF16ToUTF8(drop_data.file_description_filename));
EXPECT_EQ(embedded_test_server()->GetURL(frame_site,
"/image_decoding/droids.jpg"),
- text);
- EXPECT_THAT(html,
- testing::MatchesRegex("<img .*src=\""
+ drop_data.url);
+
+ ASSERT_FALSE(drop_data.html.is_null());
+ EXPECT_THAT(base::UTF16ToUTF8(drop_data.html.string()),
+ testing::MatchesRegex("^<img .*src=\""
"http://.*/image_decoding/droids.jpg"
- "\">"));
- EXPECT_EQ(expected_location_of_drag_start_in_left_frame(),
- location_inside_web_contents);
- EXPECT_EQ(ui::DragDropTypes::DRAG_COPY, operation);
+ "\".*$"));
+
+ EXPECT_THAT(drop_data.filenames, testing::IsEmpty());
+ EXPECT_THAT(drop_data.file_mime_types, testing::IsEmpty());
+
+ EXPECT_THAT(drop_data.custom_data, testing::IsEmpty());
+
+ EXPECT_EQ("", base::UTF16ToUTF8(drop_data.filesystem_id));
+ EXPECT_THAT(drop_data.file_system_files, testing::IsEmpty());
+
+ EXPECT_EQ(blink::WebDragOperationCopy, operation);
}
// Try to leave everything in a clean state.
@@ -874,7 +710,7 @@ IN_PROC_BROWSER_TEST_P(DragAndDropBrowserTest, MAYBE_DragImageBetweenFrames) {
state.expected_dom_event_data.set_expected_page_position("(55, 50)");
// Start the drag in the left frame.
- DragStartWaiter drag_start_waiter(web_contents());
+ DragStartWaiter drag_start_waiter;
drag_start_waiter.PostTaskWhenDragStarts(
base::Bind(&DragAndDropBrowserTest::DragImageBetweenFrames_Step2,
base::Unretained(this), base::Unretained(&state)));
@@ -885,7 +721,7 @@ IN_PROC_BROWSER_TEST_P(DragAndDropBrowserTest, MAYBE_DragImageBetweenFrames) {
// The next step of the test (DragImageBetweenFrames_Step2) runs inside the
// nested drag-and-drop message loop - the call below won't return until the
// drag-and-drop has already ended.
- drag_start_waiter.WaitUntilDragStart(nullptr, nullptr, nullptr, nullptr);
+ drag_start_waiter.WaitUntilDragStart(nullptr, nullptr);
DragImageBetweenFrames_Step3(&state);
}
@@ -1085,7 +921,7 @@ IN_PROC_BROWSER_TEST_P(DragAndDropBrowserTest, MAYBE_CrossSiteDrag) {
new DOMDragEventCounter(right_frame()));
// Start the drag in the left frame.
- DragStartWaiter drag_start_waiter(web_contents());
+ DragStartWaiter drag_start_waiter;
drag_start_waiter.PostTaskWhenDragStarts(
base::Bind(&DragAndDropBrowserTest::CrossSiteDrag_Step2,
base::Unretained(this), base::Unretained(&state)));
@@ -1094,7 +930,7 @@ IN_PROC_BROWSER_TEST_P(DragAndDropBrowserTest, MAYBE_CrossSiteDrag) {
// The next step of the test (CrossSiteDrag_Step2) runs inside the
// nested drag-and-drop message loop - the call below won't return until the
// drag-and-drop has already ended.
- drag_start_waiter.WaitUntilDragStart(nullptr, nullptr, nullptr, nullptr);
+ drag_start_waiter.WaitUntilDragStart(nullptr, nullptr);
CrossSiteDrag_Step3(&state);
}

Powered by Google App Engine
This is Rietveld 408576698