|  | // 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/browser/display_cutout/display_cutout_host_impl.h" | 
|  |  | 
|  | #include "content/browser/display_cutout/display_cutout_constants.h" | 
|  | #include "content/browser/display_cutout/safe_area_insets_host.h" | 
|  | #include "content/browser/renderer_host/render_frame_host_impl.h" | 
|  | #include "content/browser/web_contents/web_contents_impl.h" | 
|  | #include "content/public/browser/navigation_handle.h" | 
|  | #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" | 
|  |  | 
|  | namespace content { | 
|  |  | 
|  | DisplayCutoutHostImpl::DisplayCutoutHostImpl(WebContentsImpl* web_contents) | 
|  | : SafeAreaInsetsHost(web_contents) {} | 
|  |  | 
|  | DisplayCutoutHostImpl::~DisplayCutoutHostImpl() = default; | 
|  |  | 
|  | void DisplayCutoutHostImpl::ViewportFitChangedForFrame( | 
|  | RenderFrameHost* rfh, | 
|  | blink::mojom::ViewportFit value) { | 
|  | if (GetValueOrDefault(rfh) == value) | 
|  | return; | 
|  |  | 
|  | values_[rfh] = value; | 
|  |  | 
|  | // If we are the current |RenderFrameHost| frame then notify | 
|  | // WebContentsObservers about the new value. | 
|  | if (current_rfh_.get() == rfh) | 
|  | web_contents_impl_->NotifyViewportFitChanged(value); | 
|  | } | 
|  |  | 
|  | void DisplayCutoutHostImpl::DidAcquireFullscreen(RenderFrameHost* rfh) { | 
|  | SetCurrentRenderFrameHost(rfh); | 
|  | } | 
|  |  | 
|  | void DisplayCutoutHostImpl::DidExitFullscreen() { | 
|  | SetCurrentRenderFrameHost(nullptr); | 
|  | } | 
|  |  | 
|  | void DisplayCutoutHostImpl::DidFinishNavigation( | 
|  | NavigationHandle* navigation_handle) { | 
|  | // If the navigation is not in the main frame or if we are a same document | 
|  | // navigation then we should stop now. | 
|  | if (!navigation_handle->IsInPrimaryMainFrame() || | 
|  | navigation_handle->IsSameDocument()) { | 
|  | return; | 
|  | } | 
|  |  | 
|  | // When Edge To Edge on Android is enabled it needs the messaging sent to | 
|  | // Java. | 
|  | bool is_not_just_fullscreen = | 
|  | base::FeatureList::IsEnabled(features::kDrawCutoutEdgeToEdge); | 
|  |  | 
|  | // If we finish a main frame navigation and the |WebDisplayMode| is | 
|  | // fullscreen then we should make the main frame the current | 
|  | // |RenderFrameHost|.  Note that this is probably not correct; we do not check | 
|  | // that the navigation completed successfully, nor do we check if the main | 
|  | // frame is still IsRenderFrameLive(). | 
|  | blink::mojom::DisplayMode mode = web_contents_impl_->GetDisplayMode(); | 
|  | if (is_not_just_fullscreen || | 
|  | mode == blink::mojom::DisplayMode::kFullscreen) { | 
|  | SetCurrentRenderFrameHost(web_contents_impl_->GetPrimaryMainFrame()); | 
|  | } | 
|  | } | 
|  |  | 
|  | void DisplayCutoutHostImpl::RenderFrameDeleted(RenderFrameHost* rfh) { | 
|  | values_.erase(rfh); | 
|  |  | 
|  | // If we were the current |RenderFrameHost| then we should clear that. | 
|  | if (current_rfh_.get() == rfh) | 
|  | SetCurrentRenderFrameHost(nullptr); | 
|  | } | 
|  |  | 
|  | void DisplayCutoutHostImpl::RenderFrameCreated(RenderFrameHost* rfh) { | 
|  | ViewportFitChangedForFrame(rfh, blink::mojom::ViewportFit::kAuto); | 
|  | } | 
|  |  | 
|  | void DisplayCutoutHostImpl::SetDisplayCutoutSafeArea(gfx::Insets insets) { | 
|  | insets_ = insets; | 
|  |  | 
|  | if (current_rfh_) | 
|  | SendSafeAreaToFrame(current_rfh_.get(), insets); | 
|  | } | 
|  |  | 
|  | void DisplayCutoutHostImpl::SetCurrentRenderFrameHost(RenderFrameHost* rfh) { | 
|  | if (current_rfh_.get() == rfh) { | 
|  | if (rfh) { | 
|  | // Send an update even when navigating to the same page or doing a reload. | 
|  | // When we finish navigation we need to push the Safe Area back to the | 
|  | // client to set env() variables for that frame so it can draw correctly. | 
|  | SendSafeAreaToFrame(rfh, insets_); | 
|  | } | 
|  | return; | 
|  | } | 
|  |  | 
|  | // If we had a previous frame then we should clear the insets on that frame. | 
|  | if (current_rfh_) | 
|  | SendSafeAreaToFrame(current_rfh_.get(), gfx::Insets()); | 
|  |  | 
|  | // If the new RenderFrameHost is nullptr we should stop here and notify | 
|  | // observers that the new viewport fit is kAuto (the default). | 
|  | if (!rfh) { | 
|  | current_rfh_ = nullptr; | 
|  | web_contents_impl_->NotifyViewportFitChanged( | 
|  | blink::mojom::ViewportFit::kAuto); | 
|  | return; | 
|  | } | 
|  |  | 
|  | // Update the |current_rfh_| with the new frame. | 
|  | current_rfh_ = static_cast<RenderFrameHostImpl*>(rfh)->GetWeakPtr(); | 
|  |  | 
|  | // Send the current safe area to the new frame. | 
|  | SendSafeAreaToFrame(rfh, insets_); | 
|  |  | 
|  | // Notify the WebContentsObservers that the viewport fit value has changed. | 
|  | web_contents_impl_->NotifyViewportFitChanged(GetValueOrDefault(rfh)); | 
|  | } | 
|  |  | 
|  | blink::mojom::ViewportFit DisplayCutoutHostImpl::GetValueOrDefault( | 
|  | RenderFrameHost* rfh) const { | 
|  | auto value = values_.find(rfh); | 
|  | if (value != values_.end()) | 
|  | return value->second; | 
|  | return blink::mojom::ViewportFit::kAuto; | 
|  | } | 
|  |  | 
|  | }  // namespace content |