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);