From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: deepak1556 <hop2deep@gmail.com>
Date: Mon, 3 Jun 2019 14:20:05 -0700
Subject: frame_host_manager.patch

Allows embedder to intercept site instances chosen by chromium
and respond with custom instance. Also allows for us to at-runtime
enable or disable this patch.

diff --git a/content/browser/browsing_instance.cc b/content/browser/browsing_instance.cc
index 1e6b4b91485ae9a528beed77b12f6532e5968c07..c4a9db033bb56d097c4ce84ecd195e7bf4d7afd4 100644
--- a/content/browser/browsing_instance.cc
+++ b/content/browser/browsing_instance.cc
@@ -83,6 +83,13 @@ scoped_refptr<SiteInstanceImpl> BrowsingInstance::GetSiteInstanceForURL(
   return instance;
 }
 
+scoped_refptr<SiteInstanceImpl> BrowsingInstance::CreateSiteInstanceForURL(
+    const GURL& url) {
+  scoped_refptr<SiteInstanceImpl> instance = new SiteInstanceImpl(this);
+  instance->SetSite(url);
+  return instance;
+}
+
 void BrowsingInstance::GetSiteAndLockForURL(const GURL& url,
                                             bool allow_default_instance,
                                             GURL* site_url,
diff --git a/content/browser/browsing_instance.h b/content/browser/browsing_instance.h
index 906a1ee4ac58b0744a32153bbaafeac4322a60e4..c90f4aead36cbf3767dc5094728963c24798e204 100644
--- a/content/browser/browsing_instance.h
+++ b/content/browser/browsing_instance.h
@@ -136,6 +136,11 @@ class CONTENT_EXPORT BrowsingInstance final
       const GURL& url,
       bool allow_default_instance);
 
+  // Create a new SiteInstance for the given URL bound the current
+  // BrowsingInstance.
+  scoped_refptr<SiteInstanceImpl> CreateSiteInstanceForURL(
+      const GURL& url);
+
   // Adds the given SiteInstance to our map, to ensure that we do not create
   // another SiteInstance for the same site.
   void RegisterSiteInstance(SiteInstanceImpl* site_instance);
