From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: deepak1556 <hop2deep@gmail.com>
Date: Wed, 14 Nov 2018 20:38:46 +0530
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 88e2bfabe6ca749fd588b92131abddbbb7814202..d8aa8910a01df716944b7a224d7b07ee6885c6da 100644
--- a/content/browser/browsing_instance.cc
+++ b/content/browser/browsing_instance.cc
@@ -143,6 +143,13 @@ scoped_refptr<SiteInstanceImpl> BrowsingInstance::GetSiteInstanceForURLHelper(
   return nullptr;
 }
 
+scoped_refptr<SiteInstanceImpl> BrowsingInstance::CreateSiteInstanceForURL(
+    const GURL& url) {
+  scoped_refptr<SiteInstanceImpl> instance = new SiteInstanceImpl(this);
+  instance->SetSite(url);
+  return instance;
+}
+
 void BrowsingInstance::RegisterSiteInstance(SiteInstanceImpl* site_instance) {
   DCHECK(site_instance->browsing_instance_.get() == this);
   DCHECK(site_instance->HasSite());
diff --git a/content/browser/browsing_instance.h b/content/browser/browsing_instance.h
index 775b64a8d20f89845812852a2904a1e6875c2b4a..5235b57bbf44fc7b30ca6943c43a290f07f003bf 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 297b61198dd46114b3d8c89488a71ed01aa299c4..6adf8ef7c00cabff4cd3c3ad6af01125c24791c7 100644
--- a/content/browser/frame_host/render_frame_host_manager.cc
+++ b/content/browser/frame_host/render_frame_host_manager.cc
@@ -2127,6 +2127,20 @@ bool RenderFrameHostManager::InitRenderView(
 scoped_refptr<SiteInstance>
 RenderFrameHostManager::GetSiteInstanceForNavigationRequest(
     const NavigationRequest& request) {
+  BrowserContext* browser_context = nullptr;
+  scoped_refptr<SiteInstance> candidate_site_instance;
+  if (!GetContentClient()->browser()->CanUseCustomSiteInstance()) {
+    browser_context =
+        delegate_->GetControllerForRenderManager().GetBrowserContext();
+    // If the navigation can swap SiteInstances, compute the SiteInstance it
+    // should use.
+    // TODO(clamy): We should also consider as a candidate SiteInstance the
+    // speculative SiteInstance that was computed on redirects.
+    candidate_site_instance =
+        speculative_render_frame_host_
+            ? speculative_render_frame_host_->GetSiteInstance()
+            : nullptr;
+  }
   // First, check if the navigation can switch SiteInstances. If not, the
   // navigation should use the current SiteInstance.
   SiteInstance* current_site_instance = render_frame_host_->GetSiteInstance();
@@ -2158,6 +2172,59 @@ RenderFrameHostManager::GetSiteInstanceForNavigationRequest(
                                               request.common_params().url);
     no_renderer_swap_allowed |=
         request.from_begin_navigation() && !can_renderer_initiate_transfer;
+
+    if (!GetContentClient()->browser()->CanUseCustomSiteInstance()) {
+      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;
+      }
+    }
   } else {
     // Subframe navigations will use the current renderer, unless specifically
     // allowed to swap processes.
@@ -2169,23 +2236,28 @@ RenderFrameHostManager::GetSiteInstanceForNavigationRequest(
   if (no_renderer_swap_allowed && !should_swap_for_error_isolation)
     return scoped_refptr<SiteInstance>(current_site_instance);
 
+  if (GetContentClient()->browser()->CanUseCustomSiteInstance()) {
   // If the navigation can swap SiteInstances, compute the SiteInstance it
   // should use.
   // TODO(clamy): We should also consider as a candidate SiteInstance the
   // speculative SiteInstance that was computed on redirects.
-  SiteInstance* candidate_site_instance =
+  candidate_site_instance =
       speculative_render_frame_host_
           ? speculative_render_frame_host_->GetSiteInstance()
           : nullptr;
+  }
 
   scoped_refptr<SiteInstance> dest_site_instance = GetSiteInstanceForNavigation(
       request.common_params().url, request.source_site_instance(),
-      request.dest_site_instance(), candidate_site_instance,
+      request.dest_site_instance(), candidate_site_instance.get(),
       request.common_params().transition,
       request.state() == NavigationRequest::FAILED,
       request.restore_type() != RestoreType::NONE, request.is_view_source(),
       was_server_redirect);
 
+  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 f7cffe3b5bce5fc87a0a4b2fd838d0c25849da66..a7ed785356c4e3a634777bad5e40f08120377e83 100644
--- a/content/browser/site_instance_impl.cc
+++ b/content/browser/site_instance_impl.cc
@@ -342,6 +342,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 a46901055bdf17b6b0dab14edf753b234dc04a12..29c201b0c95eb0c7a35f47d6f3ab5b48c73dbf15 100644
--- a/content/browser/site_instance_impl.h
+++ b/content/browser/site_instance_impl.h
@@ -83,6 +83,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 e51c018b95b0f2dff650a83b4af638ef431aaa11..b5099cba2f5a09d04dd40cb3be4d87895c6980e6 100644
--- a/content/public/browser/content_browser_client.cc
+++ b/content/public/browser/content_browser_client.cc
@@ -52,6 +52,21 @@ void OverrideOnBindInterface(const service_manager::BindSourceInfo& remote_info,
                                                          handle);
 }
 
+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 f8e52b835c556ccb9526f1df644eb367152af75e..c040a866285adb570fd3f809ef602612706fc332 100644
--- a/content/public/browser/content_browser_client.h
+++ b/content/public/browser/content_browser_client.h
@@ -211,8 +211,44 @@ CONTENT_EXPORT void OverrideOnBindInterface(
 // 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..61bbf88265e717934533117efbc2330661e32b11 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
