Force MimeHandlerView to always use BrowserPlugin

Currently, with the flag --use-cross-process-frames-for-guests switched
on, MimeHandlerView still creates a BrowserPlugin while on the browser
side we expect an OOPIF based implementation. This causes PDF viewer to
crash.

On the other hand, GuestViews will soon use OOPIF. Hence, temporarily,
we need to make MimeHandlerView an exception and force it to use
BrowserPlugin's codepath even when the switch above is turned on.

BUG=563285
CQ_INCLUDE_TRYBOTS=master.tryserver.chromium.linux:linux_site_isolation

Review-Url: https://codereview.chromium.org/2165523004
Cr-Commit-Position: refs/heads/master@{#420712}
diff --git a/content/browser/browser_plugin/browser_plugin_guest.cc b/content/browser/browser_plugin/browser_plugin_guest.cc
index 65ad76bb..c518aca 100644
--- a/content/browser/browser_plugin/browser_plugin_guest.cc
+++ b/content/browser/browser_plugin/browser_plugin_guest.cc
@@ -42,11 +42,11 @@
 #include "content/public/browser/browser_plugin_guest_manager.h"
 #include "content/public/browser/content_browser_client.h"
 #include "content/public/browser/guest_host.h"
+#include "content/public/browser/guest_mode.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_widget_host_view.h"
 #include "content/public/browser/user_metrics.h"
 #include "content/public/browser/web_contents_observer.h"
-#include "content/public/common/browser_plugin_guest_mode.h"
 #include "content/public/common/drop_data.h"
 #include "ui/events/blink/web_input_event_traits.h"
 #include "ui/gfx/geometry/size_conversions.h"
@@ -106,6 +106,7 @@
       seen_embedder_drag_source_ended_at_(false),
       ignore_dragged_url_(true),
       delegate_(delegate),
+      can_use_cross_process_frames_(delegate->CanUseCrossProcessFrames()),
       weak_ptr_factory_(this) {
   DCHECK(web_contents);
   DCHECK(delegate);
@@ -115,7 +116,7 @@
 }
 
 int BrowserPluginGuest::GetGuestProxyRoutingID() {
-  if (BrowserPluginGuestMode::UseCrossProcessFramesForGuests()) {
+  if (GuestMode::IsCrossProcessFrameGuest(GetWebContents())) {
     // We don't use the proxy to send postMessage in --site-per-process, since
     // we use the contentWindow directly from the frame element instead.
     return MSG_ROUTING_NONE;
@@ -294,7 +295,7 @@
 
   if (owner_web_contents_ != owner_web_contents) {
     WebContentsViewGuest* new_view = nullptr;
-    if (!BrowserPluginGuestMode::UseCrossProcessFramesForGuests()) {
+    if (!GuestMode::IsCrossProcessFrameGuest(GetWebContents())) {
       new_view =
           static_cast<WebContentsViewGuest*>(GetWebContents()->GetView());
     }
@@ -684,9 +685,8 @@
   // TODO(lazyboy): Fix this as part of http://crbug.com/330264. The required
   // parts of code from this class should be extracted to a separate class for
   // --site-per-process.
-  if (BrowserPluginGuestMode::UseCrossProcessFramesForGuests()) {
+  if (GuestMode::IsCrossProcessFrameGuest(GetWebContents()))
     return false;
-  }
 
   IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuest, message)
     IPC_MESSAGE_HANDLER(InputHostMsg_ImeCancelComposition,
@@ -936,7 +936,7 @@
 void BrowserPluginGuest::OnSetVisibility(int browser_plugin_instance_id,
                                          bool visible) {
   // For OOPIF-<webivew>, the remote frame will handle visibility state.
-  if (BrowserPluginGuestMode::UseCrossProcessFramesForGuests())
+  if (GuestMode::IsCrossProcessFrameGuest(GetWebContents()))
     return;
 
   guest_visible_ = visible;
diff --git a/content/browser/browser_plugin/browser_plugin_guest.h b/content/browser/browser_plugin/browser_plugin_guest.h
index b961282..b99654e 100644
--- a/content/browser/browser_plugin/browser_plugin_guest.h
+++ b/content/browser/browser_plugin/browser_plugin_guest.h
@@ -253,6 +253,11 @@
 
   void ResendEventToEmbedder(const blink::WebInputEvent& event);
 
+  // TODO(ekaramad): Remove this once https://crbug.com/642826 is resolved.
+  bool can_use_cross_process_frames() const {
+    return can_use_cross_process_frames_;
+  }
+
  protected:
 
   // BrowserPluginGuest is a WebContentsObserver of |web_contents| and
@@ -446,6 +451,11 @@
 
   BrowserPluginGuestDelegate* const delegate_;
 
+  // Whether or not this BrowserPluginGuest can use cross process frames. This
+  // means when we have --use-cross-process-frames-for-guests on, the
+  // WebContents associated with this BrowserPluginGuest has OOPIF structure.
+  bool can_use_cross_process_frames_;
+
   // Weak pointer used to ask GeolocationPermissionContext about geolocation
   // permission.
   base::WeakPtrFactory<BrowserPluginGuest> weak_ptr_factory_;
diff --git a/content/browser/frame_host/render_frame_host_manager.cc b/content/browser/frame_host/render_frame_host_manager.cc
index 3a1921bb..1e1d5425 100644
--- a/content/browser/frame_host/render_frame_host_manager.cc
+++ b/content/browser/frame_host/render_frame_host_manager.cc
@@ -40,11 +40,11 @@
 #include "content/common/site_isolation_policy.h"
 #include "content/common/view_messages.h"
 #include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/guest_mode.h"
 #include "content/public/browser/render_process_host_observer.h"
 #include "content/public/browser/render_widget_host_iterator.h"
 #include "content/public/browser/render_widget_host_view.h"
 #include "content/public/browser/user_metrics.h"
-#include "content/public/common/browser_plugin_guest_mode.h"
 #include "content/public/common/browser_side_navigation_policy.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/referrer.h"
@@ -1825,7 +1825,8 @@
 void RenderFrameHostManager::CreateOuterDelegateProxy(
     SiteInstance* outer_contents_site_instance,
     RenderFrameHostImpl* render_frame_host) {
-  CHECK(BrowserPluginGuestMode::UseCrossProcessFramesForGuests());
+  // We only get here when Delegate for this manager is an inner delegate and is
+  // based on cross process frames.
   RenderFrameProxyHost* proxy =
       CreateRenderFrameProxyHost(outer_contents_site_instance, nullptr);
 
diff --git a/content/browser/frame_host/render_frame_host_manager.h b/content/browser/frame_host/render_frame_host_manager.h
index 41698cc..4533fb7 100644
--- a/content/browser/frame_host/render_frame_host_manager.h
+++ b/content/browser/frame_host/render_frame_host_manager.h
@@ -482,7 +482,8 @@
   // RenderFrameProxyHost in its outer WebContents's SiteInstance,
   // |outer_contents_site_instance|. The frame in outer WebContents that is
   // hosting the inner WebContents is |render_frame_host|, and the frame will
-  // be swapped out with the proxy.
+  // be swapped out with the proxy.Note that this method must only be called
+  // for an OOPIF-based inner WebContents.
   void CreateOuterDelegateProxy(SiteInstance* outer_contents_site_instance,
                                 RenderFrameHostImpl* render_frame_host);
 
diff --git a/content/browser/frame_host/render_widget_host_view_child_frame.cc b/content/browser/frame_host/render_widget_host_view_child_frame.cc
index 12bf547..b433f06 100644
--- a/content/browser/frame_host/render_widget_host_view_child_frame.cc
+++ b/content/browser/frame_host/render_widget_host_view_child_frame.cc
@@ -30,8 +30,8 @@
 #include "content/browser/renderer_host/render_widget_host_input_event_router.h"
 #include "content/common/text_input_state.h"
 #include "content/common/view_messages.h"
+#include "content/public/browser/guest_mode.h"
 #include "content/public/browser/render_process_host.h"
-#include "content/public/common/browser_plugin_guest_mode.h"
 #include "gpu/ipc/common/gpu_messages.h"
 #include "third_party/WebKit/public/web/WebInputEvent.h"
 #include "ui/gfx/geometry/size_conversions.h"
@@ -199,7 +199,12 @@
 }
 
 gfx::NativeView RenderWidgetHostViewChildFrame::GetNativeView() const {
-  NOTREACHED();
+  // TODO(ekaramad): To accomodate MimeHandlerViewGuest while embedded inside
+  // OOPIF-webview, we need to return the native view to be used by
+  // RenderWidgetHostViewGuest. Remove this once https://crbug.com/642826 is
+  // fixed.
+  if (frame_connector_)
+    return frame_connector_->GetParentRenderWidgetHostView()->GetNativeView();
   return nullptr;
 }
 
@@ -248,11 +253,9 @@
   // is a RenderWidgetHostViewChildFrame. In contrast, when there is no
   // inner/outer WebContents, only subframe's RenderWidgetHostView can be a
   // RenderWidgetHostViewChildFrame which do not get a SetIsLoading() call.
-  if (BrowserPluginGuestMode::UseCrossProcessFramesForGuests() &&
-      BrowserPluginGuest::IsGuest(
-          static_cast<RenderViewHostImpl*>(RenderViewHost::From(host_)))) {
+  if (GuestMode::IsCrossProcessFrameGuest(
+          WebContents::FromRenderViewHost(RenderViewHost::From(host_))))
     return;
-  }
 
   NOTREACHED();
 }
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index b4379ca1..5806c7d 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -92,6 +92,7 @@
 #include "content/public/browser/devtools_agent_host.h"
 #include "content/public/browser/download_manager.h"
 #include "content/public/browser/download_url_parameters.h"
+#include "content/public/browser/guest_mode.h"
 #include "content/public/browser/invalidate_type.h"
 #include "content/public/browser/javascript_dialog_manager.h"
 #include "content/public/browser/load_notification_details.h"
@@ -108,7 +109,6 @@
 #include "content/public/browser/web_contents_binding_set.h"
 #include "content/public/browser/web_contents_delegate.h"
 #include "content/public/common/bindings_policy.h"
-#include "content/public/common/browser_plugin_guest_mode.h"
 #include "content/public/common/browser_side_navigation_policy.h"
 #include "content/public/common/child_process_host.h"
 #include "content/public/common/content_constants.h"
@@ -1426,7 +1426,7 @@
 void WebContentsImpl::AttachToOuterWebContentsFrame(
     WebContents* outer_web_contents,
     RenderFrameHost* outer_contents_frame) {
-  CHECK(BrowserPluginGuestMode::UseCrossProcessFramesForGuests());
+  CHECK(GuestMode::IsCrossProcessFrameGuest(this));
   RenderFrameHostManager* render_manager = GetRenderManager();
 
   // When the WebContents being initialized has an opener, the  browser side
@@ -1582,8 +1582,7 @@
 #endif
 
   if (!view_) {
-    if (browser_plugin_guest_ &&
-        BrowserPluginGuestMode::UseCrossProcessFramesForGuests()) {
+    if (GuestMode::IsCrossProcessFrameGuest(this)) {
       view_.reset(new WebContentsViewChildFrame(
           this, delegate, &render_view_host_delegate_view_));
     } else {
@@ -1592,8 +1591,7 @@
     }
   }
 
-  if (browser_plugin_guest_ &&
-      !BrowserPluginGuestMode::UseCrossProcessFramesForGuests()) {
+  if (browser_plugin_guest_ && !GuestMode::IsCrossProcessFrameGuest(this)) {
     view_.reset(new WebContentsViewGuest(this, browser_plugin_guest_.get(),
                                          std::move(view_),
                                          &render_view_host_delegate_view_));
@@ -4227,13 +4225,12 @@
 }
 
 WebContentsImpl* WebContentsImpl::GetOuterWebContents() {
-  if (BrowserPluginGuestMode::UseCrossProcessFramesForGuests()) {
-    if (node_)
-      return node_->outer_web_contents();
-  } else {
-    if (GetBrowserPluginGuest())
-      return GetBrowserPluginGuest()->embedder_web_contents();
-  }
+  if (GuestMode::IsCrossProcessFrameGuest(this) && node_)
+    return node_->outer_web_contents();
+
+  if (browser_plugin_guest_)
+    return browser_plugin_guest_->embedder_web_contents();
+
   return nullptr;
 }
 
@@ -4663,7 +4660,7 @@
     // then we should not create a RenderView. AttachToOuterWebContentsFrame()
     // already created a RenderFrameProxyHost for that purpose.
     if (GetBrowserPluginEmbedder() &&
-        BrowserPluginGuestMode::UseCrossProcessFramesForGuests()) {
+        GuestMode::IsCrossProcessFrameGuest(source_web_contents)) {
       return;
     }
 
@@ -4684,7 +4681,7 @@
 
 void WebContentsImpl::SetFocusedFrame(FrameTreeNode* node,
                                       SiteInstance* source) {
-  if (!BrowserPluginGuestMode::UseCrossProcessFramesForGuests()) {
+  if (!GuestMode::IsCrossProcessFrameGuest(this) && browser_plugin_guest_) {
     frame_tree_.SetFocusedFrame(node, source);
     return;
   }
@@ -4703,8 +4700,7 @@
 
   // TODO(avallee): Remove this once page focus is fixed.
   RenderWidgetHostImpl* rwh = node->current_frame_host()->GetRenderWidgetHost();
-  if (rwh && old_focused_contents != this &&
-      BrowserPluginGuestMode::UseCrossProcessFramesForGuests())
+  if (rwh && old_focused_contents != this)
     rwh->Focus();
 }
 
diff --git a/content/common/site_isolation_policy.cc b/content/common/site_isolation_policy.cc
index 789bde7..4ab845d 100644
--- a/content/common/site_isolation_policy.cc
+++ b/content/common/site_isolation_policy.cc
@@ -6,7 +6,6 @@
 
 #include "base/command_line.h"
 #include "base/lazy_instance.h"
-#include "content/public/common/browser_plugin_guest_mode.h"
 #include "content/public/common/browser_side_navigation_policy.h"
 #include "content/public/common/content_client.h"
 #include "content/public/common/content_switches.h"
@@ -18,7 +17,8 @@
   return UseDedicatedProcessesForAllSites() ||
          IsTopDocumentIsolationEnabled() ||
          GetContentClient()->IsSupplementarySiteIsolationModeEnabled() ||
-         BrowserPluginGuestMode::UseCrossProcessFramesForGuests();
+         base::CommandLine::ForCurrentProcess()->HasSwitch(
+             switches::kUseCrossProcessFramesForGuests);
 }
 
 // static
diff --git a/content/public/browser/BUILD.gn b/content/public/browser/BUILD.gn
index 2a4d09f5..d5746648 100644
--- a/content/public/browser/BUILD.gn
+++ b/content/public/browser/BUILD.gn
@@ -118,6 +118,8 @@
     "gpu_service_registry.h",
     "gpu_utils.cc",
     "gpu_utils.h",
+    "guest_mode.cc",
+    "guest_mode.h",
     "histogram_fetcher.h",
     "host_zoom_map.h",
     "indexed_db_context.h",
diff --git a/content/public/browser/browser_plugin_guest_delegate.cc b/content/public/browser/browser_plugin_guest_delegate.cc
index bfa19e4..732df23 100644
--- a/content/public/browser/browser_plugin_guest_delegate.cc
+++ b/content/public/browser/browser_plugin_guest_delegate.cc
@@ -32,4 +32,8 @@
   return false;
 }
 
+bool BrowserPluginGuestDelegate::CanUseCrossProcessFrames() {
+  return true;
+}
+
 }  // namespace content
diff --git a/content/public/browser/browser_plugin_guest_delegate.h b/content/public/browser/browser_plugin_guest_delegate.h
index 4dd1a4cd..0f805651 100644
--- a/content/public/browser/browser_plugin_guest_delegate.h
+++ b/content/public/browser/browser_plugin_guest_delegate.h
@@ -92,6 +92,11 @@
   // fromt he guest renderer is incorrect in situations where BrowserPlugin is
   // subject to CSS transforms.
   virtual void SetContextMenuPosition(const gfx::Point& position) {}
+
+  // TODO(ekaramad): A short workaround to force some types of guests to use
+  // a BrowserPlugin even when we are using cross process frames for guests. It
+  // should be removed after resolving https://crbug.com/642826).
+  virtual bool CanUseCrossProcessFrames();
 };
 
 }  // namespace content
diff --git a/content/public/browser/guest_mode.cc b/content/public/browser/guest_mode.cc
new file mode 100644
index 0000000..e02fa64c
--- /dev/null
+++ b/content/public/browser/guest_mode.cc
@@ -0,0 +1,26 @@
+// Copyright 2016 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/browser/guest_mode.h"
+
+#include "base/command_line.h"
+#include "content/browser/browser_plugin/browser_plugin_guest.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/content_switches.h"
+
+namespace content {
+
+// static
+bool GuestMode::IsCrossProcessFrameGuest(WebContents* web_contents) {
+  if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kUseCrossProcessFramesForGuests))
+    return false;
+  BrowserPluginGuest* browser_plugin_guest =
+      static_cast<WebContentsImpl*>(web_contents)->GetBrowserPluginGuest();
+  return browser_plugin_guest &&
+         browser_plugin_guest->can_use_cross_process_frames();
+}
+
+}  // namespace content
diff --git a/content/public/browser/guest_mode.h b/content/public/browser/guest_mode.h
new file mode 100644
index 0000000..058f280
--- /dev/null
+++ b/content/public/browser/guest_mode.h
@@ -0,0 +1,29 @@
+// Copyright 2016 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.
+
+#ifndef CONTENT_PUBLIC_BROWSER_GUEST_MODE_H_
+#define CONTENT_PUBLIC_BROWSER_GUEST_MODE_H_
+
+#include "base/macros.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+class WebContents;
+
+class CONTENT_EXPORT GuestMode {
+ public:
+  // Returns true if |web_contents| is an inner WebContents based on cross
+  // process frames.
+  static bool IsCrossProcessFrameGuest(WebContents* web_contents);
+
+ private:
+  GuestMode();
+
+  DISALLOW_COPY_AND_ASSIGN(GuestMode);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_PUBLIC_BROWSER_GUEST_MODE_H_
diff --git a/content/public/common/BUILD.gn b/content/public/common/BUILD.gn
index a483c1b..42e486e 100644
--- a/content/public/common/BUILD.gn
+++ b/content/public/common/BUILD.gn
@@ -96,8 +96,6 @@
     "associated_interface_provider.h",
     "associated_interface_registry.h",
     "bindings_policy.h",
-    "browser_plugin_guest_mode.cc",
-    "browser_plugin_guest_mode.h",
     "browser_side_navigation_policy.cc",
     "browser_side_navigation_policy.h",
     "cdm_info.h",
diff --git a/content/public/common/browser_plugin_guest_mode.cc b/content/public/common/browser_plugin_guest_mode.cc
deleted file mode 100644
index 7c3986a..0000000
--- a/content/public/common/browser_plugin_guest_mode.cc
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2015 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/common/browser_plugin_guest_mode.h"
-
-#include "base/command_line.h"
-#include "content/public/common/content_switches.h"
-
-namespace content {
-
-// static
-bool BrowserPluginGuestMode::UseCrossProcessFramesForGuests() {
-  return base::CommandLine::ForCurrentProcess()->HasSwitch(
-      switches::kUseCrossProcessFramesForGuests);
-}
-
-}  // namespace content
diff --git a/content/public/common/browser_plugin_guest_mode.h b/content/public/common/browser_plugin_guest_mode.h
deleted file mode 100644
index c77a1e8e..0000000
--- a/content/public/common/browser_plugin_guest_mode.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2015 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.
-
-#ifndef CONTENT_PUBLIC_COMMON_BROWSER_PLUGIN_GUEST_MODE_H_
-#define CONTENT_PUBLIC_COMMON_BROWSER_PLUGIN_GUEST_MODE_H_
-
-#include "base/macros.h"
-#include "content/common/content_export.h"
-
-namespace content {
-
-class CONTENT_EXPORT BrowserPluginGuestMode {
- public:
-  // Returns true if inner WebContents should be implemented in terms of cross-
-  // process iframes.
-  static bool UseCrossProcessFramesForGuests();
-
- private:
-  BrowserPluginGuestMode();  // Not instantiable
-
-  DISALLOW_COPY_AND_ASSIGN(BrowserPluginGuestMode);
-};
-
-}  // namespace
-
-#endif  // CONTENT_PUBLIC_COMMON_BROWSER_PLUGIN_GUEST_MODE_H_
diff --git a/content/public/renderer/BUILD.gn b/content/public/renderer/BUILD.gn
index 74205af..c9b39c9 100644
--- a/content/public/renderer/BUILD.gn
+++ b/content/public/renderer/BUILD.gn
@@ -38,6 +38,8 @@
     "context_menu_client.h",
     "document_state.cc",
     "document_state.h",
+    "guest_mode.cc",
+    "guest_mode.h",
     "navigation_state.cc",
     "navigation_state.h",
     "pepper_plugin_instance.h",
diff --git a/content/public/renderer/guest_mode.cc b/content/public/renderer/guest_mode.cc
new file mode 100644
index 0000000..aa60e0e
--- /dev/null
+++ b/content/public/renderer/guest_mode.cc
@@ -0,0 +1,18 @@
+// Copyright 2016 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/renderer/guest_mode.h"
+
+#include "base/command_line.h"
+#include "content/public/common/content_switches.h"
+
+namespace content {
+
+// static
+bool GuestMode::UseCrossProcessFramesForGuests() {
+  return base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kUseCrossProcessFramesForGuests);
+}
+
+}  // namespace content
diff --git a/content/public/renderer/guest_mode.h b/content/public/renderer/guest_mode.h
new file mode 100644
index 0000000..6b28f841
--- /dev/null
+++ b/content/public/renderer/guest_mode.h
@@ -0,0 +1,26 @@
+// Copyright 2016 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.
+
+#ifndef CONTENT_PUBLIC_RENDERER_GUEST_MODE_H_
+#define CONTENT_PUBLIC_RENDERER_GUEST_MODE_H_
+
+#include "base/macros.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+class CONTENT_EXPORT GuestMode {
+ public:
+  // Returns true if guests could be using cross process frames.
+  static bool UseCrossProcessFramesForGuests();
+
+ private:
+  GuestMode();
+
+  DISALLOW_COPY_AND_ASSIGN(GuestMode);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_PUBLIC_RENDERER_GUEST_MODE_H_