1 // Copyright 2018 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "content/public/test/hit_test_region_observer.h" 6 7 #include <algorithm> 8 9 #include "base/test/test_timeouts.h" 10 #include "components/viz/host/hit_test/hit_test_query.h" 11 #include "components/viz/host/host_frame_sink_manager.h" 12 #include "content/browser/compositor/surface_utils.h" 13 #include "content/browser/renderer_host/render_frame_host_impl.h" 14 #include "content/browser/renderer_host/render_widget_host_impl.h" 15 #include "content/browser/renderer_host/render_widget_host_view_base.h" 16 #include "content/browser/renderer_host/render_widget_host_view_child_frame.h" 17 #include "content/browser/web_contents/web_contents_impl.h" 18 #include "content/public/browser/render_frame_host.h" 19 #include "content/public/browser/web_contents.h" 20 #include "content/public/test/browser_test_utils.h" 21 22 namespace content { 23 WaitForHitTestData(RenderFrameHost * child_frame)24void WaitForHitTestData(RenderFrameHost* child_frame) { 25 RenderWidgetHostViewBase* child_view = 26 static_cast<RenderFrameHostImpl*>(child_frame) 27 ->GetRenderWidgetHost() 28 ->GetView(); 29 30 HitTestRegionObserver observer(child_view->GetFrameSinkId()); 31 observer.WaitForHitTestData(); 32 } 33 WaitForHitTestData(WebContents * guest_web_contents)34void WaitForHitTestData(WebContents* guest_web_contents) { 35 DCHECK(static_cast<RenderWidgetHostViewBase*>( 36 guest_web_contents->GetRenderWidgetHostView()) 37 ->IsRenderWidgetHostViewChildFrame()); 38 RenderWidgetHostViewChildFrame* child_view = 39 static_cast<RenderWidgetHostViewChildFrame*>( 40 guest_web_contents->GetRenderWidgetHostView()); 41 42 HitTestRegionObserver observer(child_view->GetFrameSinkId()); 43 observer.WaitForHitTestData(); 44 } 45 HitTestRegionObserver(const viz::FrameSinkId & frame_sink_id)46HitTestRegionObserver::HitTestRegionObserver( 47 const viz::FrameSinkId& frame_sink_id) 48 : frame_sink_id_(frame_sink_id) { 49 CHECK(frame_sink_id.is_valid()); 50 GetHostFrameSinkManager()->AddHitTestRegionObserver(this); 51 } 52 ~HitTestRegionObserver()53HitTestRegionObserver::~HitTestRegionObserver() { 54 GetHostFrameSinkManager()->RemoveHitTestRegionObserver(this); 55 } 56 WaitForHitTestData()57void HitTestRegionObserver::WaitForHitTestData() { 58 DCHECK(cached_hit_test_data_.empty()); 59 60 for (auto& it : GetHostFrameSinkManager()->display_hit_test_query()) { 61 if (it.second->ContainsActiveFrameSinkId(frame_sink_id_)) { 62 cached_hit_test_data_ = it.second->GetHitTestData(); 63 return; 64 } 65 } 66 67 run_loop_ = std::make_unique<base::RunLoop>(); 68 run_loop_->Run(); 69 run_loop_.reset(); 70 } 71 WaitForHitTestDataChange()72void HitTestRegionObserver::WaitForHitTestDataChange() { 73 DCHECK(!cached_hit_test_data_.empty()); 74 75 for (auto& it : GetHostFrameSinkManager()->display_hit_test_query()) { 76 DCHECK(it.second->ContainsActiveFrameSinkId(frame_sink_id_)); 77 if (it.second->GetHitTestData() != cached_hit_test_data_) { 78 cached_hit_test_data_ = it.second->GetHitTestData(); 79 return; 80 } 81 } 82 83 hit_test_data_change_run_loop_ = std::make_unique<base::RunLoop>(); 84 hit_test_data_change_run_loop_->Run(); 85 hit_test_data_change_run_loop_.reset(); 86 } 87 OnAggregatedHitTestRegionListUpdated(const viz::FrameSinkId & frame_sink_id,const std::vector<viz::AggregatedHitTestRegion> & hit_test_data)88void HitTestRegionObserver::OnAggregatedHitTestRegionListUpdated( 89 const viz::FrameSinkId& frame_sink_id, 90 const std::vector<viz::AggregatedHitTestRegion>& hit_test_data) { 91 if (hit_test_data_change_run_loop_ && 92 cached_hit_test_data_ != hit_test_data) { 93 cached_hit_test_data_ = hit_test_data; 94 hit_test_data_change_run_loop_->Quit(); 95 } 96 97 if (!run_loop_) 98 return; 99 100 for (auto& it : hit_test_data) { 101 if (it.frame_sink_id == frame_sink_id_ && 102 !(it.flags & viz::HitTestRegionFlags::kHitTestNotActive)) { 103 run_loop_->Quit(); 104 return; 105 } 106 } 107 } 108 109 const std::vector<viz::AggregatedHitTestRegion>& GetHitTestData()110HitTestRegionObserver::GetHitTestData() { 111 const auto& hit_test_query_map = 112 GetHostFrameSinkManager()->display_hit_test_query(); 113 const auto iter = hit_test_query_map.find(frame_sink_id_); 114 DCHECK(iter != hit_test_query_map.end()); 115 return iter->second.get()->GetHitTestData(); 116 } 117 118 } // namespace content 119