diff --git a/DEPS b/DEPS
index 3f8aa64..dbac309 100644
--- a/DEPS
+++ b/DEPS
@@ -1241,7 +1241,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@8d6106e6549ad0691e686145979669c7b3bd7bab',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@611e7ba3af511b16a5b9c19b52f8f45162ed47ea',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/chrome/VERSION b/chrome/VERSION
index b5e786a..4e024cf 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=73
 MINOR=0
 BUILD=3683
-PATCH=79
+PATCH=84
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandler.java
index a5865b89..2479ef2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandler.java
@@ -347,11 +347,9 @@
         if (params.getUrl().startsWith(WTAI_MC_URL_PREFIX)) {
             // wtai://wp/mc;number
             // number=string(phone-number)
-            Intent wtaiIntent = new Intent(Intent.ACTION_VIEW,
+            mDelegate.startActivity(new Intent(Intent.ACTION_VIEW,
                     Uri.parse(WebView.SCHEME_TEL
-                            + params.getUrl().substring(WTAI_MC_URL_PREFIX.length())));
-            wtaiIntent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
-            mDelegate.startActivity(wtaiIntent, false);
+                            + params.getUrl().substring(WTAI_MC_URL_PREFIX.length()))), false);
             if (DEBUG) Log.i(TAG, "OVERRIDE_WITH_EXTERNAL_INTENT wtai:// link handled");
             RecordUserAction.record("Android.PhoneIntent");
             return OverrideUrlLoadingResult.OVERRIDE_WITH_EXTERNAL_INTENT;
@@ -406,9 +404,6 @@
         // Sanitize the Intent, ensuring web pages can not bypass browser
         // security (only access to BROWSABLE activities).
         intent.addCategory(Intent.CATEGORY_BROWSABLE);
-        // Do not target packages that have not been launched directly by the
-        // user at least once.
-        intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
         intent.setComponent(null);
         Intent selector = intent.getSelector();
         if (selector != null) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandlerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandlerTest.java
index 4f5cc0f..e4e83d5d3 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandlerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandlerTest.java
@@ -1950,18 +1950,6 @@
             Assert.assertEquals(expectStartFile, mDelegate.startFileIntentCalled);
             Assert.assertEquals(expectProxyForIA, mDelegate.mCalledWithProxy);
 
-            if (startActivityCalled) {
-                final Intent intent = mDelegate.startActivityIntent;
-                final Uri uri = intent.getData();
-                if (uri == null || uri.getScheme() == null || !uri.getScheme().equals("market")) {
-                    Assert.assertTrue("The intent URL " + mUrl + " (" + uri
-                                    + ") doesn't have FLAG_EXCLUDE_STOPPED_PACKAGES set\n",
-                            (mDelegate.startActivityIntent.getFlags()
-                                    & Intent.FLAG_EXCLUDE_STOPPED_PACKAGES)
-                                    != 0);
-                }
-            }
-
             if (startActivityCalled && expectSaneIntent) {
                 checkIntentSanity(mDelegate.startActivityIntent, "Intent");
                 if (mDelegate.startActivityIntent.getSelector() != null) {
diff --git a/chrome/browser/extensions/global_shortcut_listener_win.cc b/chrome/browser/extensions/global_shortcut_listener_win.cc
index eb58c51..f5d0ac4 100644
--- a/chrome/browser/extensions/global_shortcut_listener_win.cc
+++ b/chrome/browser/extensions/global_shortcut_listener_win.cc
@@ -93,12 +93,18 @@
     return success;
   }
 
+  // Convert Accelerator modifiers to OS modifiers.
+  int modifiers = 0;
+  modifiers |= accelerator.IsShiftDown() ? MOD_SHIFT : 0;
+  modifiers |= accelerator.IsCtrlDown() ? MOD_CONTROL : 0;
+  modifiers |= accelerator.IsAltDown() ? MOD_ALT : 0;
+
   // Create an observer that registers a hot key for |accelerator|.
   std::unique_ptr<gfx::SingletonHwndHotKeyObserver> observer =
       gfx::SingletonHwndHotKeyObserver::Create(
           base::BindRepeating(&GlobalShortcutListenerWin::OnWndProc,
                               base::Unretained(this)),
-          accelerator.key_code(), accelerator.modifiers());
+          accelerator.key_code(), modifiers);
 
   if (!observer) {
     // Most likely error: 1409 (Hotkey already registered).
diff --git a/chrome/browser/media/media_engagement_score.cc b/chrome/browser/media/media_engagement_score.cc
index bdda9b1..9a32200 100644
--- a/chrome/browser/media/media_engagement_score.cc
+++ b/chrome/browser/media/media_engagement_score.cc
@@ -57,6 +57,13 @@
   return std::make_unique<base::DictionaryValue>();
 }
 
+void GetIntegerFromScore(base::DictionaryValue* dict,
+                         base::StringPiece key,
+                         int* out) {
+  if (base::Value* v = dict->FindKeyOfType(key, base::Value::Type::INTEGER))
+    *out = v->GetInt();
+}
+
 }  // namespace
 
 // static.
@@ -101,21 +108,31 @@
   if (!score_dict_)
     return;
 
-  score_dict_->GetInteger(kVisitsKey, &visits_);
-  score_dict_->GetInteger(kMediaPlaybacksKey, &media_playbacks_);
-  score_dict_->GetBoolean(kHasHighScoreKey, &is_high_);
-  score_dict_->GetInteger(kAudiblePlaybacksKey, &audible_playbacks_);
-  score_dict_->GetInteger(kSignificantPlaybacksKey, &significant_playbacks_);
-  score_dict_->GetInteger(kVisitsWithMediaTagKey, &visits_with_media_tag_);
-  score_dict_->GetInteger(kHighScoreChanges, &high_score_changes_);
-  score_dict_->GetInteger(kSignificantMediaPlaybacksKey,
-                          &media_element_playbacks_);
-  score_dict_->GetInteger(kSignificantAudioContextPlaybacksKey,
-                          &audio_context_playbacks_);
+  GetIntegerFromScore(score_dict_.get(), kVisitsKey, &visits_);
+  GetIntegerFromScore(score_dict_.get(), kMediaPlaybacksKey, &media_playbacks_);
+  GetIntegerFromScore(score_dict_.get(), kAudiblePlaybacksKey,
+                      &audible_playbacks_);
+  GetIntegerFromScore(score_dict_.get(), kSignificantPlaybacksKey,
+                      &significant_playbacks_);
+  GetIntegerFromScore(score_dict_.get(), kVisitsWithMediaTagKey,
+                      &visits_with_media_tag_);
+  GetIntegerFromScore(score_dict_.get(), kHighScoreChanges,
+                      &high_score_changes_);
+  GetIntegerFromScore(score_dict_.get(), kSignificantMediaPlaybacksKey,
+                      &media_element_playbacks_);
+  GetIntegerFromScore(score_dict_.get(), kSignificantAudioContextPlaybacksKey,
+                      &audio_context_playbacks_);
 
