Move window closing out of WebWidgetClient.

JS can request to close a window even if there is no main frame in the
process, in which case it goes to the WebView and needs to get to the
browser to land at the main frame's RenderViewHost.

Currently this goes through WebWidgetClient but we don't want a
WebWidgetClient to *exist* when there's no local main frame - as that
would be a frozen RenderWidget. So we move it from WebWidgetClient to
two places:
- WebViewClient for frames
- WebPagePopupClient for popups

The IPC moves from WidgetHostMsg to ViewHostMsg and is captured
directly in RenderViewHost instead of going through the owner delegate.

[email protected], [email protected]

Bug: 912193
Change-Id: I10bc4158803d8ad5419aa8429756c131537f9e3e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1480232
Reviewed-by: Avi Drissman <[email protected]>
Reviewed-by: Daniel Cheng <[email protected]>
Commit-Queue: danakj <[email protected]>
Cr-Commit-Position: refs/heads/master@{#640130}
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index c748edb..21ce69a 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -1489,7 +1489,7 @@
       /*never_visible=*/false, std::move(widget_channel_request));
 
   // The returned WebPagePopup is self-referencing, so the pointer here is not
-  // an owning pointer.
+  // an owning pointer. It is de-referenced by calling Close().
   blink::WebPagePopup* popup_web_widget =
       blink::WebPagePopup::Create(popup_widget.get());
 
@@ -1510,6 +1510,20 @@
   return popup_web_widget;
 }
 
+void RenderViewImpl::CloseWindowSoon() {
+  if (render_widget_->is_frozen()) {
+    // The main widget is currently not active. The active main frame widget is
+    // in a different process.  Have the browser route the close request to the
+    // active widget instead, so that the correct unload handlers are run.
+    Send(new ViewHostMsg_RouteCloseEvent(GetRoutingID()));
+    return;
+  }
+
+  // If the main widget is not frozen then the Close request goes directly
+  // through it, because the RenderWidget ultimately owns the RenderViewImpl.
+  render_widget_->CloseWidgetSoon();
+}
+
 base::StringPiece RenderViewImpl::GetSessionStorageNamespaceId() {
   CHECK(!session_storage_namespace_id_.empty());
   return session_storage_namespace_id_;