Allow non-WebUI navigations in single-process mode

WebUINavigationThrottle blocks WebUI (chrome://...) pages from loading
non-WebUI pages in subframes.

When a renderer navigates to a WebUI page, a "WebUI bindings" bit is set
in that renderer's ChildProcessSecurityPolicyImpl::SecurityState, and it
remains for the lifetime of the renderer process.
WebUINavigationThrottles are created for renderers with this bit set.

In multi-process mode, navigating away from the WebUI page creates a
fresh renderer with a fresh SecurityState, so subsequent non-WebUI pages
are again able to load non-WebUI subframes.

In single-process mode, the WebUI bit remains. After visiting a WebUI
page, iframes on all other pages will be broken until Chrome is
restarted.

This breaks Android WebView as well, since WebView uses single-process
on old Android versions and low-memory devices. It breaks CTS because
testOnSafeBrowsingHit loads chrome://safe-browsing/match?type=malware,
which sets the bit, and then testShouldOverrideUrlLoadingOnCreateWindow
tries to use an iframe.

Fix this by not creating a WebUINavigationThrottle in single-process
mode.

BUG=924799

Change-Id: I5a61f45dc065681f0e6b97e0b205e804edbd7402
Reviewed-on: https://chromium-review.googlesource.com/c/1432953
Commit-Queue: Paul Miller <paulmiller@chromium.org>
Reviewed-by: Nasko Oskov <nasko@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#626267}(cherry picked from commit 8a5d9397e612ca062c702a0f8f017db516790b85)
Reviewed-on: https://chromium-review.googlesource.com/c/1452372
Reviewed-by: Paul Miller <paulmiller@chromium.org>
Cr-Commit-Position: refs/branch-heads/3683@{#176}
Cr-Branched-From: e51029943e0a38dd794b73caaf6373d5496ae783-refs/heads/master@{#625896}
diff --git a/content/browser/frame_host/webui_navigation_throttle.cc b/content/browser/frame_host/webui_navigation_throttle.cc
index 625b1cb1..90c03d6 100644
--- a/content/browser/frame_host/webui_navigation_throttle.cc
+++ b/content/browser/frame_host/webui_navigation_throttle.cc
@@ -4,10 +4,12 @@
 
 #include "content/browser/frame_host/webui_navigation_throttle.h"
 
+#include "base/command_line.h"
 #include "content/browser/child_process_security_policy_impl.h"
 #include "content/browser/frame_host/navigation_handle_impl.h"
 #include "content/browser/frame_host/render_frame_host_impl.h"
 #include "content/public/browser/navigation_handle.h"
+#include "content/public/common/content_switches.h"
 #include "content/public/common/url_constants.h"
 
 namespace content {
@@ -35,7 +37,13 @@
 std::unique_ptr<NavigationThrottle>
 WebUINavigationThrottle::CreateThrottleForNavigation(
     NavigationHandle* navigation_handle) {
-  // Create the throttle only for subframe navigations.
+  // The WebUI security model (which keeps renderes with WebUI bindings separate
+  // from untrusted renderers) only makes sense in multi-process mode.
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kSingleProcess))
+    return nullptr;
+
+  // Only throttle subframe navigations.
   if (navigation_handle->IsInMainFrame())
     return nullptr;
 
@@ -45,8 +53,8 @@
           ->parent()
           ->current_frame_host();
 
-  // Create a throttle only for navigations where the parent frame is either
-  // at a chrome:// URL or is in a process with WebUI bindings.
+  // Throttle if the renderer process has WebUI bindings, or if the parent frame
+  // is on a WebUI page.
   if (ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
           parent->GetProcess()->GetID()) ||
       parent->GetLastCommittedURL().SchemeIs(kChromeUIScheme)) {