-  double internal_time;
-  if (score_dict_->GetDouble(kLastMediaPlaybackTimeKey, &internal_time))
-    last_media_playback_time_ = base::Time::FromInternalValue(internal_time);
+  if (base::Value* value = score_dict_->FindKeyOfType(
+          kHasHighScoreKey, base::Value::Type::BOOLEAN)) {
+    is_high_ = value->GetBool();
+  }
+
+  if (base::Value* value = score_dict_->FindKeyOfType(
+          kLastMediaPlaybackTimeKey, base::Value::Type::DOUBLE)) {
+    last_media_playback_time_ =
+        base::Time::FromInternalValue(value->GetDouble());
+  }
 
   // Recalculate the total score and high bit. If the high bit changed we
   // should commit this. This should only happen if we change the threshold
@@ -184,21 +201,34 @@
   int stored_media_element_playbacks = 0;
   int stored_audio_context_playbacks = 0;
 
-  score_dict_->GetInteger(kVisitsKey, &stored_visits);
-  score_dict_->GetInteger(kMediaPlaybacksKey, &stored_media_playbacks);
-  score_dict_->GetDouble(kLastMediaPlaybackTimeKey,
-                         &stored_last_media_playback_internal);
-  score_dict_->GetBoolean(kHasHighScoreKey, &is_high);
-  score_dict_->GetInteger(kAudiblePlaybacksKey, &stored_audible_playbacks);
-  score_dict_->GetInteger(kSignificantPlaybacksKey,
-                          &stored_significant_playbacks);
-  score_dict_->GetInteger(kVisitsWithMediaTagKey,
-                          &stored_visits_with_media_tag);
-  score_dict_->GetInteger(kHighScoreChanges, &high_score_changes);
-  score_dict_->GetInteger(kSignificantMediaPlaybacksKey,
-                          &stored_media_element_playbacks);
-  score_dict_->GetInteger(kSignificantAudioContextPlaybacksKey,
-                          &stored_audio_context_playbacks);
+  if (!score_dict_)
+    return false;
+
+  if (base::Value* value = score_dict_->FindKeyOfType(
+          kHasHighScoreKey, base::Value::Type::BOOLEAN)) {
+    is_high = value->GetBool();
+  }
+
+  if (base::Value* value = score_dict_->FindKeyOfType(
+          kLastMediaPlaybackTimeKey, base::Value::Type::DOUBLE)) {
+    stored_last_media_playback_internal = value->GetDouble();
+  }
+
+  GetIntegerFromScore(score_dict_.get(), kVisitsKey, &stored_visits);
+  GetIntegerFromScore(score_dict_.get(), kMediaPlaybacksKey,
+                      &stored_media_playbacks);
+  GetIntegerFromScore(score_dict_.get(), kAudiblePlaybacksKey,
+                      &stored_audible_playbacks);
+  GetIntegerFromScore(score_dict_.get(), kSignificantPlaybacksKey,
+                      &stored_significant_playbacks);
+  GetIntegerFromScore(score_dict_.get(), kVisitsWithMediaTagKey,
+                      &stored_visits_with_media_tag);
+  GetIntegerFromScore(score_dict_.get(), kHighScoreChanges,
+                      &high_score_changes);
+  GetIntegerFromScore(score_dict_.get(), kSignificantMediaPlaybacksKey,
+                      &stored_media_element_playbacks);
+  GetIntegerFromScore(score_dict_.get(), kSignificantAudioContextPlaybacksKey,
+                      &stored_audio_context_playbacks);
 
   bool changed = stored_visits != visits() ||
                  stored_media_playbacks != media_playbacks() ||
diff --git a/chrome/browser/web_applications/components/web_app_shortcut_mac.mm b/chrome/browser/web_applications/components/web_app_shortcut_mac.mm
index caf98db..963c5c97 100644
--- a/chrome/browser/web_applications/components/web_app_shortcut_mac.mm
+++ b/chrome/browser/web_applications/components/web_app_shortcut_mac.mm
@@ -74,6 +74,7 @@
 @implementation TerminationObserver
 - (id)initWithRunningApplication:(NSRunningApplication*)app
                         callback:(base::OnceClosure)callback {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (self = [super init]) {
     callback_ = std::move(callback);
     app_.reset(app, base::scoped_policy::RETAIN);
@@ -95,22 +96,60 @@
   NSNumber* newNumberValue = [change objectForKey:NSKeyValueChangeNewKey];
   BOOL newValue = [newNumberValue boolValue];
   if (newValue) {
+    base::scoped_nsobject<TerminationObserver> scoped_self(
+        self, base::scoped_policy::RETAIN);
     base::PostTaskWithTraits(
         FROM_HERE, {content::BrowserThread::UI},
         base::BindOnce(
-            [](TerminationObserver* observer) { [observer onTerminated]; },
-            self));
+            [](base::scoped_nsobject<TerminationObserver> observer) {
+              [observer onTerminated];
+            },
+            scoped_self));
   }
 }
 
 - (void)onTerminated {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  // If |onTerminated| is called repeatedly (which in theory it should not),
+  // then ensure that we only call removeObserver and release once by doing an
+  // early-out if |callback_| has already been made.
+  if (!callback_)
+    return;
   std::move(callback_).Run();
+  DCHECK(!callback_);
   [app_ removeObserver:self forKeyPath:@"isTerminated" context:nullptr];
   [self release];
 }
 @end
 
