Index: content/browser/site_per_process_browsertest.cc |
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc |
index c8fa716929efe53b4a79d82206f6b7027f69d236..754a60e119883a5c6494cf9cc7bf06f90442cb4b 100644 |
--- a/content/browser/site_per_process_browsertest.cc |
+++ b/content/browser/site_per_process_browsertest.cc |
@@ -20,6 +20,10 @@ |
#include "base/test/test_timeouts.h" |
#include "base/thread_task_runner_handle.h" |
#include "build/build_config.h" |
+#include "cc/surfaces/surface.h" |
+#include "cc/surfaces/surface_manager.h" |
+#include "content/browser/compositor/delegated_frame_host.h" |
+#include "content/browser/compositor/surface_utils.h" |
#include "content/browser/frame_host/cross_process_frame_connector.h" |
#include "content/browser/frame_host/frame_tree.h" |
#include "content/browser/frame_host/navigator.h" |
@@ -51,7 +55,12 @@ |
#include "third_party/WebKit/public/web/WebSandboxFlags.h" |
#include "ui/gfx/switches.h" |
+#if defined(USE_AURA) |
+#include "content/browser/renderer_host/render_widget_host_view_aura.h" |
+#endif |
+ |
#if defined(OS_MACOSX) |
+#include "content/browser/renderer_host/render_widget_host_view_mac.h" |
#include "ui/base/test/scoped_preferred_scroller_style_legacy_mac.h" |
#endif |
@@ -161,6 +170,76 @@ class RenderWidgetHostMouseEventMonitor { |
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostMouseEventMonitor); |
}; |
+// Helper class to assist with hit testing surfaces in multiple processes. |
+// WaitForSurfaceReady() will only return after a Surface from |target_view| |
+// has been composited in the top-level frame's Surface. At that point, |
+// browser process hit testing to target_view's Surface can succeed. |
+class SurfaceHitTestReadyNotifier { |
nasko
2016/02/26 18:33:51
nit: Shouldn't this be in content_browser_test_uti
kenrb
2016/02/26 21:33:19
Done.
|
+ public: |
+ SurfaceHitTestReadyNotifier(RenderWidgetHostViewChildFrame* target_view) |
+ : target_view_(target_view) { |
+ surface_manager_ = GetSurfaceManager(); |
+ } |
+ ~SurfaceHitTestReadyNotifier() {} |
+ |
+ void WaitForSurfaceReady() { |
+ root_surface_id_ = getRootSurfaceId(); |
+ if (containsSurfaceId()) |
+ return; |
+ |
+ while (true) { |
+ // TODO(kenrb): Need a better way to do this. If |
+ // RenderWidgetHostViewBase lifetime observer lands (see |
+ // https://codereview.chromium.org/1711103002/), we can add a callback |
+ // from OnSwapCompositorFrame and avoid this busy waiting, which is very |
+ // frequent in tests in this file. |
+ base::RunLoop run_loop; |
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
+ FROM_HERE, run_loop.QuitClosure(), |
+ base::TimeDelta::FromMilliseconds(10)); |
nasko
2016/02/26 18:33:51
TestTimeouts::tiny_timeout()?
kenrb
2016/02/26 21:33:19
Done.
|
+ run_loop.Run(); |
+ if (containsSurfaceId()) |
+ break; |
+ } |
+ } |
+ |
+ private: |
+ bool containsSurfaceId() { |
nasko
2016/02/26 18:33:51
ContainsSurfaceId
kenrb
2016/02/26 21:33:18
Done.
|
+ if (root_surface_id_.is_null()) |
+ return false; |
+ for (cc::SurfaceId id : surface_manager_->GetSurfaceForId(root_surface_id_) |
+ ->referenced_surfaces()) { |
+ if (id == target_view_->SurfaceIdForTesting()) |
+ return true; |
+ } |
+ return false; |
+ } |
+ |
+ cc::SurfaceId getRootSurfaceId() { |
nasko
2016/02/26 18:33:51
GetRootSurfaceId
kenrb
2016/02/26 21:33:19
This method is removed as part of the refactor.
|
+#if defined(OS_MACOSX) |
+ RenderWidgetHostViewMac* root_view = static_cast<RenderWidgetHostViewMac*>( |
+ target_view_->FrameConnectorForTesting() |
+ ->GetRootRenderWidgetHostViewForTesting()); |
+ return root_view->delegated_frame_host_->SurfaceIdForTesting(); |
+#elif defined(USE_AURA) |
+ RenderWidgetHostViewAura* root_view = |
+ static_cast<RenderWidgetHostViewAura*>( |
+ target_view_->FrameConnectorForTesting() |
+ ->GetRootRenderWidgetHostViewForTesting()); |
+ return root_view->GetDelegatedFrameHostForTesting()->SurfaceIdForTesting(); |
+#else |
+ return cc::SurfaceId(); |
+#endif |
+ } |
+ |
+ cc::SurfaceManager* surface_manager_; |
+ cc::SurfaceId root_surface_id_; |
+ RenderWidgetHostViewChildFrame* target_view_; |
+ base::Closure quit_; |
nasko
2016/02/26 18:33:51
Unused?
kenrb
2016/02/26 21:33:18
Done.
|
+ |
+ DISALLOW_COPY_AND_ASSIGN(SurfaceHitTestReadyNotifier); |
+}; |
+ |
// Helper function that performs a surface hittest. |
void SurfaceHitTestTestHelper( |
Shell* shell, |
@@ -196,20 +275,6 @@ void SurfaceHitTestTestHelper( |
RenderWidgetHostViewBase* rwhv_child = static_cast<RenderWidgetHostViewBase*>( |
child_node->current_frame_host()->GetRenderWidgetHost()->GetView()); |
- // We need to wait for a compositor frame from the child frame, at which |
- // point its surface will be created. |
- while (rwhv_child->RendererFrameNumber() <= 0) { |
- // TODO(lazyboy): Find a better way to avoid sleeping like this. See |
- // http://crbug.com/405282 for details. |
- base::RunLoop run_loop; |
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
- FROM_HERE, run_loop.QuitClosure(), |
- base::TimeDelta::FromMilliseconds(10)); |
- run_loop.Run(); |
- } |
- |
- uint32_t cur_render_frame_number = root_view->RendererFrameNumber(); |
- |
// Target input event to child frame. |
blink::WebMouseEvent child_event; |
child_event.type = blink::WebInputEvent::MouseDown; |
@@ -221,31 +286,9 @@ void SurfaceHitTestTestHelper( |
child_frame_monitor.ResetEventReceived(); |
router->RouteMouseEvent(root_view, &child_event); |
- while (!child_frame_monitor.EventWasReceived()) { |
- // This is working around a big synchronization problem. It is very |
- // difficult to know if we have received a compositor frame from the |
- // main frame renderer *after* it received the child frame's surface |
- // ID. Hit testing won't work until this happens. So if the hit test |
- // fails then we wait for another frame to arrive and try again. |
- // TODO(kenrb): We need a better way to do all of this, possibly coming |
- // from http://crbug.com/405282. |
- while (root_view->RendererFrameNumber() <= cur_render_frame_number) { |
- base::RunLoop run_loop; |
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
- FROM_HERE, run_loop.QuitClosure(), |
- base::TimeDelta::FromMilliseconds(10)); |
- run_loop.Run(); |
- } |
- cur_render_frame_number = root_view->RendererFrameNumber(); |
- child_event.type = blink::WebInputEvent::MouseDown; |
- child_event.button = blink::WebPointerProperties::ButtonLeft; |
- child_event.x = 75; |
- child_event.y = 75; |
- child_event.clickCount = 1; |
- main_frame_monitor.ResetEventReceived(); |
- child_frame_monitor.ResetEventReceived(); |
- router->RouteMouseEvent(root_view, &child_event); |
- } |
+ SurfaceHitTestReadyNotifier notifier( |
+ static_cast<RenderWidgetHostViewChildFrame*>(rwhv_child)); |
+ notifier.WaitForSurfaceReady(); |
EXPECT_TRUE(child_frame_monitor.EventWasReceived()); |
EXPECT_EQ(23, child_frame_monitor.event().x); |
@@ -823,17 +866,9 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, |
RenderWidgetHostViewBase* rwhv_child = static_cast<RenderWidgetHostViewBase*>( |
child_node->current_frame_host()->GetRenderWidgetHost()->GetView()); |
- // We need to wait for a compositor frame from the child frame, at which |
- // point its surface will be created. |
- while (rwhv_child->RendererFrameNumber() <= 0) { |
- // TODO(lazyboy): Find a better way to avoid sleeping like this. See |
- // http://crbug.com/405282 for details. |
- base::RunLoop run_loop; |
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
- FROM_HERE, run_loop.QuitClosure(), |
- base::TimeDelta::FromMilliseconds(10)); |
- run_loop.Run(); |
- } |
+ SurfaceHitTestReadyNotifier notifier( |
+ static_cast<RenderWidgetHostViewChildFrame*>(rwhv_child)); |
+ notifier.WaitForSurfaceReady(); |
// Target input event to child frame. |
blink::WebMouseEvent child_event; |