[Reland] Display Cutout: Track ViewportFit in WCO

Adds a DisplayCutoutHost mojo interface that is implemented
by WebContentsImpl. When ViewportFitChanged is called by
the renderer we fire the ViewportFitChanged method on
WCO. This allows the browser to change the UI based on
the ViewportFit state.

On the Blink side changes to ViewportFit bubble up through
Document which will call the DisplayCutoutHost Mojo
interface.

BUG=838400

Change-Id: If38efdd14b6bb4652448053424090ce5e48aad5c
Reviewed-on: https://chromium-review.googlesource.com/1093264
Commit-Queue: Becca Hughes <[email protected]>
Reviewed-by: Alex Moshchuk <[email protected]>
Reviewed-by: Daniel Cheng <[email protected]>
Cr-Commit-Position: refs/heads/master@{#565845}
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index e4c5b882..ce464be 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -390,6 +390,54 @@
   blink::mojom::ColorChooserClientPtr client_;
 };
 
+// WebContentsImpl::DisplayCutoutHostImpl --------------------------------------
+
+class WebContentsImpl::DisplayCutoutHostImpl
+    : public blink::mojom::DisplayCutoutHost {
+ public:
+  explicit DisplayCutoutHostImpl(WebContentsImpl* web_contents)
+      : web_contents_(web_contents), bindings_(web_contents, this) {}
+
+  // blink::mojom::DisplayCutoutHost
+  void ViewportFitChanged(blink::mojom::ViewportFit value) override {
+    ViewportFitChangedForFrame(bindings_.GetCurrentTargetFrame(), value);
+  }
+
+  // Stores the updated viewport fit value for a frame and notifies observers if
+  // it has changed.
+  void ViewportFitChangedForFrame(RenderFrameHost* rfh,
+                                  blink::mojom::ViewportFit value) {
+    if (GetValueOrDefault(rfh) == value)
+      return;
+
+    values_[rfh] = value;
+
+    // TODO(beccahughes): Add logic based on fullscreen and orientation to
+    // decide which frame's viewport fit value should be used.
+    for (auto& observer : web_contents_->observers_)
+      observer.ViewportFitChanged(value);
+  }
+
+  // Removes any state built up by a render frame.
+  void RenderFrameDeleted(RenderFrameHost* rfh) { values_.erase(rfh); }
+
+ private:
+  // Get the stored viewport fit value for a frame or kAuto if there is no
+  // stored value.
+  blink::mojom::ViewportFit GetValueOrDefault(RenderFrameHost* rfh) const {
+    auto value = values_.find(rfh);
+    if (value != values_.end())
+      return value->second;
+    return blink::mojom::ViewportFit::kAuto;
+  }
+
+  // Stores a map of RenderFrameHosts and their current viewport fit values.
+  std::map<RenderFrameHost*, blink::mojom::ViewportFit> values_;
+
+  WebContentsImpl* web_contents_;
+  WebContentsFrameBindingSet<blink::mojom::DisplayCutoutHost> bindings_;
+};
+
 // WebContentsImpl::WebContentsTreeNode ----------------------------------------
 WebContentsImpl::WebContentsTreeNode::WebContentsTreeNode(
     WebContentsImpl* current_web_contents)
@@ -543,6 +591,8 @@
   host_zoom_map_observer_.reset(new HostZoomMapObserver(this));
 #endif  // !defined(OS_ANDROID)
 
+  display_cutout_host_impl_ = std::make_unique<DisplayCutoutHostImpl>(this);
+
   registry_.AddInterface(base::BindRepeating(
       &WebContentsImpl::OnColorChooserFactoryRequest, base::Unretained(this)));
 }
@@ -3935,6 +3985,11 @@
       net::IsCertStatusError(navigation_handle->GetSSLInfo().cert_status));
 
   SetNotWaitingForResponse();
+
+  // Reset the viewport fit
+  display_cutout_host_impl_->ViewportFitChangedForFrame(
+      navigation_handle->GetRenderFrameHost(),
+      blink::mojom::ViewportFit::kAuto);
 }
 
 void WebContentsImpl::DidFinishNavigation(NavigationHandle* navigation_handle) {
@@ -4848,6 +4903,7 @@
 #if BUILDFLAG(ENABLE_PLUGINS)
   pepper_playback_observer_->RenderFrameDeleted(render_frame_host);
 #endif
+  display_cutout_host_impl_->RenderFrameDeleted(render_frame_host);
 }
 
 void WebContentsImpl::ShowContextMenu(RenderFrameHost* render_frame_host,