diff --git a/.gitignore b/.gitignore index f50a151..79990a0 100644 --- a/.gitignore +++ b/.gitignore
@@ -72,8 +72,9 @@ /base/base_unittests_run.xml # See build/.gitignore for entries covering src/build. -# The Chrome OS build creates a /c symlink due to http://crbug.com/54866. +# The Chrome OS build creates a /c and /c_icu symlink due to http://crbug.com/54866. /c +/c_icu /cdm /ceee/internal/ /chrome/android/profiles/afdo.prof @@ -327,4 +328,3 @@ # Ignore the default results output directory for tools/run-swarmed.py /results -
diff --git a/DEPS b/DEPS index fb7744e..d0d37fd9 100644 --- a/DEPS +++ b/DEPS
@@ -195,11 +195,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': 'a5f3c3149033dffc4d706fe34eb40714fc63d8c0', + 'skia_revision': '3eb813e0cc134767a10e9efd4811fc519eccb280', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': '7b2a8dea4181d991083b4e4ade123aeffb1a66df', + 'v8_revision': 'e0d5b2a8208346a0c10ac96bfef2a78311b7f7a0', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other. @@ -207,7 +207,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': 'b44af6625286df933a688779d139ec33cd3e492a', + 'angle_revision': 'ee7ae7aba2c91034b6304dcad1df5823ff3d5702', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -901,7 +901,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '407b5a54a9b5a96fcd6ec33717782fb2f1dd6447', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'd1580d53b7bc1f244d4eaf797aca0d066fad166c', 'src/third_party/devtools-frontend/src': Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), @@ -1032,7 +1032,7 @@ Var('chromium_git') + '/chromium/deps/hunspell_dictionaries.git' + '@' + '18e09b9197a3b1d771c077c530d1a4ebad04c167', 'src/third_party/icu': - Var('chromium_git') + '/chromium/deps/icu.git' + '@' + '79326efe26e5440f530963704c3c0ff965b3a4ac', + Var('chromium_git') + '/chromium/deps/icu.git' + '@' + 'aef20f06d47ba76fdf13abcdb033e2a408b5a94d', 'src/third_party/icu4j': { 'packages': [ @@ -1544,7 +1544,7 @@ 'packages': [ { 'package': 'skia/tools/goldctl/mac-amd64', - 'version': 'nLiRBOlDnLpGaONe3dMmjU3S8K3bfjiA0p4VZkqV2IEC', + 'version': 'McQX6w7ojyNaDcWISrmicbt00IsXxTSvxjuEPfPLiIEC', }, ], 'dep_type': 'cipd', @@ -1558,7 +1558,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@9bcb0cadf78f889a0eca925b2f38efd420b206e4', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@aad83522fd172502e4b3783190db56538bb706bd', 'condition': 'checkout_src_internal', },
diff --git a/android_webview/java/src/org/chromium/android_webview/common/crash/SystemWideCrashDirectories.java b/android_webview/java/src/org/chromium/android_webview/common/crash/SystemWideCrashDirectories.java index fe3bc09c..a020efed0 100644 --- a/android_webview/java/src/org/chromium/android_webview/common/crash/SystemWideCrashDirectories.java +++ b/android_webview/java/src/org/chromium/android_webview/common/crash/SystemWideCrashDirectories.java
@@ -17,6 +17,7 @@ private static final String WEBVIEW_CRASH_LOG_DIR = "crash_logs"; private static final String WEBVIEW_CRASH_DIR = "WebView_Crashes"; private static final String WEBVIEW_TMP_CRASH_DIR = "WebView_Crashes_Tmp"; + private static final String WEBVIEW_CRASH_LOG_SUFFIX = "_log.json"; /** * Create the directory in which WebView will log crashes info. @@ -61,6 +62,14 @@ return new File(ContextUtils.getApplicationContext().getCacheDir(), WEBVIEW_TMP_CRASH_DIR); } + /** + * Create Crash json log file in the crash log directory. + * @return a File pointing to the created crash json log file. + */ + public static File createCrashJsonLogFile(String logFileName) { + return new File(getOrCreateWebViewCrashLogDir(), logFileName + WEBVIEW_CRASH_LOG_SUFFIX); + } + private static File getOrCreateDir(File dir) { // Call mkdir before isDirectory to ensure that if another thread created the directory // just before the call to mkdir, the current thread fails mkdir, but passes isDirectory.
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwAutofillTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwAutofillTest.java index a078f7c..9c2f2fb 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwAutofillTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwAutofillTest.java
@@ -1238,12 +1238,13 @@ } /** - * This test is verifying the session is still alive after navigation. + * This test is verifying that a navigation occurring while there is a probably-submitted + * form will trigger commit of the current autofill session. */ @Test @SmallTest @Feature({"AndroidWebView"}) - public void testSessionAliveAfterNavigation() throws Throwable { + public void testNavigationAfterProbableSubmitResultsInSessionCommit() throws Throwable { int cnt = 0; final String data = "<!DOCTYPE html>" + "<html>"
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/devui/CrashesListFragmentTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/devui/CrashesListFragmentTest.java index b3b9220..71aa218 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/devui/CrashesListFragmentTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/devui/CrashesListFragmentTest.java
@@ -268,9 +268,36 @@ */ private static DataInteraction checkUnknownPackageCrashItemHeader( DataInteraction headerDataInteraction, CrashInfo crashInfo) { + return checkPackageCrashItemHeader(headerDataInteraction, crashInfo, FAKE_APP_PACKAGE_NAME); + } + + /** + * Check that the given crash item header shows the "unknown app" package name, capture date and + * icon for the given {@code crashInfo}. + * + * @param {@link DataInteraction} represents the crash item header. + * @param {@link CrashInfo} to match. + * @return the same {@code headerDataInteraction} passed for the convenience of chaining. + */ + private static DataInteraction checkMissingPackageInfoCrashItemHeader( + DataInteraction headerDataInteraction, CrashInfo crashInfo) { + return checkPackageCrashItemHeader(headerDataInteraction, crashInfo, "unknown app"); + } + + /** + * Check that the given crash item header shows the given package name, capture date and + * icon for the given {@code crashInfo}. + * + * @param {@link DataInteraction} represents the crash item header. + * @param {@link CrashInfo} to match. + * @param packageName to match. + * @return the same {@code headerDataInteraction} passed for the convenience of chaining. + */ + private static DataInteraction checkPackageCrashItemHeader( + DataInteraction headerDataInteraction, CrashInfo crashInfo, String packageName) { String captureDate = new Date(crashInfo.captureTime).toString(); headerDataInteraction.onChildView(withId(android.R.id.text1)) - .check(matches(withText(FAKE_APP_PACKAGE_NAME))); + .check(matches(withText(packageName))); headerDataInteraction.onChildView(withId(android.R.id.text2)) .check(matches(withText(captureDate))); // There should not be an app with FAKE_APP_PACKAGE_NAME so system default icon should be @@ -282,6 +309,19 @@ } /** + * Perform click on hide crash button by checking the required conditions for the button. + * + * @param {@link DataInteraction} represents the crash item body. + */ + private static void clickHideCrashButton(DataInteraction bodyDataInteraction) { + bodyDataInteraction.onChildView(withId(R.id.crash_hide_button)) + .check(matches(isDisplayed())) + .check(matches(isEnabled())) + .check(matches(withDrawable(R.drawable.ic_delete))) + .perform(click()); + } + + /** * Check that the given crash item body shows the correct uploadState, uploadId and uploadDate. * * @param {@link DataInteraction} represents the crash item body. @@ -701,11 +741,44 @@ onView(withId(R.id.crashes_list)).check(matches(withCount(1))); - DataInteraction headerDataInteraction = onData(anything()).atPosition(0); - headerDataInteraction.onChildView(withId(android.R.id.text1)) - .check(matches(withText("unknown app"))); - headerDataInteraction.onChildView(withId(R.id.crash_package_icon)) - .check(matches(withDrawable(android.R.drawable.sym_def_app_icon))); + checkMissingPackageInfoCrashItemHeader(onData(anything()).atPosition(0), crashInfo); + } + + @Test + @Feature({"AndroidWebView"}) + // Test when crash is missing json, but has upload log file and minidump. + public void testShowingSingleCrashReport_uploaded_missingJson() throws Throwable { + CrashInfo crashInfo = createCrashInfo("123456", -1, null, 1000, null, UploadState.UPLOADED); + + assertThat("temp minidump file should exist", createMinidumpFile(crashInfo).exists()); + assertThat("upload log file should exist", appendUploadedEntryToLog(crashInfo).exists()); + + CallbackHelper helper = getCrashListLoadedListener(); + int crashListLoadInitCount = helper.getCallCount(); + launchCrashesFragment(); + helper.waitForCallback(crashListLoadInitCount, 1); + + onView(withId(R.id.crashes_list)).check(matches(withCount(1))); + + checkMissingPackageInfoCrashItemHeader(onData(anything()).atPosition(0), crashInfo); + } + + @Test + @Feature({"AndroidWebView"}) + // Test when crash is missing json, but has upload log file and minidump. + public void testShowingSingleCrashReport_pending_missingJson() throws Throwable { + CrashInfo crashInfo = createCrashInfo("123456", -1, null, 1000, null, UploadState.PENDING); + + assertThat("temp minidump file should exist", createMinidumpFile(crashInfo).exists()); + + CallbackHelper helper = getCrashListLoadedListener(); + int crashListLoadInitCount = helper.getCallCount(); + launchCrashesFragment(); + helper.waitForCallback(crashListLoadInitCount, 1); + + onView(withId(R.id.crashes_list)).check(matches(withCount(1))); + + checkMissingPackageInfoCrashItemHeader(onData(anything()).atPosition(0), crashInfo); } @Test @@ -766,13 +839,7 @@ DataInteraction bodyDataInteraction = onData(anything()).atPosition(1); crashListLoadInitCount = helper.getCallCount(); - - bodyDataInteraction.onChildView(withId(R.id.crash_hide_button)) - .check(matches(isDisplayed())) - .check(matches(isEnabled())) - .check(matches(withDrawable(R.drawable.ic_delete))) - .perform(click()); - + clickHideCrashButton(bodyDataInteraction); helper.waitForCallback(crashListLoadInitCount, 1); onView(withId(R.id.crashes_list)).check(matches(withCount(0))); @@ -803,13 +870,64 @@ DataInteraction bodyDataInteraction = onData(anything()).atPosition(1); crashListLoadInitCount = helper.getCallCount(); + clickHideCrashButton(bodyDataInteraction); + helper.waitForCallback(crashListLoadInitCount, 1); - bodyDataInteraction.onChildView(withId(R.id.crash_hide_button)) - .check(matches(isDisplayed())) - .check(matches(isEnabled())) - .check(matches(withDrawable(R.drawable.ic_delete))) - .perform(click()); + onView(withId(R.id.crashes_list)).check(matches(withCount(0))); + } + @Test + @Feature({"AndroidWebView"}) + public void testHideCrashButton_uploaded_missingJson() throws Throwable { + CrashInfo crashInfo = createCrashInfo("123456", -1, null, 1000, null, UploadState.UPLOADED); + + assertThat("temp minidump file should exist", createMinidumpFile(crashInfo).exists()); + assertThat("upload log file should exist", appendUploadedEntryToLog(crashInfo).exists()); + + CallbackHelper helper = getCrashListLoadedListener(); + int crashListLoadInitCount = helper.getCallCount(); + launchCrashesFragment(); + helper.waitForCallback(crashListLoadInitCount, 1); + + onView(withId(R.id.crashes_list)).check(matches(withCount(1))); + + // Check crash item header + checkMissingPackageInfoCrashItemHeader(onData(anything()).atPosition(0), crashInfo) + .perform(click()); // click to expand it + // The body is considered item#2 in the list view after expansion + onView(withId(R.id.crashes_list)).check(matches(withCount(2))); + DataInteraction bodyDataInteraction = onData(anything()).atPosition(1); + + crashListLoadInitCount = helper.getCallCount(); + clickHideCrashButton(bodyDataInteraction); + helper.waitForCallback(crashListLoadInitCount, 1); + + onView(withId(R.id.crashes_list)).check(matches(withCount(0))); + } + + @Test + @Feature({"AndroidWebView"}) + public void testHideCrashButton_pending_missingJson() throws Throwable { + CrashInfo crashInfo = createCrashInfo("123456", -1, null, -1, null, UploadState.PENDING); + + assertThat("temp minidump file should exist", createMinidumpFile(crashInfo).exists()); + + CallbackHelper helper = getCrashListLoadedListener(); + int crashListLoadInitCount = helper.getCallCount(); + launchCrashesFragment(); + helper.waitForCallback(crashListLoadInitCount, 1); + + onView(withId(R.id.crashes_list)).check(matches(withCount(1))); + + // Check crash item header + checkMissingPackageInfoCrashItemHeader(onData(anything()).atPosition(0), crashInfo) + .perform(click()); // click to expand it + // The body is considered item#2 in the list view after expansion + onView(withId(R.id.crashes_list)).check(matches(withCount(2))); + DataInteraction bodyDataInteraction = onData(anything()).atPosition(1); + + crashListLoadInitCount = helper.getCallCount(); + clickHideCrashButton(bodyDataInteraction); helper.waitForCallback(crashListLoadInitCount, 1); onView(withId(R.id.crashes_list)).check(matches(withCount(0)));
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/devui/util/WebViewCrashInfoCollectorTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/devui/util/WebViewCrashInfoCollectorTest.java index 55ba41ce..d391a6c 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/devui/util/WebViewCrashInfoCollectorTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/devui/util/WebViewCrashInfoCollectorTest.java
@@ -230,6 +230,6 @@ WebViewCrashInfoCollector.updateCrashLogFileWithNewCrashInfo(newCrashInfo); CrashInfo resultCrashInfo = getCrashFromJsonLogFile("xyz123"); - Assert.assertThat(resultCrashInfo, equalsTo(null)); + Assert.assertThat(resultCrashInfo, equalsTo(newCrashInfo)); } }
diff --git a/android_webview/nonembedded/java/src/org/chromium/android_webview/devui/util/WebViewCrashInfoCollector.java b/android_webview/nonembedded/java/src/org/chromium/android_webview/devui/util/WebViewCrashInfoCollector.java index 4f4062f..e965e77 100644 --- a/android_webview/nonembedded/java/src/org/chromium/android_webview/devui/util/WebViewCrashInfoCollector.java +++ b/android_webview/nonembedded/java/src/org/chromium/android_webview/devui/util/WebViewCrashInfoCollector.java
@@ -146,28 +146,31 @@ * Modify WebView crash JSON log file with the new crash info if the JSON file exists */ public static void updateCrashLogFileWithNewCrashInfo(CrashInfo crashInfo) { - File logDir = SystemWideCrashDirectories.getWebViewCrashLogDir(); + File logDir = SystemWideCrashDirectories.getOrCreateWebViewCrashLogDir(); File[] logFiles = logDir.listFiles(); - if (logFiles == null) { - return; - } for (File logFile : logFiles) { // Ignore non-json files. if (!logFile.isFile() || !logFile.getName().endsWith(".json")) continue; // Ignore unrelated json files if (!logFile.getName().contains(crashInfo.localId)) continue; - try { - FileWriter writer = new FileWriter(logFile); - try { - writer.write(crashInfo.serializeToJson()); - } finally { - writer.close(); - } - } catch (IOException e) { - Log.e(TAG, "failed to modify JSON log entry for crash", e); - } + tryWritingCrashInfoToLogFile(crashInfo, logFile); return; } - // logfile does not exist + // logfile does not exist, so creates and writes to a new logfile + File newLogFile = SystemWideCrashDirectories.createCrashJsonLogFile(crashInfo.localId); + tryWritingCrashInfoToLogFile(crashInfo, newLogFile); + } + + private static void tryWritingCrashInfoToLogFile(CrashInfo crashInfo, File logFile) { + try { + FileWriter writer = new FileWriter(logFile); + try { + writer.write(crashInfo.serializeToJson()); + } finally { + writer.close(); + } + } catch (IOException e) { + Log.e(TAG, "failed to modify JSON log entry for crash", e); + } } }
diff --git a/android_webview/nonembedded/java/src/org/chromium/android_webview/services/CrashReceiverService.java b/android_webview/nonembedded/java/src/org/chromium/android_webview/services/CrashReceiverService.java index 30378a7..39c7329 100644 --- a/android_webview/nonembedded/java/src/org/chromium/android_webview/services/CrashReceiverService.java +++ b/android_webview/nonembedded/java/src/org/chromium/android_webview/services/CrashReceiverService.java
@@ -30,7 +30,6 @@ */ public class CrashReceiverService extends Service { private static final String TAG = "CrashReceiverService"; - private static final String WEBVIEW_CRASH_LOG_SUFFIX = "_log.json"; private final Object mCopyingLock = new Object(); private boolean mIsCopying; @@ -123,9 +122,8 @@ copiedAnything = true; if (crashesInfo != null) { Map<String, String> crashInfo = crashesInfo.get(i); - File logFile = new File( - SystemWideCrashDirectories.getOrCreateWebViewCrashLogDir(), - copiedFile.getName() + WEBVIEW_CRASH_LOG_SUFFIX); + File logFile = SystemWideCrashDirectories.createCrashJsonLogFile( + copiedFile.getName()); writeCrashInfoToLogFile(logFile, copiedFile, crashInfo); } }
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index 15eadfc0..c7863b9 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -926,12 +926,12 @@ "system/holding_space/holding_space_item_chip_view.h", "system/holding_space/holding_space_item_chips_container.cc", "system/holding_space/holding_space_item_chips_container.h", + "system/holding_space/holding_space_item_context_menu.cc", + "system/holding_space/holding_space_item_context_menu.h", "system/holding_space/holding_space_item_screenshot_view.cc", "system/holding_space/holding_space_item_screenshot_view.h", "system/holding_space/holding_space_item_view.cc", "system/holding_space/holding_space_item_view.h", - "system/holding_space/holding_space_item_view_delegate.cc", - "system/holding_space/holding_space_item_view_delegate.h", "system/holding_space/holding_space_item_views_container.cc", "system/holding_space/holding_space_item_views_container.h", "system/holding_space/holding_space_tray.cc",
diff --git a/ash/ambient/ambient_constants.h b/ash/ambient/ambient_constants.h index fb1959a..8248007 100644 --- a/ash/ambient/ambient_constants.h +++ b/ash/ambient/ambient_constants.h
@@ -48,6 +48,10 @@ constexpr base::TimeDelta kTokenUsageTimeBuffer = base::TimeDelta::FromMinutes(10); +// PhotoView related constants. +// Spacing between two portrait images. +constexpr int kMarginLeftOfRelatedImageDip = 8; + } // namespace ash #endif // ASH_AMBIENT_AMBIENT_CONSTANTS_H_
diff --git a/ash/ambient/ambient_photo_controller.cc b/ash/ambient/ambient_photo_controller.cc index 5b00b627..b892d22 100644 --- a/ash/ambient/ambient_photo_controller.cc +++ b/ash/ambient/ambient_photo_controller.cc
@@ -14,6 +14,7 @@ #include "ash/public/cpp/ambient/ambient_client.h" #include "ash/public/cpp/image_downloader.h" #include "ash/shell.h" +#include "base/barrier_closure.h" #include "base/base64.h" #include "base/base_paths.h" #include "base/bind.h" @@ -324,15 +325,44 @@ StartDownloadingWeatherConditionIcon(screen_update.weather_info); } +void AmbientPhotoController::ResetImageData() { + image_data_.reset(); + related_image_data_.reset(); + image_details_.reset(); + + image_ = gfx::ImageSkia(); + related_image_ = gfx::ImageSkia(); +} + void AmbientPhotoController::FetchPhotoRawData() { const AmbientModeTopic* topic = GetNextTopic(); + ResetImageData(); + if (topic) { + const int num_callbacks = (topic->related_image_url) ? 2 : 1; + auto on_done = base::BarrierClosure( + num_callbacks, + base::BindOnce(&AmbientPhotoController::OnAllPhotoRawDataAvailable, + weak_factory_.GetWeakPtr(), + /*from_downloading=*/true)); + url_loader_->Download( - topic->GetUrl(), + topic->url, base::BindOnce(&AmbientPhotoController::OnPhotoRawDataAvailable, weak_factory_.GetWeakPtr(), /*from_downloading=*/true, + /*is_related_image=*/false, on_done, std::make_unique<std::string>(topic->details))); + + if (topic->related_image_url) { + url_loader_->Download( + *(topic->related_image_url), + base::BindOnce(&AmbientPhotoController::OnPhotoRawDataAvailable, + weak_factory_.GetWeakPtr(), + /*from_downloading=*/true, + /*is_related_image=*/true, on_done, + std::make_unique<std::string>(topic->details))); + } return; } @@ -367,6 +397,10 @@ auto photo_data = std::make_unique<std::string>(); auto photo_details = std::make_unique<std::string>(); + auto on_done = + base::BindRepeating(&AmbientPhotoController::OnAllPhotoRawDataAvailable, + weak_factory_.GetWeakPtr(), + /*from_downloading=*/false); task_runner_->PostTaskAndReply( FROM_HERE, base::BindOnce( @@ -386,14 +420,27 @@ file_name, photo_data.get(), photo_details.get()), base::BindOnce(&AmbientPhotoController::OnPhotoRawDataAvailable, weak_factory_.GetWeakPtr(), /*from_downloading=*/false, + /*is_related_image=*/false, on_done, std::move(photo_details), std::move(photo_data))); } void AmbientPhotoController::OnPhotoRawDataAvailable( bool from_downloading, + bool is_related_image, + base::RepeatingClosure on_done, std::unique_ptr<std::string> details, std::unique_ptr<std::string> data) { - if (!data || data->empty()) { + if (is_related_image) + related_image_data_ = std::move(data); + else { + image_data_ = std::move(data); + image_details_ = std::move(details); + } + std::move(on_done).Run(); +} + +void AmbientPhotoController::OnAllPhotoRawDataAvailable(bool from_downloading) { + if (!image_data_ || image_data_->empty()) { if (from_downloading) { LOG(ERROR) << "Failed to download image"; resume_fetch_image_backoff_.InformOfRequest(/*succeeded=*/false); @@ -414,6 +461,12 @@ if (cache_index_for_store_ == kMaxNumberOfCachedImages) cache_index_for_store_ = 0; + const int num_callbacks = related_image_data_ ? 2 : 1; + auto on_done = base::BarrierClosure( + num_callbacks, + base::BindOnce(&AmbientPhotoController::OnAllPhotoDecoded, + weak_factory_.GetWeakPtr(), from_downloading)); + task_runner_->PostTaskAndReply( FROM_HERE, base::BindOnce( @@ -425,28 +478,44 @@ details); } }, - file_name, from_downloading, *data, *details), + file_name, from_downloading, *image_data_, *image_details_), base::BindOnce(&AmbientPhotoController::DecodePhotoRawData, weak_factory_.GetWeakPtr(), from_downloading, - std::move(details), std::move(data))); + /*is_related_image=*/false, on_done, + std::move(image_data_))); + + if (related_image_data_) { + DecodePhotoRawData(from_downloading, /*is_related_image=*/true, on_done, + std::move(related_image_data_)); + } } void AmbientPhotoController::DecodePhotoRawData( bool from_downloading, - std::unique_ptr<std::string> details, + bool is_related_image, + base::RepeatingClosure on_done, std::unique_ptr<std::string> data) { std::vector<uint8_t> image_bytes(data->begin(), data->end()); image_decoder_->Decode( image_bytes, base::BindOnce(&AmbientPhotoController::OnPhotoDecoded, weak_factory_.GetWeakPtr(), from_downloading, - std::move(details))); + is_related_image, on_done)); } -void AmbientPhotoController::OnPhotoDecoded( - bool from_downloading, - std::unique_ptr<std::string> details, - const gfx::ImageSkia& image) { - if (image.isNull()) { +void AmbientPhotoController::OnPhotoDecoded(bool from_downloading, + bool is_related_image, + base::RepeatingClosure on_done, + const gfx::ImageSkia& image) { + if (is_related_image) + related_image_ = image; + else + image_ = image; + + std::move(on_done).Run(); +} + +void AmbientPhotoController::OnAllPhotoDecoded(bool from_downloading) { + if (image_.isNull()) { LOG(WARNING) << "Image is null"; if (from_downloading) resume_fetch_image_backoff_.InformOfRequest(/*succeeded=*/false); @@ -461,8 +530,12 @@ resume_fetch_image_backoff_.InformOfRequest(/*succeeded=*/true); PhotoWithDetails detailed_photo; - detailed_photo.photo = image; - detailed_photo.details = *details; + detailed_photo.photo = image_; + detailed_photo.related_photo = related_image_; + detailed_photo.details = *image_details_; + + ResetImageData(); + ambient_backend_model_.AddNextImage(std::move(detailed_photo)); ScheduleRefreshImage();
diff --git a/ash/ambient/ambient_photo_controller.h b/ash/ambient/ambient_photo_controller.h index 85abd91..256c247 100644 --- a/ash/ambient/ambient_photo_controller.h +++ b/ash/ambient/ambient_photo_controller.h
@@ -118,6 +118,9 @@ void OnScreenUpdateInfoFetched(const ash::ScreenUpdate& screen_update); + // Clear temporary image data to prepare next photos. + void ResetImageData(); + // Fetch photo raw data by downloading or reading from cache. void FetchPhotoRawData(); @@ -125,17 +128,25 @@ void TryReadPhotoRawData(); void OnPhotoRawDataAvailable(bool from_downloading, + bool is_related_image, + base::RepeatingClosure on_done, std::unique_ptr<std::string> details, std::unique_ptr<std::string> data); + void OnAllPhotoRawDataAvailable(bool from_downloading); + void DecodePhotoRawData(bool from_downloading, - std::unique_ptr<std::string> details, + bool is_related_image, + base::RepeatingClosure on_done, std::unique_ptr<std::string> data); void OnPhotoDecoded(bool from_downloading, - std::unique_ptr<std::string> details, + bool is_related_image, + base::RepeatingClosure on_done, const gfx::ImageSkia& image); + void OnAllPhotoDecoded(bool from_downloading); + void StartDownloadingWeatherConditionIcon( const base::Optional<WeatherInfo>& weather_info); @@ -209,6 +220,13 @@ scoped_refptr<base::SequencedTaskRunner> task_runner_; + // Temporary data store when fetching images and details. + std::unique_ptr<std::string> image_data_; + std::unique_ptr<std::string> related_image_data_; + std::unique_ptr<std::string> image_details_; + gfx::ImageSkia image_; + gfx::ImageSkia related_image_; + base::WeakPtrFactory<AmbientPhotoController> weak_factory_{this}; DISALLOW_COPY_AND_ASSIGN(AmbientPhotoController);
diff --git a/ash/ambient/backdrop/ambient_backend_controller_impl.cc b/ash/ambient/backdrop/ambient_backend_controller_impl.cc index 97b4d309..7d3cacc8 100644 --- a/ash/ambient/backdrop/ambient_backend_controller_impl.cc +++ b/ash/ambient/backdrop/ambient_backend_controller_impl.cc
@@ -127,9 +127,22 @@ for (auto& backdrop_topic : backdrop_screen_update.next_topics()) { AmbientModeTopic ambient_topic; DCHECK(backdrop_topic.has_url()); - ambient_topic.url = backdrop_topic.url(); + if (backdrop_topic.has_portrait_image_url()) - ambient_topic.portrait_image_url = backdrop_topic.portrait_image_url(); + ambient_topic.url = backdrop_topic.portrait_image_url(); + else + ambient_topic.url = backdrop_topic.url(); + + if (backdrop_topic.has_related_topic()) { + if (backdrop_topic.related_topic().has_portrait_image_url()) { + ambient_topic.related_image_url = + backdrop_topic.related_topic().portrait_image_url(); + } else { + ambient_topic.related_image_url = + backdrop_topic.related_topic().url(); + } + } + BuildBackdropTopicDetails(backdrop_topic, ambient_topic); screen_update.next_topics.emplace_back(ambient_topic); }
diff --git a/ash/ambient/model/ambient_backend_model.h b/ash/ambient/model/ambient_backend_model.h index 7d295f8f..bdad83d 100644 --- a/ash/ambient/model/ambient_backend_model.h +++ b/ash/ambient/model/ambient_backend_model.h
@@ -34,6 +34,7 @@ bool IsNull() const; gfx::ImageSkia photo; + gfx::ImageSkia related_photo; std::string details; };
diff --git a/ash/ambient/ui/ambient_background_image_view.cc b/ash/ambient/ui/ambient_background_image_view.cc index b4d28189..ae4b540 100644 --- a/ash/ambient/ui/ambient_background_image_view.cc +++ b/ash/ambient/ui/ambient_background_image_view.cc
@@ -6,17 +6,22 @@ #include <memory> +#include "ash/ambient/ambient_constants.h" #include "ash/ambient/ui/glanceable_info_view.h" #include "ash/ambient/util/ambient_util.h" #include "ash/assistant/ui/assistant_view_ids.h" #include "base/rand_util.h" #include "ui/events/event.h" #include "ui/gfx/geometry/insets.h" +#include "ui/gfx/image/image_skia_operations.h" #include "ui/views/controls/image_view.h" #include "ui/views/controls/label.h" #include "ui/views/layout/box_layout.h" #include "ui/views/layout/fill_layout.h" +#include "ui/views/layout/flex_layout.h" +#include "ui/views/layout/flex_layout_types.h" #include "ui/views/metadata/metadata_impl_macros.h" +#include "ui/views/view_class_properties.h" namespace ash { @@ -39,6 +44,37 @@ int current_x_translation = 0; int current_y_translation = 0; +const views::FlexSpecification kUnboundedScaleToZero( + views::MinimumFlexSizeRule::kScaleToZero, + views::MaximumFlexSizeRule::kUnbounded); + +gfx::ImageSkia ResizeImage(const gfx::ImageSkia& image, + const gfx::Size& view_size) { + if (image.isNull()) + return gfx::ImageSkia(); + + const double image_width = image.width(); + const double image_height = image.height(); + const double view_width = view_size.width(); + const double view_height = view_size.height(); + const double horizontal_ratio = view_width / image_width; + const double vertical_ratio = view_height / image_height; + const double image_ratio = image_height / image_width; + const double view_ratio = view_height / view_width; + + // If the image and the container view has the same orientation, e.g. both + // portrait, the |scale| will make the image filled the whole view with + // possible cropping on one direction. If they are in different orientation, + // the |scale| will display the image in the view without any cropping, but + // with empty background. + const double scale = (image_ratio - 1) * (view_ratio - 1) > 0 + ? std::max(horizontal_ratio, vertical_ratio) + : std::min(horizontal_ratio, vertical_ratio); + const gfx::Size& resized = gfx::ScaleToCeiledSize(image.size(), scale); + return gfx::ImageSkiaOperations::CreateResizedImage( + image, skia::ImageOperations::RESIZE_BEST, resized); +} + } // namespace AmbientBackgroundImageView::AmbientBackgroundImageView( @@ -65,10 +101,43 @@ } } -void AmbientBackgroundImageView::UpdateImage(const gfx::ImageSkia& img) { - image_view_->SetImage(img); +void AmbientBackgroundImageView::OnBoundsChanged( + const gfx::Rect& previous_bounds) { + if (!GetVisible()) + return; + + if (width() == 0) + return; + + // When bounds changes, recalculate the visibility of related image view. + UpdateRelatedImageViewVisibility(); +} + +void AmbientBackgroundImageView::OnViewBoundsChanged( + views::View* observed_view) { + if (observed_view == image_view_) + SetResizedImage(image_view_, image_unscaled_); + else + SetResizedImage(related_image_view_, related_image_unscaled_); +} + +void AmbientBackgroundImageView::UpdateImage( + const gfx::ImageSkia& image, + const gfx::ImageSkia& related_image) { + image_unscaled_ = image; + related_image_unscaled_ = related_image; UpdateGlanceableInfoPosition(); + + const bool has_change = UpdateRelatedImageViewVisibility(); + + // If there is no change in the visibility of related image view, call + // SetResizedImages() directly. Otherwise it will be called from + // OnViewBoundsChanged(). + if (!has_change) { + SetResizedImage(image_view_, image_unscaled_); + SetResizedImage(related_image_view_, related_image_unscaled_); + } } void AmbientBackgroundImageView::UpdateImageDetails( @@ -80,15 +149,49 @@ return image_view_->GetImage(); } -gfx::Rect AmbientBackgroundImageView::GetCurrentImageBoundsForTesting() const { +gfx::Rect AmbientBackgroundImageView::GetImageBoundsForTesting() const { return image_view_->GetImageBounds(); } +gfx::Rect AmbientBackgroundImageView::GetRelatedImageBoundsForTesting() const { + return related_image_view_->GetVisible() + ? related_image_view_->GetImageBounds() + : gfx::Rect(); +} + +void AmbientBackgroundImageView::ResetRelatedImageForTesting() { + related_image_unscaled_ = gfx::ImageSkia(); + UpdateRelatedImageViewVisibility(); +} + void AmbientBackgroundImageView::InitLayout() { SetLayoutManager(std::make_unique<views::FillLayout>()); - // Inits the image view. This view should have the same size of the screen. - image_view_ = AddChildView(std::make_unique<views::ImageView>()); + // Inits container for images. + image_container_ = AddChildView(std::make_unique<views::View>()); + views::FlexLayout* image_layout = + image_container_->SetLayoutManager(std::make_unique<views::FlexLayout>()); + image_layout->SetOrientation(views::LayoutOrientation::kHorizontal); + image_layout->SetMainAxisAlignment(views::LayoutAlignment::kCenter); + image_layout->SetCrossAxisAlignment(views::LayoutAlignment::kStretch); + image_view_ = + image_container_->AddChildView(std::make_unique<views::ImageView>()); + // Set a place holder size for Flex layout to assign bounds. + image_view_->SetPreferredSize(gfx::Size(1, 1)); + image_view_->SetProperty(views::kFlexBehaviorKey, kUnboundedScaleToZero); + observed_views_.Add(image_view_); + + related_image_view_ = + image_container_->AddChildView(std::make_unique<views::ImageView>()); + // Set a place holder size for Flex layout to assign bounds. + related_image_view_->SetPreferredSize(gfx::Size(1, 1)); + related_image_view_->SetProperty(views::kFlexBehaviorKey, + kUnboundedScaleToZero); + observed_views_.Add(related_image_view_); + + // Set spacing between two images. + related_image_view_->SetProperty( + views::kMarginsKey, gfx::Insets(0, kMarginLeftOfRelatedImageDip, 0, 0)); gfx::Insets shadow_insets = gfx::ShadowValue::GetMargin(ambient::util::GetTextShadowValues()); @@ -161,6 +264,41 @@ details_label_->layer()->SetTransform(transform); } +bool AmbientBackgroundImageView::UpdateRelatedImageViewVisibility() { + const bool did_show_pair = related_image_view_->GetVisible(); + const bool show_pair = IsLandscapeOrientation() && HasPairedPortraitImages(); + related_image_view_->SetVisible(show_pair); + return did_show_pair != show_pair; +} + +void AmbientBackgroundImageView::SetResizedImage( + views::ImageView* image_view, + const gfx::ImageSkia& image_unscaled) { + if (!image_view->GetVisible()) + return; + + if (image_unscaled.isNull()) + return; + + image_view->SetImage(ResizeImage(image_unscaled, image_view->size())); + + // Intend to update the image origin in image view. + // There is no bounds change or preferred size change when updating image from + // landscape to portrait when device is in portrait orientation because we + // only show one photo. Call ResetImageSize() to trigger UpdateImageOrigin(). + image_view->ResetImageSize(); +} + +bool AmbientBackgroundImageView::IsLandscapeOrientation() const { + return width() > height(); +} + +bool AmbientBackgroundImageView::HasPairedPortraitImages() const { + const auto& primary_image = image_unscaled_; + return !primary_image.isNull() && !related_image_unscaled_.isNull() && + primary_image.height() > primary_image.width(); +} + BEGIN_METADATA(AmbientBackgroundImageView, views::View) END_METADATA
diff --git a/ash/ambient/ui/ambient_background_image_view.h b/ash/ambient/ui/ambient_background_image_view.h index fbbb046e..efffebe 100644 --- a/ash/ambient/ui/ambient_background_image_view.h +++ b/ash/ambient/ui/ambient_background_image_view.h
@@ -9,9 +9,11 @@ #include "ash/ambient/ui/ambient_view_delegate.h" #include "ash/ash_export.h" +#include "base/scoped_observer.h" #include "ui/views/controls/image_view.h" #include "ui/views/metadata/metadata_header_macros.h" #include "ui/views/view.h" +#include "ui/views/view_observer.h" namespace views { class Label; @@ -25,7 +27,8 @@ // A custom ImageView to display photo image and details information on ambient. // It also handles specific mouse/gesture events to dismiss ambient when user // interacts with the background photos. -class ASH_EXPORT AmbientBackgroundImageView : public views::View { +class ASH_EXPORT AmbientBackgroundImageView : public views::View, + public views::ViewObserver { public: METADATA_HEADER(AmbientBackgroundImageView); @@ -34,36 +37,60 @@ AmbientBackgroundImageView& operator=(AmbientBackgroundImageView&) = delete; ~AmbientBackgroundImageView() override; - // views::View + // views::View: bool OnMousePressed(const ui::MouseEvent& event) override; void OnGestureEvent(ui::GestureEvent* event) override; + void OnBoundsChanged(const gfx::Rect& previous_bounds) override; - // Updates the display image. - void UpdateImage(const gfx::ImageSkia& img); + // views::ViewObserver: + void OnViewBoundsChanged(views::View* observed_view) override; + + // Updates the display images. + void UpdateImage(const gfx::ImageSkia& image, + const gfx::ImageSkia& related_image); // Updates the details for the currently displayed image. void UpdateImageDetails(const base::string16& details); const gfx::ImageSkia& GetCurrentImage(); - gfx::Rect GetCurrentImageBoundsForTesting() const; + gfx::Rect GetImageBoundsForTesting() const; + gfx::Rect GetRelatedImageBoundsForTesting() const; + void ResetRelatedImageForTesting(); private: void InitLayout(); void UpdateGlanceableInfoPosition(); + bool UpdateRelatedImageViewVisibility(); + void SetResizedImage(views::ImageView* image_view, + const gfx::ImageSkia& image_unscaled); + + // Whether the device is in landscape orientation. + bool IsLandscapeOrientation() const; + + bool HasPairedPortraitImages() const; + // Owned by |AmbientController| and should always outlive |this|. AmbientViewDelegate* delegate_ = nullptr; - // View to display the current image on ambient. Owned by the view hierarchy. + // View to display current image(s) on ambient. Owned by the view hierarchy. + views::View* image_container_ = nullptr; views::ImageView* image_view_ = nullptr; + views::ImageView* related_image_view_ = nullptr; + + // The unscaled images used for scaling and displaying in different bounds. + gfx::ImageSkia image_unscaled_; + gfx::ImageSkia related_image_unscaled_; GlanceableInfoView* glanceable_info_view_ = nullptr; // Label to show details text, i.e. attribution, to be displayed for the // current image. Owned by the view hierarchy. views::Label* details_label_ = nullptr; + + ScopedObserver<views::View, views::ViewObserver> observed_views_{this}; }; } // namespace ash
diff --git a/ash/ambient/ui/photo_view.cc b/ash/ambient/ui/photo_view.cc index 95e23cae7..6b5cd5a 100644 --- a/ash/ambient/ui/photo_view.cc +++ b/ash/ambient/ui/photo_view.cc
@@ -21,7 +21,6 @@ #include "ui/compositor/animation_throughput_reporter.h" #include "ui/compositor/layer.h" #include "ui/compositor/scoped_layer_animation_settings.h" -#include "ui/gfx/image/image_skia_operations.h" #include "ui/views/controls/image_view.h" #include "ui/views/layout/fill_layout.h" @@ -36,32 +35,6 @@ base::UmaHistogramPercentage(kPhotoTransitionSmoothness, value); } -gfx::ImageSkia ResizeImage(const gfx::ImageSkia& image, - const gfx::Size& view_size) { - if (image.isNull()) - return gfx::ImageSkia(); - - const double image_width = image.width(); - const double image_height = image.height(); - const double view_width = view_size.width(); - const double view_height = view_size.height(); - const double horizontal_ratio = view_width / image_width; - const double vertical_ratio = view_height / image_height; - const double image_ratio = image_height / image_width; - const double view_ratio = view_height / view_width; - - // If the image and the container view has the same orientation, e.g. both - // portrait, the |scale| will make the image filled the whole view with - // possible cropping on one direction. If they are in different orientation, - // the |scale| will display the image in the view without any cropping, but - // with empty background. - const double scale = (image_ratio - 1) * (view_ratio - 1) > 0 - ? std::max(horizontal_ratio, vertical_ratio) - : std::min(horizontal_ratio, vertical_ratio); - const gfx::Size& resized = gfx::ScaleToCeiledSize(image.size(), scale); - return gfx::ImageSkiaOperations::CreateResizedImage( - image, skia::ImageOperations::RESIZE_BEST, resized); -} } // namespace @@ -80,14 +53,6 @@ return "PhotoView"; } -void PhotoView::OnBoundsChanged(const gfx::Rect& previous_bounds) { - for (const int index : {0, 1}) { - auto image = images_unscaled_[index]; - auto image_resized = ResizeImage(image, size()); - image_views_[index]->UpdateImage(image_resized); - } -} - void PhotoView::OnImagesChanged() { // If NeedToAnimate() is true, will start transition animation and // UpdateImages() when animation completes. Otherwise, update images @@ -123,12 +88,11 @@ void PhotoView::UpdateImages() { auto* model = delegate_->GetAmbientBackendModel(); auto& next_image = model->GetNextImage(); - images_unscaled_[image_index_] = next_image.photo; - if (images_unscaled_[image_index_].isNull()) + if (next_image.photo.isNull()) return; - auto next_resized = ResizeImage(images_unscaled_[image_index_], size()); - image_views_[image_index_]->UpdateImage(next_resized); + image_views_[image_index_]->UpdateImage(next_image.photo, + next_image.related_photo); image_views_[image_index_]->UpdateImageDetails( base::UTF8ToUTF16(next_image.details)); image_index_ = 1 - image_index_; @@ -178,7 +142,7 @@ bool PhotoView::NeedToAnimateTransition() const { // Can do transition animation if both two images in |images_unscaled_| are // not nullptr. Check the image index 1 is enough. - return !images_unscaled_[1].isNull(); + return !image_views_[1]->GetCurrentImage().isNull(); } const gfx::ImageSkia& PhotoView::GetCurrentImagesForTesting() {
diff --git a/ash/ambient/ui/photo_view.h b/ash/ambient/ui/photo_view.h index f35af10..457b043 100644 --- a/ash/ambient/ui/photo_view.h +++ b/ash/ambient/ui/photo_view.h
@@ -35,7 +35,6 @@ // views::View: const char* GetClassName() const override; - void OnBoundsChanged(const gfx::Rect& previous_bounds) override; // AmbientBackendModelObserver: void OnImagesChanged() override; @@ -47,7 +46,9 @@ friend class AmbientAshTestBase; void Init(); + void UpdateImages(); + void StartTransitionAnimation(); // Return if can start transition animation. @@ -62,9 +63,6 @@ // Image containers used for animation. Owned by view hierarchy. AmbientBackgroundImageView* image_views_[2]{nullptr, nullptr}; - // The unscaled images used for scaling and displaying in different bounds. - gfx::ImageSkia images_unscaled_[2]; - // The index of |image_views_| to update the next image. int image_index_ = 0; };
diff --git a/ash/ambient/ui/photo_view_unittest.cc b/ash/ambient/ui/photo_view_unittest.cc index c1dd844..9663844 100644 --- a/ash/ambient/ui/photo_view_unittest.cc +++ b/ash/ambient/ui/photo_view_unittest.cc
@@ -32,8 +32,9 @@ // Image should be full width. Image height should extend above and below the // visible part of the screen. - ASSERT_EQ(image_view->GetCurrentImageBoundsForTesting(), + ASSERT_EQ(image_view->GetImageBoundsForTesting(), gfx::Rect(/*x=*/0, /*y=*/-200, /*width=*/600, /*height=*/1200)); + ASSERT_EQ(image_view->GetRelatedImageBoundsForTesting(), gfx::Rect()); } // Test that image is scaled to fill screen width when the image is landscape @@ -52,14 +53,92 @@ // Image should be full width. Image should have equal empty space top and // bottom. - ASSERT_EQ(image_view->GetCurrentImageBoundsForTesting(), + ASSERT_EQ(image_view->GetImageBoundsForTesting(), gfx::Rect(/*x=*/0, /*y=*/200, /*width=*/600, /*height=*/400)); + ASSERT_EQ(image_view->GetRelatedImageBoundsForTesting(), gfx::Rect()); } -// Test that image is scaled to fill screen height when the image is portrait -// and screen is landscape. There will be black bars to the left and right of -// the image, as the width of the image is less than the width of the screen. -TEST_F(AmbientPhotoViewTest, ShouldResizePortraitImageForLandscapeScreen) { +// Test that two portrait images are scaled and tiled to fill screen when the +// screen is landscape. +TEST_F(AmbientPhotoViewTest, ShouldTileTwoPortraitImagesForLandscapeScreen) { + SetPhotoViewImageSize(/*width=*/10, /*height=*/20); + + UpdateDisplay("808x600"); + + ShowAmbientScreen(); + + FastForwardToNextImage(); + + auto* image_view = GetAmbientBackgroundImageView(); + + // Will tile two portrait images. Each image will fill 400x600 area with 8px + // spaing in between. + // Image should be full width. Image height should extend above and below the + // visible part of the view. + ASSERT_EQ(image_view->GetImageBoundsForTesting(), + gfx::Rect(/*x=*/0, /*y=*/-100, /*width=*/400, /*height=*/800)); + ASSERT_EQ(image_view->GetRelatedImageBoundsForTesting(), + gfx::Rect(/*x=*/0, /*y=*/-100, /*width=*/400, /*height=*/800)); +} + +// Test that two portrait images are scaled and tiled to fill screen when the +// screen is landscape. For odd screen width, the first image will take one more +// pixel. +TEST_F(AmbientPhotoViewTest, + ShouldTileTwoPortraitImagesForLandscapeScreenWithOddWidth) { + SetPhotoViewImageSize(/*width=*/10, /*height=*/20); + + constexpr int kScreenWidth = 809; + constexpr int kScreenHeight = 600; + std::string display_size = base::NumberToString(kScreenWidth) + "x" + + base::NumberToString(kScreenHeight); + UpdateDisplay(display_size); + + ShowAmbientScreen(); + + FastForwardToNextImage(); + + auto* image_view = GetAmbientBackgroundImageView(); + + // Will tile two portrait images. + // The first image will fill 401x802 area with 8px spaing in between. Image + // should be full width. Image height should extend above and below the + // visible part of the view. + const int image_width = (kScreenWidth - kMarginLeftOfRelatedImageDip + 1) / 2; + const int image_height = 20 * image_width / 10; + const int y = (kScreenHeight - image_height) / 2; + ASSERT_EQ(image_view->GetImageBoundsForTesting(), + gfx::Rect(/*x=*/0, /*y=*/y, /*width=*/image_width, + /*height=*/image_height)); + ASSERT_EQ(image_view->GetRelatedImageBoundsForTesting(), + gfx::Rect(/*x=*/0, /*y=*/-100, /*width=*/400, /*height=*/800)); +} + +// Test that landscape images will not be tiled when screen is landscape. +TEST_F(AmbientPhotoViewTest, + ShouldNotTileTwoLandscapeImagesForLandscapeScreen) { + SetPhotoViewImageSize(/*width=*/20, /*height=*/10); + + UpdateDisplay("808x600"); + + ShowAmbientScreen(); + + FastForwardToNextImage(); + + auto* image_view = GetAmbientBackgroundImageView(); + + // Only show one landscape image. + // Image should be full height. Image width should extend equally to the left + // and right of the visible part of the screen. + ASSERT_EQ(image_view->GetImageBoundsForTesting(), + gfx::Rect(/*x=*/-196, /*y=*/0, /*width=*/1200, /*height=*/600)); + ASSERT_EQ(image_view->GetRelatedImageBoundsForTesting(), gfx::Rect()); +} + +// Test that only have one available image will not be tiled when screen is +// landscape. +TEST_F(AmbientPhotoViewTest, + ShouldNotTileIfRelatedImageIsNullForLandscapeScreen) { SetPhotoViewImageSize(/*width=*/10, /*height=*/20); UpdateDisplay("800x600"); @@ -70,17 +149,25 @@ auto* image_view = GetAmbientBackgroundImageView(); - // Image should be full height. Image width should have equal empty space on - // left and right. - ASSERT_EQ(image_view->GetCurrentImageBoundsForTesting(), - gfx::Rect(/*x=*/250, /*y=*/0, /*width=*/300, /*height=*/600)); + // Remove the related image. + image_view->ResetRelatedImageForTesting(); + + // Trigger layout. + UpdateDisplay("808x600"); + + // Only show one portrait image. + // Image should be full height. Image should have equal empty space left and + // right. + ASSERT_EQ(image_view->GetImageBoundsForTesting(), + gfx::Rect(/*x=*/254, /*y=*/0, /*width=*/300, /*height=*/600)); + ASSERT_EQ(image_view->GetRelatedImageBoundsForTesting(), gfx::Rect()); } // Test that image is scaled to fill screen height when the image is landscape // and the screen is landscape. The image will be zoomed in and the left and // right will be cut off, as the width of the image is greater than the width of // the screen. -TEST_F(AmbientPhotoViewTest, ShouldResizeLandscapeImageForFillLandscapeScreen) { +TEST_F(AmbientPhotoViewTest, ShouldResizeLandscapeImageForLandscapeScreen) { SetPhotoViewImageSize(/*width=*/30, /*height=*/20); UpdateDisplay("800x600"); @@ -93,8 +180,131 @@ // Image should be full height. Image width should extend equally to the left // and right of the visible part of the screen. - ASSERT_EQ(image_view->GetCurrentImageBoundsForTesting(), + ASSERT_EQ(image_view->GetImageBoundsForTesting(), gfx::Rect(/*x=*/-50, /*y=*/0, /*width=*/900, /*height=*/600)); + ASSERT_EQ(image_view->GetRelatedImageBoundsForTesting(), gfx::Rect()); +} + +// Test that when rotates to portrait screen, will dynamically only show one +// portrait image. +TEST_F(AmbientPhotoViewTest, ShouldNotTileWhenRotateToPortraitScreen) { + SetPhotoViewImageSize(/*width=*/10, /*height=*/20); + + UpdateDisplay("808x600"); + + ShowAmbientScreen(); + + FastForwardToNextImage(); + + auto* image_view = GetAmbientBackgroundImageView(); + + // Will tile two portrait images. Each image will fill 400x600 area with 8px + // spaing in between. + // Image should be full width. Image height should extend above and below the + // visible part of the view. + ASSERT_EQ(image_view->GetImageBoundsForTesting(), + gfx::Rect(/*x=*/0, /*y=*/-100, /*width=*/400, /*height=*/800)); + ASSERT_EQ(image_view->GetRelatedImageBoundsForTesting(), + gfx::Rect(/*x=*/0, /*y=*/-100, /*width=*/400, /*height=*/800)); + + // Rotate screen. + UpdateDisplay("600x808"); + // Only one image will show. + // Image should be full width. Image height should extend above and below the + // visible part of the screen. + ASSERT_EQ(image_view->GetImageBoundsForTesting(), + gfx::Rect(/*x=*/0, /*y=*/-196, /*width=*/600, /*height=*/1200)); + ASSERT_EQ(image_view->GetRelatedImageBoundsForTesting(), gfx::Rect()); +} + +// Test that when rotates to landscape screen, will dynamically tile two +// portrait images. +TEST_F(AmbientPhotoViewTest, ShouldTileWhenRotateToLandscapeScreen) { + SetPhotoViewImageSize(/*width=*/10, /*height=*/20); + + UpdateDisplay("600x808"); + + ShowAmbientScreen(); + + FastForwardToNextImage(); + + auto* image_view = GetAmbientBackgroundImageView(); + + // Only one image will show. + // Image should be full width. Image height should extend above and below the + // visible part of the screen. + ASSERT_EQ(image_view->GetImageBoundsForTesting(), + gfx::Rect(/*x=*/0, /*y=*/-196, /*width=*/600, /*height=*/1200)); + ASSERT_EQ(image_view->GetRelatedImageBoundsForTesting(), gfx::Rect()); + + // Rotate screen. + UpdateDisplay("808x600"); + + // Will tile two portrait images. Each image will fill 400x600 area with 8px + // spaing in between. + // Image should be full width. Image height should extend above and below the + // visible part of the view. + ASSERT_EQ(image_view->GetImageBoundsForTesting(), + gfx::Rect(/*x=*/0, /*y=*/-100, /*width=*/400, /*height=*/800)); + ASSERT_EQ(image_view->GetRelatedImageBoundsForTesting(), + gfx::Rect(/*x=*/0, /*y=*/-100, /*width=*/400, /*height=*/800)); +} + +// Test that two protrat images will resize when bounds changes in landscape. +TEST_F(AmbientPhotoViewTest, ShouldResizeTiledPortraitImagesWhenBoundsChanged) { + SetPhotoViewImageSize(/*width=*/10, /*height=*/20); + + UpdateDisplay("808x600"); + + ShowAmbientScreen(); + + FastForwardToNextImage(); + + auto* image_view = GetAmbientBackgroundImageView(); + + // Will tile two portrait images. Each image will fill 400x600 area with 8px + // spaing in between. + // Image should be full width. Image height should extend above and below the + // visible part of the view. + ASSERT_EQ(image_view->GetImageBoundsForTesting(), + gfx::Rect(/*x=*/0, /*y=*/-100, /*width=*/400, /*height=*/800)); + ASSERT_EQ(image_view->GetRelatedImageBoundsForTesting(), + gfx::Rect(/*x=*/0, /*y=*/-100, /*width=*/400, /*height=*/800)); + + // Bounds changes so that image will be shown in portrait view. + UpdateDisplay("508x200"); + + // Will tile two portrait images. Each image will fill 250x200 area with 8px + // spaing in between. + // Image should be full height. Image should have equal empty space left and + // right. + ASSERT_EQ(image_view->GetImageBoundsForTesting(), + gfx::Rect(/*x=*/75, /*y=*/0, /*width=*/100, /*height=*/200)); + ASSERT_EQ(image_view->GetRelatedImageBoundsForTesting(), + gfx::Rect(/*x=*/75, /*y=*/0, /*width=*/100, /*height=*/200)); + + // Bounds changes so that image will be shown in portrait view. + UpdateDisplay("308x200"); + + // Will tile two portrait images. Each image will fill 150x200 area with 8px + // spaing in between. + // Image should be full width. Image height should extend above and below the + // visible part of the view. + ASSERT_EQ(image_view->GetImageBoundsForTesting(), + gfx::Rect(/*x=*/0, /*y=*/-50, /*width=*/150, /*height=*/300)); + ASSERT_EQ(image_view->GetRelatedImageBoundsForTesting(), + gfx::Rect(/*x=*/0, /*y=*/-50, /*width=*/150, /*height=*/300)); + + // Bounds changes to exact aspect ratio of the image. + UpdateDisplay("208x200"); + + // Will tile two portrait images. Each image will fill 100x200 area with 8px + // spaing in between. + // Image should be full width and height. + ASSERT_EQ(image_view->GetImageBoundsForTesting(), + gfx::Rect(/*x=*/0, /*y=*/0, /*width=*/100, /*height=*/200)); + ASSERT_EQ(image_view->GetRelatedImageBoundsForTesting(), + gfx::Rect(/*x=*/0, /*y=*/0, /*width=*/100, /*height=*/200)); } } // namespace ash
diff --git a/ash/public/cpp/ambient/ambient_backend_controller.cc b/ash/public/cpp/ambient/ambient_backend_controller.cc index f08b7bda..2d1a1be 100644 --- a/ash/public/cpp/ambient/ambient_backend_controller.cc +++ b/ash/public/cpp/ambient/ambient_backend_controller.cc
@@ -31,10 +31,6 @@ AmbientModeTopic::~AmbientModeTopic() = default; -std::string AmbientModeTopic::GetUrl() const { - return portrait_image_url.value_or(url); -} - // WeatherInfo------------------------------------------------------------------ WeatherInfo::WeatherInfo() = default;
diff --git a/ash/public/cpp/ambient/ambient_backend_controller.h b/ash/public/cpp/ambient/ambient_backend_controller.h index 8811751c..9edbc4c 100644 --- a/ash/public/cpp/ambient/ambient_backend_controller.h +++ b/ash/public/cpp/ambient/ambient_backend_controller.h
@@ -27,9 +27,6 @@ AmbientModeTopic& operator=(const AmbientModeTopic&); ~AmbientModeTopic(); - // Returns a non-empty url to load the landscape or portrait image. - std::string GetUrl() const; - // Details, i.e. the attribution, to be displayed for the current photo on // ambient. std::string details; @@ -37,9 +34,8 @@ // Image url. std::string url; - // Optional for non-cropped portrait style images. The same image as in - // |url| but it is not cropped and is better for portrait displaying. - base::Optional<std::string> portrait_image_url; + // Only support portrait image tiling in landscape orientation. + base::Optional<std::string> related_image_url; }; // WeatherInfo contains the weather information we need for rendering a
diff --git a/ash/public/cpp/ambient/fake_ambient_backend_controller_impl.cc b/ash/public/cpp/ambient/fake_ambient_backend_controller_impl.cc index 228325b..251e826 100644 --- a/ash/public/cpp/ambient/fake_ambient_backend_controller_impl.cc +++ b/ash/public/cpp/ambient/fake_ambient_backend_controller_impl.cc
@@ -81,6 +81,7 @@ ash::AmbientModeTopic topic; topic.url = kFakeUrl; topic.details = kFakeDetails; + topic.related_image_url = kFakeUrl; ash::WeatherInfo weather_info; weather_info.temp_f = .0f;
diff --git a/ash/system/holding_space/holding_space_item_chip_view.cc b/ash/system/holding_space/holding_space_item_chip_view.cc index e15ddc0..959b61d 100644 --- a/ash/system/holding_space/holding_space_item_chip_view.cc +++ b/ash/system/holding_space/holding_space_item_chip_view.cc
@@ -30,10 +30,8 @@ namespace ash { -HoldingSpaceItemChipView::HoldingSpaceItemChipView( - HoldingSpaceItemViewDelegate* delegate, - const HoldingSpaceItem* item) - : HoldingSpaceItemView(delegate, item) { +HoldingSpaceItemChipView::HoldingSpaceItemChipView(const HoldingSpaceItem* item) + : HoldingSpaceItemView(item) { auto* layout = SetLayoutManager(std::make_unique<views::BoxLayout>( views::BoxLayout::Orientation::kHorizontal, gfx::Insets(kHoldingSpaceChipPadding), kHoldingSpaceChipChildSpacing));
diff --git a/ash/system/holding_space/holding_space_item_chip_view.h b/ash/system/holding_space/holding_space_item_chip_view.h index 71479cd9e..c2ca9d6 100644 --- a/ash/system/holding_space/holding_space_item_chip_view.h +++ b/ash/system/holding_space/holding_space_item_chip_view.h
@@ -21,7 +21,6 @@ namespace ash { class HoldingSpaceItem; -class HoldingSpaceItemViewDelegate; namespace tray { class RoundedImageView; @@ -34,8 +33,7 @@ public: METADATA_HEADER(HoldingSpaceItemChipView); - HoldingSpaceItemChipView(HoldingSpaceItemViewDelegate* delegate, - const HoldingSpaceItem* item); + explicit HoldingSpaceItemChipView(const HoldingSpaceItem* item); HoldingSpaceItemChipView(const HoldingSpaceItemChipView&) = delete; HoldingSpaceItemChipView& operator=(const HoldingSpaceItemChipView&) = delete; ~HoldingSpaceItemChipView() override;
diff --git a/ash/system/holding_space/holding_space_item_chips_container.cc b/ash/system/holding_space/holding_space_item_chips_container.cc index 7ca8638..0890800 100644 --- a/ash/system/holding_space/holding_space_item_chips_container.cc +++ b/ash/system/holding_space/holding_space_item_chips_container.cc
@@ -5,6 +5,9 @@ #include "ash/system/holding_space/holding_space_item_chips_container.h" #include "ash/public/cpp/holding_space/holding_space_constants.h" +#include "ash/public/cpp/holding_space/holding_space_item.h" +#include "ash/system/holding_space/holding_space_item_chip_view.h" +#include "base/debug/stack_trace.h" #include "ui/views/layout/layout_manager_base.h" #include "ui/views/layout/proposed_layout.h"
diff --git a/ash/system/holding_space/holding_space_item_chips_container.h b/ash/system/holding_space/holding_space_item_chips_container.h index e7c3ffe..ac7b352 100644 --- a/ash/system/holding_space/holding_space_item_chips_container.h +++ b/ash/system/holding_space/holding_space_item_chips_container.h
@@ -10,7 +10,8 @@ namespace ash { -// A container view which arranges item chips into a 2 column grid. +// A container view which automatically arranges item chips into a 2 column +// grid. class HoldingSpaceItemChipsContainer : public views::View { public: HoldingSpaceItemChipsContainer();
diff --git a/ash/system/holding_space/holding_space_item_context_menu.cc b/ash/system/holding_space/holding_space_item_context_menu.cc new file mode 100644 index 0000000..bf7974f --- /dev/null +++ b/ash/system/holding_space/holding_space_item_context_menu.cc
@@ -0,0 +1,106 @@ +// Copyright 2020 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. + +#include "ash/system/holding_space/holding_space_item_context_menu.h" + +#include "ash/public/cpp/holding_space/holding_space_client.h" +#include "ash/public/cpp/holding_space/holding_space_constants.h" +#include "ash/public/cpp/holding_space/holding_space_controller.h" +#include "ash/public/cpp/holding_space/holding_space_model.h" +#include "ash/resources/vector_icons/vector_icons.h" +#include "ash/strings/grit/ash_strings.h" +#include "ash/system/holding_space/holding_space_item_view.h" +#include "base/bind.h" +#include "net/base/mime_util.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/models/simple_menu_model.h" +#include "ui/views/controls/menu/menu_runner.h" +#include "ui/views/vector_icons.h" +#include "ui/views/view.h" + +namespace ash { + +HoldingSpaceItemContextMenu::HoldingSpaceItemContextMenu( + const HoldingSpaceItem* item) + : item_(item) {} + +HoldingSpaceItemContextMenu::~HoldingSpaceItemContextMenu() = default; + +void HoldingSpaceItemContextMenu::ShowContextMenuForViewImpl( + views::View* source, + const gfx::Point& point, + ui::MenuSourceType source_type) { + int run_types = views::MenuRunner::USE_TOUCHABLE_LAYOUT | + views::MenuRunner::CONTEXT_MENU | + views::MenuRunner::FIXED_ANCHOR; + + context_menu_runner_ = + std::make_unique<views::MenuRunner>(BuildMenuModel(), run_types); + + context_menu_runner_->RunMenuAt( + source->GetWidget(), nullptr /*button_controller*/, + source->GetBoundsInScreen(), views::MenuAnchorPosition::kBubbleRight, + source_type); +} + +void HoldingSpaceItemContextMenu::ExecuteCommand(int command_id, + int event_flags) { + switch (command_id) { + case HoldingSpaceCommandId::kCopyImageToClipboard: + HoldingSpaceController::Get()->client()->CopyImageToClipboard( + *item_, base::DoNothing()); + break; + case HoldingSpaceCommandId::kPinItem: + HoldingSpaceController::Get()->client()->PinItem(*item_); + break; + case HoldingSpaceCommandId::kShowInFolder: + HoldingSpaceController::Get()->client()->ShowItemInFolder( + *item_, base::DoNothing()); + break; + case HoldingSpaceCommandId::kUnpinItem: + HoldingSpaceController::Get()->client()->UnpinItem(*item_); + break; + } +} + +ui::SimpleMenuModel* HoldingSpaceItemContextMenu::BuildMenuModel() { + context_menu_model_ = std::make_unique<ui::SimpleMenuModel>(this); + context_menu_model_->AddItemWithIcon( + HoldingSpaceCommandId::kShowInFolder, + l10n_util::GetStringUTF16( + IDS_ASH_HOLDING_SPACE_CONTEXT_MENU_SHOW_IN_FOLDER), + ui::ImageModel::FromVectorIcon(kFolderIcon)); + + std::string mime_type; + const bool is_image = + net::GetMimeTypeFromFile(item_->file_path(), &mime_type) && + net::MatchesMimeType(kMimeTypeImage, mime_type); + + if (is_image) { + context_menu_model_->AddItemWithIcon( + HoldingSpaceCommandId::kCopyImageToClipboard, + l10n_util::GetStringUTF16( + IDS_ASH_HOLDING_SPACE_CONTEXT_MENU_COPY_IMAGE_TO_CLIPBOARD), + ui::ImageModel::FromVectorIcon(kCopyIcon)); + } + + const bool is_pinned = HoldingSpaceController::Get()->model()->GetItem( + HoldingSpaceItem::GetFileBackedItemId(HoldingSpaceItem::Type::kPinnedFile, + item_->file_path())); + if (!is_pinned) { + context_menu_model_->AddItemWithIcon( + HoldingSpaceCommandId::kPinItem, + l10n_util::GetStringUTF16(IDS_ASH_HOLDING_SPACE_CONTEXT_MENU_PIN), + ui::ImageModel::FromVectorIcon(views::kPinIcon)); + } else { + context_menu_model_->AddItemWithIcon( + HoldingSpaceCommandId::kUnpinItem, + l10n_util::GetStringUTF16(IDS_ASH_HOLDING_SPACE_CONTEXT_MENU_UNPIN), + ui::ImageModel::FromVectorIcon(views::kUnpinIcon)); + } + + return context_menu_model_.get(); +} + +} // namespace ash
diff --git a/ash/system/holding_space/holding_space_item_context_menu.h b/ash/system/holding_space/holding_space_item_context_menu.h new file mode 100644 index 0000000..5371f67 --- /dev/null +++ b/ash/system/holding_space/holding_space_item_context_menu.h
@@ -0,0 +1,53 @@ +// Copyright 2020 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. + +#ifndef ASH_SYSTEM_HOLDING_SPACE_HOLDING_SPACE_ITEM_CONTEXT_MENU_H_ +#define ASH_SYSTEM_HOLDING_SPACE_HOLDING_SPACE_ITEM_CONTEXT_MENU_H_ + +#include <memory> + +#include "ash/ash_export.h" +#include "ash/public/cpp/holding_space/holding_space_item.h" +#include "ui/base/models/simple_menu_model.h" +#include "ui/views/context_menu_controller.h" + +namespace views { +class MenuRunner; +} // namespace views + +namespace ash { + +// This class handles creation of the context menu view and handling +// commands available in the menu. +class ASH_EXPORT HoldingSpaceItemContextMenu + : public views::ContextMenuController, + public ui::SimpleMenuModel::Delegate { + public: + explicit HoldingSpaceItemContextMenu(const HoldingSpaceItem* item); + HoldingSpaceItemContextMenu(const HoldingSpaceItemContextMenu&) = delete; + HoldingSpaceItemContextMenu& operator=(const HoldingSpaceItemContextMenu&) = + delete; + ~HoldingSpaceItemContextMenu() override; + + // views::ContextMenuController: + void ShowContextMenuForViewImpl(views::View* source, + const gfx::Point& point, + ui::MenuSourceType source_type) override; + + // SimpleMenuModel::Delegate: + void ExecuteCommand(int command_id, int event_flags) override; + + private: + ui::SimpleMenuModel* BuildMenuModel(); + + std::unique_ptr<ui::SimpleMenuModel> context_menu_model_; + std::unique_ptr<views::MenuRunner> context_menu_runner_; + + // The holding space item that this context menu's actions will effect. + const HoldingSpaceItem* const item_; +}; + +} // namespace ash + +#endif // ASH_SYSTEM_HOLDING_SPACE_HOLDING_SPACE_ITEM_CONTEXT_MENU_H_
diff --git a/ash/system/holding_space/holding_space_item_screenshot_view.cc b/ash/system/holding_space/holding_space_item_screenshot_view.cc index 233f739..39e07b0 100644 --- a/ash/system/holding_space/holding_space_item_screenshot_view.cc +++ b/ash/system/holding_space/holding_space_item_screenshot_view.cc
@@ -16,9 +16,8 @@ namespace ash { HoldingSpaceItemScreenshotView::HoldingSpaceItemScreenshotView( - HoldingSpaceItemViewDelegate* delegate, const HoldingSpaceItem* item) - : HoldingSpaceItemView(delegate, item) { + : HoldingSpaceItemView(item) { SetLayoutManager(std::make_unique<views::FillLayout>()); image_ = AddChildView(
diff --git a/ash/system/holding_space/holding_space_item_screenshot_view.h b/ash/system/holding_space/holding_space_item_screenshot_view.h index 3f6e72f..ec5f8f1 100644 --- a/ash/system/holding_space/holding_space_item_screenshot_view.h +++ b/ash/system/holding_space/holding_space_item_screenshot_view.h
@@ -13,7 +13,6 @@ namespace ash { class HoldingSpaceItem; -class HoldingSpaceItemViewDelegate; namespace tray { class RoundedImageView; @@ -23,8 +22,7 @@ public: METADATA_HEADER(HoldingSpaceItemScreenshotView); - HoldingSpaceItemScreenshotView(HoldingSpaceItemViewDelegate* delegate, - const HoldingSpaceItem* item); + explicit HoldingSpaceItemScreenshotView(const HoldingSpaceItem* item); HoldingSpaceItemScreenshotView(const HoldingSpaceItemScreenshotView&) = delete; HoldingSpaceItemScreenshotView& operator=(
diff --git a/ash/system/holding_space/holding_space_item_view.cc b/ash/system/holding_space/holding_space_item_view.cc index 6508d51..e91cd9d 100644 --- a/ash/system/holding_space/holding_space_item_view.cc +++ b/ash/system/holding_space/holding_space_item_view.cc
@@ -4,36 +4,41 @@ #include "ash/system/holding_space/holding_space_item_view.h" +#include "ash/public/cpp/holding_space/holding_space_client.h" #include "ash/public/cpp/holding_space/holding_space_constants.h" +#include "ash/public/cpp/holding_space/holding_space_controller.h" #include "ash/public/cpp/holding_space/holding_space_item.h" #include "ash/public/cpp/shelf_config.h" -#include "ash/system/holding_space/holding_space_item_view_delegate.h" -#include "ui/base/class_property.h" +#include "ash/strings/grit/ash_strings.h" +#include "ash/system/holding_space/holding_space_item_context_menu.h" +#include "base/bind_helpers.h" +#include "ui/base/dragdrop/drag_drop_types.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/gfx/text_constants.h" #include "ui/views/accessibility/view_accessibility.h" #include "ui/views/controls/focus_ring.h" #include "ui/views/controls/highlight_path_generator.h" +#include "ui/views/controls/menu/menu_runner.h" namespace ash { namespace { -// A UI class property used to identify if a view is an instance of -// `HoldingSpaceItemView`. Class name is not an adequate identifier as it may be -// overridden by subclasses. -DEFINE_UI_CLASS_PROPERTY_KEY(bool, kIsHoldingSpaceItemViewProperty, false) +// Helpers --------------------------------------------------------------------- + +// Attempts to open the specified holding space `item`. +void OpenItem(const HoldingSpaceItem& item) { + HoldingSpaceController::Get()->client()->OpenItem(item, base::DoNothing()); +} } // namespace // HoldingSpaceItemView -------------------------------------------------------- -HoldingSpaceItemView::HoldingSpaceItemView( - HoldingSpaceItemViewDelegate* delegate, - const HoldingSpaceItem* item) - : delegate_(delegate), item_(item) { - SetProperty(kIsHoldingSpaceItemViewProperty, true); - - set_context_menu_controller(delegate_); - set_drag_controller(delegate_); +HoldingSpaceItemView::HoldingSpaceItemView(const HoldingSpaceItem* item) + : item_(item), + context_menu_(std::make_unique<HoldingSpaceItemContextMenu>(item_)) { + set_context_menu_controller(context_menu_.get()); SetPaintToLayer(); layer()->SetFillsBoundsOpaquely(false); @@ -49,14 +54,10 @@ kHoldingSpaceCornerRadius); } -HoldingSpaceItemView::~HoldingSpaceItemView() { - delegate_->OnHoldingSpaceItemViewDestroyed(this); -} +HoldingSpaceItemView::~HoldingSpaceItemView() = default; -// static -HoldingSpaceItemView* HoldingSpaceItemView::Cast(views::View* view) { - DCHECK(view->GetProperty(kIsHoldingSpaceItemViewProperty)); - return static_cast<HoldingSpaceItemView*>(view); +int HoldingSpaceItemView::GetDragOperations(const gfx::Point& point) { + return ui::DragDropTypes::DRAG_COPY; } SkColor HoldingSpaceItemView::GetInkDropBaseColor() const { @@ -64,15 +65,29 @@ } void HoldingSpaceItemView::OnGestureEvent(ui::GestureEvent* event) { - delegate_->OnHoldingSpaceItemViewGestureEvent(this, *event); + if (event->type() == ui::ET_GESTURE_TAP) + OpenItem(*item()); } bool HoldingSpaceItemView::OnKeyPressed(const ui::KeyEvent& event) { - return delegate_->OnHoldingSpaceItemViewKeyPressed(this, event); + if (event.key_code() == ui::KeyboardCode::VKEY_RETURN) { + OpenItem(*item()); + return true; + } + return false; } bool HoldingSpaceItemView::OnMousePressed(const ui::MouseEvent& event) { - return delegate_->OnHoldingSpaceItemViewMousePressed(this, event); + if (event.flags() & ui::EF_IS_DOUBLE_CLICK) { + OpenItem(*item()); + return true; + } + return false; +} + +void HoldingSpaceItemView::WriteDragData(const gfx::Point& point, + ui::OSExchangeData* data) { + data->SetFilename(item_->file_path()); } } // namespace ash
diff --git a/ash/system/holding_space/holding_space_item_view.h b/ash/system/holding_space/holding_space_item_view.h index 94c8067..9b6c7985 100644 --- a/ash/system/holding_space/holding_space_item_view.h +++ b/ash/system/holding_space/holding_space_item_view.h
@@ -5,37 +5,38 @@ #ifndef ASH_SYSTEM_HOLDING_SPACE_HOLDING_SPACE_ITEM_VIEW_H_ #define ASH_SYSTEM_HOLDING_SPACE_HOLDING_SPACE_ITEM_VIEW_H_ +#include <memory> + #include "ash/ash_export.h" +#include "ui/base/dragdrop/drag_drop_types.h" #include "ui/views/animation/ink_drop_host_view.h" namespace ash { class HoldingSpaceItem; -class HoldingSpaceItemViewDelegate; +class HoldingSpaceItemContextMenu; // Base class for HoldingSpaceItemChipView and HoldingSpaceItemScreenshotView. class ASH_EXPORT HoldingSpaceItemView : public views::InkDropHostView { public: - HoldingSpaceItemView(HoldingSpaceItemViewDelegate*, const HoldingSpaceItem*); + explicit HoldingSpaceItemView(const HoldingSpaceItem* item); HoldingSpaceItemView(const HoldingSpaceItemView&) = delete; HoldingSpaceItemView& operator=(const HoldingSpaceItemView&) = delete; ~HoldingSpaceItemView() override; - // Returns `view` cast as a `HoldingSpaceItemView`. Note that this performs a - // DCHECK to assert that `view` is in fact a `HoldingSpaceItemView` instance. - static HoldingSpaceItemView* Cast(views::View* view); - // views::InkDropHostView: + int GetDragOperations(const gfx::Point& point) override; SkColor GetInkDropBaseColor() const override; void OnGestureEvent(ui::GestureEvent* event) override; bool OnKeyPressed(const ui::KeyEvent& event) override; bool OnMousePressed(const ui::MouseEvent& event) override; + void WriteDragData(const gfx::Point& point, ui::OSExchangeData*) override; const HoldingSpaceItem* item() const { return item_; } private: - HoldingSpaceItemViewDelegate* delegate_; const HoldingSpaceItem* const item_; + std::unique_ptr<HoldingSpaceItemContextMenu> const context_menu_; }; } // namespace ash
diff --git a/ash/system/holding_space/holding_space_item_view_delegate.cc b/ash/system/holding_space/holding_space_item_view_delegate.cc deleted file mode 100644 index e98b61d7..0000000 --- a/ash/system/holding_space/holding_space_item_view_delegate.cc +++ /dev/null
@@ -1,211 +0,0 @@ -// Copyright 2020 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. - -#include "ash/system/holding_space/holding_space_item_view_delegate.h" - -#include "ash/public/cpp/holding_space/holding_space_client.h" -#include "ash/public/cpp/holding_space/holding_space_constants.h" -#include "ash/public/cpp/holding_space/holding_space_controller.h" -#include "ash/public/cpp/holding_space/holding_space_item.h" -#include "ash/public/cpp/holding_space/holding_space_model.h" -#include "ash/resources/vector_icons/vector_icons.h" -#include "ash/strings/grit/ash_strings.h" -#include "ash/system/holding_space/holding_space_item_view.h" -#include "base/bind.h" -#include "net/base/mime_util.h" -#include "ui/base/dragdrop/drag_drop_types.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/base/models/simple_menu_model.h" -#include "ui/views/controls/menu/menu_runner.h" -#include "ui/views/vector_icons.h" -#include "ui/views/view.h" - -namespace ash { - -namespace { - -// It is expected that all `HoldingSpaceItemView`s share the same delegate in -// order to support multiple selections. We cache the singleton `instance` in -// order to enforce this requirement. -HoldingSpaceItemViewDelegate* instance = nullptr; - -// Helpers --------------------------------------------------------------------- - -// Attempts to open the specified holding space `item`. -void OpenItem(const HoldingSpaceItem& item) { - HoldingSpaceController::Get()->client()->OpenItem(item, base::DoNothing()); -} - -} // namespace - -// HoldingSpaceItemViewDelegate ------------------------------------------------ - -HoldingSpaceItemViewDelegate::HoldingSpaceItemViewDelegate() { - DCHECK_EQ(nullptr, instance); - instance = this; -} - -HoldingSpaceItemViewDelegate::~HoldingSpaceItemViewDelegate() { - DCHECK_EQ(instance, this); - instance = nullptr; -} - -// TODO(dmblack): Implement multiple selection. -void HoldingSpaceItemViewDelegate::OnHoldingSpaceItemViewGestureEvent( - HoldingSpaceItemView* view, - const ui::GestureEvent& event) { - if (event.type() == ui::ET_GESTURE_TAP) - OpenItem(*view->item()); -} - -// TODO(dmblack): Handle multiple selection. -bool HoldingSpaceItemViewDelegate::OnHoldingSpaceItemViewKeyPressed( - HoldingSpaceItemView* view, - const ui::KeyEvent& event) { - if (event.key_code() == ui::KeyboardCode::VKEY_RETURN) { - OpenItem(*view->item()); - return true; - } - return false; -} - -// TODO(dmblack): Handle multiple selection. -bool HoldingSpaceItemViewDelegate::OnHoldingSpaceItemViewMousePressed( - HoldingSpaceItemView* view, - const ui::MouseEvent& event) { - if (event.flags() & ui::EF_IS_DOUBLE_CLICK) { - OpenItem(*view->item()); - return true; - } - return false; -} - -void HoldingSpaceItemViewDelegate::OnHoldingSpaceItemViewDestroyed( - HoldingSpaceItemView* view) { - selected_views_by_item_id_.erase(view->item()->id()); -} - -// TODO(dmblack): Handle multiple selection. -void HoldingSpaceItemViewDelegate::ShowContextMenuForViewImpl( - views::View* source, - const gfx::Point& point, - ui::MenuSourceType source_type) { - selected_views_by_item_id_.clear(); - - HoldingSpaceItemView* selected_view = HoldingSpaceItemView::Cast(source); - selected_views_by_item_id_[selected_view->item()->id()] = selected_view; - - int run_types = views::MenuRunner::USE_TOUCHABLE_LAYOUT | - views::MenuRunner::CONTEXT_MENU | - views::MenuRunner::FIXED_ANCHOR; - - context_menu_runner_ = - std::make_unique<views::MenuRunner>(BuildMenuModel(), run_types); - - context_menu_runner_->RunMenuAt( - source->GetWidget(), nullptr /*button_controller*/, - source->GetBoundsInScreen(), views::MenuAnchorPosition::kBubbleRight, - source_type); -} - -// TODO(dmblack): Handle multiple selection. -bool HoldingSpaceItemViewDelegate::CanStartDragForView( - views::View* sender, - const gfx::Point& press_pt, - const gfx::Point& current_pt) { - selected_views_by_item_id_.clear(); - - HoldingSpaceItemView* selected_view = HoldingSpaceItemView::Cast(sender); - selected_views_by_item_id_[selected_view->item()->id()] = selected_view; - - return true; -} - -int HoldingSpaceItemViewDelegate::GetDragOperationsForView( - views::View* sender, - const gfx::Point& press_pt) { - return ui::DragDropTypes::DRAG_COPY; -} - -// TODO(dmblack): Handle multiple selection. -void HoldingSpaceItemViewDelegate::WriteDragDataForView( - views::View* sender, - const gfx::Point& press_pt, - ui::OSExchangeData* data) { - DCHECK_EQ(1u, selected_views_by_item_id_.size()); - auto* selected_view = selected_views_by_item_id_.begin()->second; - data->SetFilename(selected_view->item()->file_path()); -} - -// TODO(dmblack): Handle multiple selection. -void HoldingSpaceItemViewDelegate::ExecuteCommand(int command_id, - int event_flags) { - DCHECK_EQ(1u, selected_views_by_item_id_.size()); - auto* selected_view = selected_views_by_item_id_.begin()->second; - - switch (command_id) { - case HoldingSpaceCommandId::kCopyImageToClipboard: - HoldingSpaceController::Get()->client()->CopyImageToClipboard( - *selected_view->item(), base::DoNothing()); - break; - case HoldingSpaceCommandId::kPinItem: - HoldingSpaceController::Get()->client()->PinItem(*selected_view->item()); - break; - case HoldingSpaceCommandId::kShowInFolder: - HoldingSpaceController::Get()->client()->ShowItemInFolder( - *selected_view->item(), base::DoNothing()); - break; - case HoldingSpaceCommandId::kUnpinItem: - HoldingSpaceController::Get()->client()->UnpinItem( - *selected_view->item()); - break; - } -} - -// TODO(dmblack): Handle multiple selection. -ui::SimpleMenuModel* HoldingSpaceItemViewDelegate::BuildMenuModel() { - DCHECK_EQ(1u, selected_views_by_item_id_.size()); - auto* selected_view = selected_views_by_item_id_.begin()->second; - - context_menu_model_ = std::make_unique<ui::SimpleMenuModel>(this); - context_menu_model_->AddItemWithIcon( - HoldingSpaceCommandId::kShowInFolder, - l10n_util::GetStringUTF16( - IDS_ASH_HOLDING_SPACE_CONTEXT_MENU_SHOW_IN_FOLDER), - ui::ImageModel::FromVectorIcon(kFolderIcon)); - - std::string mime_type; - const bool is_image = net::GetMimeTypeFromFile( - selected_view->item()->file_path(), &mime_type) && - net::MatchesMimeType(kMimeTypeImage, mime_type); - - if (is_image) { - context_menu_model_->AddItemWithIcon( - HoldingSpaceCommandId::kCopyImageToClipboard, - l10n_util::GetStringUTF16( - IDS_ASH_HOLDING_SPACE_CONTEXT_MENU_COPY_IMAGE_TO_CLIPBOARD), - ui::ImageModel::FromVectorIcon(kCopyIcon)); - } - - const bool is_pinned = HoldingSpaceController::Get()->model()->GetItem( - HoldingSpaceItem::GetFileBackedItemId( - HoldingSpaceItem::Type::kPinnedFile, - selected_view->item()->file_path())); - - if (!is_pinned) { - context_menu_model_->AddItemWithIcon( - HoldingSpaceCommandId::kPinItem, - l10n_util::GetStringUTF16(IDS_ASH_HOLDING_SPACE_CONTEXT_MENU_PIN), - ui::ImageModel::FromVectorIcon(views::kPinIcon)); - } else { - context_menu_model_->AddItemWithIcon( - HoldingSpaceCommandId::kUnpinItem, - l10n_util::GetStringUTF16(IDS_ASH_HOLDING_SPACE_CONTEXT_MENU_UNPIN), - ui::ImageModel::FromVectorIcon(views::kUnpinIcon)); - } - - return context_menu_model_.get(); -} - -} // namespace ash
diff --git a/ash/system/holding_space/holding_space_item_view_delegate.h b/ash/system/holding_space/holding_space_item_view_delegate.h deleted file mode 100644 index 5d3c4d1..0000000 --- a/ash/system/holding_space/holding_space_item_view_delegate.h +++ /dev/null
@@ -1,92 +0,0 @@ -// Copyright 2020 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. - -#ifndef ASH_SYSTEM_HOLDING_SPACE_HOLDING_SPACE_ITEM_VIEW_DELEGATE_H_ -#define ASH_SYSTEM_HOLDING_SPACE_HOLDING_SPACE_ITEM_VIEW_DELEGATE_H_ - -#include <map> -#include <memory> -#include <string> - -#include "ash/ash_export.h" -#include "ui/base/models/simple_menu_model.h" -#include "ui/views/context_menu_controller.h" -#include "ui/views/drag_controller.h" - -namespace ui { -class GestureEvent; -class KeyEvent; -class MouseEvent; -} // namespace ui - -namespace views { -class MenuRunner; -} // namespace views - -namespace ash { - -class HoldingSpaceItemView; - -// TODO(dmblack): Implement multiple selection. -// A delegate for `HoldingSpaceItemView`s which implements context menu, -// drag-and-drop, and selection functionality. In order to support multiple -// selections at a time, all `HoldingSpaceItemView`s must share the same -// `HoldingSpaceItemViewDelegate` instance. -class ASH_EXPORT HoldingSpaceItemViewDelegate - : public views::ContextMenuController, - public views::DragController, - public ui::SimpleMenuModel::Delegate { - public: - HoldingSpaceItemViewDelegate(); - HoldingSpaceItemViewDelegate(const HoldingSpaceItemViewDelegate&) = delete; - HoldingSpaceItemViewDelegate& operator=(const HoldingSpaceItemViewDelegate&) = - delete; - ~HoldingSpaceItemViewDelegate() override; - - // Invoked when `view` receives the specified gesture `event`. - void OnHoldingSpaceItemViewGestureEvent(HoldingSpaceItemView* view, - const ui::GestureEvent& event); - - // Invoked when `view` receives the specified key pressed `event`. - bool OnHoldingSpaceItemViewKeyPressed(HoldingSpaceItemView* view, - const ui::KeyEvent& event); - - // Invoked when `view` receives the specified mouse pressed `event`. - bool OnHoldingSpaceItemViewMousePressed(HoldingSpaceItemView* view, - const ui::MouseEvent& event); - - // Invoked when `view` has been destroyed. - void OnHoldingSpaceItemViewDestroyed(HoldingSpaceItemView* view); - - private: - // views::ContextMenuController: - void ShowContextMenuForViewImpl(views::View* source, - const gfx::Point& point, - ui::MenuSourceType source_type) override; - - // views::DragController: - bool CanStartDragForView(views::View* sender, - const gfx::Point& press_pt, - const gfx::Point& current_pt) override; - int GetDragOperationsForView(views::View* sender, - const gfx::Point& press_pt) override; - void WriteDragDataForView(views::View* sender, - const gfx::Point& press_pt, - ui::OSExchangeData* data) override; - - // SimpleMenuModel::Delegate: - void ExecuteCommand(int command_id, int event_flags) override; - - // Builds and returns a raw pointer to `context_menu_model_`. - ui::SimpleMenuModel* BuildMenuModel(); - - std::unique_ptr<ui::SimpleMenuModel> context_menu_model_; - std::unique_ptr<views::MenuRunner> context_menu_runner_; - - std::map<std::string, HoldingSpaceItemView*> selected_views_by_item_id_; -}; - -} // namespace ash - -#endif // ASH_SYSTEM_HOLDING_SPACE_HOLDING_SPACE_ITEM_VIEW_DELEGATE_H_
diff --git a/ash/system/holding_space/holding_space_tray.cc b/ash/system/holding_space/holding_space_tray.cc index d9335ac..15b6eb2a 100644 --- a/ash/system/holding_space/holding_space_tray.cc +++ b/ash/system/holding_space/holding_space_tray.cc
@@ -149,8 +149,8 @@ bubble_view->set_margins(GetSecondaryBubbleInsets()); // Add pinned files container. - pinned_files_container_ = bubble_view->AddChildView( - std::make_unique<PinnedFilesContainer>(&delegate_)); + pinned_files_container_ = + bubble_view->AddChildView(std::make_unique<PinnedFilesContainer>()); SetupChildLayer(pinned_files_container_); // Separator between the two containers, gives illusion of 2 separate bubbles. @@ -159,8 +159,8 @@ separator->SetBorder(views::CreateEmptyBorder( gfx::Insets(kHoldingSpaceContainerSpacing, 0, 0, 0))); - recent_files_container_ = bubble_view->AddChildView( - std::make_unique<RecentFilesContainer>(&delegate_)); + recent_files_container_ = + bubble_view->AddChildView(std::make_unique<RecentFilesContainer>()); SetupChildLayer(recent_files_container_); // Show the bubble.
diff --git a/ash/system/holding_space/holding_space_tray.h b/ash/system/holding_space/holding_space_tray.h index 223a48a..27eea26 100644 --- a/ash/system/holding_space/holding_space_tray.h +++ b/ash/system/holding_space/holding_space_tray.h
@@ -8,7 +8,6 @@ #include <memory> #include "ash/ash_export.h" -#include "ash/system/holding_space/holding_space_item_view_delegate.h" #include "ash/system/tray/tray_background_view.h" #include "base/memory/weak_ptr.h" @@ -61,10 +60,6 @@ std::unique_ptr<TrayBubbleWrapper> bubble_; - // The singleton delegate for `HoldingSpaceItemView`s that implements support - // for context menu, drag-and-drop, and multiple selection. - HoldingSpaceItemViewDelegate delegate_; - PinnedFilesContainer* pinned_files_container_ = nullptr; RecentFilesContainer* recent_files_container_ = nullptr;
diff --git a/ash/system/holding_space/pinned_files_container.cc b/ash/system/holding_space/pinned_files_container.cc index 37f8e6b..f3161171 100644 --- a/ash/system/holding_space/pinned_files_container.cc +++ b/ash/system/holding_space/pinned_files_container.cc
@@ -22,9 +22,7 @@ namespace ash { -PinnedFilesContainer::PinnedFilesContainer( - HoldingSpaceItemViewDelegate* delegate) - : delegate_(delegate) { +PinnedFilesContainer::PinnedFilesContainer() { SetID(kHoldingSpacePinnedFilesContainerId); SetLayoutManager(std::make_unique<views::BoxLayout>( @@ -54,8 +52,7 @@ if (item->type() == HoldingSpaceItem::Type::kPinnedFile) { views_by_item_id_[item->id()] = item_chips_container_->AddChildViewAt( - std::make_unique<HoldingSpaceItemChipView>(delegate_, item), - /*index=*/0); + std::make_unique<HoldingSpaceItemChipView>(item), 0 /*index*/); } }
diff --git a/ash/system/holding_space/pinned_files_container.h b/ash/system/holding_space/pinned_files_container.h index d27ef533..f026928 100644 --- a/ash/system/holding_space/pinned_files_container.h +++ b/ash/system/holding_space/pinned_files_container.h
@@ -12,12 +12,11 @@ namespace ash { class HoldingSpaceItemChipsContainer; -class HoldingSpaceItemViewDelegate; // Container for pinned files that the user adds to the holding space bubble. class PinnedFilesContainer : public HoldingSpaceItemViewsContainer { public: - explicit PinnedFilesContainer(HoldingSpaceItemViewDelegate* delegate); + PinnedFilesContainer(); PinnedFilesContainer(const PinnedFilesContainer& other) = delete; PinnedFilesContainer& operator=(const PinnedFilesContainer& other) = delete; ~PinnedFilesContainer() override; @@ -28,7 +27,6 @@ void RemoveHoldingSpaceItemView(const HoldingSpaceItem* item) override; private: - HoldingSpaceItemViewDelegate* const delegate_; HoldingSpaceItemChipsContainer* item_chips_container_ = nullptr; std::map<std::string, views::View*> views_by_item_id_;
diff --git a/ash/system/holding_space/recent_files_container.cc b/ash/system/holding_space/recent_files_container.cc index ce0cd9c..57d4ed4 100644 --- a/ash/system/holding_space/recent_files_container.cc +++ b/ash/system/holding_space/recent_files_container.cc
@@ -22,9 +22,7 @@ namespace ash { -RecentFilesContainer::RecentFilesContainer( - HoldingSpaceItemViewDelegate* delegate) - : delegate_(delegate) { +RecentFilesContainer::RecentFilesContainer() { SetID(kHoldingSpaceRecentFilesContainerId); SetLayoutManager(std::make_unique<views::BoxLayout>( @@ -68,12 +66,10 @@ DCHECK(!base::Contains(views_by_item_id_, item->id())); if (item->type() == HoldingSpaceItem::Type::kScreenshot) { views_by_item_id_[item->id()] = screenshots_container_->AddChildViewAt( - std::make_unique<HoldingSpaceItemScreenshotView>(delegate_, item), - /*index=*/0); + std::make_unique<HoldingSpaceItemScreenshotView>(item), 0 /*index*/); } else if (item->type() == HoldingSpaceItem::Type::kDownload) { views_by_item_id_[item->id()] = recent_downloads_container_->AddChildViewAt( - std::make_unique<HoldingSpaceItemChipView>(delegate_, item), - /*index=*/0); + std::make_unique<HoldingSpaceItemChipView>(item), 0 /*index*/); } } @@ -88,13 +84,13 @@ auto it = views_by_item_id_.find(item->id()); if (it == views_by_item_id_.end()) return; + views::View* view = it->second; if (item->type() == HoldingSpaceItem::Type::kScreenshot) { - screenshots_container_->RemoveChildViewT(it->second); + screenshots_container_->RemoveChildViewT(view); } else if (item->type() == HoldingSpaceItem::Type::kDownload) { - recent_downloads_container_->RemoveChildViewT(it->second); + recent_downloads_container_->RemoveChildViewT(view); } - views_by_item_id_.erase(it); }
diff --git a/ash/system/holding_space/recent_files_container.h b/ash/system/holding_space/recent_files_container.h index 36befed1..5d906a8 100644 --- a/ash/system/holding_space/recent_files_container.h +++ b/ash/system/holding_space/recent_files_container.h
@@ -12,12 +12,11 @@ namespace ash { class HoldingSpaceItemChipsContainer; -class HoldingSpaceItemViewDelegate; // Container for the recent files (Screenshots, downloads etc). class RecentFilesContainer : public HoldingSpaceItemViewsContainer { public: - explicit RecentFilesContainer(HoldingSpaceItemViewDelegate* delegate); + RecentFilesContainer(); RecentFilesContainer(const RecentFilesContainer& other) = delete; RecentFilesContainer& operator=(const RecentFilesContainer& other) = delete; ~RecentFilesContainer() override; @@ -28,7 +27,6 @@ void RemoveHoldingSpaceItemView(const HoldingSpaceItem* item) override; private: - HoldingSpaceItemViewDelegate* const delegate_; views::View* screenshots_container_ = nullptr; HoldingSpaceItemChipsContainer* recent_downloads_container_ = nullptr;
diff --git a/ash/system/media/media_tray.cc b/ash/system/media/media_tray.cc index e9ba5b4..157e0c2 100644 --- a/ash/system/media/media_tray.cc +++ b/ash/system/media/media_tray.cc
@@ -65,6 +65,8 @@ if (MediaNotificationProvider::Get()) MediaNotificationProvider::Get()->AddObserver(this); + Shell::Get()->session_controller()->AddObserver(this); + auto icon = std::make_unique<views::ImageView>(); icon->SetTooltipText(l10n_util::GetStringUTF16( IDS_ASH_GLOBAL_MEDIA_CONTROLS_BUTTON_TOOLTIP_TEXT)); @@ -82,6 +84,8 @@ if (MediaNotificationProvider::Get()) MediaNotificationProvider::Get()->RemoveObserver(this); + + Shell::Get()->session_controller()->RemoveObserver(this); } void MediaTray::OnNotificationListChanged() { @@ -171,13 +175,18 @@ CloseBubble(); } +void MediaTray::OnLockStateChanged(bool locked) { + UpdateDisplayState(); +} + void MediaTray::UpdateDisplayState() { if (!MediaNotificationProvider::Get()) return; bool should_show = - MediaNotificationProvider::Get()->HasActiveNotifications() || - MediaNotificationProvider::Get()->HasFrozenNotifications(); + (MediaNotificationProvider::Get()->HasActiveNotifications() || + MediaNotificationProvider::Get()->HasFrozenNotifications()) && + !Shell::Get()->session_controller()->IsScreenLocked(); if (!should_show && bubble_) CloseBubble();
diff --git a/ash/system/media/media_tray.h b/ash/system/media/media_tray.h index 9131d2a8..dac2a05f 100644 --- a/ash/system/media/media_tray.h +++ b/ash/system/media/media_tray.h
@@ -6,6 +6,7 @@ #define ASH_SYSTEM_MEDIA_MEDIA_TRAY_H_ #include "ash/public/cpp/media_notification_provider_observer.h" +#include "ash/public/cpp/session/session_observer.h" #include "ash/system/tray/tray_background_view.h" namespace views { @@ -18,7 +19,8 @@ class TrayBubbleWrapper; class MediaTray : public MediaNotificationProviderObserver, - public TrayBackgroundView { + public TrayBackgroundView, + public SessionObserver { public: explicit MediaTray(Shelf* shelf); ~MediaTray() override; @@ -37,6 +39,9 @@ void HideBubbleWithView(const TrayBubbleView* bubble_view) override; void ClickedOutsideBubble() override; + // SessionObserver implementation. + void OnLockStateChanged(bool locked) override; + TrayBubbleWrapper* tray_bubble_wrapper_for_testing() { return bubble_.get(); } private:
diff --git a/ash/system/media/media_tray_unittest.cc b/ash/system/media/media_tray_unittest.cc index e8d7914..eef1c9d 100644 --- a/ash/system/media/media_tray_unittest.cc +++ b/ash/system/media/media_tray_unittest.cc
@@ -28,6 +28,10 @@ [](auto, auto) { return std::make_unique<views::View>(); }); } + ~MockMediaNotificationProvider() override { + MediaNotificationProvider::Set(nullptr); + } + // Medianotificationprovider implementations. MOCK_METHOD2(GetMediaNotificationListView, std::unique_ptr<views::View>(SkColor, int)); @@ -111,6 +115,15 @@ provider()->SetHasFrozenNotifications(true); SimulateNotificationListChanged(); EXPECT_TRUE(media_tray()->GetVisible()); + + // Media tray should be hidden when screen is locked. + GetSessionControllerClient()->LockScreen(); + GetSessionControllerClient()->FlushForTest(); + EXPECT_FALSE(media_tray()->GetVisible()); + + // Media tray should be visible again when we unlock the screen. + GetSessionControllerClient()->UnlockScreen(); + EXPECT_TRUE(media_tray()->GetVisible()); } TEST_F(MediaTrayTest, ShowAndHideBubbleTest) {
diff --git a/ash/system/unified/unified_system_tray_controller.cc b/ash/system/unified/unified_system_tray_controller.cc index e9db7093..3f0f01b 100644 --- a/ash/system/unified/unified_system_tray_controller.cc +++ b/ash/system/unified/unified_system_tray_controller.cc
@@ -133,7 +133,8 @@ unified_view_ = new UnifiedSystemTrayView(this, model_->IsExpandedOnOpen()); InitFeaturePods(); - if (base::FeatureList::IsEnabled(media::kGlobalMediaControlsForChromeOS)) { + if (base::FeatureList::IsEnabled(media::kGlobalMediaControlsForChromeOS) && + !Shell::Get()->session_controller()->IsScreenLocked()) { media_controls_controller_ = std::make_unique<UnifiedMediaControlsController>(this); unified_view_->AddMediaControlsView(
diff --git a/base/allocator/partition_allocator/spinning_futex_linux.h b/base/allocator/partition_allocator/spinning_futex_linux.h index c1800bc..b7fd6df 100644 --- a/base/allocator/partition_allocator/spinning_futex_linux.h +++ b/base/allocator/partition_allocator/spinning_futex_linux.h
@@ -56,8 +56,9 @@ static constexpr int kLockedUncontended = 1; static constexpr int kLockedContended = 2; - // Same as SpinLock, not scientifically calibrated. - static constexpr int kSpinCount = 10; + // Same as SpinLock, not scientifically calibrated. Consider lowering later, + // as the slow path has better characteristics than SpinLocks's. + static constexpr int kSpinCount = 1000; std::atomic<int32_t> state_{kUnlocked}; }; @@ -78,7 +79,8 @@ ALWAYS_INLINE bool SpinningFutex::Try() { int expected = kUnlocked; - return state_.compare_exchange_strong(expected, kLockedUncontended, + return (state_.load(std::memory_order_relaxed) == expected) && + state_.compare_exchange_strong(expected, kLockedUncontended, std::memory_order_acquire, std::memory_order_relaxed); }
diff --git a/base/at_exit.h b/base/at_exit.h index fa652ac..2a11046 100644 --- a/base/at_exit.h +++ b/base/at_exit.h
@@ -8,7 +8,6 @@ #include "base/base_export.h" #include "base/callback.h" #include "base/containers/stack.h" -#include "base/macros.h" #include "base/synchronization/lock.h" #include "base/thread_annotations.h" @@ -33,6 +32,8 @@ typedef void (*AtExitCallbackType)(void*); AtExitManager(); + AtExitManager(const AtExitManager&) = delete; + AtExitManager& operator=(const AtExitManager&) = delete; // The dtor calls all the registered callbacks. Do not try to register more // callbacks after this point. @@ -71,8 +72,6 @@ // Stack of managers to allow shadowing. AtExitManager* const next_manager_; - - DISALLOW_COPY_AND_ASSIGN(AtExitManager); }; #if defined(UNIT_TEST)
diff --git a/base/atomic_sequence_num.h b/base/atomic_sequence_num.h index 717e37a..d0ab9eb4 100644 --- a/base/atomic_sequence_num.h +++ b/base/atomic_sequence_num.h
@@ -7,8 +7,6 @@ #include <atomic> -#include "base/macros.h" - namespace base { // AtomicSequenceNumber is a thread safe increasing sequence number generator. @@ -17,6 +15,8 @@ class AtomicSequenceNumber { public: constexpr AtomicSequenceNumber() = default; + AtomicSequenceNumber(const AtomicSequenceNumber&) = delete; + AtomicSequenceNumber& operator=(const AtomicSequenceNumber&) = delete; // Returns an increasing sequence number starts from 0 for each call. // This function can be called from any thread without data race. @@ -24,8 +24,6 @@ private: std::atomic_int seq_{0}; - - DISALLOW_COPY_AND_ASSIGN(AtomicSequenceNumber); }; } // namespace base
diff --git a/base/bind_unittest.cc b/base/bind_unittest.cc index 36282ac1..7336240 100644 --- a/base/bind_unittest.cc +++ b/base/bind_unittest.cc
@@ -10,7 +10,6 @@ #include <vector> #include "base/callback.h" -#include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" @@ -35,6 +34,9 @@ class NoRef { public: NoRef() = default; + NoRef(const NoRef&) = delete; + // Particularly important in this test to ensure no copies are made. + NoRef& operator=(const NoRef&) = delete; MOCK_METHOD0(VoidMethod0, void()); MOCK_CONST_METHOD0(VoidConstMethod0, void()); @@ -45,22 +47,18 @@ MOCK_METHOD1(VoidMethodWithIntArg, void(int)); MOCK_METHOD0(UniquePtrMethod0, std::unique_ptr<int>()); - private: - // Particularly important in this test to ensure no copies are made. - DISALLOW_COPY_AND_ASSIGN(NoRef); }; class HasRef : public NoRef { public: HasRef() = default; + HasRef(const HasRef&) = delete; + // Particularly important in this test to ensure no copies are made. + HasRef& operator=(const HasRef&) = delete; MOCK_CONST_METHOD0(AddRef, void()); MOCK_CONST_METHOD0(Release, bool()); MOCK_CONST_METHOD0(HasAtLeastOneRef, bool()); - - private: - // Particularly important in this test to ensure no copies are made. - DISALLOW_COPY_AND_ASSIGN(HasRef); }; class HasRefPrivateDtor : public HasRef { @@ -326,7 +324,8 @@ const_no_ref_ptr_ = &no_ref_; static_func_mock_ptr = &static_func_mock_; } - + BindTest(const BindTest&) = delete; + BindTest& operator=(const BindTest&) = delete; ~BindTest() override = default; static void VoidFunc0() { @@ -346,9 +345,6 @@ // Used by the static functions to perform expectations. static StrictMock<NoRef>* static_func_mock_ptr; - - private: - DISALLOW_COPY_AND_ASSIGN(BindTest); }; StrictMock<NoRef>* BindTest::static_func_mock_ptr;
diff --git a/base/callback_helpers.h b/base/callback_helpers.h index ad3fc32..2ed1011 100644 --- a/base/callback_helpers.h +++ b/base/callback_helpers.h
@@ -10,6 +10,7 @@ #ifndef BASE_CALLBACK_HELPERS_H_ #define BASE_CALLBACK_HELPERS_H_ +#include <memory> #include <type_traits> #include <utility> @@ -17,7 +18,6 @@ #include "base/bind.h" #include "base/callback.h" #include "base/compiler_specific.h" -#include "base/macros.h" #include "base/memory/ptr_util.h" namespace base { @@ -72,6 +72,10 @@ : callback_(std::move(callback)) { DCHECK(callback_); } + AdaptCallbackForRepeatingHelper(const AdaptCallbackForRepeatingHelper&) = + delete; + AdaptCallbackForRepeatingHelper& operator=( + const AdaptCallbackForRepeatingHelper&) = delete; void Run(Args... args) { if (subtle::NoBarrier_AtomicExchange(&has_run_, 1)) @@ -83,8 +87,6 @@ private: volatile subtle::Atomic32 has_run_ = 0; base::OnceCallback<void(Args...)> callback_; - - DISALLOW_COPY_AND_ASSIGN(AdaptCallbackForRepeatingHelper); }; } // namespace internal @@ -112,6 +114,8 @@ public: ScopedClosureRunner(); explicit ScopedClosureRunner(OnceClosure closure); + ScopedClosureRunner(const ScopedClosureRunner&) = delete; + ScopedClosureRunner& operator=(const ScopedClosureRunner&) = delete; ~ScopedClosureRunner(); ScopedClosureRunner(ScopedClosureRunner&& other); @@ -131,8 +135,6 @@ private: OnceClosure closure_; - - DISALLOW_COPY_AND_ASSIGN(ScopedClosureRunner); }; } // namespace base
diff --git a/base/callback_internal.h b/base/callback_internal.h index fdfdf7f8..54add71 100644 --- a/base/callback_internal.h +++ b/base/callback_internal.h
@@ -10,7 +10,6 @@ #include "base/base_export.h" #include "base/callback_forward.h" -#include "base/macros.h" #include "base/memory/ref_counted.h" namespace base { @@ -61,6 +60,9 @@ using InvokeFuncStorage = void(*)(); + BindStateBase(const BindStateBase&) = delete; + BindStateBase& operator=(const BindStateBase&) = delete; + private: BindStateBase(InvokeFuncStorage polymorphic_invoke, void (*destructor)(const BindStateBase*)); @@ -100,8 +102,6 @@ void (*destructor_)(const BindStateBase*); bool (*query_cancellation_traits_)(const BindStateBase*, CancellationQueryMode mode); - - DISALLOW_COPY_AND_ASSIGN(BindStateBase); }; // Holds the Callback methods that don't require specialization to reduce
diff --git a/base/callback_list_unittest.nc b/base/callback_list_unittest.nc index c6af89a..7a0e1c1e 100644 --- a/base/callback_list_unittest.nc +++ b/base/callback_list_unittest.nc
@@ -12,7 +12,6 @@ #include "base/bind.h" #include "base/bind_helpers.h" -#include "base/macros.h" namespace base { @@ -24,14 +23,13 @@ class FooListener { public: - FooListener() {} + FooListener() = default; + FooListener(const FooListener&) = delete; + FooListener& operator=(const FooListener&) = delete; void GotAScopedFoo(std::unique_ptr<Foo> f) { foo_ = std::move(f); } std::unique_ptr<Foo> foo_; - - private: - DISALLOW_COPY_AND_ASSIGN(FooListener); };
diff --git a/base/cancelable_callback.h b/base/cancelable_callback.h index aafa6d75..c19e9a36 100644 --- a/base/cancelable_callback.h +++ b/base/cancelable_callback.h
@@ -53,7 +53,6 @@ #include "base/callback_internal.h" #include "base/check.h" #include "base/compiler_specific.h" -#include "base/macros.h" #include "base/memory/weak_ptr.h" namespace base { @@ -62,7 +61,9 @@ template <typename CallbackType> class CancelableCallbackImpl { public: - CancelableCallbackImpl() {} + CancelableCallbackImpl() = default; + CancelableCallbackImpl(const CancelableCallbackImpl&) = delete; + CancelableCallbackImpl& operator=(const CancelableCallbackImpl&) = delete; // |callback| must not be null. explicit CancelableCallbackImpl(CallbackType callback) @@ -130,8 +131,6 @@ // The stored closure that may be cancelled. CallbackType callback_; mutable base::WeakPtrFactory<CancelableCallbackImpl> weak_ptr_factory_{this}; - - DISALLOW_COPY_AND_ASSIGN(CancelableCallbackImpl); }; } // namespace internal
diff --git a/base/cpu_affinity_posix_unittest.cc b/base/cpu_affinity_posix_unittest.cc index 406ccae8..aa476d67 100644 --- a/base/cpu_affinity_posix_unittest.cc +++ b/base/cpu_affinity_posix_unittest.cc
@@ -6,6 +6,8 @@ #include <sched.h> +#include <string> + #include "base/synchronization/waitable_event.h" #include "base/system/sys_info.h" #include "base/threading/platform_thread.h" @@ -24,6 +26,8 @@ WaitableEvent::InitialState::NOT_SIGNALED), terminate_thread_(WaitableEvent::ResetPolicy::MANUAL, WaitableEvent::InitialState::NOT_SIGNALED) {} + TestThread(const TestThread&) = delete; + TestThread& operator=(const TestThread&) = delete; ~TestThread() override { EXPECT_TRUE(terminate_thread_.IsSignaled()) << "Need to mark thread for termination and join the underlying thread " @@ -66,8 +70,6 @@ mutable WaitableEvent termination_ready_; WaitableEvent terminate_thread_; bool done_ = false; - - DISALLOW_COPY_AND_ASSIGN(TestThread); }; } // namespace
diff --git a/base/critical_closure.h b/base/critical_closure.h index 0eb6a3e..d47442d 100644 --- a/base/critical_closure.h +++ b/base/critical_closure.h
@@ -8,7 +8,6 @@ #include <utility> #include "base/callback.h" -#include "base/macros.h" #include "base/strings/string_piece.h" #include "build/build_config.h" @@ -31,14 +30,14 @@ class CriticalClosure { public: explicit CriticalClosure(StringPiece task_name, OnceClosure closure); + CriticalClosure(const CriticalClosure&) = delete; + CriticalClosure& operator=(const CriticalClosure&) = delete; ~CriticalClosure(); void Run(); private: ios::ScopedCriticalAction critical_action_; OnceClosure closure_; - - DISALLOW_COPY_AND_ASSIGN(CriticalClosure); }; #endif // defined(OS_IOS)
diff --git a/base/deferred_sequenced_task_runner.h b/base/deferred_sequenced_task_runner.h index c5fb57b7..864b8d5 100644 --- a/base/deferred_sequenced_task_runner.h +++ b/base/deferred_sequenced_task_runner.h
@@ -10,7 +10,6 @@ #include "base/base_export.h" #include "base/callback.h" #include "base/compiler_specific.h" -#include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/sequenced_task_runner.h" #include "base/synchronization/lock.h" @@ -33,6 +32,9 @@ // Use this constructor when you don't have the target SequencedTaskRunner. // When using this call StartWithTaskRunner(). DeferredSequencedTaskRunner(); + DeferredSequencedTaskRunner(const DeferredSequencedTaskRunner&) = delete; + DeferredSequencedTaskRunner& operator=(const DeferredSequencedTaskRunner&) = + delete; // TaskRunner implementation bool PostDelayedTask(const Location& from_here, @@ -87,8 +89,6 @@ bool started_ GUARDED_BY(lock_) = false; scoped_refptr<SequencedTaskRunner> target_task_runner_ GUARDED_BY(lock_); std::vector<DeferredTask> deferred_tasks_queue_ GUARDED_BY(lock_); - - DISALLOW_COPY_AND_ASSIGN(DeferredSequencedTaskRunner); }; } // namespace base
diff --git a/base/feature_list.h b/base/feature_list.h index 4618d02..4474b510 100644 --- a/base/feature_list.h +++ b/base/feature_list.h
@@ -9,11 +9,11 @@ #include <map> #include <memory> #include <string> +#include <utility> #include <vector> #include "base/base_export.h" #include "base/gtest_prod_util.h" -#include "base/macros.h" #include "base/metrics/field_trial_params.h" #include "base/metrics/persistent_memory_allocator.h" #include "base/strings/string_piece.h" @@ -99,6 +99,8 @@ class BASE_EXPORT FeatureList { public: FeatureList(); + FeatureList(const FeatureList&) = delete; + FeatureList& operator=(const FeatureList&) = delete; ~FeatureList(); // Used by common test fixture classes to prevent abuse of ScopedFeatureList @@ -106,14 +108,14 @@ class BASE_EXPORT ScopedDisallowOverrides { public: explicit ScopedDisallowOverrides(const char* reason); + ScopedDisallowOverrides(const ScopedDisallowOverrides&) = delete; + ScopedDisallowOverrides& operator=(const ScopedDisallowOverrides&) = delete; ~ScopedDisallowOverrides(); private: #if DCHECK_IS_ON() const char* const previous_reason_; #endif - - DISALLOW_COPY_AND_ASSIGN(ScopedDisallowOverrides); }; // Specifies whether a feature override enables or disables the feature. @@ -370,8 +372,6 @@ // Whether this object has been initialized from command line. bool initialized_from_command_line_ = false; - - DISALLOW_COPY_AND_ASSIGN(FeatureList); }; } // namespace base
diff --git a/base/feature_list_unittest.cc b/base/feature_list_unittest.cc index 9aae7d0..86dcfc0 100644 --- a/base/feature_list_unittest.cc +++ b/base/feature_list_unittest.cc
@@ -51,12 +51,12 @@ // Provide an empty FeatureList to each test by default. scoped_feature_list_.InitWithFeatureList(std::make_unique<FeatureList>()); } + FeatureListTest(const FeatureListTest&) = delete; + FeatureListTest& operator=(const FeatureListTest&) = delete; ~FeatureListTest() override = default; private: test::ScopedFeatureList scoped_feature_list_; - - DISALLOW_COPY_AND_ASSIGN(FeatureListTest); }; TEST_F(FeatureListTest, DefaultStates) {
diff --git a/base/file_descriptor_store.h b/base/file_descriptor_store.h index b6bd079..f22e124 100644 --- a/base/file_descriptor_store.h +++ b/base/file_descriptor_store.h
@@ -10,7 +10,6 @@ #include "base/files/memory_mapped_file.h" #include "base/files/scoped_file.h" -#include "base/macros.h" namespace base { @@ -19,6 +18,8 @@ // It is used to share file descriptors from a process to its child. class BASE_EXPORT FileDescriptorStore { public: + FileDescriptorStore(const FileDescriptorStore&) = delete; + FileDescriptorStore& operator=(const FileDescriptorStore&) = delete; struct Descriptor { Descriptor(const std::string& key, base::ScopedFD fd); Descriptor(const std::string& key, @@ -64,8 +65,6 @@ ~FileDescriptorStore(); Mapping descriptors_; - - DISALLOW_COPY_AND_ASSIGN(FileDescriptorStore); }; } // namespace base
diff --git a/base/file_version_info_mac.h b/base/file_version_info_mac.h index cd10a9c..0ac2b41 100644 --- a/base/file_version_info_mac.h +++ b/base/file_version_info_mac.h
@@ -10,13 +10,14 @@ #include "base/file_version_info.h" #include "base/mac/scoped_nsobject.h" -#include "base/macros.h" @class NSBundle; class FileVersionInfoMac : public FileVersionInfo { public: explicit FileVersionInfoMac(NSBundle *bundle); + FileVersionInfoMac(const FileVersionInfoMac&) = delete; + FileVersionInfoMac& operator=(const FileVersionInfoMac&) = delete; ~FileVersionInfoMac() override; // Accessors to the different version properties. @@ -38,8 +39,6 @@ base::string16 GetString16Value(CFStringRef name); base::scoped_nsobject<NSBundle> bundle_; - - DISALLOW_COPY_AND_ASSIGN(FileVersionInfoMac); }; #endif // BASE_FILE_VERSION_INFO_MAC_H_
diff --git a/base/file_version_info_win.h b/base/file_version_info_win.h index f0dbde8..7fd4d20 100644 --- a/base/file_version_info_win.h +++ b/base/file_version_info_win.h
@@ -15,7 +15,6 @@ #include "base/base_export.h" #include "base/file_version_info.h" -#include "base/macros.h" #include "base/version.h" struct tagVS_FIXEDFILEINFO; @@ -23,6 +22,8 @@ class BASE_EXPORT FileVersionInfoWin : public FileVersionInfo { public: + FileVersionInfoWin(const FileVersionInfoWin&) = delete; + FileVersionInfoWin& operator=(const FileVersionInfoWin&) = delete; ~FileVersionInfoWin() override; // Accessors to the different version properties. @@ -70,8 +71,6 @@ // This is a reference for a portion of |data_|. const VS_FIXEDFILEINFO& fixed_file_info_; - - DISALLOW_COPY_AND_ASSIGN(FileVersionInfoWin); }; #endif // BASE_FILE_VERSION_INFO_WIN_H_
diff --git a/base/file_version_info_win_unittest.cc b/base/file_version_info_win_unittest.cc index 4886896..dea983b 100644 --- a/base/file_version_info_win_unittest.cc +++ b/base/file_version_info_win_unittest.cc
@@ -12,7 +12,6 @@ #include "base/file_version_info.h" #include "base/files/file_path.h" -#include "base/macros.h" #include "base/path_service.h" #include "base/scoped_native_library.h" #include "base/strings/string_util.h" @@ -35,6 +34,8 @@ class FileVersionInfoFactory { public: explicit FileVersionInfoFactory(const FilePath& path) : path_(path) {} + FileVersionInfoFactory(const FileVersionInfoFactory&) = delete; + FileVersionInfoFactory& operator=(const FileVersionInfoFactory&) = delete; std::unique_ptr<FileVersionInfo> Create() const { return FileVersionInfo::CreateFileVersionInfo(path_); @@ -42,8 +43,6 @@ private: const FilePath path_; - - DISALLOW_COPY_AND_ASSIGN(FileVersionInfoFactory); }; class FileVersionInfoForModuleFactory { @@ -56,6 +55,10 @@ LOAD_LIBRARY_AS_IMAGE_RESOURCE)) { EXPECT_TRUE(library_.is_valid()); } + FileVersionInfoForModuleFactory(const FileVersionInfoForModuleFactory&) = + delete; + FileVersionInfoForModuleFactory& operator=( + const FileVersionInfoForModuleFactory&) = delete; std::unique_ptr<FileVersionInfo> Create() const { return FileVersionInfo::CreateFileVersionInfoForModule(library_.get()); @@ -63,8 +66,6 @@ private: const base::ScopedNativeLibrary library_; - - DISALLOW_COPY_AND_ASSIGN(FileVersionInfoForModuleFactory); }; template <typename T>
diff --git a/base/lazy_instance_unittest.cc b/base/lazy_instance_unittest.cc index ad1f0eb..bc990b0 100644 --- a/base/lazy_instance_unittest.cc +++ b/base/lazy_instance_unittest.cc
@@ -32,12 +32,12 @@ ConstructAndDestructLogger() { constructed_seq_.GetNext(); } + ConstructAndDestructLogger(const ConstructAndDestructLogger&) = delete; + ConstructAndDestructLogger& operator=(const ConstructAndDestructLogger&) = + delete; ~ConstructAndDestructLogger() { destructed_seq_.GetNext(); } - - private: - DISALLOW_COPY_AND_ASSIGN(ConstructAndDestructLogger); }; class SlowConstructor { @@ -48,13 +48,13 @@ ++constructed; some_int_ = 12; } + SlowConstructor(const SlowConstructor&) = delete; + SlowConstructor& operator=(const SlowConstructor&) = delete; int some_int() const { return some_int_; } static int constructed; private: int some_int_; - - DISALLOW_COPY_AND_ASSIGN(SlowConstructor); }; // static @@ -65,6 +65,8 @@ explicit SlowDelegate( base::LazyInstance<SlowConstructor>::DestructorAtExit* lazy) : lazy_(lazy) {} + SlowDelegate(const SlowDelegate&) = delete; + SlowDelegate& operator=(const SlowDelegate&) = delete; void Run() override { EXPECT_EQ(12, lazy_->Get().some_int()); @@ -73,8 +75,6 @@ private: base::LazyInstance<SlowConstructor>::DestructorAtExit* lazy_; - - DISALLOW_COPY_AND_ASSIGN(SlowDelegate); }; } // namespace @@ -212,7 +212,8 @@ base::PlatformThread::YieldCurrentThread(); done_construction_ = true; } - + BlockingConstructor(const BlockingConstructor&) = delete; + BlockingConstructor& operator=(const BlockingConstructor&) = delete; ~BlockingConstructor() { // Restore static state for the next test. base::subtle::NoBarrier_Store(&constructor_called_, 0); @@ -229,7 +230,7 @@ base::subtle::NoBarrier_Store(&complete_construction_, 1); } - bool done_construction() { return done_construction_; } + bool done_construction() const { return done_construction_; } private: // Use Atomic32 instead of AtomicFlag for them to be trivially initialized. @@ -237,8 +238,6 @@ static base::subtle::Atomic32 complete_construction_; bool done_construction_ = false; - - DISALLOW_COPY_AND_ASSIGN(BlockingConstructor); }; // A SimpleThread running at |thread_priority| which invokes |before_get| @@ -252,6 +251,9 @@ : SimpleThread("BlockingConstructorThread", Options(thread_priority)), lazy_(lazy), before_get_(std::move(before_get)) {} + BlockingConstructorThread(const BlockingConstructorThread&) = delete; + BlockingConstructorThread& operator=(const BlockingConstructorThread&) = + delete; void Run() override { if (before_get_) @@ -262,8 +264,6 @@ private: base::LazyInstance<BlockingConstructor>::DestructorAtExit* lazy_; base::OnceClosure before_get_; - - DISALLOW_COPY_AND_ASSIGN(BlockingConstructorThread); }; // static
diff --git a/base/logging.cc b/base/logging.cc index 3ced75a20..2696c0e 100644 --- a/base/logging.cc +++ b/base/logging.cc
@@ -18,6 +18,8 @@ #include <limits.h> #include <stdint.h> +#include <vector> + #include "base/pending_task.h" #include "base/stl_util.h" #include "base/task/common/task_annotator.h" @@ -635,26 +637,28 @@ public: explicit ASLClient(const std::string& facility) : client_(asl_open(nullptr, facility.c_str(), ASL_OPT_NO_DELAY)) {} + ASLClient(const ASLClient&) = delete; + ASLClient& operator=(const ASLClient&) = delete; ~ASLClient() { asl_close(client_); } aslclient get() const { return client_; } private: aslclient client_; - DISALLOW_COPY_AND_ASSIGN(ASLClient); } asl_client(main_bundle_id.empty() ? main_bundle_id : "com.apple.console"); const class ASLMessage { public: ASLMessage() : message_(asl_new(ASL_TYPE_MSG)) {} + ASLMessage(const ASLMessage&) = delete; + ASLMessage& operator=(const ASLMessage&) = delete; ~ASLMessage() { asl_free(message_); } aslmsg get() const { return message_; } private: aslmsg message_; - DISALLOW_COPY_AND_ASSIGN(ASLMessage); } asl_message; // By default, messages are only readable by the admin group. Explicitly @@ -697,6 +701,8 @@ explicit OSLog(const char* subsystem) : os_log_(subsystem ? os_log_create(subsystem, "chromium_logging") : OS_LOG_DEFAULT) {} + OSLog(const OSLog&) = delete; + OSLog& operator=(const OSLog&) = delete; ~OSLog() { if (os_log_ != OS_LOG_DEFAULT) { os_release(os_log_); @@ -706,7 +712,6 @@ private: os_log_t os_log_; - DISALLOW_COPY_AND_ASSIGN(OSLog); } log(main_bundle_id.empty() ? nullptr : main_bundle_id.c_str()); const os_log_type_t os_log_type = [](LogSeverity severity) { switch (severity) {
diff --git a/base/logging.h b/base/logging.h index cbf6da4..9e06ae9 100644 --- a/base/logging.h +++ b/base/logging.h
@@ -16,7 +16,6 @@ #include "base/callback_forward.h" #include "base/compiler_specific.h" #include "base/dcheck_is_on.h" -#include "base/macros.h" #include "base/scoped_clear_last_error.h" #include "base/strings/string_piece_forward.h" @@ -336,10 +335,9 @@ class BASE_EXPORT ScopedLogAssertHandler { public: explicit ScopedLogAssertHandler(LogAssertHandlerFunction handler); + ScopedLogAssertHandler(const ScopedLogAssertHandler&) = delete; + ScopedLogAssertHandler& operator=(const ScopedLogAssertHandler&) = delete; ~ScopedLogAssertHandler(); - - private: - DISALLOW_COPY_AND_ASSIGN(ScopedLogAssertHandler); }; // Sets the Log Message Handler that gets passed every log message before @@ -580,7 +578,8 @@ // Used for CHECK(). Implied severity = LOG_FATAL. LogMessage(const char* file, int line, const char* condition); - + LogMessage(const LogMessage&) = delete; + LogMessage& operator=(const LogMessage&) = delete; virtual ~LogMessage(); std::ostream& stream() { return stream_; } @@ -616,8 +615,6 @@ bool enable_timestamp, bool enable_tickcount); #endif - - DISALLOW_COPY_AND_ASSIGN(LogMessage); }; // This class is used to explicitly ignore values in the conditional @@ -650,14 +647,13 @@ int line, LogSeverity severity, SystemErrorCode err); - + Win32ErrorLogMessage(const Win32ErrorLogMessage&) = delete; + Win32ErrorLogMessage& operator=(const Win32ErrorLogMessage&) = delete; // Appends the error message before destructing the encapsulated class. ~Win32ErrorLogMessage() override; private: SystemErrorCode err_; - - DISALLOW_COPY_AND_ASSIGN(Win32ErrorLogMessage); }; #elif defined(OS_POSIX) || defined(OS_FUCHSIA) // Appends a formatted system message of the errno type @@ -667,14 +663,13 @@ int line, LogSeverity severity, SystemErrorCode err); - + ErrnoLogMessage(const ErrnoLogMessage&) = delete; + ErrnoLogMessage& operator=(const ErrnoLogMessage&) = delete; // Appends the error message before destructing the encapsulated class. ~ErrnoLogMessage() override; private: SystemErrorCode err_; - - DISALLOW_COPY_AND_ASSIGN(ErrnoLogMessage); }; #endif // OS_WIN
diff --git a/base/logging_unittest.cc b/base/logging_unittest.cc index b11ce9d..389f1ef4 100644 --- a/base/logging_unittest.cc +++ b/base/logging_unittest.cc
@@ -10,7 +10,6 @@ #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/logging.h" -#include "base/macros.h" #include "base/no_destructor.h" #include "base/run_loop.h" #include "base/sanitizer_buildflags.h" @@ -719,6 +718,8 @@ : public fuchsia::logger::testing::LogListenerSafe_TestBase { public: TestLogListenerSafe() = default; + TestLogListenerSafe(const TestLogListenerSafe&) = delete; + TestLogListenerSafe& operator=(const TestLogListenerSafe&) = delete; ~TestLogListenerSafe() override = default; void set_on_dump_logs_done(base::OnceClosure on_dump_logs_done) { @@ -755,8 +756,6 @@ fuchsia::logger::LogListenerSafePtr log_listener_; std::vector<fuchsia::logger::LogMessage> log_messages_; base::OnceClosure on_dump_logs_done_; - - DISALLOW_COPY_AND_ASSIGN(TestLogListenerSafe); }; // Verifies that calling the log macro goes to the Fuchsia system logs.
diff --git a/base/logging_win.h b/base/logging_win.h index cdde7bb..8aca72b9 100644 --- a/base/logging_win.h +++ b/base/logging_win.h
@@ -11,7 +11,6 @@ #include "base/base_export.h" #include "base/logging.h" -#include "base/macros.h" #include "base/win/event_trace_provider.h" namespace base { @@ -55,6 +54,8 @@ // with Event Tracing for Windows. class BASE_EXPORT LogEventProvider : public base::win::EtwTraceProvider { public: + LogEventProvider(const LogEventProvider&) = delete; + LogEventProvider& operator=(const LogEventProvider&) = delete; static LogEventProvider* GetInstance(); static bool LogMessage(logging::LogSeverity severity, const char* file, @@ -76,7 +77,6 @@ logging::LogSeverity old_log_level_; friend struct base::StaticMemorySingletonTraits<LogEventProvider>; - DISALLOW_COPY_AND_ASSIGN(LogEventProvider); }; } // namespace logging
diff --git a/base/native_library_unittest.cc b/base/native_library_unittest.cc index 623f636..3933202d 100644 --- a/base/native_library_unittest.cc +++ b/base/native_library_unittest.cc
@@ -3,7 +3,6 @@ // found in the LICENSE file. #include "base/files/file_path.h" -#include "base/macros.h" #include "base/native_library.h" #include "base/path_service.h" #include "base/test/native_library_test_utils.h" @@ -88,7 +87,8 @@ exe_path.AppendASCII(kTestLibraryName), options, nullptr); CHECK(library_); } - + TestLibrary(const TestLibrary&) = delete; + TestLibrary& operator=(const TestLibrary&) = delete; ~TestLibrary() { UnloadNativeLibrary(library_); } @@ -101,8 +101,6 @@ private: NativeLibrary library_; - - DISALLOW_COPY_AND_ASSIGN(TestLibrary); }; // NativeLibraaryTest.LoadLibrary is failing on M tablets only.
diff --git a/base/no_destructor_unittest.cc b/base/no_destructor_unittest.cc index 63d5c13e..54ac1b53 100644 --- a/base/no_destructor_unittest.cc +++ b/base/no_destructor_unittest.cc
@@ -4,8 +4,10 @@ #include "base/no_destructor.h" +#include <memory> #include <string> #include <utility> +#include <vector> #include "base/atomicops.h" #include "base/barrier_closure.h" @@ -93,7 +95,8 @@ PlatformThread::YieldCurrentThread(); done_construction_ = true; } - + BlockingConstructor(const BlockingConstructor&) = delete; + BlockingConstructor& operator=(const BlockingConstructor&) = delete; ~BlockingConstructor() = delete; // Returns true if BlockingConstructor() was entered. @@ -106,7 +109,7 @@ subtle::NoBarrier_Store(&complete_construction_, 1); } - bool done_construction() { return done_construction_; } + bool done_construction() const { return done_construction_; } private: // Use Atomic32 instead of AtomicFlag for them to be trivially initialized. @@ -114,8 +117,6 @@ static subtle::Atomic32 complete_construction_; bool done_construction_ = false; - - DISALLOW_COPY_AND_ASSIGN(BlockingConstructor); }; // static @@ -132,6 +133,9 @@ OnceClosure before_get) : SimpleThread("BlockingConstructorThread", Options(thread_priority)), before_get_(std::move(before_get)) {} + BlockingConstructorThread(const BlockingConstructorThread&) = delete; + BlockingConstructorThread& operator=(const BlockingConstructorThread&) = + delete; void Run() override { if (before_get_) @@ -143,8 +147,6 @@ private: OnceClosure before_get_; - - DISALLOW_COPY_AND_ASSIGN(BlockingConstructorThread); }; } // namespace
diff --git a/base/observer_list.h b/base/observer_list.h index 52c8fad0..28369a25 100644 --- a/base/observer_list.h +++ b/base/observer_list.h
@@ -15,7 +15,6 @@ #include "base/check_op.h" #include "base/gtest_prod_util.h" -#include "base/macros.h" #include "base/notreached.h" #include "base/observer_list_internal.h" #include "base/sequence_checker.h" @@ -247,7 +246,8 @@ // Sequence checks only apply when iterators are live. DETACH_FROM_SEQUENCE(iteration_sequence_checker_); } - + ObserverList(const ObserverList&) = delete; + ObserverList& operator=(const ObserverList&) = delete; ~ObserverList() { // If there are live iterators, ensure destruction is thread-safe. if (!live_iterators_.empty()) @@ -337,8 +337,6 @@ const ObserverListPolicy policy_; SEQUENCE_CHECKER(iteration_sequence_checker_); - - DISALLOW_COPY_AND_ASSIGN(ObserverList); }; template <class ObserverType, bool check_empty = false>
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index 5f64aa2..41ac39e 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -0.20200922.3.1 +0.20200923.0.1
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index 5f64aa2..41ac39e 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -0.20200922.3.1 +0.20200923.0.1
diff --git a/chrome/VERSION b/chrome/VERSION index cdbeef96..e5811f6 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=87 MINOR=0 -BUILD=4272 +BUILD=4273 PATCH=0
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantLiteScriptCoordinator.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantLiteScriptCoordinator.java index a1a03296..584cb3a 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantLiteScriptCoordinator.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantLiteScriptCoordinator.java
@@ -84,6 +84,15 @@ case LiteScriptFinishedState.LITE_SCRIPT_PROMPT_FAILED_CONDITION_NO_LONGER_TRUE: case LiteScriptFinishedState.LITE_SCRIPT_PROMPT_FAILED_OTHER: case LiteScriptFinishedState.LITE_SCRIPT_PROMPT_SUCCEEDED: + case LiteScriptFinishedState.LITE_SCRIPT_BROWSE_FAILED_NAVIGATE: + case LiteScriptFinishedState.LITE_SCRIPT_BROWSE_FAILED_OTHER: + case LiteScriptFinishedState.LITE_SCRIPT_GET_ACTIONS_FAILED: + case LiteScriptFinishedState.LITE_SCRIPT_GET_ACTIONS_PARSE_ERROR: + case LiteScriptFinishedState.LITE_SCRIPT_INVALID_SCRIPT: + case LiteScriptFinishedState.LITE_SCRIPT_PATH_MISMATCH: + case LiteScriptFinishedState.LITE_SCRIPT_SERVICE_DELETED: + case LiteScriptFinishedState.LITE_SCRIPT_UNKNOWN_FAILURE: + case LiteScriptFinishedState.LITE_SCRIPT_UNSAFE_ACTIONS: break; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuChipController.java b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuChipController.java index 9cec9ec..8dbd134e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuChipController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuChipController.java
@@ -127,8 +127,17 @@ mPopupWindow.show(); } - @VisibleForTesting + // This method should only be used in test files. It is not marked + // @VisibleForTesting to allow the Coordinator to reference it in its + // own testing methods. AnchoredPopupWindow getCurrentPopupWindowForTesting() { return mPopupWindow; } + + // This method should only be used in test files. It is not marked + // @VisibleForTesting to allow the Coordinator to reference it in its + // own testing methods. + void clickChipForTesting() { + onClick(mChipView); + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuCoordinator.java index 2a55aa8..5b7d838 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuCoordinator.java
@@ -36,6 +36,7 @@ import org.chromium.ui.modelutil.MVCListAdapter.ModelList; import org.chromium.ui.modelutil.ModelListAdapter; import org.chromium.ui.modelutil.PropertyModel; +import org.chromium.ui.widget.AnchoredPopupWindow; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -299,6 +300,25 @@ activity, PerformanceClass.PERFORMANCE_UNKNOWN, params, profile); } + @VisibleForTesting + void simulateShoppyImageClassificationForTesting() { + // Don't need to initialize controller because that should be triggered by + // forcing feature flags. + mChipController.handleImageClassification(true); + } + + // Public only to allow references from RevampedContextMenuUtils.java + public void clickChipForTesting() { + mChipController.clickChipForTesting(); // IN-TEST + } + + // Public only to allow references from RevampedContextMenuUtils.java + public AnchoredPopupWindow getCurrentPopupWindowForTesting() { + // Don't need to initialize controller because that should be triggered by + // forcing feature flags. + return mChipController.getCurrentPopupWindowForTesting(); // IN-TEST + } + public void clickListItemForTesting(int id) { mListView.performItemClick(null, -1, id); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuTest.java index c45c8d0..e91fac6a 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuTest.java
@@ -9,6 +9,7 @@ import android.content.ClipData; import android.content.ClipboardManager; import android.content.Context; +import android.os.Looper; import android.support.test.InstrumentationRegistry; import android.view.KeyEvent; @@ -408,6 +409,66 @@ @Test @MediumTest + @Feature({"Browser"}) + @Features.EnableFeatures({ChromeFeatureList.CONTEXT_MENU_GOOGLE_LENS_CHIP}) + public void testSelectLensChip() throws Throwable { + // Required to avoid runtime error. + Looper.prepare(); + + Tab tab = mDownloadTestRule.getActivity().getActivityTab(); + ShareHelper.setIgnoreActivityNotFoundExceptionForTesting(true); + hardcodeTestImageForSharing(TEST_JPG_IMAGE_FILE_EXTENSION); + + RevampedContextMenuCoordinator menuCoordinator = + RevampedContextMenuUtils.openContextMenu(tab, "testImage"); + // Needs to run on UI thread so creation happens on same thread as dismissal. + TestThreadUtils.runOnUiThreadBlocking( + () -> menuCoordinator.simulateShoppyImageClassificationForTesting()); + + Assert.assertTrue("Chip popoup not showing.", + menuCoordinator.getCurrentPopupWindowForTesting().isShowing()); + + RevampedContextMenuUtils.selectAlreadyOpenedContextMenuChipWithExpectedIntent( + InstrumentationRegistry.getInstrumentation(), mDownloadTestRule.getActivity(), + menuCoordinator, "testImage", R.id.contextmenu_shop_image_with_google_lens, + "com.google.android.googlequicksearchbox"); + Assert.assertEquals("Selection histogram pings not equal to one", 1, + RecordHistogram.getHistogramTotalCountForTesting( + "ContextMenu.SelectedOptionAndroid.Image")); + Assert.assertFalse("Chip popoup still showing.", + menuCoordinator.getCurrentPopupWindowForTesting().isShowing()); + } + + // Assert that focus is unchanged and that the chip popup does not block the dismissal of the + // context menu. + @Test + @MediumTest + @Features.EnableFeatures({ChromeFeatureList.CONTEXT_MENU_GOOGLE_LENS_CHIP}) + public void testDismissContextMenuOnClickLensChipEnabled() throws TimeoutException { + // Required to avoid runtime error. + Looper.prepare(); + + Tab tab = mDownloadTestRule.getActivity().getActivityTab(); + RevampedContextMenuCoordinator menuCoordinator = + RevampedContextMenuUtils.openContextMenu(tab, "testImage"); + // Needs to run on UI thread so creation happens on same thread as dismissal. + TestThreadUtils.runOnUiThreadBlocking( + () -> menuCoordinator.simulateShoppyImageClassificationForTesting()); + Assert.assertNotNull("Context menu was not properly created", menuCoordinator); + CriteriaHelper.pollUiThread(() -> { + return !mDownloadTestRule.getActivity().hasWindowFocus(); + }, "Context menu did not have window focus"); + + TestTouchUtils.singleClickView(InstrumentationRegistry.getInstrumentation(), tab.getView(), + tab.getView().getWidth() - 5, tab.getView().getHeight() - 5); + + CriteriaHelper.pollUiThread(() -> { + return mDownloadTestRule.getActivity().hasWindowFocus(); + }, "Activity did not regain focus."); + } + + @Test + @MediumTest public void testDismissContextMenuOnClick() throws TimeoutException { Tab tab = mDownloadTestRule.getActivity().getActivityTab(); RevampedContextMenuCoordinator menuCoordinator =
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp index 265bd22..b54c439 100644 --- a/chrome/app/settings_strings.grdp +++ b/chrome/app/settings_strings.grdp
@@ -352,6 +352,12 @@ =1 {{COUNT} compromised password} other {{COUNT} compromised passwords}} </message> + <message name="IDS_SETTINGS_INSECURE_PASSWORDS_COUNT" desc="Number of insecure passwords present in the database"> + {COUNT, plural, + =0 {No security issues found} + =1 {Found {COUNT} security issue} + other {Found {COUNT} security issues}} + </message> <message name="IDS_SETTINGS_CHECK_PASSWORDS_AGAIN" desc="Button to start bulk password check manually in passwords check section."> Check again </message>
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_INSECURE_PASSWORDS_COUNT.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_INSECURE_PASSWORDS_COUNT.png.sha1 new file mode 100644 index 0000000..bfdf6d7f --- /dev/null +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_INSECURE_PASSWORDS_COUNT.png.sha1
@@ -0,0 +1 @@ +121c305725484c75be7ab0ed6f627abdfc5023ac \ No newline at end of file
diff --git a/chrome/app/sharesheet_strings.grdp b/chrome/app/sharesheet_strings.grdp index 01f6838..ccc3415b 100644 --- a/chrome/app/sharesheet_strings.grdp +++ b/chrome/app/sharesheet_strings.grdp
@@ -5,4 +5,13 @@ <message name="IDS_SHARESHEET_TITLE_LABEL" desc="The label to be shown as the title of the sharesheet bubble when a user clicks on the share button."> Share </message> + <message name="IDS_SHARESHEET_APPS_LIST_LABEL" desc="The label to be shown before the list of apps."> + Apps list + </message> + <message name="IDS_SHARESHEET_MORE_APPS_LABEL" desc="The label for the button at the bottom of the sharesheet which clicks into the expanded sharesheet."> + More apps + </message> + <message name="IDS_SHARESHEET_FEWER_APPS_LABEL" desc="The label for the button at the bottom of the sharesheet which clicks into the default sharesheet."> + Fewer apps + </message> </grit-part>
diff --git a/chrome/app/sharesheet_strings_grdp/IDS_SHARESHEET_APPS_LIST_LABEL.png.sha1 b/chrome/app/sharesheet_strings_grdp/IDS_SHARESHEET_APPS_LIST_LABEL.png.sha1 new file mode 100644 index 0000000..82fb6857 --- /dev/null +++ b/chrome/app/sharesheet_strings_grdp/IDS_SHARESHEET_APPS_LIST_LABEL.png.sha1
@@ -0,0 +1 @@ +32501db09db820361f32e8debbde95b81810da7b \ No newline at end of file
diff --git a/chrome/app/sharesheet_strings_grdp/IDS_SHARESHEET_FEWER_APPS_LABEL.png.sha1 b/chrome/app/sharesheet_strings_grdp/IDS_SHARESHEET_FEWER_APPS_LABEL.png.sha1 new file mode 100644 index 0000000..29a5166 --- /dev/null +++ b/chrome/app/sharesheet_strings_grdp/IDS_SHARESHEET_FEWER_APPS_LABEL.png.sha1
@@ -0,0 +1 @@ +9eea332d3d39da4a1e5887e755bcf47a09127eb6 \ No newline at end of file
diff --git a/chrome/app/sharesheet_strings_grdp/IDS_SHARESHEET_MORE_APPS_LABEL.png.sha1 b/chrome/app/sharesheet_strings_grdp/IDS_SHARESHEET_MORE_APPS_LABEL.png.sha1 new file mode 100644 index 0000000..4b23489 --- /dev/null +++ b/chrome/app/sharesheet_strings_grdp/IDS_SHARESHEET_MORE_APPS_LABEL.png.sha1
@@ -0,0 +1 @@ +cb42423ee0b152a7460364e832abf984524d26bb \ No newline at end of file
diff --git a/chrome/app/vector_icons/BUILD.gn b/chrome/app/vector_icons/BUILD.gn index e10625e8..acb69dc 100644 --- a/chrome/app/vector_icons/BUILD.gn +++ b/chrome/app/vector_icons/BUILD.gn
@@ -10,6 +10,7 @@ aggregate_vector_icons("chrome_vector_icons") { icon_directory = "." + # Keep sorted alphabetically. icons = [ "account_box.icon", "account_child.icon", @@ -18,24 +19,21 @@ "apps.icon", "autofill/webauthn_dialog_header.icon", "autofill/webauthn_dialog_header_dark.icon", + "back_arrow_touch.icon", "blocked_redirect.icon", + "bookmarkbar_touch_overflow.icon", "browser_tools.icon", "browser_tools_error.icon", + "browser_tools_error_touch.icon", + "browser_tools_touch.icon", "browser_tools_update.icon", + "browser_tools_update_touch.icon", "caret_down.icon", "caret_up.icon", + "cast_for_education.icon", "click_to_call_illustration.icon", "click_to_call_illustration_dark.icon", "close_all.icon", - - # Alternative squarer content_paste icon optimised for display at 18x18dip. - # Currently only used in the Page Info bubble. - "back_arrow_touch.icon", - "bookmarkbar_touch_overflow.icon", - "browser_tools_error_touch.icon", - "browser_tools_touch.icon", - "browser_tools_update_touch.icon", - "cast_for_education.icon", "computer_with_circle_background.icon", "copy.icon", "crashed_tab.icon", @@ -50,10 +48,12 @@ "fullscreen.icon", "generic_stop.icon", "globe.icon", + "guest_menu_art.icon", "hardware_computer.icon", "hardware_smartphone.icon", "horizontal_menu.icon", "incognito.icon", + "incognito_menu_art.icon", "incognito_profile.icon", "input.icon", "key.icon",
diff --git a/chrome/app/vector_icons/guest_menu_art.icon b/chrome/app/vector_icons/guest_menu_art.icon new file mode 100644 index 0000000..d26b82c --- /dev/null +++ b/chrome/app/vector_icons/guest_menu_art.icon
@@ -0,0 +1,104 @@ +// Copyright 2020 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. + +CANVAS_DIMENSIONS, 272, +MOVE_TO, 209.9f, 56.8f, +CUBIC_TO, 209.3f, 56.2f, 208.4f, 56, 207.6f, 56.2f, +LINE_TO, 200.4f, 58.1f, +CUBIC_TO, 199.6f, 58.3f, 198.9f, 59, 198.7f, 59.8f, +LINE_TO, 196.8f, 67, +CUBIC_TO, 196.6f, 67.8f, 196.8f, 68.7f, 197.4f, 69.3f, +LINE_TO, 200, 72, +H_LINE_TO, 202.1f, +LINE_TO, 198.4f, 68.3f, +CUBIC_TO, 198.2f, 68.1f, 198.1f, 67.8f, 198.2f, 67.5f, +LINE_TO, 200.1f, 60.3f, +CUBIC_TO, 200.2f, 60, 200.4f, 59.8f, 200.7f, 59.7f, +LINE_TO, 207.9f, 57.8f, +CUBIC_TO, 208.2f, 57.7f, 208.5f, 57.8f, 208.7f, 58, +LINE_TO, 214, 63.3f, +CUBIC_TO, 214.2f, 63.5f, 214.3f, 63.8f, 214.2f, 64.1f, +LINE_TO, 212.3f, 71.3f, +CUBIC_TO, 212.2f, 71.6f, 212, 71.8f, 211.7f, 71.9f, +LINE_TO, 211.3f, 72, +H_LINE_TO, 213.7f, +CUBIC_TO, 213.7f, 71.9f, 213.8f, 71.8f, 213.8f, 71.7f, +LINE_TO, 215.7f, 64.5f, +CUBIC_TO, 215.9f, 63.7f, 215.7f, 62.8f, 215.1f, 62.2f, +LINE_TO, 209.9f, 56.8f, +CLOSE, +MOVE_TO, 176.1f, 6.4f, +CUBIC_TO, 176.1f, 15.3f, 183.3f, 22.5f, 192.2f, 22.5f, +CUBIC_TO, 201.1f, 22.5f, 208.3f, 15.3f, 208.3f, 6.4f, +CUBIC_TO, 208.3f, 4.1f, 207.8f, 1.9f, 207, 0, +H_LINE_TO, 177.5f, +CUBIC_TO, 176.6f, 2, 176.1f, 4.1f, 176.1f, 6.4f, +CLOSE, +MOVE_TO, 102.5f, 18.7f, +CUBIC_TO, 105.92f, 18.7f, 108.7f, 15.92f, 108.7f, 12.5f, +CUBIC_TO, 108.7f, 9.08f, 105.92f, 6.3f, 102.5f, 6.3f, +CUBIC_TO, 99.08f, 6.3f, 96.3f, 9.08f, 96.3f, 12.5f, +CUBIC_TO, 96.3f, 15.92f, 99.08f, 18.7f, 102.5f, 18.7f, +CLOSE, +MOVE_TO, 56.1f, 4.9f, +CUBIC_TO, 58.3f, 8, 57.6f, 12.4f, 54.4f, 14.6f, +CUBIC_TO, 52.9f, 15.7f, 51, 16.1f, 49.2f, 15.8f, +CUBIC_TO, 47.4f, 15.5f, 45.8f, 14.5f, 44.7f, 13, +LINE_TO, 35.9f, 0.4f, +CUBIC_TO, 35.8f, 0.3f, 35.7f, 0.1f, 35.7f, 0, +H_LINE_TO, 34, +CUBIC_TO, 34.2f, 0.4f, 34.4f, 0.8f, 34.7f, 1.2f, +LINE_TO, 43.6f, 13.8f, +CUBIC_TO, 44.9f, 15.6f, 46.8f, 16.9f, 49.1f, 17.3f, +CUBIC_TO, 49.6f, 17.4f, 50.1f, 17.4f, 50.6f, 17.4f, +CUBIC_TO, 52.3f, 17.4f, 54, 16.9f, 55.5f, 15.9f, +CUBIC_TO, 59.3f, 13.2f, 60.2f, 7.9f, 57.5f, 4.1f, +LINE_TO, 54.5f, 0, +H_LINE_TO, 52.7f, +LINE_TO, 56.1f, 4.9f, +CLOSE, +MOVE_TO, 272, 27.2f, +CUBIC_TO, 270.8f, 27.1f, 269.7f, 27.3f, 268.6f, 27.7f, +CUBIC_TO, 267.3f, 28.2f, 265.9f, 28.3f, 264.6f, 27.8f, +LINE_TO, 264, 27.6f, +CUBIC_TO, 262.7f, 27.1f, 261.7f, 26.1f, 261.2f, 24.8f, +CUBIC_TO, 260.4f, 22.9f, 258.8f, 21.4f, 256.6f, 20.8f, +CUBIC_TO, 253.4f, 19.9f, 249.8f, 21.3f, 248.2f, 24.3f, +CUBIC_TO, 246.1f, 28.2f, 247.9f, 32.9f, 251.9f, 34.4f, +CUBIC_TO, 253.7f, 35.1f, 255.7f, 35.1f, 257.4f, 34.4f, +CUBIC_TO, 258.7f, 33.9f, 260.1f, 33.8f, 261.3f, 34.3f, +LINE_TO, 261.9f, 34.5f, +CUBIC_TO, 263.2f, 35, 264.2f, 36, 264.7f, 37.3f, +CUBIC_TO, 265.4f, 39, 266.8f, 40.4f, 268.6f, 41.1f, +CUBIC_TO, 269.7f, 41.5f, 270.8f, 41.7f, 271.9f, 41.6f, +V_LINE_TO, 27.2f, +H_LINE_TO, 272, +CLOSE, +MOVE_TO, 0, 34.1f, +V_LINE_TO, 56.9f, +LINE_TO, 25, 48.3f, +CUBIC_TO, 25.8f, 48, 26.2f, 47.1f, 25.9f, 46.3f, +CUBIC_TO, 21.6f, 36.2f, 10.5f, 31, 0, 34.1f, +CLOSE, +MOVE_TO, 65.9f, 52.9f, +CUBIC_TO, 65.3f, 52.4f, 64.5f, 52.7f, 64.3f, 53.4f, +LINE_TO, 60.4f, 72, +H_LINE_TO, 65.1f, +LINE_TO, 72.35f, 69.6f, +LINE_TO, 79.6f, 67.2f, +CUBIC_TO, 80.3f, 67, 80.5f, 66, 79.9f, 65.6f, +LINE_TO, 65.9f, 52.9f, +CLOSE, +NEW_PATH, +STROKE, 1, +MOVE_TO, 0.5f, 4, +CUBIC_TO, 0.5f, 2.07f, 2.07f, 0.5f, 4, 0.5f, +H_LINE_TO, 268, +CUBIC_TO, 269.93f, 0.5f, 271.5f, 2.07f, 271.5f, 4, +V_LINE_TO, 68, +CUBIC_TO, 271.5f, 69.93f, 269.93f, 71.5f, 268, 71.5f, +H_LINE_TO, 4, +CUBIC_TO, 2.07f, 71.5f, 0.5f, 69.93f, 0.5f, 68, +V_LINE_TO, 4, +CLOSE \ No newline at end of file
diff --git a/chrome/app/vector_icons/incognito_menu_art.icon b/chrome/app/vector_icons/incognito_menu_art.icon new file mode 100644 index 0000000..5fa6158 --- /dev/null +++ b/chrome/app/vector_icons/incognito_menu_art.icon
@@ -0,0 +1,116 @@ +// Copyright 2020 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. + +CANVAS_DIMENSIONS, 272, +MOVE_TO, 203.7f, 0, +H_LINE_TO, 268, +CUBIC_TO, 270.21f, 0, 272, 1.79f, 272, 4, +V_LINE_TO, 69, +CUBIC_TO, 272, 71.21f, 270.21f, 73, 268, 73, +H_LINE_TO, 259.4f, +LINE_TO, 258, 61.6f, +CUBIC_TO, 256.3f, 62.1f, 254.5f, 62.4f, 252.6f, 62.4f, +CUBIC_TO, 243.1f, 62.4f, 235.4f, 55.1f, 234.5f, 45.7f, +CUBIC_TO, 229.4f, 42.5f, 225.3f, 44.5f, 223.8f, 45.6f, +CUBIC_TO, 223.1f, 55, 215.3f, 62.4f, 205.7f, 62.4f, +CUBIC_TO, 195.6f, 62.4f, 187.5f, 54.2f, 187.5f, 44.2f, +CUBIC_TO, 187.5f, 34.1f, 195.7f, 26, 205.7f, 26, +CUBIC_TO, 214.3f, 26, 221.5f, 32, 223.4f, 40.1f, +CUBIC_TO, 226.4f, 38.8f, 230.5f, 38.3f, 234.9f, 40.2f, +CUBIC_TO, 236.8f, 32.1f, 244, 26.1f, 252.6f, 26.1f, +H_LINE_TO, 253.8f, +LINE_TO, 253.2f, 20.8f, +H_LINE_TO, 182.2f, +H_LINE_TO, 94.4f, +LINE_TO, 100.1f, 13.5f, +H_LINE_TO, 172.1f, +LINE_TO, 167.1f, 0, +H_LINE_TO, 188.5f, +LINE_TO, 184, 15.5f, +H_LINE_TO, 252.6f, +LINE_TO, 252, 10.3f, +H_LINE_TO, 199.8f, +LINE_TO, 203.7f, 0, +CLOSE, +MOVE_TO, 68.2f, 0, +H_LINE_TO, 4, +CUBIC_TO, 1.79f, 0, 0, 1.79f, 0, 4, +V_LINE_TO, 69, +CUBIC_TO, 0, 71.21f, 1.79f, 73, 4, 73, +LINE_TO, 4.5f, 73, +LINE_TO, 13.8f, 47.7f, +CUBIC_TO, 16.4f, 49.4f, 19.5f, 50.4f, 22.8f, 50.4f, +CUBIC_TO, 31.3f, 50.4f, 38.3f, 43.8f, 38.9f, 35.5f, +CUBIC_TO, 40.3f, 34.5f, 44, 32.7f, 48.5f, 35.6f, +CUBIC_TO, 49.2f, 43.9f, 56.1f, 50.4f, 64.6f, 50.4f, +CUBIC_TO, 67.5f, 50.4f, 70.2f, 49.7f, 72.6f, 48.3f, +LINE_TO, 53, 73, +H_LINE_TO, 76.4f, +CUBIC_TO, 74.4f, 69.3f, 73.2f, 65.1f, 73.2f, 60.6f, +CUBIC_TO, 73.2f, 46.6f, 84.6f, 35.2f, 98.6f, 35.2f, +CUBIC_TO, 110.6f, 35.2f, 120.6f, 43.6f, 123.3f, 54.8f, +CUBIC_TO, 127.5f, 53, 133.2f, 52.3f, 139.3f, 54.9f, +CUBIC_TO, 141.9f, 43.6f, 152, 35.2f, 164, 35.2f, +CUBIC_TO, 168.8f, 35.2f, 173.3f, 36.6f, 177.1f, 38.9f, +LINE_TO, 180.3f, 28, +H_LINE_TO, 88.7f, +LINE_TO, 80.1f, 38.8f, +CUBIC_TO, 80.6f, 37.3f, 80.8f, 35.8f, 80.8f, 34.2f, +CUBIC_TO, 80.8f, 25.3f, 73.5f, 18, 64.6f, 18, +CUBIC_TO, 56.9f, 18, 50.5f, 23.4f, 48.8f, 30.5f, +CUBIC_TO, 44.9f, 28.9f, 41.3f, 29.3f, 38.6f, 30.5f, +CUBIC_TO, 37, 24, 31.6f, 19, 24.9f, 18.1f, +LINE_TO, 26.7f, 13.3f, +H_LINE_TO, 85.5f, +V_LINE_TO, 8.7f, +H_LINE_TO, 28.4f, +LINE_TO, 30.1f, 4.1f, +H_LINE_TO, 69.7f, +LINE_TO, 68.2f, 0, +CLOSE, +MOVE_TO, 85.3f, 73, +H_LINE_TO, 111.7f, +CUBIC_TO, 114.7f, 69.7f, 116.6f, 65.4f, 116.6f, 60.6f, +CUBIC_TO, 116.6f, 50.6f, 108.5f, 42.5f, 98.5f, 42.5f, +CUBIC_TO, 88.5f, 42.5f, 80.4f, 50.6f, 80.4f, 60.6f, +CUBIC_TO, 80.4f, 65.4f, 82.3f, 69.8f, 85.3f, 73, +CLOSE, +MOVE_TO, 120.5f, 73, +H_LINE_TO, 141.6f, +CUBIC_TO, 139.9f, 69.9f, 138.8f, 66.5f, 138.5f, 62.8f, +CUBIC_TO, 131.5f, 58.3f, 125.8f, 61.2f, 123.6f, 62.7f, +CUBIC_TO, 123.3f, 66.4f, 122.2f, 69.9f, 120.5f, 73, +CLOSE, +MOVE_TO, 150.4f, 73, +H_LINE_TO, 167.2f, +LINE_TO, 174.6f, 46.2f, +CUBIC_TO, 171.5f, 43.9f, 167.7f, 42.5f, 163.6f, 42.5f, +CUBIC_TO, 153.6f, 42.5f, 145.5f, 50.6f, 145.5f, 60.6f, +CUBIC_TO, 145.5f, 65.4f, 147.4f, 69.8f, 150.4f, 73, +CLOSE, +MOVE_TO, 76.2f, 34.2f, +CUBIC_TO, 76.2f, 40.61f, 71.01f, 45.8f, 64.6f, 45.8f, +CUBIC_TO, 58.19f, 45.8f, 53, 40.61f, 53, 34.2f, +CUBIC_TO, 53, 27.79f, 58.19f, 22.6f, 64.6f, 22.6f, +CUBIC_TO, 71.01f, 22.6f, 76.2f, 27.79f, 76.2f, 34.2f, +CLOSE, +MOVE_TO, 34.4f, 34.2f, +CUBIC_TO, 34.4f, 27.9f, 29.4f, 22.8f, 23.2f, 22.6f, +LINE_TO, 15.5f, 43.2f, +CUBIC_TO, 17.5f, 44.8f, 20, 45.8f, 22.8f, 45.8f, +CUBIC_TO, 29.2f, 45.8f, 34.4f, 40.6f, 34.4f, 34.2f, +CLOSE, +MOVE_TO, 218.7f, 44.2f, +CUBIC_TO, 218.7f, 51.38f, 212.88f, 57.2f, 205.7f, 57.2f, +CUBIC_TO, 198.52f, 57.2f, 192.7f, 51.38f, 192.7f, 44.2f, +CUBIC_TO, 192.7f, 37.02f, 198.52f, 31.2f, 205.7f, 31.2f, +CUBIC_TO, 212.88f, 31.2f, 218.7f, 37.02f, 218.7f, 44.2f, +CLOSE, +MOVE_TO, 239.6f, 44.2f, +CUBIC_TO, 239.6f, 51.4f, 245.4f, 57.2f, 252.6f, 57.2f, +CUBIC_TO, 254.3f, 57.2f, 255.9f, 56.9f, 257.4f, 56.3f, +LINE_TO, 254.4f, 31.3f, +CUBIC_TO, 253.8f, 31.2f, 253.2f, 31.2f, 252.5f, 31.2f, +CUBIC_TO, 245.4f, 31.1f, 239.6f, 37, 239.6f, 44.2f, +CLOSE \ No newline at end of file
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 6993b98..4595b9d 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -3485,6 +3485,15 @@ kOsCrOS, SINGLE_VALUE_TYPE( ::switches::kEnableExperimentalAccessibilityChromeVoxTutorial)}, + {"enable-experimental-accessibility-magnifier-new-focus-following", + flag_descriptions:: + kExperimentalAccessibilityMagnifierNewFocusFollowingName, + flag_descriptions:: + kExperimentalAccessibilityMagnifierNewFocusFollowingDescription, + kOsCrOS, + SINGLE_VALUE_TYPE( + ::switches:: + kEnableExperimentalAccessibilityMagnifierNewFocusFollowing)}, #endif // OS_CHROMEOS #if defined(OS_MAC) {"enable-immersive-fullscreen-toolbar",
diff --git a/chrome/browser/apps/app_service/app_service_metrics.cc b/chrome/browser/apps/app_service/app_service_metrics.cc index 9927220..c731dcff 100644 --- a/chrome/browser/apps/app_service/app_service_metrics.cc +++ b/chrome/browser/apps/app_service/app_service_metrics.cc
@@ -56,10 +56,11 @@ kYouTubeMusic = 38, // This is our test SWA. It's only installed in tests. kMockSystemApp = 39, + kStadia = 40, // Add any new values above this one, and update kMaxValue to the highest // enumerator value. - kMaxValue = kMockSystemApp, + kMaxValue = kStadia, }; void RecordDefaultAppLaunch(DefaultAppName default_app_name, @@ -249,6 +250,8 @@ #endif // OS_CHROMEOS else if (app_id == chromeos::default_web_apps::kYoutubeMusicAppId) RecordDefaultAppLaunch(DefaultAppName::kYouTubeMusic, launch_source); + else if (app_id == chromeos::default_web_apps::kStadiaAppId) + RecordDefaultAppLaunch(DefaultAppName::kStadia, launch_source); // Above are default apps; below are built-in apps.
diff --git a/chrome/browser/chromeos/child_accounts/family_user_session_metrics.cc b/chrome/browser/chromeos/child_accounts/family_user_session_metrics.cc index f393f4d..e0dafaa 100644 --- a/chrome/browser/chromeos/child_accounts/family_user_session_metrics.cc +++ b/chrome/browser/chromeos/child_accounts/family_user_session_metrics.cc
@@ -10,7 +10,6 @@ #include "base/logging.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/user_metrics.h" -#include "base/time/time.h" #include "chrome/common/pref_names.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" @@ -21,6 +20,9 @@ constexpr int kEngagementHourBuckets = base::Time::kHoursPerDay; constexpr base::TimeDelta kOneHour = base::TimeDelta::FromHours(1); +constexpr base::TimeDelta kMinSessionDuration = base::TimeDelta::FromSeconds(1); +constexpr base::TimeDelta kMaxSessionDuration = base::TimeDelta::FromDays(1); +constexpr int kSessionDurationBuckets = 100; // Returns the hour (0-23) within the day for given local time. int HourOfDay(base::Time time) { @@ -81,12 +83,14 @@ "FamilyUser.SessionEngagement.Weekend"; const char FamilyUserSessionMetrics::kSessionEngagementTotalHistogramName[] = "FamilyUser.SessionEngagement.Total"; +const char FamilyUserSessionMetrics::kSessionEngagementDurationHistogramName[] = + "FamilyUser.SessionEngagement.Duration"; // static void FamilyUserSessionMetrics::RegisterProfilePrefs( PrefRegistrySimple* registry) { - registry->RegisterTimePref( - prefs::kFamilyUserMetricsSessionEngagementStartTime, base::Time()); + registry->RegisterTimeDeltaPref( + prefs::kFamilyUserMetricsSessionEngagementDuration, base::TimeDelta()); } FamilyUserSessionMetrics::FamilyUserSessionMetrics(PrefService* pref_service) @@ -96,34 +100,57 @@ } FamilyUserSessionMetrics::~FamilyUserSessionMetrics() { - if (is_user_active_) { - is_user_active_ = false; - UpdateUserEngagement(); + // |active_session_start_| will be reset in UpdateUserEngagement() after user + // becomes inactive. |active_session_start_| equals to base::Time() indicates + // that UpdateUserEngagement(false) has already been called. + if (active_session_start_ != base::Time()) { + UpdateUserEngagement(/*is_user_active=*/false); } UsageTimeStateNotifier::GetInstance()->RemoveObserver(this); } -void FamilyUserSessionMetrics::OnUsageTimeStateChange( - UsageTimeStateNotifier::UsageTimeState state) { - is_user_active_ = state == UsageTimeStateNotifier::UsageTimeState::ACTIVE; - - UpdateUserEngagement(); +void FamilyUserSessionMetrics::OnNewDay() { + base::TimeDelta unreported_duration = pref_service_->GetTimeDelta( + prefs::kFamilyUserMetricsSessionEngagementDuration); + if (unreported_duration <= base::TimeDelta()) + return; + base::UmaHistogramCustomTimes(kSessionEngagementDurationHistogramName, + unreported_duration, kMinSessionDuration, + kMaxSessionDuration, kSessionDurationBuckets); + pref_service_->ClearPref(prefs::kFamilyUserMetricsSessionEngagementDuration); } -void FamilyUserSessionMetrics::UpdateUserEngagement() { - if (is_user_active_) { +void FamilyUserSessionMetrics::SetActiveSessionStartForTesting( + base::Time time) { + active_session_start_ = time; +} + +void FamilyUserSessionMetrics::OnUsageTimeStateChange( + UsageTimeStateNotifier::UsageTimeState state) { + UpdateUserEngagement(/*is_user_active=*/state == + UsageTimeStateNotifier::UsageTimeState::ACTIVE); +} + +void FamilyUserSessionMetrics::UpdateUserEngagement(bool is_user_active) { + base::Time now = base::Time::Now(); + if (is_user_active) { base::RecordAction( base::UserMetricsAction(kSessionEngagementStartActionName)); - pref_service_->SetTime(prefs::kFamilyUserMetricsSessionEngagementStartTime, - base::Time::Now()); + active_session_start_ = now; } else { - base::Time start = pref_service_->GetTime( - prefs::kFamilyUserMetricsSessionEngagementStartTime); - ReportUserEngagementHourToUma( - /*start=*/start, - /*end=*/base::Time::Now()); + /*start=*/active_session_start_, + /*end=*/now); + if (now > active_session_start_) { + base::TimeDelta unreported_duration = pref_service_->GetTimeDelta( + prefs::kFamilyUserMetricsSessionEngagementDuration); + pref_service_->SetTimeDelta( + prefs::kFamilyUserMetricsSessionEngagementDuration, + unreported_duration + now - active_session_start_); + } + + active_session_start_ = base::Time(); } }
diff --git a/chrome/browser/chromeos/child_accounts/family_user_session_metrics.h b/chrome/browser/chromeos/child_accounts/family_user_session_metrics.h index 2ac5361..158f1e2d 100644 --- a/chrome/browser/chromeos/child_accounts/family_user_session_metrics.h +++ b/chrome/browser/chromeos/child_accounts/family_user_session_metrics.h
@@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_FAMILY_USER_SESSION_METRICS_H_ #define CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_FAMILY_USER_SESSION_METRICS_H_ +#include "base/time/time.h" #include "chrome/browser/chromeos/child_accounts/family_user_metrics_service.h" #include "chrome/browser/chromeos/child_accounts/usage_time_state_notifier.h" @@ -21,6 +22,9 @@ // day when the user is active split by weekday/weekend and total of // weekday/weekend. Recorded when UsageTimeNotifier::UsageTimeState changes to // INACTIVE. Covers the time between ACTIVE and INACTIVE. +// - FamilyUser.SessionEngagement.Duration: Daily sum of user's active time in +// milliseconds. Recorded at the beginning of the first active session on a +// subsequent day. class FamilyUserSessionMetrics : public FamilyUserMetricsService::Observer, public UsageTimeStateNotifier::Observer { public: @@ -28,6 +32,7 @@ static const char kSessionEngagementWeekdayHistogramName[]; static const char kSessionEngagementWeekendHistogramName[]; static const char kSessionEngagementTotalHistogramName[]; + static const char kSessionEngagementDurationHistogramName[]; static void RegisterProfilePrefs(PrefRegistrySimple* registry); @@ -36,21 +41,28 @@ FamilyUserSessionMetrics& operator=(const FamilyUserSessionMetrics&) = delete; ~FamilyUserSessionMetrics() override; + // FamilyUserMetricsService::Observer: + void OnNewDay() override; + + void SetActiveSessionStartForTesting(base::Time time); + private: // UsageTimeStateNotifier::Observer: // When the user signs out, this function doesn't get called and - // |is_user_active_| doesn't change to false. Destructor will be called - // instead. + // UsageTimeStateNotifier::UsageTimeState doesn't change to inactive. + // Destructor will be called instead. void OnUsageTimeStateChange( UsageTimeStateNotifier::UsageTimeState state) override; - // Called when user engagement changes, save engagement data to pref - // or report to UMA. - void UpdateUserEngagement(); + // Called when user engagement changes.Saves engagement hour and session + // duration data to prefs or report to UMA. + void UpdateUserEngagement(bool is_user_active); PrefService* const pref_service_; - bool is_user_active_ = false; + // The time when the user becomes active. It will be reset to base::Time() + // when the user becomes inactive. + base::Time active_session_start_; }; } // namespace chromeos
diff --git a/chrome/browser/chromeos/child_accounts/family_user_session_metrics_unittest.cc b/chrome/browser/chromeos/child_accounts/family_user_session_metrics_unittest.cc index 675dae7..c275dc3d4 100644 --- a/chrome/browser/chromeos/child_accounts/family_user_session_metrics_unittest.cc +++ b/chrome/browser/chromeos/child_accounts/family_user_session_metrics_unittest.cc
@@ -6,6 +6,7 @@ #include <memory> +#include "base/logging.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/metrics/user_action_tester.h" #include "base/test/task_environment.h" @@ -23,6 +24,10 @@ namespace { +constexpr base::TimeDelta kTenMinutes = base::TimeDelta::FromMinutes(10); +constexpr base::TimeDelta kOneHour = base::TimeDelta::FromHours(1); +constexpr base::TimeDelta kOneDay = base::TimeDelta::FromDays(1); + void SetScreenOff(bool is_screen_off) { power_manager::ScreenIdleState screen_idle_state; screen_idle_state.set_off(is_screen_off); @@ -73,19 +78,22 @@ task_environment_.FastForwardBy(forward_by); } - void SetSessionEngagementStartPref(base::Time start) { - pref_service_.SetTime(prefs::kFamilyUserMetricsSessionEngagementStartTime, - start); - } - void SetSessionState(session_manager::SessionState state) { session_manager_.SetSessionState(state); } + void SetActiveSessionStartTime(base::Time time) { + family_user_session_metrics_->SetActiveSessionStartForTesting(time); + } + session_manager::SessionState GetSessionState() { return session_manager_.session_state(); } + void OnNewDay() { family_user_session_metrics_->OnNewDay(); } + + PrefService* pref_service() { return &pref_service_; } + base::test::TaskEnvironment task_environment_{ base::test::TaskEnvironment::TimeSource::MOCK_TIME}; @@ -104,67 +112,150 @@ user_action_tester.GetActionCount( FamilyUserSessionMetrics::kSessionEngagementStartActionName)); - SetupTaskRunnerWithTime("1 Jan 2020 10:00"); + SetupTaskRunnerWithTime("1 Jan 2020 23:00"); SetSessionState(session_manager::SessionState::ACTIVE); - task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(10)); - // Session locked at 10:10:00. + task_environment_.FastForwardBy(kTenMinutes); + // Session locked at 23:10:00. SetSessionState(session_manager::SessionState::LOCKED); - task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(10)); - // Session activated at 10:20:00. + task_environment_.FastForwardBy(kOneHour); + // Session activated at 00:10:00 on 2 Jan 2020. SetSessionState(session_manager::SessionState::ACTIVE); - task_environment_.FastForwardBy(base::TimeDelta::FromDays(1)); + OnNewDay(); - // Session locked at 10:20:00 on the second day. + task_environment_.FastForwardBy(kOneHour); + // Session locked at 01:10:00 on 2 Jan 2020. SetSessionState(session_manager::SessionState::LOCKED); + // Engagement start metric result: EXPECT_EQ(2, user_action_tester.GetActionCount( FamilyUserSessionMetrics::kSessionEngagementStartActionName)); - histogram_tester.ExpectBucketCount( - FamilyUserSessionMetrics::kSessionEngagementWeekdayHistogramName, 10, 3); + for (int i = 0; i <= 23; i++) { + if (i == 0 || i == 1 || i == 23) { + histogram_tester.ExpectBucketCount( + FamilyUserSessionMetrics::kSessionEngagementWeekdayHistogramName, i, + 1); + histogram_tester.ExpectBucketCount( + FamilyUserSessionMetrics::kSessionEngagementTotalHistogramName, i, 1); + } else { + histogram_tester.ExpectBucketCount( + FamilyUserSessionMetrics::kSessionEngagementWeekdayHistogramName, i, + 0); + histogram_tester.ExpectBucketCount( + FamilyUserSessionMetrics::kSessionEngagementTotalHistogramName, i, 0); + } + } histogram_tester.ExpectTotalCount( - FamilyUserSessionMetrics::kSessionEngagementWeekdayHistogramName, 26); - histogram_tester.ExpectTotalCount( - FamilyUserSessionMetrics::kSessionEngagementTotalHistogramName, 26); + FamilyUserSessionMetrics::kSessionEngagementTotalHistogramName, 3); + + // Duration metric result: + histogram_tester.ExpectUniqueTimeSample( + FamilyUserSessionMetrics::kSessionEngagementDurationHistogramName, + kTenMinutes, 1); + EXPECT_EQ(kOneHour, pref_service()->GetTimeDelta( + prefs::kFamilyUserMetricsSessionEngagementDuration)); } TEST_F(FamilyUserSessionMetricsTest, ScreenStateChange) { base::HistogramTester histogram_tester; base::UserActionTester user_action_tester; - SetupTaskRunnerWithTime("3 Jan 2020 23:00"); + SetupTaskRunnerWithTime("3 Jan 2020 23:10"); SetSessionState(session_manager::SessionState::ACTIVE); - task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(60)); + task_environment_.FastForwardBy(kOneHour); - // Test screen off at 0:00:00. + // Test screen off after midnight at 0:10:00 on 4 Jan 2020. SetScreenOff(true); - task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(10)); - // Test screen on at 0:10:00. + OnNewDay(); + + // Engagement start metric result: + EXPECT_EQ(1, + user_action_tester.GetActionCount( + FamilyUserSessionMetrics::kSessionEngagementStartActionName)); + + // Engagement Hour metric result: + histogram_tester.ExpectUniqueSample( + FamilyUserSessionMetrics::kSessionEngagementWeekdayHistogramName, 23, 1); + histogram_tester.ExpectUniqueSample( + FamilyUserSessionMetrics::kSessionEngagementWeekendHistogramName, 0, 1); + histogram_tester.ExpectTotalCount( + FamilyUserSessionMetrics::kSessionEngagementTotalHistogramName, 2); + + // Duration metric result: + histogram_tester.ExpectUniqueTimeSample( + FamilyUserSessionMetrics::kSessionEngagementDurationHistogramName, + kOneHour, 1); + EXPECT_EQ(base::TimeDelta(), + pref_service()->GetTimeDelta( + prefs::kFamilyUserMetricsSessionEngagementDuration)); + + // Test screen on on 4 Jan 2020 0:10:00. SetScreenOff(false); - task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(10)); - // Session locked at 0:20:00. - SetSessionState(session_manager::SessionState::LOCKED); + task_environment_.FastForwardBy(base::TimeDelta::FromHours(25)); + // Test screen off on 5 Jan 2020 1:10:00. + SetScreenOff(true); + OnNewDay(); + + // Engagement start metric result: EXPECT_EQ(2, user_action_tester.GetActionCount( FamilyUserSessionMetrics::kSessionEngagementStartActionName)); + // Engagement Hour metric result: histogram_tester.ExpectUniqueSample( FamilyUserSessionMetrics::kSessionEngagementWeekdayHistogramName, 23, 1); - histogram_tester.ExpectUniqueSample( - FamilyUserSessionMetrics::kSessionEngagementWeekendHistogramName, 0, 2); + for (int i = 0; i <= 23; i++) { + if (i == 0) { + histogram_tester.ExpectBucketCount( + FamilyUserSessionMetrics::kSessionEngagementWeekendHistogramName, i, + 3); + histogram_tester.ExpectBucketCount( + FamilyUserSessionMetrics::kSessionEngagementTotalHistogramName, i, 3); + } else if (i == 1) { + histogram_tester.ExpectBucketCount( + FamilyUserSessionMetrics::kSessionEngagementWeekendHistogramName, i, + 2); + histogram_tester.ExpectBucketCount( + FamilyUserSessionMetrics::kSessionEngagementTotalHistogramName, i, 2); + } else if (i == 23) { + histogram_tester.ExpectBucketCount( + FamilyUserSessionMetrics::kSessionEngagementWeekendHistogramName, i, + 1); + histogram_tester.ExpectBucketCount( + FamilyUserSessionMetrics::kSessionEngagementTotalHistogramName, i, 2); + + } else { + histogram_tester.ExpectBucketCount( + FamilyUserSessionMetrics::kSessionEngagementWeekendHistogramName, i, + 1); + } + } histogram_tester.ExpectTotalCount( - FamilyUserSessionMetrics::kSessionEngagementTotalHistogramName, 3); + FamilyUserSessionMetrics::kSessionEngagementTotalHistogramName, 28); + + // Duration metric result: + histogram_tester.ExpectTimeBucketCount( + FamilyUserSessionMetrics::kSessionEngagementDurationHistogramName, + kOneHour, 1); + histogram_tester.ExpectTimeBucketCount( + FamilyUserSessionMetrics::kSessionEngagementDurationHistogramName, + kOneDay, 1); + histogram_tester.ExpectTotalCount( + FamilyUserSessionMetrics::kSessionEngagementDurationHistogramName, 2); + EXPECT_EQ(base::TimeDelta(), + pref_service()->GetTimeDelta( + prefs::kFamilyUserMetricsSessionEngagementDuration)); } TEST_F(FamilyUserSessionMetricsTest, SuspendStateChange) { @@ -174,32 +265,41 @@ SetupTaskRunnerWithTime("4 Jan 2020 6:00"); SetSessionState(session_manager::SessionState::ACTIVE); - task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(10)); + task_environment_.FastForwardBy(kTenMinutes); // Test suspend at 6:10:00. SetSuspendImminent(); - task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(10)); + task_environment_.FastForwardBy(kTenMinutes); // Test cancel at 6:20:00. CancelSuspend(); - task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(10)); + task_environment_.FastForwardBy(kTenMinutes); // Test suspend at 6:30:00. SetSuspendImminent(); - task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(10)); + task_environment_.FastForwardBy(kTenMinutes); // Session locked at 6:40:00. SetSessionState(session_manager::SessionState::LOCKED); + // Engagement start metric result: EXPECT_EQ(2, user_action_tester.GetActionCount( FamilyUserSessionMetrics::kSessionEngagementStartActionName)); + // Engagement Hour metric result: histogram_tester.ExpectUniqueSample( FamilyUserSessionMetrics::kSessionEngagementWeekendHistogramName, 6, 2); histogram_tester.ExpectTotalCount( FamilyUserSessionMetrics::kSessionEngagementTotalHistogramName, 2); + + // Duration metric result: + histogram_tester.ExpectTotalCount( + FamilyUserSessionMetrics::kSessionEngagementDurationHistogramName, 0); + EXPECT_EQ(base::TimeDelta::FromMinutes(20), + pref_service()->GetTimeDelta( + prefs::kFamilyUserMetricsSessionEngagementDuration)); } TEST_F(FamilyUserSessionMetricsTest, ClockBackward) { @@ -215,20 +315,29 @@ // Set session start prefs to 11:00:00. Mock a state that start time > end // time. - SetSessionEngagementStartPref(mock_session_start); + SetActiveSessionStartTime(mock_session_start); // Session locked at 10:00:00. SetSessionState(session_manager::SessionState::LOCKED); + // Engagement start metric result: EXPECT_EQ(1, user_action_tester.GetActionCount( FamilyUserSessionMetrics::kSessionEngagementStartActionName)); - // Engagement hour data will be ignored if start time > end time. + // Engagement Hour metric result: + // Engagement hour and duration data will be ignored if start time > end time. histogram_tester.ExpectTotalCount( FamilyUserSessionMetrics::kSessionEngagementWeekdayHistogramName, 0); histogram_tester.ExpectTotalCount( FamilyUserSessionMetrics::kSessionEngagementTotalHistogramName, 0); + + // Duration metric result: + histogram_tester.ExpectTotalCount( + FamilyUserSessionMetrics::kSessionEngagementDurationHistogramName, 0); + EXPECT_EQ(base::TimeDelta(), + pref_service()->GetTimeDelta( + prefs::kFamilyUserMetricsSessionEngagementDuration)); } // Tests destroying FamilyUserSessionMetrics without invoking @@ -242,33 +351,52 @@ SetSessionState(session_manager::SessionState::ACTIVE); - task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(1)); + task_environment_.FastForwardBy(kTenMinutes); DestructFamilyUserSessionMetrics(); SetSessionState(session_manager::SessionState::UNKNOWN); + // Engagement start metric result: EXPECT_EQ(1, user_action_tester.GetActionCount( FamilyUserSessionMetrics::kSessionEngagementStartActionName)); + + // Engagement Hour metric result: histogram_tester.ExpectUniqueSample( FamilyUserSessionMetrics::kSessionEngagementWeekdayHistogramName, 10, 1); + // Duration metric result: + histogram_tester.ExpectTotalCount( + prefs::kFamilyUserMetricsSessionEngagementDuration, 0); + EXPECT_EQ(kTenMinutes, + pref_service()->GetTimeDelta( + prefs::kFamilyUserMetricsSessionEngagementDuration)); + // Test restart. InitiateFamilyUserSessionMetrics(); EXPECT_NE(session_manager::SessionState::ACTIVE, GetSessionState()); SetSessionState(session_manager::SessionState::ACTIVE); + // Engagement start metric result: EXPECT_EQ(2, user_action_tester.GetActionCount( FamilyUserSessionMetrics::kSessionEngagementStartActionName)); - task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(1)); + task_environment_.FastForwardBy(kTenMinutes); SetSessionState(session_manager::SessionState::LOCKED); + // Engagement Hour metric result: histogram_tester.ExpectUniqueSample( FamilyUserSessionMetrics::kSessionEngagementWeekdayHistogramName, 10, 2); histogram_tester.ExpectTotalCount( FamilyUserSessionMetrics::kSessionEngagementTotalHistogramName, 2); + + // Duration metric result: + histogram_tester.ExpectTotalCount( + prefs::kFamilyUserMetricsSessionEngagementDuration, 0); + EXPECT_EQ(base::TimeDelta::FromMinutes(20), + pref_service()->GetTimeDelta( + prefs::kFamilyUserMetricsSessionEngagementDuration)); } } // namespace chromeos
diff --git a/chrome/browser/chromeos/crostini/crostini_util.cc b/chrome/browser/chromeos/crostini/crostini_util.cc index a3d68b0..08e4c6d 100644 --- a/chrome/browser/chromeos/crostini/crostini_util.cc +++ b/chrome/browser/chromeos/crostini/crostini_util.cc
@@ -130,7 +130,7 @@ const std::string& app_id, guest_os::GuestOsRegistryService::Registration registration, int64_t display_id, - const std::vector<std::string>& files, + const std::vector<std::string>& args, crostini::CrostiniSuccessCallback callback, bool success, const std::string& failure_reason) { @@ -143,7 +143,7 @@ registration.ContainerName()); if (app_id == kCrostiniTerminalSystemAppId) { // Use first file as 'cwd'. - std::string cwd = !files.empty() ? files[0] : ""; + std::string cwd = !args.empty() ? args[0] : ""; if (!LaunchTerminal(profile, display_id, container_id, cwd)) { return OnLaunchFailed(app_id, std::move(callback), "failed to launch terminal"); @@ -152,8 +152,7 @@ crostini::CrostiniResult::SUCCESS, true, ""); } crostini::CrostiniManager::GetForProfile(profile)->LaunchContainerApplication( - container_id, registration.DesktopFileId(), files, - registration.IsScaled(), + container_id, registration.DesktopFileId(), args, registration.IsScaled(), base::BindOnce(OnApplicationLaunched, app_id, std::move(callback), crostini::CrostiniResult::UNKNOWN_ERROR)); } @@ -163,7 +162,7 @@ const std::string& app_id, guest_os::GuestOsRegistryService::Registration registration, int64_t display_id, - const std::vector<storage::FileSystemURL>& files, + const std::vector<LaunchArg>& args, crostini::CrostiniSuccessCallback callback) { ChromeLauncherController* chrome_launcher_controller = ChromeLauncherController::instance(); @@ -178,8 +177,14 @@ // Share any paths not in crostini. The user will see the spinner while this // is happening. std::vector<base::FilePath> paths_to_share; - std::vector<std::string> files_to_launch; - for (const storage::FileSystemURL& url : files) { + std::vector<std::string> launch_args; + launch_args.reserve(args.size()); + for (const auto& arg : args) { + if (absl::holds_alternative<std::string>(arg)) { + launch_args.push_back(absl::get<std::string>(arg)); + continue; + } + const storage::FileSystemURL& url = absl::get<storage::FileSystemURL>(arg); base::FilePath path; if (!file_manager::util::ConvertFileSystemURLToPathInsideCrostini( profile, url, &path)) { @@ -191,19 +196,19 @@ file_manager::util::GetCrostiniMountPointName(profile)) { paths_to_share.push_back(url.path()); } - files_to_launch.push_back(path.value()); + launch_args.push_back(path.value()); } if (paths_to_share.empty()) { OnSharePathForLaunchApplication(profile, app_id, std::move(registration), - display_id, std::move(files_to_launch), + display_id, std::move(launch_args), std::move(callback), true, ""); } else { guest_os::GuestOsSharePath::GetForProfile(profile)->SharePaths( registration.VmName(), std::move(paths_to_share), /*persist=*/false, base::BindOnce(OnSharePathForLaunchApplication, profile, app_id, std::move(registration), display_id, - std::move(files_to_launch), std::move(callback))); + std::move(launch_args), std::move(callback))); } } @@ -297,7 +302,7 @@ const std::string& app_id, guest_os::GuestOsRegistryService::Registration registration, int64_t display_id, - const std::vector<storage::FileSystemURL>& files, + const std::vector<LaunchArg>& args, CrostiniSuccessCallback callback) { auto* crostini_manager = crostini::CrostiniManager::GetForProfile(profile); auto* registry_service = @@ -311,13 +316,16 @@ // and share the path before launching terminal. bool requires_share = false; base::FilePath cwd; - if (!files.empty()) { - if (files[0].mount_filesystem_id() != + if (!args.empty() && + absl::holds_alternative<storage::FileSystemURL>(args[0])) { + const storage::FileSystemURL& url = + absl::get<storage::FileSystemURL>(args[0]); + if (url.mount_filesystem_id() != file_manager::util::GetCrostiniMountPointName(profile)) { requires_share = true; } else { - file_manager::util::ConvertFileSystemURLToPathInsideCrostini( - profile, files[0], &cwd); + file_manager::util::ConvertFileSystemURLToPathInsideCrostini(profile, + url, &cwd); } } @@ -343,8 +351,7 @@ base::BindOnce( [](Profile* profile, const std::string& app_id, guest_os::GuestOsRegistryService::Registration registration, - int64_t display_id, - const std::vector<storage::FileSystemURL> files, + int64_t display_id, const std::vector<LaunchArg> args, crostini::CrostiniSuccessCallback callback, crostini::CrostiniResult result) { if (result != crostini::CrostiniResult::SUCCESS) { @@ -361,9 +368,9 @@ } LaunchApplication(profile, app_id, std::move(registration), - display_id, files, std::move(callback)); + display_id, args, std::move(callback)); }, - profile, app_id, std::move(registration), display_id, files, + profile, app_id, std::move(registration), display_id, args, std::move(callback))); base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( @@ -374,7 +381,7 @@ void LaunchCrostiniApp(Profile* profile, const std::string& app_id, int64_t display_id, - const std::vector<storage::FileSystemURL>& files, + const std::vector<LaunchArg>& args, CrostiniSuccessCallback callback) { // Policies can change under us, and crostini may now be forbidden. if (!CrostiniFeatures::Get()->IsUIAllowed(profile)) { @@ -404,7 +411,7 @@ // Prompt for user-restart. return ShowCrostiniRecoveryView( profile, crostini::CrostiniUISurface::kAppList, app_id, display_id, - files, std::move(callback)); + args, std::move(callback)); } if (crostini_manager->GetCrostiniDialogStatus(DialogType::UPGRADER)) { @@ -416,7 +423,7 @@ return; } LaunchCrostiniAppImpl(profile, app_id, std::move(*registration), display_id, - files, std::move(callback)); + args, std::move(callback)); } std::string CryptohomeIdForProfile(Profile* profile) {
diff --git a/chrome/browser/chromeos/crostini/crostini_util.h b/chrome/browser/chromeos/crostini/crostini_util.h index 5c5a57a..2214c70 100644 --- a/chrome/browser/chromeos/crostini/crostini_util.h +++ b/chrome/browser/chromeos/crostini/crostini_util.h
@@ -16,6 +16,7 @@ #include "base/values.h" #include "chrome/browser/chromeos/crostini/crostini_simple_types.h" #include "storage/browser/file_system/file_system_url.h" +#include "third_party/abseil-cpp/absl/types/variant.h" namespace base { class FilePath; @@ -89,13 +90,15 @@ bool MaybeShowCrostiniDialogBeforeLaunch(Profile* profile, CrostiniResult result); +using LaunchArg = absl::variant<storage::FileSystemURL, std::string>; + // Launch a Crostini App with a given set of files, given as absolute paths in // the container. For apps which can only be launched with a single file, // launch multiple instances. void LaunchCrostiniApp(Profile* profile, const std::string& app_id, int64_t display_id, - const std::vector<storage::FileSystemURL>& files = {}, + const std::vector<LaunchArg>& args = {}, CrostiniSuccessCallback callback = base::DoNothing()); // Retrieves cryptohome_id from profile. @@ -172,7 +175,7 @@ CrostiniUISurface ui_surface, const std::string& app_id, int64_t display_id, - const std::vector<storage::FileSystemURL>& files, + const std::vector<LaunchArg>& args, CrostiniSuccessCallback callback); // Add a newly created LXD container to the kCrostiniContainers pref
diff --git a/chrome/browser/chromeos/extensions/default_app_order.cc b/chrome/browser/chromeos/extensions/default_app_order.cc index 03c9eaa1..42efb4db 100644 --- a/chrome/browser/chromeos/extensions/default_app_order.cc +++ b/chrome/browser/chromeos/extensions/default_app_order.cc
@@ -68,6 +68,7 @@ extension_misc::kGooglePhotosAppId, arc::kGooglePhotosAppId, arc::kGoogleDuoAppId, + default_web_apps::kStadiaAppId, app_list::kDefaultPageBreak1, // First default page break // TODO(crbug.com/976578): Remove after M78. extension_misc::kGoogleMapsAppId,
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc index a22739e3..b4cb0cd 100644 --- a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc +++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
@@ -521,6 +521,7 @@ TestCase("openQuickViewMtp"), TestCase("openQuickViewTabIndexImage"), TestCase("openQuickViewTabIndexText"), + TestCase("openQuickViewTabIndexHtml"), TestCase("openQuickViewTabIndexAudio"), TestCase("openQuickViewTabIndexVideo"), TestCase("openQuickViewTabIndexDeleteDialog"),
diff --git a/chrome/browser/chromeos/file_manager/guest_os_file_tasks.cc b/chrome/browser/chromeos/file_manager/guest_os_file_tasks.cc index 2a04a96f..95d43f9 100644 --- a/chrome/browser/chromeos/file_manager/guest_os_file_tasks.cc +++ b/chrome/browser/chromeos/file_manager/guest_os_file_tasks.cc
@@ -282,13 +282,19 @@ return; } + using LaunchArg = absl::variant<storage::FileSystemURL, std::string>; + std::vector<LaunchArg> args; + args.reserve(file_system_urls.size()); + for (const auto& url : file_system_urls) { + args.emplace_back(url); + } guest_os::GuestOsRegistryService::VmType vm_type = registration->VmType(); switch (vm_type) { case guest_os::GuestOsRegistryService::VmType:: ApplicationList_VmType_TERMINA: DCHECK(crostini::CrostiniFeatures::Get()->IsUIAllowed(profile)); crostini::LaunchCrostiniApp( - profile, task.app_id, display::kInvalidDisplayId, file_system_urls, + profile, task.app_id, display::kInvalidDisplayId, args, base::BindOnce( [](FileTaskFinishedCallback done, bool success, const std::string& failure_reason) { @@ -310,7 +316,7 @@ ApplicationList_VmType_PLUGIN_VM: DCHECK(plugin_vm::PluginVmFeatures::Get()->IsEnabled(profile)); plugin_vm::LaunchPluginVmApp( - profile, task.app_id, file_system_urls, + profile, task.app_id, args, base::BindOnce( [](FileTaskFinishedCallback done, plugin_vm::LaunchPluginVmAppResult result,
diff --git a/chrome/browser/chromeos/plugin_vm/plugin_vm_files.cc b/chrome/browser/chromeos/plugin_vm/plugin_vm_files.cc index 4902eaf..8993df0 100644 --- a/chrome/browser/chromeos/plugin_vm/plugin_vm_files.cc +++ b/chrome/browser/chromeos/plugin_vm/plugin_vm_files.cc
@@ -147,7 +147,7 @@ void LaunchPluginVmApp(Profile* profile, std::string app_id, - const std::vector<storage::FileSystemURL>& files, + const std::vector<LaunchArg>& args, LaunchPluginVmAppCallback callback) { if (!plugin_vm::PluginVmFeatures::Get()->IsEnabled(profile)) { return std::move(callback).Run(LaunchPluginVmAppResult::FAILED, @@ -164,31 +164,35 @@ // Forward slashes are converted to backslash during path conversion. base::FilePath vm_mount("//ChromeOS"); - std::vector<std::string> file_paths; - file_paths.reserve(files.size()); - for (const auto& file : files) { + std::vector<std::string> launch_args; + launch_args.reserve(args.size()); + for (const auto& arg : args) { + if (absl::holds_alternative<std::string>(arg)) { + launch_args.push_back(absl::get<std::string>(arg)); + continue; + } + const storage::FileSystemURL& url = absl::get<storage::FileSystemURL>(arg); base::FilePath file_path; // Validate paths are already shared, and convert file paths. - if (!share_path->IsPathShared(kPluginVmName, file.path()) || + if (!share_path->IsPathShared(kPluginVmName, url.path()) || !file_manager::util::ConvertFileSystemURLToPathInsideVM( - profile, file, vm_mount, &file_path)) { + profile, url, vm_mount, &file_path)) { return std::move(callback).Run( file_manager::util::GetMyFilesFolderForProfile(profile).IsParent( - file.path()) + url.path()) ? LaunchPluginVmAppResult::FAILED_DIRECTORY_NOT_SHARED : LaunchPluginVmAppResult::FAILED_FILE_ON_EXTERNAL_DRIVE, - "Only files in shared dirs are supported. Got: " + - file.DebugString()); + "Only files in shared dirs are supported. Got: " + url.DebugString()); } // Convert slashes: '/' => '\'. std::string result; base::ReplaceChars(file_path.value(), "/", "\\", &result); - file_paths.push_back(std::move(result)); + launch_args.push_back(std::move(result)); } manager->LaunchPluginVm( base::BindOnce(&LaunchPluginVmAppImpl, profile, std::move(app_id), - std::move(file_paths), std::move(callback))); + std::move(launch_args), std::move(callback))); } } // namespace plugin_vm
diff --git a/chrome/browser/chromeos/plugin_vm/plugin_vm_files.h b/chrome/browser/chromeos/plugin_vm/plugin_vm_files.h index 493dc7e1..ed4e9ea 100644 --- a/chrome/browser/chromeos/plugin_vm/plugin_vm_files.h +++ b/chrome/browser/chromeos/plugin_vm/plugin_vm_files.h
@@ -8,6 +8,7 @@ #include "base/callback.h" #include "base/files/file_path.h" #include "storage/browser/file_system/file_system_url.h" +#include "third_party/abseil-cpp/absl/types/variant.h" class Profile; @@ -27,6 +28,8 @@ FAILED_FILE_ON_EXTERNAL_DRIVE, }; +using LaunchArg = absl::variant<storage::FileSystemURL, std::string>; + using LaunchPluginVmAppCallback = base::OnceCallback<void(LaunchPluginVmAppResult result, const std::string& failure_reason)>; @@ -35,7 +38,7 @@ // the VM. Will start Plugin VM if it is not already running. void LaunchPluginVmApp(Profile* profile, std::string app_id, - const std::vector<storage::FileSystemURL>& files, + const std::vector<LaunchArg>& files, LaunchPluginVmAppCallback callback); } // namespace plugin_vm
diff --git a/chrome/browser/chromeos/plugin_vm/plugin_vm_files_unittest.cc b/chrome/browser/chromeos/plugin_vm/plugin_vm_files_unittest.cc index 3f38b3a..004896d 100644 --- a/chrome/browser/chromeos/plugin_vm/plugin_vm_files_unittest.cc +++ b/chrome/browser/chromeos/plugin_vm/plugin_vm_files_unittest.cc
@@ -122,8 +122,7 @@ LaunchPluginVmApp(&profile_, crostini::CrostiniTestHelper::GenerateAppId(app_id, vm_name, container_name), - std::vector<storage::FileSystemURL>{}, - app_launched_callback.Get()); + {}, app_launched_callback.Get()); ASSERT_FALSE(launch_plugin_vm_callback.is_null()); // Add app to app_list.
diff --git a/chrome/browser/chromeos/web_applications/DEPS b/chrome/browser/chromeos/web_applications/DEPS new file mode 100644 index 0000000..d6dded2 --- /dev/null +++ b/chrome/browser/chromeos/web_applications/DEPS
@@ -0,0 +1,5 @@ +specific_include_rules = { + "camera_app_integration_browsertest.cc": [ + "+chrome/browser/ui/views", + ], +}
diff --git a/chrome/browser/chromeos/web_applications/camera_app_integration_browsertest.cc b/chrome/browser/chromeos/web_applications/camera_app_integration_browsertest.cc new file mode 100644 index 0000000..2ac2b2b2 --- /dev/null +++ b/chrome/browser/chromeos/web_applications/camera_app_integration_browsertest.cc
@@ -0,0 +1,36 @@ +// Copyright 2020 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. + +#include "base/test/scoped_feature_list.h" +#include "chrome/browser/chromeos/web_applications/system_web_app_integration_test.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/views/frame/browser_view.h" +#include "chrome/browser/web_applications/system_web_app_manager_browsertest.h" +#include "chromeos/constants/chromeos_features.h" +#include "content/public/test/browser_test.h" + +class CameraAppIntegrationTest : public SystemWebAppIntegrationTest { + public: + CameraAppIntegrationTest() { + scoped_feature_list_.InitWithFeatures( + {chromeos::features::kCameraSystemWebApp}, {}); + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; +}; + +// TODO(crbug.com/1129340): Remove this test after CCA supports responsive UI. +// Test that the window of Camera App is not resizeable. +IN_PROC_BROWSER_TEST_P(CameraAppIntegrationTest, WindowNotResizeable) { + WaitForTestSystemAppInstall(); + Browser* browser; + LaunchApp(web_app::SystemAppType::CAMERA, &browser); + BrowserView* const browser_view = + BrowserView::GetBrowserViewForBrowser(browser); + EXPECT_FALSE(browser_view->CanResize()); +} + +INSTANTIATE_SYSTEM_WEB_APP_MANAGER_TEST_SUITE_MANIFEST_INSTALL_P( + CameraAppIntegrationTest);
diff --git a/chrome/browser/chromeos/web_applications/default_web_app_ids.h b/chrome/browser/chromeos/web_applications/default_web_app_ids.h index dc8e5dd9..4d07623 100644 --- a/chrome/browser/chromeos/web_applications/default_web_app_ids.h +++ b/chrome/browser/chromeos/web_applications/default_web_app_ids.h
@@ -58,6 +58,10 @@ // web_app::GenerateAppIdFromURL(GURL("https://music.youtube.com/?source=pwa")). constexpr char kYoutubeMusicAppId[] = "cinhimbnkkaeohfgghhklpknlkffjgod"; +// Generated as +// web_app::GenerateAppIdFromURL(GURL("https://stadia.google.com/?lfhs=2")). +constexpr char kStadiaAppId[] = "pnkcfpnngfokcnnijgkllghjlhkailce"; + } // namespace default_web_apps } // namespace chromeos
diff --git a/chrome/browser/chromeos/web_applications/help_app_integration_browsertest.cc b/chrome/browser/chromeos/web_applications/help_app_integration_browsertest.cc index e75353ce..7f5e236 100644 --- a/chrome/browser/chromeos/web_applications/help_app_integration_browsertest.cc +++ b/chrome/browser/chromeos/web_applications/help_app_integration_browsertest.cc
@@ -27,6 +27,7 @@ #include "chrome/common/pref_names.h" #include "chrome/common/url_constants.h" #include "chrome/test/base/interactive_test_utils.h" +#include "chrome/test/base/ui_test_utils.h" #include "chromeos/components/help_app_ui/url_constants.h" #include "chromeos/components/web_applications/test/sandboxed_web_ui_test_base.h" #include "chromeos/constants/chromeos_features.h" @@ -56,6 +57,10 @@ using HelpAppAllProfilesIntegrationTest = HelpAppIntegrationTest; +content::WebContents* GetActiveWebContents() { + return chrome::FindLastActive()->tab_strip_model()->GetActiveWebContents(); +} + // Waits for and expects that the correct url is opened. void WaitForAppToOpen(const GURL& expected_url) { // Start with a number of browsers (may include an incognito browser). @@ -68,10 +73,7 @@ // There should be another browser window for the newly opened app. EXPECT_EQ(num_browsers + 1, chrome::GetTotalBrowserCount()); // Help app should have opened at the expected page. - EXPECT_EQ(expected_url, chrome::FindLastActive() - ->tab_strip_model() - ->GetActiveWebContents() - ->GetVisibleURL()); + EXPECT_EQ(expected_url, GetActiveWebContents()->GetVisibleURL()); } // Test that the Help App installs and launches correctly. Runs some spot @@ -163,10 +165,7 @@ #else EXPECT_EQ(1u, chrome::GetTotalBrowserCount()); EXPECT_EQ(GURL(chrome::kChromeHelpViaKeyboardURL), - chrome::FindLastActive() - ->tab_strip_model() - ->GetActiveWebContents() - ->GetVisibleURL()); + GetActiveWebContents()->GetVisibleURL()); #endif } @@ -194,13 +193,10 @@ EXPECT_EQ(2u, chrome::GetTotalBrowserCount()); // The opened window should be showing the url with attached WebUI. - content::WebContents* web_contents = - chrome::FindLastActive()->tab_strip_model()->GetActiveWebContents(); - // The inner frame should be the pathname for the release notes pathname. EXPECT_EQ("chrome-untrusted://help-app/updates", SandboxedWebUiAppTestBase::EvalJsInAppFrame( - web_contents, "window.location.href")); + GetActiveWebContents(), "window.location.href")); #else // Nothing should happen on non-branded builds. EXPECT_EQ(1u, chrome::GetTotalBrowserCount()); @@ -328,10 +324,7 @@ // Settings should be active in a new window. EXPECT_EQ(3u, chrome::GetTotalBrowserCount()); - EXPECT_EQ(expected_url, chrome::FindLastActive() - ->tab_strip_model() - ->GetActiveWebContents() - ->GetVisibleURL()); + EXPECT_EQ(expected_url, GetActiveWebContents()->GetVisibleURL()); } // Test that the Help App opens when Gesture help requested. @@ -362,10 +355,7 @@ #if defined(OS_CHROMEOS) && BUILDFLAG(GOOGLE_CHROME_BRANDING) // Default browser tab and Help app are open. EXPECT_EQ(2u, chrome::GetTotalBrowserCount()); - EXPECT_EQ("chrome://help-app/", chrome::FindLastActive() - ->tab_strip_model() - ->GetActiveWebContents() - ->GetVisibleURL()); + EXPECT_EQ("chrome://help-app/", GetActiveWebContents()->GetVisibleURL()); // The HELP app is 18, see DefaultAppName in // src/chrome/browser/apps/app_service/app_service_metrics.cc histogram_tester.ExpectUniqueSample("Apps.DefaultAppLaunch.FromKeyboard", 18, @@ -374,10 +364,7 @@ // We just have the one browser. Navigates chrome. EXPECT_EQ(1u, chrome::GetTotalBrowserCount()); EXPECT_EQ(GURL(chrome::kChromeHelpViaKeyboardURL), - chrome::FindLastActive() - ->tab_strip_model() - ->GetActiveWebContents() - ->GetVisibleURL()); + GetActiveWebContents()->GetVisibleURL()); // The HELP app is 18, see DefaultAppName in // src/chrome/browser/apps/app_service/app_service_metrics.cc histogram_tester.ExpectUniqueSample("Apps.DefaultAppLaunch.FromKeyboard", 18, @@ -385,6 +372,25 @@ #endif } +// Test that the Help App opens in a new window if try to navigate there in a +// browser. +IN_PROC_BROWSER_TEST_P(HelpAppIntegrationTest, + HelpAppCapturesBrowserNavigation) { + WaitForTestSystemAppInstall(); + content::TestNavigationObserver navigation_observer( + GURL("chrome://help-app")); + navigation_observer.StartWatchingNewWebContents(); + ASSERT_EQ(1u, chrome::GetTotalBrowserCount()); + + // Try to navigate to the help app in the browser. + ui_test_utils::SendToOmniboxAndSubmit(browser(), "chrome://help-app"); + navigation_observer.Wait(); + + // We now have two browsers, one for the chrome window, one for the Help app. + EXPECT_EQ(2u, chrome::GetTotalBrowserCount()); + EXPECT_EQ(GURL("chrome://help-app"), GetActiveWebContents()->GetVisibleURL()); +} + INSTANTIATE_SYSTEM_WEB_APP_MANAGER_TEST_SUITE_MANIFEST_INSTALL_P( HelpAppIntegrationTest);
diff --git a/chrome/browser/extensions/api/settings_private/prefs_util.cc b/chrome/browser/extensions/api/settings_private/prefs_util.cc index e0aafd5..4d8e04a 100644 --- a/chrome/browser/extensions/api/settings_private/prefs_util.cc +++ b/chrome/browser/extensions/api/settings_private/prefs_util.cc
@@ -309,8 +309,6 @@ // Nearby Share. (*s_allowlist)[::prefs::kNearbySharingEnabledPrefName] = settings_api::PrefType::PREF_TYPE_BOOLEAN; - (*s_allowlist)[::prefs::kNearbySharingOnboardingCompletePrefName] = - settings_api::PrefType::PREF_TYPE_BOOLEAN; (*s_allowlist)[::prefs::kNearbySharingActiveProfilePrefName] = settings_api::PrefType::PREF_TYPE_BOOLEAN; (*s_allowlist)[::prefs::kNearbySharingDeviceNamePrefName] =
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 457e2d8..4446c323 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -1483,6 +1483,11 @@ "expiry_milestone": 87 }, { + "name": "enable-experimental-accessibility-magnifier-new-focus-following", + "owners": [ "josiahk", "//ui/accessibility/OWNERS" ], + "expiry_milestone": 88 + }, + { "name": "enable-experimental-accessibility-switch-access-text", "owners": [ "anastasi@google.com", "//ui/accessibility/OWNERS" ], "expiry_milestone": 90 @@ -1569,7 +1574,7 @@ { "name": "enable-generic-sensor-extra-classes", "owners": [ "reillyg@chromium.org", "raphael.kubo.da.costa@intel.com" ], - "expiry_milestone": 86 + "expiry_milestone": 90 }, { "name": "enable-google-srp-isolated-prerender-nsp", @@ -3153,7 +3158,7 @@ { "name": "new-shortcut-mapping", "owners": [ "oshima", "afakhry" ], - "expiry_milestone": 86 + "expiry_milestone": 90 }, { "name": "new-tabstrip-animation", @@ -3765,8 +3770,8 @@ }, { "name": "pull-to-refresh", - "owners": [ "afakhry" ], - "expiry_milestone": 83 + "owners": [ "afakhry", "tclaiborne" ], + "expiry_milestone": 89 }, { "name": "query-tiles",
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 06ef05b..64e9c3f 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -4033,6 +4033,12 @@ "Enable experimental feature which allows setting cursor color in " "Accessibility settings."; +const char kExperimentalAccessibilityMagnifierNewFocusFollowingName[] = + "Enable new focus following in Magnifier"; +const char kExperimentalAccessibilityMagnifierNewFocusFollowingDescription[] = + "Enable experimental feature which allows more comprehensive focus " + "following in Magnifier."; + const char kFilesAppCopyImageName[] = "Enable Copy Images from Files App"; const char kFilesAppCopyImageDescription[] = "Enables the Files App to copy images selected to the system clipboard";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 4769d119..92211ac 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -2335,6 +2335,10 @@ extern const char kExperimentalAccessibilityCursorColorsName[]; extern const char kExperimentalAccessibilityCursorColorsDescription[]; +extern const char kExperimentalAccessibilityMagnifierNewFocusFollowingName[]; +extern const char + kExperimentalAccessibilityMagnifierNewFocusFollowingDescription[]; + extern const char kFilesAppCopyImageName[]; extern const char kFilesAppCopyImageDescription[];
diff --git a/chrome/browser/media/router/providers/cast/cast_activity.h b/chrome/browser/media/router/providers/cast/cast_activity.h index 2278a2d8..a242826 100644 --- a/chrome/browser/media/router/providers/cast/cast_activity.h +++ b/chrome/browser/media/router/providers/cast/cast_activity.h
@@ -81,9 +81,6 @@ virtual void SendStopSessionMessageToClients(const std::string& hash_token); // Sends |message| to the client given by |client_id|. - // - // TODO(jrw): This method's functionality overlaps that of OnAppMessage(). - // Can the methods be combined? virtual void SendMessageToClient( const std::string& client_id, blink::mojom::PresentationConnectionMessagePtr message);
diff --git a/chrome/browser/media/router/providers/cast/mirroring_activity.cc b/chrome/browser/media/router/providers/cast/mirroring_activity.cc index 21f1bfbf..017ff960 100644 --- a/chrome/browser/media/router/providers/cast/mirroring_activity.cc +++ b/chrome/browser/media/router/providers/cast/mirroring_activity.cc
@@ -280,12 +280,7 @@ DVLOG(2) << "Relaying internal message from receiver: " << message.message; mirroring::mojom::CastMessagePtr ptr = mirroring::mojom::CastMessage::New(); ptr->message_namespace = message.message_namespace; - - // TODO(jrw): This line re-serializes a JSON string that was parsed by the - // caller of this method. Yuck! This is probably a necessary evil as long as - // the extension needs to communicate with the mirroring service. CHECK(base::JSONWriter::Write(message.message, &ptr->json_format_data)); - channel_to_service_->Send(std::move(ptr)); } @@ -308,8 +303,6 @@ const std::string message_namespace = GetMirroringNamespace(*result.value); - // TODO(jrw): Can some of this logic be shared with - // AppActivity::SendAppMessageToReceiver? cast::channel::CastMessage cast_message = cast_channel::CreateCastMessage( message_namespace, std::move(*result.value), message_handler_->sender_id(), session->transport_id());
diff --git a/chrome/browser/nearby_sharing/common/nearby_share_prefs.cc b/chrome/browser/nearby_sharing/common/nearby_share_prefs.cc index db1d842..b80ad4a 100644 --- a/chrome/browser/nearby_sharing/common/nearby_share_prefs.cc +++ b/chrome/browser/nearby_sharing/common/nearby_share_prefs.cc
@@ -26,8 +26,6 @@ const char kNearbySharingDeviceIdPrefName[] = "nearby_sharing.device_id"; const char kNearbySharingDeviceNamePrefName[] = "nearby_sharing.device_name"; const char kNearbySharingEnabledPrefName[] = "nearby_sharing.enabled"; -const char kNearbySharingOnboardingCompletePrefName[] = - "nearby_sharing.onboarding_complete"; const char kNearbySharingFullNamePrefName[] = "nearby_sharing.full_name"; const char kNearbySharingIconUrlPrefName[] = "nearby_sharing.icon_url"; const char kNearbySharingOnboardingDismissedTimePrefName[] = @@ -60,8 +58,6 @@ // available. registry->RegisterBooleanPref(prefs::kNearbySharingEnabledPrefName, /*default_value=*/true); - registry->RegisterBooleanPref(prefs::kNearbySharingOnboardingCompletePrefName, - /*default_value=*/false); registry->RegisterIntegerPref( prefs::kNearbySharingBackgroundVisibilityName, /*default_value=*/static_cast<int>(Visibility::kUnknown));
diff --git a/chrome/browser/nearby_sharing/common/nearby_share_prefs.h b/chrome/browser/nearby_sharing/common/nearby_share_prefs.h index fd95db8..62c49427 100644 --- a/chrome/browser/nearby_sharing/common/nearby_share_prefs.h +++ b/chrome/browser/nearby_sharing/common/nearby_share_prefs.h
@@ -17,7 +17,6 @@ extern const char kNearbySharingDeviceIdPrefName[]; extern const char kNearbySharingDeviceNamePrefName[]; extern const char kNearbySharingEnabledPrefName[]; -extern const char kNearbySharingOnboardingCompletePrefName[]; extern const char kNearbySharingFullNamePrefName[]; extern const char kNearbySharingIconUrlPrefName[]; extern const char kNearbySharingOnboardingDismissedTimePrefName[];
diff --git a/chrome/browser/nearby_sharing/nearby_share_settings.cc b/chrome/browser/nearby_sharing/nearby_share_settings.cc index 935ce45..c2c227d 100644 --- a/chrome/browser/nearby_sharing/nearby_share_settings.cc +++ b/chrome/browser/nearby_sharing/nearby_share_settings.cc
@@ -83,12 +83,6 @@ void NearbyShareSettings::SetEnabled(bool enabled) { pref_service_->SetBoolean(prefs::kNearbySharingEnabledPrefName, enabled); - if (enabled) { - // We rely on the the UI to enforce that if the feature was enabled for the - // first time, that onboarding was run. - pref_service_->SetBoolean(prefs::kNearbySharingOnboardingCompletePrefName, - true); - } } void NearbyShareSettings::GetDeviceName(
diff --git a/chrome/browser/resource_coordinator/tab_manager_unittest.cc b/chrome/browser/resource_coordinator/tab_manager_unittest.cc index b181c55..f45c5b1 100644 --- a/chrome/browser/resource_coordinator/tab_manager_unittest.cc +++ b/chrome/browser/resource_coordinator/tab_manager_unittest.cc
@@ -17,13 +17,8 @@ #include "base/metrics/field_trial.h" #include "base/notreached.h" #include "base/strings/string16.h" -#include "base/task/current_thread.h" #include "base/test/mock_entropy_provider.h" #include "base/test/scoped_feature_list.h" -#include "base/test/simple_test_tick_clock.h" -#include "base/test/test_mock_time_task_runner.h" -#include "base/threading/thread_task_runner_handle.h" -#include "base/time/tick_clock.h" #include "base/time/time.h" #include "build/build_config.h" #include "chrome/browser/browser_process.h" @@ -113,15 +108,10 @@ class TabManagerTest : public ChromeRenderViewHostTestHarness { public: TabManagerTest() - : scoped_context_( - std::make_unique<base::TestMockTimeTaskRunner::ScopedContext>( - task_runner_)), - scoped_set_tick_clock_for_testing_(task_runner_->GetMockTickClock()), - previous_task_runner_(base::ThreadTaskRunnerHandle::Get()) { - base::CurrentThread::Get()->SetTaskRunner(task_runner_); - + : ChromeRenderViewHostTestHarness( + base::test::TaskEnvironment::TimeSource::MOCK_TIME) { // Start with a non-zero time. - task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(42)); + task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(42)); } std::unique_ptr<WebContents> CreateWebContents() { @@ -131,9 +121,6 @@ content::WebContentsTester::For(web_contents.get()) ->NavigateAndCommit(GURL("https://www.example.com")); - base::RepeatingClosure run_loop_cb = base::BindRepeating( - &base::TestMockTimeTaskRunner::RunUntilIdle, task_runner_); - return web_contents; } @@ -171,8 +158,6 @@ void TearDown() override { ResetState(); - base::CurrentThread::Get()->SetTaskRunner(std::move(previous_task_runner_)); - scoped_context_.reset(); ChromeRenderViewHostTestHarness::TearDown(); } @@ -263,11 +248,6 @@ } TabManager* tab_manager_ = nullptr; - scoped_refptr<base::TestMockTimeTaskRunner> task_runner_ = - base::MakeRefCounted<base::TestMockTimeTaskRunner>(); - std::unique_ptr<base::TestMockTimeTaskRunner::ScopedContext> scoped_context_; - ScopedSetTickClockForTesting scoped_set_tick_clock_for_testing_; - scoped_refptr<base::SingleThreadTaskRunner> previous_task_runner_; std::unique_ptr<BackgroundTabNavigationThrottle> throttle1_; std::unique_ptr<BackgroundTabNavigationThrottle> throttle2_; std::unique_ptr<BackgroundTabNavigationThrottle> throttle3_; @@ -363,7 +343,7 @@ tab_strip2->GetWebContentsAt(1)->WasHidden(); // Advance time enough that the tabs are urgent discardable. - task_runner_->AdvanceMockTickClock(kBackgroundUrgentProtectionTime); + task_environment()->AdvanceClock(kBackgroundUrgentProtectionTime); for (int i = 0; i < 4; ++i) tab_manager_->DiscardTab(LifecycleUnitDiscardReason::URGENT); @@ -517,7 +497,7 @@ // Simulate timeout when loading the 1st tab. TabManager should start loading // the 2nd tab. - task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(10)); + task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(10)); EXPECT_TRUE(tab_manager_->IsTabLoadingForTest(contents1_.get())); EXPECT_TRUE(tab_manager_->IsTabLoadingForTest(contents2_.get())); @@ -527,7 +507,7 @@ EXPECT_TRUE(tab_manager_->IsNavigationDelayedForTest(nav_handle3_.get())); // Simulate timeout again. TabManager should start loading the 3rd tab. - task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(10)); + task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(10)); EXPECT_TRUE(tab_manager_->IsTabLoadingForTest(contents1_.get())); EXPECT_TRUE(tab_manager_->IsTabLoadingForTest(contents2_.get())); @@ -560,7 +540,7 @@ tab_manager_->background_tab_loading_mode_); // Simulate timeout when loading the 1st tab. - task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(10)); + task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(10)); // Tab 2 and 3 are still pending because of the paused loading mode. EXPECT_FALSE(tab_manager_->IsTabLoadingForTest(contents2_.get())); @@ -924,7 +904,7 @@ const int num_of_tabs_to_test = 20; for (int i = 0; i < num_of_tabs_to_test; ++i) { - task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(10)); + task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(10)); tab_strip->AppendWebContents(CreateWebContents(), /*foreground=*/true); }
diff --git a/chrome/browser/resources/chromeos/input_method/google_xkb_manifest.json b/chrome/browser/resources/chromeos/input_method/google_xkb_manifest.json index deeb9d9f..50507dbc 100644 --- a/chrome/browser/resources/chromeos/input_method/google_xkb_manifest.json +++ b/chrome/browser/resources/chromeos/input_method/google_xkb_manifest.json
@@ -144,7 +144,7 @@ "options_page": "hmm_options.html?code=xkb:us:intl:nld" }, { - "name": "__MSG_keyboard_us_international_pc__", + "name": "__MSG_keyboard_netherlands_us_international_pc__", "type": "ime", "id": "xkb:us:intl_pc:nld", "indicator": "NLD", @@ -248,7 +248,7 @@ "options_page": "hmm_options.html?code=xkb:us:workman-intl:eng" }, { - "name": "__MSG_keyboard_belgian__", + "name": "__MSG_keyboard_belgian_dutch__", "type": "ime", "id": "xkb:be::nld", "description": "", @@ -289,7 +289,7 @@ "options_page": "hmm_options.html?code=xkb:fr:bepo:fra" }, { - "name": "__MSG_keyboard_belgian__", + "name": "__MSG_keyboard_belgian_french__", "type": "ime", "id": "xkb:be::fra", "description": "", @@ -390,7 +390,7 @@ "options_page": "hmm_options.html?code=xkb:de:neo:ger" }, { - "name": "__MSG_keyboard_belgian__", + "name": "__MSG_keyboard_belgian_german__", "type": "ime", "id": "xkb:be::ger", "description": "", @@ -471,7 +471,7 @@ "options_page": "hmm_options.html?code=xkb:br::por" }, { - "name": "__MSG_keyboard_us_international__", + "name": "__MSG_keyboard_portuguese_us_international__", "type": "ime", "id": "xkb:us:intl:por", "indicator": "INTL", @@ -485,7 +485,7 @@ "options_page": "hmm_options.html?code=xkb:us:intl:por" }, { - "name": "__MSG_keyboard_us_international_pc__", + "name": "__MSG_keyboard_portuguese_us_international_pc__", "type": "ime", "id": "xkb:us:intl_pc:por", "indicator": "INTL",
diff --git a/chrome/browser/resources/settings/autofill_page/password_check.html b/chrome/browser/resources/settings/autofill_page/password_check.html index 617b9ccb..24633c8 100644 --- a/chrome/browser/resources/settings/autofill_page/password_check.html +++ b/chrome/browser/resources/settings/autofill_page/password_check.html
@@ -7,7 +7,7 @@ width: 1.6em; } - iron-icon.has-leaks { + iron-icon.has-security-issues { --iron-icon-fill-color: var(--google-red-600); background: radial-gradient(circle 1.1em at 1.1em, #FCE8E6 100%, @@ -21,7 +21,7 @@ } @media (prefers-color-scheme: dark) { - iron-icon.has-leaks { + iron-icon.has-security-issues { --iron-icon-fill-color: var(--google-red-refresh-300); background: radial-gradient(circle 1.1em at 1.1em, var(--google-grey-900) 100%, @@ -29,7 +29,7 @@ } } - iron-icon.no-leaks { + iron-icon.no-security-issues { --iron-icon-fill-color: var(--google-blue-600); background-size: 16px 16px; } @@ -38,7 +38,7 @@ display: none; } - #leakCheckHeader { + #securityCheckHeader { border-bottom: var(--cr-separator-line); } @@ -47,8 +47,9 @@ } </style> - <!-- The banner is visible if no compromised password was found (yet). --> - <template is="dom-if" if="[[shouldShowBanner_(status, leakedPasswords)]]"> + <!-- The banner is visible if no insecure password was found (yet). --> + <template is="dom-if" + if="[[shouldShowBanner_(status, leakedPasswords, weakPasswords)]]"> <picture> <source srcset="[[bannerImageSrc_(1, status)]]" media="(prefers-color-scheme: dark)"> @@ -57,11 +58,11 @@ </template> <!-- The header showing progress or result of the check--> - <div class="cr-row first two-line" id="leakCheckHeader"> + <div class="cr-row first two-line" id="securityCheckHeader"> <!-- If the password check concluded, show only a status Icon. --> <template is="dom-if" if="[[!isCheckInProgress_(status)]]"> - <iron-icon class$="[[getStatusIconClass_(status, leakedPasswords)]]" - icon="[[getStatusIcon_(status, leakedPasswords)]]"> + <iron-icon class$="[[getStatusIconClass_(status, leakedPasswords, weakPasswords)]]" + icon="[[getStatusIcon_(status, leakedPasswords, weakPasswords)]]"> </iron-icon> </template> @@ -80,8 +81,8 @@ </span> </div> <div class="secondary" id="subtitle" - hidden$="[[!showsPasswordsCount_(status, leakedPasswords)]]"> - [[compromisedPasswordsCount]] + hidden$="[[!showsPasswordsCount_(status, leakedPasswords, weakPasswords)]]"> + [[getPasswordsCount_(insecurePasswordsCount, compromisedPasswordsCount)]] </div> </div> <cr-button id="controlPasswordCheckButton"
diff --git a/chrome/browser/resources/settings/autofill_page/password_check.js b/chrome/browser/resources/settings/autofill_page/password_check.js index 890fa9d..a77d186 100644 --- a/chrome/browser/resources/settings/autofill_page/password_check.js +++ b/chrome/browser/resources/settings/autofill_page/password_check.js
@@ -275,6 +275,24 @@ }, /** + * Returns true if there are any weak credentials. + * @return {boolean} + * @private + */ + hasWeakCredentials_() { + return !!this.weakPasswords.length; + }, + + /** + * Returns true if there are any insecure credentials. + * @return {boolean} + * @private + */ + hasInsecureCredentials_() { + return !!this.leakedPasswords.length || !!this.weakPasswords.length; + }, + + /** * @param {!CustomEvent<{moreActionsButton: !HTMLElement}>} event * @private */ @@ -374,10 +392,10 @@ * @private */ getStatusIcon_() { - if (!this.hasLeaksOrErrors_()) { + if (!this.hasInsecureCredentialsOrErrors_()) { return 'settings:check-circle'; } - if (this.hasLeakedCredentials_()) { + if (this.hasInsecureCredentials_()) { return 'cr:warning'; } return 'cr:info'; @@ -389,11 +407,11 @@ * @private */ getStatusIconClass_() { - if (!this.hasLeaksOrErrors_()) { - return this.waitsForFirstCheck_() ? 'hidden' : 'no-leaks'; + if (!this.hasInsecureCredentialsOrErrors_()) { + return this.waitsForFirstCheck_() ? 'hidden' : 'no-security-issues'; } - if (this.hasLeakedCredentials_()) { - return 'has-leaks'; + if (this.hasInsecureCredentials_()) { + return 'has-security-issues'; } return ''; }, @@ -537,21 +555,21 @@ * @private */ shouldShowBanner_() { - if (this.hasLeakedCredentials_()) { + if (this.hasInsecureCredentials_()) { return false; } return this.status.state === CheckState.CANCELED || - !this.hasLeaksOrErrors_(); + !this.hasInsecureCredentialsOrErrors_(); }, /** - * Returns true if there are leaked credentials or the status is unexpected + * Returns true if there are insecure credentials or the status is unexpected * for a regular password check. * @return {boolean} * @private */ - hasLeaksOrErrors_() { - if (this.hasLeakedCredentials_()) { + hasInsecureCredentialsOrErrors_() { + if (this.hasInsecureCredentials_()) { return true; } switch (this.status.state) { @@ -571,13 +589,13 @@ }, /** - * Returns true if there are leaked credentials or the status is unexpected + * Returns true if there are insecure credentials or the status is unexpected * for a regular password check. * @return {boolean} * @private */ showsPasswordsCount_() { - if (this.hasLeakedCredentials_()) { + if (this.hasInsecureCredentials_()) { return true; } switch (this.status.state) { @@ -598,6 +616,20 @@ }, /** + * Returns count of insecure credentials, if |passwordsWeaknessCheckEnabled| + * is true, otherwise, returns count of compromised credentials. + * @return {string} + * @private + */ + getPasswordsCount_() { + if (this.passwordsWeaknessCheckEnabled) { + return this.insecurePasswordsCount; + } else { + return this.compromisedPasswordsCount; + } + }, + + /** * Returns true iff the leak check was performed at least once before. * @return {boolean} * @private
diff --git a/chrome/browser/resources/settings/autofill_page/password_check_behavior.js b/chrome/browser/resources/settings/autofill_page/password_check_behavior.js index 7229dc4c..4a596bf 100644 --- a/chrome/browser/resources/settings/autofill_page/password_check_behavior.js +++ b/chrome/browser/resources/settings/autofill_page/password_check_behavior.js
@@ -3,6 +3,7 @@ // found in the LICENSE file. import {assert} from 'chrome://resources/js/assert.m.js'; +import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; import {PluralStringProxyImpl} from 'chrome://resources/js/plural_string_proxy.js'; import {PasswordManagerImpl, PasswordManagerProxy} from './password_manager_proxy.js'; @@ -24,6 +25,11 @@ compromisedPasswordsCount: String, /** + * The number of insecure passwords as a formatted string. + */ + insecurePasswordsCount: String, + + /** * An array of leaked passwords to display. * @type {!Array<!PasswordManagerProxy.InsecureCredential>} */ @@ -33,6 +39,15 @@ }, /** + * An array of weak passwords to display. + * @type {!Array<!PasswordManagerProxy.InsecureCredential>} + */ + weakPasswords: { + type: Array, + value: () => [], + }, + + /** * The status indicates progress and affects banner, title and icon. * @type {!PasswordManagerProxy.PasswordCheckStatus} */ @@ -49,6 +64,17 @@ type: Boolean, value: true, }, + + /** + * Returns true if passwords weakness check is enabled. + * @type {boolean} + */ + passwordsWeaknessCheckEnabled: { + type: Boolean, + value() { + return loadTimeData.getBoolean('passwordsWeaknessCheck'); + } + }, }, /** @@ -57,6 +83,11 @@ leakedCredentialsListener_: null, /** + * @private {?function(!PasswordManagerProxy.InsecureCredentials):void} + */ + weakCredentialsListener_: null, + + /** * @private {?function(!PasswordManagerProxy.PasswordCheckStatus):void} */ statusChangedListener_: null, @@ -78,6 +109,25 @@ .then(count => { this.compromisedPasswordsCount = count; }); + PluralStringProxyImpl.getInstance() + .getPluralString( + 'insecurePasswords', + this.leakedPasswords.length + this.weakPasswords.length) + .then(count => { + this.insecurePasswordsCount = count; + }); + }; + + this.weakCredentialsListener_ = weakCredentials => { + this.weakPasswords = weakCredentials; + + PluralStringProxyImpl.getInstance() + .getPluralString( + 'insecurePasswords', + this.leakedPasswords.length + this.weakPasswords.length) + .then(count => { + this.insecurePasswordsCount = count; + }); }; this.passwordManager = PasswordManagerImpl.getInstance(); @@ -85,11 +135,15 @@ this.statusChangedListener_); this.passwordManager.getCompromisedCredentials().then( this.leakedCredentialsListener_); + this.passwordManager.getWeakCredentials().then( + this.weakCredentialsListener_); this.passwordManager.addPasswordCheckStatusListener( this.statusChangedListener_); this.passwordManager.addCompromisedCredentialsListener( this.leakedCredentialsListener_); + this.passwordManager.addWeakCredentialsListener( + this.weakCredentialsListener_); }, /** @override */ @@ -100,6 +154,9 @@ this.passwordManager.removeCompromisedCredentialsListener( assert(this.leakedCredentialsListener_)); this.leakedCredentialsListener_ = null; + this.passwordManager.removeWeakCredentialsListener( + assert(this.weakCredentialsListener_)); + this.weakCredentialsListener_ = null; }, /**
diff --git a/chrome/browser/resources/settings/autofill_page/password_manager_proxy.js b/chrome/browser/resources/settings/autofill_page/password_manager_proxy.js index 7abe200..5349d1a 100644 --- a/chrome/browser/resources/settings/autofill_page/password_manager_proxy.js +++ b/chrome/browser/resources/settings/autofill_page/password_manager_proxy.js
@@ -204,6 +204,12 @@ getCompromisedCredentials() {} /** + * Requests the latest information about weak credentials. + * @return {!Promise<(PasswordManagerProxy.InsecureCredentials)>} + */ + getWeakCredentials() {} + + /** * Returns the current status of the check via |callback|. * @return {!Promise<(PasswordManagerProxy.PasswordCheckStatus)>} */ @@ -230,6 +236,20 @@ removeCompromisedCredentialsListener(listener) {} /** + * Add an observer to the weak passwords change. + * @param {function(!PasswordManagerProxy.InsecureCredentials):void} + * listener + */ + addWeakCredentialsListener(listener) {} + + /** + * Remove an observer to the weak passwords change. + * @param {function(!PasswordManagerProxy.InsecureCredentials):void} + * listener + */ + removeWeakCredentialsListener(listener) {} + + /** * Add an observer to the passwords check status change. * @param {function(!PasswordManagerProxy.PasswordCheckStatus):void} listener */ @@ -529,6 +549,13 @@ } /** @override */ + getWeakCredentials() { + return new Promise(resolve => { + chrome.passwordsPrivate.getWeakCredentials(resolve); + }); + } + + /** @override */ removeInsecureCredential(insecureCredential) { chrome.passwordsPrivate.removeInsecureCredential(insecureCredential); } @@ -546,6 +573,16 @@ } /** @override */ + addWeakCredentialsListener(listener) { + chrome.passwordsPrivate.onWeakCredentialsChanged.addListener(listener); + } + + /** @override */ + removeWeakCredentialsListener(listener) { + chrome.passwordsPrivate.onWeakCredentialsChanged.removeListener(listener); + } + + /** @override */ addPasswordCheckStatusListener(listener) { chrome.passwordsPrivate.onPasswordCheckStatusChanged.addListener(listener); }
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/internet_page/BUILD.gn index 6675a10..2bb6a511 100644 --- a/chrome/browser/resources/settings/chromeos/internet_page/BUILD.gn +++ b/chrome/browser/resources/settings/chromeos/internet_page/BUILD.gn
@@ -4,6 +4,7 @@ import("//chrome/browser/resources/settings/chromeos/os_settings.gni") import("//third_party/closure_compiler/compile_js.gni") +import("//ui/webui/resources/tools/js_modulizer.gni") js_type_check("closure_compile") { deps = [ @@ -180,12 +181,12 @@ js_type_check("closure_compile_module") { is_polymer3 = true deps = [ -# ":cellular_setup_dialog.m" -# ":internet_config.m", + ":cellular_setup_dialog.m", + ":internet_config.m", # ":internet_detail_page.m", ":internet_known_networks_page.m", # ":internet_page.m", -# ":internet_page_browser_proxy.m", + ":internet_page_browser_proxy.m", ":internet_shared_css.m", # ":internet_subpage.m", # ":network_proxy_section.m", @@ -195,10 +196,30 @@ ] } +js_library("cellular_setup_dialog.m") { + sources = [ "$root_gen_dir/chrome/browser/resources/settings/chromeos/internet_page/cellular_setup_dialog.m.js" ] + deps = [ + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + "//ui/webui/resources/cr_components/chromeos/cellular_setup:cellular_setup.m", + "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog.m", + "//ui/webui/resources/js:i18n_behavior.m", + ] + extra_deps = [ ":cellular_setup_dialog_module" ] +} + js_library("internet_config.m") { sources = [ "$root_gen_dir/chrome/browser/resources/settings/chromeos/internet_page/internet_config.m.js" ] deps = [ - # TODO: Fill those in. + ":internet_shared_css.m", + "//chrome/browser/resources/settings/chromeos:metrics_recorder.m", + "//chrome/browser/resources/settings:router.m", + "//third_party/polymer/v3_0/components-chromium/iron-flex-layout:iron-flex-layout", + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + "//ui/webui/resources/cr_components/chromeos/network:network_config.m", + "//ui/webui/resources/cr_elements/cr_button:cr_button.m", + "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog.m", + "//ui/webui/resources/js:i18n_behavior.m", + "//ui/webui/resources/js:util.m", ] extra_deps = [ ":internet_config_module" ] } @@ -293,14 +314,6 @@ extra_deps = [ ":tether_connection_dialog_module" ] } -js_library("cellular_setup_dialog.m") { - sources = [ "$root_gen_dir/chrome/browser/resources/settings/chromeos/internet_page/cellular_setup_dialog.m.js" ] - deps = [ - # TODO: Fill those in. - ] - extra_deps = [ ":cellular_setup_dialog_module" ] -} - import("//tools/polymer/polymer.gni") group("polymer3_elements") { @@ -324,6 +337,8 @@ js_file = "internet_config.js" html_file = "internet_config.html" html_type = "dom-module" + auto_imports = os_settings_auto_imports + namespace_rewrites = os_settings_namespace_rewrites } polymer_modulizer("internet_detail_page") { @@ -388,8 +403,7 @@ html_type = "dom-module" } -import("//ui/webui/resources/tools/js_modulizer.gni") - js_modulizer("modulize") { input_files = [ "internet_page_browser_proxy.js" ] + namespace_rewrites = os_settings_namespace_rewrites }
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/cellular_setup_dialog.html b/chrome/browser/resources/settings/chromeos/internet_page/cellular_setup_dialog.html index f9e5c272..950461a 100644 --- a/chrome/browser/resources/settings/chromeos/internet_page/cellular_setup_dialog.html +++ b/chrome/browser/resources/settings/chromeos/internet_page/cellular_setup_dialog.html
@@ -3,6 +3,8 @@ <link rel="import" href="chrome://resources/cr_components/chromeos/cellular_setup/cellular_setup.html"> <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html"> <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html"> +<link rel="import" href="chrome://resources/html/i18n_behavior.html"> +<link rel="import" href="../../settings_shared_css.html"> <dom-module id="os-settings-cellular-setup-dialog"> <template>
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/internet_config.html b/chrome/browser/resources/settings/chromeos/internet_page/internet_config.html index a051e5b..92b37dfc 100644 --- a/chrome/browser/resources/settings/chromeos/internet_page/internet_config.html +++ b/chrome/browser/resources/settings/chromeos/internet_page/internet_config.html
@@ -4,6 +4,7 @@ <link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html"> <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html"> <link rel="import" href="chrome://resources/html/i18n_behavior.html"> +<link rel="import" href="chrome://resources/html/util.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html"> <link rel="import" href="../metrics_recorder.html"> <link rel="import" href="internet_shared_css.html">
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/internet_config.js b/chrome/browser/resources/settings/chromeos/internet_page/internet_config.js index 1cb79e3..516668bc 100644 --- a/chrome/browser/resources/settings/chromeos/internet_page/internet_config.js +++ b/chrome/browser/resources/settings/chromeos/internet_page/internet_config.js
@@ -121,7 +121,7 @@ /** @private */ onSaveTap_() { - this.$.networkConfig.save(); + /** @type {!NetworkConfigElement} */ (this.$.networkConfig).save(); settings.recordSettingChange(); },
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/internet_page_browser_proxy.js b/chrome/browser/resources/settings/chromeos/internet_page/internet_page_browser_proxy.js index 70f9670..430dd1e 100644 --- a/chrome/browser/resources/settings/chromeos/internet_page/internet_page_browser_proxy.js +++ b/chrome/browser/resources/settings/chromeos/internet_page/internet_page_browser_proxy.js
@@ -2,10 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// clang-format off +// #import {addSingletonGetter, addWebUIListener} from 'chrome://resources/js/cr.m.js'; +// clang-format on + /** @fileoverview A helper object used for Internet page. */ cr.define('settings', function() { /** @interface */ - class InternetPageBrowserProxy { + /* #export */ class InternetPageBrowserProxy { /** * Shows the Cellular activation UI. * @param {string} guid @@ -47,7 +51,7 @@ /** * @implements {settings.InternetPageBrowserProxy} */ - class InternetPageBrowserProxyImpl { + /* #export */ class InternetPageBrowserProxyImpl { /** @override */ showCellularSetupUI(guid) { chrome.send('showCellularSetupUI', [guid]);
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_page.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_page.js index 05d89d3c..f8b59e6 100644 --- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_page.js +++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_page.js
@@ -467,25 +467,12 @@ * @private */ nearbyShareClick_(event) { - const nearbyEnabled = this.getPref('nearby_sharing.enabled').value; - const onboardingComplete = - this.getPref('nearby_sharing.onboarding_complete').value; - let params = undefined; - if (!nearbyEnabled) { - if (onboardingComplete) { - - // If we have already run onboarding at least once, we don't need to do - // it again, just enabled the feature in place. - this.setPrefValue('nearby_sharing.enabled', true); - return; - } - // Otherwise we need to go into the subpage and trigger the onboarding - // dialog. - params = new URLSearchParams(); - params.set('onboarding', ''); + if (!this.getPref('nearby_sharing.enabled').value) { + this.setPrefValue('nearby_sharing.enabled', true); + } else { + // Navigate to Nearby Share subpage. + settings.Router.getInstance().navigateTo(settings.routes.NEARBY_SHARE); } - settings.Router.getInstance().navigateTo( - settings.routes.NEARBY_SHARE, params); }, /** @private */
diff --git a/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_receive_dialog.js b/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_receive_dialog.js index 32651cc5..1b36a69 100644 --- a/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_receive_dialog.js +++ b/chrome/browser/resources/settings/chromeos/nearby_share_page/nearby_share_receive_dialog.js
@@ -103,6 +103,11 @@ if (this.observerReceiver_) { this.observerReceiver_.$.close(); } + + if (this.receiveManager_) { + /** @type {nearbyShare.mojom.ReceiveManagerRemote} */ + (this.receiveManager_).$.close(); + } }, /**
diff --git a/chrome/browser/resources/settings/chromeos/os_settings.gni b/chrome/browser/resources/settings/chromeos/os_settings.gni index 76367c5..4bdddc4 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings.gni +++ b/chrome/browser/resources/settings/chromeos/os_settings.gni
@@ -32,6 +32,7 @@ "settings.FingerprintResultType|FingerprintResultType", "settings.FingerprintScan|FingerprintScan", "settings.FingerprintSetupStep|FingerprintSetupStep", + "settings.InternetPageBrowserProxy|InternetPageBrowserProxy", "settings.input_method_util.generateOptions|generateOptions", "settings.input_method_util.getFirstPartyInputMethodEngineId|getFirstPartyInputMethodEngineId", "settings.input_method_util.getOptionLabelName|getOptionLabelName", @@ -130,6 +131,7 @@ "ui/webui/resources/html/cr.html|sendWithPromise,removeWebUIListener,addWebUIListener,WebUIListener", "ui/webui/resources/html/icon.html|getImage", "ui/webui/resources/html/polymer.html|afterNextRender,Polymer,html,flush", + "ui/webui/resources/html/util.html|HTMLEscape", "chrome/browser/resources/settings/chromeos/os_printing_page/cups_printers_browser_proxy.html|CupsPrintersBrowserProxy,CupsPrintersBrowserProxyImpl,CupsPrinterInfo,PrinterSetupResult,CupsPrintersList,PrinterPpdMakeModel,ManufacturersInfo,ModelsInfo,PrintServerResult,PrinterMakeModel", "chrome/browser/resources/settings/chromeos/os_printing_page/cups_printers_entry_list_behavior.html|CupsPrintersEntryListBehavior", "chrome/browser/resources/settings/chromeos/os_printing_page/cups_printers_entry_manager.html|CupsPrintersEntryManager",
diff --git a/chrome/browser/resources/settings/chromeos/os_settings.js b/chrome/browser/resources/settings/chromeos/os_settings.js index db885698..1eb19a8 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings.js +++ b/chrome/browser/resources/settings/chromeos/os_settings.js
@@ -7,6 +7,8 @@ import './bluetooth_page/bluetooth_page.m.js'; import './bluetooth_page/bluetooth_subpage.m.js'; import './bluetooth_page/bluetooth_device_list_item.m.js'; +import './internet_page/cellular_setup_dialog.m.js'; +import './internet_page/internet_config.m.js'; import './internet_page/internet_known_networks_page.m.js'; import './nearby_share_page/nearby_share_receive_dialog.m.js'; import './nearby_share_page/nearby_share_subpage.m.js'; @@ -37,6 +39,7 @@ export {AmbientModeBrowserProxyImpl} from './ambient_mode_page/ambient_mode_browser_proxy.m.js'; export {AmbientModeTemperatureUnit, AmbientModeTopicSource} from './ambient_mode_page/constants.m.js'; export {bluetoothApis} from './bluetooth_page/bluetooth_page.m.js'; +export {InternetPageBrowserProxy, InternetPageBrowserProxyImpl} from './internet_page/internet_page_browser_proxy.m.js'; export {MultiDeviceBrowserProxy, MultiDeviceBrowserProxyImpl} from './multidevice_page/multidevice_browser_proxy.m.js'; export {MultiDeviceFeature, MultiDeviceFeatureState, MultiDevicePageContentData, MultiDeviceSettingsMode, SmartLockSignInEnabledState} from './multidevice_page/multidevice_constants.m.js'; export {Account, NearbyAccountManagerBrowserProxy, NearbyAccountManagerBrowserProxyImpl} from './nearby_share_page/nearby_account_manager_browser_proxy.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_resources_v3.grdp b/chrome/browser/resources/settings/chromeos/os_settings_resources_v3.grdp index e5709e59..e795836 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings_resources_v3.grdp +++ b/chrome/browser/resources/settings/chromeos/os_settings_resources_v3.grdp
@@ -30,11 +30,26 @@ use_base_dir="false" compress="false" type="BINDATA" /> + <include name="IDR_OS_SETTINGS_CELLULAR_SETUP_DIALOG_M_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/internet_page/cellular_setup_dialog.m.js" + use_base_dir="false" + compress="false" + type="BINDATA" /> + <include name="IDR_OS_SETTINGS_INTERNET_CONFIG_M_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/internet_page/internet_config.m.js" + use_base_dir="false" + compress="false" + type="BINDATA" /> <include name="IDR_OS_SETTINGS_INTERNET_KNOWN_NETWORKS_PAGE_M_JS" file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/internet_page/internet_known_networks_page.m.js" use_base_dir="false" compress="false" type="BINDATA" /> + <include name="IDR_OS_SETTINGS_INTERNET_PAGE_BROWSER_PROXY_M_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/internet_page/internet_page_browser_proxy.m.js" + use_base_dir="false" + compress="false" + type="BINDATA" /> <include name="IDR_OS_SETTINGS_INTERNET_SHARED_CSS_M_JS" file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/internet_page/internet_shared_css.m.js" use_base_dir="false"
diff --git a/chrome/browser/resources/settings/icons.html b/chrome/browser/resources/settings/icons.html index 02cf6bdd..6e5af49 100644 --- a/chrome/browser/resources/settings/icons.html +++ b/chrome/browser/resources/settings/icons.html
@@ -94,6 +94,7 @@ <g id="palette"><path d="M12 3c-4.97 0-9 4.03-9 9s4.03 9 9 9c.83 0 1.5-.67 1.5-1.5 0-.39-.15-.74-.39-1.01-.23-.26-.38-.61-.38-.99 0-.83.67-1.5 1.5-1.5H16c2.76 0 5-2.24 5-5 0-4.42-4.03-8-9-8zm-5.5 9c-.83 0-1.5-.67-1.5-1.5S5.67 9 6.5 9 8 9.67 8 10.5 7.33 12 6.5 12zm3-4C8.67 8 8 7.33 8 6.5S8.67 5 9.5 5s1.5.67 1.5 1.5S10.33 8 9.5 8zm5 0c-.83 0-1.5-.67-1.5-1.5S13.67 5 14.5 5s1.5.67 1.5 1.5S15.33 8 14.5 8zm3 4c-.83 0-1.5-.67-1.5-1.5S16.67 9 17.5 9s1.5.67 1.5 1.5-.67 1.5-1.5 1.5z"></path></g> <g id="payment-handler"><path d="M20 4H4c-1.11 0-1.99.89-1.99 2L2 18c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V6c0-1.11-.89-2-2-2zm0 14H4v-6h16v6zm0-10H4V6h16v2z"></path></g> <g id="insecure-content"><path d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"></path></g> + <g id="person"><path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"></path></g> <g id="photo"><path d="M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z"></path></g> <g id="power-settings-new"><path d="M13 3h-2v10h2V3zm4.83 2.17l-1.42 1.42C17.99 7.86 19 9.81 19 12c0 3.87-3.13 7-7 7s-7-3.13-7-7c0-2.19 1.01-4.14 2.58-5.42L6.17 5.17C4.23 6.82 3 9.26 3 12c0 4.97 4.03 9 9 9s9-4.03 9-9c0-2.74-1.23-5.18-3.17-6.83z"></path></g> <g id="protocol-handler"><path d="M21.72 11.33l-6.644-7.035a.97.97 0 0 0-1.38-.01l-1.67 1.72-1.617-1.712a.97.97 0 0 0-1.38-.01l-6.737 6.935c-.187.191-.29.447-.292.719-.002.272.099.529.28.722l6.644 7.034a.949.949 0 0 0 1.38.011l1.671-1.718 1.615 1.71a.949.949 0 0 0 1.381.01l6.74-6.935a1.054 1.054 0 0 0 .01-1.44zM6.947 12.464l3.657 3.785-.974.98-5.273-5.456 5.349-5.378.929.962-3.677 3.7a.998.998 0 0 0-.292.702 1 1 0 0 0 .28.705zm7.35 4.768l-.931-.963 3.68-3.7a1.012 1.012 0 0 0 .007-1.407l-3.656-3.784.974-.98 5.273 5.456-5.348 5.378z"></path></g> @@ -113,7 +114,6 @@ <g id="web"><path d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-5 14H4v-4h11v4zm0-5H4V9h11v4zm5 5h-4V9h4v9z"></path></g> </if> <g id="window-placement"><path d="M21 1H8c-1.1 0-2 .9-2 2v6H3c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h13c1.1 0 2-.9 2-2v-6h3c1.1 0 2-.9 2-2V3c0-1.1-.9-2-2-2zm-5 20H3v-8h13v8zm5-8h-3v-2c0-1.1-.9-2-2-2H8V5h13v8z"></path></g> - <g id="idle-detection"><path d="M21,10.12h-6.78l2.74-2.82c-2.73-2.7-7.15-2.8-9.88-0.1c-2.73,2.71-2.73,7.08,0,9.79s7.15,2.71,9.88,0 C18.32,15.65,19,14.08,19,12.1h2c0,1.98-0.88,4.55-2.64,6.29c-3.51,3.48-9.21,3.48-12.72,0c-3.5-3.47-3.53-9.11-0.02-12.58 s9.14-3.47,12.65,0L21,3V10.12z M12.5,8v4.25l3.5,2.08l-0.72,1.21L11,13V8H12.5z"></path></g> <g id="zoom-in"><path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"></path></g> <g id="font-access"><path d="M0 0h24v24H0V0z" fill="none"></path><path d="M20 2H4c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm0 18H4V4h16v16zM10.69 6h2.6l4.51 12h-2.5l-1.01-2.87H9.7L8.7 18H6.2l4.49-12zm2.87 7.06l-1.06-3.02-.43-1.44h-.13l-.44 1.44-1.07 3.02h3.13z"></path></g> </defs>
diff --git a/chrome/browser/resources/settings/site_settings/site_details.html b/chrome/browser/resources/settings/site_settings/site_details.html index 85817fb..161b726b 100644 --- a/chrome/browser/resources/settings/site_settings/site_details.html +++ b/chrome/browser/resources/settings/site_settings/site_details.html
@@ -232,7 +232,7 @@ </site-details-permission> <site-details-permission category="[[ContentSettingsTypes.IDLE_DETECTION]]" - icon="settings:idle-detection" + icon="settings:person" label="$i18n{siteSettingsIdleDetection}"> </site-details-permission> <template is="dom-if" if="[[enableExperimentalWebPlatformFeatures_]]">
diff --git a/chrome/browser/resources/settings/site_settings_page/site_settings_page.js b/chrome/browser/resources/settings/site_settings_page/site_settings_page.js index a25b71c..cbbddf3 100644 --- a/chrome/browser/resources/settings/site_settings_page/site_settings_page.js +++ b/chrome/browser/resources/settings/site_settings_page/site_settings_page.js
@@ -143,7 +143,7 @@ route: routes.SITE_SETTINGS_IDLE_DETECTION, id: Id.IDLE_DETECTION, label: 'siteSettingsIdleDetection', - icon: 'settings:idle-detection', + icon: 'settings:person', enabledLabel: 'siteSettingsIdleDetectionAsk', disabledLabel: 'siteSettingsIdleDetectionBlock', },
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index e4023dc..4cea73d 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -1735,6 +1735,8 @@ "app_list/search/files/drive_zero_state_provider.h", "app_list/search/files/file_result.cc", "app_list/search/files/file_result.h", + "app_list/search/files/item_suggest_cache.cc", + "app_list/search/files/item_suggest_cache.h", "app_list/search/launcher_search/launcher_search_icon_image_loader.cc", "app_list/search/launcher_search/launcher_search_icon_image_loader.h", "app_list/search/launcher_search/launcher_search_icon_image_loader_impl.cc",
diff --git a/chrome/browser/ui/app_list/search/files/drive_zero_state_provider.cc b/chrome/browser/ui/app_list/search/files/drive_zero_state_provider.cc index a85dd90..dd68e98 100644 --- a/chrome/browser/ui/app_list/search/files/drive_zero_state_provider.cc +++ b/chrome/browser/ui/app_list/search/files/drive_zero_state_provider.cc
@@ -20,6 +20,7 @@ #include "chrome/browser/ui/app_list/search/drive_quick_access_chip_result.h" #include "chrome/browser/ui/app_list/search/drive_quick_access_result.h" #include "chrome/browser/ui/app_list/search/search_controller.h" +#include "content/public/browser/browser_context.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" @@ -27,10 +28,12 @@ DriveZeroStateProvider::DriveZeroStateProvider( Profile* profile, - SearchController* search_controller) + SearchController* search_controller, + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) : profile_(profile), drive_service_( drive::DriveIntegrationServiceFactory::GetForProfile(profile)), + item_suggest_cache_(profile, std::move(url_loader_factory)), suggested_files_enabled_(app_list_features::IsSuggestedFilesEnabled()) { DCHECK(profile_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -66,7 +69,7 @@ void DriveZeroStateProvider::AppListShown() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - + item_suggest_cache_.UpdateCache(); // TODO(crbug.com/1034842): Query ItemSuggest, consider rate-limiting. }
diff --git a/chrome/browser/ui/app_list/search/files/drive_zero_state_provider.h b/chrome/browser/ui/app_list/search/files/drive_zero_state_provider.h index 56437a9..8260cd5 100644 --- a/chrome/browser/ui/app_list/search/files/drive_zero_state_provider.h +++ b/chrome/browser/ui/app_list/search/files/drive_zero_state_provider.h
@@ -15,6 +15,7 @@ #include "base/time/time.h" #include "chrome/browser/chromeos/drive/drive_integration_service.h" #include "chrome/browser/chromeos/file_manager/file_tasks_notifier.h" +#include "chrome/browser/ui/app_list/search/files/item_suggest_cache.h" #include "chrome/browser/ui/app_list/search/search_provider.h" class Profile; @@ -26,7 +27,10 @@ class DriveZeroStateProvider : public SearchProvider, public drive::DriveIntegrationServiceObserver { public: - DriveZeroStateProvider(Profile* profile, SearchController* search_controller); + DriveZeroStateProvider( + Profile* profile, + SearchController* search_controller, + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory); ~DriveZeroStateProvider() override; DriveZeroStateProvider(const DriveZeroStateProvider&) = delete; @@ -44,6 +48,8 @@ Profile* const profile_; drive::DriveIntegrationService* const drive_service_; + ItemSuggestCache item_suggest_cache_; + // Whether the suggested files experiment is enabled. const bool suggested_files_enabled_; @@ -54,13 +60,7 @@ SEQUENCE_CHECKER(sequence_checker_); scoped_refptr<base::SequencedTaskRunner> task_runner_; - // Factory for general use. - base::WeakPtrFactory<DriveZeroStateProvider> weak_ptr_factory_{this}; - // Factory only for weak pointers for ItemSuggest API calls. Using two - // factories allows in-flight API calls to be cancelled independently of other - // tasks by invalidating only this factory's weak pointers. - base::WeakPtrFactory<DriveZeroStateProvider> item_suggest_weak_ptr_factory_{ - this}; + base::WeakPtrFactory<DriveZeroStateProvider> weak_factory_{this}; }; } // namespace app_list
diff --git a/chrome/browser/ui/app_list/search/files/item_suggest_cache.cc b/chrome/browser/ui/app_list/search/files/item_suggest_cache.cc new file mode 100644 index 0000000..0ed559d --- /dev/null +++ b/chrome/browser/ui/app_list/search/files/item_suggest_cache.cc
@@ -0,0 +1,251 @@ +// Copyright 2020 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. + +#include "chrome/browser/ui/app_list/search/files/item_suggest_cache.h" + +#include "base/bind.h" +#include "base/metrics/histogram_macros.h" +#include "base/strings/strcat.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/signin/identity_manager_factory.h" +#include "components/google/core/common/google_util.h" +#include "components/signin/public/identity_manager/access_token_info.h" +#include "components/signin/public/identity_manager/account_info.h" +#include "components/signin/public/identity_manager/consent_level.h" +#include "components/signin/public/identity_manager/identity_manager.h" +#include "components/signin/public/identity_manager/scope_set.h" +#include "net/base/load_flags.h" +#include "net/base/net_errors.h" +#include "net/http/http_request_headers.h" +#include "net/http/http_status_code.h" +#include "net/traffic_annotation/network_traffic_annotation.h" +#include "services/network/public/cpp/resource_request.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" +#include "services/network/public/cpp/simple_url_loader.h" +#include "url/gurl.h" + +namespace app_list { +namespace { + +// Maximum accepted size of an ItemSuggest response. 10 KB. +constexpr int kMaxResponseSize = 10 * 1024; + +// TODO(crbug.com/1034842): Investigate: +// - enterprise policies that should limit this traffic. +// - settings that should disable drive results. +constexpr net::NetworkTrafficAnnotationTag kTrafficAnnotation = + net::DefineNetworkTrafficAnnotation("launcher_item_suggest", R"( + semantics { + sender: "Launcher suggested drive files" + description: + "The Chrome OS launcher requests suggestions for Drive files from " + "the Drive ItemSuggest API. These are displayed in the launcher." + trigger: + "Once on login after Drive FS is mounted. Afterwards, whenever the " + "Chrome OS launcher is opened." + data: + "OAuth2 access token." + destination: GOOGLE_OWNED_SERVICE + } + policy { + cookies_allowed: NO + setting: + "This cannot be disabled." + })"); + +// The scope required for an access token in order to query ItemSuggest. +constexpr char kDriveScope[] = "https://www.googleapis.com/auth/drive.readonly"; + +// TODO(crbug.com/1034842): Check this is correct. Also consider: +// - controlling at least the scenario type by experiment param. +// - whether we can filter the response to certain fields +constexpr char kRequestBody[] = R"({ + 'max_suggestions': 5, + 'client_info': { + 'platform_type': 'CHROMEOS', + 'application_type': 'GOOGLE_DRIVE', + 'scenario_type': 'QUICK_ACCESS' + }})"; + +//---------------- +// Error utilities +//---------------- + +// Possible error states of the item suggest cache. These values persist to +// logs. Entries should not be renumbered and numeric values should never be +// reused. +enum class Error { + kDisabled = 1, + kInvalidServerUrl = 2, + kNoIdentityManager = 3, + kGoogleAuthError = 4, + kNetError = 5, + k3xxError = 6, + k4xxError = 7, + k5xxError = 8, + kEmptyResponse = 9, + kNoResultsInResponse = 10, + kJsonParseFailure = 11, + kJsonConversionFailure = 12, + kMaxValue = kJsonConversionFailure, +}; + +void LogError(Error error) { + // TODO(crbug.com/1034842): Implement. +} + +void LogResponseSize(const int size) { + // TODO(crbug.com/1034842): Implement. +} + +} // namespace + +// static +const base::Feature ItemSuggestCache::kExperiment{ + "LauncherItemSuggest", base::FEATURE_DISABLED_BY_DEFAULT}; +constexpr base::FeatureParam<bool> ItemSuggestCache::kEnabled; +constexpr base::FeatureParam<std::string> ItemSuggestCache::kServerUrl; + +ItemSuggestCache::ItemSuggestCache( + Profile* profile, + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) + : enabled_(kEnabled.Get()), + server_url_(kServerUrl.Get()), + profile_(profile), + url_loader_factory_(std::move(url_loader_factory)) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); +} + +ItemSuggestCache::~ItemSuggestCache() = default; + +void ItemSuggestCache::UpdateCache() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + // TODO(crbug.com/1034842): Add rate-limiting for cache updates. + + // Make no requests and exit in four cases: + // - item suggest has been disabled via experiment + // - the server url is not https + // - the server url is not trusted by Google + // - another request is in-flight (url_loader_ is non-null) + if (url_loader_) { + return; + } else if (!enabled_) { + LogError(Error::kDisabled); + return; + } else if (!server_url_.SchemeIs(url::kHttpsScheme) || + !google_util::IsGoogleAssociatedDomainUrl(server_url_)) { + LogError(Error::kInvalidServerUrl); + return; + } + + signin::IdentityManager* identity_manager = + IdentityManagerFactory::GetForProfile(profile_); + if (!identity_manager) { + LogError(Error::kNoIdentityManager); + return; + } + + signin::ScopeSet scopes({kDriveScope}); + + // Fetch an OAuth2 access token. + token_fetcher_ = std::make_unique<signin::PrimaryAccountAccessTokenFetcher>( + "launcher_item_suggest", identity_manager, scopes, + base::BindOnce(&ItemSuggestCache::OnTokenReceived, + weak_factory_.GetWeakPtr()), + signin::PrimaryAccountAccessTokenFetcher::Mode::kImmediate, + signin::ConsentLevel::kSync); +} + +void ItemSuggestCache::OnTokenReceived(GoogleServiceAuthError error, + signin::AccessTokenInfo token_info) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + token_fetcher_.reset(); + + if (error.state() != GoogleServiceAuthError::NONE) { + LogError(Error::kGoogleAuthError); + return; + } + + // Make a new request. + url_loader_ = MakeRequestLoader(token_info.token); + url_loader_->SetRetryOptions(0, network::SimpleURLLoader::RETRY_NEVER); + url_loader_->AttachStringForUpload(kRequestBody, "application/json"); + + // Perform the request. + url_loader_->DownloadToString( + url_loader_factory_.get(), + base::BindOnce(&ItemSuggestCache::OnSuggestionsReceived, + weak_factory_.GetWeakPtr()), + kMaxResponseSize); +} + +void ItemSuggestCache::OnSuggestionsReceived( + const std::unique_ptr<std::string> json_response) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + const int net_error = url_loader_->NetError(); + if (net_error != net::OK) { + if (!url_loader_->ResponseInfo() || !url_loader_->ResponseInfo()->headers) { + LogError(Error::kNetError); + } else { + const int status = url_loader_->ResponseInfo()->headers->response_code(); + if (status >= 500) { + LogError(Error::k5xxError); + } else if (status >= 400) { + LogError(Error::k4xxError); + } else if (status >= 300) { + LogError(Error::k3xxError); + } + } + + return; + } else if (!json_response || json_response->empty()) { + LogError(Error::kEmptyResponse); + return; + } + + LogResponseSize(json_response->size()); + + // Parse the JSON response from ItemSuggest. + data_decoder::DataDecoder::ParseJsonIsolated( + *json_response, base::BindOnce(&ItemSuggestCache::OnJsonParsed, + weak_factory_.GetWeakPtr())); +} + +void ItemSuggestCache::OnJsonParsed( + data_decoder::DataDecoder::ValueOrError result) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + if (!result.value) { + LogError(Error::kJsonParseFailure); + return; + } + + // TODO(crbug.com/1034842): Convert json to result objects. +} + +std::unique_ptr<network::SimpleURLLoader> ItemSuggestCache::MakeRequestLoader( + const std::string& token) { + auto resource_request = std::make_unique<network::ResourceRequest>(); + + resource_request->method = "POST"; + resource_request->url = server_url_; + // Do not allow cookies. + resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit; + // Ignore the cache because we always want fresh results. + resource_request->load_flags = + net::LOAD_BYPASS_CACHE | net::LOAD_DISABLE_CACHE; + + DCHECK(resource_request->url.is_valid()); + + resource_request->headers.SetHeader(net::HttpRequestHeaders::kContentType, + "application/json"); + resource_request->headers.SetHeader(net::HttpRequestHeaders::kAuthorization, + "Bearer " + token); + + return network::SimpleURLLoader::Create(std::move(resource_request), + kTrafficAnnotation); +} + +} // namespace app_list
diff --git a/chrome/browser/ui/app_list/search/files/item_suggest_cache.h b/chrome/browser/ui/app_list/search/files/item_suggest_cache.h new file mode 100644 index 0000000..56f48703 --- /dev/null +++ b/chrome/browser/ui/app_list/search/files/item_suggest_cache.h
@@ -0,0 +1,73 @@ +// Copyright 2020 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. + +#ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_ITEM_SUGGEST_CACHE_H_ +#define CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_ITEM_SUGGEST_CACHE_H_ + +#include "base/feature_list.h" +#include "base/macros.h" +#include "base/memory/scoped_refptr.h" +#include "base/memory/weak_ptr.h" +#include "base/metrics/field_trial_params.h" +#include "base/sequence_checker.h" +#include "components/signin/public/identity_manager/primary_account_access_token_fetcher.h" +#include "google_apis/gaia/google_service_auth_error.h" +#include "services/data_decoder/public/cpp/data_decoder.h" + +class Profile; + +namespace network { +class SharedURLLoaderFactory; +class SimpleURLLoader; +} // namespace network + +namespace app_list { + +class ItemSuggestCache { + public: + ItemSuggestCache( + Profile* profile, + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory); + ~ItemSuggestCache(); + + ItemSuggestCache(const ItemSuggestCache&) = delete; + ItemSuggestCache& operator=(const ItemSuggestCache&) = delete; + + void UpdateCache(); + + // Whether or not to override configuration of the cache with an experiment. + static const base::Feature kExperiment; + + private: + // Whether or not the ItemSuggestCache is enabled. + static constexpr base::FeatureParam<bool> kEnabled{&kExperiment, "enabled", + true}; + // The url of the service that fetches descriptions given image pixels. + static constexpr base::FeatureParam<std::string> kServerUrl{ + &kExperiment, "server_url", + "https://appsitemsuggest-pa.googleapis.com/v1/items"}; + + void OnTokenReceived(GoogleServiceAuthError error, + signin::AccessTokenInfo token_info); + void OnSuggestionsReceived(const std::unique_ptr<std::string> json_response); + void OnJsonParsed(data_decoder::DataDecoder::ValueOrError result); + std::unique_ptr<network::SimpleURLLoader> MakeRequestLoader( + const std::string& token); + + const bool enabled_; + const GURL server_url_; + + Profile* profile_; + std::unique_ptr<signin::PrimaryAccountAccessTokenFetcher> token_fetcher_; + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_; + std::unique_ptr<network::SimpleURLLoader> url_loader_; + + SEQUENCE_CHECKER(sequence_checker_); + + base::WeakPtrFactory<ItemSuggestCache> weak_factory_{this}; +}; + +} // namespace app_list + +#endif // CHROME_BROWSER_UI_APP_LIST_SEARCH_FILES_ITEM_SUGGEST_CACHE_H_
diff --git a/chrome/browser/ui/app_list/search/search_controller_factory.cc b/chrome/browser/ui/app_list/search/search_controller_factory.cc index 635c4e5..dffb677 100644 --- a/chrome/browser/ui/app_list/search/search_controller_factory.cc +++ b/chrome/browser/ui/app_list/search/search_controller_factory.cc
@@ -25,6 +25,7 @@ #include "chrome/browser/ui/app_list/search/assistant_search_provider.h" #include "chrome/browser/ui/app_list/search/assistant_text_search_provider.h" #include "chrome/browser/ui/app_list/search/drive_quick_access_provider.h" +#include "chrome/browser/ui/app_list/search/files/drive_zero_state_provider.h" #include "chrome/browser/ui/app_list/search/launcher_search/launcher_search_provider.h" #include "chrome/browser/ui/app_list/search/mixer.h" #include "chrome/browser/ui/app_list/search/omnibox_provider.h" @@ -36,6 +37,8 @@ #include "chrome/common/chrome_switches.h" #include "chromeos/services/assistant/public/cpp/features.h" #include "components/arc/arc_util.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/storage_partition.h" namespace app_list { @@ -83,6 +86,13 @@ // TODO(wutao): Need UX spec. constexpr size_t kMaxSettingsShortcutResults = 6; +// A flag to easily replace the old Drive zero-state provider with the new one +// during development. +// +// TODO(crbug.com/1034842): Once implementation is finished, remove this flag +// and always use the new provider. +constexpr bool kUseNewDriveProvider = false; + } // namespace std::unique_ptr<SearchController> CreateSearchController( @@ -195,9 +205,19 @@ std::make_unique<ZeroStateFileProvider>(profile)); size_t drive_quick_access_group_id = controller->AddGroup(kMaxDriveQuickAccessResults); - controller->AddProvider( - drive_quick_access_group_id, - std::make_unique<DriveQuickAccessProvider>(profile, controller.get())); + + if (kUseNewDriveProvider) { + controller->AddProvider( + drive_quick_access_group_id, + std::make_unique<DriveZeroStateProvider>( + profile, controller.get(), + content::BrowserContext::GetDefaultStoragePartition(profile) + ->GetURLLoaderFactoryForBrowserProcess())); + } else { + controller->AddProvider(drive_quick_access_group_id, + std::make_unique<DriveQuickAccessProvider>( + profile, controller.get())); + } } if (app_list_features::IsLauncherSettingsSearchEnabled()) {
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc index 2d26d60..604d77d0 100644 --- a/chrome/browser/ui/browser.cc +++ b/chrome/browser/ui/browser.cc
@@ -359,7 +359,10 @@ Browser::CreateParams::CreateParams(Type type, Profile* profile, bool user_gesture) - : type(type), profile(profile), user_gesture(user_gesture) {} + : type(type), + profile(profile), + user_gesture(user_gesture), + can_resize(!chrome::IsRunningInForcedAppMode()) {} Browser::CreateParams::CreateParams(const CreateParams& other) = default;
diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h index 7c4a3b8..f53d9be0 100644 --- a/chrome/browser/ui/browser.h +++ b/chrome/browser/ui/browser.h
@@ -234,6 +234,9 @@ // programmatically created. bool user_gesture; + // True if the app is resizeable. + bool can_resize; + // Whether this browser was created specifically for dragged tab(s). bool in_tab_dragging = false; @@ -645,6 +648,9 @@ type_ == TYPE_APP_POPUP; } + // True if the browser is resizeable. + bool can_resize() const { return create_params_.can_resize; } + // True when the mouse cursor is locked. bool IsMouseLocked() const;
diff --git a/chrome/browser/ui/extensions/application_launch.cc b/chrome/browser/ui/extensions/application_launch.cc index 8b6223a..0ac6f37 100644 --- a/chrome/browser/ui/extensions/application_launch.cc +++ b/chrome/browser/ui/extensions/application_launch.cc
@@ -403,7 +403,8 @@ Browser* CreateApplicationWindow(Profile* profile, const apps::AppLaunchParams& params, - const GURL& url) { + const GURL& url, + bool can_resize) { const Extension* const extension = GetExtension(profile, params); std::string app_name; @@ -442,6 +443,7 @@ browser_params.initial_show_state = DetermineWindowShowState(profile, params.container, extension); + browser_params.can_resize = can_resize; return new Browser(browser_params); }
diff --git a/chrome/browser/ui/extensions/application_launch.h b/chrome/browser/ui/extensions/application_launch.h index 52b87f5..7fe45f04 100644 --- a/chrome/browser/ui/extensions/application_launch.h +++ b/chrome/browser/ui/extensions/application_launch.h
@@ -38,7 +38,8 @@ // delaying activating and showing it. Browser* CreateApplicationWindow(Profile* profile, const apps::AppLaunchParams& params, - const GURL& url); + const GURL& url, + bool can_resize = true); // Navigate application window to application url, but do not show it yet. content::WebContents* NavigateApplicationWindow(
diff --git a/chrome/browser/ui/views/crostini/crostini_recovery_view.cc b/chrome/browser/ui/views/crostini/crostini_recovery_view.cc index 1475a10..7eede3f 100644 --- a/chrome/browser/ui/views/crostini/crostini_recovery_view.cc +++ b/chrome/browser/ui/views/crostini/crostini_recovery_view.cc
@@ -36,27 +36,26 @@ crostini::CrostiniUISurface ui_surface, const std::string& app_id, int64_t display_id, - const std::vector<storage::FileSystemURL>& files, + const std::vector<crostini::LaunchArg>& args, crostini::CrostiniSuccessCallback callback) { - CrostiniRecoveryView::Show(profile, app_id, display_id, files, + CrostiniRecoveryView::Show(profile, app_id, display_id, args, std::move(callback)); base::UmaHistogramEnumeration(kCrostiniRecoverySourceHistogram, ui_surface, crostini::CrostiniUISurface::kCount); } -void CrostiniRecoveryView::Show( - Profile* profile, - const std::string& app_id, - int64_t display_id, - const std::vector<storage::FileSystemURL>& files, - crostini::CrostiniSuccessCallback callback) { +void CrostiniRecoveryView::Show(Profile* profile, + const std::string& app_id, + int64_t display_id, + const std::vector<crostini::LaunchArg>& args, + crostini::CrostiniSuccessCallback callback) { DCHECK(crostini::CrostiniFeatures::Get()->IsUIAllowed(profile)); // Any new apps launched during recovery are immediately cancelled. if (g_crostini_recovery_view) { std::move(callback).Run(false, "recovery in progress"); } else { g_crostini_recovery_view = new CrostiniRecoveryView( - profile, app_id, display_id, files, std::move(callback)); + profile, app_id, display_id, args, std::move(callback)); CreateDialogWidget(g_crostini_recovery_view, nullptr, nullptr); } // Always call Show to bring the dialog to the front of the screen. @@ -88,7 +87,7 @@ } base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(&crostini::LaunchCrostiniApp, profile_, app_id_, - display_id_, files_, std::move(callback_))); + display_id_, args_, std::move(callback_))); GetWidget()->CloseWithReason( views::Widget::ClosedReason::kAcceptButtonClicked); } @@ -110,12 +109,12 @@ Profile* profile, const std::string& app_id, int64_t display_id, - const std::vector<storage::FileSystemURL>& files, + const std::vector<crostini::LaunchArg>& args, crostini::CrostiniSuccessCallback callback) : profile_(profile), app_id_(app_id), display_id_(display_id), - files_(files), + args_(args), callback_(std::move(callback)), weak_ptr_factory_(this) { SetButtons(ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL);
diff --git a/chrome/browser/ui/views/crostini/crostini_recovery_view.h b/chrome/browser/ui/views/crostini/crostini_recovery_view.h index ef45537..4b4daf4 100644 --- a/chrome/browser/ui/views/crostini/crostini_recovery_view.h +++ b/chrome/browser/ui/views/crostini/crostini_recovery_view.h
@@ -6,6 +6,7 @@ #define CHROME_BROWSER_UI_VIEWS_CROSTINI_CROSTINI_RECOVERY_VIEW_H_ #include "chrome/browser/chromeos/crostini/crostini_simple_types.h" +#include "chrome/browser/chromeos/crostini/crostini_util.h" #include "storage/browser/file_system/file_system_url.h" #include "ui/views/bubble/bubble_dialog_delegate_view.h" @@ -22,7 +23,7 @@ static void Show(Profile* profile, const std::string& app_id, int64_t display_id, - const std::vector<storage::FileSystemURL>& files, + const std::vector<crostini::LaunchArg>& args, crostini::CrostiniSuccessCallback callback); // views::DialogDelegateView: @@ -36,7 +37,7 @@ CrostiniRecoveryView(Profile* profile, const std::string& app_id, int64_t display_id, - const std::vector<storage::FileSystemURL>& files, + const std::vector<crostini::LaunchArg>& args, crostini::CrostiniSuccessCallback callback); ~CrostiniRecoveryView() override; @@ -45,7 +46,7 @@ Profile* profile_; // Not owned. std::string app_id_; int64_t display_id_; - const std::vector<storage::FileSystemURL> files_; + const std::vector<crostini::LaunchArg> args_; crostini::CrostiniSuccessCallback callback_; base::WeakPtrFactory<CrostiniRecoveryView> weak_ptr_factory_;
diff --git a/chrome/browser/ui/views/eye_dropper/eye_dropper_view.cc b/chrome/browser/ui/views/eye_dropper/eye_dropper_view.cc index 90d9949..7103b05 100644 --- a/chrome/browser/ui/views/eye_dropper/eye_dropper_view.cc +++ b/chrome/browser/ui/views/eye_dropper/eye_dropper_view.cc
@@ -186,10 +186,17 @@ flags); } - // Paint central pixel in red. + // Paint central pixel. gfx::RectF pixel((size().width() - kPixelSize) / 2, (size().height() - kPixelSize) / 2, kPixelSize, kPixelSize); - flags.setColor(SK_ColorRED); + flags.setAntiAlias(true); + flags.setColor(SK_ColorWHITE); + flags.setStrokeWidth(2); + pixel.Inset(-0.5f, -0.5f); + view_canvas->DrawRect(pixel, flags); + flags.setColor(SK_ColorBLACK); + flags.setStrokeWidth(1); + pixel.Inset(0.5f, 0.5f); view_canvas->DrawRect(pixel, flags); // Paint outline.
diff --git a/chrome/browser/ui/views/eye_dropper/eye_dropper_view_mac.mm b/chrome/browser/ui/views/eye_dropper/eye_dropper_view_mac.mm index fa6e562..e3c30d6b 100644 --- a/chrome/browser/ui/views/eye_dropper/eye_dropper_view_mac.mm +++ b/chrome/browser/ui/views/eye_dropper/eye_dropper_view_mac.mm
@@ -94,11 +94,11 @@ } gfx::Size EyeDropperView::GetSize() const { - return gfx::Size(70, 70); + return gfx::Size(90, 90); } float EyeDropperView::GetDiameter() const { - return 70; + return 90; } std::unique_ptr<content::EyeDropper> ShowEyeDropper(
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc index 071a287..750861e 100644 --- a/chrome/browser/ui/views/frame/browser_view.cc +++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -516,6 +516,7 @@ : views::ClientView(nullptr, nullptr), browser_(std::move(browser)) { SetShowIcon(::ShouldShowWindowIcon(browser_.get())); SetHasWindowSizeControls(!chrome::IsRunningInForcedAppMode()); + SetCanResize(browser_->can_resize()); browser_->tab_strip_model()->AddObserver(this); immersive_mode_controller_ = chrome::CreateImmersiveModeController(); @@ -698,19 +699,6 @@ return IsTabStripVisible() ? tabstrip_->GetPreferredSize().height() : 0; } -TabSearchButton* BrowserView::GetTabSearchButton() { - if (!base::FeatureList::IsEnabled(features::kTabSearch)) - return nullptr; - - // If kTabSearchFixedEntrypoint is enabled then the tab search button is - // defined in the tab strip region view. - // TODO(tluk): Consolidate these once Tab Scrolling successfully moves the - // tab controls container to the tab strip region view. - return base::FeatureList::IsEnabled(features::kTabSearchFixedEntrypoint) - ? tab_strip_region_view_->tab_search_button() - : tabstrip_->tab_search_button(); -} - bool BrowserView::IsTabStripVisible() const { // Return false if this window does not normally display a tabstrip. if (!browser_->SupportsWindowFeature(Browser::FEATURE_TABSTRIP)) @@ -2623,8 +2611,13 @@ return; #endif // BUILDFLAG(ENABLE_WEBUI_TAB_STRIP) - DCHECK(GetTabSearchButton()); - if (GetTabSearchButton()->ShowTabSearchBubble()) { + // If kTabSearchFixedEntrypoint is enabled then the tab search button is + // defined in the tab strip region view. + // TODO(tluk): Consolidate these once Tab Scrolling successfully moves the + // tab controls container to the tab strip region view. + if ((base::FeatureList::IsEnabled(features::kTabSearchFixedEntrypoint) && + tab_strip_region_view_->tab_search_button()->ShowTabSearchBubble()) || + tabstrip_->tab_search_button()->ShowTabSearchBubble()) { // Only log the open action if it resulted in creating a new instance of the // Tab Search bubble. base::UmaHistogramEnumeration("Tabs.TabSearch.OpenAction",
diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h index eb4256ff..58daed3 100644 --- a/chrome/browser/ui/views/frame/browser_view.h +++ b/chrome/browser/ui/views/frame/browser_view.h
@@ -66,7 +66,6 @@ class InfoBarContainerView; class LocationBarView; class StatusBubbleViews; -class TabSearchButton; class TabStrip; class TabStripRegionView; class ToolbarButtonProvider; @@ -220,9 +219,6 @@ // Accessor for the contents WebView. views::WebView* contents_web_view() { return contents_web_view_; } - // Accessor for the BrowserView's TabSearchButton instance. - TabSearchButton* GetTabSearchButton(); - // Returns true if various window components are visible. bool IsTabStripVisible() const;
diff --git a/chrome/browser/ui/views/intent_picker_bubble_view.h b/chrome/browser/ui/views/intent_picker_bubble_view.h index 5f387868c..eb5c90f0 100644 --- a/chrome/browser/ui/views/intent_picker_bubble_view.h +++ b/chrome/browser/ui/views/intent_picker_bubble_view.h
@@ -115,6 +115,14 @@ FRIEND_TEST_ALL_PREFIXES(IntentPickerBubbleViewTest, ButtonLabels); FRIEND_TEST_ALL_PREFIXES(IntentPickerBubbleViewBrowserTestChromeOS, BubblePopOut); + FRIEND_TEST_ALL_PREFIXES(IntentPickerBubbleViewBrowserTestChromeOS, + OutOfScopeDoesNotShowBubble); + FRIEND_TEST_ALL_PREFIXES(IntentPickerBubbleViewBrowserTestChromeOS, + PWAOnlyDoesNotShowBubble); + FRIEND_TEST_ALL_PREFIXES(IntentPickerBubbleViewBrowserTestChromeOS, + NotLinkDoesNotShowBubble); + FRIEND_TEST_ALL_PREFIXES(IntentPickerBubbleViewBrowserTestChromeOS, + DismissBubble); static std::unique_ptr<IntentPickerBubbleView> CreateBubbleViewForTesting( views::View* anchor_view,
diff --git a/chrome/browser/ui/views/intent_picker_bubble_view_browsertest_chromeos.cc b/chrome/browser/ui/views/intent_picker_bubble_view_browsertest_chromeos.cc index 77dae26..e5b906f2 100644 --- a/chrome/browser/ui/views/intent_picker_bubble_view_browsertest_chromeos.cc +++ b/chrome/browser/ui/views/intent_picker_bubble_view_browsertest_chromeos.cc
@@ -63,11 +63,16 @@ apps::AppServiceTest& app_service_test() { return app_service_test_; } + IntentPickerBubbleView* intent_picker_bubble() { + return IntentPickerBubbleView::intent_picker_bubble(); + } + private: apps::AppServiceProxy* app_service_proxy_ = nullptr; apps::AppServiceTest app_service_test_; }; +// Test that the intent picker bubble will pop out for ARC apps. IN_PROC_BROWSER_TEST_F(IntentPickerBubbleViewBrowserTestChromeOS, BubblePopOut) { GURL test_url("https://www.google.com/"); @@ -87,12 +92,128 @@ ui_test_utils::NavigateToURL(¶ms); app_service_test().WaitForAppService(); EXPECT_TRUE(intent_picker_view->GetVisible()); - EXPECT_TRUE(IntentPickerBubbleView::intent_picker_bubble_); - EXPECT_EQ(1U, - IntentPickerBubbleView::intent_picker_bubble_->GetScrollViewSize()); - auto& app_info = - IntentPickerBubbleView::intent_picker_bubble_->app_info_for_testing(); + EXPECT_TRUE(intent_picker_bubble()); + EXPECT_TRUE(intent_picker_bubble()->GetVisible()); + EXPECT_EQ(1U, intent_picker_bubble()->GetScrollViewSize()); + auto& app_info = intent_picker_bubble()->app_info_for_testing(); ASSERT_EQ(1U, app_info.size()); EXPECT_EQ(kAppId1, app_info[0].launch_name); EXPECT_EQ(app_name, app_info[0].display_name); } + +// Test that navigate outside url scope will not show the intent picker icon or +// bubble. +IN_PROC_BROWSER_TEST_F(IntentPickerBubbleViewBrowserTestChromeOS, + OutOfScopeDoesNotShowBubble) { + GURL test_url("https://www.google.com/"); + GURL out_of_scope_url("https://www.example.com/"); + std::string app_name = "test_name"; + AddFakeAppWithIntentFilter(kAppId1, app_name, test_url, + apps::mojom::AppType::kArc); + PageActionIconView* intent_picker_view = GetIntentPickerIcon(); + + chrome::NewTab(browser()); + ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL)); + + // Navigate from a link. + NavigateParams params(browser(), out_of_scope_url, + ui::PageTransition::PAGE_TRANSITION_LINK); + + // Navigates and waits for loading to finish. + ui_test_utils::NavigateToURL(¶ms); + app_service_test().WaitForAppService(); + EXPECT_FALSE(intent_picker_view->GetVisible()); + EXPECT_FALSE(intent_picker_bubble()); +} + +// Test that intent picker bubble will not pop up for only PWA apps. +IN_PROC_BROWSER_TEST_F(IntentPickerBubbleViewBrowserTestChromeOS, + PWAOnlyDoesNotShowBubble) { + GURL test_url("https://www.google.com/"); + std::string app_name = "test_name"; + AddFakeAppWithIntentFilter(kAppId1, app_name, test_url, + apps::mojom::AppType::kWeb); + PageActionIconView* intent_picker_view = GetIntentPickerIcon(); + + chrome::NewTab(browser()); + ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL)); + + // Navigate from a link. + NavigateParams params(browser(), test_url, + ui::PageTransition::PAGE_TRANSITION_LINK); + + // Navigates and waits for loading to finish. + ui_test_utils::NavigateToURL(¶ms); + app_service_test().WaitForAppService(); + EXPECT_TRUE(intent_picker_view->GetVisible()); + EXPECT_FALSE(intent_picker_bubble()); +} + +// Test that intent picker bubble will not pop up for non-link navigation. +IN_PROC_BROWSER_TEST_F(IntentPickerBubbleViewBrowserTestChromeOS, + NotLinkDoesNotShowBubble) { + GURL test_url("https://www.google.com/"); + std::string app_name = "test_name"; + AddFakeAppWithIntentFilter(kAppId1, app_name, test_url, + apps::mojom::AppType::kArc); + PageActionIconView* intent_picker_view = GetIntentPickerIcon(); + + chrome::NewTab(browser()); + ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL)); + + // Navigate from a link. + NavigateParams params(browser(), test_url, + ui::PageTransition::PAGE_TRANSITION_FROM_ADDRESS_BAR); + + // Navigates and waits for loading to finish. + ui_test_utils::NavigateToURL(¶ms); + app_service_test().WaitForAppService(); + EXPECT_TRUE(intent_picker_view->GetVisible()); + EXPECT_FALSE(intent_picker_bubble()); +} + +// Test that dismiss the bubble for 2 times for the same origin will not show +// the bubble again. Test that the intent picker bubble will pop out for ARC +// apps. +IN_PROC_BROWSER_TEST_F(IntentPickerBubbleViewBrowserTestChromeOS, + DismissBubble) { + GURL test_url("https://www.google.com/"); + std::string app_name = "test_name"; + AddFakeAppWithIntentFilter(kAppId1, app_name, test_url, + apps::mojom::AppType::kArc); + PageActionIconView* intent_picker_view = GetIntentPickerIcon(); + + chrome::NewTab(browser()); + ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL)); + + // Navigate from a link. + NavigateParams params(browser(), test_url, + ui::PageTransition::PAGE_TRANSITION_LINK); + + // Navigates and waits for loading to finish. + ui_test_utils::NavigateToURL(¶ms); + app_service_test().WaitForAppService(); + EXPECT_TRUE(intent_picker_view->GetVisible()); + EXPECT_TRUE(intent_picker_bubble()); + EXPECT_TRUE(intent_picker_bubble()->GetVisible()); + EXPECT_EQ(1U, intent_picker_bubble()->GetScrollViewSize()); + auto& app_info = intent_picker_bubble()->app_info_for_testing(); + ASSERT_EQ(1U, app_info.size()); + EXPECT_EQ(kAppId1, app_info[0].launch_name); + EXPECT_EQ(app_name, app_info[0].display_name); + EXPECT_TRUE(intent_picker_bubble()->Close()); + + ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL)); + ui_test_utils::NavigateToURL(¶ms); + app_service_test().WaitForAppService(); + EXPECT_TRUE(intent_picker_view->GetVisible()); + EXPECT_TRUE(intent_picker_bubble()); + EXPECT_TRUE(intent_picker_bubble()->GetVisible()); + EXPECT_TRUE(intent_picker_bubble()->Close()); + + ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL)); + ui_test_utils::NavigateToURL(¶ms); + app_service_test().WaitForAppService(); + EXPECT_TRUE(intent_picker_view->GetVisible()); + EXPECT_FALSE(intent_picker_bubble()); +}
diff --git a/chrome/browser/ui/views/profiles/incognito_menu_view.cc b/chrome/browser/ui/views/profiles/incognito_menu_view.cc index 764e259..8e64be0e 100644 --- a/chrome/browser/ui/views/profiles/incognito_menu_view.cc +++ b/chrome/browser/ui/views/profiles/incognito_menu_view.cc
@@ -52,7 +52,10 @@ int incognito_window_count = BrowserList::GetOffTheRecordBrowsersActiveForProfile( browser()->profile()); - + // TODO(crbug.com/1105763): Add asset colors to native theme and update icon + // temporary color placeholder to align with the design deck colors. + ui::ThemedVectorIcon header_art_icon(&kIncognitoMenuArtIcon, + ui::NativeTheme::kColorId_MenuIconColor); SetProfileIdentityInfo( /*profile_name=*/base::string16(), /*background_color=*/SK_ColorTRANSPARENT, @@ -63,7 +66,8 @@ incognito_window_count > 1 ? l10n_util::GetPluralStringFUTF16(IDS_INCOGNITO_WINDOW_COUNT_MESSAGE, incognito_window_count) - : base::string16()); + : base::string16(), + header_art_icon); #if defined(OS_WIN) if (ProfileShortcutManager::IsFeatureEnabled() &&
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view.cc b/chrome/browser/ui/views/profiles/profile_menu_view.cc index c6a4375..f93e7d6 100644 --- a/chrome/browser/ui/views/profiles/profile_menu_view.cc +++ b/chrome/browser/ui/views/profiles/profile_menu_view.cc
@@ -491,11 +491,16 @@ guest_window_count); } + // TODO(crbug.com/1105763): Add asset colors to native theme and update icon + // temporary color placeholder to align with the design deck colors. + ui::ThemedVectorIcon header_art_icon(&kGuestMenuArtIcon, + ui::NativeTheme::kColorId_MenuIconColor); SetProfileIdentityInfo( /*profile_name=*/base::string16(), /*background_color=*/SK_ColorTRANSPARENT, /*edit_button=*/base::nullopt, profiles::GetGuestAvatar(), - l10n_util::GetStringUTF16(IDS_GUEST_PROFILE_NAME), subtitle); + l10n_util::GetStringUTF16(IDS_GUEST_PROFILE_NAME), subtitle, + header_art_icon); } void ProfileMenuView::BuildAutofillButtons() {
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view_base.cc b/chrome/browser/ui/views/profiles/profile_menu_view_base.cc index 5332d75..bac3c57 100644 --- a/chrome/browser/ui/views/profiles/profile_menu_view_base.cc +++ b/chrome/browser/ui/views/profiles/profile_menu_view_base.cc
@@ -61,6 +61,9 @@ constexpr int kDefaultMargin = 8; constexpr int kBadgeSize = 16; constexpr int kCircularImageButtonSize = 28; +// TODO(crbug.com/1128499): Remove this constant by extracting art height from +// |avatar_header_art|. +constexpr int kHeaderArtHeight = 72; constexpr int kIdentityImageBorder = 2; constexpr int kIdentityImageSizeInclBorder = ProfileMenuViewBase::kIdentityImageSize + 2 * kIdentityImageBorder; @@ -360,7 +363,8 @@ base::Optional<SkColor> background_color, int corner_radius, std::unique_ptr<views::View> avatar_image_view, - std::unique_ptr<views::View> edit_button) { + std::unique_ptr<views::View> edit_button, + const ui::ThemedVectorIcon& avatar_header_art) { constexpr int kExtraMarginInsideProfileBackground = 2; views::View* profile_background_container = @@ -389,8 +393,23 @@ views::CreateBackgroundFromPainter( views::Painter::CreateSolidRoundRectPainter( background_color.value(), corner_radius, background_insets))); + } else { + profile_background_container->SetBackground( + views::CreateThemedVectorIconBackground(profile_background_container, + avatar_header_art)); } + // |avatar_margin| is derived from |avatar_header_art| asset height, it + // increases margin for the avatar icon to make |avatar_header_art| visible + // above the center of the avatar icon. + // Subtracting |kIdentityImageBorder| from the height as it isn't part of the + // actual image and shouldn't affect the margin. + const int avatar_margin = + avatar_header_art.empty() + ? kDefaultMargin + : kHeaderArtHeight - kIdentityImageBorder - + ProfileMenuViewBase::kIdentityImageSize / 2; + // The |heading_and_image_container| is on the left and it stretches almost // the full width. It contains the profile heading and the avatar image. views::View* heading_and_image_container = @@ -406,12 +425,14 @@ ->SetOrientation(views::LayoutOrientation::kVertical) .SetMainAxisAlignment(views::LayoutAlignment::kCenter) .SetCrossAxisAlignment(views::LayoutAlignment::kCenter) - .SetInteriorMargin(gfx::Insets(/*top=*/kDefaultMargin, 0, 0, 0)); + .SetInteriorMargin(gfx::Insets(/*top=*/avatar_margin, 0, 0, 0)); if (heading_label) { + DCHECK(avatar_header_art.empty()); heading_label->SetBorder( views::CreateEmptyBorder(gfx::Insets(/*vertical=*/kDefaultMargin, 0))); heading_and_image_container->AddChildView(std::move(heading_label)); } + heading_and_image_container->AddChildView(std::move(avatar_image_view)); // The |edit_button| is on the right and has fixed width. @@ -520,7 +541,8 @@ base::Optional<EditButtonParams> edit_button_params, const ui::ImageModel& image_model, const base::string16& title, - const base::string16& subtitle) { + const base::string16& subtitle, + const ui::ThemedVectorIcon& avatar_header_art) { constexpr int kBottomMargin = kDefaultMargin; const bool new_design = base::FeatureList::IsEnabled(features::kNewProfilePicker); @@ -603,7 +625,7 @@ /*parent=*/identity_info_container_, std::move(heading_label), background_color, GetCornerRadius(), // Use the same radius as the bubble has. - std::move(avatar_image_view), std::move(edit_button)); + std::move(avatar_image_view), std::move(edit_button), avatar_header_art); BuildProfileTitleAndSubtitle(/*parent=*/identity_info_container_, title, subtitle); }
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view_base.h b/chrome/browser/ui/views/profiles/profile_menu_view_base.h index e4cf118..c1492c4 100644 --- a/chrome/browser/ui/views/profiles/profile_menu_view_base.h +++ b/chrome/browser/ui/views/profiles/profile_menu_view_base.h
@@ -128,7 +128,8 @@ base::Optional<EditButtonParams> edit_button_params, const ui::ImageModel& image_model, const base::string16& title, - const base::string16& subtitle = base::string16()); + const base::string16& subtitle = base::string16(), + const ui::ThemedVectorIcon& avatar_header_art = ui::ThemedVectorIcon()); void SetSyncInfo(const SyncInfo& sync_info, const base::RepeatingClosure& action, bool show_badge);
diff --git a/chrome/browser/ui/views/sharesheet/sharesheet_bubble_view.cc b/chrome/browser/ui/views/sharesheet/sharesheet_bubble_view.cc index 98e8d5b..b9b6d6a3 100644 --- a/chrome/browser/ui/views/sharesheet/sharesheet_bubble_view.cc +++ b/chrome/browser/ui/views/sharesheet/sharesheet_bubble_view.cc
@@ -189,10 +189,9 @@ kExpandViewPadding); expanded_layout->StartRow(views::GridLayout::kFixedSize, COLUMN_SET_ID_TITLE, kExpandViewTitleLabelHeight); - // TODO(crbug.com/1130409) Add translation for this string. auto* app_list_label = expanded_layout->AddView(std::make_unique<views::Label>( - base::UTF8ToUTF16(base::StringPiece("Apps list")))); + l10n_util::GetStringUTF16(IDS_SHARESHEET_APPS_LIST_LABEL))); app_list_label->SetFontList(gfx::FontList(kExpandViewTitleFont)); app_list_label->SetLineHeight(kExpandViewTitleLabelHeight); app_list_label->SetEnabledColor(kShareTargetTitleColor); @@ -247,7 +246,7 @@ auto target_view = std::make_unique<SharesheetTargetButton>( this, target.display_name, secondary_display_name, &target.icon); - target_view->set_tag(++target_counter); + target_view->set_tag(target_counter++); layout_for_target->AddView(std::move(target_view)); }
diff --git a/chrome/browser/ui/views/sharesheet/sharesheet_expand_button.cc b/chrome/browser/ui/views/sharesheet/sharesheet_expand_button.cc index f6fdc9ef..d7bf31a 100644 --- a/chrome/browser/ui/views/sharesheet/sharesheet_expand_button.cc +++ b/chrome/browser/ui/views/sharesheet/sharesheet_expand_button.cc
@@ -5,7 +5,9 @@ #include "chrome/browser/ui/views/sharesheet/sharesheet_expand_button.h" #include "chrome/app/vector_icons/vector_icons.h" +#include "chrome/grit/generated_resources.h" #include "third_party/skia/include/core/SkColor.h" +#include "ui/base/l10n/l10n_util.h" #include "ui/gfx/font_list.h" #include "ui/gfx/paint_vector_icon.h" #include "ui/views/layout/box_layout.h" @@ -45,14 +47,13 @@ void SharesheetExpandButton::SetDefaultView() { icon_->SetImage( gfx::CreateVectorIcon(kCaretDownIcon, kCaretIconSize, kLabelColor)); - // TODO(crbug.com/1130409) Add translation for this and below strings. - label_->SetText(base::UTF8ToUTF16(base::StringPiece("More apps"))); + label_->SetText(l10n_util::GetStringUTF16(IDS_SHARESHEET_MORE_APPS_LABEL)); } void SharesheetExpandButton::SetExpandedView() { icon_->SetImage( gfx::CreateVectorIcon(kCaretUpIcon, kCaretIconSize, kLabelColor)); - label_->SetText(base::UTF8ToUTF16(base::StringPiece("Fewer apps"))); + label_->SetText(l10n_util::GetStringUTF16(IDS_SHARESHEET_FEWER_APPS_LABEL)); } gfx::Size SharesheetExpandButton::CalculatePreferredSize() const {
diff --git a/chrome/browser/ui/views/tabs/tab_search_button_browsertest.cc b/chrome/browser/ui/views/tabs/tab_search_button_browsertest.cc deleted file mode 100644 index a7fe2cba4..0000000 --- a/chrome/browser/ui/views/tabs/tab_search_button_browsertest.cc +++ /dev/null
@@ -1,110 +0,0 @@ -// Copyright 2020 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. - -#include "chrome/browser/ui/views/tabs/tab_search_button.h" - -#include <vector> - -#include "base/feature_list.h" -#include "base/test/scoped_feature_list.h" -#include "build/build_config.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/ui_features.h" -#include "chrome/browser/ui/views/frame/browser_view.h" -#include "chrome/browser/ui/views/tabs/tab_search_button.h" -#include "chrome/test/base/in_process_browser_test.h" -#include "content/public/test/browser_test.h" -#include "ui/base/accelerators/accelerator.h" - -namespace { -ui::MouseEvent GetDummyEvent() { - return ui::MouseEvent(ui::ET_MOUSE_PRESSED, gfx::PointF(), gfx::PointF(), - base::TimeTicks::Now(), 0, 0); -} -} // namespace - -class TabSearchButtonBrowserTest : public InProcessBrowserTest, - public ::testing::WithParamInterface<bool> { - public: - // InProcessBrowserTest: - void SetUp() override { - // Run the test with both kTabSearchFixedEntrypoint enabled and disabled. - if (GetParam()) { - scoped_feature_list_.InitWithFeatures( - /*enabled_features=*/{features::kTabSearch, - features::kTabSearchFixedEntrypoint}, - /*disabled_features=*/{}); - } else { - scoped_feature_list_.InitWithFeatures( - /*enabled_features=*/{features::kTabSearch}, - /*disabled_features=*/{features::kTabSearchFixedEntrypoint}); - } - InProcessBrowserTest::SetUp(); - } - - BrowserView* browser_view() { - return BrowserView::GetBrowserViewForBrowser(browser()); - } - - TabSearchButton* tab_search_button() { - return browser_view()->GetTabSearchButton(); - } - - private: - base::test::ScopedFeatureList scoped_feature_list_; -}; - -IN_PROC_BROWSER_TEST_P(TabSearchButtonBrowserTest, CreateAndClose) { - ASSERT_EQ(nullptr, tab_search_button()->bubble_for_testing()); - tab_search_button()->ButtonPressed(tab_search_button(), GetDummyEvent()); - ASSERT_NE(nullptr, tab_search_button()->bubble_for_testing()); - - // Close the tab search bubble widget, the bubble should be cleared from the - // TabSearchButton. - tab_search_button()->bubble_for_testing()->CloseWithReason( - views::Widget::ClosedReason::kUnspecified); - ASSERT_EQ(nullptr, tab_search_button()->bubble_for_testing()); -} - -IN_PROC_BROWSER_TEST_P(TabSearchButtonBrowserTest, TestBubbleVisible) { - EXPECT_FALSE(tab_search_button()->IsBubbleVisible()); - - ASSERT_EQ(nullptr, tab_search_button()->bubble_for_testing()); - tab_search_button()->ButtonPressed(tab_search_button(), GetDummyEvent()); - ASSERT_NE(nullptr, tab_search_button()->bubble_for_testing()); - - // The bubble should not be visible initially since the UI must notify the - // bubble it is ready before the bubble is shown. - EXPECT_FALSE(tab_search_button()->IsBubbleVisible()); - - // Trigger showing the bubble. - tab_search_button()->bubble_for_testing()->Show(); - - // The bubble should be visible after being shown. - EXPECT_TRUE(tab_search_button()->IsBubbleVisible()); -} - -// On macOS, most accelerators are handled by CommandDispatcher. -#if !defined(OS_MAC) -IN_PROC_BROWSER_TEST_P(TabSearchButtonBrowserTest, TestBubbleKeyboardShortcut) { - ASSERT_EQ(nullptr, tab_search_button()->bubble_for_testing()); - - auto accelerator = ui::Accelerator( - ui::VKEY_A, ui::EF_SHIFT_DOWN | ui::EF_PLATFORM_ACCELERATOR); - browser_view()->AcceleratorPressed(accelerator); - - // Accelerator keys should have created the tab search bubble. - ASSERT_NE(nullptr, tab_search_button()->bubble_for_testing()); - - // Close the tab search bubble widget, the bubble should be cleared from the - // TabSearchButton. - tab_search_button()->bubble_for_testing()->CloseWithReason( - views::Widget::ClosedReason::kUnspecified); - ASSERT_EQ(nullptr, tab_search_button()->bubble_for_testing()); -} -#endif - -INSTANTIATE_TEST_SUITE_P(All, - TabSearchButtonBrowserTest, - ::testing::Values(true, false));
diff --git a/chrome/browser/ui/views/tabs/tab_strip_browsertest.cc b/chrome/browser/ui/views/tabs/tab_strip_browsertest.cc index 6a13c71..aa7e857 100644 --- a/chrome/browser/ui/views/tabs/tab_strip_browsertest.cc +++ b/chrome/browser/ui/views/tabs/tab_strip_browsertest.cc
@@ -13,6 +13,7 @@ #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/ui_features.h" #include "chrome/browser/ui/views/frame/browser_view.h" +#include "chrome/browser/ui/views/tabs/tab_search_button.h" #include "chrome/browser/ui/views/tabs/tab_strip_controller.h" #include "chrome/test/base/in_process_browser_test.h" #include "components/tab_groups/tab_group_id.h" @@ -812,3 +813,28 @@ tab_strip()->SelectTab(tab_strip()->tab_at(0), GetDummyEvent()); EXPECT_FALSE(tab_strip()->controller()->IsGroupCollapsed(group)); } + +class TabSearchButtonTest : public TabStripBrowsertest { + public: + void SetUp() override { + scoped_feature_list_.InitWithFeatureState(features::kTabSearch, true); + TabStripBrowsertest::SetUp(); + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; +}; + +IN_PROC_BROWSER_TEST_F(TabSearchButtonTest, TabSearchBubble_CreateAndClose) { + TabSearchButton* tab_search_button = tab_strip()->tab_search_button(); + + DCHECK_EQ(nullptr, tab_search_button->bubble_for_testing()); + tab_search_button->ButtonPressed(tab_search_button, GetDummyEvent()); + DCHECK_NE(nullptr, tab_search_button->bubble_for_testing()); + + // Close the tab search bubble widget, the bubble should be cleared from the + // TabSearchButton. + tab_search_button->bubble_for_testing()->CloseWithReason( + views::Widget::ClosedReason::kUnspecified); + DCHECK_EQ(nullptr, tab_search_button->bubble_for_testing()); +}
diff --git a/chrome/browser/ui/web_applications/system_web_app_ui_utils.cc b/chrome/browser/ui/web_applications/system_web_app_ui_utils.cc index 7194eecd..53725337 100644 --- a/chrome/browser/ui/web_applications/system_web_app_ui_utils.cc +++ b/chrome/browser/ui/web_applications/system_web_app_ui_utils.cc
@@ -168,10 +168,13 @@ content::WebContents* web_contents = nullptr; + // TODO(crbug.com/1129340): Remove these lines and make CCA resizeable after + // CCA supports responsive UI. + bool can_resize = app_type != SystemAppType::CAMERA; if (base::FeatureList::IsEnabled(features::kDesktopPWAsWithoutExtensions)) { if (!browser) browser = CreateWebApplicationWindow(profile, params->app_id, - params->disposition); + params->disposition, can_resize); // Navigate application window to application's |url| if necessary. // Help app always navigates because its url might not match the url inside @@ -184,7 +187,7 @@ } } else { if (!browser) - browser = CreateApplicationWindow(profile, *params, url); + browser = CreateApplicationWindow(profile, *params, url, can_resize); // Navigate application window to application's |url| if necessary. // Help app always navigates because its url might not match the url inside
diff --git a/chrome/browser/ui/web_applications/web_app_launch_manager.cc b/chrome/browser/ui/web_applications/web_app_launch_manager.cc index 31590a0..f6babbf 100644 --- a/chrome/browser/ui/web_applications/web_app_launch_manager.cc +++ b/chrome/browser/ui/web_applications/web_app_launch_manager.cc
@@ -76,7 +76,8 @@ Browser* CreateWebApplicationWindow(Profile* profile, const std::string& app_id, - WindowOpenDisposition disposition) { + WindowOpenDisposition disposition, + bool can_resize) { std::string app_name = GenerateApplicationNameFromAppId(app_id); gfx::Rect initial_bounds; Browser::CreateParams browser_params = @@ -88,6 +89,7 @@ app_name, /*trusted_source=*/true, initial_bounds, profile, /*user_gesture=*/true); browser_params.initial_show_state = DetermineWindowShowState(); + browser_params.can_resize = can_resize; return new Browser(browser_params); }
diff --git a/chrome/browser/ui/web_applications/web_app_launch_manager.h b/chrome/browser/ui/web_applications/web_app_launch_manager.h index 3ff6ca1f..a9d0c587a 100644 --- a/chrome/browser/ui/web_applications/web_app_launch_manager.h +++ b/chrome/browser/ui/web_applications/web_app_launch_manager.h
@@ -66,7 +66,8 @@ Browser* CreateWebApplicationWindow(Profile* profile, const std::string& app_id, - WindowOpenDisposition disposition); + WindowOpenDisposition disposition, + bool can_resize = true); content::WebContents* NavigateWebApplicationWindow( Browser* browser,
diff --git a/chrome/browser/ui/webui/settings/settings_ui.cc b/chrome/browser/ui/webui/settings/settings_ui.cc index 0d48bc4e..bac67a83f 100644 --- a/chrome/browser/ui/webui/settings/settings_ui.cc +++ b/chrome/browser/ui/webui/settings/settings_ui.cc
@@ -320,6 +320,8 @@ auto plural_string_handler = std::make_unique<PluralStringHandler>(); plural_string_handler->AddLocalizedString( "compromisedPasswords", IDS_SETTINGS_COMPROMISED_PASSWORDS_COUNT); + plural_string_handler->AddLocalizedString( + "insecurePasswords", IDS_SETTINGS_INSECURE_PASSWORDS_COUNT); web_ui->AddMessageHandler(std::move(plural_string_handler)); // Add the metrics handler to write uma stats.
diff --git a/chrome/browser/web_applications/system_web_app_manager.cc b/chrome/browser/web_applications/system_web_app_manager.cc index 665f933..783beab 100644 --- a/chrome/browser/web_applications/system_web_app_manager.cc +++ b/chrome/browser/web_applications/system_web_app_manager.cc
@@ -157,6 +157,7 @@ infos.at(SystemAppType::HELP).additional_search_terms = { IDS_GENIUS_APP_NAME, IDS_HELP_APP_PERKS, IDS_HELP_APP_OFFERS}; infos.at(SystemAppType::HELP).minimum_window_size = {600, 320}; + infos.at(SystemAppType::HELP).capture_navigations = true; } if (SystemWebAppManager::IsAppEnabled(SystemAppType::MEDIA)) {
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt index 6c19ffe..dac9693 100644 --- a/chrome/build/linux.pgo.txt +++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@ -chrome-linux-master-1600797595-fd8ddba8caaa456739bdf5b1d17d7be117d929dc.profdata +chrome-linux-master-1600840405-46e4cd70bd3de973a171c7f611770f78487d203a.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index 9de06df..bde3448 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-master-1600775907-1d0a614b540ad15c6823911f93c081428c564ce9.profdata +chrome-mac-master-1600840405-f4d8e4031cebaee3fd15a03b0f21d18ea0743d9a.profdata
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index 55622d9..83746d7 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc
@@ -949,15 +949,15 @@ const char kPerAppTimeLimitsAllowlistPolicy[] = "child_user.per_app_time_limits.whitelist"; -// Time pref to record the user engagement session start time for family user -// metrics. -const char kFamilyUserMetricsSessionEngagementStartTime[] = - "family_user.metrics.session_engagement_start_time"; - // Integer pref to record the day id (number of days since origin of time) when // family user metrics were last recorded. const char kFamilyUserMetricsDayId[] = "family_user.metrics.day_id"; +// TimeDelta pref to record the accumulated user session duration for family +// user metrics. +const char kFamilyUserMetricsSessionEngagementDuration[] = + "family_user.metrics.session_engagement_duration"; + // List of preconfigured network file shares. const char kNetworkFileSharesPreconfiguredShares[] = "network_file_shares.preconfigured_shares";
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index f619661..c687068 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h
@@ -324,8 +324,8 @@ extern const char kPerAppTimeLimitsLatestLimitUpdateTime[]; extern const char kPerAppTimeLimitsPolicy[]; extern const char kPerAppTimeLimitsAllowlistPolicy[]; -extern const char kFamilyUserMetricsSessionEngagementStartTime[]; extern const char kFamilyUserMetricsDayId[]; +extern const char kFamilyUserMetricsSessionEngagementDuration[]; extern const char kDeviceWallpaperImageFilePath[]; extern const char kKerberosRememberPasswordEnabled[]; extern const char kKerberosAddAccountsAllowed[];
diff --git a/chrome/services/cups_proxy/BUILD.gn b/chrome/services/cups_proxy/BUILD.gn index 88bdf62..beacb68 100644 --- a/chrome/services/cups_proxy/BUILD.gn +++ b/chrome/services/cups_proxy/BUILD.gn
@@ -56,6 +56,7 @@ sources = [ "ipp_validator_unittest.cc", "printer_installer_unittest.cc", + "proxy_manager_unittest.cc", "socket_manager_unittest.cc", ] @@ -71,6 +72,7 @@ "//chrome/services/cups_proxy/public/cpp:unit_tests", "//chrome/services/cups_proxy/test:test_support", "//chromeos", + "//content/public/browser", "//testing/gmock", "//testing/gtest", ]
diff --git a/chrome/services/cups_proxy/proxy_manager.cc b/chrome/services/cups_proxy/proxy_manager.cc index 8b54a05..9bc19aae 100644 --- a/chrome/services/cups_proxy/proxy_manager.cc +++ b/chrome/services/cups_proxy/proxy_manager.cc
@@ -12,6 +12,7 @@ #include <vector> #include "base/bind.h" +#include "base/containers/ring_buffer.h" #include "base/feature_list.h" #include "base/logging.h" #include "base/task/post_task.h" @@ -45,8 +46,16 @@ std::unique_ptr<CupsProxyServiceDelegate> delegate, std::unique_ptr<IppValidator> ipp_validator, std::unique_ptr<PrinterInstaller> printer_installer, - std::unique_ptr<SocketManager> socket_manager); - ~ProxyManagerImpl() override; + std::unique_ptr<SocketManager> socket_manager) + : delegate_(std::move(delegate)), + ipp_validator_(std::move(ipp_validator)), + printer_installer_(std::move(printer_installer)), + socket_manager_(std::move(socket_manager)), + receiver_(this, std::move(request)) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + } + + ~ProxyManagerImpl() override = default; void ProxyRequest(const std::string& method, const std::string& url, @@ -85,6 +94,9 @@ // Current in-flight request. std::unique_ptr<InFlightRequest> in_flight_; + // Timestamp ring buffer. + base::RingBuffer<base::TimeTicks, kRateLimit> timestamp_; + // CupsIppParser Service handle. mojo::Remote<ipp_parser::mojom::IppParser> ipp_parser_; @@ -125,22 +137,6 @@ return ret; } -ProxyManagerImpl::ProxyManagerImpl( - mojo::PendingReceiver<CupsProxier> receiver, - std::unique_ptr<CupsProxyServiceDelegate> delegate, - std::unique_ptr<IppValidator> ipp_validator, - std::unique_ptr<PrinterInstaller> printer_installer, - std::unique_ptr<SocketManager> socket_manager) - : delegate_(std::move(delegate)), - ipp_validator_(std::move(ipp_validator)), - printer_installer_(std::move(printer_installer)), - socket_manager_(std::move(socket_manager)), - receiver_(this, std::move(receiver)) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); -} - -ProxyManagerImpl::~ProxyManagerImpl() = default; - void ProxyManagerImpl::ProxyRequest( const std::string& method, const std::string& url, @@ -150,6 +146,23 @@ ProxyRequestCallback cb) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + // Limit the rate of requests to kRateLimit per second. + // The way the algorithm works is if the number of times this method was + // called between a second ago and now, including the current call, exceeds + // kRateLimit, the request is blocked and the HTTP 429 Too Many Requests + // response status code is returned. + base::TimeTicks time = base::TimeTicks::Now(); + bool block_request = + timestamp_.CurrentIndex() >= timestamp_.BufferSize() && + time - timestamp_.ReadBuffer(0) < base::TimeDelta::FromSeconds(1); + timestamp_.SaveToBuffer(time); + if (block_request) { + DVLOG(1) << "CupsPrintService Error: Rate limit (" << kRateLimit + << ") exceeded"; + std::move(cb).Run({}, {}, 429); // HTTP_STATUS_TOO_MANY_REQUESTS + return; + } + if (!delegate_->IsPrinterAccessAllowed()) { DVLOG(1) << "Printer access not allowed"; std::move(cb).Run(/*headers=*/{}, /*ipp_message=*/{}, @@ -343,14 +356,12 @@ std::unique_ptr<ProxyManager> ProxyManager::Create( mojo::PendingReceiver<mojom::CupsProxier> request, std::unique_ptr<CupsProxyServiceDelegate> delegate) { - // Setting up injected managers. - auto ipp_validator = std::make_unique<IppValidator>(delegate.get()); - auto printer_installer = std::make_unique<PrinterInstaller>(delegate.get()); - auto socket_manager = SocketManager::Create(delegate.get()); - + auto* delegate_ptr = delegate.get(); return std::make_unique<ProxyManagerImpl>( - std::move(request), std::move(delegate), std::move(ipp_validator), - std::move(printer_installer), std::move(socket_manager)); + std::move(request), std::move(delegate), + std::make_unique<IppValidator>(delegate_ptr), + std::make_unique<PrinterInstaller>(delegate_ptr), + SocketManager::Create(delegate_ptr)); } std::unique_ptr<ProxyManager> ProxyManager::CreateForTesting(
diff --git a/chrome/services/cups_proxy/proxy_manager.h b/chrome/services/cups_proxy/proxy_manager.h index ba3c599..76aae82 100644 --- a/chrome/services/cups_proxy/proxy_manager.h +++ b/chrome/services/cups_proxy/proxy_manager.h
@@ -25,12 +25,15 @@ // This handler's job is vetting incoming arbitrary CUPS IPP requests before // they reach the CUPS Daemon. Requests are parsed out-of-process, by the // CupsIppParser Service, and validated/rebuilt in-process before being proxied. -// This handler must be created/accessed from a seqeunced context. +// This handler must be created/accessed from a sequenced context. // // Note: This handler only supports processing one request at a time; any // concurrent requests will immediately fail with an empty response. class ProxyManager : public mojom::CupsProxier { public: + // Request rate limit per second. + static constexpr int kRateLimit = 10; + // Factory function. static std::unique_ptr<ProxyManager> Create( mojo::PendingReceiver<mojom::CupsProxier> request,
diff --git a/chrome/services/cups_proxy/proxy_manager_unittest.cc b/chrome/services/cups_proxy/proxy_manager_unittest.cc new file mode 100644 index 0000000..accccac --- /dev/null +++ b/chrome/services/cups_proxy/proxy_manager_unittest.cc
@@ -0,0 +1,116 @@ +// Copyright 2020 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. + +#include "chrome/services/cups_proxy/proxy_manager.h" + +#include <map> + +#include "base/test/task_environment.h" +#include "chrome/services/cups_proxy/fake_cups_proxy_service_delegate.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace cups_proxy { + +namespace { + +constexpr int kHttpTooManyRequests = 429; + +class MyFakeCupsProxyServiceDelegate : public FakeCupsProxyServiceDelegate { + bool IsPrinterAccessAllowed() const override { return false; } +}; + +class ProxyManagerTest : public testing::Test { + public: + ProxyManagerTest() + : manager_(ProxyManager::Create( + {}, + std::make_unique<MyFakeCupsProxyServiceDelegate>())) {} + + // Proxy a dummy request and add the response code to count_. + void ProxyRequest() const { + manager_->ProxyRequest({}, {}, {}, {}, {}, + base::BindOnce(&ProxyManagerTest::Callback, + weak_factory_.GetWeakPtr())); + } + + // Return the number of times response code status has been received. + int NumRequestsByStatusCode(int32_t status) const { + const auto it = count_.find(status); + return it == count_.end() ? 0 : it->second; + } + + // Fast forward the task environment's fake clock. + void FastForwardBy(base::TimeDelta delta) { + return task_environment_.FastForwardBy(delta); + } + + private: + // Add the response code status to count_. + void Callback(const std::vector<ipp_converter::HttpHeader>&, + const std::vector<uint8_t>&, + int32_t status) { + count_[status]++; + } + + base::test::TaskEnvironment task_environment_{ + base::test::TaskEnvironment::TimeSource::MOCK_TIME}; + + std::map<int32_t, int> count_; + + std::unique_ptr<ProxyManager> manager_; + + base::WeakPtrFactory<ProxyManagerTest> weak_factory_{this}; +}; + +// Test a burst of simultaneous function calls. +TEST_F(ProxyManagerTest, ProxyRequestRateLimitBurst) { + for (int i = 0; i < ProxyManager::kRateLimit + 3; i++) + ProxyRequest(); + EXPECT_EQ(NumRequestsByStatusCode(kHttpTooManyRequests), 3); +} + +// Test a 0.99s gap between two bursts of function calls. +TEST_F(ProxyManagerTest, ProxyRequestRateLimitShortGap) { + for (int i = 0; i < ProxyManager::kRateLimit + 1; i++) { + if (i == ProxyManager::kRateLimit / 2) + FastForwardBy(base::TimeDelta::FromSecondsD(.99)); + ProxyRequest(); + } + EXPECT_EQ(NumRequestsByStatusCode(kHttpTooManyRequests), 1); +} + +// Test that the rate limit is reset after 1.01s. +TEST_F(ProxyManagerTest, ProxyRequestRateLimitLongGap) { + for (int i = 0; i < ProxyManager::kRateLimit + 1; i++) + ProxyRequest(); + EXPECT_EQ(NumRequestsByStatusCode(kHttpTooManyRequests), 1); + FastForwardBy(base::TimeDelta::FromSecondsD(1.01)); + for (int i = 0; i < ProxyManager::kRateLimit + 1; i++) + ProxyRequest(); + EXPECT_EQ(NumRequestsByStatusCode(kHttpTooManyRequests), 2); +} + +// Test that calls at a constant rate below the rate limit are allowed. +TEST_F(ProxyManagerTest, ProxyRequestRateLimitBelow) { + for (int i = 0; i < ProxyManager::kRateLimit + 10; i++) { + FastForwardBy( + base::TimeDelta::FromSecondsD(1.01 / ProxyManager::kRateLimit)); + ProxyRequest(); + } + EXPECT_EQ(NumRequestsByStatusCode(kHttpTooManyRequests), 0); +} + +// Test that calls at a constant rate above the rate limit are blocked. +TEST_F(ProxyManagerTest, ProxyRequestRateLimitAbove) { + for (int i = 0; i < ProxyManager::kRateLimit + 10; i++) { + FastForwardBy( + base::TimeDelta::FromSecondsD(.99 / ProxyManager::kRateLimit)); + ProxyRequest(); + } + EXPECT_EQ(NumRequestsByStatusCode(kHttpTooManyRequests), 10); +} + +} // namespace + +} // namespace cups_proxy
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 74bd3b6..4737b2a 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -1454,7 +1454,6 @@ "../browser/ui/views/sharing/shared_clipboard_browsertest.cc", "../browser/ui/views/sharing/sharing_browsertest.cc", "../browser/ui/views/sharing/sharing_browsertest.h", - "../browser/ui/views/tabs/tab_search_button_browsertest.cc", "../browser/ui/views/tabs/tab_strip_browsertest.cc", "../browser/ui/views/try_chrome_dialog_win/try_chrome_dialog_browsertest.cc", "../browser/ui/views/web_apps/web_app_frame_toolbar_browsertest.cc", @@ -2605,6 +2604,7 @@ "../browser/chromeos/startup_settings_cache_browsertest.cc", "../browser/chromeos/system/device_disabling_browsertest.cc", "../browser/chromeos/system/tray_accessibility_browsertest.cc", + "../browser/chromeos/web_applications/camera_app_integration_browsertest.cc", "../browser/chromeos/web_applications/diagnostics_app_integration_browsertest.cc", "../browser/chromeos/web_applications/help_app_integration_browsertest.cc", "../browser/chromeos/web_applications/media_app_integration_browsertest.cc",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/contextmenu/RevampedContextMenuUtils.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/contextmenu/RevampedContextMenuUtils.java index 984a70c..9a198de 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/contextmenu/RevampedContextMenuUtils.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/contextmenu/RevampedContextMenuUtils.java
@@ -116,6 +116,28 @@ } /** + * Selects the context menu chip asserting that an intent will be sent with a + * specific package name. Note that this method does not open the context menu. + * @param instrumentation Instrumentation module used for executing test behavior. + * @param expectedActivity The activity to assert for gaining focus after click or null. + * @param menuCoordinator The menu coordinator which manages the context menu. + * @param openerDOMNodeId The DOM node to long press to open the context menu for. + * @param itemId The context menu item ID to select. + * @param expectedIntentPackage If firing an external intent the expected package name of the + * target. + * @throws TimeoutException + */ + public static void selectAlreadyOpenedContextMenuChipWithExpectedIntent( + Instrumentation instrumentation, Activity expectedActivity, + RevampedContextMenuCoordinator menuCoordinator, String openerDOMNodeId, + final int itemId, String expectedIntentPackage) throws TimeoutException { + Assert.assertNotNull("Menu coordinator was not provided.", menuCoordinator); + + selectAlreadyOpenedContextMenuChip( + instrumentation, expectedActivity, menuCoordinator, itemId, expectedIntentPackage); + } + + /** * Long presses to open and selects an item from a context menu. * @param instrumentation Instrumentation module used for executing test behavior. * @param expectedActivity The activity to assert for gaining focus after click or null. @@ -183,4 +205,25 @@ Intents.release(); } } + + private static void selectAlreadyOpenedContextMenuChip(Instrumentation instrumentation, + final Activity expectedActivity, final RevampedContextMenuCoordinator menuCoordinator, + final int itemId, final String expectedIntentPackage) { + if (expectedIntentPackage != null) { + Intents.init(); + } + + instrumentation.runOnMainSync(() -> menuCoordinator.clickChipForTesting()); + + if (expectedActivity != null) { + CriteriaHelper.pollInstrumentationThread(expectedActivity::hasWindowFocus); + } + + if (expectedIntentPackage != null) { + // This line must only execute after all test behavior has completed + // or it will intefere with the expected behavior. + intended(IntentMatchers.hasPackage(expectedIntentPackage)); + Intents.release(); + } + } }
diff --git a/chrome/test/base/chrome_render_view_host_test_harness.cc b/chrome/test/base/chrome_render_view_host_test_harness.cc index 4453824..b21500c 100644 --- a/chrome/test/base/chrome_render_view_host_test_harness.cc +++ b/chrome/test/base/chrome_render_view_host_test_harness.cc
@@ -38,24 +38,11 @@ std::unique_ptr<TestingProfile> ChromeRenderViewHostTestHarness::CreateTestingProfile() { - // Maintain the profile directory ourselves so that it isn't deleted along - // with TestingProfile. RenderViewHostTestHarness::TearDown() will destroy - // the profile and also destroy the thread bundle to ensure that any tasks - // posted throughout the test run to completion. By postponing the deletion - // of the profile directory until ~ChromeRenderViewHostTestHarness() we - // guarantee that no tasks will try to access the profile directory when it's - // (being) deleted. - auto temp_dir = std::make_unique<base::ScopedTempDir>(); - CHECK(temp_dir->CreateUniqueTempDir()); - TestingProfile::Builder builder; - builder.SetPath(temp_dir->GetPath()); for (auto& pair : GetTestingFactories()) builder.AddTestingFactory(pair.first, pair.second); - temp_dirs_.push_back(std::move(temp_dir)); - return builder.Build(); }
diff --git a/chrome/test/base/chrome_render_view_host_test_harness.h b/chrome/test/base/chrome_render_view_host_test_harness.h index 7bbb3ea4..c779104 100644 --- a/chrome/test/base/chrome_render_view_host_test_harness.h +++ b/chrome/test/base/chrome_render_view_host_test_harness.h
@@ -7,10 +7,8 @@ #include <memory> #include <utility> -#include <vector> #include "base/compiler_specific.h" -#include "base/files/scoped_temp_dir.h" #include "chrome/test/base/testing_profile.h" #include "content/public/test/test_renderer_host.h" @@ -43,9 +41,6 @@ // content::RenderViewHostTestHarness. std::unique_ptr<content::BrowserContext> CreateBrowserContext() final; - - private: - std::vector<std::unique_ptr<base::ScopedTempDir>> temp_dirs_; }; #endif // CHROME_TEST_BASE_CHROME_RENDER_VIEW_HOST_TEST_HARNESS_H_
diff --git a/chrome/test/data/chromeos/file_manager/utf8.txt b/chrome/test/data/chromeos/file_manager/utf8.txt new file mode 100644 index 0000000..43ab174 --- /dev/null +++ b/chrome/test/data/chromeos/file_manager/utf8.txt
@@ -0,0 +1,5 @@ +Hello नोपहिनस्ति أن 害 +色は匂へど 散りぬるを +κόσμε ᚹᛦᛗ コンニチハ +волн ապակի Կրնամ +їсти मुझे |∊☀✌✂♁ 🙂
diff --git a/chrome/test/data/webui/BUILD.gn b/chrome/test/data/webui/BUILD.gn index b629157..6e5b36f 100644 --- a/chrome/test/data/webui/BUILD.gn +++ b/chrome/test/data/webui/BUILD.gn
@@ -283,6 +283,7 @@ "$root_gen_dir/chrome/test/data/webui/nearby_share/shared/nearby_visibility_page_test.m.js", "$root_gen_dir/chrome/test/data/webui/settings/chromeos/ambient_mode_page_test.m.js", "$root_gen_dir/chrome/test/data/webui/settings/chromeos/bluetooth_page_tests.m.js", + "$root_gen_dir/chrome/test/data/webui/settings/chromeos/cellular_setup_dialog_test.m.js", "$root_gen_dir/chrome/test/data/webui/settings/chromeos/date_time_page_tests.m.js", "$root_gen_dir/chrome/test/data/webui/settings/chromeos/fake_bluetooth_private.m.js", "$root_gen_dir/chrome/test/data/webui/settings/chromeos/fake_bluetooth.m.js", @@ -290,6 +291,7 @@ "$root_gen_dir/chrome/test/data/webui/settings/chromeos/fake_quick_unlock_private.m.js", "$root_gen_dir/chrome/test/data/webui/settings/chromeos/input_method_options_page_test.m.js", "$root_gen_dir/chrome/test/data/webui/settings/chromeos/input_page_test.m.js", + "$root_gen_dir/chrome/test/data/webui/settings/chromeos/internet_config_test.m.js", "$root_gen_dir/chrome/test/data/webui/settings/chromeos/internet_known_networks_page_tests.m.js", "$root_gen_dir/chrome/test/data/webui/settings/chromeos/localized_link_test.m.js", "$root_gen_dir/chrome/test/data/webui/settings/chromeos/multidevice_feature_item_tests.m.js",
diff --git a/chrome/test/data/webui/settings/chromeos/BUILD.gn b/chrome/test/data/webui/settings/chromeos/BUILD.gn index 86011e5..6d5782a 100644 --- a/chrome/test/data/webui/settings/chromeos/BUILD.gn +++ b/chrome/test/data/webui/settings/chromeos/BUILD.gn
@@ -33,6 +33,7 @@ input_files = [ "ambient_mode_page_test.js", "bluetooth_page_tests.js", + "cellular_setup_dialog_test.js", "date_time_page_tests.js", "fake_bluetooth.js", "fake_bluetooth_private.js", @@ -42,6 +43,7 @@ "fake_user_action_recorder.js", "input_method_options_page_test.js", "input_page_test.js", + "internet_config_test.js", "internet_known_networks_page_tests.js", "localized_link_test.js", "multidevice_feature_item_tests.js",
diff --git a/chrome/test/data/webui/settings/chromeos/cellular_setup_dialog_test.js b/chrome/test/data/webui/settings/chromeos/cellular_setup_dialog_test.js new file mode 100644 index 0000000..7548ecc0 --- /dev/null +++ b/chrome/test/data/webui/settings/chromeos/cellular_setup_dialog_test.js
@@ -0,0 +1,28 @@ +// Copyright 2020 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. + +// clang-format off +// #import 'chrome://os-settings/chromeos/os_settings.js'; + +// #import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +// clang-format on + +suite('CellularSetupDialog', function() { + test('Dialog opened on attach', function(done) { + /** @type {!OsSettingsCellularSetupDialog} */ + const cellularSetupDialog = + document.createElement('os-settings-cellular-setup-dialog'); + + // Verify the dialog is opened. + cellularSetupDialog.addEventListener('cr-dialog-open', function(e) { + done(); + }); + + // Attach the element to the DOM, which opens the dialog. + document.body.appendChild(cellularSetupDialog); + Polymer.dom.flush(); + + assertTrue(cellularSetupDialog.$.dialog.open); + }); +});
diff --git a/chrome/test/data/webui/settings/chromeos/internet_config_test.js b/chrome/test/data/webui/settings/chromeos/internet_config_test.js new file mode 100644 index 0000000..6198cf66 --- /dev/null +++ b/chrome/test/data/webui/settings/chromeos/internet_config_test.js
@@ -0,0 +1,41 @@ +// Copyright 2020 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. + +// clang-format off +// #import 'chrome://os-settings/chromeos/os_settings.js'; + +// #import {FakeNetworkConfig} from 'chrome://test/chromeos/fake_network_config_mojom.m.js'; +// #import {MojoInterfaceProviderImpl} from 'chrome://resources/cr_components/chromeos/network/mojo_interface_provider.m.js'; +// #import {OncMojo} from 'chrome://resources/cr_components/chromeos/network/onc_mojo.m.js'; +// #import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +// clang-format on + +suite('InternetConfig', function() { + /** @type {!InternetConfig|undefined} */ + let internetConfig; + + /** @type {!chromeos.networkConfig.mojom.CrosNetworkConfigRemote|undefined} */ + let mojoApi_; + + suiteSetup(function() { + mojoApi_ = new FakeNetworkConfig(); + network_config.MojoInterfaceProviderImpl.getInstance().remote_ = mojoApi_; + }); + + setup(function() { + internetConfig = document.createElement('internet-config'); + internetConfig.type = OncMojo.getNetworkTypeString( + chromeos.networkConfig.mojom.NetworkType.kWiFi); + document.body.appendChild(internetConfig); + Polymer.dom.flush(); + }); + + test('Cancel button closes the dialog', function() { + internetConfig.open(); + assertTrue(internetConfig.$.dialog.open); + + internetConfig.$$('cr-button.cancel-button').click(); + assertFalse(internetConfig.$.dialog.open); + }); +});
diff --git a/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js b/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js index ce8ddbe..dc7fb57 100644 --- a/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js +++ b/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js
@@ -732,6 +732,22 @@ // Test fixture for settings-internet-detail-page. // eslint-disable-next-line no-var +var OSSettingsInternetConfigTest = class extends OSSettingsBrowserTest { + /** @override */ + get extraLibraries() { + return super.extraLibraries.concat([ + BROWSER_SETTINGS_PATH + '../chromeos/fake_network_config_mojom.js', + 'internet_config_test.js', + ]); + } +}; + +TEST_F('OSSettingsInternetConfigTest', 'All', () => { + mocha.run(); +}); + +// Test fixture for settings-internet-detail-page. +// eslint-disable-next-line no-var var OSSettingsInternetDetailPageTest = class extends OSSettingsBrowserTest { /** @override */ get browsePreload() { @@ -864,6 +880,37 @@ mocha.run(); }); +// Test fixture for settings-internet-known-networks-page. +// eslint-disable-next-line no-var +var OSSettingsCellularSetupDialogTest = + class extends OSSettingsBrowserTest { + /** @override */ + get browsePreload() { + return super.browsePreload;/* + + 'chromeos/internet_page/cellular_setup_dialog.html';*/ + } + + /** @override */ + get featureList() { + return {enabled: ['chromeos::features::kUpdatedCellularActivationUi']}; + } + + /** @override */ + get extraLibraries() { + return super.extraLibraries.concat([ + '//ui/webui/resources/js/assert.js', + BROWSER_SETTINGS_PATH + '../test_util.js', + 'cellular_setup_dialog_test.js', + ]); + } +}; + +TEST_F( + 'OSSettingsCellularSetupDialogTest', 'CellularSetupDialog', + () => { + mocha.run(); + }); + // Test fixture for the main settings page. // eslint-disable-next-line no-var var OSSettingsMainTest = class extends OSSettingsBrowserTest {
diff --git a/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js b/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js index 78a61b5..7299c010 100644 --- a/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js +++ b/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js
@@ -32,6 +32,7 @@ return { enabled: [ 'chromeos::features::kOsSettingsPolymer3', + 'chromeos::features::kUpdatedCellularActivationUi', ], }; } @@ -92,8 +93,10 @@ [['AmbientModePage', 'ambient_mode_page_test.m.js'], ['BluetoothPage', 'bluetooth_page_tests.m.js'], + ['CellularSetupDialog', 'cellular_setup_dialog_test.m.js'], ['DateTimePage', 'date_time_page_tests.m.js'], ['InputMethodOptionPage', 'input_method_options_page_test.m.js'], + ['InternetConfig', 'internet_config_test.m.js'], ['InternetKnownNetworksPage', 'internet_known_networks_page_tests.m.js'], ['LocalizedLink', 'localized_link_test.m.js'], ['MultideviceFeatureItem', 'multidevice_feature_item_tests.m.js'],
diff --git a/chrome/test/data/webui/settings/password_check_test.js b/chrome/test/data/webui/settings/password_check_test.js index e5f9bb2a..8b250d3 100644 --- a/chrome/test/data/webui/settings/password_check_test.js +++ b/chrome/test/data/webui/settings/password_check_test.js
@@ -10,9 +10,10 @@ import {isChromeOS} from 'chrome://resources/js/cr.m.js'; import {webUIListenerCallback} from 'chrome://resources/js/cr.m.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; +import {PluralStringProxyImpl} from 'chrome://resources/js/plural_string_proxy.js'; import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {OpenWindowProxyImpl, PasswordManagerImpl, PasswordManagerProxy, Router, routes} from 'chrome://settings/settings.js'; -import {makeCompromisedCredential, makePasswordCheckStatus} from 'chrome://test/settings/passwords_and_autofill_fake_data.js'; +import {makeCompromisedCredential, makeInsecureCredential, makePasswordCheckStatus} from 'chrome://test/settings/passwords_and_autofill_fake_data.js'; import {getSyncAllPrefs,simulateSyncStatus} from 'chrome://test/settings/sync_test_util.m.js'; import {TestOpenWindowProxy} from 'chrome://test/settings/test_open_window_proxy.js'; import {TestPasswordManagerProxy} from 'chrome://test/settings/test_password_manager_proxy.js'; @@ -493,8 +494,8 @@ const spinner = checkPasswordSection.$$('paper-spinner-lite'); expectFalse(isElementVisible(spinner)); assertTrue(isElementVisible(icon)); - expectFalse(icon.classList.contains('has-leaks')); - expectTrue(icon.classList.contains('no-leaks')); + expectFalse(icon.classList.contains('has-security-issues')); + expectTrue(icon.classList.contains('no-security-issues')); }); // Tests that there is neither spinner nor icon if the check hasn't run yet. @@ -527,8 +528,8 @@ const spinner = checkPasswordSection.$$('paper-spinner-lite'); expectFalse(isElementVisible(spinner)); assertTrue(isElementVisible(icon)); - expectTrue(icon.classList.contains('has-leaks')); - expectFalse(icon.classList.contains('no-leaks')); + expectTrue(icon.classList.contains('has-security-issues')); + expectFalse(icon.classList.contains('no-security-issues')); }); // Tests that the spinner is replaced with a warning on errors. @@ -545,8 +546,8 @@ const spinner = checkPasswordSection.$$('paper-spinner-lite'); expectFalse(isElementVisible(spinner)); assertTrue(isElementVisible(icon)); - expectFalse(icon.classList.contains('has-leaks')); - expectFalse(icon.classList.contains('no-leaks')); + expectFalse(icon.classList.contains('has-security-issues')); + expectFalse(icon.classList.contains('no-security-issues')); }); // Tests that the spinner replaces any icon while the check is running. @@ -619,6 +620,54 @@ expectEquals(section.i18n('checkPasswordsProgress', 2, 5), title.innerText); }); + // If passwords weakness check is enabled, shows count of insecure + // credentials. + test('showInsecurePasswordsCount', async function() { + loadTimeData.overrideValues({passwordsWeaknessCheck: true}); + const data = passwordManager.data; + data.leakedCredentials = [ + makeCompromisedCredential('one.com', 'test4', 'LEAKED'), + ]; + data.weakCredentials = [ + makeInsecureCredential('one.com', 'test4'), + ]; + + const section = createCheckPasswordSection(); + await passwordManager.whenCalled('getPasswordCheckStatus'); + flush(); + const subtitle = section.$.subtitle; + assertTrue(isElementVisible(subtitle)); + + return PluralStringProxyImpl.getInstance() + .getPluralString('insecurePasswords', 2) + .then(count => { + expectEquals(count, subtitle.textContent.trim()); + }); + }); + + // If passwords weakness check is disabled, shows count of compromised + // credentials. + test('showCompromisedPasswordsCount', async function() { + loadTimeData.overrideValues({passwordsWeaknessCheck: false}); + const data = passwordManager.data; + data.leakedCredentials = [ + makeCompromisedCredential('one.com', 'test4', 'LEAKED'), + ]; + + const section = createCheckPasswordSection(); + await passwordManager.whenCalled('getPasswordCheckStatus'); + flush(); + + const subtitle = section.$.subtitle; + assertTrue(isElementVisible(subtitle)); + + return PluralStringProxyImpl.getInstance() + .getPluralString('compromisedPasswords', 1) + .then(count => { + expectEquals(count, subtitle.textContent.trim()); + }); + }); + // When canceled, show string explaining that and already found leak // count. test('showProgressAndLeaksAfterCanceled', async function() {
diff --git a/chrome/test/data/webui/settings/passwords_and_autofill_fake_data.js b/chrome/test/data/webui/settings/passwords_and_autofill_fake_data.js index 6bc9740..285279a 100644 --- a/chrome/test/data/webui/settings/passwords_and_autofill_fake_data.js +++ b/chrome/test/data/webui/settings/passwords_and_autofill_fake_data.js
@@ -244,6 +244,26 @@ } /** + * Creates a new insecure credential. + * @param {string} url + * @param {string} username + * @param {number=} id + * @return {chrome.passwordsPrivate.InsecureCredential} + * @private + */ +export function makeInsecureCredential(url, username, id) { + return { + id: id || 0, + formattedOrigin: url, + changePasswordUrl: `http://${url}/`, + username: username, + detailedOrigin: '', + isAndroidCredential: false, + signonRealm: '', + }; +} + +/** * Creates a new compromised credential. * @param {string} url * @param {string} username @@ -255,20 +275,13 @@ */ export function makeCompromisedCredential( url, username, type, id, elapsedMinSinceCompromise) { - return { - id: id || 0, - formattedOrigin: url, - changePasswordUrl: `http://${url}/`, - username: username, - compromisedInfo: { - compromiseTime: Date.now() - (elapsedMinSinceCompromise * 60000), - elapsedTimeSinceCompromise: `${elapsedMinSinceCompromise} minutes ago`, - compromiseType: type, - }, - detailedOrigin: '', - isAndroidCredential: false, - signonRealm: '', + const credential = makeInsecureCredential(url, username, id); + credential.compromisedInfo = { + compromiseTime: Date.now() - (elapsedMinSinceCompromise * 60000), + elapsedTimeSinceCompromise: `${elapsedMinSinceCompromise} minutes ago`, + compromiseType: type, }; + return credential; } /**
diff --git a/chrome/test/data/webui/settings/test_password_manager_proxy.js b/chrome/test/data/webui/settings/test_password_manager_proxy.js index 8b4655606..a2b25078 100644 --- a/chrome/test/data/webui/settings/test_password_manager_proxy.js +++ b/chrome/test/data/webui/settings/test_password_manager_proxy.js
@@ -47,6 +47,7 @@ 'startBulkPasswordCheck', 'stopBulkPasswordCheck', 'getCompromisedCredentials', + 'getWeakCredentials', 'getPasswordCheckStatus', 'getPlaintextInsecurePassword', 'changeInsecureCredential', @@ -70,6 +71,7 @@ passwords: [], exceptions: [], leakedCredentials: [], + weakCredentials: [], checkStatus: makePasswordCheckStatus(), }; @@ -80,6 +82,7 @@ addExceptionListChangedListener: null, requestPlaintextPassword: null, addCompromisedCredentialsListener: null, + addWeakCredentialsListener: null, addAccountStorageOptInStateListener: null, }; @@ -242,6 +245,12 @@ } /** @override */ + getWeakCredentials() { + this.methodCalled('getWeakCredentials'); + return Promise.resolve(this.data.weakCredentials); + } + + /** @override */ getPasswordCheckStatus() { this.methodCalled('getPasswordCheckStatus'); return Promise.resolve(this.data.checkStatus); @@ -256,6 +265,14 @@ removeCompromisedCredentialsListener(listener) {} /** @override */ + addWeakCredentialsListener(listener) { + this.lastCallback.addWeakCredentialsListener = listener; + } + + /** @override */ + removeWeakCredentialsListener(listener) {} + + /** @override */ addPasswordCheckStatusListener(listener) { this.lastCallback.addPasswordCheckStatusListener = listener; }
diff --git a/chromecast/BUILD.gn b/chromecast/BUILD.gn index bd07af4..28640aa4f 100644 --- a/chromecast/BUILD.gn +++ b/chromecast/BUILD.gn
@@ -613,6 +613,7 @@ "SUPPORTS_MULTIZONE=$supports_multizone", "USE_ANDROID_USER_AGENT=$use_android_user_agent", "USE_CHROMECAST_CDMS=$use_chromecast_cdms", + "ENABLE_CHROMIUM_RUNTIME_CAST_RENDERER=$enable_chromium_runtime_cast_renderer", ] }
diff --git a/chromecast/chromecast.gni b/chromecast/chromecast.gni index ea3ff09..f4e1033 100644 --- a/chromecast/chromecast.gni +++ b/chromecast/chromecast.gni
@@ -141,6 +141,9 @@ # Set to true to forward crashes to the system's crash handler instead of # handling them internally. This disables the built-in crash handler. use_system_crash_handler = false + + # True to use the Chromium runtime for cast rendering. + enable_chromium_runtime_cast_renderer = false } declare_args() {
diff --git a/chromecast/media/audio/BUILD.gn b/chromecast/media/audio/BUILD.gn index 762458c..eb0dcda 100644 --- a/chromecast/media/audio/BUILD.gn +++ b/chromecast/media/audio/BUILD.gn
@@ -108,6 +108,7 @@ "//chromecast/base", "//chromecast/common/mojom", "//chromecast/media/api", + "//chromecast/media/audio/capture_service:common", "//chromecast/media/audio/capture_service:receiver", "//chromecast/media/audio/capture_service:utils", "//chromecast/media/audio/mixer_service:common",
diff --git a/chromecast/media/audio/capture_service/capture_service_receiver.cc b/chromecast/media/audio/capture_service/capture_service_receiver.cc index d47ced4..3d2f417 100644 --- a/chromecast/media/audio/capture_service/capture_service_receiver.cc +++ b/chromecast/media/audio/capture_service/capture_service_receiver.cc
@@ -91,10 +91,8 @@ bool CaptureServiceReceiver::Socket::SendRequest() { DCHECK_EQ(state_, State::kInit); - auto request_buffer = capture_service::MakeMessage( - capture_service::PacketInfo{capture_service::MessageType::kHandshake, - request_stream_info_, 0 /* timestamp_us */}, - nullptr /* data */, 0 /* data_size */); + auto request_buffer = + capture_service::MakeHandshakeMessage(request_stream_info_); if (!request_buffer) { return false; } @@ -157,9 +155,9 @@ bool CaptureServiceReceiver::Socket::HandleAck(char* data, size_t size) { DCHECK_EQ(state_, State::kWaitForAck); - capture_service::PacketInfo info; - if (!capture_service::ReadHeader(data, size, &info) || - !delegate_->OnInitialStreamInfo(info.stream_info)) { + capture_service::StreamInfo info; + if (!capture_service::ReadHandshakeMessage(data, size, &info) || + !delegate_->OnInitialStreamInfo(info)) { ReportErrorAndStop(); return false; }
diff --git a/chromecast/media/audio/capture_service/capture_service_receiver_unittest.cc b/chromecast/media/audio/capture_service/capture_service_receiver_unittest.cc index 7c7e36a..0e47cc5 100644 --- a/chromecast/media/audio/capture_service/capture_service_receiver_unittest.cc +++ b/chromecast/media/audio/capture_service/capture_service_receiver_unittest.cc
@@ -34,30 +34,18 @@ SampleFormat::PLANAR_FLOAT, 16000, 160}; -constexpr PacketHeader kHandshakePacketHeader = - PacketHeader{0, - static_cast<uint8_t>(MessageType::kHandshake), - static_cast<uint8_t>(kStreamInfo.stream_type), - static_cast<uint8_t>(kStreamInfo.audio_codec), - kStreamInfo.num_channels, - kStreamInfo.sample_rate, - kStreamInfo.frames_per_buffer}; -constexpr PacketHeader kPcmAudioPacketHeader = - PacketHeader{0, - static_cast<uint8_t>(MessageType::kPcmAudio), - static_cast<uint8_t>(kStreamInfo.stream_type), - static_cast<uint8_t>(kStreamInfo.sample_format), - kStreamInfo.num_channels, - kStreamInfo.sample_rate, - 0}; - -void FillHeader(char* buf, uint16_t size, const PacketHeader& header) { - base::WriteBigEndian(buf, size); - memcpy(buf + sizeof(size), - reinterpret_cast<const char*>(&header) + - offsetof(struct PacketHeader, message_type), - sizeof(header) - offsetof(struct PacketHeader, message_type)); -} +constexpr HandshakePacket kHandshakePacket = + HandshakePacket{0, + static_cast<uint8_t>(MessageType::kHandshake), + static_cast<uint8_t>(kStreamInfo.stream_type), + static_cast<uint8_t>(kStreamInfo.audio_codec), + static_cast<uint8_t>(kStreamInfo.sample_format), + kStreamInfo.num_channels, + kStreamInfo.frames_per_buffer, + kStreamInfo.sample_rate}; +constexpr PcmPacketHeader kPcmAudioPacketHeader = + PcmPacketHeader{0, static_cast<uint8_t>(MessageType::kPcmAudio), + static_cast<uint8_t>(kStreamInfo.stream_type), 0}; class MockStreamSocket : public chromecast::MockStreamSocket { public: @@ -95,7 +83,7 @@ auto socket1 = std::make_unique<MockStreamSocket>(); auto socket2 = std::make_unique<MockStreamSocket>(); EXPECT_CALL(*socket1, Connect).WillOnce(Return(net::OK)); - EXPECT_CALL(*socket1, Write).WillOnce(Return(16)); + EXPECT_CALL(*socket1, Write).WillOnce(Return(sizeof(HandshakePacket))); EXPECT_CALL(*socket1, Read).WillOnce(Return(net::ERR_IO_PENDING)); EXPECT_CALL(*socket2, Connect).WillOnce(Return(net::OK)); @@ -135,17 +123,19 @@ .WillOnce(Invoke([](net::IOBuffer* buf, int buf_len, net::CompletionOnceCallback, const net::NetworkTrafficAnnotationTag&) { - EXPECT_EQ(buf_len, static_cast<int>(sizeof(PacketHeader))); + EXPECT_EQ(buf_len, static_cast<int>(sizeof(HandshakePacket))); const char* data = buf->data(); uint16_t size; base::ReadBigEndian(data, &size); - EXPECT_EQ(size, sizeof(PacketHeader) - sizeof(size)); - PacketHeader header; - std::memcpy(&header, data, sizeof(PacketHeader)); - EXPECT_EQ(header.message_type, kHandshakePacketHeader.message_type); - EXPECT_EQ(header.stream_type, kHandshakePacketHeader.stream_type); - EXPECT_EQ(header.codec_or_sample_format, - kHandshakePacketHeader.codec_or_sample_format); + EXPECT_EQ(size, sizeof(HandshakePacket) - sizeof(size)); + HandshakePacket packet; + std::memcpy(&packet, data, sizeof(HandshakePacket)); + EXPECT_EQ(packet.message_type, kHandshakePacket.message_type); + EXPECT_EQ(packet.stream_type, kHandshakePacket.stream_type); + EXPECT_EQ(packet.audio_codec, kHandshakePacket.audio_codec); + EXPECT_EQ(packet.num_channels, kHandshakePacket.num_channels); + EXPECT_EQ(packet.num_frames, kHandshakePacket.num_frames); + EXPECT_EQ(packet.sample_rate, kHandshakePacket.sample_rate); return buf_len; })); EXPECT_CALL(*socket, Read).WillOnce(Return(net::ERR_IO_PENDING)); @@ -161,26 +151,24 @@ TEST_F(CaptureServiceReceiverTest, ReceivePcmAudioMessage) { auto socket = std::make_unique<MockStreamSocket>(); EXPECT_CALL(*socket, Connect).WillOnce(Return(net::OK)); - EXPECT_CALL(*socket, Write).WillOnce(Return(16)); + EXPECT_CALL(*socket, Write).WillOnce(Return(sizeof(HandshakePacket))); EXPECT_CALL(*socket, Read) // Ack message. .WillOnce(Invoke( [](net::IOBuffer* buf, int buf_len, net::CompletionOnceCallback) { - int total_size = sizeof(PacketHeader); + int total_size = sizeof(HandshakePacket); EXPECT_GE(buf_len, total_size); - uint16_t size = total_size - sizeof(uint16_t); - PacketHeader header = kHandshakePacketHeader; - FillHeader(buf->data(), size, header); + FillBuffer(buf->data(), total_size, &kHandshakePacket.message_type, + sizeof(HandshakePacket) - sizeof(uint16_t)); return total_size; })) // Audio message. .WillOnce(Invoke([](net::IOBuffer* buf, int buf_len, net::CompletionOnceCallback) { - int total_size = sizeof(PacketHeader) + DataSizeInBytes(kStreamInfo); + int total_size = sizeof(PcmPacketHeader) + DataSizeInBytes(kStreamInfo); EXPECT_GE(buf_len, total_size); - uint16_t size = total_size - sizeof(uint16_t); - PacketHeader header = kPcmAudioPacketHeader; - FillHeader(buf->data(), size, header); + FillBuffer(buf->data(), total_size, &kPcmAudioPacketHeader.message_type, + sizeof(PcmPacketHeader) - sizeof(uint16_t)); return total_size; // No need to fill audio frames. })) .WillOnce(Return(net::ERR_IO_PENDING)); @@ -198,7 +186,7 @@ TEST_F(CaptureServiceReceiverTest, ReceiveMetadataMessage) { auto socket = std::make_unique<MockStreamSocket>(); EXPECT_CALL(*socket, Connect).WillOnce(Return(net::OK)); - EXPECT_CALL(*socket, Write).WillOnce(Return(16)); + EXPECT_CALL(*socket, Write).WillOnce(Return(sizeof(HandshakePacket))); EXPECT_CALL(*socket, Read) .WillOnce(Invoke( [](net::IOBuffer* buf, int buf_len, net::CompletionOnceCallback) { @@ -223,7 +211,7 @@ TEST_F(CaptureServiceReceiverTest, ReceiveError) { auto socket = std::make_unique<MockStreamSocket>(); EXPECT_CALL(*socket, Connect).WillOnce(Return(net::OK)); - EXPECT_CALL(*socket, Write).WillOnce(Return(16)); + EXPECT_CALL(*socket, Write).WillOnce(Return(sizeof(HandshakePacket))); EXPECT_CALL(*socket, Read).WillOnce(Return(net::ERR_CONNECTION_RESET)); EXPECT_CALL(delegate_, OnCaptureError); @@ -234,7 +222,7 @@ TEST_F(CaptureServiceReceiverTest, ReceiveEosMessage) { auto socket = std::make_unique<MockStreamSocket>(); EXPECT_CALL(*socket, Connect).WillOnce(Return(net::OK)); - EXPECT_CALL(*socket, Write).WillOnce(Return(16)); + EXPECT_CALL(*socket, Write).WillOnce(Return(sizeof(HandshakePacket))); EXPECT_CALL(*socket, Read).WillOnce(Return(0)); EXPECT_CALL(delegate_, OnCaptureError);
diff --git a/chromecast/media/audio/capture_service/constants.h b/chromecast/media/audio/capture_service/constants.h index fc44325b..e87050bb0 100644 --- a/chromecast/media/audio/capture_service/constants.h +++ b/chromecast/media/audio/capture_service/constants.h
@@ -78,20 +78,8 @@ int frames_per_buffer = 0; }; -// Info describes the message packet. PacketInfo is only for message types that -// support packet header, i.e., kHandshake and kPcmAudio. |timestamp_us| is -// about when the buffer is captured. If the audio source is from ALSA, i.e., -// stream type is raw mic, it's the ALSA capture timestamp; otherwise, it may be -// shifted based on the samples and sample rate upon raw mic input. -struct PacketInfo { - MessageType message_type; - StreamInfo stream_info; - int64_t timestamp_us = 0; -}; - -// Size of a message header. The header can be parsed into PacketInfo with -// methods in message_parsing_utils.h -constexpr size_t kMessageHeaderBytes = 14; +// Size of a PCM audio message header. +constexpr size_t kPcmAudioHeaderBytes = 10; } // namespace capture_service } // namespace media
diff --git a/chromecast/media/audio/capture_service/message_parsing_fuzzer.cc b/chromecast/media/audio/capture_service/message_parsing_fuzzer.cc index c21c697..f8ec5ce4 100644 --- a/chromecast/media/audio/capture_service/message_parsing_fuzzer.cc +++ b/chromecast/media/audio/capture_service/message_parsing_fuzzer.cc
@@ -14,8 +14,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { static Environment env; - PacketInfo info; - chromecast::media::capture_service::ReadHeader( + StreamInfo info; + chromecast::media::capture_service::ReadHandshakeMessage( reinterpret_cast<const char*>(data), size, &info); return 0; }
diff --git a/chromecast/media/audio/capture_service/message_parsing_utils.cc b/chromecast/media/audio/capture_service/message_parsing_utils.cc index 57f148f..78d07de 100644 --- a/chromecast/media/audio/capture_service/message_parsing_utils.cc +++ b/chromecast/media/audio/capture_service/message_parsing_utils.cc
@@ -10,6 +10,8 @@ #include <limits> #include "base/big_endian.h" +#include "base/check.h" +#include "base/check_op.h" #include "base/logging.h" #include "base/notreached.h" #include "chromecast/media/audio/capture_service/constants.h" @@ -21,12 +23,18 @@ namespace capture_service { namespace { -// Size in bytes of the total message header. -constexpr size_t kTotalHeaderBytes = kMessageHeaderBytes + sizeof(uint16_t); +// Size in bytes of the header part of a handshake message. +constexpr size_t kHandshakeHeaderBytes = + sizeof(HandshakePacket) - sizeof(uint16_t); -static_assert(sizeof(PacketHeader) == kTotalHeaderBytes, - "Invalid packet header size."); -static_assert(offsetof(struct PacketHeader, message_type) == sizeof(uint16_t), +static_assert(kPcmAudioHeaderBytes == + sizeof(PcmPacketHeader) - sizeof(uint16_t), + "Invalid message header size."); +static_assert(offsetof(struct PcmPacketHeader, message_type) == + sizeof(uint16_t), + "Invalid message header offset."); +static_assert(offsetof(struct HandshakePacket, message_type) == + sizeof(uint16_t), "Invalid message header offset."); // Check if audio data is properly aligned and has valid frame size. Return the @@ -141,110 +149,97 @@ return false; } -bool HasPacketHeader(MessageType type) { - // Packet header is only for the messages generated from packet info. For - // other message type such as kOpusAudio and kMetadata, the packet does not - // contain the packet header and only contains the message type and serialized - // data. - return type == MessageType::kHandshake || type == MessageType::kPcmAudio; -} - } // namespace -char* PopulateHeader(char* data, size_t size, const PacketInfo& packet_info) { - DCHECK(HasPacketHeader(packet_info.message_type)); - const StreamInfo& stream_info = packet_info.stream_info; - PacketHeader header; - header.message_type = static_cast<uint8_t>(packet_info.message_type); - header.stream_type = static_cast<uint8_t>(stream_info.stream_type); - header.num_channels = stream_info.num_channels; - header.sample_rate = stream_info.sample_rate; - // In request/ack message, the header contains a codec field and a - // frames_per_buffer field, while in PCM audio message, it instead contains a - // sample format field and a timestamp field. - if (packet_info.message_type == MessageType::kHandshake) { - header.codec_or_sample_format = - static_cast<uint8_t>(stream_info.audio_codec); - header.timestamp_or_frames = stream_info.frames_per_buffer; - } else if (packet_info.message_type == MessageType::kPcmAudio) { - header.codec_or_sample_format = - static_cast<uint8_t>(stream_info.sample_format); - header.timestamp_or_frames = packet_info.timestamp_us; - } else { - NOTREACHED(); - } +void FillBuffer(char* buf, + size_t buf_size, + const void* data, + size_t data_size) { + DCHECK_LE(data_size, buf_size - sizeof(uint16_t)); base::WriteBigEndian( // Deduct the size of |size| itself. - data, static_cast<uint16_t>(size - sizeof(uint16_t))); - DCHECK_EQ(sizeof(header), kTotalHeaderBytes); - memcpy(data + sizeof(uint16_t), &header.message_type, kMessageHeaderBytes); - return data + kTotalHeaderBytes; + buf, static_cast<uint16_t>(buf_size - sizeof(uint16_t))); + memcpy(buf + sizeof(uint16_t), data, data_size); } -bool ReadHeader(const char* data, size_t size, PacketInfo* packet_info) { - DCHECK(packet_info); - if (size < kMessageHeaderBytes) { - LOG(ERROR) << "Message doesn't have a complete header."; +char* PopulatePcmAudioHeader(char* data, + size_t size, + StreamType stream_type, + int64_t timestamp_us) { + PcmPacketHeader header; + header.message_type = static_cast<uint8_t>(MessageType::kPcmAudio); + header.stream_type = static_cast<uint8_t>(stream_type); + header.timestamp_us = timestamp_us; + FillBuffer(data, size, &header.message_type, + sizeof(header) - sizeof(uint16_t)); + return data + sizeof(header); +} + +void PopulateHandshakeMessage(char* data, + size_t size, + const StreamInfo& stream_info) { + HandshakePacket packet; + packet.message_type = static_cast<uint8_t>(MessageType::kHandshake); + packet.stream_type = static_cast<uint8_t>(stream_info.stream_type); + packet.audio_codec = static_cast<uint8_t>(stream_info.audio_codec); + packet.sample_format = static_cast<uint8_t>(stream_info.sample_format); + packet.num_channels = stream_info.num_channels; + packet.num_frames = stream_info.frames_per_buffer; + packet.sample_rate = stream_info.sample_rate; + FillBuffer(data, size, &packet.message_type, + sizeof(packet) - sizeof(uint16_t)); +} + +bool ReadPcmAudioHeader(const char* data, + size_t size, + const StreamInfo& stream_info, + int64_t* timestamp_us) { + DCHECK(timestamp_us); + if (size < kPcmAudioHeaderBytes) { + LOG(ERROR) << "Message doesn't have a complete header: " << size << " v.s. " + << kPcmAudioHeaderBytes << "."; return false; } - PacketHeader header; - memcpy(&header.message_type, data, kMessageHeaderBytes); - MessageType message_type = static_cast<MessageType>(header.message_type); - uint8_t last_codec_or_sample_format = - (message_type == MessageType::kHandshake) - ? static_cast<uint8_t>(AudioCodec::kLastCodec) - : static_cast<uint8_t>(SampleFormat::LAST_FORMAT); - if (!HasPacketHeader(message_type) || - header.stream_type > static_cast<uint8_t>(StreamType::kLastType) || - header.codec_or_sample_format > last_codec_or_sample_format) { - LOG(ERROR) << "Invalid message header."; + PcmPacketHeader header; + memcpy(&header.message_type, data, kPcmAudioHeaderBytes); + if (static_cast<MessageType>(header.message_type) != MessageType::kPcmAudio) { + LOG(ERROR) << "Message type mismatch."; return false; } - if (header.num_channels > ::media::limits::kMaxChannels) { - LOG(ERROR) << "Invalid number of channels: " << header.num_channels; + if (static_cast<StreamType>(header.stream_type) != stream_info.stream_type) { + LOG(ERROR) << "Stream type mistach."; return false; } - packet_info->message_type = message_type; - packet_info->stream_info.stream_type = - static_cast<StreamType>(header.stream_type); - packet_info->stream_info.num_channels = header.num_channels; - packet_info->stream_info.sample_rate = header.sample_rate; - if (message_type == MessageType::kHandshake) { - packet_info->stream_info.audio_codec = - static_cast<AudioCodec>(header.codec_or_sample_format); - packet_info->stream_info.frames_per_buffer = header.timestamp_or_frames; - } else if (message_type == MessageType::kPcmAudio) { - packet_info->stream_info.sample_format = - static_cast<SampleFormat>(header.codec_or_sample_format); - packet_info->timestamp_us = header.timestamp_or_frames; - } else { - NOTREACHED(); - } + *timestamp_us = header.timestamp_us; return true; } -scoped_refptr<net::IOBufferWithSize> MakeMessage(const PacketInfo& packet_info, - const char* data, - size_t data_size) { - if (!HasPacketHeader(packet_info.message_type)) { - LOG(ERROR) - << "Only kHandshake and kPcmAudio message have packet header, use " - "MakeSerializedMessage otherwise."; - return nullptr; - } - const size_t total_size = kTotalHeaderBytes + data_size; +scoped_refptr<net::IOBufferWithSize> MakePcmAudioMessage(StreamType stream_type, + int64_t timestamp_us, + const char* data, + size_t data_size) { + const size_t total_size = sizeof(PcmPacketHeader) + data_size; DCHECK_LE(total_size, std::numeric_limits<uint16_t>::max()); auto io_buffer = base::MakeRefCounted<net::IOBufferWithSize>(total_size); - char* ptr = PopulateHeader(io_buffer->data(), io_buffer->size(), packet_info); + char* ptr = PopulatePcmAudioHeader(io_buffer->data(), io_buffer->size(), + stream_type, timestamp_us); if (!ptr) { return nullptr; } - if (packet_info.message_type == MessageType::kPcmAudio && data_size > 0) { + if (data_size > 0) { DCHECK(data); std::copy(data, data + data_size, ptr); } return io_buffer; } +scoped_refptr<net::IOBufferWithSize> MakeHandshakeMessage( + const StreamInfo& stream_info) { + auto io_buffer = + base::MakeRefCounted<net::IOBufferWithSize>(sizeof(HandshakePacket)); + PopulateHandshakeMessage(io_buffer->data(), io_buffer->size(), stream_info); + return io_buffer; +} + scoped_refptr<net::IOBufferWithSize> MakeSerializedMessage( MessageType message_type, const char* data, @@ -278,22 +273,51 @@ DCHECK(audio_bus); DCHECK_EQ(stream_info.num_channels, audio_bus->channels()); return ConvertData(stream_info.num_channels, stream_info.sample_format, - data + kMessageHeaderBytes, size - kMessageHeaderBytes, + data + kPcmAudioHeaderBytes, size - kPcmAudioHeaderBytes, audio_bus); } bool ReadPcmAudioMessage(const char* data, size_t size, - PacketInfo* packet_info, + const StreamInfo& stream_info, + int64_t* timestamp_us, ::media::AudioBus* audio_bus) { - if (!ReadHeader(data, size, packet_info)) { + if (!ReadPcmAudioHeader(data, size, stream_info, timestamp_us)) { return false; } - if (packet_info->message_type != MessageType::kPcmAudio) { - LOG(WARNING) << "Received non-pcm-audio message."; + return ReadDataToAudioBus(stream_info, data, size, audio_bus); +} + +bool ReadHandshakeMessage(const char* data, + size_t size, + StreamInfo* stream_info) { + DCHECK(stream_info); + if (size != kHandshakeHeaderBytes) { + LOG(ERROR) << "Message doesn't have a complete handshake packet: " << size + << " v.s. " << kHandshakeHeaderBytes << "."; return false; } - return ReadDataToAudioBus(packet_info->stream_info, data, size, audio_bus); + HandshakePacket packet; + memcpy(&packet.message_type, data, kHandshakeHeaderBytes); + MessageType message_type = static_cast<MessageType>(packet.message_type); + if (message_type != MessageType::kHandshake || + packet.stream_type > static_cast<uint8_t>(StreamType::kLastType) || + packet.audio_codec > static_cast<uint8_t>(AudioCodec::kLastCodec) || + packet.sample_format > static_cast<uint8_t>(SampleFormat::LAST_FORMAT)) { + LOG(ERROR) << "Invalid message header."; + return false; + } + if (packet.num_channels > ::media::limits::kMaxChannels) { + LOG(ERROR) << "Invalid number of channels: " << packet.num_channels; + return false; + } + stream_info->stream_type = static_cast<StreamType>(packet.stream_type); + stream_info->audio_codec = static_cast<AudioCodec>(packet.audio_codec); + stream_info->sample_format = static_cast<SampleFormat>(packet.sample_format); + stream_info->num_channels = packet.num_channels; + stream_info->frames_per_buffer = packet.num_frames; + stream_info->sample_rate = packet.sample_rate; + return true; } size_t DataSizeInBytes(const StreamInfo& stream_info) {
diff --git a/chromecast/media/audio/capture_service/message_parsing_utils.h b/chromecast/media/audio/capture_service/message_parsing_utils.h index 9140b42..3aef84f 100644 --- a/chromecast/media/audio/capture_service/message_parsing_utils.h +++ b/chromecast/media/audio/capture_service/message_parsing_utils.h
@@ -16,31 +16,33 @@ namespace media { namespace capture_service { -// Read message header to |packet_info|, and return whether success. -// The header of the message consists of <uint8_t message_type> -// <uint8_t stream_type> <uint8_t audio_codec|sample_format> <uint8_t channels> -// <uint16_t sample_rate> <uint64_t frames_per_buffer|timestamp_us>. -// If |message_type| is kHandshake, it is a handshake message that has -// |audio_codec| and |frames_per_buffer|, otherwise if |message_type| is -// kPcmAudio, it's a PCM audio data message that has |sample_format| and -// |timestamp_us|. Note it cannot be used to read kOpusAudio or kMetadata -// messages, which don't have header besides |message_type| bits. Note -// |packet_info| will be untouched if fails to read header. Note unsigned -// |timestamp_us| will be converted to signed |timestamp| if valid. Note |data| -// here has been parsed firstly by SmallMessageSocket, and thus doesn't have -// <uint16_t size> bits. -bool ReadHeader(const char* data, size_t size, PacketInfo* packet_info); +// Read message header, check if it matches |stream_info|, retrieve timestamp, +// and return whether success. +// Note |data| here has been parsed firstly by SmallMessageSocket, and thus +// doesn't have <uint16_t size> bits. +bool ReadPcmAudioHeader(const char* data, + size_t size, + const StreamInfo& stream_info, + int64_t* timestamp_us); -// Make a IO buffer for stream message. It will populate the header with -// |packet_info|, and copy |data| into the message if packet has audio and -// |data| is not null. The returned buffer will have a length of |data_size| + -// header size. Return nullptr if fails. Caller must guarantee the memory of -// |data| has at least |data_size| when has audio. +// Make a IO buffer for stream message. It will populate the header and copy +// |data| into the message if packet has audio and |data| is not null. The +// returned buffer will have a length of |data_size| + header size. Return +// nullptr if fails. Caller must guarantee the memory of |data| has at least +// |data_size| when has audio. // Note buffer will be sent with SmallMessageSocket, and thus contains a uint16 // size field in the very first. -scoped_refptr<net::IOBufferWithSize> MakeMessage(const PacketInfo& packet_info, - const char* data, - size_t data_size); +scoped_refptr<net::IOBufferWithSize> MakePcmAudioMessage(StreamType stream_type, + int64_t timestamp_us, + const char* data, + size_t data_size); + +// Make a IO buffer for handshake message. It will populate the header with +// |stream_info|. Return nullptr if fails. +// Note buffer will be sent with SmallMessageSocket, and thus contains a uint16 +// size field in the very first. +scoped_refptr<net::IOBufferWithSize> MakeHandshakeMessage( + const StreamInfo& stream_info); // Make a IO buffer for serialized message. It will populate message size and // type fields, and copy |data| into the message. The returned buffer will have @@ -60,21 +62,43 @@ size_t size, ::media::AudioBus* audio_bus); -// Read the header part of the PCM audio message to packet info and the audio -// data part to audio bus, and return whether success. This will run -// ReadHeader() and ReadDataToAudioBus() in the underlying implementation. +// Read the PCM audio message and copy the audio data to audio bus, as well as +// the timestamp. Return whether success. This will run ReadPcmAudioHeader() and +// ReadDataToAudioBus() in the underlying implementation. bool ReadPcmAudioMessage(const char* data, size_t size, - PacketInfo* packet_info, + const StreamInfo& stream_info, + int64_t* timestamp_us, ::media::AudioBus* audio_bus); -// Populate header of the message, including the SmallMessageSocket size bits. -// Note this is used by unittest, user should use MakeMessage directly. -char* PopulateHeader(char* data, size_t size, const PacketInfo& stream_info); +// Read the handshake message to |stream_info|, and return true on success. +bool ReadHandshakeMessage(const char* data, + size_t size, + StreamInfo* stream_info); // Return the expected size of the data of a stream message with |stream_info|. size_t DataSizeInBytes(const StreamInfo& stream_info); +// Following methods are exposed for unittests: + +// Write |buf_size|, in big-endian order, to |buf|, and fill |data| to |buf| +// afterward. +void FillBuffer(char* buf, size_t buf_size, const void* data, size_t data_size); + +// Populate header of the PCM audio message, including the SmallMessageSocket +// size bits. +// Note this is used by unittest, user should use MakePcmAudioMessage directly. +char* PopulatePcmAudioHeader(char* data, + size_t size, + StreamType stream_type, + int64_t timestamp_us); + +// Populate the handshake message, including the SmallMessageSocket size bits. +// Note this is used by unittest, user should use MakeHandshakeMessage directly. +void PopulateHandshakeMessage(char* data, + size_t size, + const StreamInfo& stream_info); + } // namespace capture_service } // namespace media } // namespace chromecast
diff --git a/chromecast/media/audio/capture_service/message_parsing_utils_unittest.cc b/chromecast/media/audio/capture_service/message_parsing_utils_unittest.cc index 8ed8fa7..ed6feafe 100644 --- a/chromecast/media/audio/capture_service/message_parsing_utils_unittest.cc +++ b/chromecast/media/audio/capture_service/message_parsing_utils_unittest.cc
@@ -16,7 +16,6 @@ namespace capture_service { namespace { -constexpr size_t kTotalHeaderBytes = 16; constexpr size_t kFrames = 10; constexpr size_t kChannels = 2; constexpr StreamInfo kStreamInfo = @@ -26,37 +25,72 @@ SampleFormat::PLANAR_FLOAT, 16000, kFrames}; -constexpr PacketInfo kHandshakePacketInfo = {MessageType::kHandshake, - kStreamInfo, 0}; -constexpr PacketInfo kPcmAudioPacketInfo = {MessageType::kPcmAudio, kStreamInfo, - 0}; + +class PacketHeaderTest + : public testing::TestWithParam< + std::tuple<StreamType, AudioCodec, int, SampleFormat, int, int>> { + protected: + StreamInfo GetStreamInfo() { + StreamInfo info; + info.stream_type = std::get<0>(GetParam()); + info.audio_codec = std::get<1>(GetParam()); + info.num_channels = std::get<2>(GetParam()); + info.sample_format = std::get<3>(GetParam()); + info.sample_rate = std::get<4>(GetParam()); + info.frames_per_buffer = std::get<5>(GetParam()); + return info; + } +}; + +TEST_P(PacketHeaderTest, HandshakeMessage) { + std::vector<char> data(sizeof(HandshakePacket), 0); + StreamInfo stream_info = GetStreamInfo(); + PopulateHandshakeMessage(data.data(), data.size(), stream_info); + + StreamInfo info_out; + bool success = + ReadHandshakeMessage(data.data() + sizeof(uint16_t), + data.size() - sizeof(uint16_t), &info_out); + EXPECT_TRUE(success); + EXPECT_EQ(info_out.stream_type, stream_info.stream_type); + EXPECT_EQ(info_out.audio_codec, stream_info.audio_codec); + EXPECT_EQ(info_out.sample_format, stream_info.sample_format); + EXPECT_EQ(info_out.num_channels, stream_info.num_channels); + EXPECT_EQ(info_out.sample_rate, stream_info.sample_rate); + EXPECT_EQ(info_out.frames_per_buffer, stream_info.frames_per_buffer); +} + +TEST(MessageParsingUtilsTest, PcmAudioMessage) { + size_t data_size = sizeof(PcmPacketHeader) / sizeof(float); + std::vector<float> data(data_size, 1.0f); + int64_t timestamp_us = 100; + PopulatePcmAudioHeader(reinterpret_cast<char*>(data.data()), + data.size() * sizeof(float), kStreamInfo.stream_type, + timestamp_us); + + int64_t timestamp_out = 0; + bool success = ReadPcmAudioHeader( + reinterpret_cast<char*>(data.data()) + sizeof(uint16_t), + data_size * sizeof(float) - sizeof(uint16_t), kStreamInfo, + ×tamp_out); + EXPECT_TRUE(success); + EXPECT_EQ(timestamp_out, timestamp_us); +} TEST(MessageParsingUtilsTest, ValidPlanarFloat) { - size_t data_size = kTotalHeaderBytes / sizeof(float) + kFrames * kChannels; + size_t data_size = + sizeof(PcmPacketHeader) / sizeof(float) + kFrames * kChannels; std::vector<float> data(data_size, .0f); - PopulateHeader(reinterpret_cast<char*>(data.data()), - data.size() * sizeof(float), kPcmAudioPacketInfo); + PopulatePcmAudioHeader(reinterpret_cast<char*>(data.data()), + data.size() * sizeof(float), kStreamInfo.stream_type, + 0); // Fill the last k frames, i.e., the second channel, with 0.5f. for (size_t i = data_size - kFrames; i < data_size; i++) { data[i] = .5f; } - // Audio header. - PacketInfo info; - bool success = - ReadHeader(reinterpret_cast<char*>(data.data()) + sizeof(uint16_t), - data_size * sizeof(float) - sizeof(uint16_t), &info); - EXPECT_TRUE(success); - EXPECT_EQ(info.message_type, kPcmAudioPacketInfo.message_type); - EXPECT_EQ(info.stream_info.stream_type, kStreamInfo.stream_type); - EXPECT_EQ(info.stream_info.num_channels, kStreamInfo.num_channels); - EXPECT_EQ(info.stream_info.sample_format, kStreamInfo.sample_format); - EXPECT_EQ(info.stream_info.sample_rate, kStreamInfo.sample_rate); - EXPECT_EQ(info.timestamp_us, kPcmAudioPacketInfo.timestamp_us); - - // Audio data. auto audio_bus = ::media::AudioBus::Create(kChannels, kFrames); - success = ReadDataToAudioBus( + bool success = ReadDataToAudioBus( kStreamInfo, reinterpret_cast<char*>(data.data()) + sizeof(uint16_t), data_size * sizeof(float) - sizeof(uint16_t), audio_bus.get()); EXPECT_TRUE(success); @@ -67,22 +101,23 @@ } TEST(MessageParsingUtilsTest, ValidInterleavedInt16) { - size_t data_size = kTotalHeaderBytes / sizeof(int16_t) + kFrames * kChannels; + size_t data_size = + sizeof(PcmPacketHeader) / sizeof(int16_t) + kFrames * kChannels; std::vector<int16_t> data(data_size, std::numeric_limits<int16_t>::max()); - PacketInfo packet_info = kPcmAudioPacketInfo; - packet_info.stream_info.sample_format = SampleFormat::INTERLEAVED_INT16; - PopulateHeader(reinterpret_cast<char*>(data.data()), - data.size() * sizeof(int16_t), packet_info); + PopulatePcmAudioHeader(reinterpret_cast<char*>(data.data()), + data.size() * sizeof(int16_t), kStreamInfo.stream_type, + 0); // Fill the second channel with min(). - for (size_t i = kTotalHeaderBytes / sizeof(int16_t) + 1; i < data_size; + for (size_t i = sizeof(PcmPacketHeader) / sizeof(int16_t) + 1; i < data_size; i += 2) { data[i] = std::numeric_limits<int16_t>::min(); } auto audio_bus = ::media::AudioBus::Create(kChannels, kFrames); + StreamInfo stream_info = kStreamInfo; + stream_info.sample_format = SampleFormat::INTERLEAVED_INT16; bool success = ReadDataToAudioBus( - packet_info.stream_info, - reinterpret_cast<char*>(data.data()) + sizeof(uint16_t), + stream_info, reinterpret_cast<char*>(data.data()) + sizeof(uint16_t), data_size * sizeof(int16_t) - sizeof(uint16_t), audio_bus.get()); EXPECT_TRUE(success); for (size_t f = 0; f < kFrames; f++) { @@ -92,22 +127,23 @@ } TEST(MessageParsingUtilsTest, ValidInterleavedInt32) { - size_t data_size = kTotalHeaderBytes / sizeof(int32_t) + kFrames * kChannels; + size_t data_size = + sizeof(PcmPacketHeader) / sizeof(int32_t) + kFrames * kChannels; std::vector<int32_t> data(data_size, std::numeric_limits<int32_t>::min()); - PacketInfo packet_info = kPcmAudioPacketInfo; - packet_info.stream_info.sample_format = SampleFormat::INTERLEAVED_INT32; - PopulateHeader(reinterpret_cast<char*>(data.data()), - data.size() * sizeof(int32_t), packet_info); + PopulatePcmAudioHeader(reinterpret_cast<char*>(data.data()), + data.size() * sizeof(int32_t), kStreamInfo.stream_type, + 0); // Fill the second channel with max(). - for (size_t i = kTotalHeaderBytes / sizeof(int32_t) + 1; i < data_size; + for (size_t i = sizeof(PcmPacketHeader) / sizeof(int32_t) + 1; i < data_size; i += 2) { data[i] = std::numeric_limits<int32_t>::max(); } auto audio_bus = ::media::AudioBus::Create(kChannels, kFrames); + StreamInfo stream_info = kStreamInfo; + stream_info.sample_format = SampleFormat::INTERLEAVED_INT32; bool success = ReadDataToAudioBus( - packet_info.stream_info, - reinterpret_cast<char*>(data.data()) + sizeof(uint16_t), + stream_info, reinterpret_cast<char*>(data.data()) + sizeof(uint16_t), data_size * sizeof(int32_t) - sizeof(uint16_t), audio_bus.get()); EXPECT_TRUE(success); for (size_t f = 0; f < kFrames; f++) { @@ -116,92 +152,68 @@ } } -TEST(MessageParsingUtilsTest, InvalidType) { - size_t data_size = kTotalHeaderBytes / sizeof(float); - std::vector<float> data(data_size, 1.0f); - // Request packet - PacketInfo request_packet_info = kHandshakePacketInfo; - PopulateHeader(reinterpret_cast<char*>(data.data()), - data.size() * sizeof(float), request_packet_info); +TEST(MessageParsingUtilsTest, InvalidTypeHandshake) { + std::vector<char> data(sizeof(HandshakePacket), 0); + StreamInfo stream_info = kStreamInfo; + PopulateHandshakeMessage(data.data(), data.size(), stream_info); *(reinterpret_cast<uint8_t*>(data.data()) + - offsetof(struct PacketHeader, stream_type)) = + offsetof(struct HandshakePacket, stream_type)) = static_cast<uint8_t>(StreamType::kLastType) + 1; - bool success = ReadHeader( - reinterpret_cast<char*>(data.data()) + sizeof(uint16_t), - data_size * sizeof(float) - sizeof(uint16_t), &request_packet_info); + bool success = + ReadHandshakeMessage(data.data() + sizeof(uint16_t), + data.size() - sizeof(uint16_t), &stream_info); EXPECT_FALSE(success); +} - // PCM audio packet - PacketInfo pcm_audio_packet_info = kPcmAudioPacketInfo; - PopulateHeader(reinterpret_cast<char*>(data.data()), - data.size() * sizeof(float), pcm_audio_packet_info); +TEST(MessageParsingUtilsTest, InvalidTypePcmAudio) { + size_t data_size = sizeof(PcmPacketHeader) / sizeof(float); + std::vector<float> data(data_size, 1.0f); + PopulatePcmAudioHeader(reinterpret_cast<char*>(data.data()), + data.size() * sizeof(float), kStreamInfo.stream_type, + 0); *(reinterpret_cast<uint8_t*>(data.data()) + - offsetof(struct PacketHeader, stream_type)) = + offsetof(struct PcmPacketHeader, stream_type)) = static_cast<uint8_t>(StreamType::kLastType) + 1; - success = ReadHeader(reinterpret_cast<char*>(data.data()) + sizeof(uint16_t), - data_size * sizeof(float) - sizeof(uint16_t), - &pcm_audio_packet_info); + int64_t timestamp_us; + bool success = ReadPcmAudioHeader( + reinterpret_cast<char*>(data.data()) + sizeof(uint16_t), + data_size * sizeof(float) - sizeof(uint16_t), kStreamInfo, ×tamp_us); EXPECT_FALSE(success); } TEST(MessageParsingUtilsTest, InvalidCodec) { - size_t data_size = kTotalHeaderBytes / sizeof(float); - std::vector<float> data(data_size, 1.0f); - PacketInfo packet_info = kHandshakePacketInfo; - PopulateHeader(reinterpret_cast<char*>(data.data()), - data.size() * sizeof(float), packet_info); + std::vector<char> data(sizeof(HandshakePacket), 0); + StreamInfo stream_info = kStreamInfo; + PopulateHandshakeMessage(data.data(), data.size(), stream_info); *(reinterpret_cast<uint8_t*>(data.data()) + - offsetof(struct PacketHeader, codec_or_sample_format)) = + offsetof(struct HandshakePacket, audio_codec)) = static_cast<uint8_t>(AudioCodec::kLastCodec) + 1; - bool success = - ReadHeader(reinterpret_cast<char*>(data.data()) + sizeof(uint16_t), - data_size * sizeof(float) - sizeof(uint16_t), &packet_info); + ReadHandshakeMessage(data.data() + sizeof(uint16_t), + data.size() - sizeof(uint16_t), &stream_info); EXPECT_FALSE(success); } TEST(MessageParsingUtilsTest, InvalidFormat) { - size_t data_size = kTotalHeaderBytes / sizeof(float); - std::vector<float> data(data_size, 1.0f); - PacketInfo packet_info = kPcmAudioPacketInfo; - PopulateHeader(reinterpret_cast<char*>(data.data()), - data.size() * sizeof(float), packet_info); + std::vector<char> data(sizeof(HandshakePacket), 0); + StreamInfo stream_info = kStreamInfo; + PopulateHandshakeMessage(data.data(), data.size(), stream_info); *(reinterpret_cast<uint8_t*>(data.data()) + - offsetof(struct PacketHeader, codec_or_sample_format)) = + offsetof(struct HandshakePacket, sample_format)) = static_cast<uint8_t>(SampleFormat::LAST_FORMAT) + 1; - bool success = - ReadHeader(reinterpret_cast<char*>(data.data()) + sizeof(uint16_t), - data_size * sizeof(float) - sizeof(uint16_t), &packet_info); + ReadHandshakeMessage(data.data() + sizeof(uint16_t), + data.size() - sizeof(uint16_t), &stream_info); EXPECT_FALSE(success); } -TEST(MessageParsingUtilsTest, RequestMessage) { - size_t data_size = kTotalHeaderBytes / sizeof(float); - std::vector<float> data(data_size, 1.0f); - PacketInfo packet_info = kHandshakePacketInfo; - PopulateHeader(reinterpret_cast<char*>(data.data()), - data.size() * sizeof(float), packet_info); - - PacketInfo info; - bool success = - ReadHeader(reinterpret_cast<char*>(data.data()) + sizeof(uint16_t), - data_size * sizeof(float) - sizeof(uint16_t), &info); - EXPECT_TRUE(success); - EXPECT_EQ(info.message_type, kHandshakePacketInfo.message_type); - EXPECT_EQ(info.stream_info.stream_type, kStreamInfo.stream_type); - EXPECT_EQ(info.stream_info.audio_codec, kStreamInfo.audio_codec); - EXPECT_EQ(info.stream_info.num_channels, kStreamInfo.num_channels); - EXPECT_EQ(info.stream_info.sample_rate, kStreamInfo.sample_rate); - EXPECT_EQ(info.stream_info.frames_per_buffer, kStreamInfo.frames_per_buffer); -} - TEST(MessageParsingUtilsTest, InvalidDataLength) { size_t data_size = - kTotalHeaderBytes / sizeof(float) + kFrames * kChannels + 1; + sizeof(PcmPacketHeader) / sizeof(float) + kFrames * kChannels + 1; std::vector<float> data(data_size, 1.0f); - PopulateHeader(reinterpret_cast<char*>(data.data()), - data.size() * sizeof(float), kPcmAudioPacketInfo); + PopulatePcmAudioHeader(reinterpret_cast<char*>(data.data()), + data.size() * sizeof(float), kStreamInfo.stream_type, + 0); auto audio_bus = ::media::AudioBus::Create(kChannels, kFrames); bool success = ReadDataToAudioBus( @@ -212,10 +224,11 @@ TEST(MessageParsingUtilsTest, NotAlignedData) { size_t data_size = - kTotalHeaderBytes / sizeof(float) + kFrames * kChannels + 1; + sizeof(PcmPacketHeader) / sizeof(float) + kFrames * kChannels + 1; std::vector<float> data(data_size, 1.0f); - PopulateHeader(reinterpret_cast<char*>(data.data()) + 1, - data.size() * sizeof(float) - 1, kPcmAudioPacketInfo); + PopulatePcmAudioHeader(reinterpret_cast<char*>(data.data()) + 1, + data.size() * sizeof(float) - 1, + kStreamInfo.stream_type, 0); auto audio_bus = ::media::AudioBus::Create(kChannels, kFrames); bool success = ReadDataToAudioBus( @@ -224,6 +237,18 @@ EXPECT_FALSE(success); } +INSTANTIATE_TEST_SUITE_P( + MessageParsingUtilsTest, + PacketHeaderTest, + testing::Combine(testing::Values(StreamType::kMicRaw, + StreamType::kHardwareEchoRescaled), + testing::Values(AudioCodec::kPcm, AudioCodec::kOpus), + testing::Values(1, 8), + testing::Values(SampleFormat::INTERLEAVED_INT16, + SampleFormat::PLANAR_FLOAT), + testing::Values(16000, 96000), + testing::Values(0, 32761))); + } // namespace } // namespace capture_service } // namespace media
diff --git a/chromecast/media/audio/capture_service/packet_header.h b/chromecast/media/audio/capture_service/packet_header.h index dee72c9..2f5b6ec 100644 --- a/chromecast/media/audio/capture_service/packet_header.h +++ b/chromecast/media/audio/capture_service/packet_header.h
@@ -11,19 +11,29 @@ namespace media { namespace capture_service { -// Memory block of a packet header. Changes to it need to make sure about the -// memory alignment to avoid extra paddings being inserted. It reflects real -// packet header structure, however, the |size| bits are in big-endian order, -// and thus is only for padding purpose in this struct, when all bytes after it -// represent a message header. -struct __attribute__((__packed__)) PacketHeader { +// Memory block of a PCM audio packet header. Changes to it need to ensure the +// size is a multiple of 4 bytes. It reflects real packet header structure, +// however, the |size| bits are in big-endian order, and thus is only for +// padding purpose in this struct, when all bytes after it represent a message +// header. +struct __attribute__((__packed__)) PcmPacketHeader { uint16_t size; uint8_t message_type; uint8_t stream_type; - uint8_t codec_or_sample_format; + int64_t timestamp_us; +}; + +// Memory block of a handshake packet. There is no size restriction for this +// structure. +struct __attribute__((__packed__)) HandshakePacket { + uint16_t size; + uint8_t message_type; + uint8_t stream_type; + uint8_t audio_codec; + uint8_t sample_format; uint8_t num_channels; - uint16_t sample_rate; - int64_t timestamp_or_frames; + uint16_t num_frames; + uint32_t sample_rate; }; } // namespace capture_service
diff --git a/chromecast/media/audio/cast_audio_input_stream.cc b/chromecast/media/audio/cast_audio_input_stream.cc index e8607101..12c7629 100644 --- a/chromecast/media/audio/cast_audio_input_stream.cc +++ b/chromecast/media/audio/cast_audio_input_stream.cc
@@ -48,14 +48,14 @@ audio_bus_ = ::media::AudioBus::Create(audio_params_.channels(), audio_params_.frames_per_buffer()); - capture_service_receiver_ = std::make_unique<CaptureServiceReceiver>( - capture_service::StreamInfo{ - capture_service::StreamType::kSoftwareEchoCancelled, - capture_service::AudioCodec::kPcm, audio_params_.channels(), - // Format doesn't matter in the request. - capture_service::SampleFormat::LAST_FORMAT, - audio_params_.sample_rate(), audio_params_.frames_per_buffer()}, - this); + stream_info_ = capture_service::StreamInfo{ + capture_service::StreamType::kSoftwareEchoCancelled, + capture_service::AudioCodec::kPcm, audio_params_.channels(), + // Format doesn't matter in the request. + capture_service::SampleFormat::LAST_FORMAT, audio_params_.sample_rate(), + audio_params_.frames_per_buffer()}; + capture_service_receiver_ = + std::make_unique<CaptureServiceReceiver>(stream_info_, this); return true; } @@ -117,33 +117,40 @@ bool CastAudioInputStream::OnInitialStreamInfo( const capture_service::StreamInfo& stream_info) { const bool is_params_match = - stream_info.stream_type == - capture_service::StreamType::kSoftwareEchoCancelled && - stream_info.audio_codec == capture_service::AudioCodec::kPcm && - stream_info.num_channels == audio_params_.channels() && - stream_info.sample_rate == audio_params_.sample_rate() && - stream_info.frames_per_buffer == audio_params_.frames_per_buffer(); + stream_info.stream_type == stream_info_.stream_type && + stream_info.audio_codec == stream_info_.audio_codec && + stream_info.num_channels == stream_info_.num_channels && + stream_info.sample_rate == stream_info_.sample_rate && + stream_info.frames_per_buffer == stream_info_.frames_per_buffer; LOG_IF(ERROR, !is_params_match) - << "Got different parameters from sender, sample_rate: " - << audio_params_.sample_rate() << " Hz -> " << stream_info.sample_rate - << " Hz, num_channels: " << audio_params_.channels() << " -> " + << "Got different parameters from sender, stream_type: " + << static_cast<int>(stream_info_.stream_type) << " -> " + << static_cast<int>(stream_info.stream_type) + << ", audio_codec: " << static_cast<int>(stream_info_.audio_codec) + << " -> " << static_cast<int>(stream_info.audio_codec) + << ", sample_rate: " << stream_info_.sample_rate << " Hz -> " + << stream_info.sample_rate + << " Hz, num_channels: " << stream_info_.num_channels << " -> " << stream_info.num_channels - << ", frames_per_buffer: " << audio_params_.frames_per_buffer() << " -> " + << ", frames_per_buffer: " << stream_info_.frames_per_buffer << " -> " << stream_info.frames_per_buffer << "."; + stream_info_.sample_format = stream_info.sample_format; + LOG(INFO) << "Set sample_format: " + << static_cast<int>(stream_info.sample_format); return is_params_match; } bool CastAudioInputStream::OnCaptureData(const char* data, size_t size) { - capture_service::PacketInfo info; - if (!capture_service::ReadPcmAudioMessage(data, size, &info, - audio_bus_.get())) { + int64_t timestamp_us; + if (!capture_service::ReadPcmAudioMessage(data, size, stream_info_, + ×tamp_us, audio_bus_.get())) { return false; } DCHECK(input_callback_); input_callback_->OnData( audio_bus_.get(), - base::TimeTicks() + base::TimeDelta::FromMicroseconds(info.timestamp_us), + base::TimeTicks() + base::TimeDelta::FromMicroseconds(timestamp_us), /* volume */ 1.0); return true; }
diff --git a/chromecast/media/audio/cast_audio_input_stream.h b/chromecast/media/audio/cast_audio_input_stream.h index 7d222029..4f06e1e 100644 --- a/chromecast/media/audio/cast_audio_input_stream.h +++ b/chromecast/media/audio/cast_audio_input_stream.h
@@ -10,6 +10,7 @@ #include "base/threading/thread_checker.h" #include "chromecast/media/audio/capture_service/capture_service_receiver.h" +#include "chromecast/media/audio/capture_service/constants.h" #include "media/audio/audio_io.h" #include "media/base/audio_bus.h" #include "media/base/audio_parameters.h" @@ -58,6 +59,7 @@ // may be null, if |this| is not created by audio manager, e.g., in unit test. ::media::AudioManagerBase* const audio_manager_; const ::media::AudioParameters audio_params_; + capture_service::StreamInfo stream_info_; std::unique_ptr<CaptureServiceReceiver> capture_service_receiver_; AudioInputCallback* input_callback_ = nullptr; std::unique_ptr<::media::AudioBus> audio_bus_;
diff --git a/chromecast/media/cma/BUILD.gn b/chromecast/media/cma/BUILD.gn index 0a26786..901ac35 100644 --- a/chromecast/media/cma/BUILD.gn +++ b/chromecast/media/cma/BUILD.gn
@@ -51,6 +51,7 @@ testonly = true sources = [ "backend/audio_video_pipeline_device_unittest.cc", + "backend/proxy/cma_backend_proxy_unittest.cc", "base/balanced_media_task_runner_unittest.cc", "base/buffering_controller_unittest.cc", "base/buffering_frame_provider_unittest.cc", @@ -71,6 +72,7 @@ "//chromecast/media:libcast_media", "//chromecast/media/api", "//chromecast/media/api:test_support", + "//chromecast/media/cma/backend/proxy", "//media", "//testing/gmock", "//testing/gtest",
diff --git a/chromecast/media/cma/backend/BUILD.gn b/chromecast/media/cma/backend/BUILD.gn index 8a1f641..f19c87b 100644 --- a/chromecast/media/cma/backend/BUILD.gn +++ b/chromecast/media/cma/backend/BUILD.gn
@@ -44,6 +44,10 @@ "//chromecast/media/cma/decoder", ] + if (enable_chromium_runtime_cast_renderer) { + deps += [ "//chromecast/media/cma/backend/proxy" ] + } + if (have_full_mixer) { sources += [ "media_pipeline_backend_manager_mixer.cc" ] deps += [ "//chromecast/media/audio/mixer_service:control_connection" ]
diff --git a/chromecast/media/cma/backend/android/audio_sink_android.cc b/chromecast/media/cma/backend/android/audio_sink_android.cc index 88da3e2e..54ccaf6 100644 --- a/chromecast/media/cma/backend/android/audio_sink_android.cc +++ b/chromecast/media/cma/backend/android/audio_sink_android.cc
@@ -12,22 +12,6 @@ namespace media { // static -const char* GetAudioContentTypeName(const AudioContentType type) { - switch (type) { - case AudioContentType::kMedia: - return "kMedia"; - case AudioContentType::kAlarm: - return "kAlarm"; - case AudioContentType::kCommunication: - return "kCommunication"; - case AudioContentType::kOther: - return "kOther"; - default: - return "Unknown"; - } -} - -// static bool AudioSinkAndroid::GetSessionIds(SinkType sink_type, int* media_id, int* communication_id) {
diff --git a/chromecast/media/cma/backend/android/audio_sink_android.h b/chromecast/media/cma/backend/android/audio_sink_android.h index acf9d61..f9cd4c6 100644 --- a/chromecast/media/cma/backend/android/audio_sink_android.h +++ b/chromecast/media/cma/backend/android/audio_sink_android.h
@@ -20,8 +20,6 @@ const int kDefaultSlewTimeMs = 15; -const char* GetAudioContentTypeName(const AudioContentType type); - class DecoderBufferBase; // Input handle to the sink. All methods (including constructor and destructor) @@ -101,7 +99,6 @@ virtual bool primary() const = 0; virtual std::string device_id() const = 0; virtual AudioContentType content_type() const = 0; - virtual const char* GetContentTypeName() const = 0; }; // Implementation of "managed" AudioSinkAndroid* object that is
diff --git a/chromecast/media/cma/backend/android/audio_sink_android_audiotrack_impl.cc b/chromecast/media/cma/backend/android/audio_sink_android_audiotrack_impl.cc index a7406492..ab71a3c 100644 --- a/chromecast/media/cma/backend/android/audio_sink_android_audiotrack_impl.cc +++ b/chromecast/media/cma/backend/android/audio_sink_android_audiotrack_impl.cc
@@ -100,7 +100,7 @@ << " num_channels_=" << num_channels_ << " input_samples_per_second_=" << input_samples_per_second_ << " primary_=" << primary_ << " device_id_=" << device_id_ - << " content_type__=" << GetContentTypeName(); + << " content_type_=" << content_type_; DCHECK(delegate_); DCHECK_GT(num_channels_, 0); @@ -149,10 +149,6 @@ return content_type_; } -const char* AudioSinkAndroidAudioTrackImpl::GetContentTypeName() const { - return GetAudioContentTypeName(content_type_); -} - void AudioSinkAndroidAudioTrackImpl::FinalizeOnFeederThread() { RUN_ON_FEEDER_THREAD(FinalizeOnFeederThread); if (j_audio_sink_audiotrack_impl_.is_null()) {
diff --git a/chromecast/media/cma/backend/android/audio_sink_android_audiotrack_impl.h b/chromecast/media/cma/backend/android/audio_sink_android_audiotrack_impl.h index 4c222a35..572b8d05 100644 --- a/chromecast/media/cma/backend/android/audio_sink_android_audiotrack_impl.h +++ b/chromecast/media/cma/backend/android/audio_sink_android_audiotrack_impl.h
@@ -70,7 +70,6 @@ bool primary() const override; std::string device_id() const override; AudioContentType content_type() const override; - const char* GetContentTypeName() const override; // Prevents any further calls to the delegate (ie, called when the delegate // is being destroyed).
diff --git a/chromecast/media/cma/backend/android/audio_sink_manager.cc b/chromecast/media/cma/backend/android/audio_sink_manager.cc index 4b584cf..b3f58cb 100644 --- a/chromecast/media/cma/backend/android/audio_sink_manager.cc +++ b/chromecast/media/cma/backend/android/audio_sink_manager.cc
@@ -51,7 +51,7 @@ LOG(INFO) << __func__ << " sink(" << sink << "): id=" << sink->device_id() << " primary=" << sink->primary() - << " type=" << sink->GetContentTypeName(); + << " type=" << sink->content_type(); base::AutoLock lock(lock_); UpdateLimiterMultiplier(sink); @@ -62,7 +62,7 @@ DCHECK(sink); LOG(INFO) << __func__ << " sink(" << sink << "): id=" << sink->device_id() - << " type=" << sink->GetContentTypeName(); + << " type=" << sink->content_type(); base::AutoLock lock(lock_); @@ -75,8 +75,7 @@ } void AudioSinkManager::SetTypeVolumeDb(AudioContentType type, float level_db) { - LOG(INFO) << __func__ << ": level_db=" << level_db - << " type=" << GetAudioContentTypeName(type); + LOG(INFO) << __func__ << ": level_db=" << level_db << " type=" << type; base::AutoLock lock(lock_); volume_info_[type].volume_db = level_db; // Since the type volume changed we need to reflect that in the limiter @@ -85,8 +84,7 @@ } void AudioSinkManager::SetOutputLimitDb(AudioContentType type, float limit_db) { - LOG(INFO) << __func__ << ": limit_db=" << limit_db - << " type=" << GetAudioContentTypeName(type); + LOG(INFO) << __func__ << ": limit_db=" << limit_db << " type=" << type; base::AutoLock lock(lock_); volume_info_[type].limit_db = limit_db; UpdateAllLimiterMultipliers(type);
diff --git a/chromecast/media/cma/backend/cma_backend_factory_impl.cc b/chromecast/media/cma/backend/cma_backend_factory_impl.cc index a0f6ba7..f0d53be 100644 --- a/chromecast/media/cma/backend/cma_backend_factory_impl.cc +++ b/chromecast/media/cma/backend/cma_backend_factory_impl.cc
@@ -4,8 +4,12 @@ #include "chromecast/media/cma/backend/cma_backend_factory_impl.h" +#include "chromecast/chromecast_buildflags.h" #include "chromecast/media/api/cma_backend.h" #include "chromecast/media/cma/backend/media_pipeline_backend_manager.h" +#if BUILDFLAG(ENABLE_CHROMIUM_RUNTIME_CAST_RENDERER) +#include "chromecast/media/cma/backend/proxy/cma_backend_proxy.h" // nogncheck +#endif // BUILDFLAG(ENABLE_CHROMIUM_RUNTIME_CAST_RENDERER) #include "chromecast/public/media/media_pipeline_device_params.h" namespace chromecast { @@ -21,7 +25,14 @@ std::unique_ptr<CmaBackend> CmaBackendFactoryImpl::CreateBackend( const MediaPipelineDeviceParams& params) { - return media_pipeline_backend_manager_->CreateBackend(params); + std::unique_ptr<CmaBackend> backend = + media_pipeline_backend_manager_->CreateBackend(params); + +#if BUILDFLAG(ENABLE_CHROMIUM_RUNTIME_CAST_RENDERER) + backend = std::make_unique<CmaBackendProxy>(std::move(backend)); +#endif // BUILDFLAG(ENABLE_CHROMIUM_RUNTIME_CAST_RENDERER) + + return backend; } } // namespace media
diff --git a/chromecast/media/cma/backend/mixer/mixer_input_connection.cc b/chromecast/media/cma/backend/mixer/mixer_input_connection.cc index be5d9bd..ca54705 100644 --- a/chromecast/media/cma/backend/mixer/mixer_input_connection.cc +++ b/chromecast/media/cma/backend/mixer/mixer_input_connection.cc
@@ -51,17 +51,6 @@ constexpr int kRateShifterOutputFrames = 4096; -std::string AudioContentTypeToString(media::AudioContentType type) { - switch (type) { - case media::AudioContentType::kAlarm: - return "alarm"; - case media::AudioContentType::kCommunication: - return "communication"; - default: - return "media"; - } -} - int64_t SamplesToMicroseconds(double samples, int sample_rate) { return std::round(samples * 1000000 / sample_rate); } @@ -206,9 +195,8 @@ weak_this_ = weak_factory_.GetWeakPtr(); LOG(INFO) << "Create " << this << " (" << device_id_ - << "), content type: " << AudioContentTypeToString(content_type_) - << ", focus type: " << AudioContentTypeToString(focus_type_) - << ", fill size: " << fill_size_ + << "), content type: " << content_type_ + << ", focus type: " << focus_type_ << ", fill size: " << fill_size_ << ", algorithm fill size: " << algorithm_fill_size_ << ", channel count: " << num_channels_ << ", input sample rate: " << input_samples_per_second_
diff --git a/chromecast/media/cma/backend/proxy/BUILD.gn b/chromecast/media/cma/backend/proxy/BUILD.gn index a2cab83..30ee1bb 100644 --- a/chromecast/media/cma/backend/proxy/BUILD.gn +++ b/chromecast/media/cma/backend/proxy/BUILD.gn
@@ -6,8 +6,11 @@ cast_source_set("proxy") { sources = [ - "multizone_audio_decoder_proxy.cc", + "cma_backend_proxy.cc", + "cma_backend_proxy.h", "multizone_audio_decoder_proxy.h", + "multizone_audio_decoder_proxy_impl.cc", + "multizone_audio_decoder_proxy_impl.h", ] deps = [
diff --git a/chromecast/media/cma/backend/proxy/cma_backend_proxy.cc b/chromecast/media/cma/backend/proxy/cma_backend_proxy.cc new file mode 100644 index 0000000..8fff8f7 --- /dev/null +++ b/chromecast/media/cma/backend/proxy/cma_backend_proxy.cc
@@ -0,0 +1,158 @@ +// Copyright 2020 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. + +#include "chromecast/media/cma/backend/proxy/cma_backend_proxy.h" + +#include <algorithm> + +#include "base/bind.h" +#include "base/logging.h" +#include "base/macros.h" +#include "base/notreached.h" +#include "chromecast/media/cma/backend/proxy/multizone_audio_decoder_proxy_impl.h" +#include "chromecast/public/media/decoder_config.h" + +namespace chromecast { +namespace media { +namespace { + +// The maximum allowed difference between the audio and video decoders used for +// the CmaBackendProxy. +// TODO(b/168748626): Determine the correct value for this variable +// experimentally. +int64_t kMaxAllowedPtsDrift = 500; + +} // namespace + +CmaBackendProxy::CmaBackendProxy( + std::unique_ptr<CmaBackend> delegated_video_pipeline) + : CmaBackendProxy( + std::move(delegated_video_pipeline), + base::BindOnce([]() -> std::unique_ptr<MultizoneAudioDecoderProxy> { + return std::make_unique<MultizoneAudioDecoderProxyImpl>(); + })) {} + +CmaBackendProxy::CmaBackendProxy( + std::unique_ptr<CmaBackend> delegated_video_pipeline, + CmaBackendProxy::AudioDecoderFactoryCB audio_decoder_factory) + : delegated_video_pipeline_(std::move(delegated_video_pipeline)), + audio_decoder_factory_(std::move(audio_decoder_factory)) { + DCHECK(delegated_video_pipeline_); + DCHECK(audio_decoder_factory_); +} + +CmaBackendProxy::~CmaBackendProxy() = default; + +CmaBackend::AudioDecoder* CmaBackendProxy::CreateAudioDecoder() { + DCHECK(!audio_decoder_); + DCHECK(audio_decoder_factory_); + audio_decoder_ = std::move(audio_decoder_factory_).Run(); + return audio_decoder_.get(); +} + +CmaBackend::VideoDecoder* CmaBackendProxy::CreateVideoDecoder() { + has_video_decoder_ = true; + return delegated_video_pipeline_->CreateVideoDecoder(); +} + +bool CmaBackendProxy::Initialize() { + if (has_video_decoder_ && !delegated_video_pipeline_->Initialize()) { + return false; + } + + return !audio_decoder_ || audio_decoder_->Initialize(); +} + +bool CmaBackendProxy::Start(int64_t start_pts) { + if (has_video_decoder_ && !delegated_video_pipeline_->Start(start_pts)) { + return false; + } + + return !audio_decoder_ || audio_decoder_->Start(start_pts); +} + +void CmaBackendProxy::Stop() { + if (has_video_decoder_) { + delegated_video_pipeline_->Stop(); + } + + if (audio_decoder_) { + audio_decoder_->Stop(); + } +} + +bool CmaBackendProxy::Pause() { + bool result = true; + + if (has_video_decoder_) { + result &= delegated_video_pipeline_->Pause(); + } + + if (audio_decoder_) { + result &= audio_decoder_->Pause(); + } + + return result; +} + +bool CmaBackendProxy::Resume() { + if (has_video_decoder_ && !delegated_video_pipeline_->Resume()) { + return false; + } + + return !audio_decoder_ || audio_decoder_->Resume(); +} + +int64_t CmaBackendProxy::GetCurrentPts() { + if (audio_decoder_ && has_video_decoder_) { + const int64_t audio_pts = audio_decoder_->GetCurrentPts(); + const int64_t video_pts = delegated_video_pipeline_->GetCurrentPts(); + const int64_t min = std::min(audio_pts, video_pts); + LOG_IF(WARNING, std::max(audio_pts, video_pts) - min > kMaxAllowedPtsDrift); + return min; + } else if (audio_decoder_) { + return audio_decoder_->GetCurrentPts(); + } else if (has_video_decoder_) { + return delegated_video_pipeline_->GetCurrentPts(); + } else { + return std::numeric_limits<int64_t>::min(); + } +} + +bool CmaBackendProxy::SetPlaybackRate(float rate) { + bool result = true; + + if (has_video_decoder_) { + result &= delegated_video_pipeline_->SetPlaybackRate(rate); + } + + if (audio_decoder_) { + result &= audio_decoder_->SetPlaybackRate(rate); + } + + return result; +} + +void CmaBackendProxy::LogicalPause() { + if (has_video_decoder_) { + delegated_video_pipeline_->LogicalPause(); + } + + if (audio_decoder_) { + audio_decoder_->LogicalPause(); + } +} + +void CmaBackendProxy::LogicalResume() { + if (has_video_decoder_) { + delegated_video_pipeline_->LogicalResume(); + } + + if (audio_decoder_) { + audio_decoder_->LogicalResume(); + } +} + +} // namespace media +} // namespace chromecast
diff --git a/chromecast/media/cma/backend/proxy/cma_backend_proxy.h b/chromecast/media/cma/backend/proxy/cma_backend_proxy.h new file mode 100644 index 0000000..342272d --- /dev/null +++ b/chromecast/media/cma/backend/proxy/cma_backend_proxy.h
@@ -0,0 +1,78 @@ +// Copyright 2020 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. + +#ifndef CHROMECAST_MEDIA_CMA_BACKEND_PROXY_CMA_BACKEND_PROXY_H_ +#define CHROMECAST_MEDIA_CMA_BACKEND_PROXY_CMA_BACKEND_PROXY_H_ + +#include <stdint.h> + +#include <memory> + +#include "base/callback.h" +#include "base/optional.h" +#include "chromecast/media/api/cma_backend.h" +#include "chromecast/media/cma/backend/proxy/multizone_audio_decoder_proxy.h" + +namespace chromecast { +namespace media { + +// This class is used to proxy audio data to an external +// CmaBackend::AudioDecoder over gRPC, while delegating video decoding to an +// alternate CMA Backend. +// NOTE: By design, this class does NOT handle a/v sync drift between +// |audio_decoder_| and |delegated_video_pipeline_|. +class CmaBackendProxy : public CmaBackend { + public: + using AudioDecoderFactoryCB = + base::OnceCallback<std::unique_ptr<MultizoneAudioDecoderProxy>()>; + + // Creates a new CmaBackendProxy such that all video processing is delegated + // to |delegated_video_pipeline|. + explicit CmaBackendProxy( + std::unique_ptr<CmaBackend> delegated_video_pipeline); + ~CmaBackendProxy() override; + + // MediaPipelineBackend implementation: + CmaBackend::AudioDecoder* CreateAudioDecoder() override; + CmaBackend::VideoDecoder* CreateVideoDecoder() override; + bool Initialize() override; + bool Start(int64_t start_pts) override; + void Stop() override; + bool Pause() override; + bool Resume() override; + int64_t GetCurrentPts() override; + bool SetPlaybackRate(float rate) override; + void LogicalPause() override; + void LogicalResume() override; + + private: + friend class CmaBackendProxyTest; + + // Creates a new CmaBackendProxy such that all video processing is delegated + // to |delegated_video_pipeline| and all audio processing is delegated to a + // new MultizoneAudioDecoderProxy created by |audio_decoder_factory|. + CmaBackendProxy(std::unique_ptr<CmaBackend> delegated_video_pipeline, + AudioDecoderFactoryCB audio_decoder_factory); + + // The audio decoder to which audio operations should be delegated. + std::unique_ptr<MultizoneAudioDecoderProxy> audio_decoder_; + + // The CMA Backend to which all video decoding is delegated. + std::unique_ptr<CmaBackend> delegated_video_pipeline_; + + // Determines whether a video decoder is being used. If not, calls should not + // be delegated to the |delegated_video_pipeline_|, as it may not behave as + // expected when neither the audio or video decoders are initialized. + bool has_video_decoder_ = false; + + // The factory to use to populate the |audio_decoder_| object when needed. + AudioDecoderFactoryCB audio_decoder_factory_; + + DISALLOW_COPY_AND_ASSIGN(CmaBackendProxy); +}; + +} // namespace media +} // namespace chromecast + +#endif // CHROMECAST_MEDIA_CMA_BACKEND_PROXY_CMA_BACKEND_PROXY_H_
diff --git a/chromecast/media/cma/backend/proxy/cma_backend_proxy_unittest.cc b/chromecast/media/cma/backend/proxy/cma_backend_proxy_unittest.cc new file mode 100644 index 0000000..ea3ffc2 --- /dev/null +++ b/chromecast/media/cma/backend/proxy/cma_backend_proxy_unittest.cc
@@ -0,0 +1,305 @@ +// Copyright 2020 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. + +#include "chromecast/media/cma/backend/proxy/cma_backend_proxy.h" + +#include "base/bind.h" +#include "base/memory/ref_counted.h" +#include "chromecast/media/api/cma_backend.h" +#include "chromecast/media/api/decoder_buffer_base.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using testing::Return; +using testing::StrictMock; + +namespace chromecast { +namespace media { +namespace { + +class MockCmaBackend : public CmaBackend { + public: + MOCK_METHOD0(CreateAudioDecoder, CmaBackend::AudioDecoder*()); + MOCK_METHOD0(CreateVideoDecoder, CmaBackend::VideoDecoder*()); + MOCK_METHOD0(Initialize, bool()); + MOCK_METHOD1(Start, bool(int64_t)); + MOCK_METHOD0(Stop, void()); + MOCK_METHOD0(Pause, bool()); + MOCK_METHOD0(Resume, bool()); + MOCK_METHOD0(GetCurrentPts, int64_t()); + MOCK_METHOD1(SetPlaybackRate, bool(float rate)); + MOCK_METHOD0(LogicalPause, void()); + MOCK_METHOD0(LogicalResume, void()); +}; + +class MockMultizoneAudioDecoderProxy : public MultizoneAudioDecoderProxy { + public: + MOCK_METHOD0(Initialize, bool()); + MOCK_METHOD1(Start, bool(int64_t)); + MOCK_METHOD0(Stop, void()); + MOCK_METHOD0(Pause, bool()); + MOCK_METHOD0(Resume, bool()); + MOCK_CONST_METHOD0(GetCurrentPts, int64_t()); + MOCK_METHOD1(SetPlaybackRate, bool(float rate)); + MOCK_METHOD0(LogicalPause, void()); + MOCK_METHOD0(LogicalResume, void()); + MOCK_METHOD1(SetDelegate, void(Delegate*)); + MOCK_METHOD1(PushBuffer, BufferStatus(scoped_refptr<DecoderBufferBase>)); + MOCK_METHOD1(SetConfig, bool(const AudioConfig&)); + MOCK_METHOD1(SetVolume, bool(float)); + MOCK_METHOD0(GetRenderingDelay, RenderingDelay()); + MOCK_METHOD1(GetStatistics, void(Statistics*)); + MOCK_METHOD0(RequiresDecryption, bool()); + MOCK_METHOD1(SetObserver, void(Observer*)); +}; + +} // namespace + +class CmaBackendProxyTest : public testing::Test { + public: + CmaBackendProxyTest() { + auto delegated_video_backend = + std::make_unique<StrictMock<MockCmaBackend>>(); + auto audio_decoder = + std::make_unique<StrictMock<MockMultizoneAudioDecoderProxy>>(); + + delegated_video_backend_ = delegated_video_backend.get(); + audio_decoder_ = audio_decoder.get(); + + CmaBackendProxy::AudioDecoderFactoryCB factory = base::BindOnce( + [](std::unique_ptr<MultizoneAudioDecoderProxy> ptr) { return ptr; }, + std::move(audio_decoder)); + CmaBackendProxy* proxy = new CmaBackendProxy( + std::move(delegated_video_backend), std::move(factory)); + backend_.reset(proxy); + } + + protected: + void CreateVideoDecoder() { + EXPECT_CALL(*delegated_video_backend_, CreateVideoDecoder()).Times(1); + backend_->CreateVideoDecoder(); + testing::Mock::VerifyAndClearExpectations(delegated_video_backend_); + } + + std::unique_ptr<CmaBackendProxy> backend_; + MockCmaBackend* delegated_video_backend_; + MockMultizoneAudioDecoderProxy* audio_decoder_; +}; + +TEST_F(CmaBackendProxyTest, Initialize) { + EXPECT_TRUE(backend_->Initialize()); + + ASSERT_EQ(backend_->CreateAudioDecoder(), audio_decoder_); + + EXPECT_CALL(*audio_decoder_, Initialize()) + .WillOnce(Return(true)) + .WillOnce(Return(false)); + EXPECT_TRUE(backend_->Initialize()); + EXPECT_FALSE(backend_->Initialize()); + testing::Mock::VerifyAndClearExpectations(audio_decoder_); + + CreateVideoDecoder(); + EXPECT_CALL(*audio_decoder_, Initialize()) + .WillOnce(Return(true)) + .WillOnce(Return(false)); + EXPECT_CALL(*delegated_video_backend_, Initialize()) + .WillOnce(Return(true)) + .WillOnce(Return(true)) + .WillOnce(Return(false)) + .WillOnce(Return(false)); + + EXPECT_TRUE(backend_->Initialize()); + EXPECT_FALSE(backend_->Initialize()); + testing::Mock::VerifyAndClearExpectations(audio_decoder_); + + EXPECT_FALSE(backend_->Initialize()); + EXPECT_FALSE(backend_->Initialize()); +} + +TEST_F(CmaBackendProxyTest, Start) { + constexpr float kStartPts = 42; + EXPECT_TRUE(backend_->Start(kStartPts)); + + ASSERT_EQ(backend_->CreateAudioDecoder(), audio_decoder_); + + EXPECT_CALL(*audio_decoder_, Start(kStartPts)) + .WillOnce(Return(true)) + .WillOnce(Return(false)); + EXPECT_TRUE(backend_->Start(kStartPts)); + EXPECT_FALSE(backend_->Start(kStartPts)); + testing::Mock::VerifyAndClearExpectations(audio_decoder_); + + CreateVideoDecoder(); + EXPECT_CALL(*audio_decoder_, Start(kStartPts)) + .WillOnce(Return(true)) + .WillOnce(Return(false)); + EXPECT_CALL(*delegated_video_backend_, Start(kStartPts)) + .WillOnce(Return(true)) + .WillOnce(Return(true)) + .WillOnce(Return(false)) + .WillOnce(Return(false)); + + EXPECT_TRUE(backend_->Start(kStartPts)); + EXPECT_FALSE(backend_->Start(kStartPts)); + EXPECT_FALSE(backend_->Start(kStartPts)); + EXPECT_FALSE(backend_->Start(kStartPts)); +} + +TEST_F(CmaBackendProxyTest, Stop) { + backend_->Stop(); + + ASSERT_EQ(backend_->CreateAudioDecoder(), audio_decoder_); + + EXPECT_CALL(*audio_decoder_, Stop()); + backend_->Stop(); + testing::Mock::VerifyAndClearExpectations(audio_decoder_); + + CreateVideoDecoder(); + EXPECT_CALL(*audio_decoder_, Stop()); + EXPECT_CALL(*delegated_video_backend_, Stop()); + backend_->Stop(); +} + +TEST_F(CmaBackendProxyTest, Pause) { + EXPECT_TRUE(backend_->Pause()); + + ASSERT_EQ(backend_->CreateAudioDecoder(), audio_decoder_); + + EXPECT_CALL(*audio_decoder_, Pause()) + .WillOnce(Return(true)) + .WillOnce(Return(false)); + EXPECT_TRUE(backend_->Pause()); + EXPECT_FALSE(backend_->Pause()); + testing::Mock::VerifyAndClearExpectations(audio_decoder_); + + CreateVideoDecoder(); + EXPECT_CALL(*audio_decoder_, Pause()) + .WillOnce(Return(true)) + .WillOnce(Return(false)) + .WillOnce(Return(true)) + .WillOnce(Return(false)); + EXPECT_CALL(*delegated_video_backend_, Pause()) + .WillOnce(Return(true)) + .WillOnce(Return(true)) + .WillOnce(Return(false)) + .WillOnce(Return(false)); + + EXPECT_TRUE(backend_->Pause()); + EXPECT_FALSE(backend_->Pause()); + EXPECT_FALSE(backend_->Pause()); + EXPECT_FALSE(backend_->Pause()); +} + +TEST_F(CmaBackendProxyTest, Resume) { + EXPECT_TRUE(backend_->Resume()); + + ASSERT_EQ(backend_->CreateAudioDecoder(), audio_decoder_); + + EXPECT_CALL(*audio_decoder_, Resume()) + .WillOnce(Return(true)) + .WillOnce(Return(false)); + EXPECT_TRUE(backend_->Resume()); + EXPECT_FALSE(backend_->Resume()); + testing::Mock::VerifyAndClearExpectations(audio_decoder_); + + CreateVideoDecoder(); + EXPECT_CALL(*audio_decoder_, Resume()) + .WillOnce(Return(true)) + .WillOnce(Return(false)); + EXPECT_CALL(*delegated_video_backend_, Resume()) + .WillOnce(Return(true)) + .WillOnce(Return(true)) + .WillOnce(Return(false)) + .WillOnce(Return(false)); + + EXPECT_TRUE(backend_->Resume()); + EXPECT_FALSE(backend_->Resume()); + EXPECT_FALSE(backend_->Resume()); + EXPECT_FALSE(backend_->Resume()); +} + +TEST_F(CmaBackendProxyTest, GetCurrentPts) { + EXPECT_EQ(backend_->GetCurrentPts(), std::numeric_limits<int64_t>::min()); + + ASSERT_EQ(backend_->CreateAudioDecoder(), audio_decoder_); + + EXPECT_CALL(*audio_decoder_, GetCurrentPts()).WillOnce(Return(42)); + EXPECT_EQ(backend_->GetCurrentPts(), 42); + testing::Mock::VerifyAndClearExpectations(audio_decoder_); + + CreateVideoDecoder(); + EXPECT_CALL(*audio_decoder_, GetCurrentPts()) + .WillOnce(Return(42)) + .WillOnce(Return(42)); + EXPECT_CALL(*delegated_video_backend_, GetCurrentPts()) + .WillOnce(Return(16)) + .WillOnce(Return(360)); + + EXPECT_EQ(backend_->GetCurrentPts(), 16); + EXPECT_EQ(backend_->GetCurrentPts(), 42); +} + +TEST_F(CmaBackendProxyTest, SetPlaybackRate) { + constexpr float kSetPlaybackRatePts = 0.5; + EXPECT_TRUE(backend_->SetPlaybackRate(kSetPlaybackRatePts)); + + ASSERT_EQ(backend_->CreateAudioDecoder(), audio_decoder_); + + EXPECT_CALL(*audio_decoder_, SetPlaybackRate(kSetPlaybackRatePts)) + .WillOnce(Return(true)) + .WillOnce(Return(false)); + EXPECT_TRUE(backend_->SetPlaybackRate(kSetPlaybackRatePts)); + EXPECT_FALSE(backend_->SetPlaybackRate(kSetPlaybackRatePts)); + testing::Mock::VerifyAndClearExpectations(audio_decoder_); + + CreateVideoDecoder(); + EXPECT_CALL(*audio_decoder_, SetPlaybackRate(kSetPlaybackRatePts)) + .WillOnce(Return(true)) + .WillOnce(Return(false)) + .WillOnce(Return(true)) + .WillOnce(Return(false)); + EXPECT_CALL(*delegated_video_backend_, SetPlaybackRate(kSetPlaybackRatePts)) + .WillOnce(Return(true)) + .WillOnce(Return(true)) + .WillOnce(Return(false)) + .WillOnce(Return(false)); + + EXPECT_TRUE(backend_->SetPlaybackRate(kSetPlaybackRatePts)); + EXPECT_FALSE(backend_->SetPlaybackRate(kSetPlaybackRatePts)); + EXPECT_FALSE(backend_->SetPlaybackRate(kSetPlaybackRatePts)); + EXPECT_FALSE(backend_->SetPlaybackRate(kSetPlaybackRatePts)); +} + +TEST_F(CmaBackendProxyTest, LogicalPause) { + backend_->LogicalPause(); + + ASSERT_EQ(backend_->CreateAudioDecoder(), audio_decoder_); + + EXPECT_CALL(*audio_decoder_, LogicalPause()); + backend_->LogicalPause(); + testing::Mock::VerifyAndClearExpectations(audio_decoder_); + + CreateVideoDecoder(); + EXPECT_CALL(*audio_decoder_, LogicalPause()); + EXPECT_CALL(*delegated_video_backend_, LogicalPause()); + backend_->LogicalPause(); +} + +TEST_F(CmaBackendProxyTest, LogicalResume) { + backend_->LogicalResume(); + + ASSERT_EQ(backend_->CreateAudioDecoder(), audio_decoder_); + + EXPECT_CALL(*audio_decoder_, LogicalResume()); + backend_->LogicalResume(); + testing::Mock::VerifyAndClearExpectations(audio_decoder_); + + CreateVideoDecoder(); + EXPECT_CALL(*audio_decoder_, LogicalResume()); + EXPECT_CALL(*delegated_video_backend_, LogicalResume()); + backend_->LogicalResume(); +} + +} // namespace media +} // namespace chromecast
diff --git a/chromecast/media/cma/backend/proxy/multizone_audio_decoder_proxy.cc b/chromecast/media/cma/backend/proxy/multizone_audio_decoder_proxy.cc deleted file mode 100644 index eca3b07..0000000 --- a/chromecast/media/cma/backend/proxy/multizone_audio_decoder_proxy.cc +++ /dev/null
@@ -1,53 +0,0 @@ -// Copyright 2020 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. - -#include "chromecast/media/cma/backend/proxy/multizone_audio_decoder_proxy.h" - -#include "base/notreached.h" -#include "chromecast/public/media/decoder_config.h" - -namespace chromecast { -namespace media { - -void MultizoneAudioDecoderProxy::SetDelegate(Delegate* delegate) { - NOTREACHED(); -} - -MultizoneAudioDecoderProxy::BufferStatus MultizoneAudioDecoderProxy::PushBuffer( - scoped_refptr<DecoderBufferBase> buffer) { - NOTREACHED(); - return BufferStatus::kBufferSuccess; -} - -bool MultizoneAudioDecoderProxy::SetConfig(const AudioConfig& config) { - NOTREACHED(); - return true; -} - -bool MultizoneAudioDecoderProxy::SetVolume(float multiplier) { - NOTREACHED(); - return true; -} - -MultizoneAudioDecoderProxy::RenderingDelay -MultizoneAudioDecoderProxy::GetRenderingDelay() { - NOTREACHED(); - return RenderingDelay{}; -} - -void MultizoneAudioDecoderProxy::GetStatistics(Statistics* statistics) { - NOTREACHED(); -} - -bool MultizoneAudioDecoderProxy::RequiresDecryption() { - NOTREACHED(); - return true; -} - -void MultizoneAudioDecoderProxy::SetObserver(Observer* observer) { - NOTREACHED(); -} - -} // namespace media -} // namespace chromecast
diff --git a/chromecast/media/cma/backend/proxy/multizone_audio_decoder_proxy.h b/chromecast/media/cma/backend/proxy/multizone_audio_decoder_proxy.h index c67e5593..5b1f5a3 100644 --- a/chromecast/media/cma/backend/proxy/multizone_audio_decoder_proxy.h +++ b/chromecast/media/cma/backend/proxy/multizone_audio_decoder_proxy.h
@@ -5,6 +5,9 @@ #ifndef CHROMECAST_MEDIA_CMA_BACKEND_PROXY_MULTIZONE_AUDIO_DECODER_PROXY_H_ #define CHROMECAST_MEDIA_CMA_BACKEND_PROXY_MULTIZONE_AUDIO_DECODER_PROXY_H_ +#include <limits> + +#include "base/callback.h" #include "base/memory/ref_counted.h" #include "chromecast/media/api/cma_backend.h" #include "chromecast/media/api/decoder_buffer_base.h" @@ -12,8 +15,6 @@ namespace chromecast { namespace media { -struct AudioConfig; - // This class is used to decrypt then proxy audio data to an external // CmaBackend::AudioDecoder over gRPC. class MultizoneAudioDecoderProxy : public CmaBackend::AudioDecoder { @@ -24,17 +25,17 @@ using RenderingDelay = CmaBackend::AudioDecoder::RenderingDelay; using Statistics = CmaBackend::AudioDecoder::Statistics; - ~MultizoneAudioDecoderProxy() override; + ~MultizoneAudioDecoderProxy() override = default; - // CmaBackend::AudioDecoder implementation: - void SetDelegate(Delegate* delegate) override; - BufferStatus PushBuffer(scoped_refptr<DecoderBufferBase> buffer) override; - bool SetConfig(const AudioConfig& config) override; - bool SetVolume(float multiplier) override; - RenderingDelay GetRenderingDelay() override; - void GetStatistics(Statistics* statistics) override; - bool RequiresDecryption() override; - void SetObserver(Observer* observer) override; + virtual bool Initialize() = 0; + virtual bool Start(int64_t start_pts) = 0; + virtual void Stop() = 0; + virtual bool Pause() = 0; + virtual bool Resume() = 0; + virtual bool SetPlaybackRate(float rate) = 0; + virtual void LogicalPause() = 0; + virtual void LogicalResume() = 0; + virtual int64_t GetCurrentPts() const = 0; }; } // namespace media
diff --git a/chromecast/media/cma/backend/proxy/multizone_audio_decoder_proxy_impl.cc b/chromecast/media/cma/backend/proxy/multizone_audio_decoder_proxy_impl.cc new file mode 100644 index 0000000..2df82c3 --- /dev/null +++ b/chromecast/media/cma/backend/proxy/multizone_audio_decoder_proxy_impl.cc
@@ -0,0 +1,99 @@ +// Copyright 2020 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. + +#include "chromecast/media/cma/backend/proxy/multizone_audio_decoder_proxy_impl.h" + +#include "base/notreached.h" +#include "chromecast/public/media/decoder_config.h" + +namespace chromecast { +namespace media { + +MultizoneAudioDecoderProxyImpl::MultizoneAudioDecoderProxyImpl() = default; + +MultizoneAudioDecoderProxyImpl::~MultizoneAudioDecoderProxyImpl() = default; + +bool MultizoneAudioDecoderProxyImpl::Initialize() { + NOTIMPLEMENTED(); + return true; +} + +bool MultizoneAudioDecoderProxyImpl::Start(int64_t start_pts) { + NOTIMPLEMENTED(); + return true; +} + +void MultizoneAudioDecoderProxyImpl::Stop() { + NOTIMPLEMENTED(); +} + +bool MultizoneAudioDecoderProxyImpl::Pause() { + NOTIMPLEMENTED(); + return true; +} + +bool MultizoneAudioDecoderProxyImpl::Resume() { + NOTIMPLEMENTED(); + return true; +} + +bool MultizoneAudioDecoderProxyImpl::SetPlaybackRate(float rate) { + NOTIMPLEMENTED(); + return true; +} + +void MultizoneAudioDecoderProxyImpl::LogicalPause() { + NOTIMPLEMENTED(); +} + +void MultizoneAudioDecoderProxyImpl::LogicalResume() { + NOTIMPLEMENTED(); +} + +int64_t MultizoneAudioDecoderProxyImpl::GetCurrentPts() const { + return pts_offset_; +} + +void MultizoneAudioDecoderProxyImpl::SetDelegate(Delegate* delegate) { + NOTIMPLEMENTED(); +} + +MultizoneAudioDecoderProxy::BufferStatus +MultizoneAudioDecoderProxyImpl::PushBuffer( + scoped_refptr<DecoderBufferBase> buffer) { + NOTIMPLEMENTED(); + return BufferStatus::kBufferSuccess; +} + +bool MultizoneAudioDecoderProxyImpl::SetConfig(const AudioConfig& config) { + NOTIMPLEMENTED(); + return true; +} + +bool MultizoneAudioDecoderProxyImpl::SetVolume(float multiplier) { + NOTIMPLEMENTED(); + return true; +} + +MultizoneAudioDecoderProxyImpl::RenderingDelay +MultizoneAudioDecoderProxyImpl::GetRenderingDelay() { + NOTIMPLEMENTED(); + return RenderingDelay{}; +} + +void MultizoneAudioDecoderProxyImpl::GetStatistics(Statistics* statistics) { + NOTIMPLEMENTED(); +} + +bool MultizoneAudioDecoderProxyImpl::RequiresDecryption() { + NOTIMPLEMENTED(); + return true; +} + +void MultizoneAudioDecoderProxyImpl::SetObserver(Observer* observer) { + NOTIMPLEMENTED(); +} + +} // namespace media +} // namespace chromecast
diff --git a/chromecast/media/cma/backend/proxy/multizone_audio_decoder_proxy_impl.h b/chromecast/media/cma/backend/proxy/multizone_audio_decoder_proxy_impl.h new file mode 100644 index 0000000..e1cb3ba2 --- /dev/null +++ b/chromecast/media/cma/backend/proxy/multizone_audio_decoder_proxy_impl.h
@@ -0,0 +1,59 @@ +// Copyright 2020 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. + +#ifndef CHROMECAST_MEDIA_CMA_BACKEND_PROXY_MULTIZONE_AUDIO_DECODER_PROXY_IMPL_H_ +#define CHROMECAST_MEDIA_CMA_BACKEND_PROXY_MULTIZONE_AUDIO_DECODER_PROXY_IMPL_H_ + +#include <limits> + +#include "base/memory/ref_counted.h" +#include "chromecast/media/api/cma_backend.h" +#include "chromecast/media/api/decoder_buffer_base.h" +#include "chromecast/media/cma/backend/proxy/multizone_audio_decoder_proxy.h" + +namespace chromecast { +namespace media { + +struct AudioConfig; + +// This class is used to proxy audio data to an external +// CmaBackend::AudioDecoder over gRPC. +class MultizoneAudioDecoderProxyImpl : public MultizoneAudioDecoderProxy { + public: + // Creates a new MultizoneAudioDecoderProxy, such that in the event of an + // unrecoverable error, |fatal_error_callback| will be called. Fallowing this + // call, this instance will be in an undefined state. + MultizoneAudioDecoderProxyImpl(); + ~MultizoneAudioDecoderProxyImpl() override; + + // MultizoneAudioDecoderProxy implementation: + bool Initialize() override; + bool Start(int64_t start_pts) override; + void Stop() override; + bool Pause() override; + bool Resume() override; + int64_t GetCurrentPts() const override; + bool SetPlaybackRate(float rate) override; + void LogicalPause() override; + void LogicalResume() override; + void SetDelegate(Delegate* delegate) override; + BufferStatus PushBuffer(scoped_refptr<DecoderBufferBase> buffer) override; + bool SetConfig(const AudioConfig& config) override; + bool SetVolume(float multiplier) override; + RenderingDelay GetRenderingDelay() override; + void GetStatistics(Statistics* statistics) override; + bool RequiresDecryption() override; + void SetObserver(Observer* observer) override; + + private: + // The PTS offset as determined by the receiver of the gRPC endpoint wrapped + // by this class. This value is updated as new PTS values are received over + // the IPC. + int64_t pts_offset_ = std::numeric_limits<int64_t>::min(); +}; + +} // namespace media +} // namespace chromecast + +#endif // CHROMECAST_MEDIA_CMA_BACKEND_PROXY_MULTIZONE_AUDIO_DECODER_PROXY_IMPL_H_
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index 829b44f..6edf245 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -13477.0.0 \ No newline at end of file +13485.0.0 \ No newline at end of file
diff --git a/chromeos/components/diagnostics_ui/backend/system_data_provider.cc b/chromeos/components/diagnostics_ui/backend/system_data_provider.cc index de4a3a7..caac24f 100644 --- a/chromeos/components/diagnostics_ui/backend/system_data_provider.cc +++ b/chromeos/components/diagnostics_ui/backend/system_data_provider.cc
@@ -65,6 +65,14 @@ out_system_info.device_capabilities = std::move(capabilities); } +void PopulateBatteryInfo(const healthd::BatteryInfo& battery_info, + mojom::BatteryInfo& out_battery_info) { + out_battery_info.manufacturer = battery_info.vendor; + // Multiply by 1000 to convert amps to milliamps. + out_battery_info.charge_full_design_milliamp_hours = + battery_info.charge_full_design * 1000; +} + } // namespace SystemDataProvider::SystemDataProvider() = default; @@ -80,6 +88,15 @@ base::Unretained(this), std::move(callback))); } +void SystemDataProvider::GetBatteryInfo(GetBatteryInfoCallback callback) { + BindCrosHealthdProbeServiceIfNeccessary(); + + probe_service_->ProbeTelemetryInfo( + {ProbeCategories::kBattery}, + base::BindOnce(&SystemDataProvider::OnBatteryInfoProbeResponse, + base::Unretained(this), std::move(callback))); +} + void SystemDataProvider::OnSystemInfoProbeResponse( GetSystemInfoCallback callback, healthd::TelemetryInfoPtr info_ptr) { @@ -124,6 +141,29 @@ std::move(callback).Run(std::move(system_info)); } +void SystemDataProvider::OnBatteryInfoProbeResponse( + GetBatteryInfoCallback callback, + healthd::TelemetryInfoPtr info_ptr) { + mojom::BatteryInfoPtr battery_info = mojom::BatteryInfo::New(); + + if (info_ptr.is_null()) { + LOG(ERROR) << "Null response from croshealthd::ProbeTelemetryInfo."; + std::move(callback).Run(std::move(battery_info)); + return; + } + + const healthd::BatteryInfo* battery_info_ptr = + diagnostics::GetBatteryInfo(*info_ptr); + if (!battery_info_ptr) { + LOG(ERROR) << "BatteryInfo requested by device does not have a battery."; + std::move(callback).Run(std::move(battery_info)); + return; + } + + PopulateBatteryInfo(*battery_info_ptr, *battery_info.get()); + std::move(callback).Run(std::move(battery_info)); +} + void SystemDataProvider::BindCrosHealthdProbeServiceIfNeccessary() { if (!probe_service_ || !probe_service_.is_connected()) { cros_healthd::ServiceConnection::GetInstance()->GetProbeService(
diff --git a/chromeos/components/diagnostics_ui/backend/system_data_provider.h b/chromeos/components/diagnostics_ui/backend/system_data_provider.h index a2146b6..b3ed40696 100644 --- a/chromeos/components/diagnostics_ui/backend/system_data_provider.h +++ b/chromeos/components/diagnostics_ui/backend/system_data_provider.h
@@ -23,6 +23,7 @@ // mojom::SystemDataProvider: void GetSystemInfo(GetSystemInfoCallback callback) override; + void GetBatteryInfo(GetBatteryInfoCallback callback) override; private: void BindCrosHealthdProbeServiceIfNeccessary(); @@ -33,6 +34,10 @@ GetSystemInfoCallback callback, cros_healthd::mojom::TelemetryInfoPtr info_ptr); + void OnBatteryInfoProbeResponse( + GetBatteryInfoCallback callback, + cros_healthd::mojom::TelemetryInfoPtr info_ptr); + mojo::Remote<cros_healthd::mojom::CrosHealthdProbeService> probe_service_; };
diff --git a/chromeos/components/diagnostics_ui/backend/system_data_provider_unittest.cc b/chromeos/components/diagnostics_ui/backend/system_data_provider_unittest.cc index 5c43966..79c874c 100644 --- a/chromeos/components/diagnostics_ui/backend/system_data_provider_unittest.cc +++ b/chromeos/components/diagnostics_ui/backend/system_data_provider_unittest.cc
@@ -22,6 +22,33 @@ namespace diagnostics { namespace { +void SetProbeTelemetryInfoResponse( + cros_healthd::mojom::BatteryInfoPtr battery_info, + cros_healthd::mojom::CpuInfoPtr cpu_info, + cros_healthd::mojom::MemoryInfoPtr memory_info, + cros_healthd::mojom::SystemInfoPtr system_info) { + auto info = cros_healthd::mojom::TelemetryInfo::New(); + if (system_info) { + info->system_result = cros_healthd::mojom::SystemResult::NewSystemInfo( + std::move(system_info)); + } + if (battery_info) { + info->battery_result = cros_healthd::mojom::BatteryResult::NewBatteryInfo( + std::move(battery_info)); + } + if (memory_info) { + info->memory_result = cros_healthd::mojom::MemoryResult::NewMemoryInfo( + std::move(memory_info)); + } + if (cpu_info) { + info->cpu_result = + cros_healthd::mojom::CpuResult::NewCpuInfo(std::move(cpu_info)); + } + + cros_healthd::FakeCrosHealthdClient::Get() + ->SetProbeTelemetryInfoResponseForTesting(info); +} + void SetCrosHealthdSystemInfoResponse(const std::string& board_name, const std::string& cpu_model, uint32_t total_memory_kib, @@ -50,17 +77,66 @@ cpu_info->num_total_threads = cpu_threads_count; cpu_info->physical_cpus.emplace_back(std::move(physical_cpu_info)); - auto info = cros_healthd::mojom::TelemetryInfo::New(); - info->system_result = - cros_healthd::mojom::SystemResult::NewSystemInfo(std::move(system_info)); - info->battery_result = cros_healthd::mojom::BatteryResult::NewBatteryInfo( - std::move(battery_info)); - info->memory_result = - cros_healthd::mojom::MemoryResult::NewMemoryInfo(std::move(memory_info)); - info->cpu_result = - cros_healthd::mojom::CpuResult::NewCpuInfo(std::move(cpu_info)); - cros_healthd::FakeCrosHealthdClient::Get() - ->SetProbeTelemetryInfoResponseForTesting(info); + SetProbeTelemetryInfoResponse(std::move(battery_info), std::move(cpu_info), + std::move(memory_info), std::move(system_info)); +} + +// Constructs a BatteryInfoPtr. If |temperature| = 0, it will be omitted from +// the response to simulate an empty temperature field. +cros_healthd::mojom::BatteryInfoPtr CreateCrosHealthdBatteryInfoResponse( + int64_t cycle_count, + double voltage_now, + const std::string& vendor, + const std::string& serial_number, + double charge_full_design, + double charge_full, + double voltage_min_design, + const std::string& model_name, + double charge_now, + double current_now, + const std::string& technology, + const std::string& status, + const base::Optional<std::string>& manufacture_date, + uint64_t temperature) { + cros_healthd::mojom::UInt64ValuePtr temp_value_ptr( + cros_healthd::mojom::UInt64Value::New()); + if (temperature != 0) { + temp_value_ptr->value = temperature; + } + auto battery_info = cros_healthd::mojom::BatteryInfo::New( + cycle_count, voltage_now, vendor, serial_number, charge_full_design, + charge_full, voltage_min_design, model_name, charge_now, current_now, + technology, status, manufacture_date, std::move(temp_value_ptr)); + return battery_info; +} + +cros_healthd::mojom::BatteryInfoPtr CreateCrosHealthdBatteryInfoResponse( + const std::string& vendor, + double charge_full_design) { + return CreateCrosHealthdBatteryInfoResponse( + /*cycle_count=*/0, + /*voltage_now=*/0, + /*vendor=*/vendor, + /*serial_number=*/"", + /*charge_full_design=*/charge_full_design, + /*charge_full=*/0, + /*voltage_min_design=*/0, + /*model_name=*/"", + /*charge_now=*/0, + /*current_now=*/0, + /*technology=*/"", + /*status=*/"", + /*manufacture_date=*/base::nullopt, + /*temperature=*/0); +} + +void SetCrosHealthdBatteryInfoResponse(const std::string& vendor, + double charge_full_design) { + cros_healthd::mojom::BatteryInfoPtr battery_info = + CreateCrosHealthdBatteryInfoResponse(vendor, charge_full_design); + SetProbeTelemetryInfoResponse(std::move(battery_info), /*cpu_info=*/nullptr, + /*memory_info=*/nullptr, + /*memory_info=*/nullptr); } } // namespace @@ -144,5 +220,28 @@ run_loop.Run(); } +TEST_F(SystemDataProviderTest, BatteryInfo) { + const std::string expected_manufacturer = "manufacturer"; + const double charge_full_amp_hours = 25; + + SetCrosHealthdBatteryInfoResponse(expected_manufacturer, + charge_full_amp_hours); + + const uint32_t expected_charge_full_design_milliamp_hours = + charge_full_amp_hours * 1000; + + base::RunLoop run_loop; + system_data_provider_->GetBatteryInfo( + base::BindLambdaForTesting([&](mojom::BatteryInfoPtr ptr) { + ASSERT_TRUE(ptr); + EXPECT_EQ(expected_manufacturer, ptr->manufacturer); + EXPECT_EQ(expected_charge_full_design_milliamp_hours, + ptr->charge_full_design_milliamp_hours); + + run_loop.Quit(); + })); + run_loop.Run(); +} + } // namespace diagnostics } // namespace chromeos
diff --git a/chromeos/components/diagnostics_ui/mojom/system_data_provider.mojom b/chromeos/components/diagnostics_ui/mojom/system_data_provider.mojom index be8b10e..1e55f33 100644 --- a/chromeos/components/diagnostics_ui/mojom/system_data_provider.mojom +++ b/chromeos/components/diagnostics_ui/mojom/system_data_provider.mojom
@@ -24,10 +24,21 @@ DeviceCapabilities device_capabilities; }; +// Contains information about the battery. +struct BatteryInfo { + string manufacturer; + uint32 charge_full_design_milliamp_hours; +}; + // Provides telemetric information about the system. This API is exposed to the // Diagnostics SWA. interface SystemDataProvider { // Returns a snapshot of system information. |system_info| is static // information that does not change during the lifetime of the service. GetSystemInfo() => (SystemInfo system_info); + + // Returns information about the battery. |battery_info| is static + // information that does not change during the lifetime fo the service. + // If the device does not have a battery, returns an empty BatteryInfo. + GetBatteryInfo() => (BatteryInfo battery_info); };
diff --git a/components/autofill/android/provider/autofill_provider_android.cc b/components/autofill/android/provider/autofill_provider_android.cc index 408ff96..85b68d3d 100644 --- a/components/autofill/android/provider/autofill_provider_android.cc +++ b/components/autofill/android/provider/autofill_provider_android.cc
@@ -337,25 +337,7 @@ void AutofillProviderAndroid::OnFormsSeen(AutofillHandlerProxy* handler, const std::vector<FormData>& forms, - const base::TimeTicks) { - handler_for_testing_ = handler->GetWeakPtr(); - if (!check_submission_) - return; - - if (handler != handler_.get()) - return; - - if (form_.get() == nullptr) - return; - - for (auto const& form : forms) { - if (form_->SimilarFormAs(form)) - return; - } - // The form_ disappeared after it was submitted, we consider the submission - // succeeded. - FireSuccessfulSubmission(pending_submission_source_); -} + const base::TimeTicks timestamp) {} void AutofillProviderAndroid::OnHidePopup(AutofillHandlerProxy* handler) { DCHECK_CURRENTLY_ON(BrowserThread::UI); @@ -372,6 +354,12 @@ void AutofillProviderAndroid::Reset(AutofillHandlerProxy* handler) { DCHECK_CURRENTLY_ON(BrowserThread::UI); if (handler == handler_.get()) { + // If we previously received a notification from the renderer that the form + // was likely submitted and no event caused a reset of state in the interim, + // we consider this navigation to be resulting from the submission. + if (check_submission_ && form_.get()) + FireSuccessfulSubmission(pending_submission_source_); + JNIEnv* env = AttachCurrentThread(); ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); if (obj.is_null())
diff --git a/components/autofill/android/provider/autofill_provider_android.h b/components/autofill/android/provider/autofill_provider_android.h index b0830e23..5ed22d4 100644 --- a/components/autofill/android/provider/autofill_provider_android.h +++ b/components/autofill/android/provider/autofill_provider_android.h
@@ -118,8 +118,6 @@ // Valid only if check_submission_ is true. mojom::SubmissionSource pending_submission_source_; - base::WeakPtr<AutofillHandlerProxy> handler_for_testing_; - DISALLOW_COPY_AND_ASSIGN(AutofillProviderAndroid); }; } // namespace autofill
diff --git a/components/browser_ui/site_settings/OWNERS b/components/browser_ui/site_settings/OWNERS index b8659d3..51a2813f 100644 --- a/components/browser_ui/site_settings/OWNERS +++ b/components/browser_ui/site_settings/OWNERS
@@ -1,7 +1,6 @@ finnur@chromium.org hkamila@chromium.org andypaicu@chromium.org - -per-file CookieControls*=dullweber@chromium.org +dullweber@chromium.org # COMPONENT: UI>Browser>Mobile>Settings
diff --git a/components/content_capture/common/content_capture_features.cc b/components/content_capture/common/content_capture_features.cc index 58832c3..3258e664 100644 --- a/components/content_capture/common/content_capture_features.cc +++ b/components/content_capture/common/content_capture_features.cc
@@ -16,7 +16,7 @@ base::FEATURE_ENABLED_BY_DEFAULT}; const base::Feature kContentCaptureTriggeringForExperiment{ - "ContentCaptureTriggeringForExperiment", base::FEATURE_ENABLED_BY_DEFAULT}; + "ContentCaptureTriggeringForExperiment", base::FEATURE_DISABLED_BY_DEFAULT}; #else const base::Feature kContentCapture{"ContentCapture", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/components/omnibox/browser/autocomplete_match.cc b/components/omnibox/browser/autocomplete_match.cc index 859a792b..81f6995 100644 --- a/components/omnibox/browser/autocomplete_match.cc +++ b/components/omnibox/browser/autocomplete_match.cc
@@ -973,6 +973,8 @@ return OmniboxEventProto::Suggestion::CLIPBOARD_TEXT; case AutocompleteMatchType::CLIPBOARD_IMAGE: return OmniboxEventProto::Suggestion::CLIPBOARD_IMAGE; + case AutocompleteMatchType::TILE_SUGGESTION: + return OmniboxEventProto::Suggestion::TILE_SUGGESTION; case AutocompleteMatchType::VOICE_SUGGEST: // VOICE_SUGGEST matches are only used in Java and are not logged, // so we should never reach this case. @@ -980,7 +982,6 @@ case AutocompleteMatchType::PHYSICAL_WEB_DEPRECATED: case AutocompleteMatchType::PHYSICAL_WEB_OVERFLOW_DEPRECATED: case AutocompleteMatchType::TAB_SEARCH_DEPRECATED: - case AutocompleteMatchType::TILE_SUGGESTION: case AutocompleteMatchType::NUM_TYPES: break; }
diff --git a/components/page_info/page_info_ui.cc b/components/page_info/page_info_ui.cc index 3da415e..982612b 100644 --- a/components/page_info/page_info_ui.cc +++ b/components/page_info/page_info_ui.cc
@@ -639,7 +639,7 @@ icon = &vector_icons::kVideogameAssetIcon; break; case ContentSettingsType::IDLE_DETECTION: - icon = &vector_icons::kIdleDetectionIcon; + icon = &vector_icons::kPersonIcon; break; default: // All other |ContentSettingsType|s do not have icons on desktop or are
diff --git a/components/permissions/android/res/drawable/permission_idle_detection.xml b/components/permissions/android/res/drawable/permission_idle_detection.xml index 48b03075..301f353 100644 --- a/components/permissions/android/res/drawable/permission_idle_detection.xml +++ b/components/permissions/android/res/drawable/permission_idle_detection.xml
@@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <!--Copyright 2020 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.--> <vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" tools:targetApi="21" android:width="24dp" android:height="24dp" android:viewportWidth="24" android:viewportHeight="24"> - <path android:pathData="M21,10.12h-6.78l2.74,-2.82c-2.73,-2.7 -7.15,-2.8 -9.88,-0.1c-2.73,2.71 -2.73,7.08 0,9.79s7.15,2.71 9.88,0C18.32,15.65 19,14.08 19,12.1h2c0,1.98 -0.88,4.55 -2.64,6.29c-3.51,3.48 -9.21,3.48 -12.72,0c-3.5,-3.47 -3.53,-9.11 -0.02,-12.58s9.14,-3.47 12.65,0L21,3V10.12zM12.5,8v4.25l3.5,2.08l-0.72,1.21L11,13V8H12.5z" android:fillColor="#000000"/> + <path android:pathData="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z" android:fillColor="#000000"/> </vector>
diff --git a/components/permissions/permission_request_impl.cc b/components/permissions/permission_request_impl.cc index fac2ab16..d2dc71ac 100644 --- a/components/permissions/permission_request_impl.cc +++ b/components/permissions/permission_request_impl.cc
@@ -105,7 +105,7 @@ case ContentSettingsType::FONT_ACCESS: return vector_icons::kFontDownloadIcon; case ContentSettingsType::IDLE_DETECTION: - return vector_icons::kIdleDetectionIcon; + return vector_icons::kPersonIcon; default: NOTREACHED(); return vector_icons::kExtensionIcon;
diff --git a/components/vector_icons/BUILD.gn b/components/vector_icons/BUILD.gn index 224f4217..9bc67ec 100644 --- a/components/vector_icons/BUILD.gn +++ b/components/vector_icons/BUILD.gn
@@ -42,7 +42,6 @@ "headset.icon", "help.icon", "help_outline.icon", - "idle_detection.icon", "info_outline.icon", "insert_drive_file_outline.icon", "launch.icon", @@ -65,6 +64,7 @@ "open_in_new.icon", "page_info_content_paste.icon", "pause.icon", + "person.icon", "photo.icon", "play_arrow.icon", "protected_content.icon",
diff --git a/components/vector_icons/idle_detection.icon b/components/vector_icons/idle_detection.icon deleted file mode 100644 index 80aafb0..0000000 --- a/components/vector_icons/idle_detection.icon +++ /dev/null
@@ -1,28 +0,0 @@ -// Copyright 2020 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. - -CANVAS_DIMENSIONS, 24, -MOVE_TO, 21, 10.12f, -R_H_LINE_TO, -6.78f, -R_LINE_TO, 2.74f, -2.82f, -R_CUBIC_TO, -2.73f, -2.7f, -7.15f, -2.8f, -9.88f, -0.1f, -R_CUBIC_TO, -2.73f, 2.71f, -2.73f, 7.08f, 0, 9.79f, -R_CUBIC_TO, 2.73f, 2.71f, 7.15f, 2.71f, 9.88f, 0, -CUBIC_TO, 18.32f, 15.65f, 19, 14.08f, 19, 12.1f, -R_H_LINE_TO, 2, -R_CUBIC_TO, 0, 1.98f, -0.88f, 4.55f, -2.64f, 6.29f, -R_CUBIC_TO, -3.51f, 3.48f, -9.21f, 3.48f, -12.72f, 0, -R_CUBIC_TO, -3.5f, -3.47f, -3.53f, -9.11f, -0.02f, -12.58f, -R_CUBIC_TO, 3.51f, -3.47f, 9.14f, -3.47f, 12.65f, 0, -LINE_TO, 21, 3, -V_LINE_TO, 10.12f, -CLOSE, -MOVE_TO, 12.5f, 8, -R_V_LINE_TO, 4.25f, -R_LINE_TO, 3.5f, 2.08f, -R_LINE_TO, -0.72f, 1.21f, -LINE_TO, 11, 13, -V_LINE_TO, 8, -H_LINE_TO, 12.5f, -CLOSE
diff --git a/components/vector_icons/person.icon b/components/vector_icons/person.icon new file mode 100644 index 0000000..2a06e2a --- /dev/null +++ b/components/vector_icons/person.icon
@@ -0,0 +1,18 @@ +// Copyright 2020 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. + +CANVAS_DIMENSIONS, 24, +MOVE_TO, 12, 12, +R_CUBIC_TO, 2.21f, 0, 4, -1.79f, 4, -4, +R_CUBIC_TO, 0, -2.21f, -1.79f, -4, -4, -4, +R_CUBIC_TO, -2.21f, 0, -4, 1.79f, -4, 4, +R_CUBIC_TO, 0, 2.21f, 1.79f, 4, 4, 4, +CLOSE, +R_MOVE_TO, 0, 2, +R_CUBIC_TO, -2.67f, 0, -8, 1.34f, -8, 4, +R_V_LINE_TO, 2, +R_H_LINE_TO, 16, +R_V_LINE_TO, -2, +R_CUBIC_TO, 0, -2.66f, -5.33f, -4, -8, -4, +CLOSE
diff --git a/content/browser/loader/quic_transport_browsertest.cc b/content/browser/loader/quic_transport_browsertest.cc index 7c3f53a..73ec95f2 100644 --- a/content/browser/loader/quic_transport_browsertest.cc +++ b/content/browser/loader/quic_transport_browsertest.cc
@@ -422,5 +422,76 @@ ASSERT_TRUE(WaitForTitle(ASCIIToUTF16("PASS"), {ASCIIToUTF16("FAIL")})); } +IN_PROC_BROWSER_TEST_F(QuicTransportBrowserTest, ReceiveBidirectionalStream) { + ASSERT_TRUE(embedded_test_server()->Start()); + ASSERT_TRUE( + NavigateToURL(shell(), embedded_test_server()->GetURL("/title2.html"))); + + ASSERT_TRUE(WaitForTitle(ASCIIToUTF16("Title Of Awesomeness"))); + + ASSERT_TRUE(ExecuteScript( + shell(), base::StringPrintf(R"JS( + async function run() { + const transport = new QuicTransport( + 'quic-transport://localhost:%d/receive-bidirectional'); + + await transport.ready; + + // Trigger the server to create a bidirectional stream. + const sendStream = await transport.createSendStream(); + // Need to actually write some data to inform the server. + sendStream.writable.getWriter().write(new Uint8Array([1])); + + const streams = transport.receiveBidirectionalStreams(); + const reader = streams.getReader(); + const {value, done} = await reader.read(); + if (done) { + throw new Error('bidirectional streams should not be closed'); + } + await testBidiStream(value); + } + + async function testBidiStream(bidiStream) { + // Consume the initial "hello" that is sent by the server. + const reader = bidiStream.readable.getReader(); + const {value: valueAsBinary, done: done0} = await reader.read(); + if (done0) { + throw new Error('at least one read should happen'); + } + const valueAsString = new TextDecoder().decode(valueAsBinary); + if (valueAsString !== 'hello') { + throw new Error(`expected 'hello', got '${valueAsString}'`); + } + + const data = [65, 66, 67]; + + const writer = bidiStream.writable.getWriter(); + await writer.write(new Uint8Array(data)); + + const {value, done: done1} = await reader.read(); + if (done1) { + throw new Error('reading should not be done'); + } + const actual = Array.from(value); + if (JSON.stringify(actual) !== JSON.stringify(data)) { + throw new Error('arrays do not match'); + } + + await writer.close(); + + const {done: done2} = await reader.read(); + if (!done2) { + throw new Error('receiveStream should be done'); + } + } + + run().then(() => { document.title = 'PASS'; }, + (e) => { console.log(e); document.title = 'FAIL'; }); +)JS", + server_.server_address().port()))); + + ASSERT_TRUE(WaitForTitle(ASCIIToUTF16("PASS"), {ASCIIToUTF16("FAIL")})); +} + } // namespace } // namespace content
diff --git a/content/browser/payments/payment_app_browsertest.cc b/content/browser/payments/payment_app_browsertest.cc index 81f7db3a..08e6dae 100644 --- a/content/browser/payments/payment_app_browsertest.cc +++ b/content/browser/payments/payment_app_browsertest.cc
@@ -295,8 +295,9 @@ ClearStoragePartitionData(); } -// TODO(crbug.com/869790) Flakes on linux-chromeos-dbg -#if defined(OS_CHROMEOS) && !defined(NDEBUG) +// TODO(https://crbug.com/1129411) Fix flake on all desktop platforms. +#if defined(OS_CHROMEOS) || defined(OS_LINUX) || defined(OS_MAC) || \ + defined(OS_WIN) #define MAYBE_CanMakePayment DISABLED_CanMakePayment #else #define MAYBE_CanMakePayment CanMakePayment @@ -351,8 +352,9 @@ ClearStoragePartitionData(); } -// TODO(crbug.com/869790) Flakes on linux-chromeos-dbg -#if defined(OS_CHROMEOS) && !defined(NDEBUG) +// TODO(https://crbug.com/1129411) Fix flake on all desktop platforms. +#if defined(OS_CHROMEOS) || defined(OS_LINUX) || defined(OS_MAC) || \ + defined(OS_WIN) #define MAYBE_PaymentAppInvocation DISABLED_PaymentAppInvocation #else #define MAYBE_PaymentAppInvocation PaymentAppInvocation @@ -393,8 +395,9 @@ PopConsoleString() /* instrumentKey */); } -// TODO(crbug.com/869790) Flakes on linux-chromeos-dbg -#if defined(OS_CHROMEOS) && !defined(NDEBUG) +// TODO(https://crbug.com/1129411) Fix flake on all desktop platforms. +#if defined(OS_CHROMEOS) || defined(OS_LINUX) || defined(OS_MAC) || \ + defined(OS_WIN) #define MAYBE_PaymentAppOpenWindowFailed DISABLED_PaymentAppOpenWindowFailed #else #define MAYBE_PaymentAppOpenWindowFailed PaymentAppOpenWindowFailed
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index 54f63e0..00365af8 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -4473,32 +4473,19 @@ render_process_host = GetUnusedProcessHostForServiceWorker(site_instance); } - if (render_process_host) { - site_instance->set_process_assignment( - SiteInstanceProcessAssignment::REUSED_EXISTING_PROCESS); - } - // See if the spare RenderProcessHost can be used. auto& spare_process_manager = SpareRenderProcessHostManager::GetInstance(); bool spare_was_taken = false; if (!render_process_host) { render_process_host = spare_process_manager.MaybeTakeSpareRenderProcessHost( browser_context, site_instance); - if (render_process_host) { - site_instance->set_process_assignment( - SiteInstanceProcessAssignment::USED_SPARE_PROCESS); - spare_was_taken = true; - } + spare_was_taken = (render_process_host != nullptr); } // If not (or if none found), see if we should reuse an existing process. if (!render_process_host && ShouldTryToUseExistingProcessHost( browser_context, site_info.site_url())) { render_process_host = GetExistingProcessHost(site_instance); - if (render_process_host) { - site_instance->set_process_assignment( - SiteInstanceProcessAssignment::REUSED_EXISTING_PROCESS); - } } // If we found a process to reuse, sanity check that it is suitable for @@ -4524,9 +4511,6 @@ // issues as TestBrowserContext initialization is done on the main thread. render_process_host = CreateRenderProcessHost(browser_context, site_instance); - - site_instance->set_process_assignment( - SiteInstanceProcessAssignment::CREATED_NEW_PROCESS); } // It is important to call PrepareForFutureRequests *after* potentially
diff --git a/content/browser/renderer_host/render_process_host_unittest.cc b/content/browser/renderer_host/render_process_host_unittest.cc index 2a0b3b0..e9c43852 100644 --- a/content/browser/renderer_host/render_process_host_unittest.cc +++ b/content/browser/renderer_host/render_process_host_unittest.cc
@@ -81,7 +81,7 @@ // Verify that the renderer sharing will happen. GURL test_url("http://foo.com"); EXPECT_TRUE(RenderProcessHostImpl::ShouldTryToUseExistingProcessHost( - browser_context(), test_url)); + browser_context(), test_url)); } #endif @@ -97,7 +97,7 @@ // Verify that the renderer sharing still won't happen. GURL test_url("http://foo.com"); EXPECT_FALSE(RenderProcessHostImpl::ShouldTryToUseExistingProcessHost( - browser_context(), test_url)); + browser_context(), test_url)); } #endif @@ -112,8 +112,6 @@ SiteInstanceImpl::CreateReusableInstanceForTesting(browser_context(), kUrl1); EXPECT_NE(main_test_rfh()->GetProcess(), site_instance->GetProcess()); - EXPECT_EQ(SiteInstanceProcessAssignment::CREATED_NEW_PROCESS, - site_instance->GetLastProcessAssignmentOutcome()); // Have the main frame navigate to the first url. Getting a RenderProcessHost // with the REUSE_PENDING_OR_COMMITTED_SITE policy should now return the @@ -122,8 +120,6 @@ site_instance = SiteInstanceImpl::CreateReusableInstanceForTesting( browser_context(), kUrl1); EXPECT_EQ(main_test_rfh()->GetProcess(), site_instance->GetProcess()); - EXPECT_EQ(SiteInstanceProcessAssignment::REUSED_EXISTING_PROCESS, - site_instance->GetLastProcessAssignmentOutcome()); // Navigate away. Getting a RenderProcessHost with the // REUSE_PENDING_OR_COMMITTED_SITE policy should again return a new process. @@ -131,11 +127,6 @@ site_instance = SiteInstanceImpl::CreateReusableInstanceForTesting( browser_context(), kUrl1); EXPECT_NE(main_test_rfh()->GetProcess(), site_instance->GetProcess()); - EXPECT_EQ(RenderProcessHostImpl::IsSpareProcessKeptAtAllTimes() - ? SiteInstanceProcessAssignment::USED_SPARE_PROCESS - : SiteInstanceProcessAssignment::CREATED_NEW_PROCESS, - site_instance->GetLastProcessAssignmentOutcome()); - // Now add a subframe that navigates to kUrl1. Getting a RenderProcessHost // with the REUSE_PENDING_OR_COMMITTED_SITE policy for kUrl1 should now // return the process of the subframe RFH. @@ -155,8 +146,6 @@ site_instance = SiteInstanceImpl::CreateReusableInstanceForTesting( browser_context(), kUrl1); EXPECT_EQ(subframe->GetProcess(), site_instance->GetProcess()); - EXPECT_EQ(SiteInstanceProcessAssignment::REUSED_EXISTING_PROCESS, - site_instance->GetLastProcessAssignmentOutcome()); } // Check that only new processes that haven't yet hosted any web content are @@ -196,8 +185,6 @@ scoped_refptr<SiteInstanceImpl> sw_site_instance1 = SiteInstanceImpl::CreateForServiceWorker(browser_context(), kUrl); RenderProcessHost* sw_host1 = sw_site_instance1->GetProcess(); - EXPECT_EQ(SiteInstanceProcessAssignment::CREATED_NEW_PROCESS, - sw_site_instance1->GetLastProcessAssignmentOutcome()); // Getting a RenderProcessHost for a service worker with DEFAULT reuse policy // should not reuse the existing service worker's process. We create this @@ -206,16 +193,12 @@ SiteInstanceImpl::CreateForServiceWorker(browser_context(), kUrl); RenderProcessHost* sw_host2 = sw_site_instance2->GetProcess(); EXPECT_NE(sw_host1, sw_host2); - EXPECT_EQ(SiteInstanceProcessAssignment::CREATED_NEW_PROCESS, - sw_site_instance2->GetLastProcessAssignmentOutcome()); // Getting a RenderProcessHost for a navigation to the same site must reuse // the newest unmatched service worker's process (i.e., sw_host2). scoped_refptr<SiteInstanceImpl> site_instance1 = SiteInstanceImpl::CreateForURL(browser_context(), kUrl); EXPECT_EQ(sw_host2, site_instance1->GetProcess()); - EXPECT_EQ(SiteInstanceProcessAssignment::REUSED_EXISTING_PROCESS, - site_instance1->GetLastProcessAssignmentOutcome()); // Getting a RenderProcessHost for a navigation to the same site must reuse // the newest unmatched service worker's process (i.e., sw_host1). sw_host2 @@ -224,8 +207,6 @@ scoped_refptr<SiteInstanceImpl> site_instance2 = SiteInstanceImpl::CreateForURL(browser_context(), kUrl); EXPECT_EQ(sw_host1, site_instance2->GetProcess()); - EXPECT_EQ(SiteInstanceProcessAssignment::REUSED_EXISTING_PROCESS, - site_instance2->GetLastProcessAssignmentOutcome()); // Getting a RenderProcessHost for a navigation should return a new process // because there is no unmatched service worker's process. @@ -233,8 +214,6 @@ SiteInstanceImpl::CreateForURL(browser_context(), kUrl); EXPECT_NE(sw_host1, site_instance3->GetProcess()); EXPECT_NE(sw_host2, site_instance3->GetProcess()); - EXPECT_EQ(SiteInstanceProcessAssignment::CREATED_NEW_PROCESS, - site_instance3->GetLastProcessAssignmentOutcome()); } class UnsuitableHostContentBrowserClient : public ContentBrowserClient { @@ -259,8 +238,6 @@ scoped_refptr<SiteInstanceImpl> sw_site_instance = SiteInstanceImpl::CreateForServiceWorker(browser_context(), kUrl); RenderProcessHost* sw_host = sw_site_instance->GetProcess(); - EXPECT_EQ(SiteInstanceProcessAssignment::CREATED_NEW_PROCESS, - sw_site_instance->GetLastProcessAssignmentOutcome()); // Simulate a situation where |sw_host| won't be considered suitable for // future navigations to |kUrl|. In https://crbug.com/782349, this happened @@ -281,8 +258,6 @@ scoped_refptr<SiteInstanceImpl> site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl); EXPECT_NE(sw_host, site_instance->GetProcess()); - EXPECT_EQ(SiteInstanceProcessAssignment::CREATED_NEW_PROCESS, - sw_site_instance->GetLastProcessAssignmentOutcome()); SetBrowserClientForTesting(regular_client); } @@ -295,8 +270,6 @@ SiteInstanceImpl::CreateForServiceWorker(browser_context(), kUrl, /* can_reuse_process */ true); RenderProcessHost* sw_host1 = sw_site_instance1->GetProcess(); - EXPECT_EQ(SiteInstanceProcessAssignment::CREATED_NEW_PROCESS, - sw_site_instance1->GetLastProcessAssignmentOutcome()); // Getting a RenderProcessHost for a service worker with DEFAULT reuse policy // should not reuse the existing service worker's process. This is because @@ -307,8 +280,6 @@ SiteInstanceImpl::CreateForServiceWorker(browser_context(), kUrl); RenderProcessHost* sw_host2 = sw_site_instance2->GetProcess(); EXPECT_NE(sw_host1, sw_host2); - EXPECT_EQ(SiteInstanceProcessAssignment::CREATED_NEW_PROCESS, - sw_site_instance2->GetLastProcessAssignmentOutcome()); // Getting a RenderProcessHost for a service worker of the same site with // REUSE_PENDING_OR_COMMITTED_SITE reuse policy should reuse the newest @@ -318,8 +289,6 @@ /* can_reuse_process */ true); RenderProcessHost* sw_host3 = sw_site_instance3->GetProcess(); EXPECT_EQ(sw_host2, sw_host3); - EXPECT_EQ(SiteInstanceProcessAssignment::REUSED_EXISTING_PROCESS, - sw_site_instance3->GetLastProcessAssignmentOutcome()); // Getting a RenderProcessHost for a service worker of the same site with // REUSE_PENDING_OR_COMMITTED_SITE reuse policy should reuse the newest @@ -331,16 +300,12 @@ /* can_reuse_process */ true); RenderProcessHost* sw_host4 = sw_site_instance4->GetProcess(); EXPECT_EQ(sw_host2, sw_host4); - EXPECT_EQ(SiteInstanceProcessAssignment::REUSED_EXISTING_PROCESS, - sw_site_instance4->GetLastProcessAssignmentOutcome()); // Getting a RenderProcessHost for a navigation to the same site must reuse // the newest unmatched service worker's process (i.e., sw_host2). scoped_refptr<SiteInstanceImpl> site_instance1 = SiteInstanceImpl::CreateForURL(browser_context(), kUrl); EXPECT_EQ(sw_host2, site_instance1->GetProcess()); - EXPECT_EQ(SiteInstanceProcessAssignment::REUSED_EXISTING_PROCESS, - site_instance1->GetLastProcessAssignmentOutcome()); // Getting a RenderProcessHost for a navigation to the same site must reuse // the newest unmatched service worker's process (i.e., sw_host1). sw_host2 @@ -349,8 +314,6 @@ scoped_refptr<SiteInstanceImpl> site_instance2 = SiteInstanceImpl::CreateForURL(browser_context(), kUrl); EXPECT_EQ(sw_host1, site_instance2->GetProcess()); - EXPECT_EQ(SiteInstanceProcessAssignment::REUSED_EXISTING_PROCESS, - site_instance2->GetLastProcessAssignmentOutcome()); } TEST_F(RenderProcessHostUnitTest, @@ -363,8 +326,6 @@ scoped_refptr<SiteInstanceImpl> sw_site_instance1 = SiteInstanceImpl::CreateForServiceWorker(browser_context(), kUrl); RenderProcessHost* sw_host1 = sw_site_instance1->GetProcess(); - EXPECT_EQ(SiteInstanceProcessAssignment::CREATED_NEW_PROCESS, - sw_site_instance1->GetLastProcessAssignmentOutcome()); // Getting a RenderProcessHost for a service worker of the same site with // process-per-site flag should reuse the unmatched service worker's process. @@ -372,8 +333,6 @@ SiteInstanceImpl::CreateForServiceWorker(browser_context(), kUrl); RenderProcessHost* sw_host2 = sw_site_instance2->GetProcess(); EXPECT_EQ(sw_host1, sw_host2); - EXPECT_EQ(SiteInstanceProcessAssignment::REUSED_EXISTING_PROCESS, - sw_site_instance2->GetLastProcessAssignmentOutcome()); // Getting a RenderProcessHost for a navigation to the same site with // process-per-site flag should reuse the unmatched service worker's process. @@ -381,8 +340,6 @@ SiteInstanceImpl::CreateForURL(browser_context(), kUrl); RenderProcessHost* sw_host3 = sw_site_instance3->GetProcess(); EXPECT_EQ(sw_host1, sw_host3); - EXPECT_EQ(SiteInstanceProcessAssignment::REUSED_EXISTING_PROCESS, - sw_site_instance3->GetLastProcessAssignmentOutcome()); // Getting a RenderProcessHost for a navigation to the same site again with // process-per-site flag should reuse the unmatched service worker's process. @@ -390,8 +347,6 @@ SiteInstanceImpl::CreateForURL(browser_context(), kUrl); RenderProcessHost* sw_host4 = sw_site_instance4->GetProcess(); EXPECT_EQ(sw_host1, sw_host4); - EXPECT_EQ(SiteInstanceProcessAssignment::REUSED_EXISTING_PROCESS, - sw_site_instance4->GetLastProcessAssignmentOutcome()); } TEST_F(RenderProcessHostUnitTest, DoNotReuseOtherSiteServiceWorkerProcess) { @@ -402,16 +357,12 @@ scoped_refptr<SiteInstanceImpl> sw_site_instance1 = SiteInstanceImpl::CreateForServiceWorker(browser_context(), kUrl1); RenderProcessHost* sw_host1 = sw_site_instance1->GetProcess(); - EXPECT_EQ(SiteInstanceProcessAssignment::CREATED_NEW_PROCESS, - sw_site_instance1->GetLastProcessAssignmentOutcome()); // Getting a RenderProcessHost for a service worker of a different site should // return a new process because there is no reusable process. scoped_refptr<SiteInstanceImpl> sw_site_instance2 = SiteInstanceImpl::CreateForURL(browser_context(), kUrl2); EXPECT_NE(sw_host1, sw_site_instance2->GetProcess()); - EXPECT_EQ(SiteInstanceProcessAssignment::CREATED_NEW_PROCESS, - sw_site_instance2->GetLastProcessAssignmentOutcome()); } // Tests that RenderProcessHost will not consider reusing a process that has @@ -915,18 +866,6 @@ } } -// Checks that SiteInstanceProcessAssignment::UNKNOWN is used as the zero-value -// when no renderer process has been assigned to the SiteInstance yet. -TEST_F(RenderProcessHostUnitTest, ProcessAssignmentDefault) { - const GURL kUrl("https://foo.com"); - - scoped_refptr<SiteInstanceImpl> site_instance = - SiteInstanceImpl::CreateForURL(browser_context(), kUrl); - EXPECT_EQ(SiteInstanceProcessAssignment::UNKNOWN, - site_instance->GetLastProcessAssignmentOutcome()); - EXPECT_FALSE(site_instance->HasProcess()); -} - class SpareRenderProcessHostUnitTest : public RenderViewHostImplTestHarness { public: SpareRenderProcessHostUnitTest() {}
diff --git a/content/browser/site_instance_impl.cc b/content/browser/site_instance_impl.cc index 7eb2353..ed973ac9 100644 --- a/content/browser/site_instance_impl.cc +++ b/content/browser/site_instance_impl.cc
@@ -163,8 +163,7 @@ has_site_(false), process_reuse_policy_(ProcessReusePolicy::DEFAULT), is_for_service_worker_(false), - is_guest_(false), - process_assignment_(SiteInstanceProcessAssignment::UNKNOWN) { + is_guest_(false) { DCHECK(browsing_instance); } @@ -499,8 +498,8 @@ void SiteInstanceImpl::SetSite(const GURL& url) { // TODO(creis): Consider calling ShouldAssignSiteForURL internally, rather // than before multiple call sites. See https://crbug.com/949220. - TRACE_EVENT2("navigation", "SiteInstanceImpl::SetSite", "site id", id_, "url", - url.possibly_invalid_spec()); + TRACE_EVENT2("navigation", "SiteInstanceImpl::SetSite", + "site id", id_, "url", url.possibly_invalid_spec()); // A SiteInstance's site should not change. // TODO(creis): When following links or script navigations, we can currently // render pages from other sites in this SiteInstance. This will eventually @@ -581,11 +580,6 @@ SetSite(url); } -SiteInstanceProcessAssignment -SiteInstanceImpl::GetLastProcessAssignmentOutcome() { - return process_assignment_; -} - const GURL& SiteInstanceImpl::GetSiteURL() { return site_info_.site_url(); } @@ -613,9 +607,8 @@ } bool SiteInstanceImpl::IsRelatedSiteInstance(const SiteInstance* instance) { - return browsing_instance_.get() == - static_cast<const SiteInstanceImpl*>(instance) - ->browsing_instance_.get(); + return browsing_instance_.get() == static_cast<const SiteInstanceImpl*>( + instance)->browsing_instance_.get(); } size_t SiteInstanceImpl::GetRelatedActiveContentsCount() {
diff --git a/content/browser/site_instance_impl.h b/content/browser/site_instance_impl.h index c8ae97da..ecebcc5 100644 --- a/content/browser/site_instance_impl.h +++ b/content/browser/site_instance_impl.h
@@ -236,13 +236,6 @@ bool RequiresDedicatedProcess() override; bool IsSameSiteWithURL(const GURL& url) override; bool IsGuest() override; - SiteInstanceProcessAssignment GetLastProcessAssignmentOutcome() override; - - // This is called every time a renderer process is assigned to a SiteInstance - // and is used by the content embedder for collecting metrics. - void set_process_assignment(SiteInstanceProcessAssignment assignment) { - process_assignment_ = assignment; - } // The policy to apply when selecting a RenderProcessHost for the // SiteInstance. If no suitable RenderProcessHost for the SiteInstance exists @@ -458,7 +451,8 @@ // hosts. // Only public so that we can make a consistent process swap decision in // RenderFrameHostManager. - static GURL GetEffectiveURL(BrowserContext* browser_context, const GURL& url); + static GURL GetEffectiveURL(BrowserContext* browser_context, + const GURL& url); // Returns true if pages loaded from |site_info| ought to be handled only by a // renderer process isolated from other sites. If --site-per-process is used, @@ -693,9 +687,6 @@ // TODO(734722): Move this into the SecurityPrincipal once it is available. bool is_guest_; - // How |this| was last assigned to a renderer process. - SiteInstanceProcessAssignment process_assignment_; - base::ObserverList<Observer, true>::Unchecked observers_; DISALLOW_COPY_AND_ASSIGN(SiteInstanceImpl);
diff --git a/content/public/browser/BUILD.gn b/content/public/browser/BUILD.gn index 309e4a8..e9202703 100644 --- a/content/public/browser/BUILD.gn +++ b/content/public/browser/BUILD.gn
@@ -341,7 +341,6 @@ "shared_worker_instance.h", "shared_worker_service.h", "site_instance.h", - "site_instance_process_assignment.h", "site_isolation_policy.cc", "site_isolation_policy.h", "sms_fetcher.h",
diff --git a/content/public/browser/site_instance.h b/content/public/browser/site_instance.h index a721f2f..0e6c3d0 100644 --- a/content/public/browser/site_instance.h +++ b/content/public/browser/site_instance.h
@@ -10,7 +10,6 @@ #include "base/memory/ref_counted.h" #include "content/common/content_export.h" -#include "content/public/browser/site_instance_process_assignment.h" #include "url/gurl.h" namespace content { @@ -170,12 +169,6 @@ // Returns true if this object is used for a <webview> guest. virtual bool IsGuest() = 0; - // Returns how this SiteInstance was assigned to a renderer process the most - // recent time that such an assignment was done. This allows the content - // embedder to collect metrics on how renderer process starting or reuse - // affects performance. - virtual SiteInstanceProcessAssignment GetLastProcessAssignmentOutcome() = 0; - // Factory method to create a new SiteInstance. This will create a new // BrowsingInstance, so it should only be used when creating a new tab from // scratch (or similar circumstances).
diff --git a/content/public/browser/site_instance_process_assignment.h b/content/public/browser/site_instance_process_assignment.h deleted file mode 100644 index 04cfd1f..0000000 --- a/content/public/browser/site_instance_process_assignment.h +++ /dev/null
@@ -1,27 +0,0 @@ -// Copyright (c) 2020 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. - -#ifndef CONTENT_PUBLIC_BROWSER_SITE_INSTANCE_PROCESS_ASSIGNMENT_H_ -#define CONTENT_PUBLIC_BROWSER_SITE_INSTANCE_PROCESS_ASSIGNMENT_H_ - -namespace content { - -// This enum describes how a renderer process is assigned to a SiteInstance. -enum class SiteInstanceProcessAssignment { - // No renderer process has been assigned to the SiteInstance yet. - UNKNOWN, - - // Reused some pre-existing process. - REUSED_EXISTING_PROCESS, - - // Used an existing spare process. - USED_SPARE_PROCESS, - - // No renderer could be reused, so a new one was created for the SiteInstance. - CREATED_NEW_PROCESS, -}; - -} // namespace content - -#endif // CONTENT_PUBLIC_BROWSER_SITE_INSTANCE_PROCESS_ASSIGNMENT_H_
diff --git a/content/test/gpu/gpu_tests/skia_gold/gpu_skia_gold_session_manager.py b/content/test/gpu/gpu_tests/skia_gold/gpu_skia_gold_session_manager.py index 6fe4207..d1b7e23 100644 --- a/content/test/gpu/gpu_tests/skia_gold/gpu_skia_gold_session_manager.py +++ b/content/test/gpu/gpu_tests/skia_gold/gpu_skia_gold_session_manager.py
@@ -13,7 +13,7 @@ class GpuSkiaGoldSessionManager(sgsm.SkiaGoldSessionManager): @staticmethod def _GetDefaultInstance(): - return 'chrome-gpu' + return 'chrome' @staticmethod def _GetSessionClass():
diff --git a/content/test/gpu/gpu_tests/skia_gold_integration_test_base.py b/content/test/gpu/gpu_tests/skia_gold_integration_test_base.py index 8233720..b720910 100644 --- a/content/test/gpu/gpu_tests/skia_gold_integration_test_base.py +++ b/content/test/gpu/gpu_tests/skia_gold_integration_test_base.py
@@ -29,8 +29,7 @@ os.path.join(path_util.GetChromiumSrcDir(), 'media/test/data'), ] -SKIA_GOLD_INSTANCE = 'chrome-gpu' -SKIA_GOLD_CORPUS = SKIA_GOLD_INSTANCE +SKIA_GOLD_CORPUS = 'chrome-gpu' class _ImageParameters(object): @@ -344,25 +343,13 @@ gpu_keys = self.GetGoldJsonKeys(page) gold_session = self.GetSkiaGoldSessionManager().GetSkiaGoldSession( - gpu_keys, corpus=SKIA_GOLD_CORPUS, instance='chrome') + gpu_keys, corpus=SKIA_GOLD_CORPUS) gold_properties = self.GetSkiaGoldProperties() use_luci = not (gold_properties.local_pixel_tests or gold_properties.no_luci_auth) inexact_matching_args = page.matching_algorithm.GetCmdline() - # TODO(crbug.com/1113308): Switch the FYI session to the only session once - # all the data is migrated to the Chrome Gold instance. - status, error = gold_session.RunComparison( - name=image_name, - png_file=png_temp_file, - inexact_matching_args=inexact_matching_args, - use_luci=use_luci) - if status: - logging.warning('FYI Gold comparison failed with status %s and error %s', - status, error) - - gold_session = self.GetSkiaGoldSessionManager().GetSkiaGoldSession(gpu_keys) status, error = gold_session.RunComparison( name=image_name, png_file=png_temp_file,
diff --git a/gpu/command_buffer/service/webgpu_decoder_impl.cc b/gpu/command_buffer/service/webgpu_decoder_impl.cc index d8d31f4..bacd6d5 100644 --- a/gpu/command_buffer/service/webgpu_decoder_impl.cc +++ b/gpu/command_buffer/service/webgpu_decoder_impl.cc
@@ -652,6 +652,10 @@ device_descriptor.requiredExtensions.push_back("shader_float16"); } + if (request_device_properties.timestampQuery) { + device_descriptor.requiredExtensions.push_back("timestamp_query"); + } + WGPUDevice wgpu_device = dawn_adapters_[requested_adapter_index].CreateDevice(&device_descriptor); if (wgpu_device == nullptr) {
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_app_interface.h b/ios/chrome/browser/ui/content_suggestions/content_suggestions_app_interface.h index 429cc58..ffdae458 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_app_interface.h +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_app_interface.h
@@ -46,8 +46,11 @@ + (void)resetWhatsNewPromo; // Returns the width the search field is supposed to have when the collection -// has |collectionWidth|. -+ (CGFloat)searchFieldWidthForCollectionWidth:(CGFloat)collectionWidth; +// has |collectionWidth|. |traitCollection| is the trait collection of the view +// displaying the omnibox, its Size Class is used in the computation. ++ (CGFloat)searchFieldWidthForCollectionWidth:(CGFloat)collectionWidth + traitCollection: + (UITraitCollection*)traitCollection; // Returns the collection view. + (UICollectionView*)collectionView;
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_app_interface.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_app_interface.mm index 75a50f8..480e11e 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_app_interface.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_app_interface.mm
@@ -178,8 +178,11 @@ ios::NotificationPromo::MigrateUserPrefs(local_state); } -+ (CGFloat)searchFieldWidthForCollectionWidth:(CGFloat)collectionWidth { - return content_suggestions::searchFieldWidth(collectionWidth); ++ (CGFloat)searchFieldWidthForCollectionWidth:(CGFloat)collectionWidth + traitCollection: + (UITraitCollection*)traitCollection { + return content_suggestions::searchFieldWidth(collectionWidth, + traitCollection); } + (UICollectionView*)collectionView {
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils.h b/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils.h index 243871850..3b5e48c 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils.h +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils.h
@@ -14,26 +14,35 @@ extern const CGFloat kHintTextScale; // Returns the proper height for the doodle. |logoIsShowing| refers to the -// Google logo or the doodle. -CGFloat doodleHeight(BOOL logoIsShowing); +// Google logo or the doodle. The SizeClass of the |traitCollection| of the view +// displaying the doodle is used in the computation. +CGFloat doodleHeight(BOOL logoIsShowing, UITraitCollection* traitCollection); // Returns the proper margin to the top of the header for the doodle. // If |toolbarPresent| is true, the top margin include a space to display the -// toolbar. Adds |topInset| to non-RxR displays. -CGFloat doodleTopMargin(BOOL toolbarPresent, CGFloat topInset); +// toolbar. Adds |topInset| to non-RxR displays. The SizeClass of the +// |traitCollection| of the view displaying the doodle is used. +CGFloat doodleTopMargin(BOOL toolbarPresent, + CGFloat topInset, + UITraitCollection* traitCollection); // Returns the proper margin to the bottom of the doodle for the search field. CGFloat searchFieldTopMargin(); // Returns the proper width for the search field inside a view with a |width|. -CGFloat searchFieldWidth(CGFloat superviewWidth); +// The SizeClass of the |traitCollection| of the view displaying the search +// field is used in the computation. +CGFloat searchFieldWidth(CGFloat superviewWidth, + UITraitCollection* traitCollection); // TODO(crbug.com/761817): Remove |toolbarPresent| once the transition to the // new architecture is completed. // Returns the expected height of the header. |logoIsShowing| refers to the // Google logo or the doodle. |promoCanShow| represents whether a what's new // promo can be displayed. |toolbarPresent| represent whether the height should -// take into account a space to show the toolbar. +// take into account a space to show the toolbar. The SizeClass of the +// |traitCollection| of the view displaying the logo is used in the computation. CGFloat heightForLogoHeader(BOOL logoIsShowing, BOOL promoCanShow, BOOL toolbarPresent, - CGFloat topInset); + CGFloat topInset, + UITraitCollection* traitCollection); // Configure the |searchHintLabel| for the fake omnibox. |hintLabelContainer| // is added to the |searchTapTarget| with autolayout and |searchHintLabel| is // added to |hintLabelContainer| with autoresizing. This is done due to the
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils.mm index e899216..3b3a982f 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils.mm
@@ -58,17 +58,19 @@ const int kSearchFieldBackgroundColor = 0xF1F3F4; const CGFloat kHintTextScale = 0.15; -CGFloat doodleHeight(BOOL logoIsShowing) { - if (!IsRegularXRegularSizeClass() && !logoIsShowing) +CGFloat doodleHeight(BOOL logoIsShowing, UITraitCollection* traitCollection) { + if (!IsRegularXRegularSizeClass(traitCollection) && !logoIsShowing) return kNonGoogleSearchDoodleHeight; return kGoogleSearchDoodleHeight; } -CGFloat doodleTopMargin(BOOL toolbarPresent, CGFloat topInset) { - if (!IsCompactWidth() && !IsCompactHeight()) +CGFloat doodleTopMargin(BOOL toolbarPresent, + CGFloat topInset, + UITraitCollection* traitCollection) { + if (IsRegularXRegularSizeClass(traitCollection)) return kDoodleTopMarginRegularXRegular; - if (IsCompactHeight()) + if (IsCompactHeight(traitCollection)) return topInset; return topInset + kDoodleTopMarginOther + AlignValueToPixel(kDoodleScaledTopMarginOther * @@ -79,8 +81,9 @@ return kSearchFieldTopMargin; } -CGFloat searchFieldWidth(CGFloat superviewWidth) { - if (!IsCompactWidth() && !IsCompactHeight()) +CGFloat searchFieldWidth(CGFloat superviewWidth, + UITraitCollection* traitCollection) { + if (!IsCompactWidth(traitCollection) && !IsCompactHeight(traitCollection)) return kSearchFieldLarge; // Special case for narrow sizes. @@ -90,14 +93,15 @@ CGFloat heightForLogoHeader(BOOL logoIsShowing, BOOL promoCanShow, BOOL toolbarPresent, - CGFloat topInset) { + CGFloat topInset, + UITraitCollection* traitCollection) { CGFloat headerHeight = - doodleTopMargin(toolbarPresent, topInset) + doodleHeight(logoIsShowing) + - searchFieldTopMargin() + + doodleTopMargin(toolbarPresent, topInset, traitCollection) + + doodleHeight(logoIsShowing, traitCollection) + searchFieldTopMargin() + ToolbarExpandedHeight( [UIApplication sharedApplication].preferredContentSizeCategory) + kNTPSearchFieldBottomPadding; - if (!IsRegularXRegularSizeClass()) { + if (!IsRegularXRegularSizeClass(traitCollection)) { return headerHeight; } if (!logoIsShowing) {
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils_unittest.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils_unittest.mm index 4dd94ebb..e5aad302 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils_unittest.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils_unittest.mm
@@ -21,86 +21,41 @@ class ContentSuggestionsCollectionUtilsTest : public PlatformTest { public: - void SetAsIPad() { + UITraitCollection* IPadTraitCollection() { UITraitCollection* horizontalRegular = [UITraitCollection traitCollectionWithHorizontalSizeClass:UIUserInterfaceSizeClassRegular]; UITraitCollection* verticalRegular = [UITraitCollection traitCollectionWithVerticalSizeClass:UIUserInterfaceSizeClassRegular]; - UITraitCollection* custom_trait_collection = - [UITraitCollection traitCollectionWithTraitsFromCollections:@[ - verticalRegular, horizontalRegular - ]]; - - SetSwizzlersUp(custom_trait_collection, UIUserInterfaceIdiomPad, - UIInterfaceOrientationPortrait); + return [UITraitCollection traitCollectionWithTraitsFromCollections:@[ + verticalRegular, horizontalRegular + ]]; } - void SetAsIPhoneLandscape() { + UITraitCollection* IPhoneLandscapeTraitCollection() { UITraitCollection* horizontalCompact = [UITraitCollection traitCollectionWithHorizontalSizeClass:UIUserInterfaceSizeClassCompact]; UITraitCollection* verticalCompact = [UITraitCollection traitCollectionWithVerticalSizeClass:UIUserInterfaceSizeClassCompact]; - UITraitCollection* custom_trait_collection = - [UITraitCollection traitCollectionWithTraitsFromCollections:@[ - verticalCompact, horizontalCompact - ]]; - - SetSwizzlersUp(custom_trait_collection, UIUserInterfaceIdiomPhone, - UIInterfaceOrientationLandscapeLeft); + return [UITraitCollection traitCollectionWithTraitsFromCollections:@[ + verticalCompact, horizontalCompact + ]]; } - void SetAsIPhonePortrait() { + UITraitCollection* IPhonePortraitTraitCollection() { UITraitCollection* horizontalCompact = [UITraitCollection traitCollectionWithHorizontalSizeClass:UIUserInterfaceSizeClassCompact]; UITraitCollection* verticalRegular = [UITraitCollection traitCollectionWithVerticalSizeClass:UIUserInterfaceSizeClassRegular]; - UITraitCollection* custom_trait_collection = - [UITraitCollection traitCollectionWithTraitsFromCollections:@[ - verticalRegular, horizontalCompact - ]]; - - SetSwizzlersUp(custom_trait_collection, UIUserInterfaceIdiomPhone, - UIInterfaceOrientationPortrait); + return [UITraitCollection traitCollectionWithTraitsFromCollections:@[ + verticalRegular, horizontalCompact + ]]; } - - private: - // Sets up the swizzler for the different parameters passed. - void SetSwizzlersUp(UITraitCollection* custom_trait_collection, - UIUserInterfaceIdiom custom_interface, - UIInterfaceOrientation custom_orientation) { - customTraitCollection_ = custom_trait_collection; - trait_swizzler_ = std::make_unique<ScopedBlockSwizzler>( - [UIWindow class], @selector(traitCollection), - ^UITraitCollection*(id self) { - return customTraitCollection_; - }); - - device_type_swizzler_ = std::make_unique<ScopedBlockSwizzler>( - [UIDevice class], @selector(userInterfaceIdiom), - ^UIUserInterfaceIdiom(id self) { - return custom_interface; - }); - - orientation_swizzler_ = std::make_unique<ScopedBlockSwizzler>( - [UIApplication class], @selector(statusBarOrientation), - ^UIInterfaceOrientation(id self) { - return custom_orientation; - }); - } - - UITraitCollection* customTraitCollection_; - std::unique_ptr<ScopedBlockSwizzler> trait_swizzler_; - std::unique_ptr<ScopedBlockSwizzler> device_type_swizzler_; - std::unique_ptr<ScopedBlockSwizzler> orientation_swizzler_; }; TEST_F(ContentSuggestionsCollectionUtilsTest, doodleFrameIPad) { - // Setup. - SetAsIPad(); - // Action. - CGFloat height = doodleHeight(YES); - CGFloat topMargin = doodleTopMargin(YES, kTopInset); + CGFloat height = doodleHeight(YES, IPadTraitCollection()); + CGFloat topMargin = doodleTopMargin(YES, kTopInset, IPadTraitCollection()); // Test. EXPECT_EQ(120, height); @@ -108,13 +63,11 @@ } TEST_F(ContentSuggestionsCollectionUtilsTest, doodleFrameIPhonePortrait) { - // Setup. - SetAsIPhonePortrait(); - // Action. - CGFloat heightLogo = doodleHeight(YES); - CGFloat heightNoLogo = doodleHeight(NO); - CGFloat topMargin = doodleTopMargin(YES, kTopInset); + CGFloat heightLogo = doodleHeight(YES, IPhonePortraitTraitCollection()); + CGFloat heightNoLogo = doodleHeight(NO, IPhonePortraitTraitCollection()); + CGFloat topMargin = + doodleTopMargin(YES, kTopInset, IPhonePortraitTraitCollection()); // Test. EXPECT_EQ(120, heightLogo); @@ -123,13 +76,11 @@ } TEST_F(ContentSuggestionsCollectionUtilsTest, doodleFrameIPhoneLandscape) { - // Setup. - SetAsIPhoneLandscape(); - // Action. - CGFloat heightLogo = doodleHeight(YES); - CGFloat heightNoLogo = doodleHeight(NO); - CGFloat topMargin = doodleTopMargin(YES, kTopInset); + CGFloat heightLogo = doodleHeight(YES, IPhoneLandscapeTraitCollection()); + CGFloat heightNoLogo = doodleHeight(NO, IPhoneLandscapeTraitCollection()); + CGFloat topMargin = + doodleTopMargin(YES, kTopInset, IPhoneLandscapeTraitCollection()); // Test. EXPECT_EQ(120, heightLogo); @@ -139,13 +90,13 @@ TEST_F(ContentSuggestionsCollectionUtilsTest, searchFieldFrameIPad) { // Setup. - SetAsIPad(); CGFloat width = 500; CGFloat largeIPadWidth = 1366; // Action. - CGFloat resultWidth = searchFieldWidth(width); - CGFloat resultWidthLargeIPad = searchFieldWidth(largeIPadWidth); + CGFloat resultWidth = searchFieldWidth(width, IPadTraitCollection()); + CGFloat resultWidthLargeIPad = + searchFieldWidth(largeIPadWidth, IPadTraitCollection()); CGFloat topMargin = searchFieldTopMargin(); // Test. @@ -156,11 +107,11 @@ TEST_F(ContentSuggestionsCollectionUtilsTest, searchFieldFrameIPhonePortrait) { // Setup. - SetAsIPhonePortrait(); CGFloat width = 500; // Action. - CGFloat resultWidth = searchFieldWidth(width); + CGFloat resultWidth = + searchFieldWidth(width, IPhonePortraitTraitCollection()); CGFloat topMargin = searchFieldTopMargin(); // Test. @@ -170,11 +121,11 @@ TEST_F(ContentSuggestionsCollectionUtilsTest, searchFieldFrameIPhoneLandscape) { // Setup. - SetAsIPhoneLandscape(); CGFloat width = 500; // Action. - CGFloat resultWidth = searchFieldWidth(width); + CGFloat resultWidth = + searchFieldWidth(width, IPhoneLandscapeTraitCollection()); CGFloat topMargin = searchFieldTopMargin(); // Test. @@ -183,25 +134,23 @@ } TEST_F(ContentSuggestionsCollectionUtilsTest, heightForLogoHeaderIPad) { - // Setup. - SetAsIPad(); - // Action, tests. - EXPECT_EQ(382, heightForLogoHeader(YES, YES, YES, 0)); - EXPECT_EQ(406, heightForLogoHeader(YES, NO, YES, 0)); - EXPECT_EQ(382, heightForLogoHeader(YES, YES, NO, 0)); - EXPECT_EQ(406, heightForLogoHeader(YES, NO, NO, 0)); + EXPECT_EQ(382, heightForLogoHeader(YES, YES, YES, 0, IPadTraitCollection())); + EXPECT_EQ(406, heightForLogoHeader(YES, NO, YES, 0, IPadTraitCollection())); + EXPECT_EQ(382, heightForLogoHeader(YES, YES, NO, 0, IPadTraitCollection())); + EXPECT_EQ(406, heightForLogoHeader(YES, NO, NO, 0, IPadTraitCollection())); } TEST_F(ContentSuggestionsCollectionUtilsTest, heightForLogoHeaderIPhone) { - // Setup. - SetAsIPhonePortrait(); - // Action, tests. - EXPECT_EQ(278, heightForLogoHeader(YES, YES, YES, 0)); - EXPECT_EQ(278, heightForLogoHeader(YES, NO, YES, 0)); - EXPECT_EQ(278, heightForLogoHeader(YES, YES, NO, 0)); - EXPECT_EQ(278, heightForLogoHeader(YES, NO, NO, 0)); + EXPECT_EQ(278, heightForLogoHeader(YES, YES, YES, 0, + IPhonePortraitTraitCollection())); + EXPECT_EQ(278, heightForLogoHeader(YES, NO, YES, 0, + IPhonePortraitTraitCollection())); + EXPECT_EQ(278, heightForLogoHeader(YES, YES, NO, 0, + IPhonePortraitTraitCollection())); + EXPECT_EQ(278, heightForLogoHeader(YES, NO, NO, 0, + IPhonePortraitTraitCollection())); } TEST_F(ContentSuggestionsCollectionUtilsTest, NearestAncestor) {
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view.mm index 05fba0f..e328821 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view.mm
@@ -313,7 +313,7 @@ return; CGFloat searchFieldNormalWidth = - content_suggestions::searchFieldWidth(contentWidth); + content_suggestions::searchFieldWidth(contentWidth, self.traitCollection); CGFloat percent = [self searchFieldProgressForOffset:offset safeAreaInsets:safeAreaInsets];
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller.mm index 5511a4c..bdada462 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller.mm
@@ -133,7 +133,7 @@ void (^transition)(id<UIViewControllerTransitionCoordinatorContext>) = ^(id<UIViewControllerTransitionCoordinatorContext> context) { // Ensure omnibox is reset when not a regular tablet. - if (IsSplitToolbarMode()) { + if (IsSplitToolbarMode(newCollection)) { [self.toolbarDelegate setScrollProgressForTabletOmnibox:1]; } // Fake Tap button only needs to work in portrait. Disable the button @@ -161,7 +161,7 @@ safeAreaInsets:safeAreaInsets] // RxR with no logo hides the fakebox, so always show the omnibox. : 1; - if (!IsSplitToolbarMode()) { + if (!IsSplitToolbarMode(self)) { [self.toolbarDelegate setScrollProgressForTabletOmnibox:progress]; } else { // Ensure omnibox is reset when not a regular tablet. @@ -182,7 +182,7 @@ - (void)updateFakeOmniboxForWidth:(CGFloat)width { self.fakeOmniboxWidthConstraint.constant = - content_suggestions::searchFieldWidth(width); + content_suggestions::searchFieldWidth(width, self.traitCollection); } - (void)unfocusOmnibox { @@ -200,13 +200,15 @@ // Update the doodle top margin to the new -doodleTopMargin value. - (void)updateConstraints { self.doodleTopMarginConstraint.constant = - content_suggestions::doodleTopMargin(YES, [self topInset]); + content_suggestions::doodleTopMargin(YES, [self topInset], + self.traitCollection); [self.headerView updateForTopSafeAreaInset:[self topInset]]; } - (CGFloat)pinnedOffsetY { CGFloat headerHeight = content_suggestions::heightForLogoHeader( - self.logoIsShowing, self.promoCanShow, YES, [self topInset]); + self.logoIsShowing, self.promoCanShow, YES, [self topInset], + self.traitCollection); CGFloat offsetY = headerHeight - ntp_header::kScrolledToTopOmniboxBottomMargin; @@ -231,7 +233,8 @@ - (CGFloat)headerHeight { return content_suggestions::heightForLogoHeader( - self.logoIsShowing, self.promoCanShow, YES, [self topInset]); + self.logoIsShowing, self.promoCanShow, YES, [self topInset], + self.traitCollection); } #pragma mark - ContentSuggestionsHeaderProvider @@ -271,7 +274,8 @@ 0, width - safeAreaInsets.left - safeAreaInsets.right); self.fakeOmniboxWidthConstraint = [self.fakeOmnibox.widthAnchor - constraintEqualToConstant:content_suggestions::searchFieldWidth(width)]; + constraintEqualToConstant:content_suggestions::searchFieldWidth( + width, self.traitCollection)]; [self addConstraintsForLogoView:self.logoVendor.view fakeOmnibox:self.fakeOmnibox andHeaderView:self.headerView]; @@ -461,7 +465,8 @@ // shows fakebox if the logo is visible and hides otherwise - (void)updateFakeboxDisplay { [self.doodleHeightConstraint - setConstant:content_suggestions::doodleHeight(self.logoIsShowing)]; + setConstant:content_suggestions::doodleHeight(self.logoIsShowing, + self.traitCollection)]; self.fakeOmnibox.hidden = IsRegularXRegularSizeClass(self) && !self.logoIsShowing; [self.collectionSynchronizer invalidateLayout]; @@ -493,10 +498,10 @@ self.doodleTopMarginConstraint = [logoView.topAnchor constraintEqualToAnchor:headerView.topAnchor constant:content_suggestions::doodleTopMargin( - YES, [self topInset])]; + YES, [self topInset], self.traitCollection)]; self.doodleHeightConstraint = [logoView.heightAnchor constraintEqualToConstant:content_suggestions::doodleHeight( - self.logoIsShowing)]; + self.logoIsShowing, self.traitCollection)]; self.fakeOmniboxHeightConstraint = [fakeOmnibox.heightAnchor constraintEqualToConstant:ToolbarExpandedHeight( self.traitCollection
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm index 4808b73..a63b2cc 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm
@@ -591,8 +591,8 @@ parentInset.right = margin; } else if (self.styler.cellStyle == MDCCollectionViewCellStyleCard) { CGFloat collectionWidth = collectionView.bounds.size.width; - CGFloat maxCardWidth = - content_suggestions::searchFieldWidth(collectionWidth); + CGFloat maxCardWidth = content_suggestions::searchFieldWidth( + collectionWidth, self.traitCollection); CGFloat margin = MAX(0, (collectionView.frame.size.width - maxCardWidth) / 2); parentInset.left = margin;
diff --git a/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm b/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm index 8fb54e7f..d28f50f6 100644 --- a/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm +++ b/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm
@@ -237,13 +237,15 @@ EARL_GREY_TEST_DISABLED(@"Disabled for iPad due to device rotation bug."); } [ChromeEarlGreyUI waitForAppToIdle]; - UIEdgeInsets safeArea = - [ContentSuggestionsAppInterface collectionView].safeAreaInsets; - CGFloat collectionWidth = CGRectGetWidth(UIEdgeInsetsInsetRect( - [ContentSuggestionsAppInterface collectionView].bounds, safeArea)); + UICollectionView* collectionView = + [ContentSuggestionsAppInterface collectionView]; + UIEdgeInsets safeArea = collectionView.safeAreaInsets; + CGFloat collectionWidth = + CGRectGetWidth(UIEdgeInsetsInsetRect(collectionView.bounds, safeArea)); GREYAssertTrue(collectionWidth > 0, @"The collection width is nil."); CGFloat fakeOmniboxWidth = [ContentSuggestionsAppInterface - searchFieldWidthForCollectionWidth:collectionWidth]; + searchFieldWidthForCollectionWidth:collectionWidth + traitCollection:collectionView.traitCollection]; [[EarlGrey selectElementWithMatcher:chrome_test_util::FakeOmnibox()] assertWithMatcher:OmniboxWidth(fakeOmniboxWidth)]; @@ -257,13 +259,15 @@ [ChromeEarlGreyUI waitForAppToIdle]; - safeArea = [ContentSuggestionsAppInterface collectionView].safeAreaInsets; - CGFloat collectionWidthAfterRotation = CGRectGetWidth(UIEdgeInsetsInsetRect( - [ContentSuggestionsAppInterface collectionView].bounds, safeArea)); + collectionView = [ContentSuggestionsAppInterface collectionView]; + safeArea = collectionView.safeAreaInsets; + CGFloat collectionWidthAfterRotation = + CGRectGetWidth(UIEdgeInsetsInsetRect(collectionView.bounds, safeArea)); GREYAssertNotEqual(collectionWidth, collectionWidthAfterRotation, @"The collection width has not changed."); fakeOmniboxWidth = [ContentSuggestionsAppInterface - searchFieldWidthForCollectionWidth:collectionWidthAfterRotation]; + searchFieldWidthForCollectionWidth:collectionWidthAfterRotation + traitCollection:collectionView.traitCollection]; [[EarlGrey selectElementWithMatcher:chrome_test_util::FakeOmnibox()] assertWithMatcher:OmniboxWidth(fakeOmniboxWidth)]; @@ -278,13 +282,15 @@ EARL_GREY_TEST_DISABLED(@"Disabled for iPad due to device rotation bug."); } [ChromeEarlGreyUI waitForAppToIdle]; - UIEdgeInsets safeArea = - [ContentSuggestionsAppInterface collectionView].safeAreaInsets; - CGFloat collectionWidth = CGRectGetWidth(UIEdgeInsetsInsetRect( - [ContentSuggestionsAppInterface collectionView].bounds, safeArea)); + UICollectionView* collectionView = + [ContentSuggestionsAppInterface collectionView]; + UIEdgeInsets safeArea = collectionView.safeAreaInsets; + CGFloat collectionWidth = + CGRectGetWidth(UIEdgeInsetsInsetRect(collectionView.bounds, safeArea)); GREYAssertTrue(collectionWidth > 0, @"The collection width is nil."); CGFloat fakeOmniboxWidth = [ContentSuggestionsAppInterface - searchFieldWidthForCollectionWidth:collectionWidth]; + searchFieldWidthForCollectionWidth:collectionWidth + traitCollection:collectionView.traitCollection]; [[EarlGrey selectElementWithMatcher:chrome_test_util::FakeOmnibox()] assertWithMatcher:OmniboxWidth(fakeOmniboxWidth)]; @@ -303,13 +309,15 @@ [[EarlGrey selectElementWithMatcher:chrome_test_util::SettingsDoneButton()] performAction:grey_tap()]; - safeArea = [ContentSuggestionsAppInterface collectionView].safeAreaInsets; - CGFloat collectionWidthAfterRotation = CGRectGetWidth(UIEdgeInsetsInsetRect( - [ContentSuggestionsAppInterface collectionView].bounds, safeArea)); + collectionView = [ContentSuggestionsAppInterface collectionView]; + safeArea = collectionView.safeAreaInsets; + CGFloat collectionWidthAfterRotation = + CGRectGetWidth(UIEdgeInsetsInsetRect(collectionView.bounds, safeArea)); GREYAssertNotEqual(collectionWidth, collectionWidthAfterRotation, @"The collection width has not changed."); fakeOmniboxWidth = [ContentSuggestionsAppInterface - searchFieldWidthForCollectionWidth:collectionWidthAfterRotation]; + searchFieldWidthForCollectionWidth:collectionWidthAfterRotation + traitCollection:collectionView.traitCollection]; [[EarlGrey selectElementWithMatcher:chrome_test_util::FakeOmnibox()] assertWithMatcher:OmniboxWidth(fakeOmniboxWidth)];
diff --git a/ios/chrome/browser/ui/util/uikit_ui_util.h b/ios/chrome/browser/ui/util/uikit_ui_util.h index c7b000d..1be6b7c 100644 --- a/ios/chrome/browser/ui/util/uikit_ui_util.h +++ b/ios/chrome/browser/ui/util/uikit_ui_util.h
@@ -202,6 +202,9 @@ // Whether the |environment| has a compact horizontal size class. bool IsCompactWidth(id<UITraitEnvironment> environment); +// Whether the |traitCollection| has a compact horizontal size class. +bool IsCompactWidth(UITraitCollection* traitCollection); + // Whether the main application window's rootViewController has a compact // horizontal size class. bool IsCompactWidth(); @@ -220,6 +223,9 @@ // Whether the |environment| has a compact vertical size class. bool IsCompactHeight(id<UITraitEnvironment> environment); +// Whether the |traitCollection| has a compact vertical size class. +bool IsCompactHeight(UITraitCollection* traitCollection); + // Whether toolbar should be shown in compact mode. bool ShouldShowCompactToolbar(); // Whether toolbar should be shown in compact mode in |traitCollection|. @@ -243,6 +249,10 @@ // toolbar or if it is displayed as only one toolbar. bool IsSplitToolbarMode(id<UITraitEnvironment> environment); +// Returns whether the |traitCollection|'s toolbar is split between top and +// bottom toolbar or if it is displayed as only one toolbar. +bool IsSplitToolbarMode(UITraitCollection* traitCollection); + // Returns the current first responder for keyWindow. UIResponder* GetFirstResponder();
diff --git a/ios/chrome/browser/ui/util/uikit_ui_util.mm b/ios/chrome/browser/ui/util/uikit_ui_util.mm index dd375ae2..57215a4b 100644 --- a/ios/chrome/browser/ui/util/uikit_ui_util.mm +++ b/ios/chrome/browser/ui/util/uikit_ui_util.mm
@@ -572,8 +572,11 @@ } bool IsCompactWidth(id<UITraitEnvironment> environment) { - return environment.traitCollection.horizontalSizeClass == - UIUserInterfaceSizeClassCompact; + return IsCompactWidth(environment.traitCollection); +} + +bool IsCompactWidth(UITraitCollection* traitCollection) { + return traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassCompact; } bool IsCompactWidth() { @@ -594,8 +597,11 @@ } bool IsCompactHeight(id<UITraitEnvironment> environment) { - return environment.traitCollection.verticalSizeClass == - UIUserInterfaceSizeClassCompact; + return IsCompactHeight(environment.traitCollection); +} + +bool IsCompactHeight(UITraitCollection* traitCollection) { + return traitCollection.verticalSizeClass == UIUserInterfaceSizeClassCompact; } bool IsRegularXRegularSizeClass() { @@ -621,11 +627,16 @@ } bool IsSplitToolbarMode() { - return IsCompactWidth() && !IsCompactHeight(); + return IsSplitToolbarMode( + [UIApplication sharedApplication].keyWindow.traitCollection); } bool IsSplitToolbarMode(id<UITraitEnvironment> environment) { - return IsCompactWidth(environment) && !IsCompactHeight(environment); + return IsSplitToolbarMode(environment.traitCollection); +} + +bool IsSplitToolbarMode(UITraitCollection* traitCollection) { + return IsCompactWidth(traitCollection) && !IsCompactHeight(traitCollection); } UIView* GetFirstResponderSubview(UIView* view) {
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc index 86deb48e..b3cc57d07 100644 --- a/media/base/media_switches.cc +++ b/media/base/media_switches.cc
@@ -664,6 +664,11 @@ const base::Feature MEDIA_EXPORT kAVFoundationCaptureV2{ "AVFoundationCaptureV2", base::FEATURE_DISABLED_BY_DEFAULT}; +// Controls whether or not the V2 capturer exports IOSurfaces for zero-copy. +// This feature only has any effect if kAVFoundationCaptureV2 is also enabled. +const base::Feature MEDIA_EXPORT kAVFoundationCaptureV2ZeroCopy{ + "AVFoundationCaptureV2ZeroCopy", base::FEATURE_ENABLED_BY_DEFAULT}; + const base::Feature MEDIA_EXPORT kVideoToolboxVp9Decoding{ "VideoToolboxVp9Decoding", base::FEATURE_DISABLED_BY_DEFAULT}; #endif // defined(OS_MAC)
diff --git a/media/base/media_switches.h b/media/base/media_switches.h index 63c36c1..06cf7223 100644 --- a/media/base/media_switches.h +++ b/media/base/media_switches.h
@@ -226,6 +226,7 @@ #if defined(OS_MAC) MEDIA_EXPORT extern const base::Feature kAVFoundationCaptureV2; +MEDIA_EXPORT extern const base::Feature kAVFoundationCaptureV2ZeroCopy; MEDIA_EXPORT extern const base::Feature kVideoToolboxVp9Decoding; #endif
diff --git a/media/capture/video/mac/video_capture_device_avfoundation_mac.mm b/media/capture/video/mac/video_capture_device_avfoundation_mac.mm index 526b3658..5ebc7073 100644 --- a/media/capture/video/mac/video_capture_device_avfoundation_mac.mm +++ b/media/capture/video/mac/video_capture_device_avfoundation_mac.mm
@@ -17,6 +17,7 @@ #include "base/sequenced_task_runner.h" #include "base/strings/string_util.h" #include "base/strings/sys_string_conversions.h" +#include "media/base/media_switches.h" #include "media/base/timestamp_constants.h" #include "media/base/video_types.h" #import "media/capture/video/mac/video_capture_device_avfoundation_utils_mac.h" @@ -654,9 +655,8 @@ DCHECK_EQ(pixelBufferPixelFormat, sampleBufferPixelFormat); // First preference is to use an NV12 IOSurface as a GpuMemoryBuffer. - // TODO(https://crbug.com/1125879): This path cannot be used in software - // mode yet, and so it cannot be enabled yet. - constexpr bool kEnableGpuMemoryBuffers = false; + static const bool kEnableGpuMemoryBuffers = + base::FeatureList::IsEnabled(media::kAVFoundationCaptureV2ZeroCopy); if (kEnableGpuMemoryBuffers) { IOSurfaceRef ioSurface = CVPixelBufferGetIOSurface(pixelBuffer); if (ioSurface && videoPixelFormat == media::PIXEL_FORMAT_NV12) {
diff --git a/media/capture/video/mac/video_capture_device_avfoundation_mac_unittest.mm b/media/capture/video/mac/video_capture_device_avfoundation_mac_unittest.mm index 63e3cf8..f6e0e1a1 100644 --- a/media/capture/video/mac/video_capture_device_avfoundation_mac_unittest.mm +++ b/media/capture/video/mac/video_capture_device_avfoundation_mac_unittest.mm
@@ -19,7 +19,7 @@ namespace media { -TEST(VideoCaptureDeviceAVFoundationMacTest, TakePhoto) { +TEST(VideoCaptureDeviceAVFoundationMacTest, DISABLED_TakePhoto) { RunTestCase(base::BindOnce([] { NSString* deviceId = GetFirstDeviceId(); if (!deviceId) { @@ -46,7 +46,8 @@ })); } -TEST(VideoCaptureDeviceAVFoundationMacTest, StopCaptureWhileTakingPhoto) { +TEST(VideoCaptureDeviceAVFoundationMacTest, + DISABLED_StopCaptureWhileTakingPhoto) { RunTestCase(base::BindOnce([] { NSString* deviceId = GetFirstDeviceId(); if (!deviceId) { @@ -77,7 +78,8 @@ })); } -TEST(VideoCaptureDeviceAVFoundationMacTest, MultiplePendingTakePhotos) { +TEST(VideoCaptureDeviceAVFoundationMacTest, + DISABLED_MultiplePendingTakePhotos) { RunTestCase(base::BindOnce([] { NSString* deviceId = GetFirstDeviceId(); if (!deviceId) { @@ -113,7 +115,7 @@ } TEST(VideoCaptureDeviceAVFoundationMacTest, - StopCaptureWhileMultiplePendingTakePhotos) { + DISABLED_StopCaptureWhileMultiplePendingTakePhotos) { RunTestCase(base::BindOnce([] { NSString* deviceId = GetFirstDeviceId(); if (!deviceId) { @@ -153,7 +155,7 @@ } TEST(VideoCaptureDeviceAVFoundationMacTest, - StopStillImageOutputWhenNoLongerTakingPhotos) { + DISABLED_StopStillImageOutputWhenNoLongerTakingPhotos) { RunTestCase(base::BindOnce([] { NSString* deviceId = GetFirstDeviceId(); if (!deviceId) { @@ -190,7 +192,7 @@ // This test ensures we don't crash even if we leave operations pending. TEST(VideoCaptureDeviceAVFoundationMacTest, - TakePhotoAndShutDownWithoutWaiting) { + DISABLED_TakePhotoAndShutDownWithoutWaiting) { RunTestCase(base::BindOnce([] { NSString* deviceId = GetFirstDeviceId(); if (!deviceId) {
diff --git a/media/capture/video/mac/video_capture_device_factory_mac.mm b/media/capture/video/mac/video_capture_device_factory_mac.mm index 9f5b3a98..da4edcb6 100644 --- a/media/capture/video/mac/video_capture_device_factory_mac.mm +++ b/media/capture/video/mac/video_capture_device_factory_mac.mm
@@ -120,10 +120,11 @@ : VideoCaptureTransportType::OTHER_TRANSPORT; const std::string model_id = VideoCaptureDeviceMac::GetDeviceModelId( device_id, capture_api, device_transport_type); + bool pan_tilt_zoom_supported = + VideoCaptureDeviceMac::IsPanTiltZoomSupported(model_id); VideoCaptureDeviceDescriptor descriptor( [[[capture_devices valueForKey:key] deviceName] UTF8String], device_id, - model_id, capture_api, - /*pan_tilt_zoom_supported=*/false, device_transport_type); + model_id, capture_api, pan_tilt_zoom_supported, device_transport_type); if (IsDeviceBlocked(descriptor)) continue; devices_info.emplace_back(descriptor);
diff --git a/media/capture/video/mac/video_capture_device_factory_mac_unittest.mm b/media/capture/video/mac/video_capture_device_factory_mac_unittest.mm index be079c39..4b6f6ac 100644 --- a/media/capture/video/mac/video_capture_device_factory_mac_unittest.mm +++ b/media/capture/video/mac/video_capture_device_factory_mac_unittest.mm
@@ -47,21 +47,6 @@ })); } -TEST_P(VideoCaptureDeviceFactoryMacTest, ListDevicesWithNoPanTiltZoomSupport) { - RunTestCase(base::BindOnce([]() { - VideoCaptureDeviceFactoryMac video_capture_device_factory; - - std::vector<VideoCaptureDeviceInfo> devices_info = - GetDevicesInfo(&video_capture_device_factory); - if (devices_info.empty()) { - DVLOG(1) << "No camera available. Exiting test."; - return; - } - for (const auto& device : devices_info) - EXPECT_FALSE(device.descriptor.pan_tilt_zoom_supported()); - })); -} - INSTANTIATE_TEST_SUITE_P(, VideoCaptureDeviceFactoryMacTest, ::testing::Values(AVFoundationCaptureV2::kEnabled,
diff --git a/media/capture/video/mac/video_capture_device_mac.h b/media/capture/video/mac/video_capture_device_mac.h index d23a545..e1af2ca6 100644 --- a/media/capture/video/mac/video_capture_device_mac.h +++ b/media/capture/video/mac/video_capture_device_mac.h
@@ -103,6 +103,8 @@ VideoCaptureApi capture_api, VideoCaptureTransportType transport_type); + static bool IsPanTiltZoomSupported(const std::string& device_model); + private: void SetErrorState(VideoCaptureError error, const base::Location& from_here,
diff --git a/media/capture/video/mac/video_capture_device_mac.mm b/media/capture/video/mac/video_capture_device_mac.mm index 56f56b2..be33fc1 100644 --- a/media/capture/video/mac/video_capture_device_mac.mm +++ b/media/capture/video/mac/video_capture_device_mac.mm
@@ -32,6 +32,9 @@ #include "media/capture/video/mac/video_capture_device_avfoundation_utils_mac.h" #include "ui/gfx/geometry/size.h" +using ScopedIOUSBInterfaceInterface = + base::mac::ScopedIOPluginInterface<IOUSBInterfaceInterface220>; + @implementation DeviceNameAndTransportType - (id)initWithName:(NSString*)deviceName transportType:(int32_t)transportType { @@ -64,27 +67,59 @@ // The following constants are extracted from the specification "Universal // Serial Bus Device Class Definition for Video Devices", Rev. 1.1 June 1, 2005. // http://www.usb.org/developers/devclass_docs/USB_Video_Class_1_1.zip -// CS_INTERFACE: Sec. A.4 "Video Class-Specific Descriptor Types". -const int kVcCsInterface = 0x24; -// VC_PROCESSING_UNIT: Sec. A.5 "Video Class-Specific VC Interface Descriptor -// Subtypes". -const int kVcProcessingUnit = 0x5; -// SET_CUR: Sec. A.8 "Video Class-Specific Request Codes". -const int kVcRequestCodeSetCur = 0x1; -// PU_POWER_LINE_FREQUENCY_CONTROL: Sec. A.9.5 "Processing Unit Control -// Selectors". -const int kPuPowerLineFrequencyControl = 0x5; -// Sec. 4.2.2.3.5 Power Line Frequency Control. +// Sec. A.4 "Video Class-Specific Descriptor Types". +const int kVcCsInterface = 0x24; // CS_INTERFACE +// Sec. A.5 "Video Class-Specific VC Interface Descriptor Subtypes". +const int kVcInputTerminal = 0x2; // VC_INPUT_TERMINAL +const int kVcProcessingUnit = 0x5; // VC_PROCESSING_UNIT +// Sec. A.8 "Video Class-Specific Request Codes". +const int kVcRequestCodeSetCur = 0x1; // SET_CUR +const int kVcRequestCodeGetCur = 0x81; // GET_CUR +const int kVcRequestCodeGetMin = 0x82; // GET_MIN +const int kVcRequestCodeGetMax = 0x83; // GET_MAX +const int kVcRequestCodeGetRes = 0x84; // GET_RES +// Sec. A.9.4. "Camera Terminal Control Selectors". +const int kCtZoomAbsoluteControl = 0x0b; // CT_ZOOM_ABSOLUTE_CONTROL +const int kCtPanTiltAbsoluteControl = 0x0d; // CT_PANTILT_ABSOLUTE_CONTROL +// Sec. A.9.5 "Processing Unit Control Selectors". +const int kPuPowerLineFrequencyControl = + 0x5; // PU_POWER_LINE_FREQUENCY_CONTROL +// Sec. 4.2.2.3.5 "Power Line Frequency Control". const int k50Hz = 1; const int k60Hz = 2; const int kPuPowerLineFrequencyControlCommandSize = 1; +// Sec. 4.2.2.1.11 "Zoom (Absolute) Control". +const int kCtZoomAbsoluteControlCommandSize = 2; +// Sec. 4.2.2.1.13 "PanTilt (Absolute) Control". +const int kCtPanTiltAbsoluteControlCommandSize = 8; // Addition to the IOUSB family of structures, with subtype and unit ID. -typedef struct IOUSBInterfaceDescriptor { +// Sec. 3.7.2 "Class-Specific VC Interface Descriptor" +typedef struct VcCsInterfaceDescriptor { IOUSBDescriptorHeader header; UInt8 bDescriptorSubType; UInt8 bUnitID; -} IOUSBInterfaceDescriptor; +} VcCsInterfaceDescriptor; + +static bool FindDeviceWithVendorAndProductIds(int vendor_id, + int product_id, + io_iterator_t* usb_iterator) { + // Compose a search dictionary with vendor and product ID. + base::ScopedCFTypeRef<CFMutableDictionaryRef> query_dictionary( + IOServiceMatching(kIOUSBDeviceClassName)); + CFDictionarySetValue(query_dictionary, CFSTR(kUSBVendorName), + base::mac::NSToCFCast(@(vendor_id))); + CFDictionarySetValue(query_dictionary, CFSTR(kUSBProductName), + base::mac::NSToCFCast(@(product_id))); + + kern_return_t kr = IOServiceGetMatchingServices( + kIOMasterPortDefault, query_dictionary.release(), usb_iterator); + if (kr != kIOReturnSuccess) { + DLOG(ERROR) << "No devices found with specified Vendor and Product ID."; + return false; + } + return true; +} // Tries to create a user-side device interface for a given USB device. Returns // true if interface was found and passes it back in |device_interface|. The @@ -169,33 +204,29 @@ const PowerLineFrequency frequency) { // Create, the control interface for the found plugin, and release // the intermediate plugin. - IOUSBInterfaceInterface** control_interface = NULL; + ScopedIOUSBInterfaceInterface control_interface; HRESULT res = (*plugin_interface) - ->QueryInterface(plugin_interface, - CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), - reinterpret_cast<LPVOID*>(&control_interface)); + ->QueryInterface( + plugin_interface, CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), + reinterpret_cast<LPVOID*>(control_interface.InitializeInto())); if (!SUCCEEDED(res) || !control_interface) { DLOG(ERROR) << "Couldn’t create control interface"; return; } - base::mac::ScopedIOPluginInterface<IOUSBInterfaceInterface> - control_interface_ref(control_interface); // Find the device's unit ID presenting type 0x24 (kVcCsInterface) and // subtype 0x5 (kVcProcessingUnit). Inside this unit is where we find the // power line frequency removal setting, and this id is device dependent. int real_unit_id = -1; IOUSBDescriptorHeader* descriptor = NULL; - IOUSBInterfaceDescriptor* cs_descriptor = NULL; - IOUSBInterfaceInterface220** interface = - reinterpret_cast<IOUSBInterfaceInterface220**>(control_interface); - while ((descriptor = (*interface) - ->FindNextAssociatedDescriptor(interface, descriptor, - kUSBAnyDesc))) { - cs_descriptor = reinterpret_cast<IOUSBInterfaceDescriptor*>(descriptor); - if ((descriptor->bDescriptorType == kVcCsInterface) && - (cs_descriptor->bDescriptorSubType == kVcProcessingUnit)) { + while ((descriptor = + (*control_interface) + ->FindNextAssociatedDescriptor(control_interface.get(), + descriptor, kVcCsInterface))) { + auto* cs_descriptor = + reinterpret_cast<VcCsInterfaceDescriptor*>(descriptor); + if (cs_descriptor->bDescriptorSubType == kVcProcessingUnit) { real_unit_id = cs_descriptor->bUnitID; break; } @@ -254,22 +285,11 @@ DVLOG(1) << "Setting Power Line Frequency to " << static_cast<int>(frequency) << " Hz, device " << std::hex << vendor_id << "-" << product_id; - // Compose a search dictionary with vendor and product ID. - base::ScopedCFTypeRef<CFMutableDictionaryRef> query_dictionary( - IOServiceMatching(kIOUSBDeviceClassName)); - CFDictionarySetValue(query_dictionary, CFSTR(kUSBVendorName), - base::mac::NSToCFCast(@(vendor_id))); - CFDictionarySetValue(query_dictionary, CFSTR(kUSBProductName), - base::mac::NSToCFCast(@(product_id))); - - io_iterator_t usb_iterator; - kern_return_t kr = IOServiceGetMatchingServices( - kIOMasterPortDefault, query_dictionary.release(), &usb_iterator); - if (kr != kIOReturnSuccess) { - DLOG(ERROR) << "No devices found with specified Vendor and Product ID."; + base::mac::ScopedIOObject<io_iterator_t> usb_iterator; + if (!FindDeviceWithVendorAndProductIds(vendor_id, product_id, + usb_iterator.InitializeInto())) { return; } - base::mac::ScopedIOObject<io_iterator_t> usb_iterator_ref(usb_iterator); while (io_service_t usb_device = IOIteratorNext(usb_iterator)) { base::mac::ScopedIOObject<io_service_t> usb_device_ref(usb_device); @@ -294,6 +314,287 @@ } } +// Create an empty IOUSBDevRequest for a USB device to either control or get +// information from pan, tilt, and zoom controls. +static IOUSBDevRequest CreateEmptyPanTiltZoomRequest( + IOUSBInterfaceInterface220** control_interface, + int unit_id, + int request_code, + int endpoint_direction, + int control_selector, + int control_command_size) { + DCHECK((endpoint_direction == kUSBIn) || (endpoint_direction == kUSBOut)); + UInt8 interface_number; + (*control_interface) + ->GetInterfaceNumber(control_interface, &interface_number); + IOUSBDevRequest command; + command.bmRequestType = + USBmakebmRequestType(endpoint_direction, kUSBClass, kUSBInterface); + command.bRequest = request_code; + command.wIndex = (unit_id << 8) | interface_number; + command.wValue = (control_selector << 8); + command.wLength = control_command_size; + command.wLenDone = 0; + return command; +} + +// Send USB request to get information about pan and tilt controls. +// Returns true if the request is successful. To send the request, the interface +// must be opened already. +static bool SendPanTiltControlRequest( + IOUSBInterfaceInterface220** control_interface, + int unit_id, + int request_code, + int* pan_result, + int* tilt_result) { + IOUSBDevRequest command = CreateEmptyPanTiltZoomRequest( + control_interface, unit_id, request_code, kUSBIn, + kCtPanTiltAbsoluteControl, kCtPanTiltAbsoluteControlCommandSize); + int32_t data[2]; + command.pData = &data; + + IOReturn ret = + (*control_interface)->ControlRequest(control_interface, 0, &command); + DLOG_IF(ERROR, ret != kIOReturnSuccess) + << "Control pan tilt request" + << " failed (0x" << std::hex << ret << "), unit id: " << unit_id; + if (ret != kIOReturnSuccess) + return false; + + *pan_result = USBToHostLong(data[0]); + *tilt_result = USBToHostLong(data[1]); + return true; +} + +// Send USB request to get information about zoom control. +// Returns true if the request is successful. To send the request, the interface +// must be opened already. +static bool SendZoomControlRequest( + IOUSBInterfaceInterface220** control_interface, + int unit_id, + int request_code, + int* result) { + IOUSBDevRequest command = CreateEmptyPanTiltZoomRequest( + control_interface, unit_id, request_code, kUSBIn, kCtZoomAbsoluteControl, + kCtZoomAbsoluteControlCommandSize); + uint16_t data; + command.pData = &data; + + IOReturn ret = + (*control_interface)->ControlRequest(control_interface, 0, &command); + DLOG_IF(ERROR, ret != kIOReturnSuccess) + << "Control zoom request" + << " failed (0x" << std::hex << ret << "), unit id: " << unit_id; + if (ret != kIOReturnSuccess) + return false; + + *result = USBToHostLong(data); + return true; +} + +// Retrieves the control range and current value of pan and tilt controls. +// The interface must be opened already. +static void GetPanTiltControlRangeAndCurrent( + IOUSBInterfaceInterface220** control_interface, + int unit_id, + mojom::Range* pan_range, + mojom::Range* tilt_range) { + int pan_max, pan_min, pan_step, pan_current; + int tilt_max, tilt_min, tilt_step, tilt_current; + if (!SendPanTiltControlRequest(control_interface, unit_id, + kVcRequestCodeGetMax, &pan_max, &tilt_max) || + !SendPanTiltControlRequest(control_interface, unit_id, + kVcRequestCodeGetMin, &pan_min, &tilt_min) || + !SendPanTiltControlRequest(control_interface, unit_id, + kVcRequestCodeGetRes, &pan_step, &tilt_step) || + !SendPanTiltControlRequest(control_interface, unit_id, + kVcRequestCodeGetCur, &pan_current, + &tilt_current)) { + return; + } + pan_range->max = pan_max; + pan_range->min = pan_min; + pan_range->step = pan_step; + pan_range->current = pan_current; + tilt_range->max = tilt_max; + tilt_range->min = tilt_min; + tilt_range->step = tilt_step; + tilt_range->current = tilt_current; +} + +// Retrieves the control range and current value of a zoom control. The +// interface must be opened already. +static void GetZoomControlRangeAndCurrent( + IOUSBInterfaceInterface220** control_interface, + int unit_id, + mojom::Range* zoom_range) { + int max, min, step, current; + if (!SendZoomControlRequest(control_interface, unit_id, kVcRequestCodeGetMax, + &max) || + !SendZoomControlRequest(control_interface, unit_id, kVcRequestCodeGetMin, + &min) || + !SendZoomControlRequest(control_interface, unit_id, kVcRequestCodeGetRes, + &step) || + !SendZoomControlRequest(control_interface, unit_id, kVcRequestCodeGetCur, + ¤t)) { + return; + } + zoom_range->max = max; + zoom_range->min = min; + zoom_range->step = step; + zoom_range->current = current; +} + +// Set pan and tilt values for a USB camera device. The interface must be opened +// already. +static void SetPanTiltInUsbDevice( + IOUSBInterfaceInterface220** control_interface, + int unit_id, + base::Optional<int> pan, + base::Optional<int> tilt) { + if (!pan.has_value() && !tilt.has_value()) + return; + + int pan_current, tilt_current; + if ((!pan.has_value() || !tilt.has_value()) && + !SendPanTiltControlRequest(control_interface, unit_id, + kVcRequestCodeGetCur, &pan_current, + &tilt_current)) { + return; + } + + uint32_t pan_tilt_data[2]; + pan_tilt_data[0] = + CFSwapInt32HostToLittle((uint32_t)pan.value_or(pan_current)); + pan_tilt_data[1] = + CFSwapInt32HostToLittle((uint32_t)tilt.value_or(tilt_current)); + + IOUSBDevRequest command = CreateEmptyPanTiltZoomRequest( + control_interface, unit_id, kVcRequestCodeSetCur, kUSBOut, + kCtPanTiltAbsoluteControl, kCtPanTiltAbsoluteControlCommandSize); + command.pData = pan_tilt_data; + + IOReturn ret = + (*control_interface)->ControlRequest(control_interface, 0, &command); + DLOG_IF(ERROR, ret != kIOReturnSuccess) + << "Control request" + << " failed (0x" << std::hex << ret << "), unit id: " << unit_id + << " pan value: " << pan.value_or(pan_current) + << " tilt value: " << tilt.value_or(tilt_current); + DVLOG_IF(1, ret == kIOReturnSuccess) + << "Setting pan value to " << pan.value_or(pan_current) + << " and tilt value to " << tilt.value_or(tilt_current); +} + +// Set zoom value for a USB camera device. The interface must be opened already. +static void SetZoomInUsbDevice(IOUSBInterfaceInterface220** control_interface, + int unit_id, + int zoom) { + IOUSBDevRequest command = CreateEmptyPanTiltZoomRequest( + control_interface, unit_id, kVcRequestCodeSetCur, kUSBOut, + kCtZoomAbsoluteControl, kCtZoomAbsoluteControlCommandSize); + command.pData = &zoom; + + IOReturn ret = + (*control_interface)->ControlRequest(control_interface, 0, &command); + DLOG_IF(ERROR, ret != kIOReturnSuccess) + << "Control request" + << " failed (0x" << std::hex << ret << "), unit id: " << unit_id + << " zoom value: " << zoom; + DVLOG_IF(1, ret == kIOReturnSuccess) << "Setting zoom value to " << zoom; +} + +// Open the pan, tilt, zoom interface in a USB webcam identified by +// |device_model|. Returns interface when it is succcessfully opened. You have +// to close the interface manually when you're done. +static ScopedIOUSBInterfaceInterface OpenPanTiltZoomControlInterface( + std::string device_model, + int* unit_id) { + if (device_model.length() <= 2 * kVidPidSize) { + return ScopedIOUSBInterfaceInterface(); + } + std::string vendor_id = device_model.substr(0, kVidPidSize); + std::string product_id = device_model.substr(kVidPidSize + 1); + int vendor_id_as_int, product_id_as_int; + if (!base::HexStringToInt(vendor_id, &vendor_id_as_int) || + !base::HexStringToInt(product_id, &product_id_as_int)) { + return ScopedIOUSBInterfaceInterface(); + } + + base::mac::ScopedIOObject<io_iterator_t> usb_iterator; + if (!FindDeviceWithVendorAndProductIds(vendor_id_as_int, product_id_as_int, + usb_iterator.InitializeInto())) { + return ScopedIOUSBInterfaceInterface(); + } + + base::mac::ScopedIOPluginInterface<IOCFPlugInInterface> + video_control_interface; + + while (io_service_t usb_device = IOIteratorNext(usb_iterator)) { + base::mac::ScopedIOObject<io_service_t> usb_device_ref(usb_device); + base::mac::ScopedIOPluginInterface<IOUSBDeviceInterface> device_interface; + + if (!FindDeviceInterfaceInUsbDevice(vendor_id_as_int, product_id_as_int, + usb_device, + device_interface.InitializeInto())) { + continue; + } + + if (FindVideoControlInterfaceInDeviceInterface( + device_interface, video_control_interface.InitializeInto())) { + break; + } + } + + if (video_control_interface == nullptr) { + return ScopedIOUSBInterfaceInterface(); + } + + // Create the control interface for the found plugin, and release + // the intermediate plugin. + ScopedIOUSBInterfaceInterface control_interface; + HRESULT res = + (*video_control_interface) + ->QueryInterface( + video_control_interface, + CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID220), + reinterpret_cast<LPVOID*>(control_interface.InitializeInto())); + if (!SUCCEEDED(res) || !control_interface) { + DLOG(ERROR) << "Couldn’t get control interface"; + return ScopedIOUSBInterfaceInterface(); + } + + // Find the device's unit ID presenting type 0x24 (kVcCsInterface) and + // subtype 0x2 (kVcInputTerminal). Inside this unit is where we find the + // settings for pan, tilt, and zoom, and this id is device dependent. + IOUSBDescriptorHeader* descriptor = nullptr; + while ((descriptor = + (*control_interface) + ->FindNextAssociatedDescriptor(control_interface.get(), + descriptor, kVcCsInterface))) { + auto* cs_descriptor = + reinterpret_cast<VcCsInterfaceDescriptor*>(descriptor); + if (cs_descriptor->bDescriptorSubType == kVcInputTerminal) { + *unit_id = cs_descriptor->bUnitID; + break; + } + } + + DVLOG_IF(1, *unit_id == -1) + << "This USB device doesn't seem to have a " + << " VC_INPUT_TERMINAL. Pan, tilt, zoom are not available."; + if (*unit_id == -1) + return ScopedIOUSBInterfaceInterface(); + + if ((*control_interface)->USBInterfaceOpen(control_interface) != + kIOReturnSuccess) { + DLOG(ERROR) << "Unable to open control interface"; + return ScopedIOUSBInterfaceInterface(); + } + + return control_interface; +} + VideoCaptureDeviceMac::VideoCaptureDeviceMac( const VideoCaptureDeviceDescriptor& device_descriptor) : device_descriptor_(device_descriptor), @@ -350,11 +651,11 @@ device_descriptor_.transport_type); if (device_model.length() > 2 * kVidPidSize) { std::string vendor_id = device_model.substr(0, kVidPidSize); - std::string model_id = device_model.substr(kVidPidSize + 1); - int vendor_id_as_int, model_id_as_int; - if (base::HexStringToInt(base::StringPiece(vendor_id), &vendor_id_as_int) && - base::HexStringToInt(base::StringPiece(model_id), &model_id_as_int)) { - SetAntiFlickerInUsbDevice(vendor_id_as_int, model_id_as_int, + std::string product_id = device_model.substr(kVidPidSize + 1); + int vendor_id_as_int, product_id_as_int; + if (base::HexStringToInt(vendor_id, &vendor_id_as_int) && + base::HexStringToInt(product_id, &product_id_as_int)) { + SetAntiFlickerInUsbDevice(vendor_id_as_int, product_id_as_int, GetPowerLineFrequency(params)); } } @@ -405,6 +706,21 @@ capture_format_.frame_size.width(), capture_format_.frame_size.width(), capture_format_.frame_size.width(), 0 /* step */); + const std::string device_model = GetDeviceModelId( + device_descriptor_.device_id, device_descriptor_.capture_api, + device_descriptor_.transport_type); + int unit_id = -1; + ScopedIOUSBInterfaceInterface control_interface( + OpenPanTiltZoomControlInterface(device_model, &unit_id)); + if (control_interface) { + GetPanTiltControlRangeAndCurrent(control_interface, unit_id, + photo_state->pan.get(), + photo_state->tilt.get()); + GetZoomControlRangeAndCurrent(control_interface, unit_id, + photo_state->zoom.get()); + (*control_interface)->USBInterfaceClose(control_interface); + } + std::move(callback).Run(std::move(photo_state)); } @@ -420,6 +736,31 @@ settings->has_fill_light_mode || settings->has_red_eye_reduction) { return; } + + if (settings->has_pan || settings->has_tilt || settings->has_zoom) { + const std::string device_model = GetDeviceModelId( + device_descriptor_.device_id, device_descriptor_.capture_api, + device_descriptor_.transport_type); + int unit_id = -1; + ScopedIOUSBInterfaceInterface control_interface( + OpenPanTiltZoomControlInterface(device_model, &unit_id)); + if (!control_interface) + return; + + if (settings->has_pan || settings->has_tilt) { + SetPanTiltInUsbDevice( + control_interface, unit_id, + settings->has_pan ? base::make_optional(settings->pan) + : base::nullopt, + settings->has_tilt ? base::make_optional(settings->tilt) + : base::nullopt); + } + if (settings->has_zoom) { + SetZoomInUsbDevice(control_interface, unit_id, settings->zoom); + } + (*control_interface)->USBInterfaceClose(control_interface); + } + std::move(callback).Run(true); } @@ -539,6 +880,41 @@ return id_vendor + ":" + id_product; } +// Check if the video capture device supports at least one of pan, tilt and zoom +// controls. +// static +bool VideoCaptureDeviceMac::IsPanTiltZoomSupported( + const std::string& device_model) { + int unit_id = -1; + ScopedIOUSBInterfaceInterface control_interface( + OpenPanTiltZoomControlInterface(device_model, &unit_id)); + if (!control_interface) + return false; + + bool result = false; + int zoom_max, zoom_min = 0; + if (SendZoomControlRequest(control_interface, unit_id, kVcRequestCodeGetMax, + &zoom_max) && + SendZoomControlRequest(control_interface, unit_id, kVcRequestCodeGetMin, + &zoom_min) && + zoom_min < zoom_max) { + result = true; + } + int pan_max, pan_min = 0; + int tilt_max, tilt_min = 0; + if (!result && + SendPanTiltControlRequest(control_interface, unit_id, + kVcRequestCodeGetMax, &pan_max, &tilt_max) && + SendPanTiltControlRequest(control_interface, unit_id, + kVcRequestCodeGetMin, &pan_min, &tilt_min) && + ((pan_min < pan_max || tilt_min < tilt_max))) { + result = true; + } + + (*control_interface)->USBInterfaceClose(control_interface); + return result; +} + void VideoCaptureDeviceMac::SetErrorState(VideoCaptureError error, const base::Location& from_here, const std::string& reason) {
diff --git a/media/fuchsia/audio/fuchsia_audio_renderer.cc b/media/fuchsia/audio/fuchsia_audio_renderer.cc index 62a1ef1..3049d4b 100644 --- a/media/fuchsia/audio/fuchsia_audio_renderer.cc +++ b/media/fuchsia/audio/fuchsia_audio_renderer.cc
@@ -485,6 +485,12 @@ is_demuxer_read_pending_ = false; + if (drop_next_demuxer_read_result_) { + drop_next_demuxer_read_result_ = false; + ScheduleReadDemuxerStream(); + return; + } + if (read_status != DemuxerStream::kOk) { if (read_status == DemuxerStream::kError) { OnError(PIPELINE_ERROR_READ); @@ -586,6 +592,10 @@ SetBufferState(BUFFERING_HAVE_NOTHING); last_packet_timestamp_ = base::TimeDelta::Min(); read_timer_.Stop(); + + if (is_demuxer_read_pending_) { + drop_next_demuxer_read_result_ = true; + } } void FuchsiaAudioRenderer::OnEndOfStream() {
diff --git a/media/fuchsia/audio/fuchsia_audio_renderer.h b/media/fuchsia/audio/fuchsia_audio_renderer.h index 95ead1af..1a873caa 100644 --- a/media/fuchsia/audio/fuchsia_audio_renderer.h +++ b/media/fuchsia/audio/fuchsia_audio_renderer.h
@@ -131,6 +131,7 @@ DemuxerStream* demuxer_stream_ = nullptr; bool is_demuxer_read_pending_ = false; + bool drop_next_demuxer_read_result_ = false; RendererClient* client_ = nullptr;
diff --git a/media/gpu/vaapi/vaapi_utils.cc b/media/gpu/vaapi/vaapi_utils.cc index 72e7ab68..450f0c8 100644 --- a/media/gpu/vaapi/vaapi_utils.cc +++ b/media/gpu/vaapi/vaapi_utils.cc
@@ -190,20 +190,20 @@ va_rt_format_ != kInvalidVaRtFormat; } -bool FillVP8DataStructures(VaapiWrapper* vaapi_wrapper, - VASurfaceID va_surface_id, - const Vp8FrameHeader& frame_header, - const Vp8ReferenceFrameVector& reference_frames) { - DCHECK_NE(va_surface_id, VA_INVALID_SURFACE); - DCHECK(vaapi_wrapper); - +void FillVP8DataStructures(const Vp8FrameHeader& frame_header, + const Vp8ReferenceFrameVector& reference_frames, + VAIQMatrixBufferVP8* iq_matrix_buf, + VAProbabilityDataBufferVP8* prob_buf, + VAPictureParameterBufferVP8* pic_param, + VASliceParameterBufferVP8* slice_param) { const Vp8SegmentationHeader& sgmnt_hdr = frame_header.segmentation_hdr; const Vp8QuantizationHeader& quant_hdr = frame_header.quantization_hdr; - VAIQMatrixBufferVP8 iq_matrix_buf{}; - static_assert(base::size(iq_matrix_buf.quantization_index) == kMaxMBSegments, + static_assert(base::size(decltype(iq_matrix_buf->quantization_index){}) == + kMaxMBSegments, "incorrect quantization matrix segment size"); - static_assert(base::size(iq_matrix_buf.quantization_index[0]) == 6, - "incorrect quantization matrix Q index size"); + static_assert( + base::size(decltype(iq_matrix_buf->quantization_index){}[0]) == 6, + "incorrect quantization matrix Q index size"); for (size_t i = 0; i < kMaxMBSegments; ++i) { int q = quant_hdr.y_ac_qi; @@ -217,52 +217,54 @@ } #define CLAMP_Q(q) base::ClampToRange(q, 0, 127) - iq_matrix_buf.quantization_index[i][0] = CLAMP_Q(q); - iq_matrix_buf.quantization_index[i][1] = CLAMP_Q(q + quant_hdr.y_dc_delta); - iq_matrix_buf.quantization_index[i][2] = CLAMP_Q(q + quant_hdr.y2_dc_delta); - iq_matrix_buf.quantization_index[i][3] = CLAMP_Q(q + quant_hdr.y2_ac_delta); - iq_matrix_buf.quantization_index[i][4] = CLAMP_Q(q + quant_hdr.uv_dc_delta); - iq_matrix_buf.quantization_index[i][5] = CLAMP_Q(q + quant_hdr.uv_ac_delta); + iq_matrix_buf->quantization_index[i][0] = CLAMP_Q(q); + iq_matrix_buf->quantization_index[i][1] = CLAMP_Q(q + quant_hdr.y_dc_delta); + iq_matrix_buf->quantization_index[i][2] = + CLAMP_Q(q + quant_hdr.y2_dc_delta); + iq_matrix_buf->quantization_index[i][3] = + CLAMP_Q(q + quant_hdr.y2_ac_delta); + iq_matrix_buf->quantization_index[i][4] = + CLAMP_Q(q + quant_hdr.uv_dc_delta); + iq_matrix_buf->quantization_index[i][5] = + CLAMP_Q(q + quant_hdr.uv_ac_delta); #undef CLAMP_Q } const Vp8EntropyHeader& entr_hdr = frame_header.entropy_hdr; - VAProbabilityDataBufferVP8 prob_buf{}; - CheckedMemcpy(prob_buf.dct_coeff_probs, entr_hdr.coeff_probs); + CheckedMemcpy(prob_buf->dct_coeff_probs, entr_hdr.coeff_probs); - VAPictureParameterBufferVP8 pic_param{}; - pic_param.frame_width = frame_header.width; - pic_param.frame_height = frame_header.height; + pic_param->frame_width = frame_header.width; + pic_param->frame_height = frame_header.height; const auto last_frame = reference_frames.GetFrame(Vp8RefType::VP8_FRAME_LAST); if (last_frame) { - pic_param.last_ref_frame = + pic_param->last_ref_frame = last_frame->AsVaapiVP8Picture()->GetVASurfaceID(); } else { - pic_param.last_ref_frame = VA_INVALID_SURFACE; + pic_param->last_ref_frame = VA_INVALID_SURFACE; } const auto golden_frame = reference_frames.GetFrame(Vp8RefType::VP8_FRAME_GOLDEN); if (golden_frame) { - pic_param.golden_ref_frame = + pic_param->golden_ref_frame = golden_frame->AsVaapiVP8Picture()->GetVASurfaceID(); } else { - pic_param.golden_ref_frame = VA_INVALID_SURFACE; + pic_param->golden_ref_frame = VA_INVALID_SURFACE; } const auto alt_frame = reference_frames.GetFrame(Vp8RefType::VP8_FRAME_ALTREF); if (alt_frame) - pic_param.alt_ref_frame = alt_frame->AsVaapiVP8Picture()->GetVASurfaceID(); + pic_param->alt_ref_frame = alt_frame->AsVaapiVP8Picture()->GetVASurfaceID(); else - pic_param.alt_ref_frame = VA_INVALID_SURFACE; + pic_param->alt_ref_frame = VA_INVALID_SURFACE; - pic_param.out_of_loop_frame = VA_INVALID_SURFACE; + pic_param->out_of_loop_frame = VA_INVALID_SURFACE; const Vp8LoopFilterHeader& lf_hdr = frame_header.loopfilter_hdr; -#define FHDR_TO_PP_PF(a, b) pic_param.pic_fields.bits.a = (b) +#define FHDR_TO_PP_PF(a, b) pic_param->pic_fields.bits.a = (b) FHDR_TO_PP_PF(key_frame, frame_header.IsKeyframe() ? 0 : 1); FHDR_TO_PP_PF(version, frame_header.version); FHDR_TO_PP_PF(segmentation_enabled, sgmnt_hdr.segmentation_enabled); @@ -280,10 +282,10 @@ FHDR_TO_PP_PF(loop_filter_disable, lf_hdr.level == 0); #undef FHDR_TO_PP_PF - CheckedMemcpy(pic_param.mb_segment_tree_probs, sgmnt_hdr.segment_prob); + CheckedMemcpy(pic_param->mb_segment_tree_probs, sgmnt_hdr.segment_prob); static_assert(std::extent<decltype(sgmnt_hdr.lf_update_value)>() == - std::extent<decltype(pic_param.loop_filter_level)>(), + std::extent<decltype(pic_param->loop_filter_level)>(), "loop filter level arrays mismatch"); for (size_t i = 0; i < base::size(sgmnt_hdr.lf_update_value); ++i) { int lf_level = lf_hdr.level; @@ -296,61 +298,53 @@ } } - pic_param.loop_filter_level[i] = base::ClampToRange(lf_level, 0, 63); + pic_param->loop_filter_level[i] = base::ClampToRange(lf_level, 0, 63); } static_assert( std::extent<decltype(lf_hdr.ref_frame_delta)>() == - std::extent<decltype(pic_param.loop_filter_deltas_ref_frame)>(), + std::extent<decltype(pic_param->loop_filter_deltas_ref_frame)>(), "loop filter deltas arrays size mismatch"); static_assert(std::extent<decltype(lf_hdr.mb_mode_delta)>() == - std::extent<decltype(pic_param.loop_filter_deltas_mode)>(), + std::extent<decltype(pic_param->loop_filter_deltas_mode)>(), "loop filter deltas arrays size mismatch"); static_assert(std::extent<decltype(lf_hdr.ref_frame_delta)>() == std::extent<decltype(lf_hdr.mb_mode_delta)>(), "loop filter deltas arrays size mismatch"); for (size_t i = 0; i < base::size(lf_hdr.ref_frame_delta); ++i) { - pic_param.loop_filter_deltas_ref_frame[i] = lf_hdr.ref_frame_delta[i]; - pic_param.loop_filter_deltas_mode[i] = lf_hdr.mb_mode_delta[i]; + pic_param->loop_filter_deltas_ref_frame[i] = lf_hdr.ref_frame_delta[i]; + pic_param->loop_filter_deltas_mode[i] = lf_hdr.mb_mode_delta[i]; } -#define FHDR_TO_PP(a) pic_param.a = frame_header.a +#define FHDR_TO_PP(a) pic_param->a = frame_header.a FHDR_TO_PP(prob_skip_false); FHDR_TO_PP(prob_intra); FHDR_TO_PP(prob_last); FHDR_TO_PP(prob_gf); #undef FHDR_TO_PP - CheckedMemcpy(pic_param.y_mode_probs, entr_hdr.y_mode_probs); - CheckedMemcpy(pic_param.uv_mode_probs, entr_hdr.uv_mode_probs); - CheckedMemcpy(pic_param.mv_probs, entr_hdr.mv_probs); + CheckedMemcpy(pic_param->y_mode_probs, entr_hdr.y_mode_probs); + CheckedMemcpy(pic_param->uv_mode_probs, entr_hdr.uv_mode_probs); + CheckedMemcpy(pic_param->mv_probs, entr_hdr.mv_probs); - pic_param.bool_coder_ctx.range = frame_header.bool_dec_range; - pic_param.bool_coder_ctx.value = frame_header.bool_dec_value; - pic_param.bool_coder_ctx.count = frame_header.bool_dec_count; + pic_param->bool_coder_ctx.range = frame_header.bool_dec_range; + pic_param->bool_coder_ctx.value = frame_header.bool_dec_value; + pic_param->bool_coder_ctx.count = frame_header.bool_dec_count; - VASliceParameterBufferVP8 slice_param{}; - slice_param.slice_data_size = frame_header.frame_size; - slice_param.slice_data_offset = frame_header.first_part_offset; - slice_param.slice_data_flag = VA_SLICE_DATA_FLAG_ALL; - slice_param.macroblock_offset = frame_header.macroblock_bit_offset; + slice_param->slice_data_size = frame_header.frame_size; + slice_param->slice_data_offset = frame_header.first_part_offset; + slice_param->slice_data_flag = VA_SLICE_DATA_FLAG_ALL; + slice_param->macroblock_offset = frame_header.macroblock_bit_offset; // Number of DCT partitions plus control partition. - slice_param.num_of_partitions = frame_header.num_of_dct_partitions + 1; + slice_param->num_of_partitions = frame_header.num_of_dct_partitions + 1; // Per VAAPI, this size only includes the size of the macroblock data in // the first partition (in bytes), so we have to subtract the header size. - slice_param.partition_size[0] = + slice_param->partition_size[0] = frame_header.first_part_size - ((frame_header.macroblock_bit_offset + 7) / 8); for (size_t i = 0; i < frame_header.num_of_dct_partitions; ++i) - slice_param.partition_size[i + 1] = frame_header.dct_partition_sizes[i]; - - return vaapi_wrapper->SubmitBuffers( - {{VAIQMatrixBufferType, sizeof(iq_matrix_buf), &iq_matrix_buf}, - {VAProbabilityBufferType, sizeof(prob_buf), &prob_buf}, - {VAPictureParameterBufferType, sizeof(pic_param), &pic_param}, - {VASliceParameterBufferType, sizeof(slice_param), &slice_param}, - {VASliceDataBufferType, frame_header.frame_size, frame_header.data}}); + slice_param->partition_size[i + 1] = frame_header.dct_partition_sizes[i]; } } // namespace media
diff --git a/media/gpu/vaapi/vaapi_utils.h b/media/gpu/vaapi/vaapi_utils.h index ac4bb78f..0db323e 100644 --- a/media/gpu/vaapi/vaapi_utils.h +++ b/media/gpu/vaapi/vaapi_utils.h
@@ -174,12 +174,13 @@ ReleaseCB release_cb_; }; -// Adapts |frame_header| to the Vaapi data types, prepping it for consumption by -// |vaapi_wrapper| -bool FillVP8DataStructures(VaapiWrapper* vaapi_wrapper, - VASurfaceID va_surface_id, - const Vp8FrameHeader& frame_header, - const Vp8ReferenceFrameVector& reference_frames); +// Adapts |frame_header| to the Vaapi data types. +void FillVP8DataStructures(const Vp8FrameHeader& frame_header, + const Vp8ReferenceFrameVector& reference_frames, + VAIQMatrixBufferVP8* iq_matrix_buf, + VAProbabilityDataBufferVP8* prob_buf, + VAPictureParameterBufferVP8* pic_param, + VASliceParameterBufferVP8* slice_param); } // namespace media #endif // MEDIA_GPU_VAAPI_VAAPI_UTILS_H_
diff --git a/media/gpu/vaapi/vaapi_video_decode_accelerator.cc b/media/gpu/vaapi/vaapi_video_decode_accelerator.cc index dbbd453d..3772ad5 100644 --- a/media/gpu/vaapi/vaapi_video_decode_accelerator.cc +++ b/media/gpu/vaapi/vaapi_video_decode_accelerator.cc
@@ -1066,7 +1066,8 @@ // Notify |decoder_delegate_| of an imminent VAContextID destruction, so it // can destroy any internal structures making use of it. At this point - // |decoder_thread_| is stopped so we can access these from |task_runner_|. + // |decoder_thread_| is stopped so we can access |decoder_delegate_| from + // |task_runner_|. decoder_delegate_->OnVAContextDestructionSoon(); vaapi_wrapper_->DestroyContext();
diff --git a/media/gpu/vaapi/vaapi_webp_decoder.cc b/media/gpu/vaapi/vaapi_webp_decoder.cc index 866965d..ef395f914 100644 --- a/media/gpu/vaapi/vaapi_webp_decoder.cc +++ b/media/gpu/vaapi/vaapi_webp_decoder.cc
@@ -120,14 +120,24 @@ } DCHECK(scoped_va_context_and_surface_->IsValid()); } + DCHECK_NE(scoped_va_context_and_surface_->id(), VA_INVALID_SURFACE); - if (!FillVP8DataStructures(vaapi_wrapper_.get(), - scoped_va_context_and_surface_->id(), - *parse_result, Vp8ReferenceFrameVector())) { - return VaapiImageDecodeStatus::kSubmitVABuffersFailed; - } + VAIQMatrixBufferVP8 iq_matrix_buf{}; + VAProbabilityDataBufferVP8 prob_buf{}; + VAPictureParameterBufferVP8 pic_param{}; + VASliceParameterBufferVP8 slice_param{}; + FillVP8DataStructures(*parse_result, Vp8ReferenceFrameVector(), + &iq_matrix_buf, &prob_buf, &pic_param, &slice_param); - return VaapiImageDecodeStatus::kSuccess; + const bool success = vaapi_wrapper_->SubmitBuffers( + {{VAIQMatrixBufferType, sizeof(iq_matrix_buf), &iq_matrix_buf}, + {VAProbabilityBufferType, sizeof(prob_buf), &prob_buf}, + {VAPictureParameterBufferType, sizeof(pic_param), &pic_param}, + {VASliceParameterBufferType, sizeof(slice_param), &slice_param}, + {VASliceDataBufferType, parse_result->frame_size, parse_result->data}}); + + return success ? VaapiImageDecodeStatus::kSuccess + : VaapiImageDecodeStatus::kSubmitVABuffersFailed; } } // namespace media
diff --git a/media/gpu/vaapi/vp8_vaapi_video_decoder_delegate.cc b/media/gpu/vaapi/vp8_vaapi_video_decoder_delegate.cc index c68ca3b..e9e2150 100644 --- a/media/gpu/vaapi/vp8_vaapi_video_decoder_delegate.cc +++ b/media/gpu/vaapi/vp8_vaapi_video_decoder_delegate.cc
@@ -18,7 +18,12 @@ scoped_refptr<VaapiWrapper> vaapi_wrapper) : VaapiVideoDecoderDelegate(vaapi_dec, std::move(vaapi_wrapper)) {} -VP8VaapiVideoDecoderDelegate::~VP8VaapiVideoDecoderDelegate() = default; +VP8VaapiVideoDecoderDelegate::~VP8VaapiVideoDecoderDelegate() { + DCHECK(!iq_matrix_); + DCHECK(!prob_buffer_); + DCHECK(!picture_params_); + DCHECK(!slice_params_); +} scoped_refptr<VP8Picture> VP8VaapiVideoDecoderDelegate::CreateVP8Picture() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -35,14 +40,63 @@ TRACE_EVENT0("media,gpu", "VP8VaapiVideoDecoderDelegate::SubmitDecode"); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - auto va_surface_id = pic->AsVaapiVP8Picture()->va_surface()->id(); + const auto va_surface_id = pic->AsVaapiVP8Picture()->va_surface()->id(); + DCHECK_NE(va_surface_id, VA_INVALID_SURFACE); - if (!FillVP8DataStructures(vaapi_wrapper_.get(), va_surface_id, - *pic->frame_hdr, reference_frames)) { - return false; + VAIQMatrixBufferVP8 iq_matrix_buf{}; + VAProbabilityDataBufferVP8 prob_buf{}; + VAPictureParameterBufferVP8 pic_param{}; + VASliceParameterBufferVP8 slice_param{}; + + const Vp8FrameHeader* const header = pic->frame_hdr.get(); + DCHECK(header); + + FillVP8DataStructures(*header, reference_frames, &iq_matrix_buf, &prob_buf, + &pic_param, &slice_param); + + if (!iq_matrix_) { + iq_matrix_ = vaapi_wrapper_->CreateVABuffer(VAIQMatrixBufferType, + sizeof(iq_matrix_buf)); + if (!iq_matrix_) + return false; } + if (!prob_buffer_) { + prob_buffer_ = vaapi_wrapper_->CreateVABuffer(VAProbabilityBufferType, + sizeof(prob_buf)); + if (!prob_buffer_) + return false; + } + if (!picture_params_) { + picture_params_ = vaapi_wrapper_->CreateVABuffer( + VAPictureParameterBufferType, sizeof(pic_param)); + if (!picture_params_) + return false; + } + if (!slice_params_) { + slice_params_ = vaapi_wrapper_->CreateVABuffer(VASliceParameterBufferType, + sizeof(slice_param)); + if (!slice_params_) + return false; + } + // |encoded_data| cannot be reused even when it's of the appropriate size, due + // to strange stutterings in e.g. Gen 9.5. + std::unique_ptr<ScopedVABuffer> encoded_data = + vaapi_wrapper_->CreateVABuffer(VASliceDataBufferType, header->frame_size); + if (!encoded_data) + return false; - return vaapi_wrapper_->ExecuteAndDestroyPendingBuffers(va_surface_id); + return vaapi_wrapper_->MapAndCopyAndExecute( + va_surface_id, + {{iq_matrix_->id(), + {iq_matrix_->type(), iq_matrix_->size(), &iq_matrix_buf}}, + {prob_buffer_->id(), + {prob_buffer_->type(), prob_buffer_->size(), &prob_buf}}, + {picture_params_->id(), + {picture_params_->type(), picture_params_->size(), &pic_param}}, + {slice_params_->id(), + {slice_params_->type(), slice_params_->size(), &slice_param}}, + {encoded_data->id(), + {encoded_data->type(), header->frame_size, header->data}}}); } bool VP8VaapiVideoDecoderDelegate::OutputPicture( @@ -56,4 +110,12 @@ return true; } +void VP8VaapiVideoDecoderDelegate::OnVAContextDestructionSoon() { + // Destroy the member ScopedVABuffers below since they refer to a VAContextID + // that will be destroyed soon. iq_matrix_.reset(); + prob_buffer_.reset(); + picture_params_.reset(); + slice_params_.reset(); +} + } // namespace media
diff --git a/media/gpu/vaapi/vp8_vaapi_video_decoder_delegate.h b/media/gpu/vaapi/vp8_vaapi_video_decoder_delegate.h index 01a3013..9a299d8 100644 --- a/media/gpu/vaapi/vp8_vaapi_video_decoder_delegate.h +++ b/media/gpu/vaapi/vp8_vaapi_video_decoder_delegate.h
@@ -13,6 +13,7 @@ namespace media { +class ScopedVABuffer; class VP8Picture; class VP8VaapiVideoDecoderDelegate : public VP8Decoder::VP8Accelerator, @@ -29,6 +30,15 @@ const Vp8ReferenceFrameVector& reference_frames) override; bool OutputPicture(scoped_refptr<VP8Picture> pic) override; + // VaapiVideoDecoderDelegate impl. + void OnVAContextDestructionSoon() override; + + private: + std::unique_ptr<ScopedVABuffer> iq_matrix_; + std::unique_ptr<ScopedVABuffer> prob_buffer_; + std::unique_ptr<ScopedVABuffer> picture_params_; + std::unique_ptr<ScopedVABuffer> slice_params_; + DISALLOW_COPY_AND_ASSIGN(VP8VaapiVideoDecoderDelegate); };
diff --git a/mojo/public/tools/bindings/README.md b/mojo/public/tools/bindings/README.md index 1a3d5c5..228a2d3 100644 --- a/mojo/public/tools/bindings/README.md +++ b/mojo/public/tools/bindings/README.md
@@ -555,13 +555,14 @@ }; ``` -and you would like to add a birthday field. You can do: +and you would like to add birthday and nickname fields. You can do: ``` cpp struct Employee { uint64 employee_id; string name; [MinVersion=1] Date? birthday; + [MinVersion=1] string? nickname; }; ``` @@ -570,10 +571,14 @@ with the `MinVersion` attribute set to a number greater than any previous existing versions. +The value of `MinVersion` is unrelated to ordinals. The choice of a particular +version number is arbitrary. All its usage means is that a field isn't present +before the numbered version. + *** note **NOTE:** do not change existing fields in versioned structs, as this is not backwards-compatible. Instead, rename the old field to make its -deprecation clear and add a new field with the new version number. +deprecation clear and add a new field with a new `MinVersion` number. *** **Ordinal value** refers to the relative positional layout of a struct's fields @@ -602,6 +607,7 @@ uint64 employee_id@0; [MinVersion=1] Date? birthday@2; string name@1; + [MinVersion=1] string? nickname@3; }; ```
diff --git a/mojo/public/tools/mojom/check_stable_mojom_compatibility.py b/mojo/public/tools/mojom/check_stable_mojom_compatibility.py index 7e74611..08bd672f 100755 --- a/mojo/public/tools/mojom/check_stable_mojom_compatibility.py +++ b/mojo/public/tools/mojom/check_stable_mojom_compatibility.py
@@ -131,7 +131,8 @@ 'renamed, please add a [RenamedFrom] attribute to the new type. This ' 'can be deleted by a subsequent change.' % qualified_name) - if not new_types[new_name].IsBackwardCompatible(kind): + checker = module.BackwardCompatibilityChecker() + if not checker.IsBackwardCompatible(new_types[new_name], kind): raise Exception('Stable type %s appears to have changed in a way which ' 'breaks backward-compatibility. Please fix!\n\nIf you ' 'believe this assessment to be incorrect, please file a '
diff --git a/mojo/public/tools/mojom/mojom/generate/module.py b/mojo/public/tools/mojom/mojom/generate/module.py index a8083bd..ebbc9b3 100644 --- a/mojo/public/tools/mojom/mojom/generate/module.py +++ b/mojo/public/tools/mojom/mojom/generate/module.py
@@ -14,6 +14,27 @@ import pickle + +class BackwardCompatibilityChecker(object): + """Used for memoization while recursively checking two type definitions for + backward-compatibility.""" + + def __init__(self): + self._cache = {} + + def IsBackwardCompatible(self, new_kind, old_kind): + key = (new_kind, old_kind) + result = self._cache.get(key) + if result is None: + # Assume they're compatible at first to effectively ignore recursive + # checks between these types, e.g. if both kinds are a struct or union + # that references itself in a field. + self._cache[key] = True + result = new_kind.IsBackwardCompatible(old_kind, self) + self._cache[key] = result + return result + + # We use our own version of __repr__ when displaying the AST, as the # AST currently doesn't capture which nodes are reference (e.g. to # types) and which nodes are definitions. This allows us to e.g. print @@ -114,7 +135,8 @@ # during a subsequent run of the parser. return hash((self.spec, self.parent_kind)) - def IsBackwardCompatible(self, rhs): + # pylint: disable=unused-argument + def IsBackwardCompatible(self, rhs, checker): return self == rhs @@ -198,8 +220,8 @@ def __hash__(self): return hash((super(ReferenceKind, self).__hash__(), self.is_nullable)) - def IsBackwardCompatible(self, rhs): - return (super(ReferenceKind, self).IsBackwardCompatible(rhs) + def IsBackwardCompatible(self, rhs, checker): + return (super(ReferenceKind, self).IsBackwardCompatible(rhs, checker) and self.is_nullable == rhs.is_nullable) @@ -383,11 +405,11 @@ pass -def _IsFieldBackwardCompatible(new_field, old_field): +def _IsFieldBackwardCompatible(new_field, old_field, checker): if (new_field.min_version or 0) != (old_field.min_version or 0): return False - return new_field.kind.IsBackwardCompatible(old_field.kind) + return checker.IsBackwardCompatible(new_field.kind, old_field.kind) class Struct(ReferenceKind): @@ -462,7 +484,7 @@ for constant in self.constants: constant.Stylize(stylizer) - def IsBackwardCompatible(self, older_struct): + def IsBackwardCompatible(self, older_struct, checker): """This struct is backward-compatible with older_struct if and only if all of the following conditions hold: - Any newly added field is tagged with a [MinVersion] attribute specifying @@ -501,7 +523,7 @@ old_field = old_fields[ordinal] if (old_field.min_version or 0) > max_old_min_version: max_old_min_version = old_field.min_version - if not _IsFieldBackwardCompatible(new_field, old_field): + if not _IsFieldBackwardCompatible(new_field, old_field, checker): # Type or min-version mismatch between old and new versions of the same # ordinal field. return False @@ -595,7 +617,7 @@ for field in self.fields: field.Stylize(stylizer) - def IsBackwardCompatible(self, older_union): + def IsBackwardCompatible(self, older_union, checker): """This union is backward-compatible with older_union if and only if all of the following conditions hold: - Any newly added field is tagged with a [MinVersion] attribute specifying @@ -628,7 +650,7 @@ if not new_field: # A field was removed, which is not OK. return False - if not _IsFieldBackwardCompatible(new_field, old_field): + if not _IsFieldBackwardCompatible(new_field, old_field, checker): # An field changed its type or MinVersion, which is not OK. return False old_min_version = old_field.min_version or 0 @@ -708,9 +730,9 @@ def __hash__(self): return id(self) - def IsBackwardCompatible(self, rhs): + def IsBackwardCompatible(self, rhs, checker): return (isinstance(rhs, Array) and self.length == rhs.length - and self.kind.IsBackwardCompatible(rhs.kind)) + and checker.IsBackwardCompatible(self.kind, rhs.kind)) class Map(ReferenceKind): @@ -756,10 +778,10 @@ def __hash__(self): return id(self) - def IsBackwardCompatible(self, rhs): + def IsBackwardCompatible(self, rhs, checker): return (isinstance(rhs, Map) - and self.key_kind.IsBackwardCompatible(rhs.key_kind) - and self.value_kind.IsBackwardCompatible(rhs.value_kind)) + and checker.IsBackwardCompatible(self.key_kind, rhs.key_kind) + and checker.IsBackwardCompatible(self.value_kind, rhs.value_kind)) class PendingRemote(ReferenceKind): @@ -782,9 +804,9 @@ def __hash__(self): return id(self) - def IsBackwardCompatible(self, rhs): + def IsBackwardCompatible(self, rhs, checker): return (isinstance(rhs, PendingRemote) - and self.kind.IsBackwardCompatible(rhs.kind)) + and checker.IsBackwardCompatible(self.kind, rhs.kind)) class PendingReceiver(ReferenceKind): @@ -807,9 +829,9 @@ def __hash__(self): return id(self) - def IsBackwardCompatible(self, rhs): - return isinstance(rhs, PendingReceiver) and self.kind.IsBackwardCompatible( - rhs.kind) + def IsBackwardCompatible(self, rhs, checker): + return isinstance(rhs, PendingReceiver) and checker.IsBackwardCompatible( + self.kind, rhs.kind) class PendingAssociatedRemote(ReferenceKind): @@ -832,10 +854,10 @@ def __hash__(self): return id(self) - def IsBackwardCompatible(self, rhs): - return isinstance( - rhs, PendingAssociatedRemote) and self.kind.IsBackwardCompatible( - rhs.kind) + def IsBackwardCompatible(self, rhs, checker): + return isinstance(rhs, + PendingAssociatedRemote) and checker.IsBackwardCompatible( + self.kind, rhs.kind) class PendingAssociatedReceiver(ReferenceKind): @@ -858,10 +880,10 @@ def __hash__(self): return id(self) - def IsBackwardCompatible(self, rhs): + def IsBackwardCompatible(self, rhs, checker): return isinstance( - rhs, PendingAssociatedReceiver) and self.kind.IsBackwardCompatible( - rhs.kind) + rhs, PendingAssociatedReceiver) and checker.IsBackwardCompatible( + self.kind, rhs.kind) class InterfaceRequest(ReferenceKind): @@ -883,9 +905,9 @@ def __hash__(self): return id(self) - def IsBackwardCompatible(self, rhs): - return isinstance(rhs, InterfaceRequest) and self.kind.IsBackwardCompatible( - rhs.kind) + def IsBackwardCompatible(self, rhs, checker): + return isinstance(rhs, InterfaceRequest) and checker.IsBackwardCompatible( + self.kind, rhs.kind) class AssociatedInterfaceRequest(ReferenceKind): @@ -909,10 +931,10 @@ def __hash__(self): return id(self) - def IsBackwardCompatible(self, rhs): + def IsBackwardCompatible(self, rhs, checker): return isinstance( - rhs, AssociatedInterfaceRequest) and self.kind.IsBackwardCompatible( - rhs.kind) + rhs, AssociatedInterfaceRequest) and checker.IsBackwardCompatible( + self.kind, rhs.kind) class Parameter(object): @@ -1075,7 +1097,7 @@ for constant in self.constants: constant.Stylize(stylizer) - def IsBackwardCompatible(self, older_interface): + def IsBackwardCompatible(self, older_interface, checker): """This interface is backward-compatible with older_interface if and only if all of the following conditions hold: - All defined methods in older_interface (when identified by ordinal) have @@ -1113,8 +1135,8 @@ # A method was removed, which is not OK. return False - if not new_method.param_struct.IsBackwardCompatible( - old_method.param_struct): + if not checker.IsBackwardCompatible(new_method.param_struct, + old_method.param_struct): # The parameter list is not backward-compatible, which is not OK. return False @@ -1127,8 +1149,8 @@ if new_method.response_param_struct is None: # A reply was removed from a message, which is not OK. return False - if not new_method.response_param_struct.IsBackwardCompatible( - old_method.response_param_struct): + if not checker.IsBackwardCompatible(new_method.response_param_struct, + old_method.response_param_struct): # The new message's reply is not backward-compatible with the old # message's reply, which is not OK. return False @@ -1190,9 +1212,10 @@ def __hash__(self): return id(self) - def IsBackwardCompatible(self, rhs): - return isinstance( - rhs, AssociatedInterface) and self.kind.IsBackwardCompatible(rhs.kind) + def IsBackwardCompatible(self, rhs, checker): + return isinstance(rhs, + AssociatedInterface) and checker.IsBackwardCompatible( + self.kind, rhs.kind) class EnumField(object): @@ -1266,7 +1289,8 @@ prefix = self.module.GetNamespacePrefix() return '%s%s' % (prefix, self.mojom_name) - def IsBackwardCompatible(self, older_enum): + # pylint: disable=unused-argument + def IsBackwardCompatible(self, older_enum, checker): """This enum is backward-compatible with older_enum if and only if one of the following conditions holds: - Neither enum is [Extensible] and both have the exact same set of valid
diff --git a/mojo/public/tools/mojom/version_compatibility_unittest.py b/mojo/public/tools/mojom/version_compatibility_unittest.py index b70cf8f0..65db4dc 100644 --- a/mojo/public/tools/mojom/version_compatibility_unittest.py +++ b/mojo/public/tools/mojom/version_compatibility_unittest.py
@@ -2,6 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +from mojom.generate import module from mojom_parser_test_case import MojomParserTestCase @@ -20,9 +21,11 @@ self.assertEqual(set(old.keys()), set(new.keys()), 'Old and new test mojoms should use the same type names.') + checker = module.BackwardCompatibilityChecker() compatibility_map = {} for name in old.keys(): - compatibility_map[name] = new[name].IsBackwardCompatible(old[name]) + compatibility_map[name] = checker.IsBackwardCompatible( + new[name], old[name]) return compatibility_map def assertBackwardCompatible(self, old_mojom, new_mojom): @@ -261,6 +264,20 @@ struct S { pending_receiver<F> r; }; """) + def testRecursiveTypeChange(self): + """Recursive types do not break the compatibility checker.""" + self.assertBackwardCompatible( + """\ + struct S { + string a; + array<S> others; + };""", """\ + struct S { + string a; + array<S> others; + [MinVersion=1] string? b; + };""") + def testUnionFieldBecomingNonOptional(self): """Changing a field from optional to non-optional breaks backward-compatibility."""
diff --git a/pdf/document_layout.cc b/pdf/document_layout.cc index 0809cc75..9f5b12c 100644 --- a/pdf/document_layout.cc +++ b/pdf/document_layout.cc
@@ -8,8 +8,6 @@ #include "base/check_op.h" #include "base/values.h" -#include "ppapi/cpp/var.h" -#include "ppapi/cpp/var_dictionary.h" #include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size.h" @@ -59,11 +57,11 @@ return dictionary; } -void DocumentLayout::Options::FromVar(const pp::Var& var) { - pp::VarDictionary dictionary(var); +void DocumentLayout::Options::FromValue(const base::Value& value) { + DCHECK(value.is_dict()); int32_t default_page_orientation = - dictionary.Get(kDefaultPageOrientation).AsInt(); + value.FindKey(kDefaultPageOrientation)->GetInt(); DCHECK_GE(default_page_orientation, static_cast<int32_t>(PageOrientation::kOriginal)); DCHECK_LE(default_page_orientation, @@ -71,7 +69,7 @@ default_page_orientation_ = static_cast<PageOrientation>(default_page_orientation); - two_up_view_enabled_ = dictionary.Get(kTwoUpViewEnabled).AsBool(); + two_up_view_enabled_ = value.FindKey(kTwoUpViewEnabled)->GetBool(); } void DocumentLayout::Options::RotatePagesClockwise() {
diff --git a/pdf/document_layout.h b/pdf/document_layout.h index e998c74f..fb028424 100644 --- a/pdf/document_layout.h +++ b/pdf/document_layout.h
@@ -18,10 +18,6 @@ class Value; } -namespace pp { -class Var; -} // namespace pp - namespace chrome_pdf { // Layout of pages within a PDF document. Pages are placed as rectangles @@ -55,8 +51,8 @@ // Serializes layout options to a base::Value. base::Value ToValue() const; - // Deserializes layout options from a pp::Var. - void FromVar(const pp::Var& var); + // Deserializes layout options from a base::Value. + void FromValue(const base::Value& value); PageOrientation default_page_orientation() const { return default_page_orientation_;
diff --git a/pdf/out_of_process_instance.cc b/pdf/out_of_process_instance.cc index e15a66b..f683127 100644 --- a/pdf/out_of_process_instance.cc +++ b/pdf/out_of_process_instance.cc
@@ -1833,7 +1833,7 @@ pp::Var layout_options_var = dict.Get(kJSLayoutOptions); if (!layout_options_var.is_undefined()) { DocumentLayout::Options layout_options; - layout_options.FromVar(layout_options_var); + layout_options.FromValue(ValueFromVar(layout_options_var)); // TODO(crbug.com/1013800): Eliminate need to get document size from here. document_size_ = PPSizeFromSize(engine()->ApplyDocumentLayout(layout_options));
diff --git a/pdf/ppapi_migration/value_conversions.cc b/pdf/ppapi_migration/value_conversions.cc index 1890d89..c0b894ea 100644 --- a/pdf/ppapi_migration/value_conversions.cc +++ b/pdf/ppapi_migration/value_conversions.cc
@@ -6,6 +6,8 @@ #include <algorithm> +#include "base/containers/span.h" +#include "base/notreached.h" #include "base/values.h" #include "ppapi/cpp/var.h" #include "ppapi/cpp/var_array.h" @@ -55,4 +57,57 @@ } } -} // namespace chrome_pdf \ No newline at end of file +base::Value ValueFromVar(const pp::Var& var) { + switch (var.pp_var().type) { + case PP_VARTYPE_UNDEFINED: + return base::Value(); + case PP_VARTYPE_NULL: + return base::Value(); + case PP_VARTYPE_BOOL: + return base::Value(var.AsBool()); + case PP_VARTYPE_INT32: + return base::Value(var.AsInt()); + case PP_VARTYPE_DOUBLE: + return base::Value(var.AsDouble()); + case PP_VARTYPE_STRING: + return base::Value(var.AsString()); + case PP_VARTYPE_OBJECT: + // There is no valid conversion from PP_VARTYPE_OBJECT to a base::Value + // type. This should not be called to convert this type. + NOTREACHED(); + return base::Value(); + case PP_VARTYPE_ARRAY: { + pp::VarArray var_array(var); + base::Value::ListStorage list_storage(var_array.GetLength()); + for (uint32_t i = 0; i < var_array.GetLength(); ++i) { + list_storage[i] = ValueFromVar(var_array.Get(i)); + } + return base::Value(std::move(list_storage)); + } + case PP_VARTYPE_DICTIONARY: { + base::Value val_dictionary(base::Value::Type::DICTIONARY); + pp::VarDictionary var_dict(var); + pp::VarArray dict_keys = var_dict.GetKeys(); + for (uint32_t i = 0; i < dict_keys.GetLength(); ++i) { + pp::Var key = dict_keys.Get(i); + val_dictionary.SetKey(key.AsString(), ValueFromVar(var_dict.Get(key))); + } + return val_dictionary; + } + case PP_VARTYPE_ARRAY_BUFFER: { + pp::VarArrayBuffer var_array_buffer(var); + base::Value value( + base::make_span(static_cast<uint8_t*>(var_array_buffer.Map()), + var_array_buffer.ByteLength())); + var_array_buffer.Unmap(); + return value; + } + case PP_VARTYPE_RESOURCE: + // There is no valid conversion from PP_VARTYPE_RESOURCE to a base::Value + // type. This should not be called to convert this type. + NOTREACHED(); + return base::Value(); + } +} + +} // namespace chrome_pdf
diff --git a/pdf/ppapi_migration/value_conversions.h b/pdf/ppapi_migration/value_conversions.h index 3b93df5..edfea99 100644 --- a/pdf/ppapi_migration/value_conversions.h +++ b/pdf/ppapi_migration/value_conversions.h
@@ -16,7 +16,8 @@ namespace chrome_pdf { pp::Var VarFromValue(const base::Value& value); +base::Value ValueFromVar(const pp::Var& var); } // namespace chrome_pdf -#endif // PDF_PPAPI_MIGRATION_VALUE_CONVERSIONS_H_ \ No newline at end of file +#endif // PDF_PPAPI_MIGRATION_VALUE_CONVERSIONS_H_
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json index 8959d30..4912fd5 100644 --- a/testing/buildbot/chromium.android.json +++ b/testing/buildbot/chromium.android.json
@@ -29652,7 +29652,8 @@ "args": [ "--gs-results-bucket=chromium-result-details", "--recover-devices", - "--avd-config=../../tools/android/avd/proto/generic_android23.textpb" + "--avd-config=../../tools/android/avd/proto/generic_android23.textpb", + "--test-launcher-filter-file=../../testing/buildbot/filters/android.emulator_m.unit_tests.filter" ], "merge": { "args": [
diff --git a/testing/buildbot/chromium.ci.json b/testing/buildbot/chromium.ci.json index 464d7e7..0ef037cd 100644 --- a/testing/buildbot/chromium.ci.json +++ b/testing/buildbot/chromium.ci.json
@@ -185476,7 +185476,8 @@ "args": [ "--gs-results-bucket=chromium-result-details", "--recover-devices", - "--avd-config=../../tools/android/avd/proto/generic_android23.textpb" + "--avd-config=../../tools/android/avd/proto/generic_android23.textpb", + "--test-launcher-filter-file=../../testing/buildbot/filters/android.emulator_m.unit_tests.filter" ], "merge": { "args": [
diff --git a/testing/buildbot/filters/BUILD.gn b/testing/buildbot/filters/BUILD.gn index fb3518ad..1db0905 100644 --- a/testing/buildbot/filters/BUILD.gn +++ b/testing/buildbot/filters/BUILD.gn
@@ -192,6 +192,7 @@ data = [ "//testing/buildbot/filters/android.asan.unit_tests.filter", + "//testing/buildbot/filters/android.emulator_m.unit_tests.filter", "//testing/buildbot/filters/bfcache.unit_tests.filter", "//testing/buildbot/filters/lacros.unit_tests.filter", ]
diff --git a/testing/buildbot/filters/android.emulator_m.unit_tests.filter b/testing/buildbot/filters/android.emulator_m.unit_tests.filter new file mode 100644 index 0000000..f3770296 --- /dev/null +++ b/testing/buildbot/filters/android.emulator_m.unit_tests.filter
@@ -0,0 +1,5 @@ +# crbug.com/1131181 +-MediaRouterAndroidTest.DetachRoute +-MediaRouterAndroidTest.OnRouteClosed +-MediaRouterAndroidTest.OnRouteClosedWithError +-MediaRouterAndroidTest.OnRouteTerminated
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl index 0ff2730..62e6ac5 100644 --- a/testing/buildbot/test_suite_exceptions.pyl +++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -2671,6 +2671,11 @@ 'shards': 8, }, }, + 'android-marshmallow-x86-rel': { + 'args': [ + '--test-launcher-filter-file=../../testing/buildbot/filters/android.emulator_m.unit_tests.filter', + ], + }, 'linux-chromeos-chrome': { 'args': [ '--test-launcher-filter-file=../../testing/buildbot/filters/chromeos.unit_tests.filter',
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 7c981d46..621abd4 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -1504,9 +1504,9 @@ ], "experiments": [ { - "name": "UseMap1_20200903", + "name": "UseMap2_20200922", "params": { - "map": "1" + "map": "2" }, "enable_features": [ "EmojiSuggestAddition" @@ -1734,7 +1734,7 @@ ] } ], - "ContentCapture": [ + "ContentCaptureExperiment": [ { "platforms": [ "android", @@ -1743,14 +1743,9 @@ ], "experiments": [ { - "name": "ContentCaptureUseTextHolder", - "params": { - "task_long_delay_in_milliseconds": "5000", - "task_short_delay_in_milliseconds": "500", - "use_node_id": "false" - }, + "name": "EnableExperiment", "enable_features": [ - "ContentCapture" + "ContentCaptureTriggeringForExperiment" ] } ]
diff --git a/third_party/blink/renderer/bindings/core/v8/dom_wrapper_world_test.cc b/third_party/blink/renderer/bindings/core/v8/dom_wrapper_world_test.cc index b33fe56..147afbb 100644 --- a/third_party/blink/renderer/bindings/core/v8/dom_wrapper_world_test.cc +++ b/third_party/blink/renderer/bindings/core/v8/dom_wrapper_world_test.cc
@@ -4,6 +4,8 @@ #include "third_party/blink/renderer/platform/bindings/dom_wrapper_world.h" +#include <algorithm> + #include "base/single_thread_task_runner.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/platform/platform.h" @@ -19,39 +21,6 @@ namespace blink { namespace { -Vector<scoped_refptr<DOMWrapperWorld>> CreateIsolatedWorlds( - v8::Isolate* isolate) { - Vector<scoped_refptr<DOMWrapperWorld>> worlds; - worlds.push_back(DOMWrapperWorld::EnsureIsolatedWorld( - isolate, DOMWrapperWorld::kMainWorldId + 1)); - worlds.push_back(DOMWrapperWorld::EnsureIsolatedWorld( - isolate, DOMWrapperWorld::kDOMWrapperWorldEmbedderWorldIdLimit - 1)); - EXPECT_TRUE(worlds[0]->IsIsolatedWorld()); - EXPECT_TRUE(worlds[1]->IsIsolatedWorld()); - return worlds; -} - -Vector<scoped_refptr<DOMWrapperWorld>> CreateWorlds(v8::Isolate* isolate) { - Vector<scoped_refptr<DOMWrapperWorld>> worlds; - worlds.push_back( - DOMWrapperWorld::Create(isolate, DOMWrapperWorld::WorldType::kWorker)); - worlds.push_back( - DOMWrapperWorld::Create(isolate, DOMWrapperWorld::WorldType::kWorker)); - worlds.push_back( - DOMWrapperWorld::Create(isolate, DOMWrapperWorld::WorldType::kWorker)); - EXPECT_TRUE(worlds[0]->IsWorkerWorld()); - EXPECT_TRUE(worlds[1]->IsWorkerWorld()); - EXPECT_TRUE(worlds[2]->IsWorkerWorld()); - - // World ids should be unique. - HashSet<int32_t> world_ids; - EXPECT_TRUE(world_ids.insert(worlds[0]->GetWorldId()).is_new_entry); - EXPECT_TRUE(world_ids.insert(worlds[1]->GetWorldId()).is_new_entry); - EXPECT_TRUE(world_ids.insert(worlds[2]->GetWorldId()).is_new_entry); - - return worlds; -} - void WorkerThreadFunc( WorkerBackingThread* thread, scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner) { @@ -59,23 +28,26 @@ WorkerBackingThreadStartupData::CreateDefault()); // Worlds on the main thread should not be visible from the worker thread. - Vector<scoped_refptr<DOMWrapperWorld>> retrieved_worlds; - DOMWrapperWorld::AllWorldsInCurrentThread(retrieved_worlds); - EXPECT_TRUE(retrieved_worlds.IsEmpty()); + Vector<scoped_refptr<DOMWrapperWorld>> initial_worlds; + DOMWrapperWorld::AllWorldsInCurrentThread(initial_worlds); + EXPECT_TRUE(initial_worlds.IsEmpty()); // Create worlds on the worker thread and verify them. - Vector<scoped_refptr<DOMWrapperWorld>> worlds = - CreateWorlds(thread->GetIsolate()); - DOMWrapperWorld::AllWorldsInCurrentThread(retrieved_worlds); - EXPECT_EQ(worlds.size(), retrieved_worlds.size()); - retrieved_worlds.clear(); + v8::Isolate* isolate = thread->GetIsolate(); + auto worker_world1 = + DOMWrapperWorld::Create(isolate, DOMWrapperWorld::WorldType::kWorker); + auto worker_world2 = + DOMWrapperWorld::Create(isolate, DOMWrapperWorld::WorldType::kWorker); + Vector<scoped_refptr<DOMWrapperWorld>> worlds; + DOMWrapperWorld::AllWorldsInCurrentThread(worlds); + EXPECT_EQ(worlds.size(), initial_worlds.size() + 2); + worlds.clear(); // Dispose of remaining worlds. - for (scoped_refptr<DOMWrapperWorld>& world : worlds) { - if (world->IsWorkerWorld()) - world->Dispose(); - } - worlds.clear(); + worker_world1->Dispose(); + worker_world2->Dispose(); + worker_world1.reset(); + worker_world2.reset(); thread->ShutdownOnBackingThread(); PostCrossThreadTask(*main_thread_task_runner, FROM_HERE, @@ -83,33 +55,70 @@ } TEST(DOMWrapperWorldTest, Basic) { - // Create the main world and verify it. + // Initial setup DOMWrapperWorld& main_world = DOMWrapperWorld::MainWorld(); EXPECT_TRUE(main_world.IsMainWorld()); - EXPECT_FALSE(DOMWrapperWorld::NonMainWorldsExistInMainThread()); - Vector<scoped_refptr<DOMWrapperWorld>> retrieved_worlds; - DOMWrapperWorld::AllWorldsInCurrentThread(retrieved_worlds); - EXPECT_EQ(1u, retrieved_worlds.size()); - EXPECT_TRUE(retrieved_worlds[0]->IsMainWorld()); - retrieved_worlds.clear(); - - // Create isolated worlds and verify them. + Vector<scoped_refptr<DOMWrapperWorld>> initial_worlds; + DOMWrapperWorld::AllWorldsInCurrentThread(initial_worlds); + int32_t used_isolated_world_id = DOMWrapperWorld::kMainWorldId; + for (const auto& world : initial_worlds) { + if (world->IsIsolatedWorld()) { + used_isolated_world_id = + std::max(used_isolated_world_id, world->GetWorldId()); + } + } + ASSERT_TRUE(DOMWrapperWorld::IsIsolatedWorldId(used_isolated_world_id + 1)); V8TestingScope scope; - Vector<scoped_refptr<DOMWrapperWorld>> isolated_worlds = - CreateIsolatedWorlds(scope.GetIsolate()); - EXPECT_TRUE(DOMWrapperWorld::NonMainWorldsExistInMainThread()); - DOMWrapperWorld::AllWorldsInCurrentThread(retrieved_worlds); - EXPECT_EQ(isolated_worlds.size() + 1, retrieved_worlds.size()); + v8::Isolate* isolate = scope.GetIsolate(); - // Create other worlds and verify them. - Vector<scoped_refptr<DOMWrapperWorld>> worlds = - CreateWorlds(scope.GetIsolate()); + // Isolated worlds + auto isolated_world1 = + DOMWrapperWorld::EnsureIsolatedWorld(isolate, used_isolated_world_id + 1); + auto isolated_world2 = + DOMWrapperWorld::EnsureIsolatedWorld(isolate, used_isolated_world_id + 2); + EXPECT_TRUE(isolated_world1->IsIsolatedWorld()); + EXPECT_TRUE(isolated_world2->IsIsolatedWorld()); + Vector<scoped_refptr<DOMWrapperWorld>> worlds; EXPECT_TRUE(DOMWrapperWorld::NonMainWorldsExistInMainThread()); - retrieved_worlds.clear(); - DOMWrapperWorld::AllWorldsInCurrentThread(retrieved_worlds); - EXPECT_EQ(isolated_worlds.size() + worlds.size() + 1, - retrieved_worlds.size()); - retrieved_worlds.clear(); + DOMWrapperWorld::AllWorldsInCurrentThread(worlds); + EXPECT_EQ(worlds.size(), initial_worlds.size() + 2); + worlds.clear(); + isolated_world1.reset(); + isolated_world2.reset(); + DOMWrapperWorld::AllWorldsInCurrentThread(worlds); + EXPECT_EQ(worlds.size(), initial_worlds.size()); + worlds.clear(); + + // Worker worlds + auto worker_world1 = + DOMWrapperWorld::Create(isolate, DOMWrapperWorld::WorldType::kWorker); + auto worker_world2 = + DOMWrapperWorld::Create(isolate, DOMWrapperWorld::WorldType::kWorker); + auto worker_world3 = + DOMWrapperWorld::Create(isolate, DOMWrapperWorld::WorldType::kWorker); + EXPECT_TRUE(worker_world1->IsWorkerWorld()); + EXPECT_TRUE(worker_world2->IsWorkerWorld()); + EXPECT_TRUE(worker_world3->IsWorkerWorld()); + HashSet<int32_t> worker_world_ids; + EXPECT_TRUE( + worker_world_ids.insert(worker_world1->GetWorldId()).is_new_entry); + EXPECT_TRUE( + worker_world_ids.insert(worker_world2->GetWorldId()).is_new_entry); + EXPECT_TRUE( + worker_world_ids.insert(worker_world3->GetWorldId()).is_new_entry); + EXPECT_TRUE(DOMWrapperWorld::NonMainWorldsExistInMainThread()); + DOMWrapperWorld::AllWorldsInCurrentThread(worlds); + EXPECT_EQ(worlds.size(), initial_worlds.size() + 3); + worlds.clear(); + worker_world1->Dispose(); + worker_world2->Dispose(); + worker_world3->Dispose(); + worker_world1.reset(); + worker_world2.reset(); + worker_world3.reset(); + DOMWrapperWorld::AllWorldsInCurrentThread(worlds); + EXPECT_EQ(worlds.size(), initial_worlds.size()); + worlds.clear(); // Start a worker thread and create worlds on that. std::unique_ptr<WorkerBackingThread> thread = @@ -125,28 +134,9 @@ test::EnterRunLoop(); // Worlds on the worker thread should not be visible from the main thread. - EXPECT_TRUE(DOMWrapperWorld::NonMainWorldsExistInMainThread()); - DOMWrapperWorld::AllWorldsInCurrentThread(retrieved_worlds); - EXPECT_EQ(isolated_worlds.size() + worlds.size() + 1, - retrieved_worlds.size()); - retrieved_worlds.clear(); - - // Dispose of the isolated worlds. - isolated_worlds.clear(); - EXPECT_TRUE(DOMWrapperWorld::NonMainWorldsExistInMainThread()); - DOMWrapperWorld::AllWorldsInCurrentThread(retrieved_worlds); - EXPECT_EQ(worlds.size() + 1, retrieved_worlds.size()); - retrieved_worlds.clear(); - - // Dispose of the other worlds. - for (scoped_refptr<DOMWrapperWorld>& world : worlds) { - if (world->IsWorkerWorld()) - world->Dispose(); - } + DOMWrapperWorld::AllWorldsInCurrentThread(worlds); + EXPECT_EQ(worlds.size(), initial_worlds.size()); worlds.clear(); - EXPECT_FALSE(DOMWrapperWorld::NonMainWorldsExistInMainThread()); - DOMWrapperWorld::AllWorldsInCurrentThread(retrieved_worlds); - EXPECT_EQ(1u, retrieved_worlds.size()); } } // namespace
diff --git a/third_party/blink/renderer/bindings/generated_in_core.gni b/third_party/blink/renderer/bindings/generated_in_core.gni index 4cd5338..941430e 100644 --- a/third_party/blink/renderer/bindings/generated_in_core.gni +++ b/third_party/blink/renderer/bindings/generated_in_core.gni
@@ -2,6 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +# Generated sources for production + generated_dictionary_sources_in_core = [ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_add_event_listener_options.cc", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_add_event_listener_options.h", @@ -1207,8 +1209,6 @@ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_svg_view_element.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_task_attribution_timing.cc", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_task_attribution_timing.h", - "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_visibility_state_entry.cc", - "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_visibility_state_entry.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_test_report_body.cc", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_test_report_body.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_text.cc", @@ -1275,6 +1275,8 @@ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_video_track.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_video_track_list.cc", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_video_track_list.h", + "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_visibility_state_entry.cc", + "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_visibility_state_entry.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_visual_viewport.cc", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_visual_viewport.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_vtt_cue.cc",
diff --git a/third_party/blink/renderer/bindings/generated_in_modules.gni b/third_party/blink/renderer/bindings/generated_in_modules.gni index 613efdd1..31ffaad6 100644 --- a/third_party/blink/renderer/bindings/generated_in_modules.gni +++ b/third_party/blink/renderer/bindings/generated_in_modules.gni
@@ -4,6 +4,8 @@ import("//third_party/blink/renderer/config.gni") +# Generated sources for production + generated_dictionary_sources_in_modules = [ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_address_errors.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_address_errors.h", @@ -790,10 +792,10 @@ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_client_lifecycle_state_query.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_client_type.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_client_type.h", - "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_color_gamut.cc", - "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_color_gamut.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_codec_state.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_codec_state.h", + "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_color_gamut.cc", + "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_color_gamut.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_connection_type.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_connection_type.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_contact_property.cc", @@ -816,10 +818,10 @@ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_encoded_video_chunk_type.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_end_of_stream_error.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_end_of_stream_error.h", - "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_fill_light_mode.cc", - "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_fill_light_mode.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_file_system_permission_mode.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_file_system_permission_mode.h", + "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_fill_light_mode.cc", + "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_fill_light_mode.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gamepad_haptic_actuator_type.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gamepad_haptic_actuator_type.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gamepad_haptic_effect_type.cc", @@ -1431,6 +1433,8 @@ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_out_of_memory_error.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_pipeline_layout.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_pipeline_layout.h", + "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_query_set.cc", + "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_query_set.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_queue.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_queue.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_gpu_render_bundle.cc",
diff --git a/third_party/blink/renderer/bindings/idl_in_core.gni b/third_party/blink/renderer/bindings/idl_in_core.gni index b15ac38..29c16bc9 100644 --- a/third_party/blink/renderer/bindings/idl_in_core.gni +++ b/third_party/blink/renderer/bindings/idl_in_core.gni
@@ -2,7 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -# Statically-defined (not runtime-generated) IDL files in 'core' component. +# Statically-defined (not runtime-generated) IDL files in 'core' component +# for production. # # CAUTION: static_idl_files_in_core is used only by a new V8 bindings generator, # which is under development. You have to update core/core_idl_files.gni in
diff --git a/third_party/blink/renderer/bindings/idl_in_modules.gni b/third_party/blink/renderer/bindings/idl_in_modules.gni index 0ea2e92..b079d8d 100644 --- a/third_party/blink/renderer/bindings/idl_in_modules.gni +++ b/third_party/blink/renderer/bindings/idl_in_modules.gni
@@ -4,7 +4,8 @@ import("//third_party/blink/renderer/config.gni") -# Statically-defined (not runtime-generated) IDL files in 'modules' component. +# Statically-defined (not runtime-generated) IDL files in 'modules' component +# for production. # # CAUTION: static_idl_files_in_modules is used only by a new V8 bindings # generator, which is under development. You have to update @@ -171,6 +172,8 @@ "//third_party/blink/renderer/modules/device_orientation/device_orientation_event_init.idl", "//third_party/blink/renderer/modules/device_orientation/window_device_motion.idl", "//third_party/blink/renderer/modules/device_orientation/window_device_orientation.idl", + "//third_party/blink/renderer/modules/direct_sockets/navigator_socket.idl", + "//third_party/blink/renderer/modules/direct_sockets/socket_options.idl", "//third_party/blink/renderer/modules/donottrack/navigator_do_not_track.idl", "//third_party/blink/renderer/modules/encoding/text_decode_options.idl", "//third_party/blink/renderer/modules/encoding/text_decoder.idl", @@ -381,8 +384,8 @@ "//third_party/blink/renderer/modules/native_file_system/file_system_writable_file_stream.idl", "//third_party/blink/renderer/modules/native_file_system/native_file_system_directory_iterator.idl", "//third_party/blink/renderer/modules/native_file_system/open_file_picker_options.idl", - "//third_party/blink/renderer/modules/native_file_system/storage_manager_native_file_system.idl", "//third_party/blink/renderer/modules/native_file_system/save_file_picker_options.idl", + "//third_party/blink/renderer/modules/native_file_system/storage_manager_native_file_system.idl", "//third_party/blink/renderer/modules/native_file_system/window_native_file_system.idl", "//third_party/blink/renderer/modules/native_file_system/write_params.idl", "//third_party/blink/renderer/modules/native_io/native_io_file.idl", @@ -418,7 +421,6 @@ "//third_party/blink/renderer/modules/payments/address_init.idl", "//third_party/blink/renderer/modules/payments/android_pay_method_data.idl", "//third_party/blink/renderer/modules/payments/basic_card_request.idl", - "//third_party/blink/renderer/modules/payments/secure_payment_confirmation_request.idl", "//third_party/blink/renderer/modules/payments/can_make_payment_event.idl", "//third_party/blink/renderer/modules/payments/can_make_payment_event_init.idl", "//third_party/blink/renderer/modules/payments/can_make_payment_response.idl", @@ -456,6 +458,7 @@ "//third_party/blink/renderer/modules/payments/payment_response.idl", "//third_party/blink/renderer/modules/payments/payment_shipping_option.idl", "//third_party/blink/renderer/modules/payments/payment_validation_errors.idl", + "//third_party/blink/renderer/modules/payments/secure_payment_confirmation_request.idl", "//third_party/blink/renderer/modules/peerconnection/rtc_answer_options.idl", "//third_party/blink/renderer/modules/peerconnection/rtc_certificate.idl", "//third_party/blink/renderer/modules/peerconnection/rtc_configuration.idl", @@ -579,8 +582,6 @@ "//third_party/blink/renderer/modules/quota/storage_usage_details.idl", "//third_party/blink/renderer/modules/quota/window_quota.idl", "//third_party/blink/renderer/modules/quota/worker_navigator_storage_quota.idl", - "//third_party/blink/renderer/modules/direct_sockets/navigator_socket.idl", - "//third_party/blink/renderer/modules/direct_sockets/socket_options.idl", "//third_party/blink/renderer/modules/remoteplayback/html_media_element_remote_playback.idl", "//third_party/blink/renderer/modules/remoteplayback/remote_playback.idl", "//third_party/blink/renderer/modules/sanitizer_api/sanitizer.idl", @@ -885,6 +886,8 @@ "//third_party/blink/renderer/modules/webgpu/gpu_pipeline_layout_descriptor.idl", "//third_party/blink/renderer/modules/webgpu/gpu_programmable_pass_encoder.idl", "//third_party/blink/renderer/modules/webgpu/gpu_programmable_stage_descriptor.idl", + "//third_party/blink/renderer/modules/webgpu/gpu_query_set_descriptor.idl", + "//third_party/blink/renderer/modules/webgpu/gpu_query_set.idl", "//third_party/blink/renderer/modules/webgpu/gpu_queue.idl", "//third_party/blink/renderer/modules/webgpu/gpu_rasterization_state_descriptor.idl", "//third_party/blink/renderer/modules/webgpu/gpu_render_bundle.idl",
diff --git a/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc b/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc index 104e677..01ed8594 100644 --- a/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc +++ b/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc
@@ -192,7 +192,7 @@ void WebSharedWorkerImpl::StartWorkerContext( const WebURL& script_request_url, - mojom::ScriptType script_type, + mojom::blink::ScriptType script_type, network::mojom::CredentialsMode credentials_mode, const WebString& name, WebSecurityOrigin constructor_origin, @@ -300,14 +300,14 @@ GetWorkerThread()->GetTaskRunner(TaskType::kDOMManipulation); switch (script_type) { - case mojom::ScriptType::kClassic: + case mojom::blink::ScriptType::kClassic: GetWorkerThread()->FetchAndRunClassicScript( script_request_url, std::move(worker_main_script_load_params), outside_settings_object->CopyData(), nullptr /* outside_resource_timing_notifier */, v8_inspector::V8StackTraceId()); break; - case mojom::ScriptType::kModule: + case mojom::blink::ScriptType::kModule: GetWorkerThread()->FetchAndRunModuleScript( script_request_url, std::move(worker_main_script_load_params), outside_settings_object->CopyData(), @@ -328,7 +328,7 @@ std::unique_ptr<WebSharedWorker> WebSharedWorker::CreateAndStart( const blink::SharedWorkerToken& token, const WebURL& script_request_url, - mojom::ScriptType script_type, + mojom::blink::ScriptType script_type, network::mojom::CredentialsMode credentials_mode, const WebString& name, WebSecurityOrigin constructor_origin,
diff --git a/third_party/blink/renderer/core/exported/web_shared_worker_impl.h b/third_party/blink/renderer/core/exported/web_shared_worker_impl.h index ebe4764..22e76ca 100644 --- a/third_party/blink/renderer/core/exported/web_shared_worker_impl.h +++ b/third_party/blink/renderer/core/exported/web_shared_worker_impl.h
@@ -98,7 +98,7 @@ void StartWorkerContext( const WebURL&, - mojom::ScriptType, + mojom::blink::ScriptType, network::mojom::CredentialsMode, const WebString& name, WebSecurityOrigin constructor_origin,
diff --git a/third_party/blink/renderer/core/frame/web_view_frame_widget.cc b/third_party/blink/renderer/core/frame/web_view_frame_widget.cc index bb208c3..193fd171 100644 --- a/third_party/blink/renderer/core/frame/web_view_frame_widget.cc +++ b/third_party/blink/renderer/core/frame/web_view_frame_widget.cc
@@ -524,7 +524,9 @@ gfx::Rect new_compositor_viewport_pixel_rect = visual_properties.compositor_viewport_pixel_rect; if (AutoResizeMode()) { - new_compositor_viewport_pixel_rect = gfx::Rect(size_); + new_compositor_viewport_pixel_rect = gfx::Rect(gfx::ScaleToCeiledSize( + widget_base_->BlinkSpaceToDIPs(size_), + visual_properties.screen_info.device_scale_factor)); } widget_base_->UpdateSurfaceAndScreenInfo(
diff --git a/third_party/blink/renderer/core/html/html_view_source_document.cc b/third_party/blink/renderer/core/html/html_view_source_document.cc index 2742eed..d8cb488 100644 --- a/third_party/blink/renderer/core/html/html_view_source_document.cc +++ b/third_party/blink/renderer/core/html/html_view_source_document.cc
@@ -45,9 +45,7 @@ HTMLViewSourceDocument::HTMLViewSourceDocument(const DocumentInit& initializer) : HTMLDocument(initializer), type_(initializer.GetMimeType()) { SetIsViewSource(true); - - // FIXME: Why do view-source pages need to load in quirks mode? - SetCompatibilityMode(kQuirksMode); + SetCompatibilityMode(kNoQuirksMode); LockCompatibilityMode(); }
diff --git a/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc b/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc index 2eb850c..163fd0d 100644 --- a/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc +++ b/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc
@@ -287,7 +287,7 @@ if ((Match(tag_impl_, html_names::kScriptTag) && type_attribute_value_ == "module") || IsLinkRelModulePreload()) { - request->SetScriptType(mojom::ScriptType::kModule); + request->SetScriptType(mojom::blink::ScriptType::kModule); } request->SetCrossOrigin(cross_origin_); @@ -665,7 +665,7 @@ if (Match(tag_impl_, html_names::kInputTag) && !input_is_image_) return false; if (Match(tag_impl_, html_names::kScriptTag)) { - mojom::ScriptType script_type = mojom::ScriptType::kClassic; + mojom::blink::ScriptType script_type = mojom::blink::ScriptType::kClassic; bool is_import_map = false; if (!ScriptLoader::IsValidScriptTypeAndLanguage( type_attribute_value_, language_attribute_value_,
diff --git a/third_party/blink/renderer/core/html/parser/preload_request.cc b/third_party/blink/renderer/core/html/parser/preload_request.cc index 5caac86a..8318f626 100644 --- a/third_party/blink/renderer/core/html/parser/preload_request.cc +++ b/third_party/blink/renderer/core/html/parser/preload_request.cc
@@ -96,7 +96,7 @@ params.SetCrossOriginAccessControl(origin, kCrossOriginAttributeAnonymous); } - if (script_type_ == mojom::ScriptType::kModule) { + if (script_type_ == mojom::blink::ScriptType::kModule) { DCHECK_EQ(resource_type_, ResourceType::kScript); params.SetCrossOriginAccessControl( origin, ScriptLoader::ModuleScriptCredentialsMode(cross_origin_)); @@ -114,7 +114,7 @@ if (request_type_ == kRequestTypeLinkRelPreload) params.SetLinkPreload(true); - if (script_type_ == mojom::ScriptType::kModule) { + if (script_type_ == mojom::blink::ScriptType::kModule) { DCHECK_EQ(resource_type_, ResourceType::kScript); params.SetDecoderOptions(TextResourceDecoderOptions::CreateUTF8Decode()); } else if (resource_type_ == ResourceType::kScript ||
diff --git a/third_party/blink/renderer/core/html/parser/preload_request.h b/third_party/blink/renderer/core/html/parser/preload_request.h index b33b6e3..bb277995 100644 --- a/third_party/blink/renderer/core/html/parser/preload_request.h +++ b/third_party/blink/renderer/core/html/parser/preload_request.h
@@ -91,7 +91,7 @@ return referrer_policy_; } - void SetScriptType(mojom::ScriptType script_type) { + void SetScriptType(mojom::blink::ScriptType script_type) { script_type_ = script_type; } @@ -130,7 +130,7 @@ resource_url_(resource_url), base_url_(base_url), resource_type_(resource_type), - script_type_(mojom::ScriptType::kClassic), + script_type_(mojom::blink::ScriptType::kClassic), cross_origin_(kCrossOriginAttributeNotSet), importance_(mojom::FetchImportanceMode::kImportanceAuto), defer_(FetchParameters::kNoDefer), @@ -151,7 +151,7 @@ const KURL base_url_; String charset_; const ResourceType resource_type_; - mojom::ScriptType script_type_; + mojom::blink::ScriptType script_type_; CrossOriginAttributeValue cross_origin_; mojom::FetchImportanceMode importance_; String nonce_;
diff --git a/third_party/blink/renderer/core/layout/layout_block.cc b/third_party/blink/renderer/core/layout/layout_block.cc index 422cc271..50ecaf1 100644 --- a/third_party/blink/renderer/core/layout/layout_block.cc +++ b/third_party/blink/renderer/core/layout/layout_block.cc
@@ -132,6 +132,7 @@ } void LayoutBlock::RemoveFromGlobalMaps() { + CheckIsNotDestroyed(); if (HasPositionedObjects()) { std::unique_ptr<TrackedLayoutBoxListHashSet> descendants = GetPositionedDescendantsMap().Take(this); @@ -157,6 +158,7 @@ } void LayoutBlock::WillBeDestroyed() { + CheckIsNotDestroyed(); if (!DocumentBeingDestroyed() && Parent()) Parent()->DirtyLinesFromChangedChild(this); @@ -173,6 +175,7 @@ void LayoutBlock::StyleWillChange(StyleDifference diff, const ComputedStyle& new_style) { + CheckIsNotDestroyed(); SetIsAtomicInlineLevel(new_style.IsDisplayInlineType()); LayoutBox::StyleWillChange(diff, new_style); } @@ -198,6 +201,7 @@ void LayoutBlock::StyleDidChange(StyleDifference diff, const ComputedStyle* old_style) { + CheckIsNotDestroyed(); LayoutBox::StyleDidChange(diff, old_style); const ComputedStyle& new_style = StyleRef(); @@ -242,6 +246,7 @@ } void LayoutBlock::UpdateFromStyle() { + CheckIsNotDestroyed(); LayoutBox::UpdateFromStyle(); bool should_clip_overflow = !StyleRef().IsOverflowVisibleAlongBothAxes() && @@ -259,12 +264,14 @@ } bool LayoutBlock::AllowsNonVisibleOverflow() const { + CheckIsNotDestroyed(); // If overflow has been propagated to the viewport, it has no effect here. return GetNode() != GetDocument().ViewportDefiningElement(); } void LayoutBlock::AddChildBeforeDescendant(LayoutObject* new_child, LayoutObject* before_descendant) { + CheckIsNotDestroyed(); DCHECK_NE(before_descendant->Parent(), this); LayoutObject* before_descendant_container = before_descendant->Parent(); while (before_descendant_container->Parent() != this) @@ -315,6 +322,7 @@ void LayoutBlock::AddChild(LayoutObject* new_child, LayoutObject* before_child) { + CheckIsNotDestroyed(); if (before_child && before_child->Parent() != this) { AddChildBeforeDescendant(new_child, before_child); return; @@ -353,6 +361,7 @@ } void LayoutBlock::RemoveLeftoverAnonymousBlock(LayoutBlock* child) { + CheckIsNotDestroyed(); DCHECK(child->IsAnonymousBlock()); DCHECK(!child->ChildrenInline()); DCHECK_EQ(child->Parent(), this); @@ -384,12 +393,14 @@ } void LayoutBlock::UpdateAfterLayout() { + CheckIsNotDestroyed(); InvalidateStickyConstraints(); LayoutBox::UpdateAfterLayout(); } void LayoutBlock::UpdateLayout() { + CheckIsNotDestroyed(); DCHECK(!GetScrollableArea() || GetScrollableArea()->GetScrollAnchor()); LayoutAnalyzer::Scope analyzer(*this); @@ -415,6 +426,7 @@ } bool LayoutBlock::WidthAvailableToChildrenHasChanged() { + CheckIsNotDestroyed(); // TODO(robhogan): Does m_widthAvailableToChildrenChanged always get reset // when it needs to? bool width_available_to_children_has_changed = @@ -437,17 +449,20 @@ DISABLE_CFI_PERF bool LayoutBlock::UpdateLogicalWidthAndColumnWidth() { + CheckIsNotDestroyed(); LayoutUnit old_width = LogicalWidth(); UpdateLogicalWidth(); return old_width != LogicalWidth() || WidthAvailableToChildrenHasChanged(); } void LayoutBlock::UpdateBlockLayout(bool) { + CheckIsNotDestroyed(); NOTREACHED(); ClearNeedsLayout(); } void LayoutBlock::AddVisualOverflowFromChildren() { + CheckIsNotDestroyed(); // It is an error to call this function on a LayoutBlock that it itself inside // a display-locked subtree. DCHECK(!DisplayLockUtilities::LockedAncestorPreventingPrePaint(*this)); @@ -463,6 +478,7 @@ } void LayoutBlock::AddLayoutOverflowFromChildren() { + CheckIsNotDestroyed(); if (ChildLayoutBlockedByDisplayLock()) return; @@ -473,6 +489,7 @@ } void LayoutBlock::ComputeVisualOverflow(bool) { + CheckIsNotDestroyed(); DCHECK(!SelfNeedsLayout()); LayoutRect previous_visual_overflow_rect = VisualOverflowRect(); @@ -490,6 +507,7 @@ DISABLE_CFI_PERF void LayoutBlock::ComputeLayoutOverflow(LayoutUnit old_client_after_edge, bool) { + CheckIsNotDestroyed(); ClearSelfNeedsLayoutOverflowRecalc(); ClearLayoutOverflow(); AddLayoutOverflowFromChildren(); @@ -529,6 +547,7 @@ } void LayoutBlock::AddVisualOverflowFromBlockChildren() { + CheckIsNotDestroyed(); for (LayoutBox* child = FirstChildBox(); child; child = child->NextSiblingBox()) { if ((!IsLayoutNGContainingBlock(this) && child->IsFloating()) || @@ -549,6 +568,7 @@ } void LayoutBlock::AddLayoutOverflowFromBlockChildren() { + CheckIsNotDestroyed(); for (LayoutBox* child = FirstChildBox(); child; child = child->NextSiblingBox()) { if ((!IsLayoutNGContainingBlock(this) && child->IsFloating()) || @@ -570,6 +590,7 @@ } void LayoutBlock::AddLayoutOverflowFromPositionedObjects() { + CheckIsNotDestroyed(); if (IsLayoutNGBlockFlow()) return; @@ -603,6 +624,7 @@ void LayoutBlock::UpdateBlockChildDirtyBitsBeforeLayout(bool relayout_children, LayoutBox& child) { + CheckIsNotDestroyed(); if (child.IsOutOfFlowPositioned()) { // It's rather useless to mark out-of-flow children at this point. We may // not be their containing block (and if we are, it's just pure luck), so @@ -633,6 +655,7 @@ } void LayoutBlock::SimplifiedNormalFlowLayout() { + CheckIsNotDestroyed(); if (ChildrenInline()) { SECURITY_DCHECK(IsLayoutBlockFlow()); auto* block_flow = To<LayoutBlockFlow>(this); @@ -650,6 +673,7 @@ } bool LayoutBlock::SimplifiedLayout() { + CheckIsNotDestroyed(); // Check if we need to do a full layout. if (NormalChildNeedsLayout() || SelfNeedsLayout()) return false; @@ -735,6 +759,7 @@ void LayoutBlock::MarkFixedPositionObjectForLayoutIfNeeded( LayoutObject* child, SubtreeLayoutScope& layout_scope) { + CheckIsNotDestroyed(); if (child->StyleRef().GetPosition() != EPosition::kFixed) return; @@ -775,6 +800,7 @@ LayoutUnit LayoutBlock::MarginIntrinsicLogicalWidthForChild( const LayoutBox& child) const { + CheckIsNotDestroyed(); // A margin has three types: fixed, percentage, and auto (variable). // Auto and percentage margins become 0 when computing min/max width. // Fixed margins can be added in as is. @@ -817,6 +843,7 @@ void LayoutBlock::LayoutPositionedObjects(bool relayout_children, PositionedLayoutBehavior info) { + CheckIsNotDestroyed(); if (ChildLayoutBlockedByDisplayLock()) return; @@ -832,6 +859,7 @@ void LayoutBlock::LayoutPositionedObject(LayoutBox* positioned_object, bool relayout_children, PositionedLayoutBehavior info) { + CheckIsNotDestroyed(); positioned_object->SetShouldCheckForPaintInvalidation(); SubtreeLayoutScope layout_scope(*positioned_object); @@ -940,6 +968,7 @@ } void LayoutBlock::MarkPositionedObjectsForLayout() { + CheckIsNotDestroyed(); if (TrackedLayoutBoxListHashSet* positioned_descendants = PositionedObjects()) { for (auto* descendant : *positioned_descendants) @@ -948,24 +977,29 @@ } void LayoutBlock::Paint(const PaintInfo& paint_info) const { + CheckIsNotDestroyed(); BlockPainter(*this).Paint(paint_info); } void LayoutBlock::PaintChildren(const PaintInfo& paint_info, const PhysicalOffset&) const { + CheckIsNotDestroyed(); BlockPainter(*this).PaintChildren(paint_info); } void LayoutBlock::PaintObject(const PaintInfo& paint_info, const PhysicalOffset& paint_offset) const { + CheckIsNotDestroyed(); BlockPainter(*this).PaintObject(paint_info, paint_offset); } TrackedLayoutBoxListHashSet* LayoutBlock::PositionedObjectsInternal() const { + CheckIsNotDestroyed(); return GetPositionedDescendantsMap().at(this); } void LayoutBlock::InsertPositionedObject(LayoutBox* o) { + CheckIsNotDestroyed(); DCHECK(!IsAnonymousBlock()); DCHECK_EQ(o->ContainingBlock(), this); @@ -1011,6 +1045,7 @@ } bool LayoutBlock::IsAnonymousNGFieldsetContentWrapper() const { + CheckIsNotDestroyed(); if (!RuntimeEnabledFeatures::LayoutNGFieldsetEnabled() || !Parent()) return false; return Parent()->IsLayoutNGFieldset(); @@ -1018,11 +1053,13 @@ void LayoutBlock::InvalidatePaint( const PaintInvalidatorContext& context) const { + CheckIsNotDestroyed(); BlockPaintInvalidator(*this).InvalidatePaint(context); } void LayoutBlock::ImageChanged(WrappedImagePtr image, CanDeferInvalidation defer) { + CheckIsNotDestroyed(); LayoutBox::ImageChanged(image, defer); if (!StyleRef().HasPseudoElementStyle(kPseudoIdFirstLine)) @@ -1046,6 +1083,7 @@ void LayoutBlock::RemovePositionedObjects( LayoutObject* o, ContainingBlockState containing_block_state) { + CheckIsNotDestroyed(); TrackedLayoutBoxListHashSet* positioned_descendants = PositionedObjects(); if (!positioned_descendants) return; @@ -1100,6 +1138,7 @@ } void LayoutBlock::AddPercentHeightDescendant(LayoutBox* descendant) { + CheckIsNotDestroyed(); // A replaced object is incapable of properly acting as a containing block for // its children. This is an issue with VIDEO elements, for instance, which // insert some percentage height flexbox children. It is also very easily @@ -1141,6 +1180,7 @@ } void LayoutBlock::RemovePercentHeightDescendant(LayoutBox* descendant) { + CheckIsNotDestroyed(); if (TrackedLayoutBoxListHashSet* descendants = PercentHeightDescendants()) { descendants->erase(descendant); descendant->SetPercentHeightContainer(nullptr); @@ -1153,11 +1193,13 @@ TrackedLayoutBoxListHashSet* LayoutBlock::PercentHeightDescendantsInternal() const { + CheckIsNotDestroyed(); return GetPercentHeightDescendantsMap().at(this); } void LayoutBlock::DirtyForLayoutFromPercentageHeightDescendants( SubtreeLayoutScope& layout_scope) { + CheckIsNotDestroyed(); TrackedLayoutBoxListHashSet* descendants = PercentHeightDescendants(); if (!descendants) return; @@ -1177,6 +1219,7 @@ } LayoutUnit LayoutBlock::TextIndentOffset() const { + CheckIsNotDestroyed(); LayoutUnit cw; if (StyleRef().TextIndent().IsPercentOrCalc()) cw = ContentLogicalWidth(); @@ -1187,6 +1230,7 @@ HitTestResult& result, const PhysicalOffset& hit_test_location, const PhysicalOffset& accumulated_offset) const { + CheckIsNotDestroyed(); if (!ScrollsOverflow()) return false; @@ -1198,6 +1242,7 @@ HitTestResult& result, const HitTestLocation& hit_test_location, const PhysicalOffset& adjusted_location) const { + CheckIsNotDestroyed(); if (VisibleToHitTestRequest(result.GetHitTestRequest()) && IsPointInOverflowControl(result, hit_test_location.Point(), adjusted_location)) { @@ -1214,6 +1259,7 @@ const HitTestLocation& hit_test_location, const PhysicalOffset& accumulated_offset, HitTestAction hit_test_action) { + CheckIsNotDestroyed(); // We may use legacy code to hit-test the anonymous fieldset content wrapper // child. The layout object for the rendered legend will be a child of that // one, and has to be skipped here, since its fragment is actually laid out on @@ -1258,6 +1304,7 @@ } Position LayoutBlock::PositionForBox(InlineBox* box, bool start) const { + CheckIsNotDestroyed(); if (!box) return Position(); @@ -1294,6 +1341,7 @@ PositionWithAffinity LayoutBlock::PositionForPointRespectingEditingBoundaries( LineLayoutBox child, const PhysicalOffset& point_in_parent_coordinates) const { + CheckIsNotDestroyed(); PhysicalOffset child_location = child.PhysicalLocation(); if (child.IsInFlowPositioned()) child_location += child.OffsetForInFlowPosition(); @@ -1332,6 +1380,7 @@ PositionWithAffinity LayoutBlock::PositionForPointIfOutsideAtomicInlineLevel( const PhysicalOffset& point) const { + CheckIsNotDestroyed(); DCHECK(IsAtomicInlineLevel()); LogicalOffset logical_offset = point.ConvertToLogical(StyleRef().GetWritingMode(), ResolvedDirection(), @@ -1355,6 +1404,7 @@ PositionWithAffinity LayoutBlock::PositionForPoint( const PhysicalOffset& point) const { + CheckIsNotDestroyed(); if (IsTable()) return LayoutBox::PositionForPoint(point); @@ -1409,6 +1459,7 @@ } void LayoutBlock::OffsetForContents(PhysicalOffset& offset) const { + CheckIsNotDestroyed(); if (IsScrollContainer()) offset += PhysicalOffset(PixelSnappedScrolledContentOffset()); } @@ -1416,11 +1467,13 @@ void LayoutBlock::ScrollbarsChanged(bool horizontal_scrollbar_changed, bool vertical_scrollbar_changed, ScrollbarChangeContext context) { + CheckIsNotDestroyed(); width_available_to_children_changed_ |= vertical_scrollbar_changed; height_available_to_children_changed_ |= horizontal_scrollbar_changed; } MinMaxSizes LayoutBlock::ComputeIntrinsicLogicalWidths() const { + CheckIsNotDestroyed(); MinMaxSizes sizes; sizes += BorderAndPaddingLogicalWidth() + ComputeLogicalScrollbars().InlineSum(); @@ -1480,6 +1533,7 @@ DISABLE_CFI_PERF MinMaxSizes LayoutBlock::PreferredLogicalWidths() const { + CheckIsNotDestroyed(); MinMaxSizes sizes; // FIXME: The isFixed() calls here should probably be checking for isSpecified @@ -1520,6 +1574,7 @@ void LayoutBlock::ComputeBlockPreferredLogicalWidths( LayoutUnit& min_logical_width, LayoutUnit& max_logical_width) const { + CheckIsNotDestroyed(); const ComputedStyle& style_to_use = StyleRef(); bool nowrap = style_to_use.WhiteSpace() == EWhiteSpace::kNowrap; @@ -1644,6 +1699,7 @@ LayoutObject& child, LayoutUnit& min_preferred_logical_width, LayoutUnit& max_preferred_logical_width) const { + CheckIsNotDestroyed(); if (child.IsBox() && child.IsHorizontalWritingMode() != IsHorizontalWritingMode()) { // If the child is an orthogonal flow, child's height determines the width, @@ -1677,6 +1733,7 @@ } bool LayoutBlock::HasLineIfEmpty() const { + CheckIsNotDestroyed(); if (GetNode()) { if (IsRootEditableElement(*GetNode())) return true; @@ -1686,6 +1743,7 @@ LayoutUnit LayoutBlock::EmptyLineBaseline( LineDirectionMode line_direction) const { + CheckIsNotDestroyed(); if (!HasLineIfEmpty()) return LayoutUnit(-1); const auto baseline_offset = BaselineForEmptyLine(line_direction); @@ -1694,6 +1752,7 @@ base::Optional<LayoutUnit> LayoutBlock::BaselineForEmptyLine( LineDirectionMode line_direction) const { + CheckIsNotDestroyed(); const SimpleFontData* font_data = FirstLineStyle()->GetFont().PrimaryFont(); if (!font_data) return base::nullopt; @@ -1711,6 +1770,7 @@ LayoutUnit LayoutBlock::LineHeight(bool first_line, LineDirectionMode direction, LinePositionMode line_position_mode) const { + CheckIsNotDestroyed(); // Inline blocks are replaced elements. Otherwise, just pass off to // the base class. If we're being queried as though we're the root line // box, then the fact that we're an inline-block is irrelevant, and we behave @@ -1725,6 +1785,7 @@ LayoutUnit LayoutBlock::BeforeMarginInLineDirection( LineDirectionMode direction) const { + CheckIsNotDestroyed(); // InlineFlowBox::placeBoxesInBlockDirection will flip lines in // case of verticalLR mode, so we can assume verticalRL for now. return direction == kHorizontalLine ? MarginTop() : MarginRight(); @@ -1735,6 +1796,7 @@ bool first_line, LineDirectionMode direction, LinePositionMode line_position_mode) const { + CheckIsNotDestroyed(); // Inline blocks are replaced elements. Otherwise, just pass off to // the base class. If we're being queried as though we're the root line // box, then the fact that we're an inline-block is irrelevant, and we behave @@ -1796,6 +1858,7 @@ LayoutUnit LayoutBlock::MinLineHeightForReplacedObject( bool is_first_line, LayoutUnit replaced_height) const { + CheckIsNotDestroyed(); if (!GetDocument().InNoQuirksMode() && replaced_height) return replaced_height; @@ -1813,6 +1876,7 @@ // those two layout modes, though. LayoutUnit LayoutBlock::FirstLineBoxBaseline() const { + CheckIsNotDestroyed(); DCHECK(!ChildrenInline()); if (ShouldApplyLayoutContainment()) return LayoutUnit(-1); @@ -1833,6 +1897,7 @@ } bool LayoutBlock::UseLogicalBottomMarginEdgeForInlineBlockBaseline() const { + CheckIsNotDestroyed(); // CSS2.1 states that the baseline of an 'inline-block' is: // the baseline of the last line box in the normal flow, unless it has // either no in-flow line boxes or if its 'overflow' property has a computed @@ -1848,6 +1913,7 @@ LayoutUnit LayoutBlock::InlineBlockBaseline( LineDirectionMode line_direction) const { + CheckIsNotDestroyed(); DCHECK(!ChildrenInline()); if (UseLogicalBottomMarginEdgeForInlineBlockBaseline()) { // We are not calling LayoutBox::baselinePosition here because the caller @@ -1877,6 +1943,7 @@ } const LayoutBlock* LayoutBlock::EnclosingFirstLineStyleBlock() const { + CheckIsNotDestroyed(); const LayoutBlock* first_line_block = this; bool has_pseudo = false; while (true) { @@ -1902,6 +1969,7 @@ } LayoutBlockFlow* LayoutBlock::NearestInnerBlockWithFirstLine() { + CheckIsNotDestroyed(); if (ChildrenInline()) return To<LayoutBlockFlow>(this); for (LayoutObject* child = FirstChild(); @@ -1917,15 +1985,18 @@ // An inline-block uses its inlineBox as the inlineBoxWrapper, // so the firstChild() is nullptr if the only child is an empty inline-block. inline bool LayoutBlock::IsInlineBoxWrapperActuallyChild() const { + CheckIsNotDestroyed(); return IsInlineBlockOrInlineTable() && !Size().IsEmpty() && GetNode() && EditingIgnoresContent(*GetNode()); } bool LayoutBlock::ShouldPaintCursorCaret() const { + CheckIsNotDestroyed(); return GetFrame()->Selection().ShouldPaintCaret(*this); } bool LayoutBlock::ShouldPaintDragCaret() const { + CheckIsNotDestroyed(); return GetFrame()->GetPage()->GetDragCaret().ShouldPaintCaret(*this); } @@ -1933,6 +2004,7 @@ const InlineBox* inline_box, int caret_offset, LayoutUnit* extra_width_to_end_of_line) const { + CheckIsNotDestroyed(); // Do the normal calculation in most cases. if ((FirstChild() && !FirstChild()->IsPseudoElement()) || IsInlineBoxWrapperActuallyChild()) @@ -1951,6 +2023,7 @@ void LayoutBlock::AddOutlineRects(Vector<PhysicalRect>& rects, const PhysicalOffset& additional_offset, NGOutlineType include_block_overflows) const { + CheckIsNotDestroyed(); #if DCHECK_IS_ON() // TODO(crbug.com/987836): enable this DCHECK universally. Page* page = GetDocument().GetPage(); @@ -1977,11 +2050,13 @@ LayoutBox* LayoutBlock::CreateAnonymousBoxWithSameTypeAs( const LayoutObject* parent) const { + CheckIsNotDestroyed(); return CreateAnonymousWithParentAndDisplay(parent, StyleRef().Display()); } void LayoutBlock::PaginatedContentWasLaidOut( LayoutUnit logical_bottom_offset_after_pagination) { + CheckIsNotDestroyed(); if (LayoutFlowThread* flow_thread = FlowThreadContainingBlock()) flow_thread->ContentWasLaidOut(OffsetFromLogicalTopOfFirstPage() + logical_bottom_offset_after_pagination); @@ -1989,6 +2064,7 @@ LayoutUnit LayoutBlock::CollapsedMarginBeforeForChild( const LayoutBox& child) const { + CheckIsNotDestroyed(); // If the child has the same directionality as we do, then we can just return // its collapsed margin. if (!child.IsWritingModeRoot()) @@ -2008,6 +2084,7 @@ LayoutUnit LayoutBlock::CollapsedMarginAfterForChild( const LayoutBox& child) const { + CheckIsNotDestroyed(); // If the child has the same directionality as we do, then we can just return // its collapsed margin. if (!child.IsWritingModeRoot()) @@ -2026,6 +2103,7 @@ } bool LayoutBlock::HasMarginBeforeQuirk(const LayoutBox* child) const { + CheckIsNotDestroyed(); // If the child has the same directionality as we do, then we can just return // its margin quirk. auto* child_layout_block = DynamicTo<LayoutBlock>(child); @@ -2048,6 +2126,7 @@ } bool LayoutBlock::HasMarginAfterQuirk(const LayoutBox* child) const { + CheckIsNotDestroyed(); // If the child has the same directionality as we do, then we can just return // its margin quirk. auto* child_layout_block = DynamicTo<LayoutBlock>(child); @@ -2070,6 +2149,7 @@ } const char* LayoutBlock::GetName() const { + CheckIsNotDestroyed(); NOTREACHED(); return "LayoutBlock"; } @@ -2124,12 +2204,14 @@ bool LayoutBlock::RecalcNormalFlowChildLayoutOverflowIfNeeded( LayoutObject* layout_object) { + CheckIsNotDestroyed(); if (layout_object->IsOutOfFlowPositioned()) return false; return layout_object->RecalcLayoutOverflow(); } bool LayoutBlock::RecalcChildLayoutOverflow() { + CheckIsNotDestroyed(); DCHECK(!IsTable()); DCHECK(ChildNeedsLayoutOverflowRecalc()); ClearChildNeedsLayoutOverflowRecalc(); @@ -2152,6 +2234,7 @@ } void LayoutBlock::RecalcChildVisualOverflow() { + CheckIsNotDestroyed(); DCHECK(!IsTable()); // It is an error to call this function on a LayoutBlock that it itself inside // a display-locked subtree. @@ -2172,6 +2255,7 @@ } bool LayoutBlock::RecalcPositionedDescendantsLayoutOverflow() { + CheckIsNotDestroyed(); bool children_layout_overflow_changed = false; TrackedLayoutBoxListHashSet* positioned_descendants = PositionedObjects(); @@ -2186,6 +2270,7 @@ } void LayoutBlock::RecalcPositionedDescendantsVisualOverflow() { + CheckIsNotDestroyed(); TrackedLayoutBoxListHashSet* positioned_descendants = PositionedObjects(); if (!positioned_descendants) return; @@ -2198,6 +2283,7 @@ } bool LayoutBlock::RecalcLayoutOverflow() { + CheckIsNotDestroyed(); bool children_layout_overflow_changed = false; if (ChildNeedsLayoutOverflowRecalc()) children_layout_overflow_changed = RecalcChildLayoutOverflow(); @@ -2210,11 +2296,13 @@ } void LayoutBlock::RecalcVisualOverflow() { + CheckIsNotDestroyed(); RecalcChildVisualOverflow(); RecalcSelfVisualOverflow(); } bool LayoutBlock::RecalcSelfLayoutOverflow() { + CheckIsNotDestroyed(); bool self_needs_layout_overflow_recalc = SelfNeedsLayoutOverflowRecalc(); // If the current block needs layout, overflow will be recalculated during // layout time anyway. We can safely exit here. @@ -2230,6 +2318,7 @@ } void LayoutBlock::RecalcSelfVisualOverflow() { + CheckIsNotDestroyed(); ComputeVisualOverflow(true); } @@ -2237,6 +2326,7 @@ // A simplified layout is attempted that just updates the object's position. // If the size does change, the object remains dirty. bool LayoutBlock::TryLayoutDoingPositionedMovementOnly() { + CheckIsNotDestroyed(); LayoutUnit old_width = LogicalWidth(); LogicalExtentComputedValues computed_values; LogicalExtentAfterUpdatingLogicalWidth(LogicalTop(), computed_values); @@ -2272,6 +2362,7 @@ #if DCHECK_IS_ON() void LayoutBlock::CheckPositionedObjectsNeedLayout() { + CheckIsNotDestroyed(); if (ChildLayoutBlockedByDisplayLock()) return; @@ -2293,6 +2384,7 @@ #endif LayoutUnit LayoutBlock::AvailableLogicalHeightForPercentageComputation() const { + CheckIsNotDestroyed(); LayoutUnit available_height(-1); // For anonymous blocks that are skipped during percentage height calculation, @@ -2371,10 +2463,12 @@ } bool LayoutBlock::HasDefiniteLogicalHeight() const { + CheckIsNotDestroyed(); return AvailableLogicalHeightForPercentageComputation() != LayoutUnit(-1); } bool LayoutBlock::NeedsPreferredWidthsRecalculation() const { + CheckIsNotDestroyed(); return (HasRelativeLogicalHeight() && StyleRef().LogicalWidth().IsAuto()) || LayoutBox::NeedsPreferredWidthsRecalculation(); }
diff --git a/third_party/blink/renderer/core/layout/layout_block.h b/third_party/blink/renderer/core/layout/layout_block.h index 02f7c69..1201e930 100644 --- a/third_party/blink/renderer/core/layout/layout_block.h +++ b/third_party/blink/renderer/core/layout/layout_block.h
@@ -110,10 +110,12 @@ public: LayoutObject* FirstChild() const { + CheckIsNotDestroyed(); DCHECK_EQ(Children(), VirtualChildren()); return Children()->FirstChild(); } LayoutObject* LastChild() const { + CheckIsNotDestroyed(); DCHECK_EQ(Children(), VirtualChildren()); return Children()->LastChild(); } @@ -122,8 +124,14 @@ void SlowFirstChild() const = delete; void SlowLastChild() const = delete; - const LayoutObjectChildList* Children() const { return &children_; } - LayoutObjectChildList* Children() { return &children_; } + const LayoutObjectChildList* Children() const { + CheckIsNotDestroyed(); + return &children_; + } + LayoutObjectChildList* Children() { + CheckIsNotDestroyed(); + return &children_; + } // These two functions are overridden for inline-block. LayoutUnit LineHeight( @@ -143,6 +151,7 @@ const char* GetName() const override; virtual const NGPhysicalBoxFragment* CurrentFragment() const { + CheckIsNotDestroyed(); return nullptr; } @@ -167,10 +176,12 @@ ContainingBlockState = kSameContainingBlock); TrackedLayoutBoxListHashSet* PositionedObjects() const { + CheckIsNotDestroyed(); return UNLIKELY(HasPositionedObjects()) ? PositionedObjectsInternal() : nullptr; } bool HasPositionedObjects() const { + CheckIsNotDestroyed(); DCHECK(has_positioned_objects_ ? (PositionedObjectsInternal() && !PositionedObjectsInternal()->IsEmpty()) : !PositionedObjectsInternal()); @@ -180,15 +191,18 @@ void AddPercentHeightDescendant(LayoutBox*); void RemovePercentHeightDescendant(LayoutBox*); bool HasPercentHeightDescendant(LayoutBox* o) const { + CheckIsNotDestroyed(); return HasPercentHeightDescendants() && PercentHeightDescendantsInternal()->Contains(o); } TrackedLayoutBoxListHashSet* PercentHeightDescendants() const { + CheckIsNotDestroyed(); return HasPercentHeightDescendants() ? PercentHeightDescendantsInternal() : nullptr; } bool HasPercentHeightDescendants() const { + CheckIsNotDestroyed(); DCHECK(has_percent_height_descendants_ ? (PercentHeightDescendantsInternal() && !PercentHeightDescendantsInternal()->IsEmpty()) @@ -197,6 +211,7 @@ } void NotifyScrollbarThicknessChanged() { + CheckIsNotDestroyed(); width_available_to_children_changed_ = true; } @@ -206,14 +221,32 @@ // itself for the legend is still a child of this object. bool IsAnonymousNGFieldsetContentWrapper() const; - void SetHasMarkupTruncation(bool b) { has_markup_truncation_ = b; } - bool HasMarkupTruncation() const { return has_markup_truncation_; } + void SetHasMarkupTruncation(bool b) { + CheckIsNotDestroyed(); + has_markup_truncation_ = b; + } + bool HasMarkupTruncation() const { + CheckIsNotDestroyed(); + return has_markup_truncation_; + } - void SetHasMarginBeforeQuirk(bool b) { has_margin_before_quirk_ = b; } - void SetHasMarginAfterQuirk(bool b) { has_margin_after_quirk_ = b; } + void SetHasMarginBeforeQuirk(bool b) { + CheckIsNotDestroyed(); + has_margin_before_quirk_ = b; + } + void SetHasMarginAfterQuirk(bool b) { + CheckIsNotDestroyed(); + has_margin_after_quirk_ = b; + } - bool HasMarginBeforeQuirk() const { return has_margin_before_quirk_; } - bool HasMarginAfterQuirk() const { return has_margin_after_quirk_; } + bool HasMarginBeforeQuirk() const { + CheckIsNotDestroyed(); + return has_margin_before_quirk_; + } + bool HasMarginAfterQuirk() const { + CheckIsNotDestroyed(); + return has_margin_after_quirk_; + } bool HasMarginBeforeQuirk(const LayoutBox* child) const; bool HasMarginAfterQuirk(const LayoutBox* child) const; @@ -228,6 +261,7 @@ const LayoutObject*, EDisplay = EDisplay::kBlock); LayoutBlock* CreateAnonymousBlock(EDisplay display = EDisplay::kBlock) const { + CheckIsNotDestroyed(); return CreateAnonymousWithParentAndDisplay(this, display); } @@ -237,48 +271,61 @@ // Accessors for logical width/height and margins in the containing block's // block-flow direction. LayoutUnit LogicalWidthForChild(const LayoutBox& child) const { + CheckIsNotDestroyed(); return LogicalWidthForChildSize(child.Size()); } LayoutUnit LogicalWidthForChildSize(LayoutSize child_size) const { + CheckIsNotDestroyed(); return IsHorizontalWritingMode() ? child_size.Width() : child_size.Height(); } LayoutUnit LogicalHeightForChild(const LayoutBox& child) const { + CheckIsNotDestroyed(); return IsHorizontalWritingMode() ? child.Size().Height() : child.Size().Width(); } LayoutSize LogicalSizeForChild(const LayoutBox& child) const { + CheckIsNotDestroyed(); return IsHorizontalWritingMode() ? child.Size() : child.Size().TransposedSize(); } LayoutUnit LogicalTopForChild(const LayoutBox& child) const { + CheckIsNotDestroyed(); return IsHorizontalWritingMode() ? child.Location().Y() : child.Location().X(); } DISABLE_CFI_PERF LayoutUnit MarginBeforeForChild(const LayoutBoxModelObject& child) const { + CheckIsNotDestroyed(); return child.MarginBefore(Style()); } DISABLE_CFI_PERF LayoutUnit MarginAfterForChild(const LayoutBoxModelObject& child) const { + CheckIsNotDestroyed(); return child.MarginAfter(Style()); } DISABLE_CFI_PERF LayoutUnit MarginStartForChild(const LayoutBoxModelObject& child) const { + CheckIsNotDestroyed(); return child.MarginStart(Style()); } LayoutUnit MarginEndForChild(const LayoutBoxModelObject& child) const { + CheckIsNotDestroyed(); return child.MarginEnd(Style()); } void SetMarginStartForChild(LayoutBox& child, LayoutUnit value) const { + CheckIsNotDestroyed(); child.SetMarginStart(value, Style()); } void SetMarginEndForChild(LayoutBox& child, LayoutUnit value) const { + CheckIsNotDestroyed(); child.SetMarginEnd(value, Style()); } void SetMarginBeforeForChild(LayoutBox& child, LayoutUnit value) const { + CheckIsNotDestroyed(); child.SetMarginBefore(value, Style()); } void SetMarginAfterForChild(LayoutBox& child, LayoutUnit value) const { + CheckIsNotDestroyed(); child.SetMarginAfter(value, Style()); } LayoutUnit CollapsedMarginBeforeForChild(const LayoutBox& child) const; @@ -290,21 +337,26 @@ ScrollbarChangeContext = kLayout); LayoutUnit AvailableLogicalWidthForContent() const { + CheckIsNotDestroyed(); return (LogicalRightOffsetForContent() - LogicalLeftOffsetForContent()) .ClampNegativeToZero(); } DISABLE_CFI_PERF LayoutUnit LogicalLeftOffsetForContent() const { + CheckIsNotDestroyed(); return IsHorizontalWritingMode() ? ContentLeft() : ContentTop(); } LayoutUnit LogicalRightOffsetForContent() const { + CheckIsNotDestroyed(); return LogicalLeftOffsetForContent() + AvailableLogicalWidth(); } LayoutUnit StartOffsetForContent() const { + CheckIsNotDestroyed(); return StyleRef().IsLeftToRightDirection() ? LogicalLeftOffsetForContent() : LogicalWidth() - LogicalRightOffsetForContent(); } LayoutUnit EndOffsetForContent() const { + CheckIsNotDestroyed(); return !StyleRef().IsLeftToRightDirection() ? LogicalLeftOffsetForContent() : LogicalWidth() - LogicalRightOffsetForContent(); @@ -380,10 +432,12 @@ public: bool IsLegacyInitiatedOutOfFlowLayout() const { + CheckIsNotDestroyed(); return is_legacy_initiated_out_of_flow_layout_; } void SetIsLegacyInitiatedOutOfFlowLayout(bool b) { + CheckIsNotDestroyed(); is_legacy_initiated_out_of_flow_layout_ = b; } @@ -411,7 +465,9 @@ virtual void AdjustInlineDirectionLineBounds( unsigned /* expansionOpportunityCount */, LayoutUnit& /* logicalLeft */, - LayoutUnit& /* logicalWidth */) const {} + LayoutUnit& /* logicalWidth */) const { + CheckIsNotDestroyed(); + } MinMaxSizes ComputeIntrinsicLogicalWidths() const override; void ComputeChildPreferredLogicalWidths( @@ -470,12 +526,14 @@ // Alternatively it should be removed as we clarify the meaning of // isAtomicInlineLevel to imply isInline. bool IsInlineBlockOrInlineTable() const final { + CheckIsNotDestroyed(); return IsInline() && IsAtomicInlineLevel(); } bool NeedsPreferredWidthsRecalculation() const override; bool IsInSelfHitTestingPhase(HitTestAction hit_test_action) const final { + CheckIsNotDestroyed(); return hit_test_action == kHitTestBlockBackground || hit_test_action == kHitTestChildBlockBackground; } @@ -486,12 +544,19 @@ LayoutUnit EmptyLineBaseline(LineDirectionMode line_direction) const; private: - LayoutObjectChildList* VirtualChildren() final { return Children(); } + LayoutObjectChildList* VirtualChildren() final { + CheckIsNotDestroyed(); + return Children(); + } const LayoutObjectChildList* VirtualChildren() const final { + CheckIsNotDestroyed(); return Children(); } - bool IsLayoutBlock() const final { return true; } + bool IsLayoutBlock() const final { + CheckIsNotDestroyed(); + return true; + } virtual void RemoveLeftoverAnonymousBlock(LayoutBlock* child); @@ -512,6 +577,7 @@ bool ShouldPaintCursorCaret() const; bool ShouldPaintDragCaret() const; bool ShouldPaintCarets() const { + CheckIsNotDestroyed(); return ShouldPaintCursorCaret() || ShouldPaintDragCaret(); }
diff --git a/third_party/blink/renderer/core/layout/layout_block_flow.cc b/third_party/blink/renderer/core/layout/layout_block_flow.cc index 30c1e9de..3109c6f7 100644 --- a/third_party/blink/renderer/core/layout/layout_block_flow.cc +++ b/third_party/blink/renderer/core/layout/layout_block_flow.cc
@@ -296,6 +296,7 @@ LayoutObject* LayoutBlockFlow::LayoutSpecialExcludedChild( bool relayout_children, SubtreeLayoutScope& layout_scope) { + CheckIsNotDestroyed(); LayoutMultiColumnFlowThread* flow_thread = MultiColumnFlowThread(); if (!flow_thread) return nullptr; @@ -306,6 +307,7 @@ } bool LayoutBlockFlow::UpdateLogicalWidthAndColumnWidth() { + CheckIsNotDestroyed(); bool relayout_children = LayoutBlock::UpdateLogicalWidthAndColumnWidth(); if (LayoutMultiColumnFlowThread* flow_thread = MultiColumnFlowThread()) { if (flow_thread->NeedsNewWidth()) @@ -315,6 +317,7 @@ } void LayoutBlockFlow::SetBreakAtLineToAvoidWidow(int line_to_break) { + CheckIsNotDestroyed(); DCHECK_GE(line_to_break, 0); EnsureRareData(); DCHECK(!rare_data_->did_break_at_line_to_avoid_widow_); @@ -322,6 +325,7 @@ } void LayoutBlockFlow::SetDidBreakAtLineToAvoidWidow() { + CheckIsNotDestroyed(); DCHECK(!ShouldBreakAtLineToAvoidWidow()); // This function should be called only after a break was applied to avoid @@ -332,6 +336,7 @@ } void LayoutBlockFlow::ClearDidBreakAtLineToAvoidWidow() { + CheckIsNotDestroyed(); if (!rare_data_) return; @@ -339,6 +344,7 @@ } void LayoutBlockFlow::ClearShouldBreakAtLineToAvoidWidow() const { + CheckIsNotDestroyed(); DCHECK(ShouldBreakAtLineToAvoidWidow()); if (!rare_data_) return; @@ -347,6 +353,7 @@ } bool LayoutBlockFlow::IsSelfCollapsingBlock() const { + CheckIsNotDestroyed(); if (NeedsLayout()) { // Sometimes we don't lay out objects in DOM order (column spanners being // one such relevant type of object right here). As long as the object in @@ -361,6 +368,7 @@ } bool LayoutBlockFlow::CheckIfIsSelfCollapsingBlock() const { + CheckIsNotDestroyed(); // We are not self-collapsing if we // (a) have a non-zero height according to layout (an optimization to avoid // wasting time) @@ -440,6 +448,7 @@ DISABLE_CFI_PERF void LayoutBlockFlow::UpdateBlockLayout(bool relayout_children) { + CheckIsNotDestroyed(); DCHECK(NeedsLayout()); DCHECK(IsInlineBlockOrInlineTable() || !IsInline()); @@ -542,6 +551,7 @@ DISABLE_CFI_PERF void LayoutBlockFlow::ResetLayout() { + CheckIsNotDestroyed(); if (!FirstChild() && !IsAnonymousBlock()) SetChildrenInline(true); SetContainsInlineWithOutlineAndContinuation(false); @@ -599,6 +609,7 @@ DISABLE_CFI_PERF void LayoutBlockFlow::LayoutChildren(bool relayout_children, SubtreeLayoutScope& layout_scope) { + CheckIsNotDestroyed(); ResetLayout(); if (ChildLayoutBlockedByDisplayLock()) @@ -629,6 +640,7 @@ void LayoutBlockFlow::AddOverhangingFloatsFromChildren( LayoutUnit unconstrained_height) { + CheckIsNotDestroyed(); LayoutBlockFlow* lowest_block = nullptr; bool added_overhanging_floats = false; // One of our children's floats may have become an overhanging float for us. @@ -660,6 +672,7 @@ } void LayoutBlockFlow::AddLowestFloatFromChildren(LayoutBlockFlow* block) { + CheckIsNotDestroyed(); // TODO(robhogan): Make createsNewFormattingContext an ASSERT. if (!block || !block->ContainsFloats() || block->CreatesNewFormattingContext()) @@ -683,6 +696,7 @@ DISABLE_CFI_PERF void LayoutBlockFlow::DetermineLogicalLeftPositionForChild(LayoutBox& child) { + CheckIsNotDestroyed(); LayoutUnit start_position = BorderStart() + PaddingStart(); LayoutUnit initial_start_position = start_position; start_position -= LogicalLeftScrollbarWidth(); @@ -718,6 +732,7 @@ void LayoutBlockFlow::SetLogicalLeftForChild(LayoutBox& child, LayoutUnit logical_left) { + CheckIsNotDestroyed(); LayoutPoint new_location(child.Location()); if (IsHorizontalWritingMode()) { new_location.SetX(logical_left); @@ -729,6 +744,7 @@ void LayoutBlockFlow::SetLogicalTopForChild(LayoutBox& child, LayoutUnit logical_top) { + CheckIsNotDestroyed(); if (IsHorizontalWritingMode()) { child.SetY(logical_top); } else { @@ -740,6 +756,7 @@ LayoutBlockFlow& child, LayoutUnit new_logical_top, LayoutUnit previous_float_logical_bottom) { + CheckIsNotDestroyed(); // TODO(mstensho): rework the code to return early when there is no need for // marking, instead of this |markDescendantsWithFloats| flag. bool mark_descendants_with_floats = false; @@ -770,6 +787,7 @@ LayoutBox& child, LayoutUnit new_logical_top, BlockChildrenLayoutInfo& layout_info) { + CheckIsNotDestroyed(); if (LayoutFlowThread* flow_thread = FlowThreadContainingBlock()) layout_info.RollBackToInitialMultiColumnLayoutState(*flow_thread); @@ -834,6 +852,7 @@ void LayoutBlockFlow::InsertForcedBreakBeforeChildIfNeeded( LayoutBox& child, BlockChildrenLayoutInfo& layout_info) { + CheckIsNotDestroyed(); LayoutState* layout_state = View()->GetLayoutState(); // If the child has a start/end page name, that's the current name. Otherwise @@ -912,6 +931,7 @@ void LayoutBlockFlow::LayoutBlockChild(LayoutBox& child, BlockChildrenLayoutInfo& layout_info) { + CheckIsNotDestroyed(); MarginInfo& margin_info = layout_info.GetMarginInfo(); auto* child_layout_block_flow = DynamicTo<LayoutBlockFlow>(&child); LayoutUnit old_pos_margin_before = MaxPositiveMarginBefore(); @@ -1067,6 +1087,7 @@ LayoutBox& child, BlockChildrenLayoutInfo& layout_info, bool at_before_side_of_block) { + CheckIsNotDestroyed(); auto* child_block_flow = DynamicTo<LayoutBlockFlow>(&child); // See if we need a soft (unforced) break in front of this child, and set the @@ -1153,6 +1174,7 @@ LayoutUnit LayoutBlockFlow::AdjustFloatLogicalTopForPagination( LayoutBox& child, LayoutUnit logical_top_margin_edge) { + CheckIsNotDestroyed(); // The first piece of content inside the child may have set a strut during // layout. LayoutUnit strut; @@ -1238,6 +1260,7 @@ void LayoutBlockFlow::AdjustLinePositionForPagination(RootInlineBox& line_box, LayoutUnit& delta) { + CheckIsNotDestroyed(); // TODO(mstensho): Pay attention to line overflow. It should be painted in the // same column as the rest of the line, possibly overflowing the column. We // currently only allow overflow above the first column. We clip at all other @@ -1359,6 +1382,7 @@ LayoutUnit LayoutBlockFlow::AdjustForUnsplittableChild( LayoutBox& child, LayoutUnit logical_offset) const { + CheckIsNotDestroyed(); if (child.GetLegacyPaginationBreakability() == kAllowAnyBreaks) return logical_offset; LayoutUnit child_logical_height = LogicalHeightForChild(child); @@ -1397,6 +1421,7 @@ DISABLE_CFI_PERF void LayoutBlockFlow::RebuildFloatsFromIntruding() { + CheckIsNotDestroyed(); if (floating_objects_) floating_objects_->SetHorizontalWritingMode(IsHorizontalWritingMode()); @@ -1576,6 +1601,7 @@ SubtreeLayoutScope& layout_scope, LayoutUnit before_edge, LayoutUnit after_edge) { + CheckIsNotDestroyed(); DirtyForLayoutFromPercentageHeightDescendants(layout_scope); BlockChildrenLayoutInfo layout_info(this, before_edge, after_edge); @@ -1691,6 +1717,7 @@ LayoutBlockFlow::MarginValues LayoutBlockFlow::MarginValuesForChild( LayoutBox& child) const { + CheckIsNotDestroyed(); LayoutUnit child_before_positive; LayoutUnit child_before_negative; LayoutUnit child_after_positive; @@ -1760,6 +1787,7 @@ LayoutUnit logical_top_margin_edge, LayoutUnit logical_top_border_edge, const BlockChildrenLayoutInfo& layout_info) const { + CheckIsNotDestroyed(); LayoutUnit effective_margin = logical_top_border_edge - logical_top_margin_edge; DCHECK(IsPageLogicalHeightKnown()); @@ -1798,6 +1826,7 @@ LayoutBox& child, BlockChildrenLayoutInfo& layout_info, bool child_is_self_collapsing) { + CheckIsNotDestroyed(); MarginInfo& margin_info = layout_info.GetMarginInfo(); // Get the four margin values for the child and cache them. @@ -1969,6 +1998,7 @@ void LayoutBlockFlow::AdjustPositionedBlock( LayoutBox& child, const BlockChildrenLayoutInfo& layout_info) { + CheckIsNotDestroyed(); LayoutUnit logical_top = LogicalHeight(); // Forced breaks are only specified on in-flow objects, but auto-positioned @@ -2001,6 +2031,7 @@ LayoutUnit old_top_neg_margin, LayoutUnit y_pos, bool child_is_self_collapsing) { + CheckIsNotDestroyed(); LayoutUnit height_increase = GetClearDelta(&child, y_pos); margin_info.SetLastChildIsSelfCollapsingBlockWithClearance(false); @@ -2062,6 +2093,7 @@ } void LayoutBlockFlow::SetCollapsedBottomMargin(const MarginInfo& margin_info) { + CheckIsNotDestroyed(); if (margin_info.CanCollapseWithMarginAfter() && !margin_info.CanCollapseWithMarginBefore()) { // Update our max pos/neg bottom margins, since we collapsed our bottom @@ -2087,6 +2119,7 @@ LayoutBox& child, LayoutUnit& positive_margin_before, LayoutUnit& negative_margin_before) const { + CheckIsNotDestroyed(); // Give up if in quirks mode and we're a body/table cell and the top margin of // the child box is quirky. // FIXME: Use writing mode independent accessor for marginBeforeCollapse. @@ -2156,6 +2189,7 @@ LayoutBox& child, const BlockChildrenLayoutInfo& layout_info, LayoutUnit& estimate_without_pagination) { + CheckIsNotDestroyed(); const MarginInfo& margin_info = layout_info.GetMarginInfo(); // FIXME: We need to eliminate the estimation of vertical position, because // when it's wrong we sometimes trigger a pathological @@ -2225,6 +2259,7 @@ } void LayoutBlockFlow::AdjustFloatingBlock(const MarginInfo& margin_info) { + CheckIsNotDestroyed(); // The float should be positioned taking into account the bottom margin // of the previous flow. We add that margin into the height, get the // float positioned properly, and then subtract the margin out of the @@ -2248,6 +2283,7 @@ LayoutUnit before_side, LayoutUnit after_side, MarginInfo& margin_info) { + CheckIsNotDestroyed(); margin_info.SetAtAfterSideOfBlock(true); // If our last child was a self-collapsing block with clearance then our @@ -2299,6 +2335,7 @@ } void LayoutBlockFlow::SetMaxMarginBeforeValues(LayoutUnit pos, LayoutUnit neg) { + CheckIsNotDestroyed(); if (!rare_data_) { if (pos == LayoutBlockFlowRareData::PositiveMarginBeforeDefault(this) && neg == LayoutBlockFlowRareData::NegativeMarginBeforeDefault(this)) @@ -2310,6 +2347,7 @@ } void LayoutBlockFlow::SetMaxMarginAfterValues(LayoutUnit pos, LayoutUnit neg) { + CheckIsNotDestroyed(); if (!rare_data_) { if (pos == LayoutBlockFlowRareData::PositiveMarginAfterDefault(this) && neg == LayoutBlockFlowRareData::NegativeMarginAfterDefault(this)) @@ -2322,6 +2360,7 @@ LayoutUnit LayoutBlockFlow::ApplyForcedBreak(LayoutUnit logical_offset, EBreakBetween break_value) { + CheckIsNotDestroyed(); if (!IsForcedFragmentainerBreakValue(break_value)) return logical_offset; // TODO(mstensho): honor breakValue. There are different types of forced @@ -2351,6 +2390,7 @@ } void LayoutBlockFlow::SetBreakBefore(EBreakBetween break_value) { + CheckIsNotDestroyed(); if (break_value != EBreakBetween::kAuto && !IsBreakBetweenControllable(break_value)) break_value = EBreakBetween::kAuto; @@ -2360,6 +2400,7 @@ } void LayoutBlockFlow::SetBreakAfter(EBreakBetween break_value) { + CheckIsNotDestroyed(); if (break_value != EBreakBetween::kAuto && !IsBreakBetweenControllable(break_value)) break_value = EBreakBetween::kAuto; @@ -2369,16 +2410,19 @@ } EBreakBetween LayoutBlockFlow::BreakBefore() const { + CheckIsNotDestroyed(); return rare_data_ ? static_cast<EBreakBetween>(rare_data_->break_before_) : EBreakBetween::kAuto; } EBreakBetween LayoutBlockFlow::BreakAfter() const { + CheckIsNotDestroyed(); return rare_data_ ? static_cast<EBreakBetween>(rare_data_->break_after_) : EBreakBetween::kAuto; } void LayoutBlockFlow::AddVisualOverflowFromFloats() { + CheckIsNotDestroyed(); if (ChildPrePaintBlockedByDisplayLock() || !floating_objects_) return; @@ -2396,6 +2440,7 @@ void LayoutBlockFlow::AddVisualOverflowFromFloats( const NGPhysicalContainerFragment& fragment) { + CheckIsNotDestroyed(); DCHECK(!NeedsLayout()); DCHECK(!ChildPrePaintBlockedByDisplayLock()); DCHECK(fragment.HasFloatingDescendantsForPaint()); @@ -2419,6 +2464,7 @@ } void LayoutBlockFlow::AddLayoutOverflowFromFloats() { + CheckIsNotDestroyed(); if (ChildLayoutBlockedByDisplayLock() || !floating_objects_) return; @@ -2434,16 +2480,19 @@ void LayoutBlockFlow::SetPaintFragment( const NGBlockBreakToken*, - scoped_refptr<const NGPhysicalFragment>) {} + scoped_refptr<const NGPhysicalFragment>) { + CheckIsNotDestroyed(); +} const NGFragmentItems* LayoutBlockFlow::FragmentItems() const { + CheckIsNotDestroyed(); if (const NGPhysicalBoxFragment* box_fragment = CurrentFragment()) return box_fragment->Items(); return nullptr; } -void LayoutBlockFlow::ComputeVisualOverflow( - bool recompute_floats) { +void LayoutBlockFlow::ComputeVisualOverflow(bool recompute_floats) { + CheckIsNotDestroyed(); DCHECK(!SelfNeedsLayout()); LayoutRect previous_visual_overflow_rect = VisualOverflowRect(); @@ -2465,6 +2514,7 @@ void LayoutBlockFlow::ComputeLayoutOverflow(LayoutUnit old_client_after_edge, bool recompute_floats) { + CheckIsNotDestroyed(); LayoutBlock::ComputeLayoutOverflow(old_client_after_edge, recompute_floats); // TODO(chrishtr): why does it check for a self-painting layer? That should // only apply to visual overflow. @@ -2476,6 +2526,7 @@ void LayoutBlockFlow::AbsoluteQuads(Vector<FloatQuad>& quads, MapCoordinatesFlags mode) const { + CheckIsNotDestroyed(); if (!IsAnonymousBlockContinuation()) { LayoutBlock::AbsoluteQuads(quads, mode); return; @@ -2485,6 +2536,7 @@ void LayoutBlockFlow::AbsoluteQuadsForSelf(Vector<FloatQuad>& quads, MapCoordinatesFlags mode) const { + CheckIsNotDestroyed(); // For blocks inside inlines, we go ahead and include margins so that we run // right up to the inline boxes above and below us (thus getting merged with // them to form a single irregular shape). @@ -2496,11 +2548,13 @@ } LayoutObject* LayoutBlockFlow::HoverAncestor() const { + CheckIsNotDestroyed(); return IsAnonymousBlockContinuation() ? Continuation() : LayoutBlock::HoverAncestor(); } RootInlineBox* LayoutBlockFlow::CreateAndAppendRootInlineBox() { + CheckIsNotDestroyed(); RootInlineBox* root_box = CreateRootInlineBox(); line_boxes_.AppendLineBox(root_box); @@ -2510,6 +2564,7 @@ // Note: When this function is called from |LayoutInline::SplitFlow()|, some // fragments point to destroyed |LayoutObject|. void LayoutBlockFlow::DeleteLineBoxTree() { + CheckIsNotDestroyed(); if (ContainsFloats()) floating_objects_->ClearLineBoxTreePointers(); @@ -2524,6 +2579,7 @@ int LayoutBlockFlow::LineCount( const RootInlineBox* stop_root_inline_box) const { + CheckIsNotDestroyed(); #if DCHECK_IS_ON() DCHECK(!stop_root_inline_box || stop_root_inline_box->Block().DebugPointer() == this); @@ -2542,6 +2598,7 @@ } LayoutUnit LayoutBlockFlow::FirstLineBoxBaseline() const { + CheckIsNotDestroyed(); if (ShouldApplyLayoutContainment()) return LayoutUnit(-1); // Orthogonal grid items can participante in baseline alignment along column @@ -2583,6 +2640,7 @@ LayoutUnit LayoutBlockFlow::InlineBlockBaseline( LineDirectionMode line_direction) const { + CheckIsNotDestroyed(); if (UseLogicalBottomMarginEdgeForInlineBlockBaseline()) { // We are not calling baselinePosition here because the caller should add // the margin-top/margin-right, not us. @@ -2612,6 +2670,7 @@ } void LayoutBlockFlow::RemoveFloatingObjectsFromDescendants() { + CheckIsNotDestroyed(); if (!ContainsFloats()) return; RemoveFloatingObjects(); @@ -2649,6 +2708,7 @@ void LayoutBlockFlow::MarkAllDescendantsWithFloatsForLayout( LayoutBox* float_to_remove, bool in_layout) { + CheckIsNotDestroyed(); if (!EverHadLayout() && !ContainsFloats()) return; @@ -2692,6 +2752,7 @@ void LayoutBlockFlow::MarkSiblingsWithFloatsForLayout( LayoutBox* float_to_remove) { + CheckIsNotDestroyed(); if (!floating_objects_) return; @@ -2718,6 +2779,7 @@ LayoutUnit LayoutBlockFlow::GetClearDelta(LayoutBox* child, LayoutUnit logical_top) { + CheckIsNotDestroyed(); // There is no need to compute clearance if we have no floats. if (!ContainsFloats()) return LayoutUnit(); @@ -2776,11 +2838,13 @@ } void LayoutBlockFlow::CreateFloatingObjects() { + CheckIsNotDestroyed(); floating_objects_ = std::make_unique<FloatingObjects>(this, IsHorizontalWritingMode()); } void LayoutBlockFlow::WillBeDestroyed() { + CheckIsNotDestroyed(); // Make sure to destroy anonymous children first while they are still // connected to the rest of the tree, so that they will properly dirty line // boxes that they are removed from. Effects that do :before/:after only on @@ -2820,6 +2884,7 @@ void LayoutBlockFlow::StyleWillChange(StyleDifference diff, const ComputedStyle& new_style) { + CheckIsNotDestroyed(); const ComputedStyle* old_style = Style(); can_propagate_float_into_sibling_ = old_style && !IsFloatingOrOutOfFlowPositioned() && @@ -2836,6 +2901,7 @@ DISABLE_CFI_PERF void LayoutBlockFlow::StyleDidChange(StyleDifference diff, const ComputedStyle* old_style) { + CheckIsNotDestroyed(); bool had_self_painting_layer = HasSelfPaintingLayer(); LayoutBlock::StyleDidChange(diff, old_style); @@ -2907,6 +2973,7 @@ void LayoutBlockFlow::UpdateBlockChildDirtyBitsBeforeLayout( bool relayout_children, LayoutBox& child) { + CheckIsNotDestroyed(); if (child.IsLayoutMultiColumnSpannerPlaceholder()) ToLayoutMultiColumnSpannerPlaceholder(child) .MarkForLayoutIfObjectInFlowThreadNeedsLayout(); @@ -2917,6 +2984,7 @@ LayoutBox& child, LayoutUnit logical_top, IndentTextOrNot indent_text) { + CheckIsNotDestroyed(); if (child.StyleRef().IsOriginalDisplayInlineType()) SetStaticInlinePositionForChild( child, StartAlignedOffsetForLine(logical_top, indent_text)); @@ -2927,10 +2995,12 @@ void LayoutBlockFlow::SetStaticInlinePositionForChild( LayoutBox& child, LayoutUnit inline_position) { + CheckIsNotDestroyed(); child.Layer()->SetStaticInlinePosition(inline_position); } LayoutInline* LayoutBlockFlow::InlineElementContinuation() const { + CheckIsNotDestroyed(); LayoutBoxModelObject* continuation = Continuation(); return continuation && continuation->IsInline() ? ToLayoutInline(continuation) : nullptr; @@ -2938,6 +3008,7 @@ void LayoutBlockFlow::AddChild(LayoutObject* new_child, LayoutObject* before_child) { + CheckIsNotDestroyed(); if (LayoutMultiColumnFlowThread* flow_thread = MultiColumnFlowThread()) { if (before_child == flow_thread) before_child = flow_thread->FirstChild(); @@ -3020,6 +3091,7 @@ } void LayoutBlockFlow::RemoveChild(LayoutObject* old_child) { + CheckIsNotDestroyed(); // No need to waste time in merging or removing empty anonymous blocks. // We can just bail out if our document is getting destroyed. if (DocumentBeingDestroyed()) { @@ -3126,6 +3198,7 @@ void LayoutBlockFlow::MoveAllChildrenIncludingFloatsTo( LayoutBlock* to_block, bool full_remove_insert) { + CheckIsNotDestroyed(); auto* to_block_flow = To<LayoutBlockFlow>(to_block); DCHECK(full_remove_insert || @@ -3171,6 +3244,7 @@ } void LayoutBlockFlow::ChildBecameFloatingOrOutOfFlow(LayoutBox* child) { + CheckIsNotDestroyed(); MakeChildrenInlineIfPossible(); // Reparent the child to an adjacent anonymous block if one is available. @@ -3191,6 +3265,7 @@ } void LayoutBlockFlow::CollapseAnonymousBlockChild(LayoutBlockFlow* child) { + CheckIsNotDestroyed(); // It's possible that this block's destruction may have been triggered by the // child's removal. Just bail if the anonymous child block is already being // destroyed. See crbug.com/282088 @@ -3220,6 +3295,7 @@ bool LayoutBlockFlow::MergeSiblingContiguousAnonymousBlock( LayoutBlockFlow* sibling_that_may_be_deleted) { + CheckIsNotDestroyed(); // Note: |this| and |siblingThatMayBeDeleted| may not be adjacent siblings at // this point. There may be an object between them which is about to be // removed. @@ -3245,6 +3321,7 @@ } void LayoutBlockFlow::ReparentSubsequentFloatingOrOutOfFlowSiblings() { + CheckIsNotDestroyed(); auto* parent_block_flow = DynamicTo<LayoutBlockFlow>(Parent()); if (!parent_block_flow) return; @@ -3265,6 +3342,7 @@ } void LayoutBlockFlow::ReparentPrecedingFloatingOrOutOfFlowSiblings() { + CheckIsNotDestroyed(); auto* parent_block_flow = DynamicTo<LayoutBlockFlow>(Parent()); if (!parent_block_flow) return; @@ -3279,6 +3357,7 @@ } void LayoutBlockFlow::MakeChildrenInlineIfPossible() { + CheckIsNotDestroyed(); // Collapsing away anonymous wrappers isn't relevant for the children of // anonymous blocks, unless they are ruby bases. if (IsAnonymousBlock() && !IsRubyBase()) @@ -3379,6 +3458,7 @@ } void LayoutBlockFlow::MakeChildrenNonInline(LayoutObject* insertion_point) { + CheckIsNotDestroyed(); // makeChildrenNonInline takes a block whose children are *all* inline and it // makes sure that inline children are coalesced under anonymous blocks. // If |insertionPoint| is defined, then it represents the insertion point for @@ -3422,6 +3502,7 @@ } void LayoutBlockFlow::ChildBecameNonInline(LayoutObject*) { + CheckIsNotDestroyed(); MakeChildrenNonInline(); auto* parent_layout_block = DynamicTo<LayoutBlock>(Parent()); if (IsAnonymousBlock() && parent_layout_block) @@ -3430,6 +3511,7 @@ } void LayoutBlockFlow::ClearFloats(EClear clear) { + CheckIsNotDestroyed(); PlaceNewFloats(LogicalHeight()); // set y position LayoutUnit new_y = LowestFloatLogicalBottom(clear); @@ -3438,12 +3520,14 @@ } bool LayoutBlockFlow::ContainsFloat(LayoutBox* layout_box) const { + CheckIsNotDestroyed(); return floating_objects_ && floating_objects_->Set().Contains<FloatingObjectHashTranslator>( layout_box); } void LayoutBlockFlow::RemoveFloatingObjects() { + CheckIsNotDestroyed(); if (!floating_objects_) return; @@ -3455,6 +3539,7 @@ LayoutPoint LayoutBlockFlow::FlipFloatForWritingModeForChild( const FloatingObject& child, const LayoutPoint& point) const { + CheckIsNotDestroyed(); if (!StyleRef().IsFlippedBlocksWritingMode()) return point; @@ -3472,6 +3557,7 @@ LayoutUnit logical_top, LayoutUnit fixed_offset, LayoutUnit* height_remaining) const { + CheckIsNotDestroyed(); LayoutUnit offset = fixed_offset; if (floating_objects_ && floating_objects_->HasLeftObjects()) offset = floating_objects_->LogicalLeftOffsetForPositioningFloat( @@ -3483,6 +3569,7 @@ LayoutUnit logical_top, LayoutUnit fixed_offset, LayoutUnit* height_remaining) const { + CheckIsNotDestroyed(); LayoutUnit offset = fixed_offset; if (floating_objects_ && floating_objects_->HasRightObjects()) offset = floating_objects_->LogicalRightOffsetForPositioningFloat( @@ -3493,6 +3580,7 @@ LayoutUnit LayoutBlockFlow::AdjustLogicalLeftOffsetForLine( LayoutUnit offset_from_floats, IndentTextOrNot apply_text_indent) const { + CheckIsNotDestroyed(); LayoutUnit left = offset_from_floats; if (apply_text_indent == kIndentText && StyleRef().IsLeftToRightDirection()) @@ -3504,6 +3592,7 @@ LayoutUnit LayoutBlockFlow::AdjustLogicalRightOffsetForLine( LayoutUnit offset_from_floats, IndentTextOrNot apply_text_indent) const { + CheckIsNotDestroyed(); LayoutUnit right = offset_from_floats; if (apply_text_indent == kIndentText && !StyleRef().IsLeftToRightDirection()) @@ -3515,6 +3604,7 @@ LayoutPoint LayoutBlockFlow::ComputeLogicalLocationForFloat( const FloatingObject& floating_object, LayoutUnit logical_top_offset) const { + CheckIsNotDestroyed(); LayoutBox* child_box = floating_object.GetLayoutObject(); LayoutUnit logical_left_offset = LogicalLeftOffsetForContent(); // Constant part of left offset. @@ -3569,6 +3659,7 @@ } FloatingObject* LayoutBlockFlow::InsertFloatingObject(LayoutBox& float_box) { + CheckIsNotDestroyed(); DCHECK(float_box.IsFloating()); // Create the list of special objects if we don't aleady have one @@ -3594,6 +3685,7 @@ } void LayoutBlockFlow::RemoveFloatingObject(LayoutBox* float_box) { + CheckIsNotDestroyed(); if (floating_objects_) { const FloatingObjectSet& floating_object_set = floating_objects_->Set(); FloatingObjectSetIterator it = @@ -3634,6 +3726,7 @@ void LayoutBlockFlow::RemoveFloatingObjectsBelow(FloatingObject* last_float, LayoutUnit logical_offset) { + CheckIsNotDestroyed(); if (!ContainsFloats()) return; @@ -3650,6 +3743,7 @@ FloatingObject* LayoutBlockFlow::LastPlacedFloat( FloatingObjectSetIterator* iterator) const { + CheckIsNotDestroyed(); const FloatingObjectSet& floating_object_set = floating_objects_->Set(); FloatingObjectSetIterator it = floating_object_set.end(); --it; // Go to last item. @@ -3670,6 +3764,7 @@ bool LayoutBlockFlow::PlaceNewFloats(LayoutUnit logical_top_margin_edge, LineWidth* width) { + CheckIsNotDestroyed(); if (!floating_objects_) return false; @@ -3716,6 +3811,7 @@ LayoutUnit LayoutBlockFlow::PositionAndLayoutFloat( FloatingObject& floating_object, LayoutUnit logical_top_margin_edge) { + CheckIsNotDestroyed(); // Once a float has been placed, we cannot update its position, or the float // interval tree will be out of sync with reality. This may in turn lead to // objects being used after they have been deleted. @@ -3845,6 +3941,7 @@ } bool LayoutBlockFlow::HasOverhangingFloat(LayoutBox* layout_box) { + CheckIsNotDestroyed(); if (!floating_objects_ || !Parent()) return false; @@ -3860,6 +3957,7 @@ void LayoutBlockFlow::AddIntrudingFloats(LayoutBlockFlow* prev, LayoutUnit logical_left_offset, LayoutUnit logical_top_offset) { + CheckIsNotDestroyed(); DCHECK(!CreatesNewFormattingContext()); // If we create our own block formatting context then our contents don't @@ -3911,6 +4009,7 @@ void LayoutBlockFlow::AddOverhangingFloats(LayoutBlockFlow* child, bool make_child_paint_other_floats) { + CheckIsNotDestroyed(); // Prevent floats from being added to the canvas by the root element, e.g., // <html>. if (!child->ContainsFloats() || child->CreatesNewFormattingContext()) @@ -3993,6 +4092,7 @@ } LayoutUnit LayoutBlockFlow::LowestFloatLogicalBottom(EClear clear) const { + CheckIsNotDestroyed(); if (clear == EClear::kNone || !floating_objects_) return LayoutUnit(); @@ -4006,6 +4106,7 @@ LayoutUnit LayoutBlockFlow::NextFloatLogicalBottomBelow( LayoutUnit logical_height) const { + CheckIsNotDestroyed(); if (!floating_objects_) return logical_height; return floating_objects_->FindNextFloatLogicalBottomBelow(logical_height); @@ -4013,6 +4114,7 @@ LayoutUnit LayoutBlockFlow::NextFloatLogicalBottomBelowForBlock( LayoutUnit logical_height) const { + CheckIsNotDestroyed(); if (!floating_objects_) return logical_height; @@ -4021,11 +4123,13 @@ } LayoutUnit LayoutBlockFlow::LogicalHeightWithVisibleOverflow() const { + CheckIsNotDestroyed(); LayoutUnit logical_height = LayoutBlock::LogicalHeightWithVisibleOverflow(); return std::max(logical_height, LowestFloatLogicalBottom()); } Node* LayoutBlockFlow::NodeForHitTest() const { + CheckIsNotDestroyed(); // If we are in the margins of block elements that are part of a // continuation we're actually still inside the enclosing element // that was split. Use the appropriate inner node. @@ -4037,6 +4141,7 @@ const HitTestLocation& hit_test_location, const PhysicalOffset& accumulated_offset, HitTestAction hit_test_action) { + CheckIsNotDestroyed(); PhysicalOffset scrolled_offset = accumulated_offset; if (IsScrollContainer()) scrolled_offset -= PhysicalOffset(PixelSnappedScrolledContentOffset()); @@ -4068,6 +4173,7 @@ bool LayoutBlockFlow::HitTestFloats(HitTestResult& result, const HitTestLocation& hit_test_location, const PhysicalOffset& accumulated_offset) { + CheckIsNotDestroyed(); if (!floating_objects_) return false; @@ -4098,6 +4204,7 @@ } PhysicalOffset LayoutBlockFlow::AccumulateRelativePositionOffsets() const { + CheckIsNotDestroyed(); if (!IsAnonymousBlock() || !IsInFlowPositioned()) return PhysicalOffset(); PhysicalOffset offset; @@ -4113,6 +4220,7 @@ LayoutUnit logical_top, LayoutUnit fixed_offset, LayoutUnit logical_height) const { + CheckIsNotDestroyed(); if (floating_objects_ && floating_objects_->HasLeftObjects()) return floating_objects_->LogicalLeftOffset(fixed_offset, logical_top, logical_height); @@ -4124,6 +4232,7 @@ LayoutUnit logical_top, LayoutUnit fixed_offset, LayoutUnit logical_height) const { + CheckIsNotDestroyed(); if (floating_objects_ && floating_objects_->HasRightObjects()) return floating_objects_->LogicalRightOffset(fixed_offset, logical_top, logical_height); @@ -4135,6 +4244,7 @@ LayoutUnit logical_top, LayoutUnit fixed_offset, LayoutUnit logical_height) const { + CheckIsNotDestroyed(); if (floating_objects_ && floating_objects_->HasLeftObjects()) { return floating_objects_->LogicalLeftOffsetForAvoidingFloats( fixed_offset, logical_top, logical_height); @@ -4147,6 +4257,7 @@ LayoutUnit logical_top, LayoutUnit fixed_offset, LayoutUnit logical_height) const { + CheckIsNotDestroyed(); if (floating_objects_ && floating_objects_->HasRightObjects()) { return floating_objects_->LogicalRightOffsetForAvoidingFloats( fixed_offset, logical_top, logical_height); @@ -4210,6 +4321,7 @@ } bool LayoutBlockFlow::AllowsPaginationStrut() const { + CheckIsNotDestroyed(); // The block needs to be contained by a LayoutBlockFlow (and not by e.g. a // flexbox, grid, or a table (the latter being the case for table cell or // table caption)). The reason for this limitation is simply that @@ -4256,6 +4368,7 @@ } void LayoutBlockFlow::SetPaginationStrutPropagatedFromChild(LayoutUnit strut) { + CheckIsNotDestroyed(); strut = std::max(strut, LayoutUnit()); if (!rare_data_) { if (!strut) @@ -4266,6 +4379,7 @@ } void LayoutBlockFlow::SetFirstForcedBreakOffset(LayoutUnit block_offset) { + CheckIsNotDestroyed(); if (!rare_data_) { if (!block_offset) return; @@ -4275,24 +4389,28 @@ } const AtomicString LayoutBlockFlow::StartPageName() const { + CheckIsNotDestroyed(); if (const AtomicString& propagated_name = PropagatedStartPageName()) return propagated_name; return StyleRef().Page(); } const AtomicString LayoutBlockFlow::EndPageName() const { + CheckIsNotDestroyed(); if (const AtomicString& propagated_name = PropagatedEndPageName()) return propagated_name; return StyleRef().Page(); } const AtomicString LayoutBlockFlow::PropagatedStartPageName() const { + CheckIsNotDestroyed(); if (!rare_data_) return AtomicString(); return rare_data_->propagated_start_page_name_; } void LayoutBlockFlow::SetPropagatedStartPageName(const AtomicString& name) { + CheckIsNotDestroyed(); if (name.IsEmpty() && !rare_data_) return; LayoutBlockFlowRareData& rare_data = EnsureRareData(); @@ -4300,12 +4418,14 @@ } const AtomicString LayoutBlockFlow::PropagatedEndPageName() const { + CheckIsNotDestroyed(); if (!rare_data_) return AtomicString(); return rare_data_->propagated_end_page_name_; } void LayoutBlockFlow::SetPropagatedEndPageName(const AtomicString& name) { + CheckIsNotDestroyed(); if (name.IsEmpty() && !rare_data_) return; LayoutBlockFlowRareData& rare_data = EnsureRareData(); @@ -4314,6 +4434,7 @@ void LayoutBlockFlow::PositionSpannerDescendant( LayoutMultiColumnSpannerPlaceholder& child) { + CheckIsNotDestroyed(); LayoutBox& spanner = *child.LayoutObjectInFlowThread(); // FIXME: |spanner| is a descendant, but never a direct child, so the names // here are bad, if nothing else. @@ -4323,6 +4444,7 @@ DISABLE_CFI_PERF bool LayoutBlockFlow::CreatesNewFormattingContext() const { + CheckIsNotDestroyed(); if (IsInline() || IsFloatingOrOutOfFlowPositioned() || IsScrollContainer() || IsFlexItemIncludingDeprecatedAndNG() || IsCustomItem() || IsDocumentElement() || IsGridItemIncludingNG() || IsWritingModeRoot() || @@ -4349,6 +4471,7 @@ LayoutObject* end_child, LayoutObject* before_child, bool full_remove_insert) { + CheckIsNotDestroyed(); if (ChildrenInline()) DeleteLineBoxTree(); LayoutBoxModelObject::MoveChildrenTo(to_box_model_object, start_child, @@ -4357,11 +4480,13 @@ } RootInlineBox* LayoutBlockFlow::CreateRootInlineBox() { + CheckIsNotDestroyed(); return new RootInlineBox(LineLayoutItem(this)); } void LayoutBlockFlow::CreateOrDestroyMultiColumnFlowThreadIfNeeded( const ComputedStyle* old_style) { + CheckIsNotDestroyed(); bool specifies_columns = StyleRef().SpecifiesColumns(); if (MultiColumnFlowThread()) { @@ -4428,6 +4553,7 @@ } LayoutBlockFlow::LayoutBlockFlowRareData& LayoutBlockFlow::EnsureRareData() { + CheckIsNotDestroyed(); if (rare_data_) return *rare_data_; @@ -4436,6 +4562,7 @@ } void LayoutBlockFlow::PositionDialog() { + CheckIsNotDestroyed(); base::Optional<LayoutUnit> y = ComputeAbsoluteDialogYPosition(*this, Size().Height()); if (y.has_value()) @@ -4443,6 +4570,7 @@ } void LayoutBlockFlow::SimplifiedNormalFlowInlineLayout() { + CheckIsNotDestroyed(); DCHECK(ChildrenInline()); LinkedHashSet<RootInlineBox*> line_boxes; for (InlineWalker walker(LineLayoutBlockFlow(this)); !walker.AtEnd(); @@ -4472,6 +4600,7 @@ } bool LayoutBlockFlow::RecalcInlineChildrenLayoutOverflow() { + CheckIsNotDestroyed(); DCHECK(ChildrenInline()); bool children_layout_overflow_changed = false; HashSet<RootInlineBox*> line_boxes; @@ -4502,6 +4631,7 @@ } void LayoutBlockFlow::RecalcInlineChildrenVisualOverflow() { + CheckIsNotDestroyed(); DCHECK(ChildrenInline()); if (const NGPaintFragment* paint_fragment = PaintFragment()) { @@ -4555,6 +4685,7 @@ PositionWithAffinity LayoutBlockFlow::PositionForPoint( const LayoutObject& offset_parent, const PhysicalOffset& offset) const { + CheckIsNotDestroyed(); // Currently this function is called only from an inline child of this // |LayoutBlockFlow|. DCHECK(offset_parent.IsInline()); @@ -4576,6 +4707,7 @@ PositionWithAffinity LayoutBlockFlow::PositionForPoint( const PhysicalOffset& point) const { + CheckIsNotDestroyed(); if (IsAtomicInlineLevel()) { PositionWithAffinity position = PositionForPointIfOutsideAtomicInlineLevel(point); @@ -4710,6 +4842,7 @@ bool LayoutBlockFlow::ShouldMoveCaretToHorizontalBoundaryWhenPastTopOrBottom() const { + CheckIsNotDestroyed(); return GetDocument() .GetFrame() ->GetEditor() @@ -4724,6 +4857,7 @@ const InlineBox* marked_box2, const char* marked_label2, const LayoutObject* obj) const { + CheckIsNotDestroyed(); StringBuilder string_blockflow; DumpLayoutObject(string_blockflow, true, kShowTreeCharacterOffset); for (const RootInlineBox* root = FirstRootBox(); root; @@ -4740,6 +4874,7 @@ Vector<PhysicalRect>& rects, const PhysicalOffset& additional_offset, NGOutlineType include_block_overflows) const { + CheckIsNotDestroyed(); // For blocks inside inlines, we go ahead and include margins so that we run // right up to the inline boxes above and below us (thus getting merged with // them to form a single irregular shape). @@ -4806,11 +4941,13 @@ void LayoutBlockFlow::InvalidateDisplayItemClients( PaintInvalidationReason invalidation_reason) const { + CheckIsNotDestroyed(); BlockFlowPaintInvalidator(*this).InvalidateDisplayItemClients( invalidation_reason); } void LayoutBlockFlow::IncrementLayoutPassCount() { + CheckIsNotDestroyed(); int layout_pass_count = 0; HashMap<LayoutBlockFlow*, int>::iterator layout_count_iterator = GetLayoutPassCountMap().find(this); @@ -4820,6 +4957,7 @@ } int LayoutBlockFlow::GetLayoutPassCountForTesting() { + CheckIsNotDestroyed(); return GetLayoutPassCountMap().find(this)->value; } @@ -4837,6 +4975,7 @@ LayoutBlockFlow::LayoutBlockFlowRareData::~LayoutBlockFlowRareData() = default; void LayoutBlockFlow::ClearOffsetMappingIfNeeded() { + CheckIsNotDestroyed(); DCHECK(!IsLayoutNGObject()); if (!rare_data_) return; @@ -4844,6 +4983,7 @@ } const NGOffsetMapping* LayoutBlockFlow::GetOffsetMapping() const { + CheckIsNotDestroyed(); DCHECK(!IsLayoutNGObject()); CHECK(!SelfNeedsLayout()); CHECK(!NeedsLayout() || ChildLayoutBlockedByDisplayLock()); @@ -4852,6 +4992,7 @@ void LayoutBlockFlow::SetOffsetMapping( std::unique_ptr<NGOffsetMapping> offset_mapping) { + CheckIsNotDestroyed(); DCHECK(!IsLayoutNGObject()); DCHECK(offset_mapping); EnsureRareData().offset_mapping_ = std::move(offset_mapping);
diff --git a/third_party/blink/renderer/core/layout/layout_block_flow.h b/third_party/blink/renderer/core/layout/layout_block_flow.h index ebbcaff..4192f31c 100644 --- a/third_party/blink/renderer/core/layout/layout_block_flow.h +++ b/third_party/blink/renderer/core/layout/layout_block_flow.h
@@ -105,7 +105,10 @@ scoped_refptr<ComputedStyle>, LegacyLayout); - bool IsLayoutBlockFlow() const final { return true; } + bool IsLayoutBlockFlow() const final { + CheckIsNotDestroyed(); + return true; + } void UpdateBlockLayout(bool relayout_children) override; @@ -121,6 +124,7 @@ LayoutUnit position, IndentTextOrNot indent_text, LayoutUnit logical_height = LayoutUnit()) const { + CheckIsNotDestroyed(); return (LogicalRightOffsetForLine(position, indent_text, logical_height) - LogicalLeftOffsetForLine(position, indent_text, logical_height)) .ClampNegativeToZero(); @@ -129,6 +133,7 @@ LayoutUnit position, IndentTextOrNot indent_text, LayoutUnit logical_height = LayoutUnit()) const { + CheckIsNotDestroyed(); return LogicalRightOffsetForLine(position, LogicalRightOffsetForContent(), indent_text, logical_height); } @@ -136,6 +141,7 @@ LayoutUnit position, IndentTextOrNot indent_text, LayoutUnit logical_height = LayoutUnit()) const { + CheckIsNotDestroyed(); return LogicalLeftOffsetForLine(position, LogicalLeftOffsetForContent(), indent_text, logical_height); } @@ -143,6 +149,7 @@ LayoutUnit position, IndentTextOrNot indent_text, LayoutUnit logical_height = LayoutUnit()) const { + CheckIsNotDestroyed(); return StyleRef().IsLeftToRightDirection() ? LogicalLeftOffsetForLine(position, indent_text, logical_height) : LogicalWidth() - LogicalRightOffsetForLine( @@ -152,6 +159,7 @@ LayoutUnit AvailableLogicalWidthForAvoidingFloats( LayoutUnit position, LayoutUnit logical_height = LayoutUnit()) const { + CheckIsNotDestroyed(); return (LogicalRightOffsetForAvoidingFloats(position, logical_height) - LogicalLeftOffsetForAvoidingFloats(position, logical_height)) .ClampNegativeToZero(); @@ -159,18 +167,21 @@ LayoutUnit LogicalLeftOffsetForAvoidingFloats( LayoutUnit position, LayoutUnit logical_height = LayoutUnit()) const { + CheckIsNotDestroyed(); return LogicalLeftFloatOffsetForAvoidingFloats( position, LogicalLeftOffsetForContent(), logical_height); } LayoutUnit LogicalRightOffsetForAvoidingFloats( LayoutUnit position, LayoutUnit logical_height = LayoutUnit()) const { + CheckIsNotDestroyed(); return LogicalRightFloatOffsetForAvoidingFloats( position, LogicalRightOffsetForContent(), logical_height); } LayoutUnit StartOffsetForAvoidingFloats( LayoutUnit position, LayoutUnit logical_height = LayoutUnit()) const { + CheckIsNotDestroyed(); return StyleRef().IsLeftToRightDirection() ? LogicalLeftOffsetForAvoidingFloats(position, logical_height) : LogicalWidth() - LogicalRightOffsetForAvoidingFloats( @@ -179,20 +190,35 @@ LayoutUnit EndOffsetForAvoidingFloats( LayoutUnit position, LayoutUnit logical_height = LayoutUnit()) const { + CheckIsNotDestroyed(); return !StyleRef().IsLeftToRightDirection() ? LogicalLeftOffsetForAvoidingFloats(position, logical_height) : LogicalWidth() - LogicalRightOffsetForAvoidingFloats( position, logical_height); } - const LineBoxList& LineBoxes() const { return line_boxes_; } - LineBoxList* LineBoxes() { return &line_boxes_; } - InlineFlowBox* FirstLineBox() const { return line_boxes_.First(); } - InlineFlowBox* LastLineBox() const { return line_boxes_.Last(); } + const LineBoxList& LineBoxes() const { + CheckIsNotDestroyed(); + return line_boxes_; + } + LineBoxList* LineBoxes() { + CheckIsNotDestroyed(); + return &line_boxes_; + } + InlineFlowBox* FirstLineBox() const { + CheckIsNotDestroyed(); + return line_boxes_.First(); + } + InlineFlowBox* LastLineBox() const { + CheckIsNotDestroyed(); + return line_boxes_.Last(); + } RootInlineBox* FirstRootBox() const { + CheckIsNotDestroyed(); return static_cast<RootInlineBox*>(FirstLineBox()); } RootInlineBox* LastRootBox() const { + CheckIsNotDestroyed(); return static_cast<RootInlineBox*>(LastLineBox()); } @@ -215,6 +241,7 @@ void MarkSiblingsWithFloatsForLayout(LayoutBox* float_to_remove = nullptr); bool ContainsFloats() const { + CheckIsNotDestroyed(); return floating_objects_ && !floating_objects_->Set().IsEmpty(); } bool ContainsFloat(LayoutBox*) const; @@ -222,9 +249,11 @@ void RemoveFloatingObjects(); LayoutBoxModelObject* VirtualContinuation() const final { + CheckIsNotDestroyed(); return Continuation(); } bool IsAnonymousBlockContinuation() const { + CheckIsNotDestroyed(); return Continuation() && IsAnonymousBlock(); } @@ -246,29 +275,35 @@ bool GeneratesLineBoxesForInlineChild(LayoutObject*); LayoutUnit LogicalTopForFloat(const FloatingObject& floating_object) const { + CheckIsNotDestroyed(); return IsHorizontalWritingMode() ? floating_object.Y() : floating_object.X(); } LayoutUnit LogicalBottomForFloat( const FloatingObject& floating_object) const { + CheckIsNotDestroyed(); return IsHorizontalWritingMode() ? floating_object.MaxY() : floating_object.MaxX(); } LayoutUnit LogicalLeftForFloat(const FloatingObject& floating_object) const { + CheckIsNotDestroyed(); return IsHorizontalWritingMode() ? floating_object.X() : floating_object.Y(); } LayoutUnit LogicalRightForFloat(const FloatingObject& floating_object) const { + CheckIsNotDestroyed(); return IsHorizontalWritingMode() ? floating_object.MaxX() : floating_object.MaxY(); } LayoutUnit LogicalWidthForFloat(const FloatingObject& floating_object) const { + CheckIsNotDestroyed(); return IsHorizontalWritingMode() ? floating_object.Width() : floating_object.Height(); } void SetLogicalTopForFloat(FloatingObject& floating_object, LayoutUnit logical_top) { + CheckIsNotDestroyed(); if (IsHorizontalWritingMode()) floating_object.SetY(logical_top); else @@ -276,6 +311,7 @@ } void SetLogicalLeftForFloat(FloatingObject& floating_object, LayoutUnit logical_left) { + CheckIsNotDestroyed(); if (IsHorizontalWritingMode()) floating_object.SetX(logical_left); else @@ -283,6 +319,7 @@ } void SetLogicalHeightForFloat(FloatingObject& floating_object, LayoutUnit logical_height) { + CheckIsNotDestroyed(); if (IsHorizontalWritingMode()) floating_object.SetHeight(logical_height); else @@ -290,6 +327,7 @@ } void SetLogicalWidthForFloat(FloatingObject& floating_object, LayoutUnit logical_width) { + CheckIsNotDestroyed(); if (IsHorizontalWritingMode()) floating_object.SetWidth(logical_width); else @@ -310,9 +348,11 @@ } LayoutMultiColumnFlowThread* MultiColumnFlowThread() const { + CheckIsNotDestroyed(); return rare_data_ ? rare_data_->multi_column_flow_thread_ : nullptr; } void ResetMultiColumnFlowThread() { + CheckIsNotDestroyed(); if (rare_data_) rare_data_->multi_column_flow_thread_ = nullptr; } @@ -343,12 +383,14 @@ // between the content logical top of an object and its first child or line // (only *between* blocks or lines). LayoutUnit PaginationStrutPropagatedFromChild() const { + CheckIsNotDestroyed(); return rare_data_ ? rare_data_->pagination_strut_propagated_from_child_ : LayoutUnit(); } void SetPaginationStrutPropagatedFromChild(LayoutUnit); LayoutUnit FirstForcedBreakOffset() const { + CheckIsNotDestroyed(); if (!rare_data_) return LayoutUnit(); return rare_data_->first_forced_break_offset_; @@ -371,6 +413,7 @@ LayoutUnit XPositionForFloatIncludingMargin( const FloatingObject& child) const { + CheckIsNotDestroyed(); LayoutUnit scrollbar_adjustment(OriginAdjustmentForScrollbars().Width()); if (IsHorizontalWritingMode()) { return child.X() + child.GetLayoutObject()->MarginLeft() + @@ -382,6 +425,7 @@ DISABLE_CFI_PERF LayoutUnit YPositionForFloatIncludingMargin( const FloatingObject& child) const { + CheckIsNotDestroyed(); if (IsHorizontalWritingMode()) return child.Y() + MarginBeforeForChild(*child.GetLayoutObject()); @@ -391,7 +435,10 @@ LayoutPoint FlipFloatForWritingModeForChild(const FloatingObject&, const LayoutPoint&) const; - const char* GetName() const override { return "LayoutBlockFlow"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutBlockFlow"; + } FloatingObject* InsertFloatingObject(LayoutBox&); @@ -423,6 +470,7 @@ LayoutUnit NextFloatLogicalBottomBelowForBlock(LayoutUnit) const; FloatingObject* LastFloatFromPreviousLine() const { + CheckIsNotDestroyed(); return ContainsFloats() ? floating_objects_->Set().back().get() : nullptr; } @@ -440,16 +488,19 @@ LayoutUnit LowestFloatLogicalBottom(EClear = EClear::kBoth) const; bool HasOverhangingFloats() const { + CheckIsNotDestroyed(); return Parent() && ContainsFloats() && LowestFloatLogicalBottom() > LogicalHeight(); } bool IsOverhangingFloat(const FloatingObject& float_object) const { + CheckIsNotDestroyed(); return LogicalBottomForFloat(float_object) > LogicalHeight(); } LayoutUnit LogicalHeightWithVisibleOverflow() const final; void SetIsSelfCollapsingFromNG(bool is_self_collapsing) { + CheckIsNotDestroyed(); is_self_collapsing_ = is_self_collapsing; } @@ -459,12 +510,21 @@ void AddVisualOverflowFromFloats(const NGPhysicalContainerFragment& fragment); void AddLayoutOverflowFromFloats(); - virtual NGInlineNodeData* TakeNGInlineNodeData() { return nullptr; } - virtual NGInlineNodeData* GetNGInlineNodeData() const { return nullptr; } - virtual void ResetNGInlineNodeData() {} - virtual void ClearNGInlineNodeData() {} - virtual bool HasNGInlineNodeData() const { return false; } - virtual void WillCollectInlines() {} + virtual NGInlineNodeData* TakeNGInlineNodeData() { + CheckIsNotDestroyed(); + return nullptr; + } + virtual NGInlineNodeData* GetNGInlineNodeData() const { + CheckIsNotDestroyed(); + return nullptr; + } + virtual void ResetNGInlineNodeData() { CheckIsNotDestroyed(); } + virtual void ClearNGInlineNodeData() { CheckIsNotDestroyed(); } + virtual bool HasNGInlineNodeData() const { + CheckIsNotDestroyed(); + return false; + } + virtual void WillCollectInlines() { CheckIsNotDestroyed(); } virtual void SetPaintFragment(const NGBlockBreakToken*, scoped_refptr<const NGPhysicalFragment>); const NGFragmentItems* FragmentItems() const; @@ -502,6 +562,7 @@ LayoutUnit fixed_offset, IndentTextOrNot apply_text_indent, LayoutUnit logical_height = LayoutUnit()) const { + CheckIsNotDestroyed(); return AdjustLogicalRightOffsetForLine( LogicalRightFloatOffsetForLine(logical_top, fixed_offset, logical_height), @@ -512,6 +573,7 @@ LayoutUnit fixed_offset, IndentTextOrNot apply_text_indent, LayoutUnit logical_height = LayoutUnit()) const { + CheckIsNotDestroyed(); return AdjustLogicalLeftOffsetForLine( LogicalLeftFloatOffsetForLine(logical_top, fixed_offset, logical_height), @@ -625,6 +687,7 @@ void DirtyLinesFromChangedChild( LayoutObject* child, MarkingBehavior marking_behaviour = kMarkContainerChain) override { + CheckIsNotDestroyed(); line_boxes_.DirtyLinesFromChangedChild( LineLayoutItem(this), LineLayoutItem(child), marking_behaviour == kMarkContainerChain); @@ -659,16 +722,19 @@ unsigned expansion_opportunity_count); bool ShouldBreakAtLineToAvoidWidow() const { + CheckIsNotDestroyed(); return rare_data_ && rare_data_->line_break_to_avoid_widow_ >= 0; } void ClearShouldBreakAtLineToAvoidWidow() const; int LineBreakToAvoidWidow() const { + CheckIsNotDestroyed(); return rare_data_ ? rare_data_->line_break_to_avoid_widow_ : -1; } void SetBreakAtLineToAvoidWidow(int); void ClearDidBreakAtLineToAvoidWidow(); void SetDidBreakAtLineToAvoidWidow(); bool DidBreakAtLineToAvoidWidow() const { + CheckIsNotDestroyed(); return rare_data_ && rare_data_->did_break_at_line_to_avoid_widow_; } @@ -802,6 +868,7 @@ void SetOffsetMapping(std::unique_ptr<NGOffsetMapping>); const FloatingObjects* GetFloatingObjects() const { + CheckIsNotDestroyed(); return floating_objects_.get(); } @@ -817,21 +884,25 @@ protected: LayoutUnit MaxPositiveMarginBefore() const { + CheckIsNotDestroyed(); return rare_data_ ? rare_data_->margins_.PositiveMarginBefore() : LayoutBlockFlowRareData::PositiveMarginBeforeDefault(this); } LayoutUnit MaxNegativeMarginBefore() const { + CheckIsNotDestroyed(); return rare_data_ ? rare_data_->margins_.NegativeMarginBefore() : LayoutBlockFlowRareData::NegativeMarginBeforeDefault(this); } LayoutUnit MaxPositiveMarginAfter() const { + CheckIsNotDestroyed(); return rare_data_ ? rare_data_->margins_.PositiveMarginAfter() : LayoutBlockFlowRareData::PositiveMarginAfterDefault(this); } LayoutUnit MaxNegativeMarginAfter() const { + CheckIsNotDestroyed(); return rare_data_ ? rare_data_->margins_.NegativeMarginAfter() : LayoutBlockFlowRareData::NegativeMarginAfterDefault(this); @@ -841,6 +912,7 @@ void SetMaxMarginAfterValues(LayoutUnit pos, LayoutUnit neg); void InitMaxMarginValues() { + CheckIsNotDestroyed(); if (rare_data_) { rare_data_->margins_ = MarginValues( LayoutBlockFlowRareData::PositiveMarginBeforeDefault(this), @@ -854,9 +926,11 @@ private: LayoutUnit CollapsedMarginBefore() const final { + CheckIsNotDestroyed(); return MaxPositiveMarginBefore() - MaxNegativeMarginBefore(); } LayoutUnit CollapsedMarginAfter() const final { + CheckIsNotDestroyed(); return MaxPositiveMarginAfter() - MaxNegativeMarginAfter(); }
diff --git a/third_party/blink/renderer/core/layout/layout_block_flow_line.cc b/third_party/blink/renderer/core/layout/layout_block_flow_line.cc index 94fa554..5284d11 100644 --- a/third_party/blink/renderer/core/layout/layout_block_flow_line.cc +++ b/third_party/blink/renderer/core/layout/layout_block_flow_line.cc
@@ -181,6 +181,7 @@ InlineFlowBox* LayoutBlockFlow::CreateLineBoxes(LineLayoutItem line_layout_item, const LineInfo& line_info, InlineBox* child_box) { + CheckIsNotDestroyed(); // See if we have an unconstructed line box for this object that is also // the last item on the line. unsigned line_depth = 1; @@ -287,6 +288,7 @@ RootInlineBox* LayoutBlockFlow::ConstructLine(BidiRunList<BidiRun>& bidi_runs, const LineInfo& line_info) { + CheckIsNotDestroyed(); DCHECK(bidi_runs.FirstRun()); InlineFlowBox* parent_box = nullptr; @@ -366,6 +368,7 @@ ETextAlign LayoutBlockFlow::TextAlignmentForLine( bool ends_with_soft_break) const { + CheckIsNotDestroyed(); return StyleRef().GetTextAlign(!ends_with_soft_break); } @@ -474,6 +477,7 @@ LayoutRubyRun* layout_ruby_run, LayoutObject* previous_object, const LineInfo& line_info) { + CheckIsNotDestroyed(); int start_overhang; int end_overhang; LayoutObject* next_object = nullptr; @@ -661,6 +665,7 @@ LayoutUnit& total_logical_width, LayoutUnit& available_logical_width, unsigned expansion_opportunity_count) { + CheckIsNotDestroyed(); TextDirection direction; if (root_inline_box && root_inline_box->GetLineLayoutItem().StyleRef().GetUnicodeBidi() == @@ -729,6 +734,7 @@ } bool LayoutBlockFlow::CanContainFirstFormattedLine() const { + CheckIsNotDestroyed(); // The 'text-indent' only affects a line if it is the first formatted // line of an element. For example, the first line of an anonymous block // box is only affected if it is the first child of its parent element. @@ -761,6 +767,7 @@ GlyphOverflowAndFallbackFontsMap& text_box_data_map, VerticalPositionCache& vertical_position_cache, const WordMeasurements& word_measurements) { + CheckIsNotDestroyed(); bool is_first_line = line_info.IsFirstLine() && CanContainFirstFormattedLine(); bool is_after_hard_line_break = @@ -802,6 +809,7 @@ GlyphOverflowAndFallbackFontsMap& text_box_data_map, VerticalPositionCache& vertical_position_cache, const WordMeasurements& word_measurements) { + CheckIsNotDestroyed(); bool needs_word_spacing = true; LayoutUnit total_logical_width = line_box->GetFlowSpacingLogicalWidth(); bool is_after_expansion = true; @@ -880,6 +888,7 @@ BidiRun* first_run, GlyphOverflowAndFallbackFontsMap& text_box_data_map, VerticalPositionCache& vertical_position_cache) { + CheckIsNotDestroyed(); SetLogicalHeight(line_box->AlignBoxesInBlockDirection( LogicalHeight(), text_box_data_map, vertical_position_cache)); @@ -907,6 +916,7 @@ void LayoutBlockFlow::AppendFloatingObjectToLastLine( FloatingObject& floating_object) { + CheckIsNotDestroyed(); DCHECK(!floating_object.OriginatingLine()); floating_object.SetOriginatingLine(LastRootBox()); LastRootBox()->AppendFloat(floating_object.GetLayoutObject()); @@ -922,6 +932,7 @@ VerticalPositionCache& vertical_position_cache, BidiRun* trailing_space_run, const WordMeasurements& word_measurements) { + CheckIsNotDestroyed(); if (!bidi_runs.RunCount()) return nullptr; @@ -983,6 +994,7 @@ } void LayoutBlockFlow::LayoutRunsAndFloats(LineLayoutState& layout_state) { + CheckIsNotDestroyed(); // We want to skip ahead to the first dirty line InlineBidiResolver resolver; RootInlineBox* start_line = DetermineStartPosition(layout_state, resolver); @@ -1016,6 +1028,7 @@ FloatingObject* last_float_from_previous_line, InlineBidiResolver& resolver, const InlineIterator& old_end) { + CheckIsNotDestroyed(); RemoveFloatingObjectsBelow(last_float_from_previous_line, old_logical_height); SetLogicalHeight(new_logical_height); resolver.SetPositionIgnoringNestedIsolates(old_end); @@ -1027,6 +1040,7 @@ const InlineIterator& clean_line_start, const InlineBidiResolver& resolver, const BidiStatus& clean_line_bidi_status) { + CheckIsNotDestroyed(); const FloatingObjectSet& floating_object_set = floating_objects_->Set(); FloatingObjectSetIterator it = floating_object_set.begin(); FloatingObjectSetIterator end = floating_object_set.end(); @@ -1075,6 +1089,7 @@ InlineBidiResolver& resolver, const InlineIterator& clean_line_start, const BidiStatus& clean_line_bidi_status) { + CheckIsNotDestroyed(); const ComputedStyle& style_to_use = StyleRef(); bool paginated = View()->GetLayoutState() && View()->GetLayoutState()->IsPaginated(); @@ -1387,6 +1402,7 @@ } void LayoutBlockFlow::LinkToEndLineIfNeeded(LineLayoutState& layout_state) { + CheckIsNotDestroyed(); if (layout_state.EndLine()) { if (layout_state.EndLineMatched()) { bool recalculate_struts = @@ -1432,6 +1448,7 @@ void LayoutBlockFlow::MarkDirtyFloatsForPaintInvalidation( Vector<FloatWithRect>& floats) { + CheckIsNotDestroyed(); size_t float_count = floats.size(); // Floats that did not have layout did not paint invalidations when we laid // them out. They would have painted by now if they had moved, but if they @@ -1614,6 +1631,7 @@ void LayoutBlockFlow::ComputeInlinePreferredLogicalWidths( LayoutUnit& min_logical_width, LayoutUnit& max_logical_width) { + CheckIsNotDestroyed(); LayoutUnit inline_max; LayoutUnit inline_min; @@ -1940,6 +1958,7 @@ } bool LayoutBlockFlow::ShouldTruncateOverflowingText() const { + CheckIsNotDestroyed(); const LayoutObject* object_to_check = this; if (IsAnonymousBlock()) { const LayoutObject* parent = Parent(); @@ -1954,6 +1973,7 @@ DISABLE_CFI_PERF void LayoutBlockFlow::LayoutInlineChildren(bool relayout_children, LayoutUnit after_edge) { + CheckIsNotDestroyed(); // Figure out if we should clear out our line boxes. // FIXME: Handle resize eventually! bool is_full_layout = @@ -2100,6 +2120,7 @@ RootInlineBox* LayoutBlockFlow::DetermineStartPosition( LineLayoutState& layout_state, InlineBidiResolver& resolver) { + CheckIsNotDestroyed(); RootInlineBox* curr = nullptr; RootInlineBox* last = nullptr; RootInlineBox* first_line_box_with_break_and_clearance = nullptr; @@ -2228,6 +2249,7 @@ } bool LayoutBlockFlow::LineBoxHasBRWithClearance(RootInlineBox* curr) { + CheckIsNotDestroyed(); // If the linebox breaks cleanly and with clearance then dirty from at least // this point onwards so that we can clear the correct floats without // difficulty. @@ -2244,6 +2266,7 @@ RootInlineBox* start_line, InlineIterator& clean_line_start, BidiStatus& clean_line_bidi_status) { + CheckIsNotDestroyed(); DCHECK(!layout_state.EndLine()); RootInlineBox* last = nullptr; bool previous_was_clean = false; @@ -2289,6 +2312,7 @@ bool LayoutBlockFlow::CheckPaginationAndFloatsAtEndLine( LineLayoutState& layout_state) { + CheckIsNotDestroyed(); if (!floating_objects_ || !layout_state.EndLine()) return true; @@ -2340,6 +2364,7 @@ const InlineBidiResolver& resolver, const InlineIterator& end_line_start, const BidiStatus& end_line_status) { + CheckIsNotDestroyed(); if (resolver.GetPosition() == end_line_start) { if (resolver.Status() != end_line_status) return false; @@ -2380,6 +2405,7 @@ bool LayoutBlockFlow::GeneratesLineBoxesForInlineChild(LayoutObject* inline_obj) { + CheckIsNotDestroyed(); DCHECK_EQ(inline_obj->Parent(), this); InlineIterator it(LineLayoutBlockFlow(this), LineLayoutItem(inline_obj), 0); @@ -2391,6 +2417,7 @@ } void LayoutBlockFlow::AddVisualOverflowFromInlineChildren() { + CheckIsNotDestroyed(); DCHECK(!NeedsLayout()); DCHECK(!ChildPrePaintBlockedByDisplayLock()); @@ -2456,6 +2483,7 @@ } void LayoutBlockFlow::AddLayoutOverflowFromInlineChildren() { + CheckIsNotDestroyed(); DCHECK(!ChildLayoutBlockedByDisplayLock()); LayoutUnit end_padding = @@ -2502,6 +2530,7 @@ } void LayoutBlockFlow::DeleteEllipsisLineBoxes() { + CheckIsNotDestroyed(); ETextAlign text_align = StyleRef().GetTextAlign(); IndentTextOrNot indent_text = kIndentText; for (RootInlineBox* curr = FirstRootBox(); curr; curr = curr->NextRootBox()) { @@ -2528,6 +2557,7 @@ } void LayoutBlockFlow::ClearTruncationOnAtomicInlines(RootInlineBox* root) { + CheckIsNotDestroyed(); bool ltr = StyleRef().IsLeftToRightDirection(); InlineBox* first_child = ltr ? root->LastChild() : root->FirstChild(); for (InlineBox* box = first_child; box; @@ -2544,6 +2574,7 @@ } void LayoutBlockFlow::CheckLinesForTextOverflow() { + CheckIsNotDestroyed(); // Determine the width of the ellipsis using the current font. const Font& font = StyleRef().GetFont(); @@ -2652,6 +2683,7 @@ LayoutUnit ellipsis_width, const AtomicString& selected_ellipsis_str, InlineBox* box_truncation_starts_at) { + CheckIsNotDestroyed(); bool found_box = box_truncation_starts_at ? true : false; bool ltr = StyleRef().IsLeftToRightDirection(); LayoutUnit logical_left_offset = block_left_edge; @@ -2730,6 +2762,7 @@ void LayoutBlockFlow::MarkLinesDirtyInBlockRange(LayoutUnit logical_top, LayoutUnit logical_bottom, RootInlineBox* highest) { + CheckIsNotDestroyed(); if (logical_top >= logical_bottom) return; @@ -2753,6 +2786,7 @@ LayoutUnit LayoutBlockFlow::StartAlignedOffsetForLine( LayoutUnit position, IndentTextOrNot indent_text) { + CheckIsNotDestroyed(); ETextAlign text_align = StyleRef().GetTextAlign(); bool apply_indent_text; @@ -2793,6 +2827,7 @@ } void LayoutBlockFlow::SetShouldDoFullPaintInvalidationForFirstLine() { + CheckIsNotDestroyed(); DCHECK(ChildrenInline()); if (const NGPaintFragment* paint_fragment = PaintFragment()) {
diff --git a/third_party/blink/renderer/core/layout/layout_box.cc b/third_party/blink/renderer/core/layout/layout_box.cc index 8d973c0..72192f4 100644 --- a/third_party/blink/renderer/core/layout/layout_box.cc +++ b/third_party/blink/renderer/core/layout/layout_box.cc
@@ -291,6 +291,7 @@ LayoutBox::~LayoutBox() = default; PaintLayerType LayoutBox::LayerTypeRequired() const { + CheckIsNotDestroyed(); if (IsStacked() || HasHiddenBackface() || (StyleRef().SpecifiesColumns() && !CanTraversePhysicalFragments()) || IsEffectiveRootScroller()) @@ -306,6 +307,7 @@ } void LayoutBox::WillBeDestroyed() { + CheckIsNotDestroyed(); ClearOverrideSize(); ClearOverrideContainingBlockContentSize(); ClearOverridePercentageResolutionBlockSize(); @@ -337,6 +339,7 @@ } void LayoutBox::InsertedIntoTree() { + CheckIsNotDestroyed(); LayoutBoxModelObject::InsertedIntoTree(); AddScrollSnapMapping(); AddCustomLayoutChildIfNeeded(); @@ -346,6 +349,7 @@ } void LayoutBox::WillBeRemovedFromTree() { + CheckIsNotDestroyed(); if (!DocumentBeingDestroyed() && IsOrthogonalWritingModeRoot()) UnmarkOrthogonalWritingModeRoot(); @@ -355,6 +359,7 @@ } void LayoutBox::RemoveFloatingOrPositionedChildFromBlockLists() { + CheckIsNotDestroyed(); DCHECK(IsFloatingOrOutOfFlowPositioned()); if (DocumentBeingDestroyed()) @@ -382,6 +387,7 @@ void LayoutBox::StyleWillChange(StyleDifference diff, const ComputedStyle& new_style) { + CheckIsNotDestroyed(); const ComputedStyle* old_style = Style(); if (old_style) { LayoutFlowThread* flow_thread = FlowThreadContainingBlock(); @@ -441,6 +447,7 @@ void LayoutBox::StyleDidChange(StyleDifference diff, const ComputedStyle* old_style) { + CheckIsNotDestroyed(); // Horizontal writing mode definition is updated in LayoutBoxModelObject:: // updateFromStyle, (as part of the LayoutBoxModelObject::styleDidChange call // below). So, we can safely cache the horizontal writing mode value before @@ -560,6 +567,7 @@ } void LayoutBox::UpdateBackgroundAttachmentFixedStatusAfterStyleChange() { + CheckIsNotDestroyed(); if (!GetFrameView()) return; @@ -571,6 +579,7 @@ void LayoutBox::UpdateShapeOutsideInfoAfterStyleChange( const ComputedStyle& style, const ComputedStyle* old_style) { + CheckIsNotDestroyed(); const ShapeValue* shape_outside = style.ShapeOutside(); const ShapeValue* old_shape_outside = old_style ? old_style->ShapeOutside() @@ -603,6 +612,7 @@ void LayoutBox::UpdateGridPositionAfterStyleChange( const ComputedStyle* old_style) { + CheckIsNotDestroyed(); if (!old_style || !Parent() || !Parent()->IsLayoutGrid()) return; @@ -627,6 +637,7 @@ void LayoutBox::UpdateScrollSnapMappingAfterStyleChange( const ComputedStyle& old_style) { + CheckIsNotDestroyed(); DCHECK(Style()); SnapCoordinator& snap_coordinator = GetDocument().GetSnapCoordinator(); // scroll-snap-type and scroll-padding invalidate the snap container. @@ -654,16 +665,19 @@ } void LayoutBox::AddScrollSnapMapping() { + CheckIsNotDestroyed(); SnapCoordinator& snap_coordinator = GetDocument().GetSnapCoordinator(); snap_coordinator.SnapAreaDidChange(*this, Style()->GetScrollSnapAlign()); } void LayoutBox::ClearScrollSnapMapping() { + CheckIsNotDestroyed(); SnapCoordinator& snap_coordinator = GetDocument().GetSnapCoordinator(); snap_coordinator.SnapAreaDidChange(*this, cc::ScrollSnapAlign()); } void LayoutBox::UpdateFromStyle() { + CheckIsNotDestroyed(); LayoutBoxModelObject::UpdateFromStyle(); const ComputedStyle& style_to_use = StyleRef(); @@ -676,6 +690,7 @@ } void LayoutBox::LayoutSubtreeRoot() { + CheckIsNotDestroyed(); if (RuntimeEnabledFeatures::LayoutNGEnabled() && !NGBlockNode::CanUseNewLayout(*this) && GetCachedLayoutResult()) { // If this object is laid out by the legacy engine, while its containing @@ -725,6 +740,7 @@ } void LayoutBox::UpdateLayout() { + CheckIsNotDestroyed(); DCHECK(NeedsLayout()); LayoutAnalyzer::Scope analyzer(*this); @@ -752,6 +768,7 @@ // border and scrollbar. DISABLE_CFI_PERF LayoutUnit LayoutBox::ClientWidth() const { + CheckIsNotDestroyed(); // We need to clamp negative values. This function may be called during layout // before frame_rect_ gets the final proper value. Another reason: While // border side values are currently limited to 2^20px (a recent change in the @@ -769,6 +786,7 @@ DISABLE_CFI_PERF LayoutUnit LayoutBox::ClientHeight() const { + CheckIsNotDestroyed(); // We need to clamp negative values. This function can be called during layout // before frame_rect_ gets the final proper value. The scrollbar may be wider // than the padding box. Another reason: While border side values are @@ -786,15 +804,18 @@ } int LayoutBox::PixelSnappedClientWidth() const { + CheckIsNotDestroyed(); return SnapSizeToPixel(ClientWidth(), Location().X() + ClientLeft()); } DISABLE_CFI_PERF int LayoutBox::PixelSnappedClientHeight() const { + CheckIsNotDestroyed(); return SnapSizeToPixel(ClientHeight(), Location().Y() + ClientTop()); } int LayoutBox::PixelSnappedClientWidthWithTableSpecialBehavior() const { + CheckIsNotDestroyed(); // clientWidth/Height is the visual portion of the box content, not including // borders or scroll bars, but includes padding. And per // https://www.w3.org/TR/CSS2/tables.html#model, @@ -813,6 +834,7 @@ DISABLE_CFI_PERF int LayoutBox::PixelSnappedClientHeightWithTableSpecialBehavior() const { + CheckIsNotDestroyed(); // clientWidth/Height is the visual portion of the box content, not including // borders or scroll bars, but includes padding. And per // https://www.w3.org/TR/CSS2/tables.html#model, @@ -830,14 +852,17 @@ } int LayoutBox::PixelSnappedOffsetWidth(const Element*) const { + CheckIsNotDestroyed(); return SnapSizeToPixel(OffsetWidth(), Location().X() + ClientLeft()); } int LayoutBox::PixelSnappedOffsetHeight(const Element*) const { + CheckIsNotDestroyed(); return SnapSizeToPixel(OffsetHeight(), Location().Y() + ClientTop()); } LayoutUnit LayoutBox::ScrollWidth() const { + CheckIsNotDestroyed(); if (IsScrollContainer() || StyleRef().ScrollbarGutterIsForce()) return GetScrollableArea()->ScrollWidth(); // For objects with visible overflow, this matches IE. @@ -849,6 +874,7 @@ } LayoutUnit LayoutBox::ScrollHeight() const { + CheckIsNotDestroyed(); if (IsScrollContainer() || StyleRef().ScrollbarGutterIsForce()) return GetScrollableArea()->ScrollHeight(); // For objects with visible overflow, this matches IE. @@ -857,10 +883,12 @@ } int LayoutBox::PixelSnappedScrollWidth() const { + CheckIsNotDestroyed(); return SnapSizeToPixel(ScrollWidth(), Location().X() + ClientLeft()); } int LayoutBox::PixelSnappedScrollHeight() const { + CheckIsNotDestroyed(); if (IsScrollContainer()) return SnapSizeToPixel(GetScrollableArea()->ScrollHeight(), Location().Y() + ClientTop()); @@ -872,6 +900,7 @@ PhysicalRect LayoutBox::ScrollRectToVisibleRecursive( const PhysicalRect& absolute_rect, mojom::blink::ScrollIntoViewParamsPtr params) { + CheckIsNotDestroyed(); DCHECK(params->type == mojom::blink::ScrollType::kProgrammatic || params->type == mojom::blink::ScrollType::kUser); @@ -951,6 +980,7 @@ } void LayoutBox::SetMargin(const NGPhysicalBoxStrut& box) { + CheckIsNotDestroyed(); margin_box_outsets_.SetTop(box.top); margin_box_outsets_.SetRight(box.right); margin_box_outsets_.SetBottom(box.bottom); @@ -959,6 +989,7 @@ void LayoutBox::AbsoluteQuads(Vector<FloatQuad>& quads, MapCoordinatesFlags mode) const { + CheckIsNotDestroyed(); if (LayoutFlowThread* flow_thread = FlowThreadContainingBlock()) { flow_thread->AbsoluteQuadsForDescendant(*this, quads, mode); return; @@ -967,11 +998,13 @@ } FloatRect LayoutBox::LocalBoundingBoxRectForAccessibility() const { + CheckIsNotDestroyed(); return FloatRect(0, 0, frame_rect_.Width().ToFloat(), frame_rect_.Height().ToFloat()); } void LayoutBox::UpdateAfterLayout() { + CheckIsNotDestroyed(); // Transform-origin depends on box size, so we need to update the layer // transform after layout. if (HasLayer()) { @@ -997,6 +1030,7 @@ } bool LayoutBox::HasOverrideIntrinsicContentWidth() const { + CheckIsNotDestroyed(); if (!ShouldApplySizeContainment()) return false; @@ -1005,6 +1039,7 @@ } bool LayoutBox::HasOverrideIntrinsicContentHeight() const { + CheckIsNotDestroyed(); if (!ShouldApplySizeContainment()) return false; @@ -1013,6 +1048,7 @@ } LayoutUnit LayoutBox::OverrideIntrinsicContentWidth() const { + CheckIsNotDestroyed(); DCHECK(HasOverrideIntrinsicContentWidth()); const auto& style = StyleRef(); const Length& intrinsic_length = style.ContainIntrinsicSize().Width(); @@ -1023,6 +1059,7 @@ } LayoutUnit LayoutBox::OverrideIntrinsicContentHeight() const { + CheckIsNotDestroyed(); DCHECK(HasOverrideIntrinsicContentHeight()); const auto& style = StyleRef(); const Length& intrinsic_length = style.ContainIntrinsicSize().Height(); @@ -1033,6 +1070,7 @@ } LayoutUnit LayoutBox::DefaultIntrinsicContentInlineSize() const { + CheckIsNotDestroyed(); // If the intrinsic-inline-size is specified, then we shouldn't ever need to // get here. DCHECK(!HasOverrideIntrinsicContentLogicalWidth()); @@ -1060,6 +1098,7 @@ } LayoutUnit LayoutBox::DefaultIntrinsicContentBlockSize() const { + CheckIsNotDestroyed(); // If the intrinsic-block-size is specified, then we shouldn't ever need to // get here. DCHECK(!HasOverrideIntrinsicContentLogicalHeight()); @@ -1076,6 +1115,7 @@ } LayoutUnit LayoutBox::LogicalHeightWithVisibleOverflow() const { + CheckIsNotDestroyed(); if (!LayoutOverflowIsSet() || IsScrollContainer() || StyleRef().OverflowY() == EOverflow::kClip) return LogicalHeight(); @@ -1089,6 +1129,7 @@ LayoutUnit logical_width, LayoutUnit available_width, const LayoutBlock* cb) const { + CheckIsNotDestroyed(); const ComputedStyle& style_to_use = StyleRef(); // This implements the transferred min/max sizes per @@ -1122,6 +1163,7 @@ LayoutUnit LayoutBox::ConstrainLogicalHeightByMinMax( LayoutUnit logical_height, LayoutUnit intrinsic_content_height) const { + CheckIsNotDestroyed(); // Note that the values 'min-content', 'max-content' and 'fit-content' should // behave as the initial value if specified in the block direction. const Length& logical_max_height = StyleRef().LogicalMaxHeight(); @@ -1152,6 +1194,7 @@ LayoutUnit LayoutBox::ConstrainContentBoxLogicalHeightByMinMax( LayoutUnit logical_height, LayoutUnit intrinsic_content_height) const { + CheckIsNotDestroyed(); // If the min/max height and logical height are both percentages we take // advantage of already knowing the current resolved percentage height // to avoid recursing up through our containing blocks again to determine it. @@ -1191,6 +1234,7 @@ void LayoutBox::SetLocationAndUpdateOverflowControlsIfNeeded( const LayoutPoint& location) { + CheckIsNotDestroyed(); if (!HasLayer()) { SetLocation(location); return; @@ -1216,12 +1260,14 @@ } FloatQuad LayoutBox::AbsoluteContentQuad(MapCoordinatesFlags flags) const { + CheckIsNotDestroyed(); PhysicalRect rect = PhysicalContentBoxRect(); return LocalRectToAbsoluteQuad(rect, flags); } PhysicalRect LayoutBox::PhysicalBackgroundRect( BackgroundRectType rect_type) const { + CheckIsNotDestroyed(); // If the background transfers to view, the used background of this object // is transparent. if (rect_type == kBackgroundKnownOpaqueRect && BackgroundTransfersToView()) @@ -1295,10 +1341,12 @@ void LayoutBox::AddOutlineRects(Vector<PhysicalRect>& rects, const PhysicalOffset& additional_offset, NGOutlineType) const { + CheckIsNotDestroyed(); rects.emplace_back(additional_offset, Size()); } bool LayoutBox::CanResize() const { + CheckIsNotDestroyed(); // We need a special case for <iframe> because they never have // hasOverflowClip(). However, they do "implicitly" clip their contents, so // we want to allow resizing them also. @@ -1306,6 +1354,7 @@ } MinMaxSizes LayoutBox::ComputeMinMaxLogicalWidthFromAspectRatio() const { + CheckIsNotDestroyed(); DCHECK(StyleRef().LogicalAspectRatio()); // The spec requires us to clamp these by the specified size (it calls it the @@ -1344,6 +1393,7 @@ } bool LayoutBox::HasScrollbarGutters(ScrollbarOrientation orientation) const { + CheckIsNotDestroyed(); if (StyleRef().ScrollbarGutterIsAuto()) return false; @@ -1371,6 +1421,7 @@ NGPhysicalBoxStrut LayoutBox::ComputeScrollbarsInternal( ShouldClampToContentBox clamp_to_content_box, OverlayScrollbarClipBehavior overlay_scrollbar_clip_behavior) const { + CheckIsNotDestroyed(); NGPhysicalBoxStrut scrollbars; PaintLayerScrollableArea* scrollable_area = GetScrollableArea(); if (!scrollable_area) @@ -1424,12 +1475,14 @@ } bool LayoutBox::CanBeScrolledAndHasScrollableArea() const { + CheckIsNotDestroyed(); return CanBeProgramaticallyScrolled() && (PixelSnappedScrollHeight() != PixelSnappedClientHeight() || PixelSnappedScrollWidth() != PixelSnappedClientWidth()); } bool LayoutBox::CanBeProgramaticallyScrolled() const { + CheckIsNotDestroyed(); Node* node = GetNode(); if (node && node->IsDocumentNode()) return true; @@ -1446,6 +1499,7 @@ } void LayoutBox::Autoscroll(const PhysicalOffset& position_in_root_frame) { + CheckIsNotDestroyed(); LocalFrame* frame = GetFrame(); if (!frame) return; @@ -1465,6 +1519,7 @@ } bool LayoutBox::CanAutoscroll() const { + CheckIsNotDestroyed(); // TODO(skobes): Remove one of these methods. return CanBeScrolledAndHasScrollableArea(); } @@ -1474,6 +1529,7 @@ // direction of scrolling. PhysicalOffset LayoutBox::CalculateAutoscrollDirection( const FloatPoint& point_in_root_frame) const { + CheckIsNotDestroyed(); if (!GetFrame()) return PhysicalOffset(); @@ -1532,6 +1588,7 @@ } void LayoutBox::ScrollByRecursively(const ScrollOffset& delta) { + CheckIsNotDestroyed(); if (delta.IsZero() || !IsScrollContainer()) return; @@ -1562,11 +1619,13 @@ } bool LayoutBox::NeedsPreferredWidthsRecalculation() const { + CheckIsNotDestroyed(); return StyleRef().PaddingStart().IsPercentOrCalc() || StyleRef().PaddingEnd().IsPercentOrCalc(); } IntSize LayoutBox::OriginAdjustmentForScrollbars() const { + CheckIsNotDestroyed(); if (CanSkipComputeScrollbars()) { return IntSize(); } else { @@ -1577,22 +1636,26 @@ } IntPoint LayoutBox::ScrollOrigin() const { + CheckIsNotDestroyed(); return GetScrollableArea() ? GetScrollableArea()->ScrollOrigin() : IntPoint(); } LayoutSize LayoutBox::ScrolledContentOffset() const { + CheckIsNotDestroyed(); DCHECK(IsScrollContainer()); DCHECK(GetScrollableArea()); return LayoutSize(GetScrollableArea()->GetScrollOffset()); } LayoutSize LayoutBox::PixelSnappedScrolledContentOffset() const { + CheckIsNotDestroyed(); DCHECK(IsScrollContainer()); DCHECK(GetScrollableArea()); return LayoutSize(GetScrollableArea()->ScrollOffsetInt()); } PhysicalRect LayoutBox::ClippingRect(const PhysicalOffset& location) const { + CheckIsNotDestroyed(); PhysicalRect result(PhysicalRect::InfiniteIntRect()); if (ShouldClipOverflow()) result = OverflowClipRect(location); @@ -1609,6 +1672,7 @@ const LayoutObject* ancestor, VisualRectFlags visual_rect_flags, TransformState& transform_state) const { + CheckIsNotDestroyed(); bool container_preserve_3d = container_object->StyleRef().Preserves3D(); TransformState::TransformAccumulation accumulation = @@ -1708,6 +1772,7 @@ TransformState::TransformAccumulation accumulation, const LayoutObject& contents, VisualRectFlags visual_rect_flags) const { + CheckIsNotDestroyed(); if (!HasClipRelatedProperty()) return true; @@ -1718,6 +1783,7 @@ } bool LayoutBox::ContainedContentsScroll(const LayoutObject& contents) const { + CheckIsNotDestroyed(); if (IsA<LayoutView>(this) && contents.StyleRef().GetPosition() == EPosition::kFixed) { return false; @@ -1729,6 +1795,7 @@ TransformState& transform_state, TransformState::TransformAccumulation accumulation, VisualRectFlags visual_rect_flags) const { + CheckIsNotDestroyed(); // This won't work fully correctly for fixed-position elements, who should // receive CSS clip but for whom the current object is not in the containing // block chain. @@ -1749,11 +1816,13 @@ } MinMaxSizes LayoutBox::PreferredLogicalWidths() const { + CheckIsNotDestroyed(); NOTREACHED(); return MinMaxSizes(); } MinMaxSizes LayoutBox::IntrinsicLogicalWidths(MinMaxSizesType type) const { + CheckIsNotDestroyed(); if (type == MinMaxSizesType::kContent && StyleRef().AspectRatio()) { MinMaxSizes sizes; if (ComputeLogicalWidthFromAspectRatio(&sizes.min_size)) { @@ -1766,6 +1835,7 @@ } void LayoutBox::UpdateCachedIntrinsicLogicalWidthsIfNeeded() { + CheckIsNotDestroyed(); if (!IntrinsicLogicalWidthsDirty()) return; @@ -1780,6 +1850,7 @@ } LayoutUnit LayoutBox::OverrideLogicalWidth() const { + CheckIsNotDestroyed(); DCHECK(HasOverrideLogicalWidth()); if (extra_input_ && extra_input_->override_inline_size) return *extra_input_->override_inline_size; @@ -1787,6 +1858,7 @@ } LayoutUnit LayoutBox::OverrideLogicalHeight() const { + CheckIsNotDestroyed(); DCHECK(HasOverrideLogicalHeight()); if (extra_input_ && extra_input_->override_block_size) return *extra_input_->override_block_size; @@ -1794,63 +1866,74 @@ } bool LayoutBox::IsOverrideLogicalHeightDefinite() const { + CheckIsNotDestroyed(); return extra_input_ && extra_input_->is_override_block_size_definite; } bool LayoutBox::HasOverrideLogicalHeight() const { + CheckIsNotDestroyed(); if (extra_input_ && extra_input_->override_block_size) return true; return rare_data_ && rare_data_->override_logical_height_ != -1; } bool LayoutBox::HasOverrideLogicalWidth() const { + CheckIsNotDestroyed(); if (extra_input_ && extra_input_->override_inline_size) return true; return rare_data_ && rare_data_->override_logical_width_ != -1; } void LayoutBox::SetOverrideLogicalHeight(LayoutUnit height) { + CheckIsNotDestroyed(); DCHECK(!extra_input_); DCHECK_GE(height, 0); EnsureRareData().override_logical_height_ = height; } void LayoutBox::SetOverrideLogicalWidth(LayoutUnit width) { + CheckIsNotDestroyed(); DCHECK(!extra_input_); DCHECK_GE(width, 0); EnsureRareData().override_logical_width_ = width; } void LayoutBox::ClearOverrideLogicalHeight() { + CheckIsNotDestroyed(); DCHECK(!extra_input_); if (rare_data_) rare_data_->override_logical_height_ = LayoutUnit(-1); } void LayoutBox::ClearOverrideLogicalWidth() { + CheckIsNotDestroyed(); DCHECK(!extra_input_); if (rare_data_) rare_data_->override_logical_width_ = LayoutUnit(-1); } void LayoutBox::ClearOverrideSize() { + CheckIsNotDestroyed(); ClearOverrideLogicalHeight(); ClearOverrideLogicalWidth(); } LayoutUnit LayoutBox::OverrideContentLogicalWidth() const { + CheckIsNotDestroyed(); return (OverrideLogicalWidth() - BorderAndPaddingLogicalWidth() - ComputeLogicalScrollbars().InlineSum()) .ClampNegativeToZero(); } LayoutUnit LayoutBox::OverrideContentLogicalHeight() const { + CheckIsNotDestroyed(); return (OverrideLogicalHeight() - BorderAndPaddingLogicalHeight() - ComputeLogicalScrollbars().BlockSum()) .ClampNegativeToZero(); } LayoutUnit LayoutBox::OverrideContainingBlockContentWidth() const { + CheckIsNotDestroyed(); DCHECK(HasOverrideContainingBlockContentWidth()); return ContainingBlock()->StyleRef().IsHorizontalWritingMode() ? OverrideContainingBlockContentLogicalWidth() @@ -1858,6 +1941,7 @@ } LayoutUnit LayoutBox::OverrideContainingBlockContentHeight() const { + CheckIsNotDestroyed(); DCHECK(HasOverrideContainingBlockContentHeight()); return ContainingBlock()->StyleRef().IsHorizontalWritingMode() ? OverrideContainingBlockContentLogicalHeight() @@ -1865,6 +1949,7 @@ } bool LayoutBox::HasOverrideContainingBlockContentWidth() const { + CheckIsNotDestroyed(); if (!ContainingBlock()) return false; @@ -1874,6 +1959,7 @@ } bool LayoutBox::HasOverrideContainingBlockContentHeight() const { + CheckIsNotDestroyed(); if (!ContainingBlock()) return false; @@ -1885,6 +1971,7 @@ // TODO (lajava) Shouldn't we implement these functions based on physical // direction ?. LayoutUnit LayoutBox::OverrideContainingBlockContentLogicalWidth() const { + CheckIsNotDestroyed(); DCHECK(HasOverrideContainingBlockContentLogicalWidth()); if (extra_input_) return extra_input_->containing_block_content_inline_size; @@ -1894,6 +1981,7 @@ // TODO (lajava) Shouldn't we implement these functions based on physical // direction ?. LayoutUnit LayoutBox::OverrideContainingBlockContentLogicalHeight() const { + CheckIsNotDestroyed(); DCHECK(HasOverrideContainingBlockContentLogicalHeight()); if (extra_input_) return extra_input_->containing_block_content_block_size; @@ -1903,6 +1991,7 @@ // TODO (lajava) Shouldn't we implement these functions based on physical // direction ?. bool LayoutBox::HasOverrideContainingBlockContentLogicalWidth() const { + CheckIsNotDestroyed(); if (extra_input_) return true; return rare_data_ && @@ -1912,6 +2001,7 @@ // TODO (lajava) Shouldn't we implement these functions based on physical // direction ?. bool LayoutBox::HasOverrideContainingBlockContentLogicalHeight() const { + CheckIsNotDestroyed(); if (extra_input_) return true; return rare_data_ && @@ -1922,6 +2012,7 @@ // direction ?. void LayoutBox::SetOverrideContainingBlockContentLogicalWidth( LayoutUnit logical_width) { + CheckIsNotDestroyed(); DCHECK(!extra_input_); DCHECK_GE(logical_width, LayoutUnit(-1)); EnsureRareData().override_containing_block_content_logical_width_ = @@ -1933,6 +2024,7 @@ // direction ?. void LayoutBox::SetOverrideContainingBlockContentLogicalHeight( LayoutUnit logical_height) { + CheckIsNotDestroyed(); DCHECK(!extra_input_); DCHECK_GE(logical_height, LayoutUnit(-1)); EnsureRareData().override_containing_block_content_logical_height_ = @@ -1943,6 +2035,7 @@ // TODO (lajava) Shouldn't we implement these functions based on physical // direction ?. void LayoutBox::ClearOverrideContainingBlockContentSize() { + CheckIsNotDestroyed(); DCHECK(!extra_input_); if (!rare_data_) return; @@ -1952,17 +2045,20 @@ } LayoutUnit LayoutBox::OverridePercentageResolutionBlockSize() const { + CheckIsNotDestroyed(); DCHECK(HasOverridePercentageResolutionBlockSize()); return rare_data_->override_percentage_resolution_block_size_; } bool LayoutBox::HasOverridePercentageResolutionBlockSize() const { + CheckIsNotDestroyed(); return rare_data_ && rare_data_->has_override_percentage_resolution_block_size_; } void LayoutBox::SetOverridePercentageResolutionBlockSize( LayoutUnit logical_height) { + CheckIsNotDestroyed(); DCHECK_GE(logical_height, LayoutUnit(-1)); auto& rare_data = EnsureRareData(); rare_data.override_percentage_resolution_block_size_ = logical_height; @@ -1970,12 +2066,14 @@ } void LayoutBox::ClearOverridePercentageResolutionBlockSize() { + CheckIsNotDestroyed(); if (!rare_data_) return; EnsureRareData().has_override_percentage_resolution_block_size_ = false; } LayoutUnit LayoutBox::OverrideAvailableInlineSize() const { + CheckIsNotDestroyed(); DCHECK(HasOverrideAvailableInlineSize()); if (extra_input_) return extra_input_->available_inline_size; @@ -1984,6 +2082,7 @@ LayoutUnit LayoutBox::AdjustBorderBoxLogicalWidthForBoxSizing( float width) const { + CheckIsNotDestroyed(); LayoutUnit borders_plus_padding = CollapsedBorderAndCSSPaddingLogicalWidth(); LayoutUnit result(width); if (StyleRef().BoxSizing() == EBoxSizing::kContentBox) @@ -1993,6 +2092,7 @@ LayoutUnit LayoutBox::AdjustBorderBoxLogicalHeightForBoxSizing( float height) const { + CheckIsNotDestroyed(); LayoutUnit borders_plus_padding = CollapsedBorderAndCSSPaddingLogicalHeight(); LayoutUnit result(height); if (StyleRef().BoxSizing() == EBoxSizing::kContentBox) @@ -2002,6 +2102,7 @@ LayoutUnit LayoutBox::AdjustContentBoxLogicalWidthForBoxSizing( float width) const { + CheckIsNotDestroyed(); LayoutUnit result(width); if (StyleRef().BoxSizing() == EBoxSizing::kBorderBox) result -= CollapsedBorderAndCSSPaddingLogicalWidth(); @@ -2010,6 +2111,7 @@ LayoutUnit LayoutBox::AdjustContentBoxLogicalHeightForBoxSizing( float height) const { + CheckIsNotDestroyed(); LayoutUnit result(height); if (StyleRef().BoxSizing() == EBoxSizing::kBorderBox) result -= CollapsedBorderAndCSSPaddingLogicalHeight(); @@ -2021,6 +2123,7 @@ const HitTestLocation& hit_test_location, const PhysicalOffset& accumulated_offset, HitTestFilter hit_test_filter) { + CheckIsNotDestroyed(); // Check if we need to do anything at all. // If we have clipping, then we can't have any spillout. // TODO(pdr): Why is this optimization not valid for the effective root? @@ -2048,6 +2151,7 @@ const HitTestLocation& hit_test_location, const PhysicalOffset& accumulated_offset, HitTestAction action) { + CheckIsNotDestroyed(); bool should_hit_test_self = IsInSelfHitTestingPhase(action); if (should_hit_test_self && IsScrollContainer() && @@ -2110,6 +2214,7 @@ const HitTestLocation& hit_test_location, const PhysicalOffset& accumulated_offset, HitTestAction action) { + CheckIsNotDestroyed(); for (LayoutObject* child = SlowLastChild(); child; child = child->PreviousSibling()) { if (child->HasLayer() && @@ -2131,6 +2236,7 @@ bool LayoutBox::HitTestClippedOutByBorder( const HitTestLocation& hit_test_location, const PhysicalOffset& border_box_location) const { + CheckIsNotDestroyed(); PhysicalRect border_rect = PhysicalBorderBoxRect(); border_rect.Move(border_box_location); return !hit_test_location.Intersects( @@ -2139,16 +2245,19 @@ } void LayoutBox::Paint(const PaintInfo& paint_info) const { + CheckIsNotDestroyed(); BoxPainter(*this).Paint(paint_info); } void LayoutBox::PaintBoxDecorationBackground( const PaintInfo& paint_info, const PhysicalOffset& paint_offset) const { + CheckIsNotDestroyed(); BoxPainter(*this).PaintBoxDecorationBackground(paint_info, paint_offset); } bool LayoutBox::GetBackgroundPaintedExtent(PhysicalRect& painted_extent) const { + CheckIsNotDestroyed(); DCHECK(StyleRef().HasBackground()); // LayoutView is special in the sense that it expands to the whole canvas, @@ -2184,6 +2293,7 @@ bool LayoutBox::BackgroundIsKnownToBeOpaqueInRect( const PhysicalRect& local_rect) const { + CheckIsNotDestroyed(); // If the element has appearance, it might be painted by theme. // We cannot be sure if theme paints the background opaque. // In this case it is safe to not assume opaqueness. @@ -2206,6 +2316,7 @@ // TODO(wangxianzhu): The current rules are very basic. May use more complex // rules if they can improve LCD text. bool LayoutBox::TextIsKnownToBeOnOpaqueBackground() const { + CheckIsNotDestroyed(); // Text may overflow the background area. if (!ShouldClipOverflow()) return false; @@ -2234,6 +2345,7 @@ bool LayoutBox::ForegroundIsKnownToBeOpaqueInRect( const PhysicalRect& local_rect, unsigned max_depth_to_test) const { + CheckIsNotDestroyed(); if (!max_depth_to_test) return false; for (LayoutObject* child = SlowFirstChild(); child; @@ -2266,6 +2378,7 @@ DISABLE_CFI_PERF bool LayoutBox::ComputeBackgroundIsKnownToBeObscured() const { + CheckIsNotDestroyed(); if (ScrollsOverflow()) return false; // Test to see if the children trivially obscure the background. @@ -2285,11 +2398,13 @@ void LayoutBox::PaintMask(const PaintInfo& paint_info, const PhysicalOffset& paint_offset) const { + CheckIsNotDestroyed(); BoxPainter(*this).PaintMask(paint_info, paint_offset); } void LayoutBox::ImageChanged(WrappedImagePtr image, CanDeferInvalidation defer) { + CheckIsNotDestroyed(); bool is_box_reflect_image = (StyleRef().BoxReflect() && StyleRef().BoxReflect()->Mask().GetImage() && StyleRef().BoxReflect()->Mask().GetImage()->Data() == image); @@ -2349,6 +2464,7 @@ } ResourcePriority LayoutBox::ComputeResourcePriority() const { + CheckIsNotDestroyed(); PhysicalRect view_bounds = ViewRect(); PhysicalRect object_bounds = PhysicalContentBoxRect(); // TODO(japhet): Is this IgnoreTransforms correct? Would it be better to use @@ -2379,6 +2495,7 @@ } void LayoutBox::LocationChanged() { + CheckIsNotDestroyed(); // The location may change because of layout of other objects. Should check // this object for paint invalidation. if (!NeedsLayout()) @@ -2386,6 +2503,7 @@ } void LayoutBox::SizeChanged() { + CheckIsNotDestroyed(); // The size may change because of layout of other objects. Should check this // object for paint invalidation. if (!NeedsLayout()) @@ -2393,6 +2511,7 @@ } bool LayoutBox::IntersectsVisibleViewport() const { + CheckIsNotDestroyed(); PhysicalRect rect = PhysicalVisualOverflowRect(); LayoutView* layout_view = View(); while (layout_view->GetFrame()->OwnerLayoutObject()) @@ -2403,6 +2522,7 @@ } void LayoutBox::EnsureIsReadyForPaintInvalidation() { + CheckIsNotDestroyed(); LayoutBoxModelObject::EnsureIsReadyForPaintInvalidation(); bool new_obscured = ComputeBackgroundIsKnownToBeObscured(); @@ -2429,6 +2549,7 @@ } void LayoutBox::InvalidatePaintRectangle(const PhysicalRect& dirty_rect) { + CheckIsNotDestroyed(); DCHECK_NE(GetDocument().Lifecycle().GetState(), DocumentLifecycle::kInPaint); if (dirty_rect.IsEmpty()) @@ -2439,11 +2560,13 @@ } void LayoutBox::ClearPartialInvalidationVisualRect() const { + CheckIsNotDestroyed(); if (rare_data_) rare_data_->partial_invalidation_rect_ = PhysicalRect(); } IntRect LayoutBox::PartialInvalidationVisualRect() const { + CheckIsNotDestroyed(); if (!rare_data_) return IntRect(); PhysicalRect rect = rare_data_->partial_invalidation_rect_; @@ -2454,10 +2577,12 @@ } void LayoutBox::InvalidatePaint(const PaintInvalidatorContext& context) const { + CheckIsNotDestroyed(); BoxPaintInvalidator(*this, context).InvalidatePaint(); } void LayoutBox::ClearPaintFlags() { + CheckIsNotDestroyed(); LayoutObject::ClearPaintFlags(); if (auto* scrollable_area = GetScrollableArea()) { @@ -2473,6 +2598,7 @@ PhysicalRect LayoutBox::OverflowClipRect( const PhysicalOffset& location, OverlayScrollbarClipBehavior overlay_scrollbar_clip_behavior) const { + CheckIsNotDestroyed(); PhysicalRect clip_rect; if (IsEffectiveRootScroller()) { @@ -2516,6 +2642,7 @@ } bool LayoutBox::HasControlClip() const { + CheckIsNotDestroyed(); return UNLIKELY(IsTextField() || IsFileUploadControl() || IsMenuList(this) || (IsButtonOrNGButton() && IsA<HTMLInputElement>(GetNode()))); } @@ -2523,6 +2650,7 @@ void LayoutBox::ExcludeScrollbars( PhysicalRect& rect, OverlayScrollbarClipBehavior overlay_scrollbar_clip_behavior) const { + CheckIsNotDestroyed(); if (CanSkipComputeScrollbars()) return; @@ -2536,6 +2664,7 @@ } PhysicalRect LayoutBox::ClipRect(const PhysicalOffset& location) const { + CheckIsNotDestroyed(); PhysicalRect clip_rect(location, Size()); LayoutUnit width = Size().Width(); LayoutUnit height = Size().Height(); @@ -2580,6 +2709,7 @@ LayoutUnit child_margin_start, LayoutUnit child_margin_end, const LayoutBlockFlow* cb) const { + CheckIsNotDestroyed(); LayoutUnit logical_top_position = LogicalTop(); LayoutUnit start_offset_for_content = cb->StartOffsetForContent(); LayoutUnit end_offset_for_content = cb->EndOffsetForContent(); @@ -2622,6 +2752,7 @@ } LayoutUnit LayoutBox::ContainingBlockLogicalHeightForGetComputedStyle() const { + CheckIsNotDestroyed(); if (HasOverrideContainingBlockContentLogicalHeight()) return OverrideContainingBlockContentLogicalHeight(); @@ -2637,6 +2768,7 @@ } LayoutUnit LayoutBox::ContainingBlockLogicalWidthForContent() const { + CheckIsNotDestroyed(); if (HasOverrideContainingBlockContentLogicalWidth()) return OverrideContainingBlockContentLogicalWidth(); @@ -2648,6 +2780,7 @@ LayoutUnit LayoutBox::ContainingBlockLogicalHeightForContent( AvailableLogicalHeightType height_type) const { + CheckIsNotDestroyed(); if (HasOverrideContainingBlockContentLogicalHeight()) return OverrideContainingBlockContentLogicalHeight(); @@ -2656,6 +2789,7 @@ } LayoutUnit LayoutBox::ContainingBlockAvailableLineWidth() const { + CheckIsNotDestroyed(); LayoutBlock* cb = ContainingBlock(); auto* child_block_flow = DynamicTo<LayoutBlockFlow>(cb); if (child_block_flow) { @@ -2666,6 +2800,7 @@ } LayoutUnit LayoutBox::PerpendicularContainingBlockLogicalHeight() const { + CheckIsNotDestroyed(); if (HasOverrideContainingBlockContentLogicalHeight()) return OverrideContainingBlockContentLogicalHeight(); @@ -2698,6 +2833,7 @@ void LayoutBox::MapLocalToAncestor(const LayoutBoxModelObject* ancestor, TransformState& transform_state, MapCoordinatesFlags mode) const { + CheckIsNotDestroyed(); bool is_fixed_pos = StyleRef().GetPosition() == EPosition::kFixed; // If this box has a transform or contains paint, it acts as a fixed position @@ -2714,6 +2850,7 @@ void LayoutBox::MapAncestorToLocal(const LayoutBoxModelObject* ancestor, TransformState& transform_state, MapCoordinatesFlags mode) const { + CheckIsNotDestroyed(); if (this == ancestor) return; @@ -2733,6 +2870,7 @@ PhysicalOffset LayoutBox::OffsetFromContainerInternal( const LayoutObject* o, bool ignore_scroll_offset) const { + CheckIsNotDestroyed(); DCHECK_EQ(o, Container()); PhysicalOffset offset; @@ -2753,10 +2891,12 @@ } InlineBox* LayoutBox::CreateInlineBox() { + CheckIsNotDestroyed(); return new InlineBox(LineLayoutItem(this)); } void LayoutBox::DirtyLineBoxes(bool full_layout) { + CheckIsNotDestroyed(); if (!IsInLayoutNGInlineFormattingContext() && inline_box_wrapper_) { if (full_layout) { inline_box_wrapper_->Destroy(); @@ -2768,6 +2908,7 @@ } bool LayoutBox::HasInlineFragments() const { + CheckIsNotDestroyed(); if (!IsInLayoutNGInlineFormattingContext()) return inline_box_wrapper_; if (!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) @@ -2776,18 +2917,21 @@ } void LayoutBox::SetFirstInlineFragment(NGPaintFragment* fragment) { + CheckIsNotDestroyed(); CHECK(IsInLayoutNGInlineFormattingContext()) << *this; DCHECK(!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()); first_paint_fragment_ = fragment; } void LayoutBox::ClearFirstInlineFragmentItemIndex() { + CheckIsNotDestroyed(); CHECK(IsInLayoutNGInlineFormattingContext()) << *this; DCHECK(RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()); first_fragment_item_index_ = 0u; } void LayoutBox::SetFirstInlineFragmentItemIndex(wtf_size_t index) { + CheckIsNotDestroyed(); CHECK(IsInLayoutNGInlineFormattingContext()) << *this; DCHECK(RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()); DCHECK_NE(index, 0u); @@ -2795,6 +2939,7 @@ } void LayoutBox::InLayoutNGInlineFormattingContextWillChange(bool new_value) { + CheckIsNotDestroyed(); if (IsInLayoutNGInlineFormattingContext()) { if (!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) { SetFirstInlineFragment(nullptr); @@ -2823,6 +2968,7 @@ void LayoutBox::SetCachedLayoutResult( scoped_refptr<const NGLayoutResult> result) { + CheckIsNotDestroyed(); DCHECK(!result->PhysicalFragment().BreakToken()); DCHECK(!result->IsSingleUse()); @@ -2847,6 +2993,7 @@ void LayoutBox::AddLayoutResult(scoped_refptr<const NGLayoutResult> result, wtf_size_t index) { + CheckIsNotDestroyed(); DCHECK_EQ(result->Status(), NGLayoutResult::kSuccess); if (index != WTF::kNotFound && layout_results_.size() > index) { if (layout_results_.size() > index + 1) @@ -2868,6 +3015,7 @@ void LayoutBox::ReplaceLayoutResult(scoped_refptr<const NGLayoutResult> result, wtf_size_t index) { + CheckIsNotDestroyed(); DCHECK_LE(index, layout_results_.size()); const NGLayoutResult* old_result = layout_results_[index].get(); if (old_result == result.get()) @@ -2901,6 +3049,7 @@ } void LayoutBox::ClearLayoutResults() { + CheckIsNotDestroyed(); if (measure_result_) InvalidateItems(*measure_result_); measure_result_ = nullptr; @@ -2909,6 +3058,7 @@ } void LayoutBox::ShrinkLayoutResults(wtf_size_t results_to_keep) { + CheckIsNotDestroyed(); DCHECK_GE(layout_results_.size(), results_to_keep); // Invalidate if inline |DisplayItemClient|s will be destroyed. for (wtf_size_t i = results_to_keep; i < layout_results_.size(); i++) @@ -2923,6 +3073,7 @@ } void LayoutBox::InvalidateItems(const NGLayoutResult& result) { + CheckIsNotDestroyed(); // Invalidate if inline |DisplayItemClient|s will be destroyed. const auto& box_fragment = To<NGPhysicalBoxFragment>(result.PhysicalFragment()); @@ -2939,6 +3090,7 @@ } const NGLayoutResult* LayoutBox::GetCachedLayoutResult() const { + CheckIsNotDestroyed(); if (layout_results_.IsEmpty()) return nullptr; // Only return re-usable results. @@ -2952,6 +3104,7 @@ } const NGLayoutResult* LayoutBox::GetCachedMeasureResult() const { + CheckIsNotDestroyed(); if (!measure_result_) return nullptr; @@ -2967,6 +3120,7 @@ const NGEarlyBreak* early_break, base::Optional<NGFragmentGeometry>* initial_fragment_geometry, NGLayoutCacheStatus* out_cache_status) { + CheckIsNotDestroyed(); *out_cache_status = NGLayoutCacheStatus::kNeedsLayout; const bool use_layout_cache_slot = @@ -3194,6 +3348,7 @@ const NGPhysicalBoxFragment* LayoutBox::GetPhysicalFragment( wtf_size_t index) const { + CheckIsNotDestroyed(); return &To<NGPhysicalBoxFragment>(layout_results_[index]->PhysicalFragment()); } @@ -3204,6 +3359,7 @@ const FragmentData* LayoutBox::FragmentDataFromPhysicalFragment( const NGPhysicalBoxFragment& physical_fragment) const { + CheckIsNotDestroyed(); const FragmentData* fragment_data = &FirstFragment(); for (const auto& result : layout_results_) { if (&result->PhysicalFragment() == &physical_fragment) @@ -3216,6 +3372,7 @@ } void LayoutBox::PositionLineBox(InlineBox* box) { + CheckIsNotDestroyed(); if (IsOutOfFlowPositioned()) { // Cache the x position only if we were an INLINE type originally. bool originally_inline = StyleRef().IsOriginalDisplayInlineType(); @@ -3247,6 +3404,7 @@ } void LayoutBox::MoveWithEdgeOfInlineContainerIfNecessary(bool is_horizontal) { + CheckIsNotDestroyed(); DCHECK(IsOutOfFlowPositioned()); DCHECK(Container()->IsLayoutInline()); DCHECK(Container()->CanContainOutOfFlowPositionedElement( @@ -3263,6 +3421,7 @@ } void LayoutBox::DeleteLineBoxWrapper() { + CheckIsNotDestroyed(); if (!IsInLayoutNGInlineFormattingContext() && inline_box_wrapper_) { if (!DocumentBeingDestroyed()) inline_box_wrapper_->Remove(); @@ -3273,24 +3432,28 @@ void LayoutBox::SetSpannerPlaceholder( LayoutMultiColumnSpannerPlaceholder& placeholder) { + CheckIsNotDestroyed(); // Not expected to change directly from one spanner to another. CHECK(!rare_data_ || !rare_data_->spanner_placeholder_); EnsureRareData().spanner_placeholder_ = &placeholder; } void LayoutBox::ClearSpannerPlaceholder() { + CheckIsNotDestroyed(); if (!rare_data_) return; rare_data_->spanner_placeholder_ = nullptr; } void LayoutBox::SetPaginationStrut(LayoutUnit strut) { + CheckIsNotDestroyed(); if (!strut && !rare_data_) return; EnsureRareData().pagination_strut_ = strut; } bool LayoutBox::IsBreakBetweenControllable(EBreakBetween break_value) const { + CheckIsNotDestroyed(); if (break_value == EBreakBetween::kAuto) return true; // We currently only support non-auto break-before and break-after values on @@ -3330,6 +3493,7 @@ } bool LayoutBox::IsBreakInsideControllable(EBreakInside break_value) const { + CheckIsNotDestroyed(); if (break_value == EBreakInside::kAuto) return true; // First check multicol. @@ -3350,6 +3514,7 @@ } EBreakBetween LayoutBox::BreakAfter() const { + CheckIsNotDestroyed(); EBreakBetween break_value = StyleRef().BreakAfter(); if (break_value == EBreakBetween::kAuto || IsBreakBetweenControllable(break_value)) @@ -3358,6 +3523,7 @@ } EBreakBetween LayoutBox::BreakBefore() const { + CheckIsNotDestroyed(); EBreakBetween break_value = StyleRef().BreakBefore(); if (break_value == EBreakBetween::kAuto || IsBreakBetweenControllable(break_value)) @@ -3366,6 +3532,7 @@ } EBreakInside LayoutBox::BreakInside() const { + CheckIsNotDestroyed(); EBreakInside break_value = StyleRef().BreakInside(); if (break_value == EBreakInside::kAuto || IsBreakInsideControllable(break_value)) @@ -3375,6 +3542,7 @@ EBreakBetween LayoutBox::ClassABreakPointValue( EBreakBetween previous_break_after_value) const { + CheckIsNotDestroyed(); // First assert that we're at a class A break point. DCHECK(IsBreakBetweenControllable(previous_break_after_value)); @@ -3384,6 +3552,7 @@ bool LayoutBox::NeedsForcedBreakBefore( EBreakBetween previous_break_after_value) const { + CheckIsNotDestroyed(); // Forced break values are only honored when specified on in-flow objects, but // floats and out-of-flow positioned objects may be affected by a break-after // value of the previous in-flow object, even though we're not at a class A @@ -3396,14 +3565,17 @@ } const AtomicString LayoutBox::StartPageName() const { + CheckIsNotDestroyed(); return StyleRef().Page(); } const AtomicString LayoutBox::EndPageName() const { + CheckIsNotDestroyed(); return StyleRef().Page(); } PhysicalRect LayoutBox::LocalVisualRectIgnoringVisibility() const { + CheckIsNotDestroyed(); return PhysicalSelfVisualOverflowRect(); } @@ -3411,6 +3583,7 @@ TransformState& transform_state, const LayoutObject& container, const LayoutBoxModelObject* ancestor_to_stop_at) const { + CheckIsNotDestroyed(); transform_state.Flatten(); // Apply visual overflow caused by reflections and filters defined on objects // between this object and container (not included) or ancestorToStopAt @@ -3437,6 +3610,7 @@ const LayoutBoxModelObject* ancestor, TransformState& transform_state, VisualRectFlags visual_rect_flags) const { + CheckIsNotDestroyed(); InflateVisualRectForFilter(transform_state); if (ancestor == this) @@ -3524,6 +3698,7 @@ void LayoutBox::InflateVisualRectForFilter( TransformState& transform_state) const { + CheckIsNotDestroyed(); if (!Layer() || !Layer()->PaintsWithFilters()) return; @@ -3558,6 +3733,7 @@ } void LayoutBox::UpdateLogicalWidth() { + CheckIsNotDestroyed(); if (NeedsPreferredWidthsRecalculation()) { if (ShouldRecalculateMinMaxWidthsAffectedByAncestor(this)) { // Laying out this object means that its containing block is also being @@ -3619,6 +3795,7 @@ } LayoutUnit LayoutBox::ContainerWidthInInlineDirection() const { + CheckIsNotDestroyed(); LayoutBlock* cb = ContainingBlock(); if (IsParallelWritingMode(cb->StyleRef().GetWritingMode(), @@ -3634,6 +3811,7 @@ bool LayoutBox::ShouldComputeLogicalWidthFromAspectRatio( LayoutUnit* out_logical_height) const { + CheckIsNotDestroyed(); if (!StyleRef().AspectRatio() || (!StyleRef().LogicalHeight().IsFixed() && !StyleRef().LogicalHeight().IsPercentOrCalc())) { @@ -3653,6 +3831,7 @@ bool LayoutBox::ComputeLogicalWidthFromAspectRatio( LayoutUnit* out_logical_width) const { + CheckIsNotDestroyed(); LayoutUnit logical_height_for_ar; if (!ShouldComputeLogicalWidthFromAspectRatio(&logical_height_for_ar)) return false; @@ -3675,6 +3854,7 @@ DISABLE_CFI_PERF void LayoutBox::ComputeLogicalWidth( LogicalExtentComputedValues& computed_values) const { + CheckIsNotDestroyed(); computed_values.position_ = LogicalLeft(); computed_values.margins_.start_ = MarginStart(); computed_values.margins_.end_ = MarginEnd(); @@ -3790,6 +3970,7 @@ LayoutUnit LayoutBox::FillAvailableMeasure( LayoutUnit available_logical_width) const { + CheckIsNotDestroyed(); LayoutUnit margin_start; LayoutUnit margin_end; return FillAvailableMeasure(available_logical_width, margin_start, @@ -3799,6 +3980,7 @@ LayoutUnit LayoutBox::FillAvailableMeasure(LayoutUnit available_logical_width, LayoutUnit& margin_start, LayoutUnit& margin_end) const { + CheckIsNotDestroyed(); DCHECK_GE(available_logical_width, 0); bool isOrthogonalElement = @@ -3823,6 +4005,7 @@ LayoutUnit LayoutBox::ComputeIntrinsicLogicalWidthUsing( const Length& logical_width_length, LayoutUnit available_logical_width) const { + CheckIsNotDestroyed(); if (logical_width_length.IsFillAvailable()) { if (!IsA<HTMLMarqueeElement>(GetNode())) { UseCounter::Count(GetDocument(), @@ -3859,6 +4042,7 @@ const Length& logical_width, LayoutUnit available_logical_width, const LayoutBlock* cb) const { + CheckIsNotDestroyed(); DCHECK(width_type == kMinSize || width_type == kMainOrPreferredSize || !logical_width.IsAuto()); if (width_type == kMinSize && logical_width.IsAuto()) @@ -3906,6 +4090,7 @@ } bool LayoutBox::ColumnFlexItemHasStretchAlignment() const { + CheckIsNotDestroyed(); // auto margins mean we don't stretch. Note that this function will only be // used for widths, so we don't have to check marginBefore/marginAfter. const auto& parent_style = Parent()->StyleRef(); @@ -3920,6 +4105,7 @@ } bool LayoutBox::IsStretchingColumnFlexItem() const { + CheckIsNotDestroyed(); LayoutObject* parent = Parent(); if (parent->StyleRef().IsDeprecatedWebkitBox() && parent->StyleRef().BoxOrient() == EBoxOrient::kVertical && @@ -3939,6 +4125,7 @@ // TODO (lajava) Can/Should we move this inside specific layout classes (flex. // grid)? Can we refactor columnFlexItemHasStretchAlignment logic? bool LayoutBox::HasStretchedLogicalWidth() const { + CheckIsNotDestroyed(); const ComputedStyle& style = StyleRef(); if (!style.LogicalWidth().IsAuto() || style.MarginStart().IsAuto() || style.MarginEnd().IsAuto()) @@ -3964,6 +4151,7 @@ bool LayoutBox::SizesLogicalWidthToFitContent( const Length& logical_width) const { + CheckIsNotDestroyed(); if (IsFloating() || IsInlineBlockOrInlineTable() || StyleRef().HasOutOfFlowPosition()) return true; @@ -4015,6 +4203,7 @@ } bool LayoutBox::AutoWidthShouldFitContent() const { + CheckIsNotDestroyed(); return GetNode() && (IsA<HTMLInputElement>(*GetNode()) || IsA<HTMLSelectElement>(*GetNode()) || @@ -4030,6 +4219,7 @@ LayoutUnit& margin_end, Length margin_start_length, Length margin_end_length) const { + CheckIsNotDestroyed(); // First assert that we're not calling this method on box types that don't // support margins. DCHECK(!IsTableCell()); @@ -4139,6 +4329,7 @@ DISABLE_CFI_PERF void LayoutBox::UpdateLogicalHeight() { + CheckIsNotDestroyed(); if (!HasOverrideLogicalHeight()) { // If we have an override height, our children will have sized themselves // relative to our override height, which would make our intrinsic size @@ -4164,6 +4355,7 @@ void LayoutBox::ComputeLogicalHeight( LogicalExtentComputedValues& computed_values) const { + CheckIsNotDestroyed(); LayoutUnit height; if (HasOverrideIntrinsicContentLogicalHeight()) { height = OverrideIntrinsicContentLogicalHeight() + @@ -4188,6 +4380,7 @@ LayoutUnit logical_height, LayoutUnit logical_top, LogicalExtentComputedValues& computed_values) const { + CheckIsNotDestroyed(); computed_values.extent_ = logical_height; computed_values.position_ = logical_top; @@ -4304,6 +4497,7 @@ } LayoutUnit LayoutBox::ComputeLogicalHeightWithoutLayout() const { + CheckIsNotDestroyed(); LogicalExtentComputedValues computed_values; if (!SelfNeedsLayout() && HasOverrideIntrinsicContentLogicalHeight()) { @@ -4324,6 +4518,7 @@ SizeType height_type, const Length& height, LayoutUnit intrinsic_content_height) const { + CheckIsNotDestroyed(); LayoutUnit logical_height = ComputeContentAndScrollbarLogicalHeightUsing( height_type, height, intrinsic_content_height); if (logical_height != -1) { @@ -4339,6 +4534,7 @@ SizeType height_type, const Length& height, LayoutUnit intrinsic_content_height) const { + CheckIsNotDestroyed(); LayoutUnit height_including_scrollbar = ComputeContentAndScrollbarLogicalHeightUsing(height_type, height, intrinsic_content_height); @@ -4358,6 +4554,7 @@ const Length& logical_height_length, LayoutUnit intrinsic_content_height, LayoutUnit border_and_padding) const { + CheckIsNotDestroyed(); // FIXME(cbiesinger): The css-sizing spec is considering changing what // min-content/max-content should resolve to. // If that happens, this code will have to change. @@ -4386,6 +4583,7 @@ SizeType height_type, const Length& height, LayoutUnit intrinsic_content_height) const { + CheckIsNotDestroyed(); if (height.IsAuto()) return height_type == kMinSize ? LayoutUnit() : LayoutUnit(-1); // FIXME(cbiesinger): The css-sizing spec is considering changing what @@ -4407,6 +4605,7 @@ } bool LayoutBox::StretchesToViewportInQuirksMode() const { + CheckIsNotDestroyed(); if (!IsDocumentElement() && !IsBody()) return false; return StyleRef().LogicalHeight().IsAuto() && @@ -4458,6 +4657,7 @@ LayoutUnit LayoutBox::ContainingBlockLogicalHeightForPercentageResolution( LayoutBlock** out_cb, bool* out_skipped_auto_height_containing_block) const { + CheckIsNotDestroyed(); LayoutBlock* cb = ContainingBlock(); const LayoutBlock* const real_cb = cb; const LayoutBox* containing_block_child = this; @@ -4549,6 +4749,7 @@ LayoutUnit LayoutBox::ComputePercentageLogicalHeight( const Length& height) const { + CheckIsNotDestroyed(); bool skipped_auto_height_containing_block = false; LayoutBlock* cb = nullptr; LayoutUnit available_height = @@ -4583,6 +4784,7 @@ LayoutUnit LayoutBox::ComputeReplacedLogicalWidth( ShouldComputePreferred should_compute_preferred) const { + CheckIsNotDestroyed(); return ComputeReplacedLogicalWidthRespectingMinMaxWidth( ComputeReplacedLogicalWidthUsing(kMainOrPreferredSize, StyleRef().LogicalWidth()), @@ -4592,6 +4794,7 @@ LayoutUnit LayoutBox::ComputeReplacedLogicalWidthRespectingMinMaxWidth( LayoutUnit logical_width, ShouldComputePreferred should_compute_preferred) const { + CheckIsNotDestroyed(); LayoutUnit min_logical_width = (should_compute_preferred == kComputePreferred && StyleRef().LogicalMinWidth().IsPercentOrCalc()) @@ -4612,6 +4815,7 @@ LayoutUnit LayoutBox::ComputeReplacedLogicalWidthUsing( SizeType size_type, const Length& logical_width) const { + CheckIsNotDestroyed(); DCHECK(size_type == kMinSize || size_type == kMainOrPreferredSize || !logical_width.IsAuto()); if (size_type == kMinSize && logical_width.IsAuto()) @@ -4670,12 +4874,14 @@ } LayoutUnit LayoutBox::ComputeReplacedLogicalHeight(LayoutUnit) const { + CheckIsNotDestroyed(); return ComputeReplacedLogicalHeightRespectingMinMaxHeight( ComputeReplacedLogicalHeightUsing(kMainOrPreferredSize, StyleRef().LogicalHeight())); } bool LayoutBox::LogicalHeightComputesAsNone(SizeType size_type) const { + CheckIsNotDestroyed(); DCHECK(size_type == kMinSize || size_type == kMaxSize); const Length& logical_height = size_type == kMinSize ? StyleRef().LogicalMinHeight() @@ -4715,6 +4921,7 @@ LayoutUnit LayoutBox::ComputeReplacedLogicalHeightRespectingMinMaxHeight( LayoutUnit logical_height) const { + CheckIsNotDestroyed(); // If the height of the containing block is not specified explicitly (i.e., it // depends on content height), and this element is not absolutely positioned, // the percentage value is treated as '0' (for 'min-height') or 'none' (for @@ -4736,6 +4943,7 @@ LayoutUnit LayoutBox::ComputeReplacedLogicalHeightUsing( SizeType size_type, const Length& logical_height) const { + CheckIsNotDestroyed(); DCHECK(size_type == kMinSize || size_type == kMainOrPreferredSize || !logical_height.IsAuto()); if (size_type == kMinSize && logical_height.IsAuto()) @@ -4826,6 +5034,7 @@ LayoutUnit LayoutBox::AvailableLogicalHeight( AvailableLogicalHeightType height_type) const { + CheckIsNotDestroyed(); if (RuntimeEnabledFeatures::LayoutNGEnabled()) { // LayoutNG code is correct, Legacy code incorrectly ConstrainsMinMax // when height is -1, and returns 0, not -1. @@ -4850,6 +5059,7 @@ LayoutUnit LayoutBox::AvailableLogicalHeightUsing( const Length& h, AvailableLogicalHeightType height_type) const { + CheckIsNotDestroyed(); if (auto* layout_view = DynamicTo<LayoutView>(this)) { return LayoutUnit(IsHorizontalWritingMode() ? layout_view->GetFrameView()->Size().Height() @@ -4941,6 +5151,7 @@ void LayoutBox::ComputeAndSetBlockDirectionMargins( const LayoutBlock* containing_block) { + CheckIsNotDestroyed(); LayoutUnit margin_before; LayoutUnit margin_after; DCHECK(containing_block); @@ -4960,6 +5171,7 @@ LayoutUnit LayoutBox::ContainingBlockLogicalWidthForPositioned( const LayoutBoxModelObject* containing_block, bool check_for_perpendicular_writing_mode) const { + CheckIsNotDestroyed(); if (check_for_perpendicular_writing_mode && containing_block->IsHorizontalWritingMode() != IsHorizontalWritingMode()) return ContainingBlockLogicalHeightForPositioned(containing_block, false); @@ -5031,6 +5243,7 @@ LayoutUnit LayoutBox::ContainingBlockLogicalHeightForPositioned( const LayoutBoxModelObject* containing_block, bool check_for_perpendicular_writing_mode) const { + CheckIsNotDestroyed(); if (check_for_perpendicular_writing_mode && containing_block->IsHorizontalWritingMode() != IsHorizontalWritingMode()) return ContainingBlockLogicalWidthForPositioned(containing_block, false); @@ -5203,6 +5416,7 @@ void LayoutBox::ComputePositionedLogicalWidth( LogicalExtentComputedValues& computed_values) const { + CheckIsNotDestroyed(); // QUESTIONS // FIXME 1: Should we still deal with these the cases of 'left' or 'right' // having the type 'static' in determining whether to calculate the static @@ -5369,6 +5583,7 @@ LayoutUnit LayoutBox::ShrinkToFitLogicalWidth( LayoutUnit available_logical_width, LayoutUnit borders_plus_padding) const { + CheckIsNotDestroyed(); MinMaxSizes sizes = PreferredLogicalWidths(); sizes -= borders_plus_padding; return sizes.ShrinkToFit(available_logical_width); @@ -5386,6 +5601,7 @@ const Length& margin_logical_left, const Length& margin_logical_right, LogicalExtentComputedValues& computed_values) const { + CheckIsNotDestroyed(); LayoutUnit logical_width_value; DCHECK(width_size_type == kMinSize || @@ -5662,6 +5878,7 @@ void LayoutBox::ComputePositionedLogicalHeight( LogicalExtentComputedValues& computed_values) const { + CheckIsNotDestroyed(); // The following is based off of the W3C Working Draft from April 11, 2006 of // CSS 2.1: Section 10.6.4 "Absolutely positioned, non-replaced elements" // <http://www.w3.org/TR/2005/WD-CSS21-20050613/visudet.html#abs-non-replaced-height> @@ -5827,6 +6044,7 @@ const Length& margin_before, const Length& margin_after, LogicalExtentComputedValues& computed_values) const { + CheckIsNotDestroyed(); DCHECK(height_size_type == kMinSize || height_size_type == kMainOrPreferredSize || !logical_height_length.IsAuto()); @@ -6019,6 +6237,7 @@ const InlineBox* box, int caret_offset, LayoutUnit* extra_width_to_end_of_line) const { + CheckIsNotDestroyed(); // VisiblePositions at offsets inside containers either a) refer to the // positions before/after those containers (tables and select elements) or // b) refer to the position inside an empty block. @@ -6078,6 +6297,7 @@ PositionWithAffinity LayoutBox::PositionForPoint( const PhysicalOffset& point) const { + CheckIsNotDestroyed(); // no children...return this layout object's element, if there is one, and // offset 0 LayoutObject* first_child = SlowFirstChild(); @@ -6181,6 +6401,7 @@ DISABLE_CFI_PERF bool LayoutBox::ShrinkToAvoidFloats() const { + CheckIsNotDestroyed(); // Floating objects don't shrink. Objects that don't avoid floats don't // shrink. if (IsInline() || !CreatesNewFormattingContext() || IsFloating()) @@ -6209,6 +6430,7 @@ DISABLE_CFI_PERF bool LayoutBox::ShouldBeConsideredAsReplaced() const { + CheckIsNotDestroyed(); if (IsAtomicInlineLevel()) return true; // We need to detect all types of objects that should be treated as replaced. @@ -6234,6 +6456,7 @@ } void LayoutBox::UpdateFragmentationInfoForChild(LayoutBox& child) { + CheckIsNotDestroyed(); LayoutState* layout_state = View()->GetLayoutState(); DCHECK(layout_state->IsPaginated()); child.SetOffsetToNextPage(LayoutUnit()); @@ -6249,6 +6472,7 @@ } bool LayoutBox::ChildNeedsRelayoutForPagination(const LayoutBox& child) const { + CheckIsNotDestroyed(); // TODO(mstensho): Should try to get this to work for floats too, instead of // just marking and bailing here. if (child.IsFloating()) @@ -6291,6 +6515,7 @@ void LayoutBox::MarkChildForPaginationRelayoutIfNeeded( LayoutBox& child, SubtreeLayoutScope& layout_scope) { + CheckIsNotDestroyed(); DCHECK(!child.NeedsLayout() || child.ChildLayoutBlockedByDisplayLock()); LayoutState* layout_state = View()->GetLayoutState(); @@ -6300,11 +6525,13 @@ } void LayoutBox::MarkOrthogonalWritingModeRoot() { + CheckIsNotDestroyed(); DCHECK(GetFrameView()); GetFrameView()->AddOrthogonalWritingModeRoot(*this); } void LayoutBox::UnmarkOrthogonalWritingModeRoot() { + CheckIsNotDestroyed(); DCHECK(GetFrameView()); GetFrameView()->RemoveOrthogonalWritingModeRoot(*this); } @@ -6312,6 +6539,7 @@ // Children of LayoutCustom object's are only considered "items" when it has a // loaded algorithm. bool LayoutBox::IsCustomItem() const { + CheckIsNotDestroyed(); auto* parent_layout_box = DynamicTo<LayoutNGCustom>(Parent()); return parent_layout_box && parent_layout_box->IsLoaded(); } @@ -6319,11 +6547,13 @@ // LayoutCustom items are only shrink-to-fit during the web-developer defined // layout phase (not during fallback). bool LayoutBox::IsCustomItemShrinkToFit() const { + CheckIsNotDestroyed(); DCHECK(IsCustomItem()); return To<LayoutNGCustom>(Parent())->IsLoaded(); } void LayoutBox::AddVisualEffectOverflow() { + CheckIsNotDestroyed(); if (!StyleRef().HasVisualOverflowingEffect()) return; @@ -6341,6 +6571,7 @@ } LayoutRectOutsets LayoutBox::ComputeVisualEffectOverflowOutsets() { + CheckIsNotDestroyed(); const ComputedStyle& style = StyleRef(); DCHECK(style.HasVisualOverflowingEffect()); @@ -6363,6 +6594,7 @@ void LayoutBox::AddVisualOverflowFromChild(const LayoutBox& child, const LayoutSize& delta) { + CheckIsNotDestroyed(); // Never allow flow threads to propagate overflow up to a parent. if (child.IsLayoutFlowThread()) return; @@ -6382,6 +6614,7 @@ DISABLE_CFI_PERF void LayoutBox::AddLayoutOverflowFromChild(const LayoutBox& child, const LayoutSize& delta) { + CheckIsNotDestroyed(); DCHECK(!ChildLayoutBlockedByDisplayLock()); // Never allow flow threads to propagate overflow up to a parent. @@ -6399,17 +6632,20 @@ } void LayoutBox::SetLayoutClientAfterEdge(LayoutUnit client_after_edge) { + CheckIsNotDestroyed(); if (LayoutOverflowIsSet()) overflow_->layout_overflow->SetLayoutClientAfterEdge(client_after_edge); } LayoutUnit LayoutBox::LayoutClientAfterEdge() const { + CheckIsNotDestroyed(); return LayoutOverflowIsSet() ? overflow_->layout_overflow->LayoutClientAfterEdge() : ClientLogicalBottom(); } PhysicalRect LayoutBox::PhysicalVisualOverflowRectIncludingFilters() const { + CheckIsNotDestroyed(); PhysicalRect bounds_rect = PhysicalVisualOverflowRect(); if (!StyleRef().HasFilter()) return bounds_rect; @@ -6420,15 +6656,18 @@ } bool LayoutBox::HasTopOverflow() const { + CheckIsNotDestroyed(); return !StyleRef().IsLeftToRightDirection() && !IsHorizontalWritingMode(); } bool LayoutBox::HasLeftOverflow() const { + CheckIsNotDestroyed(); return !StyleRef().IsLeftToRightDirection() && IsHorizontalWritingMode(); } DISABLE_CFI_PERF void LayoutBox::AddLayoutOverflow(const LayoutRect& rect) { + CheckIsNotDestroyed(); if (rect.IsEmpty()) return; @@ -6473,6 +6712,7 @@ } void LayoutBox::AddSelfVisualOverflow(const LayoutRect& rect) { + CheckIsNotDestroyed(); if (rect.IsEmpty()) return; @@ -6491,6 +6731,7 @@ } void LayoutBox::AddContentsVisualOverflow(const LayoutRect& rect) { + CheckIsNotDestroyed(); if (rect.IsEmpty()) return; @@ -6513,6 +6754,7 @@ } void LayoutBox::ClearLayoutOverflow() { + CheckIsNotDestroyed(); if (overflow_) overflow_->layout_overflow.reset(); // overflow_ will be reset by MutableForPainting::ClearPreviousOverflowData() @@ -6520,6 +6762,7 @@ } void LayoutBox::ClearVisualOverflow() { + CheckIsNotDestroyed(); if (overflow_) overflow_->visual_overflow.reset(); // overflow_ will be reset by MutableForPainting::ClearPreviousOverflowData() @@ -6527,12 +6770,14 @@ } bool LayoutBox::PercentageLogicalHeightIsResolvable() const { + CheckIsNotDestroyed(); Length fake_length = Length::Percent(100); return ComputePercentageLogicalHeight(fake_length) != -1; } DISABLE_CFI_PERF bool LayoutBox::HasUnsplittableScrollingOverflow() const { + CheckIsNotDestroyed(); // We will paginate as long as we don't scroll overflow in the pagination // direction. bool is_horizontal = IsHorizontalWritingMode(); @@ -6566,6 +6811,7 @@ LayoutBox::PaginationBreakability LayoutBox::GetPaginationBreakability( FragmentationEngine engine) const { + CheckIsNotDestroyed(); if (ShouldBeConsideredAsReplaced() || HasUnsplittableScrollingOverflow() || (Parent() && IsWritingModeRoot()) || (IsOutOfFlowPositioned() && @@ -6617,6 +6863,7 @@ } PaintLayer* LayoutBox::EnclosingFloatPaintingLayer() const { + CheckIsNotDestroyed(); const LayoutObject* curr = this; while (curr) { PaintLayer* layer = curr->HasLayer() && curr->IsBox() @@ -6630,6 +6877,7 @@ } const LayoutBlock& LayoutBox::EnclosingScrollportBox() const { + CheckIsNotDestroyed(); const LayoutBlock* ancestor = ContainingBlock(); for (; ancestor; ancestor = ancestor->ContainingBlock()) { if (ancestor->IsScrollContainer()) @@ -6640,6 +6888,7 @@ } LayoutRect LayoutBox::LogicalVisualOverflowRectForPropagation() const { + CheckIsNotDestroyed(); LayoutRect rect = VisualOverflowRectForPropagation(); if (!Parent()->StyleRef().IsHorizontalWritingMode()) return rect.TransposedRect(); @@ -6648,6 +6897,7 @@ DISABLE_CFI_PERF LayoutRect LayoutBox::RectForOverflowPropagation(const LayoutRect& rect) const { + CheckIsNotDestroyed(); // If the child and parent are in the same blocks direction, then we don't // have to do anything fancy. Just return the rect. if (Parent()->StyleRef().IsFlippedBlocksWritingMode() == @@ -6664,6 +6914,7 @@ DISABLE_CFI_PERF LayoutRect LayoutBox::LogicalLayoutOverflowRectForPropagation( LayoutObject* container) const { + CheckIsNotDestroyed(); LayoutRect rect = LayoutOverflowRectForPropagation(container); if (!Parent()->StyleRef().IsHorizontalWritingMode()) return rect.TransposedRect(); @@ -6673,6 +6924,7 @@ DISABLE_CFI_PERF LayoutRect LayoutBox::LayoutOverflowRectForPropagation( LayoutObject* container) const { + CheckIsNotDestroyed(); // Only propagate interior layout overflow if we don't clip it. LayoutRect rect = BorderBoxRect(); @@ -6709,10 +6961,12 @@ DISABLE_CFI_PERF LayoutRect LayoutBox::NoOverflowRect() const { + CheckIsNotDestroyed(); return FlipForWritingMode(PhysicalPaddingBoxRect()); } LayoutRect LayoutBox::VisualOverflowRect() const { + CheckIsNotDestroyed(); if (!VisualOverflowIsSet()) return BorderBoxRect(); if (ShouldClipOverflow() || HasMask()) @@ -6722,18 +6976,22 @@ } PhysicalOffset LayoutBox::OffsetPoint(const Element* parent) const { + CheckIsNotDestroyed(); return AdjustedPositionRelativeTo(PhysicalLocation(), parent); } LayoutUnit LayoutBox::OffsetLeft(const Element* parent) const { + CheckIsNotDestroyed(); return OffsetPoint(parent).left; } LayoutUnit LayoutBox::OffsetTop(const Element* parent) const { + CheckIsNotDestroyed(); return OffsetPoint(parent).top; } LayoutBox* LayoutBox::LocationContainer() const { + CheckIsNotDestroyed(); // Location of a non-root SVG object derived from LayoutBox should not be // affected by writing-mode of the containing box (SVGRoot). if (IsSVGChild()) @@ -6747,12 +7005,14 @@ } bool LayoutBox::HasRelativeLogicalWidth() const { + CheckIsNotDestroyed(); return StyleRef().LogicalWidth().IsPercentOrCalc() || StyleRef().LogicalMinWidth().IsPercentOrCalc() || StyleRef().LogicalMaxWidth().IsPercentOrCalc(); } bool LayoutBox::HasRelativeLogicalHeight() const { + CheckIsNotDestroyed(); return StyleRef().LogicalHeight().IsPercentOrCalc() || StyleRef().LogicalMinHeight().IsPercentOrCalc() || StyleRef().LogicalMaxHeight().IsPercentOrCalc(); @@ -6787,6 +7047,7 @@ LayoutObject* LayoutBox::SplitAnonymousBoxesAroundChild( LayoutObject* before_child) { + CheckIsNotDestroyed(); LayoutBox* box_at_top_of_new_branch = nullptr; while (before_child->Parent() != this) { @@ -6839,6 +7100,7 @@ } LayoutUnit LayoutBox::OffsetFromLogicalTopOfFirstPage() const { + CheckIsNotDestroyed(); LayoutState* layout_state = View()->GetLayoutState(); if (!layout_state || !layout_state->IsPaginated()) return LayoutUnit(); @@ -6860,6 +7122,7 @@ } void LayoutBox::SetOffsetToNextPage(LayoutUnit offset) { + CheckIsNotDestroyed(); if (!rare_data_ && !offset) return; EnsureRareData().offset_to_next_page_ = offset; @@ -6868,6 +7131,7 @@ void LayoutBox::LogicalExtentAfterUpdatingLogicalWidth( const LayoutUnit& new_logical_top, LayoutBox::LogicalExtentComputedValues& computed_values) { + CheckIsNotDestroyed(); // FIXME: None of this is right for perpendicular writing-mode children. LayoutUnit old_logical_width = LogicalWidth(); LayoutUnit old_logical_left = LogicalLeft(); @@ -6891,10 +7155,12 @@ } ShapeOutsideInfo* LayoutBox::GetShapeOutsideInfo() const { + CheckIsNotDestroyed(); return ShapeOutsideInfo::Info(*this); } void LayoutBox::SetPercentHeightContainer(LayoutBlock* container) { + CheckIsNotDestroyed(); DCHECK(!container || !PercentHeightContainer()); if (!container && !rare_data_) return; @@ -6902,6 +7168,7 @@ } void LayoutBox::RemoveFromPercentHeightContainer() { + CheckIsNotDestroyed(); if (!PercentHeightContainer()) return; @@ -6913,6 +7180,7 @@ } void LayoutBox::ClearPercentHeightDescendants() { + CheckIsNotDestroyed(); for (LayoutObject* curr = SlowFirstChild(); curr; curr = curr->NextInPreOrder(this)) { if (curr->IsBox()) @@ -6921,6 +7189,7 @@ } LayoutUnit LayoutBox::PageLogicalHeightForOffset(LayoutUnit offset) const { + CheckIsNotDestroyed(); // We need to have calculated some fragmentainer logical height (even a // tentative one will do, though) in order to tell how tall one fragmentainer // is. @@ -6940,6 +7209,7 @@ } bool LayoutBox::IsPageLogicalHeightKnown() const { + CheckIsNotDestroyed(); if (const LayoutFlowThread* flow_thread = FlowThreadContainingBlock()) return flow_thread->IsPageLogicalHeightKnown(); return View()->PageLogicalHeight(); @@ -6948,6 +7218,7 @@ LayoutUnit LayoutBox::PageRemainingLogicalHeightForOffset( LayoutUnit offset, PageBoundaryRule page_boundary_rule) const { + CheckIsNotDestroyed(); DCHECK(IsPageLogicalHeightKnown()); LayoutView* layout_view = View(); offset += OffsetFromLogicalTopOfFirstPage(); @@ -6974,12 +7245,14 @@ } int LayoutBox::CurrentPageNumber(LayoutUnit child_logical_top) const { + CheckIsNotDestroyed(); LayoutUnit offset = OffsetFromLogicalTopOfFirstPage() + child_logical_top; return (offset / View()->PageLogicalHeight()).Floor(); } bool LayoutBox::CrossesPageBoundary(LayoutUnit offset, LayoutUnit logical_height) const { + CheckIsNotDestroyed(); if (!IsPageLogicalHeightKnown()) return false; return PageRemainingLogicalHeightForOffset(offset, kAssociateWithLatterPage) < @@ -6989,6 +7262,7 @@ LayoutUnit LayoutBox::CalculatePaginationStrutToFitContent( LayoutUnit offset, LayoutUnit content_logical_height) const { + CheckIsNotDestroyed(); LayoutUnit strut_to_next_page = PageRemainingLogicalHeightForOffset(offset, kAssociateWithLatterPage); @@ -7028,10 +7302,12 @@ } LayoutBox* LayoutBox::SnapContainer() const { + CheckIsNotDestroyed(); return rare_data_ ? rare_data_->snap_container_ : nullptr; } void LayoutBox::SetSnapContainer(LayoutBox* new_container) { + CheckIsNotDestroyed(); LayoutBox* old_container = SnapContainer(); if (old_container == new_container) return; @@ -7046,6 +7322,7 @@ } void LayoutBox::ClearSnapAreas() { + CheckIsNotDestroyed(); if (SnapAreaSet* areas = SnapAreas()) { for (auto* const snap_area : *areas) snap_area->rare_data_->snap_container_ = nullptr; @@ -7054,10 +7331,12 @@ } void LayoutBox::AddSnapArea(LayoutBox& snap_area) { + CheckIsNotDestroyed(); EnsureRareData().EnsureSnapAreas().insert(&snap_area); } void LayoutBox::RemoveSnapArea(const LayoutBox& snap_area) { + CheckIsNotDestroyed(); // const_cast is safe here because we only need to modify the type to match // the key type, and not actually mutate the object. if (rare_data_ && rare_data_->snap_areas_) @@ -7065,6 +7344,7 @@ } void LayoutBox::ReassignSnapAreas(LayoutBox& new_container) { + CheckIsNotDestroyed(); SnapAreaSet* areas = SnapAreas(); if (!areas) return; @@ -7077,6 +7357,7 @@ bool LayoutBox::AllowedToPropagateRecursiveScrollToParentFrame( const mojom::blink::ScrollIntoViewParamsPtr& params) { + CheckIsNotDestroyed(); if (!GetFrameView()->SafeToPropagateScrollToParent()) return false; @@ -7087,16 +7368,19 @@ } SnapAreaSet* LayoutBox::SnapAreas() const { + CheckIsNotDestroyed(); return rare_data_ ? rare_data_->snap_areas_.get() : nullptr; } CustomLayoutChild* LayoutBox::GetCustomLayoutChild() const { + CheckIsNotDestroyed(); DCHECK(rare_data_); DCHECK(rare_data_->layout_child_); return rare_data_->layout_child_.Get(); } void LayoutBox::AddCustomLayoutChildIfNeeded() { + CheckIsNotDestroyed(); if (!IsCustomItem()) return; @@ -7116,6 +7400,7 @@ } void LayoutBox::ClearCustomLayoutChild() { + CheckIsNotDestroyed(); if (!rare_data_) return; @@ -7126,10 +7411,12 @@ } PhysicalRect LayoutBox::DebugRect() const { + CheckIsNotDestroyed(); return PhysicalRect(PhysicalLocation(), Size()); } bool LayoutBox::ComputeShouldClipOverflow() const { + CheckIsNotDestroyed(); return HasNonVisibleOverflow() || ShouldApplyPaintContainment() || HasControlClip(); } @@ -7173,6 +7460,7 @@ } RasterEffectOutset LayoutBox::VisualRectOutsetForRasterEffects() const { + CheckIsNotDestroyed(); // If the box has subpixel visual effect outsets, as the visual effect may be // painted along the pixel-snapped border box, the pixels on the anti-aliased // edge of the effect may overflow the calculated visual rect. Expand visual @@ -7184,6 +7472,7 @@ } TextDirection LayoutBox::ResolvedDirection() const { + CheckIsNotDestroyed(); if (IsInline() && IsAtomicInlineLevel()) { if (IsInLayoutNGInlineFormattingContext()) { NGInlineCursor cursor; @@ -7199,6 +7488,7 @@ bool LayoutBox::NeedsScrollNode( CompositingReasons direct_compositing_reasons) const { + CheckIsNotDestroyed(); if (!IsScrollContainer()) return false;
diff --git a/third_party/blink/renderer/core/layout/layout_box.h b/third_party/blink/renderer/core/layout/layout_box.h index 7c7bbcc..6c0284acb 100644 --- a/third_party/blink/renderer/core/layout/layout_box.h +++ b/third_party/blink/renderer/core/layout/layout_box.h
@@ -228,7 +228,10 @@ const PhysicalRect& local_rect) const override; bool TextIsKnownToBeOnOpaqueBackground() const override; - virtual bool BackgroundShouldAlwaysBeClipped() const { return false; } + virtual bool BackgroundShouldAlwaysBeClipped() const { + CheckIsNotDestroyed(); + return false; + } // Returns whether this object needs a scroll paint property tree node. These // are a requirement for composited scrolling but are also created for @@ -241,28 +244,38 @@ LayoutBox* LastChildBox() const; // TODO(crbug.com/962299): This is incorrect in some cases. - int PixelSnappedWidth() const { return frame_rect_.PixelSnappedWidth(); } - int PixelSnappedHeight() const { return frame_rect_.PixelSnappedHeight(); } + int PixelSnappedWidth() const { + CheckIsNotDestroyed(); + return frame_rect_.PixelSnappedWidth(); + } + int PixelSnappedHeight() const { + CheckIsNotDestroyed(); + return frame_rect_.PixelSnappedHeight(); + } void SetX(LayoutUnit x) { + CheckIsNotDestroyed(); if (x == frame_rect_.X()) return; frame_rect_.SetX(x); LocationChanged(); } void SetY(LayoutUnit y) { + CheckIsNotDestroyed(); if (y == frame_rect_.Y()) return; frame_rect_.SetY(y); LocationChanged(); } void SetWidth(LayoutUnit width) { + CheckIsNotDestroyed(); if (width == frame_rect_.Width()) return; frame_rect_.SetWidth(width); SizeChanged(); } void SetHeight(LayoutUnit height) { + CheckIsNotDestroyed(); if (height == frame_rect_.Height()) return; frame_rect_.SetHeight(height); @@ -270,20 +283,30 @@ } LayoutUnit LogicalLeft() const { + CheckIsNotDestroyed(); return StyleRef().IsHorizontalWritingMode() ? frame_rect_.X() : frame_rect_.Y(); } - LayoutUnit LogicalRight() const { return LogicalLeft() + LogicalWidth(); } + LayoutUnit LogicalRight() const { + CheckIsNotDestroyed(); + return LogicalLeft() + LogicalWidth(); + } LayoutUnit LogicalTop() const { + CheckIsNotDestroyed(); return StyleRef().IsHorizontalWritingMode() ? frame_rect_.Y() : frame_rect_.X(); } - LayoutUnit LogicalBottom() const { return LogicalTop() + LogicalHeight(); } + LayoutUnit LogicalBottom() const { + CheckIsNotDestroyed(); + return LogicalTop() + LogicalHeight(); + } LayoutUnit LogicalWidth() const { + CheckIsNotDestroyed(); return StyleRef().IsHorizontalWritingMode() ? frame_rect_.Width() : frame_rect_.Height(); } LayoutUnit LogicalHeight() const { + CheckIsNotDestroyed(); return StyleRef().IsHorizontalWritingMode() ? frame_rect_.Height() : frame_rect_.Width(); } @@ -304,49 +327,58 @@ // TODO(crbug.com/962299): This is incorrect in some cases. int PixelSnappedLogicalHeight() const { + CheckIsNotDestroyed(); return StyleRef().IsHorizontalWritingMode() ? PixelSnappedHeight() : PixelSnappedWidth(); } int PixelSnappedLogicalWidth() const { + CheckIsNotDestroyed(); return StyleRef().IsHorizontalWritingMode() ? PixelSnappedWidth() : PixelSnappedHeight(); } LayoutUnit MinimumLogicalHeightForEmptyLine() const { + CheckIsNotDestroyed(); return BorderAndPaddingLogicalHeight() + ComputeLogicalScrollbars().BlockSum() + LogicalHeightForEmptyLine(); } LayoutUnit LogicalHeightForEmptyLine() const { + CheckIsNotDestroyed(); return LineHeight( true, IsHorizontalWritingMode() ? kHorizontalLine : kVerticalLine, kPositionOfInteriorLineBoxes); } void SetLogicalLeft(LayoutUnit left) { + CheckIsNotDestroyed(); if (StyleRef().IsHorizontalWritingMode()) SetX(left); else SetY(left); } void SetLogicalTop(LayoutUnit top) { + CheckIsNotDestroyed(); if (StyleRef().IsHorizontalWritingMode()) SetY(top); else SetX(top); } void SetLogicalLocation(const LayoutPoint& location) { + CheckIsNotDestroyed(); if (StyleRef().IsHorizontalWritingMode()) SetLocation(location); else SetLocation(location.TransposedPoint()); } void SetLogicalWidth(LayoutUnit size) { + CheckIsNotDestroyed(); if (StyleRef().IsHorizontalWritingMode()) SetWidth(size); else SetHeight(size); } void SetLogicalHeight(LayoutUnit size) { + CheckIsNotDestroyed(); if (StyleRef().IsHorizontalWritingMode()) SetHeight(size); else @@ -354,15 +386,26 @@ } // See frame_rect_. - LayoutPoint Location() const { return frame_rect_.Location(); } + LayoutPoint Location() const { + CheckIsNotDestroyed(); + return frame_rect_.Location(); + } LayoutSize LocationOffset() const { + CheckIsNotDestroyed(); return LayoutSize(frame_rect_.X(), frame_rect_.Y()); } - LayoutSize Size() const { return frame_rect_.Size(); } + LayoutSize Size() const { + CheckIsNotDestroyed(); + return frame_rect_.Size(); + } // TODO(crbug.com/962299): This is incorrect in some cases. - IntSize PixelSnappedSize() const { return frame_rect_.PixelSnappedSize(); } + IntSize PixelSnappedSize() const { + CheckIsNotDestroyed(); + return frame_rect_.PixelSnappedSize(); + } void SetLocation(const LayoutPoint& location) { + CheckIsNotDestroyed(); if (location == frame_rect_.Location()) return; frame_rect_.SetLocation(location); @@ -381,12 +424,14 @@ void SetLocationAndUpdateOverflowControlsIfNeeded(const LayoutPoint&); void SetSize(const LayoutSize& size) { + CheckIsNotDestroyed(); if (size == frame_rect_.Size()) return; frame_rect_.SetSize(size); SizeChanged(); } void Move(LayoutUnit dx, LayoutUnit dy) { + CheckIsNotDestroyed(); if (!dx && !dy) return; frame_rect_.Move(dx, dy); @@ -394,8 +439,12 @@ } // See frame_rect_. - LayoutRect FrameRect() const { return frame_rect_; } + LayoutRect FrameRect() const { + CheckIsNotDestroyed(); + return frame_rect_; + } void SetFrameRect(const LayoutRect& rect) { + CheckIsNotDestroyed(); SetLocation(rect.Location()); SetSize(rect.Size()); } @@ -405,8 +454,12 @@ // coordinate space, it can be treated as in either physical coordinates // or "physical coordinates in flipped block-flow direction", and // FlipForWritingMode() will do nothing on it. - LayoutRect BorderBoxRect() const { return LayoutRect(LayoutPoint(), Size()); } + LayoutRect BorderBoxRect() const { + CheckIsNotDestroyed(); + return LayoutRect(LayoutPoint(), Size()); + } PhysicalRect PhysicalBorderBoxRect() const { + CheckIsNotDestroyed(); // This doesn't need flipping because the result would be the same. DCHECK_EQ(PhysicalRect(BorderBoxRect()), FlipForWritingMode(BorderBoxRect())); @@ -417,6 +470,7 @@ // TODO(crbug.com/877518): Some callers of this method may actually want // "physical coordinates in flipped block-flow direction". DISABLE_CFI_PERF PhysicalRect PhysicalPaddingBoxRect() const { + CheckIsNotDestroyed(); return PhysicalRect(ClientLeft(), ClientTop(), ClientWidth(), ClientHeight()); } @@ -425,15 +479,18 @@ // Location() is not the correct paint offset. It's also incorrect in flipped // blocks writing mode. IntRect PixelSnappedBorderBoxRect() const { + CheckIsNotDestroyed(); return IntRect(IntPoint(), PixelSnappedBorderBoxSize(PhysicalOffset(Location()))); } // TODO(crbug.com/962299): This method is only correct when |offset| is the // correct paint offset. IntSize PixelSnappedBorderBoxSize(const PhysicalOffset& offset) const { + CheckIsNotDestroyed(); return PixelSnappedIntSize(Size(), offset.ToLayoutPoint()); } IntRect BorderBoundingBox() const final { + CheckIsNotDestroyed(); return PixelSnappedBorderBoxRect(); } @@ -442,12 +499,14 @@ // TODO(crbug.com/877518): Some callers of this method may actually want // "physical coordinates in flipped block-flow direction". DISABLE_CFI_PERF PhysicalRect PhysicalContentBoxRect() const { + CheckIsNotDestroyed(); return PhysicalRect(ContentLeft(), ContentTop(), ContentWidth(), ContentHeight()); } // TODO(crbug.com/877518): Some callers of this method may actually want // "physical coordinates in flipped block-flow direction". PhysicalOffset PhysicalContentBoxOffset() const { + CheckIsNotDestroyed(); return PhysicalOffset(ContentLeft(), ContentTop()); } // The content box converted to absolute coords (taking transforms into @@ -464,6 +523,7 @@ // does include the intrinsic padding in the content box as this is what some // callers expect (like getComputedStyle). LayoutRect ComputedCSSContentBoxRect() const { + CheckIsNotDestroyed(); return LayoutRect( BorderLeft() + ComputedCSSPaddingLeft(), BorderTop() + ComputedCSSPaddingTop(), @@ -499,6 +559,7 @@ bool ShouldComputeLogicalWidthFromAspectRatio( LayoutUnit* logical_height = nullptr) const; bool ShouldComputeLogicalHeightFromAspectRatio() const { + CheckIsNotDestroyed(); Length h = StyleRef().LogicalHeight(); return StyleRef().AspectRatio() && (h.IsAuto() || @@ -513,48 +574,59 @@ // in the "physical coordinates in flipped block-flow direction" of the box. LayoutRect NoOverflowRect() const; LayoutRect LayoutOverflowRect() const { + CheckIsNotDestroyed(); return LayoutOverflowIsSet() ? overflow_->layout_overflow->LayoutOverflowRect() : NoOverflowRect(); } PhysicalRect PhysicalLayoutOverflowRect() const { + CheckIsNotDestroyed(); return FlipForWritingMode(LayoutOverflowRect()); } // TODO(crbug.com/962299): This is incorrect in some cases. IntRect PixelSnappedLayoutOverflowRect() const { + CheckIsNotDestroyed(); return PixelSnappedIntRect(LayoutOverflowRect()); } LayoutSize MaxLayoutOverflow() const { + CheckIsNotDestroyed(); return LayoutSize(LayoutOverflowRect().MaxX(), LayoutOverflowRect().MaxY()); } LayoutRect VisualOverflowRect() const; PhysicalRect PhysicalVisualOverflowRect() const final { + CheckIsNotDestroyed(); return FlipForWritingMode(VisualOverflowRect()); } LayoutUnit LogicalLeftVisualOverflow() const { + CheckIsNotDestroyed(); return StyleRef().IsHorizontalWritingMode() ? VisualOverflowRect().X() : VisualOverflowRect().Y(); } LayoutUnit LogicalRightVisualOverflow() const { + CheckIsNotDestroyed(); return StyleRef().IsHorizontalWritingMode() ? VisualOverflowRect().MaxX() : VisualOverflowRect().MaxY(); } LayoutRect SelfVisualOverflowRect() const { + CheckIsNotDestroyed(); return VisualOverflowIsSet() ? overflow_->visual_overflow->SelfVisualOverflowRect() : BorderBoxRect(); } PhysicalRect PhysicalSelfVisualOverflowRect() const { + CheckIsNotDestroyed(); return FlipForWritingMode(SelfVisualOverflowRect()); } LayoutRect ContentsVisualOverflowRect() const { + CheckIsNotDestroyed(); return VisualOverflowIsSet() ? overflow_->visual_overflow->ContentsVisualOverflowRect() : LayoutRect(); } PhysicalRect PhysicalContentsVisualOverflowRect() const { + CheckIsNotDestroyed(); return FlipForWritingMode(ContentsVisualOverflowRect()); } @@ -572,10 +644,12 @@ void AddLayoutOverflow(const LayoutRect&); void AddSelfVisualOverflow(const PhysicalRect& r) { + CheckIsNotDestroyed(); AddSelfVisualOverflow(FlipForWritingMode(r)); } void AddSelfVisualOverflow(const LayoutRect&); void AddContentsVisualOverflow(const PhysicalRect& r) { + CheckIsNotDestroyed(); AddContentsVisualOverflow(FlipForWritingMode(r)); } void AddContentsVisualOverflow(const LayoutRect&); @@ -583,9 +657,11 @@ void AddVisualEffectOverflow(); LayoutRectOutsets ComputeVisualEffectOverflowOutsets(); void AddVisualOverflowFromChild(const LayoutBox& child) { + CheckIsNotDestroyed(); AddVisualOverflowFromChild(child, child.LocationOffset()); } void AddLayoutOverflowFromChild(const LayoutBox& child) { + CheckIsNotDestroyed(); AddLayoutOverflowFromChild(child, child.LocationOffset()); } void AddVisualOverflowFromChild(const LayoutBox& child, @@ -601,12 +677,15 @@ virtual void UpdateAfterLayout(); DISABLE_CFI_PERF LayoutUnit ContentLeft() const { + CheckIsNotDestroyed(); return ClientLeft() + PaddingLeft(); } DISABLE_CFI_PERF LayoutUnit ContentTop() const { + CheckIsNotDestroyed(); return ClientTop() + PaddingTop(); } DISABLE_CFI_PERF LayoutUnit ContentWidth() const { + CheckIsNotDestroyed(); // We're dealing with LayoutUnit and saturated arithmetic here, so we need // to guard against negative results. The value returned from clientWidth() // may in itself be a victim of saturated arithmetic; e.g. if both border @@ -617,6 +696,7 @@ .ClampNegativeToZero(); } DISABLE_CFI_PERF LayoutUnit ContentHeight() const { + CheckIsNotDestroyed(); // We're dealing with LayoutUnit and saturated arithmetic here, so we need // to guard against negative results. The value returned from clientHeight() // may in itself be a victim of saturated arithmetic; e.g. if both border @@ -627,13 +707,16 @@ .ClampNegativeToZero(); } LayoutSize ContentSize() const { + CheckIsNotDestroyed(); return LayoutSize(ContentWidth(), ContentHeight()); } LayoutUnit ContentLogicalWidth() const { + CheckIsNotDestroyed(); return StyleRef().IsHorizontalWritingMode() ? ContentWidth() : ContentHeight(); } LayoutUnit ContentLogicalHeight() const { + CheckIsNotDestroyed(); return StyleRef().IsHorizontalWritingMode() ? ContentHeight() : ContentWidth(); } @@ -647,21 +730,25 @@ LayoutUnit OverrideIntrinsicContentHeight() const; // Logical: bool HasOverrideIntrinsicContentLogicalWidth() const { + CheckIsNotDestroyed(); return StyleRef().IsHorizontalWritingMode() ? HasOverrideIntrinsicContentWidth() : HasOverrideIntrinsicContentHeight(); } bool HasOverrideIntrinsicContentLogicalHeight() const { + CheckIsNotDestroyed(); return StyleRef().IsHorizontalWritingMode() ? HasOverrideIntrinsicContentHeight() : HasOverrideIntrinsicContentWidth(); } LayoutUnit OverrideIntrinsicContentLogicalWidth() const { + CheckIsNotDestroyed(); return StyleRef().IsHorizontalWritingMode() ? OverrideIntrinsicContentWidth() : OverrideIntrinsicContentHeight(); } LayoutUnit OverrideIntrinsicContentLogicalHeight() const { + CheckIsNotDestroyed(); return StyleRef().IsHorizontalWritingMode() ? OverrideIntrinsicContentHeight() : OverrideIntrinsicContentWidth(); @@ -675,14 +762,21 @@ // IE extensions. Used to calculate offsetWidth/Height. Overridden by inlines // (LayoutFlow) to return the remaining width on a given line (and the height // of a single line). - LayoutUnit OffsetWidth() const final { return frame_rect_.Width(); } - LayoutUnit OffsetHeight() const final { return frame_rect_.Height(); } + LayoutUnit OffsetWidth() const final { + CheckIsNotDestroyed(); + return frame_rect_.Width(); + } + LayoutUnit OffsetHeight() const final { + CheckIsNotDestroyed(); + return frame_rect_.Height(); + } // TODO(crbug.com/962299): This is incorrect in some cases. int PixelSnappedOffsetWidth(const Element*) const final; int PixelSnappedOffsetHeight(const Element*) const final; bool UsesOverlayScrollbars() const { + CheckIsNotDestroyed(); if (StyleRef().HasPseudoElementStyle(kPseudoIdScrollbar)) return false; if (GetFrame()->GetPage()->GetScrollbarTheme().UsesOverlayScrollbars()) @@ -692,6 +786,7 @@ // Clamps the left scrollbar size so it is not wider than the content box. DISABLE_CFI_PERF LayoutUnit LogicalLeftScrollbarWidth() const { + CheckIsNotDestroyed(); if (CanSkipComputeScrollbars()) return LayoutUnit(); else if (StyleRef().IsHorizontalWritingMode()) @@ -700,6 +795,7 @@ return ComputeScrollbarsInternal(kClampToContentBox).top; } DISABLE_CFI_PERF LayoutUnit LogicalTopScrollbarHeight() const { + CheckIsNotDestroyed(); if (CanSkipComputeScrollbars()) return LayoutUnit(); else if (HasFlippedBlocksWritingMode()) @@ -713,12 +809,14 @@ // interior of an object excluding borders and scrollbars. // Clamps the left scrollbar size so it is not wider than the content box. DISABLE_CFI_PERF LayoutUnit ClientLeft() const { + CheckIsNotDestroyed(); if (CanSkipComputeScrollbars()) return BorderLeft(); else return BorderLeft() + ComputeScrollbarsInternal(kClampToContentBox).left; } DISABLE_CFI_PERF LayoutUnit ClientTop() const { + CheckIsNotDestroyed(); if (CanSkipComputeScrollbars()) return BorderTop(); else @@ -727,12 +825,15 @@ LayoutUnit ClientWidth() const; LayoutUnit ClientHeight() const; DISABLE_CFI_PERF LayoutUnit ClientLogicalWidth() const { + CheckIsNotDestroyed(); return IsHorizontalWritingMode() ? ClientWidth() : ClientHeight(); } DISABLE_CFI_PERF LayoutUnit ClientLogicalHeight() const { + CheckIsNotDestroyed(); return IsHorizontalWritingMode() ? ClientHeight() : ClientWidth(); } DISABLE_CFI_PERF LayoutUnit ClientLogicalBottom() const { + CheckIsNotDestroyed(); return BorderBefore() + LogicalTopScrollbarHeight() + ClientLogicalHeight(); } @@ -764,39 +865,62 @@ const PhysicalRect&, mojom::blink::ScrollIntoViewParamsPtr); - LayoutRectOutsets MarginBoxOutsets() const { return margin_box_outsets_; } - LayoutUnit MarginTop() const override { return margin_box_outsets_.Top(); } + LayoutRectOutsets MarginBoxOutsets() const { + CheckIsNotDestroyed(); + return margin_box_outsets_; + } + LayoutUnit MarginTop() const override { + CheckIsNotDestroyed(); + return margin_box_outsets_.Top(); + } LayoutUnit MarginBottom() const override { + CheckIsNotDestroyed(); return margin_box_outsets_.Bottom(); } - LayoutUnit MarginLeft() const override { return margin_box_outsets_.Left(); } + LayoutUnit MarginLeft() const override { + CheckIsNotDestroyed(); + return margin_box_outsets_.Left(); + } LayoutUnit MarginRight() const override { + CheckIsNotDestroyed(); return margin_box_outsets_.Right(); } void SetMargin(const NGPhysicalBoxStrut&); - void SetMarginTop(LayoutUnit margin) { margin_box_outsets_.SetTop(margin); } + void SetMarginTop(LayoutUnit margin) { + CheckIsNotDestroyed(); + margin_box_outsets_.SetTop(margin); + } void SetMarginBottom(LayoutUnit margin) { + CheckIsNotDestroyed(); margin_box_outsets_.SetBottom(margin); } - void SetMarginLeft(LayoutUnit margin) { margin_box_outsets_.SetLeft(margin); } + void SetMarginLeft(LayoutUnit margin) { + CheckIsNotDestroyed(); + margin_box_outsets_.SetLeft(margin); + } void SetMarginRight(LayoutUnit margin) { + CheckIsNotDestroyed(); margin_box_outsets_.SetRight(margin); } void SetMarginBefore(LayoutUnit value, const ComputedStyle* override_style = nullptr) { + CheckIsNotDestroyed(); LogicalMarginToPhysicalSetter(override_style).SetBefore(value); } void SetMarginAfter(LayoutUnit value, const ComputedStyle* override_style = nullptr) { + CheckIsNotDestroyed(); LogicalMarginToPhysicalSetter(override_style).SetAfter(value); } void SetMarginStart(LayoutUnit value, const ComputedStyle* override_style = nullptr) { + CheckIsNotDestroyed(); LogicalMarginToPhysicalSetter(override_style).SetStart(value); } void SetMarginEnd(LayoutUnit value, const ComputedStyle* override_style = nullptr) { + CheckIsNotDestroyed(); LogicalMarginToPhysicalSetter(override_style).SetEnd(value); } @@ -806,10 +930,20 @@ // For a non-collapsing box, such as a leaf element, this formula will simply // return the margin of the element. Blocks override the maxMarginBefore and // maxMarginAfter methods. - virtual bool IsSelfCollapsingBlock() const { return false; } - virtual LayoutUnit CollapsedMarginBefore() const { return MarginBefore(); } - virtual LayoutUnit CollapsedMarginAfter() const { return MarginAfter(); } + virtual bool IsSelfCollapsingBlock() const { + CheckIsNotDestroyed(); + return false; + } + virtual LayoutUnit CollapsedMarginBefore() const { + CheckIsNotDestroyed(); + return MarginBefore(); + } + virtual LayoutUnit CollapsedMarginAfter() const { + CheckIsNotDestroyed(); + return MarginAfter(); + } LayoutRectOutsets CollapsedMarginBoxLogicalOutsets() const { + CheckIsNotDestroyed(); return LayoutRectOutsets(CollapsedMarginBefore(), LayoutUnit(), CollapsedMarginAfter(), LayoutUnit()); } @@ -819,9 +953,11 @@ FloatRect LocalBoundingBoxRectForAccessibility() const final; void SetBoxLayoutExtraInput(const BoxLayoutExtraInput* input) { + CheckIsNotDestroyed(); extra_input_ = input; } const BoxLayoutExtraInput* GetBoxLayoutExtraInput() const { + CheckIsNotDestroyed(); return extra_input_; } @@ -831,6 +967,7 @@ void Paint(const PaintInfo&) const override; virtual bool IsInSelfHitTestingPhase(HitTestAction hit_test_action) const { + CheckIsNotDestroyed(); return hit_test_action == kHitTestForeground; } @@ -887,7 +1024,10 @@ // available inline size, rather than deducing it from the containing block // (and then subtract space taken up by adjacent floats). LayoutUnit OverrideAvailableInlineSize() const; - bool HasOverrideAvailableInlineSize() const { return extra_input_; } + bool HasOverrideAvailableInlineSize() const { + CheckIsNotDestroyed(); + return extra_input_; + } LayoutUnit AdjustBorderBoxLogicalWidthForBoxSizing(float width) const; LayoutUnit AdjustBorderBoxLogicalHeightForBoxSizing(float height) const; @@ -959,6 +1099,7 @@ // first fragmentainer it lives in. If it only lives in one fragmentainer, 0 // is returned. LayoutUnit OffsetToNextPage() const { + CheckIsNotDestroyed(); return rare_data_ ? rare_data_->offset_to_next_page_ : LayoutUnit(); } void SetOffsetToNextPage(LayoutUnit); @@ -1084,16 +1225,21 @@ }; NGPhysicalFragmentList PhysicalFragments() const { + CheckIsNotDestroyed(); return NGPhysicalFragmentList(layout_results_); } const NGPhysicalBoxFragment* GetPhysicalFragment(wtf_size_t i) const; const FragmentData* FragmentDataFromPhysicalFragment( const NGPhysicalBoxFragment&) const; - wtf_size_t PhysicalFragmentCount() const { return layout_results_.size(); } + wtf_size_t PhysicalFragmentCount() const { + CheckIsNotDestroyed(); + return layout_results_.size(); + } void SetSpannerPlaceholder(LayoutMultiColumnSpannerPlaceholder&); void ClearSpannerPlaceholder(); LayoutMultiColumnSpannerPlaceholder* SpannerPlaceholder() const final { + CheckIsNotDestroyed(); return rare_data_ ? rare_data_->spanner_placeholder_ : nullptr; } @@ -1108,10 +1254,12 @@ // Pagination struts are either set in front of a block-level box (here) or // before a line (RootInlineBox::paginationStrut()). LayoutUnit PaginationStrut() const { + CheckIsNotDestroyed(); return rare_data_ ? rare_data_->pagination_strut_ : LayoutUnit(); } void SetPaginationStrut(LayoutUnit); void ResetPaginationStrut() { + CheckIsNotDestroyed(); if (rare_data_) rare_data_->pagination_strut_ = LayoutUnit(); } @@ -1179,19 +1327,26 @@ void ComputeLogicalWidth(LogicalExtentComputedValues&) const; bool StretchesToViewport() const { + CheckIsNotDestroyed(); return GetDocument().InQuirksMode() && StretchesToViewportInQuirksMode(); } - virtual LayoutSize IntrinsicSize() const { return LayoutSize(); } + virtual LayoutSize IntrinsicSize() const { + CheckIsNotDestroyed(); + return LayoutSize(); + } LayoutUnit IntrinsicLogicalWidth() const { + CheckIsNotDestroyed(); return StyleRef().IsHorizontalWritingMode() ? IntrinsicSize().Width() : IntrinsicSize().Height(); } LayoutUnit IntrinsicLogicalHeight() const { + CheckIsNotDestroyed(); return StyleRef().IsHorizontalWritingMode() ? IntrinsicSize().Height() : IntrinsicSize().Width(); } virtual LayoutUnit IntrinsicContentLogicalHeight() const { + CheckIsNotDestroyed(); return HasOverrideIntrinsicContentLogicalHeight() ? OverrideIntrinsicContentLogicalHeight() : intrinsic_content_logical_height_; @@ -1240,6 +1395,7 @@ LayoutUnit estimated_used_width = LayoutUnit()) const; virtual bool ShouldComputeSizeAsReplaced() const { + CheckIsNotDestroyed(); return IsAtomicInlineLevel() && !IsInlineBlockOrInlineTable(); } @@ -1258,7 +1414,10 @@ // Block flows subclass availableWidth/Height to handle multi column layout // (shrinking the width/height available to children when laying out.) - LayoutUnit AvailableLogicalWidth() const { return ContentLogicalWidth(); } + LayoutUnit AvailableLogicalWidth() const { + CheckIsNotDestroyed(); + return ContentLogicalWidth(); + } LayoutUnit AvailableLogicalHeight(AvailableLogicalHeightType) const; LayoutUnit AvailableLogicalHeightUsing(const Length&, AvailableLogicalHeightType) const; @@ -1267,11 +1426,13 @@ // physical width and available physical height. Relative positioning is one // of those cases, since left/top offsets are physical. LayoutUnit AvailableWidth() const { + CheckIsNotDestroyed(); return StyleRef().IsHorizontalWritingMode() ? AvailableLogicalWidth() : AvailableLogicalHeight(kIncludeMarginBorderPadding); } LayoutUnit AvailableHeight() const { + CheckIsNotDestroyed(); return StyleRef().IsHorizontalWritingMode() ? AvailableLogicalHeight(kIncludeMarginBorderPadding) : AvailableLogicalWidth(); @@ -1279,12 +1440,14 @@ // Return both scrollbars and scrollbar gutters (defined by scrollbar-gutter). inline NGPhysicalBoxStrut ComputeScrollbars() const { + CheckIsNotDestroyed(); if (CanSkipComputeScrollbars()) return NGPhysicalBoxStrut(); else return ComputeScrollbarsInternal(); } inline NGBoxStrut ComputeLogicalScrollbars() const { + CheckIsNotDestroyed(); if (CanSkipComputeScrollbars()) { return NGBoxStrut(); } else { @@ -1303,12 +1466,15 @@ bool is_middle_click_autoscroll); DISABLE_CFI_PERF bool HasAutoVerticalScrollbar() const { + CheckIsNotDestroyed(); return HasNonVisibleOverflow() && StyleRef().HasAutoVerticalScroll(); } DISABLE_CFI_PERF bool HasAutoHorizontalScrollbar() const { + CheckIsNotDestroyed(); return HasNonVisibleOverflow() && StyleRef().HasAutoHorizontalScroll(); } DISABLE_CFI_PERF bool ScrollsOverflow() const { + CheckIsNotDestroyed(); return HasNonVisibleOverflow() && StyleRef().ScrollsOverflow(); } // We place block-direction scrollbar on the left only if the writing-mode @@ -1317,24 +1483,30 @@ // used in different contexts, e.g. the former for physical coordinate // contexts, and the later for logical coordinate contexts. bool ShouldPlaceVerticalScrollbarOnLeft() const { + CheckIsNotDestroyed(); return ShouldPlaceBlockDirectionScrollbarOnLogicalLeft(); } virtual bool ShouldPlaceBlockDirectionScrollbarOnLogicalLeft() const { + CheckIsNotDestroyed(); return StyleRef().ShouldPlaceBlockDirectionScrollbarOnLogicalLeft(); } bool HasScrollableOverflowX() const { + CheckIsNotDestroyed(); return ScrollsOverflowX() && PixelSnappedScrollWidth() != PixelSnappedClientWidth(); } bool HasScrollableOverflowY() const { + CheckIsNotDestroyed(); return ScrollsOverflowY() && PixelSnappedScrollHeight() != PixelSnappedClientHeight(); } virtual bool ScrollsOverflowX() const { + CheckIsNotDestroyed(); return HasNonVisibleOverflow() && StyleRef().ScrollsOverflowX(); } virtual bool ScrollsOverflowY() const { + CheckIsNotDestroyed(); return HasNonVisibleOverflow() && StyleRef().ScrollsOverflowY(); } @@ -1342,6 +1514,7 @@ // scrollable outside the context of the CSS overflow style virtual bool IsIntrinsicallyScrollable( ScrollbarOrientation orientation) const { + CheckIsNotDestroyed(); return false; } @@ -1369,9 +1542,11 @@ virtual PaginationBreakability GetPaginationBreakability( FragmentationEngine) const; PaginationBreakability GetLegacyPaginationBreakability() const { + CheckIsNotDestroyed(); return GetPaginationBreakability(kLegacyFragmentationEngine); } PaginationBreakability GetNGPaginationBreakability() const { + CheckIsNotDestroyed(); return GetPaginationBreakability(kNGFragmentationEngine); } @@ -1391,6 +1566,7 @@ LayoutRect OverflowClipRect(const LayoutPoint& location, OverlayScrollbarClipBehavior behavior = kIgnoreOverlayScrollbarSize) const { + CheckIsNotDestroyed(); return OverflowClipRect(PhysicalOffset(location), behavior).ToLayoutRect(); } @@ -1417,14 +1593,21 @@ const LayoutBlock& EnclosingScrollportBox() const; - virtual LayoutUnit FirstLineBoxBaseline() const { return LayoutUnit(-1); } + virtual LayoutUnit FirstLineBoxBaseline() const { + CheckIsNotDestroyed(); + return LayoutUnit(-1); + } virtual LayoutUnit InlineBlockBaseline(LineDirectionMode) const { + CheckIsNotDestroyed(); return LayoutUnit(-1); } // Returns -1 if we should skip this box when computing the baseline of an // inline-block. bool ShrinkToAvoidFloats() const; - virtual bool CreatesNewFormattingContext() const { return true; } + virtual bool CreatesNewFormattingContext() const { + CheckIsNotDestroyed(); + return true; + } bool ShouldBeConsideredAsReplaced() const; void UpdateFragmentationInfoForChild(LayoutBox&); @@ -1432,10 +1615,12 @@ void MarkChildForPaginationRelayoutIfNeeded(LayoutBox&, SubtreeLayoutScope&); bool IsWritingModeRoot() const { + CheckIsNotDestroyed(); return !Parent() || Parent()->StyleRef().GetWritingMode() != StyleRef().GetWritingMode(); } bool IsOrthogonalWritingModeRoot() const { + CheckIsNotDestroyed(); return Parent() && Parent()->IsHorizontalWritingMode() != IsHorizontalWritingMode(); } @@ -1446,6 +1631,7 @@ bool IsCustomItemShrinkToFit() const; bool IsFlexItemIncludingDeprecatedAndNG() const { + CheckIsNotDestroyed(); return IsFlexItemCommon() && Parent()->IsFlexibleBoxIncludingDeprecatedAndNG(); } @@ -1454,22 +1640,32 @@ // IsFlexItemIncludingNG when all the callsites can handle an item with an NG // parent. bool IsFlexItem() const { + CheckIsNotDestroyed(); return IsFlexItemCommon() && Parent()->IsFlexibleBox(); } bool IsFlexItemIncludingNG() const { + CheckIsNotDestroyed(); return IsFlexItemCommon() && Parent()->IsFlexibleBoxIncludingNG(); } bool IsFlexItemCommon() const { + CheckIsNotDestroyed(); return !IsInline() && !IsOutOfFlowPositioned() && Parent(); } bool IsGridItemIncludingNG() const { + CheckIsNotDestroyed(); return IsGridItem() || (Parent() && Parent()->IsLayoutNGGrid()); } - bool IsGridItem() const { return Parent() && Parent()->IsLayoutGrid(); } + bool IsGridItem() const { + CheckIsNotDestroyed(); + return Parent() && Parent()->IsLayoutGrid(); + } - bool IsMathItem() const { return Parent() && Parent()->IsMathML(); } + bool IsMathItem() const { + CheckIsNotDestroyed(); + return Parent() && Parent()->IsMathML(); + } LayoutUnit LineHeight( bool first_line, @@ -1488,6 +1684,7 @@ WARN_UNUSED_RESULT LayoutUnit FlipForWritingMode(LayoutUnit position, LayoutUnit width = LayoutUnit()) const { + CheckIsNotDestroyed(); // The offset is in the block direction (y for horizontal writing modes, x // for vertical writing modes). if (LIKELY(!HasFlippedBlocksWritingMode())) @@ -1500,9 +1697,11 @@ WARN_UNUSED_RESULT LayoutPoint DeprecatedFlipForWritingMode(const LayoutPoint& position) const { + CheckIsNotDestroyed(); return LayoutPoint(FlipForWritingMode(position.X()), position.Y()); } void DeprecatedFlipForWritingMode(LayoutRect& rect) const { + CheckIsNotDestroyed(); if (LIKELY(!HasFlippedBlocksWritingMode())) return; rect = FlipForWritingMode(rect).ToLayoutRect(); @@ -1512,6 +1711,7 @@ // that container, or LocationContainer() otherwise. PhysicalOffset PhysicalLocation( const LayoutBox* flipped_blocks_container = nullptr) const { + CheckIsNotDestroyed(); return PhysicalLocationInternal(flipped_blocks_container ? flipped_blocks_container : LocationContainer()); @@ -1523,6 +1723,7 @@ LayoutRect LogicalVisualOverflowRectForPropagation() const; LayoutRect VisualOverflowRectForPropagation() const { + CheckIsNotDestroyed(); return RectForOverflowPropagation(VisualOverflowRect()); } LayoutRect LogicalLayoutOverflowRectForPropagation( @@ -1530,13 +1731,20 @@ LayoutRect LayoutOverflowRectForPropagation(LayoutObject* container) const; bool HasSelfVisualOverflow() const { + CheckIsNotDestroyed(); return VisualOverflowIsSet() && !BorderBoxRect().Contains( overflow_->visual_overflow->SelfVisualOverflowRect()); } - bool HasVisualOverflow() const { return VisualOverflowIsSet(); } - bool HasLayoutOverflow() const { return LayoutOverflowIsSet(); } + bool HasVisualOverflow() const { + CheckIsNotDestroyed(); + return VisualOverflowIsSet(); + } + bool HasLayoutOverflow() const { + CheckIsNotDestroyed(); + return LayoutOverflowIsSet(); + } // Return true if re-laying out the containing block of this object means that // we need to recalculate the preferred min/max logical widths of this object. @@ -1600,23 +1808,27 @@ virtual LayoutBox* CreateAnonymousBoxWithSameTypeAs( const LayoutObject*) const { + CheckIsNotDestroyed(); NOTREACHED(); return nullptr; } bool HasSameDirectionAs(const LayoutBox* object) const { + CheckIsNotDestroyed(); return StyleRef().Direction() == object->StyleRef().Direction(); } ShapeOutsideInfo* GetShapeOutsideInfo() const; void MarkShapeOutsideDependentsForLayout() { + CheckIsNotDestroyed(); if (IsFloating()) RemoveFloatingOrPositionedChildFromBlockLists(); } void SetIntrinsicContentLogicalHeight( LayoutUnit intrinsic_content_logical_height) const { + CheckIsNotDestroyed(); intrinsic_content_logical_height_ = intrinsic_content_logical_height; } @@ -1630,6 +1842,7 @@ MapCoordinatesFlags) const override; LayoutBlock* PercentHeightContainer() const { + CheckIsNotDestroyed(); return rare_data_ ? rare_data_->percent_height_container_ : nullptr; } void SetPercentHeightContainer(LayoutBlock*); @@ -1658,6 +1871,7 @@ virtual bool HitTestOverflowControl(HitTestResult&, const HitTestLocation&, const PhysicalOffset&) const { + CheckIsNotDestroyed(); return false; } @@ -1710,27 +1924,35 @@ }; MutableForPainting GetMutableForPainting() const { + CheckIsNotDestroyed(); return MutableForPainting(*this); } - LayoutSize PreviousSize() const { return previous_size_; } + LayoutSize PreviousSize() const { + CheckIsNotDestroyed(); + return previous_size_; + } PhysicalRect PreviousPhysicalContentBoxRect() const { + CheckIsNotDestroyed(); return rare_data_ && rare_data_->has_previous_content_box_rect_ ? rare_data_->previous_physical_content_box_rect_ : PhysicalRect(PhysicalOffset(), PreviousSize()); } bool PreviouslyHadNonVisibleOverflow() const { + CheckIsNotDestroyed(); return overflow_ && overflow_->previous_overflow_data && overflow_->previous_overflow_data ->previously_had_non_visible_overflow; } PhysicalRect PreviousPhysicalLayoutOverflowRect() const { + CheckIsNotDestroyed(); return overflow_ && overflow_->previous_overflow_data ? overflow_->previous_overflow_data ->previous_physical_layout_overflow_rect : PhysicalRect(PhysicalOffset(), PreviousSize()); } PhysicalRect PreviousPhysicalSelfVisualOverflowRect() const { + CheckIsNotDestroyed(); return overflow_ && overflow_->previous_overflow_data ? overflow_->previous_overflow_data ->previous_physical_self_visual_overflow_rect @@ -1769,6 +1991,7 @@ bool depends_on_percentage_block_size, bool child_depends_on_percentage_block_size, const MinMaxSizes* sizes) { + CheckIsNotDestroyed(); intrinsic_logical_widths_percentage_resolution_block_size_ = intrinsic_logical_widths_percentage_resolution_block_size; SetIntrinsicLogicalWidthsDependsOnPercentageBlockSize( @@ -1786,6 +2009,7 @@ // For non-LayoutNG code this is always LayoutUnit::Min(), and should not be // used for caching purposes. LayoutUnit IntrinsicLogicalWidthsPercentageResolutionBlockSize() const { + CheckIsNotDestroyed(); return intrinsic_logical_widths_percentage_resolution_block_size_; } @@ -1797,6 +2021,7 @@ // a small region of a canvas changes. void InvalidatePaintRectangle(const PhysicalRect&); bool HasPartialInvalidationRect() const { + CheckIsNotDestroyed(); return rare_data_ && !rare_data_->partial_invalidation_rect_.IsEmpty(); } @@ -1819,6 +2044,7 @@ virtual ItemPosition SelfAlignmentNormalBehavior( const LayoutBox* child = nullptr) const { + CheckIsNotDestroyed(); DCHECK(!child); return ItemPosition::kStretch; } @@ -1907,13 +2133,16 @@ private: bool HasFragmentItems() const { + CheckIsNotDestroyed(); return ChildrenInline() && PhysicalFragments().HasFragmentItems(); } inline bool LayoutOverflowIsSet() const { + CheckIsNotDestroyed(); return overflow_ && overflow_->layout_overflow; } inline bool VisualOverflowIsSet() const { + CheckIsNotDestroyed(); return overflow_ && overflow_->visual_overflow; } @@ -1962,6 +2191,7 @@ LayoutUnit& margin_end) const; LayoutBoxRareData& EnsureRareData() { + CheckIsNotDestroyed(); if (!rare_data_) rare_data_ = MakeGarbageCollected<LayoutBoxRareData>(); return *rare_data_.Get(); @@ -1998,6 +2228,7 @@ RasterEffectOutset VisualRectOutsetForRasterEffects() const override; inline bool CanSkipComputeScrollbars() const { + CheckIsNotDestroyed(); return (StyleRef().IsOverflowVisibleAlongBothAxes() || !HasNonVisibleOverflow() || (GetScrollableArea() && @@ -2015,12 +2246,14 @@ LayoutUnit position, LayoutUnit width, const LayoutBox* box_for_flipping) const final { + CheckIsNotDestroyed(); DCHECK(!box_for_flipping || box_for_flipping == this); return FlipForWritingMode(position, width); } PhysicalOffset PhysicalLocationInternal( const LayoutBox* container_box) const { + CheckIsNotDestroyed(); DCHECK_EQ(container_box, LocationContainer()); if (LIKELY(!container_box || !container_box->HasFlippedBlocksWritingMode())) return PhysicalOffset(Location()); @@ -2064,6 +2297,7 @@ private: LogicalToPhysicalSetter<LayoutUnit, LayoutBox> LogicalMarginToPhysicalSetter( const ComputedStyle* override_style) { + CheckIsNotDestroyed(); const auto& style = override_style ? *override_style : StyleRef(); return LogicalToPhysicalSetter<LayoutUnit, LayoutBox>( style.GetWritingMode(), style.Direction(), *this,
diff --git a/third_party/blink/renderer/core/layout/layout_box_model_object.cc b/third_party/blink/renderer/core/layout/layout_box_model_object.cc index 67f1e80..644c59d 100644 --- a/third_party/blink/renderer/core/layout/layout_box_model_object.cc +++ b/third_party/blink/renderer/core/layout/layout_box_model_object.cc
@@ -86,6 +86,7 @@ } void LayoutBoxModelObject::ContentChanged(ContentChangeType change_type) { + CheckIsNotDestroyed(); if (!HasLayer()) return; @@ -96,6 +97,7 @@ : LayoutObject(node) {} bool LayoutBoxModelObject::UsesCompositedScrolling() const { + CheckIsNotDestroyed(); return IsScrollContainer() && HasLayer() && Layer()->GetScrollableArea()->UsesCompositedScrolling(); } @@ -112,6 +114,7 @@ BackgroundPaintLocation LayoutBoxModelObject::ComputeBackgroundPaintLocationIfComposited() const { + CheckIsNotDestroyed(); bool may_have_scrolling_layers_without_scrolling = IsA<LayoutView>(this); const auto* scrollable_area = GetScrollableArea(); bool scrolls_overflow = scrollable_area && scrollable_area->ScrollsOverflow(); @@ -204,6 +207,7 @@ } void LayoutBoxModelObject::WillBeDestroyed() { + CheckIsNotDestroyed(); // A continuation of this LayoutObject should be destroyed at subclasses. DCHECK(!Continuation()); @@ -231,6 +235,7 @@ void LayoutBoxModelObject::StyleWillChange(StyleDifference diff, const ComputedStyle& new_style) { + CheckIsNotDestroyed(); // SPv1: // This object's layer may begin or cease to be stacked or stacking context, // in which case the paint invalidation container of this object and @@ -267,6 +272,7 @@ DISABLE_CFI_PERF void LayoutBoxModelObject::StyleDidChange(StyleDifference diff, const ComputedStyle* old_style) { + CheckIsNotDestroyed(); bool had_transform_related_property = HasTransformRelatedProperty(); bool had_filter_inducing_property = HasFilterInducingProperty(); bool had_non_initial_backdrop_filter = HasNonInitialBackdropFilter(); @@ -515,6 +521,7 @@ } void LayoutBoxModelObject::InvalidateStickyConstraints() { + CheckIsNotDestroyed(); PaintLayer* enclosing = EnclosingLayer(); if (PaintLayerScrollableArea* scrollable_area = @@ -539,6 +546,7 @@ } void LayoutBoxModelObject::CreateLayerAfterStyleChange() { + CheckIsNotDestroyed(); DCHECK(!HasLayer() && !Layer()); GetMutableForPainting().FirstFragment().SetLayer( std::make_unique<PaintLayer>(*this)); @@ -552,6 +560,7 @@ } void LayoutBoxModelObject::DestroyLayer() { + CheckIsNotDestroyed(); DCHECK(HasLayer() && Layer()); SetHasLayer(false); GetMutableForPainting().FirstFragment().SetLayer(nullptr); @@ -562,10 +571,12 @@ } bool LayoutBoxModelObject::HasSelfPaintingLayer() const { + CheckIsNotDestroyed(); return Layer() && Layer()->IsSelfPaintingLayer(); } PaintLayerScrollableArea* LayoutBoxModelObject::GetScrollableArea() const { + CheckIsNotDestroyed(); return Layer() ? Layer()->GetScrollableArea() : nullptr; } @@ -573,6 +584,7 @@ Vector<PhysicalRect>& rects, const PhysicalOffset& additional_offset, NGOutlineType include_block_overflows) const { + CheckIsNotDestroyed(); for (LayoutObject* child = SlowFirstChild(); child; child = child->NextSibling()) { // Outlines of out-of-flow positioned descendants are handled in @@ -598,6 +610,7 @@ Vector<PhysicalRect>& rects, const PhysicalOffset& additional_offset, NGOutlineType include_block_overflows) const { + CheckIsNotDestroyed(); if (descendant.IsText() || descendant.IsListMarkerForNormalContent()) return; @@ -637,11 +650,13 @@ void LayoutBoxModelObject::AbsoluteQuadsForSelf( Vector<FloatQuad>& quads, MapCoordinatesFlags mode) const { + CheckIsNotDestroyed(); NOTREACHED(); } void LayoutBoxModelObject::AbsoluteQuads(Vector<FloatQuad>& quads, MapCoordinatesFlags mode) const { + CheckIsNotDestroyed(); AbsoluteQuadsForSelf(quads, mode); // Iterate over continuations, avoiding recursion in case there are @@ -659,6 +674,7 @@ } void LayoutBoxModelObject::UpdateFromStyle() { + CheckIsNotDestroyed(); const ComputedStyle& style_to_use = StyleRef(); SetHasBoxDecorationBackground(style_to_use.HasBoxDecorationBackground()); SetInline(style_to_use.IsDisplayInlineType()); @@ -669,6 +685,7 @@ LayoutBlock* LayoutBoxModelObject::ContainingBlockForAutoHeightDetection( const Length& logical_height) const { + CheckIsNotDestroyed(); // For percentage heights: The percentage is calculated with respect to the // height of the generated box's containing block. If the height of the // containing block is not specified explicitly (i.e., it depends on content @@ -703,6 +720,7 @@ bool LayoutBoxModelObject::HasAutoHeightOrContainingBlockWithAutoHeight( RegisterPercentageDescendant register_percentage_descendant) const { + CheckIsNotDestroyed(); // TODO(rego): Check if we can somehow reuse LayoutBlock:: // availableLogicalHeightForPercentageComputation() (see crbug.com/635655). const LayoutBox* this_box = IsBox() ? ToLayoutBox(this) : nullptr; @@ -769,6 +787,7 @@ } PhysicalOffset LayoutBoxModelObject::RelativePositionOffset() const { + CheckIsNotDestroyed(); DCHECK(IsRelPositioned()); LayoutBlock* containing_block = ContainingBlock(); @@ -898,6 +917,7 @@ } void LayoutBoxModelObject::UpdateStickyPositionConstraints() const { + CheckIsNotDestroyed(); DCHECK(StyleRef().HasStickyConstrainedPosition()); const PhysicalSize constraining_size = ComputeStickyConstrainingRect().size; @@ -1076,6 +1096,7 @@ } bool LayoutBoxModelObject::IsSlowRepaintConstrainedObject() const { + CheckIsNotDestroyed(); if (!HasLayer() || (StyleRef().GetPosition() != EPosition::kFixed && StyleRef().GetPosition() != EPosition::kSticky)) { return false; @@ -1101,6 +1122,7 @@ } PhysicalRect LayoutBoxModelObject::ComputeStickyConstrainingRect() const { + CheckIsNotDestroyed(); LayoutBox* enclosing_clipping_box = Layer()->AncestorOverflowLayer()->GetLayoutBox(); DCHECK(enclosing_clipping_box); @@ -1122,6 +1144,7 @@ } PhysicalOffset LayoutBoxModelObject::StickyPositionOffset() const { + CheckIsNotDestroyed(); // TODO(chrishtr): StickyPositionOffset depends on compositing at present, // but there are callsites within Layout for it. @@ -1150,6 +1173,7 @@ PhysicalOffset LayoutBoxModelObject::AdjustedPositionRelativeTo( const PhysicalOffset& start_point, const Element* offset_parent) const { + CheckIsNotDestroyed(); // If the element is the HTML body element or doesn't have a parent // return 0 and stop this algorithm. if (IsBody() || !Parent()) @@ -1216,6 +1240,7 @@ } PhysicalOffset LayoutBoxModelObject::OffsetForInFlowPosition() const { + CheckIsNotDestroyed(); if (IsRelPositioned()) return RelativePositionOffset(); @@ -1226,28 +1251,33 @@ } LayoutUnit LayoutBoxModelObject::OffsetLeft(const Element* parent) const { + CheckIsNotDestroyed(); // Note that LayoutInline and LayoutBox override this to pass a different // startPoint to adjustedPositionRelativeTo. return AdjustedPositionRelativeTo(PhysicalOffset(), parent).left; } LayoutUnit LayoutBoxModelObject::OffsetTop(const Element* parent) const { + CheckIsNotDestroyed(); // Note that LayoutInline and LayoutBox override this to pass a different // startPoint to adjustedPositionRelativeTo. return AdjustedPositionRelativeTo(PhysicalOffset(), parent).top; } int LayoutBoxModelObject::PixelSnappedOffsetWidth(const Element* parent) const { + CheckIsNotDestroyed(); return SnapSizeToPixel(OffsetWidth(), OffsetLeft(parent)); } int LayoutBoxModelObject::PixelSnappedOffsetHeight( const Element* parent) const { + CheckIsNotDestroyed(); return SnapSizeToPixel(OffsetHeight(), OffsetTop(parent)); } LayoutUnit LayoutBoxModelObject::ComputedCSSPadding( const Length& padding) const { + CheckIsNotDestroyed(); LayoutUnit w; if (padding.IsPercentOrCalc()) w = ContainingBlockLogicalWidthForContent(); @@ -1255,14 +1285,17 @@ } LayoutUnit LayoutBoxModelObject::ContainingBlockLogicalWidthForContent() const { + CheckIsNotDestroyed(); return ContainingBlock()->AvailableLogicalWidth(); } LayoutBoxModelObject* LayoutBoxModelObject::Continuation() const { + CheckIsNotDestroyed(); return GetContinuationMap().at(this); } void LayoutBoxModelObject::SetContinuation(LayoutBoxModelObject* continuation) { + CheckIsNotDestroyed(); if (continuation) { DCHECK(continuation->IsLayoutInline() || continuation->IsLayoutBlockFlow()); GetContinuationMap().Set(this, continuation); @@ -1274,6 +1307,7 @@ LayoutRect LayoutBoxModelObject::LocalCaretRectForEmptyElement( LayoutUnit width, LayoutUnit text_indent_offset) const { + CheckIsNotDestroyed(); DCHECK(!SlowFirstChild() || SlowFirstChild()->IsPseudoElement()); // FIXME: This does not take into account either :first-line or :first-letter @@ -1355,6 +1389,7 @@ const LayoutObject* LayoutBoxModelObject::PushMappingToContainer( const LayoutBoxModelObject* ancestor_to_stop_at, LayoutGeometryMap& geometry_map) const { + CheckIsNotDestroyed(); DCHECK_NE(ancestor_to_stop_at, this); AncestorSkipInfo skip_info(ancestor_to_stop_at); @@ -1426,6 +1461,7 @@ LayoutObject* child, LayoutObject* before_child, bool full_remove_insert) { + CheckIsNotDestroyed(); // We assume that callers have cleared their positioned objects list for child // moves (!fullRemoveInsert) so the positioned layoutObject maps don't become // stale. It would be too slow to do the map lookup on each call. @@ -1471,6 +1507,7 @@ LayoutObject* end_child, LayoutObject* before_child, bool full_remove_insert) { + CheckIsNotDestroyed(); // This condition is rarely hit since this function is usually called on // anonymous blocks which can no longer carry positioned objects (see r120761) // or when fullRemoveInsert is false. @@ -1494,6 +1531,7 @@ bool LayoutBoxModelObject::BackgroundTransfersToView( const ComputedStyle* document_element_style) const { + CheckIsNotDestroyed(); // In our painter implementation, ViewPainter instead of the painter of the // layout object of the document element paints the view background. if (IsDocumentElement())
diff --git a/third_party/blink/renderer/core/layout/layout_box_model_object.h b/third_party/blink/renderer/core/layout/layout_box_model_object.h index ad1c091..fdd3d6e 100644 --- a/third_party/blink/renderer/core/layout/layout_box_model_object.h +++ b/third_party/blink/renderer/core/layout/layout_box_model_object.h
@@ -135,6 +135,7 @@ PhysicalOffset RelativePositionOffset() const; LayoutSize RelativePositionLogicalOffset() const { + CheckIsNotDestroyed(); // TODO(layout-dev): This seems incorrect in flipped blocks writing mode, // but seems for legacy layout only. auto offset = RelativePositionOffset().ToLayoutSize(); @@ -161,16 +162,21 @@ virtual LayoutUnit OffsetHeight() const = 0; int PixelSnappedOffsetLeft(const Element* parent) const { + CheckIsNotDestroyed(); return RoundToInt(OffsetLeft(parent)); } int PixelSnappedOffsetTop(const Element* parent) const { + CheckIsNotDestroyed(); return RoundToInt(OffsetTop(parent)); } virtual int PixelSnappedOffsetWidth(const Element*) const; virtual int PixelSnappedOffsetHeight(const Element*) const; bool HasSelfPaintingLayer() const; - PaintLayer* Layer() const { return FirstFragment().Layer(); } + PaintLayer* Layer() const { + CheckIsNotDestroyed(); + return FirstFragment().Layer(); + } // The type of PaintLayer to instantiate. Any value returned from this // function other than NoPaintLayer will lead to a PaintLayer being created. virtual PaintLayerType LayerTypeRequired() const = 0; @@ -192,33 +198,43 @@ // These return the CSS computed padding values. LayoutUnit ComputedCSSPaddingTop() const { + CheckIsNotDestroyed(); return ComputedCSSPadding(StyleRef().PaddingTop()); } LayoutUnit ComputedCSSPaddingBottom() const { + CheckIsNotDestroyed(); return ComputedCSSPadding(StyleRef().PaddingBottom()); } LayoutUnit ComputedCSSPaddingLeft() const { + CheckIsNotDestroyed(); return ComputedCSSPadding(StyleRef().PaddingLeft()); } LayoutUnit ComputedCSSPaddingRight() const { + CheckIsNotDestroyed(); return ComputedCSSPadding(StyleRef().PaddingRight()); } LayoutUnit ComputedCSSPaddingBefore() const { + CheckIsNotDestroyed(); return ComputedCSSPadding(StyleRef().PaddingBefore()); } LayoutUnit ComputedCSSPaddingAfter() const { + CheckIsNotDestroyed(); return ComputedCSSPadding(StyleRef().PaddingAfter()); } LayoutUnit ComputedCSSPaddingStart() const { + CheckIsNotDestroyed(); return ComputedCSSPadding(StyleRef().PaddingStart()); } LayoutUnit ComputedCSSPaddingEnd() const { + CheckIsNotDestroyed(); return ComputedCSSPadding(StyleRef().PaddingEnd()); } LayoutUnit ComputedCSSPaddingOver() const { + CheckIsNotDestroyed(); return ComputedCSSPadding(StyleRef().PaddingOver()); } LayoutUnit ComputedCSSPaddingUnder() const { + CheckIsNotDestroyed(); return ComputedCSSPadding(StyleRef().PaddingUnder()); } @@ -226,117 +242,190 @@ // - Table cells override them to include the intrinsic padding (see // explanations in LayoutTableCell). // - Table override them to exclude padding with collapsing borders. - virtual LayoutUnit PaddingTop() const { return ComputedCSSPaddingTop(); } + virtual LayoutUnit PaddingTop() const { + CheckIsNotDestroyed(); + return ComputedCSSPaddingTop(); + } virtual LayoutUnit PaddingBottom() const { + CheckIsNotDestroyed(); return ComputedCSSPaddingBottom(); } - virtual LayoutUnit PaddingLeft() const { return ComputedCSSPaddingLeft(); } - virtual LayoutUnit PaddingRight() const { return ComputedCSSPaddingRight(); } + virtual LayoutUnit PaddingLeft() const { + CheckIsNotDestroyed(); + return ComputedCSSPaddingLeft(); + } + virtual LayoutUnit PaddingRight() const { + CheckIsNotDestroyed(); + return ComputedCSSPaddingRight(); + } LayoutUnit PaddingBefore() const { + CheckIsNotDestroyed(); return PhysicalPaddingToLogical().Before(); } - LayoutUnit PaddingAfter() const { return PhysicalPaddingToLogical().After(); } - LayoutUnit PaddingStart() const { return PhysicalPaddingToLogical().Start(); } - LayoutUnit PaddingEnd() const { return PhysicalPaddingToLogical().End(); } - LayoutUnit PaddingOver() const { return PhysicalPaddingToLogical().Over(); } - LayoutUnit PaddingUnder() const { return PhysicalPaddingToLogical().Under(); } + LayoutUnit PaddingAfter() const { + CheckIsNotDestroyed(); + return PhysicalPaddingToLogical().After(); + } + LayoutUnit PaddingStart() const { + CheckIsNotDestroyed(); + return PhysicalPaddingToLogical().Start(); + } + LayoutUnit PaddingEnd() const { + CheckIsNotDestroyed(); + return PhysicalPaddingToLogical().End(); + } + LayoutUnit PaddingOver() const { + CheckIsNotDestroyed(); + return PhysicalPaddingToLogical().Over(); + } + LayoutUnit PaddingUnder() const { + CheckIsNotDestroyed(); + return PhysicalPaddingToLogical().Under(); + } virtual LayoutUnit BorderTop() const { + CheckIsNotDestroyed(); return LayoutUnit(StyleRef().BorderTopWidth()); } virtual LayoutUnit BorderBottom() const { + CheckIsNotDestroyed(); return LayoutUnit(StyleRef().BorderBottomWidth()); } virtual LayoutUnit BorderLeft() const { + CheckIsNotDestroyed(); return LayoutUnit(StyleRef().BorderLeftWidth()); } virtual LayoutUnit BorderRight() const { + CheckIsNotDestroyed(); return LayoutUnit(StyleRef().BorderRightWidth()); } - LayoutUnit BorderBefore() const { return PhysicalBorderToLogical().Before(); } - LayoutUnit BorderAfter() const { return PhysicalBorderToLogical().After(); } - LayoutUnit BorderStart() const { return PhysicalBorderToLogical().Start(); } - LayoutUnit BorderEnd() const { return PhysicalBorderToLogical().End(); } - LayoutUnit BorderOver() const { return PhysicalBorderToLogical().Over(); } - LayoutUnit BorderUnder() const { return PhysicalBorderToLogical().Under(); } + LayoutUnit BorderBefore() const { + CheckIsNotDestroyed(); + return PhysicalBorderToLogical().Before(); + } + LayoutUnit BorderAfter() const { + CheckIsNotDestroyed(); + return PhysicalBorderToLogical().After(); + } + LayoutUnit BorderStart() const { + CheckIsNotDestroyed(); + return PhysicalBorderToLogical().Start(); + } + LayoutUnit BorderEnd() const { + CheckIsNotDestroyed(); + return PhysicalBorderToLogical().End(); + } + LayoutUnit BorderOver() const { + CheckIsNotDestroyed(); + return PhysicalBorderToLogical().Over(); + } + LayoutUnit BorderUnder() const { + CheckIsNotDestroyed(); + return PhysicalBorderToLogical().Under(); + } - LayoutUnit BorderWidth() const { return BorderLeft() + BorderRight(); } - LayoutUnit BorderHeight() const { return BorderTop() + BorderBottom(); } + LayoutUnit BorderWidth() const { + CheckIsNotDestroyed(); + return BorderLeft() + BorderRight(); + } + LayoutUnit BorderHeight() const { + CheckIsNotDestroyed(); + return BorderTop() + BorderBottom(); + } LayoutRectOutsets BorderBoxOutsets() const { + CheckIsNotDestroyed(); return LayoutRectOutsets(BorderTop(), BorderRight(), BorderBottom(), BorderLeft()); } LayoutRectOutsets PaddingOutsets() const { + CheckIsNotDestroyed(); return LayoutRectOutsets(PaddingTop(), PaddingRight(), PaddingBottom(), PaddingLeft()); } // Insets from the border box to the inside of the border. LayoutRectOutsets BorderInsets() const { + CheckIsNotDestroyed(); return LayoutRectOutsets(-BorderTop(), -BorderRight(), -BorderBottom(), -BorderLeft()); } LayoutUnit BorderAndPaddingStart() const { + CheckIsNotDestroyed(); return BorderStart() + PaddingStart(); } DISABLE_CFI_PERF LayoutUnit BorderAndPaddingBefore() const { + CheckIsNotDestroyed(); return BorderBefore() + PaddingBefore(); } DISABLE_CFI_PERF LayoutUnit BorderAndPaddingAfter() const { + CheckIsNotDestroyed(); return BorderAfter() + PaddingAfter(); } LayoutUnit BorderAndPaddingOver() const { + CheckIsNotDestroyed(); return BorderOver() + PaddingOver(); } LayoutUnit BorderAndPaddingUnder() const { + CheckIsNotDestroyed(); return BorderUnder() + PaddingUnder(); } DISABLE_CFI_PERF LayoutUnit BorderAndPaddingHeight() const { + CheckIsNotDestroyed(); return BorderTop() + BorderBottom() + PaddingTop() + PaddingBottom(); } DISABLE_CFI_PERF LayoutUnit BorderAndPaddingWidth() const { + CheckIsNotDestroyed(); return BorderLeft() + BorderRight() + PaddingLeft() + PaddingRight(); } DISABLE_CFI_PERF LayoutUnit BorderAndPaddingLogicalHeight() const { + CheckIsNotDestroyed(); return (StyleRef().HasBorder() || StyleRef().MayHavePadding()) ? BorderAndPaddingBefore() + BorderAndPaddingAfter() : LayoutUnit(); } DISABLE_CFI_PERF LayoutUnit BorderAndPaddingLogicalWidth() const { + CheckIsNotDestroyed(); return BorderStart() + BorderEnd() + PaddingStart() + PaddingEnd(); } DISABLE_CFI_PERF LayoutUnit BorderAndPaddingLogicalLeft() const { + CheckIsNotDestroyed(); return StyleRef().IsHorizontalWritingMode() ? BorderLeft() + PaddingLeft() : BorderTop() + PaddingTop(); } LayoutUnit BorderLogicalLeft() const { + CheckIsNotDestroyed(); return LayoutUnit(StyleRef().IsHorizontalWritingMode() ? BorderLeft() : BorderTop()); } LayoutUnit BorderLogicalRight() const { + CheckIsNotDestroyed(); return LayoutUnit(StyleRef().IsHorizontalWritingMode() ? BorderRight() : BorderBottom()); } LayoutUnit PaddingLogicalWidth() const { + CheckIsNotDestroyed(); return PaddingStart() + PaddingEnd(); } LayoutUnit PaddingLogicalHeight() const { + CheckIsNotDestroyed(); return PaddingBefore() + PaddingAfter(); } LayoutUnit CollapsedBorderAndCSSPaddingLogicalWidth() const { + CheckIsNotDestroyed(); return ComputedCSSPaddingStart() + ComputedCSSPaddingEnd() + BorderStart() + BorderEnd(); } LayoutUnit CollapsedBorderAndCSSPaddingLogicalHeight() const { + CheckIsNotDestroyed(); return ComputedCSSPaddingBefore() + ComputedCSSPaddingAfter() + BorderBefore() + BorderAfter(); } @@ -347,53 +436,69 @@ virtual LayoutUnit MarginRight() const = 0; LayoutUnit MarginBefore(const ComputedStyle* other_style = nullptr) const { + CheckIsNotDestroyed(); return PhysicalMarginToLogical(other_style).Before(); } LayoutUnit MarginAfter(const ComputedStyle* other_style = nullptr) const { + CheckIsNotDestroyed(); return PhysicalMarginToLogical(other_style).After(); } LayoutUnit MarginStart(const ComputedStyle* other_style = nullptr) const { + CheckIsNotDestroyed(); return PhysicalMarginToLogical(other_style).Start(); } LayoutUnit MarginEnd(const ComputedStyle* other_style = nullptr) const { + CheckIsNotDestroyed(); return PhysicalMarginToLogical(other_style).End(); } LayoutUnit MarginLineLeft() const { + CheckIsNotDestroyed(); return PhysicalMarginToLogical(nullptr).LineLeft(); } LayoutUnit MarginLineRight() const { + CheckIsNotDestroyed(); return PhysicalMarginToLogical(nullptr).LineRight(); } LayoutUnit MarginOver() const { + CheckIsNotDestroyed(); return PhysicalMarginToLogical(nullptr).Over(); } LayoutUnit MarginUnder() const { + CheckIsNotDestroyed(); return PhysicalMarginToLogical(nullptr).Under(); } DISABLE_CFI_PERF LayoutUnit MarginHeight() const { + CheckIsNotDestroyed(); return MarginTop() + MarginBottom(); } DISABLE_CFI_PERF LayoutUnit MarginWidth() const { + CheckIsNotDestroyed(); return MarginLeft() + MarginRight(); } DISABLE_CFI_PERF LayoutUnit MarginLogicalHeight() const { + CheckIsNotDestroyed(); return MarginBefore() + MarginAfter(); } DISABLE_CFI_PERF LayoutUnit MarginLogicalWidth() const { + CheckIsNotDestroyed(); return MarginStart() + MarginEnd(); } bool HasInlineDirectionBordersPaddingOrMargin() const { + CheckIsNotDestroyed(); return HasInlineDirectionBordersOrPadding() || MarginStart() || MarginEnd(); } bool HasInlineDirectionBordersOrPadding() const { + CheckIsNotDestroyed(); return BorderStart() || BorderEnd() || PaddingStart() || PaddingEnd(); } virtual LayoutUnit ContainingBlockLogicalWidthForContent() const; - virtual void ChildBecameNonInline(LayoutObject* /*child*/) {} + virtual void ChildBecameNonInline(LayoutObject* /*child*/) { + CheckIsNotDestroyed(); + } // Overridden by subclasses to determine line height and baseline position. virtual LayoutUnit LineHeight( @@ -415,11 +520,15 @@ // Returns true if the background is painted opaque in the given rect. // The query rect is given in local coordinate system. virtual bool BackgroundIsKnownToBeOpaqueInRect(const PhysicalRect&) const { + CheckIsNotDestroyed(); return false; } // Returns true if all text in the paint-order subtree will be painted on // opaque background. - virtual bool TextIsKnownToBeOnOpaqueBackground() const { return false; } + virtual bool TextIsKnownToBeOnOpaqueBackground() const { + CheckIsNotDestroyed(); + return false; + } // This object's background is transferred to its LayoutView if: // 1. it's the document element, or @@ -436,15 +545,23 @@ MapCoordinatesFlags mode = 0) const override; virtual LayoutUnit OverrideContainingBlockContentWidth() const { + CheckIsNotDestroyed(); NOTREACHED(); return LayoutUnit(-1); } virtual LayoutUnit OverrideContainingBlockContentHeight() const { + CheckIsNotDestroyed(); NOTREACHED(); return LayoutUnit(-1); } - virtual bool HasOverrideContainingBlockContentWidth() const { return false; } - virtual bool HasOverrideContainingBlockContentHeight() const { return false; } + virtual bool HasOverrideContainingBlockContentWidth() const { + CheckIsNotDestroyed(); + return false; + } + virtual bool HasOverrideContainingBlockContentHeight() const { + CheckIsNotDestroyed(); + return false; + } // Returns the continuation associated with |this|. // Returns nullptr if no continuation is associated with |this|. @@ -475,6 +592,7 @@ void SetContinuation(LayoutBoxModelObject*); virtual PhysicalOffset AccumulateRelativePositionOffsets() const { + CheckIsNotDestroyed(); return PhysicalOffset(); } @@ -517,15 +635,18 @@ void MoveChildTo(LayoutBoxModelObject* to_box_model_object, LayoutObject* child, bool full_remove_insert = false) { + CheckIsNotDestroyed(); MoveChildTo(to_box_model_object, child, nullptr, full_remove_insert); } void MoveAllChildrenTo(LayoutBoxModelObject* to_box_model_object, bool full_remove_insert = false) { + CheckIsNotDestroyed(); MoveAllChildrenTo(to_box_model_object, nullptr, full_remove_insert); } void MoveAllChildrenTo(LayoutBoxModelObject* to_box_model_object, LayoutObject* before_child, bool full_remove_insert = false) { + CheckIsNotDestroyed(); MoveChildrenTo(to_box_model_object, SlowFirstChild(), nullptr, before_child, full_remove_insert); } @@ -536,6 +657,7 @@ LayoutObject* start_child, LayoutObject* end_child, bool full_remove_insert = false) { + CheckIsNotDestroyed(); MoveChildrenTo(to_box_model_object, start_child, end_child, nullptr, full_remove_insert); } @@ -549,10 +671,14 @@ void CreateLayerAfterStyleChange(); LayoutUnit ComputedCSSPadding(const Length&) const; - bool IsBoxModelObject() const final { return true; } + bool IsBoxModelObject() const final { + CheckIsNotDestroyed(); + return true; + } PhysicalToLogicalGetter<LayoutUnit, LayoutBoxModelObject> PhysicalPaddingToLogical() const { + CheckIsNotDestroyed(); return PhysicalToLogicalGetter<LayoutUnit, LayoutBoxModelObject>( StyleRef().GetWritingMode(), StyleRef().Direction(), *this, &LayoutBoxModelObject::PaddingTop, &LayoutBoxModelObject::PaddingRight, @@ -562,6 +688,7 @@ PhysicalToLogicalGetter<LayoutUnit, LayoutBoxModelObject> PhysicalMarginToLogical(const ComputedStyle* other_style) const { + CheckIsNotDestroyed(); const auto& style = other_style ? *other_style : StyleRef(); return PhysicalToLogicalGetter<LayoutUnit, LayoutBoxModelObject>( style.GetWritingMode(), style.Direction(), *this, @@ -571,6 +698,7 @@ PhysicalToLogicalGetter<LayoutUnit, LayoutBoxModelObject> PhysicalBorderToLogical() const { + CheckIsNotDestroyed(); return PhysicalToLogicalGetter<LayoutUnit, LayoutBoxModelObject>( StyleRef().GetWritingMode(), StyleRef().Direction(), *this, &LayoutBoxModelObject::BorderTop, &LayoutBoxModelObject::BorderRight,
diff --git a/third_party/blink/renderer/core/layout/layout_br.cc b/third_party/blink/renderer/core/layout/layout_br.cc index c96e4cd..7c5ad63 100644 --- a/third_party/blink/renderer/core/layout/layout_br.cc +++ b/third_party/blink/renderer/core/layout/layout_br.cc
@@ -38,6 +38,7 @@ LayoutBR::~LayoutBR() = default; int LayoutBR::LineHeight(bool first_line) const { + CheckIsNotDestroyed(); const ComputedStyle& style = StyleRef( first_line && GetDocument().GetStyleEngine().UsesFirstLineRules()); return style.ComputedLineHeight(); @@ -45,22 +46,27 @@ void LayoutBR::StyleDidChange(StyleDifference diff, const ComputedStyle* old_style) { + CheckIsNotDestroyed(); LayoutText::StyleDidChange(diff, old_style); } int LayoutBR::CaretMinOffset() const { + CheckIsNotDestroyed(); return 0; } int LayoutBR::CaretMaxOffset() const { + CheckIsNotDestroyed(); return 1; } PositionWithAffinity LayoutBR::PositionForPoint(const PhysicalOffset&) const { + CheckIsNotDestroyed(); return CreatePositionWithAffinity(0); } Position LayoutBR::PositionForCaretOffset(unsigned offset) const { + CheckIsNotDestroyed(); DCHECK_LE(offset, 1u); DCHECK(GetNode()); return offset ? Position::AfterNode(*GetNode()) @@ -69,6 +75,7 @@ base::Optional<unsigned> LayoutBR::CaretOffsetForPosition( const Position& position) const { + CheckIsNotDestroyed(); if (position.IsNull() || position.AnchorNode() != GetNode()) return base::nullopt; DCHECK(position.IsBeforeAnchor() || position.IsAfterAnchor()) << position;
diff --git a/third_party/blink/renderer/core/layout/layout_br.h b/third_party/blink/renderer/core/layout/layout_br.h index 1cf6f774..d32435bc 100644 --- a/third_party/blink/renderer/core/layout/layout_br.h +++ b/third_party/blink/renderer/core/layout/layout_br.h
@@ -32,7 +32,10 @@ explicit LayoutBR(Node*); ~LayoutBR() override; - const char* GetName() const override { return "LayoutBR"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutBR"; + } // Although line breaks contain no actual text, if we're selected we need // to return a rect that includes space to illustrate a newline. @@ -46,6 +49,7 @@ HashSet<const SimpleFontData*>* = nullptr /* fallbackFonts */, FloatRect* /* glyphBounds */ = nullptr, float /* expansion */ = false) const override { + CheckIsNotDestroyed(); return 0; } float Width(unsigned /* from */, @@ -56,12 +60,14 @@ HashSet<const SimpleFontData*>* = nullptr /* fallbackFonts */, FloatRect* /* glyphBounds */ = nullptr, float /* expansion */ = false) const override { + CheckIsNotDestroyed(); return 0; } int LineHeight(bool first_line) const; bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectBr || LayoutText::IsOfType(type); }
diff --git a/third_party/blink/renderer/core/layout/layout_button.cc b/third_party/blink/renderer/core/layout/layout_button.cc index ca18ad9a..73fbdc1 100644 --- a/third_party/blink/renderer/core/layout/layout_button.cc +++ b/third_party/blink/renderer/core/layout/layout_button.cc
@@ -31,6 +31,7 @@ void LayoutButton::AddChild(LayoutObject* new_child, LayoutObject* before_child) { + CheckIsNotDestroyed(); if (!inner_) { // Create an anonymous block. DCHECK(!FirstChild()); @@ -42,6 +43,7 @@ } void LayoutButton::RemoveChild(LayoutObject* old_child) { + CheckIsNotDestroyed(); if (old_child == inner_ || !inner_) { LayoutFlexibleBox::RemoveChild(old_child); inner_ = nullptr; @@ -86,12 +88,14 @@ bool first_line, LineDirectionMode direction, LinePositionMode line_position_mode) const { + CheckIsNotDestroyed(); DCHECK_EQ(line_position_mode, kPositionOnContainingLine); // We want to call the LayoutBlock version of firstLineBoxBaseline to // avoid LayoutFlexibleBox synthesizing a baseline that we don't want. // We use this check as a proxy for "are there any line boxes in this button" if (!HasLineIfEmpty() && !ShouldApplyLayoutContainment() && LayoutBlock::FirstLineBoxBaseline() == -1) { + CheckIsNotDestroyed(); // To ensure that we have a consistent baseline when we have no children, // even when we have the anonymous LayoutBlock child, we calculate the // baseline for the empty case manually here.
diff --git a/third_party/blink/renderer/core/layout/layout_button.h b/third_party/blink/renderer/core/layout/layout_button.h index 543281a4..b865a37 100644 --- a/third_party/blink/renderer/core/layout/layout_button.h +++ b/third_party/blink/renderer/core/layout/layout_button.h
@@ -36,8 +36,12 @@ explicit LayoutButton(Element*); ~LayoutButton() override; - const char* GetName() const override { return "LayoutButton"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutButton"; + } bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectLayoutButton || LayoutFlexibleBox::IsOfType(type); } @@ -45,8 +49,13 @@ void AddChild(LayoutObject* new_child, LayoutObject* before_child = nullptr) override; void RemoveChild(LayoutObject*) override; - void RemoveLeftoverAnonymousBlock(LayoutBlock*) override {} - bool CreatesAnonymousWrapper() const override { return true; } + void RemoveLeftoverAnonymousBlock(LayoutBlock*) override { + CheckIsNotDestroyed(); + } + bool CreatesAnonymousWrapper() const override { + CheckIsNotDestroyed(); + return true; + } LayoutUnit BaselinePosition(FontBaseline, bool first_line,
diff --git a/third_party/blink/renderer/core/layout/layout_counter.cc b/third_party/blink/renderer/core/layout/layout_counter.cc index ff735e7..3cde0f71 100644 --- a/third_party/blink/renderer/core/layout/layout_counter.cc +++ b/third_party/blink/renderer/core/layout/layout_counter.cc
@@ -495,6 +495,7 @@ LayoutCounter::~LayoutCounter() = default; void LayoutCounter::WillBeDestroyed() { + CheckIsNotDestroyed(); if (counter_node_) { counter_node_->RemoveLayoutObject(this); DCHECK(!counter_node_); @@ -505,6 +506,7 @@ } scoped_refptr<StringImpl> LayoutCounter::OriginalText() const { + CheckIsNotDestroyed(); // Child will be the base of our text that we report. First, we need to find // an appropriate child. CounterNode* child = nullptr; @@ -605,10 +607,12 @@ } void LayoutCounter::UpdateCounter() { + CheckIsNotDestroyed(); SetTextIfNeeded(OriginalText()); } void LayoutCounter::Invalidate() { + CheckIsNotDestroyed(); counter_node_->RemoveLayoutObject(this); DCHECK(!counter_node_); if (DocumentBeingDestroyed())
diff --git a/third_party/blink/renderer/core/layout/layout_counter.h b/third_party/blink/renderer/core/layout/layout_counter.h index 41f35c7..bde58c9 100644 --- a/third_party/blink/renderer/core/layout/layout_counter.h +++ b/third_party/blink/renderer/core/layout/layout_counter.h
@@ -71,13 +71,17 @@ void UpdateCounter(); - const char* GetName() const override { return "LayoutCounter"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutCounter"; + } protected: void WillBeDestroyed() override; private: bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectCounter || LayoutText::IsOfType(type); } scoped_refptr<StringImpl> OriginalText() const override;
diff --git a/third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.cc b/third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.cc index 705ce2db..f93151c8 100644 --- a/third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.cc +++ b/third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.cc
@@ -96,6 +96,7 @@ int LayoutCustomScrollbarPart::ComputeSize(SizeType size_type, const Length& length, int container_size) const { + CheckIsNotDestroyed(); if (!length.IsIntrinsicOrAuto() || (size_type == kMinSize && length.IsAuto())) return MinimumValueForLength(length, LayoutUnit(container_size)).ToInt(); return CustomScrollbarTheme::GetCustomScrollbarTheme()->ScrollbarThickness( @@ -103,6 +104,7 @@ } int LayoutCustomScrollbarPart::ComputeWidth(int container_width) const { + CheckIsNotDestroyed(); if (StyleRef().Display() == EDisplay::kNone) return 0; @@ -117,6 +119,7 @@ } int LayoutCustomScrollbarPart::ComputeHeight(int container_height) const { + CheckIsNotDestroyed(); if (StyleRef().Display() == EDisplay::kNone) return 0; @@ -132,6 +135,7 @@ } int LayoutCustomScrollbarPart::ComputeThickness() const { + CheckIsNotDestroyed(); DCHECK_EQ(kScrollbarBGPart, part_); // Use 0 for container width/height, so percentage size will be ignored. @@ -142,6 +146,7 @@ } int LayoutCustomScrollbarPart::ComputeLength() const { + CheckIsNotDestroyed(); DCHECK_NE(kScrollbarBGPart, part_); IntRect visible_content_rect = @@ -158,30 +163,35 @@ } LayoutUnit LayoutCustomScrollbarPart::MarginTop() const { + CheckIsNotDestroyed(); if (scrollbar_->Orientation() == kHorizontalScrollbar) return LayoutUnit(); return ComputeMargin(StyleRef().MarginTop()); } LayoutUnit LayoutCustomScrollbarPart::MarginBottom() const { + CheckIsNotDestroyed(); if (scrollbar_->Orientation() == kHorizontalScrollbar) return LayoutUnit(); return ComputeMargin(StyleRef().MarginBottom()); } LayoutUnit LayoutCustomScrollbarPart::MarginLeft() const { + CheckIsNotDestroyed(); if (scrollbar_->Orientation() == kVerticalScrollbar) return LayoutUnit(); return ComputeMargin(StyleRef().MarginLeft()); } LayoutUnit LayoutCustomScrollbarPart::MarginRight() const { + CheckIsNotDestroyed(); if (scrollbar_->Orientation() == kVerticalScrollbar) return LayoutUnit(); return ComputeMargin(StyleRef().MarginRight()); } void LayoutCustomScrollbarPart::UpdateFromStyle() { + CheckIsNotDestroyed(); LayoutReplaced::UpdateFromStyle(); SetInline(false); ClearPositionedState(); @@ -190,6 +200,7 @@ void LayoutCustomScrollbarPart::StyleDidChange(StyleDifference diff, const ComputedStyle* old_style) { + CheckIsNotDestroyed(); LayoutReplaced::StyleDidChange(diff, old_style); if (old_style && (diff.NeedsPaintInvalidation() || diff.NeedsLayout())) SetNeedsPaintInvalidation(); @@ -197,6 +208,7 @@ } void LayoutCustomScrollbarPart::RecordPercentLengthStats() const { + CheckIsNotDestroyed(); if (!scrollbar_) return; @@ -222,11 +234,13 @@ void LayoutCustomScrollbarPart::ImageChanged(WrappedImagePtr image, CanDeferInvalidation defer) { + CheckIsNotDestroyed(); SetNeedsPaintInvalidation(); LayoutReplaced::ImageChanged(image, defer); } void LayoutCustomScrollbarPart::SetNeedsPaintInvalidation() { + CheckIsNotDestroyed(); if (scrollbar_) { scrollbar_->SetNeedsPaintInvalidation(kAllParts); return;
diff --git a/third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.h b/third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.h index 68915e2e0..e5280d7a 100644 --- a/third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.h +++ b/third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.h
@@ -41,9 +41,15 @@ CustomScrollbar* = nullptr, ScrollbarPart = kNoPart); - const char* GetName() const override { return "LayoutCustomScrollbarPart"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutCustomScrollbarPart"; + } - PaintLayerType LayerTypeRequired() const override { return kNoPaintLayer; } + PaintLayerType LayerTypeRequired() const override { + CheckIsNotDestroyed(); + return kNoPaintLayer; + } // Computes thickness of the scrollbar (which defines thickness of all parts). // For kScrollbarBGPart only. This can be called during style update. @@ -64,10 +70,14 @@ LayoutUnit MarginRight() const override; bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectLayoutCustomScrollbarPart || LayoutReplaced::IsOfType(type); } - ScrollableArea* GetScrollableArea() const { return scrollable_area_; } + ScrollableArea* GetScrollableArea() const { + CheckIsNotDestroyed(); + return scrollable_area_; + } private: LayoutCustomScrollbarPart(ScrollableArea*, CustomScrollbar*, ScrollbarPart); @@ -79,22 +89,40 @@ // A scrollbar part's Location() and PhysicalLocation() are relative to the // scrollbar (instead of relative to any LayoutBox ancestor), and both are // in physical coordinates. - LayoutBox* LocationContainer() const override { return nullptr; } + LayoutBox* LocationContainer() const override { + CheckIsNotDestroyed(); + return nullptr; + } // A scrollbar part is not in the layout tree and is not laid out like other // layout objects. CustomScrollbar will call scrollbar parts' SetFrameRect() // from its SetFrameRect() when needed. - void UpdateLayout() override { NOTREACHED(); } + void UpdateLayout() override { + CheckIsNotDestroyed(); + NOTREACHED(); + } // Have all padding getters return 0. The important point here is to avoid // resolving percents against the containing block, since scroll bar corners // don't always have one (so it would crash). Scroll bar corners are not // actually laid out, and they don't have child content, so what we return // here doesn't really matter. - LayoutUnit PaddingTop() const override { return LayoutUnit(); } - LayoutUnit PaddingBottom() const override { return LayoutUnit(); } - LayoutUnit PaddingLeft() const override { return LayoutUnit(); } - LayoutUnit PaddingRight() const override { return LayoutUnit(); } + LayoutUnit PaddingTop() const override { + CheckIsNotDestroyed(); + return LayoutUnit(); + } + LayoutUnit PaddingBottom() const override { + CheckIsNotDestroyed(); + return LayoutUnit(); + } + LayoutUnit PaddingLeft() const override { + CheckIsNotDestroyed(); + return LayoutUnit(); + } + LayoutUnit PaddingRight() const override { + CheckIsNotDestroyed(); + return LayoutUnit(); + } void SetNeedsPaintInvalidation();
diff --git a/third_party/blink/renderer/core/layout/layout_deprecated_flexible_box.cc b/third_party/blink/renderer/core/layout/layout_deprecated_flexible_box.cc index 495e406..ab00f1f5 100644 --- a/third_party/blink/renderer/core/layout/layout_deprecated_flexible_box.cc +++ b/third_party/blink/renderer/core/layout/layout_deprecated_flexible_box.cc
@@ -188,6 +188,7 @@ } MinMaxSizes LayoutDeprecatedFlexibleBox::ComputeIntrinsicLogicalWidths() const { + CheckIsNotDestroyed(); MinMaxSizes sizes; for (LayoutBox* child = FirstChildBox(); child; child = child->NextSiblingBox()) { @@ -207,6 +208,7 @@ } void LayoutDeprecatedFlexibleBox::UpdateBlockLayout(bool relayout_children) { + CheckIsNotDestroyed(); DCHECK(NeedsLayout()); DCHECK_EQ(StyleRef().BoxOrient(), EBoxOrient::kVertical); DCHECK(StyleRef().HasLineClamp()); @@ -250,6 +252,7 @@ } void LayoutDeprecatedFlexibleBox::LayoutVerticalBox(bool relayout_children) { + CheckIsNotDestroyed(); LayoutUnit to_add = BorderBottom() + PaddingBottom() + ComputeScrollbars().bottom; @@ -338,6 +341,7 @@ } void LayoutDeprecatedFlexibleBox::ApplyLineClamp(bool relayout_children) { + CheckIsNotDestroyed(); int max_line_count = 0; for (LayoutBox* child = FirstChildBox(); child; child = child->NextSiblingBox()) {
diff --git a/third_party/blink/renderer/core/layout/layout_deprecated_flexible_box.h b/third_party/blink/renderer/core/layout/layout_deprecated_flexible_box.h index 78bf29f3..86313f01 100644 --- a/third_party/blink/renderer/core/layout/layout_deprecated_flexible_box.h +++ b/third_party/blink/renderer/core/layout/layout_deprecated_flexible_box.h
@@ -34,13 +34,22 @@ LayoutDeprecatedFlexibleBox(Element* element); ~LayoutDeprecatedFlexibleBox() override; - const char* GetName() const override { return "LayoutDeprecatedFlexibleBox"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutDeprecatedFlexibleBox"; + } void UpdateBlockLayout(bool relayout_children) override; void LayoutVerticalBox(bool relayout_children); - bool IsDeprecatedFlexibleBox() const override { return true; } - bool IsFlexibleBoxIncludingDeprecatedAndNG() const override { return true; } + bool IsDeprecatedFlexibleBox() const override { + CheckIsNotDestroyed(); + return true; + } + bool IsFlexibleBoxIncludingDeprecatedAndNG() const override { + CheckIsNotDestroyed(); + return true; + } private: MinMaxSizes ComputeIntrinsicLogicalWidths() const override;
diff --git a/third_party/blink/renderer/core/layout/layout_details_marker.cc b/third_party/blink/renderer/core/layout/layout_details_marker.cc index 37ffb3e..86d0efa 100644 --- a/third_party/blink/renderer/core/layout/layout_details_marker.cc +++ b/third_party/blink/renderer/core/layout/layout_details_marker.cc
@@ -32,6 +32,7 @@ : LayoutBlockFlow(element) {} LayoutDetailsMarker::Orientation LayoutDetailsMarker::GetOrientation() const { + CheckIsNotDestroyed(); // TODO(layout-dev): Sideways-lr and sideways-rl are not yet supported. const auto mode = StyleRef().GetWritingMode(); DCHECK(mode != WritingMode::kSidewaysRl && mode != WritingMode::kSidewaysLr); @@ -47,10 +48,12 @@ } void LayoutDetailsMarker::Paint(const PaintInfo& paint_info) const { + CheckIsNotDestroyed(); DetailsMarkerPainter(*this).Paint(paint_info); } bool LayoutDetailsMarker::IsOpen() const { + CheckIsNotDestroyed(); for (LayoutObject* layout_object = Parent(); layout_object; layout_object = layout_object->Parent()) { const auto* node = layout_object->GetNode();
diff --git a/third_party/blink/renderer/core/layout/layout_details_marker.h b/third_party/blink/renderer/core/layout/layout_details_marker.h index e39df8ed..26ffbe0 100644 --- a/third_party/blink/renderer/core/layout/layout_details_marker.h +++ b/third_party/blink/renderer/core/layout/layout_details_marker.h
@@ -33,12 +33,19 @@ Orientation GetOrientation() const; - bool CreatesNewFormattingContext() const override { return true; } + bool CreatesNewFormattingContext() const override { + CheckIsNotDestroyed(); + return true; + } - const char* GetName() const override { return "LayoutDetailsMarker"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutDetailsMarker"; + } private: bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectDetailsMarker || LayoutBlockFlow::IsOfType(type); }
diff --git a/third_party/blink/renderer/core/layout/layout_embedded_content.cc b/third_party/blink/renderer/core/layout/layout_embedded_content.cc index 0c39d67e..1251e02 100644 --- a/third_party/blink/renderer/core/layout/layout_embedded_content.cc +++ b/third_party/blink/renderer/core/layout/layout_embedded_content.cc
@@ -54,11 +54,13 @@ } void LayoutEmbeddedContent::Release() { + CheckIsNotDestroyed(); if (--ref_count_ <= 0) delete this; } void LayoutEmbeddedContent::WillBeDestroyed() { + CheckIsNotDestroyed(); if (AXObjectCache* cache = GetDocument().ExistingAXObjectCache()) { cache->ChildrenChanged(Parent()); cache->Remove(this); @@ -71,6 +73,7 @@ } void LayoutEmbeddedContent::DeleteThis() { + CheckIsNotDestroyed(); // We call clearNode here because LayoutEmbeddedContent is ref counted. This // call to destroy may not actually destroy the layout object. We can keep it // around because of references from the LocalFrameView class. (The actual @@ -90,10 +93,12 @@ } FrameView* LayoutEmbeddedContent::ChildFrameView() const { + CheckIsNotDestroyed(); return DynamicTo<FrameView>(GetEmbeddedContentView()); } LayoutView* LayoutEmbeddedContent::ChildLayoutView() const { + CheckIsNotDestroyed(); if (HTMLFrameOwnerElement* owner_element = GetFrameOwnerElement()) { if (Document* content_document = owner_element->contentDocument()) return content_document->GetLayoutView(); @@ -102,6 +107,7 @@ } WebPluginContainerImpl* LayoutEmbeddedContent::Plugin() const { + CheckIsNotDestroyed(); EmbeddedContentView* embedded_content_view = GetEmbeddedContentView(); if (embedded_content_view && embedded_content_view->IsPluginView()) return To<WebPluginContainerImpl>(embedded_content_view); @@ -109,12 +115,14 @@ } EmbeddedContentView* LayoutEmbeddedContent::GetEmbeddedContentView() const { + CheckIsNotDestroyed(); if (auto* frame_owner = GetFrameOwnerElement()) return frame_owner->OwnedEmbeddedContentView(); return nullptr; } PaintLayerType LayoutEmbeddedContent::LayerTypeRequired() const { + CheckIsNotDestroyed(); if (AdditionalCompositingReasons()) return kNormalPaintLayer; @@ -135,6 +143,7 @@ } bool LayoutEmbeddedContent::ContentDocumentIsCompositing() const { + CheckIsNotDestroyed(); if (PaintLayerCompositor* inner_compositor = PaintLayerCompositor::FrameContentsCompositor(*this)) { return inner_compositor->StaleInCompositingMode(); @@ -147,6 +156,7 @@ const HitTestLocation& hit_test_location, const PhysicalOffset& accumulated_offset, HitTestAction action) { + CheckIsNotDestroyed(); bool had_result = result.InnerNode(); bool inside = LayoutReplaced::NodeAtPoint(result, hit_test_location, accumulated_offset, action); @@ -166,6 +176,7 @@ const HitTestLocation& hit_test_location, const PhysicalOffset& accumulated_offset, HitTestAction action) { + CheckIsNotDestroyed(); auto* local_frame_view = DynamicTo<LocalFrameView>(ChildFrameView()); bool skip_contents = (result.GetHitTestRequest().GetStopNode() == this || !result.GetHitTestRequest().AllowsChildFrameContent()); @@ -248,6 +259,7 @@ } CompositingReasons LayoutEmbeddedContent::AdditionalCompositingReasons() const { + CheckIsNotDestroyed(); WebPluginContainerImpl* plugin_view = Plugin(); if (plugin_view && plugin_view->CcLayer()) return CompositingReason::kPlugin; @@ -262,6 +274,7 @@ void LayoutEmbeddedContent::StyleDidChange(StyleDifference diff, const ComputedStyle* old_style) { + CheckIsNotDestroyed(); LayoutReplaced::StyleDidChange(diff, old_style); if (EmbeddedContentView* embedded_content_view = GetEmbeddedContentView()) { @@ -289,6 +302,7 @@ } void LayoutEmbeddedContent::UpdateLayout() { + CheckIsNotDestroyed(); DCHECK(NeedsLayout()); LayoutAnalyzer::Scope analyzer(*this); UpdateAfterLayout(); @@ -298,6 +312,7 @@ void LayoutEmbeddedContent::PaintReplaced( const PaintInfo& paint_info, const PhysicalOffset& paint_offset) const { + CheckIsNotDestroyed(); if (ChildPaintBlockedByDisplayLock()) return; EmbeddedContentPainter(*this).PaintReplaced(paint_info, paint_offset); @@ -305,6 +320,7 @@ void LayoutEmbeddedContent::InvalidatePaint( const PaintInvalidatorContext& context) const { + CheckIsNotDestroyed(); LayoutReplaced::InvalidatePaint(context); if (auto* plugin = Plugin()) plugin->InvalidatePaint(); @@ -312,6 +328,7 @@ CursorDirective LayoutEmbeddedContent::GetCursor(const PhysicalOffset& point, ui::Cursor& cursor) const { + CheckIsNotDestroyed(); if (Plugin()) { // A plugin is responsible for setting the cursor when the pointer is over // it. @@ -321,6 +338,7 @@ } PhysicalRect LayoutEmbeddedContent::ReplacedContentRect() const { + CheckIsNotDestroyed(); PhysicalRect content_rect = PhysicalContentBoxRect(); // IFrames set as the root scroller should get their size from their parent. if (ChildFrameView() && View() && IsEffectiveRootScroller()) { @@ -336,6 +354,7 @@ } void LayoutEmbeddedContent::UpdateOnEmbeddedContentViewChange() { + CheckIsNotDestroyed(); if (!Style()) return; @@ -365,6 +384,7 @@ void LayoutEmbeddedContent::UpdateGeometry( EmbeddedContentView& embedded_content_view) { + CheckIsNotDestroyed(); // TODO(wangxianzhu): We reset subpixel accumulation at some boundaries, so // the following code is incorrect when some ancestors are such boundaries. // What about multicol? Need a LayoutBox function to query sub-pixel @@ -415,6 +435,7 @@ } bool LayoutEmbeddedContent::IsThrottledFrameView() const { + CheckIsNotDestroyed(); if (auto* local_frame_view = DynamicTo<LocalFrameView>(ChildFrameView())) return local_frame_view->ShouldThrottleRendering(); return false;
diff --git a/third_party/blink/renderer/core/layout/layout_embedded_content.h b/third_party/blink/renderer/core/layout/layout_embedded_content.h index 816c02b..78c82ed 100644 --- a/third_party/blink/renderer/core/layout/layout_embedded_content.h +++ b/third_party/blink/renderer/core/layout/layout_embedded_content.h
@@ -51,7 +51,10 @@ const PhysicalOffset& accumulated_offset, HitTestAction) override; - void AddRef() { ++ref_count_; } + void AddRef() { + CheckIsNotDestroyed(); + ++ref_count_; + } void Release(); // LayoutEmbeddedContent::ChildFrameView returns the LocalFrameView associated @@ -68,7 +71,10 @@ void UpdateOnEmbeddedContentViewChange(); void UpdateGeometry(EmbeddedContentView&); - bool IsLayoutEmbeddedContent() const final { return true; } + bool IsLayoutEmbeddedContent() const final { + CheckIsNotDestroyed(); + return true; + } bool IsThrottledFrameView() const; @@ -82,14 +88,21 @@ void InvalidatePaint(const PaintInvalidatorContext&) const final; CursorDirective GetCursor(const PhysicalOffset&, ui::Cursor&) const final; - bool CanBeSelectionLeafInternal() const final { return true; } + bool CanBeSelectionLeafInternal() const final { + CheckIsNotDestroyed(); + return true; + } HTMLFrameOwnerElement* GetFrameOwnerElement() const { + CheckIsNotDestroyed(); return To<HTMLFrameOwnerElement>(GetNode()); } private: - bool CanHaveAdditionalCompositingReasons() const override { return true; } + bool CanHaveAdditionalCompositingReasons() const override { + CheckIsNotDestroyed(); + return true; + } CompositingReasons AdditionalCompositingReasons() const override; void WillBeDestroyed() final;
diff --git a/third_party/blink/renderer/core/layout/layout_embedded_object.cc b/third_party/blink/renderer/core/layout/layout_embedded_object.cc index 913e462..ffab276 100644 --- a/third_party/blink/renderer/core/layout/layout_embedded_object.cc +++ b/third_party/blink/renderer/core/layout/layout_embedded_object.cc
@@ -68,6 +68,7 @@ void LayoutEmbeddedObject::SetPluginAvailability( PluginAvailability availability) { + CheckIsNotDestroyed(); DCHECK_EQ(kPluginAvailable, plugin_availability_); plugin_availability_ = availability; @@ -80,16 +81,19 @@ } bool LayoutEmbeddedObject::ShowsUnavailablePluginIndicator() const { + CheckIsNotDestroyed(); return plugin_availability_ != kPluginAvailable; } void LayoutEmbeddedObject::PaintReplaced( const PaintInfo& paint_info, const PhysicalOffset& paint_offset) const { + CheckIsNotDestroyed(); EmbeddedObjectPainter(*this).PaintReplaced(paint_info, paint_offset); } void LayoutEmbeddedObject::UpdateLayout() { + CheckIsNotDestroyed(); DCHECK(NeedsLayout()); LayoutAnalyzer::Scope analyzer(*this); @@ -109,6 +113,7 @@ void LayoutEmbeddedObject::ComputeIntrinsicSizingInfo( IntrinsicSizingInfo& intrinsic_sizing_info) const { + CheckIsNotDestroyed(); DCHECK(!ShouldApplySizeContainment()); FrameView* frame_view = ChildFrameView(); if (frame_view && frame_view->GetIntrinsicSizingInfo(intrinsic_sizing_info)) { @@ -132,6 +137,7 @@ } bool LayoutEmbeddedObject::NeedsPreferredWidthsRecalculation() const { + CheckIsNotDestroyed(); if (LayoutEmbeddedContent::NeedsPreferredWidthsRecalculation()) return true; FrameView* frame_view = ChildFrameView();
diff --git a/third_party/blink/renderer/core/layout/layout_embedded_object.h b/third_party/blink/renderer/core/layout/layout_embedded_object.h index 8cc0293e..0eeedc6 100644 --- a/third_party/blink/renderer/core/layout/layout_embedded_object.h +++ b/third_party/blink/renderer/core/layout/layout_embedded_object.h
@@ -43,9 +43,13 @@ void SetPluginAvailability(PluginAvailability); bool ShowsUnavailablePluginIndicator() const; - const char* GetName() const override { return "LayoutEmbeddedObject"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutEmbeddedObject"; + } const String& UnavailablePluginReplacementText() const { + CheckIsNotDestroyed(); return unavailable_plugin_replacement_text_; } @@ -56,6 +60,7 @@ void UpdateLayout() final; bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectEmbeddedObject || LayoutEmbeddedContent::IsOfType(type); }
diff --git a/third_party/blink/renderer/core/layout/layout_fieldset.cc b/third_party/blink/renderer/core/layout/layout_fieldset.cc index 5c5afa1..7ce8759 100644 --- a/third_party/blink/renderer/core/layout/layout_fieldset.cc +++ b/third_party/blink/renderer/core/layout/layout_fieldset.cc
@@ -33,6 +33,7 @@ LayoutFieldset::LayoutFieldset(Element* element) : LayoutBlockFlow(element) {} MinMaxSizes LayoutFieldset::PreferredLogicalWidths() const { + CheckIsNotDestroyed(); MinMaxSizes sizes = LayoutBlockFlow::PreferredLogicalWidths(); // Size-contained elements don't consider their contents for preferred sizing. if (ShouldApplySizeContainment()) @@ -59,6 +60,7 @@ LayoutObject* LayoutFieldset::LayoutSpecialExcludedChild(bool relayout_children, SubtreeLayoutScope&) { + CheckIsNotDestroyed(); LayoutBox* legend = FindInFlowLegend(); if (legend) { LayoutRect old_legend_frame_rect = legend->FrameRect(); @@ -194,16 +196,19 @@ void LayoutFieldset::PaintBoxDecorationBackground( const PaintInfo& paint_info, const PhysicalOffset& paint_offset) const { + CheckIsNotDestroyed(); FieldsetPainter(*this).PaintBoxDecorationBackground(paint_info, paint_offset); } void LayoutFieldset::PaintMask(const PaintInfo& paint_info, const PhysicalOffset& paint_offset) const { + CheckIsNotDestroyed(); FieldsetPainter(*this).PaintMask(paint_info, paint_offset); } bool LayoutFieldset::BackgroundIsKnownToBeOpaqueInRect( const PhysicalRect& local_rect) const { + CheckIsNotDestroyed(); // If the field set has a legend, then it probably does not completely fill // its background. if (FindInFlowLegend())
diff --git a/third_party/blink/renderer/core/layout/layout_fieldset.h b/third_party/blink/renderer/core/layout/layout_fieldset.h index 48a366ec..0d3062e 100644 --- a/third_party/blink/renderer/core/layout/layout_fieldset.h +++ b/third_party/blink/renderer/core/layout/layout_fieldset.h
@@ -33,19 +33,29 @@ explicit LayoutFieldset(Element*); static LayoutBox* FindInFlowLegend(const LayoutBlock& fieldset); - LayoutBox* FindInFlowLegend() const { return FindInFlowLegend(*this); } + LayoutBox* FindInFlowLegend() const { + CheckIsNotDestroyed(); + return FindInFlowLegend(*this); + } static LayoutBlock* FindLegendContainingBlock(const LayoutBox& legend, AncestorSkipInfo* = nullptr); - const char* GetName() const override { return "LayoutFieldset"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutFieldset"; + } - bool CreatesNewFormattingContext() const final { return true; } + bool CreatesNewFormattingContext() const final { + CheckIsNotDestroyed(); + return true; + } bool BackgroundIsKnownToBeOpaqueInRect(const PhysicalRect&) const override; private: bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectFieldset || LayoutBlockFlow::IsOfType(type); }
diff --git a/third_party/blink/renderer/core/layout/layout_file_upload_control.cc b/third_party/blink/renderer/core/layout/layout_file_upload_control.cc index 589ba9e..81d160b5 100644 --- a/third_party/blink/renderer/core/layout/layout_file_upload_control.cc +++ b/third_party/blink/renderer/core/layout/layout_file_upload_control.cc
@@ -44,6 +44,7 @@ bool LayoutFileUploadControl::IsChildAllowed(LayoutObject* child, const ComputedStyle& style) const { + CheckIsNotDestroyed(); const Node* child_node = child->GetNode(); // Reject shadow nodes other than UploadButton. if (child_node && child_node->OwnerShadowHost() == GetNode() && @@ -53,6 +54,7 @@ } int LayoutFileUploadControl::MaxFilenameWidth() const { + CheckIsNotDestroyed(); int upload_button_width = (UploadButton() && UploadButton()->GetLayoutBox()) ? UploadButton()->GetLayoutBox()->PixelSnappedWidth() @@ -64,14 +66,17 @@ void LayoutFileUploadControl::PaintObject( const PaintInfo& paint_info, const PhysicalOffset& paint_offset) const { + CheckIsNotDestroyed(); FileUploadControlPainter(*this).PaintObject(paint_info, paint_offset); } HTMLInputElement* LayoutFileUploadControl::UploadButton() const { + CheckIsNotDestroyed(); return To<HTMLInputElement>(GetNode())->UploadButton(); } String LayoutFileUploadControl::FileTextValue() const { + CheckIsNotDestroyed(); int width = MaxFilenameWidth(); if (width <= 0) return String(); @@ -88,6 +93,7 @@ PhysicalRect LayoutFileUploadControl::OverflowClipRect( const PhysicalOffset& additional_offset, OverlayScrollbarClipBehavior) const { + CheckIsNotDestroyed(); PhysicalRect rect(additional_offset, Size()); rect.Expand(BorderInsets()); rect.offset.top -= LayoutUnit(kButtonShadowHeight);
diff --git a/third_party/blink/renderer/core/layout/layout_file_upload_control.h b/third_party/blink/renderer/core/layout/layout_file_upload_control.h index a9869961..c58dfe51 100644 --- a/third_party/blink/renderer/core/layout/layout_file_upload_control.h +++ b/third_party/blink/renderer/core/layout/layout_file_upload_control.h
@@ -38,6 +38,7 @@ ~LayoutFileUploadControl() override; bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectFileUploadControl || LayoutBlockFlow::IsOfType(type); } @@ -51,7 +52,10 @@ static const int kAfterButtonSpacing = 4; - const char* GetName() const override { return "LayoutFileUploadControl"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutFileUploadControl"; + } private: bool IsChildAllowed(LayoutObject* child,
diff --git a/third_party/blink/renderer/core/layout/layout_flexible_box.cc b/third_party/blink/renderer/core/layout/layout_flexible_box.cc index 379f1920..cd0739dc 100644 --- a/third_party/blink/renderer/core/layout/layout_flexible_box.cc +++ b/third_party/blink/renderer/core/layout/layout_flexible_box.cc
@@ -74,6 +74,7 @@ bool LayoutFlexibleBox::IsChildAllowed(LayoutObject* object, const ComputedStyle& style) const { + CheckIsNotDestroyed(); const auto* select = DynamicTo<HTMLSelectElement>(GetNode()); if (UNLIKELY(select && select->UsesMenuList())) { // For a size=1 <select>, we only render the active option label through the @@ -85,6 +86,7 @@ } MinMaxSizes LayoutFlexibleBox::ComputeIntrinsicLogicalWidths() const { + CheckIsNotDestroyed(); MinMaxSizes sizes; sizes += BorderAndPaddingLogicalWidth() + ComputeLogicalScrollbars().InlineSum(); @@ -178,6 +180,7 @@ LayoutUnit max_preferred_logical_width, LayoutBox* child, float previous_max_content_flex_fraction) const { + CheckIsNotDestroyed(); // Determine whether the new version of the intrinsic size algorithm of the // flexbox spec would produce a different result than our above algorithm. // The algorithm produces a different result iff the max-content flex @@ -214,6 +217,7 @@ bool, LineDirectionMode direction, LinePositionMode mode) const { + CheckIsNotDestroyed(); DCHECK_EQ(mode, kPositionOnContainingLine); // TODO(crbug.com/1040826): input[type=range] should not use // LayoutFlexibleBox. We should move out this code. @@ -233,6 +237,7 @@ } LayoutUnit LayoutFlexibleBox::FirstLineBoxBaseline() const { + CheckIsNotDestroyed(); if (IsWritingModeRoot() || number_of_in_flow_children_on_first_line_ <= 0 || ShouldApplyLayoutContainment()) return LayoutUnit(-1); @@ -285,10 +290,12 @@ LayoutUnit LayoutFlexibleBox::InlineBlockBaseline( LineDirectionMode direction) const { + CheckIsNotDestroyed(); return FirstLineBoxBaseline(); } bool LayoutFlexibleBox::HasTopOverflow() const { + CheckIsNotDestroyed(); if (IsHorizontalWritingMode()) return StyleRef().ResolvedIsColumnReverseFlexDirection(); return !StyleRef().IsLeftToRightDirection() ^ @@ -296,6 +303,7 @@ } bool LayoutFlexibleBox::HasLeftOverflow() const { + CheckIsNotDestroyed(); if (IsHorizontalWritingMode()) { return !StyleRef().IsLeftToRightDirection() ^ StyleRef().ResolvedIsRowReverseFlexDirection(); @@ -304,6 +312,7 @@ } void LayoutFlexibleBox::MergeAnonymousFlexItems(LayoutObject* remove_child) { + CheckIsNotDestroyed(); // When we remove a flex item, and the previous and next siblings of the item // are text nodes wrapped in anonymous flex items, the adjacent text nodes // need to be merged into the same flex item. @@ -320,6 +329,7 @@ } void LayoutFlexibleBox::RemoveChild(LayoutObject* child) { + CheckIsNotDestroyed(); if (!DocumentBeingDestroyed() && !StyleRef().IsDeprecatedFlexboxUsingFlexLayout()) { MergeAnonymousFlexItems(child); @@ -334,6 +344,7 @@ const HitTestLocation& hit_test_location, const PhysicalOffset& accumulated_offset, HitTestAction hit_test_action) { + CheckIsNotDestroyed(); if (hit_test_action != kHitTestForeground) return false; @@ -361,6 +372,7 @@ void LayoutFlexibleBox::StyleDidChange(StyleDifference diff, const ComputedStyle* old_style) { + CheckIsNotDestroyed(); LayoutBlock::StyleDidChange(diff, old_style); if (old_style && @@ -388,6 +400,7 @@ } void LayoutFlexibleBox::UpdateBlockLayout(bool relayout_children) { + CheckIsNotDestroyed(); DCHECK(NeedsLayout()); if (!relayout_children && SimplifiedLayout()) @@ -450,12 +463,14 @@ void LayoutFlexibleBox::PaintChildren(const PaintInfo& paint_info, const PhysicalOffset&) const { + CheckIsNotDestroyed(); BlockPainter(*this).PaintChildrenAtomically(this->GetOrderIterator(), paint_info); } void LayoutFlexibleBox::RepositionLogicalHeightDependentFlexItems( FlexLayoutAlgorithm& algorithm) { + CheckIsNotDestroyed(); Vector<FlexLine>& line_contexts = algorithm.FlexLines(); LayoutUnit cross_axis_start_edge = line_contexts.IsEmpty() ? LayoutUnit() @@ -487,6 +502,7 @@ DISABLE_CFI_PERF LayoutUnit LayoutFlexibleBox::ClientLogicalBottomAfterRepositioning() { + CheckIsNotDestroyed(); LayoutUnit max_child_logical_bottom; for (LayoutBox* child = FirstChildBox(); child; child = child->NextSiblingBox()) { @@ -503,6 +519,7 @@ } bool LayoutFlexibleBox::MainAxisIsInlineAxis(const LayoutBox& child) const { + CheckIsNotDestroyed(); // If we have a horizontal flow, that means the main size is the width. // That's the inline size for horizontal writing modes, and the block // size in vertical writing modes. For a vertical flow, main size is the @@ -513,16 +530,19 @@ } bool LayoutFlexibleBox::IsColumnFlow() const { + CheckIsNotDestroyed(); return StyleRef().ResolvedIsColumnFlexDirection(); } bool LayoutFlexibleBox::IsHorizontalFlow() const { + CheckIsNotDestroyed(); if (IsHorizontalWritingMode()) return !IsColumnFlow(); return IsColumnFlow(); } bool LayoutFlexibleBox::IsLeftToRightFlow() const { + CheckIsNotDestroyed(); if (IsColumnFlow()) { return blink::IsHorizontalWritingMode(StyleRef().GetWritingMode()) || IsFlippedLinesWritingMode(StyleRef().GetWritingMode()); @@ -532,10 +552,12 @@ } bool LayoutFlexibleBox::IsMultiline() const { + CheckIsNotDestroyed(); return StyleRef().FlexWrap() != EFlexWrap::kNowrap; } Length LayoutFlexibleBox::FlexBasisForChild(const LayoutBox& child) const { + CheckIsNotDestroyed(); Length flex_length = child.StyleRef().FlexBasis(); if (flex_length.IsAuto()) { flex_length = IsHorizontalFlow() ? child.StyleRef().Width() @@ -546,11 +568,13 @@ LayoutUnit LayoutFlexibleBox::CrossAxisExtentForChild( const LayoutBox& child) const { + CheckIsNotDestroyed(); return IsHorizontalFlow() ? child.Size().Height() : child.Size().Width(); } LayoutUnit LayoutFlexibleBox::ChildUnstretchedLogicalHeight( const LayoutBox& child) const { + CheckIsNotDestroyed(); // This should only be called if the logical height is the cross size DCHECK(MainAxisIsInlineAxis(child)); if (NeedToStretchChildLogicalHeight(child)) { @@ -581,6 +605,7 @@ DISABLE_CFI_PERF LayoutUnit LayoutFlexibleBox::ChildUnstretchedLogicalWidth( const LayoutBox& child) const { + CheckIsNotDestroyed(); // This should only be called if the logical width is the cross size DCHECK(!MainAxisIsInlineAxis(child)); @@ -601,37 +626,44 @@ LayoutUnit LayoutFlexibleBox::CrossAxisUnstretchedExtentForChild( const LayoutBox& child) const { + CheckIsNotDestroyed(); return MainAxisIsInlineAxis(child) ? ChildUnstretchedLogicalHeight(child) : ChildUnstretchedLogicalWidth(child); } LayoutUnit LayoutFlexibleBox::MainAxisExtentForChild( const LayoutBox& child) const { + CheckIsNotDestroyed(); return IsHorizontalFlow() ? child.Size().Width() : child.Size().Height(); } LayoutUnit LayoutFlexibleBox::MainAxisContentExtentForChild( const LayoutBox& child) const { + CheckIsNotDestroyed(); return IsHorizontalFlow() ? child.ContentWidth() : child.ContentHeight(); } LayoutUnit LayoutFlexibleBox::MainAxisContentExtentForChildIncludingScrollbar( const LayoutBox& child) const { + CheckIsNotDestroyed(); return IsHorizontalFlow() ? child.ContentWidth() + child.ComputeScrollbars().HorizontalSum() : child.ContentHeight() + child.ComputeScrollbars().VerticalSum(); } LayoutUnit LayoutFlexibleBox::CrossAxisExtent() const { + CheckIsNotDestroyed(); return IsHorizontalFlow() ? Size().Height() : Size().Width(); } LayoutUnit LayoutFlexibleBox::CrossAxisContentExtent() const { + CheckIsNotDestroyed(); return IsHorizontalFlow() ? ContentHeight() : ContentWidth(); } LayoutUnit LayoutFlexibleBox::MainAxisContentExtent( LayoutUnit content_logical_height) { + CheckIsNotDestroyed(); if (IsColumnFlow()) { LogicalExtentComputedValues computed_values; LayoutUnit border_padding_and_scrollbar = @@ -653,6 +685,7 @@ SizeType size_type, const Length& size, LayoutUnit border_and_padding) const { + CheckIsNotDestroyed(); if (!MainAxisIsInlineAxis(child)) { // We don't have to check for "auto" here - computeContentLogicalHeight // will just return -1 for that case anyway. It's safe to access @@ -682,26 +715,31 @@ } LayoutUnit LayoutFlexibleBox::ContentInsetRight() const { + CheckIsNotDestroyed(); return BorderRight() + PaddingRight() + ComputeScrollbars().right; } LayoutUnit LayoutFlexibleBox::ContentInsetBottom() const { + CheckIsNotDestroyed(); return BorderBottom() + PaddingBottom() + ComputeScrollbars().bottom; } LayoutUnit LayoutFlexibleBox::FlowAwareContentInsetStart() const { + CheckIsNotDestroyed(); if (IsHorizontalFlow()) return IsLeftToRightFlow() ? ContentLeft() : ContentInsetRight(); return IsLeftToRightFlow() ? ContentTop() : ContentInsetBottom(); } LayoutUnit LayoutFlexibleBox::FlowAwareContentInsetEnd() const { + CheckIsNotDestroyed(); if (IsHorizontalFlow()) return IsLeftToRightFlow() ? ContentInsetRight() : ContentLeft(); return IsLeftToRightFlow() ? ContentInsetBottom() : ContentTop(); } LayoutUnit LayoutFlexibleBox::FlowAwareContentInsetBefore() const { + CheckIsNotDestroyed(); switch (FlexLayoutAlgorithm::GetTransformedWritingMode(StyleRef())) { case TransformedWritingMode::kTopToBottomWritingMode: return ContentTop(); @@ -717,6 +755,7 @@ DISABLE_CFI_PERF LayoutUnit LayoutFlexibleBox::FlowAwareContentInsetAfter() const { + CheckIsNotDestroyed(); switch (FlexLayoutAlgorithm::GetTransformedWritingMode(StyleRef())) { case TransformedWritingMode::kTopToBottomWritingMode: return ContentInsetBottom(); @@ -731,23 +770,27 @@ } LayoutUnit LayoutFlexibleBox::CrossAxisScrollbarExtent() const { + CheckIsNotDestroyed(); return IsHorizontalFlow() ? ComputeScrollbars().HorizontalSum() : ComputeScrollbars().VerticalSum(); } LayoutUnit LayoutFlexibleBox::CrossAxisScrollbarExtentForChild( const LayoutBox& child) const { + CheckIsNotDestroyed(); return IsHorizontalFlow() ? child.ComputeScrollbars().HorizontalSum() : child.ComputeScrollbars().VerticalSum(); } LayoutPoint LayoutFlexibleBox::FlowAwareLocationForChild( const LayoutBox& child) const { + CheckIsNotDestroyed(); return IsHorizontalFlow() ? child.Location() : child.Location().TransposedPoint(); } bool LayoutFlexibleBox::UseChildAspectRatio(const LayoutBox& child) const { + CheckIsNotDestroyed(); if (!HasAspectRatio(child)) return false; if (!child.StyleRef().AspectRatio() && child.IntrinsicSize().Height() == 0) { @@ -762,6 +805,7 @@ LayoutUnit LayoutFlexibleBox::ComputeMainSizeFromAspectRatioUsing( const LayoutBox& child, const Length& cross_size_length) const { + CheckIsNotDestroyed(); DCHECK(HasAspectRatio(child)); LayoutUnit cross_size; @@ -792,6 +836,7 @@ void LayoutFlexibleBox::SetFlowAwareLocationForChild( LayoutBox& child, const LayoutPoint& location) { + CheckIsNotDestroyed(); if (IsHorizontalFlow()) child.SetLocationAndUpdateOverflowControlsIfNeeded(location); else @@ -802,6 +847,7 @@ bool LayoutFlexibleBox::MainAxisLengthIsDefinite(const LayoutBox& child, const Length& flex_basis, bool add_to_cb) const { + CheckIsNotDestroyed(); if (flex_basis.IsAuto()) return false; if (IsColumnFlow() && flex_basis.IsIntrinsic()) @@ -838,6 +884,7 @@ bool LayoutFlexibleBox::CrossAxisLengthIsDefinite(const LayoutBox& child, const Length& length) const { + CheckIsNotDestroyed(); if (length.IsAuto()) return false; if (length.IsPercentOrCalc()) { @@ -858,6 +905,7 @@ } void LayoutFlexibleBox::CacheChildMainSize(const LayoutBox& child) { + CheckIsNotDestroyed(); DCHECK(!child.SelfNeedsLayout()); DCHECK(!child.NeedsLayout() || child.ChildLayoutBlockedByDisplayLock()); LayoutUnit main_size; @@ -878,10 +926,12 @@ } void LayoutFlexibleBox::ClearCachedMainSizeForChild(const LayoutBox& child) { + CheckIsNotDestroyed(); intrinsic_size_along_main_axis_.erase(&child); } bool LayoutFlexibleBox::CanAvoidLayoutForNGChild(const LayoutBox& child) const { + CheckIsNotDestroyed(); if (!child.IsLayoutNGMixin()) return false; @@ -915,6 +965,7 @@ LayoutBox& child, LayoutUnit main_axis_border_and_padding, ChildLayoutType child_layout_type) { + CheckIsNotDestroyed(); if (child.IsImage() || IsA<LayoutVideo>(child) || child.IsCanvas()) UseCounter::Count(GetDocument(), WebFeature::kAspectRatioFlexItem); @@ -974,6 +1025,7 @@ void LayoutFlexibleBox::LayoutFlexItems(bool relayout_children, SubtreeLayoutScope& layout_scope) { + CheckIsNotDestroyed(); PaintLayerScrollableArea::PreventRelayoutScope prevent_relayout_scope( layout_scope); @@ -1052,6 +1104,7 @@ bool LayoutFlexibleBox::HasAutoMarginsInCrossAxis( const LayoutBox& child) const { + CheckIsNotDestroyed(); if (IsHorizontalFlow()) { return child.StyleRef().MarginTop().IsAuto() || child.StyleRef().MarginBottom().IsAuto(); @@ -1061,6 +1114,7 @@ } LayoutUnit LayoutFlexibleBox::ComputeChildMarginValue(const Length& margin) { + CheckIsNotDestroyed(); // When resolving the margins, we use the content size for resolving percent // and calc (for percents in calc expressions) margins. Fortunately, percent // margins are always computed with respect to the block's width, even for @@ -1070,6 +1124,7 @@ } void LayoutFlexibleBox::PrepareOrderIteratorAndMargins() { + CheckIsNotDestroyed(); OrderIteratorPopulator populator(order_iterator_); for (LayoutBox* child = FirstChildBox(); child; @@ -1093,6 +1148,7 @@ const FlexLayoutAlgorithm& algorithm, const LayoutBox& child, LayoutUnit border_and_padding) const { + CheckIsNotDestroyed(); MinMaxSizes sizes{LayoutUnit(), LayoutUnit::Max()}; const Length& max = IsHorizontalFlow() ? child.StyleRef().MaxWidth() @@ -1159,6 +1215,7 @@ bool LayoutFlexibleBox::CrossSizeIsDefiniteForPercentageResolution( const LayoutBox& child) const { + CheckIsNotDestroyed(); DCHECK(MainAxisIsInlineAxis(child)); if (FlexLayoutAlgorithm::AlignmentForChild(StyleRef(), child.StyleRef()) != ItemPosition::kStretch) @@ -1179,6 +1236,7 @@ bool LayoutFlexibleBox::MainSizeIsDefiniteForPercentageResolution( const LayoutBox& child) const { + CheckIsNotDestroyed(); DCHECK(!MainAxisIsInlineAxis(child)); // This function implements section 9.8. Definite and Indefinite Sizes, case // 2) of the flexbox spec. @@ -1192,6 +1250,7 @@ bool LayoutFlexibleBox::UseOverrideLogicalHeightForPerentageResolution( const LayoutBox& child) const { + CheckIsNotDestroyed(); if (MainAxisIsInlineAxis(child)) return CrossSizeIsDefiniteForPercentageResolution(child); return MainSizeIsDefiniteForPercentageResolution(child); @@ -1200,6 +1259,7 @@ LayoutUnit LayoutFlexibleBox::AdjustChildSizeForAspectRatioCrossAxisMinAndMax( const LayoutBox& child, LayoutUnit child_size) const { + CheckIsNotDestroyed(); const Length& cross_min = IsHorizontalFlow() ? child.StyleRef().MinHeight() : child.StyleRef().MinWidth(); const Length& cross_max = IsHorizontalFlow() ? child.StyleRef().MaxHeight() @@ -1225,6 +1285,7 @@ FlexLayoutAlgorithm* algorithm, LayoutBox& child, ChildLayoutType layout_type) { + CheckIsNotDestroyed(); if (layout_type != kNeverLayout && ChildHasIntrinsicMainAxisSize(*algorithm, child)) { // If this condition is true, then ComputeMainAxisExtentForChild will call @@ -1277,6 +1338,7 @@ } void LayoutFlexibleBox::SetOverrideMainAxisContentSizeForChild(FlexItem& item) { + CheckIsNotDestroyed(); if (MainAxisIsInlineAxis(*item.box)) { item.box->SetOverrideLogicalWidth(item.FlexedBorderBoxSize()); } else { @@ -1378,6 +1440,7 @@ LayoutUnit LayoutFlexibleBox::StaticMainAxisPositionForPositionedChild( const LayoutBox& child) { + CheckIsNotDestroyed(); const LayoutUnit available_space = MainAxisContentExtent(ContentLogicalHeight()) - MainAxisExtentForChild(child); @@ -1387,6 +1450,7 @@ LayoutUnit LayoutFlexibleBox::StaticCrossAxisPositionForPositionedChild( const LayoutBox& child) { + CheckIsNotDestroyed(); LayoutUnit available_space = CrossAxisContentExtent() - CrossAxisExtentForChild(child); return CrossAxisStaticPositionCommon(child, this, available_space); @@ -1394,6 +1458,7 @@ LayoutUnit LayoutFlexibleBox::StaticInlinePositionForPositionedChild( const LayoutBox& child) { + CheckIsNotDestroyed(); const LayoutUnit start_offset = StartOffsetForContent(); if (StyleRef().IsDeprecatedWebkitBox()) return start_offset; @@ -1404,12 +1469,14 @@ LayoutUnit LayoutFlexibleBox::StaticBlockPositionForPositionedChild( const LayoutBox& child) { + CheckIsNotDestroyed(); return BorderAndPaddingBefore() + (IsColumnFlow() ? StaticMainAxisPositionForPositionedChild(child) : StaticCrossAxisPositionForPositionedChild(child)); } bool LayoutFlexibleBox::SetStaticPositionForPositionedLayout(LayoutBox& child) { + CheckIsNotDestroyed(); bool position_changed = false; PaintLayer* child_layer = child.Layer(); if (child.StyleRef().HasStaticInlinePosition( @@ -1432,6 +1499,7 @@ } void LayoutFlexibleBox::PrepareChildForPositionedLayout(LayoutBox& child) { + CheckIsNotDestroyed(); DCHECK(child.IsOutOfFlowPositioned()); child.ContainingBlock()->InsertPositionedObject(&child); PaintLayer* child_layer = child.Layer(); @@ -1454,6 +1522,7 @@ void LayoutFlexibleBox::ResetAutoMarginsAndLogicalTopInCrossAxis( LayoutBox& child) { + CheckIsNotDestroyed(); if (HasAutoMarginsInCrossAxis(child)) { child.UpdateLogicalHeight(); if (IsHorizontalFlow()) { @@ -1472,6 +1541,7 @@ bool LayoutFlexibleBox::NeedToStretchChildLogicalHeight( const LayoutBox& child) const { + CheckIsNotDestroyed(); // This function is a little bit magical. It relies on the fact that blocks // intrinsically "stretch" themselves in their inline axis, i.e. a <div> has // an implicit width: 100%. So the child will automatically stretch if our @@ -1492,6 +1562,7 @@ bool LayoutFlexibleBox::ChildHasIntrinsicMainAxisSize( const FlexLayoutAlgorithm& algorithm, const LayoutBox& child) const { + CheckIsNotDestroyed(); bool result = false; if (!MainAxisIsInlineAxis(child) && !child.ShouldApplySizeContainment()) { Length child_flex_basis = FlexBasisForChild(child); @@ -1513,6 +1584,7 @@ EOverflow LayoutFlexibleBox::CrossAxisOverflowForChild( const LayoutBox& child) const { + CheckIsNotDestroyed(); if (IsHorizontalFlow()) return child.StyleRef().OverflowY(); return child.StyleRef().OverflowX(); @@ -1522,6 +1594,7 @@ void LayoutFlexibleBox::LayoutLineItems(FlexLine* current_line, bool relayout_children, SubtreeLayoutScope& layout_scope) { + CheckIsNotDestroyed(); for (wtf_size_t i = 0; i < current_line->line_items.size(); ++i) { FlexItem& flex_item = current_line->line_items[i]; LayoutBox* child = flex_item.box; @@ -1586,6 +1659,7 @@ } void LayoutFlexibleBox::ApplyLineItemsPosition(FlexLine* current_line) { + CheckIsNotDestroyed(); bool is_paginated = View()->GetLayoutState()->IsPaginated(); for (wtf_size_t i = 0; i < current_line->line_items.size(); ++i) { const FlexItem& flex_item = current_line->line_items[i]; @@ -1621,6 +1695,7 @@ void LayoutFlexibleBox::LayoutColumnReverse(FlexItemVectorView& children, LayoutUnit cross_axis_offset, LayoutUnit available_free_space) { + CheckIsNotDestroyed(); const StyleContentAlignmentData justify_content = FlexLayoutAlgorithm::ResolvedJustifyContent(StyleRef()); @@ -1653,6 +1728,7 @@ } void LayoutFlexibleBox::AlignFlexLines(FlexLayoutAlgorithm& algorithm) { + CheckIsNotDestroyed(); Vector<FlexLine>& line_contexts = algorithm.FlexLines(); const StyleContentAlignmentData align_content = FlexLayoutAlgorithm::ResolvedAlignContent(StyleRef()); @@ -1679,11 +1755,13 @@ void LayoutFlexibleBox::ResetAlignmentForChild( LayoutBox& child, LayoutUnit new_cross_axis_position) { + CheckIsNotDestroyed(); SetFlowAwareLocationForChild( child, {FlowAwareLocationForChild(child).X(), new_cross_axis_position}); } void LayoutFlexibleBox::AlignChildren(FlexLayoutAlgorithm& algorithm) { + CheckIsNotDestroyed(); Vector<FlexLine>& line_contexts = algorithm.FlexLines(); algorithm.AlignChildren(); @@ -1703,6 +1781,7 @@ } void LayoutFlexibleBox::ApplyStretchAlignmentToChild(FlexItem& flex_item) { + CheckIsNotDestroyed(); LayoutBox& child = *flex_item.box; if (flex_item.MainAxisIsInlineAxis() && child.StyleRef().LogicalHeight().IsAuto()) { @@ -1734,6 +1813,7 @@ void LayoutFlexibleBox::FlipForRightToLeftColumn( const Vector<FlexLine>& line_contexts) { + CheckIsNotDestroyed(); if (StyleRef().IsLeftToRightDirection() || !IsColumnFlow()) return;
diff --git a/third_party/blink/renderer/core/layout/layout_flexible_box.h b/third_party/blink/renderer/core/layout/layout_flexible_box.h index 493d739..fbed085c 100644 --- a/third_party/blink/renderer/core/layout/layout_flexible_box.h +++ b/third_party/blink/renderer/core/layout/layout_flexible_box.h
@@ -48,11 +48,23 @@ explicit LayoutFlexibleBox(Element*); ~LayoutFlexibleBox() override; - const char* GetName() const override { return "LayoutFlexibleBox"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutFlexibleBox"; + } - bool IsFlexibleBox() const final { return true; } - bool IsFlexibleBoxIncludingNG() const final { return true; } - bool IsFlexibleBoxIncludingDeprecatedAndNG() const final { return true; } + bool IsFlexibleBox() const final { + CheckIsNotDestroyed(); + return true; + } + bool IsFlexibleBoxIncludingNG() const final { + CheckIsNotDestroyed(); + return true; + } + bool IsFlexibleBoxIncludingDeprecatedAndNG() const final { + CheckIsNotDestroyed(); + return true; + } void UpdateBlockLayout(bool relayout_children) final; bool IsChildAllowed(LayoutObject* object, @@ -76,7 +88,10 @@ bool IsHorizontalFlow() const; - const OrderIterator& GetOrderIterator() const { return order_iterator_; } + const OrderIterator& GetOrderIterator() const { + CheckIsNotDestroyed(); + return order_iterator_; + } // These three functions are used when resolving percentages against a // flex item's logical height. In flexbox, sometimes a logical height
diff --git a/third_party/blink/renderer/core/layout/layout_flow_thread.cc b/third_party/blink/renderer/core/layout/layout_flow_thread.cc index 890492c..cd2e19b7 100644 --- a/third_party/blink/renderer/core/layout/layout_flow_thread.cc +++ b/third_party/blink/renderer/core/layout/layout_flow_thread.cc
@@ -96,6 +96,7 @@ void LayoutFlowThread::RemoveColumnSetFromThread( LayoutMultiColumnSet* column_set) { + CheckIsNotDestroyed(); DCHECK(column_set); multi_column_set_list_.erase(column_set); InvalidateColumnSets(); @@ -109,6 +110,7 @@ } void LayoutFlowThread::ValidateColumnSets() { + CheckIsNotDestroyed(); column_sets_invalidated_ = false; // Called to get the maximum logical width for the columnSet. UpdateLogicalWidth(); @@ -119,6 +121,7 @@ const LayoutBoxModelObject* ancestor, TransformState& transform_state, VisualRectFlags visual_rect_flags) const { + CheckIsNotDestroyed(); // A flow thread should never be an invalidation container. DCHECK_NE(ancestor, this); transform_state.Flatten(); @@ -130,12 +133,14 @@ } void LayoutFlowThread::UpdateLayout() { + CheckIsNotDestroyed(); page_logical_size_changed_ = column_sets_invalidated_ && EverHadLayout(); LayoutBlockFlow::UpdateLayout(); page_logical_size_changed_ = false; } PaintLayerType LayoutFlowThread::LayerTypeRequired() const { + CheckIsNotDestroyed(); if (!needs_paint_layer_) return kNoPaintLayer; // Always create a Layer for the LayoutFlowThread so that we can easily avoid @@ -148,6 +153,7 @@ LayoutUnit, LayoutUnit logical_top, LogicalExtentComputedValues& computed_values) const { + CheckIsNotDestroyed(); computed_values.position_ = logical_top; computed_values.extent_ = LayoutUnit(); @@ -162,6 +168,7 @@ void LayoutFlowThread::AbsoluteQuadsForDescendant(const LayoutBox& descendant, Vector<FloatQuad>& quads, MapCoordinatesFlags mode) { + CheckIsNotDestroyed(); LayoutPoint offset_from_flow_thread; for (const LayoutObject* object = &descendant; object != this;) { const LayoutObject* container = object->Container(); @@ -191,6 +198,7 @@ Vector<PhysicalRect>& rects, const PhysicalOffset& additional_offset, NGOutlineType include_block_overflows) const { + CheckIsNotDestroyed(); Vector<PhysicalRect> rects_in_flowthread; LayoutBlockFlow::AddOutlineRects(rects_in_flowthread, additional_offset, include_block_overflows); @@ -211,6 +219,7 @@ const HitTestLocation& hit_test_location, const PhysicalOffset& accumulated_offset, HitTestAction hit_test_action) { + CheckIsNotDestroyed(); if (hit_test_action == kHitTestBlockBackground) return false; return LayoutBlockFlow::NodeAtPoint(result, hit_test_location, @@ -219,6 +228,7 @@ LayoutUnit LayoutFlowThread::PageLogicalHeightForOffset( LayoutUnit offset) const { + CheckIsNotDestroyed(); DCHECK(IsPageLogicalHeightKnown()); LayoutMultiColumnSet* column_set = ColumnSetAtBlockOffset(offset, kAssociateWithLatterPage); @@ -231,6 +241,7 @@ LayoutUnit LayoutFlowThread::PageRemainingLogicalHeightForOffset( LayoutUnit offset, PageBoundaryRule page_boundary_rule) const { + CheckIsNotDestroyed(); DCHECK(IsPageLogicalHeightKnown()); LayoutMultiColumnSet* column_set = ColumnSetAtBlockOffset(offset, page_boundary_rule); @@ -242,6 +253,7 @@ } void LayoutFlowThread::GenerateColumnSetIntervalTree() { + CheckIsNotDestroyed(); // FIXME: Optimize not to clear the interval all the time. This implies // manually managing the tree nodes lifecycle. multi_column_set_interval_tree_.Clear(); @@ -256,6 +268,7 @@ LayoutUnit LayoutFlowThread::NextLogicalTopForUnbreakableContent( LayoutUnit flow_thread_offset, LayoutUnit content_logical_height) const { + CheckIsNotDestroyed(); LayoutMultiColumnSet* column_set = ColumnSetAtBlockOffset(flow_thread_offset, kAssociateWithLatterPage); if (!column_set) @@ -266,6 +279,7 @@ LayoutRect LayoutFlowThread::FragmentsBoundingBox( const LayoutRect& layer_bounding_box) const { + CheckIsNotDestroyed(); DCHECK(!column_sets_invalidated_); LayoutRect result; @@ -278,6 +292,7 @@ void LayoutFlowThread::FlowThreadToContainingCoordinateSpace( LayoutUnit& block_position, LayoutUnit& inline_position) const { + CheckIsNotDestroyed(); LayoutPoint position(inline_position, block_position); // First we have to make |position| physical, because that's what offsetLeft() // expects and returns.
diff --git a/third_party/blink/renderer/core/layout/layout_flow_thread.h b/third_party/blink/renderer/core/layout/layout_flow_thread.h index 3ffeb29..6947effd 100644 --- a/third_party/blink/renderer/core/layout/layout_flow_thread.h +++ b/third_party/blink/renderer/core/layout/layout_flow_thread.h
@@ -68,10 +68,17 @@ explicit LayoutFlowThread(bool needs_paint_layer); ~LayoutFlowThread() override = default; - bool IsLayoutFlowThread() const final { return true; } - virtual bool IsLayoutMultiColumnFlowThread() const { return false; } + bool IsLayoutFlowThread() const final { + CheckIsNotDestroyed(); + return true; + } + virtual bool IsLayoutMultiColumnFlowThread() const { + CheckIsNotDestroyed(); + return false; + } bool CreatesNewFormattingContext() const final { + CheckIsNotDestroyed(); // The spec requires multicol containers to establish new formatting // contexts. Blink uses an anonymous flow thread child of the multicol // container to actually perform layout inside. Therefore we need to @@ -103,18 +110,29 @@ PaintLayerType LayerTypeRequired() const final; - bool NeedsPreferredWidthsRecalculation() const final { return true; } + bool NeedsPreferredWidthsRecalculation() const final { + CheckIsNotDestroyed(); + return true; + } - virtual void FlowThreadDescendantWasInserted(LayoutObject*) {} - virtual void FlowThreadDescendantWillBeRemoved(LayoutObject*) {} + virtual void FlowThreadDescendantWasInserted(LayoutObject*) { + CheckIsNotDestroyed(); + } + virtual void FlowThreadDescendantWillBeRemoved(LayoutObject*) { + CheckIsNotDestroyed(); + } virtual void FlowThreadDescendantStyleWillChange( LayoutBox*, StyleDifference, - const ComputedStyle& new_style) {} + const ComputedStyle& new_style) { + CheckIsNotDestroyed(); + } virtual void FlowThreadDescendantStyleDidChange( LayoutBox*, StyleDifference, - const ComputedStyle& old_style) {} + const ComputedStyle& old_style) { + CheckIsNotDestroyed(); + } void AbsoluteQuadsForDescendant(const LayoutBox& descendant, Vector<FloatQuad>&, @@ -136,11 +154,18 @@ LayoutUnit logical_top, LogicalExtentComputedValues&) const override; - bool HasColumnSets() const { return multi_column_set_list_.size(); } + bool HasColumnSets() const { + CheckIsNotDestroyed(); + return multi_column_set_list_.size(); + } void ValidateColumnSets(); - void InvalidateColumnSets() { column_sets_invalidated_ = true; } + void InvalidateColumnSets() { + CheckIsNotDestroyed(); + column_sets_invalidated_ = true; + } bool HasValidColumnSetInfo() const { + CheckIsNotDestroyed(); return !column_sets_invalidated_ && !multi_column_set_list_.IsEmpty(); } @@ -171,9 +196,15 @@ LayoutUnit flow_thread_offset, LayoutUnit content_logical_height) const; - virtual bool IsPageLogicalHeightKnown() const { return true; } + virtual bool IsPageLogicalHeightKnown() const { + CheckIsNotDestroyed(); + return true; + } virtual bool MayHaveNonUniformPageLogicalHeight() const = 0; - bool PageLogicalSizeChanged() const { return page_logical_size_changed_; } + bool PageLogicalSizeChanged() const { + CheckIsNotDestroyed(); + return page_logical_size_changed_; + } // Return the visual bounding box based on the supplied flow-thread bounding // box. Both rectangles are completely physical in terms of writing mode.
diff --git a/third_party/blink/renderer/core/layout/layout_frame.cc b/third_party/blink/renderer/core/layout/layout_frame.cc index 350e48e..6b6f080 100644 --- a/third_party/blink/renderer/core/layout/layout_frame.cc +++ b/third_party/blink/renderer/core/layout/layout_frame.cc
@@ -37,11 +37,13 @@ } FrameEdgeInfo LayoutFrame::EdgeInfo() const { + CheckIsNotDestroyed(); auto* element = To<HTMLFrameElement>(GetNode()); return FrameEdgeInfo(element->NoResize(), element->HasFrameBorder()); } void LayoutFrame::ImageChanged(WrappedImagePtr image, CanDeferInvalidation) { + CheckIsNotDestroyed(); if (const CursorList* cursors = StyleRef().Cursors()) { for (const CursorData& cursor : *cursors) { if (cursor.GetImage() && cursor.GetImage()->CachedImage() == image) { @@ -58,6 +60,7 @@ } void LayoutFrame::UpdateFromElement() { + CheckIsNotDestroyed(); if (Parent() && Parent()->IsFrameSet()) ToLayoutFrameSet(Parent())->NotifyFrameEdgeInfoChanged(); }
diff --git a/third_party/blink/renderer/core/layout/layout_frame.h b/third_party/blink/renderer/core/layout/layout_frame.h index f8c70f9..709f241d 100644 --- a/third_party/blink/renderer/core/layout/layout_frame.h +++ b/third_party/blink/renderer/core/layout/layout_frame.h
@@ -38,10 +38,14 @@ void ImageChanged(WrappedImagePtr, CanDeferInvalidation) override; - const char* GetName() const override { return "LayoutFrame"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutFrame"; + } private: bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectFrame || LayoutEmbeddedContent::IsOfType(type); }
diff --git a/third_party/blink/renderer/core/layout/layout_frame_set.cc b/third_party/blink/renderer/core/layout/layout_frame_set.cc index fc00cf0c..f7bb93f0 100644 --- a/third_party/blink/renderer/core/layout/layout_frame_set.cc +++ b/third_party/blink/renderer/core/layout/layout_frame_set.cc
@@ -58,10 +58,12 @@ LayoutFrameSet::GridAxis::GridAxis() : split_being_resized_(kNoSplit) {} HTMLFrameSetElement* LayoutFrameSet::FrameSet() const { + CheckIsNotDestroyed(); return To<HTMLFrameSetElement>(GetNode()); } void LayoutFrameSet::Paint(const PaintInfo& paint_info) const { + CheckIsNotDestroyed(); FrameSetPainter(*this).Paint(paint_info); } @@ -82,6 +84,7 @@ void LayoutFrameSet::LayOutAxis(GridAxis& axis, const Vector<HTMLDimension>& grid, int available_len) { + CheckIsNotDestroyed(); available_len = max(available_len, 0); int* grid_layout = axis.sizes_.data(); @@ -285,6 +288,7 @@ } void LayoutFrameSet::NotifyFrameEdgeInfoChanged() { + CheckIsNotDestroyed(); if (NeedsLayout()) return; // FIXME: We should only recompute the edge info with respect to the frame @@ -296,6 +300,7 @@ void LayoutFrameSet::FillFromEdgeInfo(const FrameEdgeInfo& edge_info, int r, int c) { + CheckIsNotDestroyed(); if (edge_info.AllowBorder(kLeftFrameEdge)) cols_.allow_border_[c] = true; if (edge_info.AllowBorder(kRightFrameEdge)) @@ -316,6 +321,7 @@ } void LayoutFrameSet::ComputeEdgeInfo() { + CheckIsNotDestroyed(); rows_.prevent_resize_.Fill(FrameSet()->NoResize()); rows_.allow_border_.Fill(false); cols_.prevent_resize_.Fill(FrameSet()->NoResize()); @@ -343,6 +349,7 @@ } FrameEdgeInfo LayoutFrameSet::EdgeInfo() const { + CheckIsNotDestroyed(); FrameEdgeInfo result(FrameSet()->NoResize(), true); int rows = FrameSet()->TotalRows(); @@ -362,6 +369,7 @@ } void LayoutFrameSet::UpdateLayout() { + CheckIsNotDestroyed(); DCHECK(NeedsLayout()); if (!Parent()->IsFrameSet() && !GetDocument().Printing()) { @@ -404,6 +412,7 @@ } void LayoutFrameSet::PositionFrames() { + CheckIsNotDestroyed(); LayoutBox* child = FirstChildBox(); if (!child) return; @@ -447,6 +456,7 @@ } void LayoutFrameSet::StartResizing(GridAxis& axis, int position) { + CheckIsNotDestroyed(); int split = HitTestSplit(axis, position); if (split == kNoSplit || axis.prevent_resize_[split]) { axis.split_being_resized_ = kNoSplit; @@ -457,6 +467,7 @@ } void LayoutFrameSet::ContinueResizing(GridAxis& axis, int position) { + CheckIsNotDestroyed(); if (NeedsLayout()) return; if (axis.split_being_resized_ == kNoSplit) @@ -472,6 +483,7 @@ } bool LayoutFrameSet::UserResize(const MouseEvent& evt) { + CheckIsNotDestroyed(); if (!is_resizing_) { if (NeedsLayout()) return false; @@ -510,6 +522,7 @@ } void LayoutFrameSet::SetIsResizing(bool is_resizing) { + CheckIsNotDestroyed(); is_resizing_ = is_resizing; if (LocalFrame* frame = GetFrame()) { frame->GetEventHandler().SetResizingFrameSet(is_resizing ? FrameSet() @@ -518,16 +531,19 @@ } bool LayoutFrameSet::CanResizeRow(const IntPoint& p) const { + CheckIsNotDestroyed(); int r = HitTestSplit(rows_, p.Y()); return r != kNoSplit && !rows_.prevent_resize_[r]; } bool LayoutFrameSet::CanResizeColumn(const IntPoint& p) const { + CheckIsNotDestroyed(); int c = HitTestSplit(cols_, p.X()); return c != kNoSplit && !cols_.prevent_resize_[c]; } int LayoutFrameSet::SplitPosition(const GridAxis& axis, int split) const { + CheckIsNotDestroyed(); if (NeedsLayout()) return 0; @@ -544,6 +560,7 @@ } int LayoutFrameSet::HitTestSplit(const GridAxis& axis, int position) const { + CheckIsNotDestroyed(); if (NeedsLayout()) return kNoSplit; @@ -567,11 +584,13 @@ bool LayoutFrameSet::IsChildAllowed(LayoutObject* child, const ComputedStyle&) const { + CheckIsNotDestroyed(); return child->IsFrame() || child->IsFrameSet(); } CursorDirective LayoutFrameSet::GetCursor(const PhysicalOffset& point, ui::Cursor& cursor) const { + CheckIsNotDestroyed(); IntPoint rounded_point = RoundedIntPoint(point); if (CanResizeRow(rounded_point)) { cursor = RowResizeCursor();
diff --git a/third_party/blink/renderer/core/layout/layout_frame_set.h b/third_party/blink/renderer/core/layout/layout_frame_set.h index e25859a8..ec9df3f0 100644 --- a/third_party/blink/renderer/core/layout/layout_frame_set.h +++ b/third_party/blink/renderer/core/layout/layout_frame_set.h
@@ -69,10 +69,12 @@ ~LayoutFrameSet() override; LayoutObject* FirstChild() const { + CheckIsNotDestroyed(); DCHECK_EQ(Children(), VirtualChildren()); return Children()->FirstChild(); } LayoutObject* LastChild() const { + CheckIsNotDestroyed(); DCHECK_EQ(Children(), VirtualChildren()); return Children()->LastChild(); } @@ -81,8 +83,14 @@ void SlowFirstChild() const = delete; void SlowLastChild() const = delete; - const LayoutObjectChildList* Children() const { return &children_; } - LayoutObjectChildList* Children() { return &children_; } + const LayoutObjectChildList* Children() const { + CheckIsNotDestroyed(); + return &children_; + } + LayoutObjectChildList* Children() { + CheckIsNotDestroyed(); + return &children_; + } FrameEdgeInfo EdgeInfo() const; @@ -111,28 +119,46 @@ int split_resize_offset_; }; - const GridAxis& Rows() const { return rows_; } - const GridAxis& Columns() const { return cols_; } + const GridAxis& Rows() const { + CheckIsNotDestroyed(); + return rows_; + } + const GridAxis& Columns() const { + CheckIsNotDestroyed(); + return cols_; + } - const char* GetName() const override { return "LayoutFrameSet"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutFrameSet"; + } private: static const int kNoSplit = -1; - LayoutObjectChildList* VirtualChildren() override { return Children(); } + LayoutObjectChildList* VirtualChildren() override { + CheckIsNotDestroyed(); + return Children(); + } const LayoutObjectChildList* VirtualChildren() const override { + CheckIsNotDestroyed(); return Children(); } bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectFrameSet || LayoutBox::IsOfType(type); } void UpdateLayout() override; void Paint(const PaintInfo&) const override; - MinMaxSizes PreferredLogicalWidths() const override { return MinMaxSizes(); } + MinMaxSizes PreferredLogicalWidths() const override { + CheckIsNotDestroyed(); + return MinMaxSizes(); + } MinMaxSizes ComputeIntrinsicLogicalWidths() const final { + CheckIsNotDestroyed(); return MinMaxSizes(); }
diff --git a/third_party/blink/renderer/core/layout/layout_grid.cc b/third_party/blink/renderer/core/layout/layout_grid.cc index ab63ad9..693bcd1 100644 --- a/third_party/blink/renderer/core/layout/layout_grid.cc +++ b/third_party/blink/renderer/core/layout/layout_grid.cc
@@ -61,6 +61,7 @@ } void LayoutGrid::AddChild(LayoutObject* new_child, LayoutObject* before_child) { + CheckIsNotDestroyed(); LayoutBlock::AddChild(new_child, before_child); // Positioned grid items do not take up space or otherwise participate in the @@ -75,6 +76,7 @@ } void LayoutGrid::RemoveChild(LayoutObject* child) { + CheckIsNotDestroyed(); LayoutBlock::RemoveChild(child); // Positioned grid items do not take up space or otherwise participate in the @@ -92,6 +94,7 @@ GridAxis axis, const LayoutBox& child, const ComputedStyle* style) const { + CheckIsNotDestroyed(); return axis == kGridRowAxis ? JustifySelfForChild(child, style) : AlignSelfForChild(child, style); } @@ -99,6 +102,7 @@ StyleSelfAlignmentData LayoutGrid::DefaultAlignment( GridAxis axis, const ComputedStyle& style) const { + CheckIsNotDestroyed(); return axis == kGridRowAxis ? style.ResolvedJustifyItems(ItemPosition::kNormal) : style.ResolvedAlignItems(ItemPosition::kNormal); @@ -107,6 +111,7 @@ bool LayoutGrid::DefaultAlignmentIsStretchOrNormal( GridAxis axis, const ComputedStyle& style) const { + CheckIsNotDestroyed(); ItemPosition alignment = DefaultAlignment(axis, style).GetPosition(); return alignment == ItemPosition::kStretch || alignment == ItemPosition::kNormal; @@ -116,6 +121,7 @@ const ComputedStyle& old_style, const ComputedStyle& new_style, const LayoutBox& child) const { + CheckIsNotDestroyed(); return SelfAlignmentForChild(axis, child, &old_style).GetPosition() == ItemPosition::kStretch ? SelfAlignmentForChild(axis, child, &new_style).GetPosition() != @@ -128,6 +134,7 @@ GridAxis axis, const ComputedStyle& old_style, const ComputedStyle& new_style) const { + CheckIsNotDestroyed(); return DefaultAlignmentIsStretchOrNormal(axis, old_style) ? DefaultAlignment(axis, old_style).GetPosition() != DefaultAlignment(axis, new_style).GetPosition() @@ -136,6 +143,7 @@ void LayoutGrid::StyleDidChange(StyleDifference diff, const ComputedStyle* old_style) { + CheckIsNotDestroyed(); LayoutBlock::StyleDidChange(diff, old_style); if (!old_style) return; @@ -178,6 +186,7 @@ } bool LayoutGrid::ExplicitGridDidResize(const ComputedStyle& old_style) const { + CheckIsNotDestroyed(); return old_style.GridTemplateColumns().LegacyTrackList().size() != StyleRef().GridTemplateColumns().LegacyTrackList().size() || old_style.GridTemplateRows().LegacyTrackList().size() != @@ -194,6 +203,7 @@ bool LayoutGrid::NamedGridLinesDefinitionDidChange( const ComputedStyle& old_style) const { + CheckIsNotDestroyed(); return old_style.NamedGridRowLines() != StyleRef().NamedGridRowLines() || old_style.NamedGridColumnLines() != StyleRef().NamedGridColumnLines() || @@ -206,6 +216,7 @@ void LayoutGrid::ComputeTrackSizesForDefiniteSize( GridTrackSizingDirection direction, LayoutUnit available_space) { + CheckIsNotDestroyed(); track_sizing_algorithm_.Setup(direction, NumTracks(direction, *grid_), available_space); track_sizing_algorithm_.Run(); @@ -218,6 +229,7 @@ void LayoutGrid::RepeatTracksSizingIfNeeded( LayoutUnit available_space_for_columns, LayoutUnit available_space_for_rows) { + CheckIsNotDestroyed(); // In orthogonal flow cases column track's size is determined by using the // computed row track's size, which it was estimated during the first cycle of // the sizing algorithm. @@ -250,6 +262,7 @@ } void LayoutGrid::UpdateBlockLayout(bool relayout_children) { + CheckIsNotDestroyed(); DCHECK(NeedsLayout()); // We cannot perform a |SimplifiedLayout()| with a dirty grid. @@ -408,6 +421,7 @@ LayoutUnit LayoutGrid::GridGap( GridTrackSizingDirection direction, base::Optional<LayoutUnit> available_size) const { + CheckIsNotDestroyed(); const base::Optional<Length>& gap = direction == kForColumns ? StyleRef().ColumnGap() : StyleRef().RowGap(); if (!gap) @@ -417,6 +431,7 @@ } LayoutUnit LayoutGrid::GridGap(GridTrackSizingDirection direction) const { + CheckIsNotDestroyed(); LayoutUnit available_size; bool is_row_axis = direction == kForColumns; @@ -441,6 +456,7 @@ size_t start_line, size_t span, base::Optional<LayoutUnit> available_size) const { + CheckIsNotDestroyed(); if (span <= 1) return LayoutUnit(); @@ -517,6 +533,7 @@ } MinMaxSizes LayoutGrid::ComputeIntrinsicLogicalWidths() const { + CheckIsNotDestroyed(); MinMaxSizes sizes; sizes += BorderAndPaddingLogicalWidth() + ComputeLogicalScrollbars().InlineSum(); @@ -557,6 +574,7 @@ void LayoutGrid::ComputeTrackSizesForIndefiniteSize( GridTrackSizingAlgorithm& algo, GridTrackSizingDirection direction) const { + CheckIsNotDestroyed(); const Grid& grid = algo.GetGrid(); algo.Setup(direction, NumTracks(direction, grid), base::nullopt); algo.Run(); @@ -568,6 +586,7 @@ base::Optional<LayoutUnit> LayoutGrid::OverrideIntrinsicContentLogicalSize( GridTrackSizingDirection direction) const { + CheckIsNotDestroyed(); if (direction == kForColumns && HasOverrideIntrinsicContentLogicalWidth()) return OverrideIntrinsicContentLogicalWidth(); if (direction == kForRows && HasOverrideIntrinsicContentLogicalHeight()) @@ -594,6 +613,7 @@ size_t LayoutGrid::ComputeAutoRepeatTracksCount( GridTrackSizingDirection direction, base::Optional<LayoutUnit> available_size) const { + CheckIsNotDestroyed(); DCHECK(!available_size || available_size.value() != -1); bool is_row_axis = direction == kForColumns; // Since auto-fit collapses empty tracks, and contain: size dictates that @@ -757,6 +777,7 @@ LayoutGrid::ComputeEmptyTracksForAutoRepeat( Grid& grid, GridTrackSizingDirection direction) const { + CheckIsNotDestroyed(); bool is_row_axis = direction == kForColumns; if ((is_row_axis && StyleRef().GridAutoRepeatColumnsType() != AutoRepeatType::kAutoFit) || @@ -794,6 +815,7 @@ size_t LayoutGrid::ClampAutoRepeatTracks(GridTrackSizingDirection direction, size_t auto_repeat_tracks) const { + CheckIsNotDestroyed(); if (!auto_repeat_tracks) return 0; @@ -820,6 +842,7 @@ void LayoutGrid::PlaceItemsOnGrid( GridTrackSizingAlgorithm& algorithm, base::Optional<LayoutUnit> available_logical_width) const { + CheckIsNotDestroyed(); Grid& grid = algorithm.GetMutableGrid(); size_t auto_repeat_rows = ComputeAutoRepeatTracksCount( kForRows, ConvertLayoutUnitToOptional( @@ -931,6 +954,7 @@ void LayoutGrid::PerformGridItemsPreLayout( const GridTrackSizingAlgorithm& algorithm) const { + CheckIsNotDestroyed(); DCHECK(!algorithm.GetGrid().NeedsItemsPlacement()); if (!GetDocument().View()->IsInPerformLayout()) return; @@ -968,6 +992,7 @@ } void LayoutGrid::PopulateExplicitGridAndOrderIterator(Grid& grid) const { + CheckIsNotDestroyed(); OrderIteratorPopulator populator(grid.GetOrderIterator()); size_t explicit_row_start = 0; size_t explicit_column_start = 0; @@ -1032,6 +1057,7 @@ const LayoutBox& grid_item, GridTrackSizingDirection specified_direction, const GridSpan& specified_positions) const { + CheckIsNotDestroyed(); GridTrackSizingDirection cross_direction = specified_direction == kForColumns ? kForRows : kForColumns; const size_t end_of_cross_direction = grid.NumTracks(cross_direction); @@ -1051,6 +1077,7 @@ void LayoutGrid::PlaceSpecifiedMajorAxisItemsOnGrid( Grid& grid, const Vector<LayoutBox*>& auto_grid_items) const { + CheckIsNotDestroyed(); bool is_for_columns = AutoPlacementMajorAxisDirection() == kForColumns; bool is_grid_auto_flow_dense = StyleRef().IsGridAutoFlowAlgorithmDense(); @@ -1096,6 +1123,7 @@ void LayoutGrid::PlaceAutoMajorAxisItemsOnGrid( Grid& grid, const Vector<LayoutBox*>& auto_grid_items) const { + CheckIsNotDestroyed(); std::pair<size_t, size_t> auto_placement_cursor = std::make_pair(0, 0); bool is_grid_auto_flow_dense = StyleRef().IsGridAutoFlowAlgorithmDense(); @@ -1114,6 +1142,7 @@ Grid& grid, LayoutBox& grid_item, std::pair<size_t, size_t>& auto_placement_cursor) const { + CheckIsNotDestroyed(); GridSpan minor_axis_positions = grid.GridItemSpan(grid_item, AutoPlacementMinorAxisDirection()); DCHECK(!grid.GridItemSpan(grid_item, AutoPlacementMajorAxisDirection()) @@ -1202,14 +1231,17 @@ } GridTrackSizingDirection LayoutGrid::AutoPlacementMajorAxisDirection() const { + CheckIsNotDestroyed(); return StyleRef().IsGridAutoFlowDirectionColumn() ? kForColumns : kForRows; } GridTrackSizingDirection LayoutGrid::AutoPlacementMinorAxisDirection() const { + CheckIsNotDestroyed(); return StyleRef().IsGridAutoFlowDirectionColumn() ? kForRows : kForColumns; } void LayoutGrid::DirtyGrid() { + CheckIsNotDestroyed(); if (grid_->NeedsItemsPlacement()) return; @@ -1218,6 +1250,7 @@ Vector<LayoutUnit> LayoutGrid::TrackSizesForComputedStyle( GridTrackSizingDirection direction) const { + CheckIsNotDestroyed(); bool is_row_axis = direction == kForColumns; auto& positions = is_row_axis ? column_positions_ : row_positions_; size_t num_positions = positions.size(); @@ -1291,6 +1324,7 @@ void LayoutGrid::UpdateGridAreaLogicalSize( LayoutBox& child, LayoutSize grid_area_logical_size) const { + CheckIsNotDestroyed(); // Because the grid area cannot be styled, we don't need to adjust // the grid breadth to account for 'box-sizing'. bool grid_area_width_changed = @@ -1309,6 +1343,7 @@ } void LayoutGrid::LayoutGridItems() { + CheckIsNotDestroyed(); if (ChildLayoutBlockedByDisplayLock()) return; @@ -1369,6 +1404,7 @@ } void LayoutGrid::PrepareChildForPositionedLayout(LayoutBox& child) { + CheckIsNotDestroyed(); DCHECK(child.IsOutOfFlowPositioned()); child.ContainingBlock()->InsertPositionedObject(&child); @@ -1382,6 +1418,7 @@ bool LayoutGrid::HasStaticPositionForChild( const LayoutBox& child, GridTrackSizingDirection direction) const { + CheckIsNotDestroyed(); return direction == kForColumns ? child.StyleRef().HasStaticInlinePosition( IsHorizontalWritingMode()) : child.StyleRef().HasStaticBlockPosition( @@ -1390,6 +1427,7 @@ void LayoutGrid::LayoutPositionedObjects(bool relayout_children, PositionedLayoutBehavior info) { + CheckIsNotDestroyed(); if (ChildLayoutBlockedByDisplayLock()) return; @@ -1424,6 +1462,7 @@ LayoutUnit LayoutGrid::GridAreaBreadthForChildIncludingAlignmentOffsets( const LayoutBox& child, GridTrackSizingDirection direction) const { + CheckIsNotDestroyed(); // We need the cached value when available because Content Distribution // alignment properties may have some influence in the final grid area // breadth. @@ -1442,6 +1481,7 @@ void LayoutGrid::PopulateGridPositionsForDirection( GridTrackSizingDirection direction) { + CheckIsNotDestroyed(); // Since we add alignment offsets and track gutters, grid lines are not always // adjacent. Hence we will have to assume from now on that we just store // positions of the initial grid lines of each track, except the last one, @@ -1543,6 +1583,7 @@ LayoutUnit LayoutGrid::AvailableAlignmentSpaceForChildBeforeStretching( LayoutUnit grid_area_breadth_for_child, const LayoutBox& child) const { + CheckIsNotDestroyed(); // Because we want to avoid multiple layouts, stretching logic might be // performed before children are laid out, so we can't use the child cached // values. Hence, we may need to compute margins in order to determine the @@ -1554,6 +1595,7 @@ StyleSelfAlignmentData LayoutGrid::AlignSelfForChild( const LayoutBox& child, const ComputedStyle* style) const { + CheckIsNotDestroyed(); if (!style) style = Style(); return child.StyleRef().ResolvedAlignSelf(SelfAlignmentNormalBehavior(&child), @@ -1563,6 +1605,7 @@ StyleSelfAlignmentData LayoutGrid::JustifySelfForChild( const LayoutBox& child, const ComputedStyle* style) const { + CheckIsNotDestroyed(); if (!style) style = Style(); return child.StyleRef().ResolvedJustifySelf( @@ -1572,6 +1615,7 @@ // FIXME: This logic is shared by LayoutFlexibleBox, so it should be moved to // LayoutBox. void LayoutGrid::ApplyStretchAlignmentToChildIfNeeded(LayoutBox& child) { + CheckIsNotDestroyed(); GridTrackSizingDirection child_block_direction = GridLayoutUtils::FlowAwareDirectionForChild(*this, child, kForRows); bool block_flow_is_column_axis = child_block_direction == kForRows; @@ -1599,6 +1643,7 @@ // TODO(lajava): This logic is shared by LayoutFlexibleBox, so it should be // moved to LayoutBox. bool LayoutGrid::HasAutoMarginsInColumnAxis(const LayoutBox& child) const { + CheckIsNotDestroyed(); if (IsHorizontalWritingMode()) return child.StyleRef().MarginTop().IsAuto() || child.StyleRef().MarginBottom().IsAuto(); @@ -1609,6 +1654,7 @@ // TODO(lajava): This logic is shared by LayoutFlexibleBox, so it should be // moved to LayoutBox. bool LayoutGrid::HasAutoMarginsInRowAxis(const LayoutBox& child) const { + CheckIsNotDestroyed(); if (IsHorizontalWritingMode()) return child.StyleRef().MarginLeft().IsAuto() || child.StyleRef().MarginRight().IsAuto(); @@ -1620,6 +1666,7 @@ // moved to LayoutBox. DISABLE_CFI_PERF void LayoutGrid::UpdateAutoMarginsInRowAxisIfNeeded(LayoutBox& child) { + CheckIsNotDestroyed(); DCHECK(!child.IsOutOfFlowPositioned()); const Length& margin_start = child.StyleRef().MarginStartUsing(StyleRef()); @@ -1652,6 +1699,7 @@ // moved to LayoutBox. DISABLE_CFI_PERF void LayoutGrid::UpdateAutoMarginsInColumnAxisIfNeeded(LayoutBox& child) { + CheckIsNotDestroyed(); DCHECK(!child.IsOutOfFlowPositioned()); const Length& margin_before = child.StyleRef().MarginBeforeUsing(StyleRef()); @@ -1693,6 +1741,7 @@ bool, LineDirectionMode direction, LinePositionMode mode) const { + CheckIsNotDestroyed(); DCHECK_EQ(mode, kPositionOnContainingLine); LayoutUnit baseline = FirstLineBoxBaseline(); // We take border-box's bottom if no valid baseline. @@ -1705,6 +1754,7 @@ } LayoutUnit LayoutGrid::FirstLineBoxBaseline() const { + CheckIsNotDestroyed(); if (IsWritingModeRoot() || !grid_->HasGridItems() || ShouldApplyLayoutContainment()) return LayoutUnit(-1); @@ -1761,16 +1811,19 @@ } LayoutUnit LayoutGrid::InlineBlockBaseline(LineDirectionMode direction) const { + CheckIsNotDestroyed(); return FirstLineBoxBaseline(); } bool LayoutGrid::IsBaselineAlignmentForChild(const LayoutBox& child) const { + CheckIsNotDestroyed(); return IsBaselineAlignmentForChild(child, kGridRowAxis) || IsBaselineAlignmentForChild(child, kGridColumnAxis); } bool LayoutGrid::IsBaselineAlignmentForChild(const LayoutBox& child, GridAxis baseline_axis) const { + CheckIsNotDestroyed(); if (child.IsOutOfFlowPositioned()) return false; ItemPosition align = @@ -1783,16 +1836,19 @@ LayoutUnit LayoutGrid::ColumnAxisBaselineOffsetForChild( const LayoutBox& child) const { + CheckIsNotDestroyed(); return track_sizing_algorithm_.BaselineOffsetForChild(child, kGridColumnAxis); } LayoutUnit LayoutGrid::RowAxisBaselineOffsetForChild( const LayoutBox& child) const { + CheckIsNotDestroyed(); return track_sizing_algorithm_.BaselineOffsetForChild(child, kGridRowAxis); } GridAxisPosition LayoutGrid::ColumnAxisPositionForChild( const LayoutBox& child) const { + CheckIsNotDestroyed(); bool has_same_writing_mode = child.StyleRef().GetWritingMode() == StyleRef().GetWritingMode(); bool child_is_ltr = child.StyleRef().IsLeftToRightDirection(); @@ -1868,6 +1924,7 @@ GridAxisPosition LayoutGrid::RowAxisPositionForChild( const LayoutBox& child) const { + CheckIsNotDestroyed(); bool has_same_direction = child.StyleRef().Direction() == StyleRef().Direction(); bool grid_is_ltr = StyleRef().IsLeftToRightDirection(); @@ -1948,6 +2005,7 @@ } LayoutUnit LayoutGrid::ColumnAxisOffsetForChild(const LayoutBox& child) const { + CheckIsNotDestroyed(); LayoutUnit start_of_row; LayoutUnit end_of_row; GridAreaPositionForChild(child, kForRows, start_of_row, end_of_row); @@ -1978,6 +2036,7 @@ } LayoutUnit LayoutGrid::RowAxisOffsetForChild(const LayoutBox& child) const { + CheckIsNotDestroyed(); LayoutUnit start_of_column; LayoutUnit end_of_column; GridAreaPositionForChild(child, kForColumns, start_of_column, end_of_column); @@ -2009,6 +2068,7 @@ LayoutUnit LayoutGrid::ResolveAutoStartGridPosition( GridTrackSizingDirection direction) const { + CheckIsNotDestroyed(); if (direction == kForRows || StyleRef().IsLeftToRightDirection()) return LayoutUnit(); @@ -2027,6 +2087,7 @@ LayoutUnit LayoutGrid::ResolveAutoEndGridPosition( GridTrackSizingDirection direction) const { + CheckIsNotDestroyed(); if (direction == kForRows) return ClientLogicalHeight(); if (StyleRef().IsLeftToRightDirection()) @@ -2050,6 +2111,7 @@ LayoutUnit LayoutGrid::GridAreaBreadthForOutOfFlowChild( const LayoutBox& child, GridTrackSizingDirection direction) { + CheckIsNotDestroyed(); DCHECK(child.IsOutOfFlowPositioned()); bool is_row_axis = direction == kForColumns; GridSpan span = GridPositionsResolver::ResolveGridPositionsFromStyle( @@ -2116,6 +2178,7 @@ const LayoutBox& child, GridTrackSizingDirection direction, LayoutUnit track_breadth) const { + CheckIsNotDestroyed(); DCHECK(child.IsOutOfFlowPositioned()); if (HasStaticPositionForChild(child, direction)) return LayoutUnit(); @@ -2144,6 +2207,7 @@ GridTrackSizingDirection direction, LayoutUnit& start, LayoutUnit& end) const { + CheckIsNotDestroyed(); DCHECK(child.IsOutOfFlowPositioned()); DCHECK(GridLayoutUtils::HasOverrideContainingBlockContentSizeForChild( child, direction)); @@ -2167,6 +2231,7 @@ GridTrackSizingDirection direction, LayoutUnit& start, LayoutUnit& end) const { + CheckIsNotDestroyed(); DCHECK(!child.IsOutOfFlowPositioned()); const Grid& grid = track_sizing_algorithm_.GetGrid(); const GridSpan& span = grid.GridItemSpan(child, direction); @@ -2191,6 +2256,7 @@ GridTrackSizingDirection direction, LayoutUnit& start, LayoutUnit& end) const { + CheckIsNotDestroyed(); if (child.IsOutOfFlowPositioned()) GridAreaPositionForOutOfFlowChild(child, direction, start, end); else @@ -2265,6 +2331,7 @@ StyleContentAlignmentData LayoutGrid::ContentAlignment( GridTrackSizingDirection direction) const { + CheckIsNotDestroyed(); return direction == kForColumns ? StyleRef().ResolvedJustifyContent( ContentAlignmentNormalBehavior()) : StyleRef().ResolvedAlignContent( @@ -2275,6 +2342,7 @@ GridTrackSizingDirection direction, const LayoutUnit& available_free_space, unsigned number_of_grid_tracks) { + CheckIsNotDestroyed(); auto& offset = direction == kForColumns ? offset_between_columns_ : offset_between_rows_; StyleContentAlignmentData content_alignment_data = @@ -2363,6 +2431,7 @@ LayoutUnit LayoutGrid::TranslateOutOfFlowRTLCoordinate( const LayoutBox& child, LayoutUnit coordinate) const { + CheckIsNotDestroyed(); DCHECK(child.IsOutOfFlowPositioned()); DCHECK(!StyleRef().IsLeftToRightDirection()); @@ -2374,6 +2443,7 @@ } LayoutUnit LayoutGrid::TranslateRTLCoordinate(LayoutUnit coordinate) const { + CheckIsNotDestroyed(); DCHECK(!StyleRef().IsLeftToRightDirection()); LayoutUnit alignment_offset = column_positions_[0]; @@ -2385,6 +2455,7 @@ // TODO: SetLogicalPositionForChild has only one caller, consider its // refactoring in the future. void LayoutGrid::SetLogicalPositionForChild(LayoutBox& child) const { + CheckIsNotDestroyed(); // "In the positioning phase [...] calculations are performed according to the // writing mode of the containing block of the box establishing the orthogonal // flow." However, 'setLogicalPosition' will only take into account the @@ -2399,6 +2470,7 @@ void LayoutGrid::SetLogicalOffsetForChild( LayoutBox& child, GridTrackSizingDirection direction) const { + CheckIsNotDestroyed(); if (!child.IsGridItem() && HasStaticPositionForChild(child, direction)) return; // 'SetLogicalLeft' and 'SetLogicalTop' only take into account the child's @@ -2413,6 +2485,7 @@ LayoutUnit LayoutGrid::LogicalOffsetForChild( const LayoutBox& child, GridTrackSizingDirection direction) const { + CheckIsNotDestroyed(); if (direction == kForRows) { return ColumnAxisOffsetForChild(child); } @@ -2433,6 +2506,7 @@ } LayoutPoint LayoutGrid::GridAreaLogicalPosition(const GridArea& area) const { + CheckIsNotDestroyed(); LayoutUnit column_axis_offset = row_positions_[area.rows.StartLine()]; LayoutUnit row_axis_offset = column_positions_[area.columns.StartLine()]; @@ -2446,6 +2520,7 @@ void LayoutGrid::PaintChildren(const PaintInfo& paint_info, const PhysicalOffset& paint_offset) const { + CheckIsNotDestroyed(); DCHECK(!grid_->NeedsItemsPlacement()); if (grid_->HasGridItems()) { BlockPainter(*this).PaintChildrenAtomically(grid_->GetOrderIterator(), @@ -2454,12 +2529,14 @@ } bool LayoutGrid::CachedHasDefiniteLogicalHeight() const { + CheckIsNotDestroyed(); SECURITY_DCHECK(has_definite_logical_height_); return has_definite_logical_height_.value(); } size_t LayoutGrid::NonCollapsedTracks( GridTrackSizingDirection direction) const { + CheckIsNotDestroyed(); auto& tracks = track_sizing_algorithm_.Tracks(direction); size_t number_of_tracks = tracks.size(); bool has_collapsed_tracks = grid_->HasAutoRepeatEmptyTracks(direction); @@ -2471,6 +2548,7 @@ size_t LayoutGrid::NumTracks(GridTrackSizingDirection direction, const Grid& grid) const { + CheckIsNotDestroyed(); // Due to limitations in our internal representation, we cannot know the // number of columns from m_grid *if* there is no row (because m_grid would be // empty). That's why in that case we need to get it from the style. Note that @@ -2489,6 +2567,7 @@ size_t LayoutGrid::ExplicitGridEndForDirection( GridTrackSizingDirection direction) const { + CheckIsNotDestroyed(); size_t leading = ExplicitGridStartForDirection(direction); if (direction == kForRows) { @@ -2502,6 +2581,7 @@ LayoutUnit LayoutGrid::GridItemOffset( GridTrackSizingDirection direction) const { + CheckIsNotDestroyed(); return direction == kForRows ? offset_between_rows_.distribution_offset : offset_between_columns_.distribution_offset; }
diff --git a/third_party/blink/renderer/core/layout/layout_grid.h b/third_party/blink/renderer/core/layout/layout_grid.h index c127832..359150b 100644 --- a/third_party/blink/renderer/core/layout/layout_grid.h +++ b/third_party/blink/renderer/core/layout/layout_grid.h
@@ -58,7 +58,10 @@ ~LayoutGrid() override; static LayoutGrid* CreateAnonymous(Document*); - const char* GetName() const override { return "LayoutGrid"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutGrid"; + } void UpdateBlockLayout(bool relayout_children) override; @@ -67,11 +70,13 @@ Vector<LayoutUnit> TrackSizesForComputedStyle(GridTrackSizingDirection) const; const Vector<LayoutUnit>& ColumnPositions() const { + CheckIsNotDestroyed(); DCHECK(!grid_->NeedsItemsPlacement()); return column_positions_; } const Vector<LayoutUnit>& RowPositions() const { + CheckIsNotDestroyed(); DCHECK(!grid_->NeedsItemsPlacement()); return row_positions_; } @@ -79,6 +84,7 @@ // TODO(svillar): rename this method as this does not return a // GridCell but its contents. const GridItemList& GetGridCell(int row, int column) const { + CheckIsNotDestroyed(); SECURITY_DCHECK(!grid_->NeedsItemsPlacement()); return grid_->Cell(row, column); } @@ -123,11 +129,15 @@ size_t ExplicitGridEndForDirection(GridTrackSizingDirection) const; // Exposed for testing *ONLY*. - Grid* InternalGrid() const { return grid_.get(); } + Grid* InternalGrid() const { + CheckIsNotDestroyed(); + return grid_.get(); + } protected: ItemPosition SelfAlignmentNormalBehavior( const LayoutBox* child = nullptr) const override { + CheckIsNotDestroyed(); DCHECK(child); return child->IsLayoutReplaced() ? ItemPosition::kStart : ItemPosition::kStretch; @@ -135,6 +145,7 @@ private: bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectLayoutGrid || LayoutBlock::IsOfType(type); } MinMaxSizes ComputeIntrinsicLogicalWidths() const override; @@ -260,18 +271,22 @@ bool DefaultAlignmentIsStretchOrNormal(GridAxis, const ComputedStyle&) const; void ApplyStretchAlignmentToChildIfNeeded(LayoutBox&); bool HasAutoSizeInColumnAxis(const LayoutBox& child) const { + CheckIsNotDestroyed(); return IsHorizontalWritingMode() ? child.StyleRef().Height().IsAuto() : child.StyleRef().Width().IsAuto(); } bool HasAutoSizeInRowAxis(const LayoutBox& child) const { + CheckIsNotDestroyed(); return IsHorizontalWritingMode() ? child.StyleRef().Width().IsAuto() : child.StyleRef().Height().IsAuto(); } bool AllowedToStretchChildAlongColumnAxis(const LayoutBox& child) const { + CheckIsNotDestroyed(); return AlignSelfForChild(child).GetPosition() == ItemPosition::kStretch && HasAutoSizeInColumnAxis(child) && !HasAutoMarginsInColumnAxis(child); } bool AllowedToStretchChildAlongRowAxis(const LayoutBox& child) const { + CheckIsNotDestroyed(); return JustifySelfForChild(child).GetPosition() == ItemPosition::kStretch && HasAutoSizeInRowAxis(child) && !HasAutoMarginsInRowAxis(child); }
diff --git a/third_party/blink/renderer/core/layout/layout_html_canvas.cc b/third_party/blink/renderer/core/layout/layout_html_canvas.cc index 1023bca..9b95193 100644 --- a/third_party/blink/renderer/core/layout/layout_html_canvas.cc +++ b/third_party/blink/renderer/core/layout/layout_html_canvas.cc
@@ -40,15 +40,18 @@ } PaintLayerType LayoutHTMLCanvas::LayerTypeRequired() const { + CheckIsNotDestroyed(); return kNormalPaintLayer; } void LayoutHTMLCanvas::PaintReplaced(const PaintInfo& paint_info, const PhysicalOffset& paint_offset) const { + CheckIsNotDestroyed(); HTMLCanvasPainter(*this).PaintReplaced(paint_info, paint_offset); } void LayoutHTMLCanvas::CanvasSizeChanged() { + CheckIsNotDestroyed(); IntSize canvas_size = To<HTMLCanvasElement>(GetNode())->Size(); LayoutSize zoomed_size(canvas_size.Width() * StyleRef().EffectiveZoom(), canvas_size.Height() * StyleRef().EffectiveZoom()); @@ -67,6 +70,7 @@ void LayoutHTMLCanvas::InvalidatePaint( const PaintInvalidatorContext& context) const { + CheckIsNotDestroyed(); auto* element = To<HTMLCanvasElement>(GetNode()); if (element->IsDirty()) element->DoDeferredPaintInvalidation(); @@ -75,6 +79,7 @@ } CompositingReasons LayoutHTMLCanvas::AdditionalCompositingReasons() const { + CheckIsNotDestroyed(); if (To<HTMLCanvasElement>(GetNode())->ShouldBeDirectComposited()) return CompositingReason::kCanvas; return CompositingReason::kNone; @@ -82,11 +87,13 @@ void LayoutHTMLCanvas::StyleDidChange(StyleDifference diff, const ComputedStyle* old_style) { + CheckIsNotDestroyed(); LayoutReplaced::StyleDidChange(diff, old_style); To<HTMLCanvasElement>(GetNode())->StyleDidChange(old_style, StyleRef()); } void LayoutHTMLCanvas::WillBeDestroyed() { + CheckIsNotDestroyed(); LayoutReplaced::WillBeDestroyed(); To<HTMLCanvasElement>(GetNode())->LayoutObjectDestroyed(); }
diff --git a/third_party/blink/renderer/core/layout/layout_html_canvas.h b/third_party/blink/renderer/core/layout/layout_html_canvas.h index d1b8612..3a4e99a3 100644 --- a/third_party/blink/renderer/core/layout/layout_html_canvas.h +++ b/third_party/blink/renderer/core/layout/layout_html_canvas.h
@@ -37,6 +37,7 @@ explicit LayoutHTMLCanvas(HTMLCanvasElement*); bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectCanvas || LayoutReplaced::IsOfType(type); } PaintLayerType LayerTypeRequired() const override; @@ -47,16 +48,25 @@ void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override; - const char* GetName() const override { return "LayoutHTMLCanvas"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutHTMLCanvas"; + } void WillBeDestroyed() override; private: void PaintReplaced(const PaintInfo&, const PhysicalOffset& paint_offset) const override; - void IntrinsicSizeChanged() override { CanvasSizeChanged(); } + void IntrinsicSizeChanged() override { + CheckIsNotDestroyed(); + CanvasSizeChanged(); + } - bool CanHaveAdditionalCompositingReasons() const override { return true; } + bool CanHaveAdditionalCompositingReasons() const override { + CheckIsNotDestroyed(); + return true; + } CompositingReasons AdditionalCompositingReasons() const override; };
diff --git a/third_party/blink/renderer/core/layout/layout_iframe.cc b/third_party/blink/renderer/core/layout/layout_iframe.cc index bac95e51..66fab723 100644 --- a/third_party/blink/renderer/core/layout/layout_iframe.cc +++ b/third_party/blink/renderer/core/layout/layout_iframe.cc
@@ -34,20 +34,24 @@ : LayoutEmbeddedContent(element) {} bool LayoutIFrame::ShouldComputeSizeAsReplaced() const { + CheckIsNotDestroyed(); return true; } bool LayoutIFrame::IsInlineBlockOrInlineTable() const { + CheckIsNotDestroyed(); return IsInline(); } PaintLayerType LayoutIFrame::LayerTypeRequired() const { + CheckIsNotDestroyed(); if (StyleRef().HasResize()) return kNormalPaintLayer; return LayoutEmbeddedContent::LayerTypeRequired(); } void LayoutIFrame::UpdateLayout() { + CheckIsNotDestroyed(); DCHECK(NeedsLayout()); LayoutAnalyzer::Scope analyzer(*this); @@ -63,6 +67,7 @@ void LayoutIFrame::StyleWillChange(StyleDifference diff, const ComputedStyle& new_style) { + CheckIsNotDestroyed(); if (Style() && StyleRef().UsedColorSchemeForInitialColors() != new_style.UsedColorSchemeForInitialColors()) { GetFrameOwnerElement()->SetColorScheme(
diff --git a/third_party/blink/renderer/core/layout/layout_iframe.h b/third_party/blink/renderer/core/layout/layout_iframe.h index 1cc4793..0bcfa3f5 100644 --- a/third_party/blink/renderer/core/layout/layout_iframe.h +++ b/third_party/blink/renderer/core/layout/layout_iframe.h
@@ -34,7 +34,10 @@ public: explicit LayoutIFrame(HTMLFrameOwnerElement*); - const char* GetName() const override { return "LayoutIFrame"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutIFrame"; + } private: bool ShouldComputeSizeAsReplaced() const override; @@ -43,6 +46,7 @@ void UpdateLayout() override; bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectLayoutIFrame || LayoutEmbeddedContent::IsOfType(type); }
diff --git a/third_party/blink/renderer/core/layout/layout_image.cc b/third_party/blink/renderer/core/layout/layout_image.cc index 624db750..3fcc4f8 100644 --- a/third_party/blink/renderer/core/layout/layout_image.cc +++ b/third_party/blink/renderer/core/layout/layout_image.cc
@@ -67,6 +67,7 @@ LayoutImage::~LayoutImage() = default; void LayoutImage::WillBeDestroyed() { + CheckIsNotDestroyed(); DCHECK(image_resource_); image_resource_->Shutdown(); @@ -75,6 +76,7 @@ void LayoutImage::StyleDidChange(StyleDifference diff, const ComputedStyle* old_style) { + CheckIsNotDestroyed(); LayoutReplaced::StyleDidChange(diff, old_style); bool old_orientation = @@ -85,6 +87,7 @@ } void LayoutImage::SetImageResource(LayoutImageResource* image_resource) { + CheckIsNotDestroyed(); DCHECK(!image_resource_); image_resource_ = image_resource; image_resource_->Initialize(this); @@ -92,6 +95,7 @@ void LayoutImage::ImageChanged(WrappedImagePtr new_image, CanDeferInvalidation defer) { + CheckIsNotDestroyed(); DCHECK(View()); DCHECK(View()->GetFrameView()); if (DocumentBeingDestroyed()) @@ -143,12 +147,14 @@ } void LayoutImage::UpdateIntrinsicSizeIfNeeded(const LayoutSize& new_size) { + CheckIsNotDestroyed(); if (image_resource_->ErrorOccurred()) return; SetIntrinsicSize(new_size); } bool LayoutImage::NeedsLayoutOnIntrinsicSizeChange() const { + CheckIsNotDestroyed(); // If the actual area occupied by the image has changed and it is not // constrained by style then a layout is required. bool image_size_is_constrained = @@ -171,6 +177,7 @@ void LayoutImage::InvalidatePaintAndMarkForLayoutIfNeeded( CanDeferInvalidation defer) { + CheckIsNotDestroyed(); LayoutSize old_intrinsic_size = IntrinsicSize(); LayoutSize new_intrinsic_size = RoundedLayoutSize( @@ -206,6 +213,7 @@ } void LayoutImage::ImageNotifyFinished(ImageResourceContent* new_image) { + CheckIsNotDestroyed(); LayoutObject::ImageNotifyFinished(new_image); if (!image_resource_) return; @@ -222,16 +230,19 @@ void LayoutImage::PaintReplaced(const PaintInfo& paint_info, const PhysicalOffset& paint_offset) const { + CheckIsNotDestroyed(); if (ChildPaintBlockedByDisplayLock()) return; ImagePainter(*this).PaintReplaced(paint_info, paint_offset); } void LayoutImage::Paint(const PaintInfo& paint_info) const { + CheckIsNotDestroyed(); ImagePainter(*this).Paint(paint_info); } void LayoutImage::AreaElementFocusChanged(HTMLAreaElement* area_element) { + CheckIsNotDestroyed(); DCHECK_EQ(area_element->ImageElement(), GetNode()); if (area_element->GetPath(this).IsEmpty()) @@ -243,6 +254,7 @@ bool LayoutImage::ForegroundIsKnownToBeOpaqueInRect( const PhysicalRect& local_rect, unsigned) const { + CheckIsNotDestroyed(); if (!image_resource_->HasImage() || image_resource_->ErrorOccurred()) return false; ImageResourceContent* image_content = image_resource_->CachedImage(); @@ -276,6 +288,7 @@ } bool LayoutImage::ComputeBackgroundIsKnownToBeObscured() const { + CheckIsNotDestroyed(); if (!StyleRef().HasBackground()) return false; @@ -286,11 +299,13 @@ } LayoutUnit LayoutImage::MinimumReplacedHeight() const { + CheckIsNotDestroyed(); return image_resource_->ErrorOccurred() ? IntrinsicSize().Height() : LayoutUnit(); } HTMLMapElement* LayoutImage::ImageMap() const { + CheckIsNotDestroyed(); auto* i = DynamicTo<HTMLImageElement>(GetNode()); return i ? i->GetTreeScope().GetImageMap( i->FastGetAttribute(html_names::kUsemapAttr)) @@ -301,6 +316,7 @@ const HitTestLocation& hit_test_location, const PhysicalOffset& accumulated_offset, HitTestAction hit_test_action) { + CheckIsNotDestroyed(); HitTestResult temp_result(result); bool inside = LayoutReplaced::NodeAtPoint( temp_result, hit_test_location, accumulated_offset, hit_test_action); @@ -313,6 +329,7 @@ } bool LayoutImage::HasOverriddenIntrinsicSize() const { + CheckIsNotDestroyed(); if (!RuntimeEnabledFeatures::ExperimentalProductivityFeaturesEnabled()) return false; auto* image_element = DynamicTo<HTMLImageElement>(GetNode()); @@ -321,6 +338,7 @@ FloatSize LayoutImage::ImageSizeOverriddenByIntrinsicSize( float multiplier) const { + CheckIsNotDestroyed(); if (!HasOverriddenIntrinsicSize()) return image_resource_->ImageSize(multiplier); @@ -338,6 +356,7 @@ bool LayoutImage::OverrideIntrinsicSizingInfo( IntrinsicSizingInfo& intrinsic_sizing_info) const { + CheckIsNotDestroyed(); if (!HasOverriddenIntrinsicSize()) return false; @@ -352,6 +371,7 @@ void LayoutImage::ComputeIntrinsicSizingInfo( IntrinsicSizingInfo& intrinsic_sizing_info) const { + CheckIsNotDestroyed(); DCHECK(!ShouldApplySizeContainment()); if (!OverrideIntrinsicSizingInfo(intrinsic_sizing_info)) { if (SVGImage* svg_image = EmbeddedSVGImage()) { @@ -413,6 +433,7 @@ } bool LayoutImage::NeedsPreferredWidthsRecalculation() const { + CheckIsNotDestroyed(); if (LayoutReplaced::NeedsPreferredWidthsRecalculation()) return true; SVGImage* svg_image = EmbeddedSVGImage(); @@ -420,6 +441,7 @@ } SVGImage* LayoutImage::EmbeddedSVGImage() const { + CheckIsNotDestroyed(); if (!image_resource_) return nullptr; ImageResourceContent* cached_image = image_resource_->CachedImage(); @@ -431,6 +453,7 @@ } void LayoutImage::UpdateAfterLayout() { + CheckIsNotDestroyed(); LayoutBox::UpdateAfterLayout(); Node* node = GetNode(); if (auto* image_element = DynamicTo<HTMLImageElement>(node)) {
diff --git a/third_party/blink/renderer/core/layout/layout_image.h b/third_party/blink/renderer/core/layout/layout_image.h index 3ed38c1..f25f39a 100644 --- a/third_party/blink/renderer/core/layout/layout_image.h +++ b/third_party/blink/renderer/core/layout/layout_image.h
@@ -55,11 +55,16 @@ void SetImageResource(LayoutImageResource*); - LayoutImageResource* ImageResource() { return image_resource_.Get(); } + LayoutImageResource* ImageResource() { + CheckIsNotDestroyed(); + return image_resource_.Get(); + } const LayoutImageResource* ImageResource() const { + CheckIsNotDestroyed(); return image_resource_.Get(); } ImageResourceContent* CachedImage() const { + CheckIsNotDestroyed(); return image_resource_ ? image_resource_->CachedImage() : nullptr; } @@ -67,17 +72,26 @@ void AreaElementFocusChanged(HTMLAreaElement*); void SetIsGeneratedContent(bool generated = true) { + CheckIsNotDestroyed(); is_generated_content_ = generated; } - bool IsGeneratedContent() const { return is_generated_content_; } + bool IsGeneratedContent() const { + CheckIsNotDestroyed(); + return is_generated_content_; + } inline void SetImageDevicePixelRatio(float factor) { + CheckIsNotDestroyed(); image_device_pixel_ratio_ = factor; } - float ImageDevicePixelRatio() const { return image_device_pixel_ratio_; } + float ImageDevicePixelRatio() const { + CheckIsNotDestroyed(); + return image_device_pixel_ratio_; + } void IntrinsicSizeChanged() override { + CheckIsNotDestroyed(); // The replaced content transform depends on the intrinsic size (see: // FragmentPaintPropertyTreeBuilder::UpdateReplacedContentTransform). SetNeedsPaintPropertyUpdate(); @@ -85,7 +99,10 @@ ImageChanged(image_resource_->ImagePtr(), CanDeferInvalidation::kNo); } - const char* GetName() const override { return "LayoutImage"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutImage"; + } void UpdateAfterLayout() override; @@ -99,6 +116,7 @@ void Paint(const PaintInfo&) const final; bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectLayoutImage || LayoutReplaced::IsOfType(type); } @@ -106,10 +124,16 @@ void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override; - bool CanBeSelectionLeafInternal() const final { return true; } + bool CanBeSelectionLeafInternal() const final { + CheckIsNotDestroyed(); + return true; + } private: - bool IsImage() const override { return true; } + bool IsImage() const override { + CheckIsNotDestroyed(); + return true; + } void PaintReplaced(const PaintInfo&, const PhysicalOffset& paint_offset) const override; @@ -119,7 +143,10 @@ unsigned max_depth_to_test) const final; bool ComputeBackgroundIsKnownToBeObscured() const final; - bool BackgroundShouldAlwaysBeClipped() const override { return true; } + bool BackgroundShouldAlwaysBeClipped() const override { + CheckIsNotDestroyed(); + return true; + } LayoutUnit MinimumReplacedHeight() const override;
diff --git a/third_party/blink/renderer/core/layout/layout_inline.cc b/third_party/blink/renderer/core/layout/layout_inline.cc index e81f0475..2f49349 100644 --- a/third_party/blink/renderer/core/layout/layout_inline.cc +++ b/third_party/blink/renderer/core/layout/layout_inline.cc
@@ -108,6 +108,7 @@ } void LayoutInline::WillBeDestroyed() { + CheckIsNotDestroyed(); // Make sure to destroy anonymous children first while they are still // connected to the rest of the tree, so that they will properly dirty line // boxes that they are removed from. Effects that do :before/:after only on @@ -154,23 +155,27 @@ } void LayoutInline::DeleteLineBoxes() { + CheckIsNotDestroyed(); if (!IsInLayoutNGInlineFormattingContext()) MutableLineBoxes()->DeleteLineBoxes(); } void LayoutInline::SetFirstInlineFragment(NGPaintFragment* fragment) { + CheckIsNotDestroyed(); CHECK(IsInLayoutNGInlineFormattingContext()) << *this; DCHECK(!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()); first_paint_fragment_ = fragment; } void LayoutInline::ClearFirstInlineFragmentItemIndex() { + CheckIsNotDestroyed(); CHECK(IsInLayoutNGInlineFormattingContext()) << *this; DCHECK(RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()); first_fragment_item_index_ = 0u; } void LayoutInline::SetFirstInlineFragmentItemIndex(wtf_size_t index) { + CheckIsNotDestroyed(); CHECK(IsInLayoutNGInlineFormattingContext()) << *this; DCHECK(RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()); DCHECK_NE(index, 0u); @@ -178,6 +183,7 @@ } bool LayoutInline::HasInlineFragments() const { + CheckIsNotDestroyed(); if (!IsInLayoutNGInlineFormattingContext()) return FirstLineBox(); if (!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) @@ -186,6 +192,7 @@ } void LayoutInline::InLayoutNGInlineFormattingContextWillChange(bool new_value) { + CheckIsNotDestroyed(); if (IsInLayoutNGInlineFormattingContext()) { if (!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) { SetFirstInlineFragment(nullptr); @@ -205,6 +212,7 @@ } LayoutInline* LayoutInline::InlineElementContinuation() const { + CheckIsNotDestroyed(); LayoutBoxModelObject* continuation = Continuation(); if (!continuation || continuation->IsInline()) return ToLayoutInline(continuation); @@ -212,6 +220,7 @@ } void LayoutInline::UpdateFromStyle() { + CheckIsNotDestroyed(); LayoutBoxModelObject::UpdateFromStyle(); // FIXME: Is this still needed. Was needed for run-ins, since run-in is @@ -260,6 +269,7 @@ void LayoutInline::StyleDidChange(StyleDifference diff, const ComputedStyle* old_style) { + CheckIsNotDestroyed(); LayoutBoxModelObject::StyleDidChange(diff, old_style); // Ensure that all of the split inlines pick up the new style. We only do this @@ -363,6 +373,7 @@ } void LayoutInline::UpdateAlwaysCreateLineBoxes(bool full_layout) { + CheckIsNotDestroyed(); DCHECK(!IsInLayoutNGInlineFormattingContext()); // Once we have been tainted once, just assume it will happen again. This way @@ -406,6 +417,7 @@ bool LayoutInline::ComputeInitialShouldCreateBoxFragment( const ComputedStyle& style) const { + CheckIsNotDestroyed(); if (style.HasBoxDecorationBackground() || style.MayHavePadding() || style.MayHaveMargin()) return true; @@ -416,6 +428,7 @@ } bool LayoutInline::ComputeInitialShouldCreateBoxFragment() const { + CheckIsNotDestroyed(); const ComputedStyle& style = StyleRef(); if (HasSelfPaintingLayer() || ComputeInitialShouldCreateBoxFragment(style) || ShouldApplyPaintContainment() || ShouldApplyLayoutContainment()) @@ -430,6 +443,7 @@ } void LayoutInline::UpdateShouldCreateBoxFragment() { + CheckIsNotDestroyed(); // Once we have been tainted once, just assume it will happen again. This way // effects like hover highlighting that change the background color will only // cause a layout on the first rollover. @@ -452,6 +466,7 @@ const InlineBox* inline_box, int, LayoutUnit* extra_width_to_end_of_line) const { + CheckIsNotDestroyed(); if (FirstChild()) { // This condition is possible if the LayoutInline is at an editing boundary, // i.e. the VisiblePosition is: @@ -486,6 +501,7 @@ void LayoutInline::AddChild(LayoutObject* new_child, LayoutObject* before_child) { + CheckIsNotDestroyed(); // Any table-part dom child of an inline element has anonymous wrappers in the // layout tree so we need to climb up to the enclosing anonymous table wrapper // and add the new child before that. @@ -506,6 +522,7 @@ LayoutBoxModelObject* LayoutInline::ContinuationBefore( LayoutObject* before_child) { + CheckIsNotDestroyed(); if (before_child && before_child->Parent() == this) return this; @@ -531,6 +548,7 @@ void LayoutInline::AddChildIgnoringContinuation(LayoutObject* new_child, LayoutObject* before_child) { + CheckIsNotDestroyed(); // Make sure we don't append things after :after-generated content if we have // it. if (!before_child && IsAfterContent(LastChild())) @@ -553,6 +571,7 @@ } LayoutInline* LayoutInline::Clone() const { + CheckIsNotDestroyed(); DCHECK(!IsAnonymous()); LayoutInline* clone_inline = new LayoutInline(GetNode()); clone_inline->SetStyle(Style()); @@ -563,6 +582,7 @@ void LayoutInline::MoveChildrenToIgnoringContinuation( LayoutInline* to, LayoutObject* start_child) { + CheckIsNotDestroyed(); DCHECK(!IsAnonymous()); DCHECK(!to->IsAnonymous()); LayoutObject* child = start_child; @@ -579,6 +599,7 @@ LayoutBlockFlow* middle_block, LayoutObject* before_child, LayoutBoxModelObject* old_cont) { + CheckIsNotDestroyed(); DCHECK(IsDescendantOf(from_block)); DCHECK(!IsAnonymous()); @@ -661,6 +682,7 @@ LayoutBlockFlow* new_block_box, LayoutObject* new_child, LayoutBoxModelObject* old_cont) { + CheckIsNotDestroyed(); auto* block = To<LayoutBlockFlow>(ContainingBlock()); LayoutBlockFlow* pre = nullptr; @@ -730,6 +752,7 @@ } LayoutBlockFlow* LayoutInline::CreateAnonymousContainerForBlockChildren() { + CheckIsNotDestroyed(); // We are placing a block inside an inline. We have to perform a split of this // inline into continuations. This involves creating an anonymous block box to // hold |newChild|. We then make that block box a continuation of this @@ -766,6 +789,7 @@ void LayoutInline::AddChildToContinuation(LayoutObject* new_child, LayoutObject* before_child) { + CheckIsNotDestroyed(); // A continuation always consists of two potential candidates: an inline or an // anonymous block box holding block children. LayoutBoxModelObject* flow = ContinuationBefore(before_child); @@ -810,12 +834,14 @@ } void LayoutInline::Paint(const PaintInfo& paint_info) const { + CheckIsNotDestroyed(); InlinePainter(*this).Paint(paint_info); } template <typename PhysicalRectCollector> void LayoutInline::CollectLineBoxRects( const PhysicalRectCollector& yield) const { + CheckIsNotDestroyed(); if (IsInLayoutNGInlineFormattingContext()) { const auto* box_fragment = ContainingBlockFlowFragmentOf(*this); if (!box_fragment) @@ -847,6 +873,7 @@ template <typename PhysicalRectCollector> void LayoutInline::CollectCulledLineBoxRects( const PhysicalRectCollector& yield) const { + CheckIsNotDestroyed(); DCHECK(!IsInLayoutNGInlineFormattingContext()); const LayoutBlock* block_for_flipping = UNLIKELY(HasFlippedBlocksWritingMode()) ? ContainingBlock() : nullptr; @@ -885,6 +912,7 @@ void LayoutInline::CollectCulledLineBoxRectsInFlippedBlocksDirection( const FlippedRectCollector& yield, const LayoutInline* container) const { + CheckIsNotDestroyed(); if (!CulledInlineFirstLineBox()) return; @@ -961,6 +989,7 @@ void LayoutInline::AbsoluteQuadsForSelf(Vector<FloatQuad>& quads, MapCoordinatesFlags mode) const { + CheckIsNotDestroyed(); LayoutGeometryMap geometry_map(mode); geometry_map.PushMappingsToAncestor(this, nullptr); CollectLineBoxRects([&quads, &geometry_map](const PhysicalRect& r) { @@ -972,6 +1001,7 @@ base::Optional<PhysicalOffset> LayoutInline::FirstLineBoxTopLeftInternal() const { + CheckIsNotDestroyed(); if (IsInLayoutNGInlineFormattingContext()) { NGInlineCursor cursor; cursor.MoveToIncludingCulledInline(*this); @@ -991,6 +1021,7 @@ } PhysicalOffset LayoutInline::AnchorPhysicalLocation() const { + CheckIsNotDestroyed(); if (const auto& location = FirstLineBoxTopLeftInternal()) return *location; // This object doesn't have fragment/line box, probably because it's an empty @@ -1013,6 +1044,7 @@ } PhysicalRect LayoutInline::AbsoluteBoundingBoxRectHandlingEmptyInline() const { + CheckIsNotDestroyed(); Vector<PhysicalRect> rects = OutlineRects( PhysicalOffset(), NGOutlineType::kIncludeBlockVisualOverflow); PhysicalRect rect = UnionRect(rects); @@ -1023,10 +1055,12 @@ } LayoutUnit LayoutInline::OffsetLeft(const Element* parent) const { + CheckIsNotDestroyed(); return AdjustedPositionRelativeTo(FirstLineBoxTopLeft(), parent).left; } LayoutUnit LayoutInline::OffsetTop(const Element* parent) const { + CheckIsNotDestroyed(); return AdjustedPositionRelativeTo(FirstLineBoxTopLeft(), parent).top; } @@ -1043,18 +1077,22 @@ } LayoutUnit LayoutInline::MarginLeft() const { + CheckIsNotDestroyed(); return ComputeMargin(this, StyleRef().MarginLeft()); } LayoutUnit LayoutInline::MarginRight() const { + CheckIsNotDestroyed(); return ComputeMargin(this, StyleRef().MarginRight()); } LayoutUnit LayoutInline::MarginTop() const { + CheckIsNotDestroyed(); return ComputeMargin(this, StyleRef().MarginTop()); } LayoutUnit LayoutInline::MarginBottom() const { + CheckIsNotDestroyed(); return ComputeMargin(this, StyleRef().MarginBottom()); } @@ -1062,6 +1100,7 @@ const HitTestLocation& hit_test_location, const PhysicalOffset& accumulated_offset, HitTestAction hit_test_action) { + CheckIsNotDestroyed(); if (ContainingNGBlockFlow()) { // TODO(crbug.com/965976): We should fix the root cause of the missed // layout. @@ -1113,6 +1152,7 @@ const HitTestLocation& hit_test_location, const PhysicalOffset& accumulated_offset, const NGInlineCursor* parent_cursor) { + CheckIsNotDestroyed(); DCHECK(parent_cursor || !AlwaysCreateLineBoxes()); if (!VisibleToHitTestRequest(result.GetHitTestRequest())) return false; @@ -1155,6 +1195,7 @@ PositionWithAffinity LayoutInline::PositionForPoint( const PhysicalOffset& point) const { + CheckIsNotDestroyed(); // FIXME: Does not deal with relative positioned inlines (should it?) // If there are continuations, test them first because our containing block @@ -1185,6 +1226,7 @@ } PhysicalRect LayoutInline::PhysicalLinesBoundingBox() const { + CheckIsNotDestroyed(); if (IsInLayoutNGInlineFormattingContext()) { NGInlineCursor cursor; cursor.MoveToIncludingCulledInline(*this); @@ -1239,6 +1281,7 @@ } InlineBox* LayoutInline::CulledInlineFirstLineBox() const { + CheckIsNotDestroyed(); for (LayoutObject* curr = FirstChild(); curr; curr = curr->NextSibling()) { if (curr->IsFloatingOrOutOfFlowPositioned()) continue; @@ -1263,6 +1306,7 @@ } InlineBox* LayoutInline::CulledInlineLastLineBox() const { + CheckIsNotDestroyed(); for (LayoutObject* curr = LastChild(); curr; curr = curr->PreviousSibling()) { if (curr->IsFloatingOrOutOfFlowPositioned()) continue; @@ -1287,6 +1331,7 @@ } PhysicalRect LayoutInline::CulledInlineVisualOverflowBoundingBox() const { + CheckIsNotDestroyed(); PhysicalRect result; CollectCulledLineBoxRects( [&result](const PhysicalRect& r) { result.UniteIfNonZero(r); }); @@ -1333,6 +1378,7 @@ } PhysicalRect LayoutInline::LinesVisualOverflowBoundingBox() const { + CheckIsNotDestroyed(); if (IsInLayoutNGInlineFormattingContext()) { PhysicalRect result; NGInlineCursor cursor; @@ -1379,6 +1425,7 @@ } PhysicalRect LayoutInline::VisualRectInDocument(VisualRectFlags flags) const { + CheckIsNotDestroyed(); PhysicalRect rect; if (!Continuation()) { rect = PhysicalVisualOverflowRect(); @@ -1392,6 +1439,7 @@ } PhysicalRect LayoutInline::LocalVisualRectIgnoringVisibility() const { + CheckIsNotDestroyed(); if (IsInLayoutNGInlineFormattingContext()) { DCHECK(RuntimeEnabledFeatures::LayoutNGEnabled()); if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) @@ -1411,6 +1459,7 @@ } PhysicalRect LayoutInline::PhysicalVisualOverflowRect() const { + CheckIsNotDestroyed(); PhysicalRect overflow_rect = LinesVisualOverflowBoundingBox(); LayoutUnit outline_outset(StyleRef().OutlineOutsetExtent()); if (outline_outset) { @@ -1441,6 +1490,7 @@ } PhysicalRect LayoutInline::ReferenceBoxForClipPath() const { + CheckIsNotDestroyed(); // The spec just says to use the border box as clip-path reference box. It // doesn't say what to do if there are multiple lines. Gecko uses the first // fragment in that case. We'll do the same here (but correctly with respect @@ -1461,6 +1511,7 @@ const LayoutBoxModelObject* ancestor, TransformState& transform_state, VisualRectFlags visual_rect_flags) const { + CheckIsNotDestroyed(); if (ancestor == this) return true; @@ -1499,6 +1550,7 @@ PhysicalOffset LayoutInline::OffsetFromContainerInternal( const LayoutObject* container, bool ignore_scroll_offset) const { + CheckIsNotDestroyed(); DCHECK_EQ(container, Container()); PhysicalOffset offset; @@ -1512,6 +1564,7 @@ } PaintLayerType LayoutInline::LayerTypeRequired() const { + CheckIsNotDestroyed(); return IsInFlowPositioned() || CreatesGroup() || StyleRef().ShouldCompositeForCurrentAnimations() || ShouldApplyPaintContainment() @@ -1520,6 +1573,7 @@ } void LayoutInline::ChildBecameNonInline(LayoutObject* child) { + CheckIsNotDestroyed(); // We have to split the parent flow. LayoutBlockFlow* new_box = CreateAnonymousContainerForBlockChildren(); LayoutBoxModelObject* old_continuation = Continuation(); @@ -1531,6 +1585,7 @@ void LayoutInline::UpdateHitTestResult(HitTestResult& result, const PhysicalOffset& point) const { + CheckIsNotDestroyed(); if (result.InnerNode()) return; @@ -1554,6 +1609,7 @@ } void LayoutInline::DirtyLineBoxes(bool full_layout) { + CheckIsNotDestroyed(); if (full_layout) { DeleteLineBoxes(); return; @@ -1587,10 +1643,12 @@ } InlineFlowBox* LayoutInline::CreateInlineFlowBox() { + CheckIsNotDestroyed(); return new InlineFlowBox(LineLayoutItem(this)); } InlineFlowBox* LayoutInline::CreateAndAppendInlineFlowBox() { + CheckIsNotDestroyed(); SetAlwaysCreateLineBoxes(); InlineFlowBox* flow_box = CreateInlineFlowBox(); MutableLineBoxes()->AppendLineBox(flow_box); @@ -1600,6 +1658,7 @@ void LayoutInline::DirtyLinesFromChangedChild( LayoutObject* child, MarkingBehavior marking_behavior) { + CheckIsNotDestroyed(); if (IsInLayoutNGInlineFormattingContext()) { if (UNLIKELY(RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled())) { if (const LayoutBlockFlow* container = FragmentItemsContainer()) { @@ -1634,6 +1693,7 @@ bool first_line, LineDirectionMode direction, LinePositionMode line_position_mode) const { + CheckIsNotDestroyed(); DCHECK_EQ(line_position_mode, kPositionOnContainingLine); const SimpleFontData* font_data = Style(first_line)->GetFont().PrimaryFont(); DCHECK(font_data); @@ -1649,6 +1709,7 @@ PhysicalOffset LayoutInline::OffsetForInFlowPositionedInline( const LayoutBox& child) const { + CheckIsNotDestroyed(); // TODO(layout-dev): This function isn't right with mixed writing modes, // but LayoutNG has fixed the issue. This function seems to always return // zero in LayoutNG. We should probably remove this function for LayoutNG. @@ -1695,6 +1756,7 @@ } void LayoutInline::ImageChanged(WrappedImagePtr, CanDeferInvalidation) { + CheckIsNotDestroyed(); if (!Parent()) return; @@ -1706,6 +1768,7 @@ Vector<PhysicalRect>& rects, const PhysicalOffset& additional_offset, NGOutlineType include_block_overflows) const { + CheckIsNotDestroyed(); #if DCHECK_IS_ON() // TODO(crbug.com/987836): enable this DCHECK universally. Page* page = GetDocument().GetPage(); @@ -1728,6 +1791,7 @@ Vector<PhysicalRect>& rects, const PhysicalOffset& additional_offset, NGOutlineType include_block_overflows) const { + CheckIsNotDestroyed(); AddOutlineRectsForNormalChildren(rects, additional_offset, include_block_overflows); AddOutlineRectsForContinuations(rects, additional_offset, @@ -1738,6 +1802,7 @@ Vector<PhysicalRect>& rects, const PhysicalOffset& additional_offset, NGOutlineType include_block_overflows) const { + CheckIsNotDestroyed(); if (LayoutBoxModelObject* continuation = Continuation()) { if (continuation->NeedsLayout()) { // TODO(mstensho): Prevent this from happening. Before we can get the @@ -1761,12 +1826,14 @@ } FloatRect LayoutInline::LocalBoundingBoxRectForAccessibility() const { + CheckIsNotDestroyed(); Vector<PhysicalRect> rects = OutlineRects( PhysicalOffset(), NGOutlineType::kIncludeBlockVisualOverflow); return FloatRect(FlipForWritingMode(UnionRect(rects).ToLayoutRect())); } void LayoutInline::AddAnnotatedRegions(Vector<AnnotatedRegionValue>& regions) { + CheckIsNotDestroyed(); // Convert the style regions to absolute coordinates. if (StyleRef().Visibility() != EVisibility::kVisible) return; @@ -1793,6 +1860,7 @@ void LayoutInline::InvalidateDisplayItemClients( PaintInvalidationReason invalidation_reason) const { + CheckIsNotDestroyed(); ObjectPaintInvalidator paint_invalidator(*this); if (IsInLayoutNGInlineFormattingContext()) { @@ -1826,12 +1894,14 @@ void LayoutInline::MapLocalToAncestor(const LayoutBoxModelObject* ancestor, TransformState& transform_state, MapCoordinatesFlags mode) const { + CheckIsNotDestroyed(); if (CanContainFixedPositionObjects()) mode &= ~kIsFixed; LayoutBoxModelObject::MapLocalToAncestor(ancestor, transform_state, mode); } PhysicalRect LayoutInline::DebugRect() const { + CheckIsNotDestroyed(); return PhysicalRect(EnclosingIntRect(PhysicalLinesBoundingBox())); }
diff --git a/third_party/blink/renderer/core/layout/layout_inline.h b/third_party/blink/renderer/core/layout/layout_inline.h index 4e1ae54..8dbf225 100644 --- a/third_party/blink/renderer/core/layout/layout_inline.h +++ b/third_party/blink/renderer/core/layout/layout_inline.h
@@ -122,10 +122,12 @@ static LayoutInline* CreateAnonymous(Document*); LayoutObject* FirstChild() const { + CheckIsNotDestroyed(); DCHECK_EQ(Children(), VirtualChildren()); return Children()->FirstChild(); } LayoutObject* LastChild() const { + CheckIsNotDestroyed(); DCHECK_EQ(Children(), VirtualChildren()); return Children()->LastChild(); } @@ -138,6 +140,7 @@ LayoutObject* before_child = nullptr) override; Element* GetNode() const { + CheckIsNotDestroyed(); return To<Element>(LayoutBoxModelObject::GetNode()); } @@ -159,18 +162,27 @@ // LineBoxes() and FirstInlineFragment() are mutually exclusive, // depends on IsInLayoutNGInlineFormattingContext(). const LineBoxList* LineBoxes() const { + CheckIsNotDestroyed(); return IsInLayoutNGInlineFormattingContext() ? &LineBoxList::Empty() : &line_boxes_; } LineBoxList* MutableLineBoxes(); - InlineFlowBox* FirstLineBox() const { return LineBoxes()->First(); } - InlineFlowBox* LastLineBox() const { return LineBoxes()->Last(); } + InlineFlowBox* FirstLineBox() const { + CheckIsNotDestroyed(); + return LineBoxes()->First(); + } + InlineFlowBox* LastLineBox() const { + CheckIsNotDestroyed(); + return LineBoxes()->Last(); + } InlineBox* FirstLineBoxIncludingCulling() const { + CheckIsNotDestroyed(); return AlwaysCreateLineBoxes() ? FirstLineBox() : CulledInlineFirstLineBox(); } InlineBox* LastLineBoxIncludingCulling() const { + CheckIsNotDestroyed(); return AlwaysCreateLineBoxes() ? LastLineBox() : CulledInlineLastLineBox(); } @@ -182,6 +194,7 @@ void SetFirstInlineFragmentItemIndex(wtf_size_t) final; LayoutBoxModelObject* VirtualContinuation() const final { + CheckIsNotDestroyed(); return Continuation(); } LayoutInline* InlineElementContinuation() const; @@ -205,10 +218,12 @@ using LayoutBoxModelObject::SetContinuation; bool AlwaysCreateLineBoxes() const { + CheckIsNotDestroyed(); return AlwaysCreateLineBoxesForLayoutInline() && !IsInLayoutNGInlineFormattingContext(); } void SetAlwaysCreateLineBoxes(bool always_create_line_boxes = true) { + CheckIsNotDestroyed(); DCHECK(!IsInLayoutNGInlineFormattingContext()); SetAlwaysCreateLineBoxesForLayoutInline(always_create_line_boxes); } @@ -216,10 +231,12 @@ // True if this inline box should force creation of NGPhysicalBoxFragment. bool ShouldCreateBoxFragment() const { + CheckIsNotDestroyed(); return AlwaysCreateLineBoxesForLayoutInline() && IsInLayoutNGInlineFormattingContext(); } void SetShouldCreateBoxFragment(bool value = true) { + CheckIsNotDestroyed(); DCHECK(IsInLayoutNGInlineFormattingContext()); SetAlwaysCreateLineBoxesForLayoutInline(value); } @@ -240,6 +257,7 @@ const NGInlineCursor* parent_cursor = nullptr); PhysicalOffset FirstLineBoxTopLeft() const { + CheckIsNotDestroyed(); return FirstLineBoxTopLeftInternal().value_or(PhysicalOffset()); } @@ -252,7 +270,10 @@ PhysicalRect VisualRectInDocument( VisualRectFlags = kDefaultVisualRectFlags) const override; - const char* GetName() const override { return "LayoutInline"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutInline"; + } PhysicalRect DebugRect() const override; @@ -275,14 +296,27 @@ bool ignore_scroll_offset) const final; private: - LayoutObjectChildList* VirtualChildren() final { return Children(); } - const LayoutObjectChildList* VirtualChildren() const final { + LayoutObjectChildList* VirtualChildren() final { + CheckIsNotDestroyed(); return Children(); } - const LayoutObjectChildList* Children() const { return &children_; } - LayoutObjectChildList* Children() { return &children_; } + const LayoutObjectChildList* VirtualChildren() const final { + CheckIsNotDestroyed(); + return Children(); + } + const LayoutObjectChildList* Children() const { + CheckIsNotDestroyed(); + return &children_; + } + LayoutObjectChildList* Children() { + CheckIsNotDestroyed(); + return &children_; + } - bool IsLayoutInline() const final { return true; } + bool IsLayoutInline() const final { + CheckIsNotDestroyed(); + return true; + } // Compute the initial value of |ShouldCreateBoxFragment()| for this // LayoutInline. It maybe flipped to true later for other conditions. @@ -332,7 +366,10 @@ // Create an anoymous block for block children of this inline. LayoutBlockFlow* CreateAnonymousContainerForBlockChildren(); - void UpdateLayout() final { NOTREACHED(); } // Do nothing for layout() + void UpdateLayout() final { + CheckIsNotDestroyed(); + NOTREACHED(); + } // Do nothing for layout() void Paint(const PaintInfo&) const final; @@ -346,9 +383,11 @@ LayoutUnit OffsetLeft(const Element*) const final; LayoutUnit OffsetTop(const Element*) const final; LayoutUnit OffsetWidth() const final { + CheckIsNotDestroyed(); return PhysicalLinesBoundingBox().Width(); } LayoutUnit OffsetHeight() const final { + CheckIsNotDestroyed(); return PhysicalLinesBoundingBox().Height(); } @@ -366,6 +405,7 @@ PositionWithAffinity PositionForPoint(const PhysicalOffset&) const override; IntRect BorderBoundingBox() const final { + CheckIsNotDestroyed(); IntRect bounding_box = EnclosingIntRect(PhysicalLinesBoundingBox()); return IntRect(0, 0, bounding_box.Width(), bounding_box.Height()); } @@ -395,7 +435,10 @@ void AddAnnotatedRegions(Vector<AnnotatedRegionValue>&) final; void UpdateFromStyle() final; - bool AnonymousHasStylePropagationOverride() final { return true; } + bool AnonymousHasStylePropagationOverride() final { + CheckIsNotDestroyed(); + return true; + } LayoutInline* Clone() const;
diff --git a/third_party/blink/renderer/core/layout/layout_inside_list_marker.h b/third_party/blink/renderer/core/layout/layout_inside_list_marker.h index b5a8d26..ace9092 100644 --- a/third_party/blink/renderer/core/layout/layout_inside_list_marker.h +++ b/third_party/blink/renderer/core/layout/layout_inside_list_marker.h
@@ -18,13 +18,23 @@ explicit LayoutInsideListMarker(Element*); ~LayoutInsideListMarker() override; - const char* GetName() const override { return "LayoutInsideListMarker"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutInsideListMarker"; + } - const ListMarker& Marker() const { return list_marker_; } - ListMarker& Marker() { return list_marker_; } + const ListMarker& Marker() const { + CheckIsNotDestroyed(); + return list_marker_; + } + ListMarker& Marker() { + CheckIsNotDestroyed(); + return list_marker_; + } private: bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectInsideListMarker || LayoutInline::IsOfType(type); }
diff --git a/third_party/blink/renderer/core/layout/layout_list_item.cc b/third_party/blink/renderer/core/layout/layout_list_item.cc index 9f7e7ae..9638fee 100644 --- a/third_party/blink/renderer/core/layout/layout_list_item.cc +++ b/third_party/blink/renderer/core/layout/layout_list_item.cc
@@ -47,6 +47,7 @@ void LayoutListItem::StyleDidChange(StyleDifference diff, const ComputedStyle* old_style) { + CheckIsNotDestroyed(); LayoutBlockFlow::StyleDidChange(diff, old_style); StyleImage* current_image = StyleRef().ListStyleImage(); @@ -80,18 +81,21 @@ } void LayoutListItem::InsertedIntoTree() { + CheckIsNotDestroyed(); LayoutBlockFlow::InsertedIntoTree(); ListItemOrdinal::ItemInsertedOrRemoved(this); } void LayoutListItem::WillBeRemovedFromTree() { + CheckIsNotDestroyed(); LayoutBlockFlow::WillBeRemovedFromTree(); ListItemOrdinal::ItemInsertedOrRemoved(this); } void LayoutListItem::SubtreeDidChange() { + CheckIsNotDestroyed(); LayoutObject* marker = Marker(); if (!marker) return; @@ -113,15 +117,18 @@ } int LayoutListItem::Value() const { + CheckIsNotDestroyed(); DCHECK(GetNode()); return ordinal_.Value(*GetNode()); } bool LayoutListItem::IsEmpty() const { + CheckIsNotDestroyed(); return LastChild() == Marker(); } void LayoutListItem::UpdateMarkerTextIfNeeded() { + CheckIsNotDestroyed(); LayoutObject* marker = Marker(); if (ListMarker* list_marker = ListMarker::Get(marker)) list_marker->UpdateMarkerTextIfNeeded(*marker); @@ -201,6 +208,7 @@ // marker_container to 0px; else restore it to LogicalHeight of <li>. bool LayoutListItem::PrepareForBlockDirectionAlign( const LayoutObject* line_box_parent) { + CheckIsNotDestroyed(); LayoutObject* marker = Marker(); LayoutObject* marker_parent = marker->Parent(); bool is_inside = marker->IsInsideListMarker(); @@ -264,6 +272,7 @@ } bool LayoutListItem::UpdateMarkerLocation() { + CheckIsNotDestroyed(); DCHECK(Marker()); LayoutObject* marker = Marker(); @@ -327,11 +336,13 @@ } void LayoutListItem::RecalcVisualOverflow() { + CheckIsNotDestroyed(); RecalcChildVisualOverflow(); RecalcSelfVisualOverflow(); } void LayoutListItem::ComputeVisualOverflow(bool recompute_floats) { + CheckIsNotDestroyed(); LayoutRect previous_visual_overflow_rect = VisualOverflowRect(); ClearVisualOverflow(); @@ -350,6 +361,7 @@ } void LayoutListItem::AddLayoutOverflowFromChildren() { + CheckIsNotDestroyed(); LayoutBlockFlow::AddLayoutOverflowFromChildren(); UpdateOverflow(); } @@ -357,6 +369,7 @@ // Align marker_inline_box in block direction according to line_box_root's // baseline. void LayoutListItem::AlignMarkerInBlockDirection() { + CheckIsNotDestroyed(); // Specify wether need to restore to the original baseline which is the // baseline of marker parent. Because we might adjust the position at the last // layout pass. So if there's no line box in line_box_parent make sure it @@ -433,6 +446,7 @@ } void LayoutListItem::UpdateOverflow() { + CheckIsNotDestroyed(); LayoutObject* marker_object = Marker(); if (!marker_object || !marker_object->Parent() || !marker_object->Parent()->IsBox() || marker_object->IsInsideListMarker()) @@ -597,10 +611,12 @@ } void LayoutListItem::Paint(const PaintInfo& paint_info) const { + CheckIsNotDestroyed(); ListItemPainter(*this).Paint(paint_info); } void LayoutListItem::OrdinalValueChanged() { + CheckIsNotDestroyed(); LayoutObject* marker = Marker(); if (ListMarker* list_marker = ListMarker::Get(marker)) { list_marker->OrdinalValueChanged(*marker); @@ -612,6 +628,7 @@ } void LayoutListItem::UpdateLayout() { + CheckIsNotDestroyed(); LayoutObject* marker = Marker(); if (ListMarker* list_marker = ListMarker::Get(marker)) list_marker->UpdateMarkerTextIfNeeded(*marker);
diff --git a/third_party/blink/renderer/core/layout/layout_list_item.h b/third_party/blink/renderer/core/layout/layout_list_item.h index 2442bba..b7de7c2 100644 --- a/third_party/blink/renderer/core/layout/layout_list_item.h +++ b/third_party/blink/renderer/core/layout/layout_list_item.h
@@ -38,14 +38,21 @@ bool IsEmpty() const; LayoutObject* Marker() const { + CheckIsNotDestroyed(); Element* list_item = To<Element>(GetNode()); return list_item->PseudoElementLayoutObject(kPseudoIdMarker); } - ListItemOrdinal& Ordinal() { return ordinal_; } + ListItemOrdinal& Ordinal() { + CheckIsNotDestroyed(); + return ordinal_; + } void OrdinalValueChanged(); - const char* GetName() const override { return "LayoutListItem"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutListItem"; + } void RecalcVisualOverflow() override; @@ -53,6 +60,7 @@ private: bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectListItem || LayoutBlockFlow::IsOfType(type); }
diff --git a/third_party/blink/renderer/core/layout/layout_list_marker.cc b/third_party/blink/renderer/core/layout/layout_list_marker.cc index 715ade7..4be3a33 100644 --- a/third_party/blink/renderer/core/layout/layout_list_marker.cc +++ b/third_party/blink/renderer/core/layout/layout_list_marker.cc
@@ -44,12 +44,14 @@ LayoutListMarker::~LayoutListMarker() = default; void LayoutListMarker::WillBeDestroyed() { + CheckIsNotDestroyed(); if (image_) image_->RemoveClient(this); LayoutBox::WillBeDestroyed(); } const LayoutListItem* LayoutListMarker::ListItem() const { + CheckIsNotDestroyed(); LayoutObject* list_item = GetNode()->parentNode()->GetLayoutObject(); DCHECK(list_item); DCHECK(list_item->IsListItem()); @@ -57,6 +59,7 @@ } LayoutSize LayoutListMarker::ImageBulletSize() const { + CheckIsNotDestroyed(); DCHECK(IsImage()); const SimpleFontData* font_data = StyleRef().GetFont().PrimaryFont(); DCHECK(font_data); @@ -75,6 +78,7 @@ } void LayoutListMarker::ListStyleTypeChanged() { + CheckIsNotDestroyed(); if (IsImage()) return; SetNeedsLayoutAndIntrinsicWidthsRecalcAndFullPaintInvalidation( @@ -82,6 +86,7 @@ } void LayoutListMarker::UpdateMarkerImageIfNeeded(StyleImage* image) { + CheckIsNotDestroyed(); if (image_ != image) { if (image_) image_->RemoveClient(this); @@ -92,20 +97,24 @@ } InlineBox* LayoutListMarker::CreateInlineBox() { + CheckIsNotDestroyed(); InlineBox* result = LayoutBox::CreateInlineBox(); result->SetIsText(IsText()); return result; } bool LayoutListMarker::IsImage() const { + CheckIsNotDestroyed(); return image_ && !image_->ErrorOccurred(); } void LayoutListMarker::Paint(const PaintInfo& paint_info) const { + CheckIsNotDestroyed(); ListMarkerPainter(*this).Paint(paint_info); } void LayoutListMarker::UpdateLayout() { + CheckIsNotDestroyed(); DCHECK(NeedsLayout()); LayoutAnalyzer::Scope analyzer(*this); @@ -138,6 +147,7 @@ } void LayoutListMarker::ImageChanged(WrappedImagePtr o, CanDeferInvalidation) { + CheckIsNotDestroyed(); // A list marker can't have a background or border image, so no need to call // the base class method. if (!image_ || o != image_->Data()) @@ -153,6 +163,7 @@ } void LayoutListMarker::UpdateContent() { + CheckIsNotDestroyed(); DCHECK(IntrinsicLogicalWidthsDirty()); text_ = ""; @@ -178,6 +189,7 @@ } String LayoutListMarker::TextAlternative() const { + CheckIsNotDestroyed(); if (GetListStyleCategory() == ListMarker::ListStyleCategory::kStaticString) return text_; UChar suffix = @@ -188,6 +200,7 @@ LayoutUnit LayoutListMarker::GetWidthOfText( ListMarker::ListStyleCategory category) const { + CheckIsNotDestroyed(); // TODO(crbug.com/1012289): this code doesn't support bidi algorithm. if (text_.IsEmpty()) return LayoutUnit(); @@ -209,6 +222,7 @@ } MinMaxSizes LayoutListMarker::ComputeIntrinsicLogicalWidths() const { + CheckIsNotDestroyed(); DCHECK(IntrinsicLogicalWidthsDirty()); const_cast<LayoutListMarker*>(this)->UpdateContent(); @@ -237,10 +251,12 @@ } MinMaxSizes LayoutListMarker::PreferredLogicalWidths() const { + CheckIsNotDestroyed(); return IntrinsicLogicalWidths(); } void LayoutListMarker::UpdateMargins(LayoutUnit marker_inline_size) { + CheckIsNotDestroyed(); LayoutUnit margin_start; LayoutUnit margin_end; const ComputedStyle& style = StyleRef(); @@ -258,6 +274,7 @@ } void LayoutListMarker::UpdateMargins() { + CheckIsNotDestroyed(); UpdateMargins(PreferredLogicalWidths().min_size); } @@ -265,6 +282,7 @@ bool first_line, LineDirectionMode direction, LinePositionMode line_position_mode) const { + CheckIsNotDestroyed(); if (!IsImage()) return ListItem()->LineHeight(first_line, direction, kPositionOfInteriorLineBoxes); @@ -276,6 +294,7 @@ bool first_line, LineDirectionMode direction, LinePositionMode line_position_mode) const { + CheckIsNotDestroyed(); DCHECK_EQ(line_position_mode, kPositionOnContainingLine); if (!IsImage()) return ListItem()->BaselinePosition(baseline_type, first_line, direction, @@ -285,10 +304,12 @@ } ListMarker::ListStyleCategory LayoutListMarker::GetListStyleCategory() const { + CheckIsNotDestroyed(); return ListMarker::GetListStyleCategory(StyleRef().ListStyleType()); } bool LayoutListMarker::IsInside() const { + CheckIsNotDestroyed(); const LayoutListItem* list_item = ListItem(); const ComputedStyle& parent_style = list_item->StyleRef(); return parent_style.ListStylePosition() == EListStylePosition::kInside || @@ -297,6 +318,7 @@ } LayoutRect LayoutListMarker::GetRelativeMarkerRect() const { + CheckIsNotDestroyed(); if (IsImage()) return LayoutRect(LayoutPoint(), ImageBulletSize());
diff --git a/third_party/blink/renderer/core/layout/layout_list_marker.h b/third_party/blink/renderer/core/layout/layout_list_marker.h index 27b0d37..b6c3f90 100644 --- a/third_party/blink/renderer/core/layout/layout_list_marker.h +++ b/third_party/blink/renderer/core/layout/layout_list_marker.h
@@ -42,7 +42,10 @@ ~LayoutListMarker() override; // Marker text without suffix, e.g. "1". - const String& GetText() const { return text_; } + const String& GetText() const { + CheckIsNotDestroyed(); + return text_; + } // Marker text with suffix, e.g. "1. ", for use in accessibility. String TextAlternative() const; @@ -54,13 +57,20 @@ LayoutRect GetRelativeMarkerRect() const; bool IsImage() const override; - const StyleImage* GetImage() const { return image_.Get(); } + const StyleImage* GetImage() const { + CheckIsNotDestroyed(); + return image_.Get(); + } const LayoutListItem* ListItem() const; LayoutSize ImageBulletSize() const; - const char* GetName() const override { return "LayoutListMarker"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutListMarker"; + } LayoutUnit ListItemInlineStartOffset() const { + CheckIsNotDestroyed(); return list_item_inline_start_offset_; } @@ -72,6 +82,7 @@ MinMaxSizes PreferredLogicalWidths() const override; bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectListMarker || LayoutBox::IsOfType(type); } @@ -93,7 +104,10 @@ LineDirectionMode, LinePositionMode = kPositionOnContainingLine) const override; - bool IsText() const { return !IsImage(); } + bool IsText() const { + CheckIsNotDestroyed(); + return !IsImage(); + } LayoutUnit GetWidthOfText(ListMarker::ListStyleCategory) const; void UpdateMargins(LayoutUnit marker_inline_size);
diff --git a/third_party/blink/renderer/core/layout/layout_list_marker_image.cc b/third_party/blink/renderer/core/layout/layout_list_marker_image.cc index e17dbc4..9bf849bb 100644 --- a/third_party/blink/renderer/core/layout/layout_list_marker_image.cc +++ b/third_party/blink/renderer/core/layout/layout_list_marker_image.cc
@@ -21,10 +21,12 @@ } bool LayoutListMarkerImage::IsOfType(LayoutObjectType type) const { + CheckIsNotDestroyed(); return type == kLayoutObjectListMarkerImage || LayoutImage::IsOfType(type); } LayoutSize LayoutListMarkerImage::DefaultSize() const { + CheckIsNotDestroyed(); const SimpleFontData* font_data = Style()->GetFont().PrimaryFont(); DCHECK(font_data); if (!font_data) @@ -39,6 +41,7 @@ // default object size(ascent/2 x ascent/2). void LayoutListMarkerImage::ComputeIntrinsicSizingInfoByDefaultSize( IntrinsicSizingInfo& intrinsic_sizing_info) const { + CheckIsNotDestroyed(); FloatSize concrete_size = ImageResource()->ImageSizeWithDefaultSize( Style()->EffectiveZoom(), FloatSize(DefaultSize())); concrete_size.Scale(ImageDevicePixelRatio()); @@ -52,6 +55,7 @@ void LayoutListMarkerImage::ComputeIntrinsicSizingInfo( IntrinsicSizingInfo& intrinsic_sizing_info) const { + CheckIsNotDestroyed(); LayoutImage::ComputeIntrinsicSizingInfo(intrinsic_sizing_info); // If this is an image without intrinsic width and height, compute the
diff --git a/third_party/blink/renderer/core/layout/layout_list_marker_image.h b/third_party/blink/renderer/core/layout/layout_list_marker_image.h index 878cde8..1222081 100644 --- a/third_party/blink/renderer/core/layout/layout_list_marker_image.h +++ b/third_party/blink/renderer/core/layout/layout_list_marker_image.h
@@ -18,6 +18,7 @@ static LayoutListMarkerImage* CreateAnonymous(Document*); bool IsLayoutNGObject() const override { + CheckIsNotDestroyed(); return IsLayoutNGObjectForListMarkerImage(); } LayoutSize DefaultSize() const;
diff --git a/third_party/blink/renderer/core/layout/layout_media.cc b/third_party/blink/renderer/core/layout/layout_media.cc index a59ab695..41171ab 100644 --- a/third_party/blink/renderer/core/layout/layout_media.cc +++ b/third_party/blink/renderer/core/layout/layout_media.cc
@@ -42,10 +42,12 @@ LayoutMedia::~LayoutMedia() = default; HTMLMediaElement* LayoutMedia::MediaElement() const { + CheckIsNotDestroyed(); return To<HTMLMediaElement>(GetNode()); } void LayoutMedia::UpdateLayout() { + CheckIsNotDestroyed(); LayoutSize old_size(ContentWidth(), ContentHeight()); LayoutImage::UpdateLayout(); @@ -104,6 +106,7 @@ bool LayoutMedia::IsChildAllowed(LayoutObject* child, const ComputedStyle& style) const { + CheckIsNotDestroyed(); // Two types of child layout objects are allowed: media controls // and the text track container. Filter children by node type. DCHECK(child->GetNode()); @@ -132,9 +135,12 @@ } void LayoutMedia::PaintReplaced(const PaintInfo&, - const PhysicalOffset& paint_offset) const {} + const PhysicalOffset& paint_offset) const { + CheckIsNotDestroyed(); +} LayoutUnit LayoutMedia::ComputePanelWidth(const LayoutRect& media_rect) const { + CheckIsNotDestroyed(); // TODO(mlamouri): we don't know if the main frame has an horizontal scrollbar // if it is out of process. See https://crbug.com/662480 if (GetDocument().GetPage()->MainFrame()->IsRemoteFrame())
diff --git a/third_party/blink/renderer/core/layout/layout_media.h b/third_party/blink/renderer/core/layout/layout_media.h index d303267..003f2bef 100644 --- a/third_party/blink/renderer/core/layout/layout_media.h +++ b/third_party/blink/renderer/core/layout/layout_media.h
@@ -39,10 +39,12 @@ ~LayoutMedia() override; LayoutObject* FirstChild() const { + CheckIsNotDestroyed(); DCHECK_EQ(Children(), VirtualChildren()); return Children()->FirstChild(); } LayoutObject* LastChild() const { + CheckIsNotDestroyed(); DCHECK_EQ(Children(), VirtualChildren()); return Children()->LastChild(); } @@ -51,38 +53,62 @@ void SlowFirstChild() const = delete; void SlowLastChild() const = delete; - const LayoutObjectChildList* Children() const { return &children_; } - LayoutObjectChildList* Children() { return &children_; } + const LayoutObjectChildList* Children() const { + CheckIsNotDestroyed(); + return &children_; + } + LayoutObjectChildList* Children() { + CheckIsNotDestroyed(); + return &children_; + } HTMLMediaElement* MediaElement() const; - const char* GetName() const override { return "LayoutMedia"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutMedia"; + } protected: void UpdateLayout() override; bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectMedia || LayoutImage::IsOfType(type); } private: - LayoutObjectChildList* VirtualChildren() final { return Children(); } + LayoutObjectChildList* VirtualChildren() final { + CheckIsNotDestroyed(); + return Children(); + } const LayoutObjectChildList* VirtualChildren() const final { + CheckIsNotDestroyed(); return Children(); } PaintLayerType LayerTypeRequired() const override { + CheckIsNotDestroyed(); return kNormalPaintLayer; } - bool CanHaveChildren() const final { return true; } + bool CanHaveChildren() const final { + CheckIsNotDestroyed(); + return true; + } bool IsChildAllowed(LayoutObject*, const ComputedStyle&) const final; - bool IsImage() const final { return false; } + bool IsImage() const final { + CheckIsNotDestroyed(); + return false; + } void PaintReplaced(const PaintInfo&, const PhysicalOffset& paint_offset) const override; - bool BackgroundShouldAlwaysBeClipped() const final { return false; } + bool BackgroundShouldAlwaysBeClipped() const final { + CheckIsNotDestroyed(); + return false; + } LayoutUnit ComputePanelWidth(const LayoutRect& media_width) const;
diff --git a/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.cc b/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.cc index 1670a3f..e5262c42 100644 --- a/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.cc +++ b/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.cc
@@ -63,6 +63,7 @@ } LayoutMultiColumnSet* LayoutMultiColumnFlowThread::FirstMultiColumnSet() const { + CheckIsNotDestroyed(); for (LayoutObject* sibling = NextSibling(); sibling; sibling = sibling->NextSibling()) { if (sibling->IsLayoutMultiColumnSet()) @@ -72,6 +73,7 @@ } LayoutMultiColumnSet* LayoutMultiColumnFlowThread::LastMultiColumnSet() const { + CheckIsNotDestroyed(); for (LayoutObject* sibling = MultiColumnBlockFlow()->LastChild(); sibling; sibling = sibling->PreviousSibling()) { if (sibling->IsLayoutMultiColumnSet()) @@ -104,6 +106,7 @@ // spanners inside objects that don't support fragmentation. bool LayoutMultiColumnFlowThread::CanContainSpannerInParentFragmentationContext( const LayoutObject& object) const { + CheckIsNotDestroyed(); const auto* block_flow = DynamicTo<LayoutBlockFlow>(object); if (!block_flow) return false; @@ -232,6 +235,7 @@ LayoutMultiColumnSet* LayoutMultiColumnFlowThread::MapDescendantToColumnSet( LayoutObject* layout_object) const { + CheckIsNotDestroyed(); // Should not be used for spanners or content inside them. DCHECK(!ContainingColumnSpannerPlaceholder(layout_object)); DCHECK_NE(layout_object, this); @@ -271,6 +275,7 @@ LayoutMultiColumnSpannerPlaceholder* LayoutMultiColumnFlowThread::ContainingColumnSpannerPlaceholder( const LayoutObject* descendant) const { + CheckIsNotDestroyed(); DCHECK(descendant->IsDescendantOf(this)); if (!HasAnyColumnSpanners(*this)) @@ -288,6 +293,7 @@ } void LayoutMultiColumnFlowThread::Populate() { + CheckIsNotDestroyed(); LayoutBlockFlow* multicol_container = MultiColumnBlockFlow(); DCHECK(!NextSibling()); // Reparent children preceding the flow thread into the flow thread. It's @@ -300,6 +306,7 @@ } void LayoutMultiColumnFlowThread::EvacuateAndDestroy() { + CheckIsNotDestroyed(); LayoutBlockFlow* multicol_container = MultiColumnBlockFlow(); is_being_evacuated_ = true; @@ -327,6 +334,7 @@ } LayoutUnit LayoutMultiColumnFlowThread::MaxColumnLogicalHeight() const { + CheckIsNotDestroyed(); if (column_height_available_) { // If height is non-auto, it's already constrained against max-height as // well. Just return it. @@ -347,6 +355,7 @@ LayoutUnit LayoutMultiColumnFlowThread::TallestUnbreakableLogicalHeight( LayoutUnit offset_in_flow_thread) const { + CheckIsNotDestroyed(); if (LayoutMultiColumnSet* multicol_set = ColumnSetAtBlockOffset( offset_in_flow_thread, kAssociateWithLatterPage)) return multicol_set->TallestUnbreakableLogicalHeight(); @@ -355,11 +364,13 @@ LayoutSize LayoutMultiColumnFlowThread::ColumnOffset( const LayoutPoint& point) const { + CheckIsNotDestroyed(); return FlowThreadTranslationAtPoint(point, CoordinateSpaceConversion::kContaining); } bool LayoutMultiColumnFlowThread::NeedsNewWidth() const { + CheckIsNotDestroyed(); LayoutUnit new_width; unsigned dummy_column_count; // We only care if used column-width changes. CalculateColumnCountAndWidth(new_width, dummy_column_count); @@ -367,10 +378,12 @@ } bool LayoutMultiColumnFlowThread::IsPageLogicalHeightKnown() const { + CheckIsNotDestroyed(); return all_columns_have_known_height_; } bool LayoutMultiColumnFlowThread::MayHaveNonUniformPageLogicalHeight() const { + CheckIsNotDestroyed(); const LayoutMultiColumnSet* column_set = FirstMultiColumnSet(); if (!column_set) return false; @@ -383,6 +396,7 @@ LayoutUnit offset_in_flow_thread, PageBoundaryRule rule, CoordinateSpaceConversion mode) const { + CheckIsNotDestroyed(); if (!HasValidColumnSetInfo()) return LayoutSize(0, 0); LayoutMultiColumnSet* column_set = @@ -396,6 +410,7 @@ LayoutSize LayoutMultiColumnFlowThread::FlowThreadTranslationAtPoint( const LayoutPoint& flow_thread_point, CoordinateSpaceConversion mode) const { + CheckIsNotDestroyed(); LayoutPoint flipped_point = DeprecatedFlipForWritingMode(flow_thread_point); LayoutUnit block_offset = IsHorizontalWritingMode() ? flipped_point.Y() : flipped_point.X(); @@ -411,6 +426,7 @@ LayoutPoint LayoutMultiColumnFlowThread::FlowThreadPointToVisualPoint( const LayoutPoint& flow_thread_point) const { + CheckIsNotDestroyed(); return flow_thread_point + FlowThreadTranslationAtPoint(flow_thread_point, CoordinateSpaceConversion::kVisual); @@ -418,6 +434,7 @@ LayoutPoint LayoutMultiColumnFlowThread::VisualPointToFlowThreadPoint( const LayoutPoint& visual_point) const { + CheckIsNotDestroyed(); LayoutUnit block_offset = IsHorizontalWritingMode() ? visual_point.Y() : visual_point.X(); const LayoutMultiColumnSet* column_set = nullptr; @@ -434,6 +451,7 @@ LayoutUnit LayoutMultiColumnFlowThread::InlineBlockBaseline( LineDirectionMode line_direction) const { + CheckIsNotDestroyed(); LayoutUnit baseline_in_flow_thread = LayoutFlowThread::InlineBlockBaseline(line_direction); LayoutMultiColumnSet* column_set = @@ -449,6 +467,7 @@ LayoutMultiColumnSet* LayoutMultiColumnFlowThread::ColumnSetAtBlockOffset( LayoutUnit offset, PageBoundaryRule page_boundary_rule) const { + CheckIsNotDestroyed(); LayoutMultiColumnSet* column_set = last_set_worked_on_; if (column_set) { // Layout in progress. We are calculating the set heights as we speak, so @@ -522,6 +541,7 @@ void LayoutMultiColumnFlowThread::LayoutColumns( SubtreeLayoutScope& layout_scope) { + CheckIsNotDestroyed(); // Since we ended up here, it means that the multicol container (our parent) // needed layout. Since contents of the multicol container are diverted to the // flow thread, the flow thread needs layout as well. @@ -593,6 +613,7 @@ } void LayoutMultiColumnFlowThread::ColumnRuleStyleDidChange() { + CheckIsNotDestroyed(); for (LayoutMultiColumnSet* column_set = FirstMultiColumnSet(); column_set; column_set = column_set->NextSiblingMultiColumnSet()) { column_set->SetShouldDoFullPaintInvalidation( @@ -602,6 +623,7 @@ bool LayoutMultiColumnFlowThread::RemoveSpannerPlaceholderIfNoLongerValid( LayoutBox* spanner_object_in_flow_thread) { + CheckIsNotDestroyed(); DCHECK(spanner_object_in_flow_thread->SpannerPlaceholder()); if (DescendantIsValidColumnSpanner(spanner_object_in_flow_thread)) return false; // Still a valid spanner. @@ -626,6 +648,7 @@ LayoutMultiColumnFlowThread* LayoutMultiColumnFlowThread::EnclosingFlowThread( AncestorSearchConstraint constraint) const { + CheckIsNotDestroyed(); if (!MultiColumnBlockFlow()->IsInsideFlowThread()) return nullptr; return ToLayoutMultiColumnFlowThread( @@ -635,6 +658,7 @@ FragmentationContext* LayoutMultiColumnFlowThread::EnclosingFragmentationContext( AncestorSearchConstraint constraint) const { + CheckIsNotDestroyed(); // If this multicol container is strictly unbreakable (due to having // scrollbars, for instance), it's also strictly unbreakable in any outer // fragmentation context. As such, what kind of fragmentation that goes on @@ -651,6 +675,7 @@ void LayoutMultiColumnFlowThread::AppendNewFragmentainerGroupIfNeeded( LayoutUnit offset_in_flow_thread, PageBoundaryRule page_boundary_rule) { + CheckIsNotDestroyed(); LayoutMultiColumnSet* column_set = ColumnSetAtBlockOffset(offset_in_flow_thread, page_boundary_rule); if (!column_set->NewFragmentainerGroupsAllowed()) @@ -693,6 +718,7 @@ } void LayoutMultiColumnFlowThread::UpdateFromNG() { + CheckIsNotDestroyed(); all_columns_have_known_height_ = true; for (LayoutBox* column_box = FirstMultiColumnBox(); column_box; column_box = column_box->NextSiblingMultiColumnBox()) { @@ -704,23 +730,27 @@ } bool LayoutMultiColumnFlowThread::IsFragmentainerLogicalHeightKnown() { + CheckIsNotDestroyed(); return IsPageLogicalHeightKnown(); } LayoutUnit LayoutMultiColumnFlowThread::FragmentainerLogicalHeightAt( LayoutUnit block_offset) { + CheckIsNotDestroyed(); DCHECK(IsPageLogicalHeightKnown()); return PageLogicalHeightForOffset(block_offset); } LayoutUnit LayoutMultiColumnFlowThread::RemainingLogicalHeightAt( LayoutUnit block_offset) { + CheckIsNotDestroyed(); DCHECK(IsPageLogicalHeightKnown()); return PageRemainingLogicalHeightForOffset(block_offset, kAssociateWithLatterPage); } void LayoutMultiColumnFlowThread::CalculateColumnHeightAvailable() { + CheckIsNotDestroyed(); // Calculate the non-auto content box height, or set it to 0 if it's auto. We // need to know this before layout, so that we can figure out where to insert // column breaks. We also treat LayoutView (which may be paginated, which uses @@ -747,6 +777,7 @@ void LayoutMultiColumnFlowThread::CalculateColumnCountAndWidth( LayoutUnit& width, unsigned& count) const { + CheckIsNotDestroyed(); LayoutBlock* column_block = MultiColumnBlockFlow(); const ComputedStyle* column_style = column_block->Style(); LayoutUnit available_width = column_block->ContentLogicalWidth(); @@ -789,6 +820,7 @@ void LayoutMultiColumnFlowThread::CreateAndInsertMultiColumnSet( LayoutBox* insert_before) { + CheckIsNotDestroyed(); LayoutBlockFlow* multicol_container = MultiColumnBlockFlow(); LayoutMultiColumnSet* new_set = LayoutMultiColumnSet::CreateAnonymous( *this, multicol_container->StyleRef()); @@ -806,6 +838,7 @@ void LayoutMultiColumnFlowThread::CreateAndInsertSpannerPlaceholder( LayoutBox* spanner_object_in_flow_thread, LayoutObject* inserted_before_in_flow_thread) { + CheckIsNotDestroyed(); LayoutBox* insert_before_column_box = nullptr; LayoutMultiColumnSet* set_to_split = nullptr; if (inserted_before_in_flow_thread) { @@ -863,6 +896,7 @@ void LayoutMultiColumnFlowThread::DestroySpannerPlaceholder( LayoutMultiColumnSpannerPlaceholder* placeholder) { + CheckIsNotDestroyed(); if (LayoutBox* next_column_box = placeholder->NextSiblingMultiColumnBox()) { LayoutBox* previous_column_box = placeholder->PreviousSiblingMultiColumnBox(); @@ -878,6 +912,7 @@ bool LayoutMultiColumnFlowThread::DescendantIsValidColumnSpanner( LayoutObject* descendant) const { + CheckIsNotDestroyed(); // This method needs to behave correctly in the following situations: // - When the descendant doesn't have a spanner placeholder but should have // one (return true). @@ -922,6 +957,7 @@ void LayoutMultiColumnFlowThread::AddColumnSetToThread( LayoutMultiColumnSet* column_set) { + CheckIsNotDestroyed(); if (LayoutMultiColumnSet* next_set = column_set->NextSiblingMultiColumnSet()) { LayoutMultiColumnSetList::iterator it = @@ -934,6 +970,7 @@ } void LayoutMultiColumnFlowThread::InsertedIntoTree() { + CheckIsNotDestroyed(); LayoutFlowThread::InsertedIntoTree(); if (MultiColumnBlockFlow()->IsLayoutNGObject()) fragmentation_engine_ = kNGFragmentationEngine; @@ -942,6 +979,7 @@ } void LayoutMultiColumnFlowThread::WillBeRemovedFromTree() { + CheckIsNotDestroyed(); // Detach all column sets from the flow thread. Cannot destroy them at this // point, since they are siblings of this object, and there may be pointers to // this object's sibling somewhere further up on the call stack. @@ -955,6 +993,7 @@ void LayoutMultiColumnFlowThread::SkipColumnSpanner( LayoutBox* layout_object, LayoutUnit logical_top_in_flow_thread) { + CheckIsNotDestroyed(); DCHECK(layout_object->IsColumnSpanAll()); LayoutMultiColumnSpannerPlaceholder* placeholder = layout_object->SpannerPlaceholder(); @@ -987,6 +1026,7 @@ } bool LayoutMultiColumnFlowThread::FinishLayout() { + CheckIsNotDestroyed(); all_columns_have_known_height_ = true; for (const auto* column_set = FirstMultiColumnSet(); column_set; column_set = column_set->NextSiblingMultiColumnSet()) { @@ -1030,6 +1070,7 @@ void LayoutMultiColumnFlowThread::FlowThreadDescendantWasInserted( LayoutObject* descendant) { + CheckIsNotDestroyed(); DCHECK(!is_being_evacuated_); // This method ensures that the list of column sets and spanner placeholders // reflects the multicol content after having inserted a descendant (or @@ -1089,6 +1130,7 @@ void LayoutMultiColumnFlowThread::FlowThreadDescendantWillBeRemoved( LayoutObject* descendant) { + CheckIsNotDestroyed(); // This method ensures that the list of column sets and spanner placeholders // reflects the multicol content that we'll be left with after removal of a // descendant (or descendant subtree). See the header file for more @@ -1237,6 +1279,7 @@ LayoutBox* descendant, StyleDifference diff, const ComputedStyle& new_style) { + CheckIsNotDestroyed(); toggle_spanners_if_needed_ = false; if (NeedsToRemoveFromFlowThread(*descendant, descendant->StyleRef(), new_style)) { @@ -1259,6 +1302,7 @@ LayoutBox* descendant, StyleDifference diff, const ComputedStyle& old_style) { + CheckIsNotDestroyed(); bool toggle_spanners_if_needed = toggle_spanners_if_needed_; toggle_spanners_if_needed_ = false; @@ -1299,6 +1343,7 @@ void LayoutMultiColumnFlowThread::ToggleSpannersInSubtree( LayoutBox* descendant) { + CheckIsNotDestroyed(); DCHECK_NE(could_contain_spanners_, CanContainSpannerInParentFragmentationContext(*descendant)); @@ -1345,6 +1390,7 @@ } MinMaxSizes LayoutMultiColumnFlowThread::PreferredLogicalWidths() const { + CheckIsNotDestroyed(); // The min/max intrinsic widths calculated really tell how much space elements // need when laid out inside the columns. In order to eventually end up with // the desired column width, we need to convert them to values pertaining to @@ -1387,18 +1433,21 @@ LayoutUnit logical_height, LayoutUnit logical_top, LogicalExtentComputedValues& computed_values) const { + CheckIsNotDestroyed(); // We simply remain at our intrinsic height. computed_values.extent_ = logical_height; computed_values.position_ = logical_top; } void LayoutMultiColumnFlowThread::UpdateLogicalWidth() { + CheckIsNotDestroyed(); LayoutUnit column_width; CalculateColumnCountAndWidth(column_width, column_count_); SetLogicalWidth(column_width); } void LayoutMultiColumnFlowThread::UpdateLayout() { + CheckIsNotDestroyed(); DCHECK(!last_set_worked_on_); last_set_worked_on_ = FirstMultiColumnSet(); if (last_set_worked_on_) @@ -1427,6 +1476,7 @@ void LayoutMultiColumnFlowThread::ContentWasLaidOut( LayoutUnit logical_bottom_in_flow_thread_after_pagination) { + CheckIsNotDestroyed(); // Check if we need another fragmentainer group. If we've run out of columns // in the last fragmentainer group (column row), we need to insert another // fragmentainer group to hold more columns. @@ -1448,6 +1498,7 @@ } bool LayoutMultiColumnFlowThread::CanSkipLayout(const LayoutBox& root) const { + CheckIsNotDestroyed(); // Objects containing spanners is all we need to worry about, so if there are // no spanners at all in this multicol container, we can just return the good // news right away. @@ -1473,11 +1524,13 @@ MultiColumnLayoutState LayoutMultiColumnFlowThread::GetMultiColumnLayoutState() const { + CheckIsNotDestroyed(); return MultiColumnLayoutState(last_set_worked_on_); } void LayoutMultiColumnFlowThread::RestoreMultiColumnLayoutState( const MultiColumnLayoutState& state) { + CheckIsNotDestroyed(); last_set_worked_on_ = state.ColumnSet(); }
diff --git a/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.h b/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.h index 759095c..0a60069 100644 --- a/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.h +++ b/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.h
@@ -151,9 +151,13 @@ const ComputedStyle& parent_style, bool needs_paint_layer); - bool IsLayoutMultiColumnFlowThread() const final { return true; } + bool IsLayoutMultiColumnFlowThread() const final { + CheckIsNotDestroyed(); + return true; + } LayoutBlockFlow* MultiColumnBlockFlow() const { + CheckIsNotDestroyed(); return To<LayoutBlockFlow>(Parent()); } @@ -161,9 +165,13 @@ LayoutMultiColumnSet* LastMultiColumnSet() const; // Return the first column set or spanner placeholder. - LayoutBox* FirstMultiColumnBox() const { return NextSiblingBox(); } + LayoutBox* FirstMultiColumnBox() const { + CheckIsNotDestroyed(); + return NextSiblingBox(); + } // Return the last column set or spanner placeholder. LayoutBox* LastMultiColumnBox() const { + CheckIsNotDestroyed(); LayoutBox* last_sibling_box = MultiColumnBlockFlow()->LastChildBox(); // The flow thread is the first child of the multicol container. If the flow // thread is also the last child, it means that there are no siblings; i.e. @@ -190,12 +198,19 @@ // a multicol container becomes a regular block. void EvacuateAndDestroy(); - unsigned ColumnCount() const { return column_count_; } + unsigned ColumnCount() const { + CheckIsNotDestroyed(); + return column_count_; + } // Total height available to columns and spanners. This is the multicol // container's content box logical height, or 0 if auto. - LayoutUnit ColumnHeightAvailable() const { return column_height_available_; } + LayoutUnit ColumnHeightAvailable() const { + CheckIsNotDestroyed(); + return column_height_available_; + } void SetColumnHeightAvailable(LayoutUnit available) { + CheckIsNotDestroyed(); column_height_available_ = available; } @@ -250,8 +265,14 @@ // again twice or even just once will suffice. Sometimes we need more passes // than that, though, but the number of retries should not exceed the number // of columns, unless we have a bug. - bool ColumnHeightsChanged() const { return column_heights_changed_; } - void SetColumnHeightsChanged() { column_heights_changed_ = true; } + bool ColumnHeightsChanged() const { + CheckIsNotDestroyed(); + return column_heights_changed_; + } + void SetColumnHeightsChanged() { + CheckIsNotDestroyed(); + column_heights_changed_ = true; + } // Finish multicol layout. Returns true if we're really done, or false if we // need another layout pass (typically because columns got new heights in the @@ -270,6 +291,7 @@ FragmentationContext* EnclosingFragmentationContext( AncestorSearchConstraint = kIsolateUnbreakableContainers) const; LayoutUnit BlockOffsetInEnclosingFragmentationContext() const { + CheckIsNotDestroyed(); DCHECK(EnclosingFragmentationContext(kAnyAncestor)); return block_offset_in_enclosing_fragmentation_context_; } @@ -287,9 +309,15 @@ bool IsFragmentainerLogicalHeightKnown() final; LayoutUnit FragmentainerLogicalHeightAt(LayoutUnit block_offset) final; LayoutUnit RemainingLogicalHeightAt(LayoutUnit block_offset) final; - LayoutMultiColumnFlowThread* AssociatedFlowThread() final { return this; } + LayoutMultiColumnFlowThread* AssociatedFlowThread() final { + CheckIsNotDestroyed(); + return this; + } - const char* GetName() const override { return "LayoutMultiColumnFlowThread"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutMultiColumnFlowThread"; + } private: explicit LayoutMultiColumnFlowThread(bool needs_paint_layer);
diff --git a/third_party/blink/renderer/core/layout/layout_multi_column_set.cc b/third_party/blink/renderer/core/layout/layout_multi_column_set.cc index 9240379b..b1c380de 100644 --- a/third_party/blink/renderer/core/layout/layout_multi_column_set.cc +++ b/third_party/blink/renderer/core/layout/layout_multi_column_set.cc
@@ -54,6 +54,7 @@ unsigned LayoutMultiColumnSet::FragmentainerGroupIndexAtFlowThreadOffset( LayoutUnit flow_thread_offset, PageBoundaryRule rule) const { + CheckIsNotDestroyed(); DCHECK_GT(fragmentainer_groups_.size(), 0u); if (flow_thread_offset <= 0) return 0; @@ -75,6 +76,7 @@ const MultiColumnFragmentainerGroup& LayoutMultiColumnSet::FragmentainerGroupAtVisualPoint( const LayoutPoint& visual_point) const { + CheckIsNotDestroyed(); DCHECK_GT(fragmentainer_groups_.size(), 0u); LayoutUnit block_offset = IsHorizontalWritingMode() ? visual_point.Y() : visual_point.X(); @@ -88,6 +90,7 @@ LayoutUnit LayoutMultiColumnSet::PageLogicalHeightForOffset( LayoutUnit offset) const { + CheckIsNotDestroyed(); DCHECK(IsPageLogicalHeightKnown()); const MultiColumnFragmentainerGroup& last_row = LastFragmentainerGroup(); if (offset >= last_row.LogicalTopInFlowThread() + @@ -131,6 +134,7 @@ LayoutUnit LayoutMultiColumnSet::PageRemainingLogicalHeightForOffset( LayoutUnit offset_in_flow_thread, PageBoundaryRule page_boundary_rule) const { + CheckIsNotDestroyed(); const MultiColumnFragmentainerGroup& row = FragmentainerGroupAtFlowThreadOffset(offset_in_flow_thread, page_boundary_rule); @@ -159,10 +163,12 @@ } bool LayoutMultiColumnSet::IsPageLogicalHeightKnown() const { + CheckIsNotDestroyed(); return FirstFragmentainerGroup().IsLogicalHeightKnown(); } bool LayoutMultiColumnSet::NewFragmentainerGroupsAllowed() const { + CheckIsNotDestroyed(); if (!IsPageLogicalHeightKnown()) { // If we have no clue about the height of the multicol container, bail. This // situation occurs initially when an auto-height multicol container is @@ -185,6 +191,7 @@ LayoutUnit LayoutMultiColumnSet::NextLogicalTopForUnbreakableContent( LayoutUnit flow_thread_offset, LayoutUnit content_logical_height) const { + CheckIsNotDestroyed(); if (!MultiColumnFlowThread()->EnclosingFragmentationContext()) { // If there's no enclosing fragmentation context, there'll ever be only one // row, and all columns there will have the same height. @@ -216,6 +223,7 @@ } LayoutMultiColumnSet* LayoutMultiColumnSet::NextSiblingMultiColumnSet() const { + CheckIsNotDestroyed(); for (LayoutObject* sibling = NextSibling(); sibling; sibling = sibling->NextSibling()) { if (sibling->IsLayoutMultiColumnSet()) @@ -226,6 +234,7 @@ LayoutMultiColumnSet* LayoutMultiColumnSet::PreviousSiblingMultiColumnSet() const { + CheckIsNotDestroyed(); for (LayoutObject* sibling = PreviousSibling(); sibling; sibling = sibling->PreviousSibling()) { if (sibling->IsLayoutMultiColumnSet()) @@ -237,6 +246,7 @@ bool LayoutMultiColumnSet::NeedsNewFragmentainerGroupAt( LayoutUnit offset_in_flow_thread, PageBoundaryRule page_boundary_rule) const { + CheckIsNotDestroyed(); // First the cheap check: Perhaps the last fragmentainer group has sufficient // capacity? const MultiColumnFragmentainerGroup& last_row = LastFragmentainerGroup(); @@ -285,6 +295,7 @@ MultiColumnFragmentainerGroup& LayoutMultiColumnSet::AppendNewFragmentainerGroup() { + CheckIsNotDestroyed(); MultiColumnFragmentainerGroup new_group(*this); { // Extra scope here for previousGroup; it's potentially invalid once we // modify the m_fragmentainerGroups Vector. @@ -307,6 +318,7 @@ } LayoutUnit LayoutMultiColumnSet::LogicalTopFromMulticolContentEdge() const { + CheckIsNotDestroyed(); // We subtract the position of the first column set or spanner placeholder, // rather than the "before" border+padding of the multicol container. This // distinction doesn't matter after layout, but during layout it does: @@ -328,14 +340,17 @@ } LayoutUnit LayoutMultiColumnSet::LogicalTopInFlowThread() const { + CheckIsNotDestroyed(); return FirstFragmentainerGroup().LogicalTopInFlowThread(); } LayoutUnit LayoutMultiColumnSet::LogicalBottomInFlowThread() const { + CheckIsNotDestroyed(); return LastFragmentainerGroup().LogicalBottomInFlowThread(); } bool LayoutMultiColumnSet::HeightIsAuto() const { + CheckIsNotDestroyed(); LayoutMultiColumnFlowThread* flow_thread = MultiColumnFlowThread(); // If support for the column-fill property isn't enabled, we want to behave // as if column-fill were auto, so that multicol containers with specified @@ -360,12 +375,14 @@ LayoutUnit block_offset, PageBoundaryRule rule, CoordinateSpaceConversion mode) const { + CheckIsNotDestroyed(); return FragmentainerGroupAtFlowThreadOffset(block_offset, rule) .FlowThreadTranslationAtOffset(block_offset, rule, mode); } LayoutPoint LayoutMultiColumnSet::VisualPointToFlowThreadPoint( const LayoutPoint& visual_point) const { + CheckIsNotDestroyed(); const MultiColumnFragmentainerGroup& row = FragmentainerGroupAtVisualPoint(visual_point); return row.VisualPointToFlowThreadPoint(visual_point - @@ -374,11 +391,13 @@ LayoutUnit LayoutMultiColumnSet::PageLogicalTopForOffset( LayoutUnit offset) const { + CheckIsNotDestroyed(); return FragmentainerGroupAtFlowThreadOffset(offset, kAssociateWithLatterPage) .ColumnLogicalTopForOffset(offset); } bool LayoutMultiColumnSet::RecalculateColumnHeight() { + CheckIsNotDestroyed(); if (old_logical_top_ != LogicalTop() && MultiColumnFlowThread()->EnclosingFragmentationContext()) { // Preceding spanners or column sets have been moved or resized. This means @@ -396,6 +415,7 @@ } void LayoutMultiColumnSet::ResetColumnHeight() { + CheckIsNotDestroyed(); fragmentainer_groups_.DeleteExtraGroups(); fragmentainer_groups_.First().ResetColumnHeight(); tallest_unbreakable_logical_height_ = LayoutUnit(); @@ -403,6 +423,7 @@ } void LayoutMultiColumnSet::BeginFlow(LayoutUnit offset_in_flow_thread) { + CheckIsNotDestroyed(); // At this point layout is exactly at the beginning of this set. Store block // offset from flow thread start. fragmentainer_groups_.First().SetLogicalTopInFlowThread( @@ -410,6 +431,7 @@ } void LayoutMultiColumnSet::EndFlow(LayoutUnit offset_in_flow_thread) { + CheckIsNotDestroyed(); // At this point layout is exactly at the end of this set. Store block offset // from flow thread start. This set is now considered "flowed", although we // may have to revisit it later (with beginFlow()), e.g. if a subtree in the @@ -421,6 +443,7 @@ void LayoutMultiColumnSet::StyleDidChange(StyleDifference diff, const ComputedStyle* old_style) { + CheckIsNotDestroyed(); LayoutBlockFlow::StyleDidChange(diff, old_style); // column-rule is specified on the parent (the multicol container) of this @@ -436,6 +459,7 @@ } void LayoutMultiColumnSet::UpdateLayout() { + CheckIsNotDestroyed(); if (RecalculateColumnHeight()) MultiColumnFlowThread()->SetColumnHeightsChanged(); LayoutBlockFlow::UpdateLayout(); @@ -450,6 +474,7 @@ } MinMaxSizes LayoutMultiColumnSet::ComputeIntrinsicLogicalWidths() const { + CheckIsNotDestroyed(); return MinMaxSizes(); } @@ -457,6 +482,7 @@ LayoutUnit, LayoutUnit logical_top, LogicalExtentComputedValues& computed_values) const { + CheckIsNotDestroyed(); LayoutUnit logical_height; // Under some circumstances column heights are unknown at this point. This // happens e.g. when this column set got pushed down by a preceding spanner @@ -473,6 +499,7 @@ PositionWithAffinity LayoutMultiColumnSet::PositionForPoint( const PhysicalOffset& point) const { + CheckIsNotDestroyed(); LayoutPoint flipped_point = FlipForWritingMode(point); // Convert the visual point to a flow thread point. const MultiColumnFragmentainerGroup& row = @@ -486,6 +513,7 @@ } LayoutUnit LayoutMultiColumnSet::ColumnGap() const { + CheckIsNotDestroyed(); LayoutBlockFlow* parent_block = MultiColumnBlockFlow(); if (const base::Optional<Length>& column_gap = @@ -498,6 +526,7 @@ } unsigned LayoutMultiColumnSet::ActualColumnCount() const { + CheckIsNotDestroyed(); // FIXME: remove this method. It's a meaningless question to ask the set "how // many columns do you actually have?", since that may vary for each row. return FirstFragmentainerGroup().ActualColumnCount(); @@ -506,19 +535,21 @@ void LayoutMultiColumnSet::PaintObject( const PaintInfo& paint_info, const PhysicalOffset& paint_offset) const { + CheckIsNotDestroyed(); MultiColumnSetPainter(*this).PaintObject(paint_info, paint_offset); } LayoutRect LayoutMultiColumnSet::FragmentsBoundingBox( const LayoutRect& bounding_box_in_flow_thread) const { + CheckIsNotDestroyed(); LayoutRect result; for (const auto& group : fragmentainer_groups_) result.Unite(group.FragmentsBoundingBox(bounding_box_in_flow_thread)); return result; } -void LayoutMultiColumnSet::ComputeVisualOverflow( - bool recompute_floats) { +void LayoutMultiColumnSet::ComputeVisualOverflow(bool recompute_floats) { + CheckIsNotDestroyed(); LayoutRect previous_visual_overflow_rect = VisualOverflowRect(); ClearVisualOverflow(); AddVisualOverflowFromChildren(); @@ -536,6 +567,7 @@ } void LayoutMultiColumnSet::AddVisualOverflowFromChildren() { + CheckIsNotDestroyed(); if (ChildLayoutBlockedByDisplayLock()) return; @@ -553,6 +585,7 @@ } void LayoutMultiColumnSet::AddLayoutOverflowFromChildren() { + CheckIsNotDestroyed(); if (ChildLayoutBlockedByDisplayLock()) return; @@ -570,16 +603,19 @@ } void LayoutMultiColumnSet::InsertedIntoTree() { + CheckIsNotDestroyed(); LayoutBlockFlow::InsertedIntoTree(); AttachToFlowThread(); } void LayoutMultiColumnSet::WillBeRemovedFromTree() { + CheckIsNotDestroyed(); LayoutBlockFlow::WillBeRemovedFromTree(); DetachFromFlowThread(); } void LayoutMultiColumnSet::AttachToFlowThread() { + CheckIsNotDestroyed(); if (DocumentBeingDestroyed()) return; @@ -590,6 +626,7 @@ } void LayoutMultiColumnSet::DetachFromFlowThread() { + CheckIsNotDestroyed(); if (flow_thread_) { flow_thread_->RemoveColumnSetFromThread(this); flow_thread_ = nullptr; @@ -597,6 +634,7 @@ } LayoutRect LayoutMultiColumnSet::FlowThreadPortionRect() const { + CheckIsNotDestroyed(); LayoutRect portion_rect(LayoutUnit(), LogicalTopInFlowThread(), PageLogicalWidth(), LogicalHeightInFlowThread()); if (!IsHorizontalWritingMode()) @@ -607,6 +645,7 @@ bool LayoutMultiColumnSet::ComputeColumnRuleBounds( const LayoutPoint& paint_offset, Vector<LayoutRect>& column_rule_bounds) const { + CheckIsNotDestroyed(); // Reference: https://www.w3.org/TR/css3-multicol/#column-gaps-and-rules const ComputedStyle& block_style = MultiColumnBlockFlow()->StyleRef(); bool rule_transparent = block_style.ColumnRuleIsTransparent(); @@ -667,6 +706,7 @@ } PhysicalRect LayoutMultiColumnSet::LocalVisualRectIgnoringVisibility() const { + CheckIsNotDestroyed(); PhysicalRect block_flow_bounds = LayoutBlockFlow::LocalVisualRectIgnoringVisibility(); @@ -681,6 +721,7 @@ } void LayoutMultiColumnSet::UpdateFromNG() { + CheckIsNotDestroyed(); DCHECK_EQ(fragmentainer_groups_.size(), 1U); auto& group = fragmentainer_groups_[0]; group.UpdateFromNG(LogicalHeight());
diff --git a/third_party/blink/renderer/core/layout/layout_multi_column_set.h b/third_party/blink/renderer/core/layout/layout_multi_column_set.h index 6fdae46..e5d8b02 100644 --- a/third_party/blink/renderer/core/layout/layout_multi_column_set.h +++ b/third_party/blink/renderer/core/layout/layout_multi_column_set.h
@@ -70,9 +70,11 @@ const ComputedStyle& parent_style); const MultiColumnFragmentainerGroup& FirstFragmentainerGroup() const { + CheckIsNotDestroyed(); return fragmentainer_groups_.First(); } const MultiColumnFragmentainerGroup& LastFragmentainerGroup() const { + CheckIsNotDestroyed(); return fragmentainer_groups_.Last(); } unsigned FragmentainerGroupIndexAtFlowThreadOffset(LayoutUnit, @@ -80,29 +82,39 @@ MultiColumnFragmentainerGroup& FragmentainerGroupAtFlowThreadOffset( LayoutUnit flow_thread_offset, PageBoundaryRule rule) { + CheckIsNotDestroyed(); return fragmentainer_groups_[FragmentainerGroupIndexAtFlowThreadOffset( flow_thread_offset, rule)]; } const MultiColumnFragmentainerGroup& FragmentainerGroupAtFlowThreadOffset( LayoutUnit flow_thread_offset, PageBoundaryRule rule) const { + CheckIsNotDestroyed(); return fragmentainer_groups_[FragmentainerGroupIndexAtFlowThreadOffset( flow_thread_offset, rule)]; } const MultiColumnFragmentainerGroup& FragmentainerGroupAtVisualPoint( const LayoutPoint&) const; const MultiColumnFragmentainerGroupList& FragmentainerGroups() const { + CheckIsNotDestroyed(); return fragmentainer_groups_; } bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectLayoutMultiColumnSet || LayoutBlockFlow::IsOfType(type); } - bool CanHaveChildren() const final { return false; } + bool CanHaveChildren() const final { + CheckIsNotDestroyed(); + return false; + } // Return the width and height of a single column or page in the set. - LayoutUnit PageLogicalWidth() const { return FlowThread()->LogicalWidth(); } + LayoutUnit PageLogicalWidth() const { + CheckIsNotDestroyed(); + return FlowThread()->LogicalWidth(); + } LayoutUnit PageLogicalHeightForOffset(LayoutUnit) const; LayoutUnit PageRemainingLogicalHeightForOffset(LayoutUnit, PageBoundaryRule) const; @@ -113,9 +125,11 @@ bool NewFragmentainerGroupsAllowed() const; LayoutUnit TallestUnbreakableLogicalHeight() const { + CheckIsNotDestroyed(); return tallest_unbreakable_logical_height_; } void PropagateTallestUnbreakableLogicalHeight(LayoutUnit value) { + CheckIsNotDestroyed(); tallest_unbreakable_logical_height_ = std::max(value, tallest_unbreakable_logical_height_); } @@ -124,12 +138,17 @@ LayoutUnit flow_thread_offset, LayoutUnit content_logical_height) const; - LayoutFlowThread* FlowThread() const { return flow_thread_; } + LayoutFlowThread* FlowThread() const { + CheckIsNotDestroyed(); + return flow_thread_; + } LayoutBlockFlow* MultiColumnBlockFlow() const { + CheckIsNotDestroyed(); return To<LayoutBlockFlow>(Parent()); } LayoutMultiColumnFlowThread* MultiColumnFlowThread() const { + CheckIsNotDestroyed(); return ToLayoutMultiColumnFlowThread(FlowThread()); } @@ -149,6 +168,7 @@ LayoutUnit LogicalTopInFlowThread() const; LayoutUnit LogicalBottomInFlowThread() const; LayoutUnit LogicalHeightInFlowThread() const { + CheckIsNotDestroyed(); // Due to negative margins, logical bottom may actually end up above logical // top, but we never want to return negative logical heights. return (LogicalBottomInFlowThread() - LogicalTopInFlowThread()) @@ -159,6 +179,7 @@ // group can hold without overflowing. LayoutUnit FragmentainerGroupCapacity( const MultiColumnFragmentainerGroup& group) const { + CheckIsNotDestroyed(); return group.ColumnLogicalHeight() * UsedColumnCount(); } @@ -167,6 +188,7 @@ // The used CSS value of column-count, i.e. how many columns there are room // for without overflowing. unsigned UsedColumnCount() const { + CheckIsNotDestroyed(); return MultiColumnFlowThread()->ColumnCount(); } @@ -191,8 +213,14 @@ // Reset previously calculated column height. Will mark for layout if needed. void ResetColumnHeight(); - void StoreOldPosition() { old_logical_top_ = LogicalTop(); } - bool IsInitialHeightCalculated() const { return initial_height_calculated_; } + void StoreOldPosition() { + CheckIsNotDestroyed(); + old_logical_top_ = LogicalTop(); + } + bool IsInitialHeightCalculated() const { + CheckIsNotDestroyed(); + return initial_height_calculated_; + } // Layout of flow thread content that's to be rendered inside this column set // begins. This happens at the beginning of flow thread layout, and when @@ -225,7 +253,10 @@ // if any. unsigned ActualColumnCount() const; - const char* GetName() const override { return "LayoutMultiColumnSet"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutMultiColumnSet"; + } // Sets |columnRuleBounds| to the bounds of each column rule rect's painted // extent, adjusted by paint offset, before pixel snapping. Returns true if @@ -244,7 +275,10 @@ void InsertedIntoTree() final; void WillBeRemovedFromTree() final; - bool IsSelfCollapsingBlock() const override { return false; } + bool IsSelfCollapsingBlock() const override { + CheckIsNotDestroyed(); + return false; + } void ComputeLogicalHeight(LayoutUnit logical_height, LayoutUnit logical_top,
diff --git a/third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.cc b/third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.cc index 10b19d7..d00ac6b 100644 --- a/third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.cc +++ b/third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.cc
@@ -38,6 +38,7 @@ void LayoutMultiColumnSpannerPlaceholder:: LayoutObjectInFlowThreadStyleDidChange(const ComputedStyle* old_style) { + CheckIsNotDestroyed(); LayoutBox* object_in_flow_thread = layout_object_in_flow_thread_; if (FlowThread()->RemoveSpannerPlaceholderIfNoLongerValid( object_in_flow_thread)) { @@ -61,6 +62,7 @@ void LayoutMultiColumnSpannerPlaceholder::UpdateProperties( const ComputedStyle& parent_style) { + CheckIsNotDestroyed(); scoped_refptr<ComputedStyle> new_style = ComputedStyle::CreateAnonymousStyleWithDisplay(parent_style, EDisplay::kBlock); @@ -69,6 +71,7 @@ } void LayoutMultiColumnSpannerPlaceholder::InsertedIntoTree() { + CheckIsNotDestroyed(); LayoutBox::InsertedIntoTree(); // The object may previously have been laid out as a non-spanner, but since // it's a spanner now, it needs to be relaid out. @@ -77,6 +80,7 @@ } void LayoutMultiColumnSpannerPlaceholder::WillBeRemovedFromTree() { + CheckIsNotDestroyed(); if (layout_object_in_flow_thread_) { LayoutBox* ex_spanner = layout_object_in_flow_thread_; layout_object_in_flow_thread_->ClearSpannerPlaceholder(); @@ -91,10 +95,12 @@ bool LayoutMultiColumnSpannerPlaceholder::NeedsPreferredWidthsRecalculation() const { + CheckIsNotDestroyed(); return layout_object_in_flow_thread_->NeedsPreferredWidthsRecalculation(); } void LayoutMultiColumnSpannerPlaceholder::RecalcVisualOverflow() { + CheckIsNotDestroyed(); LayoutBox::RecalcVisualOverflow(); ClearVisualOverflow(); AddContentsVisualOverflow( @@ -103,6 +109,7 @@ MinMaxSizes LayoutMultiColumnSpannerPlaceholder::PreferredLogicalWidths() const { + CheckIsNotDestroyed(); // There should be no contribution from a spanner if the multicol container is // size-contained. Normally we'd stop at the object that has contain:size // applied, but for multicol, we descend into the children, in order to get @@ -116,6 +123,7 @@ } void LayoutMultiColumnSpannerPlaceholder::UpdateLayout() { + CheckIsNotDestroyed(); DCHECK(NeedsLayout()); // The placeholder, like any other block level object, has its logical top @@ -148,6 +156,7 @@ LayoutUnit, LayoutUnit logical_top, LogicalExtentComputedValues& computed_values) const { + CheckIsNotDestroyed(); computed_values.extent_ = layout_object_in_flow_thread_->LogicalHeight(); computed_values.position_ = logical_top; computed_values.margins_.before_ = MarginBefore(); @@ -156,6 +165,7 @@ void LayoutMultiColumnSpannerPlaceholder::Paint( const PaintInfo& paint_info) const { + CheckIsNotDestroyed(); if (!layout_object_in_flow_thread_->HasSelfPaintingLayer()) layout_object_in_flow_thread_->Paint(paint_info); } @@ -165,6 +175,7 @@ const HitTestLocation& hit_test_location, const PhysicalOffset& accumulated_offset, HitTestAction action) { + CheckIsNotDestroyed(); return !layout_object_in_flow_thread_->HasSelfPaintingLayer() && layout_object_in_flow_thread_->NodeAtPoint(result, hit_test_location, accumulated_offset, action);
diff --git a/third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.h b/third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.h index a2575a39..7b05321 100644 --- a/third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.h +++ b/third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.h
@@ -18,6 +18,7 @@ class LayoutMultiColumnSpannerPlaceholder final : public LayoutBox { public: bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectLayoutMultiColumnSpannerPlaceholder || LayoutBox::IsOfType(type); } @@ -27,17 +28,21 @@ LayoutBox&); LayoutBlockFlow* MultiColumnBlockFlow() const { + CheckIsNotDestroyed(); return To<LayoutBlockFlow>(Parent()); } LayoutMultiColumnFlowThread* FlowThread() const { + CheckIsNotDestroyed(); return To<LayoutBlockFlow>(Parent())->MultiColumnFlowThread(); } LayoutBox* LayoutObjectInFlowThread() const { + CheckIsNotDestroyed(); return layout_object_in_flow_thread_; } void MarkForLayoutIfObjectInFlowThreadNeedsLayout() { + CheckIsNotDestroyed(); if (!layout_object_in_flow_thread_->NeedsLayout()) return; // The containing block of a spanner is the multicol container (our parent @@ -46,12 +51,16 @@ SetChildNeedsLayout(kMarkOnlyThis); } - bool AnonymousHasStylePropagationOverride() final { return true; } + bool AnonymousHasStylePropagationOverride() final { + CheckIsNotDestroyed(); + return true; + } void LayoutObjectInFlowThreadStyleDidChange(const ComputedStyle* old_style); void UpdateProperties(const ComputedStyle& parent_style); const char* GetName() const override { + CheckIsNotDestroyed(); return "LayoutMultiColumnSpannerPlaceholder"; } @@ -75,6 +84,7 @@ LayoutMultiColumnSpannerPlaceholder(LayoutBox*); MinMaxSizes ComputeIntrinsicLogicalWidths() const final { + CheckIsNotDestroyed(); NOTREACHED(); return MinMaxSizes(); }
diff --git a/third_party/blink/renderer/core/layout/layout_object.cc b/third_party/blink/renderer/core/layout/layout_object.cc index e9c34784..3d72aca 100644 --- a/third_party/blink/renderer/core/layout/layout_object.cc +++ b/third_party/blink/renderer/core/layout/layout_object.cc
@@ -331,6 +331,7 @@ } bool LayoutObject::IsDescendantOf(const LayoutObject* obj) const { + CheckIsNotDestroyed(); for (const LayoutObject* r = this; r; r = r->parent_) { if (r == obj) return true; @@ -339,10 +340,12 @@ } bool LayoutObject::IsHR() const { + CheckIsNotDestroyed(); return IsA<HTMLHRElement>(GetNode()); } bool LayoutObject::IsStyleGenerated() const { + CheckIsNotDestroyed(); if (const auto* layout_text_fragment = ToLayoutTextFragmentOrNull(this)) return !layout_text_fragment->AssociatedTextNode(); @@ -352,6 +355,7 @@ void LayoutObject::SetIsInsideFlowThreadIncludingDescendants( bool inside_flow_thread) { + CheckIsNotDestroyed(); LayoutObject* next; for (LayoutObject* object = this; object; object = next) { // If object is a fragmentation context it already updated the descendants @@ -368,6 +372,7 @@ bool LayoutObject::RequiresAnonymousTableWrappers( const LayoutObject* new_child) const { + CheckIsNotDestroyed(); // Check should agree with: // CSS 2.1 Tables: 17.2.1 Anonymous table objects // http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes @@ -391,6 +396,7 @@ #if DCHECK_IS_ON() void LayoutObject::AssertClearedPaintInvalidationFlags() const { + CheckIsNotDestroyed(); if (!PaintInvalidationStateIsDirty() || ChildPrePaintBlockedByDisplayLock()) return; // NG text objects are exempt, as pre-paint walking doesn't visit those with @@ -408,6 +414,7 @@ DISABLE_CFI_PERF void LayoutObject::AddChild(LayoutObject* new_child, LayoutObject* before_child) { + CheckIsNotDestroyed(); DCHECK(IsAllowedToModifyLayoutTreeStructure(GetDocument())); LayoutObjectChildList* children = VirtualChildren(); @@ -440,6 +447,7 @@ } void LayoutObject::RemoveChild(LayoutObject* old_child) { + CheckIsNotDestroyed(); DCHECK(IsAllowedToModifyLayoutTreeStructure(GetDocument())); LayoutObjectChildList* children = VirtualChildren(); @@ -451,6 +459,7 @@ } void LayoutObject::NotifyPriorityScrollAnchorStatusChanged() { + CheckIsNotDestroyed(); if (!Parent()) return; for (auto* layer = Parent()->EnclosingLayer(); layer; @@ -464,6 +473,7 @@ } void LayoutObject::RegisterSubtreeChangeListenerOnDescendants(bool value) { + CheckIsNotDestroyed(); // If we're set to the same value then we're done as that means it's // set down the tree that way already. if (bitfields_.SubtreeChangeListenerRegistered() == value) @@ -476,6 +486,7 @@ } void LayoutObject::NotifyAncestorsOfSubtreeChange() { + CheckIsNotDestroyed(); if (bitfields_.NotifiedOfSubtreeChange()) return; @@ -485,6 +496,7 @@ } void LayoutObject::NotifyOfSubtreeChange() { + CheckIsNotDestroyed(); if (!bitfields_.SubtreeChangeListenerRegistered()) return; if (bitfields_.NotifiedOfSubtreeChange()) @@ -500,6 +512,7 @@ } void LayoutObject::HandleSubtreeModifications() { + CheckIsNotDestroyed(); DCHECK(WasNotifiedOfSubtreeChange()); DCHECK(GetDocument().Lifecycle().StateAllowsLayoutTreeNotifications()); @@ -517,6 +530,7 @@ } LayoutObject* LayoutObject::NextInPreOrder() const { + CheckIsNotDestroyed(); if (LayoutObject* o = SlowFirstChild()) return o; @@ -524,6 +538,7 @@ } bool LayoutObject::HasClipRelatedProperty() const { + CheckIsNotDestroyed(); // This function detects a bunch of properties that can potentially affect // clip inheritance chain. However such generalization is practically useless // because these properties change clip inheritance in different way that @@ -550,6 +565,7 @@ } bool LayoutObject::IsRenderedLegendInternal() const { + CheckIsNotDestroyed(); DCHECK(IsBox()); DCHECK(IsRenderedLegendCandidate()); @@ -572,6 +588,7 @@ } LayoutObject* LayoutObject::NextInPreOrderAfterChildren() const { + CheckIsNotDestroyed(); LayoutObject* o = NextSibling(); if (!o) { o = Parent(); @@ -586,6 +603,7 @@ LayoutObject* LayoutObject::NextInPreOrder( const LayoutObject* stay_within) const { + CheckIsNotDestroyed(); if (LayoutObject* o = SlowFirstChild()) return o; @@ -594,6 +612,7 @@ LayoutObject* LayoutObject::PreviousInPostOrder( const LayoutObject* stay_within) const { + CheckIsNotDestroyed(); if (LayoutObject* o = SlowLastChild()) return o; @@ -602,6 +621,7 @@ LayoutObject* LayoutObject::NextInPreOrderAfterChildren( const LayoutObject* stay_within) const { + CheckIsNotDestroyed(); if (this == stay_within) return nullptr; @@ -617,6 +637,7 @@ LayoutObject* LayoutObject::PreviousInPostOrderBeforeChildren( const LayoutObject* stay_within) const { + CheckIsNotDestroyed(); if (this == stay_within) return nullptr; @@ -631,6 +652,7 @@ } LayoutObject* LayoutObject::PreviousInPreOrder() const { + CheckIsNotDestroyed(); if (LayoutObject* o = PreviousSibling()) { while (LayoutObject* last_child = o->SlowLastChild()) o = last_child; @@ -642,6 +664,7 @@ LayoutObject* LayoutObject::PreviousInPreOrder( const LayoutObject* stay_within) const { + CheckIsNotDestroyed(); if (this == stay_within) return nullptr; @@ -649,6 +672,7 @@ } LayoutObject* LayoutObject::LastLeafChild() const { + CheckIsNotDestroyed(); LayoutObject* r = SlowLastChild(); while (r) { LayoutObject* n = nullptr; @@ -683,6 +707,7 @@ } void LayoutObject::AddLayers(PaintLayer* parent_layer) { + CheckIsNotDestroyed(); if (!parent_layer) return; @@ -692,6 +717,7 @@ } void LayoutObject::RemoveLayers(PaintLayer* parent_layer) { + CheckIsNotDestroyed(); if (!parent_layer) return; @@ -705,6 +731,7 @@ } void LayoutObject::MoveLayers(PaintLayer* old_parent, PaintLayer* new_parent) { + CheckIsNotDestroyed(); if (!new_parent) return; @@ -724,6 +751,7 @@ PaintLayer* LayoutObject::FindNextLayer(PaintLayer* parent_layer, LayoutObject* start_point, bool check_parent) { + CheckIsNotDestroyed(); // Error check the parent layer passed in. If it's null, we can't find // anything. if (!parent_layer) @@ -764,6 +792,7 @@ } PaintLayer* LayoutObject::EnclosingLayer() const { + CheckIsNotDestroyed(); for (const LayoutObject* current = this; current; current = current->Parent()) { if (current->HasLayer()) @@ -775,6 +804,7 @@ } PaintLayer* LayoutObject::PaintingLayer() const { + CheckIsNotDestroyed(); auto FindContainer = [](const LayoutObject& object) -> const LayoutObject* { if (object.IsRenderedLegend()) return LayoutFieldset::FindLegendContainingBlock(ToLayoutBox(object)); @@ -805,6 +835,7 @@ } bool LayoutObject::IsFixedPositionObjectInPagedMedia() const { + CheckIsNotDestroyed(); if (StyleRef().GetPosition() != EPosition::kFixed) return false; LayoutView* view = View(); @@ -817,6 +848,7 @@ PhysicalRect LayoutObject::ScrollRectToVisible( const PhysicalRect& rect, mojom::blink::ScrollIntoViewParamsPtr params) { + CheckIsNotDestroyed(); LayoutBox* enclosing_box = EnclosingBox(); if (!enclosing_box) return rect; @@ -834,6 +866,7 @@ } LayoutBox* LayoutObject::EnclosingBox() const { + CheckIsNotDestroyed(); LayoutObject* curr = const_cast<LayoutObject*>(this); while (curr) { if (curr->IsBox()) @@ -846,6 +879,7 @@ } LayoutBlockFlow* LayoutObject::RootInlineFormattingContext() const { + CheckIsNotDestroyed(); for (LayoutObject* parent = Parent(); parent; parent = parent->Parent()) { if (auto* block_flow = DynamicTo<LayoutBlockFlow>(parent)) { // Skip |LayoutFlowThread| because it is skipped when finding the first @@ -859,6 +893,7 @@ } LayoutBlockFlow* LayoutObject::FragmentItemsContainer() const { + CheckIsNotDestroyed(); for (LayoutObject* parent = Parent(); parent; parent = parent->Parent()) { if (auto* block_flow = DynamicTo<LayoutBlockFlow>(parent)) return block_flow; @@ -867,6 +902,7 @@ } LayoutBlockFlow* LayoutObject::ContainingNGBlockFlow() const { + CheckIsNotDestroyed(); DCHECK(IsInline()); if (!RuntimeEnabledFeatures::LayoutNGEnabled()) return nullptr; @@ -882,6 +918,7 @@ } const NGPhysicalBoxFragment* LayoutObject::ContainingBlockFlowFragment() const { + CheckIsNotDestroyed(); DCHECK(IsInline() || IsText()); LayoutBlockFlow* const block_flow = ContainingNGBlockFlow(); if (!block_flow || !block_flow->ChildrenInline()) @@ -892,12 +929,14 @@ } bool LayoutObject::IsFirstInlineFragmentSafe() const { + CheckIsNotDestroyed(); DCHECK(IsInline()); LayoutBlockFlow* block_flow = ContainingNGBlockFlow(); return block_flow && !block_flow->NeedsLayout(); } LayoutBox* LayoutObject::EnclosingScrollableBox() const { + CheckIsNotDestroyed(); for (LayoutObject* ancestor = Parent(); ancestor; ancestor = ancestor->Parent()) { if (!ancestor->IsBox()) @@ -912,6 +951,7 @@ } LayoutFlowThread* LayoutObject::LocateFlowThreadContainingBlock() const { + CheckIsNotDestroyed(); DCHECK(IsInsideFlowThread()); // See if we have the thread cached because we're in the middle of layout. @@ -1037,6 +1077,7 @@ // |this|. When invalidating on inline blocks, floats, or OOF, caller need to // pay attention whether it should mark its inner context or outer. void LayoutObject::SetNeedsCollectInlines() { + CheckIsNotDestroyed(); if (!RuntimeEnabledFeatures::LayoutNGEnabled()) return; @@ -1055,6 +1096,7 @@ } void LayoutObject::SetChildNeedsCollectInlines() { + CheckIsNotDestroyed(); if (!RuntimeEnabledFeatures::LayoutNGEnabled()) return; @@ -1082,6 +1124,7 @@ void LayoutObject::MarkContainerChainForLayout(bool schedule_relayout, SubtreeLayoutScope* layouter) { + CheckIsNotDestroyed(); #if DCHECK_IS_ON() DCHECK(!IsSetNeedsLayoutForbidden()); #endif @@ -1176,6 +1219,7 @@ // static-position, simply insert the object up the NGLayoutResult chain with // an invalid static-position. void LayoutObject::MarkParentForOutOfFlowPositionedChange() { + CheckIsNotDestroyed(); #if DCHECK_IS_ON() DCHECK(!IsSetNeedsLayoutForbidden()); #endif @@ -1202,6 +1246,7 @@ #if DCHECK_IS_ON() void LayoutObject::CheckBlockPositionedObjectsNeedLayout() { + CheckIsNotDestroyed(); if (ChildLayoutBlockedByDisplayLock()) return; DCHECK(!NeedsLayout()); @@ -1214,6 +1259,7 @@ void LayoutObject::SetIntrinsicLogicalWidthsDirty( MarkingBehavior mark_parents) { + CheckIsNotDestroyed(); bitfields_.SetIntrinsicLogicalWidthsDirty(true); bitfields_.SetIntrinsicLogicalWidthsDependsOnPercentageBlockSize(true); bitfields_.SetIntrinsicLogicalWidthsChildDependsOnPercentageBlockSize(true); @@ -1223,15 +1269,18 @@ } void LayoutObject::ClearIntrinsicLogicalWidthsDirty() { + CheckIsNotDestroyed(); bitfields_.SetIntrinsicLogicalWidthsDirty(false); } bool LayoutObject::IsFontFallbackValid() const { + CheckIsNotDestroyed(); return StyleRef().GetFont().IsFallbackValid() && FirstLineStyle()->GetFont().IsFallbackValid(); } void LayoutObject::InvalidateSubtreeLayoutForFontUpdates() { + CheckIsNotDestroyed(); if (!RuntimeEnabledFeatures:: CSSReducedFontLoadingLayoutInvalidationsEnabled() || !IsFontFallbackValid()) { @@ -1245,6 +1294,7 @@ } void LayoutObject::InvalidateIntersectionObserverCachedRects() { + CheckIsNotDestroyed(); if (GetNode() && GetNode()->IsElementNode()) { if (auto* data = To<Element>(GetNode())->IntersectionObserverData()) { data->InvalidateCachedRects(); @@ -1269,6 +1319,7 @@ } inline void LayoutObject::InvalidateContainerIntrinsicLogicalWidths() { + CheckIsNotDestroyed(); // In order to avoid pathological behavior when inlines are deeply nested, we // do include them in the chain that we mark dirty (even though they're kind // of irrelevant). @@ -1293,6 +1344,7 @@ LayoutObject* LayoutObject::ContainerForAbsolutePosition( AncestorSkipInfo* skip_info) const { + CheckIsNotDestroyed(); return FindAncestorByPredicate(this, skip_info, [](LayoutObject* candidate) { return candidate->CanContainAbsolutePositionObjects(); }); @@ -1300,6 +1352,7 @@ LayoutObject* LayoutObject::ContainerForFixedPosition( AncestorSkipInfo* skip_info) const { + CheckIsNotDestroyed(); DCHECK(!IsText()); return FindAncestorByPredicate(this, skip_info, [](LayoutObject* candidate) { return candidate->CanContainFixedPositionObjects(); @@ -1308,22 +1361,26 @@ LayoutBlock* LayoutObject::ContainingBlockForAbsolutePosition( AncestorSkipInfo* skip_info) const { + CheckIsNotDestroyed(); auto* container = ContainerForAbsolutePosition(skip_info); return FindNonAnonymousContainingBlock(container, skip_info); } LayoutBlock* LayoutObject::ContainingBlockForFixedPosition( AncestorSkipInfo* skip_info) const { + CheckIsNotDestroyed(); auto* container = ContainerForFixedPosition(skip_info); return FindNonAnonymousContainingBlock(container, skip_info); } const LayoutBlock* LayoutObject::InclusiveContainingBlock() const { + CheckIsNotDestroyed(); auto* layout_block = DynamicTo<LayoutBlock>(this); return layout_block ? layout_block : ContainingBlock(); } LayoutBlock* LayoutObject::ContainingBlock(AncestorSkipInfo* skip_info) const { + CheckIsNotDestroyed(); if (!IsTextOrSVGChild()) { if (style_->GetPosition() == EPosition::kFixed) return ContainingBlockForFixedPosition(skip_info); @@ -1355,6 +1412,7 @@ } LayoutObject* LayoutObject::NonAnonymousAncestor() const { + CheckIsNotDestroyed(); LayoutObject* ancestor = Parent(); while (ancestor && ancestor->IsAnonymous()) ancestor = ancestor->Parent(); @@ -1380,6 +1438,7 @@ } bool LayoutObject::ComputeIsFixedContainer(const ComputedStyle* style) const { + CheckIsNotDestroyed(); if (!style) return false; bool is_document_element = IsDocumentElement(); @@ -1430,6 +1489,7 @@ bool LayoutObject::ComputeIsAbsoluteContainer( const ComputedStyle* style) const { + CheckIsNotDestroyed(); if (!style) return false; return style->CanContainAbsolutePositionObjects() || @@ -1438,6 +1498,7 @@ FloatRect LayoutObject::AbsoluteBoundingBoxFloatRect( MapCoordinatesFlags flags) const { + CheckIsNotDestroyed(); DCHECK(!(flags & kIgnoreTransforms)); Vector<FloatQuad> quads; AbsoluteQuads(quads, flags); @@ -1453,6 +1514,7 @@ } IntRect LayoutObject::AbsoluteBoundingBoxRect(MapCoordinatesFlags flags) const { + CheckIsNotDestroyed(); DCHECK(!(flags & kIgnoreTransforms)); Vector<FloatQuad> quads; AbsoluteQuads(quads, flags); @@ -1468,10 +1530,12 @@ } PhysicalRect LayoutObject::AbsoluteBoundingBoxRectHandlingEmptyInline() const { + CheckIsNotDestroyed(); return PhysicalRect::EnclosingRect(AbsoluteBoundingBoxFloatRect()); } PhysicalRect LayoutObject::AbsoluteBoundingBoxRectForScrollIntoView() const { + CheckIsNotDestroyed(); PhysicalRect rect = AbsoluteBoundingBoxRectHandlingEmptyInline(); const auto& style = StyleRef(); rect.ExpandEdges(LayoutUnit(style.ScrollMarginTop()), @@ -1482,6 +1546,7 @@ } void LayoutObject::AddAbsoluteRectForLayer(IntRect& result) { + CheckIsNotDestroyed(); if (HasLayer()) result.Unite(AbsoluteBoundingBoxRect()); for (LayoutObject* current = SlowFirstChild(); current; @@ -1490,6 +1555,7 @@ } IntRect LayoutObject::AbsoluteBoundingBoxRectIncludingDescendants() const { + CheckIsNotDestroyed(); IntRect result = AbsoluteBoundingBoxRect(); for (LayoutObject* current = SlowFirstChild(); current; current = current->NextSibling()) @@ -1497,10 +1563,13 @@ return result; } -void LayoutObject::Paint(const PaintInfo&) const {} +void LayoutObject::Paint(const PaintInfo&) const { + CheckIsNotDestroyed(); +} const LayoutBoxModelObject& LayoutObject::DirectlyCompositableContainer() const { + CheckIsNotDestroyed(); CHECK(IsRooted()); if (const LayoutBoxModelObject* container = @@ -1520,6 +1589,7 @@ const LayoutBoxModelObject* LayoutObject::EnclosingDirectlyCompositableContainer() const { + CheckIsNotDestroyed(); DCHECK(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()); LayoutBoxModelObject* container = nullptr; // FIXME: CompositingState is not necessarily up to date for many callers of @@ -1536,6 +1606,7 @@ } bool LayoutObject::RecalcLayoutOverflow() { + CheckIsNotDestroyed(); if (!ChildNeedsLayoutOverflowRecalc()) return false; ClearChildNeedsLayoutOverflowRecalc(); @@ -1549,6 +1620,7 @@ } void LayoutObject::RecalcVisualOverflow() { + CheckIsNotDestroyed(); for (LayoutObject* current = SlowFirstChild(); current; current = current->NextSibling()) { if (current->HasLayer() && @@ -1559,6 +1631,7 @@ } void LayoutObject::RecalcNormalFlowChildVisualOverflowIfNeeded() { + CheckIsNotDestroyed(); if (IsOutOfFlowPositioned() || (HasLayer() && ToLayoutBoxModelObject(this)->HasSelfPaintingLayer())) return; @@ -1566,6 +1639,7 @@ } bool LayoutObject::HasDistortingVisualEffects() const { + CheckIsNotDestroyed(); // TODO(szager): Check occlusion information propagated from out-of-process // parent frame. @@ -1606,6 +1680,7 @@ } bool LayoutObject::HasNonZeroEffectiveOpacity() const { + CheckIsNotDestroyed(); const FragmentData& fragment = EnclosingLayer()->GetLayoutObject().FirstFragment(); @@ -1627,6 +1702,7 @@ } String LayoutObject::DecoratedName() const { + CheckIsNotDestroyed(); StringBuilder name; name.Append(GetName()); @@ -1649,6 +1725,7 @@ } String LayoutObject::DebugName() const { + CheckIsNotDestroyed(); StringBuilder name; name.Append(DecoratedName()); @@ -1660,15 +1737,18 @@ } DOMNodeId LayoutObject::OwnerNodeId() const { + CheckIsNotDestroyed(); return GetNode() ? DOMNodeIds::IdForNode(GetNode()) : kInvalidDOMNodeId; } bool LayoutObject::IsPaintInvalidationContainer() const { + CheckIsNotDestroyed(); return HasLayer() && ToLayoutBoxModelObject(this)->Layer()->IsPaintInvalidationContainer(); } bool LayoutObject::CanBeCompositedForDirectReasons() const { + CheckIsNotDestroyed(); return HasLayer() && ToLayoutBoxModelObject(this) ->Layer() ->CanBeCompositedForDirectReasons(); @@ -1676,6 +1756,7 @@ void LayoutObject::InvalidateDisplayItemClients( PaintInvalidationReason reason) const { + CheckIsNotDestroyed(); // This default implementation invalidates only the object itself as a // DisplayItemClient. DCHECK(!GetSelectionDisplayItemClient()); @@ -1684,11 +1765,13 @@ bool LayoutObject::CompositedScrollsWithRespectTo( const LayoutBoxModelObject& paint_invalidation_container) const { + CheckIsNotDestroyed(); return paint_invalidation_container.UsesCompositedScrolling() && this != &paint_invalidation_container; } PhysicalRect LayoutObject::AbsoluteSelectionRect() const { + CheckIsNotDestroyed(); PhysicalRect selection_rect = LocalSelectionVisualRect(); if (!selection_rect.IsEmpty()) MapToVisualRectInAncestorSpace(View(), selection_rect); @@ -1702,16 +1785,19 @@ DISABLE_CFI_PERF void LayoutObject::InvalidatePaint( const PaintInvalidatorContext& context) const { + CheckIsNotDestroyed(); ObjectPaintInvalidatorWithContext(*this, context).InvalidatePaint(); } PhysicalRect LayoutObject::VisualRectInDocument(VisualRectFlags flags) const { + CheckIsNotDestroyed(); PhysicalRect rect = LocalVisualRect(); MapToVisualRectInAncestorSpace(View(), rect, flags); return rect; } PhysicalRect LayoutObject::LocalVisualRectIgnoringVisibility() const { + CheckIsNotDestroyed(); NOTREACHED(); return PhysicalRect(); } @@ -1721,6 +1807,7 @@ PhysicalRect& rect, VisualRectFlags visual_rect_flags, bool& intersects) const { + CheckIsNotDestroyed(); intersects = true; if (!(visual_rect_flags & kUseGeometryMapper) || !ancestor || !ancestor->FirstFragment().HasLocalBorderBoxProperties()) @@ -1760,6 +1847,7 @@ const LayoutBoxModelObject* ancestor, PhysicalRect& rect, VisualRectFlags visual_rect_flags) const { + CheckIsNotDestroyed(); bool intersects = true; if (MapToVisualRectInAncestorSpaceInternalFastPath( ancestor, rect, visual_rect_flags, intersects)) @@ -1779,6 +1867,7 @@ const LayoutBoxModelObject* ancestor, TransformState& transform_state, VisualRectFlags visual_rect_flags) const { + CheckIsNotDestroyed(); // For any layout object that doesn't override this method (the main example // is LayoutText), the rect is assumed to be in the parent's coordinate space, // except for container flip. @@ -1807,6 +1896,7 @@ const LayoutObject* LayoutObject::GetPropertyContainer( AncestorSkipInfo* skip_info, PropertyTreeStateOrAlias* container_properties) const { + CheckIsNotDestroyed(); const LayoutObject* property_container = this; while (!property_container->FirstFragment().HasLocalBorderBoxProperties()) { property_container = property_container->Container(skip_info); @@ -1827,6 +1917,7 @@ HitTestResult LayoutObject::HitTestForOcclusion( const PhysicalRect& hit_rect) const { + CheckIsNotDestroyed(); LocalFrame* frame = GetDocument().GetFrame(); DCHECK(!frame->View()->NeedsLayout()); HitTestRequest::HitTestRequestType hit_type = @@ -1839,7 +1930,9 @@ this, true); } -void LayoutObject::DirtyLinesFromChangedChild(LayoutObject*, MarkingBehavior) {} +void LayoutObject::DirtyLinesFromChangedChild(LayoutObject*, MarkingBehavior) { + CheckIsNotDestroyed(); +} std::ostream& operator<<(std::ostream& out, const LayoutObject& object) { String info; @@ -1862,15 +1955,18 @@ #if DCHECK_IS_ON() void LayoutObject::ShowTreeForThis() const { + CheckIsNotDestroyed(); if (GetNode()) ::showTree(GetNode()); } void LayoutObject::ShowLayoutTreeForThis() const { + CheckIsNotDestroyed(); showLayoutTree(this, nullptr); } void LayoutObject::ShowLineTreeForThis() const { + CheckIsNotDestroyed(); if (const LayoutBlock* cb = InclusiveContainingBlock()) { auto* child_block_flow = DynamicTo<LayoutBlockFlow>(cb); if (child_block_flow) { @@ -1881,6 +1977,7 @@ } void LayoutObject::ShowLayoutObject() const { + CheckIsNotDestroyed(); StringBuilder string_builder; DumpLayoutObject(string_builder, true, kShowTreeCharacterOffset); DLOG(INFO) << "\n" << string_builder.ToString().Utf8(); @@ -1889,6 +1986,7 @@ void LayoutObject::DumpLayoutObject(StringBuilder& string_builder, bool dump_address, unsigned show_tree_character_offset) const { + CheckIsNotDestroyed(); string_builder.Append(DecoratedName()); if (dump_address) @@ -1918,6 +2016,7 @@ const LayoutObject* marked_object2, const char* marked_label2, unsigned depth) const { + CheckIsNotDestroyed(); StringBuilder object_info; if (marked_object1 == this && marked_label1) object_info.Append(marked_label1); @@ -1943,6 +2042,7 @@ #endif // DCHECK_IS_ON() bool LayoutObject::IsSelected() const { + CheckIsNotDestroyed(); // Keep this fast and small, used in very hot functions to skip computing // selection when this is not selected. This function may be inlined in // link-optimized builds, but keeping fast and small helps running perf @@ -1955,12 +2055,14 @@ } bool LayoutObject::IsSelectable() const { + CheckIsNotDestroyed(); return !IsInert() && !(StyleRef().UserSelect() == EUserSelect::kNone && StyleRef().UserModify() == EUserModify::kReadOnly); } const ComputedStyle& LayoutObject::SlowEffectiveStyle( NGStyleVariant style_variant) const { + CheckIsNotDestroyed(); switch (style_variant) { case NGStyleVariant::kStandard: return StyleRef(); @@ -2004,6 +2106,7 @@ StyleDifference LayoutObject::AdjustStyleDifference( StyleDifference diff) const { + CheckIsNotDestroyed(); if (diff.TransformChanged() && IsSVG()) { // Skip a full layout for transforms at the html/svg boundary which do not // affect sizes inside SVG. @@ -2052,6 +2155,7 @@ void LayoutObject::SetPseudoElementStyle( scoped_refptr<const ComputedStyle> pseudo_style) { + CheckIsNotDestroyed(); DCHECK(pseudo_style->StyleType() == kPseudoIdBefore || pseudo_style->StyleType() == kPseudoIdAfter || pseudo_style->StyleType() == kPseudoIdMarker || @@ -2079,6 +2183,7 @@ void LayoutObject::MarkContainerChainForOverflowRecalcIfNeeded( bool mark_container_chain_layout_overflow_recalc) { + CheckIsNotDestroyed(); LayoutObject* object = this; do { // Cell and row need to propagate the flag to their containing section and @@ -2115,6 +2220,7 @@ void LayoutObject::SetNeedsOverflowRecalc( OverflowRecalcType overflow_recalc_type) { + CheckIsNotDestroyed(); bool mark_container_chain_layout_overflow_recalc = !SelfNeedsLayoutOverflowRecalc(); @@ -2140,6 +2246,7 @@ DISABLE_CFI_PERF void LayoutObject::SetStyle(scoped_refptr<const ComputedStyle> style, ApplyStyleChanges apply_changes) { + CheckIsNotDestroyed(); if (style_ == style) return; @@ -2212,11 +2319,11 @@ if (diff.NeedsRecomputeVisualOverflow()) { if (!IsLayoutNGObject() && !IsLayoutBlock() && !NeedsLayout()) { - // TODO(rego): This is still needed because RecalcVisualOverflow() does - // not actually compute the visual overflow for inline elements (legacy - // layout). However in LayoutNG RecalcInlineChildrenInkOverflow() is - // called and visual overflow is recomputed properly so we don't need this - // (see crbug.com/1043927). + // TODO(crbug.com/1128199): This is still needed because + // RecalcVisualOverflow() does not actually compute the visual overflow + // for inline elements (legacy layout). However in LayoutNG + // RecalcInlineChildrenInkOverflow() is called and visual overflow is + // recomputed properly so we don't need this (see crbug.com/1043927). SetNeedsLayoutAndIntrinsicWidthsRecalc( layout_invalidation_reason::kStyleChange); } else { @@ -2261,6 +2368,7 @@ void LayoutObject::UpdateImageObservers(const ComputedStyle* old_style, const ComputedStyle* new_style) { + CheckIsNotDestroyed(); DCHECK(old_style || new_style); DCHECK(!IsText()); @@ -2306,6 +2414,7 @@ void LayoutObject::UpdateFirstLineImageObservers( const ComputedStyle* new_style) { + CheckIsNotDestroyed(); bool has_new_first_line_style = new_style && new_style->HasPseudoElementStyle(kPseudoIdFirstLine) && BehavesLikeBlockContainer(); @@ -2361,6 +2470,7 @@ void LayoutObject::StyleWillChange(StyleDifference diff, const ComputedStyle& new_style) { + CheckIsNotDestroyed(); if (style_) { bool visibility_changed = style_->Visibility() != new_style.Visibility(); // If our z-index changes value or our visibility changes, @@ -2475,6 +2585,7 @@ } void LayoutObject::ClearBaseComputedStyle() { + CheckIsNotDestroyed(); auto* element = DynamicTo<Element>(GetNode()); if (!element) return; @@ -2496,6 +2607,7 @@ } void LayoutObject::SetScrollAnchorDisablingStyleChangedOnAncestor() { + CheckIsNotDestroyed(); // Walk up the parent chain and find the first scrolling block to disable // scroll anchoring on. LayoutObject* object = Parent(); @@ -2529,6 +2641,7 @@ void LayoutObject::StyleDidChange(StyleDifference diff, const ComputedStyle* old_style) { + CheckIsNotDestroyed(); if (style_->TransformStyle3D() == ETransformStyle3D::kPreserve3d) { if (style_->HasNonInitialBackdropFilter() || style_->HasBlendMode() || !style_->HasAutoClip() || style_->ClipPath() || @@ -2633,6 +2746,7 @@ void LayoutObject::ApplyPseudoElementStyleChanges( const ComputedStyle* old_style) { + CheckIsNotDestroyed(); ApplyFirstLineChanges(old_style); if ((old_style && old_style->HasPseudoElementStyle(kPseudoIdSelection)) || @@ -2641,6 +2755,7 @@ } void LayoutObject::ApplyFirstLineChanges(const ComputedStyle* old_style) { + CheckIsNotDestroyed(); bool has_old_first_line_style = old_style && old_style->HasPseudoElementStyle(kPseudoIdFirstLine); bool has_new_first_line_style = @@ -2681,6 +2796,7 @@ } void LayoutObject::PropagateStyleToAnonymousChildren() { + CheckIsNotDestroyed(); // FIXME: We could save this call when the change only affected non-inherited // properties. for (LayoutObject* child = SlowFirstChild(); child; @@ -2741,6 +2857,7 @@ } void LayoutObject::AddAsImageObserver(StyleImage* image) { + CheckIsNotDestroyed(); if (!image) return; #if DCHECK_IS_ON() @@ -2750,6 +2867,7 @@ } void LayoutObject::RemoveAsImageObserver(StyleImage* image) { + CheckIsNotDestroyed(); if (!image) return; #if DCHECK_IS_ON() @@ -2761,6 +2879,7 @@ void LayoutObject::UpdateFillImages(const FillLayer* old_layers, const FillLayer* new_layers) { + CheckIsNotDestroyed(); // Optimize the common case if (FillLayer::ImagesIdentical(old_layers, new_layers)) return; @@ -2778,6 +2897,7 @@ void LayoutObject::UpdateCursorImages(const CursorList* old_cursors, const CursorList* new_cursors) { + CheckIsNotDestroyed(); if (old_cursors && new_cursors && *old_cursors == *new_cursors) return; @@ -2792,6 +2912,7 @@ } void LayoutObject::UpdateImage(StyleImage* old_image, StyleImage* new_image) { + CheckIsNotDestroyed(); if (old_image != new_image) { // AddAsImageObserver first, to avoid removing all clients of an image. AddAsImageObserver(new_image); @@ -2801,6 +2922,7 @@ void LayoutObject::UpdateShapeImage(const ShapeValue* old_shape_value, const ShapeValue* new_shape_value) { + CheckIsNotDestroyed(); if (old_shape_value || new_shape_value) { UpdateImage(old_shape_value ? old_shape_value->GetImage() : nullptr, new_shape_value ? new_shape_value->GetImage() : nullptr); @@ -2809,6 +2931,7 @@ void LayoutObject::CheckCounterChanges(const ComputedStyle* old_style, const ComputedStyle* new_style) { + CheckIsNotDestroyed(); DCHECK(new_style); if (old_style) { if (old_style->CounterDirectivesEqual(*new_style)) @@ -2822,6 +2945,7 @@ } PhysicalRect LayoutObject::ViewRect() const { + CheckIsNotDestroyed(); return View()->ViewRect(); } @@ -2829,6 +2953,7 @@ const LayoutBoxModelObject* ancestor, const FloatPoint& container_point, MapCoordinatesFlags mode) const { + CheckIsNotDestroyed(); TransformState transform_state( TransformState::kUnapplyInverseTransformDirection, container_point); MapAncestorToLocal(ancestor, transform_state, mode); @@ -2841,6 +2966,7 @@ const LayoutBoxModelObject* ancestor, const FloatQuad& quad, MapCoordinatesFlags mode) const { + CheckIsNotDestroyed(); TransformState transform_state( TransformState::kUnapplyInverseTransformDirection, quad.BoundingBox().Center(), quad); @@ -2852,6 +2978,7 @@ void LayoutObject::MapLocalToAncestor(const LayoutBoxModelObject* ancestor, TransformState& transform_state, MapCoordinatesFlags mode) const { + CheckIsNotDestroyed(); if (ancestor == this) return; @@ -2919,6 +3046,7 @@ const LayoutObject* LayoutObject::PushMappingToContainer( const LayoutBoxModelObject* ancestor_to_stop_at, LayoutGeometryMap& geometry_map) const { + CheckIsNotDestroyed(); NOTREACHED(); return nullptr; } @@ -2926,6 +3054,7 @@ void LayoutObject::MapAncestorToLocal(const LayoutBoxModelObject* ancestor, TransformState& transform_state, MapCoordinatesFlags mode) const { + CheckIsNotDestroyed(); if (this == ancestor) return; @@ -2979,6 +3108,7 @@ bool LayoutObject::ShouldUseTransformFromContainer( const LayoutObject* container_object) const { + CheckIsNotDestroyed(); // hasTransform() indicates whether the object has transform, transform-style // or perspective. We just care about transform, so check the layer's // transform directly. @@ -2990,6 +3120,7 @@ const LayoutObject* container_object, const PhysicalOffset& offset_in_container, TransformationMatrix& transform) const { + CheckIsNotDestroyed(); transform.MakeIdentity(); PaintLayer* layer = HasLayer() ? ToLayoutBoxModelObject(this)->Layer() : nullptr; @@ -3025,6 +3156,7 @@ const FloatPoint& local_point, const LayoutBoxModelObject* ancestor, MapCoordinatesFlags mode) const { + CheckIsNotDestroyed(); TransformState transform_state(TransformState::kApplyTransformDirection, local_point); MapLocalToAncestor(ancestor, transform_state, mode); @@ -3038,6 +3170,7 @@ const LayoutBoxModelObject* ancestor, MapCoordinatesFlags mode, PhysicalRect& result) const { + CheckIsNotDestroyed(); if (!(mode & kUseGeometryMapperMode)) return false; // No other modes are supported. @@ -3083,6 +3216,7 @@ const PhysicalRect& rect, const LayoutBoxModelObject* ancestor, MapCoordinatesFlags mode) const { + CheckIsNotDestroyed(); PhysicalRect result; if (LocalToAncestorRectFastPath(rect, ancestor, mode, result)) return result; @@ -3095,6 +3229,7 @@ const FloatQuad& local_quad, const LayoutBoxModelObject* ancestor, MapCoordinatesFlags mode) const { + CheckIsNotDestroyed(); // Track the point at the center of the quad's bounding box. As // MapLocalToAncestor() calls OffsetFromContainer(), it will use that point // as the reference point to decide which column's transform to apply in @@ -3112,6 +3247,7 @@ const LayoutBoxModelObject* ancestor, const PhysicalOffset& pre_offset, const PhysicalOffset& post_offset) const { + CheckIsNotDestroyed(); for (wtf_size_t i = 0; i < rects.size(); ++i) { PhysicalRect& rect = rects[i]; rect.Move(pre_offset); @@ -3131,6 +3267,7 @@ TransformationMatrix LayoutObject::LocalToAncestorTransform( const LayoutBoxModelObject* ancestor, MapCoordinatesFlags mode) const { + CheckIsNotDestroyed(); DCHECK(!(mode & kIgnoreTransforms)); TransformState transform_state(TransformState::kApplyTransformDirection); MapLocalToAncestor(ancestor, transform_state, mode); @@ -3140,12 +3277,14 @@ PhysicalOffset LayoutObject::OffsetFromContainer( const LayoutObject* o, bool ignore_scroll_offset) const { + CheckIsNotDestroyed(); return OffsetFromContainerInternal(o, ignore_scroll_offset); } PhysicalOffset LayoutObject::OffsetFromContainerInternal( const LayoutObject* o, bool ignore_scroll_offset) const { + CheckIsNotDestroyed(); DCHECK_EQ(o, Container()); return o->HasNonVisibleOverflow() ? OffsetFromScrollableContainer(o, ignore_scroll_offset) @@ -3155,6 +3294,7 @@ PhysicalOffset LayoutObject::OffsetFromScrollableContainer( const LayoutObject* container, bool ignore_scroll_offset) const { + CheckIsNotDestroyed(); DCHECK(container->HasNonVisibleOverflow()); const LayoutBox* box = ToLayoutBox(container); if (!ignore_scroll_offset) @@ -3167,6 +3307,7 @@ PhysicalOffset LayoutObject::OffsetFromAncestor( const LayoutObject* ancestor_container) const { + CheckIsNotDestroyed(); if (ancestor_container == this) return PhysicalOffset(); @@ -3201,6 +3342,7 @@ const InlineBox*, int, LayoutUnit* extra_width_to_end_of_line) const { + CheckIsNotDestroyed(); if (extra_width_to_end_of_line) *extra_width_to_end_of_line = LayoutUnit(); @@ -3208,6 +3350,7 @@ } bool LayoutObject::IsRooted() const { + CheckIsNotDestroyed(); const LayoutObject* object = this; while (object->Parent() && !object->HasLayer()) object = object->Parent(); @@ -3227,6 +3370,7 @@ } LayoutObject* LayoutObject::Container(AncestorSkipInfo* skip_info) const { + CheckIsNotDestroyed(); // TODO(mstensho): Get rid of this. Nobody should call this method with those // flags already set. if (skip_info) @@ -3263,12 +3407,14 @@ } inline LayoutObject* LayoutObject::ParentCrossingFrames() const { + CheckIsNotDestroyed(); if (IsA<LayoutView>(this)) return GetFrame()->OwnerLayoutObject(); return Parent(); } inline void LayoutObject::ClearLayoutRootIfNeeded() const { + CheckIsNotDestroyed(); if (LocalFrameView* view = GetFrameView()) { if (!DocumentBeingDestroyed()) view->ClearLayoutSubtreeRoot(*this); @@ -3276,6 +3422,7 @@ } void LayoutObject::WillBeDestroyed() { + CheckIsNotDestroyed(); // Destroy any leftover anonymous children. LayoutObjectChildList* children = VirtualChildren(); if (children) @@ -3344,6 +3491,7 @@ DISABLE_CFI_PERF void LayoutObject::InsertedIntoTree() { + CheckIsNotDestroyed(); // FIXME: We should DCHECK(isRooted()) here but generated content makes some // out-of-order insertion. @@ -3407,6 +3555,7 @@ } void LayoutObject::WillBeRemovedFromTree() { + CheckIsNotDestroyed(); // FIXME: We should DCHECK(isRooted()) but we have some out-of-order removals // which would need to be fixed first. @@ -3448,11 +3597,13 @@ } void LayoutObject::SetNeedsPaintPropertyUpdate() { + CheckIsNotDestroyed(); SetNeedsPaintPropertyUpdatePreservingCachedRects(); InvalidateIntersectionObserverCachedRects(); } void LayoutObject::SetNeedsPaintPropertyUpdatePreservingCachedRects() { + CheckIsNotDestroyed(); if (bitfields_.NeedsPaintPropertyUpdate()) return; @@ -3472,6 +3623,7 @@ } void LayoutObject::SetAncestorsNeedPaintPropertyUpdateForMainThreadScrolling() { + CheckIsNotDestroyed(); LayoutObject* ancestor = ParentCrossingFrames(); while (ancestor) { ancestor->SetNeedsPaintPropertyUpdate(); @@ -3480,6 +3632,7 @@ } void LayoutObject::MaybeClearIsScrollAnchorObject() { + CheckIsNotDestroyed(); if (!bitfields_.IsScrollAnchorObject()) return; bitfields_.SetIsScrollAnchorObject( @@ -3487,6 +3640,7 @@ } void LayoutObject::RemoveFromLayoutFlowThread() { + CheckIsNotDestroyed(); if (!IsInsideFlowThread()) return; @@ -3510,6 +3664,7 @@ void LayoutObject::RemoveFromLayoutFlowThreadRecursive( LayoutFlowThread* layout_flow_thread) { + CheckIsNotDestroyed(); if (const LayoutObjectChildList* children = VirtualChildren()) { for (LayoutObject* child = children->FirstChild(); child; child = child->NextSibling()) { @@ -3528,6 +3683,7 @@ } void LayoutObject::DestroyAndCleanupAnonymousWrappers() { + CheckIsNotDestroyed(); // If the tree is destroyed, there is no need for a clean-up phase. if (DocumentBeingDestroyed()) { Destroy(); @@ -3579,6 +3735,7 @@ } void LayoutObject::Destroy() { + CheckIsNotDestroyed(); CHECK(g_allow_destroying_layout_object_in_finalizer || !ThreadState::Current()->InAtomicSweepingPause()); @@ -3590,25 +3747,30 @@ } void LayoutObject::DeleteThis() { + CheckIsNotDestroyed(); delete this; } PositionWithAffinity LayoutObject::PositionForPoint( const PhysicalOffset&) const { + CheckIsNotDestroyed(); return CreatePositionWithAffinity(CaretMinOffset()); } CompositingState LayoutObject::GetCompositingState() const { + CheckIsNotDestroyed(); return HasLayer() ? ToLayoutBoxModelObject(this)->Layer()->GetCompositingState() : kNotComposited; } bool LayoutObject::CanHaveAdditionalCompositingReasons() const { + CheckIsNotDestroyed(); return false; } CompositingReasons LayoutObject::AdditionalCompositingReasons() const { + CheckIsNotDestroyed(); return CompositingReason::kNone; } @@ -3616,6 +3778,7 @@ const HitTestLocation& hit_test_location, const PhysicalOffset& accumulated_offset, HitTestFilter hit_test_filter) { + CheckIsNotDestroyed(); bool inside = false; if (hit_test_filter != kHitTestSelf) { // First test the foreground layer (lines and inlines). @@ -3643,6 +3806,7 @@ } Node* LayoutObject::NodeForHitTest() const { + CheckIsNotDestroyed(); if (Node* node = GetNode()) return node; @@ -3663,6 +3827,7 @@ void LayoutObject::UpdateHitTestResult(HitTestResult& result, const PhysicalOffset& point) const { + CheckIsNotDestroyed(); if (result.InnerNode()) return; @@ -3674,10 +3839,12 @@ const HitTestLocation&, const PhysicalOffset&, HitTestAction) { + CheckIsNotDestroyed(); return false; } void LayoutObject::ScheduleRelayout() { + CheckIsNotDestroyed(); if (auto* layout_view = DynamicTo<LayoutView>(this)) { if (LocalFrameView* view = layout_view->GetFrameView()) view->ScheduleRelayout(); @@ -3692,11 +3859,13 @@ } void LayoutObject::ForceLayout() { + CheckIsNotDestroyed(); SetSelfNeedsLayoutForAvailableSpace(true); UpdateLayout(); } const ComputedStyle* LayoutObject::FirstLineStyleWithoutFallback() const { + CheckIsNotDestroyed(); DCHECK(GetDocument().GetStyleEngine().UsesFirstLineRules()); // Normal markers don't use ::first-line styles in Chromium, so be consistent @@ -3756,6 +3925,7 @@ const ComputedStyle* LayoutObject::GetCachedPseudoElementStyle( PseudoId pseudo) const { + CheckIsNotDestroyed(); DCHECK_NE(pseudo, kPseudoIdBefore); DCHECK_NE(pseudo, kPseudoIdAfter); if (!GetNode()) @@ -3772,6 +3942,7 @@ scoped_refptr<ComputedStyle> LayoutObject::GetUncachedPseudoElementStyle( const PseudoElementStyleRequest& request, const ComputedStyle* parent_style) const { + CheckIsNotDestroyed(); DCHECK_NE(request.pseudo_id, kPseudoIdBefore); DCHECK_NE(request.pseudo_id, kPseudoIdAfter); if (!GetNode()) @@ -3787,6 +3958,7 @@ } void LayoutObject::AddAnnotatedRegions(Vector<AnnotatedRegionValue>& regions) { + CheckIsNotDestroyed(); // Convert the style regions to absolute coordinates. if (StyleRef().Visibility() != EVisibility::kVisible || !IsBox()) return; @@ -3806,6 +3978,7 @@ } bool LayoutObject::WillRenderImage() { + CheckIsNotDestroyed(); // Without visibility we won't render (and therefore don't care about // animation). if (StyleRef().Visibility() != EVisibility::kVisible) @@ -3826,6 +3999,7 @@ bool LayoutObject::GetImageAnimationPolicy( web_pref::ImageAnimationPolicy& policy) { + CheckIsNotDestroyed(); if (!GetDocument().GetSettings()) return false; policy = GetDocument().GetSettings()->GetImageAnimationPolicy(); @@ -3833,22 +4007,26 @@ } bool LayoutObject::IsInsideListMarker() const { + CheckIsNotDestroyed(); return (IsListMarkerForNormalContent() && ToLayoutListMarker(this)->IsInside()) || IsInsideListMarkerForCustomContent(); } bool LayoutObject::IsOutsideListMarker() const { + CheckIsNotDestroyed(); return (IsListMarkerForNormalContent() && !ToLayoutListMarker(this)->IsInside()) || IsOutsideListMarkerForCustomContent(); } int LayoutObject::CaretMinOffset() const { + CheckIsNotDestroyed(); return 0; } int LayoutObject::CaretMaxOffset() const { + CheckIsNotDestroyed(); if (IsAtomicInlineLevel()) return GetNode() ? std::max(1U, GetNode()->CountChildren()) : 1; if (IsHR()) @@ -3857,6 +4035,7 @@ } bool LayoutObject::IsInert() const { + CheckIsNotDestroyed(); const LayoutObject* layout_object = this; while (!layout_object->GetNode()) layout_object = layout_object->Parent(); @@ -3865,6 +4044,7 @@ void LayoutObject::ImageChanged(ImageResourceContent* image, CanDeferInvalidation defer) { + CheckIsNotDestroyed(); DCHECK(node_); // Image change notifications should not be received during paint because @@ -3877,6 +4057,7 @@ } void LayoutObject::ImageNotifyFinished(ImageResourceContent* image) { + CheckIsNotDestroyed(); if (AXObjectCache* cache = GetDocument().ExistingAXObjectCache()) cache->ImageLoaded(this); @@ -3887,6 +4068,7 @@ } Element* LayoutObject::OffsetParent(const Element* base) const { + CheckIsNotDestroyed(); if (IsDocumentElement() || IsBody()) return nullptr; @@ -3936,6 +4118,7 @@ } void LayoutObject::NotifyImageFullyRemoved(ImageResourceContent* image) { + CheckIsNotDestroyed(); if (LocalDOMWindow* window = GetDocument().domWindow()) ImageElementTiming::From(*window).NotifyImageRemoved(this, image); if (LocalFrameView* frame_view = GetFrameView()) @@ -3945,6 +4128,7 @@ PositionWithAffinity LayoutObject::CreatePositionWithAffinity( int offset, TextAffinity affinity) const { + CheckIsNotDestroyed(); // If this is a non-anonymous layoutObject in an editable area, then it's // simple. if (Node* node = NonPseudoNode()) { @@ -4007,11 +4191,13 @@ PositionWithAffinity LayoutObject::CreatePositionWithAffinity( int offset) const { + CheckIsNotDestroyed(); return CreatePositionWithAffinity(offset, TextAffinity::kDownstream); } PositionWithAffinity LayoutObject::CreatePositionWithAffinity( const Position& position) const { + CheckIsNotDestroyed(); if (position.IsNotNull()) return PositionWithAffinity(position); @@ -4021,10 +4207,12 @@ CursorDirective LayoutObject::GetCursor(const PhysicalOffset&, ui::Cursor&) const { + CheckIsNotDestroyed(); return kSetCursorBasedOnStyle; } bool LayoutObject::CanUpdateSelectionOnRootLineBoxes() const { + CheckIsNotDestroyed(); if (NeedsLayout()) return false; @@ -4033,6 +4221,7 @@ } void LayoutObject::SetNeedsBoundariesUpdate() { + CheckIsNotDestroyed(); if (IsSVGChild()) { // The boundaries affect mask clip. auto* resources = SVGResourcesCache::CachedResourcesForLayoutObject(*this); @@ -4046,29 +4235,35 @@ } FloatRect LayoutObject::ObjectBoundingBox() const { + CheckIsNotDestroyed(); NOTREACHED(); return FloatRect(); } FloatRect LayoutObject::StrokeBoundingBox() const { + CheckIsNotDestroyed(); NOTREACHED(); return FloatRect(); } FloatRect LayoutObject::VisualRectInLocalSVGCoordinates() const { + CheckIsNotDestroyed(); NOTREACHED(); return FloatRect(); } AffineTransform LayoutObject::LocalSVGTransform() const { + CheckIsNotDestroyed(); return AffineTransform(); } bool LayoutObject::IsRelayoutBoundary() const { + CheckIsNotDestroyed(); return ObjectIsRelayoutBoundary(this); } inline void LayoutObject::SetShouldCheckGeometryForPaintInvalidation() { + CheckIsNotDestroyed(); DCHECK(ShouldCheckForPaintInvalidation()); bitfields_.SetShouldCheckGeometryForPaintInvalidation(true); for (auto* ancestor = ParentCrossingFrames(); @@ -4081,12 +4276,14 @@ } void LayoutObject::SetShouldInvalidateSelection() { + CheckIsNotDestroyed(); bitfields_.SetShouldInvalidateSelection(true); SetShouldCheckForPaintInvalidation(); } void LayoutObject::SetShouldDoFullPaintInvalidation( PaintInvalidationReason reason) { + CheckIsNotDestroyed(); SetShouldDoFullPaintInvalidationWithoutGeometryChange(reason); SetShouldCheckGeometryForPaintInvalidation(); } @@ -4110,6 +4307,7 @@ void LayoutObject::SetShouldDoFullPaintInvalidationWithoutGeometryChange( PaintInvalidationReason reason) { + CheckIsNotDestroyed(); // Only full invalidation reasons are allowed. DCHECK(IsFullPaintInvalidationReason(reason)); if (ShouldDoFullPaintInvalidation()) @@ -4125,11 +4323,13 @@ } void LayoutObject::SetShouldCheckForPaintInvalidation() { + CheckIsNotDestroyed(); SetShouldCheckForPaintInvalidationWithoutGeometryChange(); SetShouldCheckGeometryForPaintInvalidation(); } void LayoutObject::SetShouldCheckForPaintInvalidationWithoutGeometryChange() { + CheckIsNotDestroyed(); if (ShouldCheckForPaintInvalidation()) return; GetFrameView()->ScheduleVisualUpdateForPaintInvalidationIfNeeded(); @@ -4143,6 +4343,7 @@ } void LayoutObject::SetSubtreeShouldCheckForPaintInvalidation() { + CheckIsNotDestroyed(); if (SubtreeShouldCheckForPaintInvalidation()) { DCHECK(ShouldCheckForPaintInvalidation()); return; @@ -4152,6 +4353,7 @@ } void LayoutObject::SetMayNeedPaintInvalidationAnimatedBackgroundImage() { + CheckIsNotDestroyed(); if (MayNeedPaintInvalidationAnimatedBackgroundImage()) return; bitfields_.SetMayNeedPaintInvalidationAnimatedBackgroundImage(true); @@ -4159,6 +4361,7 @@ } void LayoutObject::SetShouldDelayFullPaintInvalidation() { + CheckIsNotDestroyed(); // Should have already set a full paint invalidation reason. DCHECK(IsFullPaintInvalidationReason(full_paint_invalidation_reason_)); @@ -4175,6 +4378,7 @@ } void LayoutObject::ClearPaintInvalidationFlags() { + CheckIsNotDestroyed(); // PaintInvalidationStateIsDirty should be kept in sync with the // booleans that are cleared below. #if DCHECK_IS_ON() @@ -4196,6 +4400,7 @@ #if DCHECK_IS_ON() bool LayoutObject::PaintInvalidationStateIsDirty() const { + CheckIsNotDestroyed(); return BackgroundNeedsFullPaintInvalidation() || ShouldCheckForPaintInvalidation() || ShouldInvalidateSelection() || ShouldCheckGeometryForPaintInvalidation() || @@ -4208,6 +4413,7 @@ #endif void LayoutObject::EnsureIsReadyForPaintInvalidation() { + CheckIsNotDestroyed(); DCHECK(!NeedsLayout() || ChildLayoutBlockedByDisplayLock()); // Force full paint invalidation if the outline may be affected by descendants @@ -4222,6 +4428,7 @@ } void LayoutObject::ClearPaintFlags() { + CheckIsNotDestroyed(); DCHECK_EQ(GetDocument().Lifecycle().GetState(), DocumentLifecycle::kInPrePaint); ClearPaintInvalidationFlags(); @@ -4241,12 +4448,14 @@ void LayoutObject::SetSubtreeShouldDoFullPaintInvalidation( PaintInvalidationReason reason) { + CheckIsNotDestroyed(); SetShouldDoFullPaintInvalidation(reason); bitfields_.SetSubtreeShouldDoFullPaintInvalidation(true); } void LayoutObject::SetIsBackgroundAttachmentFixedObject( bool is_background_attachment_fixed_object) { + CheckIsNotDestroyed(); DCHECK(GetFrameView()); if (bitfields_.IsBackgroundAttachmentFixedObject() == is_background_attachment_fixed_object) @@ -4260,10 +4469,12 @@ } PhysicalRect LayoutObject::DebugRect() const { + CheckIsNotDestroyed(); return PhysicalRect(); } void LayoutObject::InvalidateSelectedChildrenOnStyleChange() { + CheckIsNotDestroyed(); // LayoutSelection::Commit() propagates the state up the containing node // chain to // tell if a block contains selected nodes or not. If this layout object is @@ -4290,6 +4501,7 @@ } void LayoutObject::MarkEffectiveAllowedTouchActionChanged() { + CheckIsNotDestroyed(); bitfields_.SetEffectiveAllowedTouchActionChanged(true); // If we're locked, mark our descendants as needing this change. This is used // a signal to ensure we mark the element as needing effective allowed @@ -4364,6 +4576,7 @@ } bool LayoutObject::CanBeSelectionLeaf() const { + CheckIsNotDestroyed(); if (SlowFirstChild() || StyleRef().Visibility() != EVisibility::kVisible || DisplayLockUtilities::NearestLockedExclusiveAncestor(*this)) { return false; @@ -4372,6 +4585,7 @@ } void LayoutObject::InvalidateClipPathCache() { + CheckIsNotDestroyed(); SetNeedsPaintPropertyUpdate(); for (auto* fragment = &fragment_; fragment; fragment = fragment->NextFragment()) @@ -4381,6 +4595,7 @@ Vector<PhysicalRect> LayoutObject::OutlineRects( const PhysicalOffset& additional_offset, NGOutlineType outline_type) const { + CheckIsNotDestroyed(); Vector<PhysicalRect> outline_rects; AddOutlineRects(outline_rects, additional_offset, outline_type); return outline_rects; @@ -4389,6 +4604,7 @@ void LayoutObject::SetModifiedStyleOutsideStyleRecalc( scoped_refptr<const ComputedStyle> style, ApplyStyleChanges apply_changes) { + CheckIsNotDestroyed(); SetStyle(style, apply_changes); if (IsAnonymous() || !GetNode() || !GetNode()->IsElementNode()) return; @@ -4399,6 +4615,7 @@ LayoutUnit position, LayoutUnit width, const LayoutBox* box_for_flipping) const { + CheckIsNotDestroyed(); DCHECK(!IsBox()); DCHECK(HasFlippedBlocksWritingMode()); DCHECK(!box_for_flipping || box_for_flipping == ContainingBlock()); @@ -4410,6 +4627,7 @@ } bool LayoutObject::SelfPaintingLayerNeedsVisualOverflowRecalc() const { + CheckIsNotDestroyed(); if (HasLayer()) { auto* box_model_object = ToLayoutBoxModelObject(this); if (box_model_object->HasSelfPaintingLayer()) @@ -4419,6 +4637,7 @@ } void LayoutObject::MarkSelfPaintingLayerForVisualOverflowRecalc() { + CheckIsNotDestroyed(); if (HasLayer()) { auto* box_model_object = ToLayoutBoxModelObject(this); if (box_model_object->HasSelfPaintingLayer())
diff --git a/third_party/blink/renderer/core/layout/layout_object.h b/third_party/blink/renderer/core/layout/layout_object.h index 4adf5ac..a796ef7 100644 --- a/third_party/blink/renderer/core/layout/layout_object.h +++ b/third_party/blink/renderer/core/layout/layout_object.h
@@ -285,7 +285,10 @@ bool HasNonZeroEffectiveOpacity() const; protected: - void EnsureIdForTesting() { fragment_.EnsureId(); } + void EnsureIdForTesting() { + CheckIsNotDestroyed(); + fragment_.EnsureId(); + } private: // DisplayItemClient methods. @@ -303,27 +306,42 @@ // End of DisplayItemClient methods. - LayoutObject* Parent() const { return parent_; } + LayoutObject* Parent() const { + CheckIsNotDestroyed(); + return parent_; + } bool IsDescendantOf(const LayoutObject*) const; - LayoutObject* PreviousSibling() const { return previous_; } - LayoutObject* NextSibling() const { return next_; } + LayoutObject* PreviousSibling() const { + CheckIsNotDestroyed(); + return previous_; + } + LayoutObject* NextSibling() const { + CheckIsNotDestroyed(); + return next_; + } DISABLE_CFI_PERF LayoutObject* SlowFirstChild() const { + CheckIsNotDestroyed(); if (const LayoutObjectChildList* children = VirtualChildren()) return children->FirstChild(); return nullptr; } LayoutObject* SlowLastChild() const { + CheckIsNotDestroyed(); if (const LayoutObjectChildList* children = VirtualChildren()) return children->LastChild(); return nullptr; } // See comment in the class description as to why there is no child. - virtual LayoutObjectChildList* VirtualChildren() { return nullptr; } + virtual LayoutObjectChildList* VirtualChildren() { + CheckIsNotDestroyed(); + return nullptr; + } virtual const LayoutObjectChildList* VirtualChildren() const { + CheckIsNotDestroyed(); return nullptr; } @@ -404,14 +422,21 @@ // Function to return our enclosing flow thread if we are contained inside // one. This function follows the containing block chain. LayoutFlowThread* FlowThreadContainingBlock() const { + CheckIsNotDestroyed(); if (!IsInsideFlowThread()) return nullptr; return LocateFlowThreadContainingBlock(); } #if DCHECK_IS_ON() - void SetHasAXObject(bool flag) { has_ax_object_ = flag; } - bool HasAXObject() const { return has_ax_object_; } + void SetHasAXObject(bool flag) { + CheckIsNotDestroyed(); + has_ax_object_ = flag; + } + bool HasAXObject() const { + CheckIsNotDestroyed(); + return has_ax_object_; + } // Helper class forbidding calls to setNeedsLayout() during its lifetime. class SetLayoutNeededForbiddenScope { @@ -427,12 +452,14 @@ }; void AssertLaidOut() const { + CheckIsNotDestroyed(); if (NeedsLayout() && !ChildLayoutBlockedByDisplayLock()) ShowLayoutTreeForThis(); SECURITY_DCHECK(!NeedsLayout() || ChildLayoutBlockedByDisplayLock()); } void AssertSubtreeIsLaidOut() const { + CheckIsNotDestroyed(); for (const LayoutObject* layout_object = this; layout_object; layout_object = layout_object->ChildLayoutBlockedByDisplayLock() ? layout_object->NextInPreOrderAfterChildren() @@ -444,6 +471,7 @@ void AssertClearedPaintInvalidationFlags() const; void AssertSubtreeClearedPaintInvalidationFlags() const { + CheckIsNotDestroyed(); for (const LayoutObject* layout_object = this; layout_object; layout_object = layout_object->ChildPrePaintBlockedByDisplayLock() ? layout_object->NextInPreOrderAfterChildren() @@ -457,9 +485,11 @@ // LayoutObject tree manipulation ////////////////////////////////////////// DISABLE_CFI_PERF virtual bool CanHaveChildren() const { + CheckIsNotDestroyed(); return VirtualChildren(); } virtual bool IsChildAllowed(LayoutObject*, const ComputedStyle&) const { + CheckIsNotDestroyed(); return true; } @@ -498,52 +528,69 @@ virtual void AddChildIgnoringContinuation( LayoutObject* new_child, LayoutObject* before_child = nullptr) { + CheckIsNotDestroyed(); return AddChild(new_child, before_child); } virtual void RemoveChild(LayoutObject*); - virtual bool CreatesAnonymousWrapper() const { return false; } + virtual bool CreatesAnonymousWrapper() const { + CheckIsNotDestroyed(); + return false; + } ////////////////////////////////////////// - UniqueObjectId UniqueId() const { return fragment_.UniqueId(); } + UniqueObjectId UniqueId() const { + CheckIsNotDestroyed(); + return fragment_.UniqueId(); + } inline bool ShouldApplyPaintContainment(const ComputedStyle& style) const { + CheckIsNotDestroyed(); return style.ContainsPaint() && (!IsInline() || IsAtomicInlineLevel()) && !IsRubyText() && (!IsTablePart() || IsLayoutBlockFlow()); } inline bool ShouldApplyPaintContainment() const { + CheckIsNotDestroyed(); return ShouldApplyPaintContainment(StyleRef()); } inline bool ShouldApplyLayoutContainment(const ComputedStyle& style) const { + CheckIsNotDestroyed(); return style.ContainsLayout() && (!IsInline() || IsAtomicInlineLevel()) && !IsRubyText() && (!IsTablePart() || IsLayoutBlockFlow()); } inline bool ShouldApplyLayoutContainment() const { + CheckIsNotDestroyed(); return ShouldApplyLayoutContainment(StyleRef()); } inline bool ShouldApplySizeContainment() const { + CheckIsNotDestroyed(); return StyleRef().ContainsSize() && (!IsInline() || IsAtomicInlineLevel()) && !IsRubyText() && (!IsTablePart() || IsTableCaption()) && !IsTable(); } inline bool ShouldApplyStyleContainment() const { + CheckIsNotDestroyed(); return StyleRef().ContainsStyle(); } inline bool ShouldApplyContentContainment() const { + CheckIsNotDestroyed(); return ShouldApplyPaintContainment() && ShouldApplyLayoutContainment(); } inline bool ShouldApplyStrictContainment() const { + CheckIsNotDestroyed(); return ShouldApplyPaintContainment() && ShouldApplyLayoutContainment() && ShouldApplySizeContainment(); } inline bool IsStackingContext() const { + CheckIsNotDestroyed(); return IsStackingContext(StyleRef()); } inline bool IsStackingContext(const ComputedStyle& style) const { + CheckIsNotDestroyed(); // This is an inlined version of the following: // `IsStackingContextWithoutContainment() || // ShouldApplyLayoutContainment() || @@ -556,8 +603,12 @@ (!IsTablePart() || IsLayoutBlockFlow())); } - inline bool IsStacked() const { return IsStacked(StyleRef()); } + inline bool IsStacked() const { + CheckIsNotDestroyed(); + return IsStacked(StyleRef()); + } inline bool IsStacked(const ComputedStyle& style) const { + CheckIsNotDestroyed(); return style.GetPosition() != EPosition::kStatic || IsStackingContext(style); } @@ -567,9 +618,16 @@ private: ////////////////////////////////////////// // Helper functions. Dangerous to use! - void SetPreviousSibling(LayoutObject* previous) { previous_ = previous; } - void SetNextSibling(LayoutObject* next) { next_ = next; } + void SetPreviousSibling(LayoutObject* previous) { + CheckIsNotDestroyed(); + previous_ = previous; + } + void SetNextSibling(LayoutObject* next) { + CheckIsNotDestroyed(); + next_ = next; + } void SetParent(LayoutObject* parent) { + CheckIsNotDestroyed(); parent_ = parent; // Only update if our flow thread state is different from our new parent and @@ -584,8 +642,12 @@ ////////////////////////////////////////// private: #if DCHECK_IS_ON() - bool IsSetNeedsLayoutForbidden() const { return set_needs_layout_forbidden_; } + bool IsSetNeedsLayoutForbidden() const { + CheckIsNotDestroyed(); + return set_needs_layout_forbidden_; + } void SetNeedsLayoutIsForbidden(bool flag) { + CheckIsNotDestroyed(); set_needs_layout_forbidden_ = flag; } #endif @@ -642,149 +704,318 @@ void operator delete(void*); bool IsPseudoElement() const { + CheckIsNotDestroyed(); return GetNode() && GetNode()->IsPseudoElement(); } - virtual bool IsBoxModelObject() const { return false; } - bool IsBR() const { return IsOfType(kLayoutObjectBr); } - bool IsCanvas() const { return IsOfType(kLayoutObjectCanvas); } - bool IsCounter() const { return IsOfType(kLayoutObjectCounter); } - bool IsDetailsMarker() const { return IsOfType(kLayoutObjectDetailsMarker); } + virtual bool IsBoxModelObject() const { + CheckIsNotDestroyed(); + return false; + } + bool IsBR() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectBr); + } + bool IsCanvas() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectCanvas); + } + bool IsCounter() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectCounter); + } + bool IsDetailsMarker() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectDetailsMarker); + } bool IsEmbeddedObject() const { + CheckIsNotDestroyed(); return IsOfType(kLayoutObjectEmbeddedObject); } - bool IsFieldset() const { return IsOfType(kLayoutObjectFieldset); } - bool IsLayoutNGFieldset() const { return IsOfType(kLayoutObjectNGFieldset); } + bool IsFieldset() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectFieldset); + } + bool IsLayoutNGFieldset() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectNGFieldset); + } bool IsFieldsetIncludingNG() const { + CheckIsNotDestroyed(); return IsFieldset() || IsLayoutNGFieldset(); } bool IsFileUploadControl() const { + CheckIsNotDestroyed(); return IsOfType(kLayoutObjectFileUploadControl); } - bool IsFrame() const { return IsOfType(kLayoutObjectFrame); } - bool IsFrameSet() const { return IsOfType(kLayoutObjectFrameSet); } + bool IsFrame() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectFrame); + } + bool IsFrameSet() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectFrameSet); + } bool IsInsideListMarkerForCustomContent() const { + CheckIsNotDestroyed(); return IsOfType(kLayoutObjectInsideListMarker); } bool IsLayoutNGBlockFlow() const { + CheckIsNotDestroyed(); return IsOfType(kLayoutObjectNGBlockFlow); } bool IsLayoutNGFlexibleBox() const { + CheckIsNotDestroyed(); return IsOfType(kLayoutObjectNGFlexibleBox); } - bool IsLayoutNGGrid() const { return IsOfType(kLayoutObjectNGGrid); } - bool IsLayoutNGMixin() const { return IsOfType(kLayoutObjectNGMixin); } - bool IsLayoutNGListItem() const { return IsOfType(kLayoutObjectNGListItem); } + bool IsLayoutNGGrid() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectNGGrid); + } + bool IsLayoutNGMixin() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectNGMixin); + } + bool IsLayoutNGListItem() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectNGListItem); + } bool IsLayoutNGInsideListMarker() const { + CheckIsNotDestroyed(); return IsOfType(kLayoutObjectNGInsideListMarker); } bool IsLayoutNGOutsideListMarker() const { + CheckIsNotDestroyed(); return IsOfType(kLayoutObjectNGOutsideListMarker); } - bool IsLayoutNGProgress() const { return IsOfType(kLayoutObjectNGProgress); } - bool IsLayoutNGText() const { return IsOfType(kLayoutObjectNGText); } + bool IsLayoutNGProgress() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectNGProgress); + } + bool IsLayoutNGText() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectNGText); + } bool IsLayoutTableCol() const { + CheckIsNotDestroyed(); return IsOfType(kLayoutObjectLayoutTableCol); } bool IsLayoutNGTableCol() const { + CheckIsNotDestroyed(); return IsOfType(kLayoutObjectLayoutNGTableCol); } - bool IsListItem() const { return IsOfType(kLayoutObjectListItem); } + bool IsListItem() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectListItem); + } bool IsListMarkerForNormalContent() const { + CheckIsNotDestroyed(); return IsOfType(kLayoutObjectListMarker); } bool IsListMarkerImage() const { + CheckIsNotDestroyed(); return IsOfType(kLayoutObjectListMarkerImage); } - bool IsMathML() const { return IsOfType(kLayoutObjectMathML); } - bool IsMathMLRoot() const { return IsOfType(kLayoutObjectMathMLRoot); } - bool IsMedia() const { return IsOfType(kLayoutObjectMedia); } + bool IsMathML() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectMathML); + } + bool IsMathMLRoot() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectMathMLRoot); + } + bool IsMedia() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectMedia); + } bool IsOutsideListMarkerForCustomContent() const { + CheckIsNotDestroyed(); return IsOfType(kLayoutObjectOutsideListMarker); } - bool IsProgress() const { return IsOfType(kLayoutObjectProgress); } - bool IsQuote() const { return IsOfType(kLayoutObjectQuote); } + bool IsProgress() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectProgress); + } + bool IsQuote() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectQuote); + } bool IsButtonOrNGButton() const { + CheckIsNotDestroyed(); return IsOfType(kLayoutObjectLayoutButton) || IsOfType(kLayoutObjectNGButton); } - bool IsLayoutNGButton() const { return IsOfType(kLayoutObjectNGButton); } + bool IsLayoutNGButton() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectNGButton); + } bool IsLayoutNGCustom() const { + CheckIsNotDestroyed(); return IsOfType(kLayoutObjectLayoutNGCustom); } - bool IsLayoutGrid() const { return IsOfType(kLayoutObjectLayoutGrid); } - bool IsLayoutIFrame() const { return IsOfType(kLayoutObjectLayoutIFrame); } - bool IsLayoutImage() const { return IsOfType(kLayoutObjectLayoutImage); } + bool IsLayoutGrid() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectLayoutGrid); + } + bool IsLayoutIFrame() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectLayoutIFrame); + } + bool IsLayoutImage() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectLayoutImage); + } bool IsLayoutMultiColumnSet() const { + CheckIsNotDestroyed(); return IsOfType(kLayoutObjectLayoutMultiColumnSet); } bool IsLayoutMultiColumnSpannerPlaceholder() const { + CheckIsNotDestroyed(); return IsOfType(kLayoutObjectLayoutMultiColumnSpannerPlaceholder); } bool IsLayoutReplaced() const { + CheckIsNotDestroyed(); return IsOfType(kLayoutObjectLayoutReplaced); } bool IsLayoutCustomScrollbarPart() const { + CheckIsNotDestroyed(); return IsOfType(kLayoutObjectLayoutCustomScrollbarPart); } - bool IsLayoutView() const { return IsOfType(kLayoutObjectLayoutView); } - bool IsRuby() const { return IsOfType(kLayoutObjectRuby); } - bool IsRubyBase() const { return IsOfType(kLayoutObjectRubyBase); } - bool IsRubyRun() const { return IsOfType(kLayoutObjectRubyRun); } - bool IsRubyText() const { return IsOfType(kLayoutObjectRubyText); } - bool IsTable() const { return IsOfType(kLayoutObjectTable); } - bool IsTableCaption() const { return IsOfType(kLayoutObjectTableCaption); } - bool IsTableCell() const { return IsOfType(kLayoutObjectTableCell); } + bool IsLayoutView() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectLayoutView); + } + bool IsRuby() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectRuby); + } + bool IsRubyBase() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectRubyBase); + } + bool IsRubyRun() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectRubyRun); + } + bool IsRubyText() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectRubyText); + } + bool IsTable() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectTable); + } + bool IsTableCaption() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectTableCaption); + } + bool IsTableCell() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectTableCell); + } bool IsTableCellLegacy() const { + CheckIsNotDestroyed(); return IsOfType(kLayoutObjectTableCellLegacy); } - bool IsTableRow() const { return IsOfType(kLayoutObjectTableRow); } - bool IsTableSection() const { return IsOfType(kLayoutObjectTableSection); } - bool IsTextArea() const { return IsOfType(kLayoutObjectTextArea); } - bool IsTextControl() const { return IsOfType(kLayoutObjectTextControl); } - bool IsTextField() const { return IsOfType(kLayoutObjectTextField); } - bool IsVideo() const { return IsOfType(kLayoutObjectVideo); } - bool IsWidget() const { return IsOfType(kLayoutObjectWidget); } + bool IsTableRow() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectTableRow); + } + bool IsTableSection() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectTableSection); + } + bool IsTextArea() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectTextArea); + } + bool IsTextControl() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectTextControl); + } + bool IsTextField() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectTextField); + } + bool IsVideo() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectVideo); + } + bool IsWidget() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectWidget); + } - virtual bool IsImage() const { return false; } + virtual bool IsImage() const { + CheckIsNotDestroyed(); + return false; + } - virtual bool IsInlineBlockOrInlineTable() const { return false; } - virtual bool IsLayoutBlock() const { return false; } - virtual bool IsLayoutBlockFlow() const { return false; } - virtual bool IsLayoutFlowThread() const { return false; } - virtual bool IsLayoutInline() const { return false; } - virtual bool IsLayoutEmbeddedContent() const { return false; } - virtual bool IsLayoutNGObject() const { return false; } + virtual bool IsInlineBlockOrInlineTable() const { + CheckIsNotDestroyed(); + return false; + } + virtual bool IsLayoutBlock() const { + CheckIsNotDestroyed(); + return false; + } + virtual bool IsLayoutBlockFlow() const { + CheckIsNotDestroyed(); + return false; + } + virtual bool IsLayoutFlowThread() const { + CheckIsNotDestroyed(); + return false; + } + virtual bool IsLayoutInline() const { + CheckIsNotDestroyed(); + return false; + } + virtual bool IsLayoutEmbeddedContent() const { + CheckIsNotDestroyed(); + return false; + } + virtual bool IsLayoutNGObject() const { + CheckIsNotDestroyed(); + return false; + } bool IsDocumentElement() const { + CheckIsNotDestroyed(); return GetDocument().documentElement() == node_; } // isBody is called from LayoutBox::styleWillChange and is thus quite hot. bool IsBody() const { + CheckIsNotDestroyed(); return GetNode() && GetNode()->HasTagName(html_names::kBodyTag); } bool IsHR() const; bool IsTablePart() const { + CheckIsNotDestroyed(); return IsTableCell() || IsLayoutTableCol() || IsTableCaption() || IsTableRow() || IsTableSection(); } virtual const LayoutNGTableInterface* ToLayoutNGTableInterface() const { + CheckIsNotDestroyed(); DCHECK(false); return nullptr; } virtual const LayoutNGTableSectionInterface* ToLayoutNGTableSectionInterface() const { + CheckIsNotDestroyed(); DCHECK(false); return nullptr; } virtual const LayoutNGTableRowInterface* ToLayoutNGTableRowInterface() const { + CheckIsNotDestroyed(); DCHECK(false); return nullptr; } virtual const LayoutNGTableCellInterface* ToLayoutNGTableCellInterface() const { + CheckIsNotDestroyed(); DCHECK(false); return nullptr; } @@ -802,35 +1033,56 @@ // |NGTextType::kLayoutGenerated| for the other type of generated text. bool IsStyleGenerated() const; - bool HasCounterNodeMap() const { return bitfields_.HasCounterNodeMap(); } + bool HasCounterNodeMap() const { + CheckIsNotDestroyed(); + return bitfields_.HasCounterNodeMap(); + } void SetHasCounterNodeMap(bool has_counter_node_map) { + CheckIsNotDestroyed(); bitfields_.SetHasCounterNodeMap(has_counter_node_map); } - bool IsTruncated() const { return bitfields_.IsTruncated(); } + bool IsTruncated() const { + CheckIsNotDestroyed(); + return bitfields_.IsTruncated(); + } void SetIsTruncated(bool is_truncated) { + CheckIsNotDestroyed(); bitfields_.SetIsTruncated(is_truncated); } - bool EverHadLayout() const { return bitfields_.EverHadLayout(); } + bool EverHadLayout() const { + CheckIsNotDestroyed(); + return bitfields_.EverHadLayout(); + } - bool ChildrenInline() const { return bitfields_.ChildrenInline(); } - void SetChildrenInline(bool b) { bitfields_.SetChildrenInline(b); } + bool ChildrenInline() const { + CheckIsNotDestroyed(); + return bitfields_.ChildrenInline(); + } + void SetChildrenInline(bool b) { + CheckIsNotDestroyed(); + bitfields_.SetChildrenInline(b); + } bool AlwaysCreateLineBoxesForLayoutInline() const { + CheckIsNotDestroyed(); DCHECK(IsLayoutInline()); return bitfields_.AlwaysCreateLineBoxesForLayoutInline(); } void SetAlwaysCreateLineBoxesForLayoutInline(bool always_create_line_boxes) { + CheckIsNotDestroyed(); DCHECK(IsLayoutInline()); bitfields_.SetAlwaysCreateLineBoxesForLayoutInline( always_create_line_boxes); } bool AncestorLineBoxDirty() const { + CheckIsNotDestroyed(); return bitfields_.AncestorLineBoxDirty(); } void SetAncestorLineBoxDirty(bool value = true) { + CheckIsNotDestroyed(); bitfields_.SetAncestorLineBoxDirty(value); if (value) { SetNeedsLayoutAndFullPaintInvalidation( @@ -840,40 +1092,80 @@ void SetIsInsideFlowThreadIncludingDescendants(bool); - bool IsInsideFlowThread() const { return bitfields_.IsInsideFlowThread(); } + bool IsInsideFlowThread() const { + CheckIsNotDestroyed(); + return bitfields_.IsInsideFlowThread(); + } void SetIsInsideFlowThread(bool inside_flow_thread) { + CheckIsNotDestroyed(); bitfields_.SetIsInsideFlowThread(inside_flow_thread); } // FIXME: Until all SVG layoutObjects can be subclasses of // LayoutSVGModelObject we have to add SVG layoutObject methods to // LayoutObject with an NOTREACHED() default implementation. - bool IsSVG() const { return IsOfType(kLayoutObjectSVG); } - bool IsSVGRoot() const { return IsOfType(kLayoutObjectSVGRoot); } - bool IsSVGChild() const { return IsSVG() && !IsSVGRoot(); } - bool IsSVGContainer() const { return IsOfType(kLayoutObjectSVGContainer); } + bool IsSVG() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectSVG); + } + bool IsSVGRoot() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectSVGRoot); + } + bool IsSVGChild() const { + CheckIsNotDestroyed(); + return IsSVG() && !IsSVGRoot(); + } + bool IsSVGContainer() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectSVGContainer); + } bool IsSVGTransformableContainer() const { + CheckIsNotDestroyed(); return IsOfType(kLayoutObjectSVGTransformableContainer); } bool IsSVGViewportContainer() const { + CheckIsNotDestroyed(); return IsOfType(kLayoutObjectSVGViewportContainer); } bool IsSVGHiddenContainer() const { + CheckIsNotDestroyed(); return IsOfType(kLayoutObjectSVGHiddenContainer); } - bool IsSVGShape() const { return IsOfType(kLayoutObjectSVGShape); } - bool IsSVGText() const { return IsOfType(kLayoutObjectSVGText); } - bool IsSVGTextPath() const { return IsOfType(kLayoutObjectSVGTextPath); } - bool IsSVGInline() const { return IsOfType(kLayoutObjectSVGInline); } - bool IsSVGInlineText() const { return IsOfType(kLayoutObjectSVGInlineText); } - bool IsSVGImage() const { return IsOfType(kLayoutObjectSVGImage); } + bool IsSVGShape() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectSVGShape); + } + bool IsSVGText() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectSVGText); + } + bool IsSVGTextPath() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectSVGTextPath); + } + bool IsSVGInline() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectSVGInline); + } + bool IsSVGInlineText() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectSVGInlineText); + } + bool IsSVGImage() const { + CheckIsNotDestroyed(); + return IsOfType(kLayoutObjectSVGImage); + } bool IsSVGForeignObject() const { + CheckIsNotDestroyed(); return IsOfType(kLayoutObjectSVGForeignObject); } bool IsSVGResourceContainer() const { + CheckIsNotDestroyed(); return IsOfType(kLayoutObjectSVGResourceContainer); } bool IsSVGFilterPrimitive() const { + CheckIsNotDestroyed(); return IsOfType(kLayoutObjectSVGFilterPrimitive); } @@ -881,7 +1173,7 @@ // (see above). Unfortunately we don't have such a class yet, because it's not // possible for all layoutObjects to inherit from LayoutSVGObject -> // LayoutObject (some need LayoutBlock inheritance for instance) - virtual void SetNeedsTransformUpdate() {} + virtual void SetNeedsTransformUpdate() { CheckIsNotDestroyed(); } virtual void SetNeedsBoundariesUpdate(); // Per the spec, mix-blend-mode applies to all non-SVG elements, and SVG @@ -889,6 +1181,7 @@ // referencing elements. // https://www.w3.org/TR/compositing-1/#propdef-mix-blend-mode bool IsBlendingAllowed() const { + CheckIsNotDestroyed(); return !IsSVG() || IsSVGShape() || IsSVGImage() || IsSVGText() || IsSVGInline() || IsSVGRoot() || IsSVGForeignObject() || // Blending does not apply to non-renderable elements such as @@ -896,6 +1189,7 @@ (IsSVGContainer() && !IsSVGHiddenContainer()); } virtual bool HasNonIsolatedBlendingDescendants() const { + CheckIsNotDestroyed(); // This is only implemented for layout objects that containt SVG flow. // For HTML/CSS layout objects, use the PaintLayer version instead. DCHECK(IsSVG()); @@ -906,7 +1200,9 @@ kDescendantIsolationNeedsUpdate, }; virtual void DescendantIsolationRequirementsChanged( - DescendantIsolationState) {} + DescendantIsolationState) { + CheckIsNotDestroyed(); + } // Per SVG 1.1 objectBoundingBox ignores clipping, masking, filter effects, // opacity and stroke-width. @@ -939,13 +1235,18 @@ // this includes any viewport transforms and x/y offsets as well as // localSVGTransform. virtual AffineTransform LocalToSVGParentTransform() const { + CheckIsNotDestroyed(); return LocalSVGTransform(); } // End of SVG-specific methods. - bool IsAnonymous() const { return bitfields_.IsAnonymous(); } + bool IsAnonymous() const { + CheckIsNotDestroyed(); + return bitfields_.IsAnonymous(); + } bool IsAnonymousBlock() const { + CheckIsNotDestroyed(); // This function is kept in sync with anonymous block creation conditions in // LayoutBlock::createAnonymousBlock(). This includes creating an anonymous // LayoutBlock having a BLOCK or BOX display. Other classes such as @@ -960,52 +1261,95 @@ // If node has been split into continuations, it returns the first layout // object generated for the node. const LayoutObject* ContinuationRoot() const { + CheckIsNotDestroyed(); return GetNode() ? GetNode()->GetLayoutObject() : this; } bool IsElementContinuation() const { + CheckIsNotDestroyed(); return GetNode() && GetNode()->GetLayoutObject() != this; } bool IsInlineElementContinuation() const { + CheckIsNotDestroyed(); return IsElementContinuation() && IsInline(); } - virtual LayoutBoxModelObject* VirtualContinuation() const { return nullptr; } + virtual LayoutBoxModelObject* VirtualContinuation() const { + CheckIsNotDestroyed(); + return nullptr; + } - bool IsFloating() const { return bitfields_.Floating(); } + bool IsFloating() const { + CheckIsNotDestroyed(); + return bitfields_.Floating(); + } bool IsFloatingWithNonContainingBlockParent() const { + CheckIsNotDestroyed(); return IsFloating() && Parent() && !Parent()->IsLayoutBlockFlow(); } // absolute or fixed positioning bool IsOutOfFlowPositioned() const { + CheckIsNotDestroyed(); return bitfields_.IsOutOfFlowPositioned(); } // relative or sticky positioning - bool IsInFlowPositioned() const { return bitfields_.IsInFlowPositioned(); } - bool IsRelPositioned() const { return bitfields_.IsRelPositioned(); } - bool IsStickyPositioned() const { return bitfields_.IsStickyPositioned(); } + bool IsInFlowPositioned() const { + CheckIsNotDestroyed(); + return bitfields_.IsInFlowPositioned(); + } + bool IsRelPositioned() const { + CheckIsNotDestroyed(); + return bitfields_.IsRelPositioned(); + } + bool IsStickyPositioned() const { + CheckIsNotDestroyed(); + return bitfields_.IsStickyPositioned(); + } bool IsFixedPositioned() const { + CheckIsNotDestroyed(); return IsOutOfFlowPositioned() && StyleRef().GetPosition() == EPosition::kFixed; } bool IsAbsolutePositioned() const { + CheckIsNotDestroyed(); return IsOutOfFlowPositioned() && StyleRef().GetPosition() == EPosition::kAbsolute; } - bool IsPositioned() const { return bitfields_.IsPositioned(); } + bool IsPositioned() const { + CheckIsNotDestroyed(); + return bitfields_.IsPositioned(); + } - bool IsText() const { return bitfields_.IsText(); } - bool IsBox() const { return bitfields_.IsBox(); } - bool IsInline() const { return bitfields_.IsInline(); } // inline object + bool IsText() const { + CheckIsNotDestroyed(); + return bitfields_.IsText(); + } + bool IsBox() const { + CheckIsNotDestroyed(); + return bitfields_.IsBox(); + } + bool IsInline() const { + CheckIsNotDestroyed(); + return bitfields_.IsInline(); + } // inline object bool IsInLayoutNGInlineFormattingContext() const { + CheckIsNotDestroyed(); return bitfields_.IsInLayoutNGInlineFormattingContext(); } - bool ForceLegacyLayout() const { return bitfields_.ForceLegacyLayout(); } - bool IsAtomicInlineLevel() const { return bitfields_.IsAtomicInlineLevel(); } + bool ForceLegacyLayout() const { + CheckIsNotDestroyed(); + return bitfields_.ForceLegacyLayout(); + } + bool IsAtomicInlineLevel() const { + CheckIsNotDestroyed(); + return bitfields_.IsAtomicInlineLevel(); + } bool IsHorizontalWritingMode() const { + CheckIsNotDestroyed(); return bitfields_.HorizontalWritingMode(); } bool HasFlippedBlocksWritingMode() const { + CheckIsNotDestroyed(); return StyleRef().IsFlippedBlocksWritingMode(); } @@ -1018,6 +1362,7 @@ WARN_UNUSED_RESULT LayoutRect FlipForWritingMode(const PhysicalRect& r, const LayoutBox* box_for_flipping = nullptr) const { + CheckIsNotDestroyed(); if (LIKELY(!HasFlippedBlocksWritingMode())) return r.ToLayoutRect(); return {FlipForWritingModeInternal(r.X(), r.Width(), box_for_flipping), @@ -1026,6 +1371,7 @@ WARN_UNUSED_RESULT PhysicalRect FlipForWritingMode(const LayoutRect& r, const LayoutBox* box_for_flipping = nullptr) const { + CheckIsNotDestroyed(); if (LIKELY(!HasFlippedBlocksWritingMode())) return PhysicalRect(r); return {FlipForWritingModeInternal(r.X(), r.Width(), box_for_flipping), @@ -1034,6 +1380,7 @@ WARN_UNUSED_RESULT LayoutPoint FlipForWritingMode(const PhysicalOffset& p, const LayoutBox* box_for_flipping = nullptr) const { + CheckIsNotDestroyed(); if (LIKELY(!HasFlippedBlocksWritingMode())) return p.ToLayoutPoint(); return {FlipForWritingModeInternal(p.left, LayoutUnit(), box_for_flipping), @@ -1042,22 +1389,28 @@ WARN_UNUSED_RESULT PhysicalOffset FlipForWritingMode(const LayoutPoint& p, const LayoutBox* box_for_flipping = nullptr) const { + CheckIsNotDestroyed(); if (LIKELY(!HasFlippedBlocksWritingMode())) return PhysicalOffset(p); return {FlipForWritingModeInternal(p.X(), LayoutUnit(), box_for_flipping), p.Y()}; } - bool HasLayer() const { return bitfields_.HasLayer(); } + bool HasLayer() const { + CheckIsNotDestroyed(); + return bitfields_.HasLayer(); + } // This may be different from StyleRef().hasBoxDecorationBackground() because // some objects may have box decoration background other than from their own // style. bool HasBoxDecorationBackground() const { + CheckIsNotDestroyed(); return bitfields_.HasBoxDecorationBackground(); } bool NeedsLayout() const { + CheckIsNotDestroyed(); return bitfields_.SelfNeedsLayoutForStyle() || bitfields_.SelfNeedsLayoutForAvailableSpace() || bitfields_.NormalChildNeedsLayout() || @@ -1067,6 +1420,7 @@ } bool NeedsPositionedMovementLayoutOnly() const { + CheckIsNotDestroyed(); return bitfields_.NeedsPositionedMovementLayout() && !bitfields_.SelfNeedsLayoutForStyle() && !bitfields_.SelfNeedsLayoutForAvailableSpace() && @@ -1076,6 +1430,7 @@ } bool NeedsSimplifiedLayoutOnly() const { + CheckIsNotDestroyed(); // We don't need to check |SelfNeedsLayoutForAvailableSpace| as an // additional check will determine if we need to perform full layout based // on the available space. @@ -1087,32 +1442,46 @@ } bool SelfNeedsLayout() const { + CheckIsNotDestroyed(); return bitfields_.SelfNeedsLayoutForStyle() || bitfields_.SelfNeedsLayoutForAvailableSpace(); } bool SelfNeedsLayoutForStyle() const { + CheckIsNotDestroyed(); return bitfields_.SelfNeedsLayoutForStyle(); } bool SelfNeedsLayoutForAvailableSpace() const { + CheckIsNotDestroyed(); return bitfields_.SelfNeedsLayoutForAvailableSpace(); } bool NeedsPositionedMovementLayout() const { + CheckIsNotDestroyed(); return bitfields_.NeedsPositionedMovementLayout(); } - bool PosChildNeedsLayout() const { return bitfields_.PosChildNeedsLayout(); } + bool PosChildNeedsLayout() const { + CheckIsNotDestroyed(); + return bitfields_.PosChildNeedsLayout(); + } bool NeedsSimplifiedNormalFlowLayout() const { + CheckIsNotDestroyed(); return bitfields_.NeedsSimplifiedNormalFlowLayout(); } bool NormalChildNeedsLayout() const { + CheckIsNotDestroyed(); return bitfields_.NormalChildNeedsLayout(); } - bool NeedsCollectInlines() const { return bitfields_.NeedsCollectInlines(); } + bool NeedsCollectInlines() const { + CheckIsNotDestroyed(); + return bitfields_.NeedsCollectInlines(); + } bool MaybeHasPercentHeightDescendant() const { + CheckIsNotDestroyed(); return bitfields_.MaybeHasPercentHeightDescendant(); } void SetMaybeHasPercentHeightDescendant() { + CheckIsNotDestroyed(); bitfields_.SetMaybeHasPercentHeightDescendant(true); } @@ -1123,56 +1492,74 @@ // min/max), this flag will never be cleared (since the values will never be // calculated). bool IntrinsicLogicalWidthsDirty() const { + CheckIsNotDestroyed(); return bitfields_.IntrinsicLogicalWidthsDirty(); } bool IntrinsicLogicalWidthsDependsOnPercentageBlockSize() const { + CheckIsNotDestroyed(); return bitfields_.IntrinsicLogicalWidthsDependsOnPercentageBlockSize(); } void SetIntrinsicLogicalWidthsDependsOnPercentageBlockSize(bool b) { + CheckIsNotDestroyed(); bitfields_.SetIntrinsicLogicalWidthsDependsOnPercentageBlockSize(b); } bool IntrinsicLogicalWidthsChildDependsOnPercentageBlockSize() const { + CheckIsNotDestroyed(); return bitfields_.IntrinsicLogicalWidthsChildDependsOnPercentageBlockSize(); } void SetIntrinsicLogicalWidthsChildDependsOnPercentageBlockSize(bool b) { + CheckIsNotDestroyed(); bitfields_.SetIntrinsicLogicalWidthsChildDependsOnPercentageBlockSize(b); } bool NeedsLayoutOverflowRecalc() const { + CheckIsNotDestroyed(); return bitfields_.SelfNeedsLayoutOverflowRecalc() || bitfields_.ChildNeedsLayoutOverflowRecalc(); } bool SelfNeedsLayoutOverflowRecalc() const { + CheckIsNotDestroyed(); return bitfields_.SelfNeedsLayoutOverflowRecalc(); } bool ChildNeedsLayoutOverflowRecalc() const { + CheckIsNotDestroyed(); return bitfields_.ChildNeedsLayoutOverflowRecalc(); } void SetSelfNeedsLayoutOverflowRecalc() { + CheckIsNotDestroyed(); bitfields_.SetSelfNeedsLayoutOverflowRecalc(true); } void SetChildNeedsLayoutOverflowRecalc() { + CheckIsNotDestroyed(); bitfields_.SetChildNeedsLayoutOverflowRecalc(true); } void ClearSelfNeedsLayoutOverflowRecalc() { + CheckIsNotDestroyed(); bitfields_.SetSelfNeedsLayoutOverflowRecalc(false); } void ClearChildNeedsLayoutOverflowRecalc() { + CheckIsNotDestroyed(); bitfields_.SetChildNeedsLayoutOverflowRecalc(false); } // CSS clip only applies when position is absolute or fixed. Prefer this check // over !StyleRef().HasAutoClip(). bool HasClip() const { + CheckIsNotDestroyed(); return IsOutOfFlowPositioned() && !StyleRef().HasAutoClip(); } bool HasNonVisibleOverflow() const { + CheckIsNotDestroyed(); return bitfields_.HasNonVisibleOverflow(); } - bool ShouldClipOverflow() const { return bitfields_.ShouldClipOverflow(); } + bool ShouldClipOverflow() const { + CheckIsNotDestroyed(); + return bitfields_.ShouldClipOverflow(); + } bool HasClipRelatedProperty() const; bool IsScrollContainer() const { + CheckIsNotDestroyed(); // Always check HasNonVisibleOverflow() in case the object is not allowed to // have non-visible overflow. return HasNonVisibleOverflow() && StyleRef().IsScrollContainer(); @@ -1181,15 +1568,27 @@ // Not returning StyleRef().HasTransformRelatedProperty() because some objects // ignore the transform-related styles (e.g. LayoutInline, LayoutSVGBlock). bool HasTransformRelatedProperty() const { + CheckIsNotDestroyed(); return bitfields_.HasTransformRelatedProperty(); } - bool IsTransformApplicable() const { return IsBox() || IsSVG(); } - bool HasMask() const { return StyleRef().HasMask(); } - bool HasClipPath() const { return StyleRef().ClipPath(); } + bool IsTransformApplicable() const { + CheckIsNotDestroyed(); + return IsBox() || IsSVG(); + } + bool HasMask() const { + CheckIsNotDestroyed(); + return StyleRef().HasMask(); + } + bool HasClipPath() const { + CheckIsNotDestroyed(); + return StyleRef().ClipPath(); + } bool HasHiddenBackface() const { + CheckIsNotDestroyed(); return StyleRef().BackfaceVisibility() == EBackfaceVisibility::kHidden; } bool HasNonInitialBackdropFilter() const { + CheckIsNotDestroyed(); return StyleRef().HasNonInitialBackdropFilter(); } @@ -1198,10 +1597,14 @@ // Not calling StyleRef().HasFilterInducingProperty() because some objects // ignore reflection style (e.g. LayoutInline, LayoutSVGBlock). bool HasFilterInducingProperty() const { + CheckIsNotDestroyed(); return StyleRef().HasNonInitialFilter() || HasReflection(); } - bool HasShapeOutside() const { return StyleRef().ShapeOutside(); } + bool HasShapeOutside() const { + CheckIsNotDestroyed(); + return StyleRef().ShapeOutside(); + } // Return true if the given object is the effective root scroller in its // Document. See |effective root scroller| in page/scrolling/README.md. @@ -1210,19 +1613,25 @@ // RootScrollerController::RecomputeEffectiveRootScroller in the LayoutClean // document lifecycle phase. bool IsEffectiveRootScroller() const { + CheckIsNotDestroyed(); return bitfields_.IsEffectiveRootScroller(); } // Returns true if the given object is the global root scroller. See // |global root scroller| in page/scrolling/README.md. bool IsGlobalRootScroller() const { + CheckIsNotDestroyed(); return bitfields_.IsGlobalRootScroller(); } - bool IsHTMLLegendElement() const { return bitfields_.IsHTMLLegendElement(); } + bool IsHTMLLegendElement() const { + CheckIsNotDestroyed(); + return bitfields_.IsHTMLLegendElement(); + } // Returns true if this can be used as a rendered legend. bool IsRenderedLegendCandidate() const { + CheckIsNotDestroyed(); // Note, we can't directly use LayoutObject::IsFloating() because in the // case where the legend is a flex/grid item, LayoutObject::IsFloating() // could get set to false, even if the legend's computed style indicates @@ -1237,6 +1646,7 @@ // // This function is performance sensitive. inline bool IsRenderedLegend() const { + CheckIsNotDestroyed(); if (LIKELY(!IsRenderedLegendCandidate())) return false; @@ -1255,36 +1665,56 @@ const PseudoElementStyleRequest&, const ComputedStyle* parent_style = nullptr) const; - LayoutView* View() const { return GetDocument().GetLayoutView(); } - LocalFrameView* GetFrameView() const { return GetDocument().View(); } + LayoutView* View() const { + CheckIsNotDestroyed(); + return GetDocument().GetLayoutView(); + } + LocalFrameView* GetFrameView() const { + CheckIsNotDestroyed(); + return GetDocument().View(); + } bool IsRooted() const; - Node* GetNode() const { return IsAnonymous() ? nullptr : node_; } + Node* GetNode() const { + CheckIsNotDestroyed(); + return IsAnonymous() ? nullptr : node_; + } Node* NonPseudoNode() const { + CheckIsNotDestroyed(); return IsPseudoElement() ? nullptr : GetNode(); } - void ClearNode() { node_ = nullptr; } + void ClearNode() { + CheckIsNotDestroyed(); + node_ = nullptr; + } // Returns the styled node that caused the generation of this layoutObject. // This is the same as node() except for layoutObjects of :before, :after and // :first-letter pseudo elements for which their parent node is returned. Node* GeneratingNode() const { + CheckIsNotDestroyed(); return IsPseudoElement() ? GetNode()->ParentOrShadowHostNode() : GetNode(); } Document& GetDocument() const { + CheckIsNotDestroyed(); DCHECK(node_ || Parent()); // crbug.com/402056 return node_ ? node_->GetDocument() : Parent()->GetDocument(); } - LocalFrame* GetFrame() const { return GetDocument().GetFrame(); } + LocalFrame* GetFrame() const { + CheckIsNotDestroyed(); + return GetDocument().GetFrame(); + } virtual LayoutMultiColumnSpannerPlaceholder* SpannerPlaceholder() const { + CheckIsNotDestroyed(); return nullptr; } bool IsColumnSpanAll() const { + CheckIsNotDestroyed(); return StyleRef().GetColumnSpan() == EColumnSpan::kAll && SpannerPlaceholder(); } @@ -1299,6 +1729,7 @@ // TODO(cbiesinger): Remove when buttons are implemented with align-items // instead of flex box. crbug.com/226252. bool BehavesLikeBlockContainer() const { + CheckIsNotDestroyed(); return (IsLayoutBlockFlow() && StyleRef().IsDisplayBlockContainer()) || IsButtonOrNGButton(); } @@ -1378,6 +1809,7 @@ LayoutObject* ContainerForFixedPosition(AncestorSkipInfo* = nullptr) const; bool CanContainOutOfFlowPositionedElement(EPosition position) const { + CheckIsNotDestroyed(); DCHECK(position == EPosition::kAbsolute || position == EPosition::kFixed); return (position == EPosition::kAbsolute && CanContainAbsolutePositionObjects()) || @@ -1391,7 +1823,10 @@ // This value gets cached by bitfields_.can_contain_fixed_position_objects_. bool ComputeIsFixedContainer(const ComputedStyle* style) const; - virtual LayoutObject* HoverAncestor() const { return Parent(); } + virtual LayoutObject* HoverAncestor() const { + CheckIsNotDestroyed(); + return Parent(); + } Element* OffsetParent(const Element* = nullptr) const; @@ -1399,8 +1834,14 @@ // marked too if needed. void SetNeedsCollectInlines(); void SetChildNeedsCollectInlines(); - void ClearNeedsCollectInlines() { SetNeedsCollectInlines(false); } - void SetNeedsCollectInlines(bool b) { bitfields_.SetNeedsCollectInlines(b); } + void ClearNeedsCollectInlines() { + CheckIsNotDestroyed(); + SetNeedsCollectInlines(false); + } + void SetNeedsCollectInlines(bool b) { + CheckIsNotDestroyed(); + bitfields_.SetNeedsCollectInlines(b); + } void MarkContainerChainForLayout(bool schedule_relayout = true, SubtreeLayoutScope* = nullptr); @@ -1426,11 +1867,13 @@ void SetNeedsLayoutAndIntrinsicWidthsRecalc( LayoutInvalidationReasonForTracing reason) { + CheckIsNotDestroyed(); SetNeedsLayout(reason); SetIntrinsicLogicalWidthsDirty(); } void SetNeedsLayoutAndIntrinsicWidthsRecalcAndFullPaintInvalidation( LayoutInvalidationReasonForTracing reason) { + CheckIsNotDestroyed(); SetNeedsLayoutAndFullPaintInvalidation(reason); SetIntrinsicLogicalWidthsDirty(); } @@ -1446,15 +1889,25 @@ void InvalidateIntersectionObserverCachedRects(); void SetPositionState(EPosition position) { + CheckIsNotDestroyed(); DCHECK( (position != EPosition::kAbsolute && position != EPosition::kFixed) || IsBox()); bitfields_.SetPositionedState(position); } - void ClearPositionedState() { bitfields_.ClearPositionedState(); } + void ClearPositionedState() { + CheckIsNotDestroyed(); + bitfields_.ClearPositionedState(); + } - void SetFloating(bool is_floating) { bitfields_.SetFloating(is_floating); } - void SetInline(bool is_inline) { bitfields_.SetIsInline(is_inline); } + void SetFloating(bool is_floating) { + CheckIsNotDestroyed(); + bitfields_.SetFloating(is_floating); + } + void SetInline(bool is_inline) { + CheckIsNotDestroyed(); + bitfields_.SetIsInline(is_inline); + } // Return whether we can directly traverse fragments generated for this layout // object, when it comes to painting, hit-testing and other layout read @@ -1468,57 +1921,97 @@ // Returns the associated |NGPaintFragment|. When this is not a |nullptr|, // this is the root of an inline formatting context, laid out by LayoutNG. - virtual const NGPaintFragment* PaintFragment() const { return nullptr; } + virtual const NGPaintFragment* PaintFragment() const { + CheckIsNotDestroyed(); + return nullptr; + } // Return true if |this| produces one or more inline fragments, including // whitespace-only text fragments. - virtual bool HasInlineFragments() const { return false; } + virtual bool HasInlineFragments() const { + CheckIsNotDestroyed(); + return false; + } // Paint/Physical fragments are not in sync with LayoutObject tree until it is // laid out. For inline, it needs to check if the containing block is // layout-clean. crbug.com/963103 bool IsFirstInlineFragmentSafe() const; void SetIsInLayoutNGInlineFormattingContext(bool); - virtual NGPaintFragment* FirstInlineFragment() const { return nullptr; } - virtual void SetFirstInlineFragment(NGPaintFragment*) {} - virtual wtf_size_t FirstInlineFragmentItemIndex() const { return 0u; } - virtual void ClearFirstInlineFragmentItemIndex() {} - virtual void SetFirstInlineFragmentItemIndex(wtf_size_t) {} - void SetForceLegacyLayout() { bitfields_.SetForceLegacyLayout(true); } + virtual NGPaintFragment* FirstInlineFragment() const { + CheckIsNotDestroyed(); + return nullptr; + } + virtual void SetFirstInlineFragment(NGPaintFragment*) { + CheckIsNotDestroyed(); + } + virtual wtf_size_t FirstInlineFragmentItemIndex() const { + CheckIsNotDestroyed(); + return 0u; + } + virtual void ClearFirstInlineFragmentItemIndex() { CheckIsNotDestroyed(); } + virtual void SetFirstInlineFragmentItemIndex(wtf_size_t) { + CheckIsNotDestroyed(); + } + void SetForceLegacyLayout() { + CheckIsNotDestroyed(); + bitfields_.SetForceLegacyLayout(true); + } void SetHasBoxDecorationBackground(bool); - void SetIsText() { bitfields_.SetIsText(true); } - void SetIsBox() { bitfields_.SetIsBox(true); } + void SetIsText() { + CheckIsNotDestroyed(); + bitfields_.SetIsText(true); + } + void SetIsBox() { + CheckIsNotDestroyed(); + bitfields_.SetIsBox(true); + } void SetIsAtomicInlineLevel(bool is_atomic_inline_level) { + CheckIsNotDestroyed(); bitfields_.SetIsAtomicInlineLevel(is_atomic_inline_level); } void SetHorizontalWritingMode(bool has_horizontal_writing_mode) { + CheckIsNotDestroyed(); bitfields_.SetHorizontalWritingMode(has_horizontal_writing_mode); } void SetHasNonVisibleOverflow(bool has_non_visible_overflow) { + CheckIsNotDestroyed(); bitfields_.SetHasNonVisibleOverflow(has_non_visible_overflow); } void SetShouldClipOverflow(bool should_clip_overflow) { + CheckIsNotDestroyed(); bitfields_.SetShouldClipOverflow(should_clip_overflow); } - void SetHasLayer(bool has_layer) { bitfields_.SetHasLayer(has_layer); } + void SetHasLayer(bool has_layer) { + CheckIsNotDestroyed(); + bitfields_.SetHasLayer(has_layer); + } void SetHasTransformRelatedProperty(bool has_transform) { + CheckIsNotDestroyed(); bitfields_.SetHasTransformRelatedProperty(has_transform); } void SetHasReflection(bool has_reflection) { + CheckIsNotDestroyed(); bitfields_.SetHasReflection(has_reflection); } void SetCanContainFixedPositionObjects(bool can_contain_fixed_position) { + CheckIsNotDestroyed(); bitfields_.SetCanContainFixedPositionObjects(can_contain_fixed_position); } void SetIsEffectiveRootScroller(bool is_effective_root_scroller) { + CheckIsNotDestroyed(); bitfields_.SetIsEffectiveRootScroller(is_effective_root_scroller); } void SetIsGlobalRootScroller(bool is_global_root_scroller) { + CheckIsNotDestroyed(); bitfields_.SetIsGlobalRootScroller(is_global_root_scroller); } - void SetIsHTMLLegendElement() { bitfields_.SetIsHTMLLegendElement(true); } + void SetIsHTMLLegendElement() { + CheckIsNotDestroyed(); + bitfields_.SetIsHTMLLegendElement(true); + } virtual void Paint(const PaintInfo&) const; @@ -1538,13 +2031,15 @@ virtual void UpdateLayout() = 0; void HandleSubtreeModifications(); - virtual void SubtreeDidChange() {} + virtual void SubtreeDidChange() { CheckIsNotDestroyed(); } // Flags used to mark if an object consumes subtree change notifications. bool ConsumesSubtreeChangeNotification() const { + CheckIsNotDestroyed(); return bitfields_.ConsumesSubtreeChangeNotification(); } void SetConsumesSubtreeChangeNotification() { + CheckIsNotDestroyed(); bitfields_.SetConsumesSubtreeChangeNotification(true); } @@ -1552,6 +2047,7 @@ void NotifyOfSubtreeChange(); void NotifyAncestorsOfSubtreeChange(); bool WasNotifiedOfSubtreeChange() const { + CheckIsNotDestroyed(); return bitfields_.NotifiedOfSubtreeChange(); } @@ -1559,24 +2055,27 @@ // descendants that they have had their child subtree changed. void RegisterSubtreeChangeListenerOnDescendants(bool); bool HasSubtreeChangeListenerRegistered() const { + CheckIsNotDestroyed(); return bitfields_.SubtreeChangeListenerRegistered(); } /* This function performs a layout only if one is needed. */ DISABLE_CFI_PERF void LayoutIfNeeded() { + CheckIsNotDestroyed(); if (NeedsLayout()) UpdateLayout(); } void ForceLayout(); void ForceLayoutWithPaintInvalidation() { + CheckIsNotDestroyed(); SetShouldDoFullPaintInvalidation(); ForceLayout(); } // Used for element state updates that cannot be fixed with a paint // invalidation and do not need a relayout. - virtual void UpdateFromElement() {} + virtual void UpdateFromElement() { CheckIsNotDestroyed(); } virtual void AddAnnotatedRegions(Vector<AnnotatedRegionValue>&); @@ -1680,10 +2179,12 @@ const LayoutBlock* InclusiveContainingBlock() const; bool CanContainAbsolutePositionObjects() const { + CheckIsNotDestroyed(); return style_->CanContainAbsolutePositionObjects() || CanContainFixedPositionObjects(); } bool CanContainFixedPositionObjects() const { + CheckIsNotDestroyed(); return bitfields_.CanContainFixedPositionObjects(); } @@ -1701,6 +2202,7 @@ PhysicalRect AncestorToLocalRect(const LayoutBoxModelObject* ancestor, const PhysicalRect& rect, MapCoordinatesFlags mode = 0) const { + CheckIsNotDestroyed(); return PhysicalRect::EnclosingRect( AncestorToLocalQuad(ancestor, FloatRect(rect), mode).BoundingBox()); } @@ -1710,6 +2212,7 @@ PhysicalOffset AncestorToLocalPoint(const LayoutBoxModelObject* ancestor, const PhysicalOffset& p, MapCoordinatesFlags mode = 0) const { + CheckIsNotDestroyed(); return PhysicalOffset::FromFloatPointRound( AncestorToLocalFloatPoint(ancestor, FloatPoint(p), mode)); } @@ -1735,6 +2238,7 @@ FloatQuad LocalRectToAncestorQuad(const PhysicalRect& rect, const LayoutBoxModelObject* ancestor, MapCoordinatesFlags mode = 0) const { + CheckIsNotDestroyed(); return LocalToAncestorQuad(FloatRect(rect), ancestor, mode); } FloatQuad LocalToAncestorQuad(const FloatQuad&, @@ -1743,6 +2247,7 @@ PhysicalOffset LocalToAncestorPoint(const PhysicalOffset& p, const LayoutBoxModelObject* ancestor, MapCoordinatesFlags mode = 0) const { + CheckIsNotDestroyed(); return PhysicalOffset::FromFloatPointRound( LocalToAncestorFloatPoint(FloatPoint(p), ancestor, mode)); } @@ -1763,6 +2268,7 @@ MapCoordinatesFlags = 0) const; TransformationMatrix LocalToAbsoluteTransform( MapCoordinatesFlags mode = 0) const { + CheckIsNotDestroyed(); return LocalToAncestorTransform(nullptr, mode); } @@ -1772,38 +2278,47 @@ // This method supports kUseGeometryMapperMode. PhysicalRect LocalToAbsoluteRect(const PhysicalRect& rect, MapCoordinatesFlags mode = 0) const { + CheckIsNotDestroyed(); return LocalToAncestorRect(rect, nullptr, mode); } FloatQuad LocalRectToAbsoluteQuad(const PhysicalRect& rect, MapCoordinatesFlags mode = 0) const { + CheckIsNotDestroyed(); return LocalRectToAncestorQuad(rect, nullptr, mode); } FloatQuad LocalToAbsoluteQuad(const FloatQuad& quad, MapCoordinatesFlags mode = 0) const { + CheckIsNotDestroyed(); return LocalToAncestorQuad(quad, nullptr, mode); } PhysicalOffset LocalToAbsolutePoint(const PhysicalOffset& p, MapCoordinatesFlags mode = 0) const { + CheckIsNotDestroyed(); return LocalToAncestorPoint(p, nullptr, mode); } FloatPoint LocalToAbsoluteFloatPoint(const FloatPoint& p, MapCoordinatesFlags mode = 0) const { + CheckIsNotDestroyed(); return LocalToAncestorFloatPoint(p, nullptr, mode); } PhysicalRect AbsoluteToLocalRect(const PhysicalRect& rect, MapCoordinatesFlags mode = 0) const { + CheckIsNotDestroyed(); return AncestorToLocalRect(nullptr, rect, mode); } FloatQuad AbsoluteToLocalQuad(const FloatQuad& quad, MapCoordinatesFlags mode = 0) const { + CheckIsNotDestroyed(); return AncestorToLocalQuad(nullptr, quad, mode); } PhysicalOffset AbsoluteToLocalPoint(const PhysicalOffset& p, MapCoordinatesFlags mode = 0) const { + CheckIsNotDestroyed(); return AncestorToLocalPoint(nullptr, p, mode); } FloatPoint AbsoluteToLocalFloatPoint(const FloatPoint& p, MapCoordinatesFlags mode = 0) const { + CheckIsNotDestroyed(); return AncestorToLocalFloatPoint(nullptr, p, mode); } @@ -1836,7 +2351,9 @@ // Build an array of quads in absolute coords for line boxes virtual void AbsoluteQuads(Vector<FloatQuad>&, - MapCoordinatesFlags mode = 0) const {} + MapCoordinatesFlags mode = 0) const { + CheckIsNotDestroyed(); + } // The bounding box (see: absoluteBoundingBoxRect) including all descendant // bounding boxes. @@ -1860,13 +2377,20 @@ // https://drafts.csswg.org/css-sizing-3/#min-content-inline-size // https://drafts.csswg.org/css-sizing-3/#max-content-inline-size // TODO(jchaffraix): We will probably want to rename it to match CSS 3. - virtual MinMaxSizes PreferredLogicalWidths() const { return MinMaxSizes(); } + virtual MinMaxSizes PreferredLogicalWidths() const { + CheckIsNotDestroyed(); + return MinMaxSizes(); + } - const ComputedStyle* Style() const { return style_.get(); } + const ComputedStyle* Style() const { + CheckIsNotDestroyed(); + return style_.get(); + } // style_ can only be nullptr before the first style is set, thus most // callers will never see a nullptr style and should use StyleRef(). const ComputedStyle& StyleRef() const { + CheckIsNotDestroyed(); DCHECK(style_); return *style_; } @@ -1880,6 +2404,7 @@ inline const ComputedStyle& StyleRef(bool first_line) const; const ComputedStyle& EffectiveStyle(NGStyleVariant style_variant) const { + CheckIsNotDestroyed(); return style_variant == NGStyleVariant::kStandard ? StyleRef() : SlowEffectiveStyle(style_variant); @@ -1891,6 +2416,7 @@ } inline Color ResolveColor(const CSSProperty& color_property) const { + CheckIsNotDestroyed(); return StyleRef().VisitedDependentColor(color_property); } @@ -1914,6 +2440,7 @@ // LayoutSVGRoot) should use VisualRectInLocalSVGCoordinates() and map with // SVG transforms instead. PhysicalRect LocalVisualRect() const { + CheckIsNotDestroyed(); if (StyleRef().Visibility() != EVisibility::kVisible && VisualRectRespectsVisibility()) return PhysicalRect(); @@ -1966,6 +2493,7 @@ // Do a rect-based hit test with this object as the stop node. HitTestResult HitTestForOcclusion(const PhysicalRect&) const; HitTestResult HitTestForOcclusion() const { + CheckIsNotDestroyed(); return HitTestForOcclusion(VisualRectInDocument()); } @@ -1973,12 +2501,17 @@ // flow-thread coordinates) lives. This is used to convert a flow-thread point // to a point in the containing coordinate space. virtual LayoutSize ColumnOffset(const LayoutPoint&) const { + CheckIsNotDestroyed(); return LayoutSize(); } - virtual unsigned length() const { return 1; } + virtual unsigned length() const { + CheckIsNotDestroyed(); + return 1; + } bool IsFloatingOrOutOfFlowPositioned() const { + CheckIsNotDestroyed(); return (IsFloating() || IsOutOfFlowPositioned()); } @@ -1987,21 +2520,27 @@ // generating an anonymous block box for the whitespace between the marker // and the <ol>. bool AffectsWhitespaceSiblings() const { + CheckIsNotDestroyed(); return !IsFloatingOrOutOfFlowPositioned() && !IsLayoutNGOutsideListMarker() && !IsOutsideListMarker(); } // Not returning StyleRef().BoxReflect() because some objects ignore the // reflection style (e.g. LayoutInline, LayoutSVGBlock). - bool HasReflection() const { return bitfields_.HasReflection(); } + bool HasReflection() const { + CheckIsNotDestroyed(); + return bitfields_.HasReflection(); + } // The current selection state for an object. For blocks, the state refers to // the state of the leaf descendants (as described above in the SelectionState // enum declaration). SelectionState GetSelectionState() const { + CheckIsNotDestroyed(); return bitfields_.GetSelectionState(); } void SetSelectionState(SelectionState state) { + CheckIsNotDestroyed(); bitfields_.SetSelectionState(state); } bool CanUpdateSelectionOnRootLineBoxes() const; @@ -2010,6 +2549,7 @@ // object. Used to determine the tightest possible bounding box for the // selection. The rect is in the object's local physical coordinate space. virtual PhysicalRect LocalSelectionVisualRect() const { + CheckIsNotDestroyed(); return PhysicalRect(); } @@ -2035,6 +2575,7 @@ const InlineBox* inline_box, int caret_offset, LayoutUnit* extra_width_to_end_of_line = nullptr) const { + CheckIsNotDestroyed(); return FlipForWritingMode( LocalCaretRect(inline_box, caret_offset, extra_width_to_end_of_line)); } @@ -2050,17 +2591,30 @@ // Virtual function helpers for the deprecated Flexible Box Layout (display: // -webkit-box). - virtual bool IsDeprecatedFlexibleBox() const { return false; } + virtual bool IsDeprecatedFlexibleBox() const { + CheckIsNotDestroyed(); + return false; + } // Virtual function helper for the new FlexibleBox Layout (display: // -webkit-flex). - virtual bool IsFlexibleBox() const { return false; } + virtual bool IsFlexibleBox() const { + CheckIsNotDestroyed(); + return false; + } - virtual bool IsFlexibleBoxIncludingDeprecatedAndNG() const { return false; } + virtual bool IsFlexibleBoxIncludingDeprecatedAndNG() const { + CheckIsNotDestroyed(); + return false; + } - virtual bool IsFlexibleBoxIncludingNG() const { return false; } + virtual bool IsFlexibleBoxIncludingNG() const { + CheckIsNotDestroyed(); + return false; + } bool IsListItemIncludingNG() const { + CheckIsNotDestroyed(); return IsListItem() || IsLayoutNGListItem(); } @@ -2081,50 +2635,64 @@ bool IsOutsideListMarker() const; // Any kind of legacy list marker. bool IsListMarker() const { + CheckIsNotDestroyed(); return IsListMarkerForNormalContent() || IsInsideListMarkerForCustomContent() || IsOutsideListMarkerForCustomContent(); } // Any kind of LayoutBox list marker. bool IsBoxListMarkerIncludingNG() const { + CheckIsNotDestroyed(); return IsListMarkerForNormalContent() || IsOutsideListMarkerForCustomContent() || IsLayoutNGOutsideListMarker(); } // Any kind of LayoutNG list marker. bool IsLayoutNGListMarker() const { + CheckIsNotDestroyed(); return IsLayoutNGInsideListMarker() || IsLayoutNGOutsideListMarker(); } // Any kind of list marker. bool IsListMarkerIncludingAll() const { + CheckIsNotDestroyed(); return IsListMarker() || IsLayoutNGListMarker(); } - virtual bool IsCombineText() const { return false; } + virtual bool IsCombineText() const { + CheckIsNotDestroyed(); + return false; + } virtual int CaretMinOffset() const; virtual int CaretMaxOffset() const; // ImageResourceObserver override. void ImageChanged(ImageResourceContent*, CanDeferInvalidation) final; - void ImageChanged(WrappedImagePtr, CanDeferInvalidation) override {} + void ImageChanged(WrappedImagePtr, CanDeferInvalidation) override { + CheckIsNotDestroyed(); + } void ImageNotifyFinished(ImageResourceContent*) override; void NotifyImageFullyRemoved(ImageResourceContent*) override; bool WillRenderImage() final; bool GetImageAnimationPolicy(web_pref::ImageAnimationPolicy&) final; void Remove() { + CheckIsNotDestroyed(); if (Parent()) Parent()->RemoveChild(this); } bool VisibleToHitTestRequest(const HitTestRequest& request) const { + CheckIsNotDestroyed(); return StyleRef().Visibility() == EVisibility::kVisible && (request.IgnorePointerEventsNone() || StyleRef().PointerEvents() != EPointerEvents::kNone); } - bool VisibleToHitTesting() const { return StyleRef().VisibleToHitTesting(); } + bool VisibleToHitTesting() const { + CheckIsNotDestroyed(); + return StyleRef().VisibleToHitTesting(); + } // Map points and quads through elements, potentially via 3d transforms. You // should never need to call these directly; use localToAbsolute/ @@ -2156,6 +2724,7 @@ TransformationMatrix&) const; bool CreatesGroup() const { + CheckIsNotDestroyed(); // See |HasReflection()| for why |StyleRef().BoxReflect()| is not used. return StyleRef().HasGroupingProperty(HasReflection()); } @@ -2168,13 +2737,16 @@ // rects also cover continuations. virtual void AddOutlineRects(Vector<PhysicalRect>&, const PhysicalOffset& additional_offset, - NGOutlineType) const {} + NGOutlineType) const { + CheckIsNotDestroyed(); + } // For history and compatibility reasons, we draw outline:auto (for focus // rings) and normal style outline differently. // Focus rings enclose block visual overflows (of line boxes and descendants), // while normal outlines don't. NGOutlineType OutlineRectsShouldIncludeBlockVisualOverflow() const { + CheckIsNotDestroyed(); return StyleRef().OutlineStyleIsAuto() ? NGOutlineType::kIncludeBlockVisualOverflow : NGOutlineType::kDontIncludeBlockVisualOverflow; @@ -2182,6 +2754,7 @@ // Only public for LayoutNG. void SetContainsInlineWithOutlineAndContinuation(bool b) { + CheckIsNotDestroyed(); bitfields_.SetContainsInlineWithOutlineAndContinuation(b); } @@ -2191,15 +2764,18 @@ bool IsRelayoutBoundary() const; void SetSelfNeedsLayoutForAvailableSpace(bool flag) { + CheckIsNotDestroyed(); bitfields_.SetSelfNeedsLayoutForAvailableSpace(flag); if (flag) MarkSelfPaintingLayerForVisualOverflowRecalc(); } PaintInvalidationReason FullPaintInvalidationReason() const { + CheckIsNotDestroyed(); return full_paint_invalidation_reason_; } bool ShouldDoFullPaintInvalidation() const { + CheckIsNotDestroyed(); if (!ShouldDelayFullPaintInvalidation() && full_paint_invalidation_reason_ != PaintInvalidationReason::kNone) { DCHECK(IsFullPaintInvalidationReason(full_paint_invalidation_reason_)); @@ -2226,24 +2802,29 @@ void ClearPaintInvalidationFlags(); bool ShouldCheckForPaintInvalidation() const { + CheckIsNotDestroyed(); return bitfields_.ShouldCheckForPaintInvalidation(); } void SetShouldCheckForPaintInvalidation(); void SetShouldCheckForPaintInvalidationWithoutGeometryChange(); bool SubtreeShouldCheckForPaintInvalidation() const { + CheckIsNotDestroyed(); return bitfields_.SubtreeShouldCheckForPaintInvalidation(); } void SetSubtreeShouldCheckForPaintInvalidation(); bool ShouldCheckGeometryForPaintInvalidation() const { + CheckIsNotDestroyed(); return bitfields_.ShouldCheckGeometryForPaintInvalidation(); } bool DescendantShouldCheckGeometryForPaintInvalidation() const { + CheckIsNotDestroyed(); return bitfields_.DescendantShouldCheckGeometryForPaintInvalidation(); } bool MayNeedPaintInvalidationAnimatedBackgroundImage() const { + CheckIsNotDestroyed(); return bitfields_.MayNeedPaintInvalidationAnimatedBackgroundImage(); } void SetMayNeedPaintInvalidationAnimatedBackgroundImage(); @@ -2251,6 +2832,7 @@ void SetSubtreeShouldDoFullPaintInvalidation( PaintInvalidationReason reason = PaintInvalidationReason::kSubtree); bool SubtreeShouldDoFullPaintInvalidation() const { + CheckIsNotDestroyed(); DCHECK(!bitfields_.SubtreeShouldDoFullPaintInvalidation() || ShouldDoFullPaintInvalidation()); return bitfields_.SubtreeShouldDoFullPaintInvalidation(); @@ -2260,11 +2842,13 @@ // delayed until a future frame. This can be the case for an object whose // content is not visible to the user. bool ShouldDelayFullPaintInvalidation() const { + CheckIsNotDestroyed(); return bitfields_.ShouldDelayFullPaintInvalidation(); } void SetShouldDelayFullPaintInvalidation(); bool ShouldInvalidateSelection() const { + CheckIsNotDestroyed(); return bitfields_.ShouldInvalidateSelection(); } void SetShouldInvalidateSelection(); @@ -2288,13 +2872,16 @@ // Get the dedicated DisplayItemClient for selection. Returns nullptr if this // object doesn't have a dedicated DisplayItemClient. virtual const DisplayItemClient* GetSelectionDisplayItemClient() const { + CheckIsNotDestroyed(); return nullptr; } // Called before setting style for existing/new anonymous child. Override to // set custom styles for the child. For new anonymous child, |child| is null. virtual void UpdateAnonymousChildStyle(const LayoutObject* child, - ComputedStyle& style) const {} + ComputedStyle& style) const { + CheckIsNotDestroyed(); + } // Returns a rect corresponding to this LayoutObject's bounds for use in // debugging output @@ -2303,7 +2890,10 @@ // Each LayoutObject has one or more painting fragments (exactly one // in the absence of multicol/pagination). // See ../paint/README.md for more on fragments. - const FragmentData& FirstFragment() const { return fragment_; } + const FragmentData& FirstFragment() const { + CheckIsNotDestroyed(); + return fragment_; + } enum OverflowRecalcType { kOnlyVisualOverflowRecalc, @@ -2321,17 +2911,20 @@ // The allowed touch action is the union of the effective touch action // (from style) and blocking touch event handlers. TouchAction EffectiveAllowedTouchAction() const { + CheckIsNotDestroyed(); if (InsideBlockingTouchEventHandler()) return TouchAction::kNone; return StyleRef().GetEffectiveTouchAction(); } bool HasEffectiveAllowedTouchAction() const { + CheckIsNotDestroyed(); return EffectiveAllowedTouchAction() != TouchAction::kAuto; } // Whether this object's Node has a blocking touch event handler on itself // or an ancestor. bool InsideBlockingTouchEventHandler() const { + CheckIsNotDestroyed(); return bitfields_.InsideBlockingTouchEventHandler(); } // Mark this object as having a |EffectiveAllowedTouchAction| changed, and @@ -2339,12 +2932,15 @@ // PrePaint tree walk to update effective allowed touch action. void MarkEffectiveAllowedTouchActionChanged(); bool EffectiveAllowedTouchActionChanged() const { + CheckIsNotDestroyed(); return bitfields_.EffectiveAllowedTouchActionChanged(); } bool DescendantEffectiveAllowedTouchActionChanged() const { + CheckIsNotDestroyed(); return bitfields_.DescendantEffectiveAllowedTouchActionChanged(); } void UpdateInsideBlockingTouchEventHandler(bool inside) { + CheckIsNotDestroyed(); bitfields_.SetInsideBlockingTouchEventHandler(inside); } @@ -2452,6 +3048,7 @@ LayoutObject& layout_object_; }; MutableForPainting GetMutableForPainting() const { + CheckIsNotDestroyed(); return MutableForPainting(*this); } @@ -2466,44 +3063,54 @@ void SetNeedsPaintPropertyUpdate(); void SetNeedsPaintPropertyUpdatePreservingCachedRects(); bool NeedsPaintPropertyUpdate() const { + CheckIsNotDestroyed(); return bitfields_.NeedsPaintPropertyUpdate(); } void AddSubtreePaintPropertyUpdateReason( SubtreePaintPropertyUpdateReason reason) { + CheckIsNotDestroyed(); bitfields_.AddSubtreePaintPropertyUpdateReason(reason); SetNeedsPaintPropertyUpdate(); } unsigned SubtreePaintPropertyUpdateReasons() const { + CheckIsNotDestroyed(); return bitfields_.SubtreePaintPropertyUpdateReasons(); } bool DescendantNeedsPaintPropertyUpdate() const { + CheckIsNotDestroyed(); return bitfields_.DescendantNeedsPaintPropertyUpdate(); } // Main thread scrolling reasons require fully updating paint propeties of all // ancestors (see: ScrollPaintPropertyNode.h). void SetAncestorsNeedPaintPropertyUpdateForMainThreadScrolling(); - void SetIsScrollAnchorObject() { bitfields_.SetIsScrollAnchorObject(true); } + void SetIsScrollAnchorObject() { + CheckIsNotDestroyed(); + bitfields_.SetIsScrollAnchorObject(true); + } // Clears the IsScrollAnchorObject bit if and only if no ScrollAnchors still // reference this LayoutObject. void MaybeClearIsScrollAnchorObject(); bool ScrollAnchorDisablingStyleChanged() { + CheckIsNotDestroyed(); return bitfields_.ScrollAnchorDisablingStyleChanged(); } void SetScrollAnchorDisablingStyleChanged(bool changed) { + CheckIsNotDestroyed(); bitfields_.SetScrollAnchorDisablingStyleChanged(changed); } - bool CompositedScrollsWithRespectTo( const LayoutBoxModelObject& paint_invalidation_container) const; BackgroundPaintLocation GetBackgroundPaintLocation() const { + CheckIsNotDestroyed(); return bitfields_.GetBackgroundPaintLocation(); } void SetBackgroundPaintLocation(BackgroundPaintLocation location) { + CheckIsNotDestroyed(); if (GetBackgroundPaintLocation() != location) { SetBackgroundNeedsFullPaintInvalidation(); bitfields_.SetBackgroundPaintLocation(location); @@ -2511,38 +3118,46 @@ } bool IsBackgroundAttachmentFixedObject() const { + CheckIsNotDestroyed(); return bitfields_.IsBackgroundAttachmentFixedObject(); } bool BackgroundNeedsFullPaintInvalidation() const { + CheckIsNotDestroyed(); return !ShouldDelayFullPaintInvalidation() && bitfields_.BackgroundNeedsFullPaintInvalidation(); } void SetBackgroundNeedsFullPaintInvalidation() { + CheckIsNotDestroyed(); SetShouldDoFullPaintInvalidationWithoutGeometryChange( PaintInvalidationReason::kBackground); bitfields_.SetBackgroundNeedsFullPaintInvalidation(true); } bool ContainsInlineWithOutlineAndContinuation() const { + CheckIsNotDestroyed(); return bitfields_.ContainsInlineWithOutlineAndContinuation(); } void SetOutlineMayBeAffectedByDescendants(bool b) { + CheckIsNotDestroyed(); bitfields_.SetOutlineMayBeAffectedByDescendants(b); } inline bool ChildLayoutBlockedByDisplayLock() const { + CheckIsNotDestroyed(); auto* context = GetDisplayLockContext(); return context && !context->ShouldLayoutChildren(); } bool ChildPrePaintBlockedByDisplayLock() const { + CheckIsNotDestroyed(); auto* context = GetDisplayLockContext(); return context && !context->ShouldPrePaintChildren(); } bool ChildPaintBlockedByDisplayLock() const { + CheckIsNotDestroyed(); auto* context = GetDisplayLockContext(); return context && !context->ShouldPaintChildren(); } @@ -2550,18 +3165,24 @@ // This flag caches StyleRef().HasBorderDecoration() && // !Table()->ShouldCollapseBorders(). bool HasNonCollapsedBorderDecoration() const { + CheckIsNotDestroyed(); // We can only ensure this flag is up-to-date after PrePaint. DCHECK_GE(GetDocument().Lifecycle().GetState(), DocumentLifecycle::kPrePaintClean); return bitfields_.HasNonCollapsedBorderDecoration(); } void SetHasNonCollapsedBorderDecoration(bool b) { + CheckIsNotDestroyed(); bitfields_.SetHasNonCollapsedBorderDecoration(b); } - bool BeingDestroyed() const { return bitfields_.BeingDestroyed(); } + bool BeingDestroyed() const { + CheckIsNotDestroyed(); + return bitfields_.BeingDestroyed(); + } DisplayLockContext* GetDisplayLockContext() const { + CheckIsNotDestroyed(); if (!RuntimeEnabledFeatures::CSSContentVisibilityEnabled()) return nullptr; auto* element = DynamicTo<Element>(GetNode()); @@ -2571,25 +3192,32 @@ } void SetDocumentForAnonymous(Document* document) { + CheckIsNotDestroyed(); DCHECK(IsAnonymous()); node_ = document; } bool IsLayoutNGObjectForListMarkerImage() const { + CheckIsNotDestroyed(); DCHECK(IsListMarkerImage()); return bitfields_.IsLayoutNGObjectForListMarkerImage(); } void SetIsLayoutNGObjectForListMarkerImage(bool b) { + CheckIsNotDestroyed(); DCHECK(IsListMarkerImage()); bitfields_.SetIsLayoutNGObjectForListMarkerImage(b); } bool PreviousVisibilityVisible() const { + CheckIsNotDestroyed(); return bitfields_.PreviousVisibilityVisible(); } // See LocalVisualRect(). - virtual bool VisualRectRespectsVisibility() const { return true; } + virtual bool VisualRectRespectsVisibility() const { + CheckIsNotDestroyed(); + return true; + } protected: enum LayoutObjectType { @@ -2670,7 +3298,10 @@ kLayoutObjectSVGResourceContainer, kLayoutObjectSVGFilterPrimitive, }; - virtual bool IsOfType(LayoutObjectType type) const { return false; } + virtual bool IsOfType(LayoutObjectType type) const { + CheckIsNotDestroyed(); + return false; + } // While the |DeleteThis()| method is virtual, this should only be overridden // in very rare circumstances. @@ -2679,7 +3310,10 @@ // |LayoutEmbeddedContent| overrides |DeleteThis()| for this purpose). virtual void DeleteThis(); - void SetBeingDestroyedForTesting() { bitfields_.SetBeingDestroyed(true); } + void SetBeingDestroyedForTesting() { + CheckIsNotDestroyed(); + bitfields_.SetBeingDestroyed(true); + } const ComputedStyle& SlowEffectiveStyle(NGStyleVariant style_variant) const; @@ -2687,6 +3321,7 @@ // of the object, and so only should be called when the style is known not to // have changed (or from SetStyle). void SetStyleInternal(scoped_refptr<const ComputedStyle> style) { + CheckIsNotDestroyed(); style_ = std::move(style); } // Overrides should call the superclass at the end. style_ will be 0 the @@ -2700,9 +3335,14 @@ // propagated via propagateStyleToAnonymousChildren(), but rather rely on // other custom mechanisms (if they need to be notified of parent style // changes at all). - virtual bool AnonymousHasStylePropagationOverride() { return false; } + virtual bool AnonymousHasStylePropagationOverride() { + CheckIsNotDestroyed(); + return false; + } - virtual void InLayoutNGInlineFormattingContextWillChange(bool) {} + virtual void InLayoutNGInlineFormattingContextWillChange(bool) { + CheckIsNotDestroyed(); + } // A fast path for MapToVisualRectInAncestorSpace for when GeometryMapper // can be used. |intersects| is set to whether the input rect intersected @@ -2743,7 +3383,10 @@ void SetIsBackgroundAttachmentFixedObject(bool); - void SetEverHadLayout() { bitfields_.SetEverHadLayout(true); } + void SetEverHadLayout() { + CheckIsNotDestroyed(); + bitfields_.SetEverHadLayout(true); + } // Remove this object and all descendants from the containing // LayoutFlowThread. @@ -2752,7 +3395,10 @@ // See LocalVisualRect(). virtual PhysicalRect LocalVisualRectIgnoringVisibility() const; - virtual bool CanBeSelectionLeafInternal() const { return false; } + virtual bool CanBeSelectionLeafInternal() const { + CheckIsNotDestroyed(); + return false; + } virtual PhysicalOffset OffsetFromContainerInternal( const LayoutObject*, @@ -2761,16 +3407,19 @@ bool ignore_scroll_offset) const; void NotifyDisplayLockDidLayoutChildren() { + CheckIsNotDestroyed(); if (auto* context = GetDisplayLockContext()) context->DidLayoutChildren(); } bool BackgroundIsKnownToBeObscured() const { + CheckIsNotDestroyed(); DCHECK_GE(GetDocument().Lifecycle().GetState(), DocumentLifecycle::kInPrePaint); return bitfields_.BackgroundIsKnownToBeObscured(); } void SetBackgroundIsKnownToBeObscured(bool b) { + CheckIsNotDestroyed(); DCHECK_EQ(GetDocument().Lifecycle().GetState(), DocumentLifecycle::kInPrePaint); bitfields_.SetBackgroundIsKnownToBeObscured(b); @@ -2792,6 +3441,12 @@ // object is really in the first line which is unknown before layout. const ComputedStyle* FirstLineStyleWithoutFallback() const; + // Should be called at the beginning of every method to ensure we are not + // accessing a LayoutObject after the Desroy() call. + void CheckIsNotDestroyed() const { + // TODO(keishi): Implement once LayoutObject is GCed. + } + private: bool LocalToAncestorRectFastPath(const PhysicalRect& rect, const LayoutBoxModelObject* ancestor, @@ -2844,7 +3499,10 @@ void CheckBlockPositionedObjectsNeedLayout(); #endif - bool IsTextOrSVGChild() const { return IsText() || IsSVGChild(); } + bool IsTextOrSVGChild() const { + CheckIsNotDestroyed(); + return IsText() || IsSVGChild(); + } static bool IsAllowedToModifyLayoutTreeStructure(Document&); @@ -3368,16 +4026,23 @@ LayoutObjectBitfields bitfields_; void SetSelfNeedsLayoutForStyle(bool b) { + CheckIsNotDestroyed(); bitfields_.SetSelfNeedsLayoutForStyle(b); } void SetNeedsPositionedMovementLayout(bool b) { + CheckIsNotDestroyed(); bitfields_.SetNeedsPositionedMovementLayout(b); } void SetNormalChildNeedsLayout(bool b) { + CheckIsNotDestroyed(); bitfields_.SetNormalChildNeedsLayout(b); } - void SetPosChildNeedsLayout(bool b) { bitfields_.SetPosChildNeedsLayout(b); } + void SetPosChildNeedsLayout(bool b) { + CheckIsNotDestroyed(); + bitfields_.SetPosChildNeedsLayout(b); + } void SetNeedsSimplifiedNormalFlowLayout(bool b) { + CheckIsNotDestroyed(); bitfields_.SetNeedsSimplifiedNormalFlowLayout(b); }
diff --git a/third_party/blink/renderer/core/layout/layout_outside_list_marker.cc b/third_party/blink/renderer/core/layout/layout_outside_list_marker.cc index 812b3fa..521ae89 100644 --- a/third_party/blink/renderer/core/layout/layout_outside_list_marker.cc +++ b/third_party/blink/renderer/core/layout/layout_outside_list_marker.cc
@@ -12,10 +12,12 @@ LayoutOutsideListMarker::~LayoutOutsideListMarker() = default; bool LayoutOutsideListMarker::IsMarkerImage() const { + CheckIsNotDestroyed(); return list_marker_.IsMarkerImage(*this); } void LayoutOutsideListMarker::UpdateLayout() { + CheckIsNotDestroyed(); LayoutBlockFlow::UpdateLayout(); LayoutUnit block_offset = LogicalTop(); @@ -34,6 +36,7 @@ } void LayoutOutsideListMarker::UpdateMargins() { + CheckIsNotDestroyed(); LayoutUnit margin_start; LayoutUnit margin_end; std::tie(margin_start, margin_end) = ListMarker::InlineMarginsForOutside( @@ -47,6 +50,7 @@ bool first_line, LineDirectionMode direction, LinePositionMode line_position_mode) const { + CheckIsNotDestroyed(); if (line_position_mode == kPositionOfInteriorLineBoxes) { return list_marker_.ListItemBlockFlow(*this)->LineHeight( first_line, direction, line_position_mode); @@ -59,6 +63,7 @@ bool first_line, LineDirectionMode direction, LinePositionMode line_position_mode) const { + CheckIsNotDestroyed(); if (line_position_mode == kPositionOfInteriorLineBoxes) { return list_marker_.ListItemBlockFlow(*this)->BaselinePosition( baseline_type, first_line, direction, line_position_mode);
diff --git a/third_party/blink/renderer/core/layout/layout_outside_list_marker.h b/third_party/blink/renderer/core/layout/layout_outside_list_marker.h index 210bf25..ce32449 100644 --- a/third_party/blink/renderer/core/layout/layout_outside_list_marker.h +++ b/third_party/blink/renderer/core/layout/layout_outside_list_marker.h
@@ -18,19 +18,30 @@ explicit LayoutOutsideListMarker(Element*); ~LayoutOutsideListMarker() override; - const char* GetName() const override { return "LayoutOutsideListMarker"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutOutsideListMarker"; + } bool IsMarkerImage() const; LayoutUnit ListItemInlineStartOffset() const { + CheckIsNotDestroyed(); return list_item_inline_start_offset_; } void UpdateMargins(); - const ListMarker& Marker() const { return list_marker_; } - ListMarker& Marker() { return list_marker_; } + const ListMarker& Marker() const { + CheckIsNotDestroyed(); + return list_marker_; + } + ListMarker& Marker() { + CheckIsNotDestroyed(); + return list_marker_; + } private: bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectOutsideListMarker || LayoutBlockFlow::IsOfType(type); }
diff --git a/third_party/blink/renderer/core/layout/layout_progress.cc b/third_party/blink/renderer/core/layout/layout_progress.cc index 62d8d54..b936dfa8b 100644 --- a/third_party/blink/renderer/core/layout/layout_progress.cc +++ b/third_party/blink/renderer/core/layout/layout_progress.cc
@@ -49,6 +49,7 @@ LayoutProgress::~LayoutProgress() = default; void LayoutProgress::WillBeDestroyed() { + CheckIsNotDestroyed(); if (animating_) { animation_timer_.Stop(); animating_ = false; @@ -57,6 +58,7 @@ } void LayoutProgress::UpdateFromElement() { + CheckIsNotDestroyed(); HTMLProgressElement* element = ProgressElement(); if (position_ == element->position()) return; @@ -68,6 +70,7 @@ } double LayoutProgress::AnimationProgress() const { + CheckIsNotDestroyed(); if (!animating_) return 0; const base::TimeDelta elapsed = @@ -76,25 +79,30 @@ } bool LayoutProgress::IsDeterminate() const { + CheckIsNotDestroyed(); return (HTMLProgressElement::kIndeterminatePosition != GetPosition() && HTMLProgressElement::kInvalidPosition != GetPosition()); } bool LayoutProgress::IsAnimationTimerActive() const { + CheckIsNotDestroyed(); return animation_timer_.IsActive(); } bool LayoutProgress::IsAnimating() const { + CheckIsNotDestroyed(); return animating_; } void LayoutProgress::AnimationTimerFired(TimerBase*) { + CheckIsNotDestroyed(); SetShouldDoFullPaintInvalidation(); if (!animation_timer_.IsActive() && animating_) animation_timer_.StartOneShot(kAnimationInterval, FROM_HERE); } void LayoutProgress::UpdateAnimationState() { + CheckIsNotDestroyed(); bool animating = !IsDeterminate() && StyleRef().HasEffectiveAppearance(); if (animating == animating_) return; @@ -109,6 +117,7 @@ } HTMLProgressElement* LayoutProgress::ProgressElement() const { + CheckIsNotDestroyed(); return To<HTMLProgressElement>(GetNode()); }
diff --git a/third_party/blink/renderer/core/layout/layout_progress.h b/third_party/blink/renderer/core/layout/layout_progress.h index 8aaa11a..cb92bf8 100644 --- a/third_party/blink/renderer/core/layout/layout_progress.h +++ b/third_party/blink/renderer/core/layout/layout_progress.h
@@ -33,7 +33,10 @@ explicit LayoutProgress(Element* element); ~LayoutProgress() override; - double GetPosition() const { return position_; } + double GetPosition() const { + CheckIsNotDestroyed(); + return position_; + } double AnimationProgress() const; bool IsDeterminate() const; @@ -41,11 +44,15 @@ HTMLProgressElement* ProgressElement() const; - const char* GetName() const override { return "LayoutProgress"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutProgress"; + } protected: void WillBeDestroyed() override; bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectProgress || LayoutBlockFlow::IsOfType(type); }
diff --git a/third_party/blink/renderer/core/layout/layout_quote.cc b/third_party/blink/renderer/core/layout/layout_quote.cc index 7d50dce..88e1005 100644 --- a/third_party/blink/renderer/core/layout/layout_quote.cc +++ b/third_party/blink/renderer/core/layout/layout_quote.cc
@@ -50,17 +50,20 @@ } void LayoutQuote::WillBeDestroyed() { + CheckIsNotDestroyed(); DetachQuote(); LayoutInline::WillBeDestroyed(); } void LayoutQuote::WillBeRemovedFromTree() { + CheckIsNotDestroyed(); LayoutInline::WillBeRemovedFromTree(); DetachQuote(); } void LayoutQuote::StyleDidChange(StyleDifference diff, const ComputedStyle* old_style) { + CheckIsNotDestroyed(); LayoutInline::StyleDidChange(diff, old_style); UpdateText(); } @@ -275,6 +278,7 @@ } void LayoutQuote::UpdateText() { + CheckIsNotDestroyed(); String text = ComputeText(); if (text_ == text) return; @@ -296,6 +300,7 @@ } LayoutTextFragment* LayoutQuote::FindFragmentChild() const { + CheckIsNotDestroyed(); // We walk from the end of the child list because, if we've had a first-letter // LayoutObject inserted then the remaining text will be at the end. while (LayoutObject* child = LastChild()) { @@ -307,6 +312,7 @@ } String LayoutQuote::ComputeText() const { + CheckIsNotDestroyed(); switch (type_) { case QuoteType::kNoOpen: case QuoteType::kNoClose: @@ -321,6 +327,7 @@ } const QuotesData* LayoutQuote::GetQuotesData() const { + CheckIsNotDestroyed(); if (const QuotesData* custom_quotes = StyleRef().Quotes()) return custom_quotes; @@ -331,6 +338,7 @@ } void LayoutQuote::AttachQuote() { + CheckIsNotDestroyed(); DCHECK(View()); DCHECK(!attached_); DCHECK(!next_); @@ -375,6 +383,7 @@ } void LayoutQuote::DetachQuote() { + CheckIsNotDestroyed(); DCHECK(!next_ || next_->attached_); DCHECK(!previous_ || previous_->attached_); if (!attached_) @@ -401,6 +410,7 @@ } void LayoutQuote::UpdateDepth() { + CheckIsNotDestroyed(); DCHECK(attached_); int old_depth = depth_; depth_ = 0;
diff --git a/third_party/blink/renderer/core/layout/layout_quote.h b/third_party/blink/renderer/core/layout/layout_quote.h index 1852f6e..dac6e6b 100644 --- a/third_party/blink/renderer/core/layout/layout_quote.h +++ b/third_party/blink/renderer/core/layout/layout_quote.h
@@ -44,13 +44,17 @@ ~LayoutQuote() override; void AttachQuote(); - const char* GetName() const override { return "LayoutQuote"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutQuote"; + } private: void DetachQuote(); void WillBeDestroyed() override; bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectQuote || LayoutInline::IsOfType(type); } void StyleDidChange(StyleDifference, const ComputedStyle*) override; @@ -60,7 +64,10 @@ void UpdateText(); const QuotesData* GetQuotesData() const; void UpdateDepth(); - bool IsAttached() { return attached_; } + bool IsAttached() { + CheckIsNotDestroyed(); + return attached_; + } LayoutTextFragment* FindFragmentChild() const;
diff --git a/third_party/blink/renderer/core/layout/layout_replaced.cc b/third_party/blink/renderer/core/layout/layout_replaced.cc index 652452e7..59f2a90 100644 --- a/third_party/blink/renderer/core/layout/layout_replaced.cc +++ b/third_party/blink/renderer/core/layout/layout_replaced.cc
@@ -66,6 +66,7 @@ LayoutReplaced::~LayoutReplaced() = default; void LayoutReplaced::WillBeDestroyed() { + CheckIsNotDestroyed(); if (!DocumentBeingDestroyed() && Parent()) Parent()->DirtyLinesFromChangedChild(this); @@ -74,6 +75,7 @@ void LayoutReplaced::StyleDidChange(StyleDifference diff, const ComputedStyle* old_style) { + CheckIsNotDestroyed(); LayoutBox::StyleDidChange(diff, old_style); // Replaced elements can have border-radius clips without clipping overflow; @@ -92,6 +94,7 @@ } void LayoutReplaced::UpdateLayout() { + CheckIsNotDestroyed(); DCHECK(NeedsLayout()); LayoutAnalyzer::Scope analyzer(*this); @@ -112,6 +115,7 @@ } void LayoutReplaced::IntrinsicSizeChanged() { + CheckIsNotDestroyed(); int scaled_width = static_cast<int>(kDefaultWidth * StyleRef().EffectiveZoom()); int scaled_height = @@ -122,10 +126,12 @@ } void LayoutReplaced::Paint(const PaintInfo& paint_info) const { + CheckIsNotDestroyed(); ReplacedPainter(*this).Paint(paint_info); } bool LayoutReplaced::HasReplacedLogicalHeight() const { + CheckIsNotDestroyed(); if (StyleRef().LogicalHeight().IsAuto()) return false; @@ -142,6 +148,7 @@ } bool LayoutReplaced::NeedsPreferredWidthsRecalculation() const { + CheckIsNotDestroyed(); // If the height is a percentage and the width is auto, then the // containingBlocks's height changing can cause this node to change it's // preferred width because it maintains aspect ratio. @@ -156,6 +163,7 @@ } void LayoutReplaced::RecalcVisualOverflow() { + CheckIsNotDestroyed(); ClearVisualOverflow(); LayoutObject::RecalcVisualOverflow(); AddVisualEffectOverflow(); @@ -163,6 +171,7 @@ void LayoutReplaced::ComputeIntrinsicSizingInfoForReplacedContent( IntrinsicSizingInfo& intrinsic_sizing_info) const { + CheckIsNotDestroyed(); // In cases where we apply size containment we don't need to compute sizing // information, since the final result does not depend on it. if (ShouldApplySizeContainment()) { @@ -202,6 +211,7 @@ FloatSize LayoutReplaced::ConstrainIntrinsicSizeToMinMax( const IntrinsicSizingInfo& intrinsic_sizing_info) const { + CheckIsNotDestroyed(); // Constrain the intrinsic size along each axis according to minimum and // maximum width/heights along the opposite axis. So for example a maximum // width that shrinks our width will result in the height we compute here @@ -230,6 +240,7 @@ void LayoutReplaced::ComputePositionedLogicalWidth( LogicalExtentComputedValues& computed_values) const { + CheckIsNotDestroyed(); // The following is based off of the W3C Working Draft from April 11, 2006 of // CSS 2.1: Section 10.3.8 "Absolutely positioned, replaced elements" // <http://www.w3.org/TR/2005/WD-CSS21-20050613/visudet.html#abs-replaced-width> @@ -449,6 +460,7 @@ void LayoutReplaced::ComputePositionedLogicalHeight( LogicalExtentComputedValues& computed_values) const { + CheckIsNotDestroyed(); // The following is based off of the W3C Working Draft from April 11, 2006 of // CSS 2.1: Section 10.6.5 "Absolutely positioned, replaced elements" // <http://www.w3.org/TR/2005/WD-CSS21-20050613/visudet.html#abs-replaced-height> @@ -607,6 +619,7 @@ PhysicalRect LayoutReplaced::ComputeObjectFit( const LayoutSize* overridden_intrinsic_size) const { + CheckIsNotDestroyed(); PhysicalRect content_rect = PhysicalContentBoxRect(); EObjectFit object_fit = StyleRef().GetObjectFit(); @@ -669,6 +682,7 @@ } PhysicalRect LayoutReplaced::ReplacedContentRect() const { + CheckIsNotDestroyed(); return ComputeObjectFit(); } @@ -679,6 +693,7 @@ void LayoutReplaced::ComputeIntrinsicSizingInfo( IntrinsicSizingInfo& intrinsic_sizing_info) const { + CheckIsNotDestroyed(); DCHECK(!ShouldApplySizeContainment()); intrinsic_sizing_info.size = FloatSize(IntrinsicLogicalWidth().ToFloat(), IntrinsicLogicalHeight().ToFloat()); @@ -729,6 +744,7 @@ LayoutUnit LayoutReplaced::ComputeConstrainedLogicalWidth( ShouldComputePreferred should_compute_preferred) const { + CheckIsNotDestroyed(); if (should_compute_preferred == kComputePreferred) return ComputeReplacedLogicalWidthRespectingMinMaxWidth(LayoutUnit(), kComputePreferred); @@ -753,6 +769,7 @@ LayoutUnit LayoutReplaced::ComputeReplacedLogicalWidth( ShouldComputePreferred should_compute_preferred) const { + CheckIsNotDestroyed(); if (StyleRef().LogicalWidth().IsSpecified() || StyleRef().LogicalWidth().IsIntrinsic()) return ComputeReplacedLogicalWidthRespectingMinMaxWidth( @@ -838,6 +855,7 @@ LayoutUnit LayoutReplaced::ComputeReplacedLogicalHeight( LayoutUnit estimated_used_width) const { + CheckIsNotDestroyed(); // 10.5 Content height: the 'height' property: // http://www.w3.org/TR/CSS21/visudet.html#propdef-height if (HasReplacedLogicalHeight()) { @@ -889,12 +907,14 @@ } MinMaxSizes LayoutReplaced::ComputeIntrinsicLogicalWidths() const { + CheckIsNotDestroyed(); MinMaxSizes sizes; sizes += BorderAndPaddingLogicalWidth() + IntrinsicLogicalWidth(); return sizes; } MinMaxSizes LayoutReplaced::PreferredLogicalWidths() const { + CheckIsNotDestroyed(); MinMaxSizes sizes; // We cannot resolve some logical width here (i.e. percent, fill-available or @@ -980,6 +1000,7 @@ PositionWithAffinity LayoutReplaced::PositionForPoint( const PhysicalOffset& point) const { + CheckIsNotDestroyed(); LayoutUnit top; LayoutUnit bottom; std::tie(top, bottom) = SelectionTopAndBottom(*this); @@ -1014,6 +1035,7 @@ } PhysicalRect LayoutReplaced::LocalSelectionVisualRect() const { + CheckIsNotDestroyed(); if (GetSelectionState() == SelectionState::kNone || GetSelectionState() == SelectionState::kContain) { return PhysicalRect();
diff --git a/third_party/blink/renderer/core/layout/layout_replaced.h b/third_party/blink/renderer/core/layout/layout_replaced.h index d501a40..e3e056f 100644 --- a/third_party/blink/renderer/core/layout/layout_replaced.h +++ b/third_party/blink/renderer/core/layout/layout_replaced.h
@@ -77,13 +77,19 @@ // http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-width static const int kDefaultWidth; static const int kDefaultHeight; - bool CanHaveChildren() const override { return false; } + bool CanHaveChildren() const override { + CheckIsNotDestroyed(); + return false; + } virtual void PaintReplaced(const PaintInfo&, - const PhysicalOffset& paint_offset) const {} + const PhysicalOffset& paint_offset) const { + CheckIsNotDestroyed(); + } PhysicalRect LocalSelectionVisualRect() const final; bool HasObjectFit() const { + CheckIsNotDestroyed(); return StyleRef().GetObjectFit() != ComputedStyleInitialValues::InitialObjectFit(); } @@ -108,10 +114,12 @@ void UpdateLayout() override; LayoutSize IntrinsicSize() const final { + CheckIsNotDestroyed(); return LayoutSize(IntrinsicWidth(), IntrinsicHeight()); } LayoutUnit IntrinsicWidth() const { + CheckIsNotDestroyed(); if (HasOverrideIntrinsicContentWidth()) return OverrideIntrinsicContentWidth(); else if (ShouldApplySizeContainment()) @@ -119,6 +127,7 @@ return intrinsic_size_.Width(); } LayoutUnit IntrinsicHeight() const { + CheckIsNotDestroyed(); if (HasOverrideIntrinsicContentHeight()) return OverrideIntrinsicContentHeight(); else if (ShouldApplySizeContainment()) @@ -140,20 +149,26 @@ const LayoutSize* overridden_intrinsic_size = nullptr) const; LayoutUnit IntrinsicContentLogicalHeight() const override { + CheckIsNotDestroyed(); return IntrinsicLogicalHeight(); } - virtual LayoutUnit MinimumReplacedHeight() const { return LayoutUnit(); } + virtual LayoutUnit MinimumReplacedHeight() const { + CheckIsNotDestroyed(); + return LayoutUnit(); + } void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override; void SetIntrinsicSize(const LayoutSize& intrinsic_size) { + CheckIsNotDestroyed(); intrinsic_size_ = intrinsic_size; } PositionWithAffinity PositionForPoint(const PhysicalOffset&) const override; bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectLayoutReplaced || LayoutBox::IsOfType(type); }
diff --git a/third_party/blink/renderer/core/layout/layout_ruby.cc b/third_party/blink/renderer/core/layout/layout_ruby.cc index 61ea140..c74dc4c 100644 --- a/third_party/blink/renderer/core/layout/layout_ruby.cc +++ b/third_party/blink/renderer/core/layout/layout_ruby.cc
@@ -61,12 +61,14 @@ void LayoutRubyAsInline::StyleDidChange(StyleDifference diff, const ComputedStyle* old_style) { + CheckIsNotDestroyed(); LayoutInline::StyleDidChange(diff, old_style); PropagateStyleToAnonymousChildren(); } void LayoutRubyAsInline::AddChild(LayoutObject* child, LayoutObject* before_child) { + CheckIsNotDestroyed(); // If the child is a ruby run, just add it normally. if (child->IsRubyRun()) { LayoutInline::AddChild(child, before_child); @@ -101,6 +103,7 @@ } void LayoutRubyAsInline::RemoveChild(LayoutObject* child) { + CheckIsNotDestroyed(); // If the child's parent is *this (must be a ruby run), just use the normal // remove method. if (child->Parent() == this) { @@ -126,12 +129,14 @@ void LayoutRubyAsBlock::StyleDidChange(StyleDifference diff, const ComputedStyle* old_style) { + CheckIsNotDestroyed(); LayoutBlockFlow::StyleDidChange(diff, old_style); PropagateStyleToAnonymousChildren(); } void LayoutRubyAsBlock::AddChild(LayoutObject* child, LayoutObject* before_child) { + CheckIsNotDestroyed(); // If the child is a ruby run, just add it normally. if (child->IsRubyRun()) { LayoutBlockFlow::AddChild(child, before_child); @@ -166,6 +171,7 @@ } void LayoutRubyAsBlock::RemoveChild(LayoutObject* child) { + CheckIsNotDestroyed(); // If the child's parent is *this (must be a ruby run), just use the normal // remove method. if (child->Parent() == this) {
diff --git a/third_party/blink/renderer/core/layout/layout_ruby.h b/third_party/blink/renderer/core/layout/layout_ruby.h index 66747efa..76a7ef5b 100644 --- a/third_party/blink/renderer/core/layout/layout_ruby.h +++ b/third_party/blink/renderer/core/layout/layout_ruby.h
@@ -64,16 +64,23 @@ LayoutObject* before_child = nullptr) override; void RemoveChild(LayoutObject* child) override; - const char* GetName() const override { return "LayoutRuby (inline)"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutRuby (inline)"; + } protected: void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override; private: bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectRuby || LayoutInline::IsOfType(type); } - bool CreatesAnonymousWrapper() const override { return true; } + bool CreatesAnonymousWrapper() const override { + CheckIsNotDestroyed(); + return true; + } }; // <ruby> when used as 'display:block' or 'display:inline-block' @@ -86,17 +93,27 @@ LayoutObject* before_child = nullptr) override; void RemoveChild(LayoutObject* child) override; - const char* GetName() const override { return "LayoutRuby (block)"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutRuby (block)"; + } protected: void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override; bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectRuby || LayoutBlockFlow::IsOfType(type); } private: - bool CreatesAnonymousWrapper() const override { return true; } - void RemoveLeftoverAnonymousBlock(LayoutBlock*) override { NOTREACHED(); } + bool CreatesAnonymousWrapper() const override { + CheckIsNotDestroyed(); + return true; + } + void RemoveLeftoverAnonymousBlock(LayoutBlock*) override { + CheckIsNotDestroyed(); + NOTREACHED(); + } }; } // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_ruby_base.cc b/third_party/blink/renderer/core/layout/layout_ruby_base.cc index 6418d0a3..32e173f3 100644 --- a/third_party/blink/renderer/core/layout/layout_ruby_base.cc +++ b/third_party/blink/renderer/core/layout/layout_ruby_base.cc
@@ -57,11 +57,13 @@ bool LayoutRubyBase::IsChildAllowed(LayoutObject* child, const ComputedStyle&) const { + CheckIsNotDestroyed(); return child->IsInline(); } void LayoutRubyBase::MoveChildren(LayoutRubyBase* to_base, LayoutObject* before_child) { + CheckIsNotDestroyed(); // This function removes all children that are before (!) beforeChild // and appends them to toBase. DCHECK(to_base); @@ -84,6 +86,7 @@ void LayoutRubyBase::MoveInlineChildren(LayoutRubyBase* to_base, LayoutObject* before_child) { + CheckIsNotDestroyed(); DCHECK(ChildrenInline()); DCHECK(to_base); @@ -112,6 +115,7 @@ void LayoutRubyBase::MoveBlockChildren(LayoutRubyBase* to_base, LayoutObject* before_child) { + CheckIsNotDestroyed(); DCHECK(!ChildrenInline()); DCHECK(to_base); @@ -163,6 +167,7 @@ unsigned expansion_opportunity_count, LayoutUnit& logical_left, LayoutUnit& logical_width) const { + CheckIsNotDestroyed(); int max_preferred_logical_width = PreferredLogicalWidths().max_size.ToInt(); if (max_preferred_logical_width >= logical_width) return;
diff --git a/third_party/blink/renderer/core/layout/layout_ruby_base.h b/third_party/blink/renderer/core/layout/layout_ruby_base.h index 6e474be..b4d85ca 100644 --- a/third_party/blink/renderer/core/layout/layout_ruby_base.h +++ b/third_party/blink/renderer/core/layout/layout_ruby_base.h
@@ -45,9 +45,13 @@ static LayoutRubyBase* CreateAnonymous(Document*, const LayoutRubyRun& ruby_run); - const char* GetName() const override { return "LayoutRubyBase"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutRubyBase"; + } bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectRubyBase || LayoutBlockFlow::IsOfType(type); }
diff --git a/third_party/blink/renderer/core/layout/layout_ruby_run.cc b/third_party/blink/renderer/core/layout/layout_ruby_run.cc index 99a1658..49a3d78a 100644 --- a/third_party/blink/renderer/core/layout/layout_ruby_run.cc +++ b/third_party/blink/renderer/core/layout/layout_ruby_run.cc
@@ -46,6 +46,7 @@ LayoutRubyRun::~LayoutRubyRun() = default; bool LayoutRubyRun::HasRubyText() const { + CheckIsNotDestroyed(); // The only place where a ruby text can be is in the first position // Note: As anonymous blocks, ruby runs do not have ':before' or ':after' // content themselves. @@ -53,6 +54,7 @@ } bool LayoutRubyRun::HasRubyBase() const { + CheckIsNotDestroyed(); // The only place where a ruby base can be is in the last position // Note: As anonymous blocks, ruby runs do not have ':before' or ':after' // content themselves. @@ -60,6 +62,7 @@ } LayoutRubyText* LayoutRubyRun::RubyText() const { + CheckIsNotDestroyed(); LayoutObject* child = FirstChild(); // If in future it becomes necessary to support floating or positioned ruby // text, layout will have to be changed to handle them properly. @@ -70,12 +73,14 @@ } LayoutRubyBase* LayoutRubyRun::RubyBase() const { + CheckIsNotDestroyed(); LayoutObject* child = LastChild(); return child && child->IsRubyBase() ? static_cast<LayoutRubyBase*>(child) : nullptr; } LayoutRubyBase* LayoutRubyRun::RubyBaseSafe() { + CheckIsNotDestroyed(); LayoutRubyBase* base = RubyBase(); if (!base) { base = CreateRubyBase(); @@ -86,10 +91,12 @@ bool LayoutRubyRun::IsChildAllowed(LayoutObject* child, const ComputedStyle&) const { + CheckIsNotDestroyed(); return child->IsRubyText() || child->IsInline(); } void LayoutRubyRun::AddChild(LayoutObject* child, LayoutObject* before_child) { + CheckIsNotDestroyed(); DCHECK(child); if (child->IsRubyText()) { @@ -143,6 +150,7 @@ } void LayoutRubyRun::RemoveChild(LayoutObject* child) { + CheckIsNotDestroyed(); // If the child is a ruby text, then merge the ruby base with the base of // the right sibling run, if possible. if (!BeingDestroyed() && !DocumentBeingDestroyed() && child->IsRubyText()) { @@ -183,6 +191,7 @@ } LayoutRubyBase* LayoutRubyRun::CreateRubyBase() const { + CheckIsNotDestroyed(); LayoutRubyBase* layout_object = LayoutRubyBase::CreateAnonymous(&GetDocument(), *this); scoped_refptr<ComputedStyle> new_style = @@ -216,6 +225,7 @@ LayoutObject* LayoutRubyRun::LayoutSpecialExcludedChild( bool relayout_children, SubtreeLayoutScope& layout_scope) { + CheckIsNotDestroyed(); // Don't bother positioning the LayoutRubyRun yet. LayoutRubyText* rt = RubyText(); if (!rt) @@ -227,6 +237,7 @@ } void LayoutRubyRun::UpdateLayout() { + CheckIsNotDestroyed(); LayoutBlockFlow::UpdateLayout(); LayoutRubyText* rt = RubyText(); @@ -280,6 +291,7 @@ LayoutObject* end_layout_object, int& start_overhang, int& end_overhang) const { + CheckIsNotDestroyed(); DCHECK(!NeedsLayout()); start_overhang = 0; @@ -339,6 +351,7 @@ bool LayoutRubyRun::CanBreakBefore( const LazyLineBreakIterator& iterator) const { + CheckIsNotDestroyed(); // TODO(kojii): It would be nice to improve this so that it isn't just // hard-coded, but lookahead in this case is particularly problematic. // See crbug.com/522826.
diff --git a/third_party/blink/renderer/core/layout/layout_ruby_run.h b/third_party/blink/renderer/core/layout/layout_ruby_run.h index 163a978..a54dda3 100644 --- a/third_party/blink/renderer/core/layout/layout_ruby_run.h +++ b/third_party/blink/renderer/core/layout/layout_ruby_run.h
@@ -77,7 +77,10 @@ bool CanBreakBefore(const LazyLineBreakIterator&) const; - const char* GetName() const override { return "LayoutRubyRun"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutRubyRun"; + } protected: LayoutRubyBase* CreateRubyBase() const; @@ -87,10 +90,16 @@ explicit LayoutRubyRun(Element*); bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectRubyRun || LayoutBlockFlow::IsOfType(type); } - bool CreatesAnonymousWrapper() const override { return true; } - void RemoveLeftoverAnonymousBlock(LayoutBlock*) override {} + bool CreatesAnonymousWrapper() const override { + CheckIsNotDestroyed(); + return true; + } + void RemoveLeftoverAnonymousBlock(LayoutBlock*) override { + CheckIsNotDestroyed(); + } friend class LayoutNGMixin<LayoutRubyRun>; };
diff --git a/third_party/blink/renderer/core/layout/layout_ruby_text.cc b/third_party/blink/renderer/core/layout/layout_ruby_text.cc index 7c304fd..ed5f809 100644 --- a/third_party/blink/renderer/core/layout/layout_ruby_text.cc +++ b/third_party/blink/renderer/core/layout/layout_ruby_text.cc
@@ -39,11 +39,13 @@ bool LayoutRubyText::IsChildAllowed(LayoutObject* child, const ComputedStyle&) const { + CheckIsNotDestroyed(); return child->IsInline(); } void LayoutRubyText::StyleDidChange(StyleDifference diff, const ComputedStyle* old_style) { + CheckIsNotDestroyed(); if (StyleRef().GetTextAlign() != ComputedStyleInitialValues::InitialTextAlign()) { UseCounter::Count(GetDocument(), @@ -54,6 +56,7 @@ ETextAlign LayoutRubyText::TextAlignmentForLine( bool ends_with_soft_break) const { + CheckIsNotDestroyed(); ETextAlign text_align = StyleRef().GetTextAlign(); // FIXME: This check is bogus since user can set the initial value. if (text_align != ComputedStyleInitialValues::InitialTextAlign()) @@ -68,6 +71,7 @@ unsigned expansion_opportunity_count, LayoutUnit& logical_left, LayoutUnit& logical_width) const { + CheckIsNotDestroyed(); ETextAlign text_align = StyleRef().GetTextAlign(); // FIXME: This check is bogus since user can set the initial value. if (text_align != ComputedStyleInitialValues::InitialTextAlign()) {
diff --git a/third_party/blink/renderer/core/layout/layout_ruby_text.h b/third_party/blink/renderer/core/layout/layout_ruby_text.h index c2f43d6..e95b32b 100644 --- a/third_party/blink/renderer/core/layout/layout_ruby_text.h +++ b/third_party/blink/renderer/core/layout/layout_ruby_text.h
@@ -40,9 +40,13 @@ LayoutRubyText(Element*); ~LayoutRubyText() override; - const char* GetName() const override { return "LayoutRubyText"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutRubyText"; + } bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectRubyText || LayoutBlockFlow::IsOfType(type); } @@ -52,6 +56,7 @@ const ComputedStyle* old_style) override; bool CreatesNewFormattingContext() const final { + CheckIsNotDestroyed(); // Ruby text objects are pushed around after layout, to become flush with // the associated ruby base. As such, we cannot let floats leak out from // ruby text objects.
diff --git a/third_party/blink/renderer/core/layout/layout_slider_track.cc b/third_party/blink/renderer/core/layout/layout_slider_track.cc index ad86503..46e121c6 100644 --- a/third_party/blink/renderer/core/layout/layout_slider_track.cc +++ b/third_party/blink/renderer/core/layout/layout_slider_track.cc
@@ -41,6 +41,7 @@ : LayoutBlockFlow(element) {} void LayoutSliderTrack::UpdateLayout() { + CheckIsNotDestroyed(); auto* input = To<HTMLInputElement>(GetNode()->OwnerShadowHost()); const bool is_vertical = !StyleRef().IsHorizontalWritingMode();
diff --git a/third_party/blink/renderer/core/layout/layout_table.cc b/third_party/blink/renderer/core/layout/layout_table.cc index bb36cba..c1f97d6 100644 --- a/third_party/blink/renderer/core/layout/layout_table.cc +++ b/third_party/blink/renderer/core/layout/layout_table.cc
@@ -83,6 +83,7 @@ void LayoutTable::StyleDidChange(StyleDifference diff, const ComputedStyle* old_style) { + CheckIsNotDestroyed(); LayoutBlock::StyleDidChange(diff, old_style); if (ShouldCollapseBorders()) @@ -148,6 +149,7 @@ } void LayoutTable::AddChild(LayoutObject* child, LayoutObject* before_child) { + CheckIsNotDestroyed(); bool wrap_in_anonymous_section = !child->IsOutOfFlowPositioned(); if (child->IsTableCaption()) { @@ -238,11 +240,13 @@ } void LayoutTable::AddCaption(const LayoutTableCaption* caption) { + CheckIsNotDestroyed(); DCHECK_EQ(captions_.Find(caption), kNotFound); captions_.push_back(const_cast<LayoutTableCaption*>(caption)); } void LayoutTable::RemoveCaption(const LayoutTableCaption* old_caption) { + CheckIsNotDestroyed(); wtf_size_t index = captions_.Find(old_caption); DCHECK_NE(index, kNotFound); if (index == kNotFound) @@ -252,11 +256,13 @@ } void LayoutTable::InvalidateCachedColumns() { + CheckIsNotDestroyed(); column_layout_objects_valid_ = false; column_layout_objects_.resize(0); } void LayoutTable::ColumnStructureChanged() { + CheckIsNotDestroyed(); column_structure_changed_ = true; InvalidateCachedColumns(); // We don't really need to recompute our sections, but we do need to update @@ -266,41 +272,50 @@ } void LayoutTable::AddColumn(const LayoutTableCol*) { + CheckIsNotDestroyed(); ColumnStructureChanged(); } void LayoutTable::RemoveColumn(const LayoutTableCol*) { + CheckIsNotDestroyed(); ColumnStructureChanged(); } LayoutNGTableSectionInterface* LayoutTable::FirstBodyInterface() const { + CheckIsNotDestroyed(); return FirstBody(); } LayoutNGTableSectionInterface* LayoutTable::TopSectionInterface() const { + CheckIsNotDestroyed(); return TopSection(); } LayoutNGTableSectionInterface* LayoutTable::BottomSectionInterface() const { + CheckIsNotDestroyed(); return BottomSection(); } LayoutNGTableSectionInterface* LayoutTable::TopNonEmptySectionInterface() const { + CheckIsNotDestroyed(); return TopNonEmptySection(); } LayoutNGTableSectionInterface* LayoutTable::SectionBelowInterface( const LayoutNGTableSectionInterface* section, SkipEmptySectionsValue skip_empty_sections) const { + CheckIsNotDestroyed(); return SectionBelow(section->ToLayoutTableSection(), skip_empty_sections); } LayoutNGTableSectionInterface* LayoutTable::BottomNonEmptySectionInterface() const { + CheckIsNotDestroyed(); return BottomNonEmptySection(); } bool LayoutTable::IsLogicalWidthAuto() const { + CheckIsNotDestroyed(); const Length& style_logical_width = StyleRef().LogicalWidth(); return (!style_logical_width.IsSpecified() || !style_logical_width.IsPositive()) && @@ -308,6 +323,7 @@ } void LayoutTable::UpdateLogicalWidth() { + CheckIsNotDestroyed(); RecalcSectionsIfNeeded(); // Recalculate the intrinsic logical widths now, rather than relying on them @@ -442,6 +458,7 @@ LayoutUnit LayoutTable::ConvertStyleLogicalWidthToComputedWidth( const Length& style_logical_width, LayoutUnit available_width) const { + CheckIsNotDestroyed(); if (style_logical_width.IsIntrinsic()) { return ComputeIntrinsicLogicalWidthUsing(style_logical_width, available_width); @@ -464,6 +481,7 @@ LayoutUnit LayoutTable::ConvertStyleLogicalHeightToComputedHeight( const Length& style_logical_height) const { + CheckIsNotDestroyed(); LayoutUnit border_and_padding_before = BorderBefore() + (ShouldCollapseBorders() ? LayoutUnit() : PaddingBefore()); @@ -499,6 +517,7 @@ void LayoutTable::LayoutCaption(LayoutTableCaption& caption, SubtreeLayoutScope& layouter) { + CheckIsNotDestroyed(); if (!caption.NeedsLayout()) MarkChildForPaginationRelayoutIfNeeded(caption, layouter); if (caption.NeedsLayout()) { @@ -533,6 +552,7 @@ SubtreeLayoutScope& layouter, LayoutUnit logical_left, TableHeightChangingValue table_height_changing) { + CheckIsNotDestroyed(); section.SetLogicalLocation(LayoutPoint(logical_left, LogicalHeight())); if (column_logical_width_changed_) layouter.SetChildNeedsLayout(§ion); @@ -552,6 +572,7 @@ } LayoutUnit LayoutTable::LogicalHeightFromStyle() const { + CheckIsNotDestroyed(); LayoutUnit computed_logical_height; const Length& logical_height_length = StyleRef().LogicalHeight(); if (logical_height_length.IsIntrinsic() || @@ -595,6 +616,7 @@ } void LayoutTable::DistributeExtraLogicalHeight(int extra_logical_height) { + CheckIsNotDestroyed(); if (extra_logical_height <= 0) return; @@ -608,6 +630,7 @@ } void LayoutTable::SimplifiedNormalFlowLayout() { + CheckIsNotDestroyed(); // FIXME: We should walk through the items in the tree in tree order to do the // layout here instead of walking through individual parts of the tree. // crbug.com/442737 @@ -624,6 +647,7 @@ } bool LayoutTable::RecalcLayoutOverflow() { + CheckIsNotDestroyed(); RecalcSelfLayoutOverflow(); if (!ChildNeedsLayoutOverflowRecalc()) @@ -646,6 +670,7 @@ } void LayoutTable::RecalcVisualOverflow() { + CheckIsNotDestroyed(); for (auto* caption : captions_) { if (!caption->HasSelfPaintingLayer()) caption->RecalcVisualOverflow(); @@ -662,6 +687,7 @@ } void LayoutTable::UpdateLayout() { + CheckIsNotDestroyed(); DCHECK(NeedsLayout()); LayoutAnalyzer::Scope analyzer(*this); @@ -893,6 +919,7 @@ void LayoutTable::AdjustWidthsForCollapsedColumns( Vector<int>& col_collapsed_width) { + CheckIsNotDestroyed(); DCHECK(!col_collapsed_width.size()); if (!RuntimeEnabledFeatures::VisibilityCollapseColumnEnabled()) return; @@ -931,6 +958,7 @@ bool LayoutTable::IsAbsoluteColumnCollapsed( unsigned absolute_column_index) const { + CheckIsNotDestroyed(); ColAndColGroup colElement = ColElementAtAbsoluteColumn(absolute_column_index); LayoutTableCol* col = colElement.col; LayoutTableCol* colgroup = colElement.colgroup; @@ -940,6 +968,7 @@ } void LayoutTable::InvalidateCollapsedBorders() { + CheckIsNotDestroyed(); collapsed_borders_valid_ = false; needs_invalidate_collapsed_borders_for_all_cells_ = true; collapsed_outer_borders_valid_ = false; @@ -947,6 +976,7 @@ } void LayoutTable::InvalidateCollapsedBordersForAllCellsIfNeeded() { + CheckIsNotDestroyed(); DCHECK(ShouldCollapseBorders()); if (!needs_invalidate_collapsed_borders_for_all_cells_) @@ -971,6 +1001,7 @@ } void LayoutTable::ComputeVisualOverflow(bool) { + CheckIsNotDestroyed(); LayoutRect previous_visual_overflow_rect = VisualOverflowRect(); ClearVisualOverflow(); AddVisualOverflowFromChildren(); @@ -984,6 +1015,7 @@ } void LayoutTable::AddVisualOverflowFromChildren() { + CheckIsNotDestroyed(); // Add overflow from borders. // Technically it's odd that we are incorporating the borders into layout // overflow, which is only supposed to be about overflow from our @@ -1015,6 +1047,7 @@ } void LayoutTable::AddLayoutOverflowFromChildren() { + CheckIsNotDestroyed(); // Add overflow from borders. // Technically it's odd that we are incorporating the borders into layout // overflow, which is only supposed to be about overflow from our @@ -1047,10 +1080,12 @@ void LayoutTable::PaintObject(const PaintInfo& paint_info, const PhysicalOffset& paint_offset) const { + CheckIsNotDestroyed(); TablePainter(*this).PaintObject(paint_info, paint_offset); } void LayoutTable::SubtractCaptionRect(PhysicalRect& rect) const { + CheckIsNotDestroyed(); for (unsigned i = 0; i < captions_.size(); i++) { LayoutUnit caption_logical_height = captions_[i]->LogicalHeight() + captions_[i]->MarginBefore() + @@ -1072,6 +1107,7 @@ void LayoutTable::MarkAllCellsWidthsDirtyAndOrNeedsLayout( WhatToMarkAllCells what_to_mark) { + CheckIsNotDestroyed(); for (LayoutObject* child = Children()->FirstChild(); child; child = child->NextSibling()) { if (!child->IsTableSection()) @@ -1084,15 +1120,18 @@ void LayoutTable::PaintBoxDecorationBackground( const PaintInfo& paint_info, const PhysicalOffset& paint_offset) const { + CheckIsNotDestroyed(); TablePainter(*this).PaintBoxDecorationBackground(paint_info, paint_offset); } void LayoutTable::PaintMask(const PaintInfo& paint_info, const PhysicalOffset& paint_offset) const { + CheckIsNotDestroyed(); TablePainter(*this).PaintMask(paint_info, paint_offset); } MinMaxSizes LayoutTable::ComputeIntrinsicLogicalWidths() const { + CheckIsNotDestroyed(); RecalcSectionsIfNeeded(); // FIXME: Restructure the table layout code so that we can make this method // const. @@ -1107,6 +1146,7 @@ } MinMaxSizes LayoutTable::PreferredLogicalWidths() const { + CheckIsNotDestroyed(); MinMaxSizes sizes = IntrinsicLogicalWidths(); table_layout_->ApplyPreferredLogicalWidthQuirks(sizes.min_size, @@ -1148,6 +1188,7 @@ } LayoutTableSection* LayoutTable::TopNonEmptySection() const { + CheckIsNotDestroyed(); LayoutTableSection* section = TopSection(); if (section && !section->NumRows()) section = SectionBelow(section, kSkipEmptySections); @@ -1155,6 +1196,7 @@ } LayoutTableSection* LayoutTable::BottomNonEmptySection() const { + CheckIsNotDestroyed(); LayoutTableSection* section = BottomSection(); if (section && !section->NumRows()) section = SectionAbove(section, kSkipEmptySections); @@ -1162,6 +1204,7 @@ } void LayoutTable::SplitEffectiveColumn(unsigned index, unsigned first_span) { + CheckIsNotDestroyed(); // We split the column at |index|, taking |firstSpan| cells from the span. DCHECK_GT(effective_columns_[index].span, first_span); effective_columns_.insert(index, first_span); @@ -1186,6 +1229,7 @@ } void LayoutTable::AppendEffectiveColumn(unsigned span) { + CheckIsNotDestroyed(); unsigned new_column_index = effective_columns_.size(); effective_columns_.push_back(span); @@ -1215,6 +1259,7 @@ } LayoutTableCol* LayoutTable::FirstColumn() const { + CheckIsNotDestroyed(); for (LayoutObject* child = FirstChild(); child; child = child->NextSibling()) { if (child->IsLayoutTableCol()) @@ -1225,6 +1270,7 @@ } void LayoutTable::UpdateColumnCache() const { + CheckIsNotDestroyed(); DCHECK(has_col_elements_); DCHECK(column_layout_objects_.IsEmpty()); DCHECK(!column_layout_objects_valid_); @@ -1243,6 +1289,7 @@ LayoutTable::ColAndColGroup LayoutTable::SlowColElementAtAbsoluteColumn( unsigned absolute_column_index) const { + CheckIsNotDestroyed(); DCHECK(has_col_elements_); if (!column_layout_objects_valid_) @@ -1283,6 +1330,7 @@ } void LayoutTable::RecalcSections() const { + CheckIsNotDestroyed(); DCHECK(needs_section_recalc_); head_ = nullptr; @@ -1360,6 +1408,7 @@ } LayoutUnit LayoutTable::BorderLeft() const { + CheckIsNotDestroyed(); if (ShouldCollapseBorders()) { UpdateCollapsedOuterBorders(); return LayoutUnit(LogicalCollapsedOuterBorderToPhysical().Left()); @@ -1368,6 +1417,7 @@ } LayoutUnit LayoutTable::BorderRight() const { + CheckIsNotDestroyed(); if (ShouldCollapseBorders()) { UpdateCollapsedOuterBorders(); return LayoutUnit(LogicalCollapsedOuterBorderToPhysical().Right()); @@ -1376,6 +1426,7 @@ } LayoutUnit LayoutTable::BorderTop() const { + CheckIsNotDestroyed(); if (ShouldCollapseBorders()) { UpdateCollapsedOuterBorders(); return LayoutUnit(LogicalCollapsedOuterBorderToPhysical().Top()); @@ -1384,6 +1435,7 @@ } LayoutUnit LayoutTable::BorderBottom() const { + CheckIsNotDestroyed(); if (ShouldCollapseBorders()) { UpdateCollapsedOuterBorders(); return LayoutUnit(LogicalCollapsedOuterBorderToPhysical().Bottom()); @@ -1394,6 +1446,7 @@ LayoutTableSection* LayoutTable::SectionAbove( const LayoutTableSection* section, SkipEmptySectionsValue skip_empty_sections) const { + CheckIsNotDestroyed(); RecalcSectionsIfNeeded(); if (section == head_) @@ -1418,6 +1471,7 @@ LayoutTableSection* LayoutTable::SectionBelow( const LayoutTableSection* section, SkipEmptySectionsValue skip_empty_sections) const { + CheckIsNotDestroyed(); RecalcSectionsIfNeeded(); if (section == foot_) @@ -1440,6 +1494,7 @@ } LayoutTableSection* LayoutTable::BottomSection() const { + CheckIsNotDestroyed(); RecalcSectionsIfNeeded(); if (foot_) @@ -1460,6 +1515,7 @@ } LayoutTableCell* LayoutTable::CellAbove(const LayoutTableCell& cell) const { + CheckIsNotDestroyed(); RecalcSectionsIfNeeded(); // Find the section and row to look in @@ -1488,6 +1544,7 @@ } LayoutTableCell* LayoutTable::CellBelow(const LayoutTableCell& cell) const { + CheckIsNotDestroyed(); RecalcSectionsIfNeeded(); // Find the section and row to look in @@ -1514,6 +1571,7 @@ } LayoutTableCell* LayoutTable::CellPreceding(const LayoutTableCell& cell) const { + CheckIsNotDestroyed(); RecalcSectionsIfNeeded(); LayoutTableSection* section = cell.Section(); @@ -1527,6 +1585,7 @@ } LayoutTableCell* LayoutTable::CellFollowing(const LayoutTableCell& cell) const { + CheckIsNotDestroyed(); RecalcSectionsIfNeeded(); unsigned eff_col = AbsoluteColumnToEffectiveColumn( @@ -1539,6 +1598,7 @@ bool first_line, LineDirectionMode direction, LinePositionMode line_position_mode) const { + CheckIsNotDestroyed(); DCHECK_EQ(line_position_mode, kPositionOnContainingLine); LayoutUnit baseline = FirstLineBoxBaseline(); if (baseline != -1) { @@ -1552,11 +1612,13 @@ } LayoutUnit LayoutTable::InlineBlockBaseline(LineDirectionMode) const { + CheckIsNotDestroyed(); // Tables are skipped when computing an inline-block's baseline. return LayoutUnit(-1); } LayoutUnit LayoutTable::FirstLineBoxBaseline() const { + CheckIsNotDestroyed(); // The baseline of a 'table' is the same as the 'inline-table' baseline per // CSS 3 Flexbox (CSS 2.1 doesn't define the baseline of a 'table' only an // 'inline-table'). This is also needed to properly determine the baseline of @@ -1588,6 +1650,7 @@ PhysicalRect LayoutTable::OverflowClipRect( const PhysicalOffset& location, OverlayScrollbarClipBehavior overlay_scrollbar_clip_behavior) const { + CheckIsNotDestroyed(); if (ShouldCollapseBorders()) { // Though the outer halves of the collapsed borders are considered as the // the border area of the table by means of the box model, they are actually @@ -1623,6 +1686,7 @@ const HitTestLocation& hit_test_location, const PhysicalOffset& accumulated_offset, HitTestAction action) { + CheckIsNotDestroyed(); // Check kids first. bool skip_children = (result.GetHitTestRequest().GetStopNode() == this); if (!skip_children && @@ -1661,10 +1725,12 @@ LayoutBox* LayoutTable::CreateAnonymousBoxWithSameTypeAs( const LayoutObject* parent) const { + CheckIsNotDestroyed(); return LayoutObjectFactory::CreateAnonymousTableWithParent(*parent); } void LayoutTable::EnsureIsReadyForPaintInvalidation() { + CheckIsNotDestroyed(); LayoutBlock::EnsureIsReadyForPaintInvalidation(); if (collapsed_borders_valid_) @@ -1709,10 +1775,12 @@ void LayoutTable::InvalidatePaint( const PaintInvalidatorContext& context) const { + CheckIsNotDestroyed(); TablePaintInvalidator(*this, context).InvalidatePaint(); } LayoutUnit LayoutTable::PaddingTop() const { + CheckIsNotDestroyed(); if (ShouldCollapseBorders()) return LayoutUnit(); @@ -1722,6 +1790,7 @@ } LayoutUnit LayoutTable::PaddingBottom() const { + CheckIsNotDestroyed(); if (ShouldCollapseBorders()) return LayoutUnit(); @@ -1731,6 +1800,7 @@ } LayoutUnit LayoutTable::PaddingLeft() const { + CheckIsNotDestroyed(); if (ShouldCollapseBorders()) return LayoutUnit(); @@ -1740,6 +1810,7 @@ } LayoutUnit LayoutTable::PaddingRight() const { + CheckIsNotDestroyed(); if (ShouldCollapseBorders()) return LayoutUnit(); @@ -1749,6 +1820,7 @@ } void LayoutTable::UpdateCollapsedOuterBorders() const { + CheckIsNotDestroyed(); if (collapsed_outer_borders_valid_) return; @@ -1830,6 +1902,7 @@ // LayoutNGTableCellInterface API bool LayoutTable::IsFirstCell(const LayoutNGTableCellInterface& cell) const { + CheckIsNotDestroyed(); const LayoutTableCell& layout_cell = *cell.ToLayoutTableCell(); return !(CellPreceding(layout_cell) || CellAbove(layout_cell)); }
diff --git a/third_party/blink/renderer/core/layout/layout_table.h b/third_party/blink/renderer/core/layout/layout_table.h index 1f99679..fc2e6dd 100644 --- a/third_party/blink/renderer/core/layout/layout_table.h +++ b/third_party/blink/renderer/core/layout/layout_table.h
@@ -144,10 +144,17 @@ // 'border-spacing' property represent spacing between columns and rows // respectively, not necessarily the horizontal and vertical spacing // respectively". - int16_t HBorderSpacing() const final { return h_spacing_; } - int16_t VBorderSpacing() const final { return v_spacing_; } + int16_t HBorderSpacing() const final { + CheckIsNotDestroyed(); + return h_spacing_; + } + int16_t VBorderSpacing() const final { + CheckIsNotDestroyed(); + return v_spacing_; + } bool ShouldCollapseBorders() const final { + CheckIsNotDestroyed(); return StyleRef().BorderCollapse() == EBorderCollapse::kCollapse; } @@ -167,17 +174,21 @@ }; void ForceSectionsRecalc() final { + CheckIsNotDestroyed(); SetNeedsSectionRecalc(); RecalcSections(); } const Vector<ColumnStruct>& EffectiveColumns() const { + CheckIsNotDestroyed(); return effective_columns_; } const Vector<int>& EffectiveColumnPositions() const { + CheckIsNotDestroyed(); return effective_column_positions_; } void SetEffectiveColumnPosition(unsigned index, int position) { + CheckIsNotDestroyed(); // Note that if our horizontal border-spacing changed, our position will // change but not our column's width. In practice, horizontal border-spacing // won't change often. @@ -187,29 +198,36 @@ } LayoutTableSection* Header() const { + CheckIsNotDestroyed(); DCHECK(!NeedsSectionRecalc()); return head_; } LayoutTableSection* Footer() const { + CheckIsNotDestroyed(); DCHECK(!NeedsSectionRecalc()); return foot_; } LayoutTableSection* FirstBody() const { + CheckIsNotDestroyed(); DCHECK(!NeedsSectionRecalc()); return first_body_; } void SetRowOffsetFromRepeatingHeader(LayoutUnit offset) { + CheckIsNotDestroyed(); row_offset_from_repeating_header_ = offset; } LayoutUnit RowOffsetFromRepeatingHeader() const final { + CheckIsNotDestroyed(); return row_offset_from_repeating_header_; } void SetRowOffsetFromRepeatingFooter(LayoutUnit offset) { + CheckIsNotDestroyed(); row_offset_from_repeating_footer_ = offset; } LayoutUnit RowOffsetFromRepeatingFooter() const final { + CheckIsNotDestroyed(); return row_offset_from_repeating_footer_; } @@ -222,18 +240,24 @@ LayoutTableSection* BottomNonEmptySection() const; unsigned LastEffectiveColumnIndex() const { + CheckIsNotDestroyed(); return NumEffectiveColumns() - 1; } void SplitEffectiveColumn(unsigned index, unsigned first_span); void AppendEffectiveColumn(unsigned span); - unsigned NumEffectiveColumns() const { return effective_columns_.size(); } + unsigned NumEffectiveColumns() const { + CheckIsNotDestroyed(); + return effective_columns_.size(); + } unsigned SpanOfEffectiveColumn(unsigned effective_column_index) const { + CheckIsNotDestroyed(); return effective_columns_[effective_column_index].span; } unsigned AbsoluteColumnToEffectiveColumn( unsigned absolute_column_index) const final { + CheckIsNotDestroyed(); if (absolute_column_index < no_cell_colspan_at_least_) return absolute_column_index; @@ -250,6 +274,7 @@ unsigned EffectiveColumnToAbsoluteColumn( unsigned effective_column_index) const { + CheckIsNotDestroyed(); if (effective_column_index < no_cell_colspan_at_least_) return effective_column_index; @@ -261,6 +286,7 @@ } LayoutUnit BorderSpacingInRowDirection() const { + CheckIsNotDestroyed(); if (unsigned effective_column_count = NumEffectiveColumns()) return static_cast<LayoutUnit>(effective_column_count + 1) * HBorderSpacing(); @@ -277,6 +303,7 @@ LayoutUnit PaddingRight() const override; LayoutUnit BordersPaddingAndSpacingInRowDirection() const { + CheckIsNotDestroyed(); // 'border-spacing' only applies to separate borders (see 17.6.1 The // separated borders model). return BorderStart() + BorderEnd() + @@ -302,16 +329,24 @@ }; ColAndColGroup ColElementAtAbsoluteColumn( unsigned absolute_column_index) const { + CheckIsNotDestroyed(); // The common case is to not have col/colgroup elements, make that case // fast. if (!has_col_elements_) return ColAndColGroup(); return SlowColElementAtAbsoluteColumn(absolute_column_index); } - bool HasColElements() const final { return has_col_elements_; } + bool HasColElements() const final { + CheckIsNotDestroyed(); + return has_col_elements_; + } - bool NeedsSectionRecalc() const { return needs_section_recalc_; } + bool NeedsSectionRecalc() const { + CheckIsNotDestroyed(); + return needs_section_recalc_; + } void SetNeedsSectionRecalc() { + CheckIsNotDestroyed(); if (DocumentBeingDestroyed()) return; // For all we know, sections may have been deleted at this point. Don't @@ -351,17 +386,23 @@ void InvalidateCollapsedBordersForAllCellsIfNeeded(); bool HasCollapsedBorders() const final { + CheckIsNotDestroyed(); DCHECK(collapsed_borders_valid_); return has_collapsed_borders_; } bool NeedsAdjustCollapsedBorderJoints() const { + CheckIsNotDestroyed(); DCHECK(collapsed_borders_valid_); return needs_adjust_collapsed_border_joints_; } - bool HasSections() const { return Header() || Footer() || FirstBody(); } + bool HasSections() const { + CheckIsNotDestroyed(); + return Header() || Footer() || FirstBody(); + } void RecalcSectionsIfNeeded() const final { + CheckIsNotDestroyed(); if (needs_section_recalc_) RecalcSections(); } @@ -385,13 +426,17 @@ bool IsLogicalWidthAuto() const; - const char* GetName() const override { return "LayoutTable"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutTable"; + } // Whether a table has opaque foreground depends on many factors, e.g. border // spacing, missing cells, etc. For simplicity, just conservatively assume // foreground of all tables are not opaque. bool ForegroundIsKnownToBeOpaqueInRect(const PhysicalRect&, unsigned) const override { + CheckIsNotDestroyed(); return false; } @@ -401,6 +446,7 @@ bool IsAbsoluteColumnCollapsed(unsigned absolute_column_index) const; bool IsAnyColumnEverCollapsed() const { + CheckIsNotDestroyed(); return is_any_column_ever_collapsed_; } @@ -417,11 +463,19 @@ // LayoutNGTableInterface methods start. const LayoutNGTableInterface* ToLayoutNGTableInterface() const final { + CheckIsNotDestroyed(); return this; } - const LayoutObject* ToLayoutObject() const final { return this; } - LayoutObject* ToMutableLayoutObject() final { return this; } + const LayoutObject* ToLayoutObject() const final { + CheckIsNotDestroyed(); + return this; + } + LayoutObject* ToMutableLayoutObject() final { + CheckIsNotDestroyed(); + return this; + } bool IsFixedTableLayout() const final { + CheckIsNotDestroyed(); return StyleRef().IsFixedTableLayout(); } LayoutNGTableSectionInterface* FirstBodyInterface() const final; @@ -438,6 +492,7 @@ private: bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectTable || LayoutBlock::IsOfType(type); } @@ -502,7 +557,10 @@ void DistributeExtraLogicalHeight(int extra_logical_height); - void SetIsAnyColumnEverCollapsed() { is_any_column_ever_collapsed_ = true; } + void SetIsAnyColumnEverCollapsed() { + CheckIsNotDestroyed(); + is_any_column_ever_collapsed_ = true; + } // TODO(layout-dev): All mutables in this class are lazily updated by // recalcSections() which is called by various getter methods (e.g. @@ -574,6 +632,7 @@ mutable bool column_layout_objects_valid_ : 1; mutable unsigned no_cell_colspan_at_least_; unsigned CalcNoCellColspanAtLeast() const { + CheckIsNotDestroyed(); for (unsigned c = 0; c < NumEffectiveColumns(); c++) { if (effective_columns_[c].span > 1) return c; @@ -582,6 +641,7 @@ } LogicalToPhysical<unsigned> LogicalCollapsedOuterBorderToPhysical() const { + CheckIsNotDestroyed(); return LogicalToPhysical<unsigned>( StyleRef().GetWritingMode(), StyleRef().Direction(), collapsed_outer_border_start_, collapsed_outer_border_end_,
diff --git a/third_party/blink/renderer/core/layout/layout_table_box_component.h b/third_party/blink/renderer/core/layout/layout_table_box_component.h index 78cca0f..fb63566 100644 --- a/third_party/blink/renderer/core/layout/layout_table_box_component.h +++ b/third_party/blink/renderer/core/layout/layout_table_box_component.h
@@ -38,37 +38,55 @@ : LayoutObject::MutableForPainting(box) {} }; MutableForPainting GetMutableForPainting() const { + CheckIsNotDestroyed(); return MutableForPainting(*this); } // Should use TableStyle() instead of own style to determine cell order. - const ComputedStyle& TableStyle() const { return Table()->StyleRef(); } + const ComputedStyle& TableStyle() const { + CheckIsNotDestroyed(); + return Table()->StyleRef(); + } BorderValue BorderStartInTableDirection() const { + CheckIsNotDestroyed(); return StyleRef().BorderStartUsing(TableStyle()); } BorderValue BorderEndInTableDirection() const { + CheckIsNotDestroyed(); return StyleRef().BorderEndUsing(TableStyle()); } BorderValue BorderBeforeInTableDirection() const { + CheckIsNotDestroyed(); return StyleRef().BorderBeforeUsing(TableStyle()); } BorderValue BorderAfterInTableDirection() const { + CheckIsNotDestroyed(); return StyleRef().BorderAfterUsing(TableStyle()); } protected: explicit LayoutTableBoxComponent(Element* element) - : LayoutBox(element), last_paint_result_(kFullyPainted) {} + : LayoutBox(element), last_paint_result_(kFullyPainted) { + CheckIsNotDestroyed(); + } - const LayoutObjectChildList* Children() const { return &children_; } - LayoutObjectChildList* Children() { return &children_; } + const LayoutObjectChildList* Children() const { + CheckIsNotDestroyed(); + return &children_; + } + LayoutObjectChildList* Children() { + CheckIsNotDestroyed(); + return &children_; + } LayoutObject* FirstChild() const { + CheckIsNotDestroyed(); DCHECK_EQ(Children(), VirtualChildren()); return Children()->FirstChild(); } LayoutObject* LastChild() const { + CheckIsNotDestroyed(); DCHECK_EQ(Children(), VirtualChildren()); return Children()->LastChild(); } @@ -78,14 +96,21 @@ // elements. For example, column's visibility:hidden doesn't apply; row's // visibility:hidden shouldn't hide row's background painted behind visible // cells, etc. - bool VisualRectRespectsVisibility() const final { return false; } + bool VisualRectRespectsVisibility() const final { + CheckIsNotDestroyed(); + return false; + } // If you have a LayoutTableBoxComponent, use firstChild or lastChild instead. void SlowFirstChild() const = delete; void SlowLastChild() const = delete; - LayoutObjectChildList* VirtualChildren() override { return Children(); } + LayoutObjectChildList* VirtualChildren() override { + CheckIsNotDestroyed(); + return Children(); + } const LayoutObjectChildList* VirtualChildren() const override { + CheckIsNotDestroyed(); return Children(); }
diff --git a/third_party/blink/renderer/core/layout/layout_table_caption.cc b/third_party/blink/renderer/core/layout/layout_table_caption.cc index 5374d52..8139b497 100644 --- a/third_party/blink/renderer/core/layout/layout_table_caption.cc +++ b/third_party/blink/renderer/core/layout/layout_table_caption.cc
@@ -29,23 +29,27 @@ LayoutTableCaption::~LayoutTableCaption() = default; LayoutUnit LayoutTableCaption::ContainingBlockLogicalWidthForContent() const { + CheckIsNotDestroyed(); LayoutBlock* cb = ContainingBlock(); return cb->LogicalWidth(); } void LayoutTableCaption::InsertedIntoTree() { + CheckIsNotDestroyed(); LayoutBlockFlow::InsertedIntoTree(); Table()->AddCaption(this); } void LayoutTableCaption::WillBeRemovedFromTree() { + CheckIsNotDestroyed(); LayoutBlockFlow::WillBeRemovedFromTree(); Table()->RemoveCaption(this); } LayoutTable* LayoutTableCaption::Table() const { + CheckIsNotDestroyed(); return To<LayoutTable>(Parent()); }
diff --git a/third_party/blink/renderer/core/layout/layout_table_caption.h b/third_party/blink/renderer/core/layout/layout_table_caption.h index 5ade10c..369bd9f 100644 --- a/third_party/blink/renderer/core/layout/layout_table_caption.h +++ b/third_party/blink/renderer/core/layout/layout_table_caption.h
@@ -49,9 +49,13 @@ LayoutUnit ContainingBlockLogicalWidthForContent() const override; protected: - bool CreatesNewFormattingContext() const final { return true; } + bool CreatesNewFormattingContext() const final { + CheckIsNotDestroyed(); + return true; + } bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectTableCaption || LayoutBlockFlow::IsOfType(type); }
diff --git a/third_party/blink/renderer/core/layout/layout_table_cell.cc b/third_party/blink/renderer/core/layout/layout_table_cell.cc index 9963343..3d08771 100644 --- a/third_party/blink/renderer/core/layout/layout_table_cell.cc +++ b/third_party/blink/renderer/core/layout/layout_table_cell.cc
@@ -76,6 +76,7 @@ } void LayoutTableCell::WillBeRemovedFromTree() { + CheckIsNotDestroyed(); LayoutBlockFlow::WillBeRemovedFromTree(); Section()->SetNeedsCellRecalc(); @@ -101,6 +102,7 @@ } unsigned LayoutTableCell::ParseColSpanFromDOM() const { + CheckIsNotDestroyed(); DCHECK(GetNode()); // TODO(dgrogan): HTMLTableCellElement::colSpan() already clamps to something // smaller than maxColumnIndex; can we just DCHECK here? @@ -110,6 +112,7 @@ } unsigned LayoutTableCell::ParseRowSpanFromDOM() const { + CheckIsNotDestroyed(); DCHECK(GetNode()); if (auto* cell_element = DynamicTo<HTMLTableCellElement>(GetNode())) return std::min<unsigned>(cell_element->rowSpan(), kMaxRowIndex); @@ -117,6 +120,7 @@ } void LayoutTableCell::UpdateColAndRowSpanFlags() { + CheckIsNotDestroyed(); // The vast majority of table cells do not have a colspan or rowspan, // so we keep a bool to know if we need to bother reading from the DOM. has_col_span_ = GetNode() && ParseColSpanFromDOM() != 1; @@ -124,6 +128,7 @@ } void LayoutTableCell::ColSpanOrRowSpanChanged() { + CheckIsNotDestroyed(); DCHECK(GetNode()); DCHECK(IsA<HTMLTableCellElement>(*GetNode())); @@ -141,6 +146,7 @@ Length LayoutTableCell::LogicalWidthFromColumns( LayoutTableCol* first_col_for_this_cell, const Length& width_from_style) const { + CheckIsNotDestroyed(); DCHECK(first_col_for_this_cell); DCHECK_EQ(first_col_for_this_cell, Table() @@ -180,6 +186,7 @@ } MinMaxSizes LayoutTableCell::PreferredLogicalWidths() const { + CheckIsNotDestroyed(); // The child cells rely on the grids up in the sections to do their // computePreferredLogicalWidths work. Normally the sections are set up // early, as table cells are added, but relayout can cause the cells to be @@ -221,6 +228,7 @@ int row_height, EVerticalAlign vertical_align, SubtreeLayoutScope& layouter) { + CheckIsNotDestroyed(); int old_intrinsic_padding_before = IntrinsicPaddingBefore(); int old_intrinsic_padding_after = IntrinsicPaddingAfter(); int logical_height_without_intrinsic_padding = PixelSnappedLogicalHeight() - @@ -271,10 +279,13 @@ layouter.SetNeedsLayout(this, layout_invalidation_reason::kPaddingChanged); } -void LayoutTableCell::UpdateLogicalWidth() {} +void LayoutTableCell::UpdateLogicalWidth() { + CheckIsNotDestroyed(); +} void LayoutTableCell::SetCellLogicalWidth(int table_layout_logical_width, SubtreeLayoutScope& layouter) { + CheckIsNotDestroyed(); if (table_layout_logical_width == LogicalWidth()) return; @@ -285,6 +296,7 @@ } void LayoutTableCell::UpdateLayout() { + CheckIsNotDestroyed(); DCHECK(NeedsLayout()); LayoutAnalyzer::Scope analyzer(*this); @@ -298,6 +310,7 @@ } LayoutUnit LayoutTableCell::PaddingTop() const { + CheckIsNotDestroyed(); auto result = ComputedCSSPaddingTop() + LogicalIntrinsicPaddingToPhysical().Top(); // TODO(crbug.com/377847): The ToInt call should be removed when Table is @@ -307,6 +320,7 @@ } LayoutUnit LayoutTableCell::PaddingBottom() const { + CheckIsNotDestroyed(); auto result = ComputedCSSPaddingBottom() + LogicalIntrinsicPaddingToPhysical().Bottom(); // TODO(crbug.com/377847): The ToInt call should be removed when Table is @@ -316,6 +330,7 @@ } LayoutUnit LayoutTableCell::PaddingLeft() const { + CheckIsNotDestroyed(); auto result = ComputedCSSPaddingLeft() + LogicalIntrinsicPaddingToPhysical().Left(); // TODO(crbug.com/377847): The ToInt call should be removed when Table is @@ -325,6 +340,7 @@ } LayoutUnit LayoutTableCell::PaddingRight() const { + CheckIsNotDestroyed(); auto result = ComputedCSSPaddingRight() + LogicalIntrinsicPaddingToPhysical().Right(); // TODO(crbug.com/377847): The ToInt call should be removed when Table is @@ -335,6 +351,7 @@ void LayoutTableCell::SetOverrideLogicalHeightFromRowHeight( LayoutUnit row_height) { + CheckIsNotDestroyed(); ClearIntrinsicPadding(); SetOverrideLogicalHeight(row_height); } @@ -342,6 +359,7 @@ PhysicalOffset LayoutTableCell::OffsetFromContainerInternal( const LayoutObject* o, bool ignore_scroll_offset) const { + CheckIsNotDestroyed(); DCHECK_EQ(o, Container()); PhysicalOffset offset = @@ -353,6 +371,7 @@ } void LayoutTableCell::SetIsSpanningCollapsedRow(bool spanning_collapsed_row) { + CheckIsNotDestroyed(); if (is_spanning_collapsed_row_ != spanning_collapsed_row) { is_spanning_collapsed_row_ = spanning_collapsed_row; SetShouldClipOverflow(ComputeShouldClipOverflow()); @@ -361,14 +380,15 @@ void LayoutTableCell::SetIsSpanningCollapsedColumn( bool spanning_collapsed_column) { + CheckIsNotDestroyed(); if (is_spanning_collapsed_column_ != spanning_collapsed_column) { is_spanning_collapsed_column_ = spanning_collapsed_column; SetShouldClipOverflow(ComputeShouldClipOverflow()); } } -void LayoutTableCell::ComputeVisualOverflow( - bool recompute_floats) { +void LayoutTableCell::ComputeVisualOverflow(bool recompute_floats) { + CheckIsNotDestroyed(); LayoutBlockFlow::ComputeVisualOverflow(recompute_floats); UpdateCollapsedBorderValues(); @@ -420,11 +440,13 @@ } bool LayoutTableCell::ComputeShouldClipOverflow() const { + CheckIsNotDestroyed(); return IsSpanningCollapsedRow() || IsSpanningCollapsedColumn() || LayoutBox::ComputeShouldClipOverflow(); } LayoutUnit LayoutTableCell::CellBaselinePosition() const { + CheckIsNotDestroyed(); // <http://www.w3.org/TR/2007/CR-CSS21-20070719/tables.html#height-layout>: // The baseline of a cell is the baseline of the first in-flow line box in the // cell, or the first in-flow table-row in the cell, whichever comes first. If @@ -439,6 +461,7 @@ // Legacy code does not support orthogonal table cells, and must match // row's writing mode. void LayoutTableCell::UpdateStyleWritingModeFromRow(const LayoutObject* row) { + CheckIsNotDestroyed(); DCHECK_NE(StyleRef().GetWritingMode(), row->StyleRef().GetWritingMode()); scoped_refptr<ComputedStyle> new_style = ComputedStyle::Clone(StyleRef()); new_style->SetWritingMode(row->StyleRef().GetWritingMode()); @@ -462,6 +485,7 @@ void LayoutTableCell::StyleDidChange(StyleDifference diff, const ComputedStyle* old_style) { + CheckIsNotDestroyed(); DCHECK_EQ(StyleRef().Display(), EDisplay::kTableCell); if (Parent() && @@ -526,6 +550,7 @@ } bool LayoutTableCell::IsInEndColumn() const { + CheckIsNotDestroyed(); return Table()->AbsoluteColumnToEffectiveColumn(AbsoluteColumnIndex() + ColSpan() - 1) == Table()->NumEffectiveColumns() - 1; @@ -533,11 +558,13 @@ const CSSProperty& LayoutTableCell::ResolveBorderProperty( const CSSProperty& property) const { + CheckIsNotDestroyed(); return property.ResolveDirectionAwareProperty(TableStyle().Direction(), TableStyle().GetWritingMode()); } CollapsedBorderValue LayoutTableCell::ComputeCollapsedStartBorder() const { + CheckIsNotDestroyed(); LayoutTable* table = Table(); bool in_start_column = IsInStartColumn(); LayoutTableCell* cell_preceding = @@ -668,6 +695,7 @@ } CollapsedBorderValue LayoutTableCell::ComputeCollapsedEndBorder() const { + CheckIsNotDestroyed(); LayoutTable* table = Table(); // Note: We have to use the effective column information instead of whether we // have a cell after as a table doesn't have to be regular (any row can have @@ -798,6 +826,7 @@ } CollapsedBorderValue LayoutTableCell::ComputeCollapsedBeforeBorder() const { + CheckIsNotDestroyed(); LayoutTable* table = Table(); LayoutTableCell* cell_above = table->CellAbove(*this); // We can use the border shared with |cell_above| if it is valid. @@ -929,6 +958,7 @@ } CollapsedBorderValue LayoutTableCell::ComputeCollapsedAfterBorder() const { + CheckIsNotDestroyed(); LayoutTable* table = Table(); LayoutTableCell* cell_below = table->CellBelow(*this); // We can use the border shared with |cell_below| if it is valid. @@ -1051,30 +1081,35 @@ } LayoutUnit LayoutTableCell::BorderLeft() const { + CheckIsNotDestroyed(); return Table()->ShouldCollapseBorders() ? LayoutUnit(CollapsedBorderHalfLeft(false)) : LayoutBlockFlow::BorderLeft(); } LayoutUnit LayoutTableCell::BorderRight() const { + CheckIsNotDestroyed(); return Table()->ShouldCollapseBorders() ? LayoutUnit(CollapsedBorderHalfRight(false)) : LayoutBlockFlow::BorderRight(); } LayoutUnit LayoutTableCell::BorderTop() const { + CheckIsNotDestroyed(); return Table()->ShouldCollapseBorders() ? LayoutUnit(CollapsedBorderHalfTop(false)) : LayoutBlockFlow::BorderTop(); } LayoutUnit LayoutTableCell::BorderBottom() const { + CheckIsNotDestroyed(); return Table()->ShouldCollapseBorders() ? LayoutUnit(CollapsedBorderHalfBottom(false)) : LayoutBlockFlow::BorderBottom(); } bool LayoutTableCell::IsFirstColumnCollapsed() const { + CheckIsNotDestroyed(); if (!RuntimeEnabledFeatures::VisibilityCollapseColumnEnabled()) return false; if (!HasSetAbsoluteColumnIndex()) @@ -1083,6 +1118,7 @@ } void LayoutTableCell::UpdateCollapsedBorderValues() const { + CheckIsNotDestroyed(); bool changed = false; if (!Table()->ShouldCollapseBorders()) { @@ -1132,18 +1168,21 @@ void LayoutTableCell::PaintBoxDecorationBackground( const PaintInfo& paint_info, const PhysicalOffset& paint_offset) const { + CheckIsNotDestroyed(); TableCellPainter(*this).PaintBoxDecorationBackground(paint_info, paint_offset); } void LayoutTableCell::PaintMask(const PaintInfo& paint_info, const PhysicalOffset& paint_offset) const { + CheckIsNotDestroyed(); TableCellPainter(*this).PaintMask(paint_info, paint_offset); } void LayoutTableCell::ScrollbarsChanged(bool horizontal_scrollbar_changed, bool vertical_scrollbar_changed, ScrollbarChangeContext context) { + CheckIsNotDestroyed(); LayoutBlock::ScrollbarsChanged(horizontal_scrollbar_changed, vertical_scrollbar_changed); @@ -1196,11 +1235,13 @@ LayoutBox* LayoutTableCell::CreateAnonymousBoxWithSameTypeAs( const LayoutObject* parent) const { + CheckIsNotDestroyed(); return LayoutObjectFactory::CreateAnonymousTableCellWithParent(*parent); } bool LayoutTableCell::BackgroundIsKnownToBeOpaqueInRect( const PhysicalRect& local_rect) const { + CheckIsNotDestroyed(); // If this object has layer, the area of collapsed borders should be // transparent to expose the collapsed borders painted on the underlying // layer. @@ -1210,6 +1251,7 @@ } bool LayoutTableCell::HasLineIfEmpty() const { + CheckIsNotDestroyed(); if (GetNode() && HasEditableStyle(*GetNode())) return true; @@ -1218,6 +1260,7 @@ void LayoutTableCell::InvalidatePaint( const PaintInvalidatorContext& context) const { + CheckIsNotDestroyed(); TableCellPaintInvalidator(*this, context).InvalidatePaint(); }
diff --git a/third_party/blink/renderer/core/layout/layout_table_cell.h b/third_party/blink/renderer/core/layout/layout_table_cell.h index 5ede499..f2e5b80f 100644 --- a/third_party/blink/renderer/core/layout/layout_table_cell.h +++ b/third_party/blink/renderer/core/layout/layout_table_cell.h
@@ -94,16 +94,19 @@ explicit LayoutTableCell(Element*); unsigned ColSpan() const final { + CheckIsNotDestroyed(); if (!has_col_span_) return 1; return ParseColSpanFromDOM(); } unsigned ParsedRowSpan() const { + CheckIsNotDestroyed(); if (!has_row_span_) return 1; return ParseRowSpanFromDOM(); } unsigned ResolvedRowSpan() const final { + CheckIsNotDestroyed(); unsigned row_span = ParsedRowSpan(); if (!row_span) { DCHECK(!Section()->NeedsCellRecalc()); @@ -116,24 +119,32 @@ void ColSpanOrRowSpanChanged() final; void SetAbsoluteColumnIndex(unsigned column) { + CheckIsNotDestroyed(); CHECK_LE(column, kMaxColumnIndex); absolute_column_index_ = column; } bool HasSetAbsoluteColumnIndex() const { + CheckIsNotDestroyed(); return absolute_column_index_ != kUnsetColumnIndex; } unsigned AbsoluteColumnIndex() const final { + CheckIsNotDestroyed(); DCHECK(HasSetAbsoluteColumnIndex()); return absolute_column_index_; } - LayoutTableRow* Row() const { return To<LayoutTableRow>(Parent()); } + LayoutTableRow* Row() const { + CheckIsNotDestroyed(); + return To<LayoutTableRow>(Parent()); + } LayoutTableSection* Section() const { + CheckIsNotDestroyed(); return To<LayoutTableSection>(Parent()->Parent()); } LayoutTable* Table() const { + CheckIsNotDestroyed(); return To<LayoutTable>(Parent()->Parent()->Parent()); } @@ -141,12 +152,14 @@ LayoutTableCell* NextCell() const; unsigned RowIndex() const final { + CheckIsNotDestroyed(); // This function shouldn't be called on a detached cell. DCHECK(Row()); return Row()->RowIndex(); } Length StyleOrColLogicalWidth() const final { + CheckIsNotDestroyed(); const Length& style_width = StyleRef().LogicalWidth(); if (!style_width.IsAuto()) return style_width; @@ -159,6 +172,7 @@ } int LogicalHeightFromStyle() const { + CheckIsNotDestroyed(); const Length& height = StyleRef().LogicalHeight(); int style_logical_height = height.IsIntrinsicOrAuto() @@ -178,6 +192,7 @@ } int LogicalHeightForRowSizing() const { + CheckIsNotDestroyed(); // FIXME: This function does too much work, and is very hot during table // layout! int adjusted_logical_height = @@ -202,6 +217,7 @@ LayoutUnit CellBaselinePosition() const; bool IsBaselineAligned() const { + CheckIsNotDestroyed(); EVerticalAlign va = StyleRef().VerticalAlign(); return va == EVerticalAlign::kBaseline || va == EVerticalAlign::kTextBottom || @@ -217,10 +233,19 @@ EVerticalAlign, SubtreeLayoutScope&); - void ClearIntrinsicPadding() { SetIntrinsicPadding(0, 0); } + void ClearIntrinsicPadding() { + CheckIsNotDestroyed(); + SetIntrinsicPadding(0, 0); + } - int IntrinsicPaddingBefore() const final { return intrinsic_padding_before_; } - int IntrinsicPaddingAfter() const final { return intrinsic_padding_after_; } + int IntrinsicPaddingBefore() const final { + CheckIsNotDestroyed(); + return intrinsic_padding_before_; + } + int IntrinsicPaddingAfter() const final { + CheckIsNotDestroyed(); + return intrinsic_padding_after_; + } LayoutUnit PaddingTop() const override; LayoutUnit PaddingBottom() const override; @@ -233,8 +258,12 @@ bool vertical_scrollbar_changed, ScrollbarChangeContext = kLayout) override; - bool CellChildrenNeedLayout() const { return cell_children_need_layout_; } + bool CellChildrenNeedLayout() const { + CheckIsNotDestroyed(); + return cell_children_need_layout_; + } void SetCellChildrenNeedLayout(bool b = true) { + CheckIsNotDestroyed(); cell_children_need_layout_ = b; } @@ -247,35 +276,50 @@ // The table's style determines cell order and cell adjacency in the table. // Collapsed borders also use in table's inline and block directions. - const ComputedStyle& TableStyle() const { return Table()->StyleRef(); } + const ComputedStyle& TableStyle() const { + CheckIsNotDestroyed(); + return Table()->StyleRef(); + } BorderValue BorderStartInTableDirection() const { + CheckIsNotDestroyed(); return StyleRef().BorderStartUsing(TableStyle()); } BorderValue BorderEndInTableDirection() const { + CheckIsNotDestroyed(); return StyleRef().BorderEndUsing(TableStyle()); } BorderValue BorderBeforeInTableDirection() const { + CheckIsNotDestroyed(); return StyleRef().BorderBeforeUsing(TableStyle()); } BorderValue BorderAfterInTableDirection() const { + CheckIsNotDestroyed(); return StyleRef().BorderAfterUsing(TableStyle()); } - const char* GetName() const override { return "LayoutTableCell"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutTableCell"; + } bool BackgroundIsKnownToBeOpaqueInRect(const PhysicalRect&) const override; const CollapsedBorderValues* GetCollapsedBorderValues() const { + CheckIsNotDestroyed(); UpdateCollapsedBorderValues(); return collapsed_border_values_.get(); } void InvalidateCollapsedBorderValues() { + CheckIsNotDestroyed(); collapsed_border_values_valid_ = false; } // A table cell's location is relative to its containing section. - LayoutBox* LocationContainer() const override { return Section(); } + LayoutBox* LocationContainer() const override { + CheckIsNotDestroyed(); + return Section(); + } bool HasLineIfEmpty() const override; @@ -290,52 +334,68 @@ // For the following methods, the 'start', 'end', 'before', 'after' directions // are all in the table's inline and block directions. unsigned CollapsedOuterBorderBefore() const { + CheckIsNotDestroyed(); return CollapsedBorderHalfBefore(true); } unsigned CollapsedOuterBorderAfter() const { + CheckIsNotDestroyed(); return CollapsedBorderHalfAfter(true); } unsigned CollapsedOuterBorderStart() const { + CheckIsNotDestroyed(); return CollapsedBorderHalfStart(true); } unsigned CollapsedOuterBorderEnd() const { + CheckIsNotDestroyed(); return CollapsedBorderHalfEnd(true); } unsigned CollapsedInnerBorderBefore() const { + CheckIsNotDestroyed(); return CollapsedBorderHalfBefore(false); } unsigned CollapsedInnerBorderAfter() const { + CheckIsNotDestroyed(); return CollapsedBorderHalfAfter(false); } unsigned CollapsedInnerBorderStart() const { + CheckIsNotDestroyed(); return CollapsedBorderHalfStart(false); } unsigned CollapsedInnerBorderEnd() const { + CheckIsNotDestroyed(); return CollapsedBorderHalfEnd(false); } bool StartsAtSameColumn(const LayoutTableCell* other) const { + CheckIsNotDestroyed(); return other && AbsoluteColumnIndex() == other->AbsoluteColumnIndex(); } bool EndsAtSameColumn(const LayoutTableCell* other) const { + CheckIsNotDestroyed(); return other && AbsoluteColumnIndex() + ColSpan() == other->AbsoluteColumnIndex() + other->ColSpan(); } bool StartsAtSameRow(const LayoutTableCell* other) const { + CheckIsNotDestroyed(); return other && RowIndex() == other->RowIndex(); } bool EndsAtSameRow(const LayoutTableCell* other) const { + CheckIsNotDestroyed(); return other && RowIndex() + ResolvedRowSpan() == other->RowIndex() + other->ResolvedRowSpan(); } void SetIsSpanningCollapsedRow(bool spanning_collapsed_row); - bool IsSpanningCollapsedRow() const { return is_spanning_collapsed_row_; } + bool IsSpanningCollapsedRow() const { + CheckIsNotDestroyed(); + return is_spanning_collapsed_row_; + } void SetIsSpanningCollapsedColumn(bool spanningCollapsedColumn); bool IsSpanningCollapsedColumn() const { + CheckIsNotDestroyed(); return is_spanning_collapsed_column_; } @@ -344,18 +404,39 @@ // LayoutNGTableCellInterface implementation start. const LayoutNGTableCellInterface* ToLayoutNGTableCellInterface() const final { + CheckIsNotDestroyed(); return this; } - const LayoutTableCell* ToLayoutTableCell() const final { return this; } - const LayoutObject* ToLayoutObject() const final { return this; } - LayoutObject* ToMutableLayoutObject() final { return this; } - LayoutNGTableInterface* TableInterface() const final { return Table(); } - LayoutTableCell* NextCellInterface() const final { return NextCell(); } + const LayoutTableCell* ToLayoutTableCell() const final { + CheckIsNotDestroyed(); + return this; + } + const LayoutObject* ToLayoutObject() const final { + CheckIsNotDestroyed(); + return this; + } + LayoutObject* ToMutableLayoutObject() final { + CheckIsNotDestroyed(); + return this; + } + LayoutNGTableInterface* TableInterface() const final { + CheckIsNotDestroyed(); + return Table(); + } + LayoutTableCell* NextCellInterface() const final { + CheckIsNotDestroyed(); + return NextCell(); + } LayoutTableCell* PreviousCellInterface() const final { + CheckIsNotDestroyed(); return PreviousCell(); } - LayoutNGTableRowInterface* RowInterface() const final { return Row(); } + LayoutNGTableRowInterface* RowInterface() const final { + CheckIsNotDestroyed(); + return Row(); + } LayoutNGTableSectionInterface* SectionInterface() const final { + CheckIsNotDestroyed(); return Section(); } @@ -374,10 +455,14 @@ const LayoutObject*, bool ignore_scroll_offset) const override; - bool CreatesNewFormattingContext() const final { return true; } + bool CreatesNewFormattingContext() const final { + CheckIsNotDestroyed(); + return true; + } protected: bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectTableCell || type == kLayoutObjectTableCellLegacy || LayoutBlockFlow::IsOfType(type); @@ -402,6 +487,7 @@ const CollapsedBorderValue& (CollapsedBorderValues::*)() const; LogicalToPhysical<CollapsedBorderValuesMethod> CollapsedBorderValuesMethodsPhysical() const { + CheckIsNotDestroyed(); return LogicalToPhysical<CollapsedBorderValuesMethod>( // Collapsed border logical directions are in table's directions. TableStyle().GetWritingMode(), TableStyle().Direction(), @@ -417,6 +503,7 @@ static constexpr bool kInnerHalfPixelAsOneLeft = true; PhysicalToLogical<bool> InnerHalfPixelAsOneLogical() const { + CheckIsNotDestroyed(); return PhysicalToLogical<bool>( // Collapsed border logical directions are in table's directions. TableStyle().GetWritingMode(), TableStyle().Direction(), @@ -425,18 +512,22 @@ } unsigned CollapsedBorderHalfLeft(bool outer) const { + CheckIsNotDestroyed(); return CollapsedBorderHalf(kInnerHalfPixelAsOneLeft ^ outer, CollapsedBorderValuesMethodsPhysical().Left()); } unsigned CollapsedBorderHalfRight(bool outer) const { + CheckIsNotDestroyed(); return CollapsedBorderHalf(kInnerHalfPixelAsOneRight ^ outer, CollapsedBorderValuesMethodsPhysical().Right()); } unsigned CollapsedBorderHalfTop(bool outer) const { + CheckIsNotDestroyed(); return CollapsedBorderHalf(kInnerHalfPixelAsOneTop ^ outer, CollapsedBorderValuesMethodsPhysical().Top()); } unsigned CollapsedBorderHalfBottom(bool outer) const { + CheckIsNotDestroyed(); return CollapsedBorderHalf(kInnerHalfPixelAsOneBottom ^ outer, CollapsedBorderValuesMethodsPhysical().Bottom()); } @@ -444,24 +535,29 @@ // For the following methods, the 'start', 'end', 'before', 'after' directions // are all in the table's inline and block directions. unsigned CollapsedBorderHalfStart(bool outer) const { + CheckIsNotDestroyed(); return CollapsedBorderHalf(InnerHalfPixelAsOneLogical().Start() ^ outer, &CollapsedBorderValues::StartBorder); } unsigned CollapsedBorderHalfEnd(bool outer) const { + CheckIsNotDestroyed(); return CollapsedBorderHalf(InnerHalfPixelAsOneLogical().End() ^ outer, &CollapsedBorderValues::EndBorder); } unsigned CollapsedBorderHalfBefore(bool outer) const { + CheckIsNotDestroyed(); return CollapsedBorderHalf(InnerHalfPixelAsOneLogical().Before() ^ outer, &CollapsedBorderValues::BeforeBorder); } unsigned CollapsedBorderHalfAfter(bool outer) const { + CheckIsNotDestroyed(); return CollapsedBorderHalf(InnerHalfPixelAsOneLogical().After() ^ outer, &CollapsedBorderValues::AfterBorder); } unsigned CollapsedBorderHalf(bool half_pixel_as_one, CollapsedBorderValuesMethod m) const { + CheckIsNotDestroyed(); UpdateCollapsedBorderValues(); if (const auto* values = GetCollapsedBorderValues()) return ((values->*m)().Width() + (half_pixel_as_one ? 1 : 0)) / 2; @@ -469,18 +565,29 @@ } LogicalToPhysical<int> LogicalIntrinsicPaddingToPhysical() const { + CheckIsNotDestroyed(); return LogicalToPhysical<int>( StyleRef().GetWritingMode(), StyleRef().Direction(), 0, 0, intrinsic_padding_before_, intrinsic_padding_after_); } - void SetIntrinsicPaddingBefore(int p) { intrinsic_padding_before_ = p; } - void SetIntrinsicPaddingAfter(int p) { intrinsic_padding_after_ = p; } + void SetIntrinsicPaddingBefore(int p) { + CheckIsNotDestroyed(); + intrinsic_padding_before_ = p; + } + void SetIntrinsicPaddingAfter(int p) { + CheckIsNotDestroyed(); + intrinsic_padding_after_ = p; + } void SetIntrinsicPadding(int before, int after) { + CheckIsNotDestroyed(); SetIntrinsicPaddingBefore(before); SetIntrinsicPaddingAfter(after); } - bool IsInStartColumn() const { return AbsoluteColumnIndex() == 0; } + bool IsInStartColumn() const { + CheckIsNotDestroyed(); + return AbsoluteColumnIndex() == 0; + } bool IsInEndColumn() const; // These functions implement the CSS collapsing border conflict resolution
diff --git a/third_party/blink/renderer/core/layout/layout_table_col.cc b/third_party/blink/renderer/core/layout/layout_table_col.cc index e2286b94..582e8bf8 100644 --- a/third_party/blink/renderer/core/layout/layout_table_col.cc +++ b/third_party/blink/renderer/core/layout/layout_table_col.cc
@@ -41,6 +41,7 @@ void LayoutTableCol::StyleDidChange(StyleDifference diff, const ComputedStyle* old_style) { + CheckIsNotDestroyed(); DCHECK(StyleRef().Display() == EDisplay::kTableColumn || StyleRef().Display() == EDisplay::kTableColumnGroup); @@ -71,6 +72,7 @@ } void LayoutTableCol::UpdateFromElement() { + CheckIsNotDestroyed(); unsigned old_span = span_; if (auto* tc = DynamicTo<HTMLTableColElement>(GetNode())) { @@ -85,28 +87,33 @@ } void LayoutTableCol::InsertedIntoTree() { + CheckIsNotDestroyed(); LayoutTableBoxComponent::InsertedIntoTree(); Table()->AddColumn(this); } void LayoutTableCol::WillBeRemovedFromTree() { + CheckIsNotDestroyed(); LayoutTableBoxComponent::WillBeRemovedFromTree(); Table()->RemoveColumn(this); } bool LayoutTableCol::IsChildAllowed(LayoutObject* child, const ComputedStyle& style) const { + CheckIsNotDestroyed(); // We cannot use isTableColumn here as style() may return 0. return child->IsLayoutTableCol() && style.Display() == EDisplay::kTableColumn; } bool LayoutTableCol::CanHaveChildren() const { + CheckIsNotDestroyed(); // Cols cannot have children. This is actually necessary to fix a bug // with libraries.uc.edu, which makes a <p> be a table-column. return IsTableColumnGroup(); } void LayoutTableCol::ClearIntrinsicLogicalWidthsDirtyBits() { + CheckIsNotDestroyed(); ClearIntrinsicLogicalWidthsDirty(); for (LayoutObject* child = FirstChild(); child; child = child->NextSibling()) @@ -114,6 +121,7 @@ } LayoutTable* LayoutTableCol::Table() const { + CheckIsNotDestroyed(); LayoutObject* table = Parent(); if (table && !table->IsTable()) table = table->Parent(); @@ -121,6 +129,7 @@ } LayoutTableCol* LayoutTableCol::EnclosingColumnGroup() const { + CheckIsNotDestroyed(); if (!Parent()->IsLayoutTableCol()) return nullptr; @@ -131,6 +140,7 @@ } LayoutTableCol* LayoutTableCol::NextColumn() const { + CheckIsNotDestroyed(); // If |this| is a column-group, the next column is the colgroup's first child // column. if (LayoutObject* first_child = FirstChild())
diff --git a/third_party/blink/renderer/core/layout/layout_table_col.h b/third_party/blink/renderer/core/layout/layout_table_col.h index cd905f20..394fffe 100644 --- a/third_party/blink/renderer/core/layout/layout_table_col.h +++ b/third_party/blink/renderer/core/layout/layout_table_col.h
@@ -64,13 +64,21 @@ // The 'span' attribute in HTML. // For CSS table columns or colgroups, this is always 1. - unsigned Span() const { return span_; } + unsigned Span() const { + CheckIsNotDestroyed(); + return span_; + } - bool IsTableColumnGroupWithColumnChildren() { return FirstChild(); } + bool IsTableColumnGroupWithColumnChildren() { + CheckIsNotDestroyed(); + return FirstChild(); + } bool IsTableColumn() const { + CheckIsNotDestroyed(); return StyleRef().Display() == EDisplay::kTableColumn; } bool IsTableColumnGroup() const { + CheckIsNotDestroyed(); return StyleRef().Display() == EDisplay::kTableColumnGroup; } @@ -79,19 +87,25 @@ // Returns the next column or column-group. LayoutTableCol* NextColumn() const; - const char* GetName() const override { return "LayoutTableCol"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutTableCol"; + } private: bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectLayoutTableCol || LayoutBox::IsOfType(type); } void UpdateFromElement() override; MinMaxSizes PreferredLogicalWidths() const override { + CheckIsNotDestroyed(); NOTREACHED(); return MinMaxSizes(); } MinMaxSizes ComputeIntrinsicLogicalWidths() const final { + CheckIsNotDestroyed(); NOTREACHED(); return MinMaxSizes(); } @@ -101,7 +115,10 @@ bool IsChildAllowed(LayoutObject*, const ComputedStyle&) const override; bool CanHaveChildren() const override; - PaintLayerType LayerTypeRequired() const override { return kNoPaintLayer; } + PaintLayerType LayerTypeRequired() const override { + CheckIsNotDestroyed(); + return kNoPaintLayer; + } void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override;
diff --git a/third_party/blink/renderer/core/layout/layout_table_row.cc b/third_party/blink/renderer/core/layout/layout_table_row.cc index fbb3ffc..0d3bc91 100644 --- a/third_party/blink/renderer/core/layout/layout_table_row.cc +++ b/third_party/blink/renderer/core/layout/layout_table_row.cc
@@ -47,21 +47,25 @@ } void LayoutTableRow::WillBeRemovedFromTree() { + CheckIsNotDestroyed(); LayoutTableBoxComponent::WillBeRemovedFromTree(); Section()->SetNeedsCellRecalc(); } LayoutNGTableCellInterface* LayoutTableRow::FirstCellInterface() const { + CheckIsNotDestroyed(); return FirstCell(); } LayoutNGTableCellInterface* LayoutTableRow::LastCellInterface() const { + CheckIsNotDestroyed(); return LastCell(); } void LayoutTableRow::StyleDidChange(StyleDifference diff, const ComputedStyle* old_style) { + CheckIsNotDestroyed(); DCHECK_EQ(StyleRef().Display(), EDisplay::kTableRow); // Legacy tables cannont handle relative/fixed rows. @@ -136,6 +140,7 @@ void LayoutTableRow::InvalidatePaint( const PaintInvalidatorContext& context) const { + CheckIsNotDestroyed(); LayoutTableBoxComponent::InvalidatePaint(context); if (Table()->HasCollapsedBorders()) { // Repaint the painting layer of the table. The table's composited backing @@ -146,6 +151,7 @@ } void LayoutTableRow::AddChild(LayoutObject* child, LayoutObject* before_child) { + CheckIsNotDestroyed(); if (!child->IsTableCell()) { LayoutObject* last = before_child; if (!last) @@ -222,6 +228,7 @@ } void LayoutTableRow::UpdateLayout() { + CheckIsNotDestroyed(); DCHECK(NeedsLayout()); LayoutAnalyzer::Scope analyzer(*this); bool paginated = View()->GetLayoutState()->IsPaginated(); @@ -267,6 +274,7 @@ const HitTestLocation& hit_test_location, const PhysicalOffset& accumulated_offset, HitTestAction action) { + CheckIsNotDestroyed(); // The row and the cells are all located in the section. const auto* section = Section(); PhysicalOffset section_accumulated_offset = @@ -292,6 +300,7 @@ LayoutBox::PaginationBreakability LayoutTableRow::GetPaginationBreakability( FragmentationEngine engine) const { + CheckIsNotDestroyed(); PaginationBreakability breakability = LayoutTableBoxComponent::GetPaginationBreakability(engine); if (breakability == kAllowAnyBreaks) { @@ -304,6 +313,7 @@ } void LayoutTableRow::Paint(const PaintInfo& paint_info) const { + CheckIsNotDestroyed(); TableRowPainter(*this).Paint(paint_info); } @@ -315,16 +325,19 @@ LayoutBox* LayoutTableRow::CreateAnonymousBoxWithSameTypeAs( const LayoutObject* parent) const { + CheckIsNotDestroyed(); return LayoutObjectFactory::CreateAnonymousTableRowWithParent(*parent); } void LayoutTableRow::ComputeLayoutOverflow() { + CheckIsNotDestroyed(); ClearLayoutOverflow(); for (LayoutTableCell* cell = FirstCell(); cell; cell = cell->NextCell()) AddLayoutOverflowFromCell(cell); } void LayoutTableRow::RecalcVisualOverflow() { + CheckIsNotDestroyed(); unsigned n_cols = Section()->NumCols(RowIndex()); for (unsigned c = 0; c < n_cols; c++) { auto* cell = Section()->OriginatingCellAt(RowIndex(), c); @@ -338,6 +351,7 @@ } void LayoutTableRow::ComputeVisualOverflow() { + CheckIsNotDestroyed(); const auto& old_visual_rect = VisualOverflowRect(); ClearVisualOverflow(); AddVisualEffectOverflow(); @@ -350,6 +364,7 @@ } void LayoutTableRow::AddLayoutOverflowFromCell(const LayoutTableCell* cell) { + CheckIsNotDestroyed(); LayoutRect cell_layout_overflow_rect = cell->LayoutOverflowRectForPropagation(this); @@ -363,6 +378,7 @@ } void LayoutTableRow::AddVisualOverflowFromCell(const LayoutTableCell* cell) { + CheckIsNotDestroyed(); // Note: we include visual overflow of even self-painting cells, // because the row needs to expand to contain their area in order to paint // background and collapsed borders. This is different than any other
diff --git a/third_party/blink/renderer/core/layout/layout_table_row.h b/third_party/blink/renderer/core/layout/layout_table_row.h index 82b2447e..00e8fe8 100644 --- a/third_party/blink/renderer/core/layout/layout_table_row.h +++ b/third_party/blink/renderer/core/layout/layout_table_row.h
@@ -77,9 +77,11 @@ LayoutTableRow* NextRow() const; LayoutTableSection* Section() const { + CheckIsNotDestroyed(); return To<LayoutTableSection>(Parent()); } LayoutTable* Table() const final { + CheckIsNotDestroyed(); return To<LayoutTable>(Parent()->Parent()); } @@ -88,12 +90,17 @@ const LayoutObject* parent) const override; void SetRowIndex(unsigned row_index) { + CheckIsNotDestroyed(); CHECK_LE(row_index, kMaxRowIndex); row_index_ = row_index; } - bool RowIndexWasSet() const { return row_index_ != kUnsetRowIndex; } + bool RowIndexWasSet() const { + CheckIsNotDestroyed(); + return row_index_ != kUnsetRowIndex; + } unsigned RowIndex() const final { + CheckIsNotDestroyed(); DCHECK(RowIndexWasSet()); DCHECK( !Section() || @@ -114,16 +121,21 @@ void RecalcVisualOverflow() override; - const char* GetName() const override { return "LayoutTableRow"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutTableRow"; + } // Whether a row has opaque background depends on many factors, e.g. border // spacing, border collapsing, missing cells, etc. // For simplicity, just conservatively assume all table rows are not opaque. bool ForegroundIsKnownToBeOpaqueInRect(const PhysicalRect&, unsigned) const override { + CheckIsNotDestroyed(); return false; } bool BackgroundIsKnownToBeOpaqueInRect(const PhysicalRect&) const override { + CheckIsNotDestroyed(); return false; } @@ -132,18 +144,31 @@ // LayoutNGTableRowInterface methods start. const LayoutNGTableRowInterface* ToLayoutNGTableRowInterface() const final { + CheckIsNotDestroyed(); return this; } - const LayoutObject* ToLayoutObject() const final { return this; } - const LayoutTableRow* ToLayoutTableRow() const final { return this; } - LayoutNGTableInterface* TableInterface() const final { return Table(); } + const LayoutObject* ToLayoutObject() const final { + CheckIsNotDestroyed(); + return this; + } + const LayoutTableRow* ToLayoutTableRow() const final { + CheckIsNotDestroyed(); + return this; + } + LayoutNGTableInterface* TableInterface() const final { + CheckIsNotDestroyed(); + return Table(); + } LayoutNGTableSectionInterface* SectionInterface() const final { + CheckIsNotDestroyed(); return Section(); } LayoutNGTableRowInterface* NextRowInterface() const final { + CheckIsNotDestroyed(); return NextRow(); } LayoutNGTableRowInterface* PreviousRowInterface() const final { + CheckIsNotDestroyed(); return PreviousRow(); } LayoutNGTableCellInterface* FirstCellInterface() const final; @@ -153,6 +178,7 @@ private: MinMaxSizes ComputeIntrinsicLogicalWidths() const final { + CheckIsNotDestroyed(); NOTREACHED(); return MinMaxSizes(); } @@ -162,6 +188,7 @@ void AddVisualOverflowFromCell(const LayoutTableCell*); bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectTableRow || LayoutTableBoxComponent::IsOfType(type); } @@ -173,6 +200,7 @@ void UpdateLayout() override; PaintLayerType LayerTypeRequired() const override { + CheckIsNotDestroyed(); if (HasTransformRelatedProperty() || HasHiddenBackface() || CreatesGroup() || StyleRef().ShouldCompositeForCurrentAnimations() || IsStickyPositioned())
diff --git a/third_party/blink/renderer/core/layout/layout_table_section.cc b/third_party/blink/renderer/core/layout/layout_table_section.cc index 28e6cebb..bee35de 100644 --- a/third_party/blink/renderer/core/layout/layout_table_section.cc +++ b/third_party/blink/renderer/core/layout/layout_table_section.cc
@@ -107,6 +107,7 @@ void LayoutTableSection::StyleDidChange(StyleDifference diff, const ComputedStyle* old_style) { + CheckIsNotDestroyed(); DCHECK(StyleRef().Display() == EDisplay::kTableFooterGroup || StyleRef().Display() == EDisplay::kTableRowGroup || StyleRef().Display() == EDisplay::kTableHeaderGroup); @@ -140,6 +141,7 @@ } void LayoutTableSection::WillBeRemovedFromTree() { + CheckIsNotDestroyed(); LayoutTableBoxComponent::WillBeRemovedFromTree(); // Preventively invalidate our cells as we may be re-inserted into @@ -149,6 +151,7 @@ void LayoutTableSection::AddChild(LayoutObject* child, LayoutObject* before_child) { + CheckIsNotDestroyed(); if (!child->IsTableRow()) { LayoutObject* last = before_child; if (!last) @@ -240,6 +243,7 @@ } void LayoutTableSection::AddCell(LayoutTableCell* cell, LayoutTableRow* row) { + CheckIsNotDestroyed(); // We don't insert the cell if we need cell recalc as our internal columns' // representation will have drifted from the table's representation. Also // recalcCells will call addCell at a later time after sync'ing our columns' @@ -308,6 +312,7 @@ } bool LayoutTableSection::RowHasOnlySpanningCells(unsigned row) { + CheckIsNotDestroyed(); if (grid_[row].grid_cells.IsEmpty()) return false; @@ -326,6 +331,7 @@ void LayoutTableSection::PopulateSpanningRowsHeightFromCell( LayoutTableCell* cell, struct SpanningRowsHeight& spanning_rows_height) { + CheckIsNotDestroyed(); const unsigned row_span = cell->ResolvedRowSpan(); const unsigned row_index = cell->RowIndex(); @@ -360,6 +366,7 @@ float total_percent, int& extra_row_spanning_height, Vector<int>& rows_height) { + CheckIsNotDestroyed(); if (!extra_row_spanning_height || !total_percent) return; @@ -420,6 +427,7 @@ float total_percent, int& extra_row_spanning_height, Vector<int>& rows_height) { + CheckIsNotDestroyed(); if (!extra_row_spanning_height || !total_percent) return; @@ -448,6 +456,7 @@ int total_auto_rows_height, int& extra_row_spanning_height, Vector<int>& rows_height) { + CheckIsNotDestroyed(); if (!extra_row_spanning_height || !total_auto_rows_height) return; @@ -478,6 +487,7 @@ int total_remaining_rows_height, int& extra_row_spanning_height, Vector<int>& rows_height) { + CheckIsNotDestroyed(); if (!extra_row_spanning_height || !total_remaining_rows_height) return; @@ -543,6 +553,7 @@ unsigned row_to_apply_extra_height, unsigned& extra_table_height_to_propgate, Vector<int>& rows_count_with_only_spanning_cells) { + CheckIsNotDestroyed(); DCHECK(RowHasOnlySpanningCells(row)); unsigned row_height = 0; @@ -597,6 +608,7 @@ struct SpanningRowsHeight& spanning_rows_height, unsigned& extra_height_to_propagate, Vector<int>& rows_count_with_only_spanning_cells) { + CheckIsNotDestroyed(); DCHECK(spanning_rows_height.row_height.size()); int accumulated_position_increase = 0; @@ -626,6 +638,7 @@ // height of rows in rowSpan cell. void LayoutTableSection::DistributeRowSpanHeightToRows( SpanningLayoutTableCells& row_span_cells) { + CheckIsNotDestroyed(); DCHECK(row_span_cells.size()); // 'rowSpanCells' list is already sorted based on the cells rowIndex in @@ -783,6 +796,7 @@ } bool LayoutTableSection::RowHasVisibilityCollapse(unsigned row) const { + CheckIsNotDestroyed(); return ((grid_[row].row && grid_[row].row->StyleRef().Visibility() == EVisibility::kCollapse) || StyleRef().Visibility() == EVisibility::kCollapse); @@ -795,6 +809,7 @@ void LayoutTableSection::UpdateBaselineForCell(LayoutTableCell* cell, unsigned row, LayoutUnit& baseline_descent) { + CheckIsNotDestroyed(); if (!cell->IsBaselineAligned()) return; @@ -822,6 +837,7 @@ } int16_t LayoutTableSection::VBorderSpacingBeforeFirstRow() const { + CheckIsNotDestroyed(); // We ignore the border-spacing on any non-top section, as it is already // included in the previous section's last row position. if (this != Table()->TopSection()) @@ -830,6 +846,7 @@ } int LayoutTableSection::CalcRowLogicalHeight() { + CheckIsNotDestroyed(); #if DCHECK_IS_ON() SetLayoutNeededForbiddenScope layout_forbidden_scope(*this); #endif @@ -975,6 +992,7 @@ } void LayoutTableSection::UpdateLayout() { + CheckIsNotDestroyed(); DCHECK(NeedsLayout()); LayoutAnalyzer::Scope analyzer(*this); CHECK(!NeedsCellRecalc()); @@ -1047,6 +1065,7 @@ void LayoutTableSection::DistributeExtraLogicalHeightToPercentRows( int& extra_logical_height, int total_percent) { + CheckIsNotDestroyed(); if (!total_percent) return; @@ -1079,6 +1098,7 @@ void LayoutTableSection::DistributeExtraLogicalHeightToAutoRows( int& extra_logical_height, unsigned auto_rows_count) { + CheckIsNotDestroyed(); if (!auto_rows_count) return; @@ -1098,6 +1118,7 @@ void LayoutTableSection::DistributeRemainingExtraLogicalHeight( int& extra_logical_height) { + CheckIsNotDestroyed(); unsigned total_rows = grid_.size(); if (extra_logical_height <= 0 || !row_pos_[total_rows]) @@ -1128,6 +1149,7 @@ int LayoutTableSection::DistributeExtraLogicalHeightToRows( int extra_logical_height) { + CheckIsNotDestroyed(); if (!extra_logical_height) return extra_logical_height; @@ -1166,6 +1188,7 @@ } void LayoutTableSection::LayoutRows() { + CheckIsNotDestroyed(); #if DCHECK_IS_ON() SetLayoutNeededForbiddenScope layout_forbidden_scope(*this); #endif @@ -1291,6 +1314,7 @@ void LayoutTableSection::UpdateLogicalWidthForCollapsedCells( const Vector<int>& col_collapsed_width) { + CheckIsNotDestroyed(); if (!RuntimeEnabledFeatures::VisibilityCollapseColumnEnabled()) return; unsigned total_rows = grid_.size(); @@ -1331,6 +1355,7 @@ int LayoutTableSection::PaginationStrutForRow(LayoutTableRow* row, LayoutUnit logical_offset) const { + CheckIsNotDestroyed(); DCHECK(row); const LayoutTableSection* footer = Table()->Footer(); bool make_room_for_repeating_footer = @@ -1365,6 +1390,7 @@ } void LayoutTableSection::ComputeVisualOverflowFromDescendants() { + CheckIsNotDestroyed(); auto old_self_visual_overflow_rect = SelfVisualOverflowRect(); ClearVisualOverflow(); @@ -1428,24 +1454,29 @@ } void LayoutTableSection::ComputeLayoutOverflowFromDescendants() { + CheckIsNotDestroyed(); ClearLayoutOverflow(); for (auto* row = FirstRow(); row; row = row->NextRow()) AddLayoutOverflowFromChild(*row); } LayoutNGTableRowInterface* LayoutTableSection::FirstRowInterface() const { + CheckIsNotDestroyed(); return FirstRow(); } LayoutNGTableRowInterface* LayoutTableSection::LastRowInterface() const { + CheckIsNotDestroyed(); return LastRow(); } const LayoutNGTableCellInterface* LayoutTableSection::PrimaryCellInterfaceAt( unsigned row, unsigned effective_column) const { + CheckIsNotDestroyed(); return PrimaryCellAt(row, effective_column); } bool LayoutTableSection::RecalcLayoutOverflow() { + CheckIsNotDestroyed(); if (!ChildNeedsLayoutOverflowRecalc()) return false; ClearChildNeedsLayoutOverflowRecalc(); @@ -1475,6 +1506,7 @@ } void LayoutTableSection::RecalcVisualOverflow() { + CheckIsNotDestroyed(); SECURITY_CHECK(!needs_cell_recalc_); unsigned total_rows = grid_.size(); for (unsigned r = 0; r < total_rows; r++) { @@ -1490,6 +1522,7 @@ void LayoutTableSection::MarkAllCellsWidthsDirtyAndOrNeedsLayout( LayoutTable::WhatToMarkAllCells what_to_mark) { + CheckIsNotDestroyed(); for (LayoutTableRow* row = FirstRow(); row; row = row->NextRow()) { for (LayoutTableCell* cell = row->FirstCell(); cell; cell = cell->NextCell()) { @@ -1501,6 +1534,7 @@ } LayoutUnit LayoutTableSection::FirstLineBoxBaseline() const { + CheckIsNotDestroyed(); DCHECK(!NeedsCellRecalc()); if (!grid_.size()) return LayoutUnit(-1); @@ -1522,11 +1556,13 @@ } void LayoutTableSection::Paint(const PaintInfo& paint_info) const { + CheckIsNotDestroyed(); TableSectionPainter(*this).Paint(paint_info); } LayoutRect LayoutTableSection::LogicalRectForWritingModeAndDirection( const PhysicalRect& rect) const { + CheckIsNotDestroyed(); LayoutRect table_aligned_rect = FlipForWritingMode(rect); if (!TableStyle().IsHorizontalWritingMode()) @@ -1545,6 +1581,7 @@ const LayoutRect& damage_rect, CellSpan& rows, CellSpan& columns) const { + CheckIsNotDestroyed(); DCHECK(!NeedsCellRecalc()); if (!grid_.size()) { rows = CellSpan(); @@ -1615,6 +1652,7 @@ } CellSpan LayoutTableSection::SpannedRows(const LayoutRect& flipped_rect) const { + CheckIsNotDestroyed(); // Find the first row that starts after rect top. unsigned next_row = static_cast<unsigned>( std::upper_bound(row_pos_.begin(), row_pos_.end(), flipped_rect.Y()) - @@ -1644,6 +1682,7 @@ CellSpan LayoutTableSection::SpannedEffectiveColumns( const LayoutRect& flipped_rect) const { + CheckIsNotDestroyed(); const Vector<int>& column_pos = Table()->EffectiveColumnPositions(); // Find the first column that starts after rect left. @@ -1678,6 +1717,7 @@ } void LayoutTableSection::RecalcCells() { + CheckIsNotDestroyed(); DCHECK(needs_cell_recalc_); // We reset the flag here to ensure that |addCell| works. This is safe to do // as fillRowsWithDefaultStartingAtPosition makes sure we match the table's @@ -1724,6 +1764,7 @@ // FIXME: This function could be made O(1) in certain cases (like for the // non-most-constrainive cells' case). void LayoutTableSection::RowLogicalHeightChanged(LayoutTableRow* row) { + CheckIsNotDestroyed(); if (NeedsCellRecalc()) return; @@ -1736,6 +1777,7 @@ } void LayoutTableSection::SetNeedsCellRecalc() { + CheckIsNotDestroyed(); needs_cell_recalc_ = true; SetNeedsOverflowRecalc(); if (LayoutTable* t = Table()) @@ -1743,6 +1785,7 @@ } unsigned LayoutTableSection::NumEffectiveColumns() const { + CheckIsNotDestroyed(); unsigned result = 0; for (unsigned r = 0; r < grid_.size(); ++r) { @@ -1760,6 +1803,7 @@ LayoutTableCell* LayoutTableSection::OriginatingCellAt( unsigned row, unsigned effective_column) { + CheckIsNotDestroyed(); SECURITY_CHECK(!needs_cell_recalc_); if (effective_column >= NumCols(row)) return nullptr; @@ -1774,6 +1818,7 @@ } void LayoutTableSection::AppendEffectiveColumn(unsigned pos) { + CheckIsNotDestroyed(); DCHECK(!needs_cell_recalc_); for (auto& row : grid_) @@ -1781,6 +1826,7 @@ } void LayoutTableSection::SplitEffectiveColumn(unsigned pos, unsigned first) { + CheckIsNotDestroyed(); DCHECK(!needs_cell_recalc_); if (c_col_ > pos) @@ -1810,6 +1856,7 @@ const HitTestLocation& hit_test_location, const PhysicalOffset& accumulated_offset, HitTestAction action) { + CheckIsNotDestroyed(); // If we have no children then we have nothing to do. if (!FirstRow()) return false; @@ -1880,12 +1927,14 @@ LayoutBox* LayoutTableSection::CreateAnonymousBoxWithSameTypeAs( const LayoutObject* parent) const { + CheckIsNotDestroyed(); return LayoutObjectFactory::CreateAnonymousTableSectionWithParent(*parent); } void LayoutTableSection::SetLogicalPositionForCell( LayoutTableCell* cell, unsigned effective_column) const { + CheckIsNotDestroyed(); LayoutPoint cell_location(0, row_pos_[cell->RowIndex()]); int16_t horizontal_border_spacing = Table()->HBorderSpacing(); @@ -1908,6 +1957,7 @@ void LayoutTableSection::RelayoutCellIfFlexed(LayoutTableCell& cell, int row_index, int row_height) { + CheckIsNotDestroyed(); // Force percent height children to lay themselves out again now that the // cell's final height is determined. // FIXME: There is still more work to do here to fully match WinIE (should @@ -1954,6 +2004,7 @@ int LayoutTableSection::LogicalHeightForRow( const LayoutTableRow& row_object) const { + CheckIsNotDestroyed(); unsigned row_index = row_object.RowIndex(); DCHECK_LT(row_index, grid_.size()); int logical_height = 0; @@ -1994,6 +2045,7 @@ } int LayoutTableSection::OffsetForRepeatedHeader() const { + CheckIsNotDestroyed(); LayoutTableSection* header = Table()->Header(); if (header && header != this) return Table()->RowOffsetFromRepeatingHeader().ToInt(); @@ -2003,6 +2055,7 @@ void LayoutTableSection::AdjustRowForPagination(LayoutTableRow& row_object, SubtreeLayoutScope& layouter) { + CheckIsNotDestroyed(); row_object.SetPaginationStrut(LayoutUnit()); row_object.SetLogicalHeight(LayoutUnit(LogicalHeightForRow(row_object))); if (!IsPageLogicalHeightKnown()) @@ -2070,6 +2123,7 @@ } bool LayoutTableSection::GroupShouldRepeat() const { + CheckIsNotDestroyed(); DCHECK(Table()->Header() == this || Table()->Footer() == this); if (GetLegacyPaginationBreakability() == kAllowAnyBreaks) return false; @@ -2095,6 +2149,7 @@ const LayoutBoxModelObject* ancestor, TransformState& transform_state, VisualRectFlags flags) const { + CheckIsNotDestroyed(); if (ancestor == this) return true; // Repeating table headers and footers are painted once per
diff --git a/third_party/blink/renderer/core/layout/layout_table_section.h b/third_party/blink/renderer/core/layout/layout_table_section.h index da9a4b3..c46a917 100644 --- a/third_party/blink/renderer/core/layout/layout_table_section.h +++ b/third_party/blink/renderer/core/layout/layout_table_section.h
@@ -127,7 +127,10 @@ void MarkAllCellsWidthsDirtyAndOrNeedsLayout(LayoutTable::WhatToMarkAllCells); - LayoutTable* Table() const final { return To<LayoutTable>(Parent()); } + LayoutTable* Table() const final { + CheckIsNotDestroyed(); + return To<LayoutTable>(Parent()); + } typedef Vector<LayoutTableCell*, 2> SpanningLayoutTableCells; @@ -148,15 +151,18 @@ }; TableGridCell& GridCellAt(unsigned row, unsigned effective_column) { + CheckIsNotDestroyed(); SECURITY_DCHECK(!needs_cell_recalc_); return grid_[row].grid_cells[effective_column]; } const TableGridCell& GridCellAt(unsigned row, unsigned effective_column) const { + CheckIsNotDestroyed(); SECURITY_DCHECK(!needs_cell_recalc_); return grid_[row].grid_cells[effective_column]; } LayoutTableCell* PrimaryCellAt(unsigned row, unsigned effective_column) { + CheckIsNotDestroyed(); SECURITY_DCHECK(!needs_cell_recalc_); auto& grid_cells = grid_[row].grid_cells; if (effective_column >= grid_cells.size()) @@ -165,6 +171,7 @@ } const LayoutTableCell* PrimaryCellAt(unsigned row, unsigned effective_column) const { + CheckIsNotDestroyed(); return const_cast<LayoutTableSection*>(this)->PrimaryCellAt( row, effective_column); } @@ -174,11 +181,13 @@ LayoutTableCell* OriginatingCellAt(unsigned row, unsigned effective_column); const LayoutTableCell* OriginatingCellAt(unsigned row, unsigned effective_column) const { + CheckIsNotDestroyed(); return const_cast<LayoutTableSection*>(this)->OriginatingCellAt( row, effective_column); } unsigned NumCols(unsigned row) const final { + CheckIsNotDestroyed(); DCHECK(!NeedsCellRecalc()); return grid_[row].grid_cells.size(); } @@ -186,10 +195,12 @@ // Returns null for cells with a rowspan that exceed the last row. Possibly // others. LayoutTableRow* RowLayoutObjectAt(unsigned row) { + CheckIsNotDestroyed(); SECURITY_DCHECK(!needs_cell_recalc_); return grid_[row].row; } const LayoutTableRow* RowLayoutObjectAt(unsigned row) const { + CheckIsNotDestroyed(); SECURITY_DCHECK(!needs_cell_recalc_); return grid_[row].row; } @@ -198,6 +209,7 @@ void SplitEffectiveColumn(unsigned pos, unsigned first); unsigned NumRows() const final { + CheckIsNotDestroyed(); DCHECK(!NeedsCellRecalc()); return grid_.size(); } @@ -214,14 +226,21 @@ // m_needsCellRecalc before accessing m_grid. void RecalcCells(); void RecalcCellsIfNeeded() { + CheckIsNotDestroyed(); if (needs_cell_recalc_) RecalcCells(); } - bool NeedsCellRecalc() const { return needs_cell_recalc_; } + bool NeedsCellRecalc() const { + CheckIsNotDestroyed(); + return needs_cell_recalc_; + } void SetNeedsCellRecalc() final; - LayoutUnit RowBaseline(unsigned row) { return grid_[row].baseline; } + LayoutUnit RowBaseline(unsigned row) { + CheckIsNotDestroyed(); + return grid_[row].baseline; + } void RowLogicalHeightChanged(LayoutTableRow*); @@ -247,23 +266,33 @@ CellSpan& columns) const; const HashSet<const LayoutTableCell*>& VisuallyOverflowingCells() const { + CheckIsNotDestroyed(); return visually_overflowing_cells_; } bool HasVisuallyOverflowingCell() const { + CheckIsNotDestroyed(); return visually_overflowing_cells_.size() || force_full_paint_; } - bool HasMultipleCellLevels() const { return has_multiple_cell_levels_; } + bool HasMultipleCellLevels() const { + CheckIsNotDestroyed(); + return has_multiple_cell_levels_; + } - const char* GetName() const override { return "LayoutTableSection"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutTableSection"; + } // Whether a section has opaque background depends on many factors, e.g. // border spacing, border collapsing, missing cells, etc. For simplicity, // just conservatively assume all table sections are not opaque. bool ForegroundIsKnownToBeOpaqueInRect(const PhysicalRect&, unsigned) const override { + CheckIsNotDestroyed(); return false; } bool BackgroundIsKnownToBeOpaqueInRect(const PhysicalRect&) const override { + CheckIsNotDestroyed(); return false; } @@ -275,20 +304,27 @@ VisualRectFlags = kDefaultVisualRectFlags) const override; bool IsRepeatingHeaderGroup() const final { + CheckIsNotDestroyed(); return is_repeating_header_group_; } bool IsRepeatingFooterGroup() const final { + CheckIsNotDestroyed(); return is_repeating_footer_group_; } void UpdateLayout() override; - CellSpan FullSectionRowSpan() const { return CellSpan(0, grid_.size()); } + CellSpan FullSectionRowSpan() const { + CheckIsNotDestroyed(); + return CellSpan(0, grid_.size()); + } CellSpan FullTableEffectiveColumnSpan() const { + CheckIsNotDestroyed(); return CellSpan(0, Table()->NumEffectiveColumns()); } void DetermineIfHeaderGroupShouldRepeat() { + CheckIsNotDestroyed(); is_repeating_header_group_ = HeaderGroupShouldRepeat(); } @@ -296,6 +332,7 @@ bool RowHasVisibilityCollapse(unsigned row) const; void DetermineIfFooterGroupShouldRepeat() { + CheckIsNotDestroyed(); is_repeating_footer_group_ = FooterGroupShouldRepeat(); } @@ -310,13 +347,26 @@ const LayoutNGTableSectionInterface* ToLayoutNGTableSectionInterface() const final { + CheckIsNotDestroyed(); return this; } - const LayoutTableSection* ToLayoutTableSection() const final { return this; } - const LayoutObject* ToLayoutObject() const final { return this; } - LayoutObject* ToMutableLayoutObject() final { return this; } + const LayoutTableSection* ToLayoutTableSection() const final { + CheckIsNotDestroyed(); + return this; + } + const LayoutObject* ToLayoutObject() const final { + CheckIsNotDestroyed(); + return this; + } + LayoutObject* ToMutableLayoutObject() final { + CheckIsNotDestroyed(); + return this; + } - LayoutNGTableInterface* TableInterface() const final { return Table(); } + LayoutNGTableInterface* TableInterface() const final { + CheckIsNotDestroyed(); + return Table(); + } LayoutNGTableRowInterface* FirstRowInterface() const final; LayoutNGTableRowInterface* LastRowInterface() const final; const LayoutNGTableCellInterface* PrimaryCellInterfaceAt( @@ -333,6 +383,7 @@ private: MinMaxSizes ComputeIntrinsicLogicalWidths() const final { + CheckIsNotDestroyed(); NOTREACHED(); return MinMaxSizes(); } @@ -340,21 +391,25 @@ void ComputeVisualOverflowFromDescendants(); bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectTableSection || LayoutBox::IsOfType(type); } void WillBeRemovedFromTree() override; int BorderSpacingForRow(unsigned row) const { + CheckIsNotDestroyed(); return grid_[row].row ? Table()->VBorderSpacing() : 0; } void EnsureRows(unsigned num_rows) { + CheckIsNotDestroyed(); if (num_rows > grid_.size()) grid_.Grow(num_rows); } void EnsureCols(unsigned row_index, unsigned num_cols) { + CheckIsNotDestroyed(); if (num_cols > NumCols(row_index)) grid_[row_index].grid_cells.Grow(num_cols); } @@ -423,10 +478,12 @@ int OffsetForRepeatedHeader() const; bool HeaderGroupShouldRepeat() const { + CheckIsNotDestroyed(); return Table()->Header() == this && GroupShouldRepeat(); } bool FooterGroupShouldRepeat() const { + CheckIsNotDestroyed(); return Table()->Footer() == this && GroupShouldRepeat(); }
diff --git a/third_party/blink/renderer/core/layout/layout_text.cc b/third_party/blink/renderer/core/layout/layout_text.cc index 5bd1bd8..75d911a 100644 --- a/third_party/blink/renderer/core/layout/layout_text.cc +++ b/third_party/blink/renderer/core/layout/layout_text.cc
@@ -196,11 +196,13 @@ } bool LayoutText::IsWordBreak() const { + CheckIsNotDestroyed(); return false; } void LayoutText::StyleDidChange(StyleDifference diff, const ComputedStyle* old_style) { + CheckIsNotDestroyed(); // There is no need to ever schedule paint invalidations from a style change // of a text run, since we already did this for the parent of the text run. // We do have to schedule layouts, though, since a style change can force us @@ -237,6 +239,7 @@ } void LayoutText::RemoveAndDestroyTextBoxes() { + CheckIsNotDestroyed(); if (!DocumentBeingDestroyed()) { if (FirstTextBox()) { if (IsBR()) { @@ -274,6 +277,7 @@ } void LayoutText::WillBeDestroyed() { + CheckIsNotDestroyed(); if (SecureTextTimer* secure_text_timer = GetSecureTextTimers().Take(this)) delete secure_text_timer; @@ -291,24 +295,29 @@ } void LayoutText::ExtractTextBox(InlineTextBox* box) { + CheckIsNotDestroyed(); MutableTextBoxes().ExtractLineBox(box); } void LayoutText::AttachTextBox(InlineTextBox* box) { + CheckIsNotDestroyed(); MutableTextBoxes().AttachLineBox(box); } void LayoutText::RemoveTextBox(InlineTextBox* box) { + CheckIsNotDestroyed(); MutableTextBoxes().RemoveLineBox(box); } void LayoutText::DeleteTextBoxes() { + CheckIsNotDestroyed(); if (!IsInLayoutNGInlineFormattingContext()) return MutableTextBoxes().DeleteLineBoxes(); DetachAbstractInlineTextBoxesIfNeeded(); } void LayoutText::DetachAbstractInlineTextBoxes() { + CheckIsNotDestroyed(); // TODO(layout-dev): Because We should call |WillDestroy()| once for // associated fragments, when you reuse fragments, you should construct // NGAbstractInlineTextBox for them. @@ -327,6 +336,7 @@ } void LayoutText::SetFirstInlineFragment(NGPaintFragment* first_fragment) { + CheckIsNotDestroyed(); CHECK(IsInLayoutNGInlineFormattingContext()); DCHECK(!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()); DetachAbstractInlineTextBoxesIfNeeded(); @@ -334,6 +344,7 @@ } void LayoutText::ClearFirstInlineFragmentItemIndex() { + CheckIsNotDestroyed(); CHECK(IsInLayoutNGInlineFormattingContext()) << *this; DCHECK(RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()); DetachAbstractInlineTextBoxesIfNeeded(); @@ -341,6 +352,7 @@ } void LayoutText::SetFirstInlineFragmentItemIndex(wtf_size_t index) { + CheckIsNotDestroyed(); CHECK(IsInLayoutNGInlineFormattingContext()); // TODO(yosin): Call |NGAbstractInlineTextBox::WillDestroy()|. DCHECK(RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()); @@ -350,6 +362,7 @@ } void LayoutText::InLayoutNGInlineFormattingContextWillChange(bool new_value) { + CheckIsNotDestroyed(); if (IsInLayoutNGInlineFormattingContext()) { if (!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) { SetFirstInlineFragment(nullptr); @@ -373,6 +386,7 @@ } Vector<LayoutText::TextBoxInfo> LayoutText::GetTextBoxInfo() const { + CheckIsNotDestroyed(); // This function may kick the layout (e.g., |LocalRect()|), but Inspector may // call this function outside of the layout phase. FontCachePurgePreventer fontCachePurgePreventer; @@ -450,6 +464,7 @@ } bool LayoutText::HasInlineFragments() const { + CheckIsNotDestroyed(); if (IsInLayoutNGInlineFormattingContext()) { if (!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) return first_paint_fragment_; @@ -460,11 +475,13 @@ } scoped_refptr<StringImpl> LayoutText::OriginalText() const { + CheckIsNotDestroyed(); auto* text_node = DynamicTo<Text>(GetNode()); return text_node ? text_node->DataImpl() : nullptr; } String LayoutText::PlainText() const { + CheckIsNotDestroyed(); if (GetNode()) return blink::PlainText(EphemeralRange::RangeOfContents(*GetNode())); @@ -543,6 +560,7 @@ template <typename PhysicalRectCollector> void LayoutText::CollectLineBoxRects(const PhysicalRectCollector& yield, ClippingOption option) const { + CheckIsNotDestroyed(); if (IsInLayoutNGInlineFormattingContext()) { NGInlineCursor cursor; cursor.MoveTo(*this); @@ -576,6 +594,7 @@ void LayoutText::AbsoluteQuads(Vector<FloatQuad>& quads, MapCoordinatesFlags mode) const { + CheckIsNotDestroyed(); CollectLineBoxRects([this, &quads, mode](const PhysicalRect& r) { quads.push_back(LocalRectToAbsoluteQuad(r, mode)); }); @@ -584,6 +603,7 @@ bool LayoutText::MapDOMOffsetToTextContentOffset(const NGOffsetMapping& mapping, unsigned* start, unsigned* end) const { + CheckIsNotDestroyed(); DCHECK_LE(*start, *end); // Adjust |start| to the next non-collapsed offset if |start| is collapsed. @@ -626,6 +646,7 @@ void LayoutText::AbsoluteQuadsForRange(Vector<FloatQuad>& quads, unsigned start, unsigned end) const { + CheckIsNotDestroyed(); // Work around signed/unsigned issues. This function takes unsigneds, and is // often passed UINT_MAX to mean "all the way to the end". InlineTextBox // coordinates are unsigneds, so changing this function to take ints causes @@ -726,6 +747,7 @@ } FloatRect LayoutText::LocalBoundingBoxRectForAccessibility() const { + CheckIsNotDestroyed(); FloatRect result; const LayoutBlock* block_for_flipping = UNLIKELY(HasFlippedBlocksWritingMode()) ? ContainingBlock() : nullptr; @@ -839,6 +861,7 @@ PositionWithAffinity LayoutText::PositionForPoint( const PhysicalOffset& point) const { + CheckIsNotDestroyed(); if (IsInLayoutNGInlineFormattingContext()) { NGInlineCursor cursor; for (cursor.MoveTo(*this); cursor; cursor.MoveToNextForSameLayoutObject()) { @@ -914,6 +937,7 @@ const InlineBox* inline_box, int caret_offset, LayoutUnit* extra_width_to_end_of_line) const { + CheckIsNotDestroyed(); if (!inline_box) return LayoutRect(); @@ -1023,6 +1047,7 @@ HashSet<const SimpleFontData*>* fallback_fonts, FloatRect* glyph_bounds_accumulation, float expansion) const { + CheckIsNotDestroyed(); if (StyleRef().HasTextCombine() && IsCombineText()) { const LayoutTextCombine* combine_text = ToLayoutTextCombine(this); if (combine_text->IsCombined()) @@ -1061,6 +1086,7 @@ LayoutUnit& max_width, bool& strip_front_spaces, TextDirection direction) { + CheckIsNotDestroyed(); float float_min_width = 0.0f, float_max_width = 0.0f; // Convert leadWidth to a float here, to avoid multiple implict conversions @@ -1162,6 +1188,7 @@ } float LayoutText::MinLogicalWidth() const { + CheckIsNotDestroyed(); if (IntrinsicLogicalWidthsDirty()) const_cast<LayoutText*>(this)->ComputePreferredLogicalWidths(0); @@ -1169,6 +1196,7 @@ } float LayoutText::MaxLogicalWidth() const { + CheckIsNotDestroyed(); if (IntrinsicLogicalWidthsDirty()) const_cast<LayoutText*>(this)->ComputePreferredLogicalWidths(0); @@ -1176,6 +1204,7 @@ } void LayoutText::ComputePreferredLogicalWidths(float lead_width) { + CheckIsNotDestroyed(); HashSet<const SimpleFontData*> fallback_fonts; FloatRect glyph_bounds; ComputePreferredLogicalWidths(lead_width, fallback_fonts, glyph_bounds); @@ -1265,6 +1294,7 @@ float lead_width, HashSet<const SimpleFontData*>& fallback_fonts, FloatRect& glyph_bounds) { + CheckIsNotDestroyed(); DCHECK(has_tab_ || IntrinsicLogicalWidthsDirty() || !known_to_have_no_overflow_and_no_fallback_fonts_); @@ -1619,6 +1649,7 @@ } bool LayoutText::IsAllCollapsibleWhitespace() const { + CheckIsNotDestroyed(); unsigned length = TextLength(); if (Is8Bit()) { for (unsigned i = 0; i < length; ++i) { @@ -1635,6 +1666,7 @@ } bool LayoutText::ContainsOnlyWhitespace(unsigned from, unsigned len) const { + CheckIsNotDestroyed(); DCHECK(text_); StringImpl& text = *text_.Impl(); unsigned curr_pos; @@ -1648,6 +1680,7 @@ } UChar32 LayoutText::FirstCharacterAfterWhitespaceCollapsing() const { + CheckIsNotDestroyed(); if (InlineTextBox* text_box = FirstTextBox()) { String text = text_box->GetText(); return text.length() ? text.CharacterStartingAt(0) : 0; @@ -1664,6 +1697,7 @@ } UChar32 LayoutText::LastCharacterAfterWhitespaceCollapsing() const { + CheckIsNotDestroyed(); if (InlineTextBox* text_box = LastTextBox()) { String text = text_box->GetText(); return text.length() ? StringView(text).CodepointAt(text.length() - 1) : 0; @@ -1680,6 +1714,7 @@ } PhysicalOffset LayoutText::FirstLineBoxTopLeft() const { + CheckIsNotDestroyed(); if (IsInLayoutNGInlineFormattingContext()) { // TODO(kojii): Some clients call this against dirty-tree, but NG fragments // are not safe to read for dirty-tree. crbug.com/963103 @@ -1704,6 +1739,7 @@ void LayoutText::LogicalStartingPointAndHeight( LogicalOffset& logical_starting_point, LayoutUnit& logical_height) const { + CheckIsNotDestroyed(); if (IsInLayoutNGInlineFormattingContext()) { NGInlineCursor cursor; cursor.MoveTo(*this); @@ -1738,6 +1774,7 @@ } bool LayoutText::CanOptimizeSetText() const { + CheckIsNotDestroyed(); // If we have only one line of text and "contain: layout size" we can avoid // doing a layout and only paint in the SetText() operation. auto* parent_block_flow = DynamicTo<LayoutBlockFlow>(Parent()); @@ -1758,6 +1795,7 @@ } void LayoutText::SetFirstTextBoxLogicalLeft(float text_width) const { + CheckIsNotDestroyed(); DCHECK(FirstTextBox()); DCHECK(ContainingBlock()); DCHECK(StyleRef().IsLeftToRightDirection()); @@ -1793,6 +1831,7 @@ void LayoutText::SetTextWithOffset(scoped_refptr<StringImpl> text, unsigned offset, unsigned len) { + CheckIsNotDestroyed(); if (Equal(text_.Impl(), text.get())) return; @@ -1918,6 +1957,7 @@ } void LayoutText::TransformText() { + CheckIsNotDestroyed(); if (scoped_refptr<StringImpl> text_to_transform = OriginalText()) ForceSetText(std::move(text_to_transform)); } @@ -1931,12 +1971,14 @@ } OnlyWhitespaceOrNbsp LayoutText::ContainsOnlyWhitespaceOrNbsp() const { + CheckIsNotDestroyed(); return IntrinsicLogicalWidthsDirty() ? OnlyWhitespaceOrNbsp::kUnknown : static_cast<OnlyWhitespaceOrNbsp>( contains_only_whitespace_or_nbsp_); } UChar LayoutText::PreviousCharacter() const { + CheckIsNotDestroyed(); // find previous text layoutObject if one exists const LayoutObject* previous_text = PreviousInPreOrder(); for (; previous_text; previous_text = previous_text->PreviousInPreOrder()) { @@ -1953,6 +1995,7 @@ } void LayoutText::SetTextInternal(scoped_refptr<StringImpl> text) { + CheckIsNotDestroyed(); DCHECK(text); text_ = String(std::move(text)); DCHECK(text_); @@ -1960,6 +2003,7 @@ } void LayoutText::ApplyTextTransform() { + CheckIsNotDestroyed(); if (const ComputedStyle* style = Style()) { style->ApplyTextTransform(&text_, PreviousCharacter()); @@ -1981,6 +2025,7 @@ } void LayoutText::SecureText(UChar mask) { + CheckIsNotDestroyed(); if (!text_.length()) return; @@ -2005,6 +2050,7 @@ } void LayoutText::SetTextIfNeeded(scoped_refptr<StringImpl> text) { + CheckIsNotDestroyed(); DCHECK(text); if (Equal(text_.Impl(), text.get())) @@ -2013,12 +2059,14 @@ } void LayoutText::ForceSetText(scoped_refptr<StringImpl> text) { + CheckIsNotDestroyed(); DCHECK(text); SetTextInternal(std::move(text)); TextDidChange(); } void LayoutText::TextDidChange() { + CheckIsNotDestroyed(); // If preferredLogicalWidthsDirty() of an orphan child is true, // LayoutObjectChildList::insertChildNode() fails to set true to owner. // To avoid that, we call SetNeedsLayoutAndIntrinsicWidthsRecalc() only if @@ -2031,6 +2079,7 @@ } void LayoutText::TextDidChangeWithoutInvalidation() { + CheckIsNotDestroyed(); ApplyTextTransform(); known_to_have_no_overflow_and_no_fallback_fonts_ = false; @@ -2051,6 +2100,7 @@ } void LayoutText::InvalidateSubtreeLayoutForFontUpdates() { + CheckIsNotDestroyed(); if (RuntimeEnabledFeatures:: CSSReducedFontLoadingLayoutInvalidationsEnabled() && IsFontFallbackValid()) { @@ -2065,6 +2115,7 @@ } void LayoutText::DirtyOrDeleteLineBoxesIfNeeded(bool full_layout) { + CheckIsNotDestroyed(); if (full_layout) DeleteTextBoxes(); else if (!lines_dirty_) @@ -2074,6 +2125,7 @@ } void LayoutText::DirtyLineBoxes() { + CheckIsNotDestroyed(); for (InlineTextBox* box : TextBoxes()) box->DirtyLineBoxes(); lines_dirty_ = false; @@ -2081,16 +2133,19 @@ } InlineTextBox* LayoutText::CreateTextBox(int start, uint16_t length) { + CheckIsNotDestroyed(); return new InlineTextBox(LineLayoutItem(this), start, length); } InlineTextBox* LayoutText::CreateInlineTextBox(int start, uint16_t length) { + CheckIsNotDestroyed(); InlineTextBox* text_box = CreateTextBox(start, length); MutableTextBoxes().AppendLineBox(text_box); return text_box; } void LayoutText::PositionLineBox(InlineBox* box) { + CheckIsNotDestroyed(); InlineTextBox* s = ToInlineTextBox(box); // FIXME: should not be needed!!! @@ -2113,6 +2168,7 @@ HashSet<const SimpleFontData*>* fallback_fonts, FloatRect* glyph_bounds, float expansion) const { + CheckIsNotDestroyed(); if (from >= TextLength()) return 0; @@ -2131,6 +2187,7 @@ HashSet<const SimpleFontData*>* fallback_fonts, FloatRect* glyph_bounds, float expansion) const { + CheckIsNotDestroyed(); DCHECK_LE(from + len, TextLength()); if (!TextLength()) return 0; @@ -2177,6 +2234,7 @@ } PhysicalRect LayoutText::PhysicalLinesBoundingBox() const { + CheckIsNotDestroyed(); PhysicalRect result; CollectLineBoxRects( [&result](const PhysicalRect& r) { result.UniteIfNonZero(r); }); @@ -2187,6 +2245,7 @@ } PhysicalRect LayoutText::PhysicalVisualOverflowRect() const { + CheckIsNotDestroyed(); if (IsInLayoutNGInlineFormattingContext()) { DCHECK(RuntimeEnabledFeatures::LayoutNGEnabled()); if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) @@ -2242,10 +2301,12 @@ } PhysicalRect LayoutText::LocalVisualRectIgnoringVisibility() const { + CheckIsNotDestroyed(); return UnionRect(PhysicalVisualOverflowRect(), LocalSelectionVisualRect()); } PhysicalRect LayoutText::LocalSelectionVisualRect() const { + CheckIsNotDestroyed(); DCHECK(!NeedsLayout()); if (!IsSelected()) @@ -2284,12 +2345,14 @@ } const NGOffsetMapping* LayoutText::GetNGOffsetMapping() const { + CheckIsNotDestroyed(); if (!RuntimeEnabledFeatures::LayoutNGEnabled()) return nullptr; return NGOffsetMapping::GetFor(this); } Position LayoutText::PositionForCaretOffset(unsigned offset) const { + CheckIsNotDestroyed(); // ::first-letter handling should be done by LayoutTextFragment override. DCHECK(!IsTextFragment()); // BR handling should be done by LayoutBR override. @@ -2313,6 +2376,7 @@ base::Optional<unsigned> LayoutText::CaretOffsetForPosition( const Position& position) const { + CheckIsNotDestroyed(); // ::first-letter handling should be done by LayoutTextFragment override. DCHECK(!IsTextFragment()); // BR handling should be done by LayoutBR override. @@ -2334,6 +2398,7 @@ } int LayoutText::CaretMinOffset() const { + CheckIsNotDestroyed(); DCHECK(!GetDocument().NeedsLayoutTreeUpdate()); if (auto* mapping = GetNGOffsetMapping()) { @@ -2358,6 +2423,7 @@ } int LayoutText::CaretMaxOffset() const { + CheckIsNotDestroyed(); DCHECK(!GetDocument().NeedsLayoutTreeUpdate()); if (auto* mapping = GetNGOffsetMapping()) { @@ -2383,6 +2449,7 @@ } unsigned LayoutText::ResolvedTextLength() const { + CheckIsNotDestroyed(); if (auto* mapping = GetNGOffsetMapping()) { const Position start_position = PositionForCaretOffset(0); const Position end_position = PositionForCaretOffset(TextLength()); @@ -2410,12 +2477,14 @@ } bool LayoutText::HasNonCollapsedText() const { + CheckIsNotDestroyed(); if (GetNGOffsetMapping()) return ResolvedTextLength(); return FirstTextBox(); } bool LayoutText::ContainsCaretOffset(int text_offset) const { + CheckIsNotDestroyed(); DCHECK_GE(text_offset, 0); if (auto* mapping = GetNGOffsetMapping()) { if (text_offset > static_cast<int>(TextLength())) @@ -2480,6 +2549,7 @@ } bool LayoutText::IsBeforeNonCollapsedCharacter(unsigned text_offset) const { + CheckIsNotDestroyed(); if (auto* mapping = GetNGOffsetMapping()) { if (text_offset >= TextLength()) return false; @@ -2513,6 +2583,7 @@ } bool LayoutText::IsAfterNonCollapsedCharacter(unsigned text_offset) const { + CheckIsNotDestroyed(); if (auto* mapping = GetNGOffsetMapping()) { if (!text_offset) return false; @@ -2549,6 +2620,7 @@ void LayoutText::MomentarilyRevealLastTypedCharacter( unsigned last_typed_character_offset) { + CheckIsNotDestroyed(); SecureTextTimer* secure_text_timer = GetSecureTextTimers().at(this); if (!secure_text_timer) { secure_text_timer = new SecureTextTimer(this); @@ -2558,6 +2630,7 @@ } scoped_refptr<AbstractInlineTextBox> LayoutText::FirstAbstractInlineTextBox() { + CheckIsNotDestroyed(); if (IsInLayoutNGInlineFormattingContext()) { NGInlineCursor cursor; cursor.MoveTo(*this); @@ -2568,6 +2641,7 @@ } void LayoutText::InvalidatePaint(const PaintInvalidatorContext& context) const { + CheckIsNotDestroyed(); if (ShouldInvalidateSelection() && !IsSelected()) GetSelectionDisplayItemClientMap().erase(this); LayoutObject::InvalidatePaint(context); @@ -2575,6 +2649,7 @@ void LayoutText::InvalidateDisplayItemClients( PaintInvalidationReason reason) const { + CheckIsNotDestroyed(); ObjectPaintInvalidator invalidator(*this); invalidator.InvalidateDisplayItemClient(*this, reason); @@ -2607,6 +2682,7 @@ } const DisplayItemClient* LayoutText::GetSelectionDisplayItemClient() const { + CheckIsNotDestroyed(); if (!IsSelected()) return nullptr; if (IsInLayoutNGInlineFormattingContext() && @@ -2621,10 +2697,12 @@ } PhysicalRect LayoutText::DebugRect() const { + CheckIsNotDestroyed(); return PhysicalRect(EnclosingIntRect(PhysicalLinesBoundingBox())); } DOMNodeId LayoutText::EnsureNodeId() { + CheckIsNotDestroyed(); if (node_id_ == kInvalidDOMNodeId) { if (auto* content_capture_manager = GetContentCaptureManager()) { if (auto* node = GetNode()) { @@ -2637,6 +2715,7 @@ } ContentCaptureManager* LayoutText::GetContentCaptureManager() { + CheckIsNotDestroyed(); if (auto* node = GetNode()) { if (auto* frame = node->GetDocument().GetFrame()) { return frame->LocalFrameRoot().GetContentCaptureManager(); @@ -2646,6 +2725,7 @@ } void LayoutText::SetInlineItems(NGInlineItem* begin, NGInlineItem* end) { + CheckIsNotDestroyed(); #if DCHECK_IS_ON() for (NGInlineItem* item = begin; item != end; ++item) { DCHECK_EQ(item->GetLayoutObject(), this); @@ -2659,6 +2739,7 @@ } void LayoutText::ClearInlineItems() { + CheckIsNotDestroyed(); has_bidi_control_items_ = false; valid_ng_items_ = false; if (base::span<NGInlineItem>* items = GetNGInlineItems()) @@ -2666,6 +2747,7 @@ } const base::span<NGInlineItem>& LayoutText::InlineItems() const { + CheckIsNotDestroyed(); DCHECK(valid_ng_items_); DCHECK(GetNGInlineItems()); DCHECK(!GetNGInlineItems()->empty());
diff --git a/third_party/blink/renderer/core/layout/layout_text.h b/third_party/blink/renderer/core/layout/layout_text.h index 0f5089d74..e5a8ab7 100644 --- a/third_party/blink/renderer/core/layout/layout_text.h +++ b/third_party/blink/renderer/core/layout/layout_text.h
@@ -86,9 +86,15 @@ scoped_refptr<const ComputedStyle>, LegacyLayout); - const char* GetName() const override { return "LayoutText"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutText"; + } - bool IsTextFragment() const { return is_text_fragment_; } + bool IsTextFragment() const { + CheckIsNotDestroyed(); + return is_text_fragment_; + } virtual bool IsWordBreak() const; virtual scoped_refptr<StringImpl> OriginalText() const; @@ -104,12 +110,21 @@ void ClearFirstInlineFragmentItemIndex() final; void SetFirstInlineFragmentItemIndex(wtf_size_t) final; - const String& GetText() const { return text_; } - virtual unsigned TextStartOffset() const { return 0; } + const String& GetText() const { + CheckIsNotDestroyed(); + return text_; + } + virtual unsigned TextStartOffset() const { + CheckIsNotDestroyed(); + return 0; + } String PlainText() const; // Returns first letter part of |LayoutTextFragment|. - virtual LayoutText* GetFirstLetterPart() const { return nullptr; } + virtual LayoutText* GetFirstLetterPart() const { + CheckIsNotDestroyed(); + return nullptr; + } InlineTextBox* CreateInlineTextBox(int start, uint16_t length); void DirtyOrDeleteLineBoxesIfNeeded(bool full_layout); @@ -128,15 +143,31 @@ PositionWithAffinity PositionForPoint(const PhysicalOffset&) const override; - bool Is8Bit() const { return text_.Is8Bit(); } - const LChar* Characters8() const { return text_.Impl()->Characters8(); } - const UChar* Characters16() const { return text_.Impl()->Characters16(); } - bool HasEmptyText() const { return text_.IsEmpty(); } + bool Is8Bit() const { + CheckIsNotDestroyed(); + return text_.Is8Bit(); + } + const LChar* Characters8() const { + CheckIsNotDestroyed(); + return text_.Impl()->Characters8(); + } + const UChar* Characters16() const { + CheckIsNotDestroyed(); + return text_.Impl()->Characters16(); + } + bool HasEmptyText() const { + CheckIsNotDestroyed(); + return text_.IsEmpty(); + } UChar CharacterAt(unsigned) const; UChar UncheckedCharacterAt(unsigned) const; - UChar operator[](unsigned i) const { return UncheckedCharacterAt(i); } + UChar operator[](unsigned i) const { + CheckIsNotDestroyed(); + return UncheckedCharacterAt(i); + } UChar32 CodepointAt(unsigned) const; unsigned TextLength() const { + CheckIsNotDestroyed(); return text_.length(); } // non virtual implementation of length() bool ContainsOnlyWhitespace(unsigned from, unsigned len) const; @@ -209,6 +240,7 @@ // TextBoxes() and FirstInlineFragment() are mutually exclusive, // depends on IsInLayoutNGInlineFormattingContext(). const InlineTextBoxList& TextBoxes() const { + CheckIsNotDestroyed(); return IsInLayoutNGInlineFormattingContext() ? InlineTextBoxList::Empty() : text_boxes_; } @@ -216,12 +248,21 @@ // Returns first |InlineTextBox| produces for associated |Node|. // Note: When |this| is remaining part of ::first-letter, this function // returns first-letter part of |InlineTextBox| instead of remaining part. - InlineTextBox* FirstTextBox() const { return TextBoxes().First(); } - InlineTextBox* LastTextBox() const { return TextBoxes().Last(); } + InlineTextBox* FirstTextBox() const { + CheckIsNotDestroyed(); + return TextBoxes().First(); + } + InlineTextBox* LastTextBox() const { + CheckIsNotDestroyed(); + return TextBoxes().Last(); + } // TODO(layoutng) Legacy-only implementation of HasTextBoxes. // All callers should call HasTextBoxes instead, and take NG into account. - bool HasLegacyTextBoxes() const { return FirstTextBox(); } + bool HasLegacyTextBoxes() const { + CheckIsNotDestroyed(); + return FirstTextBox(); + } // Compute the rect and offset of text boxes for this LayoutText. struct TextBoxInfo { @@ -261,9 +302,13 @@ // True if any character remains after CSS white-space collapsing. bool HasNonCollapsedText() const; - bool ContainsReversedText() const { return contains_reversed_text_; } + bool ContainsReversedText() const { + CheckIsNotDestroyed(); + return contains_reversed_text_; + } bool IsSecure() const { + CheckIsNotDestroyed(); return StyleRef().TextSecurity() != ETextSecurity::kNone; } void MomentarilyRevealLastTypedCharacter( @@ -276,16 +321,21 @@ scoped_refptr<AbstractInlineTextBox> FirstAbstractInlineTextBox(); bool HasAbstractInlineTextBox() const { + CheckIsNotDestroyed(); return has_abstract_inline_text_box_; } - void SetHasAbstractInlineTextBox() { has_abstract_inline_text_box_ = true; } + void SetHasAbstractInlineTextBox() { + CheckIsNotDestroyed(); + has_abstract_inline_text_box_ = true; + } float HyphenWidth(const Font&, TextDirection); PhysicalRect DebugRect() const override; void AutosizingMultiplerChanged() { + CheckIsNotDestroyed(); known_to_have_no_overflow_and_no_fallback_fonts_ = false; // The font size is changing, so we need to make sure to rebuild everything. @@ -309,24 +359,46 @@ unsigned* start, unsigned* end) const; DOMNodeId EnsureNodeId(); - bool HasNodeId() const { return node_id_ != kInvalidDOMNodeId; } + bool HasNodeId() const { + CheckIsNotDestroyed(); + return node_id_ != kInvalidDOMNodeId; + } void SetInlineItems(NGInlineItem* begin, NGInlineItem* end); void ClearInlineItems(); - bool HasValidInlineItems() const { return valid_ng_items_; } + bool HasValidInlineItems() const { + CheckIsNotDestroyed(); + return valid_ng_items_; + } const base::span<NGInlineItem>& InlineItems() const; // Inline items depends on context. It needs to be invalidated not only when // it was inserted/changed but also it was moved. - void InvalidateInlineItems() { valid_ng_items_ = false; } + void InvalidateInlineItems() { + CheckIsNotDestroyed(); + valid_ng_items_ = false; + } - bool HasBidiControlInlineItems() const { return has_bidi_control_items_; } - void SetHasBidiControlInlineItems() { has_bidi_control_items_ = true; } - void ClearHasBidiControlInlineItems() { has_bidi_control_items_ = false; } + bool HasBidiControlInlineItems() const { + CheckIsNotDestroyed(); + return has_bidi_control_items_; + } + void SetHasBidiControlInlineItems() { + CheckIsNotDestroyed(); + has_bidi_control_items_ = true; + } + void ClearHasBidiControlInlineItems() { + CheckIsNotDestroyed(); + has_bidi_control_items_ = false; + } virtual const base::span<NGInlineItem>* GetNGInlineItems() const { + CheckIsNotDestroyed(); return nullptr; } - virtual base::span<NGInlineItem>* GetNGInlineItems() { return nullptr; } + virtual base::span<NGInlineItem>* GetNGInlineItems() { + CheckIsNotDestroyed(); + return nullptr; + } void InvalidateSubtreeLayoutForFontUpdates() override; @@ -340,10 +412,12 @@ // For LayoutShiftTracker. Saves the value of LogicalStartingPoint() value // during the previous paint invalidation. LogicalOffset PreviousLogicalStartingPoint() const { + CheckIsNotDestroyed(); return previous_logical_starting_point_; } // This is const because LayoutObjects are const for paint invalidation. void SetPreviousLogicalStartingPoint(const LogicalOffset& point) const { + CheckIsNotDestroyed(); DCHECK_EQ(GetDocument().Lifecycle().GetState(), DocumentLifecycle::kInPrePaint); previous_logical_starting_point_ = point; @@ -355,7 +429,9 @@ protected: void WillBeDestroyed() override; - void StyleWillChange(StyleDifference, const ComputedStyle&) final {} + void StyleWillChange(StyleDifference, const ComputedStyle&) final { + CheckIsNotDestroyed(); + } void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override; void InLayoutNGInlineFormattingContextWillChange(bool) final; @@ -368,7 +444,10 @@ void InvalidatePaint(const PaintInvalidatorContext&) const final; void InvalidateDisplayItemClients(PaintInvalidationReason) const final; - bool CanBeSelectionLeafInternal() const final { return true; } + bool CanBeSelectionLeafInternal() const final { + CheckIsNotDestroyed(); + return true; + } private: InlineTextBoxList& MutableTextBoxes(); @@ -390,15 +469,25 @@ // Make length() private so that callers that have a LayoutText* // will use the more efficient textLength() instead, while // callers with a LayoutObject* can continue to use length(). - unsigned length() const final { return TextLength(); } + unsigned length() const final { + CheckIsNotDestroyed(); + return TextLength(); + } // See the class comment as to why we shouldn't call this function directly. - void Paint(const PaintInfo&) const final { NOTREACHED(); } - void UpdateLayout() final { NOTREACHED(); } + void Paint(const PaintInfo&) const final { + CheckIsNotDestroyed(); + NOTREACHED(); + } + void UpdateLayout() final { + CheckIsNotDestroyed(); + NOTREACHED(); + } bool NodeAtPoint(HitTestResult&, const HitTestLocation&, const PhysicalOffset&, HitTestAction) final { + CheckIsNotDestroyed(); NOTREACHED(); return false; }
diff --git a/third_party/blink/renderer/core/layout/layout_text_combine.cc b/third_party/blink/renderer/core/layout/layout_text_combine.cc index 60a7197..63a42de6 100644 --- a/third_party/blink/renderer/core/layout/layout_text_combine.cc +++ b/third_party/blink/renderer/core/layout/layout_text_combine.cc
@@ -36,6 +36,7 @@ void LayoutTextCombine::StyleDidChange(StyleDifference diff, const ComputedStyle* old_style) { + CheckIsNotDestroyed(); LayoutText::StyleDidChange(diff, old_style); UpdateIsCombined(); if (!IsCombined()) @@ -47,6 +48,7 @@ } void LayoutTextCombine::TextDidChange() { + CheckIsNotDestroyed(); LayoutText::TextDidChange(); bool was_combined = IsCombined(); @@ -80,6 +82,7 @@ HashSet<const SimpleFontData*>* fallback_fonts, FloatRect* glyph_bounds, float) const { + CheckIsNotDestroyed(); if (!length) return 0; @@ -107,6 +110,7 @@ GraphicsContext& context, const PhysicalRect& box_rect, bool clip) const { + CheckIsNotDestroyed(); DCHECK(is_combined_); // No transform needed if we don't have a font. @@ -150,6 +154,7 @@ } void LayoutTextCombine::UpdateIsCombined() { + CheckIsNotDestroyed(); // CSS3 spec says text-combine works only in vertical writing mode. is_combined_ = !StyleRef().IsHorizontalWritingMode() // Nothing to combine. @@ -157,6 +162,7 @@ } void LayoutTextCombine::UpdateFontStyleForCombinedText() { + CheckIsNotDestroyed(); DCHECK(is_combined_); scoped_refptr<ComputedStyle> style = ComputedStyle::Clone(StyleRef());
diff --git a/third_party/blink/renderer/core/layout/layout_text_combine.h b/third_party/blink/renderer/core/layout/layout_text_combine.h index 7fcd298..b1e2f16 100644 --- a/third_party/blink/renderer/core/layout/layout_text_combine.h +++ b/third_party/blink/renderer/core/layout/layout_text_combine.h
@@ -35,20 +35,33 @@ public: LayoutTextCombine(Node*, scoped_refptr<StringImpl>); - bool IsCombined() const { return is_combined_; } + bool IsCombined() const { + CheckIsNotDestroyed(); + return is_combined_; + } float CombinedTextWidth(const Font& font) const { + CheckIsNotDestroyed(); return font.GetFontDescription().ComputedSize(); } - const Font& OriginalFont() const { return Parent()->StyleRef().GetFont(); } + const Font& OriginalFont() const { + CheckIsNotDestroyed(); + return Parent()->StyleRef().GetFont(); + } void TransformToInlineCoordinates(GraphicsContext&, const PhysicalRect& box_rect, bool clip = false) const; LayoutUnit InlineWidthForLayout() const; - const char* GetName() const override { return "LayoutTextCombine"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutTextCombine"; + } private: - bool IsCombineText() const override { return true; } + bool IsCombineText() const override { + CheckIsNotDestroyed(); + return true; + } float Width(unsigned from, unsigned length, const Font&,
diff --git a/third_party/blink/renderer/core/layout/layout_text_control.cc b/third_party/blink/renderer/core/layout/layout_text_control.cc index 040271aa..059a626 100644 --- a/third_party/blink/renderer/core/layout/layout_text_control.cc +++ b/third_party/blink/renderer/core/layout/layout_text_control.cc
@@ -40,15 +40,18 @@ LayoutTextControl::~LayoutTextControl() = default; TextControlElement* LayoutTextControl::GetTextControlElement() const { + CheckIsNotDestroyed(); return ToTextControl(GetNode()); } TextControlInnerEditorElement* LayoutTextControl::InnerEditorElement() const { + CheckIsNotDestroyed(); return GetTextControlElement()->InnerEditorElement(); } void LayoutTextControl::StyleDidChange(StyleDifference diff, const ComputedStyle* old_style) { + CheckIsNotDestroyed(); LayoutBlockFlow::StyleDidChange(diff, old_style); TextControlInnerEditorElement* inner_editor = InnerEditorElement(); if (!inner_editor) @@ -79,6 +82,7 @@ } int LayoutTextControl::ScrollbarThickness() const { + CheckIsNotDestroyed(); return GetDocument().GetPage()->GetScrollbarTheme().ScrollbarThickness( GetDocument().GetPage()->GetChromeClient().WindowToViewportScalar( GetFrame(), 1.0f)); @@ -88,6 +92,7 @@ LayoutUnit logical_height, LayoutUnit logical_top, LogicalExtentComputedValues& computed_values) const { + CheckIsNotDestroyed(); HTMLElement* inner_editor = InnerEditorElement(); DCHECK(inner_editor); if (LayoutBox* inner_editor_box = inner_editor->GetLayoutBox()) { @@ -120,6 +125,7 @@ HitTestResult& result, const HitTestLocation& hit_test_location, const PhysicalOffset& accumulated_offset) { + CheckIsNotDestroyed(); HTMLElement* inner_editor = InnerEditorElement(); if (!inner_editor->GetLayoutObject()) return; @@ -203,6 +209,7 @@ } float LayoutTextControl::GetAvgCharWidth(const AtomicString& family) const { + CheckIsNotDestroyed(); const Font& font = StyleRef().GetFont(); const SimpleFontData* primary_font = font.PrimaryFont(); @@ -217,6 +224,7 @@ } MinMaxSizes LayoutTextControl::ComputeIntrinsicLogicalWidths() const { + CheckIsNotDestroyed(); MinMaxSizes sizes; sizes += BorderAndPaddingLogicalWidth(); @@ -240,12 +248,14 @@ void LayoutTextControl::AddOutlineRects(Vector<PhysicalRect>& rects, const PhysicalOffset& additional_offset, NGOutlineType) const { + CheckIsNotDestroyed(); rects.emplace_back(additional_offset, Size()); } LayoutObject* LayoutTextControl::LayoutSpecialExcludedChild( bool relayout_children, SubtreeLayoutScope& layout_scope) { + CheckIsNotDestroyed(); HTMLElement* placeholder = ToTextControl(GetNode())->PlaceholderElement(); LayoutObject* placeholder_layout_object = placeholder ? placeholder->GetLayoutObject() : nullptr; @@ -257,6 +267,7 @@ } LayoutUnit LayoutTextControl::FirstLineBoxBaseline() const { + CheckIsNotDestroyed(); if (ShouldApplyLayoutContainment()) return LayoutUnit(-1);
diff --git a/third_party/blink/renderer/core/layout/layout_text_control.h b/third_party/blink/renderer/core/layout/layout_text_control.h index b3298fc3..f91d803 100644 --- a/third_party/blink/renderer/core/layout/layout_text_control.h +++ b/third_party/blink/renderer/core/layout/layout_text_control.h
@@ -37,9 +37,13 @@ ~LayoutTextControl() override; TextControlElement* GetTextControlElement() const; - const char* GetName() const override { return "LayoutTextControl"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutTextControl"; + } bool CreatesNewFormattingContext() const final { + CheckIsNotDestroyed(); // INPUT and other replaced elements rendered by Blink itself should be // completely contained. return true; @@ -77,18 +81,24 @@ LayoutUnit FirstLineBoxBaseline() const override; bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectTextControl || LayoutBlockFlow::IsOfType(type); } private: MinMaxSizes ComputeIntrinsicLogicalWidths() const final; - void RemoveLeftoverAnonymousBlock(LayoutBlock*) final {} + void RemoveLeftoverAnonymousBlock(LayoutBlock*) final { + CheckIsNotDestroyed(); + } void AddOutlineRects(Vector<PhysicalRect>&, const PhysicalOffset& additional_offset, NGOutlineType) const final; - bool CanBeProgramaticallyScrolled() const final { return true; } + bool CanBeProgramaticallyScrolled() const final { + CheckIsNotDestroyed(); + return true; + } }; template <>
diff --git a/third_party/blink/renderer/core/layout/layout_text_control_multi_line.cc b/third_party/blink/renderer/core/layout/layout_text_control_multi_line.cc index c972672..74f9794 100644 --- a/third_party/blink/renderer/core/layout/layout_text_control_multi_line.cc +++ b/third_party/blink/renderer/core/layout/layout_text_control_multi_line.cc
@@ -41,6 +41,7 @@ const HitTestLocation& hit_test_location, const PhysicalOffset& accumulated_offset, HitTestAction hit_test_action) { + CheckIsNotDestroyed(); if (!LayoutTextControl::NodeAtPoint(result, hit_test_location, accumulated_offset, hit_test_action)) return false; @@ -58,6 +59,7 @@ LayoutUnit LayoutTextControlMultiLine::PreferredContentLogicalWidth( float char_width) const { + CheckIsNotDestroyed(); int factor = To<HTMLTextAreaElement>(GetNode())->cols(); return static_cast<LayoutUnit>(ceilf(char_width * factor)) + ScrollbarThickness(); @@ -66,6 +68,7 @@ LayoutUnit LayoutTextControlMultiLine::ComputeControlLogicalHeight( LayoutUnit line_height, LayoutUnit non_content_height) const { + CheckIsNotDestroyed(); return line_height * To<HTMLTextAreaElement>(GetNode())->rows() + non_content_height; } @@ -75,6 +78,7 @@ bool first_line, LineDirectionMode direction, LinePositionMode line_position_mode) const { + CheckIsNotDestroyed(); return LayoutBox::BaselinePosition(baseline_type, first_line, direction, line_position_mode); } @@ -82,6 +86,7 @@ LayoutObject* LayoutTextControlMultiLine::LayoutSpecialExcludedChild( bool relayout_children, SubtreeLayoutScope& layout_scope) { + CheckIsNotDestroyed(); LayoutObject* placeholder_layout_object = LayoutTextControl::LayoutSpecialExcludedChild(relayout_children, layout_scope); @@ -97,6 +102,7 @@ } LayoutUnit LayoutTextControlMultiLine::ScrollWidth() const { + CheckIsNotDestroyed(); // If in preview state, fake the scroll width to prevent that any information // about the suggested content can be derived from the size. if (!GetTextControlElement()->SuggestedValue().IsEmpty()) @@ -105,6 +111,7 @@ } LayoutUnit LayoutTextControlMultiLine::ScrollHeight() const { + CheckIsNotDestroyed(); // If in preview state, fake the scroll height to prevent that any information // about the suggested content can be derived from the size. if (!GetTextControlElement()->SuggestedValue().IsEmpty())
diff --git a/third_party/blink/renderer/core/layout/layout_text_control_multi_line.h b/third_party/blink/renderer/core/layout/layout_text_control_multi_line.h index 21111aa..be059db 100644 --- a/third_party/blink/renderer/core/layout/layout_text_control_multi_line.h +++ b/third_party/blink/renderer/core/layout/layout_text_control_multi_line.h
@@ -36,6 +36,7 @@ private: bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectTextArea || LayoutTextControl::IsOfType(type); } @@ -56,6 +57,7 @@ LineDirectionMode, LinePositionMode = kPositionOnContainingLine) const override; LayoutUnit InlineBlockBaseline(LineDirectionMode) const override { + CheckIsNotDestroyed(); return LayoutUnit(-1); }
diff --git a/third_party/blink/renderer/core/layout/layout_text_control_single_line.cc b/third_party/blink/renderer/core/layout/layout_text_control_single_line.cc index 11aee944..55bd72d 100644 --- a/third_party/blink/renderer/core/layout/layout_text_control_single_line.cc +++ b/third_party/blink/renderer/core/layout/layout_text_control_single_line.cc
@@ -47,26 +47,31 @@ LayoutTextControlSingleLine::~LayoutTextControlSingleLine() = default; inline Element* LayoutTextControlSingleLine::ContainerElement() const { + CheckIsNotDestroyed(); return InputElement()->UserAgentShadowRoot()->getElementById( shadow_element_names::kIdTextFieldContainer); } inline Element* LayoutTextControlSingleLine::EditingViewPortElement() const { + CheckIsNotDestroyed(); return InputElement()->UserAgentShadowRoot()->getElementById( shadow_element_names::kIdEditingViewPort); } inline HTMLElement* LayoutTextControlSingleLine::InnerSpinButtonElement() const { + CheckIsNotDestroyed(); return To<HTMLElement>(InputElement()->UserAgentShadowRoot()->getElementById( shadow_element_names::kIdSpinButton)); } void LayoutTextControlSingleLine::Paint(const PaintInfo& paint_info) const { + CheckIsNotDestroyed(); TextControlSingleLinePainter(*this).Paint(paint_info); } void LayoutTextControlSingleLine::UpdateLayout() { + CheckIsNotDestroyed(); LayoutAnalyzer::Scope analyzer(*this); LayoutBlockFlow::UpdateBlockLayout(true); @@ -141,6 +146,7 @@ const HitTestLocation& hit_test_location, const PhysicalOffset& accumulated_offset, HitTestAction hit_test_action) { + CheckIsNotDestroyed(); if (!LayoutTextControl::NodeAtPoint(result, hit_test_location, accumulated_offset, hit_test_action)) return false; @@ -174,6 +180,7 @@ } void LayoutTextControlSingleLine::CapsLockStateMayHaveChanged() { + CheckIsNotDestroyed(); if (!GetNode()) return; @@ -199,6 +206,7 @@ LayoutUnit LayoutTextControlSingleLine::PreferredContentLogicalWidth( float char_width) const { + CheckIsNotDestroyed(); int factor; bool includes_decoration = InputElement()->SizeShouldIncludeDecoration(factor); @@ -235,10 +243,12 @@ LayoutUnit LayoutTextControlSingleLine::ComputeControlLogicalHeight( LayoutUnit line_height, LayoutUnit non_content_height) const { + CheckIsNotDestroyed(); return line_height + non_content_height; } LayoutUnit LayoutTextControlSingleLine::ScrollWidth() const { + CheckIsNotDestroyed(); // If in preview state, fake the scroll width to prevent that any information // about the suggested content can be derived from the size. if (!GetTextControlElement()->SuggestedValue().IsEmpty()) @@ -256,6 +266,7 @@ } LayoutUnit LayoutTextControlSingleLine::ScrollHeight() const { + CheckIsNotDestroyed(); // If in preview state, fake the scroll height to prevent that any information // about the suggested content can be derived from the size. if (!GetTextControlElement()->SuggestedValue().IsEmpty()) @@ -273,11 +284,12 @@ } HTMLInputElement* LayoutTextControlSingleLine::InputElement() const { + CheckIsNotDestroyed(); return To<HTMLInputElement>(GetNode()); } -void LayoutTextControlSingleLine::ComputeVisualOverflow( - bool recompute_floats) { +void LayoutTextControlSingleLine::ComputeVisualOverflow(bool recompute_floats) { + CheckIsNotDestroyed(); LayoutRect previous_visual_overflow_rect = VisualOverflowRect(); ClearVisualOverflow(); AddVisualOverflowFromChildren();
diff --git a/third_party/blink/renderer/core/layout/layout_text_control_single_line.h b/third_party/blink/renderer/core/layout/layout_text_control_single_line.h index 7c0a7f1..b40e2c9 100644 --- a/third_party/blink/renderer/core/layout/layout_text_control_single_line.h +++ b/third_party/blink/renderer/core/layout/layout_text_control_single_line.h
@@ -44,6 +44,7 @@ void CapsLockStateMayHaveChanged(); bool ShouldDrawCapsLockIndicator() const { + CheckIsNotDestroyed(); return should_draw_caps_lock_indicator_; } @@ -54,6 +55,7 @@ private: bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectTextField || LayoutTextControl::IsOfType(type); } @@ -80,9 +82,12 @@ // If the INPUT content height is smaller than the font height, the // inner-editor element overflows the INPUT box intentionally, however it // shouldn't affect outside of the INPUT box. So we ignore child overflow. - void AddLayoutOverflowFromChildren() final {} + void AddLayoutOverflowFromChildren() final { CheckIsNotDestroyed(); } - bool AllowsNonVisibleOverflow() const override { return false; } + bool AllowsNonVisibleOverflow() const override { + CheckIsNotDestroyed(); + return false; + } HTMLElement* InnerSpinButtonElement() const; @@ -100,15 +105,24 @@ class LayoutTextControlInnerEditor : public LayoutBlockFlow { public: - LayoutTextControlInnerEditor(Element* element) : LayoutBlockFlow(element) {} + LayoutTextControlInnerEditor(Element* element) : LayoutBlockFlow(element) { + CheckIsNotDestroyed(); + } private: bool IsIntrinsicallyScrollable( ScrollbarOrientation orientation) const override { + CheckIsNotDestroyed(); return orientation == kHorizontalScrollbar; } - bool ScrollsOverflowX() const override { return IsScrollContainer(); } - bool ScrollsOverflowY() const override { return false; } + bool ScrollsOverflowX() const override { + CheckIsNotDestroyed(); + return IsScrollContainer(); + } + bool ScrollsOverflowY() const override { + CheckIsNotDestroyed(); + return false; + } }; } // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_text_fragment.cc b/third_party/blink/renderer/core/layout/layout_text_fragment.cc index a3a975f0..2c20041c 100644 --- a/third_party/blink/renderer/core/layout/layout_text_fragment.cc +++ b/third_party/blink/renderer/core/layout/layout_text_fragment.cc
@@ -81,6 +81,7 @@ } void LayoutTextFragment::WillBeDestroyed() { + CheckIsNotDestroyed(); if (is_remaining_text_layout_object_ && first_letter_pseudo_element_) first_letter_pseudo_element_->ClearRemainingTextLayoutObject(); first_letter_pseudo_element_ = nullptr; @@ -88,16 +89,19 @@ } scoped_refptr<StringImpl> LayoutTextFragment::CompleteText() const { + CheckIsNotDestroyed(); Text* text = AssociatedTextNode(); return text ? text->DataImpl() : ContentString(); } void LayoutTextFragment::SetContentString(StringImpl* str) { + CheckIsNotDestroyed(); content_string_ = str; SetTextIfNeeded(str); } scoped_refptr<StringImpl> LayoutTextFragment::OriginalText() const { + CheckIsNotDestroyed(); scoped_refptr<StringImpl> result = CompleteText(); if (!result) return nullptr; @@ -105,6 +109,7 @@ } void LayoutTextFragment::TextDidChange() { + CheckIsNotDestroyed(); LayoutText::TextDidChange(); start_ = 0; @@ -124,6 +129,7 @@ void LayoutTextFragment::SetTextFragment(scoped_refptr<StringImpl> text, unsigned start, unsigned length) { + CheckIsNotDestroyed(); // Note, we have to call |LayoutText::TextDidChange()| here because, if we // use our version we will, potentially, screw up the first-letter settings // where we only use portions of the string. @@ -137,6 +143,7 @@ } void LayoutTextFragment::TransformText() { + CheckIsNotDestroyed(); // Note, we have to call LayoutText::TextDidChange()| here because, if we use // our version we will, potentially, screw up the first-letter settings where // we only use portions of the string. @@ -147,6 +154,7 @@ } UChar LayoutTextFragment::PreviousCharacter() const { + CheckIsNotDestroyed(); if (Start()) { StringImpl* original = CompleteText().get(); if (original && Start() <= original->length()) @@ -159,6 +167,7 @@ // If this is the layoutObject for a first-letter pseudoNode then we have to // look at the node for the remaining text to find our content. Text* LayoutTextFragment::AssociatedTextNode() const { + CheckIsNotDestroyed(); Node* node = GetFirstLetterPseudoElement(); if (is_remaining_text_layout_object_ || !node) { // If we don't have a node, then we aren't part of a first-letter pseudo @@ -182,6 +191,7 @@ } LayoutText* LayoutTextFragment::GetFirstLetterPart() const { + CheckIsNotDestroyed(); if (!is_remaining_text_layout_object_) return nullptr; // Node: We assume first letter pseudo element has only one child and it @@ -197,6 +207,7 @@ void LayoutTextFragment::UpdateHitTestResult( HitTestResult& result, const PhysicalOffset& point) const { + CheckIsNotDestroyed(); if (result.InnerNode()) return; @@ -210,6 +221,7 @@ } Position LayoutTextFragment::PositionForCaretOffset(unsigned offset) const { + CheckIsNotDestroyed(); // TODO(layout-dev): Make the following DCHECK always enabled after we // properly support 'text-transform' changing text length. #if DCHECK_IS_ON() @@ -226,6 +238,7 @@ base::Optional<unsigned> LayoutTextFragment::CaretOffsetForPosition( const Position& position) const { + CheckIsNotDestroyed(); if (position.IsNull() || position.AnchorNode() != AssociatedTextNode()) return base::nullopt; unsigned dom_offset;
diff --git a/third_party/blink/renderer/core/layout/layout_text_fragment.h b/third_party/blink/renderer/core/layout/layout_text_fragment.h index 9dfed8a..dd5c143 100644 --- a/third_party/blink/renderer/core/layout/layout_text_fragment.h +++ b/third_party/blink/renderer/core/layout/layout_text_fragment.h
@@ -59,13 +59,25 @@ base::Optional<unsigned> CaretOffsetForPosition( const Position&) const override; - unsigned Start() const { return start_; } - unsigned FragmentLength() const { return fragment_length_; } + unsigned Start() const { + CheckIsNotDestroyed(); + return start_; + } + unsigned FragmentLength() const { + CheckIsNotDestroyed(); + return fragment_length_; + } - unsigned TextStartOffset() const override { return Start(); } + unsigned TextStartOffset() const override { + CheckIsNotDestroyed(); + return Start(); + } void SetContentString(StringImpl*); - StringImpl* ContentString() const { return content_string_.get(); } + StringImpl* ContentString() const { + CheckIsNotDestroyed(); + return content_string_.get(); + } // The complete text is all of the text in the associated DOM text node. scoped_refptr<StringImpl> CompleteText() const; // The fragment text is the text which will be used by this @@ -80,19 +92,26 @@ void TransformText() override; - const char* GetName() const override { return "LayoutTextFragment"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutTextFragment"; + } void SetFirstLetterPseudoElement(FirstLetterPseudoElement* element) { + CheckIsNotDestroyed(); first_letter_pseudo_element_ = element; } FirstLetterPseudoElement* GetFirstLetterPseudoElement() const { + CheckIsNotDestroyed(); return first_letter_pseudo_element_; } void SetIsRemainingTextLayoutObject(bool is_remaining_text) { + CheckIsNotDestroyed(); is_remaining_text_layout_object_ = is_remaining_text; } bool IsRemainingTextLayoutObject() const { + CheckIsNotDestroyed(); return is_remaining_text_layout_object_; }
diff --git a/third_party/blink/renderer/core/layout/layout_video.cc b/third_party/blink/renderer/core/layout/layout_video.cc index ee2d9d3f..cc78cb6 100644 --- a/third_party/blink/renderer/core/layout/layout_video.cc +++ b/third_party/blink/renderer/core/layout/layout_video.cc
@@ -49,12 +49,14 @@ } void LayoutVideo::IntrinsicSizeChanged() { + CheckIsNotDestroyed(); if (VideoElement()->IsShowPosterFlagSet()) LayoutMedia::IntrinsicSizeChanged(); UpdateIntrinsicSize(/* is_in_layout */ false); } void LayoutVideo::UpdateIntrinsicSize(bool is_in_layout) { + CheckIsNotDestroyed(); LayoutSize size = CalculateIntrinsicSize(StyleRef().EffectiveZoom()); // Never set the element size to zero when in a media document. @@ -74,6 +76,7 @@ } LayoutSize LayoutVideo::CalculateIntrinsicSize(float scale) { + CheckIsNotDestroyed(); HTMLVideoElement* video = VideoElement(); DCHECK(video); @@ -118,6 +121,7 @@ void LayoutVideo::ImageChanged(WrappedImagePtr new_image, CanDeferInvalidation defer) { + CheckIsNotDestroyed(); LayoutMedia::ImageChanged(new_image, defer); // Cache the image intrinsic size so we can continue to use it to draw the @@ -134,6 +138,7 @@ } LayoutVideo::DisplayMode LayoutVideo::GetDisplayMode() const { + CheckIsNotDestroyed(); if (!VideoElement()->IsShowPosterFlagSet() || VideoElement()->PosterImageURL().IsEmpty()) { return kVideo; @@ -144,19 +149,23 @@ void LayoutVideo::PaintReplaced(const PaintInfo& paint_info, const PhysicalOffset& paint_offset) const { + CheckIsNotDestroyed(); VideoPainter(*this).PaintReplaced(paint_info, paint_offset); } void LayoutVideo::UpdateLayout() { + CheckIsNotDestroyed(); UpdatePlayer(/* is_in_layout */ true); LayoutMedia::UpdateLayout(); } HTMLVideoElement* LayoutVideo::VideoElement() const { + CheckIsNotDestroyed(); return To<HTMLVideoElement>(GetNode()); } void LayoutVideo::UpdateFromElement() { + CheckIsNotDestroyed(); LayoutMedia::UpdateFromElement(); UpdatePlayer(/* is_in_layout */ false); @@ -164,6 +173,7 @@ } void LayoutVideo::UpdatePlayer(bool is_in_layout) { + CheckIsNotDestroyed(); UpdateIntrinsicSize(is_in_layout); WebMediaPlayer* media_player = MediaElement()->GetWebMediaPlayer(); @@ -178,19 +188,23 @@ LayoutUnit LayoutVideo::ComputeReplacedLogicalWidth( ShouldComputePreferred should_compute_preferred) const { + CheckIsNotDestroyed(); return LayoutReplaced::ComputeReplacedLogicalWidth(should_compute_preferred); } LayoutUnit LayoutVideo::ComputeReplacedLogicalHeight( LayoutUnit estimated_used_width) const { + CheckIsNotDestroyed(); return LayoutReplaced::ComputeReplacedLogicalHeight(estimated_used_width); } LayoutUnit LayoutVideo::MinimumReplacedHeight() const { + CheckIsNotDestroyed(); return LayoutReplaced::MinimumReplacedHeight(); } PhysicalRect LayoutVideo::ReplacedContentRect() const { + CheckIsNotDestroyed(); if (GetDisplayMode() == kVideo) { // Video codecs may need to restart from an I-frame when the output is // resized. Round size in advance to avoid 1px snap difference. @@ -202,10 +216,12 @@ } bool LayoutVideo::SupportsAcceleratedRendering() const { + CheckIsNotDestroyed(); return !!MediaElement()->CcLayer(); } CompositingReasons LayoutVideo::AdditionalCompositingReasons() const { + CheckIsNotDestroyed(); auto* element = To<HTMLMediaElement>(GetNode()); if (element->IsFullscreen() && element->UsesOverlayFullscreenVideo()) return CompositingReason::kVideo;
diff --git a/third_party/blink/renderer/core/layout/layout_video.h b/third_party/blink/renderer/core/layout/layout_video.h index bf28cb53..ca97cf4 100644 --- a/third_party/blink/renderer/core/layout/layout_video.h +++ b/third_party/blink/renderer/core/layout/layout_video.h
@@ -49,11 +49,17 @@ HTMLVideoElement* VideoElement() const; - const char* GetName() const override { return "LayoutVideo"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutVideo"; + } void IntrinsicSizeChanged() override; - bool ComputeShouldClipOverflow() const final { return true; } + bool ComputeShouldClipOverflow() const final { + CheckIsNotDestroyed(); + return true; + } private: void UpdateFromElement() override; @@ -64,6 +70,7 @@ void ImageChanged(WrappedImagePtr, CanDeferInvalidation) override; bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectVideo || LayoutMedia::IsOfType(type); } @@ -78,7 +85,10 @@ LayoutUnit estimated_used_width = LayoutUnit()) const override; LayoutUnit MinimumReplacedHeight() const override; - bool CanHaveAdditionalCompositingReasons() const override { return true; } + bool CanHaveAdditionalCompositingReasons() const override { + CheckIsNotDestroyed(); + return true; + } CompositingReasons AdditionalCompositingReasons() const override; void UpdatePlayer(bool is_in_layout);
diff --git a/third_party/blink/renderer/core/layout/layout_view.cc b/third_party/blink/renderer/core/layout/layout_view.cc index 4707295..2ca8c68 100644 --- a/third_party/blink/renderer/core/layout/layout_view.cc +++ b/third_party/blink/renderer/core/layout/layout_view.cc
@@ -129,6 +129,7 @@ bool LayoutView::HitTest(const HitTestLocation& location, HitTestResult& result) { + CheckIsNotDestroyed(); // We have to recursively update layout/style here because otherwise, when the // hit test recurses into a child document, it could trigger a layout on the // parent document, which can destroy PaintLayer that are higher up in the @@ -153,6 +154,7 @@ bool LayoutView::HitTestNoLifecycleUpdate(const HitTestLocation& location, HitTestResult& result) { + CheckIsNotDestroyed(); TRACE_EVENT_BEGIN0("blink,devtools.timeline", "HitTest"); hit_test_count_++; @@ -214,6 +216,7 @@ } void LayoutView::ClearHitTestCache() { + CheckIsNotDestroyed(); hit_test_cache_->Clear(); auto* object = GetFrame()->OwnerLayoutObject(); if (object) @@ -224,19 +227,23 @@ LayoutUnit logical_height, LayoutUnit, LogicalExtentComputedValues& computed_values) const { + CheckIsNotDestroyed(); computed_values.extent_ = LayoutUnit(ViewLogicalHeightForBoxSizing()); } void LayoutView::UpdateLogicalWidth() { + CheckIsNotDestroyed(); SetLogicalWidth(LayoutUnit(ViewLogicalWidthForBoxSizing())); } bool LayoutView::IsChildAllowed(LayoutObject* child, const ComputedStyle&) const { + CheckIsNotDestroyed(); return child->IsBox(); } bool LayoutView::CanHaveChildren() const { + CheckIsNotDestroyed(); FrameOwner* owner = GetFrame()->Owner(); if (!owner) return true; @@ -257,11 +264,13 @@ #if DCHECK_IS_ON() void LayoutView::CheckLayoutState() { + CheckIsNotDestroyed(); DCHECK(!layout_state_->Next()); } #endif bool LayoutView::ShouldPlaceBlockDirectionScrollbarOnLogicalLeft() const { + CheckIsNotDestroyed(); LocalFrame& frame = GetFrameView()->GetFrame(); // See crbug.com/249860 if (frame.IsMainFrame()) @@ -278,6 +287,7 @@ } void LayoutView::UpdateBlockLayout(bool relayout_children) { + CheckIsNotDestroyed(); SubtreeLayoutScope layout_scope(*this); // Use calcWidth/Height to get the new width/height, since this will take the @@ -314,6 +324,7 @@ } void LayoutView::UpdateLayout() { + CheckIsNotDestroyed(); if (!GetDocument().Printing()) { SetPageLogicalHeight(LayoutUnit()); named_pages_mapper_ = nullptr; @@ -368,6 +379,7 @@ } PhysicalRect LayoutView::LocalVisualRectIgnoringVisibility() const { + CheckIsNotDestroyed(); PhysicalRect rect = PhysicalVisualOverflowRect(); rect.Unite(PhysicalRect(rect.offset, ViewRect().size)); return rect; @@ -376,6 +388,7 @@ void LayoutView::MapLocalToAncestor(const LayoutBoxModelObject* ancestor, TransformState& transform_state, MapCoordinatesFlags mode) const { + CheckIsNotDestroyed(); if (!ancestor && !(mode & kIgnoreTransforms) && ShouldUseTransformFromContainer(nullptr)) { TransformationMatrix t; @@ -410,6 +423,7 @@ const LayoutObject* LayoutView::PushMappingToContainer( const LayoutBoxModelObject* ancestor_to_stop_at, LayoutGeometryMap& geometry_map) const { + CheckIsNotDestroyed(); PhysicalOffset offset; LayoutObject* container = nullptr; @@ -440,6 +454,7 @@ void LayoutView::MapAncestorToLocal(const LayoutBoxModelObject* ancestor, TransformState& transform_state, MapCoordinatesFlags mode) const { + CheckIsNotDestroyed(); if (this != ancestor && (mode & kTraverseDocumentBoundaries)) { if (auto* parent_doc_layout_object = GetFrame()->OwnerLayoutObject()) { // A LayoutView is a containing block for fixed-position elements, so @@ -465,11 +480,13 @@ } void LayoutView::Paint(const PaintInfo& paint_info) const { + CheckIsNotDestroyed(); ViewPainter(*this).Paint(paint_info); } void LayoutView::PaintBoxDecorationBackground(const PaintInfo& paint_info, const PhysicalOffset&) const { + CheckIsNotDestroyed(); ViewPainter(*this).PaintBoxDecorationBackground(paint_info); } @@ -483,6 +500,7 @@ } void LayoutView::SetShouldDoFullPaintInvalidationForViewAndAllDescendants() { + CheckIsNotDestroyed(); if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) SetSubtreeShouldDoFullPaintInvalidation(); else @@ -490,6 +508,7 @@ } void LayoutView::InvalidatePaintForViewAndCompositedLayers() { + CheckIsNotDestroyed(); SetSubtreeShouldDoFullPaintInvalidation(); if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) { @@ -504,6 +523,7 @@ PhysicalRect& rect, MapCoordinatesFlags mode, VisualRectFlags visual_rect_flags) const { + CheckIsNotDestroyed(); bool intersects = true; if (MapToVisualRectInAncestorSpaceInternalFastPath( ancestor, rect, visual_rect_flags, intersects)) @@ -523,6 +543,7 @@ const LayoutBoxModelObject* ancestor, TransformState& transform_state, VisualRectFlags visual_rect_flags) const { + CheckIsNotDestroyed(); return MapToVisualRectInAncestorSpaceInternal(ancestor, transform_state, 0, visual_rect_flags); } @@ -532,6 +553,7 @@ TransformState& transform_state, MapCoordinatesFlags mode, VisualRectFlags visual_rect_flags) const { + CheckIsNotDestroyed(); if (mode & kIsFixed) transform_state.Move(OffsetForFixedPosition()); @@ -589,34 +611,40 @@ } PhysicalOffset LayoutView::OffsetForFixedPosition() const { + CheckIsNotDestroyed(); return IsScrollContainer() ? PhysicalOffset(ScrolledContentOffset()) : PhysicalOffset(); } PhysicalOffset LayoutView::PixelSnappedOffsetForFixedPosition() const { + CheckIsNotDestroyed(); return PhysicalOffset(FlooredIntPoint(OffsetForFixedPosition())); } void LayoutView::AbsoluteQuads(Vector<FloatQuad>& quads, MapCoordinatesFlags mode) const { + CheckIsNotDestroyed(); quads.push_back(LocalRectToAbsoluteQuad( PhysicalRect(PhysicalOffset(), PhysicalSizeToBeNoop(Layer()->Size())), mode)); } void LayoutView::CommitPendingSelection() { + CheckIsNotDestroyed(); TRACE_EVENT0("blink", "LayoutView::commitPendingSelection"); DCHECK(!NeedsLayout()); frame_view_->GetFrame().Selection().CommitAppearanceIfNeeded(); } bool LayoutView::ShouldUsePrintingLayout() const { + CheckIsNotDestroyed(); if (!GetDocument().Printing() || !frame_view_) return false; return frame_view_->GetFrame().ShouldUsePrintingLayout(); } PhysicalRect LayoutView::ViewRect() const { + CheckIsNotDestroyed(); if (ShouldUsePrintingLayout()) return PhysicalRect(PhysicalOffset(), Size()); if (frame_view_) @@ -627,6 +655,7 @@ PhysicalRect LayoutView::OverflowClipRect( const PhysicalOffset& location, OverlayScrollbarClipBehavior overlay_scrollbar_clip_behavior) const { + CheckIsNotDestroyed(); PhysicalRect rect = ViewRect(); if (rect.IsEmpty()) { return LayoutBox::OverflowClipRect(location, @@ -642,6 +671,7 @@ void LayoutView::SetAutosizeScrollbarModes(mojom::blink::ScrollbarMode h_mode, mojom::blink::ScrollbarMode v_mode) { + CheckIsNotDestroyed(); DCHECK_EQ(v_mode == mojom::blink::ScrollbarMode::kAuto, h_mode == mojom::blink::ScrollbarMode::kAuto); autosize_v_scrollbar_mode_ = v_mode; @@ -651,6 +681,7 @@ void LayoutView::CalculateScrollbarModes( mojom::blink::ScrollbarMode& h_mode, mojom::blink::ScrollbarMode& v_mode) const { + CheckIsNotDestroyed(); #define RETURN_SCROLLBAR_MODE(mode) \ { \ h_mode = v_mode = mode; \ @@ -748,11 +779,13 @@ } PhysicalRect LayoutView::DocumentRect() const { + CheckIsNotDestroyed(); return FlipForWritingMode(LayoutOverflowRect()); } IntSize LayoutView::GetLayoutSize( IncludeScrollbarsInRect scrollbar_inclusion) const { + CheckIsNotDestroyed(); if (ShouldUsePrintingLayout()) return IntSize(Size().Width().ToInt(), PageLogicalHeight().ToInt()); @@ -767,27 +800,32 @@ int LayoutView::ViewLogicalWidth( IncludeScrollbarsInRect scrollbar_inclusion) const { + CheckIsNotDestroyed(); return StyleRef().IsHorizontalWritingMode() ? ViewWidth(scrollbar_inclusion) : ViewHeight(scrollbar_inclusion); } int LayoutView::ViewLogicalHeight( IncludeScrollbarsInRect scrollbar_inclusion) const { + CheckIsNotDestroyed(); return StyleRef().IsHorizontalWritingMode() ? ViewHeight(scrollbar_inclusion) : ViewWidth(scrollbar_inclusion); } LayoutUnit LayoutView::ViewLogicalHeightForPercentages() const { + CheckIsNotDestroyed(); if (ShouldUsePrintingLayout()) return PageLogicalHeight(); return LayoutUnit(ViewLogicalHeight()); } float LayoutView::ZoomFactor() const { + CheckIsNotDestroyed(); return frame_view_->GetFrame().PageZoomFactor(); } const LayoutBox& LayoutView::RootBox() const { + CheckIsNotDestroyed(); Element* document_element = GetDocument().documentElement(); DCHECK(document_element); DCHECK(document_element->GetLayoutObject()); @@ -796,6 +834,7 @@ } void LayoutView::UpdateAfterLayout() { + CheckIsNotDestroyed(); // Unlike every other layer, the root PaintLayer takes its size from the // layout viewport size. The call to AdjustViewSize() will update the // frame's contents size, which will also update the page's minimum scale @@ -814,6 +853,7 @@ void LayoutView::UpdateHitTestResult(HitTestResult& result, const PhysicalOffset& point) const { + CheckIsNotDestroyed(); if (result.InnerNode()) return; @@ -828,36 +868,43 @@ } bool LayoutView::UsesCompositing() const { + CheckIsNotDestroyed(); return compositor_ && compositor_->StaleInCompositingMode(); } PaintLayerCompositor* LayoutView::Compositor() { + CheckIsNotDestroyed(); return compositor_.get(); } void LayoutView::CleanUpCompositor() { + CheckIsNotDestroyed(); DCHECK(compositor_); compositor_->CleanUp(); } IntervalArena* LayoutView::GetIntervalArena() { + CheckIsNotDestroyed(); if (!interval_arena_) interval_arena_ = IntervalArena::Create(); return interval_arena_.get(); } bool LayoutView::BackgroundIsKnownToBeOpaqueInRect(const PhysicalRect&) const { + CheckIsNotDestroyed(); // The base background color applies to the main frame only. return GetFrame()->IsMainFrame() && !frame_view_->BaseBackgroundColor().HasAlpha(); } FloatSize LayoutView::ViewportSizeForViewportUnits() const { + CheckIsNotDestroyed(); return GetFrameView() ? GetFrameView()->ViewportSizeForViewportUnits() : FloatSize(); } void LayoutView::WillBeDestroyed() { + CheckIsNotDestroyed(); // TODO(wangxianzhu): This is a workaround of crbug.com/570706. // Should find and fix the root cause. if (PaintLayer* layer = Layer()) @@ -867,6 +914,7 @@ } void LayoutView::UpdateFromStyle() { + CheckIsNotDestroyed(); LayoutBlockFlow::UpdateFromStyle(); // LayoutView of the main frame is responsible for painting base background. @@ -875,6 +923,7 @@ } bool LayoutView::RecalcLayoutOverflow() { + CheckIsNotDestroyed(); if (!NeedsLayoutOverflowRecalc()) return false; bool result = LayoutBlockFlow::RecalcLayoutOverflow(); @@ -897,11 +946,13 @@ } PhysicalRect LayoutView::DebugRect() const { + CheckIsNotDestroyed(); return PhysicalRect(IntRect(0, 0, ViewWidth(kIncludeScrollbars), ViewHeight(kIncludeScrollbars))); } bool LayoutView::UpdateLogicalWidthAndColumnWidth() { + CheckIsNotDestroyed(); bool relayout_children = LayoutBlockFlow::UpdateLogicalWidthAndColumnWidth(); // When we're printing, the size of LayoutView is changed outside of layout, // so we'll fail to detect any changes here. Just return true. @@ -909,6 +960,7 @@ } CompositingReasons LayoutView::AdditionalCompositingReasons() const { + CheckIsNotDestroyed(); // TODO(lfg): Audit for portals const LocalFrame& frame = frame_view_->GetFrame(); if (frame.OwnerLayoutObject() && @@ -921,6 +973,7 @@ } void LayoutView::UpdateCounters() { + CheckIsNotDestroyed(); if (!needs_counter_update_) return; @@ -938,11 +991,13 @@ } bool LayoutView::HasTickmarks() const { + CheckIsNotDestroyed(); return !tickmarks_override_.IsEmpty() || GetDocument().Markers().PossiblyHasTextMatchMarkers(); } Vector<IntRect> LayoutView::GetTickmarks() const { + CheckIsNotDestroyed(); if (!tickmarks_override_.IsEmpty()) return tickmarks_override_; @@ -950,11 +1005,13 @@ } void LayoutView::OverrideTickmarks(const Vector<IntRect>& tickmarks) { + CheckIsNotDestroyed(); tickmarks_override_ = tickmarks; InvalidatePaintForTickmarks(); } void LayoutView::InvalidatePaintForTickmarks() { + CheckIsNotDestroyed(); ScrollableArea* scrollable_area = GetScrollableArea(); if (!scrollable_area) return;
diff --git a/third_party/blink/renderer/core/layout/layout_view.h b/third_party/blink/renderer/core/layout/layout_view.h index d44e74b..2e2409e 100644 --- a/third_party/blink/renderer/core/layout/layout_view.h +++ b/third_party/blink/renderer/core/layout/layout_view.h
@@ -76,18 +76,29 @@ HitTestResult&); // Returns the total count of calls to HitTest, for testing. - unsigned HitTestCount() const { return hit_test_count_; } - unsigned HitTestCacheHits() const { return hit_test_cache_hits_; } + unsigned HitTestCount() const { + CheckIsNotDestroyed(); + return hit_test_count_; + } + unsigned HitTestCacheHits() const { + CheckIsNotDestroyed(); + return hit_test_cache_hits_; + } void ClearHitTestCache(); - const char* GetName() const override { return "LayoutView"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutView"; + } bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectLayoutView || LayoutBlockFlow::IsOfType(type); } PaintLayerType LayerTypeRequired() const override { + CheckIsNotDestroyed(); return kNormalPaintLayer; } @@ -107,10 +118,12 @@ int ViewHeight( IncludeScrollbarsInRect scrollbar_inclusion = kExcludeScrollbars) const { + CheckIsNotDestroyed(); return GetLayoutSize(scrollbar_inclusion).Height(); } int ViewWidth( IncludeScrollbarsInRect scrollbar_inclusion = kExcludeScrollbars) const { + CheckIsNotDestroyed(); return GetLayoutSize(scrollbar_inclusion).Width(); } @@ -121,7 +134,10 @@ float ZoomFactor() const; - LocalFrameView* GetFrameView() const { return frame_view_; } + LocalFrameView* GetFrameView() const { + CheckIsNotDestroyed(); + return frame_view_; + } const LayoutBox& RootBox() const; void UpdateAfterLayout() override; @@ -169,33 +185,47 @@ void SetAutosizeScrollbarModes(mojom::blink::ScrollbarMode h_mode, mojom::blink::ScrollbarMode v_mode); mojom::blink::ScrollbarMode AutosizeHorizontalScrollbarMode() const { + CheckIsNotDestroyed(); return autosize_h_scrollbar_mode_; } mojom::blink::ScrollbarMode AutosizeVerticalScrollbarMode() const { + CheckIsNotDestroyed(); return autosize_v_scrollbar_mode_; } void CalculateScrollbarModes(mojom::blink::ScrollbarMode& h_mode, mojom::blink::ScrollbarMode& v_mode) const; - LayoutState* GetLayoutState() const { return layout_state_; } + LayoutState* GetLayoutState() const { + CheckIsNotDestroyed(); + return layout_state_; + } - bool CanHaveAdditionalCompositingReasons() const override { return true; } + bool CanHaveAdditionalCompositingReasons() const override { + CheckIsNotDestroyed(); + return true; + } CompositingReasons AdditionalCompositingReasons() const override; void UpdateHitTestResult(HitTestResult&, const PhysicalOffset&) const override; ViewFragmentationContext* FragmentationContext() const { + CheckIsNotDestroyed(); return fragmentation_context_.get(); } - LayoutUnit PageLogicalHeight() const { return page_logical_height_; } + LayoutUnit PageLogicalHeight() const { + CheckIsNotDestroyed(); + return page_logical_height_; + } void SetPageLogicalHeight(LayoutUnit height) { + CheckIsNotDestroyed(); page_logical_height_ = height; } NamedPagesMapper* GetNamedPagesMapper() const { + CheckIsNotDestroyed(); return named_pages_mapper_.get(); } @@ -206,23 +236,37 @@ IntervalArena* GetIntervalArena(); - void SetLayoutQuoteHead(LayoutQuote* head) { layout_quote_head_ = head; } - LayoutQuote* LayoutQuoteHead() const { return layout_quote_head_; } + void SetLayoutQuoteHead(LayoutQuote* head) { + CheckIsNotDestroyed(); + layout_quote_head_ = head; + } + LayoutQuote* LayoutQuoteHead() const { + CheckIsNotDestroyed(); + return layout_quote_head_; + } // FIXME: This is a work around because the current implementation of counters // requires walking the entire tree repeatedly and most pages don't actually // use either feature so we shouldn't take the performance hit when not // needed. Long term we should rewrite the counter and quotes code. void AddLayoutCounter() { + CheckIsNotDestroyed(); layout_counter_count_++; SetNeedsCounterUpdate(); } void RemoveLayoutCounter() { + CheckIsNotDestroyed(); DCHECK_GT(layout_counter_count_, 0u); layout_counter_count_--; } - bool HasLayoutCounters() { return layout_counter_count_; } - void SetNeedsCounterUpdate() { needs_counter_update_ = true; } + bool HasLayoutCounters() { + CheckIsNotDestroyed(); + return layout_counter_count_; + } + void SetNeedsCounterUpdate() { + CheckIsNotDestroyed(); + needs_counter_update_ = true; + } void UpdateCounters(); bool BackgroundIsKnownToBeOpaqueInRect( @@ -233,9 +277,11 @@ FloatSize ViewportSizeForViewportUnits() const; void PushLayoutState(LayoutState& layout_state) { + CheckIsNotDestroyed(); layout_state_ = &layout_state; } void PopLayoutState() { + CheckIsNotDestroyed(); DCHECK(layout_state_); layout_state_ = layout_state_->Next(); } @@ -270,16 +316,19 @@ // will be painted in this rect. It's also the positioning area of fixed- // attachment backgrounds. PhysicalRect BackgroundRect() const { + CheckIsNotDestroyed(); return OverflowClipRect(PhysicalOffset()); } // The previous BackgroundRect after the previous paint invalidation. PhysicalRect PreviousBackgroundRect() const { + CheckIsNotDestroyed(); DCHECK_EQ(GetDocument().Lifecycle().GetState(), DocumentLifecycle::kInPrePaint); return previous_background_rect_; } void SetPreviousBackgroundRect(const PhysicalRect& r) const { + CheckIsNotDestroyed(); DCHECK_EQ(GetDocument().Lifecycle().GetState(), DocumentLifecycle::kInPrePaint); previous_background_rect_ = r; @@ -310,9 +359,11 @@ void UpdateFromStyle() override; int ViewLogicalWidthForBoxSizing() const { + CheckIsNotDestroyed(); return ViewLogicalWidth(kIncludeScrollbars); } int ViewLogicalHeightForBoxSizing() const { + CheckIsNotDestroyed(); return ViewLogicalHeight(kIncludeScrollbars); }
diff --git a/third_party/blink/renderer/core/layout/layout_vtt_cue.cc b/third_party/blink/renderer/core/layout/layout_vtt_cue.cc index f882270..443e8a2 100644 --- a/third_party/blink/renderer/core/layout/layout_vtt_cue.cc +++ b/third_party/blink/renderer/core/layout/layout_vtt_cue.cc
@@ -280,6 +280,7 @@ : LayoutBlockFlow(node), snap_to_lines_position_(snap_to_lines_position) {} void LayoutVTTCue::RepositionCueSnapToLinesNotSet() { + CheckIsNotDestroyed(); // FIXME: Implement overlapping detection when snap-to-lines is not set. // http://wkb.ug/84296 @@ -324,6 +325,7 @@ } IntRect LayoutVTTCue::ComputeControlsRect() const { + CheckIsNotDestroyed(); // Determine the area covered by the media controls, if any. For this, the // LayoutVTTCue will walk the tree up to the HTMLMediaElement, then ask for // the MediaControls. @@ -359,6 +361,7 @@ } void LayoutVTTCue::UpdateLayout() { + CheckIsNotDestroyed(); LayoutBlockFlow::UpdateLayout(); DCHECK(FirstChild());
diff --git a/third_party/blink/renderer/core/layout/layout_vtt_cue.h b/third_party/blink/renderer/core/layout/layout_vtt_cue.h index c05ca7d0..de88be3 100644 --- a/third_party/blink/renderer/core/layout/layout_vtt_cue.h +++ b/third_party/blink/renderer/core/layout/layout_vtt_cue.h
@@ -38,7 +38,10 @@ // The computed line position for snap-to-lines layout, and NaN for // non-snap-to-lines layout where no adjustment should take place. - float SnapToLinesPosition() { return snap_to_lines_position_; } + float SnapToLinesPosition() { + CheckIsNotDestroyed(); + return snap_to_lines_position_; + } private: void UpdateLayout() override;
diff --git a/third_party/blink/renderer/core/layout/layout_word_break.cc b/third_party/blink/renderer/core/layout/layout_word_break.cc index 71af9f4..1e0b24a8 100644 --- a/third_party/blink/renderer/core/layout/layout_word_break.cc +++ b/third_party/blink/renderer/core/layout/layout_word_break.cc
@@ -35,10 +35,12 @@ : LayoutText(element, StringImpl::empty_) {} bool LayoutWordBreak::IsWordBreak() const { + CheckIsNotDestroyed(); return true; } Position LayoutWordBreak::PositionForCaretOffset(unsigned offset) const { + CheckIsNotDestroyed(); if (!GetNode()) return Position(); // The only allowed caret offset is 0, since LayoutWordBreak always has @@ -49,6 +51,7 @@ base::Optional<unsigned> LayoutWordBreak::CaretOffsetForPosition( const Position& position) const { + CheckIsNotDestroyed(); if (position.IsNull() || position.AnchorNode() != GetNode()) return base::nullopt; DCHECK(position.IsBeforeAnchor() || position.IsAfterAnchor());
diff --git a/third_party/blink/renderer/core/layout/layout_word_break.h b/third_party/blink/renderer/core/layout/layout_word_break.h index 35d79ff7..2c1502e 100644 --- a/third_party/blink/renderer/core/layout/layout_word_break.h +++ b/third_party/blink/renderer/core/layout/layout_word_break.h
@@ -40,7 +40,10 @@ Position PositionForCaretOffset(unsigned offset) const final; base::Optional<unsigned> CaretOffsetForPosition(const Position&) const final; - const char* GetName() const override { return "LayoutWordBreak"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutWordBreak"; + } bool IsWordBreak() const override; };
diff --git a/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text.h b/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text.h index a03bdd4..9fb42b0 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text.h +++ b/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text.h
@@ -15,18 +15,28 @@ class CORE_EXPORT LayoutNGText : public LayoutText { public: LayoutNGText(Node* node, scoped_refptr<StringImpl> text) - : LayoutText(node, text) {} + : LayoutText(node, text) { + CheckIsNotDestroyed(); + } bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectNGText || LayoutText::IsOfType(type); } - bool IsLayoutNGObject() const override { return true; } + bool IsLayoutNGObject() const override { + CheckIsNotDestroyed(); + return true; + } private: const base::span<NGInlineItem>* GetNGInlineItems() const final { + CheckIsNotDestroyed(); return &inline_items_; } - base::span<NGInlineItem>* GetNGInlineItems() final { return &inline_items_; } + base::span<NGInlineItem>* GetNGInlineItems() final { + CheckIsNotDestroyed(); + return &inline_items_; + } base::span<NGInlineItem> inline_items_; };
diff --git a/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_fragment.h b/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_fragment.h index 0612bfa..bc4f172 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_fragment.h +++ b/third_party/blink/renderer/core/layout/ng/inline/layout_ng_text_fragment.h
@@ -18,17 +18,27 @@ StringImpl* text, int start_offset, int length) - : LayoutTextFragment(node, text, start_offset, length) {} + : LayoutTextFragment(node, text, start_offset, length) { + CheckIsNotDestroyed(); + } - bool IsLayoutNGObject() const final { return true; } + bool IsLayoutNGObject() const final { + CheckIsNotDestroyed(); + return true; + } private: const base::span<NGInlineItem>* GetNGInlineItems() const final { + CheckIsNotDestroyed(); return &inline_items_; } - base::span<NGInlineItem>* GetNGInlineItems() final { return &inline_items_; } + base::span<NGInlineItem>* GetNGInlineItems() final { + CheckIsNotDestroyed(); + return &inline_items_; + } void InsertedIntoTree() final { + CheckIsNotDestroyed(); valid_ng_items_ = false; LayoutText::InsertedIntoTree(); }
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc index 14d06df..947f093 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc
@@ -141,7 +141,7 @@ return end_offsets; } - void TestAnyItrermsAreDirty(LayoutBlockFlow* block_flow, bool expected) { + void TestAnyItemsAreDirty(LayoutBlockFlow* block_flow, bool expected) { const NGFragmentItems* items = block_flow->FragmentItems(); items->DirtyLinesFromNeedsLayout(block_flow); // Check |NGFragmentItem::IsDirty| directly without using @@ -599,11 +599,14 @@ unsigned needs_collect_inlines; base::Optional<bool> is_line_dirty; } style_change_data[] = { - // Changing color, etc. should not re-run + // Changing color, text-decoration, outline, etc. should not re-run // |CollectInlines()|. {"#parent.after { color: red; }", StyleChangeData::kNone, false}, - {"#parent.after { text-decoration-color: red; }", StyleChangeData::kNone, - false}, + // TODO(crbug.com/1128199): text-decorations, outline, etc. should not + // require layout, only ink overflow, but they currently do. + {"#parent.after { text-decoration-line: underline; }", + StyleChangeData::kNone, true}, + {"#parent.after { outline: auto; }", StyleChangeData::kNone, true}, // Changing fonts should re-run |CollectInlines()|. {"#parent.after { font-size: 200%; }", StyleChangeData::kAll, true}, // Changing from/to out-of-flow should re-rerun |CollectInlines()|. @@ -682,8 +685,8 @@ if (data.is_line_dirty && RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) { - TestAnyItrermsAreDirty(To<LayoutBlockFlow>(container->GetLayoutObject()), - *data.is_line_dirty); + TestAnyItemsAreDirty(To<LayoutBlockFlow>(container->GetLayoutObject()), + *data.is_line_dirty); } ForceLayout(); // Ensure running layout does not crash.
diff --git a/third_party/blink/renderer/core/layout/ng/list/layout_ng_inside_list_marker.cc b/third_party/blink/renderer/core/layout/ng/list/layout_ng_inside_list_marker.cc index 626ba03e2..9098a82 100644 --- a/third_party/blink/renderer/core/layout/ng/list/layout_ng_inside_list_marker.cc +++ b/third_party/blink/renderer/core/layout/ng/list/layout_ng_inside_list_marker.cc
@@ -12,12 +12,14 @@ : LayoutInline(element) {} bool LayoutNGInsideListMarker::IsOfType(LayoutObjectType type) const { + CheckIsNotDestroyed(); return type == kLayoutObjectNGInsideListMarker || LayoutInline::IsOfType(type); } PositionWithAffinity LayoutNGInsideListMarker::PositionForPoint( const PhysicalOffset&) const { + CheckIsNotDestroyed(); return CreatePositionWithAffinity(0); }
diff --git a/third_party/blink/renderer/core/layout/ng/list/layout_ng_inside_list_marker.h b/third_party/blink/renderer/core/layout/ng/list/layout_ng_inside_list_marker.h index 8d1e302..fe5642c 100644 --- a/third_party/blink/renderer/core/layout/ng/list/layout_ng_inside_list_marker.h +++ b/third_party/blink/renderer/core/layout/ng/list/layout_ng_inside_list_marker.h
@@ -16,13 +16,23 @@ public: explicit LayoutNGInsideListMarker(Element*); - const char* GetName() const override { return "LayoutNGInsideListMarker"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutNGInsideListMarker"; + } - const ListMarker& Marker() const { return list_marker_; } - ListMarker& Marker() { return list_marker_; } + const ListMarker& Marker() const { + CheckIsNotDestroyed(); + return list_marker_; + } + ListMarker& Marker() { + CheckIsNotDestroyed(); + return list_marker_; + } #if DCHECK_IS_ON() void AddChild(LayoutObject* new_child, LayoutObject* before_child) override { + CheckIsNotDestroyed(); // List markers with 'content: normal' should have at most one child. DCHECK(!StyleRef().ContentBehavesAsNormal() || !FirstChild()); LayoutInline::AddChild(new_child, before_child);
diff --git a/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_column.cc b/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_column.cc index f1c8235..0468c45 100644 --- a/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_column.cc +++ b/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_column.cc
@@ -17,6 +17,7 @@ void LayoutNGTableColumn::StyleDidChange(StyleDifference diff, const ComputedStyle* old_style) { + CheckIsNotDestroyed(); if (diff.NeedsPaintInvalidation() && old_style) { if (LayoutNGTable* table = Table()) { if (NGTableBorders::HasBorder(old_style) || @@ -28,6 +29,7 @@ } void LayoutNGTableColumn::ImageChanged(WrappedImagePtr, CanDeferInvalidation) { + CheckIsNotDestroyed(); if (LayoutNGTable* table = Table()) { table->SetShouldDoFullPaintInvalidationWithoutGeometryChange( PaintInvalidationReason::kImage); @@ -36,15 +38,18 @@ bool LayoutNGTableColumn::IsChildAllowed(LayoutObject* child, const ComputedStyle& style) const { + CheckIsNotDestroyed(); return child->IsLayoutTableCol() && style.Display() == EDisplay::kTableColumn; } bool LayoutNGTableColumn::CanHaveChildren() const { + CheckIsNotDestroyed(); // <col> cannot have children. return IsColumnGroup(); } void LayoutNGTableColumn::ClearNeedsLayoutForChildren() const { + CheckIsNotDestroyed(); LayoutObject* child = children_.FirstChild(); while (child) { child->ClearNeedsLayout(); @@ -53,6 +58,7 @@ } LayoutNGTable* LayoutNGTableColumn::Table() const { + CheckIsNotDestroyed(); LayoutObject* table = Parent(); if (table && !table->IsTable()) table = table->Parent(); @@ -64,6 +70,7 @@ } void LayoutNGTableColumn::UpdateFromElement() { + CheckIsNotDestroyed(); unsigned old_span = span_; if (const auto* tc = DynamicTo<HTMLTableColElement>(GetNode())) { span_ = tc->span();
diff --git a/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_column.h b/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_column.h index 0db6305e..81c5bf1 100644 --- a/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_column.h +++ b/third_party/blink/renderer/core/layout/ng/table/layout_ng_table_column.h
@@ -20,14 +20,19 @@ LayoutNGTable* Table() const; bool IsColumn() const { + CheckIsNotDestroyed(); return StyleRef().Display() == EDisplay::kTableColumn; } bool IsColumnGroup() const { + CheckIsNotDestroyed(); return StyleRef().Display() == EDisplay::kTableColumnGroup; } - unsigned Span() const { return span_; } + unsigned Span() const { + CheckIsNotDestroyed(); + return span_; + } // Clears needs-layout for child columns too. void ClearNeedsLayoutForChildren() const; @@ -35,13 +40,17 @@ // LayoutObject methods start. const char* GetName() const override { + CheckIsNotDestroyed(); if (IsColumn()) return "LayoutNGTableCol"; else return "LayoutNGTableColGroup"; } - bool IsLayoutNGObject() const final { return true; } + bool IsLayoutNGObject() const final { + CheckIsNotDestroyed(); + return true; + } void StyleDidChange(StyleDifference diff, const ComputedStyle* old_style) final; @@ -51,11 +60,13 @@ protected: // Required by LayoutBox, but not used. MinMaxSizes ComputeIntrinsicLogicalWidths() const override { + CheckIsNotDestroyed(); NOTIMPLEMENTED(); return MinMaxSizes(); } bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectLayoutTableCol || LayoutBox::IsOfType(type); } @@ -66,11 +77,18 @@ void UpdateFromElement() override; - PaintLayerType LayerTypeRequired() const override { return kNoPaintLayer; } + PaintLayerType LayerTypeRequired() const override { + CheckIsNotDestroyed(); + return kNoPaintLayer; + } - LayoutObjectChildList* VirtualChildren() override { return &children_; } + LayoutObjectChildList* VirtualChildren() override { + CheckIsNotDestroyed(); + return &children_; + } const LayoutObjectChildList* VirtualChildren() const override { + CheckIsNotDestroyed(); return &children_; }
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_block.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_block.cc index 87407ce..823db0b 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_block.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_block.cc
@@ -41,16 +41,19 @@ transform_uses_reference_box_(false) {} SVGElement* LayoutSVGBlock::GetElement() const { + CheckIsNotDestroyed(); return To<SVGElement>(LayoutObject::GetNode()); } void LayoutSVGBlock::WillBeDestroyed() { + CheckIsNotDestroyed(); SVGResourcesCache::ClientDestroyed(*this); SVGResources::ClearClipPathFilterMask(*GetElement(), Style()); LayoutBlockFlow::WillBeDestroyed(); } void LayoutSVGBlock::InsertedIntoTree() { + CheckIsNotDestroyed(); LayoutBlockFlow::InsertedIntoTree(); if (CompositingReasonFinder::DirectReasonsForSVGChildPaintProperties(*this) != CompositingReason::kNone) { @@ -59,6 +62,7 @@ } void LayoutSVGBlock::WillBeRemovedFromTree() { + CheckIsNotDestroyed(); LayoutBlockFlow::WillBeRemovedFromTree(); if (CompositingReasonFinder::DirectReasonsForSVGChildPaintProperties(*this) != CompositingReason::kNone) { @@ -67,11 +71,13 @@ } void LayoutSVGBlock::UpdateFromStyle() { + CheckIsNotDestroyed(); LayoutBlockFlow::UpdateFromStyle(); SetFloating(false); } bool LayoutSVGBlock::CheckForImplicitTransformChange(bool bbox_changed) const { + CheckIsNotDestroyed(); // If the transform is relative to the reference box, check relevant // conditions to see if we need to recompute the transform. switch (StyleRef().TransformBox()) { @@ -85,6 +91,7 @@ } bool LayoutSVGBlock::UpdateTransformAfterLayout(bool bounds_changed) { + CheckIsNotDestroyed(); // If our transform depends on the reference box, we need to check if it needs // to be updated. if (!needs_transform_update_ && transform_uses_reference_box_) { @@ -102,6 +109,7 @@ void LayoutSVGBlock::StyleDidChange(StyleDifference diff, const ComputedStyle* old_style) { + CheckIsNotDestroyed(); transform_uses_reference_box_ = TransformHelper::DependsOnReferenceBox(StyleRef()); @@ -137,6 +145,7 @@ void LayoutSVGBlock::MapLocalToAncestor(const LayoutBoxModelObject* ancestor, TransformState& transform_state, MapCoordinatesFlags flags) const { + CheckIsNotDestroyed(); // Convert from local HTML coordinates to local SVG coordinates. transform_state.Move(PhysicalLocation()); // Apply other mappings on local SVG coordinates. @@ -146,6 +155,7 @@ void LayoutSVGBlock::MapAncestorToLocal(const LayoutBoxModelObject* ancestor, TransformState& transform_state, MapCoordinatesFlags flags) const { + CheckIsNotDestroyed(); if (this == ancestor) return; @@ -158,6 +168,7 @@ const LayoutObject* LayoutSVGBlock::PushMappingToContainer( const LayoutBoxModelObject* ancestor_to_stop_at, LayoutGeometryMap& geometry_map) const { + CheckIsNotDestroyed(); // Convert from local HTML coordinates to local SVG coordinates. geometry_map.Push(this, PhysicalLocation()); // Apply other mappings on local SVG coordinates. @@ -166,6 +177,7 @@ } PhysicalRect LayoutSVGBlock::VisualRectInDocument(VisualRectFlags flags) const { + CheckIsNotDestroyed(); return SVGLayoutSupport::VisualRectInAncestorSpace(*this, *View(), flags); } @@ -173,6 +185,7 @@ const LayoutBoxModelObject* ancestor, TransformState& transform_state, VisualRectFlags) const { + CheckIsNotDestroyed(); transform_state.Flatten(); PhysicalRect rect(LayoutRect(transform_state.LastPlanarQuad().BoundingBox())); // Convert from local HTML coordinates to local SVG coordinates. @@ -188,6 +201,7 @@ const HitTestLocation&, const PhysicalOffset&, HitTestAction) { + CheckIsNotDestroyed(); NOTREACHED(); return false; }
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_block.h b/third_party/blink/renderer/core/layout/svg/layout_svg_block.h index 7e3e67c..61ac83c3 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_block.h +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_block.h
@@ -49,10 +49,19 @@ const LayoutBoxModelObject* ancestor_to_stop_at, LayoutGeometryMap&) const final; - AffineTransform LocalSVGTransform() const final { return local_transform_; } - void SetNeedsTransformUpdate() override { needs_transform_update_ = true; } + AffineTransform LocalSVGTransform() const final { + CheckIsNotDestroyed(); + return local_transform_; + } + void SetNeedsTransformUpdate() override { + CheckIsNotDestroyed(); + needs_transform_update_ = true; + } - PaintLayerType LayerTypeRequired() const override { return kNoPaintLayer; } + PaintLayerType LayerTypeRequired() const override { + CheckIsNotDestroyed(); + return kNoPaintLayer; + } SVGElement* GetElement() const; @@ -71,6 +80,7 @@ bool transform_uses_reference_box_ : 1; bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectSVG || LayoutBlockFlow::IsOfType(type); }
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_container.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_container.cc index 1445d274..b49f276 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_container.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_container.cc
@@ -45,6 +45,7 @@ LayoutSVGContainer::~LayoutSVGContainer() = default; void LayoutSVGContainer::UpdateLayout() { + CheckIsNotDestroyed(); DCHECK(NeedsLayout()); LayoutAnalyzer::Scope analyzer(*this); @@ -88,6 +89,7 @@ void LayoutSVGContainer::AddChild(LayoutObject* child, LayoutObject* before_child) { + CheckIsNotDestroyed(); LayoutSVGModelObject::AddChild(child, before_child); SVGResourcesCache::ClientWasAddedToTree(*child); @@ -99,6 +101,7 @@ } void LayoutSVGContainer::RemoveChild(LayoutObject* child) { + CheckIsNotDestroyed(); SVGResourcesCache::ClientWillBeRemovedFromTree(*child); LayoutSVGModelObject::RemoveChild(child); @@ -110,11 +113,13 @@ } bool LayoutSVGContainer::SelfWillPaint() const { + CheckIsNotDestroyed(); return SVGLayoutSupport::HasFilterResource(*this); } void LayoutSVGContainer::StyleDidChange(StyleDifference diff, const ComputedStyle* old_style) { + CheckIsNotDestroyed(); LayoutSVGModelObject::StyleDidChange(diff, old_style); bool had_isolation = @@ -140,6 +145,7 @@ } bool LayoutSVGContainer::HasNonIsolatedBlendingDescendants() const { + CheckIsNotDestroyed(); if (has_non_isolated_blending_descendants_dirty_) { has_non_isolated_blending_descendants_ = SVGLayoutSupport::ComputeHasNonIsolatedBlendingDescendants(this); @@ -150,6 +156,7 @@ void LayoutSVGContainer::DescendantIsolationRequirementsChanged( DescendantIsolationState state) { + CheckIsNotDestroyed(); switch (state) { case kDescendantIsolationRequired: has_non_isolated_blending_descendants_ = true; @@ -170,10 +177,12 @@ } void LayoutSVGContainer::Paint(const PaintInfo& paint_info) const { + CheckIsNotDestroyed(); SVGContainerPainter(*this).Paint(paint_info); } void LayoutSVGContainer::UpdateCachedBoundaries() { + CheckIsNotDestroyed(); auto old_object_bounding_box = object_bounding_box_; SVGLayoutSupport::ComputeContainerBoundingBoxes( @@ -192,6 +201,7 @@ const HitTestLocation& hit_test_location, const PhysicalOffset& accumulated_offset, HitTestAction hit_test_action) { + CheckIsNotDestroyed(); DCHECK_EQ(accumulated_offset, PhysicalOffset()); TransformedHitTestLocation local_location(hit_test_location, LocalToSVGParentTransform()); @@ -228,6 +238,7 @@ SVGTransformChange LayoutSVGContainer::CalculateLocalTransform( bool bounds_changed) { + CheckIsNotDestroyed(); return SVGTransformChange::kNone; }
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_container.h b/third_party/blink/renderer/core/layout/svg/layout_svg_container.h index d68caa6..cc47b5d 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_container.h +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_container.h
@@ -41,37 +41,57 @@ void SlowLastChild() const = delete; LayoutObject* FirstChild() const { + CheckIsNotDestroyed(); DCHECK_EQ(Children(), VirtualChildren()); return Children()->FirstChild(); } LayoutObject* LastChild() const { + CheckIsNotDestroyed(); DCHECK_EQ(Children(), VirtualChildren()); return Children()->LastChild(); } void Paint(const PaintInfo&) const override; void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override; - void SetNeedsBoundariesUpdate() final { needs_boundaries_update_ = true; } + void SetNeedsBoundariesUpdate() final { + CheckIsNotDestroyed(); + needs_boundaries_update_ = true; + } bool DidScreenScaleFactorChange() const { + CheckIsNotDestroyed(); return did_screen_scale_factor_change_; } - bool IsObjectBoundingBoxValid() const { return object_bounding_box_valid_; } + bool IsObjectBoundingBoxValid() const { + CheckIsNotDestroyed(); + return object_bounding_box_valid_; + } bool SelfWillPaint() const; bool HasNonIsolatedBlendingDescendants() const final; - const char* GetName() const override { return "LayoutSVGContainer"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutSVGContainer"; + } - FloatRect ObjectBoundingBox() const final { return object_bounding_box_; } + FloatRect ObjectBoundingBox() const final { + CheckIsNotDestroyed(); + return object_bounding_box_; + } protected: - LayoutObjectChildList* VirtualChildren() final { return Children(); } + LayoutObjectChildList* VirtualChildren() final { + CheckIsNotDestroyed(); + return Children(); + } const LayoutObjectChildList* VirtualChildren() const final { + CheckIsNotDestroyed(); return Children(); } bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectSVGContainer || LayoutSVGModelObject::IsOfType(type); } @@ -81,7 +101,10 @@ LayoutObject* before_child = nullptr) final; void RemoveChild(LayoutObject*) final; - FloatRect StrokeBoundingBox() const final { return stroke_bounding_box_; } + FloatRect StrokeBoundingBox() const final { + CheckIsNotDestroyed(); + return stroke_bounding_box_; + } bool NodeAtPoint(HitTestResult&, const HitTestLocation&, @@ -96,8 +119,14 @@ void DescendantIsolationRequirementsChanged(DescendantIsolationState) final; private: - const LayoutObjectChildList* Children() const { return &children_; } - LayoutObjectChildList* Children() { return &children_; } + const LayoutObjectChildList* Children() const { + CheckIsNotDestroyed(); + return &children_; + } + LayoutObjectChildList* Children() { + CheckIsNotDestroyed(); + return &children_; + } LayoutObjectChildList children_; FloatRect object_bounding_box_;
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_ellipse.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_ellipse.cc index b19a0cf..d69a785 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_ellipse.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_ellipse.cc
@@ -39,6 +39,7 @@ LayoutSVGEllipse::~LayoutSVGEllipse() = default; void LayoutSVGEllipse::UpdateShapeFromElement() { + CheckIsNotDestroyed(); // Before creating a new object we need to clear the cached bounding box // to avoid using garbage. fill_bounding_box_ = FloatRect(); @@ -79,6 +80,7 @@ } void LayoutSVGEllipse::CalculateRadiiAndCenter() { + CheckIsNotDestroyed(); DCHECK(GetElement()); SVGLengthContext length_context(GetElement()); const ComputedStyle& style = StyleRef(); @@ -102,6 +104,7 @@ bool LayoutSVGEllipse::ShapeDependentStrokeContains( const HitTestLocation& location) { + CheckIsNotDestroyed(); if (radii_.Width() < 0 || radii_.Height() < 0) return false; @@ -121,6 +124,7 @@ bool LayoutSVGEllipse::ShapeDependentFillContains( const HitTestLocation& location, const WindRule fill_rule) const { + CheckIsNotDestroyed(); const FloatPoint& point = location.TransformedPoint(); const FloatPoint center = FloatPoint(center_.X() - point.X(), center_.Y() - point.Y()); @@ -133,6 +137,7 @@ } bool LayoutSVGEllipse::HasContinuousStroke() const { + CheckIsNotDestroyed(); const SVGComputedStyle& svg_style = StyleRef().SvgStyle(); return svg_style.StrokeDashArray()->data.IsEmpty(); }
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_ellipse.h b/third_party/blink/renderer/core/layout/svg/layout_svg_ellipse.h index 9672a40b..39a80bd 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_ellipse.h +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_ellipse.h
@@ -37,14 +37,19 @@ ~LayoutSVGEllipse() override; ShapeGeometryCodePath GeometryCodePath() const override { + CheckIsNotDestroyed(); return use_path_fallback_ ? kPathGeometry : kEllipseGeometryFastPath; } - const char* GetName() const override { return "LayoutSVGEllipse"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutSVGEllipse"; + } private: void UpdateShapeFromElement() override; bool IsShapeEmpty() const override { + CheckIsNotDestroyed(); return use_path_fallback_ ? LayoutSVGShape::IsShapeEmpty() : fill_bounding_box_.IsEmpty(); }
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_filter_primitive.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_filter_primitive.cc index 7ab5397..a03174f 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_filter_primitive.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_filter_primitive.cc
@@ -57,6 +57,7 @@ void LayoutSVGFilterPrimitive::StyleDidChange(StyleDifference diff, const ComputedStyle* old_style) { + CheckIsNotDestroyed(); if (!old_style) return; auto& element = To<SVGFilterPrimitiveStandardAttributes>(*GetNode()); @@ -81,6 +82,7 @@ } void LayoutSVGFilterPrimitive::UpdateLayout() { + CheckIsNotDestroyed(); ClearNeedsLayout(); }
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_filter_primitive.h b/third_party/blink/renderer/core/layout/svg/layout_svg_filter_primitive.h index b0e16f4..534a8ca 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_filter_primitive.h +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_filter_primitive.h
@@ -39,23 +39,33 @@ private: bool IsChildAllowed(LayoutObject*, const ComputedStyle&) const override { + CheckIsNotDestroyed(); return false; } void StyleDidChange(StyleDifference, const ComputedStyle*) override; void UpdateLayout() override; - const char* GetName() const override { return "LayoutSVGFilterPrimitive"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutSVGFilterPrimitive"; + } bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectSVG || type == kLayoutObjectSVGFilterPrimitive || LayoutObject::IsOfType(type); } - FloatRect ObjectBoundingBox() const override { return FloatRect(); } + FloatRect ObjectBoundingBox() const override { + CheckIsNotDestroyed(); + return FloatRect(); + } FloatRect VisualRectInLocalSVGCoordinates() const override { + CheckIsNotDestroyed(); return FloatRect(); } FloatRect LocalBoundingBoxRectForAccessibility() const override { + CheckIsNotDestroyed(); return FloatRect(); } };
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.cc index 1cc2664..5f7a312 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.cc
@@ -39,16 +39,19 @@ bool LayoutSVGForeignObject::IsChildAllowed(LayoutObject* child, const ComputedStyle& style) const { + CheckIsNotDestroyed(); // Disallow arbitary SVG content. Only allow proper <svg xmlns="svgNS"> // subdocuments. return !child->IsSVGChild(); } void LayoutSVGForeignObject::Paint(const PaintInfo& paint_info) const { + CheckIsNotDestroyed(); SVGForeignObjectPainter(*this).Paint(paint_info); } void LayoutSVGForeignObject::UpdateLogicalWidth() { + CheckIsNotDestroyed(); const ComputedStyle& style = StyleRef(); float logical_width = style.IsHorizontalWritingMode() ? viewport_.Width() : viewport_.Height(); @@ -60,6 +63,7 @@ LayoutUnit, LayoutUnit logical_top, LogicalExtentComputedValues& computed_values) const { + CheckIsNotDestroyed(); const ComputedStyle& style = StyleRef(); float logical_height = style.IsHorizontalWritingMode() ? viewport_.Height() : viewport_.Width(); @@ -69,6 +73,7 @@ } AffineTransform LayoutSVGForeignObject::LocalToSVGParentTransform() const { + CheckIsNotDestroyed(); // Include a zoom inverse in the local-to-parent transform since descendants // of the <foreignObject> will have regular zoom applied, and thus need to // have that removed when moving into the <fO> ancestors chain (the SVG root @@ -79,6 +84,7 @@ } void LayoutSVGForeignObject::UpdateLayout() { + CheckIsNotDestroyed(); DCHECK(NeedsLayout()); auto* foreign = To<SVGForeignObjectElement>(GetElement()); @@ -144,6 +150,7 @@ const HitTestLocation& hit_test_location, const PhysicalOffset& accumulated_offset, HitTestAction) { + CheckIsNotDestroyed(); DCHECK_EQ(accumulated_offset, PhysicalOffset()); TransformedHitTestLocation local_location(hit_test_location, LocalToSVGParentTransform()); @@ -179,18 +186,21 @@ const HitTestLocation& hit_test_location, const PhysicalOffset& accumulated_offset, HitTestAction hit_test_action) { + CheckIsNotDestroyed(); // Skip LayoutSVGBlock's override. return LayoutBlockFlow::NodeAtPoint(result, hit_test_location, accumulated_offset, hit_test_action); } PaintLayerType LayoutSVGForeignObject::LayerTypeRequired() const { + CheckIsNotDestroyed(); // Skip LayoutSVGBlock's override. return LayoutBlockFlow::LayerTypeRequired(); } void LayoutSVGForeignObject::StyleDidChange(StyleDifference diff, const ComputedStyle* old_style) { + CheckIsNotDestroyed(); LayoutSVGBlock::StyleDidChange(diff, old_style); if (old_style && (SVGLayoutSupport::IsOverflowHidden(*old_style) !=
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.h b/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.h index aa751ed..0d26b38 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.h +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.h
@@ -55,7 +55,10 @@ explicit LayoutSVGForeignObject(SVGForeignObjectElement*); ~LayoutSVGForeignObject() override; - const char* GetName() const override { return "LayoutSVGForeignObject"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutSVGForeignObject"; + } bool IsChildAllowed(LayoutObject*, const ComputedStyle&) const override; @@ -63,12 +66,22 @@ void UpdateLayout() override; - FloatRect ObjectBoundingBox() const override { return viewport_; } - FloatRect StrokeBoundingBox() const override { return ObjectBoundingBox(); } + FloatRect ObjectBoundingBox() const override { + CheckIsNotDestroyed(); + return viewport_; + } + FloatRect StrokeBoundingBox() const override { + CheckIsNotDestroyed(); + return ObjectBoundingBox(); + } FloatRect VisualRectInLocalSVGCoordinates() const override { + CheckIsNotDestroyed(); return FloatRect(FrameRect()); } - bool IsObjectBoundingBoxValid() const { return !viewport_.IsEmpty(); } + bool IsObjectBoundingBoxValid() const { + CheckIsNotDestroyed(); + return !viewport_.IsEmpty(); + } bool NodeAtPoint(HitTestResult&, const HitTestLocation&, @@ -85,6 +98,7 @@ HitTestAction); bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectSVGForeignObject || LayoutSVGBlock::IsOfType(type); } @@ -92,6 +106,7 @@ PaintLayerType LayerTypeRequired() const override; bool CreatesNewFormattingContext() const final { + CheckIsNotDestroyed(); // This is the root of a foreign object. Don't let anything inside it escape // to our ancestors. return true;
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_hidden_container.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_hidden_container.cc index c2c57a7..dbc61af 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_hidden_container.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_hidden_container.cc
@@ -28,6 +28,7 @@ : LayoutSVGContainer(element) {} void LayoutSVGHiddenContainer::UpdateLayout() { + CheckIsNotDestroyed(); DCHECK(NeedsLayout()); LayoutAnalyzer::Scope analyzer(*this); @@ -47,6 +48,7 @@ const HitTestLocation&, const PhysicalOffset&, HitTestAction) { + CheckIsNotDestroyed(); return false; }
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_hidden_container.h b/third_party/blink/renderer/core/layout/svg/layout_svg_hidden_container.h index 06e9e782..c3c32c4f 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_hidden_container.h +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_hidden_container.h
@@ -32,27 +32,35 @@ public: explicit LayoutSVGHiddenContainer(SVGElement*); - const char* GetName() const override { return "LayoutSVGHiddenContainer"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutSVGHiddenContainer"; + } protected: void UpdateLayout() override; bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectSVGHiddenContainer || LayoutSVGContainer::IsOfType(type); } private: // LayoutSVGHiddenContainer paints nothing. - void Paint(const PaintInfo&) const final {} + void Paint(const PaintInfo&) const final { CheckIsNotDestroyed(); } PhysicalRect VisualRectInDocument(VisualRectFlags) const final { + CheckIsNotDestroyed(); return PhysicalRect(); } FloatRect VisualRectInLocalSVGCoordinates() const final { + CheckIsNotDestroyed(); return FloatRect(); } void AbsoluteQuads(Vector<FloatQuad>&, - MapCoordinatesFlags mode = 0) const final {} + MapCoordinatesFlags mode = 0) const final { + CheckIsNotDestroyed(); + } bool NodeAtPoint(HitTestResult&, const HitTestLocation&,
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_image.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_image.cc index 3367c8d..58bfbc5 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_image.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_image.cc
@@ -61,12 +61,14 @@ void LayoutSVGImage::StyleDidChange(StyleDifference diff, const ComputedStyle* old_style) { + CheckIsNotDestroyed(); transform_uses_reference_box_ = TransformHelper::DependsOnReferenceBox(StyleRef()); LayoutSVGModelObject::StyleDidChange(diff, old_style); } void LayoutSVGImage::WillBeDestroyed() { + CheckIsNotDestroyed(); image_resource_->Shutdown(); LayoutSVGModelObject::WillBeDestroyed(); @@ -83,6 +85,7 @@ } bool LayoutSVGImage::HasOverriddenIntrinsicSize() const { + CheckIsNotDestroyed(); if (!RuntimeEnabledFeatures::ExperimentalProductivityFeaturesEnabled()) return false; auto* svg_image_element = DynamicTo<SVGImageElement>(GetElement()); @@ -90,6 +93,7 @@ } FloatSize LayoutSVGImage::CalculateObjectSize() const { + CheckIsNotDestroyed(); FloatSize intrinsic_size; ImageResourceContent* cached_image = image_resource_->CachedImage(); bool has_intrinsic_ratio = true; @@ -134,6 +138,7 @@ } bool LayoutSVGImage::UpdateBoundingBox() { + CheckIsNotDestroyed(); FloatRect old_object_bounding_box = object_bounding_box_; SVGLengthContext length_context(GetElement()); @@ -155,6 +160,7 @@ } void LayoutSVGImage::UpdateLayout() { + CheckIsNotDestroyed(); DCHECK(NeedsLayout()); LayoutAnalyzer::Scope analyzer(*this); @@ -202,6 +208,7 @@ } void LayoutSVGImage::Paint(const PaintInfo& paint_info) const { + CheckIsNotDestroyed(); SVGImagePainter(*this).Paint(paint_info); } @@ -209,6 +216,7 @@ const HitTestLocation& hit_test_location, const PhysicalOffset& accumulated_offset, HitTestAction hit_test_action) { + CheckIsNotDestroyed(); DCHECK_EQ(accumulated_offset, PhysicalOffset()); // We only draw in the forground phase, so we only hit-test then. if (hit_test_action != kHitTestForeground) @@ -242,6 +250,7 @@ } void LayoutSVGImage::ImageChanged(WrappedImagePtr, CanDeferInvalidation defer) { + CheckIsNotDestroyed(); // Notify parent resources that we've changed. This also invalidates // references from resources (filters) that may have a cached // representation of this image/layout object.
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_image.h b/third_party/blink/renderer/core/layout/svg/layout_svg_image.h index bc8b9227..0cbbbf9 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_image.h +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_image.h
@@ -36,32 +36,53 @@ explicit LayoutSVGImage(SVGImageElement*); ~LayoutSVGImage() override; - void SetNeedsBoundariesUpdate() override { needs_boundaries_update_ = true; } - void SetNeedsTransformUpdate() override { needs_transform_update_ = true; } + void SetNeedsBoundariesUpdate() override { + CheckIsNotDestroyed(); + needs_boundaries_update_ = true; + } + void SetNeedsTransformUpdate() override { + CheckIsNotDestroyed(); + needs_transform_update_ = true; + } - LayoutImageResource* ImageResource() { return image_resource_.Get(); } + LayoutImageResource* ImageResource() { + CheckIsNotDestroyed(); + return image_resource_.Get(); + } const LayoutImageResource* ImageResource() const { + CheckIsNotDestroyed(); return image_resource_.Get(); } - FloatRect ObjectBoundingBox() const override { return object_bounding_box_; } + FloatRect ObjectBoundingBox() const override { + CheckIsNotDestroyed(); + return object_bounding_box_; + } bool IsObjectBoundingBoxValid() const { + CheckIsNotDestroyed(); return !object_bounding_box_.IsEmpty(); } bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectSVGImage || LayoutSVGModelObject::IsOfType(type); } - const char* GetName() const override { return "LayoutSVGImage"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutSVGImage"; + } protected: void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override; void WillBeDestroyed() override; private: - FloatRect StrokeBoundingBox() const override { return object_bounding_box_; } + FloatRect StrokeBoundingBox() const override { + CheckIsNotDestroyed(); + return object_bounding_box_; + } void ImageChanged(WrappedImagePtr, CanDeferInvalidation) override; @@ -76,6 +97,7 @@ HitTestAction) override; AffineTransform LocalSVGTransform() const override { + CheckIsNotDestroyed(); return local_transform_; }
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_inline.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_inline.cc index 0a1f4135..592713b 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_inline.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_inline.cc
@@ -34,6 +34,7 @@ bool LayoutSVGInline::IsChildAllowed(LayoutObject* child, const ComputedStyle& style) const { + CheckIsNotDestroyed(); if (child->IsText()) return SVGLayoutSupport::IsLayoutableTextNode(child); @@ -55,12 +56,14 @@ } InlineFlowBox* LayoutSVGInline::CreateInlineFlowBox() { + CheckIsNotDestroyed(); InlineFlowBox* box = new SVGInlineFlowBox(LineLayoutItem(this)); box->SetHasVirtualLogicalHeight(); return box; } FloatRect LayoutSVGInline::ObjectBoundingBox() const { + CheckIsNotDestroyed(); FloatRect bounds; for (InlineFlowBox* box : *LineBoxes()) bounds.Unite(FloatRect(box->FrameRect())); @@ -68,12 +71,14 @@ } FloatRect LayoutSVGInline::StrokeBoundingBox() const { + CheckIsNotDestroyed(); if (!FirstLineBox()) return FloatRect(); return SVGLayoutSupport::ExtendTextBBoxWithStroke(*this, ObjectBoundingBox()); } FloatRect LayoutSVGInline::VisualRectInLocalSVGCoordinates() const { + CheckIsNotDestroyed(); if (!FirstLineBox()) return FloatRect(); const LayoutSVGText* text_root = @@ -86,24 +91,28 @@ PhysicalRect LayoutSVGInline::VisualRectInDocument( VisualRectFlags flags) const { + CheckIsNotDestroyed(); return SVGLayoutSupport::VisualRectInAncestorSpace(*this, *View(), flags); } void LayoutSVGInline::MapLocalToAncestor(const LayoutBoxModelObject* ancestor, TransformState& transform_state, MapCoordinatesFlags flags) const { + CheckIsNotDestroyed(); SVGLayoutSupport::MapLocalToAncestor(this, ancestor, transform_state, flags); } const LayoutObject* LayoutSVGInline::PushMappingToContainer( const LayoutBoxModelObject* ancestor_to_stop_at, LayoutGeometryMap& geometry_map) const { + CheckIsNotDestroyed(); return SVGLayoutSupport::PushMappingToContainer(this, ancestor_to_stop_at, geometry_map); } void LayoutSVGInline::AbsoluteQuads(Vector<FloatQuad>& quads, MapCoordinatesFlags mode) const { + CheckIsNotDestroyed(); for (InlineFlowBox* box : *LineBoxes()) { FloatRect box_rect(box->FrameRect()); quads.push_back(LocalToAbsoluteQuad( @@ -112,6 +121,7 @@ } void LayoutSVGInline::WillBeDestroyed() { + CheckIsNotDestroyed(); SVGResourcesCache::ClientDestroyed(*this); SVGResources::ClearClipPathFilterMask(To<SVGElement>(*GetNode()), Style()); SVGResources::ClearPaints(To<SVGElement>(*GetNode()), Style()); @@ -120,6 +130,7 @@ void LayoutSVGInline::StyleDidChange(StyleDifference diff, const ComputedStyle* old_style) { + CheckIsNotDestroyed(); // Since layout depends on the bounds of the filter, we need to force layout // when the filter changes. if (diff.FilterChanged()) @@ -140,6 +151,7 @@ void LayoutSVGInline::AddChild(LayoutObject* child, LayoutObject* before_child) { + CheckIsNotDestroyed(); LayoutInline::AddChild(child, before_child); SVGResourcesCache::ClientWasAddedToTree(*child); LayoutSVGText::NotifySubtreeStructureChanged( @@ -147,6 +159,7 @@ } void LayoutSVGInline::RemoveChild(LayoutObject* child) { + CheckIsNotDestroyed(); SVGResourcesCache::ClientWillBeRemovedFromTree(*child); LayoutSVGText::NotifySubtreeStructureChanged( this, layout_invalidation_reason::kChildChanged); @@ -154,6 +167,7 @@ } void LayoutSVGInline::InsertedIntoTree() { + CheckIsNotDestroyed(); LayoutInline::InsertedIntoTree(); if (CompositingReasonFinder::DirectReasonsForSVGChildPaintProperties(*this) != CompositingReason::kNone) { @@ -162,6 +176,7 @@ } void LayoutSVGInline::WillBeRemovedFromTree() { + CheckIsNotDestroyed(); LayoutInline::WillBeRemovedFromTree(); if (CompositingReasonFinder::DirectReasonsForSVGChildPaintProperties(*this) != CompositingReason::kNone) {
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_inline.h b/third_party/blink/renderer/core/layout/svg/layout_svg_inline.h index d4294b6..3a4858ae 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_inline.h +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_inline.h
@@ -29,9 +29,16 @@ public: explicit LayoutSVGInline(Element*); - const char* GetName() const override { return "LayoutSVGInline"; } - PaintLayerType LayerTypeRequired() const final { return kNoPaintLayer; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutSVGInline"; + } + PaintLayerType LayerTypeRequired() const final { + CheckIsNotDestroyed(); + return kNoPaintLayer; + } bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectSVG || type == kLayoutObjectSVGInline || LayoutInline::IsOfType(type); }
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_inline_text.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_inline_text.cc index 4df02e4..f66316b4 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_inline_text.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_inline_text.cc
@@ -57,6 +57,7 @@ scaling_factor_(1) {} void LayoutSVGInlineText::TextDidChange() { + CheckIsNotDestroyed(); SetTextInternal(NormalizeWhitespace(GetText().Impl())); LayoutText::TextDidChange(); LayoutSVGText::NotifySubtreeStructureChanged( @@ -65,6 +66,7 @@ void LayoutSVGInlineText::StyleDidChange(StyleDifference diff, const ComputedStyle* old_style) { + CheckIsNotDestroyed(); LayoutText::StyleDidChange(diff, old_style); UpdateScaledFont(); @@ -89,6 +91,7 @@ } InlineTextBox* LayoutSVGInlineText::CreateTextBox(int start, uint16_t length) { + CheckIsNotDestroyed(); InlineTextBox* box = new SVGInlineTextBox(LineLayoutItem(this), start, length); box->SetHasVirtualLogicalHeight(); @@ -98,6 +101,7 @@ LayoutRect LayoutSVGInlineText::LocalCaretRect(const InlineBox* box, int caret_offset, LayoutUnit*) const { + CheckIsNotDestroyed(); if (!box || !box->IsInlineTextBox()) return LayoutRect(); @@ -122,6 +126,7 @@ } FloatRect LayoutSVGInlineText::FloatLinesBoundingBox() const { + CheckIsNotDestroyed(); FloatRect bounding_box; for (InlineTextBox* box : TextBoxes()) bounding_box.Unite(FloatRect(box->FrameRect())); @@ -129,10 +134,12 @@ } PhysicalRect LayoutSVGInlineText::PhysicalLinesBoundingBox() const { + CheckIsNotDestroyed(); return PhysicalRect::EnclosingRect(FloatLinesBoundingBox()); } bool LayoutSVGInlineText::CharacterStartsNewTextChunk(int position) const { + CheckIsNotDestroyed(); DCHECK_GE(position, 0); DCHECK_LT(position, static_cast<int>(TextLength())); @@ -151,6 +158,7 @@ PositionWithAffinity LayoutSVGInlineText::PositionForPoint( const PhysicalOffset& point) const { + CheckIsNotDestroyed(); if (!HasInlineFragments() || !TextLength()) return CreatePositionWithAffinity(0); @@ -298,6 +306,7 @@ void LayoutSVGInlineText::AddMetricsFromRun( const TextRun& run, bool& last_character_was_white_space) { + CheckIsNotDestroyed(); Vector<CharacterRange> char_ranges = ScaledFont().IndividualCharacterRanges(run); SynthesizeGraphemeWidths(run, char_ranges); @@ -337,6 +346,7 @@ void LayoutSVGInlineText::UpdateMetricsList( bool& last_character_was_white_space) { + CheckIsNotDestroyed(); metrics_.clear(); if (!TextLength()) @@ -379,6 +389,7 @@ } void LayoutSVGInlineText::UpdateScaledFont() { + CheckIsNotDestroyed(); ComputeNewScaledFontForStyle(*this, scaling_factor_, scaled_font_); } @@ -420,10 +431,12 @@ PhysicalRect LayoutSVGInlineText::VisualRectInDocument( VisualRectFlags flags) const { + CheckIsNotDestroyed(); return Parent()->VisualRectInDocument(flags); } FloatRect LayoutSVGInlineText::VisualRectInLocalSVGCoordinates() const { + CheckIsNotDestroyed(); return Parent()->VisualRectInLocalSVGCoordinates(); }
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_inline_text.h b/third_party/blink/renderer/core/layout/svg/layout_svg_inline_text.h index 20ca818..e0f2a08 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_inline_text.h +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_inline_text.h
@@ -34,15 +34,28 @@ LayoutSVGInlineText(Node*, scoped_refptr<StringImpl>); bool CharacterStartsNewTextChunk(int position) const; - SVGCharacterDataMap& CharacterDataMap() { return character_data_map_; } + SVGCharacterDataMap& CharacterDataMap() { + CheckIsNotDestroyed(); + return character_data_map_; + } const SVGCharacterDataMap& CharacterDataMap() const { + CheckIsNotDestroyed(); return character_data_map_; } - const Vector<SVGTextMetrics>& MetricsList() const { return metrics_; } + const Vector<SVGTextMetrics>& MetricsList() const { + CheckIsNotDestroyed(); + return metrics_; + } - float ScalingFactor() const { return scaling_factor_; } - const Font& ScaledFont() const { return scaled_font_; } + float ScalingFactor() const { + CheckIsNotDestroyed(); + return scaling_factor_; + } + const Font& ScaledFont() const { + CheckIsNotDestroyed(); + return scaled_font_; + } void UpdateScaledFont(); void UpdateMetricsList(bool& last_character_was_white_space); static void ComputeNewScaledFontForStyle(const LayoutObject&, @@ -53,7 +66,10 @@ // round and does a better job than enclosingIntRect. FloatRect FloatLinesBoundingBox() const; - const char* GetName() const override { return "LayoutSVGInlineText"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutSVGInlineText"; + } private: void TextDidChange() override; @@ -62,10 +78,12 @@ void AddMetricsFromRun(const TextRun&, bool& last_character_was_white_space); FloatRect ObjectBoundingBox() const override { + CheckIsNotDestroyed(); return FloatLinesBoundingBox(); } bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectSVG || type == kLayoutObjectSVGInlineText || LayoutText::IsOfType(type); }
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.cc index d13473f7..9cfa1c37 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.cc
@@ -45,6 +45,7 @@ bool LayoutSVGModelObject::IsChildAllowed(LayoutObject* child, const ComputedStyle&) const { + CheckIsNotDestroyed(); return child->IsSVG() && !(child->IsSVGInline() || child->IsSVGInlineText()); } @@ -52,11 +53,13 @@ const LayoutBoxModelObject* ancestor, TransformState& transform_state, MapCoordinatesFlags flags) const { + CheckIsNotDestroyed(); SVGLayoutSupport::MapLocalToAncestor(this, ancestor, transform_state, flags); } PhysicalRect LayoutSVGModelObject::VisualRectInDocument( VisualRectFlags flags) const { + CheckIsNotDestroyed(); return SVGLayoutSupport::VisualRectInAncestorSpace(*this, *View(), flags); } @@ -64,18 +67,21 @@ const LayoutBoxModelObject* ancestor, TransformState& transform_state, MapCoordinatesFlags flags) const { + CheckIsNotDestroyed(); SVGLayoutSupport::MapAncestorToLocal(*this, ancestor, transform_state, flags); } const LayoutObject* LayoutSVGModelObject::PushMappingToContainer( const LayoutBoxModelObject* ancestor_to_stop_at, LayoutGeometryMap& geometry_map) const { + CheckIsNotDestroyed(); return SVGLayoutSupport::PushMappingToContainer(this, ancestor_to_stop_at, geometry_map); } void LayoutSVGModelObject::AbsoluteQuads(Vector<FloatQuad>& quads, MapCoordinatesFlags mode) const { + CheckIsNotDestroyed(); quads.push_back(LocalToAbsoluteQuad(StrokeBoundingBox(), mode)); } @@ -84,21 +90,25 @@ void LayoutSVGModelObject::AddOutlineRects(Vector<PhysicalRect>& rects, const PhysicalOffset&, NGOutlineType) const { + CheckIsNotDestroyed(); rects.push_back( PhysicalRect::EnclosingRect(VisualRectInLocalSVGCoordinates())); } FloatRect LayoutSVGModelObject::LocalBoundingBoxRectForAccessibility() const { + CheckIsNotDestroyed(); return StrokeBoundingBox(); } void LayoutSVGModelObject::WillBeDestroyed() { + CheckIsNotDestroyed(); SVGResourcesCache::ClientDestroyed(*this); SVGResources::ClearClipPathFilterMask(*GetElement(), Style()); LayoutObject::WillBeDestroyed(); } AffineTransform LayoutSVGModelObject::CalculateLocalTransform() const { + CheckIsNotDestroyed(); auto* element = GetElement(); if (element->HasTransform(SVGElement::kIncludeMotionTransform)) return element->CalculateTransform(SVGElement::kIncludeMotionTransform); @@ -107,6 +117,7 @@ bool LayoutSVGModelObject::CheckForImplicitTransformChange( bool bbox_changed) const { + CheckIsNotDestroyed(); // If the transform is relative to the reference box, check relevant // conditions to see if we need to recompute the transform. switch (StyleRef().TransformBox()) { @@ -121,6 +132,7 @@ void LayoutSVGModelObject::StyleDidChange(StyleDifference diff, const ComputedStyle* old_style) { + CheckIsNotDestroyed(); // Since layout depends on the bounds of the filter, we need to force layout // when the filter changes. We also need to make sure paint will be // performed, since if the filter changed we will not have cached result from @@ -158,6 +170,7 @@ } void LayoutSVGModelObject::InsertedIntoTree() { + CheckIsNotDestroyed(); LayoutObject::InsertedIntoTree(); if (CompositingReasonFinder::DirectReasonsForSVGChildPaintProperties(*this) != CompositingReason::kNone) { @@ -166,6 +179,7 @@ } void LayoutSVGModelObject::WillBeRemovedFromTree() { + CheckIsNotDestroyed(); LayoutObject::WillBeRemovedFromTree(); if (CompositingReasonFinder::DirectReasonsForSVGChildPaintProperties(*this) != CompositingReason::kNone) {
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.h b/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.h index 4bf6cd8..941e5d40 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.h +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.h
@@ -51,6 +51,7 @@ VisualRectFlags = kDefaultVisualRectFlags) const override; FloatRect VisualRectInLocalSVGCoordinates() const override { + CheckIsNotDestroyed(); return local_visual_rect_; } @@ -70,10 +71,12 @@ void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override; SVGElement* GetElement() const { + CheckIsNotDestroyed(); return To<SVGElement>(LayoutObject::GetNode()); } bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectSVG || LayoutObject::IsOfType(type); }
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_path.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_path.cc index 9f5bd0a..d152fd8 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_path.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_path.cc
@@ -42,27 +42,32 @@ void LayoutSVGPath::StyleDidChange(StyleDifference diff, const ComputedStyle* old_style) { + CheckIsNotDestroyed(); LayoutSVGShape::StyleDidChange(diff, old_style); SVGResources::UpdateMarkers(*GetElement(), old_style, StyleRef()); } void LayoutSVGPath::WillBeDestroyed() { + CheckIsNotDestroyed(); SVGResources::ClearMarkers(*GetElement(), Style()); LayoutSVGShape::WillBeDestroyed(); } void LayoutSVGPath::UpdateShapeFromElement() { + CheckIsNotDestroyed(); LayoutSVGShape::UpdateShapeFromElement(); UpdateMarkers(); } const StylePath* LayoutSVGPath::GetStylePath() const { + CheckIsNotDestroyed(); if (!IsA<SVGPathElement>(*GetElement())) return nullptr; return StyleRef().SvgStyle().D(); } void LayoutSVGPath::UpdateMarkers() { + CheckIsNotDestroyed(); marker_positions_.clear(); if (!StyleRef().SvgStyle().HasMarkers() ||
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_path.h b/third_party/blink/renderer/core/layout/svg/layout_svg_path.h index 97b0056..f3e1ac52 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_path.h +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_path.h
@@ -36,10 +36,14 @@ ~LayoutSVGPath() override; const Vector<MarkerPosition>* MarkerPositions() const override { + CheckIsNotDestroyed(); return &marker_positions_; } - const char* GetName() const override { return "LayoutSVGPath"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutSVGPath"; + } private: void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override;
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_rect.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_rect.cc index 03650fc..7a0bf57 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_rect.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_rect.cc
@@ -39,6 +39,7 @@ LayoutSVGRect::~LayoutSVGRect() = default; void LayoutSVGRect::UpdateShapeFromElement() { + CheckIsNotDestroyed(); // Before creating a new object we need to clear the cached bounding box // to avoid using garbage. fill_bounding_box_ = FloatRect(); @@ -86,6 +87,7 @@ bool LayoutSVGRect::ShapeDependentStrokeContains( const HitTestLocation& location) { + CheckIsNotDestroyed(); // The optimized code below does not support the cases that we set // use_path_fallback_ in UpdateShapeFromElement(). if (use_path_fallback_) @@ -112,6 +114,7 @@ bool LayoutSVGRect::ShapeDependentFillContains(const HitTestLocation& location, const WindRule fill_rule) const { + CheckIsNotDestroyed(); if (use_path_fallback_) return LayoutSVGShape::ShapeDependentFillContains(location, fill_rule); const FloatPoint& point = location.TransformedPoint(); @@ -120,6 +123,7 @@ // Returns true if the stroke is continuous and definitely uses miter joins. bool LayoutSVGRect::DefinitelyHasSimpleStroke() const { + CheckIsNotDestroyed(); const SVGComputedStyle& svg_style = StyleRef().SvgStyle(); // The four angles of a rect are 90 degrees. Using the formula at:
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_rect.h b/third_party/blink/renderer/core/layout/svg/layout_svg_rect.h index 9dc9c764..30a18f5 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_rect.h +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_rect.h
@@ -38,14 +38,19 @@ ~LayoutSVGRect() override; ShapeGeometryCodePath GeometryCodePath() const override { + CheckIsNotDestroyed(); return use_path_fallback_ ? kPathGeometry : kRectGeometryFastPath; } - const char* GetName() const override { return "LayoutSVGRect"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutSVGRect"; + } private: void UpdateShapeFromElement() override; bool IsShapeEmpty() const override { + CheckIsNotDestroyed(); return use_path_fallback_ ? LayoutSVGShape::IsShapeEmpty() : fill_bounding_box_.IsEmpty(); }
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_clipper.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_clipper.cc index 898ca49..bcfa3c9 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_clipper.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_clipper.cc
@@ -111,6 +111,7 @@ LayoutSVGResourceClipper::~LayoutSVGResourceClipper() = default; void LayoutSVGResourceClipper::RemoveAllClientsFromCache() { + CheckIsNotDestroyed(); clip_content_path_validity_ = kClipContentPathUnknown; clip_content_path_.Clear(); cached_paint_record_.reset(); @@ -120,6 +121,7 @@ } base::Optional<Path> LayoutSVGResourceClipper::AsPath() { + CheckIsNotDestroyed(); if (clip_content_path_validity_ == kClipContentPathValid) return base::Optional<Path>(clip_content_path_); if (clip_content_path_validity_ == kClipContentPathInvalid) @@ -170,6 +172,7 @@ } sk_sp<const PaintRecord> LayoutSVGResourceClipper::CreatePaintRecord() { + CheckIsNotDestroyed(); DCHECK(GetFrame()); if (cached_paint_record_) return cached_paint_record_; @@ -201,6 +204,7 @@ } void LayoutSVGResourceClipper::CalculateLocalClipBounds() { + CheckIsNotDestroyed(); // This is a rough heuristic to appraise the clip size and doesn't consider // clip on clip. for (const SVGElement& child_element : @@ -214,6 +218,7 @@ } SVGUnitTypes::SVGUnitType LayoutSVGResourceClipper::ClipPathUnits() const { + CheckIsNotDestroyed(); return To<SVGClipPathElement>(GetElement()) ->clipPathUnits() ->CurrentEnumValue(); @@ -221,6 +226,7 @@ AffineTransform LayoutSVGResourceClipper::CalculateClipTransform( const FloatRect& reference_box) const { + CheckIsNotDestroyed(); AffineTransform transform = To<SVGClipPathElement>(GetElement()) ->CalculateTransform(SVGElement::kIncludeMotionTransform); @@ -234,6 +240,7 @@ bool LayoutSVGResourceClipper::HitTestClipContent( const FloatRect& object_bounding_box, const HitTestLocation& location) const { + CheckIsNotDestroyed(); if (!SVGLayoutSupport::IntersectsClipPath(*this, object_bounding_box, location)) return false; @@ -262,6 +269,7 @@ FloatRect LayoutSVGResourceClipper::ResourceBoundingBox( const FloatRect& reference_box) { + CheckIsNotDestroyed(); // The resource has not been layouted yet. Return the reference box. if (SelfNeedsLayout()) return reference_box; @@ -274,6 +282,7 @@ void LayoutSVGResourceClipper::StyleDidChange(StyleDifference diff, const ComputedStyle* old_style) { + CheckIsNotDestroyed(); LayoutSVGResourceContainer::StyleDidChange(diff, old_style); if (diff.TransformChanged()) { MarkAllClientsForInvalidation(SVGResourceClient::kBoundariesInvalidation | @@ -282,6 +291,7 @@ } void LayoutSVGResourceClipper::WillBeDestroyed() { + CheckIsNotDestroyed(); MarkAllClientsForInvalidation(SVGResourceClient::kBoundariesInvalidation | SVGResourceClient::kPaintInvalidation); LayoutSVGResourceContainer::WillBeDestroyed();
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_clipper.h b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_clipper.h index 661f7b0..aeebef2 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_clipper.h +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_clipper.h
@@ -34,14 +34,20 @@ explicit LayoutSVGResourceClipper(SVGClipPathElement*); ~LayoutSVGResourceClipper() override; - const char* GetName() const override { return "LayoutSVGResourceClipper"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutSVGResourceClipper"; + } void RemoveAllClientsFromCache() override; FloatRect ResourceBoundingBox(const FloatRect& reference_box); static const LayoutSVGResourceType kResourceType = kClipperResourceType; - LayoutSVGResourceType ResourceType() const override { return kResourceType; } + LayoutSVGResourceType ResourceType() const override { + CheckIsNotDestroyed(); + return kResourceType; + } bool HitTestClipContent(const FloatRect&, const HitTestLocation&) const;
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_container.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_container.cc index 3f449e5..1c1715ed 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_container.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_container.cc
@@ -49,6 +49,7 @@ LayoutSVGResourceContainer::~LayoutSVGResourceContainer() = default; void LayoutSVGResourceContainer::UpdateLayout() { + CheckIsNotDestroyed(); // FIXME: Investigate a way to detect and break resource layout dependency // cycles early. Then we can remove this method altogether, and fall back onto // LayoutSVGHiddenContainer::layout(). @@ -64,6 +65,7 @@ } void LayoutSVGResourceContainer::WillBeDestroyed() { + CheckIsNotDestroyed(); LayoutSVGHiddenContainer::WillBeDestroyed(); // The resource is being torn down. // TODO(fs): Remove this when SVGResources is gone. @@ -74,6 +76,7 @@ void LayoutSVGResourceContainer::StyleDidChange( StyleDifference diff, const ComputedStyle* old_style) { + CheckIsNotDestroyed(); LayoutSVGHiddenContainer::StyleDidChange(diff, old_style); // The resource has been attached. Notify any pending clients that // they can now try to add themselves as clients to the resource. @@ -86,6 +89,7 @@ bool LayoutSVGResourceContainer::FindCycle( SVGResourcesCycleSolver& solver) const { + CheckIsNotDestroyed(); if (solver.IsKnownAcyclic(this)) return false; SVGResourcesCycleSolver::Scope scope(solver); @@ -116,6 +120,7 @@ bool LayoutSVGResourceContainer::FindCycleFromSelf( SVGResourcesCycleSolver& solver) const { + CheckIsNotDestroyed(); return FindCycleInSubtree(solver, *this); } @@ -147,6 +152,7 @@ void LayoutSVGResourceContainer::MarkAllClientsForInvalidation( InvalidationModeMask invalidation_mask) { + CheckIsNotDestroyed(); if (is_invalidating_) return; LocalSVGResource* resource = ResourceForContainer(*this); @@ -190,6 +196,7 @@ void LayoutSVGResourceContainer::InvalidateCacheAndMarkForLayout( LayoutInvalidationReasonForTracing reason, SubtreeLayoutScope* layout_scope) { + CheckIsNotDestroyed(); if (SelfNeedsLayout()) return; @@ -202,6 +209,7 @@ void LayoutSVGResourceContainer::InvalidateCacheAndMarkForLayout( SubtreeLayoutScope* layout_scope) { + CheckIsNotDestroyed(); InvalidateCacheAndMarkForLayout( layout_invalidation_reason::kSvgResourceInvalidated, layout_scope); }
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_container.h b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_container.h index 6874d6e..f0a1d75 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_container.h +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_container.h
@@ -47,10 +47,14 @@ virtual void RemoveAllClientsFromCache() = 0; // Remove any cached data for the |client|, and return true if so. - virtual bool RemoveClientFromCache(SVGResourceClient&) { return false; } + virtual bool RemoveClientFromCache(SVGResourceClient&) { + CheckIsNotDestroyed(); + return false; + } void UpdateLayout() override; bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectSVGResourceContainer || LayoutSVGHiddenContainer::IsOfType(type); } @@ -58,6 +62,7 @@ virtual LayoutSVGResourceType ResourceType() const = 0; bool IsSVGPaintServer() const { + CheckIsNotDestroyed(); LayoutSVGResourceType resource_type = ResourceType(); return resource_type == kPatternResourceType || resource_type == kLinearGradientResourceType || @@ -75,7 +80,10 @@ bool needs_layout = true); static void MarkClientForInvalidation(LayoutObject&, InvalidationModeMask); - void ClearInvalidationMask() { completed_invalidations_mask_ = 0; } + void ClearInvalidationMask() { + CheckIsNotDestroyed(); + completed_invalidations_mask_ = 0; + } protected: // Used from RemoveAllClientsFromCache methods.
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_filter.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_filter.cc index 7f0bfa6..9a52c5a 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_filter.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_filter.cc
@@ -38,26 +38,31 @@ bool LayoutSVGResourceFilter::IsChildAllowed(LayoutObject* child, const ComputedStyle&) const { + CheckIsNotDestroyed(); return child->IsSVGFilterPrimitive(); } void LayoutSVGResourceFilter::RemoveAllClientsFromCache() { + CheckIsNotDestroyed(); MarkAllClientsForInvalidation(SVGResourceClient::kLayoutInvalidation | SVGResourceClient::kBoundariesInvalidation); } FloatRect LayoutSVGResourceFilter::ResourceBoundingBox( const FloatRect& reference_box) const { + CheckIsNotDestroyed(); const auto* filter_element = To<SVGFilterElement>(GetElement()); return SVGLengthContext::ResolveRectangle(filter_element, FilterUnits(), reference_box); } SVGUnitTypes::SVGUnitType LayoutSVGResourceFilter::FilterUnits() const { + CheckIsNotDestroyed(); return To<SVGFilterElement>(GetElement())->filterUnits()->CurrentEnumValue(); } SVGUnitTypes::SVGUnitType LayoutSVGResourceFilter::PrimitiveUnits() const { + CheckIsNotDestroyed(); return To<SVGFilterElement>(GetElement()) ->primitiveUnits() ->CurrentEnumValue(); @@ -65,6 +70,7 @@ bool LayoutSVGResourceFilter::FindCycleFromSelf( SVGResourcesCycleSolver& solver) const { + CheckIsNotDestroyed(); // Traverse and check all <feImage> 'href' element references. for (auto& feimage_element : Traversal<SVGFEImageElement>::ChildrenOf(*GetElement())) {
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_filter.h b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_filter.h index 467c193..8ba1fffe 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_filter.h +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_filter.h
@@ -38,7 +38,10 @@ bool IsChildAllowed(LayoutObject*, const ComputedStyle&) const override; - const char* GetName() const override { return "LayoutSVGResourceFilter"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutSVGResourceFilter"; + } void RemoveAllClientsFromCache() override; @@ -48,7 +51,10 @@ SVGUnitTypes::SVGUnitType PrimitiveUnits() const; static const LayoutSVGResourceType kResourceType = kFilterResourceType; - LayoutSVGResourceType ResourceType() const override { return kResourceType; } + LayoutSVGResourceType ResourceType() const override { + CheckIsNotDestroyed(); + return kResourceType; + } private: bool FindCycleFromSelf(SVGResourcesCycleSolver&) const override;
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_gradient.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_gradient.cc index 24613470..6356b6b 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_gradient.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_gradient.cc
@@ -42,6 +42,7 @@ gradient_map_(MakeGarbageCollected<GradientMap>()) {} void LayoutSVGResourceGradient::RemoveAllClientsFromCache() { + CheckIsNotDestroyed(); gradient_map_->clear(); should_collect_gradient_attributes_ = true; To<SVGGradientElement>(*GetElement()).InvalidateDependentGradients(); @@ -50,6 +51,7 @@ bool LayoutSVGResourceGradient::RemoveClientFromCache( SVGResourceClient& client) { + CheckIsNotDestroyed(); auto entry = gradient_map_->find(&client); if (entry == gradient_map_->end()) return false; @@ -59,6 +61,7 @@ std::unique_ptr<GradientData> LayoutSVGResourceGradient::BuildGradientData( const FloatRect& object_bounding_box) { + CheckIsNotDestroyed(); // Create gradient object auto gradient_data = std::make_unique<GradientData>(); @@ -97,6 +100,7 @@ SVGPaintServer LayoutSVGResourceGradient::PreparePaintServer( const SVGResourceClient& client, const FloatRect& object_bounding_box) { + CheckIsNotDestroyed(); ClearInvalidationMask(); std::unique_ptr<GradientData>& gradient_data = @@ -113,6 +117,7 @@ bool LayoutSVGResourceGradient::IsChildAllowed(LayoutObject* child, const ComputedStyle&) const { + CheckIsNotDestroyed(); if (!child->IsSVGResourceContainer()) return false;
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_linear_gradient.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_linear_gradient.cc index 8d88444..7fc7f91e 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_linear_gradient.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_linear_gradient.cc
@@ -34,6 +34,7 @@ LayoutSVGResourceLinearGradient::~LayoutSVGResourceLinearGradient() = default; void LayoutSVGResourceLinearGradient::CollectGradientAttributes() { + CheckIsNotDestroyed(); DCHECK(GetElement()); attributes_wrapper_->Set(LinearGradientAttributes()); To<SVGLinearGradientElement>(GetElement()) @@ -42,6 +43,7 @@ FloatPoint LayoutSVGResourceLinearGradient::StartPoint( const LinearGradientAttributes& attributes) const { + CheckIsNotDestroyed(); return SVGLengthContext::ResolvePoint(GetElement(), attributes.GradientUnits(), *attributes.X1(), *attributes.Y1()); @@ -49,12 +51,14 @@ FloatPoint LayoutSVGResourceLinearGradient::EndPoint( const LinearGradientAttributes& attributes) const { + CheckIsNotDestroyed(); return SVGLengthContext::ResolvePoint(GetElement(), attributes.GradientUnits(), *attributes.X2(), *attributes.Y2()); } scoped_refptr<Gradient> LayoutSVGResourceLinearGradient::BuildGradient() const { + CheckIsNotDestroyed(); const LinearGradientAttributes& attributes = Attributes(); scoped_refptr<Gradient> gradient = Gradient::CreateLinear( StartPoint(attributes), EndPoint(attributes),
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_linear_gradient.h b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_linear_gradient.h index 48c43d5..fbb05e4 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_linear_gradient.h +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_linear_gradient.h
@@ -34,17 +34,23 @@ ~LayoutSVGResourceLinearGradient() override; const char* GetName() const override { + CheckIsNotDestroyed(); return "LayoutSVGResourceLinearGradient"; } static const LayoutSVGResourceType kResourceType = kLinearGradientResourceType; - LayoutSVGResourceType ResourceType() const override { return kResourceType; } + LayoutSVGResourceType ResourceType() const override { + CheckIsNotDestroyed(); + return kResourceType; + } SVGUnitTypes::SVGUnitType GradientUnits() const override { + CheckIsNotDestroyed(); return Attributes().GradientUnits(); } AffineTransform CalculateGradientTransform() const override { + CheckIsNotDestroyed(); return Attributes().GradientTransform(); } void CollectGradientAttributes() override; @@ -57,9 +63,11 @@ Persistent<LinearGradientAttributesWrapper> attributes_wrapper_; LinearGradientAttributes& MutableAttributes() { + CheckIsNotDestroyed(); return attributes_wrapper_->Attributes(); } const LinearGradientAttributes& Attributes() const { + CheckIsNotDestroyed(); return attributes_wrapper_->Attributes(); } };
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_marker.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_marker.cc index 21a99db..05a00ab 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_marker.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_marker.cc
@@ -36,6 +36,7 @@ LayoutSVGResourceMarker::~LayoutSVGResourceMarker() = default; void LayoutSVGResourceMarker::UpdateLayout() { + CheckIsNotDestroyed(); DCHECK(NeedsLayout()); if (is_in_layout_) return; @@ -51,12 +52,14 @@ } void LayoutSVGResourceMarker::RemoveAllClientsFromCache() { + CheckIsNotDestroyed(); MarkAllClientsForInvalidation(SVGResourceClient::kLayoutInvalidation | SVGResourceClient::kBoundariesInvalidation); } FloatRect LayoutSVGResourceMarker::MarkerBoundaries( const AffineTransform& marker_transformation) const { + CheckIsNotDestroyed(); FloatRect coordinates = LayoutSVGContainer::VisualRectInLocalSVGCoordinates(); // Map visual rect into parent coordinate space, in which the marker @@ -67,6 +70,7 @@ } FloatPoint LayoutSVGResourceMarker::ReferencePoint() const { + CheckIsNotDestroyed(); auto* marker = To<SVGMarkerElement>(GetElement()); DCHECK(marker); @@ -76,6 +80,7 @@ } float LayoutSVGResourceMarker::Angle() const { + CheckIsNotDestroyed(); return To<SVGMarkerElement>(GetElement()) ->orientAngle() ->CurrentValue() @@ -83,16 +88,19 @@ } SVGMarkerUnitsType LayoutSVGResourceMarker::MarkerUnits() const { + CheckIsNotDestroyed(); return To<SVGMarkerElement>(GetElement())->markerUnits()->CurrentEnumValue(); } SVGMarkerOrientType LayoutSVGResourceMarker::OrientType() const { + CheckIsNotDestroyed(); return To<SVGMarkerElement>(GetElement())->orientType()->CurrentEnumValue(); } AffineTransform LayoutSVGResourceMarker::MarkerTransformation( const MarkerPosition& position, float stroke_width) const { + CheckIsNotDestroyed(); // Apply scaling according to markerUnits ('strokeWidth' or 'userSpaceOnUse'.) float marker_scale = MarkerUnits() == kSVGMarkerUnitsStrokeWidth ? stroke_width : 1; @@ -120,6 +128,7 @@ } bool LayoutSVGResourceMarker::ShouldPaint() const { + CheckIsNotDestroyed(); // An empty viewBox disables rendering. auto* marker = To<SVGMarkerElement>(GetElement()); DCHECK(marker); @@ -129,6 +138,7 @@ } void LayoutSVGResourceMarker::SetNeedsTransformUpdate() { + CheckIsNotDestroyed(); // The transform paint property relies on the SVG transform being up-to-date // (see: PaintPropertyTreeBuilder::updateTransformForNonRootSVG). SetNeedsPaintPropertyUpdate(); @@ -137,6 +147,7 @@ SVGTransformChange LayoutSVGResourceMarker::CalculateLocalTransform( bool bounds_changed) { + CheckIsNotDestroyed(); if (!needs_transform_update_) return SVGTransformChange::kNone;
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_marker.h b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_marker.h index eadd407e..05e4c56 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_marker.h +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_marker.h
@@ -33,7 +33,10 @@ explicit LayoutSVGResourceMarker(SVGMarkerElement*); ~LayoutSVGResourceMarker() override; - const char* GetName() const override { return "LayoutSVGResourceMarker"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutSVGResourceMarker"; + } void RemoveAllClientsFromCache() override; @@ -45,13 +48,17 @@ float stroke_width) const; AffineTransform LocalToSVGParentTransform() const final { + CheckIsNotDestroyed(); return local_to_parent_transform_; } void SetNeedsTransformUpdate() final; // The viewport origin is (0,0) and not the reference point because each // marker instance includes the reference in markerTransformation(). - FloatRect Viewport() const { return FloatRect(FloatPoint(), viewport_size_); } + FloatRect Viewport() const { + CheckIsNotDestroyed(); + return FloatRect(FloatPoint(), viewport_size_); + } bool ShouldPaint() const; @@ -61,7 +68,10 @@ SVGMarkerOrientType OrientType() const; static const LayoutSVGResourceType kResourceType = kMarkerResourceType; - LayoutSVGResourceType ResourceType() const override { return kResourceType; } + LayoutSVGResourceType ResourceType() const override { + CheckIsNotDestroyed(); + return kResourceType; + } private: void UpdateLayout() override;
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_masker.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_masker.cc index 6e2b4b2..24daeec 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_masker.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_masker.cc
@@ -39,6 +39,7 @@ LayoutSVGResourceMasker::~LayoutSVGResourceMasker() = default; void LayoutSVGResourceMasker::RemoveAllClientsFromCache() { + CheckIsNotDestroyed(); cached_paint_record_.reset(); mask_content_boundaries_ = FloatRect(); MarkAllClientsForInvalidation(SVGResourceClient::kLayoutInvalidation | @@ -48,6 +49,7 @@ sk_sp<const PaintRecord> LayoutSVGResourceMasker::CreatePaintRecord( const AffineTransform& content_transformation, GraphicsContext& context) { + CheckIsNotDestroyed(); if (cached_paint_record_) return cached_paint_record_; @@ -74,6 +76,7 @@ } void LayoutSVGResourceMasker::CalculateMaskContentVisualRect() { + CheckIsNotDestroyed(); for (const SVGElement& child_element : Traversal<SVGElement>::ChildrenOf(*GetElement())) { const LayoutObject* layout_object = child_element.GetLayoutObject(); @@ -87,10 +90,12 @@ } SVGUnitTypes::SVGUnitType LayoutSVGResourceMasker::MaskUnits() const { + CheckIsNotDestroyed(); return To<SVGMaskElement>(GetElement())->maskUnits()->CurrentEnumValue(); } SVGUnitTypes::SVGUnitType LayoutSVGResourceMasker::MaskContentUnits() const { + CheckIsNotDestroyed(); return To<SVGMaskElement>(GetElement()) ->maskContentUnits() ->CurrentEnumValue(); @@ -99,6 +104,7 @@ FloatRect LayoutSVGResourceMasker::ResourceBoundingBox( const FloatRect& reference_box, float reference_box_zoom) { + CheckIsNotDestroyed(); auto* mask_element = To<SVGMaskElement>(GetElement()); DCHECK(mask_element);
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_masker.h b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_masker.h index fe02ae0..3f7ec68 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_masker.h +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_masker.h
@@ -36,7 +36,10 @@ explicit LayoutSVGResourceMasker(SVGMaskElement*); ~LayoutSVGResourceMasker() override; - const char* GetName() const override { return "LayoutSVGResourceMasker"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutSVGResourceMasker"; + } void RemoveAllClientsFromCache() override; @@ -47,7 +50,10 @@ SVGUnitTypes::SVGUnitType MaskContentUnits() const; static const LayoutSVGResourceType kResourceType = kMaskerResourceType; - LayoutSVGResourceType ResourceType() const override { return kResourceType; } + LayoutSVGResourceType ResourceType() const override { + CheckIsNotDestroyed(); + return kResourceType; + } sk_sp<const PaintRecord> CreatePaintRecord(const AffineTransform&, GraphicsContext&);
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_pattern.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_pattern.cc index 6944d12..5b1d2f107 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_pattern.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_pattern.cc
@@ -53,6 +53,7 @@ pattern_map_(MakeGarbageCollected<PatternMap>()) {} void LayoutSVGResourcePattern::RemoveAllClientsFromCache() { + CheckIsNotDestroyed(); pattern_map_->clear(); should_collect_pattern_attributes_ = true; MarkAllClientsForInvalidation(SVGResourceClient::kPaintInvalidation); @@ -60,6 +61,7 @@ bool LayoutSVGResourcePattern::RemoveClientFromCache( SVGResourceClient& client) { + CheckIsNotDestroyed(); auto entry = pattern_map_->find(&client); if (entry == pattern_map_->end()) return false; @@ -69,6 +71,7 @@ std::unique_ptr<PatternData> LayoutSVGResourcePattern::BuildPatternData( const FloatRect& object_bounding_box) { + CheckIsNotDestroyed(); auto pattern_data = std::make_unique<PatternData>(); DCHECK(GetElement()); @@ -135,6 +138,7 @@ SVGPaintServer LayoutSVGResourcePattern::PreparePaintServer( const SVGResourceClient& client, const FloatRect& object_bounding_box) { + CheckIsNotDestroyed(); ClearInvalidationMask(); std::unique_ptr<PatternData>& pattern_data = @@ -150,6 +154,7 @@ const LayoutSVGResourceContainer* LayoutSVGResourcePattern::ResolveContentElement() const { + CheckIsNotDestroyed(); DCHECK(Attributes().PatternContentElement()); LayoutSVGResourceContainer* expected_layout_object = ToLayoutSVGResourceContainer( @@ -179,6 +184,7 @@ sk_sp<PaintRecord> LayoutSVGResourcePattern::AsPaintRecord( const FloatSize& size, const AffineTransform& tile_transform) const { + CheckIsNotDestroyed(); DCHECK(!should_collect_pattern_attributes_); AffineTransform content_transform;
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_pattern.h b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_pattern.h index 4630fee..dd40d55 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_pattern.h +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_pattern.h
@@ -39,7 +39,10 @@ public: explicit LayoutSVGResourcePattern(SVGPatternElement*); - const char* GetName() const override { return "LayoutSVGResourcePattern"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutSVGResourcePattern"; + } void RemoveAllClientsFromCache() override; bool RemoveClientFromCache(SVGResourceClient&) override; @@ -49,7 +52,10 @@ const FloatRect& object_bounding_box) override; static const LayoutSVGResourceType kResourceType = kPatternResourceType; - LayoutSVGResourceType ResourceType() const override { return kResourceType; } + LayoutSVGResourceType ResourceType() const override { + CheckIsNotDestroyed(); + return kResourceType; + } private: std::unique_ptr<PatternData> BuildPatternData( @@ -63,9 +69,11 @@ Persistent<PatternAttributesWrapper> attributes_wrapper_; PatternAttributes& MutableAttributes() { + CheckIsNotDestroyed(); return attributes_wrapper_->Attributes(); } const PatternAttributes& Attributes() const { + CheckIsNotDestroyed(); return attributes_wrapper_->Attributes(); }
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_radial_gradient.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_radial_gradient.cc index bf85cc0..67e7b67 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_radial_gradient.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_radial_gradient.cc
@@ -35,6 +35,7 @@ LayoutSVGResourceRadialGradient::~LayoutSVGResourceRadialGradient() = default; void LayoutSVGResourceRadialGradient::CollectGradientAttributes() { + CheckIsNotDestroyed(); DCHECK(GetElement()); attributes_wrapper_->Set(RadialGradientAttributes()); To<SVGRadialGradientElement>(GetElement()) @@ -43,6 +44,7 @@ FloatPoint LayoutSVGResourceRadialGradient::CenterPoint( const RadialGradientAttributes& attributes) const { + CheckIsNotDestroyed(); return SVGLengthContext::ResolvePoint(GetElement(), attributes.GradientUnits(), *attributes.Cx(), *attributes.Cy()); @@ -50,6 +52,7 @@ FloatPoint LayoutSVGResourceRadialGradient::FocalPoint( const RadialGradientAttributes& attributes) const { + CheckIsNotDestroyed(); return SVGLengthContext::ResolvePoint(GetElement(), attributes.GradientUnits(), *attributes.Fx(), *attributes.Fy()); @@ -57,17 +60,20 @@ float LayoutSVGResourceRadialGradient::Radius( const RadialGradientAttributes& attributes) const { + CheckIsNotDestroyed(); return SVGLengthContext::ResolveLength( GetElement(), attributes.GradientUnits(), *attributes.R()); } float LayoutSVGResourceRadialGradient::FocalRadius( const RadialGradientAttributes& attributes) const { + CheckIsNotDestroyed(); return SVGLengthContext::ResolveLength( GetElement(), attributes.GradientUnits(), *attributes.Fr()); } scoped_refptr<Gradient> LayoutSVGResourceRadialGradient::BuildGradient() const { + CheckIsNotDestroyed(); const RadialGradientAttributes& attributes = Attributes(); scoped_refptr<Gradient> gradient = Gradient::CreateRadial( FocalPoint(attributes), FocalRadius(attributes), CenterPoint(attributes),
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_radial_gradient.h b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_radial_gradient.h index 4177123..44394005 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_radial_gradient.h +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_radial_gradient.h
@@ -34,17 +34,23 @@ ~LayoutSVGResourceRadialGradient() override; const char* GetName() const override { + CheckIsNotDestroyed(); return "LayoutSVGResourceRadialGradient"; } static const LayoutSVGResourceType kResourceType = kRadialGradientResourceType; - LayoutSVGResourceType ResourceType() const override { return kResourceType; } + LayoutSVGResourceType ResourceType() const override { + CheckIsNotDestroyed(); + return kResourceType; + } SVGUnitTypes::SVGUnitType GradientUnits() const override { + CheckIsNotDestroyed(); return Attributes().GradientUnits(); } AffineTransform CalculateGradientTransform() const override { + CheckIsNotDestroyed(); return Attributes().GradientTransform(); } void CollectGradientAttributes() override; @@ -59,9 +65,11 @@ Persistent<RadialGradientAttributesWrapper> attributes_wrapper_; RadialGradientAttributes& MutableAttributes() { + CheckIsNotDestroyed(); return attributes_wrapper_->Attributes(); } const RadialGradientAttributes& Attributes() const { + CheckIsNotDestroyed(); return attributes_wrapper_->Attributes(); } };
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc index fadff84..9abe8334 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc
@@ -76,6 +76,7 @@ void LayoutSVGRoot::UnscaledIntrinsicSizingInfo( IntrinsicSizingInfo& intrinsic_sizing_info) const { + CheckIsNotDestroyed(); // https://www.w3.org/TR/SVG/coords.html#IntrinsicSizing auto* svg = To<SVGSVGElement>(GetNode()); @@ -105,6 +106,7 @@ void LayoutSVGRoot::ComputeIntrinsicSizingInfo( IntrinsicSizingInfo& intrinsic_sizing_info) const { + CheckIsNotDestroyed(); DCHECK(!ShouldApplySizeContainment()); UnscaledIntrinsicSizingInfo(intrinsic_sizing_info); @@ -112,10 +114,12 @@ } bool LayoutSVGRoot::IsEmbeddedThroughSVGImage() const { + CheckIsNotDestroyed(); return SVGImage::IsInSVGImage(To<SVGSVGElement>(GetNode())); } bool LayoutSVGRoot::IsEmbeddedThroughFrameContainingSVGDocument() const { + CheckIsNotDestroyed(); if (!GetNode()) return false; @@ -135,6 +139,7 @@ LayoutUnit LayoutSVGRoot::ComputeReplacedLogicalWidth( ShouldComputePreferred should_compute_preferred) const { + CheckIsNotDestroyed(); // When we're embedded through SVGImage // (border-image/background-image/<html:img>/...) we're forced to resize to a // specific size. @@ -153,6 +158,7 @@ LayoutUnit LayoutSVGRoot::ComputeReplacedLogicalHeight( LayoutUnit estimated_used_width) const { + CheckIsNotDestroyed(); // When we're embedded through SVGImage // (border-image/background-image/<html:img>/...) we're forced to resize to a // specific size. @@ -176,6 +182,7 @@ } double LayoutSVGRoot::LogicalSizeScaleFactorForPercentageLengths() const { + CheckIsNotDestroyed(); if (!IsDocumentElement() || !GetDocument().IsInMainFrame()) return 1; if (GetDocument().GetLayoutView()->ShouldUsePrintingLayout()) @@ -189,6 +196,7 @@ } void LayoutSVGRoot::UpdateLayout() { + CheckIsNotDestroyed(); DCHECK(NeedsLayout()); LayoutAnalyzer::Scope analyzer(*this); @@ -271,6 +279,7 @@ } bool LayoutSVGRoot::ShouldApplyViewportClip() const { + CheckIsNotDestroyed(); // the outermost svg is clipped if auto, and svg document roots are always // clipped. When the svg is stand-alone (isDocumentElement() == true) the // viewport clipping should always be applied, noting that the window @@ -281,6 +290,7 @@ } void LayoutSVGRoot::RecalcVisualOverflow() { + CheckIsNotDestroyed(); LayoutReplaced::RecalcVisualOverflow(); UpdateCachedBoundaries(); if (!ShouldApplyViewportClip()) @@ -288,6 +298,7 @@ } LayoutRect LayoutSVGRoot::ComputeContentsVisualOverflow() const { + CheckIsNotDestroyed(); FloatRect content_visual_rect = VisualRectInLocalSVGCoordinates(); content_visual_rect = local_to_border_box_transform_.MapRect(content_visual_rect); @@ -302,18 +313,21 @@ void LayoutSVGRoot::PaintReplaced(const PaintInfo& paint_info, const PhysicalOffset& paint_offset) const { + CheckIsNotDestroyed(); if (ChildPaintBlockedByDisplayLock()) return; SVGRootPainter(*this).PaintReplaced(paint_info, paint_offset); } void LayoutSVGRoot::WillBeDestroyed() { + CheckIsNotDestroyed(); SVGResourcesCache::ClientDestroyed(*this); SVGResources::ClearClipPathFilterMask(To<SVGSVGElement>(*GetNode()), Style()); LayoutReplaced::WillBeDestroyed(); } bool LayoutSVGRoot::IntrinsicSizeIsFontMetricsDependent() const { + CheckIsNotDestroyed(); const auto& svg = To<SVGSVGElement>(*GetNode()); return svg.width()->CurrentValue()->IsFontRelative() || svg.height()->CurrentValue()->IsFontRelative(); @@ -321,6 +335,7 @@ bool LayoutSVGRoot::StyleChangeAffectsIntrinsicSize( const ComputedStyle& old_style) const { + CheckIsNotDestroyed(); const ComputedStyle& style = StyleRef(); // If the writing mode changed from a horizontal mode to a vertical // mode, or vice versa, then our intrinsic dimensions will have @@ -337,6 +352,7 @@ } void LayoutSVGRoot::IntrinsicSizingInfoChanged() { + CheckIsNotDestroyed(); SetIntrinsicLogicalWidthsDirty(); // TODO(fs): Merge with IntrinsicSizeChanged()? (from LayoutReplaced) @@ -350,6 +366,7 @@ void LayoutSVGRoot::StyleDidChange(StyleDifference diff, const ComputedStyle* old_style) { + CheckIsNotDestroyed(); if (diff.NeedsFullLayout()) SetNeedsBoundariesUpdate(); if (diff.NeedsPaintInvalidation()) { @@ -368,10 +385,12 @@ bool LayoutSVGRoot::IsChildAllowed(LayoutObject* child, const ComputedStyle&) const { + CheckIsNotDestroyed(); return child->IsSVG() && !(child->IsSVGInline() || child->IsSVGInlineText()); } void LayoutSVGRoot::AddChild(LayoutObject* child, LayoutObject* before_child) { + CheckIsNotDestroyed(); LayoutReplaced::AddChild(child, before_child); SVGResourcesCache::ClientWasAddedToTree(*child); @@ -383,6 +402,7 @@ } void LayoutSVGRoot::RemoveChild(LayoutObject* child) { + CheckIsNotDestroyed(); SVGResourcesCache::ClientWillBeRemovedFromTree(*child); LayoutReplaced::RemoveChild(child); @@ -394,6 +414,7 @@ } bool LayoutSVGRoot::HasNonIsolatedBlendingDescendants() const { + CheckIsNotDestroyed(); if (has_non_isolated_blending_descendants_dirty_) { has_non_isolated_blending_descendants_ = SVGLayoutSupport::ComputeHasNonIsolatedBlendingDescendants(this); @@ -404,6 +425,7 @@ void LayoutSVGRoot::DescendantIsolationRequirementsChanged( DescendantIsolationState state) { + CheckIsNotDestroyed(); switch (state) { case kDescendantIsolationRequired: has_non_isolated_blending_descendants_ = true; @@ -419,17 +441,20 @@ } void LayoutSVGRoot::InsertedIntoTree() { + CheckIsNotDestroyed(); LayoutReplaced::InsertedIntoTree(); SVGResourcesCache::ClientWasAddedToTree(*this); } void LayoutSVGRoot::WillBeRemovedFromTree() { + CheckIsNotDestroyed(); SVGResourcesCache::ClientWillBeRemovedFromTree(*this); LayoutReplaced::WillBeRemovedFromTree(); } PositionWithAffinity LayoutSVGRoot::PositionForPoint( const PhysicalOffset& point) const { + CheckIsNotDestroyed(); FloatPoint absolute_point = FloatPoint(point); absolute_point = local_to_border_box_transform_.Inverse().MapPoint(absolute_point); @@ -459,6 +484,7 @@ // LayoutBox methods will expect coordinates w/o any transforms in coordinates // relative to our borderBox origin. This method gives us exactly that. SVGTransformChange LayoutSVGRoot::BuildLocalToBorderBoxTransform() { + CheckIsNotDestroyed(); SVGTransformChangeDetector change_detector(local_to_border_box_transform_); auto* svg = To<SVGSVGElement>(GetNode()); DCHECK(svg); @@ -478,6 +504,7 @@ } AffineTransform LayoutSVGRoot::LocalToSVGParentTransform() const { + CheckIsNotDestroyed(); return AffineTransform::Translation(RoundToInt(Location().X()), RoundToInt(Location().Y())) * local_to_border_box_transform_; @@ -490,17 +517,20 @@ void LayoutSVGRoot::MapLocalToAncestor(const LayoutBoxModelObject* ancestor, TransformState& transform_state, MapCoordinatesFlags mode) const { + CheckIsNotDestroyed(); LayoutReplaced::MapLocalToAncestor(ancestor, transform_state, mode); } const LayoutObject* LayoutSVGRoot::PushMappingToContainer( const LayoutBoxModelObject* ancestor_to_stop_at, LayoutGeometryMap& geometry_map) const { + CheckIsNotDestroyed(); return LayoutReplaced::PushMappingToContainer(ancestor_to_stop_at, geometry_map); } void LayoutSVGRoot::UpdateCachedBoundaries() { + CheckIsNotDestroyed(); SVGLayoutSupport::ComputeContainerBoundingBoxes( this, object_bounding_box_, object_bounding_box_valid_, stroke_bounding_box_, visual_rect_in_local_svg_coordinates_); @@ -510,6 +540,7 @@ const HitTestLocation& hit_test_location, const PhysicalOffset& accumulated_offset, HitTestAction hit_test_action) { + CheckIsNotDestroyed(); HitTestLocation local_border_box_location(hit_test_location, -accumulated_offset); @@ -559,6 +590,7 @@ } void LayoutSVGRoot::NotifyDescendantCompositingReasonsChanged() { + CheckIsNotDestroyed(); if (has_descendant_with_compositing_reason_dirty_) return; has_descendant_with_compositing_reason_dirty_ = true; @@ -566,6 +598,7 @@ } PaintLayerType LayoutSVGRoot::LayerTypeRequired() const { + CheckIsNotDestroyed(); auto layer_type_required = LayoutReplaced::LayerTypeRequired(); if (layer_type_required == kNoPaintLayer) { // Force a paint layer so, @@ -579,6 +612,7 @@ } CompositingReasons LayoutSVGRoot::AdditionalCompositingReasons() const { + CheckIsNotDestroyed(); return RuntimeEnabledFeatures::CompositeSVGEnabled() && HasDescendantWithCompositingReason() ? CompositingReason::kSVGRoot @@ -586,6 +620,7 @@ } bool LayoutSVGRoot::HasDescendantWithCompositingReason() const { + CheckIsNotDestroyed(); if (has_descendant_with_compositing_reason_dirty_) { has_descendant_with_compositing_reason_ = false; for (const LayoutObject* object = FirstChild(); object;
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_root.h b/third_party/blink/renderer/core/layout/svg/layout_svg_root.h index 14e07d5..9c3f15a 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_root.h +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_root.h
@@ -46,27 +46,39 @@ void SlowLastChild() const = delete; LayoutObject* FirstChild() const { + CheckIsNotDestroyed(); DCHECK_EQ(Children(), VirtualChildren()); return Children()->FirstChild(); } LayoutObject* LastChild() const { + CheckIsNotDestroyed(); DCHECK_EQ(Children(), VirtualChildren()); return Children()->LastChild(); } - bool IsLayoutSizeChanged() const { return is_layout_size_changed_; } + bool IsLayoutSizeChanged() const { + CheckIsNotDestroyed(); + return is_layout_size_changed_; + } bool DidScreenScaleFactorChange() const { + CheckIsNotDestroyed(); return did_screen_scale_factor_change_; } void SetNeedsBoundariesUpdate() override { + CheckIsNotDestroyed(); needs_boundaries_or_transform_update_ = true; } void SetNeedsTransformUpdate() override { + CheckIsNotDestroyed(); needs_boundaries_or_transform_update_ = true; } - LayoutSize ContainerSize() const { return container_size_; } + LayoutSize ContainerSize() const { + CheckIsNotDestroyed(); + return container_size_; + } void SetContainerSize(const LayoutSize& container_size) { + CheckIsNotDestroyed(); // SVGImage::draw() does a view layout prior to painting, // and we need that layout to know of the new size otherwise // the layout may be incorrectly using the old size. @@ -80,6 +92,7 @@ // localToBorderBoxTransform maps local SVG viewport coordinates to local CSS // box coordinates. const AffineTransform& LocalToBorderBoxTransform() const { + CheckIsNotDestroyed(); return local_to_border_box_transform_; } @@ -90,27 +103,43 @@ bool HasNonIsolatedBlendingDescendants() const final; bool HasDescendantCompositingReasons() const { + CheckIsNotDestroyed(); return AdditionalCompositingReasons() != CompositingReason::kNone; } void NotifyDescendantCompositingReasonsChanged(); - const char* GetName() const override { return "LayoutSVGRoot"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutSVGRoot"; + } private: bool ComputeShouldClipOverflow() const override { + CheckIsNotDestroyed(); return LayoutBox::ComputeShouldClipOverflow() || ShouldApplyViewportClip(); } LayoutRect ComputeContentsVisualOverflow() const; - const LayoutObjectChildList* Children() const { return &children_; } - LayoutObjectChildList* Children() { return &children_; } + const LayoutObjectChildList* Children() const { + CheckIsNotDestroyed(); + return &children_; + } + LayoutObjectChildList* Children() { + CheckIsNotDestroyed(); + return &children_; + } - LayoutObjectChildList* VirtualChildren() override { return Children(); } + LayoutObjectChildList* VirtualChildren() override { + CheckIsNotDestroyed(); + return Children(); + } const LayoutObjectChildList* VirtualChildren() const override { + CheckIsNotDestroyed(); return Children(); } bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectSVG || type == kLayoutObjectSVGRoot || LayoutReplaced::IsOfType(type); } @@ -136,9 +165,16 @@ AffineTransform LocalToSVGParentTransform() const override; - FloatRect ObjectBoundingBox() const override { return object_bounding_box_; } - FloatRect StrokeBoundingBox() const override { return stroke_bounding_box_; } + FloatRect ObjectBoundingBox() const override { + CheckIsNotDestroyed(); + return object_bounding_box_; + } + FloatRect StrokeBoundingBox() const override { + CheckIsNotDestroyed(); + return stroke_bounding_box_; + } FloatRect VisualRectInLocalSVGCoordinates() const override { + CheckIsNotDestroyed(); return visual_rect_in_local_svg_coordinates_; } @@ -154,7 +190,10 @@ const LayoutBoxModelObject* ancestor_to_stop_at, LayoutGeometryMap&) const override; - bool CanHaveChildren() const override { return true; } + bool CanHaveChildren() const override { + CheckIsNotDestroyed(); + return true; + } void DescendantIsolationRequirementsChanged(DescendantIsolationState) final; @@ -171,7 +210,10 @@ double LogicalSizeScaleFactorForPercentageLengths() const; PaintLayerType LayerTypeRequired() const override; - bool CanHaveAdditionalCompositingReasons() const override { return true; } + bool CanHaveAdditionalCompositingReasons() const override { + CheckIsNotDestroyed(); + return true; + } CompositingReasons AdditionalCompositingReasons() const override; bool HasDescendantWithCompositingReason() const;
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_shape.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_shape.cc index f42c103..094c4cb 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_shape.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_shape.cc
@@ -65,6 +65,7 @@ void LayoutSVGShape::StyleDidChange(StyleDifference diff, const ComputedStyle* old_style) { + CheckIsNotDestroyed(); transform_uses_reference_box_ = TransformHelper::DependsOnReferenceBox(StyleRef()); LayoutSVGModelObject::StyleDidChange(diff, old_style); @@ -85,16 +86,19 @@ } void LayoutSVGShape::WillBeDestroyed() { + CheckIsNotDestroyed(); SVGResources::ClearPaints(*GetElement(), Style()); LayoutSVGModelObject::WillBeDestroyed(); } void LayoutSVGShape::ClearPath() { + CheckIsNotDestroyed(); path_.reset(); stroke_path_cache_.reset(); } void LayoutSVGShape::CreatePath() { + CheckIsNotDestroyed(); if (!path_) path_ = std::make_unique<Path>(); *path_ = To<SVGGeometryElement>(GetElement())->AsPath(); @@ -106,12 +110,14 @@ } float LayoutSVGShape::DashScaleFactor() const { + CheckIsNotDestroyed(); if (StyleRef().SvgStyle().StrokeDashArray()->data.IsEmpty()) return 1; return To<SVGGeometryElement>(*GetElement()).PathLengthScaleFactor(); } void LayoutSVGShape::UpdateShapeFromElement() { + CheckIsNotDestroyed(); CreatePath(); fill_bounding_box_ = GetPath().BoundingRect(); @@ -138,6 +144,7 @@ FloatRect LayoutSVGShape::ApproximateStrokeBoundingBox( const FloatRect& shape_bounds) const { + CheckIsNotDestroyed(); FloatRect stroke_box = shape_bounds; // Implementation of @@ -166,6 +173,7 @@ } FloatRect LayoutSVGShape::HitTestStrokeBoundingBox() const { + CheckIsNotDestroyed(); if (StyleRef().SvgStyle().HasStroke()) return stroke_bounding_box_; return ApproximateStrokeBoundingBox(fill_bounding_box_); @@ -173,6 +181,7 @@ bool LayoutSVGShape::ShapeDependentStrokeContains( const HitTestLocation& location) { + CheckIsNotDestroyed(); if (!stroke_path_cache_) { // In case the subclass didn't create path during UpdateShapeFromElement() // for optimization but still calls this method. @@ -212,12 +221,14 @@ bool LayoutSVGShape::ShapeDependentFillContains( const HitTestLocation& location, const WindRule fill_rule) const { + CheckIsNotDestroyed(); return GetPath().Contains(location.TransformedPoint(), fill_rule); } bool LayoutSVGShape::FillContains(const HitTestLocation& location, bool requires_fill, const WindRule fill_rule) { + CheckIsNotDestroyed(); if (!fill_bounding_box_.Contains(location.TransformedPoint())) return false; @@ -230,6 +241,7 @@ bool LayoutSVGShape::StrokeContains(const HitTestLocation& location, bool requires_stroke) { + CheckIsNotDestroyed(); // "A zero value causes no stroke to be painted." if (StyleRef().SvgStyle().StrokeWidth().IsZero()) return false; @@ -250,6 +262,7 @@ } void LayoutSVGShape::UpdateLayout() { + CheckIsNotDestroyed(); LayoutAnalyzer::Scope analyzer(*this); // Invalidate all resources of this client if our layout changed. @@ -308,6 +321,7 @@ } AffineTransform LayoutSVGShape::ComputeRootTransform() const { + CheckIsNotDestroyed(); const LayoutObject* root = this; while (root && !root->IsSVGRoot()) root = root->Parent(); @@ -315,6 +329,7 @@ } AffineTransform LayoutSVGShape::ComputeNonScalingStrokeTransform() const { + CheckIsNotDestroyed(); // Compute the CTM to the SVG root. This should probably be the CTM all the // way to the "canvas" of the page ("host" coordinate system), but with our // current approach of applying/painting non-scaling-stroke, that can break in @@ -332,6 +347,7 @@ } void LayoutSVGShape::UpdateNonScalingStrokeData() { + CheckIsNotDestroyed(); DCHECK(HasNonScalingStroke()); const AffineTransform transform = ComputeNonScalingStrokeTransform(); @@ -346,6 +362,7 @@ } void LayoutSVGShape::Paint(const PaintInfo& paint_info) const { + CheckIsNotDestroyed(); SVGShapePainter(*this).Paint(paint_info); } @@ -353,6 +370,7 @@ const HitTestLocation& hit_test_location, const PhysicalOffset& accumulated_offset, HitTestAction hit_test_action) { + CheckIsNotDestroyed(); DCHECK_EQ(accumulated_offset, PhysicalOffset()); // We only draw in the foreground phase, so we only hit-test then. if (hit_test_action != kHitTestForeground) @@ -388,6 +406,7 @@ bool LayoutSVGShape::HitTestShape(const HitTestRequest& request, const HitTestLocation& local_location, PointerEventsHitRules hit_rules) { + CheckIsNotDestroyed(); if (hit_rules.can_hit_bounding_box && local_location.Intersects(ObjectBoundingBox())) return true; @@ -409,6 +428,7 @@ } FloatRect LayoutSVGShape::CalculateStrokeBoundingBox() const { + CheckIsNotDestroyed(); if (!StyleRef().SvgStyle().HasStroke() || IsShapeEmpty()) return fill_bounding_box_; if (HasNonScalingStroke()) @@ -417,6 +437,7 @@ } FloatRect LayoutSVGShape::CalculateNonScalingStrokeBoundingBox() const { + CheckIsNotDestroyed(); DCHECK(path_); DCHECK(StyleRef().SvgStyle().HasStroke()); DCHECK(HasNonScalingStroke()); @@ -435,11 +456,13 @@ } float LayoutSVGShape::StrokeWidth() const { + CheckIsNotDestroyed(); SVGLengthContext length_context(GetElement()); return length_context.ValueForLength(StyleRef().SvgStyle().StrokeWidth()); } float LayoutSVGShape::StrokeWidthForMarkerUnits() const { + CheckIsNotDestroyed(); float stroke_width = StrokeWidth(); if (HasNonScalingStroke()) { const auto& non_scaling_transform = NonScalingStrokeTransform(); @@ -455,12 +478,14 @@ } LayoutSVGShapeRareData& LayoutSVGShape::EnsureRareData() const { + CheckIsNotDestroyed(); if (!rare_data_) rare_data_ = std::make_unique<LayoutSVGShapeRareData>(); return *rare_data_.get(); } RasterEffectOutset LayoutSVGShape::VisualRectOutsetForRasterEffects() const { + CheckIsNotDestroyed(); // Account for raster expansions due to SVG stroke hairline raster effects. if (StyleRef().SvgStyle().HasVisibleStroke()) { if (StyleRef().SvgStyle().CapStyle() != kButtCap)
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_shape.h b/third_party/blink/renderer/core/layout/svg/layout_svg_shape.h index db4452a..fed395c 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_shape.h +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_shape.h
@@ -59,15 +59,28 @@ public: ~LayoutSVGShape() override; - void SetNeedsShapeUpdate() { needs_shape_update_ = true; } - void SetNeedsBoundariesUpdate() final { needs_boundaries_update_ = true; } - void SetNeedsTransformUpdate() final { needs_transform_update_ = true; } + void SetNeedsShapeUpdate() { + CheckIsNotDestroyed(); + needs_shape_update_ = true; + } + void SetNeedsBoundariesUpdate() final { + CheckIsNotDestroyed(); + needs_boundaries_update_ = true; + } + void SetNeedsTransformUpdate() final { + CheckIsNotDestroyed(); + needs_transform_update_ = true; + } Path& GetPath() const { + CheckIsNotDestroyed(); DCHECK(path_); return *path_; } - bool HasPath() const { return path_.get(); } + bool HasPath() const { + CheckIsNotDestroyed(); + return path_.get(); + } float DashScaleFactor() const; // This method is sometimes (rarely) called with a null path and crashes. The @@ -75,19 +88,23 @@ // path but somehow that fails. The assert and check for hasPath() are // intended to detect and prevent crashes. virtual bool IsShapeEmpty() const { + CheckIsNotDestroyed(); DCHECK(path_); return !HasPath() || GetPath().IsEmpty(); } bool HasNonScalingStroke() const { + CheckIsNotDestroyed(); return StyleRef().SvgStyle().VectorEffect() == VE_NON_SCALING_STROKE; } const Path& NonScalingStrokePath() const { + CheckIsNotDestroyed(); DCHECK(HasNonScalingStroke()); DCHECK(rare_data_); return rare_data_->non_scaling_stroke_path_; } const AffineTransform& NonScalingStrokeTransform() const { + CheckIsNotDestroyed(); DCHECK(HasNonScalingStroke()); DCHECK(rare_data_); return rare_data_->non_scaling_stroke_transform_; @@ -95,9 +112,13 @@ AffineTransform ComputeRootTransform() const; AffineTransform ComputeNonScalingStrokeTransform() const; - AffineTransform LocalSVGTransform() const final { return local_transform_; } + AffineTransform LocalSVGTransform() const final { + CheckIsNotDestroyed(); + return local_transform_; + } virtual const Vector<MarkerPosition>* MarkerPositions() const { + CheckIsNotDestroyed(); return nullptr; } @@ -105,12 +126,19 @@ float StrokeWidthForMarkerUnits() const; virtual ShapeGeometryCodePath GeometryCodePath() const { + CheckIsNotDestroyed(); return kPathGeometry; } - FloatRect ObjectBoundingBox() const final { return fill_bounding_box_; } + FloatRect ObjectBoundingBox() const final { + CheckIsNotDestroyed(); + return fill_bounding_box_; + } - const char* GetName() const override { return "LayoutSVGShape"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutSVGShape"; + } protected: // Description of the geometry of the shape for stroking. @@ -155,6 +183,7 @@ bool StrokeContains(const HitTestLocation&, bool requires_stroke = true); bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectSVGShape || LayoutSVGModelObject::IsOfType(type); } @@ -169,7 +198,10 @@ const HitTestLocation&, PointerEventsHitRules); - FloatRect StrokeBoundingBox() const final { return stroke_bounding_box_; } + FloatRect StrokeBoundingBox() const final { + CheckIsNotDestroyed(); + return stroke_bounding_box_; + } // Calculates an inclusive bounding box of this shape as if this shape has a // stroke. If this shape has a stroke, then |stroke_bounding_box_| is
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_text.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_text.cc index 9c995b69..61fdd32 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_text.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_text.cc
@@ -75,11 +75,13 @@ void LayoutSVGText::StyleDidChange(StyleDifference diff, const ComputedStyle* old_style) { + CheckIsNotDestroyed(); LayoutSVGBlock::StyleDidChange(diff, old_style); SVGResources::UpdatePaints(*GetElement(), old_style, StyleRef()); } void LayoutSVGText::WillBeDestroyed() { + CheckIsNotDestroyed(); descendant_text_nodes_.clear(); SVGResources::ClearPaints(*GetElement(), Style()); LayoutSVGBlock::WillBeDestroyed(); @@ -87,6 +89,7 @@ bool LayoutSVGText::IsChildAllowed(LayoutObject* child, const ComputedStyle&) const { + CheckIsNotDestroyed(); return child->IsSVGInline() || (child->IsText() && SVGLayoutSupport::IsLayoutableTextNode(child)); } @@ -112,6 +115,7 @@ void LayoutSVGText::SubtreeStructureChanged( LayoutInvalidationReasonForTracing reason) { + CheckIsNotDestroyed(); if (BeingDestroyed() || !EverHadLayout()) { DCHECK(descendant_text_nodes_.IsEmpty()); return; @@ -159,6 +163,7 @@ } void LayoutSVGText::UpdateLayout() { + CheckIsNotDestroyed(); DCHECK(NeedsLayout()); // This flag is set and reset as needed only within this function. DCHECK(!needs_reordering_); @@ -274,6 +279,7 @@ } void LayoutSVGText::RecalcVisualOverflow() { + CheckIsNotDestroyed(); ClearVisualOverflow(); LayoutObject::RecalcVisualOverflow(); AddSelfVisualOverflow(LayoutRect(ObjectBoundingBox())); @@ -281,6 +287,7 @@ } RootInlineBox* LayoutSVGText::CreateRootInlineBox() { + CheckIsNotDestroyed(); RootInlineBox* box = new SVGRootInlineBox(LineLayoutItem(this)); box->SetHasVirtualLogicalHeight(); return box; @@ -290,6 +297,7 @@ const HitTestLocation& hit_test_location, const PhysicalOffset& accumulated_offset, HitTestAction hit_test_action) { + CheckIsNotDestroyed(); DCHECK_EQ(accumulated_offset, PhysicalOffset()); // We only draw in the foreground phase, so we only hit-test then. if (hit_test_action != kHitTestForeground) @@ -323,6 +331,7 @@ PositionWithAffinity LayoutSVGText::PositionForPoint( const PhysicalOffset& point_in_contents) const { + CheckIsNotDestroyed(); RootInlineBox* root_box = FirstRootBox(); if (!root_box) return CreatePositionWithAffinity(0); @@ -347,26 +356,31 @@ void LayoutSVGText::AbsoluteQuads(Vector<FloatQuad>& quads, MapCoordinatesFlags mode) const { + CheckIsNotDestroyed(); quads.push_back(LocalToAbsoluteQuad(StrokeBoundingBox(), mode)); } void LayoutSVGText::Paint(const PaintInfo& paint_info) const { + CheckIsNotDestroyed(); SVGTextPainter(*this).Paint(paint_info); } FloatRect LayoutSVGText::ObjectBoundingBox() const { + CheckIsNotDestroyed(); if (const RootInlineBox* box = FirstRootBox()) return FloatRect(box->FrameRect()); return FloatRect(); } FloatRect LayoutSVGText::StrokeBoundingBox() const { + CheckIsNotDestroyed(); if (!FirstRootBox()) return FloatRect(); return SVGLayoutSupport::ExtendTextBBoxWithStroke(*this, ObjectBoundingBox()); } FloatRect LayoutSVGText::VisualRectInLocalSVGCoordinates() const { + CheckIsNotDestroyed(); if (!FirstRootBox()) return FloatRect(); const FloatRect object_bounds = ObjectBoundingBox(); @@ -377,15 +391,18 @@ void LayoutSVGText::AddOutlineRects(Vector<PhysicalRect>& rects, const PhysicalOffset&, NGOutlineType) const { + CheckIsNotDestroyed(); rects.push_back(PhysicalRect::EnclosingRect(ObjectBoundingBox())); } bool LayoutSVGText::IsObjectBoundingBoxValid() const { + CheckIsNotDestroyed(); // If we don't have any line boxes, then consider the bbox invalid. return FirstLineBox(); } void LayoutSVGText::AddChild(LayoutObject* child, LayoutObject* before_child) { + CheckIsNotDestroyed(); LayoutSVGBlock::AddChild(child, before_child); SVGResourcesCache::ClientWasAddedToTree(*child); @@ -393,6 +410,7 @@ } void LayoutSVGText::RemoveChild(LayoutObject* child) { + CheckIsNotDestroyed(); SVGResourcesCache::ClientWillBeRemovedFromTree(*child); SubtreeStructureChanged(layout_invalidation_reason::kChildChanged);
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_text.h b/third_party/blink/renderer/core/layout/svg/layout_svg_text.h index b0478f6..087fdd634 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_text.h +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_text.h
@@ -37,9 +37,13 @@ bool IsChildAllowed(LayoutObject*, const ComputedStyle&) const override; void SetNeedsPositioningValuesUpdate() { + CheckIsNotDestroyed(); needs_positioning_values_update_ = true; } - void SetNeedsTextMetricsUpdate() { needs_text_metrics_update_ = true; } + void SetNeedsTextMetricsUpdate() { + CheckIsNotDestroyed(); + needs_text_metrics_update_ = true; + } FloatRect VisualRectInLocalSVGCoordinates() const override; FloatRect ObjectBoundingBox() const override; FloatRect StrokeBoundingBox() const override; @@ -55,19 +59,30 @@ static void NotifySubtreeStructureChanged(LayoutObject*, LayoutInvalidationReasonForTracing); - bool NeedsReordering() const { return needs_reordering_; } + bool NeedsReordering() const { + CheckIsNotDestroyed(); + return needs_reordering_; + } const Vector<LayoutSVGInlineText*>& DescendantTextNodes() const { + CheckIsNotDestroyed(); return descendant_text_nodes_; } void RecalcVisualOverflow() override; - const char* GetName() const override { return "LayoutSVGText"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutSVGText"; + } private: - bool AllowsNonVisibleOverflow() const override { return false; } + bool AllowsNonVisibleOverflow() const override { + CheckIsNotDestroyed(); + return false; + } bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectSVGText || LayoutSVGBlock::IsOfType(type); }
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_text_path.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_text_path.cc index d3035ebf..6ab1238f 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_text_path.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_text_path.cc
@@ -54,6 +54,7 @@ bool LayoutSVGTextPath::IsChildAllowed(LayoutObject* child, const ComputedStyle&) const { + CheckIsNotDestroyed(); if (child->IsText()) return SVGLayoutSupport::IsLayoutableTextNode(child); @@ -61,6 +62,7 @@ } std::unique_ptr<PathPositionMapper> LayoutSVGTextPath::LayoutPath() const { + CheckIsNotDestroyed(); const auto& text_path_element = To<SVGTextPathElement>(*GetNode()); Element* target_element = SVGURIReference::TargetElementFromIRIString( text_path_element.HrefString(), text_path_element.OriginatingTreeScope());
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_text_path.h b/third_party/blink/renderer/core/layout/svg/layout_svg_text_path.h index 92ccd99..523981a1 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_text_path.h +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_text_path.h
@@ -63,10 +63,14 @@ bool IsChildAllowed(LayoutObject*, const ComputedStyle&) const override; bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectSVGTextPath || LayoutSVGInline::IsOfType(type); } - const char* GetName() const override { return "LayoutSVGTextPath"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutSVGTextPath"; + } }; DEFINE_LAYOUT_OBJECT_TYPE_CASTS(LayoutSVGTextPath, IsSVGTextPath());
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_transformable_container.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_transformable_container.cc index 5ea8c6cc..254ec7d 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_transformable_container.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_transformable_container.cc
@@ -48,6 +48,7 @@ bool LayoutSVGTransformableContainer::IsChildAllowed( LayoutObject* child, const ComputedStyle& style) const { + CheckIsNotDestroyed(); DCHECK(GetElement()); Node* child_node = child->GetNode(); if (IsA<SVGSwitchElement>(*GetElement())) { @@ -72,6 +73,7 @@ } void LayoutSVGTransformableContainer::SetNeedsTransformUpdate() { + CheckIsNotDestroyed(); // The transform paint property relies on the SVG transform being up-to-date // (see: PaintPropertyTreeBuilder::updateTransformForNonRootSVG). SetNeedsPaintPropertyUpdate(); @@ -79,6 +81,7 @@ } bool LayoutSVGTransformableContainer::IsUseElement() const { + CheckIsNotDestroyed(); const SVGElement& element = *GetElement(); if (IsA<SVGUseElement>(element)) return true; @@ -90,6 +93,7 @@ SVGTransformChange LayoutSVGTransformableContainer::CalculateLocalTransform( bool bounds_changed) { + CheckIsNotDestroyed(); SVGElement* element = GetElement(); DCHECK(element); @@ -129,6 +133,7 @@ void LayoutSVGTransformableContainer::StyleDidChange( StyleDifference diff, const ComputedStyle* old_style) { + CheckIsNotDestroyed(); transform_uses_reference_box_ = TransformHelper::DependsOnReferenceBox(StyleRef()); LayoutSVGContainer::StyleDidChange(diff, old_style);
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_transformable_container.h b/third_party/blink/renderer/core/layout/svg/layout_svg_transformable_container.h index 347cf8b..f20099c 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_transformable_container.h +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_transformable_container.h
@@ -34,10 +34,12 @@ bool IsChildAllowed(LayoutObject*, const ComputedStyle&) const override; bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectSVGTransformableContainer || LayoutSVGContainer::IsOfType(type); } const FloatSize& AdditionalTranslation() const { + CheckIsNotDestroyed(); return additional_translation_; } @@ -47,6 +49,7 @@ void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override; SVGTransformChange CalculateLocalTransform(bool bounds_changed) override; AffineTransform LocalSVGTransform() const override { + CheckIsNotDestroyed(); return local_transform_; } bool IsUseElement() const;
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_tspan.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_tspan.cc index c05deb4..fda6cf1 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_tspan.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_tspan.cc
@@ -30,6 +30,7 @@ bool LayoutSVGTSpan::IsChildAllowed(LayoutObject* child, const ComputedStyle&) const { + CheckIsNotDestroyed(); // Always allow text (except empty textnodes and <br>). if (child->IsText()) return SVGLayoutSupport::IsLayoutableTextNode(child);
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_tspan.h b/third_party/blink/renderer/core/layout/svg/layout_svg_tspan.h index f25019e1..1c9a2524 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_tspan.h +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_tspan.h
@@ -31,7 +31,10 @@ bool IsChildAllowed(LayoutObject*, const ComputedStyle&) const override; - const char* GetName() const override { return "LayoutSVGTSpan"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutSVGTSpan"; + } }; }
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.cc index 97c01f49..f57ad79 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.cc
@@ -36,6 +36,7 @@ needs_transform_update_(true) {} void LayoutSVGViewportContainer::UpdateLayout() { + CheckIsNotDestroyed(); DCHECK(NeedsLayout()); const auto* svg = To<SVGSVGElement>(GetElement()); @@ -59,6 +60,7 @@ } void LayoutSVGViewportContainer::SetNeedsTransformUpdate() { + CheckIsNotDestroyed(); // The transform paint property relies on the SVG transform being up-to-date // (see: PaintPropertyTreeBuilder::updateTransformForNonRootSVG). SetNeedsPaintPropertyUpdate(); @@ -67,6 +69,7 @@ SVGTransformChange LayoutSVGViewportContainer::CalculateLocalTransform( bool bounds_changed) { + CheckIsNotDestroyed(); if (!needs_transform_update_) return SVGTransformChange::kNone; @@ -84,6 +87,7 @@ const HitTestLocation& hit_test_location, const PhysicalOffset& accumulated_offset, HitTestAction action) { + CheckIsNotDestroyed(); // Respect the viewport clip which is in parent coordinates. if (SVGLayoutSupport::IsOverflowHidden(*this)) { if (!hit_test_location.Intersects(viewport_)) @@ -96,6 +100,7 @@ void LayoutSVGViewportContainer::StyleDidChange( StyleDifference diff, const ComputedStyle* old_style) { + CheckIsNotDestroyed(); LayoutSVGContainer::StyleDidChange(diff, old_style); if (old_style && (SVGLayoutSupport::IsOverflowHidden(*old_style) !=
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.h b/third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.h index 9835f9be..3c121f9 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.h +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.h
@@ -34,20 +34,31 @@ class LayoutSVGViewportContainer final : public LayoutSVGContainer { public: explicit LayoutSVGViewportContainer(SVGSVGElement*); - FloatRect Viewport() const { return viewport_; } + FloatRect Viewport() const { + CheckIsNotDestroyed(); + return viewport_; + } - bool IsLayoutSizeChanged() const { return is_layout_size_changed_; } + bool IsLayoutSizeChanged() const { + CheckIsNotDestroyed(); + return is_layout_size_changed_; + } void SetNeedsTransformUpdate() override; - const char* GetName() const override { return "LayoutSVGViewportContainer"; } + const char* GetName() const override { + CheckIsNotDestroyed(); + return "LayoutSVGViewportContainer"; + } AffineTransform LocalToSVGParentTransform() const override { + CheckIsNotDestroyed(); return local_to_parent_transform_; } private: bool IsOfType(LayoutObjectType type) const override { + CheckIsNotDestroyed(); return type == kLayoutObjectSVGViewportContainer || LayoutSVGContainer::IsOfType(type); }
diff --git a/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc b/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc index 026281b..e0f4822 100644 --- a/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc +++ b/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc
@@ -155,12 +155,12 @@ if (RuntimeEnabledFeatures::SignedExchangeSubresourcePrefetchEnabled( document_->GetExecutionContext()) && - resource->LastResourceResponse()) { + resource->RedirectChainSize() > 0) { // See if the outer response (which must be the last response in // the redirect chain) had provided alternate links for the prefetch. alternate_resource_info = AlternateSignedExchangeResourceInfo::CreateIfValid( - resource->LastResourceResponse()->HttpHeaderField( + resource->LastResourceResponse().HttpHeaderField( http_names::kLink), response.HttpHeaderField(http_names::kLink)); }
diff --git a/third_party/blink/renderer/core/script/classic_pending_script.h b/third_party/blink/renderer/core/script/classic_pending_script.h index bb2a8ec..eaf1500 100644 --- a/third_party/blink/renderer/core/script/classic_pending_script.h +++ b/third_party/blink/renderer/core/script/classic_pending_script.h
@@ -58,8 +58,8 @@ void Trace(Visitor*) const override; - mojom::ScriptType GetScriptType() const override { - return mojom::ScriptType::kClassic; + mojom::blink::ScriptType GetScriptType() const override { + return mojom::blink::ScriptType::kClassic; } ClassicScript* GetSource(const KURL& document_url) const override;
diff --git a/third_party/blink/renderer/core/script/classic_script.h b/third_party/blink/renderer/core/script/classic_script.h index 309ba7f..ea0ccbd 100644 --- a/third_party/blink/renderer/core/script/classic_script.h +++ b/third_party/blink/renderer/core/script/classic_script.h
@@ -62,8 +62,8 @@ int32_t world_id); private: - mojom::ScriptType GetScriptType() const override { - return mojom::ScriptType::kClassic; + mojom::blink::ScriptType GetScriptType() const override { + return mojom::blink::ScriptType::kClassic; } std::pair<size_t, size_t> GetClassicScriptSizes() const override;
diff --git a/third_party/blink/renderer/core/script/module_pending_script.h b/third_party/blink/renderer/core/script/module_pending_script.h index d128a3a..73805e5 100644 --- a/third_party/blink/renderer/core/script/module_pending_script.h +++ b/third_party/blink/renderer/core/script/module_pending_script.h
@@ -59,8 +59,8 @@ private: // PendingScript - mojom::ScriptType GetScriptType() const override { - return mojom::ScriptType::kModule; + mojom::blink::ScriptType GetScriptType() const override { + return mojom::blink::ScriptType::kModule; } Script* GetSource(const KURL& document_url) const override; bool IsReady() const override { return ready_; }
diff --git a/third_party/blink/renderer/core/script/module_script.h b/third_party/blink/renderer/core/script/module_script.h index 646a00c..4147915 100644 --- a/third_party/blink/renderer/core/script/module_script.h +++ b/third_party/blink/renderer/core/script/module_script.h
@@ -64,8 +64,8 @@ Modulator* SettingsObject() const { return settings_object_; } private: - mojom::ScriptType GetScriptType() const override { - return mojom::ScriptType::kModule; + mojom::blink::ScriptType GetScriptType() const override { + return mojom::blink::ScriptType::kModule; } void RunScript(LocalFrame*) override; bool RunScriptOnWorkerOrWorklet(WorkerOrWorkletGlobalScope&) override;
diff --git a/third_party/blink/renderer/core/script/pending_script.cc b/third_party/blink/renderer/core/script/pending_script.cc index 9787590..ba76932 100644 --- a/third_party/blink/renderer/core/script/pending_script.cc +++ b/third_party/blink/renderer/core/script/pending_script.cc
@@ -246,7 +246,7 @@ // <spec step="4.B.1">Assert: The script element's node document's // currentScript attribute is null.</spec> ScriptElementBase* current_script = nullptr; - if (script->GetScriptType() == mojom::ScriptType::kClassic) + if (script->GetScriptType() == mojom::blink::ScriptType::kClassic) current_script = element; context_document->PushCurrentScript(current_script);
diff --git a/third_party/blink/renderer/core/script/pending_script.h b/third_party/blink/renderer/core/script/pending_script.h index 206c9d97..5b448694 100644 --- a/third_party/blink/renderer/core/script/pending_script.h +++ b/third_party/blink/renderer/core/script/pending_script.h
@@ -83,7 +83,7 @@ ScriptElementBase* GetElement() const; - virtual mojom::ScriptType GetScriptType() const = 0; + virtual mojom::blink::ScriptType GetScriptType() const = 0; virtual void Trace(Visitor*) const; const char* NameInHeapSnapshot() const override { return "PendingScript"; } @@ -104,7 +104,7 @@ // Used for DCHECK()s. bool IsExternalOrModule() const { - return IsExternal() || GetScriptType() == mojom::ScriptType::kModule; + return IsExternal() || GetScriptType() == mojom::blink::ScriptType::kModule; } void Dispose();
diff --git a/third_party/blink/renderer/core/script/script.cc b/third_party/blink/renderer/core/script/script.cc index bfa6a5f..3c2f207 100644 --- a/third_party/blink/renderer/core/script/script.cc +++ b/third_party/blink/renderer/core/script/script.cc
@@ -8,12 +8,12 @@ namespace blink { -base::Optional<mojom::ScriptType> Script::ParseScriptType( +base::Optional<mojom::blink::ScriptType> Script::ParseScriptType( const String& script_type) { if (script_type == "classic") - return mojom::ScriptType::kClassic; + return mojom::blink::ScriptType::kClassic; if (script_type == "module") - return mojom::ScriptType::kModule; + return mojom::blink::ScriptType::kModule; return base::nullopt; }
diff --git a/third_party/blink/renderer/core/script/script.h b/third_party/blink/renderer/core/script/script.h index 3d19ef8..05ec402b 100644 --- a/third_party/blink/renderer/core/script/script.h +++ b/third_party/blink/renderer/core/script/script.h
@@ -25,8 +25,8 @@ virtual ~Script() {} - virtual mojom::ScriptType GetScriptType() const = 0; - static base::Optional<mojom::ScriptType> ParseScriptType( + virtual mojom::blink::ScriptType GetScriptType() const = 0; + static base::Optional<mojom::blink::ScriptType> ParseScriptType( const String& script_type); // https://html.spec.whatwg.org/C/#run-a-classic-script
diff --git a/third_party/blink/renderer/core/script/script_loader.cc b/third_party/blink/renderer/core/script/script_loader.cc index 5da944d6..59234b5 100644 --- a/third_party/blink/renderer/core/script/script_loader.cc +++ b/third_party/blink/renderer/core/script/script_loader.cc
@@ -194,7 +194,7 @@ const String& type, const String& language, LegacyTypeSupport support_legacy_types, - mojom::ScriptType* out_script_type, + mojom::blink::ScriptType* out_script_type, bool* out_is_import_map) { if (IsValidClassicScriptTypeAndLanguage(type, language, support_legacy_types)) { @@ -203,7 +203,7 @@ // // TODO(hiroshige): Annotate and/or cleanup this step. if (out_script_type) - *out_script_type = mojom::ScriptType::kClassic; + *out_script_type = mojom::blink::ScriptType::kClassic; if (out_is_import_map) *out_is_import_map = false; return true; @@ -214,7 +214,7 @@ // case-insensitive match for the string "module", the script's type is // "module". ...</spec> if (out_script_type) - *out_script_type = mojom::ScriptType::kModule; + *out_script_type = mojom::blink::ScriptType::kModule; if (out_is_import_map) *out_is_import_map = false; return true; @@ -231,9 +231,9 @@ return false; } -bool ScriptLoader::BlockForNoModule(mojom::ScriptType script_type, +bool ScriptLoader::BlockForNoModule(mojom::blink::ScriptType script_type, bool nomodule) { - return nomodule && script_type == mojom::ScriptType::kClassic; + return nomodule && script_type == mojom::blink::ScriptType::kClassic; } // Corresponds to @@ -258,16 +258,17 @@ } // https://github.com/w3c/webappsec-permissions-policy/issues/135 -bool ShouldBlockSyncScriptForDocumentPolicy(const ScriptElementBase* element, - mojom::ScriptType script_type, - bool parser_inserted) { +bool ShouldBlockSyncScriptForDocumentPolicy( + const ScriptElementBase* element, + mojom::blink::ScriptType script_type, + bool parser_inserted) { if (element->GetExecutionContext()->IsFeatureEnabled( mojom::blink::DocumentPolicyFeature::kSyncScript)) { return false; } // Module scripts never block parsing. - if (script_type == mojom::ScriptType::kModule || !parser_inserted) + if (script_type == mojom::blink::ScriptType::kModule || !parser_inserted) return false; if (!element->HasSourceAttribute()) @@ -476,7 +477,7 @@ ParserDisposition parser_state = IsParserInserted() ? kParserInserted : kNotParserInserted; - if (GetScriptType() == mojom::ScriptType::kModule) + if (GetScriptType() == mojom::blink::ScriptType::kModule) UseCounter::Count(*context_window, WebFeature::kPrepareModuleScript); DCHECK(!prepared_pending_script_); @@ -567,7 +568,7 @@ return false; } - if (GetScriptType() == mojom::ScriptType::kClassic) { + if (GetScriptType() == mojom::blink::ScriptType::kClassic) { // - "classic": // <spec step="15">If the script element has a charset attribute, then let @@ -661,7 +662,7 @@ switch (GetScriptType()) { // <spec step="25.2.A">"classic"</spec> - case mojom::ScriptType::kClassic: { + case mojom::blink::ScriptType::kClassic: { // <spec step="25.2.A.1">Let script be the result of creating a classic // script using source text, settings object, base URL, and // options.</spec> @@ -689,7 +690,7 @@ } // <spec step="25.2.B">"module"</spec> - case mojom::ScriptType::kModule: { + case mojom::blink::ScriptType::kModule: { // <spec step="25.2.B.1">Fetch an inline module script graph, given // source text, base URL, settings object, and options. When this // asynchronously completes, set the script's script to the result. At @@ -753,11 +754,11 @@ // If the script's type is "module", and the element has been flagged as // "parser-inserted", and the element does not have an async attribute // ...</spec> - if ((GetScriptType() == mojom::ScriptType::kClassic && + if ((GetScriptType() == mojom::blink::ScriptType::kClassic && element_->HasSourceAttribute() && element_->DeferAttributeValue() && parser_inserted_ && !element_->AsyncAttributeValue()) || - (GetScriptType() == mojom::ScriptType::kModule && parser_inserted_ && - !element_->AsyncAttributeValue())) { + (GetScriptType() == mojom::blink::ScriptType::kModule && + parser_inserted_ && !element_->AsyncAttributeValue())) { // This clause is implemented by the caller-side of prepareScript(): // - HTMLParserScriptRunner::requestDeferredScript(), and // - TODO(hiroshige): Investigate XMLDocumentParser::endElementNs() @@ -768,7 +769,7 @@ } // Check for external script that should be force deferred. - if (GetScriptType() == mojom::ScriptType::kClassic && + if (GetScriptType() == mojom::blink::ScriptType::kClassic && element_->HasSourceAttribute() && context_window->GetFrame()->ShouldForceDeferScript() && IsA<HTMLDocument>(context_window->document()) && parser_inserted_ && @@ -789,7 +790,7 @@ // <spec step="26.B">If the script's type is "classic", and the element has a // src attribute, and the element has been flagged as "parser-inserted", and // the element does not have an async attribute ...</spec> - if (GetScriptType() == mojom::ScriptType::kClassic && + if (GetScriptType() == mojom::blink::ScriptType::kClassic && element_->HasSourceAttribute() && parser_inserted_ && !element_->AsyncAttributeValue()) { // This clause is implemented by the caller-side of prepareScript(): @@ -807,10 +808,10 @@ // If the script's type is "module", and the element does not have an async // attribute, and the element does not have the "non-blocking" flag set // ...</spec> - if ((GetScriptType() == mojom::ScriptType::kClassic && + if ((GetScriptType() == mojom::blink::ScriptType::kClassic && element_->HasSourceAttribute() && !element_->AsyncAttributeValue() && !non_blocking_) || - (GetScriptType() == mojom::ScriptType::kModule && + (GetScriptType() == mojom::blink::ScriptType::kModule && !element_->AsyncAttributeValue() && !non_blocking_)) { // <spec step="26.C">... Add the element to the end of the list of scripts // that will execute in order as soon as possible associated with the node @@ -834,9 +835,9 @@ // src attribute // // If the script's type is "module" ...</spec> - if ((GetScriptType() == mojom::ScriptType::kClassic && + if ((GetScriptType() == mojom::blink::ScriptType::kClassic && element_->HasSourceAttribute()) || - GetScriptType() == mojom::ScriptType::kModule) { + GetScriptType() == mojom::blink::ScriptType::kModule) { // <spec step="26.D">... The element must be added to the set of scripts // that will execute as soon as possible of the node document of the script // element at the time the prepare a script algorithm started. When the @@ -860,7 +861,7 @@ // The following clauses are executed only if the script's type is "classic" // and the element doesn't have a src attribute. - DCHECK_EQ(GetScriptType(), mojom::ScriptType::kClassic); + DCHECK_EQ(GetScriptType(), mojom::blink::ScriptType::kClassic); DCHECK(!is_external_script_); // Check for inline script that should be force deferred. @@ -1013,7 +1014,7 @@ // <spec step="14">If the script element has an event attribute and a for // attribute, and the script's type is "classic", then:</spec> - if (GetScriptType() != mojom::ScriptType::kClassic || + if (GetScriptType() != mojom::blink::ScriptType::kClassic || event_attribute.IsNull() || for_attribute.IsNull()) return true;
diff --git a/third_party/blink/renderer/core/script/script_loader.h b/third_party/blink/renderer/core/script/script_loader.h index dddfeb9..9a2d1c5 100644 --- a/third_party/blink/renderer/core/script/script_loader.h +++ b/third_party/blink/renderer/core/script/script_loader.h
@@ -62,18 +62,18 @@ }; // |out_is_import_map| is set separately from |out_script_type| in order - // to avoid adding import maps as a mojom::ScriptType enum, because import - // maps are processed quite differently from classic/module scripts. + // to avoid adding import maps as a mojom::blink::ScriptType enum, because + // import maps are processed quite differently from classic/module scripts. // // TODO(hiroshige, kouhei): Make the method signature simpler. static bool IsValidScriptTypeAndLanguage( const String& type_attribute_value, const String& language_attribute_value, LegacyTypeSupport support_legacy_types, - mojom::ScriptType* out_script_type = nullptr, + mojom::blink::ScriptType* out_script_type = nullptr, bool* out_is_import_map = nullptr); - static bool BlockForNoModule(mojom::ScriptType, bool nomodule); + static bool BlockForNoModule(mojom::blink::ScriptType, bool nomodule); static network::mojom::CredentialsMode ModuleScriptCredentialsMode( CrossOriginAttributeValue); @@ -97,7 +97,7 @@ bool IsParserInserted() const { return parser_inserted_; } bool AlreadyStarted() const { return already_started_; } bool IsNonBlocking() const { return non_blocking_; } - mojom::ScriptType GetScriptType() const { return script_type_; } + mojom::blink::ScriptType GetScriptType() const { return script_type_; } // Helper functions used by our parent classes. void DidNotifySubtreeInsertionsToDocument(); @@ -178,7 +178,7 @@ // <spec href="https://html.spec.whatwg.org/C/#concept-script-type">... It is // determined when the script is prepared, ...</spec> - mojom::ScriptType script_type_ = mojom::ScriptType::kClassic; + mojom::blink::ScriptType script_type_ = mojom::blink::ScriptType::kClassic; // <spec href="https://html.spec.whatwg.org/C/#concept-script-external"> // ... It is determined when the script is prepared, ...</spec>
diff --git a/third_party/blink/renderer/core/script/script_runner_test.cc b/third_party/blink/renderer/core/script/script_runner_test.cc index 266233e9..a68dafd 100644 --- a/third_party/blink/renderer/core/script/script_runner_test.cc +++ b/third_party/blink/renderer/core/script/script_runner_test.cc
@@ -41,7 +41,7 @@ } ~MockPendingScript() override {} - MOCK_CONST_METHOD0(GetScriptType, mojom::ScriptType()); + MOCK_CONST_METHOD0(GetScriptType, mojom::blink::ScriptType()); MOCK_CONST_METHOD1(CheckMIMETypeBeforeRunScript, bool(Document*)); MOCK_CONST_METHOD1(GetSource, Script*(const KURL&)); MOCK_CONST_METHOD0(IsExternal, bool());
diff --git a/third_party/blink/renderer/core/script/xml_parser_script_runner.cc b/third_party/blink/renderer/core/script/xml_parser_script_runner.cc index 01b2e9c..1b1617b 100644 --- a/third_party/blink/renderer/core/script/xml_parser_script_runner.cc +++ b/third_party/blink/renderer/core/script/xml_parser_script_runner.cc
@@ -47,7 +47,7 @@ pending_script->StopWatchingForLoad(); - CHECK_EQ(pending_script->GetScriptType(), mojom::ScriptType::kClassic); + CHECK_EQ(pending_script->GetScriptType(), mojom::blink::ScriptType::kClassic); // <spec label="Parsing" step="4">Execute the pending parsing-blocking // script.</spec> @@ -77,7 +77,7 @@ bool success = script_loader->PrepareScript( script_start_position, ScriptLoader::kAllowLegacyTypeInTypeAttribute); - if (script_loader->GetScriptType() != mojom::ScriptType::kClassic) { + if (script_loader->GetScriptType() != mojom::blink::ScriptType::kClassic) { // XMLDocumentParser does not support a module script, and thus ignores it. success = false; document.AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker.cc b/third_party/blink/renderer/core/workers/dedicated_worker.cc index 70ec512..342acee 100644 --- a/third_party/blink/renderer/core/workers/dedicated_worker.cc +++ b/third_party/blink/renderer/core/workers/dedicated_worker.cc
@@ -429,9 +429,9 @@ settings = WorkerSettings::Copy(worker_global_scope->GetWorkerSettings()); } - mojom::ScriptType script_type = (options_->type() == "classic") - ? mojom::ScriptType::kClassic - : mojom::ScriptType::kModule; + mojom::blink::ScriptType script_type = + (options_->type() == "classic") ? mojom::blink::ScriptType::kClassic + : mojom::blink::ScriptType::kModule; return std::make_unique<GlobalScopeCreationParams>( script_url, script_type, options_->name(),
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker_test.cc b/third_party/blink/renderer/core/workers/dedicated_worker_test.cc index df3b904..61fa4d89 100644 --- a/third_party/blink/renderer/core/workers/dedicated_worker_test.cc +++ b/third_party/blink/renderer/core/workers/dedicated_worker_test.cc
@@ -130,8 +130,8 @@ auto worker_settings = std::make_unique<WorkerSettings>( To<LocalDOMWindow>(GetExecutionContext())->GetFrame()->GetSettings()); auto params = std::make_unique<GlobalScopeCreationParams>( - script_url, mojom::ScriptType::kClassic, "fake global scope name", - "fake user agent", UserAgentMetadata(), + script_url, mojom::blink::ScriptType::kClassic, + "fake global scope name", "fake user agent", UserAgentMetadata(), nullptr /* web_worker_fetch_context */, headers, network::mojom::ReferrerPolicy::kDefault, security_origin_.get(), false /* starter_secure_context */,
diff --git a/third_party/blink/renderer/core/workers/global_scope_creation_params.cc b/third_party/blink/renderer/core/workers/global_scope_creation_params.cc index 77fb76e..8cb40161 100644 --- a/third_party/blink/renderer/core/workers/global_scope_creation_params.cc +++ b/third_party/blink/renderer/core/workers/global_scope_creation_params.cc
@@ -15,7 +15,7 @@ GlobalScopeCreationParams::GlobalScopeCreationParams( const KURL& script_url, - mojom::ScriptType script_type, + mojom::blink::ScriptType script_type, const String& global_scope_name, const String& user_agent, const base::Optional<UserAgentMetadata>& ua_metadata,
diff --git a/third_party/blink/renderer/core/workers/global_scope_creation_params.h b/third_party/blink/renderer/core/workers/global_scope_creation_params.h index af807289..c473093 100644 --- a/third_party/blink/renderer/core/workers/global_scope_creation_params.h +++ b/third_party/blink/renderer/core/workers/global_scope_creation_params.h
@@ -42,7 +42,7 @@ public: GlobalScopeCreationParams( const KURL& script_url, - mojom::ScriptType script_type, + mojom::blink::ScriptType script_type, const String& global_scope_name, const String& user_agent, const base::Optional<UserAgentMetadata>& ua_metadata, @@ -84,7 +84,7 @@ // workers. KURL script_url; - mojom::ScriptType script_type; + mojom::blink::ScriptType script_type; String global_scope_name; String user_agent;
diff --git a/third_party/blink/renderer/core/workers/main_thread_worklet_test.cc b/third_party/blink/renderer/core/workers/main_thread_worklet_test.cc index cadbf885..89e91e8 100644 --- a/third_party/blink/renderer/core/workers/main_thread_worklet_test.cc +++ b/third_party/blink/renderer/core/workers/main_thread_worklet_test.cc
@@ -60,7 +60,7 @@ reporting_proxy_ = std::make_unique<MainThreadWorkletReportingProxyForTest>(window); auto creation_params = std::make_unique<GlobalScopeCreationParams>( - window->Url(), mojom::ScriptType::kModule, "MainThreadWorklet", + window->Url(), mojom::blink::ScriptType::kModule, "MainThreadWorklet", window->UserAgent(), window->GetFrame()->Loader().UserAgentMetadata(), nullptr /* web_worker_fetch_context */, window->GetContentSecurityPolicy()->Headers(),
diff --git a/third_party/blink/renderer/core/workers/shared_worker.cc b/third_party/blink/renderer/core/workers/shared_worker.cc index c4586bb..7886a7c5 100644 --- a/third_party/blink/renderer/core/workers/shared_worker.cc +++ b/third_party/blink/renderer/core/workers/shared_worker.cc
@@ -122,7 +122,7 @@ return nullptr; } options->name = worker_options->name(); - base::Optional<mojom::ScriptType> type_result = + base::Optional<mojom::blink::ScriptType> type_result = Script::ParseScriptType(worker_options->type()); DCHECK(type_result); options->type = type_result.value();
diff --git a/third_party/blink/renderer/core/workers/worker_global_scope.cc b/third_party/blink/renderer/core/workers/worker_global_scope.cc index d369189..c1e4291 100644 --- a/third_party/blink/renderer/core/workers/worker_global_scope.cc +++ b/third_party/blink/renderer/core/workers/worker_global_scope.cc
@@ -248,7 +248,7 @@ // Step 1: "If worker global scope's type is "module", throw a TypeError // exception." - if (script_type_ == mojom::ScriptType::kModule) { + if (script_type_ == mojom::blink::ScriptType::kModule) { V8ThrowException::ThrowTypeError( isolate, ExceptionMessages::FailedToExecute( property_name, interface_name,
diff --git a/third_party/blink/renderer/core/workers/worker_global_scope.h b/third_party/blink/renderer/core/workers/worker_global_scope.h index d4b5f097..9f76a716 100644 --- a/third_party/blink/renderer/core/workers/worker_global_scope.h +++ b/third_party/blink/renderer/core/workers/worker_global_scope.h
@@ -240,7 +240,7 @@ void InitializeURL(const KURL& url); - mojom::ScriptType GetScriptType() const { return script_type_; } + mojom::blink::ScriptType GetScriptType() const { return script_type_; } // Sets the parameters for the worker main module script loaded by the browser // process. @@ -261,7 +261,7 @@ EventTarget* ErrorEventTarget() final { return this; } KURL url_; - const mojom::ScriptType script_type_; + const mojom::blink::ScriptType script_type_; const String user_agent_; const UserAgentMetadata ua_metadata_; std::unique_ptr<WorkerSettings> worker_settings_;
diff --git a/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc b/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc index bfd79bc1..da9e4d57 100644 --- a/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc +++ b/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc
@@ -264,7 +264,7 @@ // > "classic": Fetch a classic worker script given job's serialized script // > url, job's client, "serviceworker", and the to-be-created environment // > settings object for this service worker. - case mojom::ScriptType::kClassic: + case mojom::blink::ScriptType::kClassic: worker_thread_->FetchAndRunClassicScript( worker_start_data->script_url, nullptr /* worker_main_script_load_params */, @@ -276,7 +276,7 @@ // > "module": Fetch a module worker script graph given job’s serialized // > script url, job’s client, "serviceworker", "omit", and the // > to-be-created environment settings object for this service worker. - case mojom::ScriptType::kModule: + case mojom::blink::ScriptType::kModule: worker_thread_->FetchAndRunModuleScript( worker_start_data->script_url, nullptr /* worker_main_script_load_params */,
diff --git a/third_party/blink/renderer/modules/sensor/ambient_light_sensor_test.cc b/third_party/blink/renderer/modules/sensor/ambient_light_sensor_test.cc index fc3eeeb..ee50257 100644 --- a/third_party/blink/renderer/modules/sensor/ambient_light_sensor_test.cc +++ b/third_party/blink/renderer/modules/sensor/ambient_light_sensor_test.cc
@@ -81,85 +81,6 @@ EXPECT_FALSE(sensor->hasReading()); } -TEST(AmbientLightSensorTest, IlluminanceRounding) { - SensorTestContext context; - NonThrowableExceptionState exception_state; - - auto* sensor = AmbientLightSensor::Create(context.GetExecutionContext(), - exception_state); - sensor->start(); - SensorTestUtils::WaitForEvent(sensor, event_type_names::kActivate); - EXPECT_FALSE(sensor->hasReading()); - - // At this point, we have received an 'activate' event, so the sensor is - // initialized and it is connected to a SensorProxy that we can retrieve - // here. We then attach a new SensorProxy::Observer that we use to - // synchronously wait for OnSensorReadingChanged() to be called. Even though - // the order that each observer is notified is arbitrary, we know that by the - // time we get to the next call here all observers will have been called. - auto* sensor_proxy = - SensorProviderProxy::From( - To<LocalDOMWindow>(context.GetExecutionContext())) - ->GetSensorProxy(device::mojom::blink::SensorType::AMBIENT_LIGHT); - ASSERT_NE(sensor_proxy, nullptr); - auto* mock_observer = MakeGarbageCollected<MockSensorProxyObserver>(); - sensor_proxy->AddObserver(mock_observer); - - auto* event_counter = MakeGarbageCollected<SensorTestUtils::EventCounter>(); - sensor->addEventListener(event_type_names::kReading, event_counter); - - // Go from no reading to 24. This will cause a new "reading" event to be - // emitted, and the rounding will cause illuminance() to return 0. - context.sensor_provider()->UpdateAmbientLightSensorData(24); - mock_observer->WaitForOnSensorReadingChanged(); - SensorTestUtils::WaitForEvent(sensor, event_type_names::kReading); - EXPECT_EQ(24, sensor->latest_reading_); - ASSERT_TRUE(sensor->illuminance().has_value()); - EXPECT_EQ(0, sensor->illuminance().value()); - - // Go from 24 to 35. The difference is not significant enough, so we will not - // emit any "reading" event or store the new raw reading, as if the new - // reading had never existed. - context.sensor_provider()->UpdateAmbientLightSensorData(35); - mock_observer->WaitForOnSensorReadingChanged(); - EXPECT_EQ(24, sensor->latest_reading_); - ASSERT_TRUE(sensor->illuminance().has_value()); - EXPECT_EQ(0, sensor->illuminance().value()); - - // Go from 24 to 49. The difference is significant enough, so we will emit a - // new "reading" event, update our raw reading and return a rounded value of - // 50 in illuminance(). - context.sensor_provider()->UpdateAmbientLightSensorData(49); - mock_observer->WaitForOnSensorReadingChanged(); - SensorTestUtils::WaitForEvent(sensor, event_type_names::kReading); - EXPECT_EQ(49, sensor->latest_reading_); - ASSERT_TRUE(sensor->illuminance().has_value()); - EXPECT_EQ(50, sensor->illuminance().value()); - - // Go from 49 to 35. The difference is not significant enough, so we will not - // emit any "reading" event or store the new raw reading, as if the new - // reading had never existed. - context.sensor_provider()->UpdateAmbientLightSensorData(35); - mock_observer->WaitForOnSensorReadingChanged(); - EXPECT_EQ(49, sensor->latest_reading_); - ASSERT_TRUE(sensor->illuminance().has_value()); - EXPECT_EQ(50, sensor->illuminance().value()); - - // Go from 49 to 24. The difference is significant enough, so we will emit a - // new "reading" event, update our raw reading and return a rounded value of - // 0 in illuminance(). - context.sensor_provider()->UpdateAmbientLightSensorData(24); - mock_observer->WaitForOnSensorReadingChanged(); - SensorTestUtils::WaitForEvent(sensor, event_type_names::kReading); - EXPECT_EQ(24, sensor->latest_reading_); - ASSERT_TRUE(sensor->illuminance().has_value()); - EXPECT_EQ(0, sensor->illuminance().value()); - - // Make sure there were no stray "reading" events besides those we expected - // above. - EXPECT_EQ(3U, event_counter->event_count()); -} - TEST(AmbientLightSensorTest, PlatformSensorReadingsBeforeActivation) { SensorTestContext context; NonThrowableExceptionState exception_state;
diff --git a/third_party/blink/renderer/modules/sensor/sensor.cc b/third_party/blink/renderer/modules/sensor/sensor.cc index 3c05cf3..89e9e77 100644 --- a/third_party/blink/renderer/modules/sensor/sensor.cc +++ b/third_party/blink/renderer/modules/sensor/sensor.cc
@@ -263,11 +263,7 @@ DCHECK_EQ(state_, SensorState::kActivating); InitSensorProxyIfNeeded(); - if (!sensor_proxy_) { - HandleError(DOMExceptionCode::kInvalidStateError, - "The Sensor is no longer associated to a frame."); - return; - } + DCHECK(sensor_proxy_); if (sensor_proxy_->IsInitialized()) RequestAddConfiguration();
diff --git a/third_party/blink/renderer/modules/sensor/sensor_provider_proxy.h b/third_party/blink/renderer/modules/sensor/sensor_provider_proxy.h index c51f783..f427ad7 100644 --- a/third_party/blink/renderer/modules/sensor/sensor_provider_proxy.h +++ b/third_party/blink/renderer/modules/sensor/sensor_provider_proxy.h
@@ -48,15 +48,13 @@ return sensor_provider_.get(); } void RemoveSensorProxy(SensorProxy* proxy); - using SensorsSet = HeapHashSet<WeakMember<SensorProxy>>; - const SensorsSet& sensor_proxies() const { return sensor_proxies_; } // For SensorProviderProxy personal use. void InitializeIfNeeded(); bool IsInitialized() const { return sensor_provider_.is_bound(); } void OnSensorProviderConnectionError(); - SensorsSet sensor_proxies_; + HeapHashSet<WeakMember<SensorProxy>> sensor_proxies_; HeapMojoRemote<device::mojom::blink::SensorProvider, HeapMojoWrapperMode::kWithoutContextObserver> sensor_provider_;
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_container.cc b/third_party/blink/renderer/modules/service_worker/service_worker_container.cc index a4a827a..b162f4b2 100644 --- a/third_party/blink/renderer/modules/service_worker/service_worker_container.cc +++ b/third_party/blink/renderer/modules/service_worker/service_worker_container.cc
@@ -342,7 +342,7 @@ mojom::ServiceWorkerUpdateViaCache update_via_cache = ParseUpdateViaCache(options->updateViaCache()); - base::Optional<mojom::ScriptType> script_type = + base::Optional<mojom::blink::ScriptType> script_type = Script::ParseScriptType(options->type()); DCHECK(script_type);
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_container_test.cc b/third_party/blink/renderer/modules/service_worker/service_worker_container_test.cc index 9fbb0ab..b1e9b67a 100644 --- a/third_party/blink/renderer/modules/service_worker/service_worker_container_test.cc +++ b/third_party/blink/renderer/modules/service_worker/service_worker_container_test.cc
@@ -161,7 +161,7 @@ void RegisterServiceWorker( const WebURL& scope, const WebURL& script_url, - blink::mojom::ScriptType script_type, + blink::mojom::blink::ScriptType script_type, mojom::ServiceWorkerUpdateViaCache update_via_cache, const WebFetchClientSettingsObject& fetch_client_settings_object, std::unique_ptr<WebServiceWorkerRegistrationCallbacks> callbacks) @@ -276,7 +276,7 @@ StubWebServiceWorkerProvider() : register_call_count_(0), get_registration_call_count_(0), - script_type_(mojom::ScriptType::kClassic), + script_type_(mojom::blink::ScriptType::kClassic), update_via_cache_(mojom::ServiceWorkerUpdateViaCache::kImports) {} // Creates a WebServiceWorkerProvider. This can outlive the @@ -292,7 +292,7 @@ const WebURL& RegisterScriptURL() { return register_script_url_; } size_t GetRegistrationCallCount() { return get_registration_call_count_; } const WebURL& GetRegistrationURL() { return get_registration_url_; } - mojom::ScriptType ScriptType() const { return script_type_; } + mojom::blink::ScriptType ScriptType() const { return script_type_; } mojom::ServiceWorkerUpdateViaCache UpdateViaCache() const { return update_via_cache_; } @@ -308,7 +308,7 @@ void RegisterServiceWorker( const WebURL& scope, const WebURL& script_url, - blink::mojom::ScriptType script_type, + blink::mojom::blink::ScriptType script_type, mojom::ServiceWorkerUpdateViaCache update_via_cache, const WebFetchClientSettingsObject& fetch_client_settings_object, std::unique_ptr<WebServiceWorkerRegistrationCallbacks> callbacks) @@ -350,7 +350,7 @@ WebURL register_script_url_; size_t get_registration_call_count_; WebURL get_registration_url_; - mojom::ScriptType script_type_; + mojom::blink::ScriptType script_type_; mojom::ServiceWorkerUpdateViaCache update_via_cache_; }; @@ -375,7 +375,7 @@ stub_provider.RegisterScope()); EXPECT_EQ(WebURL(KURL("http://localhost/x/y/worker.js")), stub_provider.RegisterScriptURL()); - EXPECT_EQ(mojom::ScriptType::kClassic, stub_provider.ScriptType()); + EXPECT_EQ(mojom::blink::ScriptType::kClassic, stub_provider.ScriptType()); EXPECT_EQ(mojom::ServiceWorkerUpdateViaCache::kImports, stub_provider.UpdateViaCache()); } @@ -395,7 +395,7 @@ EXPECT_EQ(1ul, stub_provider.GetRegistrationCallCount()); EXPECT_EQ(WebURL(KURL("http://localhost/x/index.html")), stub_provider.GetRegistrationURL()); - EXPECT_EQ(mojom::ScriptType::kClassic, stub_provider.ScriptType()); + EXPECT_EQ(mojom::blink::ScriptType::kClassic, stub_provider.ScriptType()); EXPECT_EQ(mojom::ServiceWorkerUpdateViaCache::kImports, stub_provider.UpdateViaCache()); } @@ -422,7 +422,7 @@ stub_provider.RegisterScope()); EXPECT_EQ(WebURL(KURL(KURL(), "http://localhost/x/y/worker.js")), stub_provider.RegisterScriptURL()); - EXPECT_EQ(mojom::ScriptType::kClassic, stub_provider.ScriptType()); + EXPECT_EQ(mojom::blink::ScriptType::kClassic, stub_provider.ScriptType()); EXPECT_EQ(mojom::ServiceWorkerUpdateViaCache::kNone, stub_provider.UpdateViaCache()); } @@ -448,7 +448,7 @@ stub_provider.RegisterScope()); EXPECT_EQ(WebURL(KURL(KURL(), "http://localhost/x/y/worker.js")), stub_provider.RegisterScriptURL()); - EXPECT_EQ(mojom::ScriptType::kModule, stub_provider.ScriptType()); + EXPECT_EQ(mojom::blink::ScriptType::kModule, stub_provider.ScriptType()); EXPECT_EQ(mojom::ServiceWorkerUpdateViaCache::kImports, stub_provider.UpdateViaCache()); }
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc index bd425f6f..07e760c8 100644 --- a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc +++ b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
@@ -356,7 +356,7 @@ void ServiceWorkerGlobalScope::CountWorkerScript(size_t script_size, size_t cached_metadata_size) { - DCHECK_EQ(GetScriptType(), mojom::ScriptType::kClassic); + DCHECK_EQ(GetScriptType(), mojom::blink::ScriptType::kClassic); base::UmaHistogramCustomCounts( "ServiceWorker.ScriptSize", base::saturated_cast<base::Histogram::Sample>(script_size), 1000, 5000000, @@ -375,7 +375,7 @@ void ServiceWorkerGlobalScope::CountImportedScript( size_t script_size, size_t cached_metadata_size) { - DCHECK_EQ(GetScriptType(), mojom::ScriptType::kClassic); + DCHECK_EQ(GetScriptType(), mojom::blink::ScriptType::kClassic); CountScriptInternal(script_size, cached_metadata_size); } @@ -388,7 +388,7 @@ // Skip recording UMAs for module scripts because there're no ways to get the // number of static-imported scripts and the total size of the imported // scripts. - if (GetScriptType() == mojom::ScriptType::kModule) { + if (GetScriptType() == mojom::blink::ScriptType::kModule) { return; }
diff --git a/third_party/blink/renderer/modules/service_worker/web_embedded_worker_impl_test.cc b/third_party/blink/renderer/modules/service_worker/web_embedded_worker_impl_test.cc index 43bf734..5135b55c 100644 --- a/third_party/blink/renderer/modules/service_worker/web_embedded_worker_impl_test.cc +++ b/third_party/blink/renderer/modules/service_worker/web_embedded_worker_impl_test.cc
@@ -270,7 +270,7 @@ std::move(outside_settings_object)); start_data->script_url = script_url_; start_data->user_agent = WebString("dummy user agent"); - start_data->script_type = mojom::ScriptType::kClassic; + start_data->script_type = mojom::blink::ScriptType::kClassic; start_data->wait_for_debugger_mode = WebEmbeddedWorkerStartData::kDontWaitForDebugger; return start_data;
diff --git a/third_party/blink/renderer/modules/webgpu/BUILD.gn b/third_party/blink/renderer/modules/webgpu/BUILD.gn index 5854ec22..1099c436 100644 --- a/third_party/blink/renderer/modules/webgpu/BUILD.gn +++ b/third_party/blink/renderer/modules/webgpu/BUILD.gn
@@ -48,6 +48,8 @@ "gpu_pipeline_layout.h", "gpu_programmable_pass_encoder.cc", "gpu_programmable_pass_encoder.h", + "gpu_query_set.cc", + "gpu_query_set.h", "gpu_queue.cc", "gpu_queue.h", "gpu_render_bundle.cc",
diff --git a/third_party/blink/renderer/modules/webgpu/dawn_conversions.cc b/third_party/blink/renderer/modules/webgpu/dawn_conversions.cc index 823232b..b3290fd 100644 --- a/third_party/blink/renderer/modules/webgpu/dawn_conversions.cc +++ b/third_party/blink/renderer/modules/webgpu/dawn_conversions.cc
@@ -97,6 +97,43 @@ } template <> +WGPUQueryType AsDawnEnum<WGPUQueryType>(const WTF::String& webgpu_enum) { + if (webgpu_enum == "occlusion") { + return WGPUQueryType_Occlusion; + } + if (webgpu_enum == "pipeline-statistics") { + return WGPUQueryType_PipelineStatistics; + } + if (webgpu_enum == "timestamp") { + return WGPUQueryType_Timestamp; + } + NOTREACHED(); + return WGPUQueryType_Force32; +} + +template <> +WGPUPipelineStatisticName AsDawnEnum<WGPUPipelineStatisticName>( + const WTF::String& webgpu_enum) { + if (webgpu_enum == "vertex-shader-invocations") { + return WGPUPipelineStatisticName_VertexShaderInvocations; + } + if (webgpu_enum == "clipper-invocations") { + return WGPUPipelineStatisticName_ClipperInvocations; + } + if (webgpu_enum == "clipper-primitives-out") { + return WGPUPipelineStatisticName_ClipperPrimitivesOut; + } + if (webgpu_enum == "fragment-shader-invocations") { + return WGPUPipelineStatisticName_FragmentShaderInvocations; + } + if (webgpu_enum == "compute-shader-invocations") { + return WGPUPipelineStatisticName_ComputeShaderInvocations; + } + NOTREACHED(); + return WGPUPipelineStatisticName_Force32; +} + +template <> WGPUTextureFormat AsDawnEnum<WGPUTextureFormat>( const WTF::String& webgpu_enum) { if (webgpu_enum.IsNull()) {
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_adapter.cc b/third_party/blink/renderer/modules/webgpu/gpu_adapter.cc index 969f89b..d868a34 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_adapter.cc +++ b/third_party/blink/renderer/modules/webgpu/gpu_adapter.cc
@@ -30,6 +30,8 @@ extension_set.Contains("textureCompressionBC"); requested_device_properties.shaderFloat16 = extension_set.Contains("shader-float16"); + requested_device_properties.timestampQuery = + extension_set.Contains("timestamp-query"); return requested_device_properties; } @@ -81,6 +83,9 @@ if (adapter_properties_.shaderFloat16) { extension_name_list_.emplace_back("shader-float16"); } + if (adapter_properties_.timestampQuery) { + extension_name_list_.emplace_back("timestamp-query"); + } } ScriptPromise GPUAdapter::requestDevice(ScriptState* script_state,
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_adapter.idl b/third_party/blink/renderer/modules/webgpu/gpu_adapter.idl index 4c71723..16b2ead 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_adapter.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_adapter.idl
@@ -6,6 +6,7 @@ enum GPUExtensionName { "texture-compression-bc", + "timestamp-query", // Non-standard extension name string. Remove after a transition period. "textureCompressionBC", "shader-float16"
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.cc b/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.cc index 482c48f2..6569866 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.cc +++ b/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.cc
@@ -21,6 +21,7 @@ #include "third_party/blink/renderer/modules/webgpu/gpu_command_buffer.h" #include "third_party/blink/renderer/modules/webgpu/gpu_compute_pass_encoder.h" #include "third_party/blink/renderer/modules/webgpu/gpu_device.h" +#include "third_party/blink/renderer/modules/webgpu/gpu_query_set.h" #include "third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.h" #include "third_party/blink/renderer/modules/webgpu/gpu_texture.h" #include "third_party/blink/renderer/modules/webgpu/gpu_texture_view.h" @@ -323,6 +324,22 @@ GetProcs().commandEncoderInsertDebugMarker(GetHandle(), label.c_str()); } +void GPUCommandEncoder::resolveQuerySet(GPUQuerySet* querySet, + uint32_t firstQuery, + uint32_t queryCount, + GPUBuffer* destination, + uint64_t destinationOffset) { + GetProcs().commandEncoderResolveQuerySet( + GetHandle(), querySet->GetHandle(), firstQuery, queryCount, + destination->GetHandle(), destinationOffset); +} + +void GPUCommandEncoder::writeTimestamp(GPUQuerySet* querySet, + uint32_t queryIndex) { + GetProcs().commandEncoderWriteTimestamp(GetHandle(), querySet->GetHandle(), + queryIndex); +} + GPUCommandBuffer* GPUCommandEncoder::finish( const GPUCommandBufferDescriptor* descriptor) { std::string label;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.h b/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.h index 04b36eba..92d221f 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.h +++ b/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.h
@@ -18,6 +18,7 @@ class GPUCommandEncoderDescriptor; class GPUComputePassDescriptor; class GPUComputePassEncoder; +class GPUQuerySet; class GPURenderPassDescriptor; class GPURenderPassEncoder; class GPUTextureCopyView; @@ -63,6 +64,12 @@ void pushDebugGroup(String groupLabel); void popDebugGroup(); void insertDebugMarker(String markerLabel); + void resolveQuerySet(GPUQuerySet* querySet, + uint32_t firstQuery, + uint32_t queryCount, + GPUBuffer* destination, + uint64_t destinationOffset); + void writeTimestamp(GPUQuerySet* querySet, uint32_t queryIndex); GPUCommandBuffer* finish(const GPUCommandBufferDescriptor* descriptor); private:
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.idl b/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.idl index 97600ac9..d054757 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.idl
@@ -36,5 +36,14 @@ void popDebugGroup(); void insertDebugMarker(USVString markerLabel); + void resolveQuerySet( + GPUQuerySet querySet, + GPUSize32 firstQuery, + GPUSize32 queryCount, + GPUBuffer destination, + GPUSize64 destinationOffset); + + void writeTimestamp(GPUQuerySet querySet, GPUSize32 queryIndex); + GPUCommandBuffer finish(optional GPUCommandBufferDescriptor descriptor = {}); };
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_compute_pass_encoder.cc b/third_party/blink/renderer/modules/webgpu/gpu_compute_pass_encoder.cc index f8baf246..7e4738d4 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_compute_pass_encoder.cc +++ b/third_party/blink/renderer/modules/webgpu/gpu_compute_pass_encoder.cc
@@ -8,6 +8,7 @@ #include "third_party/blink/renderer/modules/webgpu/gpu_buffer.h" #include "third_party/blink/renderer/modules/webgpu/gpu_compute_pipeline.h" #include "third_party/blink/renderer/modules/webgpu/gpu_device.h" +#include "third_party/blink/renderer/modules/webgpu/gpu_query_set.h" namespace blink { @@ -81,6 +82,12 @@ GetHandle(), indirectBuffer->GetHandle(), indirectOffset); } +void GPUComputePassEncoder::writeTimestamp(GPUQuerySet* querySet, + uint32_t queryIndex) { + GetProcs().computePassEncoderWriteTimestamp( + GetHandle(), querySet->GetHandle(), queryIndex); +} + void GPUComputePassEncoder::endPass() { GetProcs().computePassEncoderEndPass(GetHandle()); }
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_compute_pass_encoder.h b/third_party/blink/renderer/modules/webgpu/gpu_compute_pass_encoder.h index 7d8dead..26cc4d9 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_compute_pass_encoder.h +++ b/third_party/blink/renderer/modules/webgpu/gpu_compute_pass_encoder.h
@@ -14,6 +14,7 @@ class GPUBindGroup; class GPUBuffer; class GPUComputePipeline; +class GPUQuerySet; class GPUComputePassEncoder : public DawnObject<WGPUComputePassEncoder>, public GPUProgrammablePassEncoder { @@ -40,6 +41,7 @@ void setPipeline(GPUComputePipeline* pipeline); void dispatch(uint32_t x, uint32_t y, uint32_t z); void dispatchIndirect(GPUBuffer* indirectBuffer, uint64_t indirectOffset); + void writeTimestamp(GPUQuerySet* querySet, uint32_t queryIndex); void endPass(); private:
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_compute_pass_encoder.idl b/third_party/blink/renderer/modules/webgpu/gpu_compute_pass_encoder.idl index ad0cc80..858b075 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_compute_pass_encoder.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_compute_pass_encoder.idl
@@ -13,7 +13,7 @@ optional GPUSize32 z = 1); void dispatchIndirect(GPUBuffer indirectBuffer, GPUSize64 indirectOffset); - + void writeTimestamp(GPUQuerySet querySet, GPUSize32 queryIndex); void endPass(); }; GPUComputePassEncoder includes GPUProgrammablePassEncoder;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_device.cc b/third_party/blink/renderer/modules/webgpu/gpu_device.cc index 2202b89..15fb088 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_device.cc +++ b/third_party/blink/renderer/modules/webgpu/gpu_device.cc
@@ -22,6 +22,7 @@ #include "third_party/blink/renderer/modules/webgpu/gpu_compute_pipeline.h" #include "third_party/blink/renderer/modules/webgpu/gpu_device_lost_info.h" #include "third_party/blink/renderer/modules/webgpu/gpu_pipeline_layout.h" +#include "third_party/blink/renderer/modules/webgpu/gpu_query_set.h" #include "third_party/blink/renderer/modules/webgpu/gpu_queue.h" #include "third_party/blink/renderer/modules/webgpu/gpu_render_bundle_encoder.h" #include "third_party/blink/renderer/modules/webgpu/gpu_render_pipeline.h" @@ -220,6 +221,11 @@ return GPURenderBundleEncoder::Create(this, descriptor); } +GPUQuerySet* GPUDevice::createQuerySet( + const GPUQuerySetDescriptor* descriptor) { + return GPUQuerySet::Create(this, descriptor); +} + void GPUDevice::pushErrorScope(const WTF::String& filter) { GetProcs().devicePushErrorScope(GetHandle(), AsDawnEnum<WGPUErrorFilter>(filter));
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_device.h b/third_party/blink/renderer/modules/webgpu/gpu_device.h index 61d4f8a1..2ebe2bde 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_device.h +++ b/third_party/blink/renderer/modules/webgpu/gpu_device.h
@@ -33,6 +33,8 @@ class GPUDeviceLostInfo; class GPUPipelineLayout; class GPUPipelineLayoutDescriptor; +class GPUQuerySet; +class GPUQuerySetDescriptor; class GPUQueue; class GPURenderBundleEncoder; class GPURenderBundleEncoderDescriptor; @@ -96,6 +98,8 @@ GPURenderBundleEncoder* createRenderBundleEncoder( const GPURenderBundleEncoderDescriptor* descriptor); + GPUQuerySet* createQuerySet(const GPUQuerySetDescriptor* descriptor); + void pushErrorScope(const WTF::String& filter); ScriptPromise popErrorScope(ScriptState* script_state);
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_device.idl b/third_party/blink/renderer/modules/webgpu/gpu_device.idl index 338fe76..aa1da249d 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_device.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_device.idl
@@ -28,6 +28,8 @@ GPUCommandEncoder createCommandEncoder(optional GPUCommandEncoderDescriptor descriptor = {}); GPURenderBundleEncoder createRenderBundleEncoder(GPURenderBundleEncoderDescriptor descriptor); + GPUQuerySet createQuerySet(GPUQuerySetDescriptor descriptor); + void pushErrorScope(GPUErrorFilter filter); [CallWith=ScriptState] Promise<GPUError?> popErrorScope();
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_query_set.cc b/third_party/blink/renderer/modules/webgpu/gpu_query_set.cc new file mode 100644 index 0000000..ddd49f6 --- /dev/null +++ b/third_party/blink/renderer/modules/webgpu/gpu_query_set.cc
@@ -0,0 +1,59 @@ +// Copyright 2020 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. + +#include "third_party/blink/renderer/modules/webgpu/gpu_query_set.h" + +#include "gpu/command_buffer/client/webgpu_interface.h" +#include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_query_set_descriptor.h" +#include "third_party/blink/renderer/modules/webgpu/dawn_conversions.h" +#include "third_party/blink/renderer/modules/webgpu/gpu_device.h" + +namespace blink { + +// static +GPUQuerySet* GPUQuerySet::Create(GPUDevice* device, + const GPUQuerySetDescriptor* webgpu_desc) { + DCHECK(device); + DCHECK(webgpu_desc); + + WGPUQuerySetDescriptor dawn_desc = {}; + dawn_desc.nextInChain = nullptr; + dawn_desc.type = AsDawnEnum<WGPUQueryType>(webgpu_desc->type()); + dawn_desc.count = webgpu_desc->count(); + + std::unique_ptr<WGPUPipelineStatisticName[]> pipeline_statistics; + if (webgpu_desc->hasPipelineStatistics()) { + pipeline_statistics = AsDawnEnum<WGPUPipelineStatisticName>( + webgpu_desc->pipelineStatistics()); + dawn_desc.pipelineStatistics = pipeline_statistics.get(); + dawn_desc.pipelineStatisticsCount = + webgpu_desc->pipelineStatistics().size(); + } + + std::string label; + if (webgpu_desc->hasLabel()) { + label = webgpu_desc->label().Utf8(); + dawn_desc.label = label.c_str(); + } + + return MakeGarbageCollected<GPUQuerySet>( + device, + device->GetProcs().deviceCreateQuerySet(device->GetHandle(), &dawn_desc)); +} + +GPUQuerySet::GPUQuerySet(GPUDevice* device, WGPUQuerySet querySet) + : DawnObject<WGPUQuerySet>(device, querySet) {} + +GPUQuerySet::~GPUQuerySet() { + if (IsDawnControlClientDestroyed()) { + return; + } + GetProcs().querySetRelease(GetHandle()); +} + +void GPUQuerySet::destroy() { + GetProcs().querySetDestroy(GetHandle()); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_query_set.h b/third_party/blink/renderer/modules/webgpu/gpu_query_set.h new file mode 100644 index 0000000..c2674938 --- /dev/null +++ b/third_party/blink/renderer/modules/webgpu/gpu_query_set.h
@@ -0,0 +1,33 @@ +// Copyright 2020 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. + +#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_GPU_QUERY_SET_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_GPU_QUERY_SET_H_ + +#include "third_party/blink/renderer/modules/webgpu/dawn_object.h" +#include "third_party/blink/renderer/platform/bindings/exception_state.h" + +namespace blink { + +class GPUQuerySetDescriptor; + +class GPUQuerySet : public DawnObject<WGPUQuerySet> { + DEFINE_WRAPPERTYPEINFO(); + + public: + static GPUQuerySet* Create(GPUDevice* device, + const GPUQuerySetDescriptor* webgpu_desc); + explicit GPUQuerySet(GPUDevice* device, WGPUQuerySet querySet); + ~GPUQuerySet() override; + + // gpu_queryset.idl + void destroy(); + + private: + DISALLOW_COPY_AND_ASSIGN(GPUQuerySet); +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_GPU_QUERY_SET_H_
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_query_set.idl b/third_party/blink/renderer/modules/webgpu/gpu_query_set.idl new file mode 100644 index 0000000..d9457806 --- /dev/null +++ b/third_party/blink/renderer/modules/webgpu/gpu_query_set.idl
@@ -0,0 +1,11 @@ +// Copyright 2020 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. + +// https://gpuweb.github.io/gpuweb/ + +[ + Exposed(Window WebGPU, Worker WebGPU) +] interface GPUQuerySet { + void destroy(); +};
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_query_set_descriptor.idl b/third_party/blink/renderer/modules/webgpu/gpu_query_set_descriptor.idl new file mode 100644 index 0000000..727f98de --- /dev/null +++ b/third_party/blink/renderer/modules/webgpu/gpu_query_set_descriptor.idl
@@ -0,0 +1,25 @@ +// Copyright 2020 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. + +// https://gpuweb.github.io/gpuweb/ + +dictionary GPUQuerySetDescriptor : GPUObjectDescriptorBase { + required GPUQueryType type; + required GPUSize32 count; + sequence<GPUPipelineStatisticName> pipelineStatistics = []; +}; + +enum GPUQueryType { + "occlusion", + "pipeline-statistics", + "timestamp" +}; + +enum GPUPipelineStatisticName { + "vertex-shader-invocations", + "clipper-invocations", + "clipper-primitives-out", + "fragment-shader-invocations", + "compute-shader-invocations" +};
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_queue.cc b/third_party/blink/renderer/modules/webgpu/gpu_queue.cc index 474d871..4ae0188 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_queue.cc +++ b/third_party/blink/renderer/modules/webgpu/gpu_queue.cc
@@ -337,6 +337,13 @@ return; } + // ImageBitmap shouldn't in closed state. + if (source->imageBitmap()->IsNeutered()) { + exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError, + "ImageBitmap is closed."); + return; + } + scoped_refptr<StaticBitmapImage> image = source->imageBitmap()->BitmapImage(); @@ -350,10 +357,18 @@ WGPUOrigin3D origin_in_image_bitmap = GPUOrigin2DToWGPUOrigin3D(&(source->origin())); + // Validate copy depth + if (dawn_copy_size.depth > 1) { + GetProcs().deviceInjectError(device_->GetHandle(), WGPUErrorType_Validation, + "Copy depth is out of bounds of imageBitmap."); + return; + } + // Validate origin value - if (static_cast<uint32_t>(image->width()) <= origin_in_image_bitmap.x || - static_cast<uint32_t>(image->height()) <= origin_in_image_bitmap.y) { - exception_state.ThrowRangeError( + if (static_cast<uint32_t>(image->width()) < origin_in_image_bitmap.x || + static_cast<uint32_t>(image->height()) < origin_in_image_bitmap.y) { + GetProcs().deviceInjectError( + device_->GetHandle(), WGPUErrorType_Validation, "Copy origin is out of bounds of imageBitmap."); return; } @@ -361,8 +376,8 @@ // Validate the copy rect is inside the imageBitmap if (image->width() - origin_in_image_bitmap.x < dawn_copy_size.width || image->height() - origin_in_image_bitmap.y < dawn_copy_size.height) { - exception_state.ThrowRangeError( - "Copy rect is out of bounds of imageBitmap."); + GetProcs().deviceInjectError(device_->GetHandle(), WGPUErrorType_Validation, + "Copy rect is out of bounds of imageBitmap."); return; } @@ -373,9 +388,12 @@ return; } + bool isNoopCopy = dawn_copy_size.width == 0 || dawn_copy_size.height == 0 || + dawn_copy_size.depth == 0; + // TODO(shaobo.yan@intel.com): Implement GPU copy path - // Try GPU path first. - if (image->IsTextureBacked()) { // Try GPU uploading path. + // Try GPU path first and delegate noop copy to CPU path. + if (image->IsTextureBacked() && !isNoopCopy) { // Try GPU uploading path. if (CanUploadThroughGPU(image.get(), destination->texture())) { if (CopyContentFromGPU(image.get(), origin_in_image_bitmap, dawn_copy_size, dawn_destination)) { @@ -405,11 +423,13 @@ WebGPUImageUploadSizeInfo info = ComputeImageBitmapWebGPUUploadSizeInfo( image_data_rect, dest_texture_format); + bool isNoopCopy = info.size_in_bytes == 0 || copy_size.depth == 0; + // Create a mapped buffer to receive image bitmap contents WGPUBufferDescriptor buffer_desc = {}; buffer_desc.usage = WGPUBufferUsage_CopySrc; buffer_desc.size = info.size_in_bytes; - buffer_desc.mappedAtCreation = true; + buffer_desc.mappedAtCreation = !isNoopCopy; if (buffer_desc.size > uint64_t(std::numeric_limits<size_t>::max())) { return false; @@ -418,18 +438,23 @@ WGPUBuffer buffer = GetProcs().deviceCreateBuffer(device_->GetHandle(), &buffer_desc); - void* data = GetProcs().bufferGetMappedRange(buffer, 0, size); - if (!CopyBytesFromImageBitmapForWebGPU( - image, base::span<uint8_t>(static_cast<uint8_t*>(data), size), - image_data_rect, dest_texture_format)) { - // Release the buffer. - GetProcs().bufferRelease(buffer); - return false; + // Bypass extract source content in noop copy but follow the copy path + // for validation. + if (!isNoopCopy) { + void* data = GetProcs().bufferGetMappedRange(buffer, 0, size); + + if (!CopyBytesFromImageBitmapForWebGPU( + image, base::span<uint8_t>(static_cast<uint8_t*>(data), size), + image_data_rect, dest_texture_format)) { + // Release the buffer. + GetProcs().bufferRelease(buffer); + return false; + } + + GetProcs().bufferUnmap(buffer); } - GetProcs().bufferUnmap(buffer); - // Start a B2T copy to move contents from buffer to destination texture WGPUBufferCopyView dawn_intermediate = {}; dawn_intermediate.nextInChain = nullptr;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.cc b/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.cc index 128382c..d13bb104 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.cc +++ b/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.cc
@@ -10,6 +10,7 @@ #include "third_party/blink/renderer/modules/webgpu/gpu_bind_group.h" #include "third_party/blink/renderer/modules/webgpu/gpu_buffer.h" #include "third_party/blink/renderer/modules/webgpu/gpu_device.h" +#include "third_party/blink/renderer/modules/webgpu/gpu_query_set.h" #include "third_party/blink/renderer/modules/webgpu/gpu_render_bundle.h" #include "third_party/blink/renderer/modules/webgpu/gpu_render_pipeline.h" @@ -178,6 +179,12 @@ dawn_bundles.get()); } +void GPURenderPassEncoder::writeTimestamp(GPUQuerySet* querySet, + uint32_t queryIndex) { + GetProcs().renderPassEncoderWriteTimestamp(GetHandle(), querySet->GetHandle(), + queryIndex); +} + void GPURenderPassEncoder::endPass() { GetProcs().renderPassEncoderEndPass(GetHandle()); }
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.h b/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.h index c92a1941..cfbb33e 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.h +++ b/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.h
@@ -16,6 +16,7 @@ class DoubleSequenceOrGPUColorDict; class GPURenderBundle; class GPURenderPipeline; +class GPUQuerySet; class GPURenderPassEncoder : public DawnObject<WGPURenderPassEncoder>, public GPUProgrammablePassEncoder { @@ -73,6 +74,7 @@ void drawIndirect(GPUBuffer* indirectBuffer, uint64_t indirectOffset); void drawIndexedIndirect(GPUBuffer* indirectBuffer, uint64_t indirectOffset); void executeBundles(const HeapVector<Member<GPURenderBundle>>& bundles); + void writeTimestamp(GPUQuerySet* querySet, uint32_t queryIndex); void endPass(); private:
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.idl b/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.idl index 6d817591..6ac8535e 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.idl
@@ -18,6 +18,7 @@ void setStencilReference(GPUStencilValue reference); void executeBundles(sequence<GPURenderBundle> bundles); + void writeTimestamp(GPUQuerySet querySet, GPUSize32 queryIndex); void endPass(); }; GPURenderPassEncoder includes GPUProgrammablePassEncoder;
diff --git a/third_party/blink/renderer/modules/webgpu/idls.gni b/third_party/blink/renderer/modules/webgpu/idls.gni index c4cc0634..31dad915 100644 --- a/third_party/blink/renderer/modules/webgpu/idls.gni +++ b/third_party/blink/renderer/modules/webgpu/idls.gni
@@ -21,6 +21,7 @@ "gpu_map_mode.idl", "gpu_out_of_memory_error.idl", "gpu_pipeline_layout.idl", + "gpu_query_set.idl", "gpu_queue.idl", "gpu_render_bundle.idl", "gpu_render_bundle_encoder.idl", @@ -64,6 +65,7 @@ "gpu_pipeline_descriptor_base.idl", "gpu_pipeline_layout_descriptor.idl", "gpu_programmable_stage_descriptor.idl", + "gpu_query_set_descriptor.idl", "gpu_rasterization_state_descriptor.idl", "gpu_render_bundle_descriptor.idl", "gpu_render_bundle_encoder_descriptor.idl",
diff --git a/third_party/blink/renderer/platform/graphics/gpu/webgpu_image_bitmap_handler.cc b/third_party/blink/renderer/platform/graphics/gpu/webgpu_image_bitmap_handler.cc index fe097f83..03e2f22c 100644 --- a/third_party/blink/renderer/platform/graphics/gpu/webgpu_image_bitmap_handler.cc +++ b/third_party/blink/renderer/platform/graphics/gpu/webgpu_image_bitmap_handler.cc
@@ -80,6 +80,8 @@ DCHECK_GT(dst.size(), static_cast<size_t>(0)); DCHECK(image->width() - rect.X() >= rect.Width()); DCHECK(image->height() - rect.Y() >= rect.Height()); + DCHECK(rect.Width()); + DCHECK(rect.Height()); WebGPUImageUploadSizeInfo wgpu_info = ComputeImageBitmapWebGPUUploadSizeInfo(rect, destination_format);
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource.cc b/third_party/blink/renderer/platform/loader/fetch/resource.cc index ecb254c3..3265d12 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource.cc
@@ -477,10 +477,14 @@ return redirect_chain_.back().request_; } -const ResourceResponse* Resource::LastResourceResponse() const { +const ResourceResponse& Resource::LastResourceResponse() const { if (!redirect_chain_.size()) - return nullptr; - return &redirect_chain_.back().redirect_response_; + return GetResponse(); + return redirect_chain_.back().redirect_response_; +} + +size_t Resource::RedirectChainSize() const { + return redirect_chain_.size(); } void Resource::SetRevalidatingRequest(const ResourceRequestHead& request) {
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource.h b/third_party/blink/renderer/platform/loader/fetch/resource.h index e9ef3dba..5ef043e5 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource.h +++ b/third_party/blink/renderer/platform/loader/fetch/resource.h
@@ -169,7 +169,9 @@ return resource_request_; } const ResourceRequestHead& LastResourceRequest() const; - const ResourceResponse* LastResourceResponse() const; + const ResourceResponse& LastResourceResponse() const; + // Returns zero if there are no redirects. + size_t RedirectChainSize() const; virtual void SetRevalidatingRequest(const ResourceRequestHead&);
diff --git a/third_party/blink/web_tests/external/wpt/generic-sensor/generic-sensor-iframe-tests.sub.js b/third_party/blink/web_tests/external/wpt/generic-sensor/generic-sensor-iframe-tests.sub.js index 513b4c7..11c9f50 100644 --- a/third_party/blink/web_tests/external/wpt/generic-sensor/generic-sensor-iframe-tests.sub.js +++ b/third_party/blink/web_tests/external/wpt/generic-sensor/generic-sensor-iframe-tests.sub.js
@@ -126,7 +126,6 @@ await sensorWatcher.wait_for('reading'); assert_greater_than(sensor.timestamp, cachedTimeStamp); sensor.stop(); - await send_message_to_iframe(iframe, {command: 'reset_sensor_backend'}); }, `${sensorName}: sensor is not suspended when focus traverses from\ to same-origin frame`);
diff --git a/third_party/blink/web_tests/external/wpt/generic-sensor/resources/iframe_sensor_handler.html b/third_party/blink/web_tests/external/wpt/generic-sensor/resources/iframe_sensor_handler.html index e2dfab5..23e8e1b 100644 --- a/third_party/blink/web_tests/external/wpt/generic-sensor/resources/iframe_sensor_handler.html +++ b/third_party/blink/web_tests/external/wpt/generic-sensor/resources/iframe_sensor_handler.html
@@ -7,52 +7,33 @@ let sensor = null; let sensorType = null; - function postReply(event, reply) { - event.source.postMessage({ command: event.data.command, result: reply }, '*'); - } - - window.onmessage = async (e) => { + async function messageHandler(e) { if (e.data.command === 'create_sensor') { - if (sensor) { - postReply(e, 'success'); - return; - } - - try { + if (!sensor) { mockBackend = await initialize_generic_sensor_tests(); sensor = new self[e.data.type](); sensorType = e.data.type; - - postReply(e, 'success'); - } catch (error) { - postReply(e, error); } + + return Promise.resolve('success'); } else if (e.data.command === 'start_sensor') { if (!sensor) { - postReply(e, '"create_sensor" must be called first'); - return; + return Promise.reject('"create_sensor" must be called first'); } - try { + return new Promise(resolve => { sensor.addEventListener('reading', () => { - postReply(e, 'success'); + resolve('success'); }, { once: true }); sensor.start(); - } catch (error) { - postReply(e, error); - } + }); } else if (e.data.command === 'is_sensor_suspended') { if (!mockBackend) { - postReply(e, '"create_sensor" must be called first'); - return; + return Promise.reject('"create_sensor" must be called first'); } - try { - const mockPlatformSensor = await mockBackend.getSensorProvider().getCreatedSensor(sensorType); - postReply(e, !mockPlatformSensor.isReadingData()); - } catch (error) { - postReply(e, error); - } + const mockPlatformSensor = await mockBackend.getSensorProvider().getCreatedSensor(sensorType); + return Promise.resolve(!mockPlatformSensor.isReadingData()); } else if (e.data.command === 'reset_sensor_backend') { if (sensor) { sensor.stop(); @@ -61,8 +42,19 @@ sensor = null; mockBackend = null; } - - postReply(e, 'success'); + return Promise.resolve('success'); + } else { + return Promise.reject(`unknown command "${e.data.command}"`); } } + + window.onmessage = async (e) => { + let reply; + try { + reply = await messageHandler(e); + } catch (error) { + reply = error; + } + e.source.postMessage({ command: e.data.command, result: reply }, '*'); + } </script>
diff --git a/third_party/blink/web_tests/wpt_internal/ambient-light/illuminance-rounding.https.window.js b/third_party/blink/web_tests/wpt_internal/ambient-light/illuminance-rounding.https.window.js new file mode 100644 index 0000000..d4a0cbc --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/ambient-light/illuminance-rounding.https.window.js
@@ -0,0 +1,51 @@ +// META: script=/generic-sensor/resources/generic-sensor-helpers.js + +'use strict'; + +sensor_test(async (t, sensorProvider) => { + const sensor = new AmbientLightSensor({ + frequency: 10 // 10Hz is the maximum frequency allowed by the Blink + // implementation. + }); + t.add_cleanup(() => { + sensor.stop(); + }); + const eventWatcher = + new EventWatcher(t, sensor, ['activate', 'reading', 'error']); + + sensor.start(); + await eventWatcher.wait_for('activate'); + assert_false( + sensor.hasReading, 'Sensor has no readings immediately after activation'); + assert_equals( + sensor.illuminance, null, + 'Sensor must have no illuminance immediately after activation'); + + const mockSensor = + await sensorProvider.getCreatedSensor('AmbientLightSensor'); + await mockSensor.setSensorReading([[24], [35], [49], [35], [24]]); + + // This loop checks that illuminance rounding causes the following to happen: + // 1. The first ever reading goes from nothing to 24. A new "reading" event is + // emitted and the rounded illuminance value is 0. + // 2. Going from 24 to 35 is not significant enough. No "reading" event is + // emitted and the illuminance value remains the same. + // 3. Going from 24 to 49 is significant enough. A "reading" event is emitted + // and the rounded illuminance value is 50. + // 4. Going from 49 to 35 is not significant enough. No "reading" event is + // emitted and the illuminance value remains the same. + // 5. Going from 49 to 24 is significant enough. A "reading" event is emitted + // and the rounded illuminance value is 0. + // 6. We are back to the first raw reading value. We are at 24 and get 24, so + // nothing happens. + // 7. Go to step 3. + for (let i = 0; i < 3; i++) { + await eventWatcher.wait_for('reading'); + assert_true(sensor.hasReading); + assert_equals(sensor.illuminance, 0, 'Rounded illuminance should be 0'); + + await eventWatcher.wait_for('reading'); + assert_true(sensor.hasReading); + assert_equals(sensor.illuminance, 50, 'Rounded illuminance should be 50'); + } +}, 'Illuminance rounding');
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index e64bd11..fed5580 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -43704,6 +43704,8 @@ label="HappinessTrackingSurveysForDesktopSettingsPrivacy:disabled"/> <int value="966415988" label="SyncPseudoUSSPasswords:enabled"/> <int value="968355926" label="ExportTaggedPDF:enabled"/> + <int value="968715406" + label="enable-experimental-accessibility-magnifier-new-focus-following"/> <int value="969340095" label="EnableDspHotword:disabled"/> <int value="972228058" label="SyncUSSSessions:disabled"/> <int value="973601997" label="SafeBrowsingUseLocalBlacklistsV2:disabled"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 8854b8f8..99274dbf 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -59058,6 +59058,19 @@ </summary> </histogram> +<histogram name="FamilyUser.SessionEngagement.Duration" units="ms" + expires_after="2021-07-14"> + <owner>agawronska@chromium.org</owner> + <owner>tobyhuang@chromium.org</owner> + <owner>xiqiruan@chromium.org</owner> + <owner>cros-families-eng@google.com</owner> + <summary> + Records the Chrome OS user session duration in milliseconds. Reports current + daily duration at the first session start on next day. This is only logged + for active usage time of device, determined by UsageTimeState::ACTIVE. + </summary> +</histogram> + <histogram name="FamilyUser.SessionEngagement.Total" units="Hour of day" expires_after="2021-07-14"> <owner>agawronska@chromium.org</owner> @@ -69076,8 +69089,9 @@ </histogram> <histogram name="Installer.Recovery.Reason" enum="ChromeOSRecoveryReason" - expires_after="M85"> - <owner>lannm@chromium.org</owner> + expires_after="2021-12-29"> + <owner>kimjae@chromium.org</owner> + <owner>chromeos-core-services@google.com</owner> <summary> The reason for entering recovery mode immediately prior to a recovery. @@ -89651,8 +89665,9 @@ </histogram> <histogram name="NativeSmbFileShare.AuthenticationMethod" - enum="NativeSmbFileShare_AuthMethod" expires_after="M85"> - <owner>zentaro@chromium.org</owner> + enum="NativeSmbFileShare_AuthMethod" expires_after="M94"> + <owner>simmonsjosh@google.com</owner> + <owner>src/chrome/browser/chromeos/smb_client/OWNERS</owner> <summary> The method used to authenticate to a share. This is called on each attempted mount. @@ -118944,7 +118959,8 @@ </summary> </histogram> -<histogram name="P2P.Server.ClientCount" units="count" expires_after="M85"> +<histogram name="P2P.Server.ClientCount" units="count" + expires_after="2021-12-29"> <owner>ahassani@chromium.org</owner> <owner>chromeos-core-services@google.com</owner> <summary> @@ -121942,7 +121958,7 @@ <histogram name="PageLoad.Experimental.PaintTiming.ParseStartToFirstMeaningfulPaint" - units="ms" expires_after="2020-09-27"> + units="ms" expires_after="2021-03-27"> <owner>ksakamoto@chromium.org</owner> <owner>speed-metrics-dev@chromium.org</owner> <summary> @@ -147036,8 +147052,8 @@ </histogram> <histogram name="SafeBrowsing.AdvancedProtection.APTokenFetchStatus" - enum="GoogleServiceAuthError" expires_after="M85"> - <owner>vakh@chromium.org</owner> + enum="GoogleServiceAuthError" expires_after="M90"> + <owner>drubery@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> <summary> For users known to be already enrolled in Advanced Proection, records the @@ -147049,8 +147065,8 @@ </histogram> <histogram name="SafeBrowsing.AdvancedProtection.TokenFetchStatus" - enum="GoogleServiceAuthError" expires_after="M85"> - <owner>vakh@chromium.org</owner> + enum="GoogleServiceAuthError" expires_after="M90"> + <owner>drubey@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> <summary> Records the service error of refreshing OAuth2 access token during fetching @@ -149345,7 +149361,7 @@ </histogram> <histogram name="SafeBrowsingBinaryUploadRequest.DlpResult" - enum="BooleanSuccess" expires_after="M85"> + enum="BooleanSuccess" expires_after="M90"> <owner>drubery@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> <summary> @@ -149356,7 +149372,7 @@ </histogram> <histogram name="SafeBrowsingBinaryUploadRequest.Duration" units="ms" - expires_after="M85"> + expires_after="M90"> <owner>drubery@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> <summary> @@ -149367,7 +149383,7 @@ </histogram> <histogram name="SafeBrowsingBinaryUploadRequest.MalwareResult" - enum="BooleanSuccess" expires_after="M85"> + enum="BooleanSuccess" expires_after="M90"> <owner>drubery@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> <summary> @@ -149390,7 +149406,7 @@ </histogram> <histogram name="SafeBrowsingBinaryUploadRequest.Result" - enum="SafeBrowsingBinaryUploadResult" expires_after="M85"> + enum="SafeBrowsingBinaryUploadResult" expires_after="M90"> <owner>drubery@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> <summary> @@ -149411,7 +149427,7 @@ </histogram> <histogram name="SafeBrowsingBinaryUploadRequest.TimeToGetToken" units="ms" - expires_after="M85"> + expires_after="M90"> <obsolete> Removed 06/2020 as SafeBrowsingBinaryUploadRequest.TimeToGetFCMToken provides the same information with a better range of durations. @@ -149425,7 +149441,7 @@ </histogram> <histogram name="SafeBrowsingFCMService.IncomingMessageHasKey" enum="Boolean" - expires_after="M85"> + expires_after="M90"> <owner>drubery@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> <summary> @@ -149435,7 +149451,7 @@ </histogram> <histogram name="SafeBrowsingFCMService.IncomingMessageHasValidToken" - enum="Boolean" expires_after="M85"> + enum="Boolean" expires_after="M90"> <owner>drubery@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> <summary> @@ -149446,7 +149462,7 @@ </histogram> <histogram name="SafeBrowsingFCMService.IncomingMessageParsedBase64" - enum="BooleanSuccess" expires_after="M85"> + enum="BooleanSuccess" expires_after="M90"> <owner>drubery@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> <summary> @@ -149457,7 +149473,7 @@ </histogram> <histogram name="SafeBrowsingFCMService.IncomingMessageParsedProto" - enum="BooleanSuccess" expires_after="M85"> + enum="BooleanSuccess" expires_after="M90"> <owner>drubery@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> <summary> @@ -152652,7 +152668,7 @@ </histogram> <histogram name="SBMultipartUploader.FailedUploadDuration" units="s" - expires_after="M85"> + expires_after="M90"> <owner>drubery@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> <summary> @@ -152663,7 +152679,7 @@ </histogram> <histogram name="SBMultipartUploader.NetworkRequestResponseCodeOrError" - enum="CombinedHttpResponseAndNetErrorCode" expires_after="M85"> + enum="CombinedHttpResponseAndNetErrorCode" expires_after="M90"> <owner>drubery@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> <summary> @@ -152675,7 +152691,7 @@ </histogram> <histogram name="SBMultipartUploader.RetriesNeeded" units="retries" - expires_after="M85"> + expires_after="M90"> <owner>drubery@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> <summary> @@ -152685,7 +152701,7 @@ </histogram> <histogram name="SBMultipartUploader.SuccessfulUploadDuration" units="s" - expires_after="M85"> + expires_after="M90"> <owner>drubery@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> <summary> @@ -152695,7 +152711,7 @@ </histogram> <histogram name="SBMultipartUploader.UploadSize" units="bytes" - expires_after="M85"> + expires_after="M90"> <owner>drubery@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> <summary> @@ -152706,7 +152722,7 @@ </histogram> <histogram name="SBMultipartUploader.UploadSuccess" enum="BooleanSuccess" - expires_after="M85"> + expires_after="M90"> <owner>drubery@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> <summary> @@ -173965,7 +173981,7 @@ </histogram> <histogram name="Sync.BookmarksWithoutFullTitle.OnInitialMerge" - units="bookmarks" expires_after="M87"> + units="bookmarks" expires_after="M89"> <owner>rushans@google.com</owner> <owner>mastiz@chromiumg.org</owner> <summary> @@ -173975,7 +173991,7 @@ </histogram> <histogram name="Sync.BookmarksWithoutFullTitle.OnRemoteUpdate" - units="bookmarks" expires_after="M87"> + units="bookmarks" expires_after="M89"> <owner>rushans@google.com</owner> <owner>mastiz@chromiumg.org</owner> <summary> @@ -182330,7 +182346,7 @@ </histogram> <histogram name="Translate.ExplicitLanguageAsk.Event" - enum="TranslateExplicitAskPromptEventType" expires_after="M85"> + enum="TranslateExplicitAskPromptEventType" expires_after="2021-01-31"> <owner>yyushkina@google.com</owner> <owner>anthonyvd@google.com</owner> <owner>chrome-language@google.com</owner> @@ -182341,7 +182357,7 @@ </histogram> <histogram name="Translate.ExplicitLanguageAsk.LanguageAdded" - enum="CLD3LanguageCode" expires_after="M85"> + enum="CLD3LanguageCode" expires_after="2021-01-31"> <owner>yyushkina@google.com</owner> <owner>anthonyvd@google.com</owner> <owner>chrome-language@google.com</owner> @@ -182352,7 +182368,7 @@ </histogram> <histogram name="Translate.ExplicitLanguageAsk.LanguageRemoved" - enum="CLD3LanguageCode" expires_after="M85"> + enum="CLD3LanguageCode" expires_after="2021-01-31"> <owner>yyushkina@google.com</owner> <owner>anthonyvd@google.com</owner> <owner>chrome-language@google.com</owner> @@ -182522,7 +182538,7 @@ </histogram> <histogram name="Translate.LocalesOnDisabledByPrefs" enum="LanguageCode" - expires_after="M85"> + expires_after="2021-01-31"> <owner>kenjibaheux@google.com</owner> <owner>chrome-language@google.com</owner> <summary> @@ -182694,7 +182710,7 @@ </histogram> <histogram name="Translate.ReportLanguageDetectionError" units="units" - expires_after="2020-12-01"> + expires_after="2021-01-31"> <owner>kenjibaheux@google.com</owner> <owner>chrome-language@google.com</owner> <summary> @@ -182739,9 +182755,9 @@ </histogram> <histogram name="Translate.ShowErrorInfobar" enum="TranslateError" - expires_after="2020-12-01"> + expires_after="2020-09-18"> <obsolete> - Removed 6/2020. Duplicate of Translate.ShowErrorUI + Removed 06/2020. Duplicate of Translate.ShowErrorUI </obsolete> <owner>chrome-language@google.com</owner> <owner>kenjibaheux@google.com</owner>
diff --git a/ui/accessibility/accessibility_switches.cc b/ui/accessibility/accessibility_switches.cc index 3fa41e0..09ce94e 100644 --- a/ui/accessibility/accessibility_switches.cc +++ b/ui/accessibility/accessibility_switches.cc
@@ -40,6 +40,11 @@ const char kEnableExperimentalAccessibilityChromeVoxTutorial[] = "enable-experimental-accessibility-chromevox-tutorial"; +// Enables new magnifier focus following feature, which provides richer focus +// following experience. +const char kEnableExperimentalAccessibilityMagnifierNewFocusFollowing[] = + "enable-experimental-accessibility-magnifier-new-focus-following"; + // Enables Switch Access point scanning. This feature hasn't launched yet. const char kEnableSwitchAccessPointScanning[] = "enable-switch-access-point-scanning";
diff --git a/ui/accessibility/accessibility_switches.h b/ui/accessibility/accessibility_switches.h index 9142a13..ad01597 100644 --- a/ui/accessibility/accessibility_switches.h +++ b/ui/accessibility/accessibility_switches.h
@@ -24,6 +24,8 @@ kEnableExperimentalAccessibilityChromeVoxAnnotations[]; AX_BASE_EXPORT extern const char kEnableExperimentalAccessibilityChromeVoxTutorial[]; +AX_BASE_EXPORT extern const char + kEnableExperimentalAccessibilityMagnifierNewFocusFollowing[]; AX_BASE_EXPORT extern const char kEnableSwitchAccessPointScanning[]; // Returns true if experimental accessibility language detection is enabled.
diff --git a/ui/base/ime/chromeos/input_method_util.cc b/ui/base/ime/chromeos/input_method_util.cc index 51334fd..6277435 100644 --- a/ui/base/ime/chromeos/input_method_util.cc +++ b/ui/base/ime/chromeos/input_method_util.cc
@@ -230,7 +230,9 @@ {"__MSG_KEYBOARD_ARMENIAN_PHONETIC__", IDS_IME_NAME_KEYBOARD_ARMENIAN_PHONETIC}, {"__MSG_KEYBOARD_BELARUSIAN__", IDS_IME_NAME_KEYBOARD_BELARUSIAN}, - {"__MSG_KEYBOARD_BELGIAN__", IDS_IME_NAME_KEYBOARD_BELGIAN}, + {"__MSG_KEYBOARD_BELGIAN_DUTCH__", IDS_IME_NAME_KEYBOARD_BELGIAN_DUTCH}, + {"__MSG_KEYBOARD_BELGIAN_FRENCH__", IDS_IME_NAME_KEYBOARD_BELGIAN_FRENCH}, + {"__MSG_KEYBOARD_BELGIAN_GERMAN__", IDS_IME_NAME_KEYBOARD_BELGIAN_GERMAN}, {"__MSG_KEYBOARD_BENGALI_PHONETIC__", IDS_IME_NAME_KEYBOARD_BENGALI_PHONETIC}, {"__MSG_KEYBOARD_BRAZILIAN__", IDS_IME_NAME_KEYBOARD_BRAZILIAN}, @@ -280,19 +282,25 @@ {"__MSG_KEYBOARD_LATVIAN__", IDS_IME_NAME_KEYBOARD_LATVIAN}, {"__MSG_KEYBOARD_LITHUANIAN__", IDS_IME_NAME_KEYBOARD_LITHUANIAN}, {"__MSG_KEYBOARD_MACEDONIAN__", IDS_IME_NAME_KEYBOARD_MACEDONIAN}, - {"__MSG_KEYBOARD_MALAY__", IDS_IME_NAME_KEYBOARD_MALAY}, {"__MSG_KEYBOARD_MALAYALAM_PHONETIC__", IDS_IME_NAME_KEYBOARD_MALAYALAM_PHONETIC}, + {"__MSG_KEYBOARD_MALAY__", IDS_IME_NAME_KEYBOARD_MALAY}, {"__MSG_KEYBOARD_MALTESE__", IDS_IME_NAME_KEYBOARD_MALTESE}, {"__MSG_KEYBOARD_MONGOLIAN__", IDS_IME_NAME_KEYBOARD_MONGOLIAN}, {"__MSG_KEYBOARD_MYANMAR_MYANSAN__", IDS_IME_NAME_KEYBOARD_MYANMAR_MYANSAN}, {"__MSG_KEYBOARD_MYANMAR__", IDS_IME_NAME_KEYBOARD_MYANMAR}, {"__MSG_KEYBOARD_NEPALI_INSCRIPT__", IDS_IME_NAME_KEYBOARD_NEPALI_INSCRIPT}, {"__MSG_KEYBOARD_NEPALI_PHONETIC__", IDS_IME_NAME_KEYBOARD_NEPALI_PHONETIC}, + {"__MSG_KEYBOARD_NETHERLANDS_US_INTERNATIONAL_PC__", + IDS_IME_NAME_KEYBOARD_NETHERLANDS_US_INTERNATIONAL_PC}, {"__MSG_KEYBOARD_NETHERLANDS__", IDS_IME_NAME_KEYBOARD_NETHERLANDS}, {"__MSG_KEYBOARD_NORWEGIAN__", IDS_IME_NAME_KEYBOARD_NORWEGIAN}, {"__MSG_KEYBOARD_PERSIAN__", IDS_IME_NAME_KEYBOARD_PERSIAN}, {"__MSG_KEYBOARD_POLISH__", IDS_IME_NAME_KEYBOARD_POLISH}, + {"__MSG_KEYBOARD_PORTUGUESE_US_INTERNATIONAL_PC__", + IDS_IME_NAME_KEYBOARD_PORTUGUESE_US_INTERNATIONAL_PC}, + {"__MSG_KEYBOARD_PORTUGUESE_US_INTERNATIONAL__", + IDS_IME_NAME_KEYBOARD_PORTUGUESE_US_INTERNATIONAL}, {"__MSG_KEYBOARD_PORTUGUESE__", IDS_IME_NAME_KEYBOARD_PORTUGUESE}, {"__MSG_KEYBOARD_ROMANIAN_STANDARD__", IDS_IME_NAME_KEYBOARD_ROMANIAN_STANDARD}, @@ -517,23 +525,9 @@ return base::UTF8ToUTF16(localized_display_name); } - // We don't show language here. Name of keyboard layout or input method - // usually imply (or explicitly include) its language. - // Special case for German, French and Dutch: these languages have multiple - // keyboard layouts and share the same layout of keyboard (Belgian). We need - // to show explicitly the language for the layout. - DCHECK(!input_method.language_codes().empty()); - const std::string language_code = input_method.language_codes().at(0); - base::string16 text = (short_name || localized_display_name.empty()) ? TranslateString(input_method.id()) : base::UTF8ToUTF16(localized_display_name); - if (language_code == "de" || language_code == "fr" || language_code == "nl") { - const base::string16 language_name = delegate_->GetDisplayLanguageName( - language_code); - text = language_name + base::UTF8ToUTF16(" - ") + text; - } - DCHECK(!text.empty()); return text; }
diff --git a/ui/base/ime/chromeos/input_method_util_unittest.cc b/ui/base/ime/chromeos/input_method_util_unittest.cc index 38d42bbd..b51c1df 100644 --- a/ui/base/ime/chromeos/input_method_util_unittest.cc +++ b/ui/base/ime/chromeos/input_method_util_unittest.cc
@@ -205,8 +205,7 @@ } TEST_F(InputMethodUtilTest, GetInputMethodLongNameTest) { - // For most languages input method or keyboard layout name is returned. - // See below for exceptions. + // Input method or keyboard layout name is returned. { InputMethodDescriptor desc = GetDesc("xkb:jp::jpn", "jp", "ja", ""); EXPECT_EQ(ASCIIToUTF16("Japanese"), util_.GetInputMethodLongName(desc)); @@ -221,35 +220,6 @@ GetDesc("xkb:gb:dvorak:eng", "gb(dvorak)", "en-US", ""); EXPECT_EQ(ASCIIToUTF16("UK Dvorak"), util_.GetInputMethodLongName(desc)); } - - // For Dutch, French, German and Hindi, - // "language - keyboard layout" pair is returned. - { - InputMethodDescriptor desc = GetDesc("xkb:be::nld", "be", "nl", ""); - EXPECT_EQ(ASCIIToUTF16("Dutch - Belgian"), - util_.GetInputMethodLongName(desc)); - } - { - InputMethodDescriptor desc = GetDesc("xkb:fr::fra", "fr", "fr", ""); - EXPECT_EQ(ASCIIToUTF16("French - French"), - util_.GetInputMethodLongName(desc)); - } - { - InputMethodDescriptor desc = GetDesc("xkb:be::fra", "be", "fr", ""); - EXPECT_EQ(ASCIIToUTF16("French - Belgian"), - util_.GetInputMethodLongName(desc)); - } - { - InputMethodDescriptor desc = GetDesc("xkb:de::ger", "de", "de", ""); - EXPECT_EQ(ASCIIToUTF16("German - German"), - util_.GetInputMethodLongName(desc)); - } - { - InputMethodDescriptor desc = GetDesc("xkb:be::ger", "be", "de", ""); - EXPECT_EQ(ASCIIToUTF16("German - Belgian"), - util_.GetInputMethodLongName(desc)); - } - { InputMethodDescriptor desc = GetDesc("invalid-id", "us", "xx", ""); // You can safely ignore the "Resouce ID is not found for: invalid-id"
diff --git a/ui/chromeos/ui_chromeos_strings.grd b/ui/chromeos/ui_chromeos_strings.grd index 0c1b696..8834625 100644 --- a/ui/chromeos/ui_chromeos_strings.grd +++ b/ui/chromeos/ui_chromeos_strings.grd
@@ -713,8 +713,14 @@ <message name="IDS_IME_NAME_KEYBOARD_BELARUSIAN" desc="The input method name shows in system tray menu, this shows [Belarusian keyboard]."> Belarusian keyboard </message> - <message name="IDS_IME_NAME_KEYBOARD_BELGIAN" desc="The input method name shows in system tray menu, this shows [Belgian keyboard]."> - Belgian keyboard + <message name="IDS_IME_NAME_KEYBOARD_BELGIAN_DUTCH" desc="The input method name shows in system tray menu and settings page."> + Dutch (Belgium) + </message> + <message name="IDS_IME_NAME_KEYBOARD_BELGIAN_FRENCH" desc="The input method name shows in system tray menu and settings page."> + French (Belgium) + </message> + <message name="IDS_IME_NAME_KEYBOARD_BELGIAN_GERMAN" desc="The input method name shows in system tray menu and settings page."> + German (Belgium) </message> <message name="IDS_IME_NAME_KEYBOARD_BRAZILIAN" desc="The input method name shows in system tray menu, this shows [Brazilian keyboard]."> Brazilian keyboard @@ -827,6 +833,9 @@ <message name="IDS_IME_NAME_KEYBOARD_MONGOLIAN" desc="The input method name shows in system tray menu, this shows [Mongolian keyboard]."> Mongolian keyboard </message> + <message name="IDS_IME_NAME_KEYBOARD_NETHERLANDS_US_INTERNATIONAL_PC" desc="The input method name shows in system tray menu and settings page."> + Dutch (Netherlands) with US International PC keyboard + </message> <message name="IDS_IME_NAME_KEYBOARD_NETHERLANDS" desc="The input method name shows in system tray menu, this shows [Netherlands keyboard]."> Netherlands keyboard </message> @@ -839,6 +848,12 @@ <message name="IDS_IME_NAME_KEYBOARD_PORTUGUESE" desc="The input method name shows in system tray menu, this shows [Portuguese keyboard]."> Portuguese keyboard </message> + <message name="IDS_IME_NAME_KEYBOARD_PORTUGUESE_US_INTERNATIONAL" desc="The input method name shows in system tray menu and settings page."> + Portuguese with US International keyboard + </message> + <message name="IDS_IME_NAME_KEYBOARD_PORTUGUESE_US_INTERNATIONAL_PC" desc="The input method name shows in system tray menu and settings page."> + Portuguese with US International PC keyboard + </message> <message name="IDS_IME_NAME_KEYBOARD_ROMANIAN" desc="The input method name shows in system tray menu, this shows [Romanian keyboard]."> Romanian keyboard </message>
diff --git a/ui/chromeos/ui_chromeos_strings_grd/IDS_IME_NAME_KEYBOARD_BELGIAN_DUTCH.png.sha1 b/ui/chromeos/ui_chromeos_strings_grd/IDS_IME_NAME_KEYBOARD_BELGIAN_DUTCH.png.sha1 new file mode 100644 index 0000000..913e4af --- /dev/null +++ b/ui/chromeos/ui_chromeos_strings_grd/IDS_IME_NAME_KEYBOARD_BELGIAN_DUTCH.png.sha1
@@ -0,0 +1 @@ +ffc8137ab73851b32db79559d9245fad97f8017f \ No newline at end of file
diff --git a/ui/chromeos/ui_chromeos_strings_grd/IDS_IME_NAME_KEYBOARD_BELGIAN_FRENCH.png.sha1 b/ui/chromeos/ui_chromeos_strings_grd/IDS_IME_NAME_KEYBOARD_BELGIAN_FRENCH.png.sha1 new file mode 100644 index 0000000..913e4af --- /dev/null +++ b/ui/chromeos/ui_chromeos_strings_grd/IDS_IME_NAME_KEYBOARD_BELGIAN_FRENCH.png.sha1
@@ -0,0 +1 @@ +ffc8137ab73851b32db79559d9245fad97f8017f \ No newline at end of file
diff --git a/ui/chromeos/ui_chromeos_strings_grd/IDS_IME_NAME_KEYBOARD_BELGIAN_GERMAN.png.sha1 b/ui/chromeos/ui_chromeos_strings_grd/IDS_IME_NAME_KEYBOARD_BELGIAN_GERMAN.png.sha1 new file mode 100644 index 0000000..913e4af --- /dev/null +++ b/ui/chromeos/ui_chromeos_strings_grd/IDS_IME_NAME_KEYBOARD_BELGIAN_GERMAN.png.sha1
@@ -0,0 +1 @@ +ffc8137ab73851b32db79559d9245fad97f8017f \ No newline at end of file
diff --git a/ui/chromeos/ui_chromeos_strings_grd/IDS_IME_NAME_KEYBOARD_NETHERLANDS_US_INTERNATIONAL_PC.png.sha1 b/ui/chromeos/ui_chromeos_strings_grd/IDS_IME_NAME_KEYBOARD_NETHERLANDS_US_INTERNATIONAL_PC.png.sha1 new file mode 100644 index 0000000..45f79d5 --- /dev/null +++ b/ui/chromeos/ui_chromeos_strings_grd/IDS_IME_NAME_KEYBOARD_NETHERLANDS_US_INTERNATIONAL_PC.png.sha1
@@ -0,0 +1 @@ +fd5c82f95ac16720f0be8706484fe32311d4bc0c \ No newline at end of file
diff --git a/ui/chromeos/ui_chromeos_strings_grd/IDS_IME_NAME_KEYBOARD_PORTUGUESE_US_INTERNATIONAL.png.sha1 b/ui/chromeos/ui_chromeos_strings_grd/IDS_IME_NAME_KEYBOARD_PORTUGUESE_US_INTERNATIONAL.png.sha1 new file mode 100644 index 0000000..45f79d5 --- /dev/null +++ b/ui/chromeos/ui_chromeos_strings_grd/IDS_IME_NAME_KEYBOARD_PORTUGUESE_US_INTERNATIONAL.png.sha1
@@ -0,0 +1 @@ +fd5c82f95ac16720f0be8706484fe32311d4bc0c \ No newline at end of file
diff --git a/ui/chromeos/ui_chromeos_strings_grd/IDS_IME_NAME_KEYBOARD_PORTUGUESE_US_INTERNATIONAL_PC.png.sha1 b/ui/chromeos/ui_chromeos_strings_grd/IDS_IME_NAME_KEYBOARD_PORTUGUESE_US_INTERNATIONAL_PC.png.sha1 new file mode 100644 index 0000000..45f79d5 --- /dev/null +++ b/ui/chromeos/ui_chromeos_strings_grd/IDS_IME_NAME_KEYBOARD_PORTUGUESE_US_INTERNATIONAL_PC.png.sha1
@@ -0,0 +1 @@ +fd5c82f95ac16720f0be8706484fe32311d4bc0c \ No newline at end of file
diff --git a/ui/file_manager/file_manager/foreground/js/quick_view_controller.js b/ui/file_manager/file_manager/foreground/js/quick_view_controller.js index 86ab1f6..e41ffe3 100644 --- a/ui/file_manager/file_manager/foreground/js/quick_view_controller.js +++ b/ui/file_manager/file_manager/foreground/js/quick_view_controller.js
@@ -603,16 +603,40 @@ } else { break; } + case 'text': + if (typeInfo.subtype === 'TXT') { + return file + .text() // Convert file content to utf-8. + .then(text => { + return new Blob( + [text], {type: 'text/plain;charset=utf-8'}); + }) + .then(blob => { + params.contentUrl = URL.createObjectURL(blob); + params.browsable = true; + return params; + }) + .catch(e => { + console.error(e); + return params; + }); + } else { + break; + } } - const browsable = tasks.some(task => { - return ['view-in-browser', 'view-pdf'].includes( - task.taskId.split('|')[2]); + + params.browsable = tasks.some(task => { + const verb = task.taskId.split('|')[2]; + return ['view-in-browser', 'view-pdf'].includes(verb); }); - params.browsable = browsable; - params.contentUrl = browsable ? URL.createObjectURL(file) : ''; - if (params.subtype == 'PDF') { - params.contentUrl += '#view=FitH'; + + if (params.browsable) { + params.contentUrl = URL.createObjectURL(file); + if (params.subtype === 'PDF') { + params.contentUrl += '#view=FitH'; + } } + return params; }) .catch(e => {
diff --git a/ui/file_manager/integration_tests/file_manager/quick_view.js b/ui/file_manager/integration_tests/file_manager/quick_view.js index 8fb00bd..a5bb1d7 100644 --- a/ui/file_manager/integration_tests/file_manager/quick_view.js +++ b/ui/file_manager/integration_tests/file_manager/quick_view.js
@@ -528,6 +528,10 @@ // Open a DocumentsProvider file in Quick View. await openQuickView(appId, ENTRIES.hello.nameText); + + // crbug.com/1131298 The text file content is not displayed. The <webview> + // instead shows a "site cannot be reached" error. + return IGNORE_APP_ERRORS; }; /** @@ -2358,6 +2362,43 @@ }; /** + * Tests the tab-index focus order when sending tab keys when an HTML file is + * shown in Quick View. + */ + testcase.openQuickViewTabIndexHtml = async () => { + // Prepare a list of tab-index focus queries. + const tabQueries = [ + {'query': ['#quick-view', '[aria-label="Back"]:focus']}, + {'query': ['#quick-view', '[aria-label="Open"]:focus']}, + {'query': ['#quick-view', '[aria-label="Delete"]:focus']}, + {'query': ['#quick-view', '[aria-label="File info"]:focus']}, + {'query': ['#quick-view', '[aria-label="Back"]:focus']}, + ]; + + // Open Files app on Downloads containing ENTRIES.tallHtml. + const appId = await setupAndWaitUntilReady( + RootPath.DOWNLOADS, [ENTRIES.tallHtml], []); + + // Open the file in Quick View. + await openQuickView(appId, ENTRIES.tallHtml.nameText); + + for (const query of tabQueries) { + // Make the browser dispatch a tab key event to FilesApp. + const result = await sendTestMessage( + {name: 'dispatchTabKey', shift: query.shift || false}); + chrome.test.assertEq( + result, 'tabKeyDispatched', 'Tab key dispatch failure'); + + // Note: Allow 500ms between key events to filter out the focus + // traversal problems noted in crbug.com/907380#c10. + await wait(500); + + // Check: the queried element should gain the focus. + await remoteCall.waitForElement(appId, query.query); + } + }; + + /** * Tests the tab-index focus order when sending tab keys when an audio file is * shown in Quick View. */
diff --git a/ui/file_manager/integration_tests/test_util.js b/ui/file_manager/integration_tests/test_util.js index 8389b8d..fb52b42 100644 --- a/ui/file_manager/integration_tests/test_util.js +++ b/ui/file_manager/integration_tests/test_util.js
@@ -724,6 +724,17 @@ typeText: 'Plain text', }), + utf8Text: new TestEntryInfo({ + type: EntryType.FILE, + sourceFileName: 'utf8.txt', + targetPath: 'utf8.txt', + mimeType: 'text/plain', + lastModifiedTime: 'Sep 4, 1998, 12:34 PM', + nameText: 'utf8.txt', + sizeText: '191 bytes', + typeText: 'Plain text', + }), + mHtml: new TestEntryInfo({ type: EntryType.FILE, sourceFileName: 'page.mhtml',
diff --git a/ui/ozone/platform_selection.cc b/ui/ozone/platform_selection.cc index 1b49a08..eb8e85ed 100644 --- a/ui/ozone/platform_selection.cc +++ b/ui/ozone/platform_selection.cc
@@ -33,6 +33,9 @@ return g_selected_platform; std::string platform_name = GetPlatformName(); + // TODO(b/169115289) remove once all Tast tests use "drm". + if (platform_name == "gbm") + platform_name = "drm"; // Search for a matching platform in the list. for (int platform_id = 0; platform_id < kPlatformCount; ++platform_id) {
diff --git a/ui/views/background.cc b/ui/views/background.cc index ed6a43f..7ab9015 100644 --- a/ui/views/background.cc +++ b/ui/views/background.cc
@@ -13,7 +13,6 @@ #include "cc/paint/paint_flags.h" #include "ui/gfx/canvas.h" #include "ui/gfx/color_utils.h" -#include "ui/native_theme/native_theme_color_id.h" #include "ui/views/painter.h" #include "ui/views/view.h" #include "ui/views/view_observer.h" @@ -62,6 +61,33 @@ DISALLOW_COPY_AND_ASSIGN(RoundedRectBackground); }; +// ThemedVectorIconBackground is an image drawn on the view's background using +// ThemedVectorIcon to react to theme changes. +class ThemedVectorIconBackground : public Background, public ViewObserver { + public: + explicit ThemedVectorIconBackground(View* view, + const ui::ThemedVectorIcon& icon) + : icon_(icon), observer_(this) { + DCHECK(!icon_.empty()); + observer_.Add(view); + OnViewThemeChanged(view); + } + + // ViewObserver: + void OnViewThemeChanged(View* view) override { view->SchedulePaint(); } + void OnViewIsDeleting(View* view) override { observer_.Remove(view); } + + void Paint(gfx::Canvas* canvas, View* view) const override { + canvas->DrawImageInt(icon_.GetImageSkia(view->GetNativeTheme()), 0, 0); + } + + private: + const ui::ThemedVectorIcon icon_; + ScopedObserver<View, ViewObserver> observer_; + + DISALLOW_COPY_AND_ASSIGN(ThemedVectorIconBackground); +}; + // ThemedSolidBackground is a solid background that stays in sync with a view's // native theme. class ThemedSolidBackground : public SolidBackground, public ViewObserver { @@ -125,6 +151,12 @@ return std::make_unique<RoundedRectBackground>(color, radius); } +std::unique_ptr<Background> CreateThemedVectorIconBackground( + View* view, + const ui::ThemedVectorIcon& icon) { + return std::make_unique<ThemedVectorIconBackground>(view, icon); +} + std::unique_ptr<Background> CreateThemedSolidBackground( View* view, ui::NativeTheme::ColorId color_id) {
diff --git a/ui/views/background.h b/ui/views/background.h index 366ce9d..1218d80 100644 --- a/ui/views/background.h +++ b/ui/views/background.h
@@ -14,6 +14,7 @@ #include "third_party/skia/include/core/SkColor.h" #include "ui/gfx/color_palette.h" #include "ui/native_theme/native_theme.h" +#include "ui/native_theme/themed_vector_icon.h" #include "ui/views/views_export.h" #if defined(OS_WIN) @@ -24,6 +25,10 @@ class Canvas; } +namespace ui { +class ThemedVectorIcon; +} + namespace views { class Painter; @@ -79,10 +84,15 @@ View* view, ui::NativeTheme::ColorId color_id); -// Creates a Background from the specified Painter. +// Creates a background from the specified Painter. VIEWS_EXPORT std::unique_ptr<Background> CreateBackgroundFromPainter( std::unique_ptr<Painter> painter); +// Creates a background from the specified ThemedVectorIcon. +VIEWS_EXPORT std::unique_ptr<Background> CreateThemedVectorIconBackground( + View* view, + const ui::ThemedVectorIcon& icon); + } // namespace views #endif // UI_VIEWS_BACKGROUND_H_
diff --git a/ui/views/controls/button/button.h b/ui/views/controls/button/button.h index 184e736..4cbab27 100644 --- a/ui/views/controls/button/button.h +++ b/ui/views/controls/button/button.h
@@ -117,6 +117,16 @@ set_callback(ListenerToPressedCallback(this, listener)); } + // Allow providing callbacks that expect either zero or one args, since many + // callers don't care about the argument and can avoid adapter functions this + // way. + void set_callback(base::RepeatingClosure callback) { + // Adapt this closure to a PressedCallback by discarding the extra arg. + callback_ = + base::BindRepeating([](base::RepeatingClosure closure, + const ui::Event& event) { closure.Run(); }, + std::move(callback)); + } void set_callback(PressedCallback callback) { callback_ = std::move(callback); }
diff --git a/ui/views/controls/link.h b/ui/views/controls/link.h index cfaf72f..ee71c971 100644 --- a/ui/views/controls/link.h +++ b/ui/views/controls/link.h
@@ -39,8 +39,8 @@ int text_style = style::STYLE_LINK); ~Link() override; - // Allow providing callbacks that expect either zero or two args, since many - // callers don't care about the arguments and can avoid adapter functions this + // Allow providing callbacks that expect either zero or one args, since many + // callers don't care about the argument and can avoid adapter functions this // way. void set_callback(base::RepeatingClosure callback) { // Adapt this closure to a ClickedCallback by discarding the extra arg.
diff --git a/ui/webui/resources/BUILD.gn b/ui/webui/resources/BUILD.gn index 13312e9..f88fee2 100644 --- a/ui/webui/resources/BUILD.gn +++ b/ui/webui/resources/BUILD.gn
@@ -140,9 +140,17 @@ in_files += [ "cr_components/chromeos/bluetooth/bluetooth_dialog.m.js", "cr_components/chromeos/cellular_setup/base_page.m.js", + "cr_components/chromeos/cellular_setup/button_bar.m.js", + "cr_components/chromeos/cellular_setup/cellular_setup.m.js", + "cr_components/chromeos/cellular_setup/cellular_types.m.js", + "cr_components/chromeos/cellular_setup/esim_flow_ui.m.js", "cr_components/chromeos/cellular_setup/final_page.m.js", "cr_components/chromeos/cellular_setup/mojo_interface_provider.m.js", + "cr_components/chromeos/cellular_setup/provisioning_page.m.js", + "cr_components/chromeos/cellular_setup/psim_flow_ui.m.js", + "cr_components/chromeos/cellular_setup/setup_selection_flow.m.js", "cr_components/chromeos/cellular_setup/sim_detect_page.m.js", + "cr_components/chromeos/cellular_setup/subflow_behavior.m.js", "cr_components/chromeos/cellular_setup/webview_post_util.m.js", "cr_components/chromeos/network/cr_policy_network_behavior_mojo.m.js", "cr_components/chromeos/network/cr_policy_network_indicator_mojo.m.js",
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_config.js b/ui/webui/resources/cr_components/chromeos/network/network_config.js index 65dc463a..d15f327 100644 --- a/ui/webui/resources/cr_components/chromeos/network/network_config.js +++ b/ui/webui/resources/cr_components/chromeos/network/network_config.js
@@ -19,8 +19,6 @@ OPEN_VPN: 'OpenVPN', }; -(function() { - // Note: This pattern does not work for elements that are stamped on initial // load because chromeos.networkConfig is not defined yet. <network-config> // however is always embedded in a <cr-dialog> so it is not stamped immediately. @@ -1740,4 +1738,3 @@ return undefined; }, }); -})();