+// TODO(https://crbug.com/941909): Change all launch functions to take a single
+// callback that returns a NSRunningApplication, rather than separate launch and
+// termination callbacks.
+void RunAppLaunchCallbacks(
+    base::scoped_nsobject<NSRunningApplication> app,
+    base::OnceCallback<void(base::Process)> launch_callback,
+    base::OnceClosure termination_callback) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  DCHECK(app);
+
+  // If the app doesn't have a valid pid, or if the application has been
+  // terminated, then indicate failure in |launch_callback|.
+  base::Process process([app processIdentifier]);
+  if (!process.IsValid() || [app isTerminated]) {
+    std::move(launch_callback).Run(base::Process());
+    return;
+  }
+
+  // Otherwise, indicate successful launch, and watch for termination.
+  // TODO(https://crbug.com/941909): This watches for termination indefinitely,
+  // but we only need to watch for termination until the app establishes a
+  // (whereupon termination will be noticed by the mojo connection closing).
+  std::move(launch_callback).Run(std::move(process));
+  [[TerminationObserver alloc]
+      initWithRunningApplication:app
+                        callback:std::move(termination_callback)];
+}
+
 bool g_app_shims_allow_update_and_launch_in_tests = false;
 
 namespace {
@@ -286,17 +325,16 @@
       command_line.AppendSwitch(app_mode::kLaunchedAfterRebuild);
 
     // Launch without activating (NSWorkspaceLaunchWithoutActivation).
-    NSRunningApplication* app = base::mac::OpenApplicationWithPath(
-        shim_path, command_line,
-        NSWorkspaceLaunchDefault | NSWorkspaceLaunchWithoutActivation);
+    base::scoped_nsobject<NSRunningApplication> app(
+        base::mac::OpenApplicationWithPath(
+            shim_path, command_line,
+            NSWorkspaceLaunchDefault | NSWorkspaceLaunchWithoutActivation),
+        base::scoped_policy::RETAIN);
     if (app) {
-      base::Process process([app processIdentifier]);
-      base::PostTaskWithTraits(
-          FROM_HERE, {content::BrowserThread::UI},
-          base::BindOnce(std::move(launched_callback), std::move(process)));
-      [[TerminationObserver alloc]
-          initWithRunningApplication:app
-                            callback:std::move(terminated_callback)];
+      base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
+                               base::BindOnce(&RunAppLaunchCallbacks, app,
+                                              std::move(launched_callback),
+                                              std::move(terminated_callback)));
       return;
     }
   }
diff --git a/content/browser/indexed_db/indexed_db_backing_store.h b/content/browser/indexed_db/indexed_db_backing_store.h
index 1f5f3ee4..353ecc1 100644
--- a/content/browser/indexed_db/indexed_db_backing_store.h
+++ b/content/browser/indexed_db/indexed_db_backing_store.h
@@ -568,11 +568,12 @@
   // an otherwise healthy backing store.
   leveldb::Status RevertSchemaToV2();
 
+  bool is_incognito() const { return !indexed_db_factory_; }
+
  protected:
   friend class base::RefCounted<IndexedDBBackingStore>;
   virtual ~IndexedDBBackingStore();
 
-  bool is_incognito() const { return !indexed_db_factory_; }
 
   leveldb::Status AnyDatabaseContainsBlobs(LevelDBTransaction* transaction,
                                            bool* blobs_exist);
diff --git a/content/browser/indexed_db/indexed_db_browsertest.cc b/content/browser/indexed_db/indexed_db_browsertest.cc
index 16e4b231..954b8550 100644
--- a/content/browser/indexed_db/indexed_db_browsertest.cc
+++ b/content/browser/indexed_db/indexed_db_browsertest.cc
@@ -90,7 +90,9 @@
         failure_class, failure_method, fail_on_instance_num, fail_on_call_num);
   }
 
-  void SimpleTest(const GURL& test_url, bool incognito = false) {
+  void SimpleTest(const GURL& test_url,
+                  bool incognito = false,
+                  Shell** shell_out = nullptr) {
     // The test page will perform tests on IndexedDB, then navigate to either
     // a #pass or #fail ref.
     Shell* the_browser = incognito ? CreateOffTheRecordBrowser() : shell();
@@ -107,6 +109,8 @@
           &js_result));
       FAIL() << "Failed: " << js_result;
     }
+    if (shell_out)
+      *shell_out = the_browser;
   }
 
   void NavigateAndWaitForTitle(Shell* shell,
@@ -307,6 +311,21 @@
   NavigateToURLBlockUntilNavigationsComplete(shell(), url, 1);
 }
 
+IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, Bug941965Test) {
+  // Double-open an incognito window to test that saving & reading a blob from
+  // indexeddb works.
+  Shell* incognito_browser = nullptr;
+  SimpleTest(GetTestUrl("indexeddb", "simple_blob_read.html"), true,
+             &incognito_browser);
+  ASSERT_TRUE(incognito_browser);
+  incognito_browser->Close();
+  incognito_browser = nullptr;
+  SimpleTest(GetTestUrl("indexeddb", "simple_blob_read.html"), true,
+             &incognito_browser);
+  ASSERT_TRUE(incognito_browser);
+  incognito_browser->Close();
+}
+
 class IndexedDBBrowserTestWithLowQuota : public IndexedDBBrowserTest {
  public:
   IndexedDBBrowserTestWithLowQuota() {}
diff --git a/content/browser/indexed_db/indexed_db_database.cc b/content/browser/indexed_db/indexed_db_database.cc
index e43ec59..de03eef 100644
--- a/content/browser/indexed_db/indexed_db_database.cc
+++ b/content/browser/indexed_db/indexed_db_database.cc
@@ -1880,10 +1880,10 @@
     request->AbortForForceClose();
   }
 
-  auto it = connections_.begin();
-  while (it != connections_.end()) {
-    IndexedDBConnection* connection = *it++;
+  while (!connections_.empty()) {
+    IndexedDBConnection* connection = *connections_.begin();
     connection->ForceClose();
+    connections_.erase(connection);
   }
   DCHECK(connections_.empty());
   DCHECK(!active_request_);
diff --git a/content/browser/indexed_db/indexed_db_database_unittest.cc b/content/browser/indexed_db/indexed_db_database_unittest.cc
index 37a644b..75066222 100644
--- a/content/browser/indexed_db/indexed_db_database_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_database_unittest.cc
@@ -314,6 +314,45 @@
   EXPECT_TRUE(request2->success_called());
 }
 
