Consolidate all TDI SiteInstances into one render process.

BUG=674215

Review-Url: https://codereview.chromium.org/2573213002
Cr-Commit-Position: refs/heads/master@{#441832}
diff --git a/content/browser/site_instance_impl.cc b/content/browser/site_instance_impl.cc
index 7980783a..a4c8862 100644
--- a/content/browser/site_instance_impl.cc
+++ b/content/browser/site_instance_impl.cc
@@ -82,6 +82,81 @@
   return false;
 }
 
+namespace {
+
+const void* const kDefaultSubframeProcessHostHolderKey =
+    &kDefaultSubframeProcessHostHolderKey;
+
+class DefaultSubframeProcessHostHolder : public base::SupportsUserData::Data,
+                                         public RenderProcessHostObserver {
+ public:
+  explicit DefaultSubframeProcessHostHolder(BrowserContext* browser_context)
+      : browser_context_(browser_context) {}
+  ~DefaultSubframeProcessHostHolder() override {}
+
+  // Gets the correct render process to use for this SiteInstance.
+  RenderProcessHost* GetProcessHost(SiteInstance* site_instance,
+                                    bool is_for_guests_only) {
+    StoragePartition* default_partition =
+        BrowserContext::GetDefaultStoragePartition(browser_context_);
+    StoragePartition* partition =
+        BrowserContext::GetStoragePartition(browser_context_, site_instance);
+
+    // Is this the default storage partition? If it isn't, then just give it its
+    // own non-shared process.
+    if (partition != default_partition || is_for_guests_only) {
+      RenderProcessHostImpl* host = new RenderProcessHostImpl(
+          browser_context_, static_cast<StoragePartitionImpl*>(partition),
+          is_for_guests_only);
+      host->SetIsNeverSuitableForReuse();
+      return host;
+    }
+
+    if (host_) {
+      // If we already have a shared host for the default storage partition, use
+      // it.
+      return host_;
+    }
+
+    host_ = new RenderProcessHostImpl(
+        browser_context_, static_cast<StoragePartitionImpl*>(partition),
+        false /* for guests only */);
+    host_->SetIsNeverSuitableForReuse();
+    host_->AddObserver(this);
+
+    return host_;
+  }
+
+  void RenderProcessHostDestroyed(RenderProcessHost* host) override {
+    DCHECK_EQ(host_, host);
+    host_->RemoveObserver(this);
+    host_ = nullptr;
+  }
+
+ private:
+  BrowserContext* browser_context_;
+
+  // The default subframe render process used for the default storage partition
+  // of this BrowserContext.
+  RenderProcessHostImpl* host_ = nullptr;
+};
+
+}  // namespace
+
+RenderProcessHost* SiteInstanceImpl::GetDefaultSubframeProcessHost(
+    BrowserContext* browser_context,
+    bool is_for_guests_only) {
+  DefaultSubframeProcessHostHolder* holder =
+      static_cast<DefaultSubframeProcessHostHolder*>(
+          browser_context->GetUserData(&kDefaultSubframeProcessHostHolderKey));
+  if (!holder) {
+    holder = new DefaultSubframeProcessHostHolder(browser_context);
+    browser_context->SetUserData(kDefaultSubframeProcessHostHolderKey, holder);
+  }
+
+  return holder->GetProcessHost(this, is_for_guests_only);
+}
+
 RenderProcessHost* SiteInstanceImpl::GetProcess() {
   // TODO(erikkay) It would be nice to ensure that the renderer type had been
   // properly set before we get here.  The default tab creation case winds up
@@ -93,6 +168,7 @@
   // Create a new process if ours went away or was reused.
   if (!process_) {
     BrowserContext* browser_context = browsing_instance_->browser_context();
+    bool is_for_guests_only = site_.SchemeIs(kGuestScheme);
 
     // If we should use process-per-site mode (either in general or for the
     // given site), then look for an existing RenderProcessHost for the site.
@@ -103,6 +179,12 @@
                                                               site_);
     }
 
+    if (!process_ && IsDefaultSubframeSiteInstance() &&
+        SiteIsolationPolicy::IsTopDocumentIsolationEnabled()) {
+      process_ =
+          GetDefaultSubframeProcessHost(browser_context, is_for_guests_only);
+    }
+
     // If not (or if none found), see if we should reuse an existing process.
     if (!process_ && RenderProcessHostImpl::ShouldTryToUseExistingProcessHost(
             browser_context, site_)) {
@@ -119,9 +201,8 @@
         StoragePartitionImpl* partition =
             static_cast<StoragePartitionImpl*>(
                 BrowserContext::GetStoragePartition(browser_context, this));
-        process_ = new RenderProcessHostImpl(browser_context,
-                                             partition,
-                                             site_.SchemeIs(kGuestScheme));
+        process_ = new RenderProcessHostImpl(browser_context, partition,
+                                             is_for_guests_only);
       }
     }
     CHECK(process_);