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 2fdd2b3f3f8dcc14a2675b1c115d7b700a33c2e0..9f20f0f37890af424aba566f88653e6142d944eb 100644
--- a/content/browser/browsing_instance.cc
+++ b/content/browser/browsing_instance.cc
@@ -77,6 +77,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(UrlInfo(url, false));
+  return instance;
+}
+
 SiteInfo BrowsingInstance::GetSiteInfoForURL(const UrlInfo& url_info,
                                              bool allow_default_instance) {
   scoped_refptr<SiteInstanceImpl> site_instance =
diff --git a/content/browser/browsing_instance.h b/content/browser/browsing_instance.h
index 65e627f2fa89352b0be27b5813d71a622bf1d326..113f4fd00f1cf994b39f64c9da38785545ba321f 100644
--- a/content/browser/browsing_instance.h
+++ b/content/browser/browsing_instance.h
@@ -149,6 +149,11 @@ class CONTENT_EXPORT BrowsingInstance final
       const UrlInfo& url_info,
       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/renderer_host/navigation_request.cc b/content/browser/renderer_host/navigation_request.cc
index 24450c34eaed19d06bed16368c21ce838ff21e88..7ea0a4b99b7d5c1444fab19913e455153577573a 100644
--- a/content/browser/renderer_host/navigation_request.cc
+++ b/content/browser/renderer_host/navigation_request.cc
@@ -1496,6 +1496,21 @@ void NavigationRequest::BeginNavigation() {
     if (IsSameDocument()) {
       render_frame_host_ = frame_tree_node_->current_frame_host();
     } else {
+      // In Electron, a new process is started for every navigation when node is
+      // integrated in the renderer. Since GetFrameHostForNavigation is called more
+      // than once per navigation, we want to return the same frame host once
+      // the response has started, otherwise if the frame host that started the response
+      // and the frame host that is available for commit don't match then request will
+      // be cancelled. We rely on the NavigationRequest::state_ to determine this
+      // factor
+      //
+      // bool has_response_started =
+      //    (request->state() >= NavigationRequest::WILL_PROCESS_RESPONSE &&
+      //     !speculative_render_frame_host_);
+      //
+      // Hence this call is necesary before the call to GetFrameHostForNavigation.
+      SetState(REUSE_SITE_INSTANCE);
+
       // Select an appropriate RenderFrameHost.
       std::string frame_host_choice_reason;
       render_frame_host_ =
@@ -5365,6 +5380,7 @@ void NavigationRequest::CheckStateTransition(NavigationState state) const {
           {WILL_START_REQUEST, {
               WILL_REDIRECT_REQUEST,
               WILL_PROCESS_RESPONSE,
+              REUSE_SITE_INSTANCE,
               READY_TO_COMMIT,
               DID_COMMIT,
               CANCELING,
@@ -5378,10 +5394,14 @@ void NavigationRequest::CheckStateTransition(NavigationState state) const {
               WILL_FAIL_REQUEST,
           }},
           {WILL_PROCESS_RESPONSE, {
+              REUSE_SITE_INSTANCE,
               READY_TO_COMMIT,
               CANCELING,
               WILL_FAIL_REQUEST,
           }},
+          {REUSE_SITE_INSTANCE, {
+              READY_TO_COMMIT,
+          }},
           {READY_TO_COMMIT, {
               NOT_STARTED,
               DID_COMMIT,
diff --git a/content/browser/renderer_host/navigation_request.h b/content/browser/renderer_host/navigation_request.h
index a5c8cafef454369e593ed5f63770b914f22b0884..396af71f380977e588da58e361b24ffe8b240a6e 100644
--- a/content/browser/renderer_host/navigation_request.h
+++ b/content/browser/renderer_host/navigation_request.h
@@ -133,6 +133,10 @@ class CONTENT_EXPORT NavigationRequest
     // asynchronous.
     WILL_PROCESS_RESPONSE,
 
+    // Electron: state that is between than WILL_PROCESS_RESPONSE and
+    // READY_TO_COMMIT to force reuse the same site instance.
+    REUSE_SITE_INSTANCE,
+
     // The response started on the IO thread and is ready to be committed.
     READY_TO_COMMIT,
 
diff --git a/content/browser/renderer_host/render_frame_host_manager.cc b/content/browser/renderer_host/render_frame_host_manager.cc
index 3b3b825f738b1b50974603d4a801aa2e2717b286..5818a15007baa8d1a078c0ddc9d30e00984876cf 100644
--- a/content/browser/renderer_host/render_frame_host_manager.cc
+++ b/content/browser/renderer_host/render_frame_host_manager.cc
@@ -2726,6 +2726,16 @@ scoped_refptr<SiteInstance>
 RenderFrameHostManager::GetSiteInstanceForNavigationRequest(
     NavigationRequest* request,
     std::string* reason) {
+  // 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
@@ -2753,10 +2763,60 @@ 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::WILL_PROCESS_RESPONSE &&
+         !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;
+    }
+  }
 
   // Account for renderer-initiated reload as well.
   // Needed as a workaround for https://crbug.com/1045524, remove it when it is
@@ -2796,6 +2856,9 @@ RenderFrameHostManager::GetSiteInstanceForNavigationRequest(
     request->ResetStateForSiteInstanceChange();
   }
 
+  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 b0903d9cd7ef9ca15bc32d230b6003a2bfb4c3d9..9da9ae8b51010b9bbf5c62ec810ffd0bc145dad5 100644
--- a/content/browser/site_instance_impl.cc
+++ b/content/browser/site_instance_impl.cc
@@ -755,6 +755,10 @@ bool SiteInstanceImpl::HasRelatedSiteInstance(const SiteInfo& site_info) {
   return browsing_instance_->HasSiteInstance(site_info);
 }
 
+scoped_refptr<SiteInstance> SiteInstanceImpl::CreateRelatedSiteInstance(const GURL& url) {
+  return browsing_instance_->CreateSiteInstanceForURL(url);
+}
+
 scoped_refptr<SiteInstance> SiteInstanceImpl::GetRelatedSiteInstance(
     const GURL& url) {
   return GetRelatedSiteInstanceImpl(
diff --git a/content/browser/site_instance_impl.h b/content/browser/site_instance_impl.h
index 1d79bf9261aad6e649a029257f7e6848cc34ad69..64cd5e188786ed60e474aeb1cabacd3d85069ae0 100644
--- a/content/browser/site_instance_impl.h
+++ b/content/browser/site_instance_impl.h
@@ -323,6 +323,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 b84afa745f7a2b378f7cda18b7cdbb5357e2234c..94cda2d735bbb313471ded7b0e922c6f96cac901 100644
--- a/content/public/browser/content_browser_client.cc
+++ b/content/public/browser/content_browser_client.cc
@@ -66,6 +66,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 a9b4f7770a04d713de363c80c3a0f2b107b6d426..ebd20fad629f24c6068e1a80c63f7811689df9ab 100644
--- a/content/public/browser/content_browser_client.h
+++ b/content/public/browser/content_browser_client.h
@@ -256,8 +256,45 @@ class CONTENT_EXPORT ContentBrowserClient {
   using IsClipboardPasteContentAllowedCallback =
       base::OnceCallback<void(ClipboardPasteContentAllowed)>;
 
+  // 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() = default;
 
+  // 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 a721f2fbab6e621085a8c7806abd92b8077340a8..e9b936e05e1d6ac8ea6eb5eb4d412b37ae4acc86 100644
--- a/content/public/browser/site_instance.h
+++ b/content/public/browser/site_instance.h
@@ -135,6 +135,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