+TEST_F(IndexedDBDatabaseTest, ForceCloseWhileOpenPending) {
+  // Verify that pending connection requests are handled correctly during a
+  // ForceClose.
+  scoped_refptr<MockIndexedDBCallbacks> request1(new MockIndexedDBCallbacks());
+  scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks1(
+      new MockIndexedDBDatabaseCallbacks());
+  const int64_t transaction_id1 = 1;
+  std::unique_ptr<IndexedDBPendingConnection> connection(
+      std::make_unique<IndexedDBPendingConnection>(
+          request1, callbacks1, kFakeChildProcessId, transaction_id1,
+          IndexedDBDatabaseMetadata::DEFAULT_VERSION));
+  db_->OpenConnection(std::move(connection));
+
+  EXPECT_EQ(db_->ConnectionCount(), 1UL);
+  EXPECT_EQ(db_->ActiveOpenDeleteCount(), 0UL);
+  EXPECT_EQ(db_->PendingOpenDeleteCount(), 0UL);
+  EXPECT_FALSE(backing_store_->HasOneRef());  // local and db
+
+  scoped_refptr<MockIndexedDBCallbacks> request2(
+      new MockIndexedDBCallbacks(false));
+  scoped_refptr<MockIndexedDBDatabaseCallbacks> callbacks2(
+      new MockIndexedDBDatabaseCallbacks());
+  const int64_t transaction_id2 = 2;
+  std::unique_ptr<IndexedDBPendingConnection> connection2(
+      std::make_unique<IndexedDBPendingConnection>(
+          request1, callbacks1, kFakeChildProcessId, transaction_id2, 3));
+  db_->OpenConnection(std::move(connection2));
+
+  EXPECT_EQ(db_->ConnectionCount(), 1UL);
+  EXPECT_EQ(db_->ActiveOpenDeleteCount(), 1UL);
+  EXPECT_EQ(db_->PendingOpenDeleteCount(), 0UL);
+  EXPECT_FALSE(backing_store_->HasOneRef());  // local and db
+
+  db_->ForceClose();
+  EXPECT_EQ(db_->ConnectionCount(), 0UL);
+  EXPECT_EQ(db_->ActiveOpenDeleteCount(), 0UL);
+  EXPECT_EQ(db_->PendingOpenDeleteCount(), 0UL);
+}
+
 leveldb::Status DummyOperation(IndexedDBTransaction* transaction) {
   return leveldb::Status::OK();
 }
diff --git a/content/browser/indexed_db/indexed_db_factory_impl.cc b/content/browser/indexed_db/indexed_db_factory_impl.cc
index 29ea6f37..40bf1db45 100644
--- a/content/browser/indexed_db/indexed_db_factory_impl.cc
+++ b/content/browser/indexed_db/indexed_db_factory_impl.cc
@@ -716,9 +716,14 @@
   if (!s.ok())
     return {std::move(backing_store), s, data_loss_info, disk_full};
 
-  backing_store = CreateBackingStore(origin, blob_path, std::move(database),
-                                     context_->TaskRunner());
-
+  if (data_directory.empty()) {
+    backing_store = base::MakeRefCounted<IndexedDBBackingStore>(
+        nullptr, origin, base::FilePath(), std::move(database),
+        context_->TaskRunner());
+  } else {
+    backing_store = CreateBackingStore(origin, blob_path, std::move(database),
+                                       context_->TaskRunner());
+  }
   bool first_open_since_startup =
       backends_opened_since_startup_.insert(origin).second;
   s = backing_store->Initialize(
diff --git a/content/browser/indexed_db/indexed_db_factory_unittest.cc b/content/browser/indexed_db/indexed_db_factory_unittest.cc
index e7ce069..120432d 100644
--- a/content/browser/indexed_db/indexed_db_factory_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_factory_unittest.cc
@@ -386,6 +386,20 @@
   loop.Run();
 }
 
