| // Copyright 2018 The Chromium Authors. All rights reserved. |
| // 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 |