diff --git a/content/browser/frame_host/render_frame_host_manager.cc b/content/browser/frame_host/render_frame_host_manager.cc
index d847c6dd1cad8077276a2097c86944780b16ff76..0a76a76e14306f2eee1961a780a08bce6b5dea64 100644
--- a/content/browser/frame_host/render_frame_host_manager.cc
+++ b/content/browser/frame_host/render_frame_host_manager.cc
@@ -2130,6 +2130,16 @@ bool RenderFrameHostManager::InitRenderView(
 scoped_refptr<SiteInstance>
 RenderFrameHostManager::GetSiteInstanceForNavigationRequest(
     NavigationRequest* request) {
+  // Compute the SiteInstance that the navigation should use, which will be
+  // either the current SiteInstance or a new one.
+  //
+  // TODO(clamy): We should also consider as a candidate SiteInstance the
+  // speculative SiteInstance that was computed on redirects.
+  SiteInstanceImpl* candidate_site_instance =
+      speculative_render_frame_host_
+          ? speculative_render_frame_host_->GetSiteInstance()
+          : nullptr;
+
   SiteInstance* current_site_instance = render_frame_host_->GetSiteInstance();
 
   // All children of MHTML documents must be MHTML documents. They all live in
@@ -2149,10 +2159,61 @@ RenderFrameHostManager::GetSiteInstanceForNavigationRequest(
   //
   // TODO(clamy): We should also consider as a candidate SiteInstance the
   // speculative SiteInstance that was computed on redirects.
-  SiteInstanceImpl* candidate_site_instance =
-      speculative_render_frame_host_
-          ? speculative_render_frame_host_->GetSiteInstance()
-          : nullptr;
+  if (!GetContentClient()->browser()->CanUseCustomSiteInstance() &&
+      frame_tree_node_->IsMainFrame()) {
+    BrowserContext* browser_context =
+        delegate_->GetControllerForRenderManager().GetBrowserContext();
+    bool has_navigation_started = request->state() != NavigationRequest::NOT_STARTED;
+    bool has_response_started =
+        (request->state() == NavigationRequest::RESPONSE_STARTED ||
+        request->state() == NavigationRequest::FAILED) &&
+        !speculative_render_frame_host_;
+    // Gives user a chance to choose a custom site instance.
+    SiteInstance* affinity_site_instance = nullptr;
+    scoped_refptr<SiteInstance> overriden_site_instance;
+    bool should_register_site_instance = false;
+    ContentBrowserClient::SiteInstanceForNavigationType siteInstanceType =
+        GetContentClient()->browser()->ShouldOverrideSiteInstanceForNavigation(
+            current_frame_host(), speculative_frame_host(), browser_context,
+            request->common_params().url, has_navigation_started,
+            has_response_started, &affinity_site_instance);
+    switch (siteInstanceType) {
+      case ContentBrowserClient::SiteInstanceForNavigationType::
+          FORCE_CANDIDATE_OR_NEW:
+        overriden_site_instance =
+            candidate_site_instance
+                ? candidate_site_instance
+                : current_site_instance->CreateRelatedSiteInstance(
+                                            request->common_params().url);
+        should_register_site_instance = true;
+        break;
+      case ContentBrowserClient::SiteInstanceForNavigationType::FORCE_NEW:
+        overriden_site_instance = current_site_instance->CreateRelatedSiteInstance(
+            request->common_params().url);
+        should_register_site_instance = true;
+        break;
+      case ContentBrowserClient::SiteInstanceForNavigationType::FORCE_CURRENT:
+        overriden_site_instance = render_frame_host_->GetSiteInstance();
+        break;
+      case ContentBrowserClient::SiteInstanceForNavigationType::FORCE_AFFINITY:
+        DCHECK(affinity_site_instance);
+        overriden_site_instance =
+            scoped_refptr<SiteInstance>(affinity_site_instance);
+        break;
+      case ContentBrowserClient::SiteInstanceForNavigationType::ASK_CHROMIUM:
+        DCHECK(!affinity_site_instance);
+        break;
+      default:
+        break;
+    }
+    if (overriden_site_instance) {
+      if (should_register_site_instance) {
+        GetContentClient()->browser()->RegisterPendingSiteInstance(
+            render_frame_host_.get(), overriden_site_instance.get());
+      }
+      return overriden_site_instance;
+    }
+  }
 
   scoped_refptr<SiteInstance> dest_site_instance = GetSiteInstanceForNavigation(
       request->common_params().url, request->GetSourceSiteInstance(),
@@ -2162,6 +2223,9 @@ RenderFrameHostManager::GetSiteInstanceForNavigationRequest(
       request->GetRestoreType() != RestoreType::NONE, request->is_view_source(),
       request->WasServerRedirect());
 
+  GetContentClient()->browser()->RegisterPendingSiteInstance(
+      render_frame_host_.get(), dest_site_instance.get());
+
   return dest_site_instance;
 }
 
diff --git a/content/browser/site_instance_impl.cc b/content/browser/site_instance_impl.cc
index ea72b3a9d57383a47c91795c11bd0b8fc2b92e55..2adb671d8c36ad22814b75c4be61fb3925dd2258 100644
--- a/content/browser/site_instance_impl.cc
+++ b/content/browser/site_instance_impl.cc
@@ -360,6 +360,10 @@ bool SiteInstanceImpl::HasRelatedSiteInstance(const GURL& url) {
   return browsing_instance_->HasSiteInstance(url);
 }
 
+scoped_refptr<SiteInstance> SiteInstanceImpl::CreateRelatedSiteInstance(const GURL& url) {
+  return browsing_instance_->CreateSiteInstanceForURL(url);
+}
+
 scoped_refptr<SiteInstance> SiteInstanceImpl::GetRelatedSiteInstance(
     const GURL& url) {
   return browsing_instance_->GetSiteInstanceForURL(
diff --git a/content/browser/site_instance_impl.h b/content/browser/site_instance_impl.h
index 9fc7e1710f3038e82d7fac6c3fb608cd3a7071ba..ad1e884811e8f7de4dea43f9b754d578e62b4d92 100644
--- a/content/browser/site_instance_impl.h
+++ b/content/browser/site_instance_impl.h
@@ -84,6 +84,7 @@ class CONTENT_EXPORT SiteInstanceImpl final : public SiteInstance,
   BrowserContext* GetBrowserContext() override;
   const GURL& GetSiteURL() override;
   scoped_refptr<SiteInstance> GetRelatedSiteInstance(const GURL& url) override;
+  scoped_refptr<SiteInstance> CreateRelatedSiteInstance(const GURL& url) override;
   bool IsRelatedSiteInstance(const SiteInstance* instance) override;
   size_t GetRelatedActiveContentsCount() override;
   bool RequiresDedicatedProcess() override;
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc
index 3fdc443b408c3d8f7ffdabf6b010d5fc1ecd22d5..0d0d0f8f90fd830882558b3358d4a168fe5746b7 100644
--- a/content/public/browser/content_browser_client.cc
+++ b/content/public/browser/content_browser_client.cc
@@ -49,6 +49,21 @@
 
 namespace content {
 
+bool ContentBrowserClient::CanUseCustomSiteInstance() {
+  return false;
+}
+
+ContentBrowserClient::SiteInstanceForNavigationType ContentBrowserClient::ShouldOverrideSiteInstanceForNavigation(
+    content::RenderFrameHost* current_rfh,
+    content::RenderFrameHost* speculative_rfh,
+    content::BrowserContext* browser_context,
+    const GURL& url,
+    bool has_navigation_started,
+    bool has_request_started,
+    content::SiteInstance** affinity_site_instance) const {
+  return SiteInstanceForNavigationType::ASK_CHROMIUM;
+}
+
 std::unique_ptr<BrowserMainParts> ContentBrowserClient::CreateBrowserMainParts(
     const MainFunctionParams& parameters) {
   return nullptr;
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
index 891b69d65de0e47719af23eb7047d22d10417019..425e7ab657a2de0ff11e6989a0dc34e11f883999 100644
--- a/content/public/browser/content_browser_client.h
+++ b/content/public/browser/content_browser_client.h
@@ -215,8 +215,45 @@ struct WebPreferences;
 // the observer interfaces.)
 class CONTENT_EXPORT ContentBrowserClient {
  public:
+  // Identifies the type of site instance to use for a navigation.
+  enum SiteInstanceForNavigationType {
+    // Use either the candidate site instance or, if it doesn't exist
+    // a new, unrelated site instance for the navigation.
+    FORCE_CANDIDATE_OR_NEW = 0,
+
+    // Use the current site instance for the navigation.
+    FORCE_CURRENT,
+
+    // Use a new, unrelated site instance.
+    FORCE_NEW,
+
+    // Use the provided affinity site instance for the navigation.
+    FORCE_AFFINITY,
+
+    // Delegate the site instance creation to Chromium.
+    ASK_CHROMIUM
+  };
+
   virtual ~ContentBrowserClient() {}
 
+  // Electron: Allows disabling the below ShouldOverride patch
+  virtual bool CanUseCustomSiteInstance();
+
+  // Electron: Allows overriding the SiteInstance when navigating.
+  virtual SiteInstanceForNavigationType ShouldOverrideSiteInstanceForNavigation(
+      content::RenderFrameHost* current_rfh,
+      content::RenderFrameHost* speculative_rfh,
+      content::BrowserContext* browser_context,
+      const GURL& url,
+      bool has_navigation_started,
+      bool has_request_started,
+      content::SiteInstance** affinity_site_instance) const;
+
+  // Electron: Registers a pending site instance during a navigation.
+  virtual void RegisterPendingSiteInstance(
+      content::RenderFrameHost* rfh,
+      content::SiteInstance* pending_site_instance) {}
+
   // Allows the embedder to set any number of custom BrowserMainParts
   // implementations for the browser startup code. See comments in
   // browser_main_parts.h.
diff --git a/content/public/browser/site_instance.h b/content/public/browser/site_instance.h
index a3e880e20e51d988175f0e8e2c42e7f5c1740104..faadd39d01530092f4f31a896ecb60f235e7f63f 100644
--- a/content/public/browser/site_instance.h
+++ b/content/public/browser/site_instance.h
@@ -121,6 +121,11 @@ class CONTENT_EXPORT SiteInstance : public base::RefCounted<SiteInstance> {
   //   corresponds to a site URL with the host "example.com".
   virtual const GURL& GetSiteURL() = 0;
 
+  // Create a SiteInstance for the given URL that shares the current
+  // BrowsingInstance.
+  virtual scoped_refptr<SiteInstance> CreateRelatedSiteInstance(
+    const GURL& url) = 0;
+
   // Gets a SiteInstance for the given URL that shares the current
   // BrowsingInstance, creating a new SiteInstance if necessary.  This ensures
   // that a BrowsingInstance only has one SiteInstance per site, so that pages
