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

Side by Side Diff: chrome/browser/drag_and_drop_browsertest.cc

Issue 2478583005: Browser tests for starting a drag-and-drop out of an OOPIF. (Closed)
Patch Set: Rebasing... Created 4 years, 1 month 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 unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
sky 2016/11/15 00:37:55 This test is ui specific, and it looks like it's a
Łukasz Anforowicz 2016/11/15 18:28:21 Thanks for the suggestion. I agree that it makes
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <memory> 5 #include <memory>
6 #include <string> 6 #include <string>
7 7
8 #include "base/callback.h"
8 #include "base/macros.h" 9 #include "base/macros.h"
10 #include "base/memory/ref_counted.h"
11 #include "base/sequenced_task_runner.h"
9 #include "base/strings/pattern.h" 12 #include "base/strings/pattern.h"
10 #include "base/strings/string_piece.h" 13 #include "base/strings/string_piece.h"
11 #include "base/strings/stringprintf.h" 14 #include "base/strings/stringprintf.h"
12 #include "base/strings/utf_string_conversions.h" 15 #include "base/strings/utf_string_conversions.h"
13 #include "content/browser/frame_host/frame_tree.h" 16 #include "base/threading/sequenced_task_runner_handle.h"
14 #include "content/browser/frame_host/frame_tree_node.h" 17 #include "chrome/browser/ui/browser.h"
15 #include "content/browser/frame_host/render_frame_host_impl.h" 18 #include "chrome/browser/ui/tabs/tab_strip_model.h"
16 #include "content/browser/web_contents/web_contents_impl.h" 19 #include "chrome/test/base/in_process_browser_test.h"
20 #include "chrome/test/base/interactive_test_utils.h"
21 #include "chrome/test/base/ui_test_utils.h"
17 #include "content/public/browser/render_frame_host.h" 22 #include "content/public/browser/render_frame_host.h"
18 #include "content/public/browser/web_contents.h" 23 #include "content/public/browser/web_contents.h"
19 #include "content/public/test/browser_test_utils.h" 24 #include "content/public/test/browser_test_utils.h"
20 #include "content/public/test/content_browser_test.h" 25 #include "content/public/test/content_browser_test.h"
21 #include "content/public/test/content_browser_test_utils.h" 26 #include "content/public/test/content_browser_test_utils.h"
27 #include "content/public/test/test_frame_navigation_observer.h"
22 #include "content/public/test/test_utils.h" 28 #include "content/public/test/test_utils.h"
23 #include "content/shell/browser/shell.h"
24 #include "net/base/escape.h" 29 #include "net/base/escape.h"
25 #include "net/dns/mock_host_resolver.h" 30 #include "net/dns/mock_host_resolver.h"
26 #include "net/test/embedded_test_server/embedded_test_server.h" 31 #include "net/test/embedded_test_server/embedded_test_server.h"
27 #include "testing/gmock/include/gmock/gmock.h" 32 #include "testing/gmock/include/gmock/gmock.h"
28 #include "testing/gtest/include/gtest/gtest.h" 33 #include "testing/gtest/include/gtest/gtest.h"
34 #include "ui/aura/client/drag_drop_client.h"
29 #include "ui/aura/client/drag_drop_delegate.h" 35 #include "ui/aura/client/drag_drop_delegate.h"
30 #include "ui/aura/client/screen_position_client.h" 36 #include "ui/aura/client/screen_position_client.h"
31 #include "ui/aura/window.h" 37 #include "ui/aura/window.h"
32 #include "ui/base/dragdrop/drag_drop_types.h" 38 #include "ui/base/dragdrop/drag_drop_types.h"
33 #include "ui/base/dragdrop/drop_target_event.h" 39 #include "ui/base/dragdrop/drop_target_event.h"
34 #include "ui/base/dragdrop/os_exchange_data.h" 40 #include "ui/base/dragdrop/os_exchange_data.h"
35 #include "ui/gfx/geometry/point.h" 41 #include "ui/gfx/geometry/point.h"
36 #include "ui/gfx/geometry/rect.h" 42 #include "ui/gfx/geometry/rect.h"
37 #include "url/gurl.h" 43 #include "url/gurl.h"
38 44
39 namespace content { 45 namespace chrome {
40 46
41 namespace { 47 namespace {
42 48
43 // TODO(lukasza): Support testing on non-Aura platforms (i.e. Android + Mac?). 49 // TODO(lukasza): Support testing on non-Aura platforms (i.e. Android + Mac?).
44 // 50 //
45 // Notes for the TODO above: 51 // Notes for the TODO above:
46 // 52 //
47 // - Why inject/simulate drag-and-drop events at the aura::Window* level. 53 // - Why inject/simulate drag-and-drop events at the aura::Window* level.
48 // 54 //
49 // - It seems better to inject into UI libraries to cover code *inside* these 55 // - It seems better to inject into UI libraries to cover code *inside* these
50 // libraries. This might complicate simulation a little bit (i.e. picking 56 // libraries. This might complicate simulation a little bit (i.e. picking
51 // the right aura::Window and/or aura::client::DragDropDelegate to target), 57 // the right aura::Window and/or aura::client::DragDropDelegate to target),
52 // but otherwise important bits of code wouldn't get test coverage (i.e. 58 // but otherwise important bits of code wouldn't get test coverage (i.e.
53 // directly injecting into RenderViewHost->DragTargetDragEnter seems wrong). 59 // directly injecting into RenderViewHost->DragTargetDragEnter seems wrong).
54 // 60 //
55 // - In theory, we could introduce WebContentsImpl::DragTargetDragEnter (to be 61 // - In theory, we could introduce WebContentsImpl::DragTargetDragEnter (to be
56 // used by all UI platforms - so reused by web_contents_view_android.cc, 62 // used by all UI platforms - so reused by web_contents_view_android.cc,
57 // web_contents_view_aura.cc, web_drag_dest_mac.mm), but it feels wrong - UI 63 // web_contents_view_aura.cc, web_drag_dest_mac.mm), but it feels wrong - UI
58 // libraries should already know which widget is the target of the event and 64 // libraries should already know which widget is the target of the event and
59 // so should be able to talk directly to the right widget (i.e. WebContents 65 // so should be able to talk directly to the right widget (i.e. WebContents
60 // should not be responsible for mapping coordinates to a widget - this is 66 // should not be responsible for mapping coordinates to a widget - this is
61 // the job of the UI library). 67 // the job of the UI library).
62 // 68 //
63 // - Unknowns: 69 // - Unknowns:
64 // 70 //
65 // - Will this work for WebView and Plugin testing. 71 // - Will this work for WebView and Plugin testing.
66 //
67 // - Will this work for simulating dragging from WebContents into outside of
68 // the browser (without leaving OS drag&drop machinery in a weird state).
69 72
70 // Test helper for simulating drag and drop happening in WebContents. 73 // Test helper for simulating drag and drop happening in WebContents.
71 class DragAndDropSimulator { 74 class DragAndDropSimulator {
72 public: 75 public:
73 explicit DragAndDropSimulator(WebContents* web_contents) 76 explicit DragAndDropSimulator(content::WebContents* web_contents)
74 : web_contents_(web_contents) {} 77 : web_contents_(web_contents) {}
75 78
76 // Simulates notification that |text| was dragged from outside of the browser, 79 // Simulates notification that |text| was dragged from outside of the browser,
77 // into the specified |location| inside |web_contents|. 80 // into the specified |location| inside |web_contents|.
78 // |location| is relative to |web_contents|. 81 // |location| is relative to |web_contents|.
79 // Returns true upon success. 82 // Returns true upon success.
80 bool SimulateDragEnter(gfx::Point location, const std::string& text) { 83 bool SimulateDragEnter(gfx::Point location, const std::string& text) {
81 ui::OSExchangeData data; 84 ui::OSExchangeData data;
82 data.SetString(base::UTF8ToUTF16(text)); 85 data.SetString(base::UTF8ToUTF16(text));
83 return SimulateDragEnter(location, data); 86 return SimulateDragEnter(location, data);
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
150 *out_event_location = root_location; 153 *out_event_location = root_location;
151 } 154 }
152 155
153 // These are ui::DropTargetEvent::source_operations_ being sent when manually 156 // These are ui::DropTargetEvent::source_operations_ being sent when manually
154 // trying out drag&drop of an image file from Nemo (Ubuntu's file explorer) 157 // trying out drag&drop of an image file from Nemo (Ubuntu's file explorer)
155 // into a content_shell. 158 // into a content_shell.
156 static constexpr int kDefaultSourceOperations = ui::DragDropTypes::DRAG_MOVE | 159 static constexpr int kDefaultSourceOperations = ui::DragDropTypes::DRAG_MOVE |
157 ui::DragDropTypes::DRAG_COPY | 160 ui::DragDropTypes::DRAG_COPY |
158 ui::DragDropTypes::DRAG_LINK; 161 ui::DragDropTypes::DRAG_LINK;
159 162
160 WebContents* web_contents_; 163 content::WebContents* web_contents_;
161 std::unique_ptr<ui::DropTargetEvent> active_drag_event_; 164 std::unique_ptr<ui::DropTargetEvent> active_drag_event_;
162 165
163 DISALLOW_COPY_AND_ASSIGN(DragAndDropSimulator); 166 DISALLOW_COPY_AND_ASSIGN(DragAndDropSimulator);
164 }; 167 };
165 168
169 // Helper for waiting until a drag-and-drop starts (e.g. in response to a
170 // mouse-down + mouse-move simulated by the test).
171 class DragStartWaiter : public aura::client::DragDropClient {
172 public:
173 // Starts monitoring |web_contents| for a start of a drag-and-drop.
174 // While alive, prevents a real, OS-level drag-and-drop from starting
175 // for this particular |web_contents|.
176 explicit DragStartWaiter(content::WebContents* web_contents)
177 : web_contents_(web_contents),
178 message_loop_runner_(new content::MessageLoopRunner),
179 drag_started_(false) {
180 DCHECK(web_contents_);
181
182 // Intercept calls to the old DragDropClient.
183 gfx::NativeWindow root_window =
184 web_contents_->GetContentNativeView()->GetRootWindow();
185 old_client_ = aura::client::GetDragDropClient(root_window);
186 aura::client::SetDragDropClient(root_window, this);
187 }
188
189 ~DragStartWaiter() override {
190 // Restore the original DragDropClient.
191 gfx::NativeWindow root_window =
192 web_contents_->GetContentNativeView()->GetRootWindow();
193 aura::client::SetDragDropClient(root_window, old_client_);
194 }
195
196 // Waits until we almost report a drag-and-drop start to the OS
197 // (notifying the OS will be prevented to help the test continue
198 // without entering a nested message loop).
199 //
200 // Returns true if drag and drop has indeed started (and in this
201 // case populates |text|, |html| and other parameters with data
202 // that would have been passed to the OS).
203 bool WaitUntilDragStartIsIntercepted(
204 std::string* text,
205 std::string* html,
206 int* operation,
207 gfx::Point* location_inside_web_contents) {
208 message_loop_runner_->Run();
sky 2016/11/15 00:37:55 Might StartDragAndDrop already have been called?
Łukasz Anforowicz 2016/11/15 18:28:21 Yes and this is okay - in this case Run will immed
209
210 if (!drag_started_)
sky 2016/11/15 00:37:55 DCHECK?
Łukasz Anforowicz 2016/11/15 18:28:21 Done.
211 return false;
212
213 *text = text_;
sky 2016/11/15 00:37:55 Why not copy the pointers and set the values direc
Łukasz Anforowicz 2016/11/15 18:28:21 I think I'd prefer to leave this as-is: 1. This a
214 *html = html_;
215 *operation = operation_;
216 *location_inside_web_contents = location_inside_web_contents_;
217 return true;
218 }
219
220 // aura::client::DragDropClient overrides:
221
sky 2016/11/15 00:37:55 no newline.
Łukasz Anforowicz 2016/11/15 18:28:21 Done.
222 int StartDragAndDrop(const ui::OSExchangeData& data,
223 aura::Window* root_window,
224 aura::Window* source_window,
225 const gfx::Point& screen_location,
226 int operation,
227 ui::DragDropTypes::DragEventSource source) override {
228 if (!drag_started_) {
sky 2016/11/15 00:37:55 DCHECK(!drag_started_)?
Łukasz Anforowicz 2016/11/15 18:28:21 Hmmm... okay. I thought that this class should be
229 drag_started_ = true;
230 message_loop_runner_->Quit();
231
232 base::string16 text;
233 if (data.GetString(&text))
234 text_ = base::UTF16ToUTF8(text);
235 else
236 text_ = "<no text>";
237
238 GURL base_url;
239 base::string16 html;
240 if (data.GetHtml(&html, &base_url))
241 html_ = base::UTF16ToUTF8(html);
242 else
243 html_ = "<no html>";
244
245 gfx::Rect bounds =
246 web_contents_->GetContentNativeView()->GetBoundsInScreen();
247 location_inside_web_contents_ =
248 screen_location - gfx::Vector2d(bounds.x(), bounds.y());
249
250 operation_ = operation;
251 }
252
253 // Forwarding to |old_client_| is undesirable, because test cannot control
254 // next steps after a nested drag-and-drop loop is entered at the OS level
255 // (as is the case in Windows, via DoDragDrop). Instead, in the test we
256 // kind of ignore renderer's request to start drag and drop and never
257 // forward this request to the OS-specific layers.
258 return 0;
259 }
260
261 void DragCancel() override {
262 ADD_FAILURE() << "Unexpected call to DragCancel";
263 }
264
265 bool IsDragDropInProgress() override { return drag_started_; }
266
267 private:
268 content::WebContents* web_contents_;
269 scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
270 aura::client::DragDropClient* old_client_;
271
272 // Data captured during the first intercepted StartDragAndDrop call.
273 bool drag_started_;
274 std::string text_;
275 std::string html_;
276 int operation_;
277 gfx::Point location_inside_web_contents_;
278 };
sky 2016/11/15 00:37:55 DISALLOW...
Łukasz Anforowicz 2016/11/15 18:28:21 Ooops. Done.
279
166 // Helper for waiting for notifications from 280 // Helper for waiting for notifications from
167 // content/test/data/drag_and_drop/event_monitoring.js 281 // content/test/data/drag_and_drop/event_monitoring.js
168 class DOMDragEventWaiter { 282 class DOMDragEventWaiter {
169 public: 283 public:
170 explicit DOMDragEventWaiter(const std::string& event_type_to_wait_for, 284 explicit DOMDragEventWaiter(const std::string& event_type_to_wait_for,
171 const ToRenderFrameHost& target) 285 const content::ToRenderFrameHost& target)
172 : target_frame_name_(target.render_frame_host()->GetFrameName()), 286 : target_frame_name_(target.render_frame_host()->GetFrameName()),
173 event_type_to_wait_for_(event_type_to_wait_for), 287 event_type_to_wait_for_(event_type_to_wait_for),
174 dom_message_queue_( 288 dom_message_queue_(content::WebContents::FromRenderFrameHost(
175 WebContents::FromRenderFrameHost(target.render_frame_host())) {} 289 target.render_frame_host())) {}
176 290
177 // Waits until |target| calls reportDragEvent in 291 // Waits until |target| calls reportDragEvent in
178 // content/test/data/drag_and_drop/event_monitoring.js with event_type 292 // chrome/test/data/drag_and_drop/event_monitoring.js with event_type
179 // property set to |event_type_to_wait_for|. (|target| and 293 // property set to |event_type_to_wait_for|. (|target| and
180 // |event_type_to_wait_for| are passed to the constructor). 294 // |event_type_to_wait_for| are passed to the constructor).
181 // 295 //
182 // Returns the event details via |found_event| (in form of a JSON-encoded 296 // Returns the event details via |found_event| (in form of a JSON-encoded
183 // object). See content/test/data/drag_and_drop/event_monitoring.js for keys 297 // object). See chrome/test/data/drag_and_drop/event_monitoring.js for keys
184 // and properties that |found_event| is expected to have. 298 // and properties that |found_event| is expected to have.
185 // 299 //
186 // Returns true upon success. It is okay if |response| is null. 300 // Returns true upon success. It is okay if |response| is null.
187 bool WaitForNextMatchingEvent(std::string* found_event) WARN_UNUSED_RESULT { 301 bool WaitForNextMatchingEvent(std::string* found_event) WARN_UNUSED_RESULT {
188 std::string candidate_event; 302 std::string candidate_event;
189 bool got_right_event_type = false; 303 bool got_right_event_type = false;
190 bool got_right_window_name = false; 304 bool got_right_window_name = false;
191 do { 305 do {
192 if (!dom_message_queue_.WaitForMessage(&candidate_event)) 306 if (!dom_message_queue_.WaitForMessage(&candidate_event))
193 return false; 307 return false;
194 308
195 got_right_event_type = base::MatchPattern( 309 got_right_event_type = base::MatchPattern(
196 candidate_event, base::StringPrintf("*\"event_type\":\"%s\"*", 310 candidate_event, base::StringPrintf("*\"event_type\":\"%s\"*",
197 event_type_to_wait_for_.c_str())); 311 event_type_to_wait_for_.c_str()));
198 312
199 got_right_window_name = base::MatchPattern( 313 got_right_window_name = base::MatchPattern(
200 candidate_event, base::StringPrintf("*\"window_name\":\"%s\"*", 314 candidate_event, base::StringPrintf("*\"window_name\":\"%s\"*",
201 target_frame_name_.c_str())); 315 target_frame_name_.c_str()));
202 } while (!got_right_event_type || !got_right_window_name); 316 } while (!got_right_event_type || !got_right_window_name);
203 317
204 if (found_event) 318 if (found_event)
205 *found_event = candidate_event; 319 *found_event = candidate_event;
206 320
207 return true; 321 return true;
208 } 322 }
209 323
210 private: 324 private:
211 std::string target_frame_name_; 325 std::string target_frame_name_;
212 std::string event_type_to_wait_for_; 326 std::string event_type_to_wait_for_;
213 DOMMessageQueue dom_message_queue_; 327 content::DOMMessageQueue dom_message_queue_;
328 };
sky 2016/11/15 00:37:55 DISALLOW...
Łukasz Anforowicz 2016/11/15 18:28:21 Done.
329
330 // Helper for verifying contents of DOM events associated with drag-and-drop.
331 class DOMDragEventVerifier {
332 public:
333 DOMDragEventVerifier(){};
sky 2016/11/15 00:37:55 no ';' and space between '()' and '{}'.
Łukasz Anforowicz 2016/11/15 18:28:21 Done.
334
335 void set_expected_drop_effect(const std::string& value) {
336 expected_drop_effect_ = value;
337 }
338
339 void set_expected_effect_allowed(const std::string& value) {
340 expected_effect_allowed_ = value;
341 }
342
343 void set_expected_mime_types(const std::string& value) {
344 expected_mime_types_ = value;
345 }
346
347 // Returns a matcher that will match a std::string (drag event data - e.g.
348 // one returned by DOMDragEventWaiter::WaitForNextMatchingEvent) if it matches
349 // the expectations of this DOMDragEventVerifier.
350 testing::Matcher<std::string> Matches() const {
351 return testing::AllOf(
352 FieldMatches("drop_effect", expected_drop_effect_),
353 FieldMatches("effect_allowed", expected_effect_allowed_),
354 FieldMatches("mime_types", expected_mime_types_));
355 }
356
357 private:
358 static testing::Matcher<std::string> FieldMatches(
359 const std::string& field_name,
360 const std::string& expected_value) {
361 if (expected_value == "<no expectation>")
362 return testing::A<std::string>();
363
364 return testing::HasSubstr(base::StringPrintf(
365 "\"%s\":\"%s\"", field_name.c_str(), expected_value.c_str()));
366 }
367
368 std::string expected_drop_effect_ = "<no expectation>";
369 std::string expected_effect_allowed_ = "<no expectation>";
370 std::string expected_mime_types_ = "<no expectation>";
214 }; 371 };
215 372
216 const char kTestPagePath[] = "/drag_and_drop/page.html"; 373 const char kTestPagePath[] = "/drag_and_drop/page.html";
217 374
218 } // namespace 375 } // namespace
219 376
220 class DragAndDropBrowserTest : public ContentBrowserTest { 377 class DragAndDropBrowserTest : public InProcessBrowserTest {
221 public: 378 public:
222 DragAndDropBrowserTest(){}; 379 DragAndDropBrowserTest(){};
223 380
224 protected: 381 protected:
225 void SetUpOnMainThread() override { 382 void SetUpOnMainThread() override {
226 host_resolver()->AddRule("*", "127.0.0.1"); 383 host_resolver()->AddRule("*", "127.0.0.1");
227 ASSERT_TRUE(embedded_test_server()->Start()); 384 ASSERT_TRUE(embedded_test_server()->Start());
228 content::SetupCrossSiteRedirector(embedded_test_server()); 385 content::SetupCrossSiteRedirector(embedded_test_server());
229 drag_simulator_.reset(new DragAndDropSimulator(shell()->web_contents())); 386 drag_simulator_.reset(new DragAndDropSimulator(web_contents()));
230 } 387 }
231 388
232 // Navigates to content/test/data/drag_and_drop/page.html, with page origin 389 content::RenderFrameHost* left_frame() {
233 // and frame contents being controlled by the parameters. 390 AssertTestPageIsLoaded();
234 bool NavigateToTestPage(const std::string& main_origin, 391 return GetFrameByName("left");
235 const std::string& left_frame, 392 }
236 const std::string& right_frame) {
237 GURL base_url = embedded_test_server()->GetURL(main_origin, kTestPagePath);
238 393
239 std::string left_arg; 394 content::RenderFrameHost* right_frame() {
240 if (!left_frame.empty()) { 395 AssertTestPageIsLoaded();
241 left_arg = net::EscapeQueryParamValue( 396 return GetFrameByName("right");
242 std::string("/cross-site/") + left_frame, true); 397 }
243 }
244 std::string right_arg;
245 if (!right_frame.empty()) {
246 right_arg = net::EscapeQueryParamValue(
247 std::string("/cross-site/") + right_frame, true);
248 }
249 std::string query = base::StringPrintf("left=%s&right=%s", left_arg.c_str(),
250 right_arg.c_str());
251 GURL::Replacements query_replacement;
252 query_replacement.SetQueryStr(query);
253 GURL target_url = base_url.ReplaceComponents(query_replacement);
254 398
255 return NavigateToURL(shell(), target_url); 399 content::WebContents* web_contents() {
400 return browser()->tab_strip_model()->GetActiveWebContents();
256 } 401 }
257 402
403 //////////////////////
404 // Navigation helpers.
405
406 bool NavigateToTestPage(const std::string& origin_of_main_frame) {
407 GURL url =
408 embedded_test_server()->GetURL(origin_of_main_frame, kTestPagePath);
409 ui_test_utils::NavigateToURL(browser(), url);
410 return web_contents()->GetLastCommittedURL() == url;
411 }
412
413 // Navigates the left frame to |filename| (found under
414 // chrome/test/data/drag_and_drop directory).
415 bool NavigateLeftFrame(const std::string& origin,
416 const std::string& filename) {
417 AssertTestPageIsLoaded();
418 return NavigateNamedFrame("left", origin, filename);
419 }
420
421 // Navigates the right frame to |filename| (found under
422 // chrome/test/data/drag_and_drop directory).
423 bool NavigateRightFrame(const std::string& origin,
424 const std::string& filename) {
425 AssertTestPageIsLoaded();
426 return NavigateNamedFrame("right", origin, filename);
427 }
428
429 ////////////////////////////////////////////////////////////
430 // Simulation of starting a drag-and-drop (using the mouse).
431
432 bool SimulateMouseDownAndDragStartInLeftFrame() {
433 AssertTestPageIsLoaded();
434 if (!SimulateMouseMove(kMiddleOfLeftFrame) || !SimulateMouseDown() ||
435 !SimulateMouseMove(expected_location_of_drag_start_in_left_frame()))
436 return false;
437
438 return true;
439 }
440
441 gfx::Point expected_location_of_drag_start_in_left_frame() {
442 // TODO(crbug.com/653490): The delta below should exceed kDragThresholdX and
443 // kDragThresholdY from MouseEventManager.cpp in blink. Ideally, it would
444 // come from the OS instead.
445 return kMiddleOfLeftFrame + gfx::Vector2d(10, 10);
446 }
447
448 bool SimulateMouseUp() {
449 return ui_test_utils::SendMouseEventsSync(ui_controls::LEFT,
450 ui_controls::UP);
451 }
452
453 ////////////////////////////////////////////////////////////////////
454 // Simulation of dragging from outside the browser into web contents
455 // (using DragAndDropSimulator, not simulating mouse events).
456
258 bool SimulateDragEnterToRightFrame(const std::string& text) { 457 bool SimulateDragEnterToRightFrame(const std::string& text) {
259 AssertTestPageIsLoaded(); 458 AssertTestPageIsLoaded();
260 return drag_simulator_->SimulateDragEnter(kMiddleOfRightFrame, text); 459 return drag_simulator_->SimulateDragEnter(kMiddleOfRightFrame, text);
261 } 460 }
262 461
263 bool SimulateDropInRightFrame() { 462 bool SimulateDropInRightFrame() {
264 AssertTestPageIsLoaded(); 463 AssertTestPageIsLoaded();
265 return drag_simulator_->SimulateDrop(kMiddleOfRightFrame); 464 return drag_simulator_->SimulateDrop(kMiddleOfRightFrame);
266 } 465 }
267 466
268 RenderFrameHost* right_frame() { 467 private:
269 AssertTestPageIsLoaded(); 468 bool SimulateMouseDown() {
270 return GetFrameByName("right"); 469 return ui_test_utils::SendMouseEventsSync(ui_controls::LEFT,
470 ui_controls::DOWN);
271 } 471 }
272 472
273 private: 473 bool SimulateMouseMove(const gfx::Point& location_inside_web_contents) {
274 RenderFrameHost* GetFrameByName(const std::string& name_to_find) { 474 gfx::Rect bounds = web_contents()->GetContainerBounds();
275 WebContentsImpl* web_contents = 475 return ui_test_utils::SendMouseMoveSync(
276 static_cast<WebContentsImpl*>(shell()->web_contents()); 476 gfx::Point(bounds.x() + location_inside_web_contents.x(),
277 FrameTree* frame_tree = web_contents->GetFrameTree(); 477 bounds.y() + location_inside_web_contents.y()));
278 return frame_tree->FindByName(name_to_find)->current_frame_host(); 478 }
479
480 bool NavigateNamedFrame(const std::string& frame_name,
481 const std::string& origin,
482 const std::string& filename) {
483 content::RenderFrameHost* frame = GetFrameByName(frame_name);
484 if (!frame)
485 return false;
486
487 std::string script;
488 int response = 0;
489
490 // Navigate the frame and wait for the load event.
491 script = base::StringPrintf(
492 "location.href = '/cross-site/%s/drag_and_drop/%s';\n"
493 "setTimeout(function() { domAutomationController.send(42); }, 0);",
494 origin.c_str(), filename.c_str());
495 content::TestFrameNavigationObserver observer(frame);
496 if (!content::ExecuteScriptAndExtractInt(frame, script, &response))
497 return false;
498 if (response != 42)
499 return false;
500 observer.Wait();
501
502 // Wait until frame contents (e.g. images) have painted (which should happen
503 // in the animation frame that *starts* after the onload event - therefore
504 // we need to wait for 2 animation frames).
505 script = std::string(
506 "requestAnimationFrame(function() {\n"
507 " requestAnimationFrame(function() {\n"
508 " domAutomationController.send(43);\n"
509 " });\n"
510 "});\n");
511 if (!content::ExecuteScriptAndExtractInt(frame, script, &response))
512 return false;
513 if (response != 43)
514 return false;
515
516 return true;
517 }
518
519 content::RenderFrameHost* GetFrameByName(const std::string& name_to_find) {
520 content::RenderFrameHost* result = nullptr;
521 for (content::RenderFrameHost* rfh : web_contents()->GetAllFrames()) {
522 if (rfh->GetFrameName() == name_to_find) {
523 if (result) {
524 ADD_FAILURE() << "More than one frame named "
525 << "'" << name_to_find << "'";
526 return nullptr;
527 }
528 result = rfh;
529 }
530 }
531
532 EXPECT_TRUE(result) << "Couldn't find a frame named "
533 << "'" << name_to_find << "'";
534 return result;
279 } 535 }
280 536
281 void AssertTestPageIsLoaded() { 537 void AssertTestPageIsLoaded() {
282 ASSERT_EQ(kTestPagePath, 538 ASSERT_EQ(kTestPagePath, web_contents()->GetLastCommittedURL().path());
283 shell()->web_contents()->GetLastCommittedURL().path());
284 } 539 }
285 540
286 std::unique_ptr<DragAndDropSimulator> drag_simulator_; 541 std::unique_ptr<DragAndDropSimulator> drag_simulator_;
287 542
288 // Constants with coordinates within content/test/data/drag_and_drop/page.html 543 // Constants with coordinates within content/test/data/drag_and_drop/page.html
289 const gfx::Point kMiddleOfLeftFrame = gfx::Point(200, 200); 544 const gfx::Point kMiddleOfLeftFrame = gfx::Point(200, 200);
290 const gfx::Point kMiddleOfRightFrame = gfx::Point(400, 200); 545 const gfx::Point kMiddleOfRightFrame = gfx::Point(400, 200);
291 546
292 DISALLOW_COPY_AND_ASSIGN(DragAndDropBrowserTest); 547 DISALLOW_COPY_AND_ASSIGN(DragAndDropBrowserTest);
293 }; 548 };
294 549
295 IN_PROC_BROWSER_TEST_F(DragAndDropBrowserTest, DropTextFromOutside) { 550 IN_PROC_BROWSER_TEST_F(DragAndDropBrowserTest, DropTextFromOutside) {
296 ASSERT_TRUE(NavigateToTestPage("a.com", 551 ASSERT_TRUE(NavigateToTestPage("a.com"));
297 "", // Left frame is unused by this test. 552 ASSERT_TRUE(NavigateRightFrame("b.com", "drop_target.html"));
298 "c.com/drag_and_drop/drop_target.html"));
299 553
554 // Setup test expectations.
555 DOMDragEventVerifier expected_dom_event_data;
556 expected_dom_event_data.set_expected_drop_effect("none");
557 expected_dom_event_data.set_expected_effect_allowed("all");
558 expected_dom_event_data.set_expected_mime_types("text/plain");
559
560 // Drag text from outside the browser into/over the right frame.
300 { 561 {
301 std::string dragover_event;
302 DOMDragEventWaiter dragover_waiter("dragover", right_frame()); 562 DOMDragEventWaiter dragover_waiter("dragover", right_frame());
303 ASSERT_TRUE(SimulateDragEnterToRightFrame("Dragged test text")); 563 ASSERT_TRUE(SimulateDragEnterToRightFrame("Dragged test text"));
564
565 std::string dragover_event;
304 ASSERT_TRUE(dragover_waiter.WaitForNextMatchingEvent(&dragover_event)); 566 ASSERT_TRUE(dragover_waiter.WaitForNextMatchingEvent(&dragover_event));
305 EXPECT_THAT(dragover_event, testing::HasSubstr("\"drop_effect\":\"none\"")); 567 EXPECT_THAT(dragover_event, expected_dom_event_data.Matches());
306 EXPECT_THAT(dragover_event,
307 testing::HasSubstr("\"effect_allowed\":\"all\""));
308 EXPECT_THAT(dragover_event,
309 testing::HasSubstr("\"mime_types\":\"text/plain\""));
310 } 568 }
311 569
570 // Drop into the right frame.
312 { 571 {
313 std::string drop_event;
314 DOMDragEventWaiter drop_waiter("drop", right_frame()); 572 DOMDragEventWaiter drop_waiter("drop", right_frame());
315 ASSERT_TRUE(SimulateDropInRightFrame()); 573 ASSERT_TRUE(SimulateDropInRightFrame());
574
575 std::string drop_event;
316 ASSERT_TRUE(drop_waiter.WaitForNextMatchingEvent(&drop_event)); 576 ASSERT_TRUE(drop_waiter.WaitForNextMatchingEvent(&drop_event));
317 EXPECT_THAT(drop_event, testing::HasSubstr("\"drop_effect\":\"none\"")); 577 EXPECT_THAT(drop_event, expected_dom_event_data.Matches());
318 EXPECT_THAT(drop_event, testing::HasSubstr("\"effect_allowed\":\"all\""));
319 EXPECT_THAT(drop_event,
320 testing::HasSubstr("\"mime_types\":\"text/plain\""));
321 } 578 }
322 } 579 }
323 580
581 // The test is disabled on Ozone because of trouble with mouse simulation
582 // during the test - see https://crbug.com/665042.
583 #if defined(USE_OZONE)
584 #define MAYBE_DragStartInFrame DISABLED_DragStartInFrame
585 #else
586 #define MAYBE_DragStartInFrame DragStartInFrame
587 #endif
588 IN_PROC_BROWSER_TEST_F(DragAndDropBrowserTest, MAYBE_DragStartInFrame) {
589 std::string frame_site = "b.com";
590 ASSERT_TRUE(NavigateToTestPage("a.com"));
591 ASSERT_TRUE(NavigateLeftFrame(frame_site, "image_source.html"));
592
593 // Setup test expectations.
594 // (dragstart event handler in image_source.html is asking for "copy" only).
595 DOMDragEventVerifier expected_dom_event_data;
596 expected_dom_event_data.set_expected_drop_effect("none");
597 expected_dom_event_data.set_expected_effect_allowed("copy");
598 expected_dom_event_data.set_expected_mime_types(
599 "Files,text/html,text/uri-list");
600
601 // Start the drag in the left frame.
602 DragStartWaiter drag_start_waiter(web_contents());
603 DOMDragEventWaiter dragstart_event_waiter("dragstart", left_frame());
604 EXPECT_TRUE(SimulateMouseDownAndDragStartInLeftFrame());
605
606 // Verify Javascript event data.
607 {
608 std::string dragstart_event;
609 EXPECT_TRUE(
610 dragstart_event_waiter.WaitForNextMatchingEvent(&dragstart_event));
611 EXPECT_THAT(dragstart_event, expected_dom_event_data.Matches());
612 }
613
614 // Verify data being passed to the OS.
615 {
616 std::string text;
617 std::string html;
618 int operation = 0;
619 gfx::Point location_inside_web_contents;
620 EXPECT_TRUE(drag_start_waiter.WaitUntilDragStartIsIntercepted(
sky 2016/11/15 00:37:55 SHould this be an assert? If it fails is there rea
Łukasz Anforowicz 2016/11/15 18:28:21 N/A - after addressing earlier comments WaitUntilD
621 &text, &html, &operation, &location_inside_web_contents));
622 EXPECT_EQ(embedded_test_server()->GetURL(frame_site,
623 "/image_decoding/droids.jpg"),
624 text);
625 EXPECT_THAT(html,
626 testing::MatchesRegex("<img .*src=\""
627 "http://.*/image_decoding/droids.jpg"
628 "\">"));
629 EXPECT_EQ(expected_location_of_drag_start_in_left_frame(),
630 location_inside_web_contents);
631 EXPECT_EQ(ui::DragDropTypes::DRAG_COPY, operation);
632 }
633
634 // Try to leave everything in a clean state.
635 SimulateMouseUp();
636 }
637
324 } // namespace chrome 638 } // namespace chrome
OLDNEW
« no previous file with comments | « chrome/browser/OWNERS ('k') | chrome/test/BUILD.gn » ('j') | chrome/test/BUILD.gn » ('J')

Powered by Google App Engine
This is Rietveld 408576698