// Copyright 2018 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "content/public/test/hit_test_region_observer.h" #include <algorithm> #include "base/test/test_timeouts.h" #include "components/viz/host/hit_test/hit_test_query.h" #include "components/viz/host/host_frame_sink_manager.h" #include "content/browser/compositor/surface_utils.h" #include "content/browser/renderer_host/render_frame_host_impl.h" #include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/browser/renderer_host/render_widget_host_view_base.h" #include "content/browser/renderer_host/render_widget_host_view_child_frame.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test_utils.h" namespace content { void WaitForHitTestData(RenderFrameHost* child_frame) { RenderWidgetHostViewBase* child_view = static_cast<RenderFrameHostImpl*>(child_frame) ->GetRenderWidgetHost() ->GetView(); HitTestRegionObserver observer(child_view->GetFrameSinkId()); observer.WaitForHitTestData(); } void WaitForHitTestData(WebContents* guest_web_contents) { DCHECK(static_cast<RenderWidgetHostViewBase*>( guest_web_contents->GetRenderWidgetHostView()) ->IsRenderWidgetHostViewChildFrame()); RenderWidgetHostViewChildFrame* child_view = static_cast<RenderWidgetHostViewChildFrame*>( guest_web_contents->GetRenderWidgetHostView()); HitTestRegionObserver observer(child_view->GetFrameSinkId()); observer.WaitForHitTestData(); } HitTestRegionObserver::HitTestRegionObserver( const viz::FrameSinkId& frame_sink_id) : frame_sink_id_(frame_sink_id) { CHECK(frame_sink_id.is_valid()); GetHostFrameSinkManager()->AddHitTestRegionObserver(this); } HitTestRegionObserver::~HitTestRegionObserver() { GetHostFrameSinkManager()->RemoveHitTestRegionObserver(this); } void HitTestRegionObserver::WaitForHitTestData() { DCHECK(cached_hit_test_data_.empty()); for (auto& it : GetHostFrameSinkManager()->display_hit_test_query()) { if (it.second->ContainsActiveFrameSinkId(frame_sink_id_)) { cached_hit_test_data_ = it.second->GetHitTestData(); return; } } run_loop_ = std::make_unique<base::RunLoop>(); run_loop_->Run(); run_loop_.reset(); } void HitTestRegionObserver::WaitForHitTestDataChange() { DCHECK(!cached_hit_test_data_.empty()); for (auto& it : GetHostFrameSinkManager()->display_hit_test_query()) { DCHECK(it.second->ContainsActiveFrameSinkId(frame_sink_id_)); if (it.second->GetHitTestData() != cached_hit_test_data_) { cached_hit_test_data_ = it.second->GetHitTestData(); return; } } hit_test_data_change_run_loop_ = std::make_unique<base::RunLoop>(); hit_test_data_change_run_loop_->Run(); hit_test_data_change_run_loop_.reset(); } void HitTestRegionObserver::OnAggregatedHitTestRegionListUpdated( const viz::FrameSinkId& frame_sink_id, const std::vector<viz::AggregatedHitTestRegion>& hit_test_data) { if (hit_test_data_change_run_loop_ && cached_hit_test_data_ != hit_test_data) { cached_hit_test_data_ = hit_test_data; hit_test_data_change_run_loop_->Quit(); } if (!run_loop_) return; for (auto& it : hit_test_data) { if (it.frame_sink_id == frame_sink_id_ && !(it.flags & viz::HitTestRegionFlags::kHitTestNotActive)) { run_loop_->Quit(); return; } } } const std::vector<viz::AggregatedHitTestRegion>& HitTestRegionObserver::GetHitTestData() { const auto& hit_test_query_map = GetHostFrameSinkManager()->display_hit_test_query(); const auto iter = hit_test_query_map.find(frame_sink_id_); DCHECK(iter != hit_test_query_map.end()); return iter->second.get()->GetHitTestData(); } } // namespace content