Chromium Code Reviews| Index: chrome/browser/drag_and_drop_browsertest.cc |
| diff --git a/content/browser/web_contents/drag_and_drop_browsertest.cc b/chrome/browser/drag_and_drop_browsertest.cc |
| similarity index 40% |
| rename from content/browser/web_contents/drag_and_drop_browsertest.cc |
| rename to chrome/browser/drag_and_drop_browsertest.cc |
| index 71dfc4765bd61ba0b812ee8707e666878c31d0e8..d706d7d9a9e4f15d1d3c5a0dc95ac0a4a03cf3aa 100644 |
| --- a/content/browser/web_contents/drag_and_drop_browsertest.cc |
| +++ b/chrome/browser/drag_and_drop_browsertest.cc |
| @@ -5,27 +5,33 @@ |
| #include <memory> |
| #include <string> |
| +#include "base/callback.h" |
| #include "base/macros.h" |
| +#include "base/memory/ref_counted.h" |
| +#include "base/sequenced_task_runner.h" |
| #include "base/strings/pattern.h" |
| #include "base/strings/string_piece.h" |
| #include "base/strings/stringprintf.h" |
| #include "base/strings/utf_string_conversions.h" |
| -#include "content/browser/frame_host/frame_tree.h" |
| -#include "content/browser/frame_host/frame_tree_node.h" |
| -#include "content/browser/frame_host/render_frame_host_impl.h" |
| -#include "content/browser/web_contents/web_contents_impl.h" |
| +#include "base/threading/sequenced_task_runner_handle.h" |
| +#include "chrome/browser/ui/browser.h" |
| +#include "chrome/browser/ui/tabs/tab_strip_model.h" |
| +#include "chrome/test/base/in_process_browser_test.h" |
| +#include "chrome/test/base/interactive_test_utils.h" |
| +#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/test/browser_test_utils.h" |
| #include "content/public/test/content_browser_test.h" |
| #include "content/public/test/content_browser_test_utils.h" |
| +#include "content/public/test/test_frame_navigation_observer.h" |
| #include "content/public/test/test_utils.h" |
| -#include "content/shell/browser/shell.h" |
| #include "net/base/escape.h" |
| #include "net/dns/mock_host_resolver.h" |
| #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" |
| @@ -36,7 +42,7 @@ |
| #include "ui/gfx/geometry/rect.h" |
| #include "url/gurl.h" |
| -namespace content { |
| +namespace chrome { |
| namespace { |
| @@ -63,14 +69,11 @@ namespace { |
| // - Unknowns: |
| // |
| // - Will this work for WebView and Plugin testing. |
| -// |
| -// - Will this work for simulating dragging from WebContents into outside of |
| -// the browser (without leaving OS drag&drop machinery in a weird state). |
| // Test helper for simulating drag and drop happening in WebContents. |
| class DragAndDropSimulator { |
| public: |
| - explicit DragAndDropSimulator(WebContents* web_contents) |
| + explicit DragAndDropSimulator(content::WebContents* web_contents) |
| : web_contents_(web_contents) {} |
| // Simulates notification that |text| was dragged from outside of the browser, |
| @@ -157,30 +160,139 @@ class DragAndDropSimulator { |
| ui::DragDropTypes::DRAG_COPY | |
| ui::DragDropTypes::DRAG_LINK; |
| - WebContents* web_contents_; |
| + 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 { |
| + public: |
| + // Starts monitoring |web_contents| for a start of a drag-and-drop. |
| + // While alive, prevents a real, OS-level drag-and-drop from starting |
| + // for this particular |web_contents|. |
| + explicit DragStartWaiter(content::WebContents* web_contents) |
| + : web_contents_(web_contents), |
| + message_loop_runner_(new content::MessageLoopRunner), |
| + 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); |
| + } |
| + |
| + ~DragStartWaiter() override { |
| + // Restore the original DragDropClient. |
| + gfx::NativeWindow root_window = |
| + web_contents_->GetContentNativeView()->GetRootWindow(); |
| + aura::client::SetDragDropClient(root_window, old_client_); |
| + } |
| + |
| + // Waits until we almost report a drag-and-drop start to the OS |
| + // (notifying the OS will be prevented to help the test continue |
| + // without entering a nested message loop). |
| + // |
| + // Returns true if drag and drop has indeed started (and in this |
| + // case populates |text|, |html| and other parameters with data |
| + // that would have been passed to the OS). |
| + bool WaitUntilDragStartIsIntercepted( |
| + std::string* text, |
| + std::string* html, |
| + int* operation, |
| + gfx::Point* location_inside_web_contents) { |
| + message_loop_runner_->Run(); |
| + |
| + if (!drag_started_) |
| + return false; |
| + |
| + *text = text_; |
| + *html = html_; |
| + *operation = operation_; |
| + *location_inside_web_contents = location_inside_web_contents_; |
| + return true; |
| + } |
| + |
|
ncarter (slow)
2016/11/11 20:56:36
// aura::client::DragDropClient:
Łukasz Anforowicz
2016/11/14 17:53:22
Done.
|
| + 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 { |
| + if (!drag_started_) { |
| + drag_started_ = true; |
| + 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; |
| + } |
| + |
| + // Forwarding to |old_client_| is undesirable, because test cannot control |
| + // next steps after a nested drag-and-drop loop is entered at the OS level |
| + // (as is the case in Windows, via DoDragDrop). Instead, in the test we |
| + // kind of ignore renderer's request to start drag and drop and never |
| + // forward this request to the OS-specific layers. |
| + return 0; |
| + } |
| + |
| + 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_; |
| + |
| + // 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_; |
| +}; |
| + |
| // Helper for waiting for notifications from |
| // content/test/data/drag_and_drop/event_monitoring.js |
| class DOMDragEventWaiter { |
| public: |
| explicit DOMDragEventWaiter(const std::string& event_type_to_wait_for, |
| - const ToRenderFrameHost& target) |
| + const content::ToRenderFrameHost& target) |
| : target_frame_name_(target.render_frame_host()->GetFrameName()), |
| event_type_to_wait_for_(event_type_to_wait_for), |
| - dom_message_queue_( |
| - WebContents::FromRenderFrameHost(target.render_frame_host())) {} |
| + dom_message_queue_(content::WebContents::FromRenderFrameHost( |
| + target.render_frame_host())) {} |
| // Waits until |target| calls reportDragEvent in |
| - // content/test/data/drag_and_drop/event_monitoring.js with event_type |
| + // chrome/test/data/drag_and_drop/event_monitoring.js with event_type |
| // property set to |event_type_to_wait_for|. (|target| and |
| // |event_type_to_wait_for| are passed to the constructor). |
| // |
| // Returns the event details via |found_event| (in form of a JSON-encoded |
| - // object). See content/test/data/drag_and_drop/event_monitoring.js for keys |
| + // object). See chrome/test/data/drag_and_drop/event_monitoring.js for keys |
| // and properties that |found_event| is expected to have. |
| // |
| // Returns true upon success. It is okay if |response| is null. |
| @@ -210,14 +322,57 @@ class DOMDragEventWaiter { |
| private: |
| std::string target_frame_name_; |
| std::string event_type_to_wait_for_; |
| - DOMMessageQueue dom_message_queue_; |
| + content::DOMMessageQueue dom_message_queue_; |
| +}; |
| + |
| +// Helper for verifying contents of DOM events associated with drag-and-drop. |
| +class DOMDragEventVerifier { |
| + public: |
| + DOMDragEventVerifier(){}; |
| + |
| + void set_expected_drop_effect(const std::string& value) { |
| + expected_drop_effect_ = value; |
| + } |
| + |
| + void set_expected_effect_allowed(const std::string& value) { |
| + expected_effect_allowed_ = value; |
| + } |
| + |
| + void set_expected_mime_types(const std::string& value) { |
| + expected_mime_types_ = value; |
| + } |
| + |
| + // Returns a matcher that will match a std::string (drag event data - e.g. |
| + // one returned by DOMDragEventWaiter::WaitForNextMatchingEvent) if it matches |
| + // the expectations of this DOMDragEventVerifier. |
| + testing::Matcher<std::string> Matches() const { |
| + return testing::AllOf( |
| + FieldMatches("drop_effect", expected_drop_effect_), |
| + FieldMatches("effect_allowed", expected_effect_allowed_), |
| + FieldMatches("mime_types", expected_mime_types_)); |
| + } |
| + |
| + private: |
| + static testing::Matcher<std::string> FieldMatches( |
| + const std::string& field_name, |
| + const std::string& expected_value) { |
| + if (expected_value == "<no expectation>") |
| + return testing::A<std::string>(); |
| + |
| + return testing::HasSubstr(base::StringPrintf( |
| + "\"%s\":\"%s\"", field_name.c_str(), expected_value.c_str())); |
| + } |
| + |
| + std::string expected_drop_effect_ = "<no expectation>"; |
| + std::string expected_effect_allowed_ = "<no expectation>"; |
| + std::string expected_mime_types_ = "<no expectation>"; |
| }; |
| const char kTestPagePath[] = "/drag_and_drop/page.html"; |
| } // namespace |
| -class DragAndDropBrowserTest : public ContentBrowserTest { |
| +class DragAndDropBrowserTest : public InProcessBrowserTest { |
| public: |
| DragAndDropBrowserTest(){}; |
| @@ -226,35 +381,74 @@ class DragAndDropBrowserTest : public ContentBrowserTest { |
| host_resolver()->AddRule("*", "127.0.0.1"); |
| ASSERT_TRUE(embedded_test_server()->Start()); |
| content::SetupCrossSiteRedirector(embedded_test_server()); |
| - drag_simulator_.reset(new DragAndDropSimulator(shell()->web_contents())); |
| + drag_simulator_.reset(new DragAndDropSimulator(web_contents())); |
| } |
| - // Navigates to content/test/data/drag_and_drop/page.html, with page origin |
| - // and frame contents being controlled by the parameters. |
| - bool NavigateToTestPage(const std::string& main_origin, |
| - const std::string& left_frame, |
| - const std::string& right_frame) { |
| - GURL base_url = embedded_test_server()->GetURL(main_origin, kTestPagePath); |
| + content::RenderFrameHost* left_frame() { |
| + AssertTestPageIsLoaded(); |
| + return GetFrameByName("left"); |
| + } |
| - std::string left_arg; |
| - if (!left_frame.empty()) { |
| - left_arg = net::EscapeQueryParamValue( |
| - std::string("/cross-site/") + left_frame, true); |
| - } |
| - std::string right_arg; |
| - if (!right_frame.empty()) { |
| - right_arg = net::EscapeQueryParamValue( |
| - std::string("/cross-site/") + right_frame, true); |
| - } |
| - std::string query = base::StringPrintf("left=%s&right=%s", left_arg.c_str(), |
| - right_arg.c_str()); |
| - GURL::Replacements query_replacement; |
| - query_replacement.SetQueryStr(query); |
| - GURL target_url = base_url.ReplaceComponents(query_replacement); |
| + content::RenderFrameHost* right_frame() { |
| + AssertTestPageIsLoaded(); |
| + return GetFrameByName("right"); |
| + } |
| - return NavigateToURL(shell(), target_url); |
| + content::WebContents* web_contents() { |
| + return browser()->tab_strip_model()->GetActiveWebContents(); |
| + } |
| + |
| + ////////////////////// |
| + // Navigation helpers. |
| + |
| + bool NavigateToTestPage(const std::string& origin_of_main_frame) { |
| + GURL url = |
| + embedded_test_server()->GetURL(origin_of_main_frame, kTestPagePath); |
| + ui_test_utils::NavigateToURL(browser(), url); |
| + return web_contents()->GetLastCommittedURL() == url; |
| + } |
| + |
| + // Navigates the left frame to |filename| (found under |
| + // chrome/test/data/drag_and_drop directory). |
| + bool NavigateLeftFrame(const std::string& origin, |
| + const std::string& filename) { |
| + AssertTestPageIsLoaded(); |
| + return NavigateNamedFrame("left", origin, filename); |
| } |
| + // Navigates the right frame to |filename| (found under |
| + // chrome/test/data/drag_and_drop directory). |
| + bool NavigateRightFrame(const std::string& origin, |
| + const std::string& filename) { |
| + AssertTestPageIsLoaded(); |
| + return NavigateNamedFrame("right", origin, filename); |
| + } |
| + |
| + //////////////////////////////////////////////////////////// |
| + // Simulation of starting a drag-and-drop (using the mouse). |
| + |
| + bool SimulateMouseDownAndDragStartInLeftFrame() { |
| + AssertTestPageIsLoaded(); |
| + if (!SimulateMouseMove(kMiddleOfLeftFrame) || !SimulateMouseDown() || |
| + !SimulateMouseMove(expected_location_of_drag_start_in_left_frame())) |
| + return false; |
| + |
| + return true; |
| + } |
| + |
| + gfx::Point expected_location_of_drag_start_in_left_frame() { |
| + return kMiddleOfLeftFrame + gfx::Vector2d(5, 5); |
| + } |
| + |
| + bool SimulateMouseUp() { |
| + return ui_test_utils::SendMouseEventsSync(ui_controls::LEFT, |
| + 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); |
| @@ -265,22 +459,78 @@ class DragAndDropBrowserTest : public ContentBrowserTest { |
| return drag_simulator_->SimulateDrop(kMiddleOfRightFrame); |
| } |
| - RenderFrameHost* right_frame() { |
| - AssertTestPageIsLoaded(); |
| - return GetFrameByName("right"); |
| + private: |
| + bool SimulateMouseDown() { |
| + return ui_test_utils::SendMouseEventsSync(ui_controls::LEFT, |
| + ui_controls::DOWN); |
| } |
| - private: |
| - RenderFrameHost* GetFrameByName(const std::string& name_to_find) { |
| - WebContentsImpl* web_contents = |
| - static_cast<WebContentsImpl*>(shell()->web_contents()); |
| - FrameTree* frame_tree = web_contents->GetFrameTree(); |
| - return frame_tree->FindByName(name_to_find)->current_frame_host(); |
| + 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())); |
| + } |
| + |
| + bool NavigateNamedFrame(const std::string& frame_name, |
| + const std::string& origin, |
| + const std::string& filename) { |
| + content::RenderFrameHost* frame = GetFrameByName(frame_name); |
| + if (!frame) |
| + return false; |
| + |
| + std::string script; |
| + int response = 0; |
| + |
| + // Navigate the frame and wait for the load event. |
| + script = base::StringPrintf( |
| + "location.href = '/cross-site/%s/drag_and_drop/%s';\n" |
| + "setTimeout(function() { domAutomationController.send(42); }, 0);", |
| + origin.c_str(), filename.c_str()); |
| + content::TestFrameNavigationObserver observer(frame); |
| + if (!content::ExecuteScriptAndExtractInt(frame, script, &response)) |
| + return false; |
| + if (response != 42) |
| + return false; |
| + observer.Wait(); |
| + |
| + // Wait until frame contents (e.g. images) have painted (which should happen |
| + // in the animation frame that *starts* after the onload event - therefore |
| + // we need to wait for 2 animation frames). |
| + script = std::string( |
| + "requestAnimationFrame(function() {\n" |
| + " requestAnimationFrame(function() {\n" |
| + " domAutomationController.send(43);\n" |
| + " });\n" |
| + "});\n"); |
| + if (!content::ExecuteScriptAndExtractInt(frame, script, &response)) |
| + return false; |
| + if (response != 43) |
| + return false; |
| + |
| + return true; |
| + } |
| + |
| + content::RenderFrameHost* GetFrameByName(const std::string& name_to_find) { |
| + content::RenderFrameHost* result = nullptr; |
| + for (content::RenderFrameHost* rfh : web_contents()->GetAllFrames()) { |
| + if (rfh->GetFrameName() == name_to_find) { |
| + if (result) { |
| + ADD_FAILURE() << "More than one frame named " |
| + << "'" << name_to_find << "'"; |
| + return nullptr; |
| + } |
| + result = rfh; |
| + } |
| + } |
| + |
| + EXPECT_TRUE(result) << "Couldn't find a frame named " |
| + << "'" << name_to_find << "'"; |
| + return result; |
| } |
| void AssertTestPageIsLoaded() { |
| - ASSERT_EQ(kTestPagePath, |
| - shell()->web_contents()->GetLastCommittedURL().path()); |
| + ASSERT_EQ(kTestPagePath, web_contents()->GetLastCommittedURL().path()); |
| } |
| std::unique_ptr<DragAndDropSimulator> drag_simulator_; |
| @@ -293,32 +543,89 @@ class DragAndDropBrowserTest : public ContentBrowserTest { |
| }; |
| IN_PROC_BROWSER_TEST_F(DragAndDropBrowserTest, DropTextFromOutside) { |
| - ASSERT_TRUE(NavigateToTestPage("a.com", |
| - "", // Left frame is unused by this test. |
| - "c.com/drag_and_drop/drop_target.html")); |
| + ASSERT_TRUE(NavigateToTestPage("a.com")); |
| + ASSERT_TRUE(NavigateRightFrame("b.com", "drop_target.html")); |
| + // Setup test expectations. |
| + DOMDragEventVerifier expected_dom_event_data; |
| + expected_dom_event_data.set_expected_drop_effect("none"); |
| + expected_dom_event_data.set_expected_effect_allowed("all"); |
| + expected_dom_event_data.set_expected_mime_types("text/plain"); |
| + |
| + // Drag text from outside the browser into/over the right frame. |
| { |
| - std::string dragover_event; |
| DOMDragEventWaiter dragover_waiter("dragover", right_frame()); |
| ASSERT_TRUE(SimulateDragEnterToRightFrame("Dragged test text")); |
| + |
| + std::string dragover_event; |
| ASSERT_TRUE(dragover_waiter.WaitForNextMatchingEvent(&dragover_event)); |
| - EXPECT_THAT(dragover_event, testing::HasSubstr("\"drop_effect\":\"none\"")); |
| - EXPECT_THAT(dragover_event, |
| - testing::HasSubstr("\"effect_allowed\":\"all\"")); |
| - EXPECT_THAT(dragover_event, |
| - testing::HasSubstr("\"mime_types\":\"text/plain\"")); |
| + EXPECT_THAT(dragover_event, expected_dom_event_data.Matches()); |
| } |
| + // Drop into the right frame. |
| { |
| - std::string drop_event; |
| DOMDragEventWaiter drop_waiter("drop", right_frame()); |
| ASSERT_TRUE(SimulateDropInRightFrame()); |
| + |
| + std::string drop_event; |
| ASSERT_TRUE(drop_waiter.WaitForNextMatchingEvent(&drop_event)); |
| - EXPECT_THAT(drop_event, testing::HasSubstr("\"drop_effect\":\"none\"")); |
| - EXPECT_THAT(drop_event, testing::HasSubstr("\"effect_allowed\":\"all\"")); |
| - EXPECT_THAT(drop_event, |
| - testing::HasSubstr("\"mime_types\":\"text/plain\"")); |
| + EXPECT_THAT(drop_event, expected_dom_event_data.Matches()); |
| + } |
| +} |
| + |
| +#if defined(USE_OZONE) |
|
ncarter (slow)
2016/11/11 20:56:36
Add a comment explaining why this is disabled in o
Łukasz Anforowicz
2016/11/14 17:53:22
Done. I've opened https://crbug.com/665042. I th
|
| +#define MAYBE_DragStartInFrame DISABLED_DragStartInFrame |
| +#else |
| +#define MAYBE_DragStartInFrame DragStartInFrame |
| +#endif |
| +IN_PROC_BROWSER_TEST_F(DragAndDropBrowserTest, MAYBE_DragStartInFrame) { |
| + std::string frame_site = "b.com"; |
| + ASSERT_TRUE(NavigateToTestPage("a.com")); |
| + ASSERT_TRUE(NavigateLeftFrame(frame_site, "image_source.html")); |
| + |
| + // Setup test expectations. |
| + // (dragstart event handler in image_source.html is asking for "copy" only). |
| + DOMDragEventVerifier expected_dom_event_data; |
| + expected_dom_event_data.set_expected_drop_effect("none"); |
| + expected_dom_event_data.set_expected_effect_allowed("copy"); |
| + expected_dom_event_data.set_expected_mime_types( |
| + "Files,text/html,text/uri-list"); |
| + |
| + // Start the drag in the left frame. |
| + DragStartWaiter drag_start_waiter(web_contents()); |
| + DOMDragEventWaiter dragstart_event_waiter("dragstart", left_frame()); |
| + EXPECT_TRUE(SimulateMouseDownAndDragStartInLeftFrame()); |
| + |
| + // Verify Javascript event data. |
| + { |
| + std::string dragstart_event; |
| + EXPECT_TRUE( |
| + dragstart_event_waiter.WaitForNextMatchingEvent(&dragstart_event)); |
| + EXPECT_THAT(dragstart_event, expected_dom_event_data.Matches()); |
| + } |
| + |
| + // Verify data being passed to the OS. |
| + { |
| + std::string text; |
| + std::string html; |
| + int operation = 0; |
| + gfx::Point location_inside_web_contents; |
| + EXPECT_TRUE(drag_start_waiter.WaitUntilDragStartIsIntercepted( |
| + &text, &html, &operation, &location_inside_web_contents)); |
| + EXPECT_EQ(embedded_test_server()->GetURL(frame_site, |
| + "/image_decoding/droids.jpg"), |
| + text); |
| + EXPECT_THAT(html, |
| + testing::MatchesRegex("<img .*src=\"" |
| + "http://.*:.*/image_decoding/droids.jpg" |
|
ncarter (slow)
2016/11/11 20:56:36
Technically this could fail if the testserver happ
Łukasz Anforowicz
2016/11/14 17:53:22
I guess I can get rid of the colon - this will sim
|
| + "\">")); |
| + EXPECT_EQ(expected_location_of_drag_start_in_left_frame(), |
| + location_inside_web_contents); |
| + EXPECT_EQ(ui::DragDropTypes::DRAG_COPY, operation); |
| } |
| + |
| + // Try to leave everything in a clean state. |
| + SimulateMouseUp(); |
| } |
| } // namespace chrome |