From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Samuel Attard <samuel.r.attard@gmail.com>
Date: Wed, 20 May 2020 13:48:51 -0700
Subject: fix: swap global proxies before initializing the windows proxies

Electron's Context Isolation implementation has a side-effect of initializing
the isolated worlds WindowProxy during the initialization of the main world
WindowProxy as a result of creating the isolated world inside the DidCreateScriptContext
hook.  This results in an assertion failing in Chromium during a frame
swap where it expects to be able to set a new global_proxy in the WindowProxy
of the isolated world BEFORE it is initialized.

To meet this assumption this patch splits SetGlobalProxy into two calls,
SetGlobalProxyWithoutInitializing and InitializeIfNeeded which has the same
resultant effect but means that all of the global_proxy objects are set
BEFORE any WindowProxy's are initialized.

This could probably be upstreamed as it doesn't affect the way Chromium works
but also it has no benefit for them at this time.

diff --git a/third_party/blink/renderer/bindings/core/v8/window_proxy.cc b/third_party/blink/renderer/bindings/core/v8/window_proxy.cc
index 389dcd940e93ee043cf7a4435991c64d67386a38..0b5c44d75ae590b493da5584a82ea38a8246a9bf 100644
--- a/third_party/blink/renderer/bindings/core/v8/window_proxy.cc
+++ b/third_party/blink/renderer/bindings/core/v8/window_proxy.cc
@@ -104,10 +104,7 @@ v8::Local<v8::Object> WindowProxy::ReleaseGlobalProxy() {
 }
 
 void WindowProxy::SetGlobalProxy(v8::Local<v8::Object> global_proxy) {
-  DCHECK_EQ(lifecycle_, Lifecycle::kContextIsUninitialized);
-
-  CHECK(global_proxy_.IsEmpty());
-  global_proxy_.Set(isolate_, global_proxy);
+  SetGlobalProxyWithoutInitializing(global_proxy);
 
   // Initialize the window proxy now, to re-establish the connection between
   // the global object and the v8::Context. This is really only needed for a
@@ -118,6 +115,13 @@ void WindowProxy::SetGlobalProxy(v8::Local<v8::Object> global_proxy) {
   Initialize();
 }
 
+void WindowProxy::SetGlobalProxyWithoutInitializing(v8::Local<v8::Object> global_proxy) {
+  DCHECK_EQ(lifecycle_, Lifecycle::kContextIsUninitialized);
+
+  CHECK(global_proxy_.IsEmpty());
+  global_proxy_.Set(isolate_, global_proxy);
+}
+
 // Create a new environment and setup the global object.
 //
 // The global object corresponds to a DOMWindow instance. However, to
diff --git a/third_party/blink/renderer/bindings/core/v8/window_proxy.h b/third_party/blink/renderer/bindings/core/v8/window_proxy.h
index ce6aac22126e0a39fa28fcde56e903abd3a9d510..1cf5e056252af5f8ba4725722ac8d9f9d4a88de2 100644
--- a/third_party/blink/renderer/bindings/core/v8/window_proxy.h
+++ b/third_party/blink/renderer/bindings/core/v8/window_proxy.h
@@ -156,6 +156,7 @@ class WindowProxy : public GarbageCollected<WindowProxy> {
   CORE_EXPORT v8::Local<v8::Object> GlobalProxyIfNotDetached();
   v8::Local<v8::Object> ReleaseGlobalProxy();
   void SetGlobalProxy(v8::Local<v8::Object>);
+  void SetGlobalProxyWithoutInitializing(v8::Local<v8::Object>);
 
   // TODO(dcheng): Temporarily exposed to avoid include cycles. Remove the need
   // for this and remove this getter.
diff --git a/third_party/blink/renderer/bindings/core/v8/window_proxy_manager.cc b/third_party/blink/renderer/bindings/core/v8/window_proxy_manager.cc
index ba9845625ea960c1f0be69251a41d51a3a1fd313..a1aa5de76a86cc0a135ae775e4d8455993f10e75 100644
--- a/third_party/blink/renderer/bindings/core/v8/window_proxy_manager.cc
+++ b/third_party/blink/renderer/bindings/core/v8/window_proxy_manager.cc
@@ -55,8 +55,11 @@ void WindowProxyManager::ReleaseGlobalProxies(
 
 void WindowProxyManager::SetGlobalProxies(
     const GlobalProxyVector& global_proxies) {
+  for (const auto& entry : global_proxies) {
+    WindowProxyMaybeUninitialized(*entry.first)->SetGlobalProxyWithoutInitializing(entry.second);
+  }
   for (const auto& entry : global_proxies)
-    WindowProxyMaybeUninitialized(*entry.first)->SetGlobalProxy(entry.second);
+    WindowProxyMaybeUninitialized(*entry.first)->InitializeIfNeeded();
 }
 
 WindowProxyManager::WindowProxyManager(Frame& frame, FrameType frame_type)