+TEST_F(IndexedDBFactoryTest, MemoryBackingStoreDetectedAsIncognito) {
+  base::RunLoop loop;
+  context()->TaskRunner()->PostTask(
+      FROM_HERE, base::BindLambdaForTesting([&]() {
+        auto factory = base::MakeRefCounted<MockIDBFactory>(context());
+        const Origin origin1 = Origin::Create(GURL("http://localhost:81"));
+        auto mem_store1 =
+            factory->TestOpenBackingStore(origin1, base::FilePath());
+        EXPECT_TRUE(mem_store1->is_incognito());
+        loop.Quit();
+      }));
+  loop.Run();
+}
+
 TEST_F(IndexedDBFactoryTest, RejectLongOrigins) {
   base::RunLoop loop;
   context()->TaskRunner()->PostTask(
diff --git a/content/browser/tracing/tracing_controller_impl.cc b/content/browser/tracing/tracing_controller_impl.cc
index beed93a..758526f 100644
--- a/content/browser/tracing/tracing_controller_impl.cc
+++ b/content/browser/tracing/tracing_controller_impl.cc
@@ -298,10 +298,7 @@
 
 bool TracingControllerImpl::GetCategories(GetCategoriesDoneCallback callback) {
   std::set<std::string> category_set;
-
-  tracing::TraceEventAgent::GetInstance()->GetCategories(&category_set);
-  for (auto& agent : agents_)
-    agent->GetCategories(&category_set);
+  tracing::TracedProcessImpl::GetInstance()->GetCategories(&category_set);
 
   std::move(callback).Run(category_set);
   return true;
diff --git a/content/browser/webrtc/webrtc_video_capture_browsertest.cc b/content/browser/webrtc/webrtc_video_capture_browsertest.cc
index 9e38210..a9eb78c 100644
--- a/content/browser/webrtc/webrtc_video_capture_browsertest.cc
+++ b/content/browser/webrtc/webrtc_video_capture_browsertest.cc
@@ -22,16 +22,6 @@
 
 namespace content {
 
-#if defined(OS_ANDROID)
-// Mojo video capture is currently not supported on Android
-// TODO(chfremer): Enable as soon as https://crbug.com/720500 is resolved.
-#define MAYBE_RecoverFromCrashInVideoCaptureProcess \
-  DISABLED_RecoverFromCrashInVideoCaptureProcess
-#else
-#define MAYBE_RecoverFromCrashInVideoCaptureProcess \
-  RecoverFromCrashInVideoCaptureProcess
-#endif  // defined(OS_ANDROID)
-
 namespace {
 
 static const char kVideoCaptureHtmlFile[] = "/media/video_capture_test.html";
@@ -63,6 +53,7 @@
   void SetUp() override {
     ASSERT_TRUE(embedded_test_server()->InitializeAndListen());
     EnablePixelOutput();
+    embedded_test_server()->StartAcceptingConnections();
     ContentBrowserTest::SetUp();
   }
 
@@ -73,8 +64,12 @@
 };
 
 IN_PROC_BROWSER_TEST_F(WebRtcVideoCaptureBrowserTest,
-                       MAYBE_RecoverFromCrashInVideoCaptureProcess) {
-  embedded_test_server()->StartAcceptingConnections();
+                       RecoverFromCrashInVideoCaptureProcess) {
+  // This test only makes sense if the video capture service runs in a
+  // separate process.
+  if (!features::IsVideoCaptureServiceEnabledForOutOfProcess())
+    return;
+
   GURL url(embedded_test_server()->GetURL(kVideoCaptureHtmlFile));
   NavigateToURL(shell(), url);
 
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
index 163f405..628f916 100644
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -5,10 +5,6 @@
 #include "content/public/common/content_features.h"
 #include "build/build_config.h"
 
-#if defined(OS_CHROMEOS)
-#include "media/capture/video/chromeos/public/cros_features.h"
-#endif
-
 namespace features {
 
 // All features in alphabetical order.
@@ -723,12 +719,11 @@
   if (!ShouldEnableVideoCaptureService())
     return VideoCaptureServiceConfiguration::kDisabled;
 
-#if defined(OS_ANDROID)
+// On ChromeOS the service must run in the browser process, because parts of the
+// code depend on global objects that are only available in the Browser process.
+// See https://crbug.com/891961.
+#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
   return VideoCaptureServiceConfiguration::kEnabledForBrowserProcess;
-#elif defined(OS_CHROMEOS)
-  return media::ShouldUseCrosCameraService()
-             ? VideoCaptureServiceConfiguration::kEnabledForBrowserProcess
-             : VideoCaptureServiceConfiguration::kEnabledForOutOfProcess;
 #else
   return base::FeatureList::IsEnabled(
              features::kRunVideoCaptureServiceInBrowserProcess)
diff --git a/content/test/data/indexeddb/simple_blob_read.html b/content/test/data/indexeddb/simple_blob_read.html
new file mode 100644
index 0000000..970600f
--- /dev/null
+++ b/content/test/data/indexeddb/simple_blob_read.html
@@ -0,0 +1,10 @@
+<html>
+  <head>
+    <title>IndexedDB simple blob reading test</title>
+    <script type="text/javascript" src="common.js"></script>
+    <script type="text/javascript" src="simple_blob_read.js"></script>
+  </head>
+  <body onLoad="test()">
+    <div id="status">Starting...</div>
+  </body>
+</html>
diff --git a/content/test/data/indexeddb/simple_blob_read.js b/content/test/data/indexeddb/simple_blob_read.js
new file mode 100644
index 0000000..e15eba5
--- /dev/null
+++ b/content/test/data/indexeddb/simple_blob_read.js
@@ -0,0 +1,68 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+const DB = 'db';
+const STORE = 'store';
+const DATA = 'blob value';
+run();
+
+function run() {
+  Object.assign(indexedDB.open(DB), {
+    unexpectedErrorCallback,
+    onupgradeneeded(e) {
+      debug("Created object store.");
+      e.target.result.createObjectStore(STORE, {
+        keyPath: 'id',
+      });
+    },
+    onsuccess(e) {
+      debug("Opened database.");
+      const idb = /** @type IDBDatabase */ e.target.result;
+      const op = idb
+        .transaction(STORE, 'readwrite')
+        .objectStore(STORE)
+        .put({
+          id: 'foo',
+          blob: new Blob([DATA]),
+        });
+      op.onerror = onerror;
+      op.onsuccess = () => {
+        debug("Wrote blob.");
+        idb.close();
+        setTimeout(verify);
+      }
+    },
+  });
+}
+
+function verify(e) {
+  debug("Reading blob.");
+  Object.assign(indexedDB.open(DB), {
+    onerror,
+    onsuccess(e) {
+      const idb = /** @type IDBDatabase */ e.target.result;
+      const op = idb
+        .transaction(STORE, 'readonly')
+        .objectStore(STORE)
+        .get('foo');
+      op.onerror = onerror;
+      op.onsuccess = async e => {
+        debug("Got blob.");
+        idb.close();
+        const entry = e.target.result;
+        if (!entry) {
+          fail('BAD: nothing was written');
+        } else {
+          const text = await (
+              await fetch(URL.createObjectURL(entry.blob))).text();
+          if (text === DATA) {
+            done();
+          } else {
+            fail(`BAD: written "${DATA}", got "${text}"`)
+          }
+        }
+      }
+    },
+  });
+}
\ No newline at end of file
diff --git a/extensions/browser/url_loader_factory_manager.cc b/extensions/browser/url_loader_factory_manager.cc
index c98ee0416..acabfb0 100644
--- a/extensions/browser/url_loader_factory_manager.cc
+++ b/extensions/browser/url_loader_factory_manager.cc
@@ -63,51 +63,105 @@
     "039F93DD1DF836F1D4E2084C1BEFDB46A854A9D1",
     "072D729E856B1F2C9894AEEC3A5DF65E519D6BEE",
     "07333481B7B8D7F57A9BA64FB98CF86EA87455FC",
+    "086E69ED9071DCB20C93A081A68360963AB09385",
+    "0C011D916B15E5451E1B84BD14397B8EC98F455B",
+    "0CB16BAEE070B7617E9188B387C44964FB705D79",
     "0EAEA2FDEE025D95B3ABB37014EFF5A98AC4BEAE",
+    "0FCD1282065485458E630683F098F591B24C406D",
     "109A37B889E7C8AEA7B0103559C3EB6AF73B7832",
     "16A81AEA09A67B03F7AEA5B957D24A4095E764BE",
     "177508B365CBF1610CC2B53707749D79272F2F0B",
     "1AB9CC404876117F49135E67BAD813F935AAE9BA",
+    "1B9251EF3EDD5A2B2872B168406F36FB18C72F37",
+    "1CDDF7436E5F891E1D5E37164F7EB992AECA0E2D",
     "1DB115A4344B58C0B7CC1595662E86C9E92C0848",
+    "1E37F1A19C1C528E616637B105CFC4838ECF52B4",
     "260871EABEDE6F2D07D0D9450096093EDAFCBF34",
+    "29427534E31BB1820714C7CAEDF9C54B47BE154F",
     "2AA94E2D3F4DA33F0D3BCF5DD48F69B8BDB26F52",
     "2FEFB2792E8FF41073E77C8E9B38C159C5A788A8",
+    "2C116B242B7425D359E188AB053B3F88DB78F78D",
+    "2E2D8A405430172AB15ADCC09740F3EEE990D605",
+    "31E6100DC7B4EAB4ABF6CA2A4E191D3945D3C731",
+    "3230014EA01150A27C1887B700E019B27A6DBA08",
     "3334952C8387B357A41DD8349D39AD9E7C423943",
     "33A4A3614CD4BF90F4F2C7984220A9D4FF24DFEF",
+    "34FB670464B5F16EF5ABD6CD53E26030E97C26B3",
     "360D8A88545D0C21CBDE2B55EA9E4E4285282B4C",
+    "37AC33A3A46D271CCE57DD6CB3FACE6B01F5A347",
+    "3CD98763C80D86E00CB1C4CAA56CEA8F3B0BA4F1",
+    "3EB17C39F8B6B28FAF34E2406E57A76013A2E066",
     "3FDD3DB17F3B686F5A05204700ABA13DF20AE957",
+    "41536C3554CD9458EB2F05F1B58CF84BB7BF83BC",
     "43865F8D555C201FE452A5A40702EA96240E749C",
+    "44943FADD66932EF56EE3D856A9FAAD4A8AF0FD9",
+    "47ADBB376050C083FFC54CC28CD3D1F54BF0BFED",
     "4913450195D177430217CAB64B356DC6F6B0F483",
     "4FC718F4549B18E68A45A11FC2B593033C7049D2",
+    "5053323D1F7B6EEC97A77A350DB6D0D8E51CD0AC",
     "505F2C1E723731B2C8C9182FEAA73D00525B2048",
+    "50DDD8734521B61564FCE273F8E60547F88BBCBE",
+    "52865B2087D0ABCD195A83DFD4BD041A3B4EBC34",
+    "52C94AC7680C3A03CCB6EA31445DD42BD0D5CA8E",
+    "58BCF05A42C8ECED4E6D76F51E2E1A64AC4F7E7C",
+    "5E052881B4847F68CFC8ED1A00C341FC14009C1E",
+    "5F0C47BC039BEDC1B29B68918F75370C292076A6",
     "61E581B10D83C0AEF8366BB64C18C6615884B3D2",
     "62D18583FC239861A9661C922A5F13A57EE7EDD7",
+    "6357533CAFFB94A9EA5268ED110079E15561E469",
+    "65C20C06ED10E6F39EED527AC736D87B0390DE70",
+    "67528F9B47BE454EC46809C33D24F2C199BE408D",
     "6AE81EF3B13B15080A2DDB23A205A24C65CCC10B",
     "6BA5F75FFF75B69507BC4B09B7094926EF93DBD2",
+    "6E49449D56D031B87835CC767734AF5A064E1A13",
+    "71CB78C3334D5122E7F23C8525AD24100CDE7D4A",
     "71EE66C0F71CD89BEE340F8568A44101D4C3A9A7",
+    "7527942941BFF13D66B46E7A2A56FDBA873FB9E6",
+    "77D83E0A4157A0E77B51AD60BAB69A346CD4FEA3",
+    "7879DB88205D880B64D55E51B9726E1D12F7261F",
     "7BFE588B209A15260DE12777B4BBB738DE98FE6C",
     "808FA9BB3CD501D7801D1CD6D5A3DBA088FDD46F",
     "82FDBBF79F3517C3946BD89EAAF90C46DFDA4681",
+    "83B6C75264D5D2F81FDEFD681EDD2076DD8F0B9B",
     "88C372CE52E21560C17BFD52556E60D694E12CAC",
     "88F5F459139892C0F5DF3022676726BB3F01FB5C",
+    "89C9B32115F19A18E9BE4906DC59F24A934CB9F0",
+    "89F40D84C0C72C6B02B320716E877FB1671218E9",
+    "8A0634388BCBB6D073E1C97B14C024396ED32D12",
     "8CDD303D6C341D9CAB16713C3CD7587B90A7A84A",
+    "8CE6227B4E53DF42FF93B24F49D15EDE31E97E79",
     "934B8F5753A3E5A276FC7D0EE5E575B335A0CC76",
     "973E35633030AD27DABEC99609424A61386C7309",
+    "97E04C5632954E778306CAC40B3F95C470B463B6",
+    "98EF7B1601119AEE1FCC28EE5CE247DED5676539",
     "99E06C364BBB2D1F82A9D20BC1645BF21E478259",
+    "A04F08A772F1C83B7A14ED29788ACA4F000BBE05",
+    "A07DA0EDB967D027E3B220208AD085FDC44C3231",
     "A30E526CF62131BFBFD7CD9B56253A8F3F171777",
     "A3660FA31A0DBF07C9F80D5342FF215DBC962719",
+    "A6057397EDC4E6CF25BC3A142F866ACC653B1CF1",
     "A8FB3967ADE404B77AC3FB5815A399C0660C3C63",
     "A9A4B26C2387BA2A5861C790B0FF39F230427AC8",
     "A9F78610B717B3992F92F490E82FC63FFF46C5FA",
+    "AA3DE48E23B2465B21F5D33E993FD959F611DD10",
     "AEEDAC793F184240CFB800DA73EE6321E5145102",
+    "B3CF6C01796E8D03378FAA77AF507E27BB847E9D",
     "B4782AE831D849EFCC2AF4BE2012816EDDF8D908",
     "BF5224FB246A6B67EA986EFF77A43F6C1BCA9672",
+    "C5539F4EBECABA792CC40D03A56144AAD3BF9D19",
     "C5BCB9E2E47C3F6FD3F7F83ED982872F77852BA7",
+    "C86D546CA47034163C12DC2C912910C3A12C3B07",
+    "C940F83135D9612865F4A44391DDDFE3B7BE1393",
     "CA89BD35059845F2DB4B4398FD339B9F210E9337",
     "CC74B2408753932B5D49C81EC073E3E4CA766EE6",
     "CD8AF9C47DDE6327F8D9A3EFA81F34C6B6C26EBB",
     "CF40F6289951CBFA3B83B792EFA774E2EA06E4C0",
     "D0537B1BADCE856227CE76E31B3772F6B68F653C",
+    "D347F78F32567E90BC32D9C16B085254EA269590",
+    "D9A97CD75380C697C65D37512E53DBECDFA45FB9",
+    "DDA21167F058A65D878DF84C3CF3FCC60B053E80",
+    "E134BC4A0FF6C59CE42CC76BA6B2D6F5DC648EC4",
+    "E178D4F4D6617C0B880C36F192DA3B18422C5064",
     "E6B12430B6166B31BE20E13941C22569EA75B0F2",
     "E7036E906DBFB77C46EDDEB003A72C0B5CC9BE7F",
     "E873675B8E754F1B1F1222CB921EA14B4335179D",
@@ -115,10 +169,15 @@
     "EC24668224116D19FF1A5FFAA61238B88773982C",
     "EC4A841BD03C8E5202043165188A9E060BF703A3",
     "EE4BE5F23D2E59E4713958465941EFB4A18166B7",
+    "F1ACA279F460440E47078D91FE372212DD9B8709",
+    "F273C23C616F5C56E8EDBAE24B21F5D408936A0D",
     "F566B33D62CE21415AF5B3F3FD8762B7454B8874",
     "F59AB261280AB3AE9826D9359507838B90B07431",
     "F73F9EF0207603992CA3C00A7A0CB223D5571B3F",
     "F9287A33E15038F2591F23E6E9C486717C7202DD",
+    "FEE3DC8C722657A4A5B0F72CA48CF950DC956148",
+    "FF0DA4BD87A88469B10709B99E79D4B0E11C0CA6",
+    "FF8257C73304BA655E10F324C962504BA6691DF2",
 };
 
 constexpr size_t kHashedExtensionIdLength = base::kSHA1Length * 2;
diff --git a/gpu/ipc/client/command_buffer_proxy_impl.cc b/gpu/ipc/client/command_buffer_proxy_impl.cc
index 57827e5..d1405a8 100644
--- a/gpu/ipc/client/command_buffer_proxy_impl.cc
+++ b/gpu/ipc/client/command_buffer_proxy_impl.cc
@@ -637,7 +637,10 @@
   if (last_state_.error != gpu::error::kNoError)
     return;
 
-  Send(new GpuCommandBufferMsg_TakeFrontBuffer(route_id_, mailbox));
+  // TakeFrontBuffer should be a deferred message so that it's sequenced
+  // correctly with respect to preceding ReturnFrontBuffer messages.
+  last_flush_id_ = channel_->EnqueueDeferredMessage(
+      GpuCommandBufferMsg_TakeFrontBuffer(route_id_, mailbox));
 }
 
 void CommandBufferProxyImpl::ReturnFrontBuffer(const gpu::Mailbox& mailbox,
diff --git a/gpu/ipc/service/gpu_channel.cc b/gpu/ipc/service/gpu_channel.cc
index c966dfe..f061ec17 100644
--- a/gpu/ipc/service/gpu_channel.cc
+++ b/gpu/ipc/service/gpu_channel.cc
@@ -237,6 +237,7 @@
     case GpuCommandBufferMsg_AsyncFlush::ID:
     case GpuCommandBufferMsg_DestroyTransferBuffer::ID:
     case GpuCommandBufferMsg_ReturnFrontBuffer::ID:
+    case GpuCommandBufferMsg_TakeFrontBuffer::ID:
     case GpuChannelMsg_CreateSharedImage::ID:
     case GpuChannelMsg_DestroySharedImage::ID:
       return MessageErrorHandler(message, "Invalid message");
diff --git a/services/tracing/public/cpp/traced_process_impl.cc b/services/tracing/public/cpp/traced_process_impl.cc
index e380d01..7ae592a 100644
--- a/services/tracing/public/cpp/traced_process_impl.cc
+++ b/services/tracing/public/cpp/traced_process_impl.cc
@@ -105,4 +105,10 @@
       tracing::mojom::PerfettoServicePtr(std::move(request->perfetto_service)));
 }
 
+void TracedProcessImpl::GetCategories(std::set<std::string>* category_set) {
+  for (auto* agent : agents_) {
+    agent->GetCategories(category_set);
+  }
+}
+
 }  // namespace tracing
diff --git a/services/tracing/public/cpp/traced_process_impl.h b/services/tracing/public/cpp/traced_process_impl.h
index 1522fdf..5d7a503a6 100644
--- a/services/tracing/public/cpp/traced_process_impl.h
+++ b/services/tracing/public/cpp/traced_process_impl.h
@@ -35,6 +35,9 @@
   void RegisterAgent(BaseAgent* agent);
   void UnregisterAgent(BaseAgent* agent);
 
+  // Populate categories from all of the registered agents.
+  void GetCategories(std::set<std::string>* category_set);
+
  private:
   friend class base::NoDestructor<TracedProcessImpl>;
   TracedProcessImpl();
diff --git a/third_party/libjingle_xmpp/README.chromium b/third_party/libjingle_xmpp/README.chromium
index 5ae9ef2..23aaef4e 100644
--- a/third_party/libjingle_xmpp/README.chromium
+++ b/third_party/libjingle_xmpp/README.chromium
@@ -21,8 +21,4 @@
 unused in Chromium, it's OK to delete it.
 
 Local Modifications:
-* Include paths in third_party/libjingle_xmpp/xmllite,
-  third_party/libjingle_xmpp/xmpp, and third_party/libjingle_xmpp/task_runner
-  are updated to reflect the new absolute paths to their own and webrtc's
-  headers.
-* disabled unstarted_task_test.DoNotDeleteTask2 under ASan
+This code does not exist in an upstream repo anymore.
diff --git a/third_party/libjingle_xmpp/xmpp/xmppclient.cc b/third_party/libjingle_xmpp/xmpp/xmppclient.cc
index 8a19078..de92055 100644
--- a/third_party/libjingle_xmpp/xmpp/xmppclient.cc
+++ b/third_party/libjingle_xmpp/xmpp/xmppclient.cc
@@ -111,7 +111,7 @@
   // For other servers, we leave the strings empty, which causes the jid's
   // domain to be used.  We do the same for gmail.com and googlemail.com as the
   // returned CN matches the account domain in those cases.
-  std::string server_name = settings.server().ToString();
+  std::string server_name = settings.server().host();
   if (server_name == jingle_xmpp::STR_TALK_GOOGLE_COM ||
       server_name == jingle_xmpp::STR_TALKX_L_GOOGLE_COM ||
       server_name == jingle_xmpp::STR_XMPP_GOOGLE_COM ||
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn
index ae38b8f..19df213 100644
--- a/ui/views/BUILD.gn
+++ b/ui/views/BUILD.gn
@@ -782,6 +782,7 @@
       "AppKit.framework",
       "CoreGraphics.framework",
       "Foundation.framework",
+      "IOSurface.framework",
       "QuartzCore.framework",  # Required by bridged_native_widget.mm.
     ]
   }
diff --git a/ui/views/cocoa/bridged_native_widget_host_impl.h b/ui/views/cocoa/bridged_native_widget_host_impl.h
index 2f82d8e9..2214108 100644
--- a/ui/views/cocoa/bridged_native_widget_host_impl.h
+++ b/ui/views/cocoa/bridged_native_widget_host_impl.h
@@ -426,6 +426,12 @@
   // Display link for getting vsync info for |display_|.
   scoped_refptr<ui::DisplayLinkMac> display_link_;
 
+  // Structure to avoid sending IOSurface mach ports over mojo.
+  // https://crbug.com/942213
+  class IOSurfaceToRemoteLayerInterceptor;
+  std::unique_ptr<IOSurfaceToRemoteLayerInterceptor>
+      io_surface_to_remote_layer_interceptor_;
+
   // The geometry of the window and its contents view, in screen coordinates.
   gfx::Rect window_bounds_in_screen_;
   gfx::Rect content_bounds_in_screen_;
diff --git a/ui/views/cocoa/bridged_native_widget_host_impl.mm b/ui/views/cocoa/bridged_native_widget_host_impl.mm
index a156f05..37206fa1e 100644
--- a/ui/views/cocoa/bridged_native_widget_host_impl.mm
+++ b/ui/views/cocoa/bridged_native_widget_host_impl.mm
@@ -9,7 +9,9 @@
 #include "base/mac/foundation_util.h"
 #include "mojo/public/cpp/bindings/strong_associated_binding.h"
 #include "ui/accelerated_widget_mac/window_resize_helper_mac.h"
+#include "ui/base/cocoa/animation_utils.h"
 #include "ui/base/cocoa/remote_accessibility_api.h"
+#include "ui/base/cocoa/remote_layer_api.h"
 #include "ui/base/hit_test.h"
 #include "ui/base/ime/input_method.h"
 #include "ui/base/ime/input_method_factory.h"
@@ -206,6 +208,60 @@
 
 }  // namespace
 
+// A gfx::CALayerParams may pass the content to be drawn across processes via
+// either an IOSurface (sent as mach port) or a CAContextID (which is an
+// integer). For historical reasons, software compositing uses IOSurfaces.
+// The mojo connection to the app shim process does not support sending mach
+// ports, which results in nothing being drawn when using software compositing.
+// To work around this issue, this structure creates a CALayer that uses the
+// IOSurface as its contents, and hosts this CALayer in a CAContext that is
+// the gfx::CALayerParams is then pointed to.
+// https://crbug.com/942213
+class BridgedNativeWidgetHostImpl::IOSurfaceToRemoteLayerInterceptor {
+ public:
+  IOSurfaceToRemoteLayerInterceptor() = default;
+  ~IOSurfaceToRemoteLayerInterceptor() = default;
+
+  void UpdateCALayerParams(gfx::CALayerParams* ca_layer_params) {
+    DCHECK(ca_layer_params->io_surface_mach_port);
+    base::ScopedCFTypeRef<IOSurfaceRef> io_surface(
+        IOSurfaceLookupFromMachPort(ca_layer_params->io_surface_mach_port));
+
+    ScopedCAActionDisabler disabler;
+    // Lazily create |io_surface_layer_| and |ca_context_|.
+    if (!io_surface_layer_) {
+      io_surface_layer_.reset([[CALayer alloc] init]);
+      [io_surface_layer_ setContentsGravity:kCAGravityTopLeft];
+      [io_surface_layer_ setAnchorPoint:CGPointMake(0, 0)];
+    }
+    if (!ca_context_) {
+      CGSConnectionID connection_id = CGSMainConnectionID();
+      ca_context_.reset([[CAContext contextWithCGSConnection:connection_id
+                                                     options:@{}] retain]);
+      [ca_context_ setLayer:io_surface_layer_];
+    }
+
+    // Update |io_surface_layer_| to draw the contents of |ca_layer_params|.
+    id new_contents = static_cast<id>(io_surface.get());
+    [io_surface_layer_ setContents:new_contents];
+    gfx::Size bounds_dip = gfx::ConvertSizeToDIP(ca_layer_params->scale_factor,
+                                                 ca_layer_params->pixel_size);
+    [io_surface_layer_
+        setBounds:CGRectMake(0, 0, bounds_dip.width(), bounds_dip.height())];
+    if ([io_surface_layer_ contentsScale] != ca_layer_params->scale_factor)
+      [io_surface_layer_ setContentsScale:ca_layer_params->scale_factor];
+
+    // Change |ca_layer_params| to use |ca_context_| instead of an IOSurface.
+    ca_layer_params->ca_context_id = [ca_context_ contextId];
+    ca_layer_params->io_surface_mach_port.reset();
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(IOSurfaceToRemoteLayerInterceptor);
+  base::scoped_nsobject<CAContext> ca_context_;
+  base::scoped_nsobject<CALayer> io_surface_layer_;
+};
+
 // static
 BridgedNativeWidgetHostImpl* BridgedNativeWidgetHostImpl::GetFromNativeWindow(
     gfx::NativeWindow native_window) {
@@ -1356,8 +1412,26 @@
 void BridgedNativeWidgetHostImpl::AcceleratedWidgetCALayerParamsUpdated() {
   const gfx::CALayerParams* ca_layer_params =
       compositor_->widget()->GetCALayerParams();
-  if (ca_layer_params)
-    bridge()->SetCALayerParams(*ca_layer_params);
+  if (ca_layer_params) {
+    // Replace IOSurface mach ports with CAContextIDs only when using the
+    // out-of-process bridge (to reduce risk, because this workaround is being
+    // merged to late-life-cycle release branches) and when an IOSurface
+    // mach port has been specified (in practice, when software compositing is
+    // enabled).
+    // https://crbug.com/942213
+    if (bridge_ptr_ && ca_layer_params->io_surface_mach_port) {
+      gfx::CALayerParams updated_ca_layer_params = *ca_layer_params;
+      if (!io_surface_to_remote_layer_interceptor_) {
+        io_surface_to_remote_layer_interceptor_ =
+            std::make_unique<IOSurfaceToRemoteLayerInterceptor>();
+      }
+      io_surface_to_remote_layer_interceptor_->UpdateCALayerParams(
+          &updated_ca_layer_params);
+      bridge_ptr_->SetCALayerParams(updated_ca_layer_params);
+    } else {
+      bridge()->SetCALayerParams(*ca_layer_params);
+    }
+  }
 
   // Take this opportunity to update the VSync parameters, if needed.
   if (display_link_) {
diff --git a/ui/views_bridge_mac/native_widget_mac_nswindow.mm b/ui/views_bridge_mac/native_widget_mac_nswindow.mm
index 54ec2c8..fac57d3 100644
--- a/ui/views_bridge_mac/native_widget_mac_nswindow.mm
+++ b/ui/views_bridge_mac/native_widget_mac_nswindow.mm
@@ -200,6 +200,12 @@
 
 // Lets the traffic light buttons on the parent window keep their active state.
 - (BOOL)hasKeyAppearance {
+  // Note that this function is called off of the main thread. In such cases,
+  // it is not safe to access the mojo interface or the ui::Widget, as they are
+  // not reentrant.
+  // https://crbug.com/941506.
+  if (![NSThread isMainThread])
+    return [super hasKeyAppearance];
   if (bridgeImpl_) {
     bool isAlwaysRenderWindowAsKey = NO;
     bridgeImpl_->host()->GetAlwaysRenderWindowAsKey(&isAlwaysRenderWindowAsKey);